trying to create ranked subgraphs in graphviz - 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;
}
}

Related

Graphviz ordering of nodes on the same rank

I made a graph and it looks like I want it to with one exception: the cluster containing nodes D and E should be placed between nodes B and C.
Here is the .dot:
digraph {
node[shape=rectangle]
graph [
newrank=true
];
Z
A
B
C
{
rank=same;
A -> B -> D;
D -> C[style=invis];
}
subgraph clusterSS {
style=dashed;
D[group=ss]
E[group=ss]
D -> E[style="dashed"; dir = none];
}
Z -> A
Z -> B
Z -> D
Z -> C
A -> P[dir = back]
B -> S
S -> B[constraint = false];
C -> S
S -> E[constraint = false]
E -> S[label = "Label"]
}
I expected that having edges between nodes
{
rank=same;
A -> B -> D;
D -> C[style=invis];
}
would ensure correct ordering, but it doesn't.
The ordering becomes correct once I delete the edge label between S and E, but I do need to keep the labels.
[non-trivial, not guaranteed to work as desired in any other circumstance]
Added clusters, invisible nodes,and more. ugh
digraph {
node[shape=rectangle]
graph [
newrank=true
];
{
rank=same;
A -> B -> D;
D -> C[style=invis];
}
subgraph clusterSS {
style=dashed;
D [group=ss]
E [group=ss]
D -> E[style="dashed"; dir = none];
}
subgraph clusterAP {
peripheries=0
A -> P[dir = back]
}
subgraph clusterB {
peripheries=0
B
bogus [style=invis shape=plain]
B->bogus [style=invis]
}
Z -> A
Z -> B
Z -> D
Z -> C
S [group=ss]
B -> S:nw
B -> S:w [dir=back]
C -> S
S -> E[constraint = false]
E -> S[label = "Label"]
}
Giving:

Is it possible to generate a small GraphViz chart?

