Plot matplotlib on the Web

14,106

Solution 1

First you need a page to load a url from the webserver controller which generates the image:

<img src="/matplot/makegraph?arg1=foo" />

Then, embed the matplotlib code into the makegraph controller. You just need to capture the canvas rendered PNG in a memory buffer, then create an HTTP response and write the bytes back to the browser:

import cStringIO
from matplotlib.figure import Figure                      
from matplotlib.backends.backend_agg import FigureCanvasAgg

fig = Figure(figsize=[4,4])                               
ax = fig.add_axes([.1,.1,.8,.8])                          
ax.scatter([1,2], [3,4])                                  
canvas = FigureCanvasAgg(fig)

# write image data to a string buffer and get the PNG image bytes
buf = cStringIO.StringIO()
canvas.print_png(buf)
data = buf.getvalue()

# pseudo-code for generating the http response from your
# webserver, and writing the bytes back to the browser.
# replace this with corresponding code for your web framework
headers = {
    'Content-Type': 'image/png',
    'Content-Length': len(data)
    }
response.write(200, 'OK', headers, data)

Note: you may want to add caching for these if they're frequently generated with the same arguments, e.g. construct a key from the args and write the image data to memcache, then check memcache before regenerating the graph.

Solution 2

Just to update for python3

The StringIO and cStringIO modules are gone. Instead, import the io module and use io.StringIO https://docs.python.org/3.5/whatsnew/3.0.html?highlight=cstringio

So now would be something like:

import io
from matplotlib.figure import Figure     
from matplotlib import pyplot as plt                 

fig = Figure(figsize=[4,4])                               
ax = fig.add_axes([.1,.1,.8,.8])                          
ax.scatter([1,2], [3,4])                                  

buf = io.BytesIO()
fig.savefig(buf, format='png')
plt.close(fig)
data=buf.getvalue()

# In my case I would have used Django for the webpage
response = HttpResponse(data, content_type='image/png')
return response
Share:
14,106

Related videos on Youtube

Jason Strimpel
Author by

Jason Strimpel

Passionate technologist and experienced leader. My super power is found at the intersection of engineering, sales and leadership.

Updated on November 11, 2020

Comments

  • Jason Strimpel
    Jason Strimpel over 3 years

    The following code will of course create a PNG named test and save it on the server:

    from matplotlib.figure import Figure                         
    from matplotlib.backends.backend_agg import FigureCanvasAgg  
    
    fig = Figure(figsize=[4,4])                                  
    ax = fig.add_axes([.1,.1,.8,.8])                             
    ax.scatter([1,2], [3,4])                                     
    canvas = FigureCanvasAgg(fig)                                
    canvas.print_figure("test.png")
    

    Then to view the image in the browser, we have to go to example.com/test.png. This means we have to call the page with the Python code first to create the test.png file, then go to the PNG file. Is there a way to draw the PNG and output from the Python page that creates the image? Thanks!

  • umbreonben
    umbreonben over 11 years
    It appears you can also do plt.savefig(buf,format="png",facecolor="white") or fig.savefig(). So you dont have to deal with the canvas object.

Related