Using MatPlotLib to dynamically generate charts in a Django web service
Based on the work with Zope, the following is a recipe for displaying a chart using Django. You need to have a working Django installation, plus matplotlib, Anti-Grain, and numpy. In Debian testing, Django plus the following packages suffice:
1. python
2. python-numpy
3. python-numpy-ext
4. python-matplotlib
5. python-imaging
6. python-numeric
Example 1 - PIL Buffer
def chart(request):
from PIL import Image as PILImage
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
from StringIO import StringIO
fig = Figure()
canvas = FigureCanvas(fig)
ax = fig.add_subplot(111)
ax.plot([1,2,3])
ax.set_title('hi mom')
ax.grid(True)
ax.set_xlabel('time')
ax.set_ylabel('volts')
canvas.draw()
size = canvas.get_renderer().get_canvas_width_height()
buf=canvas.tostring_rgb()
im=PILImage.fromstring('RGB', size, buf, 'raw', 'RGB', 0, 1)
imdata=StringIO()
im.save(imdata, format='JPEG')
response = HttpResponse(imdata.getvalue(), mimetype='image/jpeg')
return response
Example 1a - Unix Socket Pair
If the PIL buffer seems like a hack to you and you're running on an operating system that supports UNIX sockets, you can create a socket pair and use it read out image data.
def chart(request):
from socket import socketpair
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
fig = Figure()
canvas = FigureCanvas(fig)
ax = fig.add_subplot(111)
ax.plot([1,2,3])
ax.set_title('hi mom')
ax.grid(True)
ax.set_xlabel('time')
ax.set_ylabel('volts')
canvas.draw()
ins, outs = socket.socketpair()
ins = ins.makefile('w')
outs = outs.makefile('r')
canvas.print_figure(ins)
response = HttpResponse(outs, mimetype='image/png')
return response
Example 2 - Cairo Backend
With the cairo backend you can write directly to a StringIO() object without using PIL.
from django.http import HttpResponse
def cairo_chart(request):
import matplotlib
matplotlib.use('Cairo')
from matplotlib.figure import Figure
from matplotlib.backends.backend_cairo import FigureCanvasCairo as FigureCanvas
from StringIO import StringIO
fig = Figure()
canvas = FigureCanvas(fig)
ax = fig.add_subplot(111)
ax.plot([1,2,3])
ax.set_title('hi mom')
ax.grid(True)
ax.set_xlabel('time')
ax.set_ylabel('volts')
canvas.draw()
imdata=StringIO()
fig.savefig(imdata,format='png')
return HttpResponse(imdata.getvalue(), mimetype='image/png')
