I have a quite simple application (on the outside :)) which is supposed to show pictures created with matplotlib
: believe me, I would be happy to use plotly
instead but I can’t do these plots in plotly
.
There is a quite simple callback which takes values from a slider and two dropdowns, calls the matplotlib
function which produces a plot, saves it on the server and passes the filename to dash
which then takes the picture and shows it as base64-encoding. As far as I know this is the easiest way to embed pictures in a Dash application. Here is a minimal snippet from the app
app = dash.Dash(__name__)
server = app.server
app.layout = html.Div([
html.Div([dcc.Dropdown(id='chart-dropdown',
options=dropdown_options, value='gph_t_850',
style=dict(width='40%', verticalAlign="middle")
),
dcc.Dropdown(id='proj-dropdown',
options=projection_options, value='euratl',
style=dict(width='40%', verticalAlign="middle")
)],style={'float': 'left', 'width': '100%'}),
html.P('Forecast lead time'), html.Div(dcc.Slider(id='slider-step', min=0, max=120, value=0,
marks={i: i for i in steps}, step=None,
tooltip={'always_visible': True}))], style={'float': 'left', 'width': '100%'})]),
html.Div(html.Img(id="image_plt"), style={'textAlign': 'center'})
])
@app.callback(
Output('image_plt', 'src'),
[Input('chart-dropdown', 'value'), Input('slider-step', 'value'), Input('proj-dropdown', 'value')])
def update_figure(chart, f_step, projection):
filename = '/tmp/' + projection + '_' + chart + '_%s_%03d.png' % (run_string, f_step)
if os.path.exists(filename):
out = b64_image(filename)
else:
filename_fig = plot_vars(f_step, projection, load_all=False)
assert filename_fig == filename, "Mismatching filename strings! From plot_vars:%s , defined:%s" % (filename_fig, filename)
out = b64_image(filename_fig)
return out
plot_vars
is the matplotlib
function that creates the plot and save it as png
in a temp folder.
As you can see If the image already exists on the server the cached version of the picture is shown without calling the matplotlib
function. In this case the duration of _dash-update-component
is solely related to the base64
encoding, I believe. Unfortunately just loading the picture and showing it (as an effect of moving the slider) takes about 340 ms (see screenshot)
This is fine for most applications but I would like to be able to move between different images with almost no delay, as I would do in a “barebone” HTML-JS implementation as this one ICON model visualization . In this particualr implementation the delay is about 150 ms the first time that the image has to be fetched but afterwards if you select the same image it will just be fetched from the cache without calling anything, so it is basically istantaneous. I’m not sure whether this kind of behaviour can be reproduced in Dash
but I think most of the delay is due to the fact that the image has to be encoded in base64 every time.
Is there a simpler way to embed the image in the Dash application? or any way to speed up the update?
Thanks for the help
P.S. I’ve taken the liberty of publishing the app on heroku
(https://icon-forecast.herokuapp.com/) if you want to try it out, but don’t use the preload button as it will run out of memory on the free dynos