Commit 4d173029 authored by Daniel Brown's avatar Daniel Brown
Browse files

adding in fsig command (not parsing yet). See example in bin...

adding in fsig command (not parsing yet). See example in bin folder. Also made component variable an optional argument for xaxis and x2axis which will break previous scripts. Did this as when setting the parameter to tune, the Param object contains whatever component owns that parameter so no need to pass it twice. Also stops someone passing a parameter not for the component stated.
parent b705ae7b
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 2 0 n1
m m1 0.99 0.01 0 n1 n2
s cav1 1200 n2 n3
m m2 0.99 0.01 -0.1 n3 n4
attr m2 m 1 # mech sus1
ad up_refl 0 n1
ad low_refl 0 n1
qd refl_A 0 0 n1
qd refl_Q 0 90 n1
qd tran_A 0 0 n4
qd tran_Q 0 90 n4
put up_refl f $x1
put low_refl f $mx1
yaxis log re:im
kat = finesse.kat(kat_code=code)
kat.signals.apply(kat.l1.power, 1, 0)
kat.signals.apply(kat.m1.phi, 1, 90)
kat.add(xaxis('log', [1, 1000], kat.signals.f, 100))
out =, printerr=0)
# using real and imag part compute the complex value of the upper and lower sidebands
a_up = out.y[:,0] + out.y[:,1]*1j
a_lo = out.y[:,2] + out.y[:,3]*-1j
pl.loglog(out.x, np.abs(a_up + a_lo), out.x, np.abs((a_up - a_lo) / (1j)))
pl.title("Reflection quadratures with no relative carrier phase")
\ No newline at end of file
......@@ -10,6 +10,7 @@ import exceptions
from components import *
from structs import *
from pykat.param import Param, putter
import pykat.exceptions as pkex
class Command(object):
def __init__(self):
......@@ -50,7 +51,7 @@ class gauss(object):
class xaxis(Command):
def __init__(self, scale, limits, comp, param, steps, axis_type="xaxis"):
def __init__(self, scale, limits, param, steps, comp=None, axis_type="xaxis"):
self._axis_type = axis_type
self.x = putter("x1")
......@@ -79,20 +80,17 @@ class xaxis(Command):
self.steps = int(steps)
# if entered component is a string then just store and use that
if isinstance(comp, str):
self.__comp = comp
elif not isinstance(comp, Component):
raise exceptions.ValueError("{0} has not been added".format(comp))
self.__comp = comp
if isinstance(param, str):
self.__param = param
if comp == None:
raise pkex.BasePyKatException("If parameter is set with a string, the comp argument must set the component name")
self.__comp = comp
elif not isinstance(param, Param) :
raise exceptions.ValueError("param argument is not of type Param")
raise pkex.BasePyKatException("param argument is not of type Param")
self.__param = param
self.__comp =
def parseFinesseText(text):
......@@ -108,7 +106,7 @@ class xaxis(Command):
if len(values) != 6:
raise exceptions.RuntimeError("xaxis Finesse code format incorrect '{0}'".format(text))
return xaxis(values[2], [values[3], values[4]], values[0], values[1], values[5], axis_type=axis_type)
return xaxis(values[2], [values[3], values[4]], values[1], values[5], comp=values[0], axis_type=axis_type)
def getFinesseText(self):
# store either the component name of the string provided
......@@ -120,8 +118,8 @@ class xaxis(Command):
min(self.limits), max(self.limits), self.steps, axis_type=self._axis_type);
class x2axis(xaxis):
def __init__(self, scale, limits, comp, param, steps):
xaxis.__init__(self, scale, limits, comp, param, steps, axis_type="x2axis")
def __init__(self, scale, limits, param, steps, comp=None):
xaxis.__init__(self, scale, limits, param, steps, comp=comp, axis_type="x2axis")
self.x = putter("x2") = putter("mx2")
......@@ -158,11 +158,11 @@ class AbstractMirrorComponent(Component):
self.__R = Param("R", self, SIfloat(R))
self.__T = Param("T", self, SIfloat(T))
self.__phi = Param("phi", self, SIfloat(phi))
self.__phi = Param("phi", self, SIfloat(phi), canFsig=True, fsig_name="phs")
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.__xbeta = AttrParam("xbeta", self, SIfloat(xbeta), canFsig=True, fsig_name="x")
self.__ybeta = AttrParam("ybeta", self, SIfloat(ybeta), canFsig=True, fsig_name="y")
self.__mass = AttrParam("mass", self, SIfloat(mass))
self.__r_ap = AttrParam("r_ap", self, SIfloat(r_ap))
......@@ -682,9 +682,9 @@ class laser(Component):
self.__power = Param("P", self, SIfloat(P))
self.__f_offset = Param("f", self, SIfloat(f_offset))
self.__phase = Param("phase", self, SIfloat(phase))
self.__power = Param("P", self, SIfloat(P), canFsig=True, fsig_name="amp")
self.__f_offset = Param("f", self, SIfloat(f_offset), canFsig=True, fsig_name="f")
self.__phase = Param("phase", self, SIfloat(phase), canFsig=True, fsig_name="phs")
self.__noise = AttrParam("noise", self, 0)
......@@ -40,6 +40,7 @@ from pykat.components import Component
from pykat.commands import Command, xaxis
from pykat.gui.gui import pyKatGUI
from pykat.SIfloat import *
from pykat.param import Param, AttrParam
import pykat.exceptions as pkex
......@@ -127,7 +128,98 @@ class katRun2D(object):
return self.z[idx].squeeze()
raise pkex.BasePyKatException("No output by the name {0} found".format(str(value)))
class Signals:
class fsig:
def __init__(self, param, name, amplitude, phase):
self._params = []
self.__target = param
self.__name = name
self.__amplitude = Param("amp", self, SIfloat(amplitude))
self.__phase = Param("phase", self, SIfloat(phase))
# unfortunatenly the target names for fsig are not the same as the
# various parameter names of the components, e.g. mirror xbeta is x
# for fsig. So we need to check here what type of component we are targetting
# and then based on the parameter specfied get the name
if not param.canFsig:
raise pkex.BasePyKatException("Cannot fsig parameter {1} on component {0}".format(str(param._owner),
def _register_param(self, param):
def name(self): return self.__name
def amplitude(self): return self.__amplitude
def phase(self): return self.__phase
def target(self): return self.__target.fsig_name
def owner(self): return
def getFinesseText(self):
rtn = []
for p in self._params:
return rtn
def name(self):
# if we don't have any signals yet then use a dummy name
# however we need to always tune a real fsig command
# so need to get the name of at least one of them
# as if you tune one you tune them all
if len(self.targets) == 0:
return "signal"
return self.targets[0].name
def f(self): return self.__f
def __init__(self):
self.targets = []
self._params = []
self.__f = Param("f", self, 1)
def _register_param(self, param):
def apply(self, target, amplitude, phase, name=None):
if target == None:
raise pkex.BasePyKatException("No target was specified for signal to be applied")
if name == None:
name = "sig_" + "_" +
self.targets.append(Signals.fsig(target, name, amplitude, phase))
def getFinesseText(self):
rtn = []
for t in self.targets:
rtn.append("fsig {name} {comp} {target} {frequency} {phase} {amplitude}".format(name =, comp=t.owner,, frequency=str(self.f), phase=str(t.phase), amplitude=str(t.amplitude)))
for p in self._params:
return rtn
class Block:
def __init__(self, name):
self.__name = name
......@@ -154,10 +246,11 @@ class kat(object):
self.__tempdir = tempdir
self.__tempname = tempname
self.pykatgui = None
# initialise default block
self.__currentTag= NO_BLOCK
self.__blocks[NO_BLOCK] = Block(NO_BLOCK)
self.__signals = Signals()
# initialise default block
self.__currentTag= NO_BLOCK
self.__blocks[NO_BLOCK] = Block(NO_BLOCK)
# Various options for running finesse, typicaly the commands with just 1 input
# and have no name attached to them.
......@@ -181,6 +274,9 @@ class kat(object):
cls = type(self)
self.__class__ = type(cls.__name__, (cls,), {})
def signals(self): return self.__signals
def maxtem(self): return self.__maxtem
......@@ -689,6 +785,16 @@ class kat(object):
out.append(txt + "\n")
# now get any signal commands
txt = self.signals.getFinesseText()
if txt != None:
if isinstance(txt,list):
for t in txt: out.append(t+ "\n")
out.append(txt + "\n")
if self.scale != None and self.scale !='': out.append("scale {0}\n".format(self.scale))
if self.phase != None: out.append("phase {0}\n".format(self.phase))
if self.maxtem != None: out.append("maxtem {0}\n".format(self.maxtem))
......@@ -57,13 +57,22 @@ class putter(object):
class Param(putable, putter):
def __init__(self, name, owner, value, 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):
self._name = name
self._owner = owner
self._value = value
self._isPutter = isPutter
self._isTunable = isTunable
self._canFsig = False
if canFsig:
self._canFsig = True
if fsig_name == None:
raise pkex.BasePyKatException("If parameter is a possible fsig target the fsig_name argument must be set")
self.__fsig_name = fsig_name
if isPutter:
if var_name == None:
......@@ -73,7 +82,13 @@ class Param(putable, putter):
if isPutable:
putable.__init__(self,, name, isPutable)
def canFsig(self): return self._canFsig
def fsig_name(self): return self.__fsig_name
def name(self): return self._name
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment