Add cavity parameter calculations to Pykat directly
The following code is a replica of the Finesse cavity parameter calculations. I thought this would be useful to put into Pykat as you don't need to call the binary each time to find this stuff out.
Some notes:
- Only works for ring cavities
- Needs to determine when a two-mirror cavity is used and trace back on itself
- Needs to determine when a cavity is between two different components, like SRX.
- Then this needs to be wrapped up in the cavity command class
def finesse(cavity_loss):
assert(cavity_loss> 0)
if cavity_loss == 0.0:
return np.inf
elif cavity_loss == 1.0:
return 0.0
else:
l = np.sqrt(1.0 - cavity_loss);
return (np.pi / (2.0 * np.arcsin((1.0 - l) / (2.0 * np.sqrt(l)))))
node_start = "nMC1trans"
node_end = "nMC1fromMC3"
start_nodes = (base.nodes[node_end], base.nodes[node_start])
comp_list, node_list = base.nodes.getComponentsBetween(*start_nodes[::-1], True)
comp_list = list(comp_list)
node_list = list(node_list)
comp_list.append(base.MC1)
node_list.append(start_nodes)
length_RT = 0
cavity_power = 1 # Start with unit amount of power
M = np.matrix(np.eye(2))
for comp, nodes in zip(comp_list, node_list):
M = comp.ABCD(*nodes) * M
if isinstance(comp, pykat.components.space):
length_RT += comp.L.value * comp.n.value
elif isinstance(comp, (pykat.components.AbstractMirrorComponent)):
# Here we check if the cavity trace involves reflecting or
# transmitting through a mirror or beamsplitter
isRefl = False
if isinstance(comp, (pykat.components.mirror)):
if nodes[0] == nodes[1]:
isRefl = True
else:
isRefl = False
elif isinstance(comp, (pykat.components.beamSplitter)):
# here we use sets to check if the nodes we have are
# in reflection nodes or transmission
if set(nodes) >= set(comp.nodes[2:]) or set(nodes) >= set(comp.nodes[:2]):
isRefl = True
elif set(nodes) >= set(base.MC1.nodes[1::2]) or set(nodes) >= set(base.MC1.nodes[0::2]):
isRefl = False
# Then we adjust the cavity power...
if isRefl:
# Take into account R,T can be None if m1/m2/bs1/bs2 used...
if comp.R.value is None:
cavity_power *= 1-comp.T.value-comp.L.value
else:
cavity_power *= comp.R.value
else:
if comp.T.value is None:
cavity_power *= 1-comp.R.value-comp.L.value
else:
cavity_power *= comp.T.value
A,B,C,D = tuple(M.flatten()[0,i] for i in range(4))
m = (A+D)/2
g = (m + 1)/2
gouyRT = 2*np.arccos(np.sign(B) * np.sqrt(g))
FSR = 299792458 / length_RT
mode_spacing = 2*np.pi*FSR
_finesse = finesse(1-cavity_power)
FWHM = FSR / _finesse
pole = FWHM / 2.0
m, g, gouyRT, FSR, _finesse, cavity_loss, pole