mirror of
https://github.com/vale981/fibre_walk_project_code
synced 2025-03-04 09:21:38 -05:00
RESULT: weird oscillations and fitting to the transients
This commit is contained in:
parent
18a0f8c846
commit
e595fdef6e
8 changed files with 205 additions and 16 deletions
|
@ -3,8 +3,36 @@
|
|||
:END:
|
||||
#+title: Fitting Ringdown
|
||||
|
||||
* Fitting transients
|
||||
- one can solve the equation of motion for when a mode is in the
|
||||
steady state and the laser is suddenly switched. one obtains a
|
||||
decaying oscillation which can be fitted to the data.
|
||||
- this works ok, when the system /was/ in the steady state before the jump
|
||||
- see [[file:scripts/transients_without_amplification.py]]
|
||||
- we obtain \(γ\approx\SI{2.2}{\kilo\hertz}\) but this can vary a lot
|
||||
- the detuning frequency seems to be completely off
|
||||
|
||||
* Failure of the steady state
|
||||
|
||||
On the right peak on can see that there might be something fish going
|
||||
on. This is ~data/24_05_24/nice_transient2~.
|
||||
[[file:figures/non_steady.png]]
|
||||
|
||||
* Weird Oscillations :ATTACH:
|
||||
- when turning on the amp while the laser is running we get some
|
||||
oscillations at \(\sim \SI{40}{\kilo\hertz}\) which is a period of
|
||||
\(\SI{25}{\micro\second}\). this is 500 times roundrip time :(). I
|
||||
thought it might be a wave packet traveling around the loop, i.e
|
||||
multiple modes together...
|
||||
|
||||
[[attachment:osci_closeup.png][osci_closeup.png]]
|
||||
[[attachment:osci_far.png][osci_far.png]]
|
||||
[[attachment:cleaned.png][cleaned.png]]
|
||||
- it isn't close to the fsr though...
|
||||
- fitting a sine to that gives pretty much the same, as does an fft
|
||||
[[attachment:cleaned_fit.png][cleaned_fit.png]]
|
||||
|
||||
- it is pretty constant over all steps in [[file:data/09_05_24/Nicely_hybridised_2 2024,05,09, 15h57min00sec/][data]] as can be ascertained
|
||||
from [[file:scripts/weird_oscillations.py][this script]]
|
||||
- these are also present w/o the amp cutout!
|
||||
[[attachment:osci_without.png][osci_without.png]]
|
||||
|
|
|
@ -1,3 +1,58 @@
|
|||
###############################################################################
|
||||
# Fitting Routine #
|
||||
###############################################################################
|
||||
import numpy as np
|
||||
import math
|
||||
import scipy.optimize as opt
|
||||
from scipy.ndimage import uniform_filter1d
|
||||
from scipy.signal import find_peaks
|
||||
|
||||
|
||||
def transient_model(t, Δω, γ, amplitude, phase):
|
||||
comp_phase = np.exp(1j * phase)
|
||||
osci = amplitude * comp_phase * (np.expm1((-1j * Δω - γ) * (t)))
|
||||
|
||||
return np.imag(osci)
|
||||
|
||||
|
||||
def fit_transient(time: np.ndarray, transient: np.ndarray, window_size: int = 100):
|
||||
"""
|
||||
Fit a transient signal ``transient`` over ``time`` to a damped
|
||||
oscillation model.
|
||||
|
||||
The smoothing window is calculated as the length of the transient
|
||||
divided by the ``window_size``.
|
||||
"""
|
||||
|
||||
# data_length = len(transient)
|
||||
# begin, end = transient.argmax(), -int(data_length * 0.01)
|
||||
|
||||
# time = time[begin:end]
|
||||
# output_data = transient[begin:end]
|
||||
|
||||
output_data = transient
|
||||
window = len(output_data) // window_size
|
||||
output_data = uniform_filter1d(output_data, window)
|
||||
output_data -= output_data[0]
|
||||
output_data /= abs(output_data).max()
|
||||
|
||||
scaled_time = np.linspace(0, 1, len(time))
|
||||
|
||||
popt, pcov = opt.curve_fit(
|
||||
transient_model,
|
||||
scaled_time,
|
||||
output_data,
|
||||
p0=[1, 1, 1, 0],
|
||||
bounds=(
|
||||
[-np.inf, 0, 0, -np.pi],
|
||||
[np.inf, np.inf, np.pi, np.inf],
|
||||
),
|
||||
)
|
||||
|
||||
Δω, γ, amplitude, phase = popt
|
||||
|
||||
# convert back to units
|
||||
Δω = Δω / (time[-1] - time[0])
|
||||
γ = γ / (time[-1] - time[0])
|
||||
|
||||
return scaled_time, output_data, popt, np.sqrt(np.diag(pcov)), (Δω, γ)
|
||||
|
|
|
@ -92,7 +92,7 @@ def plot_scan(
|
|||
|
||||
if smoothe_output:
|
||||
if not isinstance(smoothe_output, int):
|
||||
smoothe_output_data = 60
|
||||
smoothe_output = 60
|
||||
|
||||
window = len(output_data) // smoothe_output
|
||||
output_data = uniform_filter1d(output_data, window)
|
||||
|
@ -101,7 +101,10 @@ def plot_scan(
|
|||
|
||||
if isinstance(steps, bool) and steps:
|
||||
peaks = data.laser_steps()
|
||||
for peak in peaks:
|
||||
peaks = [0, *peaks, len(data.time) - 1]
|
||||
|
||||
vertical = output_data.min()
|
||||
for peak in peaks[1:-1]:
|
||||
ax.axvline(
|
||||
data.time[peak],
|
||||
color=lighten_color(lines[0].get_color()),
|
||||
|
@ -109,6 +112,15 @@ def plot_scan(
|
|||
zorder=-10,
|
||||
)
|
||||
|
||||
for i, (begin, end) in enumerate(zip(peaks[:-1], peaks[1:])):
|
||||
ax.text(
|
||||
(data.time[begin] + data.time[end]) / 2,
|
||||
vertical,
|
||||
f"{i}",
|
||||
ha="center",
|
||||
va="bottom",
|
||||
)
|
||||
|
||||
|
||||
@wrap_plot
|
||||
def plot_transmission(data: data.ScanData, timepoints=1000, ax=None, **kwargs):
|
||||
|
|
|
@ -31,3 +31,15 @@ def find_frequency_steps(laser: np.ndarray, window_fraction: int = 60) -> np.nda
|
|||
|
||||
peaks = find_peaks(step_diffs, height=0.5, distance=window)[0]
|
||||
return peaks
|
||||
|
||||
|
||||
def shift_and_normalize(array: np.ndarray) -> np.ndarray:
|
||||
shifted = array - array.min()
|
||||
return shifted / abs(shifted).max()
|
||||
|
||||
|
||||
def smoothe_signal(signal: np.ndarray, window_size: float = 0.01) -> np.ndarray:
|
||||
"""Smoothe the signal ``signal`` using a uniform filter with a window
|
||||
size of ``window_size * len(signal)``."""
|
||||
window = int(len(signal) * window_size)
|
||||
return uniform_filter1d(signal, window)
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
import sys
|
||||
|
||||
sys.path.append("../")
|
||||
from ringfit import data
|
||||
import matplotlib.pyplot as plt
|
||||
from ringfit.data import *
|
||||
from ringfit.plotting import *
|
||||
|
||||
path = (
|
||||
"/home/hiro/Documents/org/roam/code/fitting_ringdown/data/24_05_24/nice_transient_2"
|
||||
)
|
||||
scan = ScanData.from_dir(path, truncation=[0, 50])
|
||||
|
||||
fig, ax = plot_scan(scan, smoothe_output=10, steps=1)
|
22
scripts/transients_with_blackout.py
Normal file
22
scripts/transients_with_blackout.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
import sys
|
||||
|
||||
sys.path.append("../")
|
||||
from ringfit import data
|
||||
import matplotlib.pyplot as plt
|
||||
from ringfit.data import *
|
||||
from ringfit.plotting import *
|
||||
from ringfit.fit import *
|
||||
|
||||
path = "/home/hiro/Documents/org/roam/code/fitting_ringdown/data/09_05_24/Nicely_hybridised_2 2024,05,09, 15h57min00sec/"
|
||||
scan = ScanData.from_dir(path, truncation=[0, 50])
|
||||
|
||||
fig, ax = plot_scan(scan, smoothe_output=50, normalize=True, laser=False, steps=True)
|
||||
time, output, _ = scan.for_step(10)
|
||||
t, o, params, cov, scaled = fit_transient(time, output, window_size=100)
|
||||
|
||||
plt.figure()
|
||||
plt.plot(t, o)
|
||||
plt.plot(t, transient_model(t, *params))
|
||||
plt.title(
|
||||
f"Transient 2, γ={scaled[1] / 10**3}kHz ω/2π={scaled[1] / (2*np.pi * 10**3)}kHz"
|
||||
)
|
30
scripts/transients_without_amplification.py
Normal file
30
scripts/transients_without_amplification.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
import sys
|
||||
|
||||
sys.path.append("../")
|
||||
from ringfit import data
|
||||
import matplotlib.pyplot as plt
|
||||
from ringfit.data import *
|
||||
from ringfit.plotting import *
|
||||
from ringfit.fit import *
|
||||
|
||||
path = (
|
||||
"/home/hiro/Documents/org/roam/code/fitting_ringdown/data/08_05_24/nice_transient_2"
|
||||
)
|
||||
scan = ScanData.from_dir(path, truncation=[0, 50])
|
||||
|
||||
STEPS = [2, 3, 5]
|
||||
fig, ax = plot_scan(scan, smoothe_output=50, normalize=True, laser=False, steps=True)
|
||||
|
||||
for STEP in STEPS:
|
||||
time, output, _ = scan.for_step(step=STEP)
|
||||
t, o, params, cov, scaled = fit_transient(time, output, window_size=100)
|
||||
|
||||
plt.figure()
|
||||
plt.plot(t, o)
|
||||
plt.plot(t, transient_model(t, *params))
|
||||
plt.title(
|
||||
f"Transient 2, γ={scaled[1] / 10**3:.2f}kHz ({cov[1] / 10**3:.2f}kHz)\n ω/2π={scaled[0] / (2*np.pi * 10**3):.5f}kHz\n step={STEP}"
|
||||
)
|
||||
|
||||
freq_unit = params[1] / scaled[1]
|
||||
plt.plot(t, np.sin(2 * np.pi * 4 * 10**4 * t * freq_unit), alpha=0.1)
|
44
scripts/weird_oscillations.py
Normal file
44
scripts/weird_oscillations.py
Normal file
|
@ -0,0 +1,44 @@
|
|||
import sys
|
||||
|
||||
sys.path.append("../")
|
||||
from ringfit import data
|
||||
import matplotlib.pyplot as plt
|
||||
from ringfit.data import *
|
||||
from ringfit.plotting import *
|
||||
from ringfit.fit import *
|
||||
from ringfit.utils import *
|
||||
|
||||
path = "/home/hiro/Documents/org/roam/code/fitting_ringdown/data/09_05_24/Nicely_hybridised_2 2024,05,09, 15h57min00sec/"
|
||||
scan = ScanData.from_dir(path, truncation=[0, 50])
|
||||
STEPS = [2, 33, 12]
|
||||
fig, (ax1, *axs) = plt.subplots(nrows=1, ncols=len(STEPS) + 1)
|
||||
|
||||
plot_scan(scan, smoothe_output=100, normalize=True, laser=False, steps=True, ax=ax1)
|
||||
|
||||
|
||||
def fit_frequency(step, ax):
|
||||
time, output, _ = scan.for_step(step)
|
||||
l = len(time)
|
||||
begin = int(0.5 * l)
|
||||
end = int(0.8 * l)
|
||||
time = time[begin:end]
|
||||
output = output[begin:end]
|
||||
output = smoothe_signal(output, 0.05)
|
||||
output = shift_and_normalize(output)
|
||||
output -= output.mean()
|
||||
|
||||
ax.plot(time, output)
|
||||
ff = np.fft.rfftfreq(output.size, d=time[1] - time[0])
|
||||
ft = np.fft.rfft(output)
|
||||
|
||||
freq_index = np.argmax(ft)
|
||||
|
||||
ax.plot(
|
||||
time,
|
||||
0.5 * np.sin(time * 2 * np.pi * ff[freq_index] + np.angle(ft[freq_index])),
|
||||
)
|
||||
ax.set_title(f"f={ff[freq_index]*10**(-3):.2f}kHz\n step={step}")
|
||||
|
||||
|
||||
for step, ax in zip(STEPS, axs):
|
||||
fit_frequency(step, ax)
|
Loading…
Add table
Reference in a new issue