how to define a graph with graphviz without overlapping labels - graphviz

The follow dot file demonstrates the issue I am trying to resolve:
digraph G {
splines=line;
rankdir=LR;
A -> B [label="a long label"];
A -> C [label="a long label"];
A -> A [label="a very long label"];
A -> A [label="a very long label"];
A -> D [label="a long label"];
}
It generates the follow the graph:
The labels are poorly positioned, nearly overlapping.
What can be done to improve the look of this graph?
I would define improve by saying (1) labels do not overlap with each other, (2) labels do not overlap edges, and (3) optionally / ideally labels are drawn along the edge. #3 may not be possible, but #1 and #2 should be sufficient. Using ortho splines would always provide an edge where a which a label could be drawn along and still be read normally, but this I know is not currently supported by graphviz.

"Improve" is in the eye of the beholder, but this uses ports, headlabels, spaces and newlines to rearrange the labels.
digraph G {
splines=line;
rankdir=LR;
// use ports to rearrange edges
// then headlabel, spaces, and newlines (\n)
A:n -> A:w [headlabel="a very long label "];
A:s -> A:w [headlabel="a very long label "];
A -> B [label="a long label"];
A -> C [label="a long label"];
A -> D [label="\n\na long label"];
}

There does not appear to be any supported solution in GraphViz that meet the desired criteria for edge labels. My work around is to split the edges between two nodes and insert another node containing the text of the edge label. The new node is styled to distinguish it from regular nodes.
The GraphViz layout algorithm does a good job of keep nodes separated and not allowing edges to overlap nodes.
Updating the test case with this workaround, I have the following dot file:
digraph G {
splines=ortho;
rankdir=LR;
AA1 [label="a very long label", shape="box", style = "filled", fillcolor = "#E6E6E6", color = "#FFFFFF" ]
AA2 [label="a very long label", shape="box", style = "filled", fillcolor = "#E6E6E6", color = "#FFFFFF" ]
AB1 [label="a long label", shape="box", style = "filled", fillcolor = "#E6E6E6", color = "#FFFFFF" ]
AC1 [label="a long label", shape="box", style = "filled", fillcolor = "#E6E6E6", color = "#FFFFFF" ]
AD1 [label="a long label", shape="box", style = "filled", fillcolor = "#E6E6E6", color = "#FFFFFF" ]
A -> AA1 [arrowhead = "none" ];
AA1 -> A
A -> AA2 [arrowhead = "none" ];
AA2 -> A
A -> AB1 [arrowhead = "none" ];
AB1 -> B
A -> AC1 [arrowhead = "none" ];
AC1 -> C
A -> AD1 [arrowhead = "none" ];
AD1 -> D
}
which produces this

Related

How can I separate with vertical bar in ellipse shape node in dot file?

I want to draw a clean network graph like this image.
But I couldn't find how can I do this. I have to use css for removing part of cell border line, but, as far as I know, dot file is not supported css. I want to insert ellipse shape node, separate node with vertical bar,
How can I draw a graph that satisfies these conditions? My dot file has self loop, so I can't use networkx. Any other ways are exist? or can I solve use dot file?
My dot file code is
digraph {
// size = "6,8.5";
// ratio = "fill";
// layout = "circo"
forcelabels = True;
graph[overlap=False];
node [shape = ellipse];
node [fontsize = 10];
// node [penwidth = 3];
edge [fontsize = 10];
// A [pos = "0,2"]
// B [pos = "-2,-2"]
// C [pos = "0,1"]
// D [pos = "2,-2"]
// E [pos = "0,-3"]
A
B
C
D
E;
node[shape = point];
x1[style = invis]
{rank=same; A,C}
{rank=same; B,E}
A -> C [label = "4|1.0\l"];
B -> B [label = "1|:0.979\l"];
C:nw -> C:ne [label = "3|0.167\l"];
C -> D [label = "5|0.115\l"];
D:nw -> C:sw [xlabel = "3|0.103\l4|0:0.315\l"];
D:se -> x1 [dir = none]
x1 -> D:sw [xlabel = "5|0.308\l6|0:0.253\l"];
E -> B [label = "4|0.5\l"];
E -> D [label = "6|0.5\l"];
}
Two ways to create your nodes, one fairly close (well to my eyes) and pretty easy to replicate. The other will allow you to recreate your example, but requires using two programs (dot and a program to create individual nodes in svg - like Inkscape)
digraph structs {
// if oblong is good enough, this works
node [shape=none]
try3 [label=<
<TABLE border="1" cellborder="0" cellspacing="0" cellpadding="0" style="rounded" >
<TR><TD width="40">A</TD><VR/><TD width="40">*111<BR/>*101<BR/>*011</TD></TR>
</TABLE>>];
// if you really want a circular node, perfectly split
// create the node images with another program (like Inkscape)
// and include as an image
try5 [image="/tmp/split1.svg" label=""]
}
producing:

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:

How to set bend direction for edges with splines="curved" in GraphViz? (using neato)

