I wanted to update the virtualenv I use…

I wanted to update the virtualenv I use for iPython HTML Notebook with the latest matplotlib, which includes XKCD-style plotting. I first set up the virtualenv using these instructions, and then used pip to install the RC2 version of matplotlib using the tarball (since 1.3.0rc2 is not in pypi):

$ pip install https://downloads.sourceforge.net/project/matplotlib/matplotlib/matplotlib-1.3.0rc2/matplotlib-1.3.0rc2.tar.gz
 
#pip installs matplotlib from tarball, but half-uninstalls the dateutil package that we previously installed
$ pip uninstall python-dateutil
$ pip install python-dateutil

Now, we need to install the Humor Sans font. I downloaded the ttf and put it in ~/.fonts/Humor-Sans.ttf

After installing the font, we need to make sure the fontList.cache file is rebuilt (Thanks Georg!):

$ rm ~/.matplotlib/fontList.cache

We should now be able to produce xkcd-style plots just by running this command in our notebook before plotting:

matplotlib.pyplot.xkcd()

However, there are a couple errors with matplotlib 1.3.0rc2:

  • matplotlib.font_manager’s findfont() can’t find Humor-Sans.ttf, which I placed in matplotlib.font_manager.path, so manaully set the fonts for now
  • The XKCD artist style doesn’t work with plot_time() very well, so handle x-axis dates manaully as well

I downloaded some data from graphite using &rawData=true and pasted that into my ipython notebook. This is sample graph of what it looks like:
matplotlib xkcd

Here is the code I used:

Update: The code below contains workarounds for a font issue that is now fixed (Thanks Georg!). See this post for a better example

#Use the XKCD style
matplotlib.pyplot.xkcd()
 
#Manually set the font, since I can't seem to get matplotlib to load Humor Sans automatically
ax = pylab.axes()
prop = matplotlib.font_manager.FontProperties(fname=matplotlib.font_manager.path+'/Humor-Sans.ttf', size=16)
 
#Set the Y axis
def fmt_mb(x, pos):
    if x > 14e6:
        return ""
    return '%0.0fMB/min' % (x*1e-6)
yfmt = FuncFormatter(fmt_mb)
matplotlib.pyplot.gca().yaxis.set_major_formatter(yfmt)
 
#Set the X axis
start = 1371584040
end = 1371670440
timestamps = numpy.linspace(start, end, len(x))
dates=[datetime.datetime.utcfromtimestamp(ts) for ts in timestamps]
matplotlib.pyplot.xticks(rotation=75)
xfmt = DateFormatter('%m-%d %H:%M')
matplotlib.pyplot.gca().xaxis.set_major_formatter(xfmt)
 
#Set the title, and manually specify font due to matplotlib findfont issue
plt.title("HTML5 Uploader MB/min for the last 24 hours", fontproperties=prop) 
 
#Plot the moving average
values = matplotlib.mlab.movavg(x, 15)
ax.plot(dates[:len(values)], values)
 
#Manually set font for the labels, due to findfont issue
for label in ax.get_xticklabels():
    label.set_fontproperties(prop)
 
for label in ax.get_yticklabels():
    label.set_fontproperties(prop)   
 
#Save PNG
fig = matplotlib.pyplot.gcf()
fig.set_size_inches(10,10)
plt.savefig('out.png',dpi=100)