How to adjust outer labels for nodes - graphviz

I want to plot graph with some outer labels.
I found that there some helpful attributes - xlabel,taillabel,headlabel but the result still looks weird.
MCVE
digraph {
forcelabels=true;
node [shape=point,style=filled;label="",height=0.2];
y3[color=black;xlabel=<"y3 (2)">];x3[color=gray;xlabel=<"x3 [0.25]">];
y2[color=black;xlabel=<"y2 (3)">];x2[color=gray;xlabel=<"x2 [0.3]">];
y1[color=black;xlabel=<"y1 (2)">];x1[color=gray;xlabel=<"x1 [0.1]">];
y5[color=black;xlabel=<"y5 (4)">];x5[color=gray;xlabel=<"x5 [0.15]">];
x4[color=gray;xlabel=<"x4 [0.2]">];
y3->y2[dir=none;taillabel = 0.75];
y2->y1[dir=none;taillabel = 0.45];
y1->y5[dir=none;taillabel = 0.35];
y3->x3[dir=none];
y2->x2[dir=none];
y1->x1[dir=none];
y5->x5[dir=none];
y5->x4[dir=none];
}
it looks like
As you can see, conformity between labels and nodes not always obvious.
So, the Q is - is there any way to change location of labels ?

This may not be the answer to your question as it still does not look great and takes a lot of manual adjustment, but I post it anyway: I spent quite some time fiddling around, and there may be some ideas that could be helpful for your actual context:
digraph
{
forcelabels = TRUE;
splines = FALSE;
// nodes
node[ shape = point, style = filled, color = gray, label = "", height = 0.2 ];
x3[ xlabel = <"x3 [0.25]"> ];
x2[ xlabel = <"x2 [0.3]"> ];
x1[ xlabel = <"x1 [0.1]"> ];
x5[ xlabel = <"x5 [0.15]"> ];
x4;
node[ color = black ];
y3, y2, y1, y5;
node[ shape = plaintext, fillcolor = white ];
y_3[ label = "y3 (2)" ];
y_2[ label = "y2 (3)" ];
y_1[ label = "y1 (2)" ];
y_5[ label = "y5 (4)" ];
// edges
edge[ dir = none ];
y3:se -> y2[ label = " 0.75" ];
y2:se -> y1[ label = " 0.45" ];
y1:se -> y5[ label = " 0.35" ];
y3 -> x3;
y2 -> x2;
y1 -> x1;
y5 -> x5;
y5 -> x4[ headlabel = <"x4 [0.2]"> ];
edge[ style = invis ];
{ rank = same; y3 -> y_3 }
{ rank = same; y2 -> y_2 }
{ rank = same; y1 -> y_1 }
{ rank = same; y5 -> y_5 }
}
yields

Related

Graphviz: route line from the left side of the node

I am trying to create flow chart as shown in the image #2 (with the red lines) but I am not able to position the lines from the left side of the onset node to the left side of the sampling node. If :w or :s is added to the node, line is broken and goes from the inside of the node. Is it possible to route the lines like that and put the text to the side so it doesn't collide with the line?
digraph G {
graph [splines=ortho];//, nodesep=0.8]
node [shape=record]
sampling [
label = "Sampling";
shape = rect;
];
onset [
label = "Onset\ndetection";
shape = diamond;
];
collect [
label = "Collect 1024 samples";
shape = rect;
];
xcorr [
label = "Compute\ncross correlation";
shape = rect;
];
display [
label = "Display data";
shape = rect;
];
sampling->onset;
onset->sampling [label = "No"];
onset->collect [label = "Yes"];
collect->xcorr;
xcorr->display;
xcorr->sampling [ label = "Return"; ];
{
rank = same;
collect; xcorr;
}
}

Drawing ellipsis between nodes in graphviz

