**2. Plane Waves > 4. Demodulation**

**1. Double Demodulation**

Author: Daniel TÃ¶yrÃ¤

** Recommended notebooks before you start:**

We recommend that you have looked through the notebook 01_Single_demodulation that you find in the folder 02_Plane_waves/04_Demodulation before you start this one, or that you have basic experience of IPython/Jupyter Notebooks, PyKat, Finesse, and modulation/demodulation. The link above only works if you started IPython/Jupyter Notebook in the top directory of this course.

**Reading material and references:**

[1] A. Freise, K. Strain, D. Brown, and C. Bond, "Interferometer Techniques for Gravitational-Wave Detection", *Living Reviews in Relativity* **13**, 1 (2010). - Living review article (more like a book) on laser interferometry in the frequency domain for detecting gravitational waves, and FINESSE.

[2] A. Freise, D. Brown, and C. Bond, "Finesse, Frequency domain INterferomEter Simulation SoftwarE". - FINESSE-manual

[3] FINESSE syntax reference - Useful online syntax reference for FINESSE. Also available in the Finesse manual [2], but this online version is updated more frequently.

** After this session you will... **

- have used the FINESSE component
`pd2`

to double demodulate a double amplitude modulated laser field. - have seen that by using two double demodulation schemes, with the second demodulation phases 90 degrees shifted from each other, one can extract the full amplitude and phase of the double demodulation signal.

Importing PyKat and other Python packages that we need, and setting up how to display figures.

In [2]:

```
import numpy as np # Importing numpy
import matplotlib # For plotting
import matplotlib.pyplot as plt
from pykat import finesse # Importing the pykat.finesse package
from pykat.commands import * # Importing all packages in pykat.commands.
from IPython.display import display, HTML # Allows us to display HTML.
# Telling the notebook to make plots inline.
%matplotlib inline
# Initialises the PyKat plotting tool. Change the dpi value
# to adjust size of figures on your screen.
pykat.init_pykat_plotting(dpi=90)
```

An example of an application of double demodulation is to compute how sensitive an interferometry control system is to an external signal, such as a gravitational wave, seismic noise, laser amplitude noise, laser frequency noise, quantum noise, and so on. The first modulation-demodulation scheme creates a control signal, where both the amplitude, phase and frequency of the scheme is user defined and well controlled. The second demodulation extracts information about how the control signal is affected by the external signal. The phase and amplitude of this external signal may be unknown, but just as for single demodulation we can demodulate in-phase and in-quadrature to extract both the amplitude and phase information of it. More on this in later notebooks on interferometry control systems. A double demodulation scheme can be broken down as follows:

- Modulate the carrier field twice. This can be done by an electro-optic modulator, some noise source, a gravitational wave etc. The first modulation creates the blue sidebands in the figure above, and the second creates the black and green sidebands.
- Detect the power by using a photo diode
- Demodulate the power signal with a user-defined local oscillator of frequency $\omega_x$ and phase $\varphi_x$. This step is performed by an electronic mixer, mathematically this means that the power signal is multiplied with $\cos(\omega_x t + \varphi_x)$.
- Mix the resultant signal again, this time with a signal of frequency $\omega_y$ and phase $\varphi_y$.
- Low-pass filter the signal so that only the DC part remains. The output is a DC-signal that is proportional to the amplitudes of the blue and green sidebands in the figure above.

Assuming that we already know the optimal demodulation phase $\varphi_x$ for the blue sidebands, we can by using two mixers in parallel, phase shifted 90 degrees from each other, reconstruct the phase of the demodulation signal, and subsequently obtain the phase and amplitude of the green sidebands in the figure.

You can read more about double demodulation in section 4.2. in the living review article [1]. Here we jump into a FINESSE example.

`mod`

). We first build our optical model consisting of an input laser, an two EOMs in series. The first one amplitude modulates the carrier field on 1 MHz with 20 degrees modulation phase, the second one amplitude modulates the field on 1 kHz with a modulation phase of 60 degrees. We also add an empty space between all components, as well as after the second EOM, which will soon connect the EOM with the detectors as seen in the figure above.

In [151]:

```
basekat = finesse.kat() # Initialising Finesse
basekat.verbose = False # Tells Finesse to talk less
basecode = """
## The optical system ##
l laser 100 0 n0 # Laser (P = 100 W, Freq. offset = 0 Hz)
s s1 1 n0 n1 # Space, laser to EOM (L = 1 m)
mod eom1 1M 0.5 1 am 20 n1 n2 # Modulator (f = 1 MHz, m=0.5, 1 sideband pair,
# type = amplitude modulation, phase = 20 deg.)
s s2 1 n2 n3 # Space, eom1 to eom2 (L = 1 m)
mod eom2 1k 0.3 1 am 60 n3 n4 # Modulator (f = 1 kHz, m=0.3, 1 sideband pair,
# type = amplitude modulation, phase = 60 deg.)
s s3 1 n4 n5 # Space, eom2 to output (L = 1 m)
"""
# Parsing the FINESSE-code
basekat.parseCommands(basecode)
```

