Combining networkx layout with graphviz

363 views
Skip to first unread message

Stephen Davies

unread,
Jan 21, 2021, 2:47:56 PM1/21/21
to networkx-discuss
Hello, I'm new to networkx and python; my previous experience was with igraph and R.

My question: is there a way I can use networkx's kawada_kawai_layout() to compute node positions, but then render the image of the graph using pygraphviz? I like graphviz's various plotting features, but it seems to me that if I use pygraphviz, I'm forced to allow pygraphviz to determine the node layout (with one of neato|dot|twopi|circo|fdp|nop).

But maybe there's a way to give pygraphviz a set of already-computed node positions, hence my question.

Thanks,
- Stephen

Dan Schult

unread,
Jan 21, 2021, 10:56:14 PM1/21/21
to networkx...@googlegroups.com
It looks like pygraphviz with layout "nop" does not do any layout... "nop" stands for "no operation".
So, to get up to speed, try this with a very small graph (`path_graph(3)`?) 
1) Convert the graph to a pygraphviz `AGraph`
2) print the dot file for the graph to see the format of the position attributes.
3) Go back to NetworkX and get the positions using one of the algorithms.
4) add the positions as node attributes to the graph.  `nx.set_node_attributes()`
5) convert the resulting Graph with node attributes to a pygraphviz AGraph
6) print the AGraph as a dot file (make sure the format of the positions in the dot file are the same as the pygraphviz positions)
7) draw the AGraph with `prog="nop"`

I haven't gone through this process, but theoretically that's how this should work.

--
You received this message because you are subscribed to the Google Groups "networkx-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to networkx-discu...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/networkx-discuss/f580c7fb-2ff9-4ec4-88ff-62e538869e88n%40googlegroups.com.

Stephen Davies

unread,
Jan 22, 2021, 2:19:14 PM1/22/21
to networkx-discuss
Thanks much, Dan! What you suggested did basically work for me after some finagling.

One weird thing is that if I simply add the node positions (via set_node_attributes()) from one of the nx algorithms, and then try to draw the resulting AGraph object, it gives me a "no layout information" error. To reproduce:

import networkx as nx
from networkx.drawing.nx_agraph import to_agraph
G = nx.path_graph(3)
pos = nx.kamada_kawai_layout(G)
newpos = { n:{"pos":",".join(p.astype(str)) } for n,p in pos.items() }
nx.set_node_attributes(G, newpos)
A = to_agraph(G)
A.draw("tmp.png")

AttributeError: Graph has no layout information, see layout() or specify prog=neato|dot|twopi|circo|fdp|nop.

My wild guess explanation is that A.draw() is expecting layout information for the edges in addition to the nodes, and the nx algorithms don't give that.

If I change A.draw("tmp.png") to A.draw("tmp.png",prog="nop") as another responder suggested, it produces a tmp.png file that is an ASCII file, not a valid PNG file! The workaround that finally did it for me was to use this as the final line:

A.draw("tmp.png",prog="neato")

I'm pretty surprised this works, since I would think specifying "neato" would override all the node coordinates I had set from the nx Kamada-Kawaii layout with "neato's" choice of node positions. But it doesn't seem to do so -- comparing the layout between raw networkx Kamada-Kawaii (i.e., without using graphviz at all) with the result of the above does show the nodes in pretty much the same places, whereas if I do not call nx.set_node_attributes(G, newpos), I get something completely different which presumably is the neato algorithm at work.

Curious if anyone disagrees with my reasoning and/or has suggestions to make the above code better.

- Stephen

Dan Schult

unread,
Jan 22, 2021, 2:34:24 PM1/22/21
to networkx...@googlegroups.com
Thanks for this update --  just to complete the puzzle since there has been a new graphviz release and some older pygraphviz releases are still out there....

What versions of graphviz and pygraphviz are you using?

Thanks!
Dan

Stephen Davies

unread,
Jan 22, 2021, 2:42:08 PM1/22/21
to networkx-discuss
$ conda list | grep graph
pygraphviz                1.6                      pypi_0    pypi
python-graphviz           0.16                     pypi_0    pypi

$ dot -V
dot - graphviz version 2.43.0 (0)

- Stephen

Aric Hagberg

unread,
Jan 22, 2021, 2:52:37 PM1/22/21
to networkx...@googlegroups.com
It looks like you have it figured out.

It might be a little more subtle as to what is happening. Check these
to SO threads on using the ! modifier to position attribute and the
-n2 option to neato.
https://stackoverflow.com/questions/5343899/how-to-force-node-position-x-and-y-in-graphviz
https://stackoverflow.com/questions/16775844/force-graphviz-to-preserve-node-positions

e.g. 'man neato'
-n[1|2] (no‐op) If set, neato assumes nodes have already been posi‐
tioned and all nodes have a pos attribute giving the positions. It
then performs an optional adjustment to remove node‐node overlap, de‐
pending on the value of the overlap attribute, computes the edge lay‐
outs, depending on the value of the splines attribute, and emits the
graph in the appropriate format. If num is supplied, the following ac‐
tions occur:
num = 1
Equivalent to -n.
num > 1
Use node positions as specified, with no adjustment to remove node‐node
overlaps, and use any edge layouts already specified by the pos attri‐
bute. neato computes an edge layout for any edge that does not have a
pos attribute. As usual, edge layout is guided by the splines attri‐
bute.


Note that you always do need to run through some layout algorithm
since you have to route edges in addition to nodes.

Aric

On Fri, Jan 22, 2021 at 12:42 PM Stephen Davies
> To view this discussion on the web visit https://groups.google.com/d/msgid/networkx-discuss/0d9f9ee4-b4fc-4f5c-a49b-38c43615be35n%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages