I've been looking for a while for the way to specify the node position in a graph in graphviz in python. I found rank command for a subgraph in dot, which is what I am looking for, but I could not find the way to combine subgraph and rank in graphviz in python. I also tried to force node positions, but did not work either. I created a simple example of what I want to achieve.
This is my code:
from graphviz import Digraph
top_nodes = ['a', 'b', 'c']
other_nodes = ['d', 'e', 'f', 'g', 'm', 'n']
g = Digraph('test', format='png')
for n in top_nodes:
g.node(str(n), color='red')
for n in other_nodes:
g.node(str(n))
g.edge('a', 'd')
g.edge('d', 'g')
g.edge('g', 'm')
g.edge('m', 'n')
g.edge('b', 'e')
g.edge('b', 'f')
g.edge('e', 'n')
g.edge('c', 'f')
g.view()
This is the output:
I want red nodes ('sources') to be on the top of the graph on the same level, the positions of the rest of the nodes is not so important as long as hierarchical layout is preserved.
I encountered the same problem and find out using a subgraph solves the problem.
from graphviz import Digraph
top_nodes = ['a', 'b', 'c']
other_nodes = ['d', 'e', 'f', 'g', 'm', 'n']
g = Digraph('test', format='png')
s = Digraph('subgraph')
s.graph_attr.update(rank='min')
for n in top_nodes:
s.node(str(n), color='red')
for n in other_nodes:
g.node(str(n))
g.edge('a', 'd')
g.edge('d', 'g')
g.edge('g', 'm')
g.edge('m', 'n')
g.edge('b', 'e')
g.edge('b', 'f')
g.edge('e', 'n')
g.edge('c', 'f')
g.subgraph(s)
g.view()