Select Git revision
test_2d_plot.py
Forked from
finesse / pykat
Source project has a limited visibility.
detectors.py 33.06 KiB
# -*- coding: utf-8 -*-
"""
Created on Fri Feb 01 0split()9:09:10 2013
@author: Daniel
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import pykat.external.six as six
if six.PY2:
import exceptions
import abc
from pykat.node_network import *
from pykat.param import Param, AttrParam
from pykat.SIfloat import SIfloat
import pykat.external.six as six
import pykat.exceptions as pkex
import collections
import warnings
import copy
from pykat import USE_GUI, NoGUIException
if USE_GUI:
import pykat.gui.resources
from pykat.gui.graphics import *
id___ = 0
class BaseDetector(object) :
"""
This is a base class for all detectors. Classes Detector1 and Detector2 should be used directly.
This base class can handled detectors connected to multiple nodes.
"""
__metaclass__ = abc.ABCMeta
def __new__(cls, *args, **kwargs):
# This creates an instance specific class for the component
# this enables us to add properties to instances rather than
# all classes
global id___
id___ += 1
cnew_name = str("%s.%s_%i" % (cls.__module__, cls.__name__, id___))
cnew = type(cnew_name, (cls,), {})
return object.__new__(cnew)
def __init__(self, name, nodes=None, max_nodes=1):
self.__name = name
self._svgItem = None
self._kat = None
self.noplot = False
self.enabled = True
self.tag = None
self._params = []
self._mask = {}
self.__scale = []
self.__removed = False
self.noplot = False
self._alternate_beam = []
self._nodes = []
self._requested_nodes = []
if nodes != None:
if isinstance(nodes, (list, tuple)):
if len(nodes) > max_nodes:
raise pkex.BasePyKatException("Tried to set too many nodes, %s, maximum number is %i." %(str(nodes),max_nodes))
for n in nodes:
if n[-1]=='*':
self._alternate_beam.append(True)
n = n[:-1]
else:
self._alternate_beam.append(False)
self._requested_nodes.append(n)
elif isinstance(nodes, six.string_types):
# if we don't have a collection
if nodes[-1]=='*':
self._alternate_beam.append(True)
nodes = nodes[:-1]
else:
self._alternate_beam.append(False)
self._requested_nodes.append(nodes)
else:
raise pkex.BasePyKatException("Nodes should be a list or tuple of node names or a singular node name as a string.")
def __deepcopy__(self, memo):
"""
When deep copying a kat object we need to take into account
the instance specific properties.
"""
# Here we create a copy of this object based of the base class
# of this one, otherwise we're making a copy of a copy of a copy...
result = self.__class__.__new__(self.__class__.__base__)
result.__dict__ = copy.deepcopy(self.__dict__, memo)
return result
def _register_param(self, param):
self._params.append(param)
def _on_kat_add(self, kat):
self._kat = kat
for rn in self._requested_nodes:
if rn != None:
self._nodes.append(kat.nodes.createNode(rn))
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.__removed = True
@staticmethod
def parseFinesseText(text):
raise NotImplementedError("This function is not implemented")
def getFinesseText(self):
""" Base class for individual finesse optical components """
raise NotImplementedError("This function is not implemented")
def getQGraphicsItem(self):
if not USE_GUI:
raise NoGUIException
return None
@property
def removed(self): return self.__removed
@property
def scale(self): return self.__scale
@scale.setter
def scale(self, value):
if value not in self.__scale:
self.__scale = value
@property
def name(self): return self.__name
def __str__(self): return self.name
def mask(self, n, m, factor):
_id = str(n)+"_"+str(m)
# if the mask is 1 then remove this so it doesn't get
# printed as by default the value is 1.0
if _id in self._mask and factor == 1.0:
del self._mask[_id]
self._mask[_id] = factor
def _set_node(value, index):
if self._kat is None:
raise pkex.BasePyKatException("This detector has not been added to a kat object yet")
else:
if value[-1] == '*':
self._alternate_beam[index] = True
value = value[:-1]
else:
self._alternate_beam[index] = False
if value in self._kat.nodes:
self._nodes[index] = self._kat.nodes[value]
else:
raise pkex.BasePyKatException("There is no node called " + value + " in the kat object this detector is attached to.")
def _getScaleCmds(self, rtn):
if self.scale != None:
if isinstance(self.scale, six.string_types):
rtn.append("scale {1} {0}".format(self.name, self.scale))
elif isinstance(self.scale, (list, tuple)):
for s in self.scale:
rtn.append("scale {1} {0}".format(self.name, s))
else:
raise pkex.BasePyKatException("Scale command should either be a list of scales or a single string.")
class Detector0(BaseDetector):
"""
A detector that attaches to no nodes.
"""
pass
class Detector1(BaseDetector):
"""
A detector that attaches to one node.
"""
@property
def node(self): return self._nodes[0]
@node.setter
def node(self, value):
self._set_node(value, 0)
class Detector2(BaseDetector):
"""
A detector that attaches to two node.
"""
@property
def node1(self): return self._nodes[0]
@node1.setter
def node(self, value):
self._set_node(value, 0)
@property
def node2(self): return self._nodes[1]
@node2.setter
def node(self, value):
self._set_node(value, 1)
class beam(Detector1):
def __init__(self, name, node_name, frequency=None, alternate_beam=False):
BaseDetector.__init__(self, name, node_name)
self.alternate_beam = alternate_beam
self.__f = Param("f", self, frequency)
@property
def f(self): return self.__f
@f.setter
def f(self, value):
self.__f.value = value
@staticmethod
def parseFinesseText(text):
values = text.split()
node=values[-1]
alt_beam = node[-1] == '*'
if len(values) == 3:
return beam(values[1], node, alternate_beam=alt_beam)
elif len(values) == 4:
return beam(values[1], node, alternate_beam=alt_beam, frequency=SIfloat(values[2]))
else:
raise pkex.BasePyKatException('Beam detector code "{0}" is not a valid FINESSE command'.format(text))
def getFinesseText(self) :
rtn = []
if self.alternate_beam:
alt = '*'
else:
alt = ''
if self.f.value is None:
rtn.append("beam {name} {node}{alt}".format(name=self.name, node=self.node.name, alt=alt))
else:
rtn.append("beam {name} {f} {node}{alt}".format(name=self.name, f=str(self.f.value), node=self.node.name, alt=alt))
for p in self._params:
rtn.extend(p.getFinesseText())
return rtn
class xd(Detector0):
def __init__(self, name, component, motion):
BaseDetector.__init__(self, name, None)
self.component = component
self.motion = motion
@staticmethod
def parseFinesseText(text):
values = text.split()
if len(values) == 4:
return xd(values[1], values[2], values[3])
else:
raise pkex.BasePyKatException('Motion detector code "{0}" is not a valid FINESSE command'.format(text))
def getFinesseText(self) :
rtn = []
rtn.append("xd {name} {component} {motion}".format(name=self.name,
component=self.component,
motion=self.motion))
return rtn
class ad(Detector1):
def __init__(self, name, frequency, node_name, mode=None, alternate_beam=False):
BaseDetector.__init__(self, name, node_name)
self.mode = mode
self.alternate_beam = alternate_beam
self.__f = Param("f", self, frequency)
@property
def mode(self): return self.__mode
@mode.setter
def mode(self, value):
if value != None and len(value) != 2:
raise pkex.BasePyKatException('Mode must be a container of length 2, first element the x mode and second the y mode')
self.__mode = value
@property
def f(self): return self.__f
@f.setter
def f(self, value):
self.__f.value = value
@staticmethod
def parseFinesseText(text):
values = text.split()
node=values[-1]
alt_beam = node[-1] == '*'
if len(values) == 6:
return ad(values[1], values[4], values[5], mode = [int(values[2]), int(values[3])], alternate_beam=alt_beam)
elif len(values) == 4:
return ad(values[1], values[2], values[3], alternate_beam=alt_beam)
else:
raise pkex.BasePyKatException('Amplitude detector code "{0}" is not a valid FINESSE command'.format(text))
def getFinesseText(self) :
rtn = []
if self.alternate_beam:
alt = '*'
else:
alt = ''
if self.mode is None:
rtn.append("ad {name} {f} {node}{alt}".format(name=self.name, f=str(self.f.value), node=self.node.name, alt=alt))
else:
rtn.append("ad {name} {n} {m} {f} {node}{alt}".format(name=self.name, n=str(self.mode[0]), m=str(self.mode[1]), f=str(self.f.value), node=self.node.name, alt=alt))
for p in self._params:
rtn.extend(p.getFinesseText())
return rtn
class gouy(Detector1):
def __init__(self, name, direction, spaces):
BaseDetector.__init__(self, name)
self.spaces = copy.copy(spaces)
self.direction = direction
self.alternate_beam = False
@property
def direction(self): return self.__dir
@direction.setter
def direction(self, value):
if value is None or (value != 'x' and value != 'y'):
raise pkex.BasePyKatException('Direction must be either x or y')
self.__dir = value
@property
def spaces(self): return self.__spaces
@spaces.setter
def spaces(self, value):
if value is None or len(value) < 1:
raise pkex.BasePyKatException('Must be a list of space names')
self.__spaces = value
@staticmethod
def parseFinesseText(text):
values = text.split()
if len(values) > 3:
return gouy(str(values[1]), str(values[2]), values[3:])
else:
raise pkex.BasePyKatException('Gouy detector code "{0}" is not a valid FINESSE command'.format(text))
def getFinesseText(self) :
rtn = []
rtn.append("gouy {name} {dir} {spaces}".format(name=self.name, dir=str(self.direction), spaces=" ".join(self.spaces)))
for p in self._params:
rtn.extend(p.getFinesseText())
return rtn
class bp(Detector1):
acceptedParameters = ['w', 'w0', 'z', 'zr', 'g', 'r', 'q']
def __init__(self, name, direction, parameter, node, alternate_beam=False):
BaseDetector.__init__(self, name, node)
self.parameter = parameter
self.direction = direction
self.alternate_beam = alternate_beam
@property
def direction(self): return self.__dir
@direction.setter
def direction(self, value):
if value is None or (value != 'x' and value != 'y'):
raise pkex.BasePyKatException('Direction must be either x or y')
self.__dir = value
@property
def parameter(self): return self.__param
@parameter.setter
def parameter(self, value):
if value is None or (value not in self.acceptedParameters) :
raise pkex.BasePyKatException('Parameter must be one of: %s'%(", ".join(self.acceptedParameters)))
self.__param = value
@staticmethod
def parseFinesseText(text):
values = text.split()
node=values[-1]
alt_beam = node[-1] == '*'
if len(values) > 3:
return bp(str(values[1]), str(values[2]), str(values[3]), str(values[4]), alternate_beam=alt_beam)
else:
raise pkex.BasePyKatException('Gouy detector code "{0}" is not a valid FINESSE command'.format(text))
def getFinesseText(self) :
rtn = []
if self.alternate_beam:
alt = "*"
else:
alt = ""
rtn.append("bp {name} {dir} {param} {node}{alt}".format(name=self.name, dir=str(self.direction), param=self.parameter, node=self.node.name, alt=alt))
for p in self._params:
rtn.extend(p.getFinesseText())
return rtn
id___2 = 0
class pd(Detector1):
def __new__(cls, *args, **kwargs):
# This creates an instance specific class for the component
# this enables us to add properties to instances rather than
# all classes
global id___2
id___2 += 1
cnew_name = str("%s.%s_%i" % (cls.__module__, cls.__name__, id___2))
cnew = type(cnew_name, (cls,), {})
return object.__new__(cnew)
def __deepcopy__(self, memo):
"""
When deep copying a kat object we need to take into account
the instance specific properties.
"""
# Here we create a copy of this object based of the base class
# of this one, otherwise we're making a copy of a copy of a copy...
result = self.__class__.__new__(self.__class__.__base__)
result.__dict__ = copy.deepcopy(self.__dict__, memo)
result.__set_demod_attrs()
return result
def __init__(self, name=None, num_demods=1, node_name=None, senstype=None, alternate_beam=False, pdtype=None, **kwargs):
BaseDetector.__init__(self, name, node_name)
self.__num_demods = num_demods
self.__senstype = senstype
self.alternate_beam = alternate_beam
self.__pdtype = pdtype
# create the parameters for all 5 demodulations regardless
# of how many the user specifies. Later we add properties to
# those which correspond to the number of demodulations
self.__f1 = Param("f1", self, None)
self.__f2 = Param("f2", self, None)
self.__f3 = Param("f3", self, None)
self.__f4 = Param("f4", self, None)
self.__f5 = Param("f5", self, None)
self.__phase1 = Param("phase1", self, None)
self.__phase2 = Param("phase2", self, None)
self.__phase3 = Param("phase3", self, None)
self.__phase4 = Param("phase4", self, None)
self.__phase5 = Param("phase5", self, None)
fs = [self.__f1, self.__f2, self.__f3, self.__f4, self.__f5]
ps = [self.__phase1, self.__phase2, self.__phase3, self.__phase4, self.__phase5]
for i in range(num_demods):
f = 'f{0}'.format(i+1)
#print("i {0} fs {1} f {2} keys {3}".format(i,len(fs),f, kwargs.keys()))
if f in kwargs:
fs[i].value = kwargs[f]
else:
raise pkex.BasePyKatException("Missing demodulation frequency {0} (f{0})".format(i+1))
p = 'phase{0}'.format(i+1)
if p in kwargs:
if kwargs[p] is None and i<num_demods-1:
raise pkex.BasePyKatException("Missing demodulation phase {0} (phase{0})".format(i+1))
ps[i].value = kwargs[p]
elif i<num_demods-1:
raise pkex.BasePyKatException("Missing demodulation phase {0} (phase{0})".format(i+1))
self.__set_demod_attrs()
@property
def senstype(self): return self.__senstype
@senstype.setter
def senstype(self,value):
if value == "": value = None
if value != "S" and value != "N" and value != None:
raise pkex.BasePyKatException("Photodiode sensitivity type can either be 'N', 'S' or None.")
self.__senstype = value
@property
def num_demods(self): return self.__num_demods
@num_demods.setter
def num_demods(self, value):
if value < 0 or value > 5:
raise pkex.BasePyKatException("Number of demodulations must be between 0 and 5")
self.__num_demods = value
self.__set_demod_attrs()
@property
def pdtype(self): return self.__pdtype
@pdtype.setter
def pdtype(self, value): self.__pdtype = value
def __get_fphi(self, name):
return getattr(self, '_pd__' + name)
def __set_f(self, num, value):
value = SIfloat(value)
p = getattr(self, '_pd__f' + num)
p.value = value
def __set_phi(self, num, value):
value = SIfloat(value)
if value is None and num != self.num_demods:
# check if we are setting no phase that this is only on the last
# demodulation phase.
raise pkex.BasePyKatException("Only last demodulation phase can be set to None")
elif isinstance(value, six.string_types) and not isinstance(value,float) and value.lower() != "max":
raise pkex.BasePyKatException("Demodulation phase can only be set to a 'max' or a number (or None if the last demodulation phase)")
p = getattr(self, '_pd__phase' + num)
p.value = value
def __set_demod_attrs(self):
"""
For the set number of demodulations the correct number of
Parameters are created.
"""
# if there are demodulations present then we want to add
# the various parameters so they are available for users
# to play with.
if self.__num_demods > 0:
for i in range(1,6):
name = str(i)
if i <= self.num_demods:
if not hasattr(self, "f"+name):
fget = lambda self, i=i: self.__get_fphi('f'+str(i))
fset = lambda self, value, i=i: self.__set_f(str(i), value)
setattr(self.__class__, "f"+name, property(fget=fget, fset=fset))
if not hasattr(self, "phase"+name):
setattr(self.__class__, "phase"+name, property(fget=lambda self, i=i: self.__get_fphi('phase'+str(i)), fset=lambda self, value, i=i: self.__set_phi(str(i), value)))
else:
if hasattr(self, "f"+name):
delattr(self.__class__, "f"+name)
if hasattr(self, "phase"+name):
delattr(self.__class__, "phase"+name)
else:
return
@staticmethod
def parseFinesseText(text):
values = text.split()
demods = 0
senstype = None
if len(values[0]) == 4:
senstype = values[0][2]
demods = int(values[0][3])
elif len(values[0]) == 3:
demods = int(values[0][2])
elif len(values[0]) != 2:
raise pkex.BasePyKatException("Photodiode code format incorrect '{0}' (1)".format(text))
if len(values) <= 3 and demods > 0:
raise pkex.BasePyKatException("Photodiode code format incorrect '{0}' (2)".format(text))
elif len(values) > 3 and demods == 0:
raise pkex.BasePyKatException("Photodiode code format incorrect '{0}' (3)".format(text))
num_f_phs = len(values) - 3
expected_f_phs = demods * 2
if not (num_f_phs == expected_f_phs or num_f_phs == expected_f_phs-1):
raise pkex.BasePyKatException("Photodiode code format incorrect '{0}' (4)".format(text))
f = values[2:len(values)-1:2]
phs = values[3:len(values)-1:2]
dict = {}
for i in range(len(f)):
dict['f{0}'.format(i+1)] = SIfloat(f[i])
for i in range(len(phs)):
if phs[i] == "max":
dict['phase{0}'.format(i+1)] = "max"
else:
dict['phase{0}'.format(i+1)] = SIfloat(phs[i])
node = values[-1]
alt_beam = node[-1] == '*'
if alt_beam:
node = node[0:-1]
return pd(values[1], demods, node, senstype=senstype, alternate_beam=alt_beam, **dict)
def getFinesseText(self) :
rtn = []
if self.enabled:
alt_str = ""
fphi_str = ""
if self.alternate_beam:
alt_str = "*"
for n in range(1, 1+self.num_demods):
_f = self.__getattribute__("f"+str(n))
if _f == "$fs":
fphi_str += " $fs"
else:
fphi_str += " {0:.16g}".format(float(_f))
phi_val = self.__getattribute__("phase"+str(n))
if phi_val != None:
if type(phi_val) == float:
fphi_str += " {0:.16g}".format(float(phi_val))
else:
fphi_str += " {0}".format(phi_val)
senstype = self.senstype
if senstype is None:
senstype = ""
rtn.append("pd{0}{1} {2}{3} {4}{5}".format(senstype, self.num_demods, self.name, fphi_str, self.node.name, alt_str))
self._getScaleCmds(rtn)
if self.pdtype != None:
rtn.append("pdtype {0} {1}".format(self.name, self.pdtype))
for p in self._params:
rtn.extend(p.getFinesseText())
return rtn
class qnoised(pd):
def __init__(self, name, num_demods, node_name, alternate_beam=False, pdtype=None, **kwargs):
super(qnoised, self).__init__(name, num_demods, node_name, alternate_beam=alternate_beam, pdtype=pdtype, **kwargs)
self.__homangle = AttrParam("homangle", self, None)
@property
def homangle(self): return self.__homangle
@homangle.setter
def homangle(self, value): self.__homangle.value = value
@pd.pdtype.setter
def pdtype(self, value):
raise pkex.BasePyKatException("Setting pdtype is not possible with qnoised detectors")
def parseAttributes(self, values):
for key in values.keys():
if key in ["homangle"]:
self.__homangle.value = values[key]
else:
raise pkex.BasePyKatException("No attribute {0} for qnoised".format(key))
@staticmethod
def parseFinesseText(text):
values = text.split()
if len(values) <= 3:
raise pkex.BasePyKatException("qnoised code format incorrect '{0}' (2)".format(text))
demods = int(values[2])
if len(values) <= 4 and demods > 0:
raise pkex.BasePyKatException("qnoised code format incorrect '{0}' (2)".format(text))
elif len(values) > 4 and demods == 0:
raise pkex.BasePyKatException("qnoised code format incorrect '{0}' (3)".format(text))
num_f_phs = len(values) - 4
expected_f_phs = demods * 2
if not (num_f_phs == expected_f_phs or num_f_phs == (expected_f_phs-1)):
raise pkex.BasePyKatException("qnoised code format incorrect '{0}' (4)".format(text))
f = values[3:len(values)-1:2]
phs = values[4:len(values)-1:2]
dict = {}
for i in range(len(f)):
dict['f{0}'.format(i+1)] = f[i]
for i in range(len(phs)):
dict['phase{0}'.format(i+1)] = phs[i]
node = values[-1]
alt_beam = node[-1] == '*'
if alt_beam:
node = node[0:-1]
if values[0].endswith('S'):
sens='S'
elif values[0].endswith('N'):
sens='N'
else:
sens=None
return qnoised(values[1], demods, node, senstype=sens, alternate_beam=alt_beam, **dict)
def getFinesseText(self) :
rtn = []
if self.enabled:
alt_str = ""
fphi_str = ""
if self.alternate_beam:
alt_str = "*"
for n in range(1, 1+self.num_demods):
_f = self.__getattribute__("f"+str(n))
if _f == "$fs":
fphi_str += " $fs"
else:
fphi_str += " {0:.16g}".format(float(_f))
phi_val = self.__getattribute__("phase"+str(n))
if phi_val != None:
if type(phi_val) == float:
fphi_str += " {0:.16g}".format(float(phi_val))
else:
fphi_str += " " + str(phi_val)
senstype = self.senstype
if senstype is None:
senstype = ""
rtn.append("qnoised{5} {0} {1} {2} {3}{4}".format(self.name, self.num_demods, fphi_str, self.node.name, alt_str, senstype))
self._getScaleCmds(rtn)
for p in self._params:
rtn.extend(p.getFinesseText())
return rtn
class qshot(pd):
def __init__(self, name, num_demods, node_name, alternate_beam=False, **kwargs):
super(qshot, self).__init__(name, num_demods, node_name, alternate_beam=alternate_beam, pdtype=None, **kwargs)
@pd.pdtype.setter
def pdtype(self, value):
raise pkex.BasePyKatException("Setting pdtype is not possible with qshot detectors")
@pd.senstype.setter
def senstype(self,value):
raise pkex.BasePyKatException("qshot detector has no sensitvity type")
@staticmethod
def parseFinesseText(text):
values = text.split()
if len(values) <= 3:
raise pkex.BasePyKatException("qshot code format incorrect '{0}' (2)".format(text))
demods = int(values[2])
if len(values) <= 4 and demods > 0:
raise pkex.BasePyKatException("qshot code format incorrect '{0}' (2)".format(text))
elif len(values) > 4 and demods == 0:
raise pkex.BasePyKatException("qshot code format incorrect '{0}' (3)".format(text))
num_f_phs = len(values) - 4
expected_f_phs = demods * 2
if not (num_f_phs == expected_f_phs or num_f_phs == (expected_f_phs-1)):
raise pkex.BasePyKatException("qshot code format incorrect '{0}' (4)".format(text))
f = values[3:len(values)-1:2]
phs = values[4:len(values)-1:2]
dict = {}
for i in range(len(f)):
dict['f{0}'.format(i+1)] = f[i]
for i in range(len(phs)):
dict['phase{0}'.format(i+1)] = phs[i]
node = values[-1]
alt_beam = node[-1] == '*'
if alt_beam:
node = node[0:-1]
if values[0].endswith('S'):
sens='S'
elif values[0].endswith('N'):
sens='N'
else:
sens=None
return qshot(values[1], demods, node, senstype=sens, alternate_beam=alt_beam, **dict)
def getFinesseText(self) :
rtn = []
if self.enabled:
alt_str = ""
fphi_str = ""
if self.alternate_beam:
alt_str = "*"
for n in range(1, 1+self.num_demods):
_f = self.__getattribute__("f"+str(n))
if _f == "$fs":
fphi_str += " $fs"
else:
fphi_str += " {0:.16g}".format(float(_f))
phi_val = self.__getattribute__("phase"+str(n))
if phi_val != None:
if type(phi_val) == float:
fphi_str += " {0:.16g}".format(float(phi_val))
else:
fphi_str += " " + str(phi_val)
senstype = self.senstype
if senstype is None:
senstype = ""
rtn.append("qshot{5} {0} {1} {2} {3}{4}".format(self.name, self.num_demods, fphi_str, self.node.name, alt_str,senstype))
self._getScaleCmds(rtn)
for p in self._params:
rtn.extend(p.getFinesseText())
return rtn
class hd(Detector2):
def __init__(self, name, phase, node1_name, node2_name):
BaseDetector.__init__(self, name, (node1_name, node2_name), max_nodes=2)
self.__phase = Param("phase", self, phase)
@property
def phase(self): return self.__phase
@phase.setter
def phase(self, value): self.__phase.value = value
def parseAttributes(self, values):
raise pkex.BasePyKatException("hd detector %s has no attributes to set" % self.name)
@staticmethod
def parseFinesseText(text):
values = text.split()
return hd(values[1], float(values[2]), str(values[3]), str(values[4]))
def getFinesseText(self):
rtn = []
if self.enabled:
n1 = self.node1.name
n2 = self.node2.name
if self._alternate_beam[0]: n1 += "*"
if self._alternate_beam[1]: n2 += "*"
rtn.append("hd {0} {1} {2} {3}".format(self.name, self.phase, n1, n2))
self._getScaleCmds(rtn)
for p in self._params:
rtn.extend(p.getFinesseText())
return rtn
class qhd(Detector2):
def __init__(self, name, phase, node1_name, node2_name, sensitivity=""):
BaseDetector.__init__(self, name, (node1_name, node2_name), max_nodes=2)
self.__phase = Param("phase", self, phase)
self.sensitivity = sensitivity
@property
def phase(self): return self.__phase
@phase.setter
def phase(self, value): self.__phase.value = value
@property
def sensitivity(self):
return self.__sensitivity
@sensitivity.setter
def sensitivity(self, value):
if value == 'S' or value == 'N':
self.__sensitivity = value
elif value is None or value == '':
self.__sensitivity = ""
else:
raise pkex.BasePyKatException("qhd (%s) sensitivity option '%s' is not available, use either 'S' or 'N'." % (self.name, value))
def parseAttributes(self, values):
raise pkex.BasePyKatException("hd detector %s has no attributes to set" % self.name)
@staticmethod
def parseFinesseText(text):
values = text.split()
sens = values[0][-1]
if sens != 'S' and sens != 'N':
sens = None
return qhd(values[1], float(values[2]), str(values[3]), str(values[4]), sensitivity = sens)
def getFinesseText(self):
rtn = []
if self.enabled:
n1 = self.node1.name
n2 = self.node2.name
if self._alternate_beam[0]: n1 += "*"
if self._alternate_beam[1]: n2 += "*"
rtn.append("qhd{4} {0} {1} {2} {3}".format(self.name, self.phase, n1, n2, self.sensitivity))
self._getScaleCmds(rtn)
for p in self._params:
rtn.extend(p.getFinesseText())
return rtn