I'm interested in drawing vertical ellipsis between nodes in graphviz like seen below:
The problem I'm having is whenever I try to do this I cannot seem to get x3 and xn to line up vertically as seen here:
Here is what I have tried:
digraph G {
rankdir=LR
splines=line
subgraph cluster_0 {
color=white;
node [style=solid, color=black, shape=circle];
x1 x2 x3 xn [group=g1];
label = "Input Features";
}
subgraph cluster_1 {
color=white;
node [style=solid, color=red2, shape=circle];
a1 [group=g2];
label = "Activation";
}
subgraph cluster_2 {
color=white;
node [style=solid, color=green, shape=circle];
out [group=g3];
label = "Output";
}
x1 -> a1;
x2 -> a1;
x3 -> a1;
a1 -> out;
x3 -> xn [arrowhead="none", color="black:invis:black"];
}
I'm very new to graphviz so I'm not even sure if I'm using subgraph properly here. I also tried adding the nodes in the subgraphs to groups, but that didn't seem to do anything.
Add
{ rank = same; x1 x2 x3 xn }
x1 -> x2 -> x3[ style = invis ];
to your first subgraph. This has the effect that
the four nodes are all one one level, i.e. lining up vertically
the three numbered nodes stay together
Here my version:
digraph G
{
rankdir = LR
splines = line
subgraph cluster_0
{
color = white;
node[ style = solid, color = black, shape = circle];
{ rank = same; x1 x2 x3 xn }
x1 -> x2 -> x3[ style = invis ];
label = "Input Features";
}
subgraph cluster_1
{
color = white;
node[ style = solid, color = red2, shape = circle ];
a1;
label = "Activation";
}
subgraph cluster_2
{
color =white;
node[ style = solid, color = green, shape = circle ];
out;
label = "Output";
}
x1 -> a1;
x2 -> a1;
x3 -> a1;
a1 -> out;
x3 -> xn[ arrowhead = "none", color = "black:invis:black" ];
}
which gives you
E D I T to answer the question in your comment; the key is reversing the order of node definitions and edge direction within the same rank, probably caused by the rankdir = LR layout. After all, there is a simple solution!
digraph G
{
rankdir = LR
splines = line
subgraph cluster_0
{
color = white;
label = "Input Features";
node[ style = solid, color = black, shape = circle ];
/* define and connect in reverse order */
{ rank = same; xn x3 x2 x1 }
x3 -> x2 -> x1[ style = invis ];
xn -> x3[ arrowhead = "none", color = "black:invis:black" ];
}
subgraph cluster_1
{
color = white;
node[ style = solid, color = red2, shape = circle ];
a1;
label = "Activation";
}
subgraph cluster_2
{
color =white;
node[ style = solid, color = green, shape = circle ];
out;
label = "Output";
}
{ x1 x2 x3 } -> a1;
a1 -> out;
}

Center alignment of clusters when connecting them

I have a two clusters that are connected but I can't seem to align the left most cluster (with node nd_6) with the center of the other node (cluster_circ). Here is an example:
digraph d1 {
# configs
rankdir = "LR";
compound=true;
node [shape = plaintext];
edge [arrowhead = "vee"];
nd_1 [group = g1]
nd_2 [group = g1]
# cluster for circular pattern
subgraph cluster_circ {
color=none;
node [shape = plaintext];
nd_3 [group = g1]
{rank=same nd_4[group = g2]; nd_5[group = g3]};
nd_3 -> nd_4:nw;
nd_4 -> nd_5:ne;
nd_5 -> nd_3:se;
}
# right-most cluster
subgraph cluster_r {
color=none;
node [shape = plaintext];
nd_6 [group = g1];
}
# edge connections
nd_1 -> nd_2;
nd_2 -> nd_3;
# connect clusters
nd_5 -> nd_6 [ltail=cluster_circ lhead=cluster_r]
}
Producing the following result:
What I am trying to achieve is to place the node nd_6 and its respective edge connecting to cluster_circ aligned with nd_3.
Thanks!
You need to do two things to achieve your goal:
match your compass points
have an invisible edge from nd_4 that that moves nd_6 up.
Both items are explained in the comments of the source code below. In the course of editing, I have removed a lot of stuff that were not material in the context, for easier reading.
digraph d1
{
// configs // comment characters changed to "standard"
rankdir = "LR";
node [ shape = plaintext ];
edge [ arrowhead = "vee" ];
// nodes
nd_1 nd_2 nd_3;
{ rank=same; nd_4 nd_5 }
nd_6
// edges / connections
nd_1 -> nd_2 -> nd_3;
nd_3 -> nd_4:nw; // matching :s and :n keeps the center:
nd_4:se -> nd_5:ne; // balance nd_4:n with nd_4:s
nd_3 -> nd_5:sw[ dir = back ]; // balance nd_5:n with nd_5:s
nd_4 -> nd_6[ style = invis ]; // this gives you a counterweight
nd_5 -> nd_6; // to nd_5 and thus "centers" nd_6
}
yields
E D I T to show the alternative with an empty node.
This is the result I like best, I have inserted some lines where you could play around with alternative settings. To the best of my knowledge, groups or subgraphs don't help, as edges only go between nodes, not between clusters.
digraph d1
{
// configs // comment characters changed to "standard"
rankdir = "LR";
node [ shape = plaintext ];
edge [ arrowhead = "vee" ];
// nodes
nd_1 nd_2 nd_3;
x[ shape = point, height = 0 ]; // "empty" node
// x[ shape = point, height = .25, color = white ]; // alternative
{ rank = same; nd_4 nd_5 }
// { rank = same; nd_4 x nd_5 } // try also with x in the same rank
nd_6
// edges / connections
nd_1 -> nd_2 -> nd_3;
nd_3 -> nd_4:nw;
nd_4:e -> x:n[ dir = none ]; // route edge via x
x:s -> nd_5:e; // you can try other compass points
nd_3 -> nd_5:sw[ dir = back ]; // balance nd_4:n with nd_5:s
x -> nd_6; // connect the empty node in the middle
}
which produces

Graphviz --- edge label too close to another edge

