Alignment issue with two clusters using Graphviz and Dot - graphviz

I'm trying to get the following dot file to output two subgraphs. I want the bLoop node in cluster0 to align with the ISR struct in cluster 2. I'm using an invisible node to do this now, but with the unintended consequence of lot of gray space left in cluster0.
Is there a way to do what I want without the invisible node?
I can't post images yet, so here's the link.
digraph G {
ranksep=.75;
nodesep = 1.5;
node [shape = none]
node[fontsize=16,fixedsize=false,width=0.7,shape=rectangle];
edge[fontsize=16];
ratio=fill;
splines=false;
compound=true;
subgraph cluster0 {
node [style=filled];
style=filled;
color=lightgrey;
label = "Setup and Background Loop";
a0[label = "Peripheral Configs"];
a1[label = "Solar Library Block Configs"];
a2[label = "Enable Interrupts"];
bgLoop[label = "Start Background Loop"];
e0[shape=rectangle, style=invis, fixedsize=true, width=.01];
a0 -> a1 -> a2 -> bgLoop;
bgLoop ->e0[style=invis]
}
subgraph cluster1 {
node [style=filled, shape = "doublecircle"];
start
style="invis"
}
subgraph cluster2 {
node [shape=record,color=white];
style=filled;
color=lightgrey;
label = "ISRs";
struct1 [shape = record, color=white, label="{<f1> Slow ISR | <f2> Fast ISR }"];
}
concentrate = true;
struct1 -> bgLoop[lhead=cluster0, ltail=cluster4, constraint=true];
bgLoop -> struct1[lhead=cluster4, ltail=cluster0, constraint=true];
struct1 -> e0[style=invis, constraint=true];
start -> a0[lhead=cluster0];
}

you need helper nodes to get the correct rank for struct1.
digraph G {
ranksep=.75;
nodesep = 1.5;
node[fontsize=16,fixedsize=false,width=0.7,shape=rectangle];
edge[fontsize=16];
compound=true
subgraph cluster2 { rank="max"
node [shape=record,color=white];
style=filled;
color=lightgrey;
label = "ISRs";
struct1 [shape = record, color=white, label="{<f1> Slow ISR | <f2> Fast ISR }"];
}
subgraph cluster0 {
node [style=filled];
style=filled;
color=lightgrey;
label = "Setup and Background Loop";
a0[label = "Peripheral Configs"];
a1[label = "Solar Library Block Configs"];
a2[label = "Enable Interrupts"];
bgLoop[label = "Start Background Loop"];
a0 -> a1 -> a2 -> bgLoop;
}
subgraph cluster1 {
node [style=filled, shape = "doublecircle"];
start
style="invis"
}
{node [style=invis]; 0; 1; 2; 3; }
{edge [style=invis]; 0->1->2->3->struct1; }
struct1 -> bgLoop[lhead=cluster0, ltail=cluster2, constraint=false];
bgLoop -> struct1[lhead=cluster2, ltail=cluster0, constraint=false];
start -> a0[lhead=cluster0];
}

Related

When rankdir is LR, why are the nodes in the same rank ordered bottom to top instead of top to bottom?

In the following example, the nodes in the subgraphs are ordered from the bottom to the top instead of from top to bottom. How can that be reversed, so that the start is top-left and the nodes in the subgraphs are ordered from top to bottom (A1-A4 and B1-B4)?
digraph ab
{
rankdir=LR
splines=ortho
ranksep=1
node[shape = record]
subgraph cluster_0
{
label="A"
{
rank = "same"
state0_anchor [label="", style=invis, width=0]
state0_step0 [label="A1"]
state0_step1 [label="A2"]
state0_step2 [label="A3"]
state0_step3 [label="A4"]
}
state0_anchor->state0_step0[style = invis]
state0_step0 -> state0_step1 -> state0_step2 -> state0_step3
}
state0_step3 -> state0_step0 [constraint=false]
state0_step3 -> state1_step0 [constraint=false]
subgraph cluster_state1
{
label="B"
{
rank = "same"
state1_anchor [label="", style=invis, width=0, height=0]
state1_step0 [label="B1"]
state1_step1 [label="B2"]
state1_step2 [label="B3"]
state1_step3 [label="B4"]
}
state1_anchor->state1_step0[style = invis]
state1_step0 -> state1_step1 -> state1_step2 -> state1_step3
}
state1_step3 -> state0_step0 [constraint=false]
state0_anchor -> state1_anchor[style = invis]
start -> state0_step0
}
In your example, when direction of the edges within the subgraphs are reversed, the nodes will be ordered the way you'd like. Something like this:
state0_step3 -> state0_step2 [dir=rev]
state0_step2 -> state0_step1 [dir=rev]
state0_step1 -> state0_step0 [dir=rev]
state0_step0 -> state0_anchor [style = invis]
The same for state1-nodes.
Details about transformations when going LR can be found in https://stackoverflow.com/a/9592856/63733

