plotly / dash-cytoscape

Interactive network visualization in Python and Dash, powered by Cytoscape.js
https://dash.plot.ly/cytoscape
MIT License
586 stars 120 forks source link

Dash fails to load extra layouts: No such layout `cola` found. #194

Open Lukas-Vasionis opened 10 months ago

Lukas-Vasionis commented 10 months ago

Description

I created an app with Cytoscape graph that sometimes throws out the error. It occurs randomly, and sometimes I get rid of it by restarting PyCharm. For some reason it doesn't read cyto.load_extra_layouts() in get_fig_cytoscape(df, layout)

EDIT: I noticed that problem occurs when I edit this script while it is in use. Re-executing the script doesn't help - then i must restart the PyCharm

Steps/Code to Reproduce

Example:

from my_lib import utils as gu
from dash import Dash, dcc, html, Output, Input, callback, dash_table, callback_context
import dash_bootstrap_components as dbc

df = gu.get_data_about_tbls_n_cols(pdsa)

def get_fig_cytoscape(df, layout):

    cyto.load_extra_layouts()

    node_elements = df['table_x'].unique().tolist() + df['table_y'].unique().tolist()
    node_elements = [{'data': {'id': x, 'label': x}} for x in node_elements]

    edge_elements = [{'data': {'source': x, 'target': y}} for x, y in zip(df["table_x"], df["table_y"])]

    fig_cyto = cyto.Cytoscape(
        id='org-chart',
        # zoom=len(node_elements)*2,
        boxSelectionEnabled=True,
        responsive=True,
        layout={
            'name': layout,
            'clusters': 'clusterInfo',
            'animate': False,
            'idealInterClusterEdgeLengthCoefficient': 0.5,
            'fit': True},
        style={'width': '100%', "height": "500pt"},
        elements=node_elements + edge_elements,
        stylesheet=[
            {'selector': 'label', 
             'style': {'content': 'data(label)',  
                       'color': 'black',
                       'line-color': 'grey',

                       'background-color': 'blue'  
                       }},
            {"selector": "edge",
             "style": {"weight": 1}}
        ]
    )

app = Dash(__name__)

app.layout = html.Div(
    children=[
        dbc.Row(
            children=[
                dbc.Col(
                    style={"float": "left", "width": "50%"},
                    children=
                    html.Div(id="my-network",
                             # children=get_fig_cytoscape(df, layout="cola")
                             ),
                    width=6
                ),
                dbc.Col(
                    style={"float": "left", "width": "50%"},
                    children=
                    html.Div(
                        children=[
                            html.Div(children=[
                                html.P("Select your layout"),
                                dcc.Dropdown(id="dropdown-layouts",
                                             options=["random", "preset", "circle", "concentric", "grid",
                                                      "breadthfirst", "cose", "close-bilkent",
                                                      "cola", "euler", "spread", "dagre", "klay"],
                                             value='cola',
                                             style={"width":"50%"})],
                            ),

                            html.Div(children=[
                                html.P("Add list of tables to graph (comma separated)"),
                                dcc.Input(
                                    id="input-list-tables", style={"width":"100%"})
                            ]),
                        ]
                    ),
                    width=6
                )
            ]
        )
    ])

@ callback(
    Output('my-network', 'children'),
    Input("dropdown-layouts", 'value'),
    Input("dropdown-tables", 'value'),
    Input("input-list-tables","value"),
)

def get_network(layout, selected_dropdown_tables, input_list):
    selected_tables = selected_dropdown_tables + input_list
    df_filtered = df.loc[ df['table_x'].isin(selected_tables) | df['table_y'].isin(selected_tables), :]

    G = get_fig_cytoscape(df_filtered, layout)
    return G

Expected Results

It should read cyto.load_extra_layouts() in get_fig_cytoscape(df, layout) function and open the network graph of cytoscape.

Actual Results

Instead, I get an error and the graph fails to load and respond to callbacks. I noticed that it occurs when I add a new element in the app layout (e.g. the whole div where input-list-tables resides).

_Error: No such layout `cola` found.  Did you forget to import it and `cytoscape.use()` it?
at error (webpack-internal:///./node_modules/cytoscape/dist/cytoscape.cjs.js:828:9)
at Core.layout (webpack-internal:///./node_modules/cytoscape/dist/cytoscape.cjs.js:14250:7)
at l (webpack-internal:///./node_modules/react-cytoscapejs/dist/react-cytoscape.js:1:6814)
at t.patch (webpack-internal:///./node_modules/react-cytoscapejs/dist/react-cytoscape.js:1:6687)
at t.value (webpack-internal:///./node_modules/react-cytoscapejs/dist/react-cytoscape.js:1:4242)
at t.value (webpack-internal:///./node_modules/react-cytoscapejs/dist/react-cytoscape.js:1:4098)
at commitLifeCycles (http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v2_13_0m1694674558.14.0.js:19949:24)
at commitLayoutEffects (http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v2_13_0m1694674558.14.0.js:22938:9)
at HTMLUnknownElement.callCallback (http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v2_13_0m1694674558.14.0.js:182:16)
at Object.invokeGuardedCallbackDev (http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v2_13_0m1694674558.14.0.js:231:18)_

Sometimes it can be fixed by uncommenting get_fig_cytoscape(df, layout="cola") inside div of app layout.

Versions

Dash 2.13.0
Dash Core Components 2.0.14
Dash HTML Components 2.12.0
C:\Users\user\Documents\Projects\PyCharm Projects\pdsa-grapher-git\pdsa-grapher\devs.py:3: UserWarning: 
The dash_html_components package is deprecated. Please replace
`import dash_html_components as html` with `from dash import html`
  import dash_html_components; print("Dash Core Components", dash_html_components.__version__)
C:\Users\user\Documents\Projects\PyCharm Projects\pdsa-grapher-git\pdsa-grapher\devs.py:4: UserWarning: 
The dash_core_components package is deprecated. Please replace
`import dash_core_components as dcc` with `from dash import dcc`
  import dash_core_components; print("Dash HTML Components", dash_core_components.__version__)
Traceback (most recent call last):
  File "C:\Users\user\Documents\Projects\PyCharm Projects\pdsa-grapher-git\pdsa-grapher\devs.py", line 5, in <module>
    import dash_renderer; print("Dash Renderer", dash_renderer.__version)
    ^^^^^^^^^^^^^^^^^^^^
ModuleNotFoundError: No module named 'dash_renderer'
Wheest commented 2 weeks ago

I also experiencing this issue.

cyto.__version__ = '1.0.1'

For some reason restarting the app a few times and moving some code around helped. I'm not sure a cache was getting misused or something.