✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
🧬 Learn how to build RNA-Seq data apps with Python & Dash. Register for the May 20 Webinar!

How to make dynamic graph generating Web. NEED IDEAS and HELP!

Hello,
I’m trying to make website that generates graphs.
This is what I’ve done.

  1. get file from user input
  2. let user select row and column
  3. generate graphs with row and column. Ex) row=3, col=4, generate 12 graphs in 3X4 grid.
    I used bootstrap row and col here.
  4. When generating graph, I put individual IDs to the graph.

And this is what I am trying to make.

  1. when I click graph, graph changes background color to red. If I click again, return to normal.
  2. if bg color is red, it means graph is selected.
  3. if I press a button, I want selected graphs show on different window.

so far, I tried to do this by collecting ID’s of graphs in dcc.Store with callback function. So, when I click a graph, I can check whether the graph’s ID is in the dcc.Store and update bg color and dcc.Store itself. But, since I put callback functions for each graphs, I cannot set dcc.Store as output for all callback functions.

here’s my code. This is callback function for each graphs

def select_graphs(clickData, input_name, graphWrapperId, selected_lists):
    if(clickData != None):
        raw = mne.io.Raw(input_name, preload=True)
        print(raw.info)
        
        picks = mne.pick_types(raw.info, meg='grad', exclude=[])
        start, stop = raw.time_as_index([0, 5])
        
        n_channels = 20
        data, times = raw[picks[:n_channels], start:stop]
        ch_names = [raw.info['ch_names'][p] for p in picks[:n_channels]]
        print("ch names : ", *ch_names)
        
        print(clickData)
        
        i = int(graphWrapperId[-1])
        #if graph Id is not in the list, append it and change bg color to red.
        if(graphWrapperId not in selected_lists): 
            selected_lists.append(graphWrapperId)
            
            fig=dict(
                        data=[dict(
                            x=times, y=data.T[:, i], type='scattergl'
                        )],
                        layout=dict(
                            plot_bgcolor='rgb(255, 0, 0)',
                            title='Figure ' + str(i + 1),
                            font=dict(family='Arial, monospace', size=10),
                            autosize=True,
                            margin=dict(l=50, r=50, b=30, t=30, pad=0),
                            yaxis=dict(title='Month', linewidth=1, mirror=True),
                            xaxis=dict(title='Time', linewidth=1, mirror=True),
                        )
                    )
            return fig, selected_lists
        #if graph is already in the list and bg color is red, then remove graph from the list and set bg color to white
        else:
            selected_lists.remove(graphWrapperId)
            
            fig=dict(
                        data=[dict(
                            x=times, y=data.T[:, i], type='scattergl'
                        )],
                        layout=dict(
                            plot_bgcolor='rgb(255, 255, 255)',
                            title='Figure ' + str(i + 1),
                            font=dict(family='Arial, monospace', size=10),
                            autosize=True,
                            margin=dict(l=50, r=50, b=30, t=30, pad=0),
                            yaxis=dict(title='Month', linewidth=1, mirror=True),
                            xaxis=dict(title='Time', linewidth=1, mirror=True),
                        )
                    )
            return fig, selected_lists       
    else:
        return dash.exceptions.PreventUpdate

for i in range(40):
    app.callback(
        [Output('graph-{}'.format(i), 'figure'),
          Output('selected-graphs', 'children')],
        [Input('graph-{}'.format(i), 'clickData')],
          [State('file-input', 'filename'),
            State('graphWrapper-{}'.format(i), 'id'),
            State('selected-graphs', 'children')]
        )(select_graphs)

this is callback function for generating graphs.

@app.callback(
    Output('eeg-graphs', 'children'),
    [Input('file-input', 'filename'),
      Input('row-dropdown', 'value'),
      Input('col-dropdown', 'value')]    
)
def generate_graph(input_name, row, col):
     
    raw = mne.io.Raw(input_name, preload=True)
    print(raw.info)
    
    picks = mne.pick_types(raw.info, meg='grad', exclude=[])
    start, stop = raw.time_as_index([0, 5])
    
    n_channels = row * col
    data, times = raw[picks[:n_channels], start:stop]
    ch_names = [raw.info['ch_names'][p] for p in picks[:n_channels]]
    print("ch names : ", *ch_names)
    

    row_list = []
    col_list = []
    i = 0
    #append to row_list with className = "row"/ using bootstrap
    for r in range(0, row):
        #append to col_list with className = "col"/ using bootstrap
        for c in range(0, col):
            col_list.append(
                html.Div(
                    className = "col-md-3",
                    id = 'graphWrapper-{}'.format(i),
                                   children = [
                                    # mydcc.Relayout( id = "reGraph-{}".format(i), aim = 'graph-{}'.format(i) ),
                                    dcc.Graph(
                                    style={'width': '100%', 'height': '100%'},
                                    # config={'displaylogo': False, 'editable': True, 'displayModeBar': False},
                                    id='graph-{}'.format(i),
                                    figure=dict(
                                        data=[dict(
                                            x=times, y=data.T[:, i], type='scattergl'
                                        )],
                                        layout=dict(
                                            plot_bgcolor='rgb(255, 255, 255)',
                                            title='Figure ' + str(i + 1),
                                            font=dict(family='Arial, monospace', size=10),
                                            autosize=True,
                                            margin=dict(l=50, r=50, b=30, t=30, pad=0),
                                            yaxis=dict(title='Month', linewidth=1, mirror=True),
                                            xaxis=dict(title='Time', linewidth=1, mirror=True),
                                        )
                                        )
                                    )]
                                    )        
                                  )
            i+=1
            print("=================col_list" , *col_list)
        row_list.append(html.Div(className = "row",
                                      id = 'row-{}'.format(r),
                                      children = col_list))
        col_list = []
        print("===============row_list", len(row_list))
        
    return row_list   

Any ideas or suggestions are welcomed.