Graphviz

From wikinotes
Revision as of 18:56, 1 December 2022 by Will (talk | contribs) (→‎Tutorials)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

GraphViz is a language for generating graphs. See also: http://graphs.grevian.org/example

Documentation

official docs http://www.graphviz.org/documentation/
node shapes https://www.graphviz.org/doc/info/shapes.html
official python lib docs https://graphviz.readthedocs.io/en/stable/manual.html

Tutorials

intro https://ncona.com/2020/06/create-diagrams-with-code-using-graphviz/
conversions between diagram languages https://text-to-diagram.com/

Usage

dot yourgraph.dot -Tpng > out.png  # render to file
dot yourgraph.dot -Tpng | feh -    # show image without saving it

You may also be interested in an interactive viewer:

xdot

Basics

digraph G {
	rankdir=LR; /* (TB/LR) horizontal instead of vertical */
	subgraph nodeclass {
		subgraph cluster1 {
			a -> b
			b -> c
			c -> d
		}
		subgraph cluster2 {
			A1 -> B1
			B1 -> C1
			C1 -> D1
		}
	}

	subgraph nodes {
		aa -> bb
		bb -> cc
	}
}

At it's simplest, you can just name the objects you are creating, and their connections.

diagraph mygraph {
	a -> b
   b -> c1
   b -> c2
}

You may also define shapes for specific items.

diagraph mygraph {
	a [shape=box];
	a -> b
	b -> c
}

Tools

wmgraphviz

A vim plugin with interactive graphviz editing.

:e yourfile.dot
:GraphvizInteractive

Syntax

Interactive Links

If you render a .svg image from graphviz, you can specify the links to html files, other svg files, etc that you'd like to open. (this way you can have a leveled, interactive graph). Once the SVG files are rendered, simply open them in a web-browser.

digraph {
   nodeA [URL="relative/file/path.png"];
   nodeB [URL="other/relative/file/path.html"];
}

Orientation

The orientation of the entire graph can be set by the rankdir attribute

diagraph mygraph {
	rankdir=LR; /* BT is the opposite of LR */
	a -> b
	b -> c

Subgraphs cannot set their own rankdir, or change the direction. However, cluster-subgraphs will generally appear in the order of the blocks they were defined in.

// a,b nodes will be grouped together in an invisible cluster
// above the invisible cluster containing c,d,e

digraph mygraph {
    subgraph cluster_top_group {
        color=invis;
        a;
        b;
    }

    subgraph cluster_bot_group {
        color=invis;
        c;
        d;
        e;
    }

    subgraph edges {
        edge [color=dodgerblue];
        a -> b;
        a -> c;
        a -> d;
        a -> e;
    }
}

Clusters

Subgraphs or clusters can be created to group nodes.

#        \/ prefix is required for hard-line!
subgraph cluster_nodetypes {
   label="nodetypes"

   division
   product
}

clusters can also be connected to each other semi-directly (connect a node to another node, then define that the arrow should start from the cluster by using ltail and that the arrow should end on another cluster using lhead.


digraph G {
  compound=true;
  subgraph cluster0 {
    a -> b;
    a -> c;
    b -> d;
    c -> d;
  }
  subgraph cluster1 {
    e -> g;
    e -> f;
  }
  b -> f [lhead=cluster1];
  d -> e;
  c -> g [ltail=cluster0,lhead=cluster1];
  c -> e [ltail=cluster0];
  d -> h;
}


You can utilize various levels of clusters to simulate horizontal-stacking in a vertical graph, or vertical-stacking in a horizontal graph.

custom connections

You can colour, or otherwise customize a group of connections by putting them in a subgraph.

  subgraph rows {
    edge [color=red, constraint=false];
    c0r0 -> c1r0;
    c1r0 -> c2r0;
    c0r1 -> c1r1;
    c1r1 -> c2r1;
    c0r2 -> c1r2;
    c1r2 -> c2r2;
  }

node attributes

The current recommended way of creating nodes with attributes is using the html-like table.

digraph G {
    // Table nodes
    user [label=<
        <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
            <TR><TD PORT="user" BGCOLOR="red">User</TD></TR>
        </TABLE>
    >];

    aws [label=<
        <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
            <TR><TD BGCOLOR="darkseagreen">AWS</TD></TR>
            <TR><TD PORT="route53">Route53 <i>(https://twistedmountainanimation.com/...)</i></TD></TR>
        </TABLE>
    >];

    // Connections
    user:user -> aws:route53;
}


The old (deprecated) way of having nodes with attributes is creating 'record' nodes.

AudioSampleCommand [shape="record";
                   label="AudioSampleCommand|<f0> a|<f1> b";]

Other [shape="record";
       label="Other|<f0>input";];

AudioSampleCommand:f1 -> Other:f0