In [152]:

```
kat1a = basekat.deepcopy()
code = """
## Detectors ##
pd1 inphase 1M 0 n5 # Photodiode + mixer + low pass filter
# (f1 = 1 MHz, phi1 = 0 deg)
pd1 inquad 1M 90 n5 # Photodiode + mixer + low pass filter
# (f1 = 1 MHz, phi1 = 90 deg)
## Simulation Instructions ##
noxaxis # No xaxis. Computing just one data point.
yaxis abs # Returns absolute values of detector outputs
"""
# Parsing the code and running the simulation
kat1a.parseCommands(code)
out1a = kat1a.run()
```

Now we reconstructing the full complex signal, and computing the phase of it:

In [156]:

```
# Reconstructing full complex demodulation signal
S1 = out1a['inphase'] + 1j*out1a['inquad']
# Calculating the phase
phase1 = np.angle(S1)*180.0/np.pi
print('Optimal demodulation phase at 1 MHz: {:f} deg'.format(phase1))
```

Maybe you expected the phase to be 20 degrees? If would have measured this immediately after the modulator it would have been, but we measure it 2 meters later, and the 1 MHz difference between the carrier and the sideband creates an extra phase shift.

With this information, we go to double demodulation. We will here use three different demodulation schemes, which we in FINESSE can put at the exact same node simultaneously. In reality we would need to divide the power signal into three parts, but this is not necessary in a simulation. The power is in all three cases measured by a photodiode. After the power is measured we demodulate (mix) the power signal twice. Once on 1 MHz with the demodulation phase obtained above ($\varphi_x = 17.598$ Hz), and once the frequency 1 kHz. The second demodulation is performed with a different demodulation phase in each of the three demodulation schemes: $\varphi_y = 0$ which we call in-phase, $\varphi_y = 90$ degrees which we call in-quadrature, and $\varphi_x = $ `max`

, which automatically uses the optimal demodulation phase. After mixing with local oscillators, we low pass filter our signals so that only the DC-parts remain. These four steps (photo diode + mixing1 + mixing2 + low pass filter) are performed by the the FINESSE components with the keyword `pd2`

, where `2`

stands for double demodulation. While doing these measurement, we are varying the modulation index of `eom2`

.

In [162]:

```
kat1b = basekat.deepcopy()
code = """
## Detectors ##
pd2 inphase 1M {0} 1k 0 n5 # Photodiode + mixer + low pass filter
# (f1 = 1 MHz, phi1 = 20 deg,
# f2 = 1 kHz, phi2 = 0 deg)
pd2 inquad 1M {0} 1k 90 n5 # Photodiode + mixer + low pass filter
# (f1 = 1 MHz, phi1 = 20 deg,
# f2 = 1 kHz, phi2 = 90 deg)
pd2 optimal 1M {0} 1k max n5 # Photodiode + mixer + low pass filter
# (f1 = 1 MHz, phi1 = 20 deg,
# f2 = 1 kHz, phi2 = max)
## Simulation Instructions ##
xaxis eom2 midx lin 0 1 200 # Varying EOM modulation between 0 and 1
yaxis abs # Returns absolute values of detector outputs
""".format(phase1)
# Parsing the code and running the simulation
kat1b.parseCommands(code)
out1b = kat1b.run()
# Plotting the detector outputs
fig1b = out1b.plot(xlabel='Modulation index of eom2',
ylabel='Power [W]')
```

The figure shows three traces with different second demodulation phases $\varphi_y$. The one called in phase has $\varphi_y = 0$ and the one called quadrature has $\varphi_x = 90~\mathrm{degrees})$. For the trace called optimal we used the FINESSE command `max`

to automatically get the maximum output for each data point. As we can see, the optimal trace gives the largest output for all modulation indices, as expected. Now we reconstruct the full complex signal using our in-phase and in-quadrature detector outputs according to

To see why, see section 4.2. in the living review article [1]. We compare the magnitude of this reconstructed signal with the optimal "cheat" signal obtained directly from FINESSE.

In [177]:

