pythongraphvizdotpygraphviz

Getting pygraphviz clusters to point at each other? (And render properly.)


I have seen some posts talking about this sort of thing, like here, and here, but I've recreated that graphviz spec and it's not rendering the same. In particular, where an arrow should be starting from a cluster edge and pointing at a node, it instead disappears at that edge and only the head appears at the node.

Here's the code:

G = nx.DiGraph(name='G')
G.add_nodes_from(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
A = to_agraph(G, compound=True)

cluster0 = A.add_subgraph(['a', 'b', 'c', 'd'], name='cluster0')
cluster1 = A.add_subgraph(['e', 'f', 'g'], name='cluster1')

cluster0.add_edges_from([('a', 'b'), ('a', 'c'), ('b', 'd'), ('c', 'd')])
cluster1.add_edges_from([('e', 'g'), ('e', 'f')])

A.add_edges_from([('c', 'e'), ('b', 'f'), ('c', 'g'), ('d', 'h')])#, ('d', 'e'), ])
A.get_edge('c', 'e').attr.update({'ltail': 'cluster0'})

Which produces:

strict digraph G {
    graph [compound=True,
        name=G
    ];
    subgraph cluster1 {
        e -> f;
        e -> g;
    }
    subgraph cluster0 {
        a -> b;
        a -> c;
        b -> d;
        c -> d;
    }
    b -> f;
    c -> e  [ltail=cluster0];
    c -> g;
    d -> h;
}

And to render the AGraph, I do:

A.layout(prog='dot')
png_str = A.draw(format='png', prog='dot', args=f"-Gdpi={DPI}")
sio = BytesIO(png_str)
img = mpimg.imread(sio)
plt.imshow(img)
plt.axis('off')
plt.show()

Which renders as:

Broken Arrow

Knocking out the ltail=cluster0 attribute (#A.get_edge('c', 'e').attr.update({'ltail': 'cluster0'})), the image comes out to:

Full Arrow

What am I doing wrong? (Huge bonus points if in showing me what I've done wrong, you also show an arrow whose tail starts on the border of the interior of two nested clusters and points outside of the outermost one.)


Solution

  • Good news, bad news and (maybe) good news.
    Good news: Nothing wrong with the produced dot input.
    Bad news: You are encountering this bug (https://gitlab.com/graphviz/graphviz/-/issues/2447)
    Good news: It seems to be fixed in the latest release(s). This version (dot - graphviz version 10.0.0~dev.20240113.0503 (20240113.0503)) produced:
    enter image description here

    (sorry, don't quite understand you "bonus points" question)