From charlesreid1

No edit summary
 
(2 intermediate revisions by the same user not shown)
Line 74: Line 74:
==Step 3: Should've Put a String on it==
==Step 3: Should've Put a String on it==


Let's turn that figure into a StringIO object:
Let's define a function that will turn that figure into a StringIO object:


<source lang="python">
<pre>
def stringify_dummy_figure()
def stringify_dummy_figure():
     figcanvas = make_dummy_figure()
     figcanvas = make_dummy_figure()
     img_data_str = StringIO()
     img_data_str = StringIO()
Line 83: Line 83:
     img_data_str.seek(0)  # After writing, rewind data for further use.
     img_data_str.seek(0)  # After writing, rewind data for further use.
     return img_data_str.read()
     return img_data_str.read()
</source>
</pre>


==Step 4: Make an HTTP Response==
==Step 4: Make an HTTP Response==
Line 89: Line 89:
The last step is to pass that string to an HTTP response  
The last step is to pass that string to an HTTP response  


<source lang="python">
<pre>
from django.http import HttpResponse, HttpResponseRedirect
from django.http import HttpResponse, HttpResponseRedirect


img_str = stringify_dummy_figure()
img_str = stringify_dummy_figure()
response = HttpResponse(img_str, mimetype='image/png')
response = HttpResponse(img_str, mimetype='image/png')
</source>
</pre>


and that can be embedded into your web app, wherever it lays out the logic for parsing URLs and crafting HTTP responses.
and that can be embedded into your web app, wherever it lays out the logic for parsing URLs and crafting HTTP responses.


[[Category:Python]]
 
 
 
{{ScientificComputingFlag}}
{{PythonFlag}}

Latest revision as of 07:18, 16 April 2017

Using Matplotlib in Web Apps

I wanted to write a Python web app that would call Matplotlib to visualize some data on the back end, and serve it up to a browser window on the front end.

Initially I saw [webplotlib https://pypi.python.org/pypi/webplotlib/0.1], which looked promising, but wrapped all of matplotlib into two dinky kinds of plots: time series, and bar charts. I needed something that, like webplotlib, could communicate a figure to a browser, but something that, unlike webplotlib, still kept the full functionality of matplotlib.

The fix was easy. The core functionality of webplotlib is passing a figure as a string to the browser; this is about 4 lines. The rest is entirely case-dependent.

Let's walk through how to do this.

Step 1: Create Your Figure

Some quick code to make a dummy figure:

def make_dummy_figure():
    import matplotlib.pylab as plt
    from numpy.random import *

    fig = plt.figure()
    ax1 = fig.add_subplot(1,2,1)
    ax2 = fig.add_subplot(1,2,2)

    x = range(10)
    y1 = rand(10,)
    y2 = 1000*rand(10,)

    ax1.plot(x,y1,'b-')
    ax2.plot(x,y2,'r-')

    ax1.set_xlabel('Number of Llamas')
    ax1.set_ylabel('People killed')

    ax2.set_xlabel('Number of Tigers')
    ax2.set_ylabel('People killed')

DummyPlot.png

Step 2: Make a Sendable Figure

To send a figure to our web application, we need to make the figure sendable. We modify the script to return a FigureCanvas handle to our figure,

import matplotlib.pylab as plt
from numpy.random import *

matplotlib.use('Agg')
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas

def make_dummy_figure():

    fig = plt.figure()
    ax1 = fig.add_subplot(1,2,1)
    ax2 = fig.add_subplot(1,2,2)

    x = range(10)
    y1 = rand(10,)
    y2 = 1000*rand(10,)

    ax1.plot(x,y1,'b-')
    ax2.plot(x,y2,'r-')

    ax1.set_xlabel('Number of Llamas')
    ax1.set_ylabel('People killed')

    ax2.set_xlabel('Number of Tigers')
    ax2.set_ylabel('People killed')

    return FigureCanvas(fig)

Step 3: Should've Put a String on it

Let's define a function that will turn that figure into a StringIO object:

def stringify_dummy_figure():
    figcanvas = make_dummy_figure()
    img_data_str = StringIO()
    figcanvas.print_png(img_data_str)
    img_data_str.seek(0)  # After writing, rewind data for further use.
    return img_data_str.read()

Step 4: Make an HTTP Response

The last step is to pass that string to an HTTP response

from django.http import HttpResponse, HttpResponseRedirect

img_str = stringify_dummy_figure()
response = HttpResponse(img_str, mimetype='image/png')

and that can be embedded into your web app, wherever it lays out the logic for parsing URLs and crafting HTTP responses.