fibre_walk_project_code/scripts/experiments/013_step_through.py

220 lines
6 KiB
Python
Raw Normal View History

2024-08-07 17:19:28 -04:00
from rabifun.system import *
from rabifun.plots import *
from rabifun.utilities import *
from rabifun.analysis import *
from ringfit.data import ScanData
import functools
import multiprocessing
import copy
from scipy.ndimage import rotate
# %% interactive
def make_shots(params, total_lifetimes, eom_range, eom_steps):
solutions = []
t = time_axis(params, lifetimes=total_lifetimes, resolution=0.01)
pool = multiprocessing.Pool()
shot_params = []
for step in range(eom_steps):
current_params = copy.deepcopy(params)
current_params.drive_override = (
np.array(
[
params.Ω
* (eom_range[0] + (eom_range[1] - eom_range[0]) * step / eom_steps)
]
),
np.array([1.0]),
)
shot_params.append((t, current_params))
solutions = pool.starmap(solve, shot_params)
return t, solutions
def process_shots(t, solutions, noise_amplitude, params):
average_power_spectrum = None
window = (float(params.laser_off_time) or 0, t[-1])
rng = np.random.default_rng(seed=0)
# let us get a measure calibrate the noise strength
signal_amp = 0
signals = []
for solution in solutions:
signal = output_signal(t, solution.y, params)
signals.append(signal)
signal_amp += abs(signal).max()
signal_amp /= len(solutions)
for signal in signals:
signal += rng.normal(scale=noise_amplitude * signal_amp, size=len(signal))
freq, fft = fourier_transform(
t,
signal,
2024-08-08 18:06:17 -04:00
low_cutoff=0.5 * params.Ω,
2024-08-07 17:19:28 -04:00
high_cutoff=params.Ω * (params.N + 1),
window=window,
)
power = np.abs(fft) ** 2
if average_power_spectrum is None:
average_power_spectrum = power
else:
average_power_spectrum += power
return freq, (average_power_spectrum / len(solutions))
def plot_power_spectrum(ax_spectrum, freq, average_power_spectrum, params):
offset = np.median(average_power_spectrum)
2024-08-08 18:06:17 -04:00
# ax_spectrum.plot(freq, average_power_spectrum)
# runtime = RuntimeParams(params)
# lorentz_freqs = np.linspace(freq.min(), freq.max(), 10000)
# fake_spectrum = np.zeros_like(lorentz_freqs)
# for i, peak_freq in enumerate(runtime.Ωs):
# pos = np.abs(
# params.measurement_detuning
# - peak_freq.real / (2 * np.pi)
# + params.δ * params.Ω
# + params.laser_detuning,
# )
# ax_spectrum.axvline(
# pos,
# color="red",
# linestyle="--",
# zorder=-100,
# )
# amplitude = average_power_spectrum[np.argmin(abs(freq - pos))] - offset
# ax_spectrum.annotate(
# mode_name(i),
# (
# pos + 0.1,
# (amplitude + offset) * (1 if peak_freq.real < 0 else 1.1),
# ),
# )
# fake_spectrum += lorentzian(
# lorentz_freqs, amplitude, pos, peak_freq.imag / np.pi
# )
# ax_spectrum.plot(lorentz_freqs, fake_spectrum + offset)
ringdown_params = RingdownParams(
fω_shift=params.measurement_detuning,
mode_window=(5, 5),
fΩ_guess=params.Ω,
fδ_guess=params.Ω * params.δ,
η_guess=0.5,
absolute_low_cutoff=1,
)
2024-08-07 17:19:28 -04:00
2024-08-08 18:06:17 -04:00
peak_info = find_peaks(
freq, average_power_spectrum, ringdown_params, prominence=0.001
)
peak_info = refine_peaks(peak_info, ringdown_params)
peak_info.power = average_power_spectrum
plot_spectrum_and_peak_info(ax_spectrum, peak_info, ringdown_params, annotate=True)
print(peak_info.peak_freqs)
2024-08-07 17:19:28 -04:00
def generate_data(
g_0=0.3,
η_factor=5,
noise_amplitude=0.3,
laser_detuning=0,
N=10,
eom_ranges=(0.5, 2.5),
eom_steps=20,
small_loop_detuning=0,
excitation_lifetimes=2,
measurement_lifetimes=4,
):
η = 0.2
Ω = 13
params = Params(
η=η,
η_hybrid=η_factor * η,
Ω=Ω,
δ=1 / 4,
ω_c=0.1,
g_0=g_0,
laser_detuning=13 * (-1 - 1 / 4) + 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,
drive_override=(np.array([1.0]), np.array([1.0])),
)
params.laser_off_time = params.lifetimes(excitation_lifetimes)
params.drive_off_time = params.lifetimes(excitation_lifetimes)
t, solutions = make_shots(
params, excitation_lifetimes + measurement_lifetimes, eom_ranges, eom_steps
)
_, (sol_on_res) = make_shots(
params,
excitation_lifetimes + measurement_lifetimes,
((1 + params.δ), (1 + params.δ)),
1,
)
freq, average_power_spectrum = process_shots(t, solutions, noise_amplitude, params)
_, spectrum_on_resonance = process_shots(t, sol_on_res, noise_amplitude, params)
fig = make_figure()
fig.clear()
ax_multi, ax_single = fig.subplot_mosaic("AA\nBB").values()
ax_multi.set_title("Averaged Power Spectrum")
ax_single.set_title("Single-shot Power-Spectrum with EOM on resonance")
for ax in [ax_multi, ax_single]:
ax.set_xlabel("Frequency (MHz)")
ax.set_ylabel("Power")
ax.set_yscale("log")
plot_power_spectrum(ax_multi, freq, average_power_spectrum, params)
plot_power_spectrum(ax_single, freq, spectrum_on_resonance, params)
runtime = RuntimeParams(params)
2024-08-08 18:06:17 -04:00
print(runtime.Ωs.real / (2 * np.pi) - params.laser_detuning)
2024-08-07 17:19:28 -04:00
# ax_spectrum.set_yscale(yscale)
return fig
# %% save
if __name__ == "__main__":
fig = generate_data(
g_0=1,
η_factor=5,
2024-08-08 18:06:17 -04:00
noise_amplitude=0.25 * 0,
2024-08-07 17:19:28 -04:00
N=2,
eom_ranges=(1.1, 1.3),
2024-08-08 18:06:17 -04:00
eom_steps=20,
2024-08-07 17:19:28 -04:00
small_loop_detuning=0,
laser_detuning=0,
excitation_lifetimes=2,
measurement_lifetimes=20,
)