Posted by: Duncan
Tags: Matplotlib | Django | Python
Matplotlib, the superb graphing package from the sadly-missed John Hunter, is an essential tool for anyone involved with data visualisation. But it does have a few small drawbacks, one of which is the absence of streaming to a browser.
However, as the image and associated button below demonstrate, it is not only possible but surprisingly easy to get around this limitation;
The approach used here would work with any webserver but the example below is for Django.
The key is to redirect output of the Matplotlib plot function into a cStringIO.StringIO (Python 2) or io.BytesIO (Python 3) object and dump that into the Django response object. This solution is, IMO, a lot nicer than the usual approach of using PIL as cStringIO/io is part of the standard Python library and so the additional image processing package is not needed.
Here is the code in full;
import sys from django.http import HttpResponse import matplotlib as mpl mpl.use('Agg') # Required to redirect locally import matplotlib.pyplot as plt import numpy as np from numpy.random import rand try: # Python 2 import cStringIO except ImportError: # Python 3 import io def get_image(request): """ This is an example script from the Matplotlib website, just to show a working sample >>> """ N = 50 x = np.random.rand(N) y = np.random.rand(N) colors = np.random.rand(N) area = np.pi * (15 * np.random.rand(N))**2 # 0 to 15 point radiuses plt.scatter(x, y, s=area, c=colors, alpha=0.5) """ Now the redirect into the cStringIO or BytesIO object >>> """ if cStringIO in sys.modules: f = cStringIO.StringIO() # Python 2 else: f = io.BytesIO() # Python 3 plt.savefig(f, format="png", facecolor=(0.95,0.95,0.95)) plt.clf() """ Add the contents of the StringIO or BytesIO object to the response, matching the mime type with the plot format (in this case, PNG) and return >>> """ return HttpResponse(f.getvalue(), content_type="image/png")
NB: the matplotlib.use('Agg') directive specifies the back-end renderer to use, in this case the Anti-Grain Geometry high-quality image renderer. Other renderers are available. However, a back-end renderer must be specified otherwise the redirect will fail.
That's all that's needed. This approach would work with any web framework; the only difference would be to adapt the response format accordingly.