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.
Today the goal is to introduce the so-called 'site files': what they are, what they look like, where to find them, and how to start using them.
Purpose of the site files:
--> set things up a little differently to how you might on your own, and need to bear in mind 'standard practices' that have been developed or are currently the norm.
From session 1: essentially we're covering the same things but for a large-scale, long-term, multi-user model:
kat
object)kat
object# all the usual stuff we've used before
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)
design.kat
file¶Accessing the file:
design.kat
itself~/miniconda3/envs/test/lib/python3.7/site-packages/pykat/ifo/aligo/design.kat
~/GIT/finesse/pykat/pykat/ifo/aligo/design.kat
kat.load("<path>")
but misses the initialisation steps we nearly always need, so instead:we'll come back to the processing and pykat tools later. for now, let's just take a look at the file itself.
import pykat.ifo.aligo as aligo
base = aligo.make_kat()
print(base)
nREFL
* Use the design.kat file to sketch the LIGO core optical layout (PRM to SRM) and identify the names of the main components in the kat file
--> useful reference: my inkscape sketch: aLIGO_fullwsqz_Jan2019.svg (via LIGO git)
Go back and extend your sketch to include the input and output optical paths (i.e. blocks before the PRC and blocks after the SRC)
aligo
package: make_kat()
and beyond¶The design.kat
file itself is pretty stable - the aLIGO design is, in principal, still the same as it was in 2010. It can be used on it's own, with some caveats we'll cover later, but it's quite bare-bones. This is where accompanying scripts come in.
There are 4 files: ifo/aligo/__init__.py
, ifo/aligo/plot.py
, and the more general ifo/__init__.py
and ifo/plot.py
. Together they serve several purposes:
All of these scripts are a work in progress. Literally: I added new updates yesterday. So it's sometimes tricky to know what's possible.
You might have noticed that you can often use the tab
key to auto-complete function names in python. The same is true here! And it's especially useful for larger kat files where there's lots going on.
The main ways to find things are:
kat.[...]
, kat.ALIGO_IFO.[...]
and kat.IFO.[...]
(NB: only works in cells outside the cell where the current kat
is defined, even if you've already run that cell)__init__.py
and plot.py
files or using the inspect
package, to see what your function is actually doing...Finding functions: likely locations
location | contents |
---|---|
ifo/aligo/__init__.py: main functions |
The main one to look at first. Functions to create the aLIGO pykat object and prepare it for use, using info in the ALIGO_IFO class. key functions: make_kat and setup |
ifo/aligo/__init__.py: ALIGO_IFO class |
aLIGO-specific functions to edit the main kat object where those functions involve interactions between the kat and associated IFO object, e.g. add/remove blocks, set lengths so a certain frequency is resonant, etc |
ifo/aligo/plot.py | common ligo-specific plotting functions, such as the QNLS curve or error signals vs DOFs |
ifo/__init__.py | Tools that are less detector-specific, plus definitions for classes used in all IFO objects, e.g. DOF |
ifo/plot.py | plotting functions that are less detector-specific. |
Didn't just do kat.load(design.kat)
- we used make_kat()
. Essentially that's where all the missing features are!
Run inspect on aligo.make_kat()
- bit intimidating but quick scan through shows that we basically define a lot of:
port
s of class Output
signal
s of class DOF
kat.IFO.PRCL
defines the PRCL dof, associating it with the POP_f1 port (a demodulated PD behind PR2) and the tuning of the PRM, with some scaling etc wrt other DOFs. import inspect
print(inspect.getsource(aligo.make_kat))
# 1. add a power detector automatically in the right place (and get the power there)
kat = base.deepcopy()
kat.IFO.POW_X.add_signal()
kat.noxaxis=True
o=kat.run()
print(o[kat.IFO.POW_X.name])
# 2. plot an error signal for a DOF quickly
kat = base.deepcopy()
o = kat.IFO.CARM.scan()
o.plot()
kat.IFO.CARM.signal_name
# list all available detectors (Outputs) or DOFs available for use this way
kat.IFO.Outputs, kat.IFO.DOFs
2 methods. (1) we do it by hand, and (2) we make use of a handy function included in the ligo plotting tools.
Using the plotting tool, we just need to
import pykat.ifo.aligo.plot as aligoplt
strain_sensitivity()
function from this package to directly plot the curve with some default parameter ranges.
- take a look at the function iteself in `pykat/ifo/aligo/plot.py` to see what's actually going on.
Use either method to plot the quantum-limited sensitivity of the LIGO design. How does it compare to the design curve we usually show, such as that shown on gwplotter.com?
import pykat.ifo.aligo.plot as aligoplt
aligoplt.strain_sensitivity(base)
either way, this doesn't look right. In fact, it looks rubbish!
What are we missing?
Ans: we're not at an operating point!
setup
to run through the file, using realistic error signals for the main degrees of freedom, to set the tunings of the main optics to get everything resonant (or anti-resonant) as required. all we need is
base2 = aligo.setup(base)
aligoplt.strain_sensitivity(base2)
base2 = aligo.setup(base)
aligoplt.strain_sensitivity(base2)
You might see this version which is flat at low frequencies - no Quantum Radiation Pressure Noise taken into account!
Actually, we spotted this a while ago, I made a corrected version that's propagating through the system now... If not, main issue is that the mirrors get fixed in place by setup() & have infinite mass. If we restore the mass values, they act as suspended free masses and we see the 'full' QNLS plot:
LIGO = base2.deepcopy()
LIGO.ETMX.mass = LIGO.ETMY.mass = LIGO.ITMX.mass = LIGO.ITMY.mass = 40
aligoplt.strain_sensitivity(LIGO)
print(inspect.getsource(aligoplt.strain_sensitivity))
print(base.IFO.DARM_h.signal())
print(base.IFO.DARM_h.transfer())
print(base.IFO.DARM_h.optics)
print(base.IFO.DARM.optics)
print(base.IFO.DARM_h.fsig())
kat = base2.deepcopy()
kat.parse("""
fsig DARM_h LY phase 1.0 180.0 1
fsig DARM_h LX phase 1.0 0.0 1
qnoisedS NSR 1 $fs nAS
xaxis DARM_h f log 10 5000 100
yaxis log abs
""")
o = kat.run()
o.plot(['NSR'])