"git@git.gsi.de:phelix/lv/imagesource.git" did not exist on "ebb80e666da5615d6ee23efa9d88be626cff7718"
Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/usr/bin/env python
# -*- coding: utf-8 -*-
""" Methos for making beam profile realted plots, e.g. from ionisation profile monitor (IPM) data
"""
__author__ = "Philipp Niedermayer"
__contact__ = "p.niedermayer@gsi.de"
__date__ = "2022-09-29"
from itertools import cycle
from .common import *
def plot_beam_size(ax, ipm_data, xy, time_range=None, smoothing=None, fit=fit_lorenzian, **kwargs):
"""Plot beam size as function of time from fitted IPM data
:param ipm_data: instance of IPMData
:param xy: plane to consider, either 'x' or 'y'
:param time_range: range of (start, stop) time in s to plot
:param smoothing: if specified, apply a moving average smoothing filter of this width to the data
:param fit: fit function
"""
mask = slice(None, None) if time_range is None else irng(ipm_data.t, *time_range)
data = getattr(ipm_data, xy)[mask]
#if smoothing: data = scipy.signal.savgol_filter(data, smoothing, 0, axis=0)
n = data.shape[0]
v, ve = np.nan*np.zeros(n), np.nan*np.zeros(n)
for j in range(n):
try:
(*_, v[j]), (*_, ve[j]), _, fitted = fit(ipm_data.w, data[j,:])
except RuntimeError: # fit failed
...
if smoothing:
v, ve = [scipy.signal.savgol_filter(_, smoothing, 0) for _ in (v, ve)] # savgol filter with order 0 is moving average
ls, = ax.plot(ipm_data.t[mask], v, **kwargs)
ax.fill_between(ipm_data.t[mask], v-ve, v+ve, alpha=0.3, color=ls.get_color(), zorder=-10)
ax.set(ylabel=f'Beam size $\\sigma_{xy}$ / mm', xlabel='Time / s')
def plot_beam_profile(ax, ipm_data, xy, at_time, smoothing=None, fit=fit_gaussian, cut_lower=None, **kwargs):
"""Plot IPM beam profile at given time with fits
:param ax: The axis to plot onto
:param ipm_data: data object with IPM profile data
:param xy: what to plot, 'x' or 'y'
:param at_time: time in sec of profile to plot
:param smoothing: smooth profile over every this many bins
:param fit: function or list of functions to use for fitting, see fitting.py
"""
profile = np.copy(getattr(ipm_data, xy)[np.argmin(np.abs(ipm_data.t-at_time)),:]) # copy in order not to modify in-place
if smoothing: profile = smooth(profile, n=smoothing)[0]
# cut MCP noise away
if cut_lower:
ax.stairs(profile[1:-1], (ipm_data.w[1:]+ipm_data.w[:-1])/2, color='gray', alpha=.5, **kwargs)
profile[profile<cut_lower*max(profile)] = 0
ax.stairs(profile[1:-1], (ipm_data.w[1:]+ipm_data.w[:-1])/2, #color=cmap_petroff_10(0 if xy=='x' else 2),
label=f'Profile ($t={at_time*SI.s:~L}$)', **kwargs)
# Fit
if not hasattr(fit, '__iter__'): fit = (fit,)
ls = cycle(["--",":","-."])
fitresults = []
for fit in fit:
p, pe, _, plot = fit(ipm_data.w, profile)
if fit == fit_gaussian:
s = SI.Measurement(p[3], pe[3], ipm_data.w_unit)
label = f'Gaussian fit\n$\\sigma_{xy}={s:~L}$'
elif fit == fit_lorenzian:
s = SI.Measurement(p[3], pe[3], ipm_data.w_unit)
label = f'Lorenzian fit\n$\\gamma_{xy}={s:~L}$'
else:
s = (p, pe)
label = fit.__name__
fitresults.append(s)
ax.plot(*plot, ls=next(ls), label=label)
ax.legend()
ax.set(xlabel=f'{xy} / {ipm_data.w_unit}', ylabel=f'Intensity / {ipm_data.unit}', xlim=(min(ipm_data.w), max(ipm_data.w)), ylim=(0, ax.get_ylim()[1]))
return fitresults[0] if len(fitresults)==1 else fitresults