Sunday 26 January 2014 — This is close to 11 years old. Be careful.
When I wrote Facts and myths about Python names and values, I included figures drawn with Graphviz. I made a light wrapper to help, but the figures were mostly just Graphviz. For example, this code:
g = CogGraphviz()
g.codelabel("nums = [1, 2, 3]")
g.dot("""
nums [NAMEATTRS]
list1 [shape=record, label="{<0>|<1>|<2>}"]
nums -> list1:0
subgraph nums {
rankdir=LR;
1 [INTATTRS]
2 [INTATTRS]
3 [INTATTRS]
}
list1:0 -> 1
list1:1 -> 2
list1:2 -> 3
""")
g.img(alt="nums refers to a list, which refers to ints")
produced this figure:
The beauty of Graphviz is that you describe the topology of your graph, and it lays it out for you. The problem is, if you care about the layout, it is very difficult to control. Why are the 1, 2, 3 where they are? How do I move them? I couldn’t figure it out. And I wanted to have new shapes, and control where the lines joined, etc.
So I wrote a library called Cupid to help me make the figures the way I wanted them. Cupid is an API that generates SVG figures. Half of it is generic “place this rectangle here” kinds of SVG operations, and half is very specific to the names-and-values diagrams I wanted to create.
Now to make that same figure, I use this code:
fig = start_figure(title="nums refers to a list, which refers to ints")
fig.top_code("nums = [1, 2, 3]")
n_nums = fig.auto_name("nums")
l_nums = fig.list(length=3, pos=fig.val_for_name(n_nums))
fig.reference(n_nums, l_nums[0])
y_ints = fig.y+10
for i in range(3):
i_num = fig.int(top=(l_nums[1].cx+(i-1)*35, y_ints), text=str(i+1))
fig.connect(
l_nums[i].center, 90, i_num.north, 90,
start_marker=fig.DOT, class_="arrow"
)
finish_figure(fig)
The new code is more complicated than the old code, but I can predict what it will do, and if I want it to do something new, I can extend Cupid.
Cupid isn’t the handiest thing, but I can make it do what I want. This is my way with this site: I want it the way I want it, I enjoy writing the tools that let me make it that way, and I don’t mind writing code to produce figures when other people would use a mouse.
Comments
TikZ is a similar package that I have used in the past. It is based on LaTex. There are some really nice examples out there:
http://www.texample.net/tikz/examples/tcp-state-machine/
http://packages.python.org/svgwrite/ You would still have to create the specifics on how you want the figures but the python to svg is already written and tested. More example svgwrite python programs and svg are at
https://docs.google.com/folder/d/0BwFQiTKfux0qY1Y2d1hRdndtSEk/edit
[1]: http://projects.haskell.org/diagrams/gallery.html
Add a comment: