Graphviz with HTML-like nodes, trying to control arrow shape - graphviz

I'm trying to create a representation of haproxy redirects and also linking to services behind the haproxy.
I've got the following dot code:
digraph structs {
node [shape=plaintext]
subgraph cluster_haproxy {
label = "haproxy";
haproxy [label=<
<TABLE BORDER="3" CELLBORDER="1" CELLSPACING="50">
<TR>
<TD PORT="80">80</TD>
<TD PORT="443">443</TD>
</TR>
</TABLE>
>];
}
subgraph cluster_service001 {
label = "service001";
service001 [label=<
<TABLE BORDER="3" CELLBORDER="1" CELLSPACING="4">
<TR>
<TD PORT="123456789">123456789</TD>
</TR>
</TABLE>
>];
}
haproxy:80:e -> haproxy:443:w;
haproxy:443 -> service001:123456789;
}
Which results in this image, showing that port 80 gets redirected to port 443:
What I'm looking to achieve is just a straight arrow from 80 to 443, without any curve.
Do note that there may well be more ports on that same line.
I tried adding splines=line
I tried it with record-based nodes, giving them a rank=same to keep them next to each other, but that gives me this error message:
Warning: flat edge between adjacent nodes one of which has a record
shape - replace records with HTML-like labels
I tried it with box shape, but that put the items in the wrong order left to right.
Running out of ideas here. Any suggestions for how to properly do something like this would very much be appreciated.

GraphViz do not handle internal edges in nodes vell
I suggest you switch to 2 levels of clusters instead like here:
digraph structs {
node [shape=plaintext]
subgraph cluster_haproxy {
label = "haproxy";
subgraph cluster_haproxy2 {
penwidth=3
label=""
node[shape=rect]
{rank=same
80
443}
}
}
subgraph cluster_service001 {
label = "service001";
subgraph cluster_service001 {
penwidth=3
label=""
123456789[shape=rect]
}
}
80 -> 443
443 -> 123456789
}

Related

Is there a way to add arrow from a token/word to another in graphviz?

I'm wondering if it's possible to create something like this usint graphviz, where an arrow points from a token/word to the other, instead of a node.
It is possible to simulate (a lot of things) with tables, though it's usually very ugly in source code:
digraph {
node [shape=plain]
node1 [
label=<
<table cellspacing="0" bgcolor="#d0e2f2" cellborder="0">
<tr><td></td></tr>
<tr><td port="label">foo bar</td></tr>
<tr><td></td></tr>
</table>>
]
node2 [
label=<
<table cellspacing="0" bgcolor="#d0e2f2" cellborder="0">
<tr><td></td></tr>
<tr><td port="label">baz qux</td></tr>
<tr><td></td></tr>
</table>>
]
node1:label:n -> node2:label:n [constraint=false]
}
Result:
What I did here:
I used a plain node shape and HTML-like label syntax to create a table:
node [shape=plain]
node1 [
label=<>
]
I added 3 rows for my table, first and last one being empty:
<tr><td></td></tr>
<tr><td port="label">foo bar</td></tr>
<tr><td></td></tr>
The middle row contains the actual label. Also, to be able to point an edge to specific cell I've added a port to it: <td port="label">foo bar</td>.
Finally when defining an edge I've specified the ports to be connected (documentation on ports):
node1:label:n -> node2:label:n

give each wedge a different label in style=wedged in DOT graphviz

