Skip to content
Snippets Groups Projects
Commit 60212b60 authored by Philipp Niedermayer's avatar Philipp Niedermayer
Browse files

Plot fitted tune peak

parent b1eacb84
No related branches found
No related tags found
No related merge requests found
...@@ -9,22 +9,29 @@ def fit_gaussian(S, V, **kwargs): ...@@ -9,22 +9,29 @@ def fit_gaussian(S, V, **kwargs):
vp = np.max(V)-v0 vp = np.max(V)-v0
s0 = S[np.argmax(V)] s0 = S[np.argmax(V)]
sigma = np.sqrt(np.abs(np.sum((S - s0) ** 2 * V) / np.sum(V))) sigma = np.sqrt(np.abs(np.sum((S - s0) ** 2 * V) / np.sum(V)))
return fit_function(gauss, S, V, p0=(v0, vp, s0, sigma), bounds=((-np.inf, -np.inf, -np.inf, 0), (np.inf, np.inf, np.inf, np.inf)), **kwargs) result = fit_function(gauss, S, V, p0=(v0, vp, s0, sigma), **kwargs)
param, param_error, function, [X, _] = result
param[3] = np.abs(param[3]) # return the positive sigma (could use bounds instead, but that's more likely to fail)
return param, param_error, function, [X, lorenzian(X, *param)]
def fit_lorenzian(S, V, log=False, **kwargs): def fit_lorenzian(S, V, log=False, **kwargs):
lorenzian = lambda s, v0, vp, s0, gamma: v0 + vp/(1+((s-s0)/gamma)**2) lorenzian = lambda s, v0, vp, s0, gamma: v0 + vp/(1+((s-s0)/gamma)**2)
v0 = np.min(V) v0 = np.min(V)
vp = np.max(V)-v0 vp = np.max(V)-v0
s0 = S[np.argmax(V)] s0 = S[np.argmax(V)]
sigma = np.sqrt(np.abs(np.sum((S - s0) ** 2 * V) / np.sum(V))) sigma = np.sqrt(np.abs(np.sum((S - s0) ** 2 * (V-v0)) / np.sum(V-v0)))
return fit_function(lorenzian, S, V, p0=(v0, vp, s0, sigma), bounds=((-np.inf, -np.inf, -np.inf, 0), (np.inf, np.inf, np.inf, np.inf)), **kwargs) result = fit_function(lorenzian, S, V, p0=(v0, vp, s0, sigma), **kwargs)
param, param_error, function, [X, _] = result
param[3] = np.abs(param[3]) # return the positive sigma (could use bounds instead, but that's more likely to fail)
return param, param_error, function, [X, lorenzian(X, *param)]
def fit_function(function, x, y, p0=None, **kwargs): def fit_function(function, x, y, p0=None, **kwargs):
""" """
:param log: if the y-data is log-scaled :param log: if the y-data is log-scaled
""" """
param, cov = scipy.optimize.curve_fit(function, x, y, p0, **kwargs) param, cov = scipy.optimize.curve_fit(function, x, y, p0, **kwargs)
param_error = np.sqrt(cov.diagonal()) param_error = np.sqrt(np.abs(cov.diagonal()))
X = np.linspace(min(x), max(x), 1000) X = np.linspace(min(x), max(x), 1000)
return param, param_error, function, [X, function(X, *param)] return param, param_error, function, [X, function(X, *param)]
......
...@@ -2,10 +2,19 @@ import scipy ...@@ -2,10 +2,19 @@ import scipy
import numpy as np import numpy as np
import matplotlib as mpl import matplotlib as mpl
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import pint
from .data import * from .data import *
from .fitting import *
# Setup pint
SI = pint.UnitRegistry()
SI.setup_matplotlib()
SI.default_format = '~P'
# Colors
# https://arxiv.org/abs/2107.02270 # https://arxiv.org/abs/2107.02270
petroff_colors = ["#3f90da", "#ffa90e", "#bd1f01", "#94a4a2", "#832db6", "#a96b59", "#e76300", "#b9ac70", "#717581", "#92dadd"] petroff_colors = ["#3f90da", "#ffa90e", "#bd1f01", "#94a4a2", "#832db6", "#a96b59", "#e76300", "#b9ac70", "#717581", "#92dadd"]
cmap_petroff_10 = mpl.colors.ListedColormap(petroff_colors, 'Petroff 10') cmap_petroff_10 = mpl.colors.ListedColormap(petroff_colors, 'Petroff 10')
...@@ -22,6 +31,8 @@ cmap_petroff_bipolar.set_over(petroff_colors[8]) ...@@ -22,6 +31,8 @@ cmap_petroff_bipolar.set_over(petroff_colors[8])
def add_vline(axes, r, color='k', text=None, label=None, order=None, lw=1, text_top=True, text_vertical=True, zorder=-100, **kwargs): def add_vline(axes, r, color='k', text=None, label=None, order=None, lw=1, text_top=True, text_vertical=True, zorder=-100, **kwargs):
for i, a in enumerate(axes): for i, a in enumerate(axes):
if a is None: continue if a is None: continue
...@@ -86,7 +97,8 @@ def plot_tbt(ax, libera_data, over_time=True, turn_range=None, time_range=None): ...@@ -86,7 +97,8 @@ def plot_tbt(ax, libera_data, over_time=True, turn_range=None, time_range=None):
ax2.legend([lf,ls], ['Revolution frequency', 'Pickup sum signal'], loc='center right', fontsize='small') ax2.legend([lf,ls], ['Revolution frequency', 'Pickup sum signal'], loc='center right', fontsize='small')
def plot_tune_spectrum(ax, libera_data, xy, turn_range=None, time_range=None, tune_range=None, **kwargs):
def plot_tune_spectrum(ax, libera_data, xy, turn_range=None, time_range=None, tune_range=None, fit=False, **kwargs):
"""Plot a tune spectrum based on turn-by-turn data """Plot a tune spectrum based on turn-by-turn data
:param ax: Axis to plot onto :param ax: Axis to plot onto
...@@ -112,7 +124,21 @@ def plot_tune_spectrum(ax, libera_data, xy, turn_range=None, time_range=None, tu ...@@ -112,7 +124,21 @@ def plot_tune_spectrum(ax, libera_data, xy, turn_range=None, time_range=None, tu
ax.plot(freq, mag, **kwargs) ax.plot(freq, mag, **kwargs)
ax.set(xlim=tune_range, xlabel=f'Tune $q_{xy}$', ax.set(xlim=tune_range, xlabel=f'Tune $q_{xy}$',
ylabel='Magnitude / a.u.') ylabel='a.u.')
if fit:
try:
fitr = (fit if callable(fit) else fit_lorenzian)(freq, mag)
q, w = fitr[0][2], fitr[0][3]
if q<0 or q>0.5 or w > 0.01:
raise RuntimeError('Fit failed')
except RuntimeError:
print('Warning: fit failed')
else:
q = SI.Measurement(fitr[0][2], (fitr[1][2]**2+fitr[0][3]**2+fitr[1][3]**2)**0.5, '') # conservative estimate of error including width of peak
ax.plot(*fitr[-1], '--', label=f'Fit $q_{xy}={q:~L}$')
def plot_tune_spectrogram(ax, libera_data, xy, nperseg=2**12, noverlap=None, ninterpol=4, smoothing=0, over_time=True, colorbar=False, def plot_tune_spectrogram(ax, libera_data, xy, nperseg=2**12, noverlap=None, ninterpol=4, smoothing=0, over_time=True, colorbar=False,
...@@ -135,7 +161,7 @@ def plot_tune_spectrogram(ax, libera_data, xy, nperseg=2**12, noverlap=None, nin ...@@ -135,7 +161,7 @@ def plot_tune_spectrogram(ax, libera_data, xy, nperseg=2**12, noverlap=None, nin
tbt_data = getattr(libera_data, xy)[turn_range] tbt_data = getattr(libera_data, xy)[turn_range]
tune, turn, value = scipy.signal.stft(tbt_data, fs=1, nperseg=nperseg, noverlap=noverlap, window='boxcar', boundary=None, padded=False) tune, turn, value = scipy.signal.stft(tbt_data, fs=1, nperseg=nperseg, noverlap=noverlap, window='boxcar', boundary=None, padded=False)
time = libera_data.t[turn.astype(int)] time = libera_data.t[turn_range][turn.astype(int)]
mag = np.abs(value) mag = np.abs(value)
#mag[0,:] = 0 # supress DC #mag[0,:] = 0 # supress DC
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment