RESULT: get the results of the 11_07 data in order
116
scripts/ringdown_spectrum_analysis/003_11_07_data_analysis.py
Normal file
|
@ -0,0 +1,116 @@
|
|||
from rabifun.system import *
|
||||
from rabifun.plots import *
|
||||
from rabifun.utilities import *
|
||||
from rabifun.analysis import *
|
||||
from ringfit.data import ScanData
|
||||
from ringfit.plotting import *
|
||||
import gc
|
||||
|
||||
path = "../../data/11_07_24/second_signal"
|
||||
scan = ScanData.from_dir(path, extension="npz")
|
||||
|
||||
|
||||
# %% plot scan
|
||||
gc.collect()
|
||||
fig = plt.figure("interactive", constrained_layout=True, figsize=(20, 3 * 5))
|
||||
fig.clf()
|
||||
(ax_signal, ax_window, ax_spectrum) = fig.subplot_mosaic("AA;BC").values()
|
||||
plot_scan(scan, ax=ax_signal, linewidth=0.5, every=1000)
|
||||
|
||||
|
||||
# %% window
|
||||
|
||||
# here we select a step that is resonant with a hybridized peak and
|
||||
# then plot the full photodiode voltage trace and just the window
|
||||
|
||||
T_step = 0.0002
|
||||
N = 100
|
||||
t_scan_peak = 0.0057815 + 0.1e-6 # T * N_steps
|
||||
t_scan_peak = 0.0057815 - 0.09e-6 + 11 * T_step # T * N_steps
|
||||
t_peak = t_scan_peak + N * T_step
|
||||
win_length = 5e-05
|
||||
|
||||
window = t_scan_peak, t_scan_peak + win_length * 0.3
|
||||
|
||||
|
||||
ax_signal.axvline(t_peak, color="r", linestyle="--")
|
||||
ax_signal.axvline(t_scan_peak, color="r", linestyle="--")
|
||||
ax_signal.axvspan(*window, color="r", linestyle="--")
|
||||
ax_signal.set_title("Full photodiode voltage trace")
|
||||
ax_signal.set_xlabel("Time [s]")
|
||||
ax_signal.set_ylabel("Voltage [arb]")
|
||||
|
||||
mask = (scan.time > window[0]) & (scan.time < window[1])
|
||||
ax_window.clear()
|
||||
ax_window.plot(scan.time[mask], scan.output[mask], linewidth=0.1)
|
||||
ax_window.set_title("Windowed photodiode voltage trace")
|
||||
ax_window.set_xlabel("Time [s]")
|
||||
|
||||
# %% detect peaks
|
||||
|
||||
## herein we detect the pertinent peaks and refine them using a lorentzian fit
|
||||
ringdown_params = RingdownParams(
|
||||
fω_shift=0,
|
||||
mode_window=(0, 5),
|
||||
fΩ_guess=12.9e6,
|
||||
fδ_guess=0.2 * 12.9e6,
|
||||
η_guess=0.5e6,
|
||||
absolute_low_cutoff=2e6,
|
||||
)
|
||||
|
||||
peak_info = find_peaks(scan, ringdown_params, window, prominence=0.08)
|
||||
peak_info = refine_peaks(peak_info, ringdown_params)
|
||||
plot_spectrum_and_peak_info(ax_spectrum, peak_info, ringdown_params, annotate=True)
|
||||
|
||||
|
||||
# %% hand-crafted interpretation
|
||||
b1, b2, b3, reflected = peak_info.peak_freqs[[0, 1, 3, 2]]
|
||||
Ω = b3 - b2
|
||||
δ = abs(b3 - 3 * Ω)
|
||||
δ_2 = reflected - 2 * Ω
|
||||
detuning = (δ + δ_2) / 2
|
||||
|
||||
alt_Ω = b2 - b1
|
||||
|
||||
hyb_amp = peak_info.power[peak_info.peaks[3]] / (np.sqrt(2) * 5) ** 2
|
||||
hyb_width = peak_info.peak_widths[3] * 5
|
||||
hyb_freq = 2 * detuning
|
||||
|
||||
ax_spectrum.plot(
|
||||
peak_info.freq,
|
||||
lorentzian(peak_info.freq, hyb_amp, hyb_freq, hyb_width),
|
||||
color="C3",
|
||||
label="hybridized mode?",
|
||||
)
|
||||
|
||||
ax_spectrum.legend()
|
||||
fig.suptitle(
|
||||
f"""
|
||||
Analysis of the data from the 11/07.
|
||||
We modulated at the FSR (13MHz) and FSR-δ and 2δ.
|
||||
|
||||
In the bottom right a Fourier transform of the windowed signal in the bottom left is shown.
|
||||
The first large peak is the first bath mode after the hybridized mode. It has a distance from the second bath mode of {alt_Ω*1e-6:.2f}MHz.
|
||||
The second and third peaks have a distance of {Ω*1e-6:.2f}MHz, hence the first bath mode also hybridizes with the small loop! In the second half of the trace
|
||||
up top we can see that the first bath mode is broader the n the second and so on, corroborating this interpretation. From there we can also surmise that the decay rate
|
||||
of the hybridized mode is about 3.5 times that of the bath modes. Using this, we can estimate the amplitude of the hybridized mode and its width, which we then plot as
|
||||
a lorentzian. (If the bath mode was excited to the same degree as the third bath mode which is unlikely.)
|
||||
|
||||
The width of the thrid peak is {peak_info.peak_widths[3]*1e-6:.2f}MHz. The estimated decay rate of the hybridized mode is {hyb_width*1e-6:.2f}MHz.
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
# %% save
|
||||
if __name__ == "__main__":
|
||||
save_figure(fig, "003_11_07_analysis")
|
||||
|
||||
quick_save_pickle(
|
||||
dict(
|
||||
window=window,
|
||||
peak_info=peak_info,
|
||||
ringdown_parms=ringdown_params,
|
||||
detuning=detuning,
|
||||
),
|
||||
"003_results",
|
||||
)
|
261
scripts/ringdown_spectrum_analysis/004_simulation_11_07.py
Normal file
|
@ -0,0 +1,261 @@
|
|||
from rabifun.system import *
|
||||
from rabifun.plots import *
|
||||
from rabifun.utilities import *
|
||||
from rabifun.analysis import *
|
||||
from ringfit.data import ScanData
|
||||
import functools
|
||||
|
||||
from scipy.ndimage import rotate
|
||||
|
||||
# %% interactive
|
||||
|
||||
|
||||
def make_params_and_solve(
|
||||
total_lifetimes,
|
||||
eom_off_lifetime,
|
||||
ω_c=0.1 / 2,
|
||||
N=10,
|
||||
g_0=1 / 4,
|
||||
small_loop_detuning=0,
|
||||
laser_detuning=0,
|
||||
η=1.0,
|
||||
η_hybrid=1.0,
|
||||
drive_mode="all",
|
||||
):
|
||||
"""
|
||||
Make a set of parameters for the system with the current
|
||||
best-known settings.
|
||||
"""
|
||||
|
||||
Ω = 13
|
||||
|
||||
params = Params(
|
||||
η=η,
|
||||
η_hybrid=η_hybrid,
|
||||
Ω=Ω,
|
||||
δ=1 / 4,
|
||||
ω_c=ω_c,
|
||||
g_0=g_0,
|
||||
laser_detuning=laser_detuning,
|
||||
N=N,
|
||||
N_couplings=N,
|
||||
measurement_detuning=0,
|
||||
α=0,
|
||||
rwa=False,
|
||||
flat_energies=False,
|
||||
correct_lamb_shift=0,
|
||||
laser_off_time=0,
|
||||
small_loop_detuning=small_loop_detuning,
|
||||
)
|
||||
|
||||
params.laser_off_time = params.lifetimes(eom_off_lifetime)
|
||||
params.drive_off_time = params.lifetimes(eom_off_lifetime)
|
||||
|
||||
match drive_mode:
|
||||
case "hybrid":
|
||||
params.drive_override = (
|
||||
np.array([params.Ω * params.δ * 2]),
|
||||
np.ones(1),
|
||||
)
|
||||
|
||||
case "hybrid_to_one_bath":
|
||||
params.drive_override = (
|
||||
np.array([params.Ω * (1 - params.δ), params.Ω * params.δ * 2]),
|
||||
np.ones(2),
|
||||
)
|
||||
|
||||
case "bath":
|
||||
params.drive_override = (
|
||||
np.array([params.Ω]),
|
||||
np.ones(1),
|
||||
)
|
||||
|
||||
case _:
|
||||
params.drive_override = (
|
||||
np.array(
|
||||
[params.Ω, params.Ω * (1 - params.δ), params.δ * 2 * params.Ω]
|
||||
),
|
||||
np.ones(3),
|
||||
)
|
||||
|
||||
t = time_axis(params, lifetimes=total_lifetimes, resolution=0.001)
|
||||
solution = solve(t, params)
|
||||
return params, t, solution
|
||||
|
||||
|
||||
def generate_phase_one_data(
|
||||
drive_mode="full",
|
||||
g_0=0.3,
|
||||
off_factor=0.21,
|
||||
noise=False,
|
||||
extra_title="",
|
||||
laser_detuning=0,
|
||||
yscale="linear",
|
||||
):
|
||||
"""
|
||||
This generates some intensity data for phase one of the
|
||||
calibration protocol, where the aim is to extract the resonator
|
||||
spectrum.
|
||||
"""
|
||||
|
||||
total_lifetimes = 30
|
||||
eom_off_lifetime = total_lifetimes * off_factor
|
||||
fluct_size = 0.05
|
||||
noise_amp = 0.3
|
||||
|
||||
params, t, solution = make_params_and_solve(
|
||||
total_lifetimes,
|
||||
eom_off_lifetime,
|
||||
N=10,
|
||||
g_0=g_0,
|
||||
small_loop_detuning=0,
|
||||
laser_detuning=laser_detuning,
|
||||
η=0.18,
|
||||
η_hybrid=0.18 * 5,
|
||||
drive_mode=drive_mode,
|
||||
)
|
||||
|
||||
rng = np.random.default_rng(seed=0)
|
||||
raw_signal = output_signal(t, solution.y, params)
|
||||
|
||||
signal = raw_signal.copy()
|
||||
if noise:
|
||||
signal += noise_amp * rng.standard_normal(len(signal))
|
||||
|
||||
fig = make_figure(f"simulation_noise_{noise}", figsize=(20, 3 * 5))
|
||||
|
||||
ax_realtime, ax_rotating_bath, ax_rotating_system, ax_spectrum = (
|
||||
fig.subplot_mosaic("""
|
||||
AA
|
||||
BC
|
||||
DD
|
||||
DD
|
||||
""").values()
|
||||
)
|
||||
|
||||
ax_rotating_system.sharey(ax_rotating_bath)
|
||||
ax_rotating_system.sharex(ax_rotating_bath)
|
||||
|
||||
for mode in range(2):
|
||||
ax_rotating_system.plot(
|
||||
t[::50],
|
||||
abs(np.imag(solution.y[mode, ::50])) ** 2
|
||||
/ 2
|
||||
* (params.η / params.η_hybrid) ** 2,
|
||||
)
|
||||
|
||||
for mode in range(2, solution.y.shape[0]):
|
||||
ax_rotating_bath.plot(t[::50], abs(np.imag(solution.y[mode, ::50])) ** 2)
|
||||
|
||||
for ax in [ax_rotating_bath, ax_rotating_system]:
|
||||
ax.set_xlabel("Time")
|
||||
ax.set_ylabel("Intensity")
|
||||
|
||||
ax_rotating_bath.set_title("Bath Modes")
|
||||
ax_rotating_system.set_title(
|
||||
"Hybridized Modes [corrected for magnitude visible in FFT]"
|
||||
)
|
||||
|
||||
ax_realtime.plot(t[::50], signal[::50])
|
||||
ax_realtime.axvline(params.drive_off_time, color="black", linestyle="--")
|
||||
ax_realtime.set_xlabel("Time")
|
||||
ax_realtime.set_ylabel("Intensity")
|
||||
ax_realtime.set_title("Photo-diode AC Intensity")
|
||||
|
||||
# now we plot the power spectrum
|
||||
window = (float(params.laser_off_time or 0), t[-1])
|
||||
# window = (0, float(params.laser_off_time or 0))
|
||||
|
||||
ringdown_params = RingdownParams(
|
||||
fω_shift=params.measurement_detuning,
|
||||
mode_window=(5, 5),
|
||||
fΩ_guess=params.Ω * (1 + rng.standard_normal() * fluct_size),
|
||||
fδ_guess=params.Ω * params.δ * (1 + rng.standard_normal() * fluct_size),
|
||||
η_guess=0.5, # params.η * (1 + rng.standard_normal() * fluct_size),
|
||||
absolute_low_cutoff=2,
|
||||
)
|
||||
|
||||
scan = ScanData(np.ones_like(signal), signal, t)
|
||||
peak_info = find_peaks(scan, ringdown_params, window, prominence=0.01)
|
||||
peak_info = refine_peaks(peak_info, ringdown_params)
|
||||
plot_spectrum_and_peak_info(ax_spectrum, peak_info, ringdown_params)
|
||||
|
||||
runtime = RuntimeParams(params)
|
||||
for i, freq in enumerate(runtime.Ωs.real):
|
||||
pos = np.abs(
|
||||
params.measurement_detuning
|
||||
- freq / (2 * np.pi)
|
||||
+ params.δ * params.Ω
|
||||
+ params.laser_detuning,
|
||||
)
|
||||
|
||||
ax_spectrum.axvline(
|
||||
pos,
|
||||
color="red",
|
||||
linestyle="--",
|
||||
zorder=-100,
|
||||
)
|
||||
ax_spectrum.annotate(mode_name(i), (pos + 0.1, peak_info.power.max()))
|
||||
|
||||
ax_spectrum.set_xlim(ringdown_params.low_cutoff, ringdown_params.high_cutoff)
|
||||
ax_spectrum.set_yscale(yscale)
|
||||
fig.suptitle(
|
||||
f"""Calibration Phase One Demonstration {'with noise' if noise else ''}
|
||||
N={params.N} * 2 + 2 modes g_0={params.g_0}Ω, Noise Amp={noise_amp}, η={params.η}MHz, η_hybrid={params.η_hybrid}MHz
|
||||
"""
|
||||
+ extra_title
|
||||
)
|
||||
|
||||
return fig
|
||||
|
||||
|
||||
# %% save
|
||||
if __name__ == "__main__":
|
||||
fig = generate_phase_one_data(
|
||||
noise=True,
|
||||
g_0=0.3,
|
||||
extra_title="""A simulation for the 11_07 data with parameters chosen as known, or estimated so that the result looks as similar as possible.
|
||||
At this level of drive and with these decay rates, the hybridized modes are hardly populated. The noise is (unphysical) random
|
||||
gaussian noise added to simulated photodiode voltage. Nothing can be said with certainty about the drive strength.
|
||||
""",
|
||||
)
|
||||
save_figure(fig, "004_01_11_07_simulation")
|
||||
|
||||
fig = generate_phase_one_data(
|
||||
drive_mode="hybrid",
|
||||
g_0=2,
|
||||
noise=True,
|
||||
extra_title="""
|
||||
The same as the first simulation, but driving only at 2δ. With this decay rate, nothing can be excited.
|
||||
""",
|
||||
)
|
||||
save_figure(fig, "004_02_11_07_simulation_only_a")
|
||||
|
||||
fig = generate_phase_one_data(
|
||||
noise=True,
|
||||
g_0=1,
|
||||
extra_title="""Same as the first simulation but with larger drive strength.
|
||||
Observe, how the amplitudes of the bath modes fluctuate with great amplitude.
|
||||
""",
|
||||
)
|
||||
save_figure(fig, "004_03_11_07_simulation_more_drive")
|
||||
|
||||
fig = generate_phase_one_data(
|
||||
noise=True,
|
||||
g_0=1,
|
||||
off_factor=0.3,
|
||||
extra_title="""Same as number 04 but a different drive stop time.
|
||||
Observe, how the amplitudes of the bath modes fluctuate with great amplitude.
|
||||
""",
|
||||
)
|
||||
save_figure(fig, "004_04_11_07_simulation_more_drive_different_stop")
|
||||
|
||||
fig = generate_phase_one_data(
|
||||
laser_detuning=13 * 0.8,
|
||||
g_0=0.3,
|
||||
yscale="log",
|
||||
extra_title="""
|
||||
The same as the first simulation, but with the laser at a bath mode. The hybridized modes gain no population.
|
||||
""",
|
||||
)
|
||||
save_figure(fig, "004_05_11_07_simulation_only_a_drive_on_bath")
|
BIN
scripts/ringdown_spectrum_analysis/figs/003_11_07_analysis.pdf
Normal file
|
@ -0,0 +1,8 @@
|
|||
change_id: rxuqwvztlzswqyxoqznpmqxryltwylus
|
||||
commit_id: 984c654e9cae56ee261952a1401e1fa22b4e0523
|
||||
description: get the results of the 11_07 data in order
|
||||
extra_meta: null
|
||||
function: <module>
|
||||
name: 003_11_07_analysis
|
||||
refers_to: ./figs/003_11_07_analysis.pdf
|
||||
source: scripts/ringdown_spectrum_analysis/003_11_07_data_analysis.py
|
BIN
scripts/ringdown_spectrum_analysis/figs/003_11_07_analysis.png
Normal file
After Width: | Height: | Size: 2.5 MiB |
|
@ -0,0 +1,8 @@
|
|||
change_id: rxuqwvztlzswqyxoqznpmqxryltwylus
|
||||
commit_id: 2b802eaf83102e9e09df2a8cfcc1126dffc07ee2
|
||||
description: get the results of the 11_07 data in order
|
||||
extra_meta: null
|
||||
function: <module>
|
||||
name: 004_01_11_07_simulation
|
||||
refers_to: ./figs/004_01_11_07_simulation.pdf
|
||||
source: scripts/ringdown_spectrum_analysis/004_simulation_11_07.py
|
After Width: | Height: | Size: 2.3 MiB |
|
@ -0,0 +1,8 @@
|
|||
change_id: rxuqwvztlzswqyxoqznpmqxryltwylus
|
||||
commit_id: b2f4c79ef52a9b9195efb8c8ea6dbc9ca9fcd5d6
|
||||
description: get the results of the 11_07 data in order
|
||||
extra_meta: null
|
||||
function: <module>
|
||||
name: 004_02_11_07_simulation_only_a
|
||||
refers_to: ./figs/004_02_11_07_simulation_only_a.pdf
|
||||
source: scripts/ringdown_spectrum_analysis/004_simulation_11_07.py
|
After Width: | Height: | Size: 2.7 MiB |
|
@ -0,0 +1,8 @@
|
|||
change_id: rxuqwvztlzswqyxoqznpmqxryltwylus
|
||||
commit_id: a7cabde9a6e79e6da95e560d527ebb62460a1f61
|
||||
description: get the results of the 11_07 data in order
|
||||
extra_meta: null
|
||||
function: <module>
|
||||
name: 004_02_11_07_simulation_only_a_drive_on_bath
|
||||
refers_to: ./figs/004_02_11_07_simulation_only_a_drive_on_bath.pdf
|
||||
source: scripts/ringdown_spectrum_analysis/004_simulation_11_07.py
|
After Width: | Height: | Size: 1.5 MiB |
|
@ -0,0 +1,8 @@
|
|||
change_id: rxuqwvztlzswqyxoqznpmqxryltwylus
|
||||
commit_id: 9c9f332c0ccc198b0a44e0a8d8119d38b055de79
|
||||
description: get the results of the 11_07 data in order
|
||||
extra_meta: null
|
||||
function: <module>
|
||||
name: 004_03_11_07_simulation_more_drive
|
||||
refers_to: ./figs/004_03_11_07_simulation_more_drive.pdf
|
||||
source: scripts/ringdown_spectrum_analysis/004_simulation_11_07.py
|
After Width: | Height: | Size: 2.3 MiB |
|
@ -0,0 +1,8 @@
|
|||
change_id: rxuqwvztlzswqyxoqznpmqxryltwylus
|
||||
commit_id: 49cf4c2df3390eccf280655dcb4e5e0226ab39d6
|
||||
description: get the results of the 11_07 data in order
|
||||
extra_meta: null
|
||||
function: <module>
|
||||
name: 004_04_11_07_simulation_more_drive_different_stop
|
||||
refers_to: ./figs/004_04_11_07_simulation_more_drive_different_stop.pdf
|
||||
source: scripts/ringdown_spectrum_analysis/004_simulation_11_07.py
|
After Width: | Height: | Size: 2.4 MiB |
|
@ -0,0 +1,8 @@
|
|||
change_id: rxuqwvztlzswqyxoqznpmqxryltwylus
|
||||
commit_id: 1e2260e32fcdb9af8ecb43be1fb05dd35ee10032
|
||||
description: get the results of the 11_07 data in order
|
||||
extra_meta: null
|
||||
function: <module>
|
||||
name: 004_05_11_07_simulation_only_a_drive_on_bath
|
||||
refers_to: ./figs/004_05_11_07_simulation_only_a_drive_on_bath.pdf
|
||||
source: scripts/ringdown_spectrum_analysis/004_simulation_11_07.py
|
After Width: | Height: | Size: 2.1 MiB |
BIN
scripts/ringdown_spectrum_analysis/figs/004_11_07_simulation.pdf
Normal file
|
@ -0,0 +1,8 @@
|
|||
change_id: rxuqwvztlzswqyxoqznpmqxryltwylus
|
||||
commit_id: 90feb43de79adb6761517558939dfeeb220c6724
|
||||
description: get the results of the 11_07 data in order
|
||||
extra_meta: null
|
||||
function: <module>
|
||||
name: 004_11_07_simulation
|
||||
refers_to: ./figs/004_11_07_simulation.pdf
|
||||
source: scripts/ringdown_spectrum_analysis/004_simulation_11_07.py
|
BIN
scripts/ringdown_spectrum_analysis/figs/004_11_07_simulation.png
Normal file
After Width: | Height: | Size: 2.1 MiB |
|
@ -0,0 +1,6 @@
|
|||
change_id: rxuqwvztlzswqyxoqznpmqxryltwylus
|
||||
commit_id: 60170ef1e3719c038cfca3e5cabd76e20f487ea5
|
||||
description: get the results of the 11_07 data in order
|
||||
function: <module>
|
||||
refers_to: outputs/003_results.pkl
|
||||
source: scripts/ringdown_spectrum_analysis/003_11_07_data_analysis.py
|
|
@ -16,6 +16,7 @@ def noop_if_interactive(f):
|
|||
@wraps(f)
|
||||
def wrapped(*args, **kwargs):
|
||||
if hasattr(sys, "ps1"):
|
||||
print("NOOP as the session is interactive!")
|
||||
return
|
||||
|
||||
return f(*args, **kwargs)
|
||||
|
|