Graphviz compacting graph - graphviz

I'm generating a graph with graphviz and the circo tool it provides.
The graph generated is a nice shape, but the lengths of the edges between the nodes are a lot larger than they need to be, which makes the text of the nodes be small (relative to the output image) and so hard to read.
How can I make the node be bigger (relatively) in the output image, so that the text inside the nodes is easier to read,
Output image:
Source graph file:
digraph G {
FoundUrlToFollow [shape=box];
"Fetch the URL" [shape=circle];
FoundUrlToFollow -> "Fetch the URL";
ResponseReceived [shape=box];
"Fetch the URL" [shape=circle, label=<Fetch the URL>];
"Fetch the URL" -> ResponseReceived;
ResponseError [shape=box];
"Fetch the URL" [shape=circle, label=<Fetch the URL>];
"Fetch the URL" -> ResponseError;
ResponseReceived [shape=box];
"Log response" [shape=circle];
ResponseReceived -> "Log response";
ResponseReceived [shape=box];
"Is the response OK?" [shape=circle];
ResponseReceived -> "Is the response OK?";
ResponseOk [shape=box];
"Is the response OK?" [shape=circle, label=<Is the response<br/>OK?>];
"Is the response OK?" -> ResponseOk;
ResponseOk [shape=box];
"Is the response HTML?" [shape=circle];
ResponseOk -> "Is the response HTML?";
HtmlToParse [shape=box];
"Is the response HTML?" [shape=circle, label=<Is the response<br/>HTML?>];
"Is the response HTML?" -> HtmlToParse;
HtmlToParse [shape=box];
"Parse the HTML to find links" [shape=circle];
HtmlToParse -> "Parse the HTML to find links";
FoundUrl [shape=box];
"Parse the HTML to find links" [shape=circle, label=<Parse the HTML<br/>to find links>];
"Parse the HTML to find links" -> FoundUrl;
FoundUrl [shape=box];
"Should we follow this URL?" [shape=circle];
FoundUrl -> "Should we follow this URL?";
FoundUrlToSkip [shape=box];
"Should we follow this URL?" [shape=circle, label=<Should we<br/>follow this<br/>URL?>];
"Should we follow this URL?" -> FoundUrlToSkip;
FoundUrlToFollow [shape=box];
"Should we follow this URL?" [shape=circle, label=<Should we<br/>follow this<br/>URL?>];
"Should we follow this URL?" -> FoundUrlToFollow;
FoundUrlToSkip [shape=box];
"Log skipped links" [shape=circle];
FoundUrlToSkip -> "Log skipped links";
graph [label="Switches are circles. Events are boxes.", fontsize="12", overlap=scale];
edge [splines=curved];
}
Command:
circo -Tpng -ograph_so.png graph.dot

I would try to add mindist (less than 1) to graph:
graph [..., overlap=scale, mindist=.6];
[edit]
maybe the renderer version make a difference: here is the outcome on my machine

Try varying -Gsize (units of inches) and -Gdpi. You'll find that if you change them both together, you get different outputs with the same pixel size, but with different spacing between the nodes relative to the size of the nodes themselves. -Gnodesep and -Nfontsize might also be useful to tweak. You might also have better luck by rendering to EPS or PDF or SVG and then converting that to PNG, instead of using Graphviz's PNG renderer. Getting pleasing output from Graphviz is, in my experience, a very inexact science.

Related

How to change font size of a single record item in Graphviz

