Alex Ivanov
Alex Ivanov

Reputation: 43

Graph node position in graphviz in python

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:

graph

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.

Upvotes: 4

Views: 9856

Answers (3)

user109839
user109839

Reputation:

Starting from your code, it's enough to use the subgraph context, just add

with g.subgraph() as s:
    s.attr(rank = 'same')
    for n in top_nodes: s.node(n)

it seems easier than explicitly declaring a subgraph and adding it to the original graph.

By the way, this solution generates the exact same DOT source as the ine in @RaHo answer.

digraph test {
    a [color=red]
    b [color=red]
    c [color=red]
    d
    e
    f
    g
    m
    n
    a -> d
    d -> g
    g -> m
    m -> n
    b -> e
    b -> f
    e -> n
    c -> f
    {
        rank=same
        a
        b
        c
    }
}

Upvotes: 4

user2559538
user2559538

Reputation: 51

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()

image output

Upvotes: 5

RaHo
RaHo

Reputation: 158

try the rank = same statement

enter image description here

digraph G {
a b c d e f g m n
{rank = same; a; b; c;}
a->d
d->g
g->m
m->n
b->e
b->f
e->n
c->f
}

Upvotes: 0

Related Questions