NetworkX only provides basic functionality for visualizing graphs. It looks ugly to draw trees with its built-in graph layout. This article presents how to draw beautiful trees with
pygraphviz and convert the format between NetworkX and Graphviz (dot).
1. Install PyGraphviz
pygraphviz on macOS,
$ brew install graphviz $ sudo pip install pygraphviz
2. Draw trees with PyGraphviz
We use node positioning algorithms provided by Graphviz for tree drawing.
Graphviz is a package for drawing graphs specified in DOT language scripts. It also provides a set of tools that can generate and/or process DOT files. PyGraphviz is a Python interface to Graphviz for accessing the Graphviz graph data structure and layout algorithms.
graphviz_layout is a wrapper for
pygraphviz_layout that creates node positions for a graph using Graphviz. Note that in new versions of Networkx,
graphviz_layout is moved to
nx.drawing.nx_agraph. Import it explicitly by,
from networkx.drawing.nx_agraph import graphviz_layout pos = graphviz_layout(G, prog='dot') # Interfaces graphviz_layout(G[, prog, root, args]) # Create node positions for G using Graphviz. pygraphviz_layout(G[, prog, root, args]) # Create node positions for G using Graphviz.
Here is an example. The source code is hosted on my GitHub, here.
import networkx as nx import matplotlib.pyplot as plt from networkx.drawing.nx_agraph import graphviz_layout def main(): # Create a directed graph G = nx.DiGraph() # An example l=[ ('a','b'), ('b','c'), ('c','d'), ('d','e'), ('e','f'), ('w','x'), ('w','t'), ('t','q'), ('q','r'), ('q','u')] # Build up a graph for t in l: G.add_edge(t, t) # Plot trees pos=graphviz_layout(G, prog='dot') nx.draw(G, pos, with_labels=True, arrows=False) plt.savefig('draw_trees_with_pygraphviz.png', bbox_inches='tight') plt.show() if __name__ == '__main__': main()
Fig. 1: A tree drawn with NetworkX and PyGraphviz
3. Format conversion between Networkx and Graphviz AGraph (dot)
NetworkX provides interfaces to convert the format between NetworkX and Graphviz AGraph (dot).
from_agraph(A[, create_using]) # Return a NetworkX Graph or DiGraph from a PyGraphviz graph. to_agraph(N) # Return a pygraphviz graph from a NetworkX graph N. write_dot(G, path) # Write NetworkX graph G to Graphviz dot format on path. read_dot(path) # Return a NetworkX graph from a dot file on path.
The following snippet code shows how to convert the format between them.
import networkx as nx G = nx.complete_graph(5) # <networkx.classes.graph.Graph object at 0x1057c5850> # nx --> dot A = nx.nx_agraph.to_agraph(G) # <AGraph complete_graph(5) <Swig Object of type 'Agraph_t *' at 0x1032eb8a0>> # dot --> nx H = nx.nx_agraph.from_agraph(A) # <networkx.classes.graph.Graph object at 0x1057c5310>
After a graph is converted into the format dot, we can process graphs using PyGraphviz. Refer to PyGraphviz: AGraph Class for the detailed operations.