components.py 9.49 KB
Newer Older
Daniel Brown's avatar
Daniel Brown committed
1
2
3
4
5
6
7
8
9
# -*- coding: utf-8 -*-
"""
Created on Mon Jan 28 11:10:01 2013

@author: Daniel
"""
import exceptions
import pykat.gui.resources
import pykat
10
import pykat.gui.graphics
11
#from pykat.gui.graphics import *
Daniel Brown's avatar
Daniel Brown committed
12
from pykat.node_network import *
13
14
#from PyQt4.QtGui import *
#from PyQt4.Qt import *
Daniel Brown's avatar
Daniel Brown committed
15

16
class Component(object) :
17
    def __init__(self, name):
Daniel Brown's avatar
Daniel Brown committed
18
19
20
        self.__name = name
        self._svgItem = None
        self.__nodes = []
21
22
        self._requested_node_names = []
        self._kat = None
Daniel Brown's avatar
Daniel Brown committed
23
        
24
25
        #if not isinstance(kat,pykat.finesse.kat):
        #    raise exceptions.ValueError("kat argument is not a pykat.finesse.kat object")
Daniel Brown's avatar
Daniel Brown committed
26
            
27
28
29
30
31
32
33
34
35
36
37
38
39
40
        #kat.add(self)
    
    def _on_kat_add(self, kat):
        """
        Called when this component has been added to a kat object
        """
        self._kat = kat
        
        for node_name in self._requested_node_names:
            self._addNode(node_name)
        
    @staticmethod
    def parseFinesseText(text):    
        raise NotImplementedError("This function is not implemented")
Daniel Brown's avatar
Daniel Brown committed
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
        
    def getFinesseText(self):
        """ Base class for individual finesse optical components """    
        raise NotImplementedError("This function is not implemented")
        
    def getQGraphicsItem(self):    
        return None      
        
    def _addNode(self, name):
        """ Adds a node in sequential order to the component, i.e. add them
        n1, n2, n3, n4... etc. by the name of the node"""
            
        n = self._kat.nodes.createNode(name)
        
        if n == None:
56
            raise exceptions.RuntimeError("createNode did not return a node for '{0}'".format(name))
Daniel Brown's avatar
Daniel Brown committed
57
        else:
58
59
            n.connect(self)
                
Daniel Brown's avatar
Daniel Brown committed
60
61
62
63
64
65
66
67
68
69
70
71
72
            self.__nodes.append(n)
        
        return n
        
    def getNodes(self):
        """ Returns a copy of the nodes the component has """
        return self.__nodes[:]        
            
    def __getname(self):
        return self.__name      
        
    name = property(__getname)
    
73
74
75
76
class Param(float):
    def __new__(self,name,value):
        return float.__new__(self,value)
         
Daniel Brown's avatar
Daniel Brown committed
77
78
79
    def __init__(self,name,value):
        self.__name = name
        
80
81
    name = property(lambda self: self.__name)
           
Daniel Brown's avatar
Daniel Brown committed
82
class mirror(Component):
83
    def __init__(self,name,node1,node2,R=0,T=0,phi=0,Rcx=0,Rcy=0,xbeta=0,ybeta=0):
Daniel Brown's avatar
Daniel Brown committed
84
        
85
        Component.__init__(self,name)
Daniel Brown's avatar
Daniel Brown committed
86
        
87
88
        self._requested_node_names.append(node1)
        self._requested_node_names.append(node2)
