dash-cytoscape
dash-cytoscape copied to clipboard
Adding Support for networkX
Description
At the moment, conversion between networkX graphs and Dash Cytoscape networks have to be done manually. In order to make it easier for everyone to integrate networkX in their Dash workflow, we would like to improve support for the library. Please let us know your thoughts, and we highly appreciate if you would like to contribute!
What would be the implications of using networkX objects as the Python interface for the library? This goes along with #20 and kills two birds with one stone. IMO, this would be better than writing a separate graph representation and translating between the formats: less opportunity for bugs in the graph code, more familliary for users of networkX (along with "free" documentation), less work supporting various features. The js/dict representation would still be available, ideally.
I'm unsure what to do about styling. The way networkX works, when plotting to matplotlib: generate a layout, plot shapes. I assume dash-cytoscape would use its own class for positions, or maybe just use specific node attributes from networkX.
I could try to get a prototype of some kind working, as I've done some of the manual translation mentioned. However my experience with web/reactive programming is quite limited (and so is my time, haha), so I'd prefer filtering out bad ideas before implementing them and throwing them out due to infeasibility. 😋
To offer a parallel, the dash-table uses d3-format for number formatting. While the library is very powerful and can respond to almost all the needs we have, it has been partially abstracted to allow additional features to be added. While it is very standard from a JS developer standpoint, some things do stand out for a Python dev.
The user can directly use the props:
- the specifier nested prop -- this prop offers no abstraction over the d3-format implementation
- thelocale nested prop to configure the format -- this props offers some abstractions / additional features
Preferably, the user can also use the Python helper functions here and here to create d3-format configurations without being tied down to a specific library.
This way the table's 3rd party formatting library can change in the future without impacting usage.. or an additional library could be used for other types or cases without the user necessarily knowing about it.
@xhlulu Not knowing NetworkX or its specific niche, I will only provide general guidance / questions. Some of these questions might be a little foolish in this specific case.
- Is NetworkX the only significant library for representing network graphs?
- Are there other libraries that can do better than it in specific cases that we want or need to support?
- What are the consequences of that library choice in non-Python environments that we want/need to support? Could an R dev provide the desired structure easily through an equivalent library? Does this matter for this specific component?
- Is this project/repo seem healthy on the long run?
- What is the nature of the JS implementation? Does supporting NetworkX structure as (possibly the only) first class citizen make sense there? Does it cover all we could want to support?
A negative answer to any of the above should at least warrant a deeper look.
Just some food for thought...
...I am currently assembling visualizations using Dash-Cytoscape with my NetworkX graphs. In answer to some of the above questions, for better or for worse, NetworkX is the de facto standard graphing library for Python. There are others out there, but most Python-based graph work occurs in NetworkX. The visualization capabilities though are incredibly limited, presenting a good value proposition for Dash-Cytoscape.
As it currently stands, with my graphs I have to assemble them via NetworkX. I then have to use nx.nx_agraph.graphviz_layout()
to get the (x,y)
positions of the nodes, required by Cytoscape. From there, I think have to use nx.readwrite.json_graph.cytoscape_data()
in order to get the NetworkX Graph object into Cytoscape format. I then have to do a bunch of munging to get the final element list format, since this final step does not include the (x,y)
positions.
In other words, there is a lot of munging that must occur by virtue of the fact that the most common graph library for Python is being used.
I comment on this because I know that I, for one, would have a lot of time saved if NetworkX was natively supported by Dash-Cytoscape.
As a side note, plotly docs reference networkX directly: https://plot.ly/python/network-graphs/
It's also the first search relevant result for "python graph library" and "python network graph".
When looking at different variants of graph libraries a few months ago, I settled on Networkx due to its flexibility of being able to use any hashable objects as nodes (and the dict-of-dict structure). It also felt the most mature to me, at least at the time. It definitely makes sense to look at other alternatives and make a conscious decision.
Concerning R compatability... I'm not sure such a flexible library exists or is even possible to natively implement. C++/boost's graph libraries have a Python binding here: https://graph-tool.skewed.de, perhaps an R one exists. However, from a purely Python PoV, it's much more convenient to use objects instead of ID's. What portion of the target user base is on which language?
IMO, it at least makes sense to hold a representation in the Python side of dash-cytoscape (currently, as I understand, the js side is asked every time in callbacks) that holds at least the node/edge information, if not also "last known position/styling/etc" for each node. For Python, that could be translated through a networkX graph as the implementation detail, for example. Translating between networkX graphs, or providing "views" or something, is much easier than translating all graph types by hand, for the end user.
(R could use the raw json representation, an existing or custom graph library.)
There is a parallel discussion and work being done by @cj2001 in the community forum here: https://community.plot.ly/t/converting-networkx-graph-object-into-cytoscape-format/23224. Working with nx.readwrite.json_graph.cytoscape_data()
seems like the right approach.
Once we have a robust networkx -> cytoscape converter, we can include that python function within this package so that the code becomes something like:
cyto_description = dash_cytoscape.converters.networkx(nx)
app.layout = dash_cytoscape.Cytoscape(elements=cyto_description['elements'], style=cyto_description['style'])
This is roughly the approach that we've used in the past with things like MATLAB/matplotlib -> plotly converters.
I'd recommend starting with the elements description first, and then doing the style conversions later. So form/function before style.
Any update to this?
Sadly I have had to move on to other solutions. I hope you can get something into prod soon!
Any updates on this?
any updates?