Commit 223ef74d authored by Daniel Brown's avatar Daniel Brown
Browse files

Large amount of changes to the param object which now include being able to...

Large amount of changes to the param object which now include being able to put and set parameters and commands. Also adding the modulator component.
parent 056dd5ed
class Param(float):
def __new__(self,name,value):
return float.__new__(self,value)
import abc
import pykat.exceptions as pkex
def __init__(self,name,value):
self.__name = name
class puttable(object):
"""
Objects that inherit this should be able to have something `put` to it.
Essentially this means you could write Finesse commands like
name = property(lambda self: self.__name)
put this parameter value
"""
__metaclass__ = abc.ABCMeta
def __init__(self, component_name, parameter_name):
self._parameter_name = parameter_name
self._component_name = component_name
self._putter = None
def put(self, var):
if not isinstance(var, putter):
raise pkex.BasePyKatException("var was not something that can be `put` as a value")
if self._putter != None:
self._putter.put_count -= 1
self._putter = var
self._putter.put_count += 1
def getPutFinesseText(self):
rtn = []
# if something is being put to this
if self._putter != None:
rtn.append("put {comp} {param} ${value}".format(comp=self._component_name, param=self._parameter_name, value=self._putter.put_name()))
return rtn
class putter(object):
"""
If an object can be put to something that is puttable it should inherit this
object.
"""
__metaclass__ = abc.ABCMeta
def __init__(self, put_name):
self._put_name = put_name
self.put_count = 0
def put_name(self): return self._put_name
class Beer(object):
def __init__(self, temp):
self.__T = temp
class Param(puttable, putter):
def __init__(self, name, owner, value):
self._name = name
self._owner = owner
self._value = value
putter.__init__(self,"var_{0}_{1}".format(owner.name, name))
puttable.__init__(self, owner.name, name)
@property
def temp(self):
return Param('Beer Temperature', self.__T)
def name(self): return self._name
@property
def value(self): return self._value
@value.setter
def value(self, value):
self._value = value
def __float__(self): return self.value
def getFinesseText(self):
rtn = []
rtn.extend(self.getPutFinesseText())
# if this parameter is being put somewhere then we need to
# set it as a variable
if self.put_count > 0:
rtn.append("set {put_name} {comp} {param}".format(put_name=self.put_name(), comp=self._owner.name, param=self.name))
return rtn
def __mul__(self, a):
return float(self) * a
@temp.setter
def temp(self,value):
self.__T = float(value)
def __imul__(self, a):
return self.value * float(a)
__rmul__ = __mul__
b = Beer(100)
def __add__(self, a):
return self.value + flota(a)
print b.temp.name, b.temp.__class__
def __iadd__(self, a):
return self.value + float(a)
__radd__ = __add__
def __sub__(self, a):
return self.value - float(a)
def __isub__(self, a):
return self.value - float(a)
__rsub__ = __sub__
def __div__(self, a):
return self.value / float(a)
def __idiv__(self, a):
return self.value / complex(a)
def __pow__(self, q):
return self.value**q
def __neg__(self):
return -self.value
def __eq__(self, q):
return float(q) == self.value
class Beer(object):
def __init__(self, temp, name):
self._name = name
self._T = Param('T', self, temp)
@property
def name(self): return self._name
@property
def T(self): return self._T
print b.temp * 4.5
@T.setter
def T(self,value): self._T.value = float(value)
print b.temp.name, b.temp.__class__
b.temp = 101
b = Beer(1,"b")
c = Beer(2,"c")
print b.temp.name, b.temp.__class__
c.T.put(b.T)
print b.temp
\ No newline at end of file
print c.T.getFinesseText()
print b.T.getFinesseText()
\ No newline at end of file
from pykat import finesse
from pykat.detectors import *
from pykat.components import *
from pykat.commands import *
from pykat.structs import *
import numpy as np
import pylab as pl
code = """
l l1 1 0 0 n1
s s1 10 1 n1 n2
mod eom 10 0.1 1 am 0 n2 n3
"""
kat = finesse.kat()
kat.parseCommands(code)
kat.add(photodiode('pd_ref','n3', num_demods=1, demods=[10,0]))
kat.add(xaxis("lin", [0, 1000], "pd_ref", "f1", 100))
out = kat.run(printout=0, printerr=0)
pl.figure()
pl.plot(out.x, out["pd_ref"])
pl.xlabel(out.xlabel)
pl.ylabel("Intensity [W]")
pl.legend(out.ylabels)
pl.show()
......@@ -9,6 +9,7 @@ from numpy import min,max
import exceptions
from components import *
from structs import *
from pykat.param import Param, putter
class Command(object):
def __init__(self):
......@@ -47,39 +48,14 @@ class gauss(object):
if not values[0].startswith("gauss"):
raise exceptions.RuntimeError("'{0}' not a valid Finesse gauss command".format(text))
class attr():
@staticmethod
def parseFinesseText(text, kat):
values = text.split(" ")
if values[0] != "attr":
raise exceptions.RuntimeError("'{0}' not a valid Finesse attr command".format(text))
values.pop(0) # remove initial value
if len(values) < 3:
raise exceptions.RuntimeError("attr Finesse code format incorrect '{0}'".format(text))
comp = None
comp_name = values[0]
values.pop(0)
for c in kat.getComponents():
if c.name == comp_name:
comp = c
break
if comp == None:
raise
# can list multiple attributes per command
class xaxis(Command):
def __init__(self, scale, limits, comp, param, steps, axis_type="xaxis"):
self._axis_type = axis_type
self.x = putter("x1")
self.mx = putter("mx1")
if scale == "lin":
scale = Scale.linear
elif scale == "log":
......@@ -146,6 +122,8 @@ class xaxis(Command):
class x2axis(xaxis):
def __init__(self, scale, limits, comp, param, steps):
xaxis.__init__(self, scale, limits, comp, param, steps, axis_type="x2axis")
self.x = putter("x2")
self.mx = putter("mx2")
@staticmethod
def parseFinesseText(text):
......
......@@ -15,6 +15,7 @@ import pykat.gui.resources
import pykat.gui.graphics
from pykat.gui.graphics import *
from pykat.SIfloat import *
from pykat.param import Param, AttrParam
next_component_id = 1
......@@ -58,6 +59,7 @@ class Component(object):
self._requested_node_names = []
self._kat = None
self.tag = None
self._params = []
# store a unique ID for this component
global next_component_id
......@@ -70,6 +72,9 @@ class Component(object):
cls = type(self)
self.__class__ = type(cls.__name__, (cls,), {})
def _register_param(self, param):
self._params.append(param)
def _on_kat_add(self, kat):
"""
Called when this component has been added to a kat object.
......@@ -145,87 +150,66 @@ class Component(object):
def __str__(self): return self.name
class Param(float):
def __new__(self,name,value):
return float.__new__(self,SIfloat(value))
def __init__(self,name,value):
self.__name = name
name = property(lambda self: self.__name)
class AbstractMirrorComponent(Component):
__metaclass__ = abc.ABCMeta
def __init__(self, name, R=0, T=0, phi=0, Rcx=0, Rcy=0, xbeta=0, ybeta=0, mass=0, r_ap=0):
super(AbstractMirrorComponent, self).__init__(name)
self.__R = SIfloat(R)
self.__T = SIfloat(T)
self.__phi = SIfloat(phi)
self.__Rcx = SIfloat(Rcx)
self.__Rcy = SIfloat(Rcy)
self.__xbeta = SIfloat(xbeta)
self.__ybeta = SIfloat(ybeta)
self.__mass = SIfloat(mass)
self.__r_ap = SIfloat(r_ap)
def getAttributeText(self):
rtn = []
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))
if self.mass != 0: rtn.append("attr {0} mass {1}".format(self.name,self.__mass))
if self.r_ap != 0: rtn.append("attr {0} r_ap {1}".format(self.name,self.__r_ap))
return rtn
self.__R = Param("R", self, SIfloat(R))
self.__T = Param("T", self, SIfloat(T))
self.__phi = Param("phi", self, SIfloat(phi))
self.__Rcx = AttrParam("Rcx", self, SIfloat(Rcx))
self.__Rcy = AttrParam("Rcy", self, SIfloat(Rcy))
self.__xbeta = AttrParam("xbeta", self, SIfloat(xbeta))
self.__ybeta = AttrParam("ybeta", self, SIfloat(ybeta))
self.__mass = AttrParam("mass", self, SIfloat(mass))
self.__r_ap = AttrParam("r_ap", self, SIfloat(r_ap))
@property
def r_ap(self): return Param('r_ap', self.__r_ap)
def r_ap(self): return self.__r_ap
@r_ap.setter
def r_ap(self,value): self.__aperture = SIfloat(value)
def r_ap(self,value): self.__r_ap.value = SIfloat(value)
@property
def mass(self): return Param('mass', self.__mass)
def mass(self): return self.__mass
@mass.setter
def mass(self,value): self.__mass = SIfloat(value)
def mass(self,value): self.__mass.value = SIfloat(value)
@property
def R(self): return Param('R', self.__R)
def R(self): return self.__R
@R.setter
def R(self,value): self.__R = SIfloat(value)
def R(self,value): self.__R.value = SIfloat(value)
@property
def T(self): return Param('T', self.__T)
def T(self): return self.__T
@T.setter
def T(self,value): self.__T = SIfloat(value)
def T(self,value): self.__T.value = SIfloat(value)
@property
def phi(self): return Param('phi', self.__phi)
def phi(self): return self.__phi
@phi.setter
def phi(self,value): self.__phi = SIfloat(value)
def phi(self,value): self.__phi.value = SIfloat(value)
@property
def Rcx(self): return Param('Rcx', self.__Rcx)
def Rcx(self): return self.__Rcx
@Rcx.setter
def Rcx(self,value): self.__Rcx = SIfloat(value)
def Rcx(self,value): self.__Rcx.value = SIfloat(value)
@property
def Rcy(self): return Param('Rcy', self.__Rcy)
def Rcy(self): return self.__Rcy
@Rcy.setter
def Rcy(self,value): self.__Rcy = SIfloat(value)
def Rcy(self,value): self.__Rcy.value = SIfloat(value)
@property
def xbeta(self): return Param('xbeta', self.__xbeta)
def xbeta(self): return self.__xbeta
@xbeta.setter
def xbeta(self,value): self.__xbeta = SIfloat(value)
def xbeta(self,value): self.__xbeta.value = SIfloat(value)
@property
def ybeta(self): return Param('ybeta', self.__ybeta)
def ybeta(self): return self.__ybeta
@ybeta.setter
def ybeta(self,value): self.__ybeta = SIfloat(value)
def ybeta(self,value): self.__ybeta.value = SIfloat(value)
@property
def Rc(self):
......@@ -236,8 +220,8 @@ class AbstractMirrorComponent(Component):
@Rc.setter
def Rc(self,value):
self.Rcx = SIfloat(value)
self.Rcy = SIfloat(value)
self.Rcx.value = SIfloat(value)
self.Rcy.value = SIfloat(value)
class mirror(AbstractMirrorComponent):
def __init__(self,name,node1,node2,R=0,T=0,phi=0,Rcx=0,Rcy=0,xbeta=0,ybeta=0,mass=0, r_ap=0):
......@@ -271,10 +255,11 @@ class mirror(AbstractMirrorComponent):
rtn = []
rtn.append('m {0} {1} {2} {3} {4} {5}'.format(
self.name, self.R, self.T, self.phi,
self.name, self.R.value, self.T.value, self.phi.value,
self.nodes[0].name, self.nodes[1].name))
rtn.extend(super(mirror, self).getAttributeText())
for p in self._params:
rtn.extend(p.getFinesseText())
return rtn
......@@ -293,12 +278,12 @@ class beamSplitter(AbstractMirrorComponent):
self._requested_node_names.append(node3)
self._requested_node_names.append(node4)
self.__alpha = SIfloat(alpha)
self.__alpha = AttrParam("alpha", self, SIfloat(alpha))
@property
def alpha(self): return Param('alpha', self.__alpha)
def alpha(self): return self.__alpha
@alpha.setter
def alpha(self,value): self.__alpha = SIfloat(value)
def alpha(self,value): self.__alpha.value = SIfloat(value)
@staticmethod
def parseFinesseText(text):
......@@ -325,12 +310,13 @@ class beamSplitter(AbstractMirrorComponent):
rtn = []
rtn.append('bs {0} {1} {2} {3} {4} {5} {6} {7} {8}'.format(
self.name, self.R, self.T, self.phi,
self.alpha, self.nodes[0].name,
self.name, self.R.value, self.T.value, self.phi.value,
self.alpha.value, self.nodes[0].name,
self.nodes[1].name, self.nodes[2].name,
self.nodes[3].name))
rtn.extend(super(beamSplitter, self).getAttributeText())
for p in self._params:
rtn.extend(p.getFinesseText())
return rtn
......@@ -348,17 +334,17 @@ class space(Component):
self._requested_node_names.append(node1)
self._requested_node_names.append(node2)
self._QItem = None
self.__L = SIfloat(L)
self.__n = SIfloat(n)
self.__L = Param("L", self, SIfloat(L))
self.__n = Param("n", self, SIfloat(n))
@property
def L(self): return Param('L', self.__L)
def L(self): return self.__L
@L.setter
def L(self,value): self.__L = SIfloat(value)
def L(self,value): self.__L,value = SIfloat(value)
@property
def n(self): return Param('n', self.__n)
def n(self): return self.__n
@n.setter
def n(self,value): self.__n = SIfloat(value)
def n(self,value): self.__n.value = SIfloat(value)
@staticmethod
def parseFinesseText(text):
......@@ -377,10 +363,17 @@ class space(Component):
raise exceptions.RuntimeError("Space Finesse code format incorrect '{0}'".format(text))
def getFinesseText(self):
rtn = []
if self.__n == 1:
return 's {0} {1} {2} {3}'.format(self.name, self.__L, self.nodes[0].name, self.nodes[1].name)
rtn.append('s {0} {1} {2} {3}'.format(self.name, self.__L.value, self.nodes[0].name, self.nodes[1].name))
else:
return 's {0} {1} {2} {3} {4}'.format(self.name, self.__L, self.__n, self.nodes[0].name, self.nodes[1].name)
rtn.append('s {0} {1} {2} {3} {4}'.format(self.name, self.__L.value, self.__n.value, self.nodes[0].name, self.nodes[1].name))
for p in self._params:
rtn.extend(p.getFinesseText())
return rtn
def getQGraphicsItem(self):
if self._QItem == None:
......@@ -411,13 +404,13 @@ class grating(Component):
raise exceptions.RuntimeError("Grating must have between 2 and 4 ports")
self.__n = n
self.__d = SIfloat(d)
self.__eta_0 = SIfloat(eta_0)
self.__eta_1 = SIfloat(eta_1)
self.__eta_2 = SIfloat(eta_2)
self.__eta_3 = SIfloat(eta_3)
self.__rho_0 = SIfloat(rho_0)
self.__alpha = SIfloat(alpha)
self.__d = Param("d", self, SIfloat(d))
self.__eta_0 = AttrParam("eta_0", self, SIfloat(eta_0))
self.__eta_1 = AttrParam("eta_1", self, SIfloat(eta_1))
self.__eta_2 = AttrParam("eta_2", self, SIfloat(eta_2))
self.__eta_3 = AttrParam("eta_3", self, SIfloat(eta_3))
self.__rho_0 = AttrParam("rho_0", self, SIfloat(rho_0))
self.__alpha = AttrParam("alpha", self, SIfloat(alpha))
@property
def n(self): return Param('n', self.__n)
......@@ -429,39 +422,39 @@ class grating(Component):
self.__n = value
@property
def d(self): return Param('d', self.__d)
def d(self): return self.__d
@d.setter
def d(self, value): self.__d = SIfloat(value)
def d(self, value): self.__d.value = SIfloat(value)
@property
def eta_0(self): return Param('eta_0', self.__eta_0)
def eta_0(self): return self.__eta_0
@eta_0.setter
def eta_0(self, value): self.__eta_0 = SIfloat(value)
def eta_0(self, value): self.__eta_0.value = SIfloat(value)
@property
def eta_1(self): return Param('eta_1', self.__eta_1)
def eta_1(self): return self.__eta_1
@eta_1.setter
def eta_1(self, value): self.__eta_1 = SIfloat(value)
def eta_1(self, value): self.__eta_1.value = SIfloat(value)
@property
def eta_2(self): return Param('eta_2', self.__eta_2)
def eta_2(self): return self.__eta_2
@eta_2.setter
def eta_2(self, value): self.__eta_2 = SIfloat(value)
def eta_2(self, value): self.__eta_2.value = SIfloat(value)
@property
def eta_3(self): return Param('eta_3', self.__eta_3)
def eta_3(self): return self.__eta_3
@eta_3.setter
def eta_3(self, value): self.__eta_3 = SIfloat(value)
def eta_3(self, value): self.__eta_3.value = SIfloat(value)
@property
def rho_0(self): return Param('rho_0', self.__rho_0)
def rho_0(self): return self.__rho_0
@rho_0.setter
def rho_0(self, value): self.__rho_0 = SIfloat(value)
def rho_0(self, value): self.__rho_0.value = SIfloat(value)
@property
def alpha(self): return Param('alpha', self.__alpha)
def alpha(self): return self.__alpha
@alpha.setter
def alpha(self, value): self.__alpha = SIfloat(value)
def alpha(self, value): self.__alpha.value = SIfloat(value)
@staticmethod
def parseFinesseText(text):
......@@ -500,19 +493,14 @@ class grating(Component):
rtn = []
if self.__n == 2:
rtn.append('gr{0} {1} {2} {3} {4}'.format(self.__n, self.name, self.__d, self.nodes[0].name, self.nodes[1].name))
rtn.append('gr{0} {1} {2} {3} {4}'.format(self.__n, self.name, self.__d.value, self.nodes[0].name, self.nodes[1].name))
elif self.__n == 3:
rtn.append('gr{0} {1} {2} {3} {4} {5}'.format(self.__n, self.name, self.__d, self.nodes[0].name, self.nodes[1].name, self.nodes[2].name))
rtn.append('gr{0} {1} {2} {3} {4} {5}'.format(self.__n, self.name, self.__d.value, self.nodes[0].name, self.nodes[1].name, self.nodes[2].name))
else:
rtn.append('gr{0} {1} {2} {3} {4} {5} {6}'.format(self.__n, self.name, self.__d, self.nodes[0].name, self.nodes[1].name, self.nodes[2].name, self.nodes[3].name))
rtn.append('gr{0} {1} {2} {3} {4} {5} {6}'.format(self.__n, self.name, self.__d.value, self.nodes[0].name, self.nodes[1].name, self.nodes[2].name, self.nodes[3].name))
if self.eta_0 != 0: rtn.append("attr {0} eta_0 {1}".format(self.name,self.__eta_0))
if self.eta_1 != 0: rtn.append("attr {0} eta_1 {1}".format(self.name,self.__eta_1))
if self.eta_2 != 0: rtn.append("attr {0} eta_2 {1}".format(self.name,self.__eta_2))
if self.eta_3 != 0: rtn.append("attr {0} eta_3 {1}".format(self.name,self.__eta_3))
if self.rho_0 != 0: rtn.append("attr {0} rho_0 {1}".format(self.name,self.__rho_0))
if self.alpha != 0: rtn.append("attr {0} alpha {1}".format(self.name,self.__alpha))
# TODO: implement Rcx, Rcy, Rc
for p in self._params:
rtn.extend(p.getFinesseText())