Commit 62cf82bb authored by Sean Leavey's avatar Sean Leavey
Browse files

Merge branch 'master' of gitmaster.atlas.aei.uni-hannover.de:pykat/pykat

parents a8357ced 925906a0
#!/usr/bin/env python
# -*- coding: utf-8 -*-
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 $test n2 n3
m m2 0.99 0.01 -0.1 n3 n4
attr m2 m 1 # mech sus1
const test 1200
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 = kat.run(printout=0, printerr=0)
......@@ -8,7 +8,7 @@ import numpy as np
import pylab as pl
code = """
l l1 1 0 0 n1
l l1 1 0 0 n1 ### test
s s1 10 1 n1 n2
m m1 0.5 0.5 0 n2 n3
s s2 10 1 n3 n4
......@@ -29,7 +29,7 @@ kat.add(photodiode('pd_trs','n5'))
kat.add(photodiode('pd_cav','n4', num_demods=1, demods=[1]))
kat.add(xaxis("lin", [0, 360], kat.m2, kat.m2.phi, 100))
kat.add(xaxis("lin", [0, 360], kat.m2.phi, 100))
kat.m1.Rcx = -1000.0
kat.m1.Rcy = -1000.0
......
......@@ -60,8 +60,8 @@ def main():
scale 2 PDrefl_q
"""
kat.parseKatCode(code_det)
kat.PDrefl_p.phi[0]=result['p_phase']
kat.PDrefl_q.phi[0]=result['q_phase']
kat.PDrefl_p.phi1=result['p_phase']
kat.PDrefl_q.phi1=result['q_phase']
print "--------------------------------------------------------"
print " 4. adding a 0.1nm offset to ETM and compute PDH signal"
......@@ -117,7 +117,7 @@ def pd_phase(tmpkat):
# function for root finding
def PD_q_test(x):
kat.PDrefl_q.phi[0]=x
kat.PDrefl_q.phi1=x
out = kat.run()
print '\r root finding: function value %g ' % out.y,
sys.stdout.flush()
......
......@@ -96,10 +96,10 @@ def main():
kat.parseKatCode(code_WFS2)
(WFS1_phase, WFS2_phase) = asc_phases(kat)
kat.WFS1_I.phi[0]=WFS1_phase
kat.WFS1_Q.phi[0]=WFS1_phase+90.0
kat.WFS2_I.phi[0]=WFS2_phase
kat.WFS2_Q.phi[0]=WFS2_phase+90.0
kat.WFS1_I.phi1=WFS1_phase
kat.WFS1_Q.phi1=WFS1_phase+90.0
kat.WFS2_I.phi1=WFS2_phase
kat.WFS2_Q.phi1=WFS2_phase+90.0
result['WFS1_phase']=WFS1_phase
result['WFS2_phase']=WFS2_phase
......@@ -178,7 +178,7 @@ def asc_phases(tmpkat):
kat.maxtem=1
def demod_phase1(x):
kat.WFS1_I.phi[0]=x[0]
kat.WFS1_I.phi1=x[0]
out = kat.run()
signal = out["WFS1_I"]
print '\r minimising: function value %g ' % signal ,
......@@ -186,7 +186,7 @@ def asc_phases(tmpkat):
return -1*abs(signal)
def demod_phase2(x):
kat.WFS2_I.phi[0]=x[0]
kat.WFS2_I.phi1=x[0]
out = kat.run()
signal = out["WFS2_I"]
print '\r minimising: function value %g ' % signal ,
......
......@@ -9,7 +9,7 @@ def SIfloat(value):
return convertToFloat(value)
def convertToFloat(value):
__prefix = {'y': 'e-24', # yocto
__suffix = {'y': 'e-24', # yocto
'z': 'e-21', # zepto
'a': 'e-18', # atto
'f': 'e-15', # femto
......@@ -23,12 +23,12 @@ def convertToFloat(value):
'M': 'e6', # mega
'G': 'e9', # giga
'T': 'e12', # tera
'P': 'e15', # peta
'E': 'e18', # exa
'Z': 'e21', # zetta
'Y': 'e24', # yotta
'P': 'e15' # peta
}
value = str(value)
for i, j in __prefix.iteritems():
for i, j in __suffix.iteritems():
value=value.replace(i, str(j))
return float(value)
......@@ -44,11 +44,34 @@ class cavity(Command):
class gauss(object):
@staticmethod
def parseFinesseText(text, kat):
values = text.split(" ")
values = text.split()
if not values[0].startswith("gauss"):
if not values[0].startswith("gauss") or (len(values) != 6 and len(values != 8)):
raise exceptions.RuntimeError("'{0}' not a valid Finesse gauss command".format(text))
name = values[1]
component = values[2]
node = values[3]
if values[0].endswith("**"):
if len(values) == 6:
print ""
elif len(values) == 8:
print ""
elif values[0].endswith("*"):
if len(values) == 6:
print ""
elif len(values) == 8:
print ""
else:
if len(values) == 6:
print ""
elif len(values) == 8:
print ""
class xaxis(Command):
def __init__(self, scale, limits, param, steps, comp=None, axis_type="xaxis"):
......@@ -94,7 +117,7 @@ class xaxis(Command):
@staticmethod
def parseFinesseText(text):
values = text.split(" ")
values = text.split()
if values[0] != "xaxis" and values[0] != "xaxis*":
raise exceptions.RuntimeError("'{0}' not a valid Finesse xaxis command".format(text))
......@@ -125,7 +148,7 @@ class x2axis(xaxis):
@staticmethod
def parseFinesseText(text):
values = text.split(" ")
values = text.split()
if values[0] != "x2axis" and values[0] != "x2axis*":
raise exceptions.RuntimeError("'{0}' not a valid Finesse xaxis command".format(text))
......
......@@ -17,6 +17,8 @@ from pykat.gui.graphics import *
from pykat.SIfloat import *
from pykat.param import Param, AttrParam
import pykat.exceptions as pkex
next_component_id = 1
class NodeGaussSetter(object):
......@@ -232,13 +234,13 @@ class mirror(AbstractMirrorComponent):
@staticmethod
def parseFinesseText(text):
values = text.split(" ")
values = text.split()
if values[0] != "m" and values[0] != "m1" and values[0] != "m2":
raise exceptions.RuntimeError("'{0}' not a valid Finesse mirror command".format(text))
raise pkex.BasePyKatException("'{0}' not a valid Finesse mirror command".format(text))
if len(values) != 7:
raise exceptions.RuntimeError("Mirror Finesse code format incorrect '{0}'".format(text))
raise pkex.BasePyKatException("Mirror Finesse code format incorrect '{0}'".format(text))
if len(values[0])==1:
values.pop(0) # remove initial value
......@@ -287,13 +289,13 @@ class beamSplitter(AbstractMirrorComponent):
@staticmethod
def parseFinesseText(text):
values = text.split(" ")
values = text.split()
if values[0] != "bs" and values[0] != "bs1" and values[0] != "bs2":
raise exceptions.RuntimeError("'{0}' not a valid Finesse beam splitter command".format(text))
raise pkex.BasePyKatException("'{0}' not a valid Finesse beam splitter command".format(text))
if len(values) != 10:
raise exceptions.RuntimeError("Beam splitter Finesse code format incorrect '{0}'".format(text))
raise pkex.BasePyKatException("Beam splitter Finesse code format incorrect '{0}'".format(text))
if len(values[0])==2:
values.pop(0) # remove initial value
......@@ -372,10 +374,10 @@ class space(Component):
@staticmethod
def parseFinesseText(text):
values = text.split(" ")
values = text.split()
if values[0] != "s":
raise exceptions.RuntimeError("'{0}' not a valid Finesse space command".format(text))
raise pkex.BasePyKatException("'{0}' not a valid Finesse space command".format(text))
values.pop(0) # remove initial value
......@@ -384,7 +386,7 @@ class space(Component):
elif len(values) == 4:
return space(values[0], values[2], values[3], values[1])
else:
raise exceptions.RuntimeError("Space Finesse code format incorrect '{0}'".format(text))
raise pkex.BasePyKatException("Space Finesse code format incorrect '{0}'".format(text))
def getFinesseText(self):
rtn = []
......@@ -416,16 +418,16 @@ class grating(Component):
if node3 != None:
self._requested_node_names.append(node3)
else:
raise exceptions.RuntimeError("Grating node 3 not specified")
raise pkex.BasePyKatException("Grating node 3 not specified")
if n > 3:
if node4 != None:
self._requested_node_names.append(node4)
else:
raise exceptions.RuntimeError("Grating node 4 not specified")
raise pkex.BasePyKatException("Grating node 4 not specified")
if n > 4 or n < 2:
raise exceptions.RuntimeError("Grating must have between 2 and 4 ports")
raise pkex.BasePyKatException("Grating must have between 2 and 4 ports")
self.__n = n
self.__d = Param("d", self, SIfloat(d))
......@@ -441,7 +443,7 @@ class grating(Component):
@n.setter
def n(self, value):
if value < 2 or value > 4:
raise exceptions.RuntimeError("Grating must have between 2 and 4 ports")
raise pkex.BasePyKatException("Grating must have between 2 and 4 ports")
else:
self.__n = value
......@@ -482,14 +484,14 @@ class grating(Component):
@staticmethod
def parseFinesseText(text):
values = text.split(" ")
values = text.split()
if values[0][0 : 2] != "gr":
raise exceptions.RuntimeError("'{0}' not a valid Finesse grating command".format(text))
raise pkex.BasePyKatException("'{0}' not a valid Finesse grating command".format(text))
if len(values[0]) > 2:
if int(values[0][2]) > 4 or int(values[0][2]) < 2:
raise exceptions.RuntimeError("Grating must have between 2 and 4 ports")
raise pkex.BasePyKatException("Grating must have between 2 and 4 ports")
else:
n = int(values[0][2])
else:
......@@ -499,17 +501,17 @@ class grating(Component):
if n == 2:
if len(values) != 4:
raise exceptions.RuntimeError("Two port grating must have 2 nodes defined")
raise pkex.BasePyKatException("Two port grating must have 2 nodes defined")
return grating(values[0], values[2], values[3], None, None, n, values[1])
elif n == 3:
if len(values) != 5:
raise exceptions.RuntimeError("Three port grating must have 3 nodes defined")
raise pkex.BasePyKatException("Three port grating must have 3 nodes defined")
return grating(values[0], values[2], values[3], values[4], None, n, values[1])
else:
if len(values) != 6:
raise exceptions.RuntimeError("Four port grating must have 4 nodes defined")
raise pkex.BasePyKatException("Four port grating must have 4 nodes defined")
return grating(values[0], values[2], values[3], values[4], values[5], n, values[1])
......@@ -550,17 +552,17 @@ class isolator(Component):
@staticmethod
def parseFinesseText(text):
values = text.split(" ")
values = text.split()
if values[0] != "isol":
raise exceptions.RuntimeError("'{0}' not a valid Finesse isolator command".format(text))
raise pkex.BasePyKatException("'{0}' not a valid Finesse isolator command".format(text))
values.pop(0) # remove initial value
if len(values) == 4:
return isolator(values[0], values[2], values[3], values[1])
else:
raise exceptions.RuntimeError("Isolator Finesse code format incorrect '{0}'".format(text))
raise pkex.BasePyKatException("Isolator Finesse code format incorrect '{0}'".format(text))
def getFinesseText(self):
rtn = ['isol {0} {1} {2} {3}'.format(self.name, self.S.value, self.nodes[0].name, self.nodes[1].name)]
......@@ -592,17 +594,17 @@ class lens(Component):
@staticmethod
def parseFinesseText(text):
values = text.split(" ")
values = text.split()
if values[0] != "lens":
raise exceptions.RuntimeError("'{0}' not a valid Finesse lens command".format(text))
raise pkex.BasePyKatException("'{0}' not a valid Finesse lens command".format(text))
values.pop(0) # remove initial value
if len(values) == 4:
return lens(values[0], values[2], values[3], values[1])
else:
raise exceptions.RuntimeError("Lens Finesse code format incorrect '{0}'".format(text))
raise pkex.BasePyKatException("Lens Finesse code format incorrect '{0}'".format(text))
def getFinesseText(self):
rtn = ['lens {0} {1} {2} {3}'.format(self.name, self.f.value, self.nodes[0].name, self.nodes[1].name)]
......@@ -667,10 +669,10 @@ class modulator(Component):
@staticmethod
def parseFinesseText(text):
v = text.split(" ")
v = text.split()
if v[0] != "mod":
raise exceptions.RuntimeError("'{0}' not a valid Finesse modulator command".format(text))
raise pkex.BasePyKatException("'{0}' not a valid Finesse modulator command".format(text))
v.pop(0) # remove initial value
......@@ -723,10 +725,10 @@ class laser(Component):
@staticmethod
def parseFinesseText(text):
values = text.split(" ")
values = text.split()
if values[0] != "l":
raise exceptions.RuntimeError("'{0}' not a valid Finesse laser command".format(text))
raise pkex.BasePyKatException("'{0}' not a valid Finesse laser command".format(text))
values.pop(0) # remove initial value
......
......@@ -34,6 +34,8 @@ import pykat
import warnings
import re
from collections import namedtuple
from pykat.node_network import NodeNetwork
from pykat.detectors import Detector
from pykat.components import Component
......@@ -49,7 +51,6 @@ from PyQt4.QtGui import QApplication
NO_GUI = False
NO_BLOCK = "NO_BLOCK"
pykat_version = "0.1"
pykat_web = "www.gwoptics.org/pykat"
......@@ -75,7 +76,7 @@ class katRun(object):
def get(self, value): return self[value]
def __getitem__(self, value):
idx = [i for i in range(len(self.ylabels)) if self.ylabels[i].split(" ")[0] == str(value)]
idx = [i for i in range(len(self.ylabels)) if self.ylabels[i].split()[0] == str(value)]
if len(idx) > 0 and self.y.shape == ():
# In the case we have a noxaxis and just one output...
......@@ -122,7 +123,7 @@ class katRun2D(object):
def get(self, value): return self[value]
def __getitem__(self, value):
idx = [i for i in range(len(self.zlabels)) if self.zlabels[i].split(" ")[0] == str(value)]
idx = [i for i in range(len(self.zlabels)) if self.zlabels[i].split()[0] == str(value)]
if len(idx) > 0:
return self.z[idx].squeeze()
......@@ -236,7 +237,9 @@ class Block:
@property
def name(self): return self.__name
class kat(object):
Constant = namedtuple('Constant', 'name, value, usedBy')
class kat(object):
def __init__(self, kat_file=None, kat_code=None, katdir="", katname="", tempdir=None, tempname=None):
......@@ -254,6 +257,7 @@ class kat(object):
self.__tempname = tempname
self.pykatgui = None
self.__signals = Signals()
self.constants = {}
# initialise default block
self.__currentTag= NO_BLOCK
......@@ -327,22 +331,64 @@ class kat(object):
def parseKatCode(self, code):
#commands = code.split("\n")
self.parseCommands(code)
def processConstants(self, commands):
"""
Before fully parsing a bunch of commands firstly any constants or variables
to be recorded and replaced.
"""
constants = self.constants
for line in commands:
values = line.split()
if len(values)>0 and values[0] == 'const':
if len(values) >= 3:
if values[1] in constants:
raise pkex.BasePyKatException('const command with the name "{0}" already used'.format(values[1]))
else:
constants[str(values[1])] = Constant(values[1], values[2], [])
else:
raise pkex.BasePyKatException('const command "{0}" was not the correct format'.format(line))
commands_new = []
for line in commands:
values = line.split()
if len(values) > 0 and values[0] != 'const':
# check if we have a var/constant in this line
if line.find('$') >= 0:
for key in constants.keys():
if line.find('$'+key) > -1:
constants[key].usedBy.append(line)
line = line.replace('$'+key, str(constants[key].value))
commands_new.append(line)
self.constants = constants
return commands_new
def parseCommands(self, commands):
blockComment = False
commands=self.remove_comments(commands)
commands=self.processConstants(commands)
after_process = [] # list of commands that should be processed after
# objects have been set and created
for line in commands.split("\n"):
for line in commands:
#for line in commands:
if len(line.strip()) >= 2:
line = line.strip()
# Looking for block start or end
values = line.split(" ")
values = line.split()
if values[0] == "%%%":
if values[1] == "FTblock":
newTag = values[2]
......@@ -407,13 +453,13 @@ class kat(object):
elif(first == "noxaxis"):
self.noxaxis = True
elif(first == "phase"):
v = line.split(" ")
v = line.split()
if len(v) != 2:
raise pkex.BasePyKatException("phase command `{0}` is incorrect.".format(line))
else:
self.phase = int(v[1])
elif(first == "maxtem"):
v = line.split(" ")
v = line.split()
if len(v) != 2:
raise pkex.BasePyKatException("maxtem command `{0}` is incorrect.".format(line))
else:
......@@ -422,13 +468,13 @@ class kat(object):
else:
self.maxtem = int(v[1])
elif(first == "retrace"):
v = line.split(" ")
v = line.split()
if len(v) > 2:
raise pkex.BasePyKatException("Retrace command `{0}` is incorrect.".format(line))
elif len(v) == 2:
self.retrace = v[1]
elif(first == "deriv_h"):
v = line.split(" ")
v = line.split()
if len(v) != 2:
raise pkex.BasePyKatException("deriv_h command `{0}` is incorrect.".format(line))
else:
......@@ -451,9 +497,9 @@ class kat(object):
for line in after_process:
first = line.split(" ",1)[0]
if first == "gauss" or first == "gauss*" or first == "gauss**":
pykat.commands.gauss.parseFinesseText(line)
pykat.commands.gauss.parseFinesseText(line, self)
elif (first == "scale"):
v = line.split(" ")
v = line.split()
if len(v) == 3:
component_name = v[2]
if component_name in self.__detectors :
......@@ -465,7 +511,7 @@ class kat(object):
else:
raise pkex.BasePyKatException("scale command `{0}` is incorrect.".format(text))
elif (first == "pdtype"):
v = line.split(" ")
v = line.split()
if len(v) == 3:
component_name = v[1]
if component_name in self.__detectors :
......@@ -662,7 +708,7 @@ class kat(object):
perffile = open(root[0] + ".perf",'r')
for l in perffile.readlines():
vals = l.strip().split(' ')
vals = l.strip().split()
perfData.append((vals[0], float(vals[1]), float(vals[2]), float(vals[3])))
return [r, perfData]
......@@ -941,6 +987,11 @@ class kat(object):
return getattr(self, '__comp_' + name)
def remove_comments(self, string):
"""
This takes a raw Finesse code string and removes any comments
It returns a list of lines however, not a multiline string.
Also removes any extrawhite space in command lines.
"""
pattern = r"(\".*?\"|\'.*?\'|%{3}[^\r\n]*$)|(/\*.*?\*/|%[^\r\n]*$|#[^\r\n]*$|//[^\r\n]*$)"
# first group captures quoted strings (double or single)
# second group captures comments (//single-line or /* multi-line */)
......@@ -952,7 +1003,30 @@ class kat(object):
return "" # so we will return empty to remove the comment
else: # otherwise, we will return the 1st group
return match.group(1) # captured quoted-string
return regex.sub(_replacer, string)
# remove any inline comments
string = regex.sub(_replacer, string)
commands = []
for line in string.split('\n'):
line = line.replace('\r','')
if len(line) > 0:
# remove any mutliple whitespace
line = " ".join(line.split())
# add to a list all the positions of any inline comment markers
i = [line.find('#'), line.find('\\')]
i = filter(lambda a: a != -1, i)
if len(i) == 0:
commands.append(line)
else:
line = line[0:min(i)]
if len(line):
commands.append(line)
return commands
# printing pykat logo on first input