Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python library for creating tree graphs out of nested Python objects (dicts)

Does anyone know of any Python libraries that allow you to simply and quickly feed it an object nested to arbitrary levels, like for example a dict tree along the lines of what you'd find in this gist, and it can spit out a workable tree graph file?

Simplicity is key, here, since I have to be able to work with people who are not technically minded.

What I mean by "graph tree" is something along the lines of the following, where I could feed it a nested dictionary of values and it would then create the tree structure:


(source: rubyforge.org)

like image 461
jdotjdot Avatar asked Jan 25 '13 17:01

jdotjdot


2 Answers

I'm not sure that this is quite what you have in mind, but it's the first thing that comes to mind.

blockdiag is mainly intended to be used as a standalone file processor similar to Graphviz (for which there exists a Python interface). It accepts a text file as input with a drop-dead simple syntax, and produces images as output.

You should be able to write a simple shim to output your recursive dict structure formatted for input to the standalone blockdiag script, or import the necessary innards of the blockdiag package and drive the output directly.

If this sounds promising, I'll see if I can whip up some example code.

EDIT Example code:

def print_blockdiag(tree, parent=None):
    if not parent: print('blockdiag { orientation = portrait')
    for key in tree:
        if parent: print('   {} -> {};'.format(parent, key))
        print_blockdiag(tree[key], key)
    if not parent: print('}')

This will output a file that blockdiag can read.

like image 179
neirbowj Avatar answered Sep 19 '22 11:09

neirbowj


so the library i recommend and use for my code snippet in this answer is not a python library, but it is a python-friendly library, by which i mean that code using this library can be inserted into a python module for processing data and this foreign code will connect to extant python code on both ends, ie, both input and output, and i suspect, although of course i don't know, that's all that's really meant by the "python library" criterion. So if you are writing a web app, this code would be client-side. In other words, this library is not python, but it works with python.

  1. its input is (nearly) raw python dicts, more specifically, json.load(a_python_dict) returns a json array or object, a format which this javascript library can of course recognize; and

  2. the output format is either HTML or SVG, not objects in some language-specific format

You can use d3.js. It has a class specifically for rendering trees:

var tree = d3.layout.tree().size([h, w]);

There is also a couple of examples of trees (working code) in the example folder in the d3 source, which you can clone/download form the link i provided above.

Because d3 is a javascript library, its native data format is JSON.

The basic structure is a nested dictionary, each dictionary representing a single node with two values, the node's name and its children (stored in an array), keyed to names and children, respectively:

{"name": "a_root_node", "children": ["B", "C"]}

and of course it's simple to convert between python dictionaries and JSON:

>>> d = {"name": 'A', "children": ['B', 'C']}
>>> import json as JSON
>>> dj = JSON.dumps(d)
>>> dj
    '{"name": "A", "children": ["B", "C"]}'

here's a python dictionary representation of a larger tree (a dozen or so nodes) which i converted to json as above, and then rendered in d3 as the tree shown in the image below:

tree = {'name': 'root', 'children': [{'name': 'node 2', 'children': 
       [{'name': 'node 4', 'children': [{'name': 'node 10', 'size': 7500}, 
       {'name': 'node 11', 'size': 12000}]}, {'name': 'node 5', 'children': 
       [{'name': 'node 12', 'children': [{'name': 'node 16', 'size': 10000}, 
       {'name': 'node 17', 'size': 12000}]}, {'name': 'node 13', 'size': 5000}]}]}, 
       {'name': 'node 3', 'children': [{'name': 'node 6', 'children': 
       [{'name': 'node 14', 'size': 8000}, {'name': 'node 15', 'size': 9000}]}, 
       {'name': 'node 7', 'children': [{'name': 'node 8', 'size': 10000}, 
       {'name': 'node 9', 'size': 12000}]}]}]}

tree represented as python dictionary rendered in d3:

note: d3 renders in the browser; the image above is just a screen shot of my browser window.

like image 21
doug Avatar answered Sep 20 '22 11:09

doug