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

Merge branch 'master' of gitlab.aei.uni-hannover.de:finesse/pykat

parents 0b98c87d 9546c4b7
......@@ -3,7 +3,7 @@ from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
__version__ = "1.0.6"
__version__ = "1.0.8"
# This flag is used to switch on the gui features in pkat at import time
USE_GUI = False
......
......@@ -901,7 +901,21 @@ class grating(Component):
return self._svgItem
class isolator(Component):
def __init__(self, name, node1, node2, S = 0, node3="dump", option=0):
def __init__(self, name, node1, node2, S = 0, node3="dump", option = 0, L = 0):
"""
Creates an isolator component. Ligth passes from node 1 to node 2, and from node
2 to node 3.
S Suppression factor for the reversed direction [power dB].
L Loss, fraction of input power loss. Number between 0 and 1.
option 0: Light passes from node1 to node2, and from node2 to node3. Light
is suppressed when going from node3 to node2, and from node2 to
node1.
1: Light passes from node2 to node1, and from node3 to node2. Light
is suppressed when going from node1 to node2, and from node2 to
node3.
"""
Component.__init__(self, name)
self._requested_node_names.append(node1)
......@@ -911,11 +925,18 @@ class isolator(Component):
self._option = option
self.__S = Param("S",self,SIfloat(S))
self.__L = Param("L",self,SIfloat(L))
@property
def S(self): return self.__S
@S.setter
def S(self, value): self.__S.value = SIfloat(value)
@property
def L(self): return self.__L
@L.setter
def L(self, value): self.__L.value = SIfloat(value)
@staticmethod
def parseFinesseText(text):
......@@ -934,7 +955,16 @@ class isolator(Component):
if len(values) == 4:
return isolator(values[0], values[2], values[3], values[1], option=option)
elif len(values) == 5:
return isolator(values[0], values[2], values[3], node3=values[4], S=values[1], option=option)
# Checking if loss is specified, should be a number.
if values[2].isnumeric():
return isolator(values[0], values[3], values[4], values[1],
L=values[2], option=option)
# .. if not a number, it's a node name.
else:
return isolator(values[0], values[2], values[3], node3=values[4],
S=values[1], option=option)
elif len(values) == 6:
return isolator(values[0], values[3], values[4], values[1], values[5], option, values[2])
else:
raise pkex.BasePyKatException("Isolator Finesse code format incorrect '{0}'".format(text))
......@@ -944,11 +974,11 @@ class isolator(Component):
elif self._option == 1:
cmd = "isol*"
rtn = ['{cmd} {0} {1} {2} {3} {4}'.format(self.name, self.S.value, self.nodes[0].name, self.nodes[1].name, self.nodes[2].name, cmd=cmd)]
rtn = ['{cmd} {0} {1} {2} {3} {4} {5}'.format(self.name, self.S.value, self.L.value, self.nodes[0].name, self.nodes[1].name, self.nodes[2].name, cmd=cmd)]
for p in self._params:
rtn.extend(p.getFinesseText())
return rtn
def getOptivisComponent(self):
......@@ -987,35 +1017,58 @@ class isolator(Component):
return self._svgItem
class lens(Component):
def __init__(self, name, node1, node2, f=1):
def __init__(self, name, node1, node2, f=1, p=None):
Component.__init__(self, name)
if not ((f is None) ^ (p is None)):
raise pkex.BasePyKatException("Specify either a focal length or power, not both.")
self._requested_node_names.append(node1)
self._requested_node_names.append(node2)
self._svgItem = None
self.__f = Param("f", self, SIfloat(f))
self.__p = Param("p", self, SIfloat(p))
@property
def f(self): return self.__f
@f.setter
def f(self, value): self.__f.value = SIfloat(value)
def f(self, value):
self.__f.value = SIfloat(value)
self.__p.value = None
@property
def p(self): return self.__p
@p.setter
def p(self, value):
self.__p.value = SIfloat(value)
self.__f.value = None
@staticmethod
def parseFinesseText(text):
values = text.split()
if values[0] != "lens":
if not values[0].startswith("lens"):
raise pkex.BasePyKatException("'{0}' not a valid Finesse lens command".format(text))
alt = values[0].endswith("*")
values.pop(0) # remove initial value
if len(values) == 4:
return lens(values[0], values[2], values[3], values[1])
if not alt:
return lens(values[0], values[2], values[3], f=values[1], p=None)
else:
return lens(values[0], values[2], values[3], f=None, p=values[1])
else:
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)]
if self.__p.value is None:
rtn = ['lens {0} {1} {2} {3}'.format(self.name, self.f.value, self.nodes[0].name, self.nodes[1].name)]
else:
rtn = ['lens* {0} {1} {2} {3}'.format(self.name, self.p.value, self.nodes[0].name, self.nodes[1].name)]
for p in self._params:
rtn.extend(p.getFinesseText())
......
......@@ -642,13 +642,19 @@ class Signals(object):
@property
def f(self): return self.__f
@f.setter
def f(self,value): self.__f.value = SIfloat(value)
def f(self,value):
v = SIfloat(value)
if v <= 0:
raise pkex.BasePyKatException("Signal frequency must be greater than 0.")
self.__f.value = SIfloat(value)
def __init__(self, kat):
self._default_name = "fsignal"
self.targets = []
self._params = []
self.__f = Param("f", self, 0)
self.__f = Param("f", self, None)
self._kat = kat
def _register_param(self, param):
......@@ -667,21 +673,22 @@ class Signals(object):
def getFinesseText(self):
rtn = []
if len(self.targets) == 0 and (self.f != 0 and self.f is not None):
rtn.append("fsig {name} {frequency}"
.format(name = self.name,
frequency=str(self.f)))
else:
for t in self.targets:
rtn.extend(t.getFinesseText())
rtn.append("fsig {name} {comp} {target} {frequency} {phase} {amplitude}"
.format(name = t.name,
comp=t.owner,
target=t.target,
frequency=str(self.f),
phase=str(t.phase),
amplitude=str(t.amplitude if t.amplitude != None else "")))
if self.f.value is not None and self.f is not None:
if len(self.targets) == 0:
rtn.append("fsig {name} {frequency}"
.format(name = self.name,
frequency=str(self.f.value)))
else:
for t in self.targets:
rtn.extend(t.getFinesseText())
rtn.append("fsig {name} {comp} {target} {frequency} {phase} {amplitude}"
.format(name = t.name,
comp=t.owner,
target=t.target,
frequency=str(self.f.value),
phase=str(t.phase),
amplitude=str(t.amplitude if t.amplitude != None else "")))
for p in self._params:
rtn.extend(p.getFinesseText())
......
......@@ -19,6 +19,8 @@ from scipy.optimize import minimize
from pykat.math.zernike import *
from pykat.exceptions import BasePyKatException
from copy import deepcopy
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import math
......@@ -43,7 +45,7 @@ class MirrorROQWeights:
class surfacemap(object):
def __init__(self, name, maptype, size=None, center=None, step_size=1.0, scaling=1.0e-9, data=None,
notNan=None, RcRemoved=None, zOffset=None, xyOffset=(.0,.0)):
notNan=None, zOffset=None, xyOffset=(.0,.0)):
'''
size, center, step_size, xyOffset are all tuples of the form (x, y),
i.e., (col, row).
......@@ -70,7 +72,7 @@ class surfacemap(object):
self.center = center
self.step_size = step_size
self.scaling = scaling
self.RcRemoved = RcRemoved
self._RcRemoved = None
# Offset of fitted sphere. Proably unnecessary to have here.
self.zOffset = zOffset
self.__interp = None
......@@ -119,15 +121,15 @@ class surfacemap(object):
# Checking so new suggested "center" is within the the mirror surface
if (x0new>0 and x0new<self.size[0]-1 and y0new>0 and y0new<self.size[1]-1 and
self.notNan[round(x0new),round(y0new)]):
self.notNan[round(y0new), round(x0new)]):
self.center = (x0new, y0new)
self._xyOffset = (offset[0], offset[1])
else:
print(('Error in xyOffset: ({:.2e}, {:.2e}) m --> pos = ({:.2f}, {:.2f}) '+
raise BasePyKatException( ('Error in xyOffset: ({:.2e}, {:.2e}) m --> pos = ({:.2f}, {:.2f}) '+
'is outside mirror surface.').format(offset[0],offset[1],x0new,y0new))
@property
def betaRemoved(self):
return self._betaRemoved
......@@ -409,7 +411,6 @@ class surfacemap(object):
# xlim and ylim given in centimeters
def plot(self, show=True, clabel=None, xlim=None, ylim=None, isBlock=False):
import pylab
if xlim is not None:
# Sorts out the x-values within xlim
......@@ -448,22 +449,22 @@ class surfacemap(object):
yRange = 100*self.y
# xRange, yRange = np.meshgrid(xRange,yRange)
fig = pylab.figure()
fig = plt.figure()
# Important to remember here is that xRange corresponds to column and
# yRange to row indices of the matrix self.data.
pcm = pylab.pcolormesh(xRange, yRange, self.data)
pcm = plt.pcolormesh(xRange, yRange, self.data)
pcm.set_rasterized(True)
pylab.xlabel('x [cm]')
pylab.ylabel('y [cm]')
plt.xlabel('x [cm]')
plt.ylabel('y [cm]')
if xlim is not None: pylab.xlim(xlim)
if ylim is not None: pylab.ylim(ylim)
if xlim is not None: plt.xlim(xlim)
if ylim is not None: plt.ylim(ylim)
pylab.title('Surface map {0}, type {1}'.format(self.name, self.type))
plt.title('Surface map {0}, type {1}'.format(self.name, self.type))
cbar = pylab.colorbar()
cbar = plt.colorbar()
cbar.set_clim(zmin, zmax)
# cbar.set_clim(-1.86, 1.04)
......@@ -471,7 +472,7 @@ class surfacemap(object):
cbar.set_label(clabel)
if show:
pylab.show(block=isBlock)
plt.show(block=isBlock)
return fig
......@@ -580,7 +581,7 @@ class surfacemap(object):
# x and y step sizes are different.
elif method=='area' or method=='Area' or method=='AREA':
if unit == 'meters' or unit == 'metres' or unit=='Meters' or unit=='Metres':
r = step_size[0]*math.sqrt(len(cIndx)/math.pi)
r = self.step_size[0]*math.sqrt(len(cIndx)/math.pi)
else:
r = math.sqrt(len(cIndx)/math.pi)
elif method=='min':
......@@ -1794,8 +1795,8 @@ def read_map(filename, mapFormat='finesse', scaling=1.0e-9, mapType='phase', fie
step = tuple(map(g, f.readline().split(':')[1].strip().split()))
scaling = float(f.readline().split(':')[1].strip())
data = np.loadtxt(filename, dtype=np.float64,ndmin=2,comments='%')
data = np.loadtxt(filename, dtype=np.float64,ndmin=2,comments='%')
return surfacemap(name, maptype, size, center, step, scaling, data)
elif mapFormat.lower() == 'ligo' or mapFormat.lower() == 'zygo':
......
Markdown is supported
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