Commit dc470f85 authored by Andreas Freise's avatar Andreas Freise
Browse files

trying to fix wrong commit from some time ago, still needs fixing.

parent 864005dd
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
__version__ = "0.6.2"
# This flag is used to switch on the gui features in pkat at import time
USE_GUI = False
HAS_OPTIVIS = False
import imp
try:
imp.find_module('optivis')
HAS_OPTIVIS = True
except ImportError:
HAS_OPTIVIS = False
import pykat.exceptions as pkex
......
......@@ -9,7 +9,7 @@ from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from pykat import USE_GUI, NoGUIException
from pykat import USE_GUI, HAS_OPTIVIS, NoGUIException
import pykat.external.six as six
......@@ -21,15 +21,22 @@ 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 optivis.bench.labels import Label as optivis_label
from optivis.geometry import Coordinates as optivis_coord
import PyQt4
from pykat.SIfloat import *
from pykat.param import Param, AttrParam
import weakref
import pykat.exceptions as pkex
from copy import deepcopy
next_component_id = 1
from pykat import USE_GUI, NoGUIException
next_component_id = 1
if USE_GUI:
import pykat.gui.resources
......@@ -79,7 +86,15 @@ class NodeGaussSetter(object):
class Component(object):
__metaclass__ = abc.ABCMeta
def __init__(self, name):
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
return object.__new__(type(cls.__name__, (cls,), {}), *args, **kwargs)
def __init__(self, name=None):
self._optivis_component = None
self.__name = name
self._svgItem = None
self._requested_node_names = []
......@@ -88,17 +103,25 @@ 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
self.__id = next_component_id
next_component_id += 1
# This creates an instance specific class for the component
# this enables us to add properties to instances rather than
# all classes
cls = type(self)
self.__class__ = type(cls.__name__, (cls,), {})
def __deepcopy__(self, memo):
"""
When deep copying a kat object we need to take into account
the instance specific properties.
"""
result = self.__class__.__new__(self.__class__)
result.__dict__ = copy.deepcopy(self.__dict__, memo)
result.__update_node_setters
return result
def _register_param(self, param):
self._params.append(param)
......@@ -210,18 +233,36 @@ class Component(object):
self.__removed = True
def __deepcopy__(self, memo):
cls = self.__class__
result = cls.__new__(cls)
memo[id(self)] = result
def getOptivisParameterDict(self):
if len(self._params) == 0:
return None
for k, v in self.__dict__.items():
setattr(result, k, deepcopy(v, memo))
d = OrderedDict()
for p in result._params:
p._updateOwner(result)
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
return result
class AbstractMirrorComponent(Component):
__metaclass__ = abc.ABCMeta
......@@ -258,12 +299,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
......@@ -450,6 +491,37 @@ 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, tooltip=self.getOptivisTooltip, paramList=self.getOptivisParameterDict(), pykatObject=weakref.ref(self))
lbl = optivis_label(text="", position=optivis_coord(0, -1), item=self._optivis_component)
lbl.content["Name"] = self.name
self._optivis_component.labels.append(lbl)
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 not %s" % mode)
if mode == "input":
if kat_node is self.nodes[0]:
return self._optivis_component.getInputNode("fr")
else:
return self._optivis_component.getInputNode("bk")
elif mode == "output":
if kat_node is self.nodes[0]:
return self._optivis_component.getOutputNode("fr")
else:
return self._optivis_component.getOutputNode("bk")
def getQGraphicsItem(self):
if not USE_GUI:
raise NoGUIException
......@@ -483,6 +555,39 @@ class beamSplitter(AbstractMirrorComponent):
else:
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, 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("frA")
elif kat_node is self.nodes[1]:
return self._optivis_component.getInputNode("frB")
elif kat_node is self.nodes[2]:
return self._optivis_component.getInputNode("bkB")
elif kat_node is self.nodes[3]:
return self._optivis_component.getInputNode("bkA")
elif mode == "output":
if kat_node is self.nodes[0]:
return self._optivis_component.getOutputNode("frB")
elif kat_node is self.nodes[1]:
return self._optivis_component.getOutputNode("frA")
elif kat_node is self.nodes[2]:
return self._optivis_component.getOutputNode("bkA")
elif kat_node is self.nodes[3]:
return self._optivis_component.getOutputNode("bkB")
@staticmethod
def parseFinesseText(text):
values = text.split()
......@@ -579,6 +684,18 @@ class space(Component):
@gy.setter
def gy(self,value): self.__gy.value = SIfloat(value)
def connectingComponents(self):
"""
Returns the two components that this space connects.
"""
a = list(self.nodes[0].components + self.nodes[1].components)
a = [value for value in a if value != self]
if len(a) != 2:
raise pkex.BasePyKatException("Space should only connect 2 components")
return a
def parseAttributes(self, values):
for key in values.keys():
......@@ -803,6 +920,32 @@ class isolator(Component):
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
......@@ -848,6 +991,31 @@ 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, 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
......@@ -929,6 +1097,31 @@ class modulator(Component):
return rtn
def getOptivisComponent(self):
self.setOptivisLabelContent()
if self._optivis_component is None:
self._optivis_component = optivis_components.ElectroopticModulator(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
......@@ -999,6 +1192,28 @@ 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, tooltip=self.getOptivisTooltip, paramList=self.getOptivisParameterDict(), pykatObject=weakref.ref(self))
lbl = optivis_label(text="", position=optivis_coord(0, -1), item=self._optivis_component)
lbl.content["Name"] = self.name
self._optivis_component.labels.append(lbl)
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":
return None
elif mode == "output":
return self._optivis_component.getOutputNode("out")
def getQGraphicsItem(self):
if not USE_GUI:
raise NoGUIException
......
......@@ -15,7 +15,7 @@ if six.PY2:
import abc
from pykat.node_network import *
from pykat.param import Param
from pykat.param import Param, AttrParam
from pykat.SIfloat import SIfloat
import pykat.external.six as six
......@@ -356,7 +356,13 @@ class bp(Detector1):
class pd(Detector1):
def __init__(self, name, num_demods, node_name, senstype=None, alternate_beam=False, pdtype=None, **kwargs):
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
return object.__new__(type(cls.__name__, (cls,), {}), *args, **kwargs)
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
......@@ -402,12 +408,25 @@ class pd(Detector1):
elif i<num_demods-1:
raise pkex.BasePyKatException("Missing demodulation phase {0} (phi{0})".format(i+1))
# define new class for assigning new attributes
cls = type(self)
self.__class__ = type(cls.__name__, (cls,), {})
self.__set_demod_attrs()
def __deepcopy__(self, memo):
"""
When deep copying a kat object we need to take into account
the instance specific properties.
"""
result = pd(self.name, self.num_demods, self.node.name)
memo[id(self)] = result
result.__dict__ = copy.deepcopy(self.__dict__, memo)
# Find all properties in class we are copying
# and deep copy these to the new class instance
for x in self.__class__.__dict__.items():
if isinstance(x[1], property):
setattr(result.__class__, x[0], x[1])
return result
@property
def senstype(self): return self.__senstype
@senstype.setter
......@@ -666,7 +685,7 @@ 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)
super(qshot, self).__init__(name, num_demods, node_name, alternate_beam=alternate_beam, pdtype=None, senstype=None, **kwargs)
@pd.pdtype.setter
def pdtype(self, value):
......
......@@ -34,6 +34,7 @@ import subprocess
import tempfile
import numpy as np
import datetime
import time
import pickle
import pykat
import warnings
......@@ -63,6 +64,8 @@ except ImportError: # not 2.6+ or is 3.x
print("boom")
pass
"""
from math import erfc, pi
from collections import namedtuple, OrderedDict
from pykat.node_network import NodeNetwork
......@@ -76,7 +79,13 @@ import pykat.external.six as six
import pykat.exceptions as pkex
from pykat import USE_GUI, NoGUIException
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
......@@ -174,9 +183,16 @@ def f__lkat_trace_callback(lkat, trace_info, getCavities, getNodes, getSpaces):
gouyy = space.gouy_y)
def GUILength(L):
"""
Should scale the lengths in some way to handle km and mm for time being
"""
return L # * ( 40 * erfc(L/400.0) + 0.01)
class katRun(object):
def __init__(self):
self.runDateTime = datetime.datetime.now()
self.runtime = None
self.StartDateTime = datetime.datetime.now()
self.x = None
self.y = None
self.xlabel = None
......@@ -185,7 +201,7 @@ class katRun(object):
self.katVersion = None
self.yaxis = None
def plot(self):
def plot(self, logy=False):
import pylab
pylab.plot(self.x, self.y)
......@@ -206,9 +222,10 @@ class katRun(object):
def __getitem__(self, value):
idx = [i for i in range(len(self.ylabels)) if self.ylabels[i].split()[0] == str(value)]
out = None
if len(idx) > 0:
out = self.y[:, idx]
#out = self.y[:, idx]
if len(idx) == 1:
if self.yaxis == "abs:deg":
......@@ -221,6 +238,9 @@ class katRun(object):
elif self.yaxis == "re:im":
out = self.y[:, idx[0]] + 1j*self.y[:, idx[1]]
if out == None:
out = self.y[:, idx]
if out.size == 1:
return out[0].squeeze()
else:
......@@ -230,7 +250,8 @@ class katRun(object):
class katRun2D(object):
def __init__(self):
self.runDateTime = datetime.datetime.now()
self.runtime
self.startDateTime = datetime.datetime.now()
self.x = None
self.y = None
self.z = None
......@@ -398,11 +419,19 @@ Constant = namedtuple('Constant', 'name, value, usedBy')
class kat(object):
def __new__(cls, *args, **kwargs):
# This may seem like an arbitrary step but here we are creating a
# new class that is a base class of itself. This is because when
# the kat object adds new components it also adds properties for
# each of these. There properties are unique to each kat object,
# but properties are part of the class definition. Thus if two
# kat objects share the same class definition they also have the
# same properties regardless of whether they have the actual
# object added to it. So we create an instance specific class.
return object.__new__(type(pykat.finesse.kat.__name__, (pykat.finesse.
kat,), {}), *args, **kwargs)
def __init__(self, kat_file=None, kat_code=None, katdir="", katname="", tempdir=None, tempname=None):
cls = type(self)
self.__class__ = type(cls.__name__, (cls,), {})
self.scene = None # scene object for GUI
self.verbose = True
self.__blocks = OrderedDict() # dictionary of blocks that are used
......@@ -512,9 +541,9 @@ class kat(object):
def phase(self,value): self.__phase = int(value)
@property
def getPerformanceData(self): return self.__time_code
@getPerformanceData.setter
def getPerformanceData(self,value): self.__time_code = bool(value)
def timeCode(self): return self.__time_code
@timeCode.setter
def timeCode(self,value): self.__time_code = bool(value)
@property
def components(self):
......@@ -878,6 +907,7 @@ class kat(object):
else:
raise pkex.BasePyKatException("'{0}' isnot a valid fsig command".format(line))
self.signals.f = freq
self.signals.apply(comp._default_fsig(), amp, phase, name)
else:
......@@ -913,7 +943,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
......@@ -925,6 +955,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()
......@@ -966,6 +1001,7 @@ class kat(object):
r.yaxis = self.yaxis
r.katScript = "".join(self.generateKatScript())
r.katScript += "time\n"
if (plot==None):
# ensure we don't do any plotting. That should be handled
......@@ -997,6 +1033,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
# output file, should speed up running and parsing of output files
......@@ -1061,6 +1100,12 @@ class kat(object):
</