Daniel Brown's avatar
Daniel Brown committed
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
        self.__R = R
        self.__T = T
        self.__phi = phi
        self.__Rcx = Rcx
        self.__Rcy = Rcy
        self.__xbeta = xbeta
        self.__ybeta = ybeta
            
    @property
    def R(self):
        return Param('R',self.__R)
    @R.setter
    def R(self,value):
        self.__R = value
    @property
    def T(self): return Param('T', self.__T)
    @T.setter
    def T(self,value): self.__T = value
        
    @property
    def phi(self): return Param('phi', self.__phi)
    @phi.setter
    def phi(self,value): self.__phi = value
    
    @property
    def Rcx(self): return Param('Rcx', self.__Rcx)
    @Rcx.setter
    def Rcx(self,value): self.__Rcx = value
    @property
    def Rcy(self): return Param('Rcy', self.__Rcy)
    @Rcy.setter
    def Rcy(self,value): self.__Rcy = value
    
    
    @property
    def xbeta(self): return Param('xbeta', self.__xbeta)
    @xbeta.setter
    def xbeta(self,value): self.__xbeta = value
    @property
    def ybeta(self): return Param('ybeta', self.__ybeta)
    @ybeta.setter
    def ybeta(self,value): self.__ybeta = value
    
    @property
    def Rc(self):
Daniel Brown's avatar
Daniel Brown committed
135
136
137
138
139
        if self.Rcx == self.Rcy:
            return self.Rcx
        else:
            return [self.Rcx, self.Rcy]
    
140
141
    @Rc.setter
    def Rc(self,value):
Daniel Brown's avatar
Daniel Brown committed
142
143
        self.Rcx = value
        self.Rcy = value
144
145
146
147
148
149
150
151
152
153
154
155
156
157
    
    @staticmethod
    def parseFinesseText(text):
        values = text.split(" ")

        if values[0] != "m":
            raise exceptions.RuntimeError("'{0}' not a valid Finesse mirror command".format(text))

        values.pop(0) # remove initial value
        
        if len(values) != 6:
            raise exceptions.RuntimeError("Mirror Finesse code format incorrect '{0}'".format(text))

        return mirror(values[0], values[4], values[5], R=values[1], T=values[2], phi=values[3])
Daniel Brown's avatar
Daniel Brown committed
158
159
160
        
    def getFinesseText(self):        
        rtn = []
161
162
163
164
165
        nodes = self.getNodes()
        
        if len(nodes) != 2:
            raise exceptions.RuntimeError("Not enough nodes for mirror")
            
Daniel Brown's avatar
Daniel Brown committed
166
        rtn.append('m {0} {1} {2} {3} {4} {5}'.format(
167
                self.name, self.__R, self.__T, self.__phi,
168
                nodes[0].name, nodes[1].name))
Daniel Brown's avatar
Daniel Brown committed
169
            
170
171
172
173
        if self.Rcx != 0: rtn.append("attr {0} Rcx {1}".format(self.name,self.__Rcx))
        if self.Rcy != 0: rtn.append("attr {0} Rcy {1}".format(self.name,self.__Rcy))
        if self.xbeta != 0: rtn.append("attr {0} xbeta {1}".format(self.name,self.__xbeta))
        if self.ybeta != 0: rtn.append("attr {0} ybeta {1}".format(self.name,self.__ybeta))
Daniel Brown's avatar
Daniel Brown committed
174
175
176
177
178
        
        return rtn
        
    def getQGraphicsItem(self):
        if self._svgItem == None:
179
            nodes = self.getNodes()
180
            self._svgItem = pykat.gui.graphics.ComponentQGraphicsItem(":/resources/mirror_flat.svg",self
181
                                                ,[(-4,15,self.nodes[0]),(14,15,self.nodes[1])])
Daniel Brown's avatar
Daniel Brown committed
182
183
184
185
        return self._svgItem
   
   
class space(Component):
186
187
    def __init__(self, name, node1, node2, L=0, n=1):
        Component.__init__(self,name,)
Daniel Brown's avatar
Daniel Brown committed
188
        
189
190
        self._requested_node_names.append(node1)
        self._requested_node_names.append(node2)
Daniel Brown's avatar
Daniel Brown committed
191
        
