Returning matplotlib figure in the callback

Hi there!
I’ve been wondering, what is the best way to return a matplotlib figure from the callback function and get it visualized in a Dash app properly?
The only working way I’ve been able to find was base64 encoding of the plot followed up by passing the decoded hash to the html.Img src parameter. However, this solution doesn’t work stable for me. Namely, two graphs which should be displayed next to each other tend to interchangeably not appear at all from time to time.
I’d be grateful if you could give me a hint, whether there’re some alternative solutions, or maybe point at my mistake!

Here’s an example of the callback I’m using.

@app.callback(Output(component_id='distribution-map', component_property='src'),
              Input(component_id='my-slider', component_property='value'))
def distribution(value):
    s1 = io.BytesIO()
    fig, ax = plt.subplots(1, 1, subplot_kw={"projection": ccrs.EqualEarth()}, figsize=(8, 8))
    load_distribution = # data fetching
    network.plot(bus_sizes=1e-5*load_distribution, ax=ax, title="Load distribution")
    plt.savefig(s1, format='png')
    s1 = base64.b64encode(s1.getvalue()).decode("utf-8").replace("\n", "")
    return f'data:image/png;base64,{s1}'

Maybe, the problem is that the network.plot() method of pypsa returns the plot itself preventing plt.savefig() from saving the plot contents?

Thanks in advance for your answer and help!

1 Like mpl_to_plotly ( fig , resize=False , strip_style=False , verbose=False )

This is the approach that I’ve seen work in the past. Our example in the dash-alternative-viz project uses this approach: dash-alternative-viz/ at fd2f85fd712b4667e78c5ab8d28044bf464fdf63 · plotly/dash-alternative-viz · GitHub

This may work, but FWIW it’s a bit of a hack. For a couple of years we were working on tooling to crawl matplotlib figures and convert them to interactive plotly figures. We got pretty far, but it’s not 100% and we aren’t actively making it any better. So if it works for you, then great :slightly_smiling_face: But if it doesn’t, then converting the figure to an image and displaying it in an html.Img tag is the way to go.

hi @plotlik
I used the mpld3 library for this. Actually, I made a video about Matplotlib in Dash a few months ago. Let me know if it is helpful.

Here’s the code tied to the video.


thank you very much, that helped me!

tried it out. unfortunately didn’t work for me