node_network.py 8.3 KB
Newer Older
Daniel Brown's avatar
Daniel Brown committed
1
2
3
4
5
6
7
# -*- coding: utf-8 -*-
"""
Created on Sun Jan 27 10:02:41 2013

@author: Daniel
"""
import exceptions
8
import pykat.gui.graphics
9
import pykat.exceptions as pkex
Daniel Brown's avatar
Daniel Brown committed
10
11
12
from pykat.components import Component
from pykat.detectors import Detector

13
class NodeNetwork(object):
Daniel Brown's avatar
Daniel Brown committed
14
    def __init__(self, kat):
15
        self.__nodes = {}
Daniel Brown's avatar
Daniel Brown committed
16
        self.__kat = kat
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
        self.__nodeComponents = {} # dictionary of tuples containing which components are connected to a node
        self.__componentNodes = {} # dictionary of tuples containing which nodes are connected to a given component
        self.__componentCallback = {}
        self.__node_id = 1
        
    def registerComponentNodes(self, comp, node_names, change_callback):
        """
        For a given component we create some nodes or get existing ones and 
        attach them to this component. Also specify a callback function that
        is called whenever the nodes attached to this component are changed
        , e.g. connected, disconnected, name change, etc.
        """
        if not isinstance(comp, Component):
            raise exceptions.ValueError("comp argument is not of type Component")
        
        if comp.id in self.__componentNodes:
            raise pkex.BasePyKatException("Component has already been registered")
        
        list = []
        
        for name in node_names:
38
39
            n = self.createNode(name)
            self.connectNodeToComp(n, comp, do_callback=False)
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
            list.append(n)
        
        self.__componentNodes[comp.id] = tuple(list)
        self.__componentCallback[comp.id] = change_callback
        
        change_callback()
    
    def connectNodeToComp(self, node, comp, do_callback=True):
        if node.id in self.__nodeComponents:
            comps = self.__nodeComponents[node.id]
        else:
            comps = ()
        
        if len(comps) >= 2:
            raise pkex.BasePyKatException("Node is already connected to 2 components")
        
        l = list(comps)
        l.append(comp)
        
        self.__nodeComponents[node.id] = tuple(l)
        
        if do_callback: self.__componentCallback[comp.id]()
Daniel Brown's avatar
Daniel Brown committed
62
63
64
65
66
        
    def createNode(self, node_name):
        if node_name == 'dump':
            return DumpNode()
            
67
        if node_name in self.__nodes:
68
            # then this node already exists
69
            return self.__nodes[node_name]
Daniel Brown's avatar
Daniel Brown committed
70
        else:
71
72
73
74
75
            n = Node(node_name, self, self.__node_id)
            
            self.__node_id += 1
            self.__add_node_attr(n) # add node as a member of this object, e.g. kat.nodes.n
            self.__nodes[node_name] = n
Daniel Brown's avatar
Daniel Brown committed
76
            return n
77
78
79
80
81
        
    def removeNode(self, node):
        if not isinstance(node,Node):
            raise exceptions.ValueError("node argument is not of type Node")
        
82
        if node.name not in self.__nodes:
83
84
            raise exceptions.RuntimeError("Trying to remove node {0} when it has not been added".format(node.name))
        
85
        C = self.getNodeComponents(node)
86
        
87
88
        if C[0] is not None or C[1] is not None:
            raise exceptions.RuntimeError("Cannot remove a node which is attached to components")
Daniel Brown's avatar
Daniel Brown committed
89
            
90
        if len(node.getDetectors()) > 0:
91
92
            raise exceptions.RuntimeError("Cannot remove a node which is attached to detectors still")
        
93
94
        self.__remove_node_attr(node)
        del self.__nodes[node.name] 
95
        
Daniel Brown's avatar
Daniel Brown committed
96
    def hasNode(self, name):
97
        return (name in self.__nodes)
98
99
    
    def getNodes(self):
100
        return self.__nodes.copy()
101
    
Daniel Brown's avatar
Daniel Brown committed
102
103
    def dumpInfo(self):
        
104
105
106
        for name in self.__nodes:
            
            n = self.__nodes[name]
Daniel Brown's avatar
Daniel Brown committed
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
            
            items = n.getComponents()
            comp = items[0][:]
            det = items[1]
            
            if comp[0] == None:
                comp1 = 'dump'
            else:
                comp1 = comp[0].name
            
            if comp[1] == None:
                comp2 = 'dump'
            else:
                comp2 = comp[1].name    
            
            detectors = ""
            
            if len(det) > 0:
                detectors = "Detectors: "
                
                for d in det:
                    detectors = detectors + d.name + " "
                
            print "node: {0} connected:{1} {2}->{3} {4}".format(
                    n.name,n.isConnected(),comp1, comp2, detectors)