```
# Reconstructing
S2 = out1b['inphase'] + 1j*out1b['inquad']
## Plotting ##
# Plotting the the absolute value
fig1c = plt.figure(figsize = (8,3))
ax = plt.subplot(1,1,1)
ax.plot(out1b.x, np.abs(out1b['optimal']),
'r-', label='Optimal')
ax.plot(out1b.x, np.abs(S2),
'k--', label='Reconstructed')
ax.set_ylabel('Power [W]')
ax.set_xlabel('Modulation index of eom2')
ax.set_title('')
ax.legend(loc=0, fontsize=10)
'''
# Plotting the phase (Converting from radians to degrees)
ax2 = plt.subplot(2,1,2)
ax2.plot(out1b.x, np.angle(out1b['optimal'])*180/np.pi, 'r-', label='Optimal')
ax2.plot(out1b.x, np.angle(S2)*180/np.pi, 'k--', label='Reconstructed')
ax2.set_xlabel('Modulation index of eom2')
ax2.set_ylabel('Phase [deg]')
ax2.set_ylim((0,70))
ax2.legend(loc=0, fontsize=10)
'''
plt.show()
# Calculating and printing the phase of S2 in degrees
phase2 = np.angle(S2[1])*180/np.pi
print('Phase of S2: {:.4f} deg'.format(phase2))
```

We see that our reconstructed signal exactly follows the signal obtained by using the "cheat" phase `max`

. The phase only deviated slightly from the 60 degrees modulation phase. This is because the frequency difference between the carrier and the sideband only is 1 kHz in this case, and 1 meter is not enough for building up a significant phase shift for this small frequency deviation. To explicitly show that the phase is reconstructed as well we wait until the task below.

In FINESSE you can always "cheat" and obtain the optimal trace by using the keyword `max`

, as seen above. However, we would recommend to manually find the optimal demodulation phase as it is safer for complicated setups. You can even obtain the full complex demodulation signal directly by leaving the spot for demodulation phase empty, and using `yaxis abs:deg`

, which we will see below in the task.

**Answer:**

In [ ]:

```
```

**Answer:**

We need to change two things from the example code:

- Remove
`max`

from the second demodulation phase of the`pd2`

detector`optimal`

, and leave it empty. If the`yaxis`

allows it, this detector will then output the complex representation of $S_2$. - Switch to
`yaxis abs:deg`

to obtain the full complex representation of the detector`optimal`

.

In [193]:

```
kat2 = basekat.deepcopy()
code = """
## Detectors ##
pd2 inphase 1M {0} 1k 0 n5 # Photodiode + mixer + low pass filter
# (f1 = 1 MHz, phi1 = 20 deg,
# f2 = 1 kHz, phi2 = 0 deg)
pd2 inquad 1M {0} 1k 90 n5 # Photodiode + mixer + low pass filter
# (f1 = 1 MHz, phi1 = 20 deg,
# f2 = 1 kHz, phi2 = 90 deg)
pd2 optimal 1M {0} 1k n5 # Photodiode + mixer + low pass filter
# (f1 = 1 MHz, phi1 = 20 deg,
# f2 = 1 kHz, phi2 = max)
## Simulation Instructions ##
xaxis eom2 midx lin 0 1 200 # Varying EOM modulation between 0 and 1
yaxis abs:deg # Returns absolute values of detector outputs
""".format(phase1)
# Parsing the code and running the simulation
kat2.parseCommands(code)
out2 = kat2.run()
```

`inphase`

and `inquad`

, and compare both the amplitude and phase to the output of the detector `optimal`

.

In [194]:

```
# Reconstructing
S2 = out2['inphase'] + 1j*out2['inquad']
## Plotting ##
# Plotting the the absolute value
fig2 = plt.figure(figsize = (8,6))
ax = plt.subplot(2,1,1)
ax.plot(out2.x, np.abs(out2['optimal']),
'r-', label='Optimal')
ax.plot(out2.x, np.abs(S2),
'k--', label='Reconstructed')
ax.set_ylabel('Power [W]')
ax.set_title('')
ax.legend(loc=0, fontsize=10)
# Plotting the phase (Converting from radians to degrees)
ax2 = plt.subplot(2,1,2)
ax2.plot(out1b.x, np.angle(out1b['optimal'])*180/np.pi, 'r-', label='Optimal')
ax2.plot(out1b.x, np.angle(S2)*180/np.pi, 'k--', label='Reconstructed')
ax2.set_xlabel('Modulation index of eom2')
ax2.set_ylabel('Phase [deg]')
ax2.set_ylim((0,70))
ax2.legend(loc=0, fontsize=10)
plt.show()
# Calculating and printing the phase of S2 in degrees
phase2_rec = np.angle(S2[1])*180/np.pi
phase2_opt = np.angle(out2['optimal'][1])*180/np.pi
print('Reconstructed phase: {:.14f} deg'.format(phase2_rec))
print('Optimal phase: {:.14f} deg'.format(phase2_opt))
```

`pd2`

detectors `inphase`

and `inquadrature`

, and by the FINESSE "cheat" of leaving the second demodulation phase empty for the `pd2`

detector `optimal`

. And as we see in the figures above, the the ways agree perfectly.

In this session we have:

- used a photo diode in combination with two mixers and a low pass filter to double demodulate a double amplitude modulated carrier field.
- seen that the full double demodulation signal can be extracted by two double demodulation schemes, with the second demodulation phases 90 degrees apart from each other.