How to update, in the callback function, the property of a chart that is imported from another file?

In the following dash app, the map to be updated in the callback function is imported from a separate python file creating a scatter_mapbox.

I want to use a slider to change the size_max property of the scatter_map to change the size of the dots.

I know how to do this if the code to create the map is put inside the callback function. However, I don’t know how to do it when this attribute is sepcified in that separate python file.

May I ask how to do this? Thanks.

  1. Dash app:
from dash import Dash, html, dcc, Input, Output
import dash_bootstrap_components as dbc
import graph

# -- init app ------------------------------------------------------------------
app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

# use dbc.Container
app.layout = dbc.Container([
    dbc.Row([
        dbc.Col([
            html.H1('Project Locations', style={'textAlign': 'center', 'color': '#000000', 'background': '#ffffff', 'padding': '0px'}),
        ], width = 12),
    ]),

    dbc.Row([
        dbc.Col([
            html.H5('Max Size', style={'textAlign': 'center'}),

            dcc.Slider(id = 'max_size', min = 1, max = 50, step = 1, value = 30, marks = {1: '1', 50: '50'})
        ], width = 12),
    ]),

    dbc.Row([
        dbc.Col([
            dcc.Graph(id='map', figure={}),
        ], width = 12),
    ]),
])

# -- callback ------------------------------------------------------------------
@app.callback(
    Output('map', 'figure'),
    Input('max_size', 'value'),
)
def update_graph(value):
    return graph.fig_aus2

# -- run app -------------------------------------------------------------------
if __name__ == "__main__":
    app.run_server(debug=True)
  1. the separate python file graph.py that contains the code to generate the map:
import pandas as pd
import plotly.express as px

# -- create chart --------------------------------------------------------------
aus_solar = pd.read_csv('./data/project.csv').fillna(0)

fig_aus2 = px.scatter_mapbox(
    aus_solar,
    lat = 'latitude',
    lon = 'longitude',
    size = 'DC Capacity (MWp)',
    size_max = 30,
    hover_data = ['Project/', 'DC Capacity (MWp)'],
    height = 1000,
    zoom = 4,
)

fig_aus2.update_traces(
    marker = dict(
        color = 'red',
    )
)

fig_aus2.update_layout(
    mapbox_style = 'open-street-map',
    margin = dict(l = 0, r = 0, t = 0, b = 0),
)

Hi,

You could just load the figure at startup:

 dcc.Graph(id='map', figure=graph.fig_aus2)

and use the State of the figure to change the properties you want to change:

@app.callback(
    Output('map', 'figure'),
    Input('max_size', 'value'),
    State('map', 'figure')
)
def update_graph(value, current_figure):
    changed_figure = change(current_figure)
    return changed_figure

If you want to reduce the traffic between browser ans server, you could use the Patch() object for partial updates. Some examples of how to do that here:

Hi @oat !

Actually if you need to provide the value of your slider to your figure, you need to create a function providing this value as parameter, then return the figure.

In your graph.py:

import pandas as pd
import plotly.express as px

# -- create chart --------------------------------------------------------------
aus_solar = pd.read_csv('./data/project.csv').fillna(0)

def fig_aus2(size_max):
    fig = px.scatter_mapbox(
        aus_solar,
        lat='latitude',
        lon='longitude',
        size='DC Capacity (MWp)',
        size_max=size_max,
        hover_data=['Project/', 'DC Capacity (MWp)'],
        height=1000,
        zoom=4,
    )

    fig.update_traces(marker_color='red')

    fig.update_layout(
        mapbox_style='open-street-map',
        margin=dict(l=0, r=0, t=0, b=0),
    )
    return fig

then in your callback:

@app.callback(
    Output('map', 'figure'),
    Input('max_size', 'value'),
)
def update_graph(value):
    return graph.fig_aus2(value)

I was going to propose you, as suggested by @AIMPED, to create your figure at startup and then update only the max_size in your figure, not the whole figure.
But actually it is a little more complicated than I expected, max_size is not a property of the scattermapbox figure, you must update the sizeref which depend on max_size you provide, and the max value of 'DC Capacity (MWp)' you use for the size parameter…

Tell me if you want to try with a Patch(), I’ll do it :slightly_smiling_face: