From 9ca9dcbae9a655561c30c6656d0f97b7982d56c8 Mon Sep 17 00:00:00 2001 From: Daniel Brown <ddb@star.sr.bham.ac.uk> Date: Thu, 19 Feb 2015 12:54:17 +0000 Subject: [PATCH] adding in Optivis functionality --- examples/LLO_matched.kat | 44 +--------- examples/optivis_aligo_ex.py | 6 +- examples/optivis_ex.py | 16 +++- pykat/components.py | 98 ++++++++++++++++++---- pykat/finesse.py | 152 +++++++++++++++++++++++++++++------ 5 files changed, 232 insertions(+), 84 deletions(-) diff --git a/examples/LLO_matched.kat b/examples/LLO_matched.kat index ab66558..b9c165c 100644 --- a/examples/LLO_matched.kat +++ b/examples/LLO_matched.kat @@ -379,47 +379,9 @@ noplot AS_f1_P noplot AS_f1_Q noplot AS_f2_P noplot AS_f2_Q -noplot P_DC +#noplot P_DC ########################################################################### %%% FTend errsigs - -%%% FTblock locks -########################################################################### -set PRCL_err POP_f1_P re -set MICH_err POP_f2_P re -set CARM_err REFL_f1_P re -set SRCL_err REFL_f2_P re -set DARMerr AS_f2_P re - -func DARMerr10pm = $DARMerr+0.02142517601 -lock DARM_lock $DARMerr10pm 0.081 1n - -lock PRCL_lock $PRCL_err 300 10u -lock MICH_lock $MICH_err 400 0.1m -lock CARM_lock $CARM_err -3m 0.1m -lock SRCL_lock $SRCL_err 100 10u - -func mMICH_lock = 0 - $MICH_lock -func ETMX_lock = $CARM_lock + $MICH_lock + $DARM_lock -func ETMY_lock = $CARM_lock - $MICH_lock - $DARM_lock - -put* PRM phi $PRCL_lock -put* ITMX phi $MICH_lock -put* ETMX phi $ETMX_lock -put* ITMY phi $mMICH_lock -put* ETMY phi $ETMY_lock -put* SRMHR phi $SRCL_lock - -noplot PRCL_lock -noplot SRCL_lock -noplot MICH_lock -noplot DARM_lock -noplot CARM_lock -noplot mMICH_lock -noplot ETMX_lock -noplot ETMY_lock -noplot DARMerr10pm -########################################################################### -%%% FTend locks - +time +noxaxis \ No newline at end of file diff --git a/examples/optivis_aligo_ex.py b/examples/optivis_aligo_ex.py index 95764e2..0feb58f 100644 --- a/examples/optivis_aligo_ex.py +++ b/examples/optivis_aligo_ex.py @@ -1,6 +1,8 @@ import pykat -kat = pykat.finesse.kat(kat_file="LLO_matched.kat") +kat = pykat.finesse.kat(kat_file="/Users/ddb/git/geo-simulation/geo-files/geoHF_v48.kat") -kat.optivis().show() +gui, scene = kat.optivis() + +gui.show() diff --git a/examples/optivis_ex.py b/examples/optivis_ex.py index cfa7b85..eba9810 100644 --- a/examples/optivis_ex.py +++ b/examples/optivis_ex.py @@ -9,7 +9,7 @@ s s1 100 n0 n3 bs bs1 1 0 0 45 n3 n4 n5 n6 s s3 50 n4 n4a -m m1 1 0 0 n4a n4b +m m1 0.9 0.1 0 n4a n4b s s3a 200 n4b n7a m m2 1 0 0 n7a n7b @@ -17,7 +17,19 @@ s s4 50 n5 n5a m m3 1 0 0 n5a n5b #s s4a 200 n5b n8a #m m4 1 0 0 n8a n8b + +attr m1 Rc -500 +attr m2 Rc 500 +cav c1 m1 n4b m2 n7a + +maxtem 0 +noxaxis """) -kat.optivis().show() +out, tdata = kat.run(getTraceData=True) + +gui = kat.optivis() + +kat.optivis_updateTraceData(gui, tdata[0]) +gui.show() diff --git a/pykat/components.py b/pykat/components.py index 7593f1e..4aedf93 100644 --- a/pykat/components.py +++ b/pykat/components.py @@ -9,17 +9,21 @@ from __future__ import print_function from pykat import USE_GUI, HAS_OPTIVIS, NoGUIException import pykat.external.six as six + if six.PY2: import exceptions + import pykat.exceptions as pkex import pykat from pykat.node_network import * from pykat.exceptions import * import abc import copy +from collections import OrderedDict if HAS_OPTIVIS: import optivis.bench.components as optivis_components + from optivis.view.canvas import OptivisCanvasItemDataType from pykat.SIfloat import * from pykat.param import Param, AttrParam @@ -93,6 +97,7 @@ class Component(object): self._params = [] self.__removed = False self._default_fsig_param = None + self.optivisLabelContent = None # store a unique ID for this component global next_component_id @@ -100,7 +105,6 @@ class Component(object): next_component_id += 1 - def __deepcopy__(self, memo): """ When deep copying a kat object we need to take into account @@ -222,7 +226,38 @@ class Component(object): del self._params[:] self.__removed = True + + def getOptivisParameterDict(self): + if len(self._params) == 0: + return None + + d = OrderedDict() + + for p in self._params: + d[p.name] = OptivisCanvasItemDataType.TEXTBOX + + return d + + def getOptivisTooltip(self): + tooltip = "Name: %s" % self.name + + for p in self._params: + if p.value is not None: + tooltip += "\n%s = %s" %(p.name, str(p.value)) + return tooltip + + def setOptivisLabelContent(self): + """ + Sets default Optivis label contents + """ + + if self.optivisLabelContent is None: + self.optivisLabelContent = {} + + self.optivisLabelContent["Name"] = self.name + + class AbstractMirrorComponent(Component): __metaclass__ = abc.ABCMeta @@ -258,12 +293,12 @@ 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") + self.__z = Param("z", self, None, canFsig=True, isPutable=False, isPutter=False, isTunable=False, fsig_name="z") + self.__rx = Param("rx", self, None, canFsig=True, isPutable=False, isPutter=False, isTunable=False, fsig_name="rx") + self.__ry = Param("ry", self, None, canFsig=True, isPutable=False, isPutter=False, isTunable=False, fsig_name="ry") + self.__Fz = Param("Fz", self, None, canFsig=True, isPutable=False, isPutter=False, isTunable=False, fsig_name="Fz") + self.__Frx = Param("Frx", self, None, canFsig=True, isPutable=False, isPutter=False, isTunable=False, fsig_name="Frx") + self.__Fry = Param("Fry", self, None, canFsig=True, isPutable=False, isPutter=False, isTunable=False, fsig_name="Fry") self._default_fsig_param = self.__phi @@ -451,8 +486,10 @@ class mirror(AbstractMirrorComponent): return rtn def getOptivisComponent(self): + self.setOptivisLabelContent() + if self._optivis_component is None: - self._optivis_component = optivis_components.CavityMirror(name=self.name, aoi=0) + self._optivis_component = optivis_components.CavityMirror(name=self.name, aoi=0, tooltip=self.getOptivisTooltip, paramList=self.getOptivisParameterDict(), pykatObject=weakref.ref(self)) return self._optivis_component @@ -509,8 +546,10 @@ class beamSplitter(AbstractMirrorComponent): raise pkex.BasePyKatException("No attribute {0} for mirrors".format(key)) def getOptivisComponent(self): + self.setOptivisLabelContent() + if self._optivis_component is None: - self._optivis_component = optivis_components.BeamSplitter(name=self.name, aoi=-self.alpha) + self._optivis_component = optivis_components.BeamSplitter(name=self.name, aoi=-self.alpha, tooltip=self.getOptivisTooltip, paramList=self.getOptivisParameterDict(), pykatObject=weakref.ref(self)) return self._optivis_component @@ -870,7 +909,33 @@ class isolator(Component): rtn.extend(p.getFinesseText()) return rtn - + + def getOptivisComponent(self): + self.setOptivisLabelContent() + + if self._optivis_component is None: + self._optivis_component = optivis_components.FaradayIsolator(name=self.name, tooltip=self.getOptivisTooltip, paramList=self.getOptivisParameterDict(), pykatObject=weakref.ref(self)) + + return self._optivis_component + + def getOptivisNode(self, mode, kat_node): + mode = mode.lower() + + if mode != "input" and mode.lower() != "output": + raise pkex.BasePyKatException("Mode must be either input or output") + + if mode == "input": + if kat_node is self.nodes[0]: + return self._optivis_component.getInputNode("fr") + elif kat_node is self.nodes[1]: + return self._optivis_component.getInputNode("bk") + elif mode == "output": + if kat_node is self.nodes[0]: + return self._optivis_component.getnOutputNode("fr") + elif kat_node is self.nodes[1]: + return self._optivis_component.getOutputNode("bk") + + def getQGraphicsItem(self): if not USE_GUI: raise NoGUIException @@ -917,8 +982,10 @@ class lens(Component): return rtn def getOptivisComponent(self): + self.setOptivisLabelContent() + if self._optivis_component is None: - self._optivis_component = optivis_components.ConvexLens(name=self.name) + self._optivis_component = optivis_components.ConvexLens(name=self.name, tooltip=self.getOptivisTooltip, paramList=self.getOptivisParameterDict(), pykatObject=weakref.ref(self)) return self._optivis_component @@ -1021,9 +1088,10 @@ class modulator(Component): return rtn def getOptivisComponent(self): + self.setOptivisLabelContent() + if self._optivis_component is None: - #self._optivis_component = optivis_components.Modulator(name=self.name) - self._optivis_component = optivis_components.ConvexLens(name=self.name) + self._optivis_component = optivis_components.ElectroopticModulator(name=self.name, tooltip=self.getOptivisTooltip, paramList=self.getOptivisParameterDict(), pykatObject=weakref.ref(self)) return self._optivis_component @@ -1115,8 +1183,10 @@ class laser(Component): return rtn def getOptivisComponent(self): + self.setOptivisLabelContent() + if self._optivis_component is None: - self._optivis_component = optivis_components.Laser(name=self.name) + self._optivis_component = optivis_components.Laser(name=self.name, tooltip=self.getOptivisTooltip, paramList=self.getOptivisParameterDict(), pykatObject=weakref.ref(self)) return self._optivis_component diff --git a/pykat/finesse.py b/pykat/finesse.py index c379195..50a65b7 100644 --- a/pykat/finesse.py +++ b/pykat/finesse.py @@ -56,6 +56,11 @@ import pykat.exceptions as pkex from pykat import USE_GUI, HAS_OPTIVIS, NoGUIException +if HAS_OPTIVIS: + from optivis.bench.labels import Label as optivis_label + from optivis.geometry import Coordinates as optivis_coord + import PyQt4 + if USE_GUI: from pykat.gui.gui import pyKatGUI from PyQt4.QtCore import QCoreApplication @@ -156,7 +161,7 @@ def GUILength(L): """ Should scale the lengths in some way to handle km and mm for time being """ - return L * ( 20 * erfc(L/2e3) + 0.01) + return L # * ( 40 * erfc(L/400.0) + 0.01) class katRun(object): def __init__(self): @@ -914,7 +919,7 @@ class kat(object): return Process(target=f__lkat_process, args=(callback, cmd, kwargs)) - def run(self, printout=0, printerr=0, plot=None, save_output=False, save_kat=False, kat_name=None, cmd_args=None) : + def run(self, printout=0, printerr=0, plot=None, save_output=False, save_kat=False, kat_name=None, cmd_args=None, getTraceData=False): """ Runs the current simulation setup that has been built thus far. It returns a katRun or katRun2D object which is populated with the various @@ -926,6 +931,11 @@ class kat(object): save_kat (bool) - if true does not delete kat file kat_name (string) - name of kat file if needed, will be randomly generated otherwise cmd_args (list of strings) - command line flags to pass to FINESSE + getTraceData (bool) - If true a list of dictionaries is returned along with the + output file. Each dictionary is the result of the beam tracing + that Finesse performs, the keys are the node names and the values + are the x and y beam parameters. If no tracing is done a None + is returned. """ start = datetime.datetime.now() @@ -996,6 +1006,9 @@ class kat(object): if cmd_args != None: cmd.extend(cmd_args) + + if getTraceData: + cmd.append('--trace') cmd.append('--no-backspace') # set default format so that less repeated numbers are printed to the @@ -1059,13 +1072,57 @@ class kat(object): if p.returncode != 0: print(err) sys.exit(1) - + self.__prevrunfilename = katfile.name root = os.path.splitext(katfile.name) - base = os.path.basename(root[0]) + base = os.path.basename(root[0]) + path = os.path.split(katfile.name)[0] + outfile = root[0] + ".out" + traceData = None + + if getTraceData: + # First see if we have any trace files + + traceFiles = [file for file in os.listdir(path) if file.endswith(".trace") and file.startswith(base)] + + print("Found %i trace files" % len(traceFiles)) + print(path) + print(traceFiles) + + if len(traceFiles) > 0: + import fileinput + traceData = [] + + for file in traceFiles: + traceData.append({}) + ifile = fileinput.input(os.path.join(path, file)) + + for line in ifile: + line = line.strip() + + if len(line) > 0: + a = line.split(':', 1) + + if a[0].isdigit(): + print("Found %s" % a[0]) + + values = a[1].split() + + node_name = values[1].split("(")[0] + + line1x = ifile.readline() + line2x = ifile.readline() + line1y = ifile.readline() + line2y = ifile.readline() + + qx = line2x.strip().split()[0].split("=")[1] + qy = line2y.strip().split()[0].split("=")[1] + + traceData[-1][node_name] = (pykat.beam_param(q=complex(qx)), pykat.beam_param(q=complex(qy))) + if save_output: newoutfile = "{0}.out".format(base) @@ -1079,18 +1136,19 @@ class kat(object): if self.verbose: print("\nOutput data saved to '{0}'".format(newoutfile)) - if hasattr(self, "x2axis") and self.noxaxis == False: - [r.x,r.y,r.z,hdr] = self.readOutFile(outfile) + if len(self.detectors.keys()) > 0: + if hasattr(self, "x2axis") and self.noxaxis == False: + [r.x,r.y,r.z,hdr] = self.readOutFile(outfile) - r.xlabel = hdr[0] - r.ylabel = hdr[1] - r.zlabels = map(str.strip, hdr[2:]) + r.xlabel = hdr[0] + r.ylabel = hdr[1] + r.zlabels = map(str.strip, hdr[2:]) - else: - [r.x,r.y,hdr] = self.readOutFile(outfile) + else: + [r.x,r.y,hdr] = self.readOutFile(outfile) - r.xlabel = hdr[0] - r.ylabels = map(str.strip, hdr[1:]) + r.xlabel = hdr[0] + r.ylabels = map(str.strip, hdr[1:]) if save_kat: if kat_name == None: @@ -1119,6 +1177,8 @@ class kat(object): katfile.close() perfData = [] + rtn = [r] + if self.__time_code: perffile = open(root[0] + ".perf",'r') @@ -1126,9 +1186,15 @@ class kat(object): vals = l.strip().split() perfData.append((vals[0], long(vals[1]), long(vals[2]))) - return [r, perfData] + rtn.append(perfData) + + if getTraceData: + rtn.append(traceData) + + if len(rtn) == 1: + return rtn[0] else: - return r + return rtn except pkex.FinesseRunError as fe: print(fe) @@ -1470,12 +1536,6 @@ class kat(object): scene = scene.Scene(title="My pykat layout") - # Run through once to add components, ignoring spaces - for c in self.getComponents(): - if isinstance(c, pykat.components.space): continue - - optivis_op = getattr(c, "getOptivisComponent", None) - # Run through again to add links for c in self.getComponents(): if not isinstance(c, pykat.components.space): @@ -1497,12 +1557,54 @@ class kat(object): if no is None or ni is None: raise pkex.BasePyKatException("Optivis node is None") - scene.addLink(links.Link(no, ni, GUILength(c.L.value) )) - - gui = canvas.Simple(scene=scene) + c._optivis_component = links.Link(outputNode=no, inputNode=ni, length=c.L.value) + + c.label_node1 = optivis_label(text="", position=optivis_coord(-0.5, 0), item=c._optivis_component) + c.label_node2 = optivis_label(text="", position=optivis_coord( 0.5, 0), item=c._optivis_component) + + c._optivis_component.labels.append(c.label_node1) + c._optivis_component.labels.append(c.label_node2) + + scene.addLink(c._optivis_component) + + gui = canvas.Full(scene=scene) + ### add menu and menu items + menubar = gui.qMainWindow.menuBar() + fileMenu = menubar.addMenu('&Pykat') + + trace = PyQt4.QtGui.QAction('Trace', gui.qMainWindow) + trace.triggered.connect(self.optivis_updateTraceData) + fileMenu.addAction(trace) + return gui + + def optivis_updateTraceData(self, gui, tdata): + """ + Change at some point to use a stored GUI reference + """ + if not HAS_OPTIVIS: + print("Optivis is not installed") + return None + + for c in self.getComponents(): + if not isinstance(c, pykat.components.space): + continue + c.label_node1.content["w0_x"] = tdata[c.nodes[0].name][0].w0 + c.label_node1.content["w_x"] = tdata[c.nodes[0].name][0].w + c.label_node1.content["z_x"] = tdata[c.nodes[0].name][0].z + c.label_node1.content["Rc_x"] = tdata[c.nodes[0].name][0].Rc + c.label_node1.content["Zr_x"] = tdata[c.nodes[0].name][0].zr + + c.label_node1.content["w0_y"] = tdata[c.nodes[0].name][1].w0 + c.label_node1.content["w_y"] = tdata[c.nodes[0].name][1].w + c.label_node1.content["z_y"] = tdata[c.nodes[0].name][1].z + c.label_node1.content["Rc_y"] = tdata[c.nodes[0].name][1].Rc + c.label_node1.content["Zr_y"] = tdata[c.nodes[0].name][1].zr + + gui.draw() + def openGUI(self): if not USE_GUI: raise NoGUIException @@ -1521,7 +1623,7 @@ class kat(object): self.pykatgui.show() if created: self.app.exec_() - + def getComponents(self): return self.__components.values() -- GitLab