trying to create ranked subgraphs in graphviz

I've tried to make something like this using Graphviz:
x y z
| | |
# | |
a#__\| |
# /#b |
# #__\|
# # /#c
# d#/__#
# #\ x
# # |
e#/__# |
#\ # |
But ranking doesn't seem to be working as I expect. I want e to be below all of the other nodes.
digraph x
{
rankdir = tb;
size = "7.5, 7.5";
rank = source;
a -> b -> c -> d -> e;
subgraph "cluster x"
{
style=filled;
color=lightgrey;
label="x";
a -> e [style=invis];
}
subgraph "cluster y"
{
label="y";
b -> d [style=invis];
}
subgraph "cluster z"
{
label="z";
c;
}
}
I've tried to use clusterrank = global which sort of works, but then the subgraphs are not separated into a more obvious column and there's overlap over the columns. It also is not going to the right like I want. The following image highlights one of the overlaps in red, but as you can see there are 4.
digraph x
{
rankdir = tb;
rankstep=equally;
clusterrank = global;
size = "7.5, 7.5";
a -> b -> c -> d -> e;
subgraph "cluster x"
{
style=filled;
color=lightgrey;
label="x";
a -> e [style=invis];
}
subgraph "cluster y"
{
label="y";
b -> d [style=invis];
}
subgraph "cluster z"
{
label="z";
c;
}
}
I've tried to make a separate cluster that is going to have a guaranteed top to bottom ranking and then rank the appropriate clusters together, but it does the same as the previous attempt, removing the boxes seen the the first attempt and causing unwanted overlapping.
digraph x
{
rankdir = tb;
1 -> 2 -> 3 -> 4 -> 5;
a -> b -> c -> d -> e;
{ rank=same; 1; a; }
{ rank=same; 2; b; }
{ rank=same; 3; c; }
{ rank=same; 4; d; }
{ rank=same; 5; e; }
subgraph "cluster x"
{
style=filled;
color=lightgrey;
label="x";
a -> e [style=invis];
}
subgraph "cluster y"
{
label="y";
b -> d [style=invis];
}
subgraph "cluster z"
{
label="z";
c;
}
}
Anyone have any ideas as to try and get the layout I want?
As a side note, I tried to login to the Graphviz forum regarding this matter, but found that logging in from this page doesn't seem to work. I keep getting a long timeout problem. I check my email account and nothing is there. I try creating a new account with the same email and it says that the account is already in use. I then try and get them to reset my password and I get another timeout problem.
Does anyone know who I can contact to try and fix that annoying login problem? Maybe someone who is already logged in can post that for me?
Run dot with -Gnewrank. That will get you what you want based on your sketch. If more tweaks are needed, please specify what you are after.
Your last solution will work as soon as you do a minor tuning
Use newrank=true to avoid of "unboxing" clusters
Play with splines=... to adjust arrows
Define label as separate nodes.
digraph x
{
rankdir = tb;
newrank=true;
splines=ortho;
0 -> 1 -> 2 -> 3 -> 4 -> 5;
X; Y; Z;
a -> b -> c -> d -> e;
{ rank=same; 0 X Y Z}
{ rank=same; 1; a; }
{ rank=same; 2; b; }
{ rank=same; 3; c; }
{ rank=same; 4; d; }
{ rank=same; 5; e; }
subgraph "cluster x"
{
style=filled;
color=lightgrey;
a -> e [style=invis];
}
subgraph "cluster y"
{
b -> d [style=invis];
}
subgraph "cluster z"
{
c;
}
}

Adding labels under subgraphs in Graphviz

