File: plotgraph.py

package info (click to toggle)
mccode 3.5.19%2Bds5-2
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 1,113,256 kB
  • sloc: ansic: 40,697; python: 25,137; yacc: 8,438; sh: 5,405; javascript: 4,596; lex: 1,632; cpp: 742; perl: 296; lisp: 273; makefile: 226; fortran: 132
file content (152 lines) | stat: -rw-r--r-- 4,864 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
'''
Plot graph node types.

All plot graph node types have a parent, primaries and secondaries, corresponding to 
"click", "rclick" or "ctr-click" in a user interface.

The graph is directed from parents to (multiple) children.

Descendents also have a data handle instance or list. This facilitates deferred loading 
by means of the getdata() data handle method.
'''


class PlotNode(object):
    ''' 
    Base class for plot graph nodes. 
    '''
    def __init__(self):
        self.parent = None
        ''' primary node children'''
        self.primaries = []
        ''' alternative/secondary node children '''
        self.secondaries = []
    def set_primaries(self, node_lst):
        self.primaries = node_lst
        for node in node_lst:
            node.parent = self
    def get_primaries(self):
        return self.primaries
    def set_secondaries(self, node_lst):
        self.secondaries = node_lst
        for node in node_lst: 
            node.parent = self
    def get_secondaries(self):
        return self.secondaries
    def get_parent(self):
        return self.parent
    def getdata_idx(self, idx):
        ''' must return a valid data handle index '''
    def getdata_lst(self):
        ''' must return a list '''
    def getnumdata(self):
        ''' must return the number of held data handles '''


class PNMultiple(PlotNode):
    '''
    A node containing multiple plot instances to be plotted simultaneously.
    '''
    def __init__(self, data_handle_lst):
        self._data_handle_lst = data_handle_lst
        super().__init__()
    def getdata_idx(self, idx):
        return self._data_handle_lst[idx].getdata()
    def getdata_lst(self):
        return [d.getdata() for d in self._data_handle_lst]
    def getnumdata(self):
        return len(self._data_handle_lst)
    def __str__(self):
        return 'PNMultiple'


class PNSingle(PlotNode):
    '''
    A node containing a data handle instance to be plotted singularly.
    '''
    def __init__(self, data_handle):
        self._data_handle = data_handle
        super().__init__()
    def getdata_idx(self, idx):
        if idx != 0: raise Exception('PNSingle: getdata_idx: idx must be zero.')
        return self._data_handle.getdata()
    def getdata_lst(self):
        return [self._data_handle.getdata()]
    def getnumdata(self):
        return 1
    def __str__(self):
        return 'PNSingle'


class DataHandle(object):
    ''' 
    Proxy object enabling deferred loading through the use of "getdata".
    
    Do not set the data property explicitly in the constructor unless you have a good reason.
    '''
    def __init__(self, load_fct, data=None):
        self._load_fct = load_fct
        self._data = data
    def getdata(self):
        if not self._data:
            self._data = self._load_fct()
        return self._data


class PlotGraphPrint(object):
    '''
    Simple plot graph visualization tool for debugging graph integrity.
    
    NOTE: Iteration logics has not been implemented.
    '''
    def __init__(self, rootnode, indent_str='    '):
        if indent_str == '' or type(indent_str) != str:
            raise Exception('PlotGraphPrint: indent_str must be a non-empty string.')
        self.indent_str = indent_str
        self.root = rootnode
        self.printed_ids = []
        # execute
        self.print_recurse(self.root, level=0)
        
    def print_recurse(self, node, level):
        ''' node print recursion '''
        self.printnode(node, level)
        children = node.primaries + node.secondaries
        for c in children:
            self.print_recurse( c, level+1)                

    def printnode(self, node, level=0):
        ''' 
        Prints the node id, its children id's and data reference, respecting indent and
        using self.indent_str.
        '''
        # only print nodes once
        if id(node) in self.printed_ids:
            return
        
        indent = self.indent_str
        
        # print the node
        print()
        print(indent*(level+0) + '%s (%d):' % (node, id(node)))
        
        if node.parent:
            print(indent*(level+1) + 'parent:')
            print(indent*(level+2) + '%s (%d)' % (node.parent, id(node.parent)))
        
        print(indent*(level+1) + 'data objects:')
        for d in node.getdata_lst():
            print(indent*(level+2) + '%s (%d)' % (d, id(d)))
        
        if not len(node.primaries) == 0:
            print(indent*(level+1) + 'primary children:')
            for p in node.primaries:
                print(indent*(level+2) + '%s (%d)' % (p, id(p)))
        
        if not len(node.secondaries) == 0:
            print(indent*(level+1) + 'secondary children:')
            for s in node.secondaries:
                print(indent*(level+2) + '%s (%d)' % (s, id(s)))
        
        self.printed_ids.append(id(node))