commands.py 8.5 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
from __future__ import print_function
Daniel Brown's avatar
Daniel Brown committed
8
9
import numpy
from numpy import min,max
10
11
12
import pykat.external.six as six
if six.PY2:
	import exceptions
Daniel Brown's avatar
Daniel Brown committed
13
14
15
from components import *
from structs import *
from pykat.param import Param, putter
16
import pykat.exceptions as pkex
Daniel Brown's avatar
Daniel Brown committed
17
from collections import namedtuple
18
from pykat.optics.gaussian_beams import beam_param
Daniel Brown's avatar
Daniel Brown committed
19
20

class Command(object):
21
22
23
24
25
    __metaclass__ = abc.ABCMeta
    
    def __init__(self, name):
        self.tag = None
        self.__removed = False
26
        self.__name = name.strip("*")
27
        
Daniel Brown's avatar
Daniel Brown committed
28
29
30
31
32
33
34
35
36
37
38
39
40
41
    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

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

    def getFinesseText(self):
62
        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
63
64
65
66

class gauss(object):
    @staticmethod
    def parseFinesseText(text, kat):
67
        
68
        values = text.split()
69
        if not values[0].startswith("gauss") or (len(values) != 6 and len(values) != 8):
70
            raise pkex.BasePyKatException("'{0}' not a valid Finesse gauss command".format(text))        
71
        
72
73
74
75
        name = values[1]
        component = values[2]
        node = values[3]
        
Daniel Brown's avatar
Daniel Brown committed
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
        # 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))        
        
91
        if not values[0].endswith("*"):
92
            if len(values) == 6:
93
                gp = beam_param(kat.lambda0, w0=values[-2], z=values[-1])
94
            elif len(values) == 8:
95
96
                gpx = beam_param(kat.lambda0, w0=values[-4], z=values[-3])
                gpy = beam_param(kat.lambda0, w0=values[-2], z=values[-1])
97
98
        elif values[0].endswith("*"):
            if len(values) == 6:
99
                gp = beam_param(kat.lambda0, z=values[-2], zr=values[-1])
100
            elif len(values) == 8:
101
102
                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
103
        elif values[0].endswith("**"):
104
            if len(values) == 6:
105
                gp = beam_param(kat.lambda0, w=values[-2], rc=values[-1])
106
            elif len(values) == 8:
107
108
                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
109
110
111
        else:
            raise pkex.BasePyKatException("Unexpected ending to gauss command '{0}'".format(text))
            
Daniel Brown's avatar
Daniel Brown committed
112
113
114
115
        if len(values) == 6:
            kat.nodes[node].setGauss(kat.components[component], gp)
        else:
            kat.nodes[node].setGauss(kat.components[component], gpx, gpy)
116
            
Daniel Brown's avatar
Daniel Brown committed
117
class tf(Command):
118
    fQ = namedtuple('fQ', ['f', 'Q'])
Daniel Brown's avatar
Daniel Brown committed
119
120
    
    def __init__(self, name, poles, zeros):
121
        Command.__init__(self, name)
Daniel Brown's avatar
Daniel Brown committed
122
123
        pass
      
Daniel Brown's avatar
Daniel Brown committed
124
class xaxis(Command):
125
126
127
128
129
    """
    The xaxis object is a unique object to each pykat.finesse.kat instance. It provides
    and interface to the xaxis command in FINESSE.
    """
    
130
    def __init__(self, scale, limits, param, steps, comp=None, axis_type="xaxis"):
131
132
133
134
135
136
137
138
139
        """
        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.
        """
140
        Command.__init__(self, axis_type)
141
        
Daniel Brown's avatar
Daniel Brown committed
142
143
144
145
146
147
        self._axis_type = axis_type

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

        if scale == "lin":
148
            scale = Scale.linear
Daniel Brown's avatar
Daniel Brown committed
149
150
151
152
        elif scale == "log":
            scale = Scale.logarithmic
        elif isinstance(scale, str):
            # else we have a string but not a recognisable one
153
            raise pkex.BasePyKatException("scale argument '{0}' is not valid, must be 'lin' or 'log'".format(scale))
Daniel Brown's avatar
Daniel Brown committed
154
155

        if scale != Scale.linear and scale != Scale.logarithmic:
156
            raise pkex.BasePyKatException("scale is not Scale.linear or Scale.logarithmic")
Daniel Brown's avatar
Daniel Brown committed
157
158
159
160

        self.scale = scale

        if numpy.size(limits) != 2 :
161
            raise pkex.BasePyKatException("limits input should be a 2x1 vector of limits for the xaxis")
Daniel Brown's avatar
Daniel Brown committed
162
163
164
165

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

        if steps <= 0 :
166
            raise pkex.BasePyKatException("steps value should be > 0")
Daniel Brown's avatar
Daniel Brown committed
167
168
169
170
171

        self.steps = int(steps)

        if isinstance(param, str):
            self.__param = param
172
173
174
175
            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
176
        elif not isinstance(param, Param) :
177
            raise pkex.BasePyKatException("param argument is not of type Param")
Daniel Brown's avatar
Daniel Brown committed
178
179
        else:
            self.__param = param
180
            self.__comp = param._owner()
Daniel Brown's avatar
Daniel Brown committed
181

182
183
184
185
    @property
    def param(self): return self.__param
    @param.setter
    def param(self, value):
186
187
188
189
190
191
        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
192
193
    @staticmethod
    def parseFinesseText(text):
194
        values = text.split()
Daniel Brown's avatar
Daniel Brown committed
195
196

        if values[0] != "xaxis" and values[0] != "xaxis*":
197
            raise pkex.BasePyKatException("'{0}' not a valid Finesse xaxis command".format(text))
Daniel Brown's avatar
Daniel Brown committed
198
199
200
201
202
203

        axis_type = values[0]

        values.pop(0) # remove initial value

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

206
        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
207
208

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

class x2axis(xaxis):
221
222
    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
223
224
225
226
227
        self.x = putter("x2")
        self.mx = putter("mx2")

    @staticmethod
    def parseFinesseText(text):
228
        values = text.split()
Daniel Brown's avatar
Daniel Brown committed
229
230

        if values[0] != "x2axis" and values[0] != "x2axis*":
231
            raise pkex.BasePyKatException("'{0}' not a valid Finesse xaxis command".format(text))
Daniel Brown's avatar
Daniel Brown committed
232
233
234
235
236
237

        axis_type = values[0]

        values.pop(0) # remove initial value

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

240
        return x2axis(values[2], [values[3], values[4]], values[1], values[5], comp=values[0],axis_type=axis_type)
241
242
243
244


class lock(Command):
    pass