Ed,
I believe 2 things are going on here.
- You have not specified
pack=18
as an attribute to get a 1/4 inch margin around your subclusters or nodes.
- You are missing an overall cluster which surrounds the graph with the specification
packmode=array_u1
to force all nested clusters into one stacked column.
Back to my previous example, lets look at the hierarchy of clusters in the diagram. I’ve erased the nodes and edges, and made annotations using MS Paint.
This should help you understand the packmode
and sortv
settings at each level.
I know you are using a Python package to build the graph. I don’t know Python, but I can understand what is going on in your code. You are building an object tree, emitting dot
source, then pumping the dot
source through Graphviz.
You need to make your calls in such a way that you add nodes to clusters, and add clusters to clusters.
The tree that corresponds to the structure in the picture above would look like this:
Translating the tree to code, write the code from the bottom of the tree to the top. I’m speculating that the code will look something like this (no guarantees that this works).
G.add_node('node_thing1a', label='Thing 1A', shape='box', sortv=1)
G.add_node('node_thing1b', label='Thing 1B', shape='box', sortv=2)
G.add_subgraph(name='cluster_nomargin1', nbunch=['node_thing1a','node_thing1b'], packmode='array_u2', pack=0)
G.add_node('node_thing2a', label='Thing 2A', shape='box', sortv=1)
G.add_node('node_thing2b', label='Thing 2B', shape='box', sortv=2)
G.add_subgraph(name='cluster_nomargin2', nbunch=['node_thing2a','node_thing2b'], packmode='array_u2', pack=0)
G.add_node('node_thing3a', label='Thing 3A', shape='box', sortv=1)
G.add_node('node_thing3b', label='Thing 3B', shape='box', sortv=2)
G.add_subgraph(name='cluster_nomargin3', nbunch=['node_thing3a','node_thing3b'], packmode='array_u2', pack=0)
G.add_subgraph(name='cluster_dashed1', nbunch=['cluster_nomargin1'], style='dashed', sortv=10)
G.add_subgraph(name='cluster_dashed2', nbunch=['cluster_nomargin2'], style='dashed', sortv=20)
G.add_subgraph(name='cluster_dashed3', nbunch=['cluster_nomargin3'], style='dashed', sortv=30)
G.add_node('node_thinga', label='Thing A', shape='box', sortv=1)
G.add_node('node_thingb', label='Thing B', shape='box', sortv=2)
G.add_subgraph(name='cluster_row1', nbunch=['node_thinga,node_thingb'], packmode='array_u', sortv=100)
G.add_subgraph(name='cluster_row2', nbunch=['cluster_nomargin1,cluster_nomargin2,cluster_nomargin3'], packmode='array_u3', sortv=200)
G.add_node('node_thing1c', label='Thing 1C', shape='box', sortv=1)
G.add_node('node_thing2c', label='Thing 2C', shape='box', sortv=2)
G.add_node('node_thing3c', label='Thing 3C', shape='box', sortv=3)
G.add_subgraph(name='cluster_row3', nbunch=['node_thing1c,node_thing2c,node_thing3c'], packmode='array_u3', sortv=300)
G.add_subgraph(name='cluster_page', nbunch=['cluster_row1,cluster_row2,cluster_row3'], packmode='array_u1', pack=18)
I hope this is fairly close to being accurate. The technique is to create the nodes, then attach them to a parent cluster. Then create more clusters, attaching these child clusters to them until you reach the root cluster which wraps the entire page. Then execute your code to draw the graph.
I’m not sure how attribute inheritance works here, so you may have to specify pack=0
or pack=18
in places if your margins needs adjustments.
Let me know if this works for you,
Jeff