commands.py 8.65 KB
Newer Older
Daniel Brown's avatar
Daniel Brown committed
1
2
3
4
5
6
# -*- coding: utf-8 -*-
"""
Created on Mon Jan 28 11:58:09 2013

@author: Daniel
"""
7
8
9
10
11
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

Daniel Brown's avatar
Daniel Brown committed
12
13
import numpy
from numpy import min,max
14
15
16
17
18
19
import pykat.external.six as six
if six.PY2:
	import exceptions
from pykat.components import *
from pykat.structs import *

Daniel Brown's avatar
Daniel Brown committed
20
from pykat.param import Param, putter
21
import pykat.exceptions as pkex
Daniel Brown's avatar
Daniel Brown committed
22
from collections import namedtuple
23
from pykat.optics.gaussian_beams import beam_param
Daniel Brown's avatar
Daniel Brown committed
24
25

class Command(object):
26
27
28
29
30
    __metaclass__ = abc.ABCMeta
    
    def __init__(self, name):
        self.tag = None
        self.__removed = False
31
        self.__name = name.strip("*")
32
        
Daniel Brown's avatar
Daniel Brown committed
33
34
35
36
37
38
39
40
41
42
43
44
45
46
    def getFinesseText(self):
        """ Base class for individual finesse optical components """
        raise NotImplementedError("This function is not implemented")

    @staticmethod
    def parseFinesseText(text):
        raise NotImplementedError("This function is not implemented")

    def _on_kat_add(self, kat):
        """
        Called when this component has been added to a kat object
        """
        self._kat = kat

47
48
49
50
    def remove(self):
        self._kat.remove(self)
        self.__removed = True
    
51
52
53
    @property
    def name(self): return self.__name
    
54
55
56
    @property
    def removed(self): return self.__removed
    
Daniel Brown's avatar
Daniel Brown committed
57
58
class cavity(Command):
    def __init__(self, name, c1, n1, c2, n2):
59
        Command.__init__(self, name)
60
        
Daniel Brown's avatar
Daniel Brown committed
61
62
63
64
65
66
        self.__c1 = c1
        self.__c2 = c2
        self.__n1 = n1
        self.__n2 = n2

    def getFinesseText(self):
67
        return 'cav {0} {1} {2} {3} {4}'.format(self.name, self.__c1, self.__n1, self.__c2, self.__n2);
Daniel Brown's avatar
Daniel Brown committed
68
69
70
71

class gauss(object):
    @staticmethod
    def parseFinesseText(text, kat):
72
        
73
        values = text.split()
74
        if not values[0].startswith("gauss") or (len(values) != 6 and len(values) != 8):
75
            raise pkex.BasePyKatException("'{0}' not a valid Finesse gauss command".format(text))        
76
        
77
78
79
80
        name = values[1]
        component = values[2]
        node = values[3]
        
Daniel Brown's avatar
Daniel Brown committed
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
        # setting the name of the gauss parameter is slightly convoluted
        # as we don't explicitly store gauss paramters as an object, they
        # are simply just complex numbers stored at each node. To fix this
        # the name is stored in the NodeGaussSetter object for each component
        
        if component in kat.components:
            c = kat.components[component]
            if hasattr(c, node):
                ns = getattr(c, node)
                ns.name = name
            else:
                raise pkex.BasePyKatException("Component '{0}' is not attached to node {1}".format(component, node))        
        else:
            raise pkex.BasePyKatException("Component '{0}' was not found".format(component))        
        
96
        if not values[0].endswith("*"):
97
            if len(values) == 6:
98
                gp = beam_param(kat.lambda0, w0=values[-2], z=values[-1])
99
            elif len(values) == 8:
100
101
                gpx = beam_param(kat.lambda0, w0=values[-4], z=values[-3])
                gpy = beam_param(kat.lambda0, w0=values[-2], z=values[-1])
102
103
        elif values[0].endswith("*"):
            if len(values) == 6:
104
                gp = beam_param(kat.lambda0, z=values[-2], zr=values[-1])
105
            elif len(values) == 8:
106
107
                gpx = beam_param(kat.lambda0, z=values[-4], zr=values[-3])
                gpy = beam_param(kat.lambda0, z=values[-2], zr=values[-1])
Daniel Brown's avatar
Daniel Brown committed
108
        elif values[0].endswith("**"):
109
            if len(values) == 6:
110
                gp = beam_param(kat.lambda0, w=values[-2], rc=values[-1])
111
            elif len(values) == 8:
112
113
                gpx = beam_param(kat.lambda0, w=values[-4], rc=values[-3])
                gpy = beam_param(kat.lambda0, w=values[-2], rc=values[-1])
Daniel Brown's avatar
Daniel Brown committed
114
115
116
        else:
            raise pkex.BasePyKatException("Unexpected ending to gauss command '{0}'".format(text))
            
Daniel Brown's avatar
Daniel Brown committed
117
118
119
120
        if len(values) == 6:
            kat.nodes[node].setGauss(kat.components[component], gp)
        else:
            kat.nodes[node].setGauss(kat.components[component], gpx, gpy)
121
            
Daniel Brown's avatar
Daniel Brown committed
122
class tf(Command):
123
    fQ = namedtuple('fQ', ['f', 'Q'])
Daniel Brown's avatar
Daniel Brown committed
124
125
    
    def __init__(self, name, poles, zeros):
126
        Command.__init__(self, name)
Daniel Brown's avatar
Daniel Brown committed
127
128
        pass
      
Daniel Brown's avatar
Daniel Brown committed
129
class xaxis(Command):
130
131
132
133
134
    """
    The xaxis object is a unique object to each pykat.finesse.kat instance. It provides
    and interface to the xaxis command in FINESSE.
    """
    
