Update: Version 1.16.2 has been released since this was posted.
We’re pleased to announce that Dash 1.16.1 is out
pip install dash==1.16.1
Dash 1.16.1 is a backwards compatible patch release. Highlights include:
- Community contribution from @sleighsoft:
dcc.Graph
support forprependData
- Bug fixes for the Callback Graph’s Debugging and Performance Tools announced in Dash 1.16.0
- Bug fix for
dcc.DatePickerSingle
anddcc.DatePickerRange
date persistence - Bug fix in
dcc.Graph
forautomargin
when the newticklabelmode
feature is set to"period"
. Fixed by upgrading Plotly.js 1.55.1 to Plotly.js 1.55.2.
View the Official Changelog
In More Detail
prependData
prependData
is a new dcc.Graph
property that allows you to prepend new data to the traces
of a graph without sending the entire figure
back and forth between the client and the Python callbacks. This can be much faster for incremental updates to the graph.
As inspiration, see this community example in the forum that incrementally updates the graph for rapid streaming:
The complement of prependData
is the extendData
property (used in the GIF above). extendData
has existed for a couple of years.
Here’s a complete example demonstrating the syntax taken from our test suite:
import dash
from dash.exceptions import PreventUpdate
from dash.dependencies import Input, Output, State
import dash_html_components as html
import dash_core_components as dcc
import json
app = dash.Dash(__name__)
def generate_with_id(id, data=None):
if data is None:
data = [{"x": [10, 11, 12, 13, 14], "y": [0, 0.5, 1, 0.5, 0]}]
return html.Div(
[
html.P(id),
dcc.Graph(id=id, figure=dict(data=data)),
html.Div(id="output_{}".format(id)),
]
)
figs = [
"trace_will_prepend",
"trace_will_prepend_with_no_indices",
"trace_will_prepend_with_max_points",
]
layout = [generate_with_id(id) for id in figs]
figs.append("trace_will_allow_repeated_prepend")
data = [{"y": [0, 0, 0]}]
layout.append(generate_with_id(figs[-1], data))
figs.append("trace_will_prepend_selectively")
data = [
{"x": [10, 11, 12, 13, 14], "y": [0, 0.5, 1, 0.5, 0]},
{"x": [10, 11, 12, 13, 14], "y": [1, 1, 1, 1, 1]},
]
layout.append(generate_with_id(figs[-1], data))
layout.append(
dcc.Interval(
id="interval_prependablegraph_update",
interval=10,
n_intervals=0,
max_intervals=1,
)
)
layout.append(
dcc.Interval(
id="interval_prependablegraph_prependtwice",
interval=500,
n_intervals=0,
max_intervals=2,
)
)
app.layout = html.Div(layout)
@app.callback(
Output("trace_will_allow_repeated_prepend", "prependData"),
[Input("interval_prependablegraph_prependtwice", "n_intervals")],
)
def trace_will_allow_repeated_prepend(n_intervals):
if n_intervals is None or n_intervals < 1:
raise PreventUpdate
return dict(y=[[0.1, 0.2, 0.3, 0.4, 0.5]])
@app.callback(
Output("trace_will_prepend", "prependData"),
[Input("interval_prependablegraph_update", "n_intervals")],
)
def trace_will_prepend(n_intervals):
if n_intervals is None or n_intervals < 1:
raise PreventUpdate
x_new = [5, 6, 7, 8, 9]
y_new = [0.1, 0.2, 0.3, 0.4, 0.5]
return dict(x=[x_new], y=[y_new]), [0]
@app.callback(
Output("trace_will_prepend_selectively", "prependData"),
[Input("interval_prependablegraph_update", "n_intervals")],
)
def trace_will_prepend_selectively(n_intervals):
if n_intervals is None or n_intervals < 1:
raise PreventUpdate
x_new = [5, 6, 7, 8, 9]
y_new = [0.1, 0.2, 0.3, 0.4, 0.5]
return dict(x=[x_new], y=[y_new]), [1]
@app.callback(
Output("trace_will_prepend_with_no_indices", "prependData"),
[Input("interval_prependablegraph_update", "n_intervals")],
)
def trace_will_prepend_with_no_indices(n_intervals):
if n_intervals is None or n_intervals < 1:
raise PreventUpdate
x_new = [5, 6, 7, 8, 9]
y_new = [0.1, 0.2, 0.3, 0.4, 0.5]
return dict(x=[x_new], y=[y_new])
@app.callback(
Output("trace_will_prepend_with_max_points", "prependData"),
[Input("interval_prependablegraph_update", "n_intervals")],
)
def trace_will_prepend_with_max_points(n_intervals):
if n_intervals is None or n_intervals < 1:
raise PreventUpdate
x_new = [5, 6, 7, 8, 9]
y_new = [0.1, 0.2, 0.3, 0.4, 0.5]
return dict(x=[x_new], y=[y_new]), [0], 7
for id in figs:
@app.callback(
Output("output_{}".format(id), "children"),
[Input(id, "prependData")],
[State(id, "figure")],
)
def display_data(trigger, fig):
return json.dumps(fig["data"])
app.run_server(debug=True)
Previous Releases
-
Dash v1.13.4 Release: Fixes regression with loading states from callbacks with multiple outputs
-
Dash v1.11.0 Release - Introducing Pattern-Matching Callbacks
-
Dash v1.10.0 Release - New dcc.Graph features, updated dcc.Link, React upgrade and bug fixes
-
Dash v1.8.0 release - dcc.Graph updates, markdown & link support in DataTable, and more
-
Dash v1.7.0 released - Async component fixes, inline clientside callbacks, and bug fixes
-
Dash 1.6.0 released - dcc.Graph updates, async performance improvements, improved caching
Feedback, questions, thoughts? Let us know how it goes!