def registerComponentNodes(self, comp, node_names, change_callback): """ For a given component we create some nodes or get existing ones and attach them to this component. Also specify a callback function that is called whenever the nodes attached to this component are changed , e.g. connected, disconnected, name change, etc. """ if not isinstance(comp, Component): raise pkex.BasePyKatException( "comp argument is not of type Component") if comp.id in self.__componentNodes: raise pkex.BasePyKatException( "Component has already been registered") list = [] for name in node_names: n = self.createNode(name) self.__connectNodeToComp(n, comp, do_callback=False) list.append(n) self.__componentNodes[comp.id] = tuple(list) self.__componentCallback[comp.id] = change_callback change_callback()
def __init__(self, wavelength=1064e-9, nr=1, *args, **kwargs): if self.__class__ == gauss_param or self.__class__ == beam_param: warnings.warn("Name changed. Use BeamParam instead of gauss_param or beam_param.") self.__q = None self.__lambda = SIfloat(wavelength) self.__nr = SIfloat(nr) if len(args) == 1: self.__q = complex(args[0]) elif len(kwargs) == 1: if "q" in kwargs: self.__q = complex(kwargs["q"]) else: raise pkex.BasePyKatException("Must specify: z and w0 or z and zr or rc and w or q, to define the beam parameter") elif len(kwargs) == 2: if "w0" in kwargs and "z" in kwargs: q = SIfloat(kwargs["z"]) + 1j * math.pi*SIfloat(kwargs["w0"])**2/(self.__lambda/self.__nr) elif "z" in kwargs and "zr" in kwargs: q = SIfloat(kwargs["z"]) + 1j * SIfloat(kwargs["zr"]) elif "rc" in kwargs and "w" in kwargs: one_q = 1 / SIfloat(kwargs["rc"]) - 1j * SIfloat(wavelength) / (math.pi * SIfloat(nr) * SIfloat(kwargs["w"])**2) q = 1/one_q else: raise pkex.BasePyKatException("Must specify: z and w0 or z and zr or rc and w or q, to define the beam parameter") self.__q = q else: raise pkex.BasePyKatException("Incorrect usage for gauss_param constructor")
def __connectNodeToComp(self, node, comp, do_callback=True): """ This is an internal function used to create connections between nodes """ if node.id in self.__nodeComponents: comps = self.__nodeComponents[node.id] else: comps = (None, ) * 2 if len(comps) >= 2 and comps[0] != None and comps[1] != None: raise pkex.BasePyKatException( "Node '{0}' is already connected to 2 components ({1}, {2})". format(node.name, comps[0], comps[1])) l = list(comps) if l[0] is None: l[0] = comp elif l[1] is None: l[1] = comp else: raise pkex.BasePyKatException("Connected to two coponents already") self.__nodeComponents[node.id] = tuple(l) if do_callback: self.__componentCallback[comp.id]()
def convertToFloat(value): try: # first just try and convert the value return float(value) except ValueError as ex: # Catch any casting exeception value = value.strip() # only the last value can be an SI scaling letter last = value[-1] if last in __suffix: # remove last character and append the SI scaling value = value[0:-1] + __suffix[last] else: raise pkex.BasePyKatException( "Could not convert SI scaling in '{0}' to a float".format( value)) try: return float(value) except ValueError as ex: raise pkex.BasePyKatException( "Unable to convert '{0}' into a float".format(value))
def __init__(self, name, owner, value, canFsig=False, fsig_name=None, fsig_name_options=[], isPutable=True, isPutter=True, isTunable=True, var_name=None, register=True): self._unfreeze() self._name = name self._registered = register self._owner = weakref.ref(owner) self._isPutter = isPutter self._isTunable = isTunable self._canFsig = False self._isConst = False self._constName = None if self._registered: self._owner()._register_param(self) if canFsig: self._canFsig = True if not pykat.isContainer(fsig_name_options): raise pkex.BasePyKatException( "fsig name options should be a list of names") if fsig_name is None: raise pkex.BasePyKatException( "If parameter is a possible fsig target the fsig_name argument must be set" ) self.__fsig_name = fsig_name self.__fsig_name_options = list(fsig_name_options) if fsig_name not in self.__fsig_name_options: self.__fsig_name_options.append(fsig_name) if isPutter: if var_name is None: var_name = "var_{0}_{1}".format(owner.name, name) putter.__init__(self, var_name, owner, isPutter) putable.__init__(self, owner.name, name, isPutable) self.value = value self._freeze()
def parseFinesseText(text): values = text.split() if values[0] != "x2axis" and values[0] != "x2axis*": raise pkex.BasePyKatException("'{0}' not a valid Finesse xaxis command".format(text)) axis_type = values[0] values.pop(0) # remove initial value if len(values) != 6: raise pkex.BasePyKatException("xaxis Finesse code format incorrect '{0}'".format(text)) return x2axis(values[2], [values[3], values[4]], values[1], values[5], comp=values[0],axis_type=axis_type)
def parseFinesseText(text, kat): values = text.split() if not values[0].startswith("gauss") or (len(values) != 6 and len(values) != 8): raise pkex.BasePyKatException("'{0}' not a valid Finesse gauss command".format(text)) name = values[1] component = values[2] node = values[3] # 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.gauss_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)) if not values[0].endswith("*"): if len(values) == 6: gp = BeamParam(kat.lambda0, w0=values[-2], z=values[-1]) elif len(values) == 8: gpx = BeamParam(kat.lambda0, w0=values[-4], z=values[-3]) gpy = BeamParam(kat.lambda0, w0=values[-2], z=values[-1]) elif values[0].endswith("*"): if len(values) == 6: gp = BeamParam(kat.lambda0, z=values[-2], zr=values[-1]) elif len(values) == 8: gpx = BeamParam(kat.lambda0, z=values[-4], zr=values[-3]) gpy = BeamParam(kat.lambda0, z=values[-2], zr=values[-1]) elif values[0].endswith("**"): if len(values) == 6: gp = BeamParam(kat.lambda0, w=values[-2], rc=values[-1]) elif len(values) == 8: gpx = BeamParam(kat.lambda0, w=values[-4], rc=values[-3]) gpy = BeamParam(kat.lambda0, w=values[-2], rc=values[-1]) else: raise pkex.BasePyKatException("Unexpected ending to gauss command '{0}'".format(text)) if len(values) == 6: kat.nodes[node].setGauss(kat.components[component], gp) else: kat.nodes[node].setGauss(kat.components[component], gpx, gpy)
def value(self): if self._owner().removed: raise pkex.BasePyKatException( "{0} has been removed from the simulation".format( self._owner().name)) else: if self._isConst: if self._constName[1:] not in self.owner._kat.constants: raise pkex.BasePyKatException( "Parameter {}.{} could not find a Finesse constant called `{}`" .format(self.owner.name, self.name, self._constName)) return self.owner._kat.constants[self._constName[1:]].value else: return self._value
def __init__(self, name, nodes=None, max_nodes=1): self._unfreeze() 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 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 = pd._parse_fphi(f, phs) 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 remove_IMC_HAM2(self, removeIMC, removeHAM2): """ For use with files that have the IMC and HAM2 blocks. Removes the IMC and HAM2 blocks if not required in the model. Reconnects spaces between the laser and HAM2 and PRC. Assumes spaces exists with name and node: sHAM2in and node nIMCout sPRCin and node nHAM2out This function alters the kat object directly. """ if removeHAM2 and not removeIMC: raise pkex.BasePyKatException( "Must remove IMC if removing HAM2 block") if removeIMC: self.kat.removeBlock("IMC") self.kat.cavIMC.remove() self.kat.nodes.replaceNode(self.kat.sHAM2in, 'nIMCout', 'nLaserOut') if removeHAM2: L = self.kat.sFI_IM3.L + self.kat.sIM3_IM4.L + self.kat.sPRCin.L self.kat.removeBlock("HAM2") self.kat.parse(""" s sPRCin 0 nLaserOut nFI1 dbs FI nFI1 nFI2 nFI3 nREFL s sFI_PRM {} nFI3 nPRM1 """.format(L), addToBlock='PRC')
def parseFinesseText(line, kat): v = line.split() if len(v) != 3: raise pkex.BasePyKatException("'{0}' not a valid Finesse variable command".format(line)) return variable(v[1], SIfloat(v[2]))
def __float__(self): if self._owner().removed: raise pkex.BasePyKatException( "{0} has been removed from the simulation".format( self._owner().name)) else: return float(self.value)
def __getitem__(self, value): if str(value) in self.__nodes: return self.__nodes[str(value)] else: raise pkex.BasePyKatException( "The node '%s' could not be found in the network." % str(value))
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
def remove_IMC_HAM2(self, removeIMC, removeHAM2): """ For use with files that have the IMC and HAM2 blocks. Removes the IMC and HAM2 blocks if not required in the model. Reconnects spaces between the laser and HAM2 and PRC. Assumes spaces exists with name and node: sHAM2in and node nIMCout sPRCin and node nHAM2out This function alters the kat object directly. """ if removeHAM2 and not removeIMC: raise pkex.BasePyKatException( "Must remove IMC if removing HAM2 block") if removeIMC: self.kat.removeBlock("IMC") self.kat.cavIMC.remove() self.kat.nodes.replaceNode(self.kat.sHAM2in, 'nIMCout', 'nLaserOut') if removeHAM2: self.kat.removeBlock("HAM2") self.kat.nodes.replaceNode(self.kat.sPRCin, 'nHAM2out', 'nLaserOut')
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()
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
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 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))
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
def scan_REFL_gouy_telescope_gouy_cmds(self, start, end, steps=20, xaxis=1, AB_gouy_diff=None, relative=False): """ This will return commands to scan the REFL gouy telescope gouy phase of the A and B paths. """ if "REFL_gouy_tele" not in self.kat.getBlocks(): raise pkex.BasePyKatException( "\033[91mREFL Gouy phase telescope isn't in the kat object, see kat.IFO.add_REFL_gouy_telescope()\033[0m" ) if xaxis not in [1, 2]: raise pkex.BasePyKatException("xaxis value must be 1 or 2") elif xaxis == 1: xaxis_cmd = "xaxis" elif xaxis == 2: xaxis_cmd = "x2axis" if AB_gouy_diff is None: AB_gouy_diff = self.kat.sWFS_REFL_B.gouy - self.kat.sWFS_REFL_A.gouy if relative: put = "put*" else: put = "put" cmds = ("var REFL_GOUY_SCAN 0\n" "{xaxis} REFL_GOUY_SCAN re lin {start} {end} {steps}\n" "{put} sWFS_REFL_A gx $x{axis}\n" "{put} sWFS_REFL_A gy $x{axis}\n" "func REFL_SCAN_B = $x{axis} + {AB_gouy_diff}\n" "{put} sWFS_REFL_B gx $REFL_SCAN_B\n" "{put} sWFS_REFL_B gy $REFL_SCAN_B\n").format( xaxis=xaxis_cmd, axis=xaxis, start=start, end=end, steps=steps, AB_gouy_diff=AB_gouy_diff, put=put) return cmds
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
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 = pd._parse_fphi(f, phs) 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 _set_node(self, 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 parseFinesseText(line, kat): v = line.split() if len(v) != 6: raise pkex.BasePyKatException("cav command format `{0}` is incorrect".format(line)) if v[2] not in kat.components: raise pkex.BasePyKatException("cav command `{0}` refers to component `{1}` which does not exist".format(line, v[2])) if v[4] not in kat.components: raise pkex.BasePyKatException("cav command `{0}` refers to component `{1}` which does not exist".format(line, v[4])) if v[3] not in kat.nodes.getNodes(): raise pkex.BasePyKatException("cav command `{0}` refers to node `{1}` which does not exist".format(line, v[3])) if v[5] not in kat.nodes.getNodes(): raise pkex.BasePyKatException("cav command `{0}` refers to node `{1}` which does not exist".format(line, v[5])) c1 = getattr(kat, v[2]) c2 = getattr(kat, v[4]) n1 = getattr(kat.nodes, v[3]) n2 = getattr(kat.nodes, v[5]) if not hasattr(c1, n1.name): raise pkex.BasePyKatException("cav command `{0}`: node `{1}` is not attached to `{2}`".format(line, n1.name, c1.name)) if not hasattr(c2, n2.name): raise pkex.BasePyKatException("cav command `{0}`: node `{1}` is not attached to `{2}`".format(line, n2.name, c2.name)) return pykat.commands.cavity(v[1], c1, n1, c2, n2)
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 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 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 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