diff --git a/examples/lkat_trace.py b/examples/lkat_trace.py index e29fa60e0c2fe88849fbafa479bfb57bc0062d0d..1abd65245c1cfa767aa92825c6c11b598bcd484c 100644 --- a/examples/lkat_trace.py +++ b/examples/lkat_trace.py @@ -1,10 +1,14 @@ import pykat - +import pylab +import numpy +import ctypes +import pylibkat + cmd = """ l l1 1 0 n1 s s1 1 n1 n2 m m1 0.99 0.01 0 n2 n3 -s s2 999 n3 n4 +s s2 1 n3 n4 m m2 0.99 0.01 0 n4 n5 pd circ n3 @@ -14,6 +18,8 @@ maxtem 0 attr m1 Rc 0 attr m2 Rc 1000 cav c1 m1 n3 m2 n4 +retrace force + """ kat = pykat.finesse.kat() @@ -26,3 +32,46 @@ print "n1 qx =", info["n1"].qx print "Cavity info ", info["c1"] +import numpy + +Lengths = numpy.linspace(1, 999, 10000) +g_factors = [] + +lkat = ctypes.PyDLL("libkat.dylib") + +try: + lkat._pykat_preInit() # must always be called, sets up + # exception handling and such no simulation + # specifc code here + + # reads in the kat.ini and setups up other parts + lkat._pykat_init() + + cmd = "".join(kat.generateKatScript()) + + lkat._pykat_setup(cmd) + + inter = pylibkat.interferometer.in_dll(lkat, "inter") + s2 = inter.space_list[1] + cav = inter.cavity_list[0] + + inter.rebuild = 2 + inter.retrace = 1 + s2.rebuild = 2 + + for L in Lengths: + s2.L = L + lkat._pykat_step() + + g_factors.append(cav.stability_x) + +except Exception as ex: + print "Exception caught in python: ", ex.message +finally: + # This should always be called no matter what + lkat._pykat_finish(0) + +pylab.plot(Lengths, g_factors) +pylab.show() + + diff --git a/pykat/commands.py b/pykat/commands.py index fa254fbb4f71500b67035f759c9156008437fd1c..602c423f270113f9e8b55c47483da4c068813513 100644 --- a/pykat/commands.py +++ b/pykat/commands.py @@ -158,18 +158,18 @@ class xaxis(Command): raise pkex.BasePyKatException("param argument is not of type Param") else: self.__param = param - self.__comp = param._owner().name + self.__comp = param._owner() @property def param(self): return self.__param @param.setter def param(self, value): - if not isinstance(value, Param): - raise pkex.BasePyKatException("param argument is not of type Param") - else: - self.__param = value - self.__comp = value._owner().name - + if not isinstance(value, Param): + raise pkex.BasePyKatException("param argument is not of type Param") + else: + self.__param = value + self.__comp = value._owner() + @staticmethod def parseFinesseText(text): values = text.split() @@ -188,9 +188,9 @@ class xaxis(Command): def getFinesseText(self): # store either the component name of the string provided - comp_name = self.__comp.name if isinstance(self.__comp, Component) else self.__comp + comp_name = self.__comp.name if hasattr(self.__comp, "name") else self.__comp param_name = self.__param.name if isinstance(self.__param, Param) else self.__param - + return '{axis_type} {0} {1} {2} {3} {4} {5}'.format( comp_name, param_name, self.scale, min(self.limits), max(self.limits), self.steps, axis_type=self._axis_type); diff --git a/pykat/components.py b/pykat/components.py index fa29d7b795438f4edb1381f9899daeb3f967ffde..8dac0dcdc6ca9e50abf31e0fd8d54d68962fdfee 100644 --- a/pykat/components.py +++ b/pykat/components.py @@ -170,7 +170,7 @@ class Component(object): class AbstractMirrorComponent(Component): __metaclass__ = abc.ABCMeta - + def __init__(self, name, R=None, T=None, L=None, phi=0, Rcx=None, Rcy=None, xbeta=None, ybeta=None, mass=None, r_ap=None, Ix=None, Iy=None, zmech=None, rxmech=None, rymech=None): super(AbstractMirrorComponent, self).__init__(name) @@ -203,6 +203,26 @@ class AbstractMirrorComponent(Component): self.__rxmech = AttrParam("rxmech", self, rxmech) self.__rymech = AttrParam("rymech", self, rymech) + self.__z = Param("z", self, 0, canFsig=True, isPutable=False, isPutter=False, isTunable=False, fsig_name="z") + self.__rx = Param("rx", self, 0, canFsig=True, isPutable=False, isPutter=False, isTunable=False, fsig_name="rx") + self.__ry = Param("ry", self, 0, canFsig=True, isPutable=False, isPutter=False, isTunable=False, fsig_name="ry") + self.__Fz = Param("Fz", self, 0, canFsig=True, isPutable=False, isPutter=False, isTunable=False, fsig_name="Fz") + self.__Frx = Param("Frx", self, 0, canFsig=True, isPutable=False, isPutter=False, isTunable=False, fsig_name="Frx") + self.__Fry = Param("Fry", self, 0, canFsig=True, isPutable=False, isPutter=False, isTunable=False, fsig_name="Fry") + + @property + def z(self): return self.__z + @property + def Fz(self): return self.__Fz + @property + def rx(self): return self.__rx + @property + def Frx(self): return self.__Frx + @property + def ry(self): return self.__ry + @property + def Fry(self): return self.__Fry + @property def L(self): return self.__L @L.setter @@ -501,7 +521,7 @@ class space(Component): self.__gx.value = values[key] elif key in ["gy", "gouyy"]: self.__gy.value = values[key] - elif key in ["g, gouy"]: + elif key in ["g","gouy"]: self.__gx.value = values[key] self.__gy.value = values[key] else: @@ -672,7 +692,7 @@ class grating(Component): return self._QItem class isolator(Component): - def __init__(self, name, node1, node2, node3="dump", S = 0): + def __init__(self, name, node1, node2, S = 0, node3="dump"): Component.__init__(self, name) self._requested_node_names.append(node1) @@ -698,7 +718,7 @@ class isolator(Component): if len(values) == 4: return isolator(values[0], values[2], values[3], values[1]) elif len(values) == 5: - return isolator(values[0], values[2], values[3], values[4], values[1]) + return isolator(values[0], values[2], values[3], node3=values[4], S=values[1]) else: raise pkex.BasePyKatException("Isolator Finesse code format incorrect '{0}'".format(text)) diff --git a/pykat/detectors.py b/pykat/detectors.py index ae8bde8c7b729491c53d64802b79416af3683c39..6ebad0ab31e0ffcc8085b2f6ead0001da9bb70b6 100644 --- a/pykat/detectors.py +++ b/pykat/detectors.py @@ -145,7 +145,7 @@ class ad(Detector): if self.mode == 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}".fomat(name=self.name, n=str(self.mode[0]), m=str(self.mode[1]), f=str(self.f.value), node=self.node.name, alt=alt)) + 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()) @@ -450,7 +450,7 @@ class qnoised(pd): return rtn -class qnoised(pd): +class qshot(pd): def __init__(self, name, num_demods, node_name, alternate_beam=False, **kwargs): super(qnoised, self).__init__(name, num_demods, node_name, alternate_beam=alternate_beam, pdtype=None, senstype=None, **kwargs) diff --git a/pykat/finesse.py b/pykat/finesse.py index 9abd7aa3222628cbd8544a6387c69a324055c6a7..f4de636cf8cd51bb12d88de5d782ee45f7dd1636 100644 --- a/pykat/finesse.py +++ b/pykat/finesse.py @@ -33,6 +33,7 @@ import pickle import pykat import warnings import re +import math import itertools import ctypes @@ -154,8 +155,9 @@ class katRun(object): self.ylabels = None self.katScript = None self.katVersion = None + self.yaxis = None - def saveKatRun(self, filename): + def savekatRun(self, filename): with open(filename,'w') as outfile: pickle.dump(self, outfile) @@ -173,10 +175,17 @@ class katRun(object): if len(idx) > 0: out = self.y[:, idx] + if self.yaxis == "abs:deg": + out = self.y[:, idx[0]] * np.exp(1j*math.pi*self.y[:, idx[1]]/180.0) + elif self.yaxis == "re:im": + out = self.y[:, idx[0]] + 1j*self.y[:, idx[1]] + + out.squeeze() + if out.size == 1: - return float(out) + return out[0] else: - return out.squeeze() + return out else: raise pkex.BasePyKatException("No output by the name '{0}' found in the output".format(str(value))) @@ -211,6 +220,7 @@ class katRun2D(object): else: raise pkex.BasePyKatException("No output by the name {0} found".format(str(value))) + class Signals(object): class fsig(object): def __init__(self, param, name, amplitude, phase): @@ -371,6 +381,7 @@ class kat(object): self.__maxtem = None self.__noxaxis = None self.__time_code = None + self.__yaxis = "abs" # default yaxis if kat_code != None and kat_file != None: raise pkex.BasePyKatException("Specify either a Kat file or some Kat code, not both.") @@ -387,6 +398,17 @@ class kat(object): @property def signals(self): return self.__signals + yaxis_options = ["abs:deg","db:deg","re:im","abs","db","deg"] + @property + def yaxis(self): return self.__yaxis + @yaxis.setter + def yaxis(self, value): + + if not str(value) in self.yaxis_options: + raise pkex.BasePyKatException("yaxis value '{0}' is not a value option. Valid options are: {1}".format(str(value), ",".join(self.yaxis_options) )) + + self.__yaxis = str(value) + @property def trace(self): return self.__trace @trace.setter @@ -479,11 +501,13 @@ class kat(object): # check if we have a var/constant in this line if line.find('$') >= 0: for key in constants.keys(): - if line.find('$'+key) > -1: + if line.find('$'+key+' ') > -1: + constants[key].usedBy.append(line) + line = line.replace('$'+key+' ', str(constants[key].value)+ ' ') + elif line.endswith('$'+key): constants[key].usedBy.append(line) line = line.replace('$'+key, str(constants[key].value)) - commands_new.append(line) self.constants = constants @@ -578,6 +602,10 @@ class kat(object): after_process.append(line) elif(first == "noxaxis"): self.noxaxis = True + elif(first == "yaxis"): + v = line.split() + + self.yaxis = v[-1] elif(first == "phase"): v = line.split() if len(v) != 2: @@ -589,9 +617,9 @@ class kat(object): if len(v) != 2: raise pkex.BasePyKatException("maxtem command `{0}` is incorrect.".format(line)) else: - if v[1] == "off": - self.maxtem = -1 - else: + if v[1] == "off": + self.maxtem = -1 + else: self.maxtem = int(v[1]) elif(first == "trace"): v = line.split() @@ -614,9 +642,15 @@ class kat(object): elif(first == "gnuterm" or first == "pyterm"): if self.verbose: print "Ignoring Gnuplot/Python terminal command '{0}'".format(line) + #elif(first == "fsig"): + # after_process.append(line) + elif(first == "noplot"): + obj = line + self.__blocks[self.__currentTag].contents.append(line) else: if self.verbose: 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[self.__currentTag].contents.append(line) @@ -659,7 +693,7 @@ class kat(object): raise pkex.BasePyKatException("pdtype command `{0}` is incorrect.".format(line)) elif(first == "attr"): v = line.split() - + if len(v) < 4: raise pkex.BasePyKatException("attr command `{0}` is incorrect.".format(line)) else: @@ -679,6 +713,21 @@ class kat(object): comp.parseAttributes(kv) + elif(first == "fsig"): + + v = line.split() + + if v[2] in self.__components: + comp = self.__components[v[1]] + else: + raise pkex.BasePyKatException("Could not find the component '{0}' for attr command in line '{1}'".format(v[1], line)) + + + #kat.siganls.apply() + + else: + raise pkex.BasePyKatException("Haven't handled parsing of '{0}'".format(line)) + self.__currentTag = NO_BLOCK def saveScript(self, filename=None): @@ -749,6 +798,7 @@ class kat(object): else: r = katRun() + r.yaxis = self.yaxis r.katScript = "".join(self.generateKatScript()) # create a kat file which we will write the script into @@ -1112,6 +1162,9 @@ class kat(object): if self.noxaxis == True: out.append("noxaxis\n") + if self.yaxis != None: + out.append("yaxis {0}\n".format(self.yaxis)) + # ensure we don't do any plotting. That should be handled # by user themselves out.append("gnuterm no\n") @@ -1210,6 +1263,7 @@ class kat(object): getCavities=getCavities, getNodes=getNodes, getSpaces=getSpaces) p.start() p.join() + p.terminate() # return a local copy of the trace information dictionary return dict(trace_info) diff --git a/pykat/gui/gui.py b/pykat/gui/gui.py index a6cdb947759dd33e23b9f254a83bf9428177b6c9..006709115c6afe618c697b1c7703e1f6a58f5f7c 100644 --- a/pykat/gui/gui.py +++ b/pykat/gui/gui.py @@ -116,7 +116,7 @@ class pyKatGUI(QtGui.QMainWindow, qt_gui.Ui_MainWindow): def addMirror(self, x,y): name = self.kat.getNewComponentName('m') n = self.kat.getNewNodeNames('n',2) - m = pykat.components.mirror(name,n[0],n[1]) + m = pykat.components.mirror(name,n[0],n[1],R=0.5,T=0.5) self.kat.add(m) self.addComponentToScene(m,x,y) diff --git a/pykat/param.py b/pykat/param.py index cd732b165006db3dc1c09d47a04e0216da2516ce..b5c9566860cf90cb92fde2856dbfbfec58b5307b 100644 --- a/pykat/param.py +++ b/pykat/param.py @@ -84,11 +84,10 @@ class Param(putable, putter): if var_name == None: var_name = "var_{0}_{1}".format(owner.name, name) - putter.__init__(self, var_name, isPutter) + putter.__init__(self, var_name, isPutter) - if isPutable: - putable.__init__(self, owner.name, name, isPutable) - + putable.__init__(self, owner.name, name, isPutable) + @property def canFsig(self): return self._canFsig diff --git a/pykat/utilities/optics/gaussian_beams.py b/pykat/utilities/optics/gaussian_beams.py index 2708735b99ad3ad779bb79dc778eac4d1b5d2da6..e49e704c9c12b40c7a2f184e8faeeb3a3783b17c 100644 --- a/pykat/utilities/optics/gaussian_beams.py +++ b/pykat/utilities/optics/gaussian_beams.py @@ -2,6 +2,7 @@ import pykat.exceptions as pkex import numpy import math import copy +from pykat.SIfloat import SIfloat class gauss_param(object): """ @@ -39,11 +40,11 @@ class gauss_param(object): elif len(kwargs) == 2: if "w0" in kwargs and "z" in kwargs: - q = float(kwargs["z"]) + 1j *float(math.pi*float(kwargs["w0"])**2/(self.__lambda/self.__nr) ) + q = SIfloat(kwargs["z"]) + 1j *float(math.pi*SIfloat(kwargs["w0"])**2/(self.__lambda/self.__nr) ) elif "z" in kwargs and "zr" in kwargs: - q = float(kwargs["z"]) + 1j *float(kwargs["zr"]) + q = SIfloat(kwargs["z"]) + 1j *SIfloat(kwargs["zr"]) elif "rc" in kwargs and "w" in kwargs: - one_q = 1 / float(kwargs["rc"]) - 1j * self.__lamda / (math.pi * self.__nr * float(kwargs["w"])**2) + one_q = 1 / SIfloat(kwargs["rc"]) - 1j * self.__lamda / (math.pi * self.__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")