I need to generate a small graphviz graph that represents a "price map" of the main graphviz. The main graph is:
digraph g {
graph [rankdir = "LR"];
a [label = "<f0>a | <f1> $139 | <f2> Chair | Brown" shape = "record"];
b [label = "<f0>b | <f1> $280 | <f2> Speakers | Grey" shape = "record"];
c [label = "<f0>c | <f1> $89 | <f2> Jacket | Beige" shape = "record"];
d [label = "<f0>d | <f1> $19 | <f2> Mug | Green" shape = "record"];
e [label = "<f0>e | <f1> $180 | <f2> Printer | Grey" shape = "record"];
a -> b; a -> c; c -> d; c -> e;
}
and it generates:
When I try to generate a "small" price map like:
digraph g {
graph [rankdir = "LR"];
node [shape=box];
a[color=black, fillcolor=yellow, style=filled];
b[color=black, fillcolor=red, style=filled];
c;
d;
e[color=black, fillcolor=yellow, style=filled];
a -> b; a -> c; c -> d; c -> e;
}
I get:
But I wanted a really small price map, like:
Is this possible?
You should really read the dot guide which is a pretty impressive view across using dot (although HTMl nodes don't feature so much): http://graphviz.org/pdf/dotguide.pdf
Try changing the shape to plain:
node [shape=plain];
Result:
Another possibility is to use HTML nodes - my answer in this example shows compact nodes https://stackoverflow.com/a/68320427/2318649
Another way to control spacing is useing nodesep and ranksep on the graph, for example:
digraph g {
graph [rankdir="LR" nodesep=0.1 ranksep=0.2];
node [shape=plain];
a[color=black, fillcolor=yellow, style=filled];
b[color=black, fillcolor=red, style=filled];
c;
d;
e[color=black, fillcolor=yellow, style=filled];
a -> b; a -> c; c -> d; c -> e;
}
Result:
Another way to minimize the space inside a box node is setting margin, width and height all to 0:
digraph g {
graph [rankdir="LR" nodesep=0.1 ranksep=0.2];
node [shape=box margin=0 width=0 height=0];
a[color=black, fillcolor=yellow, style=filled];
b[color=black, fillcolor=red, style=filled];
c;
d;
e[color=black, fillcolor=yellow, style=filled];
a -> b; a -> c; c -> d; c -> e;
}
Result:
You can control the arrow size on each edge, e.g.:
a -> b [arrowsize=0.5]; a -> c [arrowsize=0.5]; c -> d [arrowsize=0.5]; c -> e;
result:
Or you can control arrowsize across all edges:
digraph g {
graph [rankdir="LR" nodesep=0.1 ranksep=0.2];
node [shape=box margin=0 width=0 height=0];
edge [arrowsize=0.5]
a[color=black, fillcolor=yellow, style=filled];
b[color=black, fillcolor=red, style=filled];
c;
d;
e[color=black, fillcolor=yellow, style=filled];
a -> b; a -> c; c -> d; c -> e;
}
Result:
Read about attributes: http://graphviz.org/doc/info/attrs.html
Read about nodes: http://graphviz.org/doc/info/shapes.html
Read about using dot: http://graphviz.org/pdf/dotguide.pdf

Arranging subclusters with rank

I have this graph:
digraph G{
rankdir = TB;
hyb[label="Hybrid calculation"];
k1[label=<k<SUB>1</SUB>>];
k2[label=<k<SUB>2</SUB>>];
kn[label=<k<SUB>n</SUB>>];
// subgraph cluster_k1q {
k1q1[label=<q<SUB>1</SUB>>];
k1q2[label=<q<SUB>2</SUB>>];
k1qn[label=<q<SUB>n</SUB>>];
graph[style=dotted];
{rank=same; k1q1;k1q2;k1qn}
// }
// subgraph cluster_k2q {
k2q1[label=<q<SUB>1</SUB>>];
k2q2[label=<q<SUB>2</SUB>>];
k2qm[label=<q<SUB>m</SUB>>];
graph[style=dotted];
{rank=same; k2q1;k2q2;k2qm}
// }
// subgraph cluster_knq {
knq1[label=<q<SUB>1</SUB>>];
knq2[label=<q<SUB>2</SUB>>];
knql[label=<q<SUB>l</SUB>>];
graph[style=dotted];
{rank=same; knq1;knq2;knql}
// }
hyb -> k1;
hyb -> k2;
hyb -> kn;
k1 -> k1q1;
k1 -> k1q2;
k1 -> k1qn;
k2 -> k2q1;
k2 -> k2q2;
k2 -> k2qm;
kn -> knq1;
kn -> knq2;
kn -> knql;
bands1 -> k1q2;
bands1 -> k2qm;
bands1 -> knq1
bands2 -> k1qn;
bands2 -> knq1;
bands3 -> knql;
bands3 -> k1q1;
{edge[ style=invis];
k1->k2->kn;
k1q1->k1q2->k1qn->k2q1->k2q2->k2qm->knq1->knq2->knql;
}
{ rank=min; hyb}
{ rank=same; k1;k2;kn}
{ rank=same; k1q1;k1q2;k1qn;k2q1;k2q1;k2qm;knq1;knq2;knql}
{ rank=max; bands1;bands2;bands3}
}
Resulting in this graph:
All the ks are on one level, all the qs are one level and so are the bands. Then I would like to draw some boxes around the qs using clusters. So if I uncomment the subgraph in above code I have to comment this line:
{ rank=same; k1q1;k1q2;k1qn;k2q1;k2q1;k2qm;knq1;knq2;knql}
and I get:
Here the bands get thrown in same level with the qs. How can I get the levels from the top graph with the nice boxes from the bottom graph?
add this: newrank=true
See: https://graphviz.org/docs/attrs/newrank/
(you could also probably accomplish it by changing the direction of the bandX->qY edges, like so: k1q2->bands1 [dir=back])

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:

Straight edge between clusters in Graphviz

I'm trying to have an edge between clusters in Graphviz where the edge does not affect the ranking.
This looks fine:
digraph {
subgraph clusterX {
A
B
}
subgraph clusterY {
C
D
}
A -> B
B -> C [constraint=false]
C -> D
}
However when I add a label to the C -> D edge the B -> C edge tries to circumvent said label (which looks ugly).
digraph {
subgraph clusterX {
A
B
}
subgraph clusterY {
C
D
}
A -> B
B -> C [constraint=false]
C -> D [label=yadda]
}
Any idea how I can keep the edge from B to C straight?
The easiest way to achieve this is to add splines=false to the dot file - this forces the rendering of the edges to be straight lines:
digraph {
splines=false;
subgraph clusterX {
A;
B;
}
subgraph clusterY {
C;
D;
}
A -> B;
B -> C [constraint=false];
C -> D [label=yadda];
}
Output:
You can use this version :
digraph G {
subgraph cluster_X {
A [ pos = "0,1!" ];
B [ pos = "0,0!" ];
}
subgraph cluster_Y {
C [ pos = "1,1!" ];
D [ pos = "1,0!" ];
}
A -> B
B -> C[label="yadda"]
C -> D;
}
Then you use neato (not dot)
neato -Tpng -oyadda.png yadda.dot
And the result is :
Instead of the label attribute, you can use the attributes xlabel or headlbel or taillabel.
Result with xlabel:
Script:
digraph {
subgraph clusterX { A B }
subgraph clusterY { C D }
A -> B
B -> C [constraint=false]
C -> D [xlabel=yadda]
}
Result with headlabel:
Script:
digraph {
subgraph clusterX { A B }
subgraph clusterY { C D }
A -> B
B -> C [constraint=false]
C -> D [headlabel=yadda]
}
Result with taillabel:
Script:
digraph {
subgraph clusterX { A B }
subgraph clusterY { C D }
A -> B
B -> C [constraint=false]
C -> D [taillabel=yadda]
}

Resources