Reputation: 1431
Given a line graph with time series data in Dash (Plotly) dashboard, when I zoom in and the resolution of the x-axis (timestamp) change, how can I capture that as an input to another callback?
What I want to achieve, is plot-B displaying data based on the zoom in plot-A. When plot-A zooms in, plot-B automatically follows.
Note that plot-A and plot-B are using different dataset, with matching timestamps.
Upvotes: 5
Views: 8310
Reputation: 648
Posting little bit different solution for multiple figures than @asmaier proposed
for p in ['graph1', 'graph2', 'add-your-graphs']:
@callback(
Output(p, 'figure'),
[
Input('graph', 'relayoutData'),
State(p, 'figure')
]
)
def update_zoom(relayout_data, figure, component=p):
if relayout_data is None:
raise PreventUpdate
try:
figure['layout']["xaxis"]["range"] = [relayout_data['xaxis.range[0]'], relayout_data['xaxis.range[1]']]
figure['layout']["xaxis"]["autorange"] = False
except KeyError:
raise PreventUpdate
return figure
Upvotes: 0
Reputation: 11756
Here is an improved version of the callback based on the the answer from @Sachin Dev Sharma:
@app.callback([Output('graph2', 'figure')],
[Input('graph', 'relayoutData')], # this triggers the event
[State('graph2', 'figure')])
def zoom_event(relayout_data, *figures):
outputs = []
for fig in figures:
try:
fig['layout']["xaxis"]["range"] = [relayout_data['xaxis.range[0]'], relayout_data['xaxis.range[1]']]
fig['layout']["xaxis"]["autorange"] = False
except (KeyError, TypeError):
fig['layout']["xaxis"]["autorange"] = True
outputs.append(fig)
return outputs
The advantage here is, that we don't overwrite the complete layout of the figure in the callback. We only overwrite the xaxis.range
and xaxis.autorange
property. Also this solution allows to set the zoom on multiple output figures by accepting multiple figure arguments (see *figures
).
Upvotes: 5
Reputation: 219
Sample code for synchronizing the zoom level in plotly dash.
app=dash.Dash()
app.layout = html.Div([
dcc.Graph(id='graph',figure=fig),
html.Pre(id='relayout-data', style=styles['pre']),
dcc.Graph(id='graph2', figure=fig)])
@app.callback(Output('relayout-data', 'children'),
[Input('graph', 'relayoutData')])
def display_relayout_data(relayoutData):
return json.dumps(relayoutData, indent=2)
@app.callback(Output('graph2', 'figure'),
[Input('graph', 'relayoutData')], # this triggers the event
[State('graph2', 'figure')])
def graph_event(select_data, fig):
try:
fig['layout'] = {'xaxis':{'range':[select_data['xaxis.range[0]'],select_data['xaxis.range[1]']]}}
except KeyError:
fig['layout'] = {'xaxis':{'range':[zoomed out value]}}
return fig
app.run_server()
Upvotes: 11
Reputation: 6616
The Dash docs have an answer for this here.
relayoutData
Data from latest relayout event which occurs when the user zooms or pans on the plot or other layout-level edits. Has the form {: } describing the changes made. Read-only.
Unfortunately, as a read-only prop, you will not be able to update the second graph to follow the zoom on the first one.
Upvotes: 0