1

I'm currently displaying directed graphs with few nodes and edges connecting them, with nx.draw. The edges are labelled via nx.draw_networkx_edge_labels.

Now I wanted to "lighten" the "rigidity" aspect of the graph by setting the connectionstyle, which works fine with non-labelled edges.

Problem is that if I display labels, they are drawn as if the edge was not curved, which ends up creating a huge offset between the edge and the label.

Is there any way to work around this limitation? I could not find an "offset" option to nx.draw_networkx_edge_labels to address this issue.

EDIT:

Above is a quick example of the issue:

import matplotlib.pyplot as plt
import networkx as nx

tab = ("r", ["s", "t", "u", "v", "w", "x", "y", "z"])

producer = tab[0]
consumers = tab[1]

color_map = []
DG = nx.DiGraph()
for i, cons in enumerate(consumers):
    DG.add_edge(producer, cons, label=f"edge-{i}")

for i in range(len(DG.nodes())):
    if i < 1 + len(consumers):
        color_map.append("#DCE46F")
    else:
        color_map.append("#6FA2E4")
pos = nx.shell_layout(DG)
labels = nx.get_edge_attributes(DG, 'label')
nx.draw(DG, pos, node_color=color_map, connectionstyle="arc3, rad=0.2", with_labels=True, font_size=8, node_size=1000, node_shape='o')
nx.draw_networkx_edge_labels(DG, pos, edge_labels=labels)

plt.show()

current output:

enter image description here

mozway
  • 194,879
  • 13
  • 39
  • 75
ThylowZ
  • 55
  • 7
  • 2
    Can you please provide a minimal reproducible example? – mozway May 10 '22 at 07:43
  • Ok I'm gonna do that, I did not in a first time because I was limited in time. I'll do it ASAP. – ThylowZ May 10 '22 at 08:14
  • I've edited the post with a reproducible example. – ThylowZ May 10 '22 at 08:24
  • thanks for updating, the question is clear now! – mozway May 10 '22 at 08:28
  • You're welcome. Tbh, I don't think there is a clear solution to my problem. I plan on adding a color to edges and then using a legend to my graphs, even though I'd rather have labelled edges. – ThylowZ May 10 '22 at 09:15
  • I haven't had a chance to look yet, but I'm hopeful (and if no solution is found, that might be the opportunity to request the function to the networkx dev) – mozway May 10 '22 at 09:17
  • 1
    @mozway This has been discussed [for several years now](https://github.com/networkx/networkx/issues/3813) but drawing simply is not a priority for networkx. It might still be some time. – Paul Brodersen May 10 '22 at 09:48

1 Answers1

3

If you are open to using other libraries for the visualization, I wrote (and maintain) netgraph. In netgraph, edge labels track edges even if they are curved.

enter image description here

import numpy as np
import matplotlib.pyplot as plt
import networkx as nx

from netgraph import Graph # pip install netgraph

tab = ("r", ["s", "t", "u", "v", "w", "x", "y", "z"])

producer = tab[0]
consumers = tab[1]

DG = nx.DiGraph()
for i, cons in enumerate(consumers):
    DG.add_edge(producer, cons, label=f"edge-{i}")

node_color = dict()
for node in DG:
    if node in producer:
        node_color[node] = "#DCE46F"
    else:
        node_color[node] = "#6FA2E4"

pos = nx.shell_layout(DG)
pos[producer] = pos[producer] + np.array([0.2, 0])
edge_labels = nx.get_edge_attributes(DG, 'label')

Graph(DG, node_layout=pos, edge_layout='curved', origin=(-1, -1), scale=(2, 2),
      node_color=node_color, node_size=8.,
      node_labels=True, node_label_fontdict=dict(size=10),
      edge_labels=edge_labels, edge_label_fontdict=dict(size=10),
)
plt.show()
mozway
  • 194,879
  • 13
  • 39
  • 75
Paul Brodersen
  • 11,221
  • 21
  • 38
  • I might give it a try, I just have to see if I can insert it in my PyQt app. The sample I provided you is normally integrated within matplotlib FigureCanvas with additional "ax" parameter, so I can try it. I also have to consider the problematic of maintainability in the long term. – ThylowZ May 10 '22 at 15:19
  • additional question : it seems that the graph is not "directed" (arrow edge) in your example, is there a way to do it? It's way more important than labels in my case. – ThylowZ May 10 '22 at 15:25
  • You can pass in an axis explicitly using the `ax` keyword argument. Arrows are plotted with `arrows=True`. For a full list of available arguments: [ReadTheDocs](https://netgraph.readthedocs.io/en/latest/). I know that others have made PyQt applications with it, so that should work fine. – Paul Brodersen May 10 '22 at 15:34
  • W.r.t. maintainability: open source is exactly as well maintained as you want it to be. That being said, I have been working on netgraph for 8, maybe 9 years (oldest commit is from 6 years due to a rewrite), and as I still enjoy working on it, I don't think you have fear a complete abandonment any time soon. – Paul Brodersen May 10 '22 at 15:44
  • Ty for your comment, I'll definitely give it a try soon (maybe after work ;) ) – ThylowZ May 10 '22 at 15:51
  • OK, I tested it and I liked it a lot. It also "sharpens" (sry for my mediocre english) the graph which makes it a bit fancier. I just had a RuntimeWarning: divide by zero encountered in double_scalars rescale_factor = min(rescale_factor, diameter/np.sqrt(width**2 + height**2)), I'll have to monitor that but it's not worrying. – ThylowZ May 10 '22 at 16:51
  • May I add another question? I'm discovering your python library, especially the InteractiveGraph which I'm really interested in. However, I can't manage to make it work in my app. Would you mind to give me a tip on what I might be doing wrong? I did instantiate the InteractiveGraph class but still, I can't click the nodes. I can provide a code snippet. – ThylowZ May 10 '22 at 22:22
  • To enable to interactive matplotlib events in PyQt, you need to set the focus in a particular way. See https://github.com/paulbrodersen/netgraph/issues/34 and the matplotlib issue linked in that thread. If it is not that, I would suggest to ask another question here on SO and tag it with PyQT, matplotlib and netgraph. – Paul Brodersen May 11 '22 at 01:07
  • Or open an issue on my github. But you will get more eyes here. – Paul Brodersen May 11 '22 at 01:10
  • Ok, I opened [a new question](https://stackoverflow.com/questions/72197530/clickable-netgraph-in-pyqt-application-with-tabs) on this topic. I tried the several suggestion made on your github repo or SO, but with no success. – ThylowZ May 11 '22 at 08:10