Making a Legend/Key in GraphViz - 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
}
}

Related

Create node in graphviz using polygon as icon and text label

Is there any way to create a node in Graphviz that looks like the below?
(Placing a hexagon and text side by side inside the node instead of just placing text inside box)
You can't easily embed nodes within other nodes, but you can insert images into nodes. Create an image (or images) with the polygon shape(s) and insert them into an HTML-style node (record-style would probably also work).
Like so:
digraph i{
{rank=same
n1 [shape=plaintext,label=<
<TABLE CELLSPACING="0" CELLPADDING="0" BORDER="1" cellborder="0">
<TR><TD FIXEDSIZE="true" height="20" width="20"><IMG SRC="cow.png" scale="true"/></TD><TD>some text</TD></TR>
</TABLE>
>
]
n2 [shape=plaintext,label=<
<TABLE CELLSPACING="0" CELLPADDING="0" BORDER="1" cellborder="0" >
<TR><TD colspan="2" bgcolor="green1">Step</TD></TR>
<TR><TD FIXEDSIZE="true" height="20" width="20"><IMG SRC="cow.png" scale="true"/></TD><TD>some text</TD></TR>
</TABLE>
>
]
n1 -> n2
}
}
Giving:

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, distance between table node and edge

How can I remove the space between the border of the table and the edge ?
The node seems to have a margin outside of the table.
The definition of the graph in dot:
strict digraph {
rankdir=RL;
node [shape=none, style=filled, fillcolor=aliceblue, fontname=verdana];
Model [shape=none, label=<<table border="0" cellspacing="0">
<tr><td border="1" bgcolor="lightblue">Model</td></tr>
<tr><td border="1" align="left">Name</td></tr>
<tr><td border="1" align="left">Description</td></tr>
<tr><td border="1" align="left">Universe</td></tr>
</table>>];
Universe [shape=none, label=<<table border="0" cellspacing="0">
<tr><td border="1" bgcolor="lightblue">Universe</td></tr>
<tr><td border="1" align="left">Name</td></tr>
<tr><td border="1" align="left">Description</td></tr>
</table>>];
Model -> Universe
}
The resulting png is:
Using graphviz version 2.38.0.
Any comment much appreciated.
Employ the margin keyword:
node [shape=none, style=filled, fillcolor=aliceblue, fontname=verdana, margin=0];
That'll reduce that aliceblue area around the tables to nothing and make the arrows really connect the tables.

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:

Resources