node_network.py 9.36 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
15
16
    def __init__(self, kat):
        self._nodes = {}
        self.__kat = kat
17
        self.__componentNodes = {}
Daniel Brown's avatar
Daniel Brown committed
18
19
20
21
22
23
        
    def createNode(self, node_name):
        if node_name == 'dump':
            return DumpNode()
            
        if node_name in self._nodes:
24
25
            # then this node already exists
            return self._nodes[node_name]
Daniel Brown's avatar
Daniel Brown committed
26
        else:
Daniel Brown's avatar
Daniel Brown committed
27
            n = Node(node_name, self)
28
            self.__add_node(n) # add node as a member of this object, e.g. kat.nodes.n
Daniel Brown's avatar
Daniel Brown committed
29
30
            self._nodes[node_name] = n
            return n
31
32
33
34
35
        
    def removeNode(self, node):
        if not isinstance(node,Node):
            raise exceptions.ValueError("node argument is not of type Node")
        
Daniel Brown's avatar
Daniel Brown committed
36
        if node.name not in self._nodes:
37
38
39
40
41
42
            raise exceptions.RuntimeError("Trying to remove node {0} when it has not been added".format(node.name))
        
        C = node.getComponents()
        
        if C[0][0] is not None or C[0][1] is not None:
            raise exceptions.RuntimeError("Cannot remove a node which is attached to components still")
Daniel Brown's avatar
Daniel Brown committed
43
            
44
45
46
        if len(C[1]) > 0:
            raise exceptions.RuntimeError("Cannot remove a node which is attached to detectors still")
        
47
        self.__remove_node(node)
48
49
        del self._nodes[node.name] 
        
Daniel Brown's avatar
Daniel Brown committed
50
51
    def hasNode(self, name):
        return (name in self._nodes)
52
53
54
55
    
    def getNodes(self):
        return self._nodes.copy()
    
Daniel Brown's avatar
Daniel Brown committed
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
    def dumpInfo(self):
        
        for name in self._nodes:
            
            n = self._nodes[name]
            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)
85
86
87
88
89
90
91
92
    
    def getComponentNodes(self, comp):
    
        if not isinstance(comp, Component):
            raise pkex.BasePyKatException("Passed object was not a component")
        
        return self.__componentNodes[comp.id]
            
93
94
95
96
    def __add_node(self, node):

        if not isinstance(node, Node):
            raise exceptions.ValueError("Argument is not of type Node")
Daniel Brown's avatar
Daniel Brown committed
97
        
98
99
100
101
102
        name = node.name
        fget = lambda self: self.__get_node(name)
        
        setattr(self.__class__, name, property(fget))
        setattr(self, '__node_' + name, node)                   
Daniel Brown's avatar
Daniel Brown committed
103
    
104
105
106
107
108
    def __remove_node(self, node):
        if not isinstance(node, Node):
            raise exceptions.ValueError("Argument is not of type Node")
        
        name = node.name
109
        detattr(self, '__node_' + name)
110
111
112
113
114
115
116
117
118
119
        delattr(self.__class__, name)
        
    def __get_node(self, name):
        return getattr(self, '__node_' + name)        
        
class Node(object):
    class gauss_version:
        w0_z = 1
        z_zR = 2
        
120
    def __init__(self, name, network):
Daniel Brown's avatar
Daniel Brown committed
121
122
123
124
        self._comp1 = None
        self._comp2 = None
        self._detectors = []
        self.__name = name
125
        self._item = None
Daniel Brown's avatar
Daniel Brown committed
126
        self._network = network
127
128
        self.__gauss = None
        self.__gauss_version = None
129
130
131
        
    @property
    def network(self): return self._network
