pretty printing graphs

John Hunter jdhunter at ace.bsd.uchicago.edu
Mon Jul 28 19:13:10 CEST 2003


I have a tree structure (directed acyclic graph), where each node can
represent itself as a multi-line string that is not very wide (eg, 10
chars per line).  I would like to print the graph like

        C
   C1        C2
C1a  C1b   C2a   C2b

Where C, C1, etc.. are the multiline string blocks referred to above.
Does anybody know of a tool that can do this.  Here is an example,
somewhat long because I have to create the multiline strings.

    from __future__ import division, generators

    def enumerate(seq):
        "Waiting for python 2.3"
        for i in range(len(seq)):
            yield i, seq[i]

    class O:

        def __init__(self, text):
            self.text = text
        def __str__(self):
            return self.text 

    class Node:
        def __init__(self, o):
            self.node = o
            self.children = []

        def __str__(self):
                s = ''
                #s += str(self.node) + '\n\n'
                if len(self.children)==0: return s
                childStrs = [str(child.node) for child in self.children]

                lines = [[] for tmp in childStrs]
                for lineNum, t in enumerate(childStrs):
                    lines[lineNum].extend(t.split('\n'))

                maxLines = max([len(l) for l in lines])
                sep = '      '
                for lineNum in range(maxLines):
                    row = ''
                    for childNum in range(len(childStrs)): 
                        row += lines[childNum][lineNum] + sep
                    s += row + '\n'
                s += '\n\n'
                for l in self.children:
                    s += str(l) 
                return s



    n0 = Node(O("""1  2  3  0
    1  2  3  4 
    1  2  1  5 
    1  2  1  1 
    4  3  2  2 
    4  3  2  7 
    2  3  2  3 
    2  3  2  9"""))


    n1 = Node(O("""1  2  3  0
    1  2  3  4
    1  2  1  5
    1  2  1  1
    ----------
    1  1  0  0"""))

    n2 = Node(O("""4  3  2  2
    4  3  2  7
    2  3  2  3
    2  3  2  9
    ----------
    0  1  1  0"""))



    n1a = Node(O("""1  2  1  5
    1  2  1  1
    ----------
    1  1  1  0"""))

    n1b = Node(O("""1  2  3  0
    1  2  3  4
    ----------
    1  1  1  0"""))

    n2a = Node(O("""2  3  2  3
    2  3  2  9
    ----------
    1  1  1  0"""))

    n2b = Node(O("""4  3  2  2
    4  3  2  7
    ----------
    1  1  1  0"""))


    n0.children.extend([n1, n2])
    n1.children.extend([n1a, n1b])
    n2.children.extend([n2a, n2b])
    print n0

Which prints:

1  2  3  0      4  3  2  2      
1  2  3  4      4  3  2  7      
1  2  1  5      2  3  2  3      
1  2  1  1      2  3  2  9      
----------      ----------      
1  1  0  0      0  1  1  0      


1  2  1  5      1  2  3  0      
1  2  1  1      1  2  3  4      
----------      ----------      
1  1  1  0      1  1  1  0      


2  3  2  3      4  3  2  2      
2  3  2  9      4  3  2  7      
----------      ----------      
1  1  1  0      1  1  1  0      


This does part of the work, printing the child nodes on the same rows,
but doesn't the hierarchical part very well.  What I would like is
something like this:

			 1  2  3  0  
			 1  2  3  4 
			 1  2  1  5 
			 1  2  1  1 
			 4  3  2  2 
			 4  3  2  7 
			 2  3  2  3 
			 2  3  2  9
 
	       1  2  3  0        4  3  2  2      
	       1  2  3  4        4  3  2  7      
	       1  2  1  5        2  3  2  3      
	       1  2  1  1        2  3  2  9      
	       ----------        ----------      
	       1  1  0  0        0  1  1  0      


1  2  1  5    1  2  3  0          2  3  2  3      4  3  2  2      
1  2  1  1    1  2  3  4          2  3  2  9      4  3  2  7      
----------    ----------          ----------      ----------      
1  1  1  0    1  1  1  0          1  1  1  0      1  1  1  0      


Thanks,
John Hunter





More information about the Python-list mailing list