I’m trying to make a choropleth with ~40k polygons that gets recolored depending on the value of a dropdown menu.
I want to the menu choice to trigger a server-side recomputation of the choropleth values, colors, and legend, then send only that info to the client and not the large amount of geodata again.
Any suggestions?
I haven’t tied with Plotly Choropleth, but it should be possible with the GeJSON component in Dash leaflet. If you color the polygons based on data from the hideout prop (via a custom JS function), you can update this prop only without changing the data prop (which holds the polygons).
Hi @chriddyp , I also wanted to update plots in a Dash applications, and I was tempted to use figure updates as documented at Creating and Updating Figures | Python | Plotly. Do we agree that at the moment I can’t use that in the context of a dash application? Thanks!
I think it depends on what you want to update. Can you elaborate on what you are trying to do, e.g. what properties you are modifying?
Hi, I am reviving this thread a bit. For my usecase, I want to synchronize the x-axis is various plotly figures. Currently, I am using a RangeSlider to define the range of the x-axis. However, as pointed out by previous members, the whole figure is being updated and sent back to the client which takes time. If I understand it correctly, updating the x-axis of a plotly graph only requires an update on a specific parameter in the layout.
I would like to ask for this case:
- How do we locate this parameter.
- For multipage app, how do we call the
clientside_callback
?
Thank you!
Hello @matthewdml,
Welcome to the community!
Currently, there is no way to update only the layout from the server without sending the whole figure.
For a clientside callback, to update the layout it would look something like this:
app.clientside_callback(
“”” function (d, fig) {
if (d) {
newFig = JSON.parse(JSON.stringify(fig))
newFig.layout = newLayout
return newFig
}
return window.dash_clientside.no_update
}”””,
Output(‘target’,’figure’),
Input(‘trigger’,’value’),
State(‘target’,’figure’))
Hi @matthewdml ,
@jinnyzor was faster than me, but nevertheless I wanted to share my MRE (basically I’m trying to get better in JS )
import dash
from dash import dcc, Input, Output, State
import dash_bootstrap_components as dbc
import plotly.graph_objects as go
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = dbc.Container([
dbc.Col(
dbc.Row([
dcc.Graph(
id='graph',
figure=go.Figure(
data=go.Scatter(
x=[*range(100)],
y=[*range(100)],
mode='markers'
),
layout={'yaxis_range': [0, 20]}
)
)
]),
),
dbc.Row([
dbc.Col(
dcc.RangeSlider(
id='slider',
value=[0, 20],
min=0,
max=100,
step=1,
marks={0: 'min', 100: 'max'},
className='slider'
),
),
]),
])
# @app.callback(
# Output('graph', 'figure'),
# Input('slider', 'value'),
# State('graph', 'figure'),
# prevent_initial_call=True
# )
# def update(values, figure):
# figure.get('layout').get('yaxis').update({'range': values})
# return figure
app.clientside_callback(
"""
function(values, figure) {
newFig = JSON.parse(JSON.stringify(figure))
newFig['layout']['yaxis']['range']=values
return newFig
}
""",
Output('graph', 'figure'),
Input('slider', 'value'),
State('graph', 'figure'),
prevent_initial_call=True
)
if __name__ == "__main__":
app.run(debug=True, port=8055)
It is possible using the OperatorTransform
. This example should get you started,
Thank you for the code snippets. It took a while but I was finally able to sync several figures in my app. Client-side callback is way faster than the server-side callback that I was previously using.
For future reader who wants to sync several figures, here below is the callback that I eventually used. I am using a slider to assign the range of the xaxis.
clientside_callback(
"""
function(value, data, figure) {
updated_fig = JSON.parse(JSON.stringify(figure))
updated_fig['layout']['xaxis]['range'] = [data[value[0]], data[value[1]]]
updated_fig['layout']['xaxis]['autorange'] = false
return updated_fig
}
""",
Output('fig-id', "figure"),
Input("date-slider", "value"),
[State("clientside-store-snapshots", "data"), State('fig-id', "figure")],
prevent_initial_call=True,
)
Hey @matthewdml,
What happens if you just pust updated_fig['layout']['xaxis]['range'] = data
? I believe it is already in list format.
Glad you got something working.