diff --git a/bin/test_hg_beam.py b/bin/test_hg_beam.py new file mode 100644 index 0000000000000000000000000000000000000000..370407fdbaff41b0cb74ba768068d722b25c43fa --- /dev/null +++ b/bin/test_hg_beam.py @@ -0,0 +1,11 @@ +import pykat +from pykat.utilities.optics.gaussian_beams import * + +gx = beam_param(w0=2e-3, z=0) +gy = beam_param(w0=1e-3, z=0) + +beam = HG_beam(gx,gy,0,0) +beam.n = 5 +beam.m = 6 + +beam.plot() \ No newline at end of file diff --git a/bin/test_remove.py b/bin/test_remove.py new file mode 100644 index 0000000000000000000000000000000000000000..ce5222441618400c4584edcd31f4b6952529e45a --- /dev/null +++ b/bin/test_remove.py @@ -0,0 +1,40 @@ +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 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 +m m2 0.5 0.5 0 n4 n5 +s s3 10 1 n5 n6 + +yaxis abs:deg + +pd pd_cav n3 + +cav c1 m1 n3 m2 n4 + +attr m1 Rc 1 +""" + +kat = finesse.kat() + +kat.parseCommands(code) + +kat.add(xaxis("lin", [0, 360], kat.m2.phi, 100)) + +kat.m1.Rcx = -1000.0 +kat.m1.Rcy = -1000.0 +kat.m2.Rcx = 1000.0 +kat.m2.Rcy = 1000.0 + +kat.maxtem = 0 + +kat.parseCommands("xaxis m1 phi lin -100 100 10") \ No newline at end of file diff --git a/pykat/commands.py b/pykat/commands.py index d8f80cd5e51068108594c61bcbf4cf56ce2cfcfa..dfbe6f7e922319582c5c046119c139ab42735ce3 100644 --- a/pykat/commands.py +++ b/pykat/commands.py @@ -12,7 +12,7 @@ from structs import * from pykat.param import Param, putter import pykat.exceptions as pkex from collections import namedtuple -from pykat.utilities.optics.gaussian_beams import gauss_param +from pykat.utilities.optics.gaussian_beams import beam_param class Command(object): __metaclass__ = abc.ABCMeta @@ -73,22 +73,22 @@ class gauss(object): if not values[0].endswith("*"): if len(values) == 6: - gp = gauss_param(kat.lambda0, w0=values[-2], z=values[-1]) + gp = beam_param(kat.lambda0, w0=values[-2], z=values[-1]) elif len(values) == 8: - gpx = gauss_param(kat.lambda0, w0=values[-4], z=values[-3]) - gpy = gauss_param(kat.lambda0, w0=values[-2], z=values[-1]) + gpx = beam_param(kat.lambda0, w0=values[-4], z=values[-3]) + gpy = beam_param(kat.lambda0, w0=values[-2], z=values[-1]) elif values[0].endswith("*"): if len(values) == 6: - gp = gauss_param(kat.lambda0, z=values[-2], zr=values[-1]) + gp = beam_param(kat.lambda0, z=values[-2], zr=values[-1]) elif len(values) == 8: - gpx = gauss_param(kat.lambda0, z=values[-4], zr=values[-3]) - gpy = gauss_param(kat.lambda0, z=values[-2], zr=values[-1]) + gpx = beam_param(kat.lambda0, z=values[-4], zr=values[-3]) + gpy = beam_param(kat.lambda0, z=values[-2], zr=values[-1]) elif values[0].endswith("**"): if len(values) == 6: - gp = gauss_param(kat.lambda0, w=values[-2], rc=values[-1]) + gp = beam_param(kat.lambda0, w=values[-2], rc=values[-1]) elif len(values) == 8: - gpx = gauss_param(kat.lambda0, w=values[-4], rc=values[-3]) - gpy = gauss_param(kat.lambda0, w=values[-2], rc=values[-1]) + gpx = beam_param(kat.lambda0, w=values[-4], rc=values[-3]) + gpy = beam_param(kat.lambda0, w=values[-2], rc=values[-1]) else: raise pkex.BasePyKatException("Unexpected ending to gauss command '{0}'".format(text)) diff --git a/pykat/node_network.py b/pykat/node_network.py index a0047929ee2d8e5ec2448855f5493ac3191ddb39..f2684c5a7471aa0b0f0314f2ec7624a483cc6592 100644 --- a/pykat/node_network.py +++ b/pykat/node_network.py @@ -9,7 +9,7 @@ import pykat.gui.graphics import pykat.exceptions as pkex from pykat.components import Component from pykat.detectors import Detector -from pykat.utilities.optics.gaussian_beams import gauss_param +from pykat.utilities.optics.gaussian_beams import beam_param class NodeNetwork(object): def __init__(self, kat): @@ -276,11 +276,11 @@ class Node(object): self.__q_comp = component if len(args) == 1: - self.__q_x = gauss_param(self._network.kat.lambda0, q=args[0]) - self.__q_y = gauss_param(self._network.kat.lambda0, q=args[0]) + self.__q_x = beam_param(self._network.kat.lambda0, q=args[0]) + self.__q_y = beam_param(self._network.kat.lambda0, q=args[0]) elif len(args) == 2: - self.__q_x = gauss_param(self._network.kat.lambda0, q=args[0]) - self.__q_y = gauss_param(self._network.kat.lambda0, q=args[1]) + self.__q_x = beam_param(self._network.kat.lambda0, q=args[0]) + self.__q_y = beam_param(self._network.kat.lambda0, q=args[1]) else: raise pkex.BasePyKatException("Must specify either 1 Gaussian beam parameter or 2 for astigmatic beams") diff --git a/pykat/utilities/optics/gaussian_beams.py b/pykat/utilities/optics/gaussian_beams.py index 20e8fcb834755261eadc71ff2ee2cce5653151fe..f7623842498909badea29bf32cbb70118e34cf8b 100644 --- a/pykat/utilities/optics/gaussian_beams.py +++ b/pykat/utilities/optics/gaussian_beams.py @@ -1,11 +1,16 @@ import pykat.exceptions as pkex -import numpy +import numpy as np import math import copy +import warnings +import cmath +from scipy.special import hermite from pykat.SIfloat import SIfloat class gauss_param(object): """ + Use beam_param instead, prefer that as a name + Gaussian beam complex parameter gauss_param is effectively a complex number with extra @@ -24,8 +29,10 @@ class gauss_param(object): """ def __init__(self, wavelength=1064e-9, nr=1, *args, **kwargs): + if self.__class__ != beam_param: + warnings.warn("Name changed. Use beam_param instead of gauss_param.") + self.__q = None - print "wavelength", wavelength, kwargs self.__lambda = SIfloat(wavelength) self.__nr = SIfloat(nr) @@ -153,49 +160,141 @@ class gauss_param(object): # reverse beam direction def reverse(self): self.__q = -1.0 * self.__q.real + 1j * self.__q.imag + + +class beam_param(gauss_param): + pass + -class HG_gauss_beam(object): +class HG_beam(object): def __init__(self, qx, qy=None, n=0, m=0): self._qx = copy.deepcopy(qx) self._2pi_qrt = math.pow(2.0/math.pi, 0.25) - if qy == None: - self._q0 = copy.deepcopy(qx) + if qy.__class__ == beam_param: + self._qy = copy.deepcopy(qx) else: - self._q0 = copy.deepcopy(qy) + self._qy = copy.deepcopy(qy) - self.n = n - self.m = m + self._n = n + self._m = m + self._hn = hermite(n) + self._hm = hermite(m) self._calc_constants() @property def n(self): return self._n @n.setter def n(self,value): - self._n = float(value) + self._n = int(value) self._calc_constants() + self._hn = hermite(self._n) @property def m(self): return self._m @m.setter def m(self,value): - self._m = float(value) + self._m = int(value) self._calc_constants() + self._hm = hermite(self._m) + + @property + def q(self): + if self._qx.q == self._qy.q: + return self._qx.q + else: + return (self._qx.q, self._qy.q) + @q.setter + def q(self, value): + if value.__class__ == beam_param: + self._qx = copy.deepcopy(value) + self._qy = copy.deepcopy(value) + else: + self._qx = beam_param(q=complex(value)) + self._qy = beam_param(q=complex(value)) + + @property + def qx(self): + return self._qx.q + + @qx.setter + def qx(self, value): + if value.__class__ == beam_param: + self._qx = copy.deepcopy(value) + else: + self._qx = beam_param(q=complex(value)) + + @property + def qy(self): + return self._qy.q + @qy.setter + def qy(self, value): + if value.__class__ == beam_param: + self._qy = copy.deepcopy(value) + else: + self._qy = beam_param(q=complex(value)) + def _calc_constants(self): self.__xpre_const = math.pow(2.0/math.pi, 0.25) - self.__xpre_const *= math.sqrt(1/(2**self._n * math.factorial(self._n))) - self.__xpre_const *= math.sqrt(1j*self._qx.imag / self._qx) - self.__xpre_const *= math.pow((1j*self._qx.imag * self._qx.conjugate)/(-1j*self._qx.imag * self._qx), self._n/2.0) + self.__xpre_const *= math.sqrt(1.0/(2**self._n * math.factorial(self._n))) + self.__xpre_const *= cmath.sqrt(1j*self._qx.imag / self._qx.q) + self.__xpre_const *= ((1j*self._qx.imag * self._qx.q.conjugate())/(-1j*self._qx.imag * self._qx.q)) ** ( self._n/2.0) self.__ypre_const = math.pow(2.0/math.pi, 0.25) - self.__ypre_const *= math.sqrt(1/(2**self._m * math.factorial(self._m))) - self.__ypre_const *= math.sqrt(1j*self._qy.imag / self._qy) - self.__ypre_const *= math.pow((1j*self._qy.imag * self._qy.conjugate)/(-1j*self._qy.imag * self._qy), self._m/2.0) - - def Unm(self, n, m, x, y): - # need to finish... - return self.__xpre_const + self.__ypre_const *= math.sqrt(1.0/(2**self._m * math.factorial(self._m))) + self.__ypre_const *= cmath.sqrt(1j*self._qy.imag / self._qy.q) + self.__ypre_const *= ((1j*self._qy.imag * self._qy.conjugate())/(-1j*self._qy.imag * self._qy.q)) **(self._m/2.0) + + self.__sqrt2_wxz = math.sqrt(2) / self._qx.w + self.__sqrt2_wyz = math.sqrt(2) / self._qy.w + + self.__kx = 2*math.pi / self._qx.wavelength + self.__ky = 2*math.pi / self._qy.wavelength + + self.__invqx = 1/ self._qx.q + self.__invqy = 1/ self._qy.q + + def _Un(self, x): + return self.__xpre_const * self._hn(self.__sqrt2_wxz * x) * np.exp(-0.5j * self.__kx * x*x * self.__invqx) + + def _Um(self, y): + return self.__ypre_const * self._hm(self.__sqrt2_wyz * y) * np.exp(-0.5j * self.__ky * y*y * self.__invqy) + + def Un(self, x): + vec = np.vectorize(self._Un, otypes=[np.complex64]) + return vec(x=x) + + def Um(self, y): + vec = np.vectorize(self._Um, otypes=[np.complex64]) + return vec(y=y) + + def _unm(self, x, y): + return self._Un(x) * self._Um(y) + + def Unm(self, x, y): + vec = np.vectorize(self._unm, otypes=[np.complex64]) + return vec(x=x,y=y) + + def plot(self, ndx=100, ndy=100, xscale=4, yscale=4): + import pylab + + xrange = xscale * np.linspace(-self._qx.w, self._qx.w, ndx) + yrange = yscale * np.linspace(-self._qy.w, self._qy.w, ndy) + + dx = xrange[1]-xrange[0] + dy = yrange[1]-yrange[0] + + xx, yy = np.meshgrid(xrange,yrange) + + data = self.Unm(xx, yy) + + fig = pylab.figure() + axes = pylab.imshow(np.abs(data), aspect=dx/dy, extent=[min(xrange),max(xrange),min(yrange),max(yrange)]) + pylab.xlabel('x [m]') + pylab.ylabel('y [m]') + cbar = fig.colorbar(axes) + pylab.show()