I use the following code to produce a graph using dot in Graphviz. I have manually included the coordinates of nodes, as I require four disjoint subgraphs placed adjacent to one another, as in the picture.
I would love to add labels under each of the subgraphs: $G_0$, $G_1$, etc. Adding label under subgraph creates a box and ignores my coordinates alignment. Is there any other way, like placing arbitrary text at specified coordinates? I use "dot -Teps -Kfdp -n trees -o t.eps" for compilation.
digraph Trees {
node [shape=circle, style="filled", fixedsize=true,width=0.6]; 0; 1;2; 3;4; 5;6; 7; 8;9;10;11;12;13;14;15;
0[pos = "0,1!"]
1[fillcolor=red, pos = "-1,2!"]
2[pos = "1,2!"]
3 [pos = "0,-0.5!"]
5[label=1, fillcolor=red, pos = "2,2!"]
4[label=0, fillcolor=red, pos = "3,1!"]
6[label=2, pos = "4,2!"]
7[label=3, pos = "3, -0.5!"]
9[label=1, fillcolor=red, pos = "5,2!"]
8[label=0, fillcolor=red, pos = "6,1!"]
10[label=2, pos = "7,2!"]
11[label=3, fillcolor=red, pos = "6, -0.5!"]
12[label=1, fillcolor=red, pos = "8,2!"]
13[label=0, fillcolor=green, pos = "9,1!"]
14[label=2, pos = "10, 2!"]
15[label=3, fillcolor=green, pos = "9, -0.5!"]
overlap=false;
fontsize=10;
subgraph 1{
edge [dir=none] 1->0 2->0 3->0;
}
subgraph 2{
edge [color=red] 5->4;
edge[color=black, dir=none] 6->4 7->4;
}
subgraph 3{
edge [color=red] 9->8 8->11;
edge [color=black, dir=none] 8->10;
}
subgraph 4{
edge [color=green] 12->13; 13->15;
edge [color=black, dir=none] 13->14;
}
}
The sub-graphs can be made disjoint using clusters and the dot layout engine. The same approach will also permit the introduction of cluster labels. They can be placed at the bottom of the cluster as required without creating dummy nodes.
This way, no absolute positions are required, and, the layout is automatically generated even if other nodes are added. The exact position of the nodes change, but the graphs remain topologically unchanged.
digraph Trees { node [shape = circle, style = "filled", fixedsize = true, width=0.4];
edge [dir = none];
layout = dot; overlap = false; fontsize = 10;
graph [labelloc = "b", penwidth = 0];
{ node [fillcolor = "red"];
1; 5 [label = 1]; 4 [label = 0]; 9 [label = 1];
8 [label = 0]; 11 [label = 3]; 12 [label = 1];
}
2; 0; 3; 6 [label = 2]; 7 [label = 3];
10 [label = 2]; 14 [label = 2];
{ node [fillcolor = "green"];
13 [label = 0]; 15 [label = 3];
}
subgraph cluster1{
label = "Subgraph 1";
{ 1; 2; } -> 0 -> 3;
}
subgraph cluster2{
label = "Subgraph 2";
5 -> 4 [color = red, dir = fwd];
6 -> 4 -> 7;
}
subgraph cluster3{
label = "Subgraph 3";
9 -> 8-> 11 [color=red, dir = fwd];
10 -> 8 [color=black];
}
subgraph cluster4{
label = "Subgraph 4";
12 -> 13 -> 15 [color=green, dir = fwd];
14-> 13;
}
}
Instead of using explicit node positions, you may use a simple directed graph combined with some rank constraints, invisible edges and text nodes instead of subgraph labels:
digraph Trees {
fontsize=10;
node [shape=circle, style="filled", fixedsize=true,width=0.6];
{rank=same;
a1[label=1, fillcolor=red];
a2[label=2];
a3[label=1, fillcolor=red];
a4[label=2];
a5[label=1, fillcolor=red];
a6[label=2];
a7[label=1, fillcolor=red];
a8[label=2];
}
node[label=0];
b1;
b2[fillcolor=red];
b3[fillcolor=red];
b4[fillcolor=green];
node[label=3];
c1;
c2;
c3[fillcolor=red];
c4[fillcolor=green];
node[shape=none, fillcolor=transparent];
d1[label="Label 1"];
d2[label="Label 2"];
d3[label="Label 3"];
d4[label="Label 4"];
edge[dir=none];
a1->b1;
a2->b1;
b1->c1;
c1->d1[style=invis];
a3->b2[dir=forward, fillcolor=red, color=red];
a4->b2;
b2->c2;
c2->d2[style=invis];
a5->b3[dir=forward, fillcolor=red, color=red];
a6->b3[dir=forward, fillcolor=red, color=red];
b3->c3;
c3->d3[style=invis];
a7->b4[dir=forward, fillcolor=green, color=green];
a8->b4[dir=forward, fillcolor=green, color=green];
b4->c4;
c4->d4[style=invis];
edge[style=invis];
a2 -> a3;
a4 -> a5;
a6 -> a7;
}

Graphviz - Box positioning Problem

