'Dash callback duplicate issue - Python
I have a dashboard built with dash-plotly of this structure:
app.layout = html.Div(
children=[
html.Div(children=[
html.Div(children=[dcc.Dropdown(options=[
{'label': 'Viability', 'value':'fig_viability'},
{'label': 'Mean Diameter', 'value': 'fig_diameter'},
{'label': 'Concentration', 'value': 'fig_concentration'}],
id='graph-selector')]]),
html.Div(children=[
dcc.Graph(id='graph'),
dcc.Interval(
id='interval-component',
interval=15 * 1000, # in milliseconds
n_intervals=0)])])])
I am trying to make an app displaying 3 different graphs based on the dropdown choice. The thing is that the excel files which serve as a source of data will be changed every couple of minutes. I tried to use "Interval" component to make this live graph update but I think I messed up somewhere in callbacks, as it throws me an error:
"In the callback for output(s): graph.figure Output 0 (graph.figure) is already in use. Any given output can only have one callback that sets it."
My callbacks and excel file manipulations are below:
@app.callback(Output('graph', 'children'),
[Input('interval-component', 'n_intervals')])
def update_figures(n):
df = pd.read_excel(...)
fig_viability = px.scatter(df,
x="Sample Name",
y="Result",
color="Sample Name",
template='plotly_dark').update_layout(
{'title': 'Viability Plot (%)',
'modebar_add': ['v1hovermode', 'toggleSpikelines'],
'plot_bgcolor': 'rgba(0, 0, 0, 0)',
'paper_bgcolor': 'rgba(0, 0, 0, 255)'})
fig_diameter = px.scatter(df,
x="Sample Name",
y="Mean Diameter (microns)",
color="Sample Name",
template='plotly_dark').update_layout(
{'modebar_add': ['v1hovermode', 'toggleSpikelines'],
'title': 'Mean diameter Plot (microns)',
'plot_bgcolor': 'rgba(0, 0, 0, 0)',
'paper_bgcolor': 'rgba(0, 0, 0, 255)'})
fig_concentration = px.scatter(df,
x="Sample Name",
y="Concentration",
color="Sample Name",
template='plotly_dark').update_layout(
{'title': 'Concentration Plot',
'modebar_add': ['v1hovermode', 'toggleSpikelines'],
'plot_bgcolor': 'rgba(0, 0, 0, 0)',
'paper_bgcolor': 'rgba(0, 0, 0, 255)'})
@app.callback(
Output('graph', 'figure'),
[Input(component_id='graph-selector', component_property='value')]
)
def select_graph(value):
if value == 'fig_viability':
return fig_viability
elif value == 'fig_diameter':
return fig_diameter
else:
return fig_concentration
Sorry if that's too wordy, I am newbie to Python and Dash, so tried to give as much detail as possible. Prior to plotting the excel file, three discrete files have to be combined to get this one common file with all the data. The issue is that these files will be changed, as I mentioned earlier, hence the need for live updating.
I hope someone will know how to do it better.. :(
P.S. The data frame looks like this:
Sample Name Result Concentration Mean Diameter
0 A 244 122 8
1 A 150 8 3
2 A 133 78 10
3 B 567 34 40
4 B 122 622 4
5 B 100 180 20
6 C 55 20 12
7 C 10 11 50
8 C 76 230 37
9 D 230 67 2
Solution 1:[1]
In the current version (2.3.0) of Dash, an element can only be targeted as an Output by a single callback. You can work around the limitation by bundling callbacks with subsequent branching based on the callback context, but it quickly becomes cumbersome.
An alternative is to use dash-extensions (can be installed via pip). After installing, simply replace your dash imports with their counter parts from the enrich module,
from dash_extensions.enrich import Dash, Input, State, Output, html, dcc
and it should work without any code changes.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | emher |
