I’m setting up a plotly-dash website where I want to show data from some domains from different points in time. Therefore I have a slider with which you can decide which data from which point in time you want to see. That already works. Moreover I want that if somebody clicks on one point it shows a line between all positions of this domain from every point in time.
I have tried to define an update function, so that I update the data for the trace with the line in it. However the graph itself does not look different after the update.
# create underlying figure fig = go.Figure() for date in file.date.unique(): f = file.loc[file["date"] == date] fig.add_trace(go.Scatter(x = f.x, y = f.y, mode="markers", name = date, hovertext = f.domains, visible = False, marker=dict( color=['#a3a7e4'] * len(f.x), size=[5] * len(f.x) ), )) # trace of path dom="xxx" filt = file.loc[file["domains"] == dom] x_ = filt.x y_ = filt.y fig.add_trace(go.Scatter( x = x_, y = y_, hovertext= dom, name='"'+ dom +'"' + " development path", visible=True, mode='lines' )) # Create and add slider steps = [] for i in range(len(fig.data)-1): step = dict( method="restyle", args=["visible", [False] * len(fig.data)], label=fig.data[i].name ) step["args"][1][i] = True # Toggle i'th trace to "visible" steps.append(step) sliders = [dict( active=10, currentvalue={"prefix": "Date: "}, pad={"t": 50}, steps=steps )] # create widget from figure f = go.FigureWidget(data=fig.data, layout=fig.layout) # create our callback function def update_point(trace, points, selector): filter_2 = file[(file["x"] == points.xs[0]) & (file["y"] == points.ys[0])] domain = filter_2.domains.values[0] print(domain) small_df = file[file["domains"] == domain] fig.data[-1].hovertext = domain fig.data[-1].name = '"' + domain + '"' + " development path" fig.data[-1].x = small_df.x.values fig.data[-1].y = small_df.y.values fig.update_traces(visible=True, selector=dict(mode="line")) f = go.FigureWidget(data=fig.data, layout=fig.layout) f for i in range(len(fig.data)-1): if f.data[i].visible is True: f.data[i].on_click(update_point) f
I just want the graph to be updated as well, not just the underlying data.
Advertisement
Answer
Have a look at Dash callbacks here:
https://dash.plot.ly/getting-started-part-2
In short, you need to add decorators to your callbacks which says which input triggers the callback and which graph needs to be updated on a callback run. You cannot trigger a callback programmatically and expect it to change the graph. The callback needs to come from the UI, as far as I know.
Eg:
app.layout = html.Div([ dcc.Input(id='my-id', value='initial value', type='text'), html.Div(id='my-div') ]) @app.callback( Output(component_id='my-div', component_property='children'), [Input(component_id='my-id', component_property='value')] ) def update_output_div(input_value): return 'You have entered "{}"'.format(input_value)
This example expects the callback to be triggered when the input with id “my-id” has a change in value, and in return, it changes the value of the div. The “Output” in the decorator needs to be your graph if you need a callback to change a graph.