192
193
194
195
196
197
198
199
200
201
202
203
204
        self.__L = L
        self.__n = n
        self._QItem = None
        
    @property
    def L(self): return Param('L', self.__L)
    @L.setter
    def L(self,value): self.__L = value
    @property
    def n(self): return Param('n', self.__n)
    @n.setter
    def n(self,value): self.__n = value
    
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
    @staticmethod
    def parseFinesseText(text):
        values = text.split(" ")

        if values[0] != "s":
            raise exceptions.RuntimeError("'{0}' not a valid Finesse space command".format(text))

        values.pop(0) # remove initial value
        
        if len(values) == 5:
            return space(values[0],values[3],values[4],L=values[1],n=values[2])
        elif len(values) == 4:
            return space(values[0],values[2],values[3],L=values[1])
        else:
            raise exceptions.RuntimeError("Space Finesse code format incorrect '{0}'".format(text))
        
Daniel Brown's avatar
Daniel Brown committed
221
    def getFinesseText(self):
222
223
        nodes = self.getNodes()
        
224
        if self.__n == 1:
225
            return 's {0} {1} {2} {3}'.format(self.name, self.__L, nodes[0].name, nodes[1].name)            
Daniel Brown's avatar
Daniel Brown committed
226
        else:
227
            return 's {0} {1} {2} {3} {4}'.format(self.name, self.__L, self.__n, nodes[0].name, nodes[1].name)            
Daniel Brown's avatar
Daniel Brown committed
228
       
229
230
    def getQGraphicsItem(self):
        if self._QItem == None:
231
            self._QItem = pykat.gui.graphics.SpaceQGraphicsItem(self)
232
233
234
        
        return self._QItem  

235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
    def changeNode(self, node_old, node_new):
        '''
        Called when a space's node has been connected
        to another components node
        '''
        node_new.connect(self)
        node_old.disconnect(self)
        
        if self.node1 == node_old:
            self.node1 = node_new
        
        if self.node2 == node_old:
            self.node2 = node_new

    
Daniel Brown's avatar
Daniel Brown committed
250
class laser(Component):
251
252
253
254
    def __init__(self,name,node,P=1,f_offset=0,phase=0):
        Component.__init__(self,name)
        
        self._requested_node_names.append(node)
Daniel Brown's avatar
Daniel Brown committed
255
        
256
257
258
        self.__power = P
        self.__f_offset = f_offset
        self.__phase = phase
Daniel Brown's avatar
Daniel Brown committed
259
        
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
    @property
    def power(self): return Param('P', self.__power)
    @power.setter
    def power(self,value): self.__power = value
    
    @property
    def f_offset(self): return Param('f', self.__f_offset)
    @f_offset.setter
    def f_offset(self,value): self.__f_offset = value
    
    @property
    def phase(self): return Param('phase', self.__phase)
    @phase.setter
    def phase(self,value): self.__phase = value
    
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
    @staticmethod
    def parseFinesseText(text):
        values = text.split(" ")

        if values[0] != "l":
            raise exceptions.RuntimeError("'{0}' not a valid Finesse laser command".format(text))

        values.pop(0) # remove initial value
        
        if len(values) == 5:
            return laser(values[0],values[4],P=values[1],f_offset=values[2],phase=values[3])
        elif len(values) == 4:
            return laser(values[0],values[3],P=values[1],f_offset=values[2], phase=0)
        else:
            raise exceptions.RuntimeError("Laser Finesse code format incorrect '{0}'".format(text))
    
Daniel Brown's avatar
Daniel Brown committed
291
    def getFinesseText(self):
292
293
294
        nodes = self.getNodes()
        
        return 'l {0} {1} {2} {3} {4}'.format(self.name, self.__power, self.__f_offset, self.__phase, nodes[0].name)            
Daniel Brown's avatar
Daniel Brown committed
295
296
297
         
    def getQGraphicsItem(self):
        if self._svgItem == None:
298
            self._svgItem = pykat.gui.graphics.ComponentQGraphicsItem(":/resources/laser.svg",
299
                                                   self,[(65,25,nodes[0])])
Daniel Brown's avatar
Daniel Brown committed
300
301
302
            
        return self._svgItem