I'm trying to create a state chart from Graphviz of type record. Please check the reference here.
So here is the basic code:
digraph lamp {
node [shape=point,label=""]ENTRY
node [style=rounded shape=record ]
ON [label="{On| Some code here}"];
OFF [label="{Off| Some code here}"];
ENTRY -> ON[label="Initialization"]
ON -> OFF[label="|toggle|"]
OFF -> ON[label="|toggle|"]
}
In above code, I need to add some code below the state name like On and Off where I put the line Some code here. Since there will be a code and it can be any number of lines, I like to change the font size of this single record block where I will put the code (Not the state name record).
So in this line of code:
ON [label="{On| Some code here}"];
I like to change the font size of Some code here only not of On.
So, How can I get the control to independently change styling like font size or font name etc of the entered code here?
You can use html-like text, without building tables. (https://www.graphviz.org/doc/info/shapes.html#html). Like so:
digraph lamp {
node [shape=point,label=""]ENTRY
node [style=rounded shape=record ]
ON [label=<{<FONT COLOR="RED" POINT-SIZE="24.0">On</FONT>|<FONT COLOR="darkgreen" POINT-SIZE="10.0"> Some code here</FONT>}>];
OFF [label=<{<FONT COLOR="black" POINT-SIZE="24.0">Off</FONT>|<FONT COLOR="darkred" POINT-SIZE="10.0"> Some code here</FONT>}>];
ENTRY -> ON[label="Initialization"]
ON -> OFF[label=" |toggle| "]
OFF -> ON[label=" |toggle| "]
}
Giving:

Fine tuning edge and label placement in dot

I'm plotting a graph in dot. In order to make it legible I need to fine-tune the placement of the edge labels, as well as (if possible) making certain edges straight while others are curved. I would appreciate general advice on how to accomplish these things in dot, but for the sake of concreteness I include my specific problem below.
Here is the code, followed by what it currently looks like:
digraph myGraph {
rankdir=BT;
splines=line;
"AB.BC" -> "AB.AC.BC" [weight=4]
"AB.BC" -> "ABC" [color=red,style=dashed,label="I(A;C|B)"]
"A.B.C" -> "A.BC" [color=red, label="I(B;C)"]
"A.B.C" -> "AC.B" [color=red, label="I(A;C)"]
"A.B.C" -> "AB.C" [color=red, label="I(A;B)"]
"A.BC" -> "AB.BC" [color=red, label="I(A;B)"]
"A.BC" -> "AC.BC" [color=red, label="I(A;C)"]
"AB.AC.BC" -> "ABC" [weight=4]
"AC.B" -> "AC.BC" [color=red, label="I(B;C)"]
"AC.B" -> "AB.AC" [color=red, label="I(A;B)"]
"AC.BC" -> "AB.AC.BC" [weight=4]
"AC.BC" -> "ABC" [color=red,style=dashed, label="I(A;B|C)"]
"AB.AC" -> "AB.AC.BC" [weight=4]
"AB.AC" -> "ABC" [color=red,style=dashed, label="I(B;C|A)"]
"AB.C" -> "AB.BC" [color=red, label="I(A;B)"]
"AB.C" -> "AB.AC" [color=red, label="I(A;C)"]
}
This is close to what I want, but it has a few problems:
The labels are placed in such a way that you can't easily see which one is associated with which edge
For some reason, some of the edges have a bend in them at the label. (They came out as straight lines before I added the labels.)
I've tried playing with the rowsep and nodesep attributes but wasn't able to improve it. If I remove the splines=line line it becomes legible but isn't really what I want:
It's fine for the dotted edges to be curved -- it's actually good, because it will prevent them from overlapping the second node from the top -- but the solid ones really should be straight.
I'd like any advice on how to fine tune node, edge and label placement (as the documentation is really unhelpful and good examples are hard to find), but specifically, my questions are:
Can I tell dot to make specific edges curved while keeping others straight? (I know there is a splineType edge attribute, but the documentation doesn't give me a clue how to use it and I'm not even sure this is what it does.)
If the above is not possible, how can I tell dot to make the straight lines dead straight, rather than bending at the label?
For straight edges, how can I fine tune the placement of the labels? I don't mind doing it by hand, and there seem to be several edge attributes that should help me do that, but none of them seem to have any effect whatsoever, so I must be doing something wrong.
As a bonus question: is there a way that I can give the nodes a more grid-like layout, so that they're nicely vertically aligned?
Any answer is appreciated, but most especially helpful would be answers that explain how to handle these issues more generally, for the sake of future visitors, rather than just fixing my code.
If you use the neato layout engine, you can set the nodes explicit coordinates with attribute pos="x,y". In dot layout engine this is possible by using {rank=same; node1; node2; ...} for vertical alignment and group attribute (node1[group=g1]; node3[group=g1];) for horizontal alignment.
The position of the labels can be changed using the attributes headlabel and taillabel.
Image:
Script:
digraph myGraph {
layout=neato
splines=true
rankdir=BT
node [pin=true]
"A.B.C" [pos="0,0"]
"AC.B" [pos="0,2"]
"A.BC" [pos="-2,2"]
"AB.C" [pos="2,2"]
"AC.BC" [pos="-2,4"]
"AB.BC" [pos="0,4"]
"AB.AC" [pos="2,4"]
"AB.AC.BC" [pos="0,6"]
"ABC" [pos="0,8"]
"AB.BC" -> "AB.AC.BC"
"AB.BC" -> "ABC" [color=red,style=dashed,taillabel="I(A;C|B)"]
"A.B.C" -> "A.BC" [color=red, label="I(B;C)"]
"A.B.C" -> "AC.B" [color=red, label="I(A;C)"]
"A.B.C" -> "AB.C" [color=red, label="I(A;B)"]
"A.BC" -> "AB.BC" [color=red, taillabel="I(A;B)"]
"A.BC" -> "AC.BC" [color=red, taillabel="I(A;C)"]
"AB.AC.BC" -> "ABC"
"AC.B" -> "AC.BC" [color=red, taillabel="I(B;C)"]
"AC.B" -> "AB.AC" [color=red, taillabel="I(A;B)"]
"AC.BC" -> "AB.AC.BC"
"AC.BC" -> "ABC" [color=red,style=dashed, label="I(A;B|C)"]
"AB.AC" -> "AB.AC.BC"
"AB.AC" -> "ABC" [color=red,style=dashed, label="I(B;C|A)"]
"AB.C" -> "AB.BC" [color=red, taillabel="I(A;B)"]
"AB.C" -> "AB.AC" [color=red, taillabel="I(A;C)"]
}

Control Graphviz arrows direction

I'm tying to draw the IDEF0 diagram example using Graphviz
digraph UDEF0 {
"Plan New Information Program" [shape=box]
"Issues" [shape=none]
"Operation Data" [shape=none]
"Program Charter" [shape=none]
"Program Team" [shape=none]
"Program Plan" [shape=none]
"Issues" -> "Plan New Information Program"
"Operation Data" -> "Plan New Information Program"
"Program Charter" -> "Plan New Information Program"
"Program Team" -> "Plan New Information Program"
"Plan New Information Program" -> "Program Plan"
}
The problem is that I can't find the way to control direction of arrows around the central box.
I've tried to use hidden "frame" made of invisible South, North, East and West nodes to connect arrows to them. Unfortunately the "frame" works well only if it is empty, and when I connect my "payload" nodes to it, the structure breaks:
digraph UDEF0 {
rankdir=LR
"Plan New Information Program" [shape=box]
"Issues" [shape=none]
"Operation Data" [shape=none]
"Program Charter" [shape=none]
"Program Team" [shape=none]
"Program Plan" [shape=none]
"Program Plan" [shape=none]
"West" [shape=none]
"North" [shape=none]
"South" [shape=none]
"East" [shape=none]
"West" -> "North" -> "East"
"West" -> "South" -> "East"
"West" -> "Issues" -> "Plan New Information Program"
"West" -> "Operation Data" -> "Plan New Information Program"
"North" -> "Program Charter" -> "Plan New Information Program"
"South" -> "Program Team" -> "Plan New Information Program"
"East" -> "Plan New Information Program" -> "Program Plan"
}
Is the any correct way to implement this diagram style?
Using shape = record brings you close to what you want - here my re-written attempt:
digraph UDEF0
{
A[ label = "Plan New\nInformation\nProgram", shape=box, style = filled, fillcolor = grey ]
B[ shape = record, color = white, label = "{ Operation Data | Issues }" ]
node[ shape = none ]
c[ label = "Program Charter" ]
d[ label = "Program Team" ]
e[ label = "Program Plan" ]
{ rank = same; A B e }
c -> A;
A -> d[ dir = back ];
edge[ minlen = 3]
B -> A;
B -> A;
A -> e;
}
yields
E D I T 2018-11-29
In order to avoid the issues that #McKay has shown in his comment, I have re-coded the sample using a HTML like label:
digraph UDEF0
{
A[ label = "Plan New\nInformation\nProgram", shape=box, style = filled, fillcolor = grey ]
B[ shape = plaintext, label =<
<TABLE BORDER="0" CELLBORDER="0" CELLSPACING="15">
<TR>
<TD PORT = "p1">Issues</TD>
</TR>
<TR>
<TD PORT = "p2">Operation Data</TD>
</TR>
</TABLE>>];
node[ shape = none ]
c[ label = "Program Charter" ]
d[ label = "Program Team" ]
e[ label = "Program Plan" ]
{ rank = same; A B e }
c -> A;
A -> d[ dir = back ];
edge[ minlen = 3]
B:p1 -> A;
B:p2 -> A;
A -> e;
}
Which gives us
without warning or error message on my Linux box with graphviz version 2.38.0 (20140413.2041).

Use of \tikzexternalize

I want to improve compiling speed of my latex thesis. I have read that using \tikzexternalize, only when there is a change in the tikz codes they are compiled.
The problem is that I can no use \tikzexternalize properly. This is my preamble:
\usepackage{circuitikz}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric, arrows, shadows, calc,positioning}
\tikzexternalize
And this is not working at all. I received next error:
Undefined control sequence. \tikzexternalize
If it is useful, I am using MikTex with TextStudio and TextLive with Textstudio also under Ubuntu. It doesn't work in any of these system.
Hope you can help me.
Didn't you forget to add
\usetikzlibrary{external}
? I just found it here : tex.stackexchange
I have done it.
Now I don't have any error messages, but no figures are saved into TikzFigures folder. This is my preamble:
\usepackage{circuitikz}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric, arrows, shadows, calc,positioning,external}
\tikzexternalize[mode=graphics if exists,
figure list=true,
prefix=TikzFigures/]
This is how I add my tikz figures. First example is by using circuitikz.
\begin{figure}[h]
\centering
\tikzsetnextfilename{nonInverter}
\begin{circuitikz}[scale=1]\draw
(4,.5) node [op amp](opamp) {} % Amplificador Operacional
(0,0) node [ ground]{} to (0,1)
to [R=$Sensor A201$,-*] (opamp.-)
(opamp.out)|- (5,2.5) to [R=$R_{F}$](2.8,2.5) to (opamp.-)
(opamp.+) to [short,-o] (2.8,-1) node [right] {$V_{+}$}
(opamp.out) to [short, *-o] (6,.5) node[right] {$V_{ADC}$}
;\end{circuitikz}
\end{figure}
Next one, is by using the common tikz package:
\begin{figure}[h]
\begin{center}
\tikzsetnextfilename{masterFlowChart}
\begin{tikzpicture}[node distance = 2cm, auto]
% Colocamos los nodos
\node [cloud] (init) {Initialize System};
\node [block, below of=init] (connection) {Connection to the master};
\node [block, below of=connection] (wait) {Wait for master events};
\node [block, below of=wait] (measure) {Measure and send to master};
% invisible node helpful later
\node[right of=wait,scale=0.05](inv){};
% Colocamos las relaciones entre nodos
\path [line] (init) -- (connection);
\path [line] (connection) edge[loop left] node {No Network}();
\path [line] (connection) -- (wait);
\path[-,draw] (wait) -| node{} (inv.north);
\path[line]{} (inv.north) |- node[above]{Reconnect} (connection);
\path [line] (wait) edge[loop left] node {Sleep}();
\path [line] (wait) -- (measure);
\path [line] (measure) -- (wait);
\end{tikzpicture}
\end{center}
\label{fig:slave_flowchart}
\end{figure}
And last one is by using sequencediagram package, that if I am not wrong is also based on tikz.
\begin{figure}[h]
\begin{center}
\tikzsetnextfilename{sequenceDiagramaECnsole10}
\begin{sequencediagram}
\newthread{pc}{PC}
\newinst[2]{master}{Master}
\newinst[2]{slave}{Slave}{}
\node[below right of=master,font=\scriptsize](master_state){Idle};
\node[below right of=slave,font=\scriptsize](slave_state){Sleep};
\begin{sdblock}{Run Loop}{}
\begin{call}{pc}{Start Measurement}{master}{Master Data}
\begin{call}{master}{Data Request}{slave}{Slave Data}
\end{call}
\end{call}
\end{sdblock}
\node[below of=master_state,font=\scriptsize, node distance= 4cm]{Idle};
\node[below of=slave_state,font=\scriptsize, node distance= 4cm]{Sleep};
\end{sequencediagram}
\end{center}
\label{fig:ecnsole_sequence_diagram}
\end{figure}

