Author: Anna Green
This notebook was developed as part of a series of tutorial workshops at the University of Florida in 2019. It is currently in the process of being 'polished' to fit the Learn Interferometry course.
from pykat import finesse # import the whole pykat.finesse package
from pykat.commands import * # import all packages in pykat.commands
import numpy as np # for basic math/sci/array functions
import matplotlib.pyplot as plt # for plotting
# tell the notebook to automatically show plots inline below each cell
%matplotlib inline
# use pykat's plotting style. change dpi to change plot sizes on your screen
pykat.init_pykat_plotting(dpi=90)
Recall: PDH error signal for a FP cavity:
#initialise Finesse with a new empty kat object
basekat = finesse.kat()
#tell Finesse to talk less
basekat.verbose = False
#parse the Finesse code into PyKat
basekat.parse("""
l laser 1 0 n0
#modulator
s smod 0 n0 nmod1
mod eom 80M 0.3 1 pm nmod1 nmod2
s s0 0 nmod2 n1
#the cavity:
m1 M1 0.15 0 0 n1 n2
s scav 0.2 n2 n3
m1 M2 0.15 0 0 n3 n4
#Gaussian model
attr M1 Rc -0.15
attr M2 Rc 0.15
cav FPcav M1 n2 M2 n3
maxtem 2
#photodiode and xaxis
pd Ptrans n4
pd1 PDH 80M 0 n2
xaxis M2 phi lin -40 40 200
""")
def pltPE(kat,label=None):
out=kat.run()
ax1.plot(out.x,out["Ptrans"],label=label)
ax1.set_ylabel("Transmitted power")
ax2.plot(out.x,out["PDH"])
ax2.set_xlabel('M2 tuning [deg]')
ax2.set_ylabel('PDH Error Signal')
if label:
ax1.legend()
fig,(ax1,ax2) =plt.subplots(2,1)
pltPE(basekat)
static, simple model:
mirror tunings of zero means the cavity is on resonance. Unlike reality, we don't need an active feedback loop to keep this true.
more compex model with more going on:
changing one variable somewhere in the model ends up also affecting the resonant condition of the cavity, so we do need an active control to stay at the cavity's operating point and mimic the true situation in the experimental setup.
k = basekat.deepcopy()
k.M1.phi = 5
fig,(ax1,ax2) =plt.subplots(2,1)
pltPE(basekat,label='original')
pltPE(k,label='M1 detuned 5deg')
k = basekat.deepcopy()
k.parse("""
gauss input laser n0 150u -0.15""")
fig,(ax1,ax2) =plt.subplots(2,1)
pltPE(basekat,label='original FP cavity')
pltPE(k,label='input mode z_0 shifted')
ax1.legend(loc=2,bbox_to_anchor=(1,1))
lock
command in Finesse¶This is not a true feedback loop. It doesn't actively and dynamically respond to the system using any kind of transfer function with electronic filters etc. It just tries to mimic a simple integrator:
For each step of the x-axis command:
set
or via some additional mathematics using func
. new_val = old_val + gain * variable
, and apply this to the specified optic parameter|variable|>accuracy
, iterate steps 3 & 4 until |variable|<=accuracy
out
. Obviously it will fail if:
A fine tuning of the gain is useful to minimise the computation time
E.g. for a simple cavity with a PDH error signal on reflection called pdh
and mirrors m1
and m2
:
set err pdh re
lock z $err -10 10n
put* m1 phi $z
set
defines the variable, err
used in the iterative looplock
defines the gain and accuracy used in each integrator-like iterationput*
applies the output of the loop as a delta to the current tuning of m1
.You might also see something like
set err pdh re
func newerr = $err + 1E-1
lock z $newerr -10 10n
put* m1 phi $z
func
applies additional maths to the variable before it is used in the integrator-like iterating loop. It can be quite temperamental, so see the syntax reference for guidance.kat = finesse.kat()
kat.parse("""l i1 1 0 n0
mod eo1 40k 0.3 3 pm n0 n11
s s0 0 n11 n1
m m1 0.9 0.1 0 n1 n2
s s1 1200 n2 n3
m m2 .9 0.01 0 n3 n4
pd1 pdh 40k 0 n1
xaxis m2 phi lin 0 10 40""")
o=kat.run()
o.plot()
kat1 = kat.deepcopy()
kat1.parse("""
set err pdh re
lock z $err -10 10n
put* m1 phi $z""")
o=kat1.run()
o.plot()
kat2 = kat.deepcopy()
kat.parse("""
set err pdh re
func newerr = $err + 1E-1
lock z $newerr -10 10n
put* m1 phi $z""")
o=kat.run()
o.plot()
How to choose the gain?
kat = basekat.deepcopy()
fig,(ax1,ax2) = plt.subplots(2,1)
pltPE(kat)
ax2.set_xlim(-4,4)
plt.show()
slopeguess = 1/0.08#dx/dy
kat.parse("""
set err PDH re
lock z $err {} 10n
put* M1 phi $z
xaxis M2 phi lin 0 50 400
""".format(slopeguess))
kat.verbose=True
o=kat.run()
o.plot()
lock
command isn't a true feedback loop, but an iterative flat integrator computed at each discrete xaxis step.lock
and func
commands are a bit finniky to set up and take a lot of manual tuning to absolutely optimise. They break easily if something is set wronglock
command means that a multi-step iteration of the whole interferometer calculation for every x-axis value. I.e., it's slow, especially if not perfectly optimised.