I have the following code, and it results in the image below. As you can see, it's a little crowded around the edges and edge labels, especially around the "^a". What is the best way to create just a tad more space, so that one can clearly see which label belongs to which edge?
digraph finite_state_machine {
pad=0.2;
{
rank=same;
node [shape = point, style = invis]; q_0;
node [shape = doublecircle, style = solid]; q_5;
node [shape = circle];
q_1 [ label = <<i>q<sub>1</sub></i>> ];
q_2 [ label = <<i>q<sub>2</sub></i>> ];
q_3 [ label = <<i>q<sub>3</sub></i>> ];
q_4 [ label = <<i>q<sub>4</sub></i>> ];
q_5 [ label = <<i>q<sub>5</sub></i>> ];
q_0 -> q_1;
q_1 -> q_2 [ label = "." ];
q_1 -> q_2 [ label = <ε>, constraint=false ];
q_2 -> q_1 [ label = <ε>, constraint=false ];
q_2 -> q_3 [ label = <<i>a</i>> ];
q_3 -> q_4 [ label = <<i>^a</i>> ];
q_3 -> q_4 [ label = <ε>, constraint=false ];
q_4 -> q_3 [ label = <ε>, constraint=false ];
q_4 -> q_5 [ label = <<i>b</i>> ];
}
}
There is no attribute in Graphviz to adjust the margin/padding around edge labels. The closest you can probably get to the effect you require is to use \n to introduce blank lines above/below your label to force space.
Obviously, this will not scale to anything automatic.
Alternately, you could try to use the ranksep attribute to force in some additional space.
If xlabel doesn't solve it, then wrapping the label in a table can sometimes be a work-around. For example:
q_1 -> q_2 [ label = <<table cellpadding="10" border="0" cellborder="0">
<tr><td>ε</td></tr>
</table>>,
constraint = false ];
To add more space on one side than on another, you can add an empty cell. The code then quickly becomes (more) unreadable, but you could use a simple sed script to pre-process your dot file.
I know this is an old question, but this approach below might also be helpful, if this is what you are looking for. see the image below.
i added the following to your code:
minlen=2 (to extend gaps between nodes)
tailport=n/s (to change location of the tail of the arrow to north/south)
headport=n/s (to change location of the head to the arrow to north or south)
digraph finite_state_machine {
pad=0.2;
{
rank=same;
node [shape = point, style = invis]; q_0;
node [shape = doublecircle, style = solid]; q_5;
node [shape = circle];
q_1 [ label = <<i>q<sub>1</sub></i>> ];
q_2 [ label = <<i>q<sub>2</sub></i>> ];
q_3 [ label = <<i>q<sub>3</sub></i>> ];
q_4 [ label = <<i>q<sub>4</sub></i>> ];
q_5 [ label = <<i>q<sub>5</sub></i>> ];
q_0 -> q_1;
q_1 -> q_2 [ label = "." ];
q_1 -> q_2 [ label = <ε>, constraint=false, minlen=2, tailport=n, headport=n];
q_2 -> q_1 [ label = <ε>, constraint=false, minlen=2, tailport=s, headport=s];
q_2 -> q_3 [ label = <<i>a</i>> ];
q_3 -> q_4 [ label = <<i>^a</i>> ];
q_3 -> q_4 [ label = <ε>, constraint=false, minlen=2, tailport=n, headport=n];
q_4 -> q_3 [ label = <ε>, constraint=false, minlen=2, tailport=s, headport=s];
q_4 -> q_5 [ label = <<i>b</i>> ];
}
}

how to control edge placements and labels in dot (graphviz)

I have trouble controlling the layout of graphviz.
Trying to produce a simple automaton.
The source:
digraph mygraph {
rankdir=LR;
size="13,13"
node [shape = circle];
init -> Ready [ label = "" ];
Ready -> P1 [ label = "t<T\n----TexT----" ];
P1 -> Ready [ label = "t>T" ];
P1 -> B1 [ label = "t<T" ];
B1 -> P1 [ label = "----TexT----" ];
B1 -> U1 [ label = "----TexT----" ];
Ready -> P2 [ label = "t<T\n----TexT----" ];
P2 -> Ready [ label = "t>T" ];
P2 -> B2 [ label = "t<T" ];
B2 -> P2 [ label = "----TexT----" ];
B2 -> U2 [ label = "----TexT----" ];
U1 -> Ready [ label = "----TexT----", constraint=false];
U2 -> Ready [ label = "----TexT----", constraint=false];
P1 -> P2 [ label = "t<T\n----TexT----", constraint=false];
P2 -> P1 [ label = "t<T\n----TexT----", constraint=false];
}
trouble is, the labels are intertwined. I probably need:
1. larger spacing
2. move some of the edges up
3. control label placings
how do I do it?
Since the conflict occurs on vertical edges going in opposite directions between nodes placed by dot on the same rank (P1 & P2) you could use vertical rank direction (drop the "rankdir=LR" line) so that the labels for theses specific edges are placed one below the other rather than side by side.
Granted, it's not a universal cure for this sort of issues but should help here without unnecessarily bloating the graph (which increasing node separation via "nodesep" would do).

Resources