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

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).

Related

Align nodes in a Graphviz directed graph

I have the following Graphviz code:
digraph {
Technique [shape = box];
Path [shape = box];
KnowledgeObservation [shape = box, label = "Knowledge\nObservation"];
ManagementIntervention [shape = box, label = "Management\nIntervention"];
ResultsModification [shape = box, label = "Results\nModification"];
SharedCode [label = "Shared Code"];
MediatedRelationship [label = "Mediated Relationship"];
Art -> Technique;
Therapy -> Path;
{Technique Path} -> KnowledgeObservation -> ManagementIntervention -> ResultsModification;
{MediatedRelationship SharedCode} -> {KnowledgeObservation ResultsModification}
subgraph {
rank = same
Technique -> Path [dir = none]
}
subgraph {
rank = same
SharedCode
ManagementIntervention
MediatedRelationship
}
}
It currently produces the following output:
How can I vertically align "Management Intervention" with both "Knowledge Observation" and "Results Modification"?
"Shared Code" should be moved to the left of "Management Intervention".
"Mediated Relationship" should be moved to the right of "Management Intervention".
"Shared Code", "Management Intervention" and "Mediated Relationship" should stay horizontally aligned.
How can I accomplish this?
This can be achieved without subgraphs; the most important modification is the line
{ rank = same; SharedCode -> ManagementIntervention -> MediatedRelationship[ style = invis ] }
which keeps the three nodes not only on the right level, but also within the desired order.
Altogether, this code here
digraph
{
// node definition
Art Therapy;
Technique[ shape = box ];
Path[ shape = box ];
KnowledgeObservation[ shape = box, label = "Knowledge\nObservation" ];
ManagementIntervention[ shape = box, label = "Management\nIntervention" ];
ResultsModification[ shape = box, label = "Results\nModification" ];
SharedCode[ label = "Shared Code" ];
MediatedRelationship[ label = "Mediated Relationship" ];
// edges
Art -> Technique;
Therapy -> Path;
{ rank = same; Technique -> Path [dir = none] }
{ Technique Path} -> KnowledgeObservation -> ManagementIntervention -> ResultsModification;
{ rank = same; SharedCode -> ManagementIntervention -> MediatedRelationship[ style = invis ] }
{ MediatedRelationship SharedCode } -> { KnowledgeObservation ResultsModification }
}
gives you
which is, in my understanding, what you are looking for.
Still I would recommend to replace the last line of code with these three
KnowledgeObservation -> { SharedCode MediatedRelationship }[ dir = back ];
SharedCode -> ResultsModification;
MediatedRelationship -> ResultsModification;
Reason is that once your graph gets more complicated, graphviz will recognize and maintain the hierarchical relationships, rather than interpreting ambiguous instructions in surprising ways.
How can I vertically align "Management Intervention" with both "Knowledge Observation" and "Results Modification"?
This can be achieved with increasing the weight of the edge. Edges with higher weight tend to be straighter and shorter than with the lower.
"Mediated Relationship" should be moved to the right of "Management Intervention".
You can control this with the order in which the nodes are defined. If you define "Management Intervention" before the "Shared Code", it (MI) will be drawn first, i. e., to the left of the SI.
"Shared Code", "Management Intervention" and "Mediated Relationship" should stay horizontally aligned.
You did it right, using the rank=same subgraph attribute. Though I would put the subgraph already in the moment of node definitions. This will shorten the source size and limit the rank specification to the place where the nodes are defined, which is good for readability (everything stated in one place).
Your modified example:
digraph {
Technique [shape = box];
Path [shape = box];
KnowledgeObservation [shape = box, label = "Knowledge\nObservation"];
ResultsModification [shape = box, label = "Results\nModification"];
subgraph {
rank=same
ManagementIntervention [shape = box, label = "Management\nIntervention"];
MediatedRelationship [label = "Mediated Relationship"];
SharedCode [label = "Shared Code"];
}
Art -> Technique;
Therapy -> Path;
{Technique Path} -> KnowledgeObservation
KnowledgeObservation -> ManagementIntervention -> ResultsModification [weight=3]
{MediatedRelationship SharedCode} -> {KnowledgeObservation ResultsModification}
subgraph {
rank = same
Technique -> Path [dir = none]
}
}
Result:

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

self loop edges too short and ugly in graphviz

I drawed a picture using graphviz. Please see FSM.
I think It is ugly because self loop edges are so short.
The attribute "minlen" of edges doesn't work for me.
And I tried several ports of the node, but it all shows a mess except my current implementation. Do you have a clever idea for me ?
Code is here:
digraph finite_state_machine {
rankdir=LR;
size="8,2"
fontname="Verdana"
node [shape = doublecircle]; Idle;
node [shape = circle,nodesep = "2.0"];
Working:s -> Working:s [ label = "response[j]?" ,minlen = 50000];
Idle -> Working [ label = "boot" ];
Working:n -> Working:n [ label = "sendtx[i]!",minlen = 50000 ];
Working:e -> Working:e [ label = "qry!" ,minlen = 50000];
}
Adding nodesep=1; makes loops larger, although not nicer. So this would help:
digraph finite_state_machine {
rankdir=LR;
size="8,2"
fontname="Verdana"
node [shape = doublecircle]; Idle;
node [shape = circle,nodesep = "2.0"];
Working:s -> Working:s [ label = "response[j]?" ,minlen = 50000];
Idle -> Working [ label = "boot" ];
Working:n -> Working:n [ label = "sendtx[i]!" ];
Working:e -> Working:e [ label = "qry!"];
nodesep=1;
}
Will produce something like:
Dot Output

Graphviz forcing nodes to stack vertically despite rankdir=LR

I am new to Graphviz and trying to layout some nodes from left to right with something like the following:
digraph g {
graph [ rankdir = "LR" ];
node [ fontsize = "16", fontname="Arial" ];
nodesep = 1.0;
ranksep = 4.0;
"node0" [
label = "<f0>OBJECT0| <f1> Id | <f2> Name"
shape = "record" ];
"node1" [
label = "<f0>OBJECT1| <f1> Id | <f2> Name"
shape = "record" ];
"node2" [
label = "<f0>OBJECT2| <f1> Id | <f2> Name"
shape = "record" ];
"node4" [
label = "<f0>OBJECT3| <f1> Id | <f2> Name"
shape = "record" ];
** I also have some connectors in here across the nodes **
}
This works ok for very basic nodes, but if I have say 100 rows within a node (representing a database table and fields) the nodes are stacked vertically and nothing I do seems to influence the damn things to revert back to a horizontal layout.
Any suggestions on how I might force the issue would be most appreciated - this one has me completely stuck!
Cheers
CH
Resolved - needed to add the line node0 -> node1 -> node2 -> node3 -> node4 [style=invis]

Resources