I could not figure out looking at the Graphviz docs if there is a way to specify different labels for each wedge in a circle with style=wedged. e.g. below node draws a circle divided into 3 wedges with three colors.
nodepie [shape = "circle" style = "wedged" fillcolor = "green:red:yellow"];
I want to put different numbers on each wedge.
Could anybody help?
Thanks for your help.
Sorry, but I don't think this is possible; I've tried before. Even using weird combinations of html labels I wasn't able to get a satisfactory result. There's nothing in the label documentation that even hints at a method for achieving this.
Sorry I don't have a more positive answer for you, but in the case I think it's "no." As you can see, alignment is a mess; it might be feasible if the pie had four wedges and the html label could be superimposed on top, two rows and two columns. But with three it's hard to imagine a layout that would delight:
digraph x{
nodepie [shape = "circle" style = "wedged" fillcolor = "green:red:yellow"
label=< <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0"> <TR><TD PORT="f0">one</TD><TD>two</TD></TR> </TABLE>>];
}
Workaround for three wedgets (of approximately same size);
digraph x{
nodepie [shape = "circle" style = "wedged" fillcolor = "green:red:yellow"
label=<
<TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0">
<TR>
<TD PORT="f0" ROWSPAN="2">one</TD>
<TD ROWSPAN="2"> </TD>
<TD>two</TD>
</TR>
<TR>
<TD PORT="f0">tree</TD>
</TR>
</TABLE>
>];
}
If you create a html-table with elements using the same colors as the WEDGE, you can have your labels next to the pie.
digraph structs {
p01 [shape = none
label = <<table border="0" cellspacing="0">
<tr><td bgcolor="blue">P01</td></tr>
<tr><td bgcolor="red">P02</td></tr>
<tr><td bgcolor="yellow">P03</td></tr>
<tr><td bgcolor="green">P04</td></tr>
</table>>]
node [shape=circle]
pie [label="wedged"
style=wedged
color=none
fillcolor="blue;0.4:red;0.1:yellow;0.2:green"
fontcolor=pink]
}
Result:

Graphviz dot: How to change the colour of one record in multi-record shape

I have the following dot sample. I would like to give the first section in each record (the table name) a different background and foreground colour. I can't find any examples of how to do this for a record. Basically I want the table name in the sql query schema diagram to stand out. Can anyone help?
digraph G {
rankdir=LR;
node [shape=record];
corpus_language [label="corpus_language|<id> id\len\l|<name> name\lEnglist\l|<sentence_count> sentence_count\l1027686\l"];
corpus_sentence [label="corpus_sentence|<id> id\l1241798\l|<text> text\lBaseball is a sport\l|<creator_id> creator_id\l10859\l|<created_on> created_on\l2006-11-14 17:58:09.303128\l|<language_id> language_id\len\l|<activity_id> activity_id\l11\l|<score> score\l124\l"];
corpus_language:id -> corpus_sentence:language_id [arrowhead=normal label=language_id];
}
I'm pretty sure that it's not possible. Instead you should use HTML-style labels, that are a more developped form of record nodes. You can define your node using the <table> tag, and set the color using bgcolor="your_color". A list of available colors is available here: http://www.graphviz.org/doc/info/colors.html (you also have a RGBA way of doing it, as described here: http://www.graphviz.org/doc/info/attrs.html#k:color)
With HTML labels, your example becomes as follows:
digraph G
{
rankdir = LR;
node1
[
shape = none
label = <<table border="0" cellspacing="0">
<tr><td port="port1" border="1" bgcolor="red">corpus_language</td></tr>
<tr><td port="port2" border="1">id: en</td></tr>
<tr><td port="port3" border="1">name: Englist</td></tr>
<tr><td port="port4" border="1">sentence_count: 1027686</td></tr>
</table>>
]
node2
[
shape = none
label = <<table border="0" cellspacing="0">
<tr><td port="port1" border="1" bgcolor="blue">corpus_sentence</td></tr>
<tr><td port="port2" border="1">id: 1241798</td></tr>
<tr><td port="port3" border="1">text: Baseball is a sport</td></tr>
<tr><td port="port4" border="1">creator_id: 10859</td></tr>
<tr><td port="port5" border="1">created_on: 2006-11-14 17:58:09.303128</td></tr>
<tr><td port="port6" border="1">language_id: en</td></tr>
<tr><td port="port7" border="1">activity_id: 11</td></tr>
<tr><td port="port8" border="1">score: 124</td></tr>
</table>>
]
node1:port2 -> node2:port6 [label="language_id"]
}
Here is the result:

Graphviz: How can I make the style of an HTML table cell bold?

I'd expect the following dot code to make the title bold but the <b> tag doesn't seem to be working in this context for some reason.
digraph G {
node [shape=plaintext]
a [label=<<table border="0" cellborder="1" cellspacing="0">
<tr><td><b>title</b></td></tr>
<tr><td>row 1</td></tr>
<tr><td>row 2</td></tr>
</table>>];
}
Any working alternatives?
This exact graph actually does work. You'll most certainly need to update graphviz.
Here's the output with 2.28:

Making a Legend/Key in GraphViz

I’d like to include a legend or key in my GraphViz diagram. I’m having trouble figuring out what code to use, though. I also want to put it in a corner, but the only coord I know for sure is the bottom-left: pos="10,10!".
Does anyone know how I can get this to work?
digraph {
rankdir=LR
node [shape=plaintext]
subgraph cluster_01 {
label = "Legend";
key [label=<<table border="0" cellpadding="2" cellspacing="0" cellborder="0">
<tr><td align="right" port="i1">item 1</td></tr>
<tr><td align="right" port="i2">item 2</td></tr>
<tr><td align="right" port="i3">item 3</td></tr>
<tr><td align="right" port="i4">item 4</td></tr>
</table>>]
key2 [label=<<table border="0" cellpadding="2" cellspacing="0" cellborder="0">
<tr><td port="i1"> </td></tr>
<tr><td port="i2"> </td></tr>
<tr><td port="i3"> </td></tr>
<tr><td port="i4"> </td></tr>
</table>>]
key:i1:e -> key2:i1:w [style=dashed]
key:i2:e -> key2:i2:w [color=gray]
key:i3:e -> key2:i3:w [color=peachpuff3]
key:i4:e -> key2:i4:w [color=turquoise4, style=dotted]
}
...
I used dot.
I'm deeply convinced that graphviz should not be used this way, but you may use HTML labels to achieve what you want:
digraph {
Foo -> Bar -> Test;
Foo -> Baz -> Test;
{ rank = sink;
Legend [shape=none, margin=0, label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR>
<TD COLSPAN="2"><B>Legend</B></TD>
</TR>
<TR>
<TD>Foo</TD>
<TD><FONT COLOR="red">Foo</FONT></TD>
</TR>
<TR>
<TD>Bar</TD>
<TD BGCOLOR="RED"></TD>
</TR>
<TR>
<TD>Baz</TD>
<TD BGCOLOR="BLUE"></TD>
</TR>
<TR>
<TD>Test</TD>
<TD><IMG src="so.png" SCALE="False" /></TD>
</TR>
<TR>
<TD>Test</TD>
<TD CELLPADDING="4">
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="0">
<TR>
<TD BGCOLOR="Yellow"></TD>
</TR>
</TABLE>
</TD>
</TR>
</TABLE>
>];
}
}
That's what this looks like:
The positioning of the Legend has to be done like any other node (I used rank=sink to get it to the bottom) - you may play with its margin attribute for fine-tuning the position.
Edit:
Without using labels, that may be the direction to go for - I'm not sure whether it is to completely eliminate ranksep.
digraph {
mindist=0;
ranksep=0;
nodesep=0;
node[shape=box,margin="0,0",width=1, height=0.5];
edge [style=invis];
Legend[width=2];
Legend -> Foo;
Legend -> FooValue;
Foo -> Bar;
FooValue -> BarValue
Bar -> Baz;
BarValue -> BazValue;
edge [constraint=false];
Foo -> FooValue;
Bar -> BarValue
Baz -> BazValue;
}
Resulting in:
Lots of these anwers show nice ways to render a legend, and that's useful, but a major unaddressed problem is integration of that legend in the same output as the main graph. This causes all sorts of problems because things like rankdir and rank positions "leak" between the main diagram and the legend, making it hard to improve one without breaking the other.
After trying several ways of embedding a key within the main GraphViz image, I've decided that for me, it makes more sense to simply put the legend into its own, separate dot file, render it as it's own, separate, image, and then display the images side-by-side in my documents/pages.
This has a few advantages:
The .dot source code is substantially simpler.
It's very easy to change the rankdir of the legend graph to display the nodes above one another, or side-by-side, to produce a key that either sits to the right of the main image, or below it.
No leaking of things like rank positions from the main graph into the legend.
For example:
I had some luck with the following. I didn't like how wide it was, but otherwise it worked.
subgraph cluster1 {
label = "Legend" ;
shape = rectangle ;
color = black ;
a [style=invis] ;
b [style=invis] ;
c [style=invis] ;
d [style=invis] ;
c -> d [label="only ts", style=dashed, fontsize=20] ;
a -> b [label="ts and js", fontsize=20] ;
gui -> controller [style=invis] ;
view -> model [style=invis] ;
builtins -> utilities [style=invis] ;
gui [style=filled, fillcolor="#ffcccc"] ;
controller [style=filled, fillcolor="#ccccff"] ;
view [style=filled, fillcolor="#ccffcc"] ;
model [style=filled, fillcolor="#ffccff"] ;
builtins [style=filled, fillcolor="#ffffcc"] ;
utilities ;
"external libraries" [shape=rectangle] ;
}
The result was
subgraph cluster_01 {
label = "Legend";
node [shape=point]
{
rank=same
d0 [style = invis];
d1 [style = invis];
p0 [style = invis];
p1 [style = invis];
s0 [style = invis];
s1 [style = invis];
}
d0 -> d1 [label=deprecated style=dashed]
p0 -> p1 [label=proposed style=dotted]
s0 -> s1 [label=stable]
}
There are some problems if you use graph [splines=ortho] : the lines are in inverse order.
Dot source:
digraph {
rankdir=LR
node [shape=plaintext]
graph [splines=ortho]
subgraph cluster_01 {
label = "Legend";
key [label=<<table border="0" cellpadding="2" cellspacing="0" cellborder="0">
<tr><td align="right" port="i1">item 1</td></tr>
<tr><td align="right" port="i2">item 2</td></tr>
<tr><td align="right" port="i3">item 3</td></tr>
<tr><td align="right" port="i4">item 4</td></tr>
<tr><td align="right" port="i5">item 5</td></tr>
</table>>]
key2 [label=<<table border="0" cellpadding="2" cellspacing="0" cellborder="0">
<tr><td port="i1" bgcolor='greenyellow'> </td></tr>
<tr><td port="i2"> </td></tr>
<tr><td port="i3"> </td></tr>
<tr><td port="i4"> </td></tr>
<tr><td port="i5"> </td></tr>
</table>>]
key:i1:e -> key2:i1:w [color=red]
key:i2:e -> key2:i2:w [color=gray]
key:i3:e -> key2:i3:w [color=peachpuff3]
key:i4:e -> key2:i4:w [color=turquoise4, style=dotted]
key:i5:e -> key2:i5:w [color=red, style=dotted]
}
}
I'm trying to do the same. I have been using a subgraph to make a key of node types:
digraph G {
rankdir=RL;
graph [fontsize=10 fontname="Verdana"];
node [style=filled height=0.55 fontname="Verdana" fontsize=10];
subgraph cluster_key {
label="Key";
progress [fillcolor="wheat" label="In progress"];
todo [label="To do"];
done [fillcolor=palegreen3 label="Done"];
not_our [fillcolor=none label="Not our\nteam"];
numbers [color=none label="Numbers\nrepresent\nperson\ndays"];
progress -> done [style=invis];
todo -> progress [style=invis];
not_our -> todo [style=invis];
numbers -> not_our [style=invis];
}
mappings [fillcolor=palegreen3];
identifiers [fillcolor=palegreen3];
hyperwarp [fillcolor=wheat];
ghost [fillcolor=none]
UI [fillcolor=none]
events [fillcolor=wheat];
flag [fillcolor=palegreen3];
groups [fillcolor=wheat];
types [fillcolor=wheat];
instances [];
resources [];
optimize [];
remove_flag [];
persist [];
approval [];
edge [style="" dir=forward fontname="Verdana" fontsize=10];
types -> flag;
groups -> events;
events -> {flag mappings identifiers};
ghost -> hyperwarp;
UI -> ghost;
resources -> identifiers;
optimize -> groups;
hyperwarp -> flag;
instances -> {ghost UI types events hyperwarp flag};
resources -> {groups flag};
remove_flag -> approval;
persist -> approval;
approval -> {types resources instances};
}
which results in
But on reflection, seeing the difficulty I'm having to position the legend alongside the main graph, the way the position of node rankings in the main graph affects those in the legend, and the complication in the source that this introduces, I'm tempted to try a different approach (see my other answer, use a separate graph for the key)
This works well for simpler legends (from: https://forum.graphviz.org/t/adding-key-or-legend/351)
digraph l {
subgraph clusterMain {
graph [labelloc="b" labeljust="r" label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD>left 1</TD><TD>right 1</TD></TR>
<TR><TD>left 2</TD><TD>right 2</TD></TR>
</TABLE>>];
"x" "y"
a -> b -> c
}
}

Resources