Daniel Brown's avatar
Daniel Brown committed
132
    
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
    @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
        
    def getFinesseText(self):
        
        if not self.isConnected() or self.__gauss == None or self.__gauss_version == None:
            return None
            
            
        comp = ""
        
        if self._comp2 == None:
            comp = self._comp1.name
        else:
            comp = self._comp2.name
        
        rtn = []
        
        if self.__gauss_version == Node.gauss_version.w0_z:
            
            if len(self.__gauss) == 2:
                rtn.append("gauss gauss_{node} {comp} {node} {w0} {z}".format(node=self.name, comp=comp, w0=self.__gauss[0], z=self.__gauss[1]))
            elif len(self.__gauss) == 4:
                rtn.append("gauss gauss_{node} {comp} {node} {w0x} {zx} {w0y} {zy}".format(node=self.name, comp=comp, w0x=self.__gauss[0], zx=self.__gauss[1], w0y=self.__gauss[2], zy=self.__gauss[3]))
            else:
                raise pkex.BasePyKatException("Unexpected number of gaussian parameters")
        else:
            raise pkex.BasePyKatException("Unexpected gauss version")
            
        return rtn
        
Daniel Brown's avatar
Daniel Brown committed
179
    def isConnected(self):
180
181
182
183
184
185
186
        if (self._comp1 is not None) and (self._comp2 is not None):
            return True
        else:
            return False
      
    def remove(self):
        self._network.removeNode(self)
Daniel Brown's avatar
Daniel Brown committed
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
        
        if self._item != None:
            self._item.scene().removeItem(self._item)
    
    def disconnect(self, obj):
    
        if not (isinstance(obj,Component) or isinstance(obj,Detector)):
            raise exceptions.ValueError("Object is not a component or detector")
        
        if isinstance(obj, Component):
            
            if self._comp1 == obj:
                self._comp1 = None
            elif self._comp2 == obj:
                self._comp2 = None
            else:
                raise exceptions.RuntimeError("Cannot dettach {0} from node {1}".format(
                                    obj.name, self.__name))
          
        else:
            # we must have a detector as we check above            
            self._detectors.remove(obj)
    
        if self._item is not None:
            self._item.refresh()
            
    
Daniel Brown's avatar
Daniel Brown committed
214
215
216
217
218
219
220
221
222
223
224
225
226
    def connect(self, obj):

        if not (isinstance(obj,Component) or isinstance(obj,Detector)):
            raise exceptions.ValueError("Object is not a component or detector")
        
        if isinstance(obj, Component):
            
            if self._comp1 == None:
                self._comp1 = obj
            elif self._comp2 == None:
                self._comp2 = obj
            else:
                raise exceptions.RuntimeError("Cannot attach {0} to node {1} as it is already connected: {2} and {3}".format(
227
228
229
                                    obj.name, self.__name,self._comp1.name,self._comp2.name))
            
            if self._comp1 == self._comp2:
230
                raise exceptions.RuntimeError("Cannot connect {0} to both sides of node".format(obj.name))            
Daniel Brown's avatar
Daniel Brown committed
231
232
233
        else:
            # we must have a detector as we check above            
            self._detectors.append(obj)
234
    
235
236
237
238
239
240
241
242
243
244
245
246
        if self._item is not None:
            self._item.refresh()
            
    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,
                                                             nsize,nsize,parent)
            
        return self._item
    
Daniel Brown's avatar
Daniel Brown committed
247
248
249
250
251
252
    def getComponents(self):
        ''' Returns a tuple with the first being the 2 components that 
        connect to the node. The second item is a list of the detectors at the
        node'''
        return [(self._comp1, self._comp2),self._detectors]
        
253
254
    def amIConnected(self, obj):
        """
Daniel Brown's avatar
Daniel Brown committed
255
        Checks if obj is connected to the node. Returns true or false in tuple
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
        with None or the other object and the node index which it is attached to
        """ 
        if obj == self._comp1:
            if self._comp2 == None:
                ix = -1
            else:
                ix = self._comp2.getNodes().index(self)
                
            return [True, self._comp2, ix]
        elif obj == self._comp2:
            if self._comp1 == None:
                ix = -1
            else:
                ix = self._comp1.getNodes().index(self)
                
            return [True, self._comp1, ix]
        else:
            return [False, None]
        
Daniel Brown's avatar
Daniel Brown committed
275
276
277
278
279
280
281
    def __getname(self):
        return self.__name      
        
    name = property(__getname)
    
class DumpNode(Node):
    def __init__(self):
282
        Node.__init__(self, 'dump', None)
Daniel Brown's avatar
Daniel Brown committed
283
284