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:
uirevisionis 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
uirevisionattributes, that normally all inherit fromlayout.uirevisionbut you can set them separately if you want. In this case set a constantxaxis.uirevision = 'time'but letyaxis.revisionchange between'price'and'volume'. Be sure to still setlayout.uirevisionto 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