My structure has two main chains with side nodes in sub graphs. Every thing looks nice but when i close the two chains all the boxes in the sub graphs jumps to the right side.
At the end of my code you can remove the "I"->"J" then you can see the best what I mean.
I am not a native English speaker, sorry about my English and I am a graphviz newbie.
digraph G {
size ="6,6";
node [color=black fontsize=12, shape=box, fontname=Helvetica];
subgraph {
rank = same;
"b"->"B"[arrowhead=none];
}
subgraph {
rank=same;
"c"->"C"[arrowhead=none];
}
subgraph {
rank=same;
"e"->"E" [arrowhead=none];
}
subgraph {
rank = same;
"f"->"F"[arrowhead=none];
}
subgraph {
rank = same;
"g"->"G"[arrowhead=none];
}
"0" -> "A" -> "B" -> "C"->"D" -> "E" -> "F" -> "G" -> "H"->"I";
"0" -> "K"->"L"->"M"->"N"->"O" ->"P"->"1";
subgraph {
rank = same;
"L"->"l"[arrowhead=none];
}
subgraph {
rank=same;
"M"->"m"[arrowhead=none];
}
subgraph {
rank=same;
"N"->"n" [arrowhead=none];
}
subgraph {
rank = same;
"O"->"o"[arrowhead=none];
}
subgraph {
rank = same;
"P"->"p"[arrowhead=none];
}
"1"->"J";
"I"->"J";
}
and with "I"->"J"; removed:
This is how I'd go about it: Create a cluster for each main chain with its side nodes:
digraph G {
size ="6,6";
node [color=black fontsize=12, shape=box, fontname=Helvetica];
subgraph[style=invis];
subgraph cluster0 {
A -> B -> C -> D -> E -> F -> G -> H -> I;
edge[arrowhead=none];
{rank = same; b->B;}
{rank = same; c->C;}
{rank = same; e->E;}
{rank = same; f->F;}
{rank = same; g->G;}
}
subgraph cluster1 {
K -> L -> M -> N -> O -> P -> 1 -> J;
edge[arrowhead=none];
{rank = same; L->l;}
{rank = same; M->m;}
{rank = same; N->n;}
{rank = same; O->o;}
{rank = same; P->p;}
}
0 -> A;
0 -> K;
I -> J;
}
Resulting in:

subgraph cluster ranking in dot

I'm trying to use graphviz on media wiki as a documentation tool for software.
First, I documented some class relationships which worked well. Everything was ranked vertically as expected.
But, then, some of our modules are dlls, which I wanted to seperate into a box. When I added the nodes to a cluster, they got edged, but clusters seem to have a LR ranking rule. Or being added to a cluster broke the TB ranking of the nodes as the cluster now appears on the side of the graph.
This graph represents what I am trying to do: at the moment, cluster1 and cluster2 appear to the right of cluster0.
I want/need them to appear below.
<graphviz>
digraph d {
subgraph cluster0 {
A -> {B1 B2}
B2 -> {C1 C2 C3}
C1 -> D;
}
subgraph cluster1 {
C2 -> dll1_A;
dll1_A -> B1;
}
subgraph cluster2 {
C3 -> dll2_A;
}
dll1_A -> dll2_A;
}
</graphviz>
The layout is an attempt by Dot to minimise the overall height.
One reason for the more compact than required layout is the use of the edge that goes in the reverse direction from dll1_a to B1. It tries to pull the cluster as close back to the destination node as possible. To avoid this edge affecting the graph, either relax the constraint on the upwards edges as shown, or draw the edge in the forward direction and use the dir attribute to reverse the arrow.
This will help with many layouts but it alone is not sufficient to fix the example given. To prevent Dot from maintaining the compact layout it prefers you can add a minlen attribute to edges that should remain (near) vertical. This may be difficult to calculate in general but is practical for manually tuned layouts.
digraph d {
subgraph cluster0 {
A -> {B1 B2}
B2 -> {C1 C2 C3}
C1 -> D;
}
subgraph cluster1 {
C2 -> dll1_A [minlen = 2];
dll1_A -> B1 [constraint = false];
/* B1 -> dll1_A [dir = back]; */
}
subgraph cluster2 {
C3 -> dll2_A;
}
dll1_A -> dll2_A;
}
My experience shows that constraint=false commonly gives unnecessarily convoluted edges. It seems that weight=0 gives better results:
digraph d {
subgraph cluster0 {
A -> {B1 B2}
B2 -> {C1 C2 C3}
C1 -> D;
}
subgraph cluster1 {
C2 -> dll1_A [minlen = 2];
dll1_A -> B1 [weight = 0];
/* B1 -> dll1_A [dir = back]; */
}
subgraph cluster2 {
C3 -> dll2_A;
}
dll1_A -> dll2_A;
}
This will produce the graph you are looking for:
digraph d {
subgraph cluster0 {
A -> {B1 B2}
B2 -> {C1 C2 C3}
C1 -> D;
}
subgraph {
rankdir="TB"
subgraph cluster1 {
C2 -> dll1_A;
dll1_A -> B1;
}
subgraph cluster2 {
C3 -> dll2_A;
}
}
dll1_A -> dll2_A;
}
What this does is creat a subgraph that is used only for layout purposes to provide the top to bottom ordering that you desire.

Resources