Dash Cytoscape
Dash Cytoscape is a component library for Dash, enabling interactive network visualization in Python applications. It wraps the powerful Cytoscape.js library and offers deep integration with Dash layouts and callbacks, facilitating the creation of sophisticated graphs from data, including those from libraries like NetworkX. The current version is 1.0.2, with active development and regular updates.
Common errors
-
Dash Cytoscape callbacks not firing
cause The callback function was defined after `app.run_server()` or `app.run()` in the script.fixMove all `@app.callback` definitions and their functions to appear before the `if __name__ == '__main__': app.run_server(debug=True)` block. -
TypeError: Cannot read properties of undefined (reading 'length') when elements is not specified
cause The `elements` property of the `cyto.Cytoscape` component was not provided or was `None`.fixEnsure the `elements` property is always a list of nodes and edges, even if empty (`elements=[]`). This issue was fixed in `dash-cytoscape` version 0.1.1 but can still occur with incorrect usage. -
Graph showing incorrect connections or overlapping nodes after update, networks fused together based on common ID
cause When updating the `elements` property, new nodes or edges were introduced with IDs that already existed in the previous graph state. The underlying Cytoscape.js library can conflate elements with identical IDs, leading to unexpected graph structures.fixEnsure all node and edge IDs are unique across all elements present in the graph at any given time, especially when dynamically modifying or replacing the graph content. -
Dash app crashes without error message or restarts frequently when using Cytoscape component.
cause This can sometimes occur with complex or very large graphs, potentially related to memory usage or issues within the underlying JavaScript rendering. It might also be related to specific environment configurations or resource limitations.fixTry simplifying the graph, optimizing `stylesheet` definitions, or reducing the number of `elements`. Consider restarting the Python environment or the operating system. Check browser developer console for any JavaScript errors. For very large graphs, consider server-side rendering or pagination if applicable.
Warnings
- breaking Support for Python 3.7 and below was dropped in `dash-cytoscape` version 1.0.0. The new minimum Python version is 3.8.
- gotcha When dynamically updating the graph with new `elements` (nodes and edges), ensure that node and edge IDs are unique. Reusing IDs can lead to networks fusing or unexpected behavior due to the underlying Cytoscape.js library not properly cleaning the object.
- gotcha Callbacks must be defined *before* `app.run_server()`. If a `@app.callback` decorator and its associated function are placed after `app.run_server()`, the callback will not be registered and will not fire.
- gotcha When modifying `elements` inside a callback, you should return a *new* list/dictionary of elements rather than mutating the original object passed as `State`. Direct mutation of objects received via `State` can lead to update cycles being broken or inconsistent behavior.
- deprecated The `dash_html_components` and `dash_core_components` imports were removed from `install_requires` in older versions. While still usable, components like `html.Div` are now typically imported directly from `dash`.
Install
-
pip install dash-cytoscape -
pip install dash-cytoscape[leaflet]
Imports
- Cytoscape
import dash_cytoscape from dash import Dash, html # then use dash_cytoscape.Cytoscape
import dash_cytoscape as cyto from dash import Dash, html
- load_extra_layouts
import dash_cytoscape as cyto cyto.load_extra_layouts()
Quickstart
from dash import Dash, html
import dash_cytoscape as cyto
app = Dash(__name__)
app.layout = html.Div([
cyto.Cytoscape(
id='cytoscape-two-nodes',
layout={'name': 'preset'},
style={'width': '100%', 'height': '400px'},
elements=[
{'data': {'id': 'one', 'label': 'Node 1'}, 'position': {'x': 75, 'y': 75}},
{'data': {'id': 'two', 'label': 'Node 2'}, 'position': {'x': 200, 'y': 200}},
{'data': {'source': 'one', 'target': 'two', 'label': 'Node 1 to 2'}}
],
stylesheet=[
{
'selector': 'node',
'style': {
'background-color': '#BFD7B5',
'label': 'data(label)'
}
},
{
'selector': 'edge',
'style': {
'line-color': '#A3C4BC',
'label': 'data(label)'
}
}
]
)
])
if __name__ == '__main__':
app.run_server(debug=True)