I am creating a graph with manually positioned nodes and use the splines="curved" type of edges between them.
digraph graphname {
splines="curved";
node[shape = box, margin="0.03,0.03", fontsize=11, height=0.1, width=0.1, fixedsize=false];
"LeftFoot\nRightHand" [pos="-150,-150!"];
"RightFoot\nRightHand" [pos="-90,-150!"];
"LeftFoot\nRightFoot" [pos="0,-150!"];
...
edge[style = solid,fontsize=11];
"LeftFoot\nRightFoot":n -> "RightFoot\nRightHand":n [label = "3", penwidth = 1, color = "red"];
"LeftFoot\nRightFoot":s -> "LeftFoot\nRightHand":s [label = "7", penwidth = 1, color = "red"];
...
}
The problem is that one of the edges is bent to the wrong side, so it passes through a node:
Is there an easy way to fix this, like e.g. "bend left" or "bend right" in TikZ?
I tried to use the pos attribute on the edge to set a spline control point to change the bend, however this does not appear to change the edge at all.
In Grapvhiz 2.38 this seems to be fixed. I've scaled the pos slightly but left the rest of the code alone:
Dot source:
digraph graphname {
splines="curved";
node[shape = box, margin="0.03,0.03", fontsize=11, height=0.1, width=0.1, fixedsize=false];
"LeftFoot\nRightHand" [pos="-2,-2!"];
"RightFoot\nRightHand" [pos="-1.2,-2!"];
"LeftFoot\nRightFoot" [pos="0,-2!"];
edge[style = solid,fontsize=11];
"LeftFoot\nRightFoot":n -> "RightFoot\nRightHand":n [label = "3", penwidth = 1, color = "red"];
"LeftFoot\nRightFoot":s -> "LeftFoot\nRightHand":s [label = "7", penwidth = 1, color = "red"];
}
Command:
dot -Kneato -Tpng input.gv > output.png
Output:

graphviz - how to create a 'roundtrip' flow

I'm trying to create a 'round trip' graph using the graphviz. Given the result below, my objective is to have the PINK squares between the NET and the COM (note from the picture below that they are pushed to the right after the NET).
the COM must be the first node on the LEFT.
the dot code:
digraph {
rankdir = LR;
graph [fontname = "helvetica" ];
node [fontname = "helvetica"];
edge [fontname = "helvetica"];
COM [shape = circle, fillcolor = yellow, style = filled];
NET [shape = circle, fillcolor = yellow, style = filled];
fn1 [shape = BOX, fillcolor = green, style = filled, label = "PORT006"];
clazz1 [shape = BOX, fillcolor = red, style = filled, label = "O"];
ddate1 [shape = BOX, fillcolor = red, style = filled, label = "21-Apr-13"];
status1 [shape = BOX, fillcolor = red, style = filled, label = "OJ3COM6M"];
clazz1exch [shape = BOX, fillcolor = green, style = filled, label = "G"];
ddate1exch [shape = BOX, fillcolor = green, style = filled, label = "13-May-13"];
status1exch [shape = BOX, fillcolor = green, style = filled, label = "GJ3COM6M"];
fn2 [shape = BOX, fillcolor = pink, style = filled, label = "PORT005"];
rbd2 [shape = BOX, fillcolor = pink, style = filled, label = "O"];
ddate2 [shape = BOX, fillcolor = pink, style = filled, label = "29-Apr-13"];
fare2 [shape = BOX, fillcolor = pink, style = filled, label = "OJ3COM6M"];
{ rank=same; clazz1 -> clazz1exch; }
{ rank= same; ddate1 -> ddate1exch; }
{ rank=same; status1 -> status1exch; }
COM -> fn1 -> clazz1exch -> ddate1exch -> status1exch -> NET;
NET -> fn2 -> rbd2 -> ddate2 -> fare2 -> COM;
}
If you simply reverse the direction of the edges going back (dir=back) by changing the line
NET -> fn2 -> rbd2 -> ddate2 -> fare2 -> COM;
into
edge[dir=back];
COM -> fare2 -> ddate2 -> rbd2 -> fn2 -> NET;
you should get:

Why does Graphviz/Dot act so weirdly to this particular code?

I am using GraphViz 2.28 (the current stable version) on Windows 7, and Graphviz/Dot crashes for the following code.
digraph G {
ranksep = 1.0; size = "10,10";
{
node [shape = plaintext, fontsize = 20];
GAWM1 -> GAWM2 -> 0;
}
node [shape = box];
{rank = same;0;wx1;wx2;rx1;}
wx1 -> wx2;
wx2 -> rx1;
wx1 -> rx1[color = blue];
subgraph struct
{
node [shape = record];
rx11 [shape = record, label = "rx1 | [x=[wx2]]"];
}
{rank = same; GAWM1; "rx11";}
// W'WR Order:
wx2 -> wx1[style = dashed, color = red, label = "1"]; }
Things become weird when I perform some experiments on this example:
It works well when only the last statement "wx2 -> wx1[style = dashed, color = red, label = "1"];" is removed;
It works well when only the eighth line "{rank = same;0;wx1;wx2;rx1;}" is removed;
It also works well when only the label (that is ", label = "1"") in the last statement is removed.
I have reported the problem to Graphviz Issue Tracker, without reply yet. Could you help to find out the reason?
Thank you.
The following variation of your script does not crash:
digraph G {
ranksep = 1.0; size = "10,10";
{
node [shape = plaintext, fontsize = 20];
GAWM1 -> GAWM2 -> 0;
}
node [shape = box];
{rank = same;0;wx1;wx2;rx1;}
wx1 -> wx2;
wx2 -> rx1;
wx1 -> rx1[color = blue];
subgraph struct
{
node [shape = record];
rx11 [shape = record, label = "rx1 | [x=[wx2]]"];
}
{rank = same; GAWM1; "rx11";}
// W'WR Order:
//wx2 -> wx1[style = dashed, color = red, label = "1"];
wx2 -> wx1 [style=dashed, color=red];
}
Looks like a bug with the label of the short edge between wx1 and wx2.

Resources