Arranging graphviz clusters - graphviz

I'm trying to generate the following construct:
I have four graphs. Three of them are supposed to be in the first "row", all vertically aligned by their vertical center. The fourth graph is supposed to be below the other three, in the second "row". It should be horizontally aligned with either the horizontal center of the upper row's middle graph or the horizontal center of the entire upper row. Additionally there will be edges between some members of separate clusters/graphs.
Here there are only edges between members of cluster_a and cluster_d, but there may be edges between members of any combination of clusters.

Ususal you can do this by adding some additional invisible scarfolding nodes and edges e.g.:
digraph G {
rankdir=LR
edge[minlen=2]//enable finer control over node location when scarfolding
subgraph cluster_d { label=cluster_d
d_0->d_2
d_1->d_0
//d_1->d_3
//extra node to simulate edge between edges
d_13[shape=point]
d_1->d_13[dir=none minlen=1]
d_13->d_3[minlen=1]
d_3->d_2
d_3->d_3
}
subgraph cluster_abc { // better align cluster
subgraph cluster_a { label=cluster_a
a_0->a_2
a_0->a_3
a_1->a_0
a_1->a_1
a_1->a_2
a_1->a_3
//a_2->a_3
//extra node to simulate edge between edges
a_23[shape=point]
a_2->a_23[dir=none minlen=1]
a_23->a_3[minlen=1]
a_3->a_2
a_3->a_3
}
subgraph cluster_c { label=cluster_c
c_0->c_0
c_0->c_1
c_0->c_2
c_0->c_3
c_1->c_3
c_3->c_3
c_2->c_0
c_2->c_1
c_2->c_2
c_2->c_3
}
subgraph cluster_b { label=cluster_b
b_0->b_0
b_0->b_2
b_0->b_3
b_1->b_1
b_1->b_2
b_1->b_3
b_2->b_0
b_3->b_2
}
color=invis
}
{//scarfolding
edge[style=invis]node[style=invis] //hide scarfolding
{
rank=same
node[shape=point] //minimize impact on edge routing around the scarfolding nodes
x_0
x_1
}
a_3->c_0
c_3->b_0
// we can not use same rank across cluster boundary so instead of a_3->d_1 we do a_2->x_0 + x_1->d_1
a_2->x_0
x_1->d_1[minlen=3]
}
{
edge[headclip=false tailclip=false]
a_2->d_1[dir=none constraint=false]
a_3->d_3[dir=none]
}
a_23->d_13[dir=none constraint=false]
}

Related

Graph in Graph Extraction

