graphviz multiples edges on the same node - graphviz

I'm new on graphviz and need to create a graph for a netstat output like this image
but I can't add more than one connection to the same node, the grapviz overwrite and display only the last connection.

You will have a good start with the following (I didn't want to type all the numbers):
digraph g {
rankdir=LR
node [shape=box ]
x1[label="10.112.11.115"]
x1 -> x2[label="64939:0"]
x1 -> x2[label=1]
x1 -> x3[label=0]
x1 -> x4[label=1]
x1 -> x5[label=0]
x1 -> x5[label=1]
}

Related

Make a Graphviz plot more square

I am trying to make plot of several disconnected graphs.
digraph {
// rankdir=RL
subgraph template {
node [shape=square]
edge [color=black]
subgraph top {
node [group=1]
A
B
C
D
E
}
subgraph bottom {
node [group=2]
F
G
H
}
}
C -> c
F -> f
subgraph s1 {
edge [color=red]
A -> a
B -> b1
D -> d1
E -> e1
G -> g1
H -> h1
}
subgraph s2 {
edge [color=blue]
A -> b1
B -> a
D -> d2
E -> e2
G -> g2
H -> h2
}
subgraph s3 {
edge [color=green]
A -> a
B -> b1
D -> d2
E -> e3
G -> g3
H -> h1
}
subgraph s4 {
edge [color=purple]
A -> b1
B -> a
D -> e1
E -> e2
G -> g4
H -> h1
}
subgraph s5 {
edge [ color=orange]
A -> b1
B -> a
D -> d5
E -> e1
G -> g5
H -> h1
}
subgraph s6 {
edge [ color=brown]
A -> a
B -> b1
D -> d1
E -> e6
G -> g6
H -> h1
}
subgraph s6 {
edge [ color=tan]
A -> a
B -> b2
D -> d2
E -> e6
G -> g6
H -> h1
}
}
This creates a short, wide graph.
I would like to have a taller, narrower graph. For example, moving the F, G and H trees under the A-E nodes would be good.
I tried size, which just made the nodes bigger or smaller.
I tried ratio, which stretched the graph but did not move nodes around.
I tried using group and/or rankdir, but neither did what I wanted.
I have mostly tried using fdp, but also tried dot.
I am happy with a solution that either automatically moves the nodes around or requires me to manually move them.
Any suggestions on how to achieve this?
Here are two ways:
(easiest)
make each top-level cluster a stand-alone graph.
run each graph through dot -Tdot myfileX.gv >myfileX.dot
use gvpack (https://graphviz.org/pdf/gvpack.1.pdf) to combine the individual files into one combo graph
run the combo graph through neato -n2 -Tpng >mycombo.png (see https://www.graphviz.org/faq/#FaqDotWithCoords)
gvpack -array_ib1 myfiles*.dot |neato -Tpng -n2 >oooo.png
OR
use invisible edges to connect the nodes from one cluster to another a->C. Unfortunately, this quickly becomes tedious, trying to get all the nodes to line up as you want.

How can I cross out a node in Graphviz?

I would like to indicate that a node should be there, but is currently lacking in the process.
Intuitively I would like to cross it out as shown in below image (now done manually in Paint):
Is there a node attribute in Graphviz that I can use for this?
I can't find an attribute or node shape to do what you want, but here are two ways to do it:
build an image outside of Graphviz (with the text and the X) and use the image attribute to use the image as the node (yes, a pain if you want to do this frequently):
b [image="myB.png"]
For every X'd out node, add 2 new edges from .ne to .sw and .nw to .se (see below) Each with this (new) attribute: straightline=1. Then run this command:
dot -Tdot Xout2.gv |gvpr -f straightline.gvpr -c | neato -n2 -Tpng >out.png
Where this is straightline.gvpr:
E[straightline==1]{
int i, n;
string pt[int];
double x1, y1, x2, y2, xI1, yI1, xI2, yI2;
n=split($.pos, pt, " ");
for (i=0;i<=1;i++){
if (match(pt[i],"e,")>=0){
print ("// BEFORE: ", pt[i]);
pt[n-1]=substr(pt[i],2);
print ("// AFTER: ", pt[i]);
pt[i]=pt[i+1];
}
}
for (i=0;i<=1;i++){
if (match(pt[i],"s,")>=0){
pt[0]=substr(pt[i],2);
}
}
sscanf (pt[0], "%f,%f", &x1, &y1);
sscanf (pt[n-1], "%f,%f", &x2, &y2);
xI1=x1+(x2-x1)*.3;
yI1=y1+(y2-y1)*.3;
xI2=x1+(x2-x1)*.7;
yI2=y1+(y2-y1)*.7;
$.pos=sprintf("%s %.3f,%.3f %.3f,%.3f %s", pt[0], xI1, yI1, xI2, yI2, pt[n-1]);
}
From this input:
digraph X{
graph [outputorder=edgefirst]
b [ label="X me"]
a -> b -> c
a -> d
d -> c
e -> f
g -> i -> k
edge [color="#ff000080" penwidth=2] // note translucent color
b:ne -> b:sw [straightline=1]
b:se -> b:nw [straightline=1]
edge [color="green" penwidth=2]
e:n -> e:s [straightline=1]
f:w -> f:se [straightline=1]
edge [color="orange" penwidth=2]
g:n -> g:se [dir=back straightline=1]
edge [color="blue" penwidth=2]
g:n -> g:sw [dir=back straightline=1]
i:e -> i:w [dir=none straightline=1]
k -> k:s [dir=both straightline=1]
}
Sorry, convoluted, but it works.
While the answer of sroush gives me the exact output I need, it requires that I understand how to introduce gvpr in my workflow which will take a bit of time.
In the meantime I came up with a dot only approach, which approximates crossing out a node sufficiently for my purpose.
In below graph I would like to cross out the node Some process:
digraph graphname {
rankdir=LR
node [fillcolor="lightblue3", style="filled"]
a
c
d
b [label="Some\nprocess"]
a -> b -> c
a -> d -> c
{rank=same a;d}
}
To do so I change:
the nodestyle of the Some process node to have a diagonal hard gradient
use a HTML-like label to strikethrough the text
Make the fontcolor and node outline a shade of gray
digraph graphname {
rankdir=LR
node [fillcolor="lightblue3", style="filled"]
a
c
d
node [fillcolor="lightblue3;0.5:white", style="filled", fontcolor="gray50", color="gray50", gradientangle=100]
b [label=<<s>Some<br/>process</s>>]
a -> b -> c
a -> d -> c
{rank=same a;d}
}

GraphViz: how to connect a node to the containing subgraph

I just learned how to connect nodes and subgraphs here on Stackoverflow. However, I want to connect a node to the containing subgraph:
digraph G {
compound=true;
subgraph cluster0 {
a -> b;
a -> c;
c -> {a b c} [lhead=cluster0];
}
c -> d;
d -> {a b c} [lhead=cluster0];
}
A quick sketch what I mean:
I want to connect d -> {a b c}, but for clarity reasons, I don't want to draw three different arrows, but just one arrow to the grouping of nodes. One way to do that is only list one arrow, like d -> a. That works, but is there a way to "collapse" three arrows into one when the head points to a cluster?
However, c -> {a b c} is not possible to point to a cluster, because c is part of that cluster. Is there a way to go around this?
you will need some scaffolding i.e. invisible node (and maybe edges) e.g.:
digraph top {
compound=true
node[shape=rectangle]
subgraph cluster1 {
a->{b c}
}
c->d
d->b[lhead=cluster1]
ca[shape=point height=0] // make ca invisible
a->ca:n[dir=back ltail=cluster1] // by drawing the arrow backward we get more control of the layout, n and s compass make the edge go smooth when enter and exiting ca
ca:s->c[dir=none] // no arrow on the tail part
}
rendered on viz-js.com:

Graphviz: How to add label to arrows if nodes already have a label

I am making a graph using graphviz dot.
like this
digraph protocol {
label="Protocol workflow";
node[shape=box, style=rounded];
a[label="Byte received"];
b[label="Is start delimiter?", shape=diamond];
c[label="Recv length [n, 1B]"]; c1[label="Set count=n"];
d[label="Recv 1 payload byte and decrement count"];
e[label="count > 0", shape=diamond];
f[label="Recv CRC [2B]"];
g[label="Is CRC valid?", shape=diamond];
a -> b -> c -> c1 -> d -> e -> f -> g;
e -> d;
}
Problem is that to some arrows I need to add yes no labels but I don't know how I could do that.
You may add labels to edges like this:
e -> f [label="Yes"];

simple "T shaped" graph in graphviz

Need draw a graph with dot/graphviz like this image:
The texts can be above arrows, like graphviz does it. But how to achieve the T-layout? Need make a cluster for the top row?
This is one possibility using rank=same for a subgraph:
digraph g {
node[shape=point, width=0.2];
{
rank=same;
p1 -> n [label="text1"];
n -> p2 [label="text2"];
}
n -> p3 [label="text3", dir=back];
n[label="node", shape=rect, style=rounded];
}
You could also use a left-right layout instead of top-down.
An other possibility is to disable the effect of some edges using constraint=false:
digraph g {
node[shape=point, width=0.2];
p1 -> n [label="text1", constraint=false];
n -> p2 [label="text2", constraint=false];
n -> p3 [label="text3", dir=back];
n[label="node", shape=rect, style=rounded];
}
The result is the same.
dot usually layouts trees in layers. To force an edge to not be a layer separation you can add the constraint=false option. So something like:
digraph {
A [shape=point]
B [shape=point]
C [shape=point]
N [label="node"]
A -> N [label="text1", constraint=false]
N -> B [label="text2", constraint=false]
N -> C [label="text3", dir=back]
}
should work.
Note that the edge from the lower node to "node" has to be backwards, since dot layouts trees from top to bottom. Therefore the logical edge direction has to be from top to bottom, even though the display direction might be the other way round (which is the case here).

Resources