Generating Graphs with Org and Dot

When I want to draw graph-like pictures I almost always use dot from the graphviz suite. The language is simple and it’s easy to generate it programmatically. Still, I don’t do it every day and so I always have to do a quick review of the language to draw my picture.

The other day, while I was looking for something completely different, I came across this wonderful tutorial by Karl Voit on Org’s Worg site. In it he shows how to leverage a bit of Elisp code from Rick Frankel to produce dot diagrams from a couple of tables. The idea is that you list the nodes of the graph in one table and the edges in the other and the code runs dot for you to produce the PNG file.

The examples that Voit uses doesn’t do his tutorial justice because they involve producing flow charts and who wants to do that? Not me, at least. I almost always either want a tree of some sort or perhaps a state diagram. So here are a couple of examples that show how easy it is to use the code and techniques he describes to draw those objects. Be sure to read the tutorial so you can follow along with the examples.

 1: (org-babel-execute:dot
 2:  (concat
 3:   "digraph {\n"
 4:   (when horiz "rankdir=LR;\n")       ;up-down or left-right
 5:   (mapconcat
 6:    (lambda (x)
 7:      (format "%s [label=\"%s\" shape=%s style=\"filled\" fillcolor=\"%s\"]"
 8:              (car x)
 9:              (nth 1 x)
10:              (if (string= "" (nth 2 x)) "box" (nth 2 x))
11:              (if (string= "" (nth 3 x)) "none" (nth 3 x))
12:              )) nodes "\n")
13:   "\n"
14:   (mapconcat
15:    (lambda (x)
16:      (format "%s -> %s [taillabel=\"%s\"]"
17:              (car x) (nth 1 x) (nth 2 x))) graph "\n")
18:   "}\n") params)

I’ve reproduced the code here because I made a small tweak in line 4 so that I can produce both horizontal and vertical layouts with the same code block. With the code in the tutorial you have to uncomment code to get the horizontal layout. To use my code you should change the HEADER line to

#+HEADER: :var nodes=simple-tree-nodes graph=simple-tree-graph horiz='nil

for vertical layout or

#+HEADER: :var nodes=simple-tree-nodes graph=simple-tree-graph horiz='t

for horizontal layout. The horiz variable can be changed in #+CALL statements so that you can have both modes in the same file.

Here’s a simple tree with a blue root, white internal nodes, and yellow leaves.

Table 1: simple-tree-nodes
node label shape fillcolor
a A ellipse blue
b B ellipse none
c C ellipse none
d D ellipse yellow
e E ellipse yellow
f F ellipse yellow
g G ellipse yellow

Table 2: simple-tree-graph
from to label
a b  
a c  
b d  
b e  
c f  
c g  

simple-graph.png

As a second example, here’s the transition diagram for a simple state machine that recognizes C-style comments. It uses the #+CALL statement

#+CALL: graph-from-tables[:file ~/org/blog/state-machine.png](nodes=state-nodes[2:-1],graph=state-edges[2:-1],horiz='t) :results file

Table 3: state-nodes
node label shape fillcolor
start START ellipse green
b1 BEGIN-1 ellipse none
c IN-COMMENT ellipse none
e1 END-1 ellipse none
d DONE ellipse red

Table 4: state-edges
from to label
start start ANY
start b1 /
b1 start ANY
b1 c *
c c ANY
c e1 *
e1 c ANY
e1 d /

state-machine.png

I love how simple all this is. Just include the code (non-exported, of course) into your buffer and write the two tables and you’ve got yourself a nice diagram without having to fuss with the dot language.

This entry was posted in General and tagged , . Bookmark the permalink.