How to update Cytoscape elements(list of dics) using Patch()

Im using Cytoscape Network Graph into my Dash app.

My Dash app creates, deletes, and modifies the nodes of a graph.
Since the size of graph is big, using Patch Component seems very efficient.
However, since the datatype of the graph elements are list of dictionaries, I’m unsure how to update it with patches.
For instance, I understand how to add elements using a patch in examples like the one provided by adamschroeder(below), but I dont get how to modify specific elements.

For example, "how to find a data id which is ‘id_5’ and change its label value to ‘Check_5’.

Thankyou.

Network Graph (Cytoscape):

from dash import Dash, html, Output, Input, Patch, State
import dash_cytoscape as cyto

app = Dash(__name__)
original_elements = [
            # The nodes elements
            {'data': {'id': 'id_1', 'label': 'Node 1'},
             'position': {'x': 50, 'y': 50}},
            {'data': {'id': 'id_2', 'label': 'Node 2'},
             'position': {'x': 200, 'y': 200}},

            # The edge elements
            {'data': {'source': 'id_1', 'target': 'id_2', 'label': 'Node 1 to 2'}},
]
app.layout = html.Div([
    html.Button("Update Cytoscape", id="add-data", n_clicks=2),
    cyto.Cytoscape(
        id='my-cytoscape',
        layout={'name': 'preset'},
        style={'width': '100%', 'height': '400px'},
        elements=original_elements
    )
])

@app.callback(
    Output("my-cytoscape", "elements"),
    Input("add-data", "n_clicks"),
    prevent_initial_call=True,
)
def add_data_to_fig(n_clicks):
    patched_cyto = Patch()
    patched_cyto.append({'data': {'id': f'id_{n_clicks}', 'label': f'Node {n_clicks}'},
                         'position': {'x': 10*n_clicks, 'y': 10*n_clicks}})
    patched_cyto.append({'data': {'source': f'id_{n_clicks-1}', 'target': f'id_{n_clicks}', 'label': f'Node {n_clicks-1} to {n_clicks}'}})
    return patched_cyto


if __name__ == '__main__':
    app.run_server(debug=True)

nodes

Updating Charts

Use elements as State and enumerate them. To find the index for your Patch

@app.callback(
    Output('cytoscape', 'elements', allow_duplicate=True),
    Output('select_all', 'children'),
    Input('select_all', 'n_clicks'),
    State('cytoscape', 'elements'),
    State('select_all', 'children'),
    prevent_initial_call = True
)
def select_all(n, current_elements, text):
    if not ctx.triggered_id:
        raise PreventUpdate
    if ((n==None or n==0) and ctx.triggered_id=='select_all'):
        raise PreventUpdate
    elements_patch = Patch()

    if ctx.triggered_id == 'select_all':
        if text == 'Select All':
            for i, element in enumerate(current_elements): 
                #Check if its the node you want
                if 'id' in element['data']:
                    elements_patch[i]['classes'] = 'selected'
            return elements_patch, 'Unselect All'
        else:
            for i, element in enumerate(current_elements): 
                if 'id' in element['data']:
                    elements_patch[i]['classes'] = ''
            return elements_patch, 'Select All'
1 Like

Thanks, it works

1 Like