Monday, October 15, 2007

Converting a Leo Hierarchy to a Graphviz Digraph

Yesterday I found myself wanting to translate the relationships in a Leo outline into Graphviz digraph. Right now you're probably saying "Why would I want to do that?" (or, more likely, "Wow, what a dork..."), so I'll explain.

Suppose you're using the outlining feature of Leo to organize information about items that have a natural hierarchy. For example, I'm using such a scheme to organize my notes on the lineages of various martial arts families. Now what if you want to present this hierarchy visually? While Leo is a great outline editor its a lousy presentation tool, so you'll want to take the relationships within the Leo outline and translate them into something more suitable.

It turns out to be simple, almost trivial, to do this once you know the appropriate functions to call. In order for this Presented that others might find it useful:

@color
@language python
@ Create a Graphviz .dot file containing a digraph representing
@ the relationships in part of the Leo outline.
@c

import leoGlobals as g

# Headline of the root of the subtree to convert

root_name = "<ROOT HEADLINE>"

# Create edge between parent and child nodes, then repeat the
# process for each child node.
# parent: Position object for parent node
# accumulator: text string used to build up the result.

def CreateEdge(parent,accumulator):
    for p in parent.children_iter():
        accumulator += "\""+parent.headString()+"\" -> \""+p.headString()+"\"\n"
        accumulator = CreateEdge(p,accumulator)
    return accumulator

##### Execution begins here

g.es("Converting hierarchy to digraph...")

# Find the root node

root_to_convert = g.findReference(root_name,g.top().rootPosition())

# Graphviz preamble for a digraph. "accumulator" is used to
# accumulate the result of the conversion process.

accumulator = "digraph D {\n"

# Convert the subtree starting at the named root node

accumulator = CreateEdge(root_to_convert,accumulator)

# Graphviz postamble for a digraph

accumulator += "}"

# Find the output node

output_node = g.findReference("output",g.top().rootPosition())

# And write the result to it.

output_node.setBodyStringOrPane(accumulator)

g.es("Done")

To make this work do the following:

  1. Copy the script into a Leo node.
  2. Change root_name to match the headline of the root node of the subtree you want to convert.
  3. Create a node named "output" to hold the output graph.
  4. Highlight the node containing the script and hit ctrl-E.

0 Comments:

Post a Comment

<< Home

Blog Information Profile for gg00