I have a number of boxes that are put on the same level as such:
via multiple {rank=same a3 b3_1 b3_2 c3_1 c3_2 d3_1 d3_2}; lines whereas I define my elements with a3 [label = "Assigned"]; lines.
I'd like to get a (dotted, if possible) box around all elements that are on the same level, as such (mockup via editor):
The whole source looks as follows:
digraph customer {
layout=dot
label = "some diagram";
labelloc = "t"; // place the label at the top
node [shape=record];
{rank=same a1 b1 c1 d1};
{rank=same a2 b2 c2 d2};
{rank=same a3 b3_1 b3_2 c3_1 c3_2 d3_1 d3_2};
{rank=same a4 b4_1_1 b4_1_2 b4_2_1 b4_2_2 c4_1_1 c4_1_2 c4_2_1 c4_2_2 d4_1_1 d4_1_2 d4_2_1 d4_2_2};
{rank=same a5 b5_1 b5_2 b5_3 b5_4 c5_1 c5_2 c5_3 c5_4 d5_1 d5_2 d5_3 d5_4};
{rank=same a6 b6_1 b6_2 b6_3 b6_4 c6_1 c6_2 c6_3 c6_4 d6_1 d6_2 d6_3 d6_4};
a1 [label = "Level 1"];
a2 [label = "Level 2"];
a3 [label = "Level 3"];
a4 [label = "Level 4"];
a5 [label = "Level 5"];
a6 [label = "Level 6"];
a1 -> a2 -> a3 -> a4; a4 -> a5 [label = "case ..." ]; a5 -> a6;
b1 [label = "Text A"];
b2 [label = "false"];
b3_1 [label = "no"];
b3_2 [label = "yes"];
b4_1_1 [label = "same"];
b4_1_2 [label = "different"];
b4_2_1 [label = "same"];
b4_2_2 [label = "different"];
b5_1 [label = "no", fillcolor = red, style=filled];
b5_2 [label = "no", fillcolor = red, style=filled];
b5_3 [label = "no", fillcolor = red, style=filled];
b5_4 [label = "yes", fillcolor = green, style=filled];
b6_1 [label = "yes", fillcolor = green, style=filled];
b6_2 [label = "yes", fillcolor = green, style=filled];
b6_3 [label = "yes", fillcolor = green, style=filled];
b6_4 [label = "yes", fillcolor = green, style=filled];
b1 -> b2;
b2 -> b3_1; b3_1 -> b4_1_1; b4_1_1 -> b5_1 [label = "A" ]; b5_1 -> b6_1;
b3_1 -> b4_1_2; b4_1_2 -> b5_2 [label = "B" ]; b5_2 -> b6_2;
b2 -> b3_2; b3_2 -> b4_2_1; b4_2_1 -> b5_3 [label = "C" ]; b5_3 -> b6_3;
b3_2 -> b4_2_2; b4_2_2 -> b5_4 [label = "D" ]; b5_4 -> b6_4;
subgraph clusterone {
a1; b1; c1; d1;
label="level 1";
graph[style=dotted];
}
c1 [label = "Text B"];
c2 [label = "true"];
c3_1 [label = "no"];
c3_2 [label = "yes"];
c4_1_1 [label = "same"];
c4_1_2 [label = "different"];
c4_2_1 [label = "same"];
c4_2_2 [label = "different"];
c5_1 [label = "no", fillcolor = red, style=filled];
c5_2 [label = "no", fillcolor = red, style=filled];
c5_3 [label = "yes", fillcolor = green, style=filled];
c5_4 [label = "yes", fillcolor = green, style=filled];
c6_1 [label = "yes", fillcolor = green, style=filled];
c6_2 [label = "yes", fillcolor = green, style=filled];
c6_3 [label = "yes", fillcolor = green, style=filled];
c6_4 [label = "yes", fillcolor = green, style=filled];
c1 -> c2;
c2 -> c3_1; c3_1 -> c4_1_1; c4_1_1 -> c5_1 [label = "E" ]; c5_1 -> c6_1;
c3_1 -> c4_1_2; c4_1_2 -> c5_2 [label = "F" ]; c5_2 -> c6_2;
c2 -> c3_2; c3_2 -> c4_2_1; c4_2_1 -> c5_3 [label = "G" ]; c5_3 -> c6_3;
c3_2 -> c4_2_2; c4_2_2 -> c5_4 [label = "H" ]; c5_4 -> c6_4;
d1 [label = "(else)"];
d2 [label = "???", fillcolor = yellow, style=filled];
d3_1 [label = "no"];
d3_2 [label = "yes"];
d4_1_1 [label = "same"];
d4_1_2 [label = "different"];
d4_2_1 [label = "same"];
d4_2_2 [label = "different"];
d5_1 [label = "no", fillcolor = red, style=filled];
d5_2 [label = "no", fillcolor = red, style=filled];
d5_3 [label = "no", fillcolor = red, style=filled];
d5_4 [label = "no", fillcolor = red, style=filled];
d6_1 [label = "yes", fillcolor = green, style=filled];
d6_2 [label = "yes", fillcolor = green, style=filled];
d6_3 [label = "yes", fillcolor = green, style=filled];
d6_4 [label = "yes", fillcolor = green, style=filled];
d1 -> d2;
d2 -> d3_1; d3_1 -> d4_1_1; d4_1_1 -> d5_1 [label = "I" ]; d5_1 -> d6_1;
d3_1 -> d4_1_2; d4_1_2 -> d5_2 [label = "J" ]; d5_2 -> d6_2;
d2 -> d3_2; d3_2 -> d4_2_1; d4_2_1 -> d5_3 [label = "K" ]; d5_3 -> d6_3;
d3_2 -> d4_2_2; d4_2_2 -> d5_4 [label = "L" ]; d5_4 -> d6_4;
}
By some reason it conflicts with rank=same declaration.
Try removing it and use cluster instead with rank=same inside, like this:
subgraph cluster_one {
label="cluster one";
rank=same;
style=dotted;
a1 b1 c1 d1
};
subgraph cluster_two {
label="cluster two";
rank=same;
style=dotted;
a2 b2 c2 d2
};
or even shorter (one line):
subgraph cluster_one { label="cluster one" rank=same style=dotted a1 b1 c1 d1 }
Keep in mind, that width of subgraphs will not be the same, as it used to be.
Related
Trying to put all thick bordered items into a vertical alignment. How do I do this?
Also, I'm trying to get the empty dot, where the two lines combine into one, to go away so the edges are connected. They are denoted by the "i*" naming convention. Specifically for this, I want the two lines to merge back together then attach to the next item. I tried the concentrate = "true" and that did not work as expected. The lines basically did not merge back together.
digraph G {
concentrate = "true";
node[shape="box", style="rounded"];
{
start [penwidth = 2.0];
end [penwidth = 2.0];
}
// PROCESS
node[shape="box"];
{
calc [label = "Calculate\nSelected\nValues", penwidth = 2.0];
deployPara [label = "Deploy\nPatachute" ];
bldMsg [label = "Build\nMessage"];
sendMsg [label = "Transmit\nMessage"];
sleepCycle [label = "Sleep\nCycle", penwidth=2];
}
// Decision
node[shape="diamond", style=""]
{
decidePara [label = "Decide\nDeploy", penwidth=2];
decideMsg [label = "Decide\nMessage", penwidth=2];
}
node[shape = point, width = 0, height = 0];
{
iDeploy
iMsg
}
start -> decidePara
decidePara -> iDeploy [label = "No", arrowhead = "none"]
decidePara -> deployPara [label = "Yes"]
deployPara -> iDeploy [arrowhead = "none"]
iDeploy -> decideMsg ;
decideMsg -> iMsg [label = "No", arrowhead = "none"];
decideMsg -> bldMsg [label = "Yes"];
bldMsg -> sendMsg;
sendMsg -> iMsg [arrowhead = "none"]
iMsg -> sleepCycle
sleepCycle -> end;
{rank=same; decidePara deployPara}
{rank=same; decideMsg bldMsg sendMsg}
}
Edit the image commenter sees is:
Changes:
splines=false (assuming you want straight lines)
gave all nodes needing alignment a group attribute (see https://graphviz.org/docs/attrs/group/)
changed size of i* nodes to fill in the gap
also used headclip & tailclip attributes (https://graphviz.org/docs/attrs/headclip/) to fill in the gap (not sure if needed)
digraph G {
concentrate = "true";
splines=false
node[shape="box", style="rounded"];
{
start [penwidth = 2.0 group=S];
end [penwidth = 2.0 group=S];
}
// PROCESS
node[shape="box"];
{
calc [label = "Calculate\nSelected\nValues", penwidth = 2.0];
deployPara [label = "Deploy\nPatachute" ];
bldMsg [label = "Build\nMessage"];
sendMsg [label = "Transmit\nMessage"];
sleepCycle [label = "Sleep\nCycle", penwidth=2 group=S];
}
// Decision
node[shape="diamond", style=""]
{
decidePara [label = "Decide\nDeploy", penwidth=2 group=S];
decideMsg [label = "Decide\nMessage", penwidth=2 group=S];
}
node[shape = point, width = .01, height = .01 group=S];
{
iDeploy
iMsg
}
start -> decidePara
decidePara -> iDeploy [label = "No", arrowhead = "none" headclip=false]
decidePara -> deployPara [label = "Yes"]
deployPara -> iDeploy [arrowhead = "none" headclip=false]
iDeploy -> decideMsg [tailclip=false]
decideMsg -> iMsg [label = "No", arrowhead = "none" headclip=false];
decideMsg -> bldMsg [label = "Yes"];
bldMsg -> sendMsg;
sendMsg -> iMsg [arrowhead = "none"]
iMsg -> sleepCycle [tailclip=false]
sleepCycle -> end;
{rank=same; decidePara deployPara}
{rank=same; decideMsg bldMsg sendMsg}
}
Giving:
I have a PATRICA trie for which I'm generating a GraphViz file. The internal nodes are the skip values and the edges are dotted 0 and solid 1. It is preferred that 0 is to the left of 1, giving an alphabetical order of the leaves. I re-arranged the order I visit the graph so dot gives this result. However, when I group them in trees in a forest using subgraphs, I can't seem to force dot to reliably respect the order for inter-subgraph edges.
digraph {
rankdir=TB;
node [shape = box, style = filled, fillcolor = lightsteelblue];
// forest size 2.
subgraph cluster_tree0 {
style = filled; fillcolor = lightgray; label = "tree 0";
// branches
branch0_0 [label = "3", shape = none, fillcolor = none];
branch0_0 -> branch0_1;
branch0_1 [label = "0", shape = none, fillcolor = none];
branch0_1 -> branch0_2 [style = dashed];
branch0_2 [label = "1", shape = none, fillcolor = none];
branch0_2 -> leaf0_1 [style = dashed, color = royalblue];
branch0_2 -> leaf0_2 [color = royalblue];
branch0_1 -> branch0_3;
branch0_3 [label = "2", shape = none, fillcolor = none];
branch0_3 -> leaf0_3 [style = dashed, color = royalblue];
branch0_3 -> leaf0_4 [color = royalblue];
// leaves
leaf0_1 [label = "u"];
leaf0_2 [label = "v"];
leaf0_3 [label = "x"];
leaf0_4 [label = "y"];
}
branch0_0 -> branch1_0 [lhead = cluster_tree0, ltail = cluster_tree1, color = firebrick, style = dashed];
subgraph cluster_tree1 {
style = filled; fillcolor = lightgray; label = "tree 1";
// branches
branch1_0 [label = "0", shape = none, fillcolor = none];
branch1_0 -> leaf1_0 [style = dashed, color = royalblue];
branch1_0 -> branch1_1;
branch1_1 [label = "1", shape = none, fillcolor = none];
branch1_1 -> leaf1_1 [style = dashed, color = royalblue];
branch1_1 -> branch1_2;
branch1_2 [label = "0", shape = none, fillcolor = none];
branch1_2 -> leaf1_2 [style = dashed, color = royalblue];
branch1_2 -> leaf1_3 [color = royalblue];
// leaves
leaf1_0 [label = "f"];
leaf1_1 [label = "m"];
leaf1_2 [label = "n"];
leaf1_3 [label = "o"];
}
}
On one graph it works fine, but it the subgraphs are reversed to the order I want them.
I reversed the order in the file and it still looks the same. I played around with it and I could get it turned around by rank=same, ordering=out, and invis edges somehow, but I want it to be programmatic. Is there any easy way to draw the red dotted line, representing 0, to the left, instead of to the right, of the solid line, representing 1?
OK, a total kludge, but probably fully scriptable.
First, your input somewhat reworked:
digraph {
rankdir=TB;
newrank=true // helps
graph [splines=false]
node [shape = box, style = filled, fillcolor = lightsteelblue];
// forest size 2.
subgraph cluster_tree1 {
style = filled; fillcolor = lightgray; label = "tree 1";
// branches
branch1_0 [label = "0", shape = none, fillcolor = none];
branch1_0 -> leaf1_0 [style = dashed, color = royalblue];
branch1_0 -> branch1_1;
branch1_1 [label = "1", shape = none, fillcolor = none];
branch1_1 -> leaf1_1 [style = dashed, color = royalblue];
branch1_1 -> branch1_2;
branch1_2 [label = "0", shape = none, fillcolor = none];
branch1_2 -> leaf1_2 [style = dashed, color = royalblue];
branch1_2 -> leaf1_3 [color = royalblue];
// leaves
leaf1_0 [label = "f"];
leaf1_1 [label = "m"];
leaf1_2 [label = "n"];
leaf1_3 [label = "o"];
}
subgraph cluster_tree0 {
style = filled; fillcolor = lightgray; label = "tree 0";
// branches
branch0_0 [label = "3", shape = none, fillcolor = none];
branch0_0 -> branch0_1;
branch0_1 [label = "0", shape = none, fillcolor = none];
branch0_1 -> branch0_2 [style = dashed];
branch0_2 [label = "1", shape = none, fillcolor = none];
branch0_2 -> leaf0_1 [style = dashed, color = royalblue];
branch0_2 -> leaf0_2 [color = royalblue];
branch0_1 -> branch0_3;
branch0_3 [label = "2", shape = none, fillcolor = none];
branch0_3 -> leaf0_3 [style = dashed, color = royalblue];
branch0_3 -> leaf0_4 [color = royalblue];
// leaves
leaf0_1 [label = "u"];
leaf0_2 [label = "v"];
leaf0_3 [label = "x"];
leaf0_4 [label = "y"];
}
// position the clusters (trees)
{rank=same branch1_0 -> branch0_1 [style=invis weight=0]}
// a kludge, we'll add this edge in later
graph [comment="branch0_0 -> branch1_0 [color = firebrick, style = dashed constraint=false weight=0 ];"]
}
The "problem" is the cluster-to-cluster branch, so we remove it (for the first dot pass). And we add the invisible edge to position the clusters where we want them.
Run this input into dot -Tdot >myfile.dot. This sets positions for all nodes & edges.
Run that thru gawk (any language) to un-comment the commented branch(s) and insert into the file.
Finally, neato -n2 -Tpng fixedfile >fixed.png
(yuck, but it works)
f=atrie4.gv;
T=png; F=`basename $f .gv`;dot -Tdot $f >$F.dot;
gawk '
$1~/comment/{
sub(/[\t ]*comment="/,"")
sub(/"[\],;]?[\t ]*$/,"")
add[++a]=$0
next
}
{oline[++o]=$0}
END{
for (i=1;i<o;i++)print oline[i]
for (i=1;i<=a;i++)print add[i]
print oline[o]
}' $F.dot|
neato -n2 -Tpng >$F.$T
firefox $F.$T
I'm trying to obtain nested subgraphs in graphviz.
Graphviz version is 2.38.0 (20140413.2041)
Here is the code:
digraph G {
subgraph cluster_win {
style=filled;
color=lightgrey;
label = "Windows"
subgraph extra_enabled {
fillcolor = "#EDF1F2";
color = "#028d35";
label="Subdirectory extra included";
node [style=filled,color=white];
config_debug1 [label = "Configure Debug"];
config_release1 [label = "Configure Release"];
build_debug1 [label = "Build"];
build_release1 [label = "Build"];
config_debug1 -> build_debug1;
config_release1 -> build_release1;
shape=rect;
style=rounded;
}
subgraph extra_disabled {
label = "Subdirectory extra excluded";
config_debug2 [label = "Configure Debug"];
config_release2 [label = "Configure Release"];
build_debug2 [label = "Build"];
build_release2 [label = "Build"];
config_debug2 -> build_debug2;
config_release2 -> build_release2;
}
checkout [style=filled, color=white];
checkout -> extra_enabled;
checkout -> extra_disabled;
}
start -> checkout;
start [label="git push"; shape=Mdiamond];
}
And this is the result.
Graphviz draws two ordinary nodes "extra_enabled" and "extra_disabled". However, I want them to be subgraphs, containing nodes "Configure Release", "Configure Debug", "Build" and another "Build".
How can I fix it?
You need to do two things:
Connect nodes only, you cannot connect to a cluster
Cluster names need to be prefixed by cluster_
Applying this to your code
digraph G {
subgraph cluster_win {
style=filled;
color=lightgrey;
label = "Windows "
subgraph cluster_extra_enabled {
fillcolor = "#EDF1F2";
color = "#028d35";
label="Subdirectory extra included";
node [style=filled,color=white];
config_debug1 [label = "Configure Debug"];
config_release1 [label = "Configure Release"];
build_debug1 [label = "Build"];
build_release1 [label = "Build"];
config_debug1 -> build_debug1;
config_release1 -> build_release1;
shape=rect;
style=rounded;
}
subgraph cluster_extra_disabled {
label = "Subdirectory extra excluded";
config_debug2 [label = "Configure Debug"];
config_release2 [label = "Configure Release"];
build_debug2 [label = "Build"];
build_release2 [label = "Build"];
config_debug2 -> build_debug2;
config_release2 -> build_release2;
}
checkout [style=filled, color=white];
checkout -> config_debug1;
checkout -> config_release2;
}
start -> checkout;
start [label="git push"; shape=Mdiamond];
}
I get
which is probably close to what you want. Note that I have added a few spaces to the label "Windows " to get it out of the way of the arrow. You could also use labeljust. There are also ways to make the edge end at the boundary of the cluster, but that would have needed a lot more editing on my part which I was not sure you want it.
I just wanted to append to the answer that vaettchen added. While it is correct that you cannot directly connect edges to clusters, edges must travel between nodes, there is a way to do so visually with lhead and ltail.
You can do the following:
node1 -> node2 [lhead=cluster_name_1, ltail=cluster_name_2]
Which will cut the connectors off at the limit of the cluster to connect clusters, this is just visual and is logged as a node connection, but it is a nicer way to visually display connections between whole clusters.
How to set the graph to try to fill the area allocated to it? With an increase in the number of nodes, it simply decreases in size, but also remains in one line, although the vertical size (40) allows placement down. If you remove the rankdir, then it places vertically, but also in one line.
digraph "test_graph"{
rankdir = LR;
bgcolor = whitesmoke;
graph [size = "15, 40"];
node [shape = circle,
style = filled,
margin = 0,
fontsize = 14,
color = sandybrown];
edge [fontsize = 10,
arrowhead = vee];
1->2 [label = "R"];
2->3 [label = "R"];
3->4 [label = "R"];
3->5 [label = "B"];
4->1 [label = "R"];
5->6 [label = "U"];
6->7 [label = "U"];
7->8 [label = "U"];
7->9 [label = "F"];
8->5 [label = "U"];
9->10 [label = "F"];
10->11 [label = "D"];
11->12 [label = "D"];
12->13 [label = "D"];
13->10 [label = "D"];
13->14 [label = "L"];
14->15 [label = "L"];
15->16 [label = "D"];
16->17 [label = "D"];
17->18 [label = "D"];
17->19 [label = "L"];
18->15 [label = "D"];
19->20 [label = "F"];
20->21 [label = "F"];
21->22 [label = "F"];
21->23 [label = "L"];
22->19 [label = "F"];
23->24 [label = "L"];
24->25 [label = "F"];
}
You will need to select suitable nodes that
are connected by one edge
connect to other nodes in a way that fills the available width as you like it
and then
connect them in the desired order by invisible edges (so that you avoid graphviz reordering them)
ranking them on the same lavel so that they appear one below the other
In concrete terms this means that adding
1 -> 10 -> 19[ style = invis ];
{ rank = same; 1 10 19 }
just before the closing curly brace, as the last two lines, will produce
which is, as far as I understand your requirement, what you want.
I would like to achieve either a) vertical edge labels or b) a horizontally extending tree in order to fit this graph on a single A4 page. How would I do it?
digraph g {
node[shape=point]
root -> 1 [label = "abcdefghijklmnopqrstuvwxyz$"]
root -> 2 [label = "bcdefghijklmnopqrstuvwxyz$"]
root -> 3 [label = "cdefghijklmnopqrstuvwxyz$"]
root -> 4 [label = "defghijklmnopqrstuvwxyz$"]
root -> 5 [label = "efghijklmnopqrstuvwxyz$"]
root -> 6 [label = "fghijklmnopqrstuvwxyz$"]
root -> 7 [label = "ghijklmnopqrstuvwxyz$"]
root -> 8 [label = "hijklmnopqrstuvwxyz$"]
root -> 9 [label = "ijklmnopqrstuvwxyz$"]
root -> 10 [label = "jklmnopqrstuvwxyz$"]
root -> 11 [label = "klmnopqrstuvwxyz$"]
root -> 12 [label = "lmnopqrstuvwxyz$"]
root -> 13 [label = "mnopqrstuvwxyz$"]
root -> 14 [label = "nopqrstuvwxyz$"]
root -> 15 [label = "opqrstuvwxyz$"]
root -> 16 [label = "pqrstuvwxyz$"]
root -> 17 [label = "qrstuvwxyz$"]
root -> 18 [label = "rstuvwxyz$"]
root -> 19 [label = "stuvwxyz$"]
root -> 20 [label = "tuvwxyz$"]
root -> 21 [label = "uvwxyz$"]
root -> 22 [label = "vwxyz$"]
root -> 23 [label = "wxyz$"]
root -> 24 [label = "xyz$"]
root -> 25 [label = "yz$"]
root -> 26 [label = "z$"]
root -> 27 [label = "$"]
}
rankdir=LR can let you fit it on one page
digraph g {
graph[rankdir=LR]
node[shape=point]
root -> 1 [label = "abcdefghijklmnopqrstuvwxyz$"]
root -> 2 [label = "bcdefghijklmnopqrstuvwxyz$"]
...
}
http://www.graphviz.org/doc/info/attrs.html#d:rankdir
One work-around I just discovered on the net was to seperate every character with a '\n' (eg. a newline character). It's not pretty, but it basically achieves vertical edge labels:
For example:
root -> 1 [label = "f\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nw\nx\ny\nz\n$"]
One possibility is to use the unflatten utility.
For example:
unflatten -l 8 yourdotfile.gv | dot | neato -s -n2 -Tpng -o result.png
The resulting graph is not as wide as before.