135
    def __init__(self, scale, limits, param, steps, comp=None, axis_type="xaxis"):
136
137
138
139
140
141
142
143
144
        """
        Typical usage:
            xaxis(["lin" or "log"], [upper, lower], param, steps)
            
        param must be an object of the type pykat.param.Param whose
        isPutable() member returns true.
        
        steps is the number of points to compute between upper and lower limits.
        """
145
        Command.__init__(self, axis_type)
146
        
Daniel Brown's avatar
Daniel Brown committed
147
148
149
150
151
152
        self._axis_type = axis_type

        self.x = putter("x1")
        self.mx = putter("mx1")

        if scale == "lin":
153
            scale = Scale.linear
Daniel Brown's avatar
Daniel Brown committed
154
155
        elif scale == "log":
            scale = Scale.logarithmic
156
        elif isinstance(scale, six.string_types):
Daniel Brown's avatar
Daniel Brown committed
157
            # else we have a string but not a recognisable one
158
            raise pkex.BasePyKatException("scale argument '{0}' is not valid, must be 'lin' or 'log'".format(scale))
Daniel Brown's avatar
Daniel Brown committed
159
160

        if scale != Scale.linear and scale != Scale.logarithmic:
161
            raise pkex.BasePyKatException("scale is not Scale.linear or Scale.logarithmic")
Daniel Brown's avatar
Daniel Brown committed
162
163
164
165

        self.scale = scale

        if numpy.size(limits) != 2 :
166
            raise pkex.BasePyKatException("limits input should be a 2x1 vector of limits for the xaxis")
Daniel Brown's avatar
Daniel Brown committed
167
168
169

        self.limits = numpy.array(SIfloat(limits)).astype(float)

170
        if int(steps) <= 0 :
171
            raise pkex.BasePyKatException("steps value should be > 0")
Daniel Brown's avatar
Daniel Brown committed
172
173
174

        self.steps = int(steps)

175
        if isinstance(param, six.string_types):
Daniel Brown's avatar
Daniel Brown committed
176
            self.__param = param
177
178
179
180
            if comp == None:
                raise pkex.BasePyKatException("If parameter is set with a string, the comp argument must set the component name")
                
            self.__comp = comp
Daniel Brown's avatar
Daniel Brown committed
181
        elif not isinstance(param, Param) :
182
            raise pkex.BasePyKatException("param argument is not of type Param")
Daniel Brown's avatar
Daniel Brown committed
183
184
        else:
            self.__param = param
185
            self.__comp = param._owner()
Daniel Brown's avatar
Daniel Brown committed
186

187
188
189
190
    @property
    def param(self): return self.__param
    @param.setter
    def param(self, value):
191
192
193
194
195
196
        if not isinstance(value, Param):
            raise pkex.BasePyKatException("param argument is not of type Param")
        else:
            self.__param = value
            self.__comp = value._owner()
            
Daniel Brown's avatar
Daniel Brown committed
197
198
    @staticmethod
    def parseFinesseText(text):
199
        values = text.split()
Daniel Brown's avatar
Daniel Brown committed
200
201

        if values[0] != "xaxis" and values[0] != "xaxis*":
202
            raise pkex.BasePyKatException("'{0}' not a valid Finesse xaxis command".format(text))
Daniel Brown's avatar
Daniel Brown committed
203
204
205
206
207
208

        axis_type = values[0]

        values.pop(0) # remove initial value

        if len(values) != 6:
209
            raise pkex.BasePyKatException("xaxis Finesse code format incorrect '{0}'".format(text))
Daniel Brown's avatar
Daniel Brown committed
210

211
        return xaxis(values[2], [values[3], values[4]], values[1], values[5], comp=values[0], axis_type=axis_type)
Daniel Brown's avatar
Daniel Brown committed
212
213

    def getFinesseText(self):
214
215
216
        if(self._kat.noxaxis):
            return '# noaxis is true, switching xaxis off'
            
Daniel Brown's avatar
Daniel Brown committed
217
        # store either the component name of the string provided
218
        comp_name = self.__comp.name if hasattr(self.__comp, "name") else self.__comp
Daniel Brown's avatar
Daniel Brown committed
219
        param_name = self.__param.name if isinstance(self.__param, Param) else self.__param
220
        
221
        return '{axis_type} {0} {1} {2} {3:.16g} {4:.16g} {5}'.format(
Daniel Brown's avatar
Daniel Brown committed
222
223
224
225
                comp_name, param_name, self.scale,
                min(self.limits), max(self.limits), self.steps, axis_type=self._axis_type);

class x2axis(xaxis):
226
227
    def __init__(self, scale, limits, param, steps, comp=None, axis_type="x2axis"):
        xaxis.__init__(self, scale, limits, param, steps, comp=comp, axis_type=axis_type)
Daniel Brown's avatar
Daniel Brown committed
228
229
230
231
232
        self.x = putter("x2")
        self.mx = putter("mx2")

    @staticmethod
    def parseFinesseText(text):
233
        values = text.split()
Daniel Brown's avatar
Daniel Brown committed
234
235

        if values[0] != "x2axis" and values[0] != "x2axis*":
236
            raise pkex.BasePyKatException("'{0}' not a valid Finesse xaxis command".format(text))
Daniel Brown's avatar
Daniel Brown committed
237
238
239
240
241
242

        axis_type = values[0]

        values.pop(0) # remove initial value

        if len(values) != 6:
243
            raise pkex.BasePyKatException("xaxis Finesse code format incorrect '{0}'".format(text))
Daniel Brown's avatar
Daniel Brown committed
244

245
        return x2axis(values[2], [values[3], values[4]], values[1], values[5], comp=values[0],axis_type=axis_type)
246
247
248
249


class lock(Command):
    pass