Using GraphViz to visualize property graphs

To properly document our new project, I was trying to find a programmatic way to statically visualize property graphs. I stumbled upon GraphViz and the DOT family of languages which are fairly simple but powerful tools.

By “fairly simple” I mean compared to LaTex and ConTexT used with Tikz & PGF. If I had time to learn it I would because it is really powerful — just take a look at the examples at TeXample.net. Although these people are not kidding about the steep learning curve: the TikZ manual is 880 pages long, and it is “just” a module.

Again, GraphViz is more rudimentary but the above graph output only required minor tweaks. (Time will tell though how more complex property graphs could be rendered. This post will be updated with lessons learned.)

The DOT language is straightforward with only a handful of keywords but the GraphViz attributes can be a confusing bunch. The best way for me was to learn through examples (search results to Stackoverflow posts mostly.) as the attribute descriptions can be too vague.

Graph height and width

For example, there is a height and a width attribute but these are to alter the dimensions of a node. This Stackoverflow post has very clear examples on how to use the proper attributes: nodesep and ranksep.

Positioning edge labels

There is the lp (i.e., label position) attribute but I wasn’t able to figure out how it works and I used the solutions in this Stackoverflow answer instead.

The relationship between label and headlabel, taillabel is similar to the CSS box model positioning:

  • label is fixed to the edge and it can be quite off when there are multiple parallel edges with labels. It is not a very format-friendly attribute (and there is no way that it could follow the curves of an edge as in TikZ)
  • butheadlabel and taillabel are, used in conjunction with the modifiers labeldistance and labelangle. They detach the label from the edge and the label can be positioned relative to the edge endpoint that meets with the head or the tail.

Ordering nodes into specific columns

My problem was that my address graph model had cycles in it plus I wanted the nodes to be in a specific order. In contrast, as the DOT guide states, “the layout procedure used by dot relies on the graph being acyclic” and so it “assigns nodes to discrete ranks or levels” during the rendering process.

Here is a simplified version of the graph at the top:

Without the lines

{rank=same;  A;  kilgore;  logan;    }
{rank=same; B; unit1; unit2; }
{rank=same; C; street1; street2; }

it would look like this:

Semantically they are both the same but I had a shape in mind that requires less tracing. This example and these helped a lot to figure it out.

(1) Just create a straight (named or anonym) subgraph in the needed length,

digraph G {
rankdir=LR;
node [shape=record];
  { a->b->c->d->e; }
}

(2) make all the “ordering” graph’s nodes and edges invisible

digraph G {
rankdir=LR;
node [shape=record];
  { 
node [style="invis"];
edge [style="invis"];
a->b->c->d->e;
}
}

(3) and assign the main nodes to a specific node in the subgraph that has the right rank.

So kilgore and logan would go with a,
 { rank=same, a; kilgore; logan;}

apt and another_apt would go with b
{ rank=same, b; apt; another_apt;}
and so on.

This would create a raster effectively:

Try it out

Here are some extra examples and the webgraphviz website was an invaluable help to prototype.

Try it out by using the code below:

https://gist.github.com/toraritte/e19e732dc827c629bfb318064384743a

Or use dot -Tsvg first.gv -o first.svg from the command line. (Provided that your filename is first.gv).