Skip to content
Snippets Groups Projects
Commit 8eee71ee authored by Andreas Freise's avatar Andreas Freise
Browse files

Merge branch 'master' of gitlab.aei.uni-hannover.de:finesse/pykat

parents 17bcd615 36b80188
No related branches found
No related tags found
No related merge requests found
...@@ -3,7 +3,7 @@ from __future__ import division ...@@ -3,7 +3,7 @@ from __future__ import division
from __future__ import print_function from __future__ import print_function
from __future__ import unicode_literals from __future__ import unicode_literals
__version__ = "1.0.8" __version__ = "1.0.11"
# This flag is used to switch on the gui features in pkat at import time # This flag is used to switch on the gui features in pkat at import time
USE_GUI = False USE_GUI = False
......
...@@ -34,6 +34,22 @@ class Command(object): ...@@ -34,6 +34,22 @@ class Command(object):
self.tag = None self.tag = None
self.__removed = False self.__removed = False
self.__name = name.strip("*") self.__name = name.strip("*")
self._putters = []
def __deepcopy__(self, memo):
"""
When deep copying a kat object we need to take into account
the instance specific properties.
"""
cls = self.__class__
result = cls.__new__(cls)
result.__dict__ = copy.deepcopy(self.__dict__, memo)
for _ in result._putters:
_._updateOwner(result)
return result
def getFinesseText(self): def getFinesseText(self):
""" Base class for individual finesse optical components """ """ Base class for individual finesse optical components """
...@@ -49,9 +65,29 @@ class Command(object): ...@@ -49,9 +65,29 @@ class Command(object):
""" """
self._kat = kat self._kat = kat
for _ in self._putters:
kat.registerVariable(_.name, _)
def _on_kat_remove(self):
self.__removed = True
for i in range(len(self._putters)):
_ = self._putters[i]
self._kat.unregisterVariable(_.name)
_.clearPuts()
for i in range(len(self._putters)):
del self._putters[0]
del self._putters[:]
def remove(self): def remove(self):
if self.__removed:
raise pkex.BasePyKatException("{0} has already been marked as removed".format(self.name))
else:
self._kat.remove(self) self._kat.remove(self)
self.__removed = True
@property @property
def name(self): return self.__name def name(self): return self.__name
...@@ -95,10 +131,15 @@ class func(Command): ...@@ -95,10 +131,15 @@ class func(Command):
self.value = value self.value = value
self.noplot = False self.noplot = False
self.enabled = True
self.output = putter(name, self)
self._putters.append(self.output)
def getFinesseText(self): def getFinesseText(self):
rtn = [] rtn = []
if self.enabled:
if self.noplot: if self.noplot:
rtn.append("noplot " + self.name) rtn.append("noplot " + self.name)
...@@ -120,9 +161,6 @@ class func(Command): ...@@ -120,9 +161,6 @@ class func(Command):
raise pkex.BasePyKatException("'{0}' not a valid Finesse func command".format(line)) raise pkex.BasePyKatException("'{0}' not a valid Finesse func command".format(line))
class lock(Command): class lock(Command):
def __init__(self, name, variable, gain, accuracy, singleLock=False): def __init__(self, name, variable, gain, accuracy, singleLock=False):
Command.__init__(self, name, False) Command.__init__(self, name, False)
...@@ -134,6 +172,10 @@ class lock(Command): ...@@ -134,6 +172,10 @@ class lock(Command):
self.enabled = True self.enabled = True
self.output = putter(name, self)
self._putters.append(self.output)
@staticmethod @staticmethod
def parseFinesseText(line, kat): def parseFinesseText(line, kat):
v = line.split() v = line.split()
...@@ -279,6 +321,77 @@ class gauss(object): ...@@ -279,6 +321,77 @@ class gauss(object):
else: else:
kat.nodes[node].setGauss(kat.components[component], gpx, gpy) kat.nodes[node].setGauss(kat.components[component], gpx, gpy)
# class tf(Command):
#
# class fQ(object):
# def __init__(self, f, Q, tf):
# assert(tf is not None)
# self._tf = tf
# self.__f = Param("f", self, None, canFsig=False, isPutable=True, isPutter=False, isTunable=True)
# self.__Q = Param("Q", self, None, canFsig=False, isPutable=True, isPutter=False, isTunable=True)
#
# def _register_param(self, param):
# self._tf._params.append(param)
#
# @property
# def f(self): return self.__f
# @f.setter
# def f(self,value): self.__f.value = SIfloat(value)
#
# @property
# def Q(self): return self.__Q
# @Q.setter
# def Q(self,value): self.__Q.value = SIfloat(value)
#
# def __init__(self, name):
# Command.__init__(self, name, False)
# self.zeros = []
# self.poles = []
# self.gain = 1
# self.phase = 0
# self._params = []
#
# def addPole(self,f, Q):
# self.poles.append(tf.fQ(SIfloat(f), SIfloat(Q), self))
#
# def addZero(self,f, Q):
# self.zeros.append(tf.fQ(SIfloat(f), SIfloat(Q), self))
#
# @staticmethod
# def parseFinesseText(text):
# values = text.split()
#
# if ((len(values)-4) % 3) != 0:
# raise pkex.BasePyKatException("Transfer function Finesse code format incorrect '{0}'".format(text))
#
# _tf = tf(values[1])
#
# _tf.gain = SIfloat(values[2])
# _tf.phase = SIfloat(values[3])
#
# N = int((len(values)-4) / 3)
#
# for i in range(1,N+1):
# if values[i*3+1] == 'p':
# _tf.addPole(SIfloat(values[i*3+2]), SIfloat(values[i*3+3]))
# elif values[i*3+1] == 'z':
# _tf.addZero(SIfloat(values[i*3+2]), SIfloat(values[i*3+3]))
# else:
# raise pkex.BasePyKatException("Transfer function pole/zero Finesse code format incorrect '{0}'".format(text))
#
# return _tf
#
# def getFinesseText(self):
# rtn = "tf {name} {gain} {phase} ".format(name=self.name,gain=self.gain,phase=self.phase)
#
# for p in self.poles:
# rtn += "p {f} {Q} ".format(f=p.f, Q=p.Q)
#
# for z in self.zeros:
# rtn += "p {f} {Q} ".format(f=z.f, Q=z.Q)
#
# return rtn
class tf(Command): class tf(Command):
class fQ(object): class fQ(object):
...@@ -354,8 +467,11 @@ class xaxis(Command): ...@@ -354,8 +467,11 @@ class xaxis(Command):
self._axis_type = axis_type self._axis_type = axis_type
self.x = putter("x1") self.x = putter("x1", self)
self.mx = putter("mx1") self.mx = putter("mx1", self)
self._putters.append(self.x)
self._putters.append(self.mx)
if scale == "lin": if scale == "lin":
scale = Scale.linear scale = Scale.linear
...@@ -433,8 +549,11 @@ class xaxis(Command): ...@@ -433,8 +549,11 @@ class xaxis(Command):
class x2axis(xaxis): class x2axis(xaxis):
def __init__(self, scale, limits, param, steps, comp=None, axis_type="x2axis"): 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) xaxis.__init__(self, scale, limits, param, steps, comp=comp, axis_type=axis_type)
self.x = putter("x2") self.x = putter("x2", self)
self.mx = putter("mx2") self.mx = putter("mx2", self)
self._putters.append(self.x)
self._putters.append(self.mx)
@staticmethod @staticmethod
def parseFinesseText(text): def parseFinesseText(text):
......
...@@ -84,7 +84,7 @@ class NodeGaussSetter(object): ...@@ -84,7 +84,7 @@ class NodeGaussSetter(object):
def qy(self, value): def qy(self, value):
self.__node().setGauss(self.__comp(), self.qx, complex(value)) self.__node().setGauss(self.__comp(), self.qx, complex(value))
id___ = 0 id_____pykat_class = 0
class Component(object): class Component(object):
__metaclass__ = abc.ABCMeta __metaclass__ = abc.ABCMeta
...@@ -93,9 +93,9 @@ class Component(object): ...@@ -93,9 +93,9 @@ class Component(object):
# This creates an instance specific class for the component # This creates an instance specific class for the component
# this enables us to add properties to instances rather than # this enables us to add properties to instances rather than
# all classes # all classes
global id___ global id_____pykat_class
id___ += 1 id_____pykat_class += 1
cnew_name = str("%s.%s_%i" % (cls.__module__, cls.__name__, id___)) cnew_name = str("%s.%s_%i" % (cls.__module__, cls.__name__, id_____pykat_class))
cnew = type(cnew_name, (cls,), {}) cnew = type(cnew_name, (cls,), {})
...@@ -130,6 +130,9 @@ class Component(object): ...@@ -130,6 +130,9 @@ class Component(object):
result = self.__class__.__new__(self.__class__.__base__) result = self.__class__.__new__(self.__class__.__base__)
result.__dict__ = copy.deepcopy(self.__dict__, memo) result.__dict__ = copy.deepcopy(self.__dict__, memo)
for _ in result._params:
_._updateOwner(result)
return result return result
def _register_param(self, param): def _register_param(self, param):
...@@ -163,6 +166,16 @@ class Component(object): ...@@ -163,6 +166,16 @@ class Component(object):
kat.nodes.registerComponentNodes(self, self._requested_node_names, self.__on_node_change) kat.nodes.registerComponentNodes(self, self._requested_node_names, self.__on_node_change)
def _on_kat_remove(self):
# inform all parameters that we have removed its owner
# so that it can then warn about any puts/vars/xaxis
for p in self._params:
p._onOwnerRemoved()
del self._params[:]
self.__removed = True
def __on_node_change(self): def __on_node_change(self):
# need to update the node gauss parameter setter members # need to update the node gauss parameter setter members
self.__update_node_setters() self.__update_node_setters()
...@@ -237,17 +250,11 @@ class Component(object): ...@@ -237,17 +250,11 @@ class Component(object):
def __str__(self): return self.name def __str__(self): return self.name
def remove(self): def remove(self):
if self.__removed:
raise pkex.BasePyKatException("{0} has already been marked as removed".format(self.name))
else:
self._kat.remove(self) self._kat.remove(self)
# inform all parameters that we have removed its owner
# so that it can then warn about any puts/vars/xaxis
for p in self._params:
p._onOwnerRemoved()
del self._params[:]
self.__removed = True
def getOptivisParameterDict(self): def getOptivisParameterDict(self):
if len(self._params) == 0: if len(self._params) == 0:
return None return None
...@@ -497,8 +504,8 @@ class mirror(AbstractMirrorComponent): ...@@ -497,8 +504,8 @@ class mirror(AbstractMirrorComponent):
return mirror(values[0], values[4], values[5], T=None, R=values[1], L=values[2], phi=values[3]) return mirror(values[0], values[4], values[5], T=None, R=values[1], L=values[2], phi=values[3])
def getFinesseText(self): def getFinesseText(self):
if self.R+self.T+self.L > 1: if abs(self.R + self.T + self.L - 1) > 1e-14:
raise pkex.BasePyKatException("Mirror {0} has R+T+L > 1".format(self.name)) raise pkex.BasePyKatException("Mirror {0} has R+T+L = {1}, must equal 1 +- 1e-14".format(self.name, self.R+self.T+self.L))
rtn = [] rtn = []
...@@ -632,8 +639,8 @@ class beamSplitter(AbstractMirrorComponent): ...@@ -632,8 +639,8 @@ class beamSplitter(AbstractMirrorComponent):
values[1], None, values[2], values[3], values[4]) values[1], None, values[2], values[3], values[4])
def getFinesseText(self): def getFinesseText(self):
if self.R+self.T+self.L > 1: if abs(self.R + self.T + self.L - 1) > 1e-14:
raise pkex.BasePyKatException("Beamsplitter {0} has R+T+L > 1".format(self.name)) raise pkex.BasePyKatException("Beamsplitter {0} has R+T+L = {1}, must equal 1 +- 1e-14".format(self.name, self.R+self.T+self.L))
rtn = [] rtn = []
...@@ -1320,7 +1327,7 @@ class laser(Component): ...@@ -1320,7 +1327,7 @@ class laser(Component):
return self._svgItem return self._svgItem
class squeezer(Component): class squeezer(Component):
def __init__(self, name, node, f=0, db=0, angle=0, phase=0): def __init__(self, name, node, f=0, db=0, angle=0, phase=0, entangled_carrier=False):
Component.__init__(self,name) Component.__init__(self,name)
self._requested_node_names.append(node) self._requested_node_names.append(node)
...@@ -1330,6 +1337,7 @@ class squeezer(Component): ...@@ -1330,6 +1337,7 @@ class squeezer(Component):
self.__db = Param("db", self, SIfloat(db), canFsig=False, fsig_name="r") self.__db = Param("db", self, SIfloat(db), canFsig=False, fsig_name="r")
self.__angle = Param("angle", self, SIfloat(angle), canFsig=False, fsig_name="angle") self.__angle = Param("angle", self, SIfloat(angle), canFsig=False, fsig_name="angle")
self._svgItem = None self._svgItem = None
self.entangled_carrier = entangled_carrier
@property @property
def db(self): return self.__db def db(self): return self.__db
...@@ -1358,17 +1366,24 @@ class squeezer(Component): ...@@ -1358,17 +1366,24 @@ class squeezer(Component):
def parseFinesseText(text): def parseFinesseText(text):
values = text.split() values = text.split()
if values[0] != "sq": if values[0][:2] != "sq":
raise pkex.BasePyKatException("'{0}' not a valid Finesse squeezer command".format(text)) raise pkex.BasePyKatException("'{0}' not a valid Finesse squeezer command".format(text))
entangled_carrier = values[0].endswith("*")
values.pop(0) # remove initial value values.pop(0) # remove initial value
if len(values) == 5: if len(values) == 5:
return squeezer(values[0], values[4], f=values[1], db=values[2], angle=values[3]) return squeezer(values[0], values[4], f=values[1],
db=values[2], angle=values[3],
entangled_carrier=entangled_carrier)
else: else:
raise exceptions.FinesseParse("Squeezer Finesse code format incorrect '{0}'".format(text)) raise exceptions.FinesseParse("Squeezer Finesse code format incorrect '{0}'".format(text))
def getFinesseText(self): def getFinesseText(self):
if self.entangled_carrier:
rtn = ['sq* {0} {1} {2} {3} {4}'.format(self.name, self.f.value, self.db.value, self.angle.value, self.nodes[0].name)]
else:
rtn = ['sq {0} {1} {2} {3} {4}'.format(self.name, self.f.value, self.db.value, self.angle.value, self.nodes[0].name)] rtn = ['sq {0} {1} {2} {3} {4}'.format(self.name, self.f.value, self.db.value, self.angle.value, self.nodes[0].name)]
for p in self._params: for p in self._params:
......
...@@ -31,7 +31,7 @@ if USE_GUI: ...@@ -31,7 +31,7 @@ if USE_GUI:
import pykat.gui.resources import pykat.gui.resources
from pykat.gui.graphics import * from pykat.gui.graphics import *
id___ = 0 id_____pykat_class = 0
class BaseDetector(object) : class BaseDetector(object) :
""" """
...@@ -45,9 +45,9 @@ class BaseDetector(object) : ...@@ -45,9 +45,9 @@ class BaseDetector(object) :
# This creates an instance specific class for the component # This creates an instance specific class for the component
# this enables us to add properties to instances rather than # this enables us to add properties to instances rather than
# all classes # all classes
global id___ global id_____pykat_class
id___ += 1 id_____pykat_class += 1
cnew_name = str("%s.%s_%i" % (cls.__module__, cls.__name__, id___)) cnew_name = str("%s.%s_%i" % (cls.__module__, cls.__name__, id_____pykat_class))
cnew = type(cnew_name, (cls,), {}) cnew = type(cnew_name, (cls,), {})
...@@ -120,6 +120,9 @@ class BaseDetector(object) : ...@@ -120,6 +120,9 @@ class BaseDetector(object) :
if rn != None: if rn != None:
self._nodes.append(kat.nodes.createNode(rn)) self._nodes.append(kat.nodes.createNode(rn))
def _on_kat_remove(self):
self.__removed = True
def remove(self): def remove(self):
if self.__removed: if self.__removed:
raise pkex.BasePyKatException("{0} has already been marked as removed".format(self.name)) raise pkex.BasePyKatException("{0} has already been marked as removed".format(self.name))
...@@ -465,7 +468,7 @@ class gouy(Detector1): ...@@ -465,7 +468,7 @@ class gouy(Detector1):
class bp(Detector1): class bp(Detector1):
acceptedParameters = ['w', 'w0', 'z', 'zr', 'g', 'r', 'q'] acceptedParameters = ['w', 'w0', 'z', 'zr', 'g', 'r', 'q', 'Rc']
def __init__(self, name, direction, parameter, node, alternate_beam=False): def __init__(self, name, direction, parameter, node, alternate_beam=False):
BaseDetector.__init__(self, name, node) BaseDetector.__init__(self, name, node)
......
...@@ -328,6 +328,9 @@ class katRun(object): ...@@ -328,6 +328,9 @@ class katRun(object):
kat.verbose = False kat.verbose = False
kat.parseCommands(self.katScript) kat.parseCommands(self.katScript)
if kat.noxaxis == True:
raise pkex.BasePyKatException("This kat object has noxaxis=True, so there is nothing to plot.")
if yaxis is not None: if yaxis is not None:
kat.yaxis = yaxis kat.yaxis = yaxis
...@@ -745,6 +748,7 @@ class kat(object): ...@@ -745,6 +748,7 @@ class kat(object):
self.vacuum = [] self.vacuum = []
self.__prevrunfilename = None self.__prevrunfilename = None
self.printmatrix = None self.printmatrix = None
self.__variables = {}
# initialise default block # initialise default block
self.__currentTag= NO_BLOCK self.__currentTag= NO_BLOCK
...@@ -997,7 +1001,7 @@ class kat(object): ...@@ -997,7 +1001,7 @@ class kat(object):
else: else:
return return
for o in self.__blocks[name].contents: for o in self.__blocks[name].contents.copy():
self.remove(o) self.remove(o)
del self.__blocks[name] del self.__blocks[name]
...@@ -1005,6 +1009,31 @@ class kat(object): ...@@ -1005,6 +1009,31 @@ class kat(object):
def __str__(self): def __str__(self):
return "".join(self.generateKatScript()) return "".join(self.generateKatScript())
def getVariable(self, name):
if name not in self.__variables:
raise pkex.BasePyKatException("Finesse variable `$%s` does not exist." % name)
return self.__variables[name]
def registerVariable(self, name, putter):
if '$' in name:
raise pkex.BasePyKatException("Finesse variable name `%s` should not include the `$` symbol as it is added internally." % name)
assert(putter is not None)
assert(name == putter.name)
if name in self.__variables:
raise pkex.BasePyKatException("Finesse variable name `%s` already exists." % name)
self.__variables[name] = putter
def unregisterVariable(self, name):
del self.__variables[name]
def printVariables(self):
for key in self.__variables:
print("$" + key, "::::", "owner =", self.__variables[key].owner.name, ", use count =", self.__variables[key].putCount)
def parseCommands(self, commands, blocks=None, addToBlock=None): def parseCommands(self, commands, blocks=None, addToBlock=None):
try: try:
if addToBlock is not None and blocks is not None: if addToBlock is not None and blocks is not None:
...@@ -1077,7 +1106,7 @@ class kat(object): ...@@ -1077,7 +1106,7 @@ class kat(object):
obj = pykat.components.space.parseFinesseText(line) obj = pykat.components.space.parseFinesseText(line)
elif(first == "l"): elif(first == "l"):
obj = pykat.components.laser.parseFinesseText(line) obj = pykat.components.laser.parseFinesseText(line)
elif(first == "sq"): elif(first[:2] == "sq"):
obj = pykat.components.squeezer.parseFinesseText(line) obj = pykat.components.squeezer.parseFinesseText(line)
elif(first[0:2] == "bs"): elif(first[0:2] == "bs"):
obj = pykat.components.beamSplitter.parseFinesseText(line) obj = pykat.components.beamSplitter.parseFinesseText(line)
...@@ -1182,6 +1211,8 @@ class kat(object): ...@@ -1182,6 +1211,8 @@ class kat(object):
after_process.append((line, self.__currentTag)) after_process.append((line, self.__currentTag))
elif(first == "noplot"): elif(first == "noplot"):
after_process.append((line, self.__currentTag)) after_process.append((line, self.__currentTag))
elif(first == "put" or first == "put*"):
after_process.append((line, self.__currentTag))
else: else:
if self.verbose: if self.verbose:
print ("Parsing `{0}` into pykat object not implemented yet, added as extra line.".format(line)) print ("Parsing `{0}` into pykat object not implemented yet, added as extra line.".format(line))
...@@ -1232,6 +1263,40 @@ class kat(object): ...@@ -1232,6 +1263,40 @@ class kat(object):
getattr(self, rest).noplot = True getattr(self, rest).noplot = True
elif (first == "put" or first =="put*"):
alt = first == "put*"
values = line.split()
obj = values[1]
target = values[2]
variable = values[3]
try:
if not hasattr(self, obj):
raise pkex.BasePyKatException("put command `{0}` refers to non-existing component".format(line))
obj = getattr(self, obj)
if not hasattr(obj, target):
raise pkex.BasePyKatException("put command component `{0}` does not have a parameter `{1}`".format(line, target))
target = getattr(obj, target)
if not target.isPutable:
raise pkex.BasePyKatException("put command `{0}` parameter `{1}` cannot be put to".format(line, target))
target.put(self.getVariable(variable.replace('$', '')), alt)
except pkex.BasePyKatException as ex:
if self.verbose:
print("Warning: ", ex.msg)
print ("Parsing `{0}` into pykat object not implemented yet, added as extra line.".format(line))
obj = line
# manually add the line to the block contents
self.__blocks[block].contents.append(line)
elif (first == "scale"): elif (first == "scale"):
v = line.split() v = line.split()
accepted = ["psd","psd_hf","asd","asd_hf","meter", "ampere", "deg", "rad", "1/deg", "1/rad",] accepted = ["psd","psd_hf","asd","asd_hf","meter", "ampere", "deg", "rad", "1/deg", "1/rad",]
...@@ -1368,7 +1433,7 @@ class kat(object): ...@@ -1368,7 +1433,7 @@ class kat(object):
except pkex.BasePyKatException as ex: except pkex.BasePyKatException as ex:
pkex.PrintError("Error parsing line: '%s':"% line, ex) pkex.PrintError("Pykat error parsing line: '%s':"% line, ex)
sys.exit(1) sys.exit(1)
def saveScript(self, filename=None): def saveScript(self, filename=None):
...@@ -1600,11 +1665,10 @@ class kat(object): ...@@ -1600,11 +1665,10 @@ class kat(object):
a = line.split(':', 1) a = line.split(':', 1)
if a[0].isdigit(): if a[0].isdigit():
#print("Found %s" % a[0])
values = a[1].split() values = a[1].split()
node_name = values[1].split("(")[0] node_name = values[1].split("(")[0]
component_name = values[2].split("(")[0]
line1x = ifile.readline().replace('(','').replace(')','') line1x = ifile.readline().replace('(','').replace(')','')
line2x = ifile.readline().replace('(','').replace(')','') line2x = ifile.readline().replace('(','').replace(')','')
...@@ -1617,7 +1681,9 @@ class kat(object): ...@@ -1617,7 +1681,9 @@ class kat(object):
qx = spqx[0].split("=")[1].replace('i','j').replace(' ','') qx = spqx[0].split("=")[1].replace('i','j').replace(' ','')
qy = spqy[0].split("=")[1].replace('i','j').replace(' ','') qy = spqy[0].split("=")[1].replace('i','j').replace(' ','')
traceData[-1][node_name] = (pykat.beam_param(q=complex(qx)), pykat.beam_param(q=complex(qy))) traceData[-1][node_name] = (pykat.beam_param(q=complex(qx), wavelength=self.lambda0),
pykat.beam_param(q=complex(qy), wavelength=self.lambda0),
component_name)
finally: finally:
ifile.close() ifile.close()
...@@ -1759,6 +1825,9 @@ class kat(object): ...@@ -1759,6 +1825,9 @@ class kat(object):
del nodes del nodes
if hasattr(obj, "_on_kat_remove"):
obj._on_kat_remove()
#import gc #import gc
#print (gc.get_referrers(obj)) #print (gc.get_referrers(obj))
......
...@@ -12,7 +12,8 @@ class putable(object): ...@@ -12,7 +12,8 @@ class putable(object):
Objects that inherit this should be able to have something `put` to it. Objects that inherit this should be able to have something `put` to it.
Essentially this means you could write Finesse commands like Essentially this means you could write Finesse commands like
put this parameter value param.put(kat.xaxis.x)
""" """
__metaclass__ = abc.ABCMeta __metaclass__ = abc.ABCMeta
...@@ -20,46 +21,97 @@ class putable(object): ...@@ -20,46 +21,97 @@ class putable(object):
self._parameter_name = parameter_name self._parameter_name = parameter_name
self._component_name = component_name self._component_name = component_name
self._putter = None self._putter = None
self._alt = False
self._isPutable = isPutable self._isPutable = isPutable
@property @property
def isPutable(self): return self._isPutable def isPutable(self): return self._isPutable
def put(self, var): def put(self, var, alt=False):
if not self._isPutable:
raise pkex.BasePyKatException("Can't put to this object")
if not isinstance(var, putter): if var is not None and not isinstance(var, putter):
raise pkex.BasePyKatException("var was not something that can be `put` as a value") raise pkex.BasePyKatException("`%s` was not something that can be `put` to a parameter" % str(var))
if self._putter != None: # Remove existing puts
self._putter.put_count -= 1 if self._putter is not None:
self._putter.putees.remove(self) self._putter.unregister(self)
self._putter = var self._putter = var
if var != None: self._alt = alt
self._putter.put_count += 1
self._putter.putees.append(self) if var is not None:
self._putter.register(self)
def _getPutFinesseText(self): def _getPutFinesseText(self):
rtn = [] rtn = []
if self._isPutable and self._putter is not None:
putter_enabled = True
if hasattr(self._putter.owner, 'enabled'):
putter_enabled = self._putter.owner.enabled
if putter_enabled:
if self._alt:
alt = '*'
else:
alt = ''
# if something is being put to this # if something is being put to this
if self._putter != None: rtn.append("put{alt} {comp} {param} ${value}".format(alt=alt, comp=self._component_name, param=self._parameter_name, value=self._putter.put_name()))
rtn.append("put {comp} {param} ${value}".format(comp=self._component_name, param=self._parameter_name, value=self._putter.put_name()))
return rtn return rtn
class putter(object): class putter(object):
""" """
If an object can be put to something that is putable it should inherit this If an object can be put to something that is putable it should inherit this
object. object.
""" """
def __init__(self, put_name, isPutter=True): def __init__(self, put_name, owner, isPutter=True):
self._put_name = put_name self._put_name = put_name
self.put_count = 0 self.put_count = 0
self._isPutter = isPutter self._isPutter = isPutter
self.putees = [] # list of params that this puts to self.putees = [] # list of params that this puts to
assert(owner is not None)
self.__owner = weakref.ref(owner)
def _updateOwner(self, newOwner):
del self.__owner
self.__owner = weakref.ref(newOwner)
def clearPuts(self):
for _ in self.putees.copy():
_.put(None)
def register(self, toput):
if not self._isPutter:
raise pkex.BasePyKatException("This object can't put")
self.put_count += 1
self.putees.append(toput)
def unregister(self, item):
if not self._isPutter:
raise pkex.BasePyKatException("This object can't put")
self.put_count -= 1
self.putees.remove(item)
@property
def owner(self): return self.__owner()
@property
def name(self): return self._put_name
@property
def putCount(self): return self.put_count
@property @property
def isPutter(self): return self._isPutter def isPutter(self): return self._isPutter
...@@ -68,15 +120,18 @@ class putter(object): ...@@ -68,15 +120,18 @@ class putter(object):
class Param(putable, putter): class Param(putable, putter):
def __init__(self, name, owner, value, canFsig=False, fsig_name=None, isPutable=True, isPutter=True, isTunable=True, var_name=None): def __init__(self, name, owner, value, canFsig=False, fsig_name=None, isPutable=True, isPutter=True, isTunable=True, var_name=None, register=True):
self._name = name self._name = name
self._registered = register
self._owner = weakref.ref(owner) self._owner = weakref.ref(owner)
self._value = value self._value = value
self._isPutter = isPutter self._isPutter = isPutter
self._isTunable = isTunable self._isTunable = isTunable
self._owner()._register_param(self)
self._canFsig = False self._canFsig = False
if self._registered:
self._owner()._register_param(self)
if canFsig: if canFsig:
self._canFsig = True self._canFsig = True
...@@ -89,19 +144,10 @@ class Param(putable, putter): ...@@ -89,19 +144,10 @@ class Param(putable, putter):
if var_name is None: if var_name is None:
var_name = "var_{0}_{1}".format(owner.name, name) var_name = "var_{0}_{1}".format(owner.name, name)
putter.__init__(self, var_name, isPutter) putter.__init__(self, var_name, owner, isPutter)
putable.__init__(self, owner.name, name, isPutable) putable.__init__(self, owner.name, name, isPutable)
def _updateOwner(self, newOwner):
"""
This updates the internal weak reference to link a parameter to who owns it.
Should only be called by the __deepcopy__ component method to ensure things
are kept up to date.
"""
del self._owner
self._owner = weakref.ref(newOwner)
@property @property
def canFsig(self): return self._canFsig def canFsig(self): return self._canFsig
...@@ -163,6 +209,15 @@ class Param(putable, putter): ...@@ -163,6 +209,15 @@ class Param(putable, putter):
return rtn return rtn
def _updateOwner(self, newOwner):
"""
This updates the internal weak reference to link a parameter to who owns it.
Should only be called by the __deepcopy__ component method to ensure things
are kept up to date.
"""
del self._owner
self._owner = weakref.ref(newOwner)
def _onOwnerRemoved(self): def _onOwnerRemoved(self):
#if this param can be put somewhere we need to check if it is #if this param can be put somewhere we need to check if it is
if self.isPutable: if self.isPutable:
......
...@@ -13,9 +13,11 @@ kat.loadKatFile("LHO_IFO_maxtem2.kat") # load the conf ...@@ -13,9 +13,11 @@ kat.loadKatFile("LHO_IFO_maxtem2.kat") # load the conf
kat.parseKatCode( "fsig sig1 ETMXHR 10 180") kat.parseKatCode( "fsig sig1 ETMXHR 10 180")
kat.parseKatCode( "fsig sig1 ETMYHR 10 0") kat.parseKatCode( "fsig sig1 ETMYHR 10 0")
kat.parseKatCode( "pd1 myomc 10 nOMC_HROC_trans") kat.parseKatCode( "pd1 myomc 10 nOMC_HROC_trans")
kat.parseKatCode( "put myomc f1 $x1") # to follow
kat.parseKatCode( "xaxis sig1 f log 10 1k 10") kat.parseKatCode( "xaxis sig1 f log 10 1k 10")
kat.parseKatCode( "put myomc f1 $x1") # to follow
kat.parseKatCode( "yaxis abs:deg") kat.parseKatCode( "yaxis abs:deg")
kat.verbose = True kat.verbose = True
out = kat.run() # do the computation out = kat.run() # do the computation
result.append(out['myomc']) # append the result result.append(out['myomc']) # append the result
print("PASSED")
\ No newline at end of file
...@@ -25,6 +25,9 @@ assert(kat0.nodes.n0 != kat1.nodes.n0) ...@@ -25,6 +25,9 @@ assert(kat0.nodes.n0 != kat1.nodes.n0)
assert(kat0.o1 != kat1.o1) assert(kat0.o1 != kat1.o1)
assert(kat0.o1.__class__ != kat1.o1.__class__) assert(kat0.o1.__class__ != kat1.o1.__class__)
assert(kat0.m1.phi.owner == kat0.m1)
assert(kat1.m1.phi.owner == kat1.m1)
# use is to compare if two params are the same object as equals is override to compare the value # use is to compare if two params are the same object as equals is override to compare the value
assert(kat0.o1.f1 is not kat1.o1.f1) assert(kat0.o1.f1 is not kat1.o1.f1)
assert(kat0.o1.f1 == kat1.o1.f1) assert(kat0.o1.f1 == kat1.o1.f1)
......
# Submitted by Sebastian.
# Checks that trace data output returns the same beamsize when a different default wavelength is used
from pykat import finesse
kat_code = """
l laser 1 0 0 n1
s s1 10 1 n1 n2
m2 mITM 0.9 0.0 0 n2 n3
attr mITM Rc -2.0
s scav 1 n3 n4
m2 mETM 0.9 0.0 0 n4 n5
attr mETM Rc 2.0
cav myCav mITM n3 mETM n4
s s3 1 n5 n6
pd pd_trans n6
noxaxis
yaxis abs:deg # move detector frequency with xaxis
"""
kat = finesse.kat()
kat.verbose = False
kat.lambda0 = 1550e-9
kat.parseKatCode(kat_code)
kat.maxtem = 0
kat.trace = 2
out, T = kat.run(getTraceData=True)
print (out.stdout)
bp = T[0]['n4'][0]
# this is not overwritten to 1550nm as above
print('beam_param.wavelength: {:.0f}nm'.format(bp.wavelength*1e9))
# therefore this is wrong
print('w0 from beam_param.w0: {:.2f}um'.format(bp.w0*1e6))
# and this does not really work as the wavelength cancels out
# for z=0 and therefore the waist does not change
print('w0 from beam_param.beamsize(): {:.2f}um'.format(bp.beamsize(z=0, wavelength=1550e-9)*1e6))
assert(bp.w0 == bp.beamsize(z=0, wavelength=1550e-9))
\ No newline at end of file
...@@ -22,6 +22,7 @@ attr m1 Rc -500 ...@@ -22,6 +22,7 @@ attr m1 Rc -500
attr m2 Rc 500 attr m2 Rc 500
cav c1 m1 n4b m2 n7a cav c1 m1 n4b m2 n7a
pd P n5b
maxtem 0 maxtem 0
noxaxis noxaxis
""") """)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment