-
Notifications
You must be signed in to change notification settings - Fork 40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for NetworkX Multigraph? #45
Comments
Hi, Unfortunately, netgraph doesn't properly support multi-graphs, yet. However, it is a planned feature, albeit still some way off. Currently, if given a multi-graph, netgraph should raise a warning, remove duplicate edges, and plot the simplified graph. In the meantime, I know that pyvis has some support for multigraphs, although not without issues. If the graphs are layered multi-graphs, there is also pymnet, or this stackoverflow answer. All in all, however, the state of multigraph visualisation tools is pretty poor in python, so personally, I would probably export my network to a dot file, and then draw the graph with graphviz. |
…rkx.MultiGraph objects (issue #45)
I was able to plot MultiGraph and MultiDiGraph objects (with collapsed edges) by modifying
|
Hi @kcharlie2, the
|
It looks like the collapsed edges are only returned if there are duplicate edges. If you have a
|
I have this problem as well and it would be great if that issue might be mitigated. Would a pull-request help? |
Pull requests are always welcome but a minimum working example (including data) that results in an error would help me most. Then I can write some tests to prevent this and similar issues arising in the future. |
Very desirable feature. A lot of issues drawing multi-graphs across the graph library space. Some libraries support edge_drawing, but can't plot labels, others can draw only 2 edges, etc, etc. In short, couldn't find anything that just does the plot fine with all the data nicely. For now I wrote custom drawing functions for networkx that handle multiedges with labels, but I would rather see it implemented in a place where it belongs. I hacked the nx.draw_edges function to be called multiple times for edges and extended function from stack to handle more than 2 labels: |
Multi-graph support is already implemented on the dev branch. pip install https://github.com/paulbrodersen/netgraph/archive/dev.zip Edge labels track edges as they should. import numpy as np
import matplotlib.pyplot as plt
from netgraph import MultiGraph # see also: InteractiveMultiGraph, EditableMultiGraph
# Define the multi-graph.
# Adjacency matrix stacks (i.e. arrays with dimensions (layers, nodes, nodes)),
# networkx multi-graph, and igraph multi-graph objects are also supported.
my_multigraph = [
(0, 1, 0),
(0, 1, 1),
(0, 1, 2),
(1, 1, 0),
(1, 2, 0),
(2, 0, 0),
(0, 2, 0),
(0, 2, 1),
]
# Color edges by edge ID / type.
colors = ['tab:blue', 'tab:orange', 'tab:red']
edge_color = {(source, target, eid) : colors[eid] for (source, target, eid) in my_multigraph}
# Plot
node_positions = {
0 : np.array([0.2, 0.2]),
1 : np.array([0.5, 0.7]),
2 : np.array([0.8, 0.2]),
}
MultiGraph(
my_multigraph,
node_layout=node_positions,
edge_color=edge_color,
edge_layout='curved',
edge_layout_kwargs=dict(bundle_parallel_edges=False),
edge_labels=True,
edge_label_fontdict=dict(fontsize=6),
arrows=True,
)
plt.show() I am in the process of preparing a new major release. User-exposed functions and classes should have remained backwards compatible, but internally, I have changed a few things, primarily to facilitate writing the multi-graph classes. |
That's great. I will wait for a release then. Don't like messing with dev versions if there is no big need for it. |
Just a heads up that it might still be some time until the next release (months, not days). This library is maintained by an army of one, and mostly only during lunch breaks, as that one dude has a toddler and wife at home that both demand attention as well. |
Understandable. import numpy as np
import networkx as nx
import matplotlib.pyplot as plt
from netgraph import MultiGraph
G = nx.MultiDiGraph()
G.add_edge('a', 'b', w=1)
G.add_edge('a', 'b', w=2)
G.add_edge('a', 'b', w=3)
G.add_edge('b', 'c', w=4)
G.add_edge('b', 'c', w=5)
G.add_edge('c', 'a', w=6)
# Color edges by edge ID / type.
colors = ['tab:blue', 'tab:orange', 'tab:red']
edge_color = {(source, target, eid) : colors[eid] for (source, target, eid) in G.edges(keys=True)}
node_positions = {
'a': np.array([0.2, 0.8]),
'b' : np.array([0.5, 0.7]),
'c' : np.array([0.8, 0.2]),
}
edge_labels = {v[:3]: f'w={v[3]}' for v in G.edges(keys=True, data='w')}
MultiGraph(G,
node_layout=node_positions,
node_labels=True,
edge_color=edge_color,
edge_layout='curved',
edge_layout_kwargs=dict(bundle_parallel_edges=False),
edge_labels=edge_labels,
edge_label_fontdict=dict(fontsize=6),
arrows=True
)
plt.show() It might be convenient if edge labels could take in string of an attribute to use. But it would only save 1 fairly short line of code so not sure it's worth it... Do any of interactive and editable graphs work for MultiGraphs? |
Ok, checked it myself. All works, just 1 bug: https://github.com/paulbrodersen/netgraph/blob/dev/netgraph/_interactive_variants.py#L804 graph is not passed further here. Replacing with this worked for me. super().__init__(graph, *args, **kwargs) By "all works", I mean it plots ok, but not sure about editing. But I use 'qtagg' backend. wx and tkinter are pain to install on mac so can't check. |
It would be convenient and I did think about it but the way everything else is structured (or at least was structured at the time) meant that the code complexity would have increased quite a bit. Hard to justify working for long on such a small convenience feature when there are elephants in the room -- as e.g. multi-graph support.
Good catch. I messed around with that part just the other day, when I was trying to improve the readability of some of the more cryptic parts of the code base. Go figure. Will fix presently.
Editing should work, too, if you are using QtAgg. I have only had issues with the MacOsX backend. |
…utableMultiGraph Thanks to @dgrigonis. See #45 (comment)
It plots, but can't do anything with it. I installed PyQt6. I have never seen editable matplotlib plots, maybe I am missing something? |
Are you using an IDE such as pycharm or a notebook such as google colabs or jupyter? |
Just running script from shell. I get a pop-up window, which is interactive. I can zoom, drag, etc. But can't drag nodes. |
Are you retaining a reference to the g = EditableMultiGraph(my_multigraph, ...)
plt.show() |
That was it, thank you! Great work. I am starting to use graphs more and more, this library will definitely be useful. Not only works, but looks super nice too. |
Cheers. Let me know if you find any other bugs. ;-) |
One more thing, these label params work nice: edge_label_fontdict=dict(
fontsize=6, bbox=dict(color='white', pad=0)),
I wouldn't suggest this if it was top level parameter, but it is 3 layers down, thought maybe having a good default is convenient. |
Whatever that means... (I do get it though. It's mostly there for arc diagrams.)
"bundled" is very expensive. Anything above a few hundred edges can take minutes and even hours to compute. Also, it will never work well with edge labels as edges are meant to bundle and hence overlap. So, yeah.
I am working on making it more reliable but I do know what you mean. When I first implemented it, the algorithm seemed nice on the surface (a straightforward extension of the Fruchterman-Reingold algrithm for node layouts). Since then, it has been the bane of my existence as it is very brittle and you keep running into edge cases. Easily the most time spent / line of code in the whole library.
I think this is the best solution for this particular problem. I really don't want to complicate the basic "straight" edge routing as that one needs to be fast to support a variety of computations. |
…utableGraph Thanks to @dgrigonis. See #45 (comment)
From: dict(boxstyle='round', ec=(1.0, 1.0, 1.0), fc=(1.0, 1.0, 1.0)) To: dict(color="white", pad=0) Thanks @dgrigonis for the suggestion here: #45 (comment)
Does one get notifications from closed issues when someone comments? Just in case one doesn't. I found one more issue and commented in: #76 |
Few missing imports are missing from
Maybe it would be a good time to merge it to master? :) |
I will fix the imports on the dev branch, but I can't merge yet, as I am still in the process of implementing other features for this release. I would rather not have multiple major releases in rapid succession. |
@dgrigonis I just found a few minutes to look into your import issues.
What exactly is the problem? As far as I can tell, the imports are all there? |
When I open the link, I can not see them. 🤷♂️ |
Now I see them too. Strange stuff. |
Maybe your computer is being haunted by a disgruntled github employee turned poltergeist. I am glad it's sorted now though (yes?). |
I hope I get to have a chat with him. I have a few questions... Yes, all good. |
Hi,
I have been trying to plot multigraphs using netgraph but it seems it is not supported. Here is a minimal example and error message:
Error Trace:
The text was updated successfully, but these errors were encountered: