I have a callback set_epoch_count()
that creates sliders based on some select data. I then want to use these sliders to call display_graph()
whenever a given slider value changes to then update a graph. However, as of right now, when I change one of the dynamically generated slider it does not update the graph, i.e. it does not run the display_graph()
function.
I didn’t post all the code because there is a lot more. However, I did post the two callbacks in questions. If anyone has any ideas about what I’m doing wrong here it would be great appreciated. If you need additional code please let me know as well.
Im also running this code in Jupyter Notebook with Jupyter Dash.
@app.callback(
[Output('epoch-sliders', 'children')],
[Input('group-dropdown', 'value'),
Input('dataset-dropdown', 'value'),
Input('subject-dropdown', 'value'),
Input('event-id-dropdown', 'value')],
[State({'type': 'dynamic-sliders', 'index': ALL}, 'value'),
State({'type': 'dynamic-sliders', 'index': ALL}, 'id'),
State({'type': 'dynamic-sliders', 'index': ALL}, 'max')])
def set_epoch_count(group, dataset, subject, event, epoch_value, epoch_id, epoch_max):
children = []
if None in (group, dataset, subject, event):
raise PreventUpdate
data = grps.data_map.loc[group, dataset, subject]
if len(data.ravel()) == 0:
raise PreventUpdate
prev_epochs = {i['index']: [v, m] for i,v,m in zip(epoch_id, epoch_value, epoch_max)}
print('PREV', prev_epochs)
for _, d in data.groupby(['group', 'dataset', 'subject']):
for e in event:
key, _ = get_epoch_keys(d, e)
if key in prev_epochs:
e_max = prev_epochs[key][1]
e_value = prev_epochs[key][0]
else:
e_max = len(d[0].data.events[d[0].data.events == e])
e_value = e_max
new_element = html.Div([
html.Label(key, style={'width':'10%', 'display': 'inline-block',}),
dcc.Slider(
id={'type': 'dynamic-sliders', 'index': key},
step=1,
min=1,
max=e_max,
value=e_value,
updatemode='mouseup',
tooltip=dict(always_visible=True)
)
], style= {'width':'90%', 'display': 'inline-block'})
children.append(new_element)
print("CHILDREN: {} \n {}".format(type(children), children))
return [children]
@app.callback(
Output({'type': 'graph', 'index': MATCH}, 'figure'),
[Input('group-dropdown', 'value'),
Input('dataset-dropdown', 'value'),
Input('subject-dropdown', 'value'),
Input('event-id-dropdown', 'value'),
Input('channel-dropdown', 'value'),
Input('high-pass-input', 'value'),
Input('low-pass-input', 'value'),
Input('plot-items', 'value'),
Input({'type': 'dynamic-sliders', 'index': ALL}, 'value')],
[State({'type': 'dynamic-sliders', 'index': ALL}, 'id')])
def display_graph(
group, dataset, subject, event, channel,
high_pass, low_pass, plot_type,
epoch_values, epoch_ids
):
print('DISPLAY GRAPH')
plot_args = (group, dataset, subject, event, channel)
# Bandaid fix for catching exceptions as drop down menu options are filled out.
# Ideally, all options would be completed before plotting, this is an easier
# solution for now.
print("PLOT ARGS:\n", plot_args)
if None in plot_args:
return px.line()
elif any([len(arg) == 0 for arg in plot_args]):
return px.line()
mne_filter_kws = dict(low_pass=low_pass, high_pass=high_pass)
# Convert dyanmic sliders into dict of values
# parse slider id to get indexes
print(epoch_values, epoch_ids)
epochs = {i['index']: v for i, v in zip(epoch_ids, epoch_values)}
print('epochs', epochs)
if plot_type == 'GA':
fig, _ = plot_grand_average(group=group,
dataset=dataset,
subject=subject,
event=event,
channel=channel,
mne_filter_kws=mne_filter_kws,
epochs=epochs)
elif plot_type == 'SA':
fig, _ = plot_subject_average(group=group,
dataset=dataset,
subject=subject,
event=event,
channel=channel,
mne_filter_kws=mne_filter_kws,
epochs=epochs)
elif plot_type == 'SA+GA':
pass
return fig