Passing a Matplotlib Figure to HTML (Flask)

Passing a matplotlib figure to HTML (flask)

You have to separate the HTML and the image into two different routes.

Your /images/<cropzonekey> route will just serve the page, and in the HTML content of that page there will be a reference to the second route, the one that serves the image.

The image is served in its own route from a memory file that you generate with savefig().

I obviously didn't test this, but I believe the following example will work as is or will get you pretty close to a working solution:

@app.route('/images/<cropzonekey>')
def images(cropzonekey):
return render_template("images.html", title=cropzonekey)

@app.route('/fig/<cropzonekey>')
def fig(cropzonekey):
fig = draw_polygons(cropzonekey)
img = StringIO()
fig.savefig(img)
img.seek(0)
return send_file(img, mimetype='image/png')

Your images.html template the becomes:

<html>
<head>
<title>{{ title }} - image</title>
</head>
<body>
<img src="{{ url_for('fig', cropzonekey = title) }}" alt="Image Placeholder" height="100">
</body>
</html>

Python - Flask - MatPlotLib

Please refer to this link to learn how to do this using:

import io
import base64

https://gitlab.com/snippets/1924163

Python: How to show matplotlib in flask

You can generate the image on-the-fly in Flask URL route handler:

import io
import random
from flask import Response
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure

@app.route('/plot.png')
def plot_png():
fig = create_figure()
output = io.BytesIO()
FigureCanvas(fig).print_png(output)
return Response(output.getvalue(), mimetype='image/png')

def create_figure():
fig = Figure()
axis = fig.add_subplot(1, 1, 1)
xs = range(100)
ys = [random.randint(1, 50) for x in xs]
axis.plot(xs, ys)
return fig

Then you need to include the image in your HTML template:

<img src="/plot.png" alt="my plot">

passing a plot from matpotlib to a flask view

What Python version are you using? On Python 3.x base64.b64encode() returns bytes object and that's why it probably fails. You need to decode it into a string before passing it to Flask. Also, you should URL-escape your base64-encoded string since you're printing it inside of your HTML, something like:

import urllib.parse

# ...

img = io.BytesIO() # create the buffer
plt.savefig(img, format='png') # save figure to the buffer
img.seek(0) # rewind your buffer
plot_data = urllib.parse.quote(base64.b64encode(img.read()).decode()) # base64 encode & URL-escape
return render_template('plot.html', plot_url=plot_data)

Passing matplotlib subplots generated from a pandas dataframe to HTML for display using flask

I think there are two main issues here, see my comments in the code:

travel_df_new.unstack(level=0).plot(kind='bar', subplots=True, legend=False)

# This creates a new, empty Figure. Saving this should just be an empty plot.
fig=plt.figure()

# Now you want to save the empty Figure into your img
# This won't work, because savefig works with BytesIO
canvas = FigureCanvas(fig)
img = StringIO()
fig.savefig(img)
img.seek(0)

Try something like this instead:

travel_df_new.unstack(level=0).plot(kind='bar', subplots=True, legend=False)

buff = BytesIO()
plt.savefig(buff, format='png', dpi=180)
buff.seek(0)

Note this uses io.BytesIO instead of io. StringIO, calls plt.savefig and not fig.savefig, and is a little more verbose in the savefig arguments.

I'm also not quite sure why you call plt.ion() in your route, you won't need interactive mode when run like this.



Related Topics



Leave a reply



Submit