I want to draw a graph with "dot" format. The graph I want is a (sub)graph in a graph style. The subgraph (a child) has internal graph, and the (parent) graphs are connected among the parents, and does not connect to children that are connected only in the subgraph.
Could you please guide how writing such style with the dot-format, with an example?
Good news:
creating your "parent nodes" is pretty easy. Graphviz, (dot) calls them "cluster subgraphs" (or clusters). (well documented on p. 19 of https://www.graphviz.org/pdf/dotguide.pdf) see below for an example.
Bad news:
explicitly sizing clusters is very difficult. Dot sizes a cluster to be just big enough to contain its nodes.
explicitly positioning clusters is also quite difficult. Dot positions clusters based on the "best" positioning of the component nodes, specifically the edges that connect nodes within the various clusters.
drawing edges from one cluster to another is a kludge. You define an edge from a node contained within one cluster to another node contained within a different cluster and instruct dot to clip that edge so it appears to be from cluster to cluster. This uses the attribute compound=true. (again, read the documentation listed above)
Finally: the fdp engine allows cluster-to-cluster edges, but you lose the directionality of the edges
Drawn with dot:
digraph C {
graph [compound=true] // allows edges to/from clusters
// create an extra cluster to try to keep clusterA above clusterB
subgraph clusterWrapper {
graph [peripheries=0] // no box around
subgraph clusterA {
graph [peripheries=1] // box around
a -> c
b->c
c->d
}
subgraph clusterB {
graph [peripheries=1] // box around
f->g
e->g
}
} // end of wrapper
subgraph clusterC {
edge [dir=none ] // no arrowheads
h->k
i->k
i->l
j->l
{rank=same h->i->j [style=invis]}
}
b->f [ltail=clusterA, lhead=clusterB];
l:s->b:n [ltail=clusterC, lhead=clusterA];
l->f [style=invis weight=50]
}
Giving:

Is it possible to specify a cluster inside a subgraph

I would like to create several clusters inside a subgraph like the following :
subgraph sub {
rank=same;
subgraph cluster_test {
p4;
p5;
p6;
}
subgraph cluster_t {
p1;
p2;
p3;
}
}
My aim is to have several clusters (which group the nodes together) at the same rank. However it seems clusters do not work inside subgraphs. Is there a way around that ?
rank=same can't apply across clusters. (yes, it would be nice). Clusters are laid out independently, rank=same would require dependent layout.
Also rank=same really applies to nodes within a subgraph, not a cluster, that can consist of nodes in multiple ranks.
Clusters are positioned based on the ranks of the enclosed nodes, but to try to get multiple clusters horizontally aligned, try embedding then within a parental cluster, like so (or using invisible edges to adjust ranking):
digraph D {
subgraph cluster_outer{
subgraph cluster_test {
p4;
p5;
p6;
}
subgraph cluster_t {
p1;
p2;
p3;
}
graph [peripheries=0] // if you don't want the extra box
}
}
Giving:
[

How to have multiple label one above and one below the edges in graphviz?

I've the following output currently I want to place a label below the edge between p and z in the figure.Is it possible to do in graphviz I've tried using xlabels but it doesn't work.
Current Code:
digraph GPG{
node [shape=box];
subgraph cluster0{
node[shape=circle];
0[label=0,style=invis];
}
subgraph cluster1{
node[shape=circle];
1[label=1,style=invis];
p->z [label="2 | 1",minlen=1];
{
rank = same;
p;z;
}
}
subgraph cluster2{
node[shape=circle];
2[label=2,style=invis];
}
0->1
1->2
}
I want a label below edge p->z as well above the edge.Is it possible in graphviz?
Kind of ugly, but:
digraph overunder{
splines=false
{ rank=same
a -> b [label=" over " ]
a -> b [label="under" penwidth=0.0 dir=none]
}
}
Produces:
You may have to add the non-breaking space characters (see above) because Graphviz seems to position labels based on the length of the text - longer labels are placed above shorter labels.

Graphviz: How to place nodes only in lower semi-circle using circo layout?

In the attached figure, the nodes are arranged in a circle around the node. Is there a (possibly generic) way to arrange the nodes only in the lower semi-circle, without having to provide fixed coordinates for the nodes?
Edit: Would like to achieve something like shown in the image attached below. As one can see - all the nodes are arranged in the lower semi-circular region (this figure was made using CMap Tools).
The code is trivial, but pasting it anyway.
digraph semicircle {
rankdir="TD"
graph [nodesep="0.1", ranksep="0.3", center=true]
mindist="0.4"
S [label="Root", style="filled", fillcolor="greenyellow", shape="box"]
subgraph cluster1 {
rank="same"
A; B; C; D;
S -> {A, B, C, D};
} }
using dot/circo : graphviz version 2.40.1
I noted that circo placed nodes counter-clockwise, starting at 3 o'clock.
I added enough invisible nodes to fill the 2 through 10 o'clock positions.
To make the inter-nodal distances even more uniform I added:
node [shape=square style=rounded]
The result I got is this:
Try this:
digraph semicircle {
rankdir="TD"
graph [nodesep="0.1", ranksep="0.3", center=true, root=S]
mindist="0.4"
S [label="Root", style="filled", fillcolor="greenyellow", shape="box"]
subgraph cluster1 {
rank="same"
A
z1[style=invis label=""]
z2[style=invis label=""]
B; C; D;
S -> A
S -> z1,z2 [style=invis]
S -> { B, C, D};
}
}

graphviz/dot: can the distance between two nodes be set individually?

I'm trying to use dot (version 2.28.0) in order to make a flow chart of my source code. For that, I would like the graph to consist of subgraphs where each of these subgraphs represents a source file in the code base. At the top of each subgraph, there should be the file name as a node in a visually easily distinguishable fashion (i.e. bold, white text on dark blue background). Below the file name node should be the nodes representing the flow of routines in that file in the order they are being called.
My problem now is that I would like the distance between "filename nodes" and "routine nodes" to be smaller than the distance between individual "routine nodes", plus, there should be no arrow between.
I tried to use the minlen attribute for the edge connecting the "filename node" to the first "routine node", but when I set that to a value below 1.0, the two nodes come out next to each other rather than stacked.
Is there any way to make the first two nodes be closer to each other than the other two, yet top/bottom oriented?
digraph "prog.c"
{
edge [fontname="FreeSans",fontsize="12",labelfontname="FreeSans",labelfontsize="10"];
node [fontname="FreeSans",fontsize="14",shape=record,height=0.2];
compound=true;
subgraph cluster_main {
Node1_0 [label="main.c", shape=folder, fontcolor="white", style=filled, fillcolor="#00008b"];
Node1_1 [label="routine1()"];
Node1_2 [label="routine2()"];
edge [color="transparent", minlen="0.5"]; // stacking not ok
// edge [color="transparent", minlen="1.0"]; // stacking ok
Node1_0 -> Node1_1 ;
edge [color="black", minlen="1.0"];
Node1_1 -> Node1_2 ;
}
}
Edit: I should have commented out the line which lead to the undesired result rather than the one leading to the desired result (I had planned to attach two pngs for clarification, but I'm not allowed to do so as a newbie); so here is the code I would actually want to modify in a way that the first two nodes have a different (smaller) distance to each than the last two.
digraph "prog.c"
{
edge [fontname="FreeSans",fontsize="12",labelfontname="FreeSans",labelfontsize="10"];
node [fontname="FreeSans",fontsize="14",shape=record,height=0.2];
compound=true;
subgraph cluster_main {
Node1_0 [label="main.c", shape=folder, fontcolor="white", style=filled, fillcolor="#00008b"];
Node1_1 [label="routine1()"];
Node1_2 [label="routine2()"];
//edge [color="transparent", minlen="0.5"]; // stacking not ok
edge [color="transparent", minlen="1.0"]; // stacking ok
Node1_0 -> Node1_1 ;
edge [color="black", minlen="1.0"];
Node1_1 -> Node1_2 ;
}
}
There are a couple of "graph" properties that can control what you need.
pad, ranksep, nodesep
Also, I increased your node size, but only for my own ease of use...
digraph "prog.c"
{
graph [pad=".75", ranksep="0.25", nodesep="0.25"];
node [fontname="FreeSans",fontsize="14",shape=record,width=2, height=.5];
edge [fontname="FreeSans",fontsize="12",labelfontname="FreeSans",labelfontsize="10"];
compound=true;
subgraph cluster_main {
Node1_0 [label="main.c", shape=folder, fontcolor="white", style=filled, fillcolor="#00008b"];
Node1_1 [label="routine1()"];
Node1_2 [label="routine2()"];
edge [color="transparent", minlen="0.5"]; // stacking not ok
// edge [color="transparent", minlen="1.0"]; // stacking ok
Node1_0 -> Node1_1 ;
edge [color="black", minlen="1.0"];
Node1_1 -> Node1_2 ;
}
}

Resources