Better layout of nodes for block diagrams in dot

After a previous question (Block diagram layout with dot/Graphviz) I have further questions. The following is compiled like so:
dot -Gsplines=none test.gv | neato -n -Gsplines=ortho -Tpng -otest.png
digraph G {
graph [rankdir = LR];
node[shape=record, style=filled];
bar[label="Bar", height=1.3636363636363635];
tea[label="Tea", height=1.3636363636363635];
brew[label="Brew", height=3.6363636363636362];
bar1[label="Bar1", height=2.2727272727272725];
baz[label="Baz", height=1];
foo[label="Foo", height=5.0];
darjeeling[label="Darjeeling", height=3.1818181818181817];
example[label="Example", height=17.727272727272727];
bar -> example [label="bar_clk"];
bar -> example [label="bar_bar"];
example -> tea [label="bli1"];
example -> tea [label="blo2"];
example -> tea [label="blo3"];
example -> brew [label="bli"];
example -> brew [label="blo"];
example -> brew [label="blo"];
example -> brew [label="blo"];
example -> brew [label="blo"];
example -> brew [label="blo"];
example -> brew [label="blo"];
example -> brew [label="blo"];
bar1 -> example [label="bar1_foo"];
bar1 -> example [label="bar1_bar"];
bar1 -> example [label="bar1_baz"];
bar1 -> example [label="bar1_baz1"];
bar1 -> example [label="bar1_bar2"];
baz -> example [label="baz_foo"];
example -> foo [label="bla"];
example -> foo [label="bla"];
example -> foo [label="bla"];
example -> foo [label="bla"];
example -> foo [label="bla"];
example -> foo [label="bla"];
example -> foo [label="bla"];
example -> foo [label="bla"];
example -> foo [label="bla"];
example -> foo [label="bla"];
example -> foo [label="bla"];
example -> bar [label="blu"];
example -> baz [label="ble"];
darjeeling -> example [label="darjeeling_bli1"];
darjeeling -> example [label="darjeeling_blo2"];
darjeeling -> example [label="darjeeling_blo3"];
darjeeling -> example [label="darjeeling_bli1"];
darjeeling -> example [label="darjeeling_blo2"];
example -> darjeeling [label="bla"];
darjeeling -> example [label="darjeeling_blo3"];
}
My question is how I could take the, say, Baz and Darjeeling nodes and move them to the left side to decrease the height of the middle node. I don't know what determines this. I understand this is a directional graph, so the general "flow" of the diagram is left to right, I'd just like more control.
These diagrams will be generated automatically, so an explanation on how to lay it out as I wish and why, as opposed to a code snippet that makes it work for this particular example, is preferred.
A couple of points:
how I could take the, say, Baz and Darjeeling nodes and move them to the left side
By setting constraint=false for the edges going from Example to Baz and Darjeeling, or by grouping all the nodes to appear left of Example in a subgraph with rank=min.
You may say that this is not a suitable solution (at least not the one with constraint=false) because
These diagrams will be generated automatically
and I completely understand (been there many times) - but at the same time, you wish
to decrease the height of the middle node
which is set manually, so the graph still is not fully auto-generated (how do you calculate the height needed for Example?).
I don't know what determines this
I'm not completely sure neither - Baz could might as well be on the left.
Surprisingly, the order of appearance of the nodes changes the layout in some cases. For example, if you move up the definition of the Darjeeling node, it will appear on the left side (and Bar gets to be at the right side).
Edit: Here comes the code snippet...
A third possibility is to define all edges in the right order (top-down/left-right) and decorate the edges going back with dir=back.
If you change these 3 lines
example -> bar [label="blu"];
example -> baz [label="ble"];
example -> darjeeling [label="bla"];
into
bar -> example [label="blu", dir=back];
baz -> example [label="ble", dir=back];
darjeeling -> example [label="bla", dir=back];
or into
example -> bar [label="blu", constraint=false];
example -> baz [label="ble", constraint=false];
example -> darjeeling [label="bla", constraint=false];
(and change the height of example)
You'll get

Resources