132
    
133
134
    def getComponentNodes(self, comp): return self.__componentNodes[comp.id]
    def getNodeComponents(self, node): return self.__nodeComponents[node.id]
135
    
136
    def __add_node_attr(self, node):
137
138
139

        if not isinstance(node, Node):
            raise exceptions.ValueError("Argument is not of type Node")
Daniel Brown's avatar
Daniel Brown committed
140
        
141
        name = node.name
142
        fget = lambda self: self.__get_node_attr(name)
143
144
145
        
        setattr(self.__class__, name, property(fget))
        setattr(self, '__node_' + name, node)                   
Daniel Brown's avatar
Daniel Brown committed
146
    
147
    def __remove_node_attr(self, node):
148
149
150
151
        if not isinstance(node, Node):
            raise exceptions.ValueError("Argument is not of type Node")
        
        name = node.name
152
        detattr(self, '__node_' + name)
153
154
        delattr(self.__class__, name)
        
155
    def __get_node_attr(self, name):
156
157
158
159
160
161
162
        return getattr(self, '__node_' + name)        
        
class Node(object):
    class gauss_version:
        w0_z = 1
        z_zR = 2
        
163
    def __init__(self, name, network, id):
Daniel Brown's avatar
Daniel Brown committed
164
165
        self._detectors = []
        self.__name = name
166
        self._item = None
Daniel Brown's avatar
Daniel Brown committed
167
        self._network = network
168
169
        self.__gauss = None
        self.__gauss_version = None
170
        self.__id = id
171
        
172
173
174
    @property
    def id(self): return self.__id
    
175
176
    @property
    def network(self): return self._network
Daniel Brown's avatar
Daniel Brown committed
177
    
178
179
180
    @property
    def components(self): return self._network.getNodeComponents(self)
    
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
    @property
    def gauss(self): return self.__gauss
    
    def removeGauss():
        self.__gauss_version = None
        self.__gauss = None
        
    def gauss_w0_z(self, w0, z, w0y=None, zy=None):
        self.__gauss = []
        self.__gauss.append(w0)
        self.__gauss.append(z)
        
        if w0y != None and zy != None:
            self.__gauss.append(w0y)
            self.__gauss.append(zy)
            
        self.__gauss_version = Node.gauss_version.w0_z
        
199
200
    def getFinesseText(self):    
        return []
201
        
Daniel Brown's avatar
Daniel Brown committed
202
    def isConnected(self):
203
        if (self.components[0] is not None) and (self.self.components[1] is not None):
204
205
206
207
208
209
            return True
        else:
            return False
      
    def remove(self):
        self._network.removeNode(self)
Daniel Brown's avatar
Daniel Brown committed
210
211
212
213
        
        if self._item != None:
            self._item.scene().removeItem(self._item)
    
214
215
216
217
218
    def getQGraphicsItem(self,dx=0,dy=0,nsize=8,parent=None):
        if self._item == None:
            self._item = pykat.gui.graphics.NodeQGraphicItem(self,
                                                             dx,dy,
                                                             -nsize/2,-nsize/2,
219
                                                             nsize, nsize, parent)
220
221
222
            
        return self._item
    
223
224
    def getDetectors(self):
        return self._detectors[:]
Daniel Brown's avatar
Daniel Brown committed
225
        
226
227
    def amIConnected(self, obj):
        """
Daniel Brown's avatar
Daniel Brown committed
228
        Checks if obj is connected to the node. Returns true or false in tuple
229
230
        with None or the other object and the node index which it is attached to
        """ 
231
232
233
234
        comps = self.components
        
        if obj == comps[0]:
            if comps[1] == None:
235
236
                ix = -1
            else:
237
                ix = comps[1].getNodes().index(self)
238
                
239
240
241
242
            return [True, comps[1], ix]
            
        elif obj == comps[1]:
            if comps[0] == None:
243
244
                ix = -1
            else:
245
                ix = comps[0].getNodes().index(self)
246
                
247
            return [True, comps[0], ix]
248
249
250
        else:
            return [False, None]
        
251
252
253
    @property
    def name(self): return self.__name      
    
Daniel Brown's avatar
Daniel Brown committed
254
255
256
    
class DumpNode(Node):
    def __init__(self):
Daniel Brown's avatar
Daniel Brown committed
257
        Node.__init__(self, 'dump', None, -1)
Daniel Brown's avatar
Daniel Brown committed
258
259