Following code creates two subplots and updating it each second in browser window.
I can zoom it and hide some lines in plot, but each second all data updates and set zoom and all lines visibility to default
How I can keep settings for zoom and selected lines while updating?
import datetime
import random
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from plotly.subplots import make_subplots
# https://dash.plotly.com/live-updates
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div(
html.Div([
html.H4('Two random plots'),
dcc.Graph(id='live-update-graph'),
dcc.Interval(
id='interval-component',
interval=1 * 1000, # in milliseconds
n_intervals=0
)
])
)
DATA = {
'time': [],
'val0': [],
'val1_1': [],
'val1_2': []
}
def update_data():
DATA['val0'].append(random.randint(0, 50))
DATA['val1_1'].append(random.randint(0, 50))
DATA['val1_2'].append(random.randint(0, 50))
DATA['time'].append(datetime.datetime.now())
@app.callback(Output('live-update-graph', 'figure'),
Input('interval-component', 'n_intervals'))
def update_graph_live(n):
update_data()
# Create the graph with subplots
fig = make_subplots(rows=2, cols=1, vertical_spacing=0.2)
fig['layout']['margin'] = {'l': 30, 'r': 10, 'b': 30, 't': 10}
fig['layout']['legend'] = {'x': 0, 'y': 1, 'xanchor': 'left'}
fig.append_trace({
'x': DATA['time'],
'y': DATA['val0'],
'name': 'val 0',
'mode': 'lines+markers',
'type': 'scatter'
}, 1, 1)
fig.append_trace({
'x': DATA['time'],
'y': DATA['val1_1'],
'text': DATA['time'],
'name': 'val 1.1',
'mode': 'lines+markers',
'type': 'scatter'
}, 2, 1)
fig.append_trace({
'x': DATA['time'],
'y': DATA['val1_2'],
'text': DATA['time'],
'name': 'val 1.2',
'mode': 'lines+markers',
'type': 'scatter'
}, 2, 1)
return fig
if __name__ == '__main__':
app.run_server(debug=True)
Since November 2018, there is a solution as posted on the Plotly Community Forum. The layout
property of the figure
property of dcc.Graph
has a property uirevision
, for which the post says:
uirevision
is where the magic happens. This key is tracked internally bydcc.Graph
, when it changes from one update to the next, it resets all of the user-driven interactions (like zooming, panning, clicking on legend items). If it remains the same, then that user-driven UI state doesn’t change.
So if you never want to reset the zoom settings, no matter how much the underlying data changes, just set uirevision
to a constant, like so:
fig['layout']['uirevision'] = 'some-constant'
before returning the figure in your update function.
And there is more:
There are also cases where you want more control. Say the x and y data for a plot can be changed separately. Perhaps x is always time, but y can change between price and volume. You might want to preserve x zoom while resetting y zoom. There are lots of
uirevision
attributes, that normally all inherit fromlayout.uirevision
but you can set them separately if you want. In this case set a constantxaxis.uirevision = 'time'
but letyaxis.revision
change between'price'
and'volume'
. Be sure to still setlayout.uirevision
to preserve other items like trace visibility and modebar buttons!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With