Reduction of TOFTOF data
Introduction
This notebook is based on the paper by D. Noferini et al., “Role of the doping level in localized proton motions in acceptor-doped barium zirconate proton conductors”, PCCP 20, 13697 (2018). https://doi.org/10.1039/C7CP07340B
We kindly thank the authors for allowing us to use their data.
In this work, the authors have used Quasi Elastic Neutron Scattering (QENS), among other techniques, to investigate the microscopic details of the proton motions in two proton conducting, acceptor-doped, perovskites, namely BaZr\(_{0.9}\)In\(_{0.1}\)O\(_{2.95}\) and BaZr\(_{0.8}\)In\(_{0.2}\)O\(_{2.9}\). Both samples were measured at the time-of-flight spectrometer TOFTOF at MLZ using an incident wavelength of 2.5 \(\unicode{x212B}\), giving a Gaussian-shaped resolution function with a full width at half maximum (FWHM) of approximately 450 \(\mu\)eV and a \(Q\)-range between 0.36 and 4.7 \(\unicode{x212B}^{-1}\). However, as some of the detectors were contaminated by Bragg reflections, only a set of 9 Q-cuts were retained in the analysis: \(Q = 0.6, 0.8, 1.0, 1.2, 1.7, 1.9, 2.3, 3.5, 3.9\) \(\unicode{x212B}^{-1}\).
This experimental setup provides information about the fast (in the order of picoseconds) local dynamics of the protons in the sample, i.e., how the proton jumps between adjacent oxygens or how the O-H group reorients. This is done by fitting the measured incoherent dynamic structure factor, \(S(Q, \omega)\), as a sum of an elastic (represented by a Dirac delta function) and a quasielastic (represented by a Lorentzian function) contributions, from which the elastic incoherent structure factor (EISF) is extracted. The latter can then be compared to different theoretical models (e.g., jumps between two equivalent sites vs jumps over four sites) in order to determine the microscopic details of the initial proton diffusion mechanism at the origin of the long-range diffusion (observable on a larger time scale of the order of a few nanoseconds, and therefore requiring sub-\(\mu\)eV resolution to measure it) and hence influencing the protonic conductivity of these systems. See the article for more details.
The two samples have been measured at several temperatures (200, 350, 450 and 540 K) in order also to determine the activation energy of this process.
In this notebook we will analyse only the data of one sample (\(BaZr_{0.8}In_{0.2}O_{3}H_{0.2}\)) at 350, 450 and 540 K, starting from the fully corrected \(S(Q,\omega)\) data derived from the raw counts after applying the following reduction steps: - normalization of the detectors using a vanadium standard - suppression of noisy or blind detectors - subtraction of the scattering from an empty sample container - correction of neutron energy-dependent efficiency of the neutron counters
During the analysis, the fit was done in a limited exchanged energy range: [-5, 0.7] meV, in order to avoid the elastic multiple scattering artefacts coming from scattering of the sample environment in the Stokes part of the spectra.
Explanations to preparation of fitting
Reading input files
Each sample file corresponds to a temperature. They contain reduced data at several \(q\)-values. There are four files (named In20_2p5_###K_tt_cr.txt) containing \(S(Q,\hbar\omega)\) at T = 200, 350, 450, and 540 K, and a fifth one containing the signal of a vanadium reference sample serving as a measurement of the resolution function.
The files are written in the INX format (F. Rieutord, INX - Program for time-of-flight data reduction, ILL Technical Report 90RI17T, 1990). For each \(Q\) we have a block consisting of a header of 4 lines, followed by 3 columns of data corresponding to \(\hbar\omega\) (in meV), \(S(Q,\hbar\omega)\) for that particular \(Q\) value, and the associated error.
The header is organized as follows:
- Line 1: 8 integers.The first integer indicates the number \(N\) of following lines that correspond to the present block, and the last integer is the number of points in the spectrum, i.e., \(N-3\).
Line 2: String containing the experiment title
- Line 3: 5 floats and 1 integer.The first one corresponds to the block index (or alternatively it can contain the value of \(Q\) or \(2\theta\) in the case the file contains \(S(2\theta, \hbar\omega)\) instead of \(S(Q,\hbar\omega)\)).The second and third values correspond to the incident energy (in meV) and wavevector (in \(\unicode{x212B}^{-1}\)), respectively.The fourth float number is the temperature.Here, the remaining float and integer values do not contain relevant information.
- Line 4: 3 floats.Not used here, although the second number can contain the bin width (normally in microseconds) of the time channels used during the time-of-flight acquisition.
Expression of fitting model
The spectrum of a vanadium standard was used as a resolution function \(R(Q, \hbar \omega)\).
where $ S(Q, \hbar `:nbsphinx-math:omega`) = a_D(Q) \delta`(:nbsphinx-math:hbar :nbsphinx-math:omega`) + a_L(Q) L(Q, \hbar `:nbsphinx-math:omega`) + bkg(Q)$, \(n(\hbar \omega) = \frac{1}{\exp(\frac{\hbar \omega}{k_B T}) - 1}\) is the Bose factor, and \(\beta = \frac{1}{k_B T}\) the reciprocal of the thermodynamic temperature. \(\delta\) and \(L\) are a Dirac peak and a Lorentzian, respectively. The background is constant, only Q-dependent. \(\circledast\) is the convolution symbol.
To avoid elastic multiple scattering artefacts from the environment present in the Stokes part of the spectra, the fit range was limited to \(-5\leq \hbar \omega \leq 0.7\) meV. We further focus on the peak and use a fitting range of \(-1\leq \hbar \omega \leq 0.7\) meV at temperatures of 350, 450 amd 540 K.
In order to investigate the geometry of the observed proton dynamics, we analyze the Q-dependence of the elastic and quasielastic scattering intensities. Comparing \(a_D(Q)\) and \(a_L(Q)\) normalized for their sum, with the expressions expected within the framework of a model for a jump diffusion over 2 or 4 equivalent sites located on a circle with radius \(r\): jump length, mean residence time (Noferini et al., “Localized proton motions in acceptor-doped Barium Zirconates” J. Phys. Chem. C 121, 7088 (2017))
Calculating variances for \(\frac{a_D}{a_D+a_L}\) and \(\frac{a_L}{a_D+a_L}\)
Combinations of refined parameters will be plotted after the fit in order to compare with the above publication: \(\frac{a_D}{a_D + a_L}\) and \(\frac{a_L}{a_D + a_L}\). Therefore, we have to calculate the related uncertainty. Straightforward calculations of error propagation, assuming uncorrelated parameters, lead to the following expressions:
Importing libraries
[1]:
import numpy as np
import matplotlib.pyplot as plt
import QENSmodels
import scipy
import lmfit
from lmfit import Model, CompositeModel
from scipy.interpolate import interp1d
import pandas as pd
%matplotlib widget
q-values and range of \(\hbar \omega\)
[2]:
q_tof = [0.6, 0.8, 1.0, 1.2, 1.7, 1.9, 2.3, 3.5, 3.9] # in 1/Angstrom
# Range of energy in meV
hbar_omega_min = -1.
hbar_omega_max = 0.7
Reading reduced TOFTOF files
[3]:
def read_toftof_file(filename):
"""
Read reduced files from TOFTOF
The file contains hbar omega, I, I_err for different values of q
Some metadata are stored as the header of the array in each case
Parameters
----------
filename: str
file containing TOFTOF reduced data
Returns
-------
numpy.array: 4 columns: hbar omega, I, I_err and index corresponding to different values of q
"""
with open(filename, 'r') as fin:
file = fin.readlines()
for i, item in enumerate(file):
# get number of recording per spectrum
if i == 0:
REC_PER_SPEC = int(item.split()[0]) + 1
if (i % REC_PER_SPEC)==0:
number_records = int(item.split()[0])
elif (i % REC_PER_SPEC)==2:
q_value = item.strip()[0]
elif (i % REC_PER_SPEC) == 1 or (i % REC_PER_SPEC) == 3:
pass
elif i == 4:
list_2_store = [float(elt) for elt in item.strip().split()]
list_2_store.append(float(q_value))
data = np.array(list_2_store)
elif (i % REC_PER_SPEC) == 4 and i > 4:
pass
else:
list_2_store = [float(elt) for elt in item.strip().split()]
list_2_store.append(float(q_value))
new_row = np.array(list_2_store)
data = np.vstack([data, new_row])
return data
[4]:
data_350K = read_toftof_file('./data/toftof/In20_2p5_350K__tt_cr.txt')
data_450K = read_toftof_file('./data/toftof/In20_2p5_450K__tt_cr.txt')
data_540K = read_toftof_file('./data/toftof/In20_2p5_540K__tt_cr.txt')
vana = read_toftof_file('./data/toftof/Vana_2p5_cool__tt_cr.txt')
dict_toftof['350K']['q_0.6']['x'] stores the values of \(\hbar \omega\) at \(q=0.6\) 1/Angstrom and \(T=350K\).dict_toftof['350K']['q_0.6'] correspond to the values of \(S\) and the associated uncertainty, respectively.[5]:
dict_toftof = {}
dict_data_350K = {}
dict_data_450K = {}
dict_data_540K = {}
dict_vana = {}
for i in range(1, 10):
key = f"q_{q_tof[i-1]}"
# 350K
indx = (data_350K[:, 3]==i)
dict_data_350K[key] = {'x': data_350K[indx][:, 0],
'y': data_350K[indx][:, 1],
'e': data_350K[indx][:, 2]}
# 450K
indx = (data_450K[:, 3]==i)
dict_data_450K[key] = {'x': data_450K[indx][:, 0],
'y': data_450K[indx][:, 1],
'e': data_450K[indx][:, 2]}
# 540K
indx = (data_540K[:, 3]==i)
dict_data_540K[key] = {'x': data_540K[indx][:, 0],
'y': data_540K[indx][:, 1],
'e': data_540K[indx][:, 2]}
# vanadium
indx = (vana[:, 3]==i)
dict_vana[key] = {'x': vana[indx][:, 0],
'y': vana[indx][:, 1],
'e': vana[indx][:, 2]}
dict_toftof['350K'] = dict_data_350K
dict_toftof['450K'] = dict_data_450K
dict_toftof['540K'] = dict_data_540K
dict_toftof['vana'] = dict_vana
[6]:
fig, ax = plt.subplots(nrows=2,
ncols=2,
figsize=(10, 10),
sharex=True,
sharey=True)
[ax[0, 0].semilogy(dict_toftof['350K'][q_value]['x'],
dict_toftof['350K'][q_value]['y'],
label=f"{q_value}") for q_value in dict_toftof['350K']]
[ax[0, 1].semilogy(dict_toftof['450K'][q_value]['x'],
dict_toftof['450K'][q_value]['y'],
label=f"{q_value}") for q_value in dict_toftof['450K']]
[ax[1, 0].semilogy(dict_toftof['540K'][q_value]['x'],
dict_toftof['540K'][q_value]['y'],
label=f"{q_value}") for q_value in dict_toftof['540K']]
[ax[1, 1].semilogy(dict_toftof['vana'][q_value]['x'],
dict_toftof['vana'][q_value]['y'],
label=f"{q_value}") for q_value in dict_toftof['vana']]
for i in range(2):
for j in range(2):
ax[i, j].grid()
ax[i, j].legend()
fig.suptitle("All TOFTOF sample data")
ax[0, 0].set_title('350K')
ax[0, 1].set_title('450K')
ax[1, 0].set_title('540K')
ax[1, 1].set_title('vanadium')
ax[1, 0].set_xlabel(r"$\hbar \omega$ (meV)")
ax[1, 1].set_xlabel(r"$\hbar \omega$ (meV)")
ax[0, 0].set_ylabel(r"S(Q, $\hbar \omega$) (arb. units)")
ax[1, 0].set_ylabel(r"S(Q, $\hbar \omega$) (arb. units)");
Fitting
Creating the Model
Dirac and Lorentzian functions
[7]:
def toftof_delta_lorentz(w, aD, aL, cst_bgd, center, gamma):
""" Define S(Q, omega) using the QENS models
Parameters
----------
w: float or list or :class:`~numpy:numpy.ndarray`
Energy (meV)
aD: float
Scaling coefficient of Delta function
aL: float
Scaling coefficient of Lorentzian function
cst_bgd: float
Constant coefficient of the background
center: float
Center of the Delta and Lorentzian functions
gamma: float
Half Width at Half Maximum of Lorentzian function
Returns
-------
numpy.array: 1 column corresponding to Dirac + Lorentzian + constant_background
"""
return QENSmodels.delta(w,
scale=aD,
center=center) + \
QENSmodels.lorentzian(w,
scale=aL,
center=center,
hwhm=gamma) + \
QENSmodels.background_polynomials(w,
[cst_bgd])
def S_meas_no_convol(w, T, aD, aL, cst_bgd, center, gamma):
""" Define S_meas = S(Q, omega) multiplied by Bose factor
Parameters
----------
w: float or list or :class:`~numpy:numpy.ndarray`
Energy (meV)
T: float
Temperature (K)
aD: float
Scaling coefficient of Delta function
aL: float
Scaling coefficient of Lorentzian function
cst_bgd: float
Constant coefficient of the background
center: float
Center of the Delta and Lorentzian functions
gamma: float
Half Width at Half Maximum of Lorentzian function
Returns
-------
numpy.array: 1 column corresponding to (Dirac + Lorentzian + constant_background) * Bose factor
"""
beta = scipy.constants.physical_constants['electron volt-joule relationship'][0] / (1000 * scipy.constants.Boltzmann * T)
return (w * beta * toftof_delta_lorentz(w, aD, aL, cst_bgd, center, gamma)
* (1. + 1. / (np.exp(beta * w) - 1)))
Convolution
From https://github.com/jmborr/qef
[8]:
def convolve(model, resolution):
r"""
Convolution of resolution with model data
.. math:: (model \otimes resolution)[n] = dx * \sum_m model[m] * resolution[m-n]
"""
c = np.convolve(model, resolution, mode='valid')
if len(model) % len(resolution) == 0:
c = c[:-1]
return c
class Convolve(CompositeModel):
"""
Convolution between model and resolution.
It is assumed that the resolution FWHM is energy independent.
Non-symmetric energy ranges are allowed (when the range of negative values
is different than that of positive values).
The convolution requires multiplication by the X-spacing to preserve
normalization
"""
def __init__(self, resolution, model, **kws):
super(Convolve, self).__init__(resolution, model, convolve, **kws)
self.resolution = resolution
self.model = model
def eval(self, params=None, **kwargs):
res_data = self.resolution.eval(params=params, **kwargs)
# evaluate model on an extended energy range to avoid boundary effects
independent_var = self.resolution.independent_vars[0]
e = kwargs[independent_var] # energy values
neg_e = min(e) - np.flip(e[np.where(e > 0)], axis=0)
pos_e = max(e) - np.flip(e[np.where(e < 0)], axis=0)
e = np.concatenate((neg_e, e, pos_e))
kwargs.update({independent_var: e})
model_data = self.model.eval(params=params, **kwargs)
# Multiply by the X-spacing to preserve normalization
de = (e[-1] - e[0])/(len(e) - 1) # energy spacing
return de * convolve(model_data, res_data)
Complete fitting model and procedure
[9]:
def build_and_fit_S_meas_single_q(q_value, ini_vals, plot=True):
"""
Define the complete fitting model S_meas
Parameters
----------
q_value: float
momentum transfer (non-fitting, in 1/Angstrom)
ini_vals: dictionary of initial guesses for the parameters.
For example, {'T': 350 , 'aD': 2, 'aL': 10, 'cst_bgd': 0.1, 'center': 0, 'gamma': 0.4}
Note that the temperature, T, is not refined
plot: boolean
If True, plots initial model, experimental data and fitting result
Returns
-------
lmfit.model.ModelResult: structure containing the output of a fit using lmfit for a single value of q
"""
temperature_key = str(ini_vals['T']) + 'K'
def irf_gate(w):
"""
Function defined from the interpolation of instrument resolution data
Used to define fitting model and plot
"""
f_interp = interp1d(dict_toftof['vana'][q_value]['x'],
dict_toftof['vana'][q_value]['y']/np.sum(dict_toftof['vana'][q_value]['y']),
kind='cubic', bounds_error=False, fill_value='extrapolate')
return f_interp(w)
gmodel = Convolve(Model(irf_gate), Model(S_meas_no_convol))
pars = lmfit.Parameters()
pars.add('T', value=ini_vals['T'], vary=False)
pars.add('aD', value=ini_vals['aD'], min=0, vary=True)
pars.add('aL', value=ini_vals['aL'], min=0.01, vary=True)
pars.add('cst_bgd', value=ini_vals['cst_bgd'], min=0, vary=True)
pars.add('center', value=ini_vals['center'], min=-1, max=1, vary=True)
pars.add('gamma', value=ini_vals['gamma'], min=0.01, vary=True)
xx = dict_toftof[temperature_key][q_value]['x']
mask = np.intersect1d(np.where(xx>=hbar_omega_min), np.where(xx<=hbar_omega_max))
# remove NaNs due to singularity on model when xx=0
mask = np.intersect1d(mask, np.where(abs(xx)>=1e-12))
# remove negative S(Q, hbar omega) values
mask = np.intersect1d(mask, np.where(dict_toftof[temperature_key][q_value]['y']>0))
out = gmodel.fit(dict_toftof[temperature_key][q_value]['y'][mask],
pars,
method='leastsq',
w=xx[mask],
weights=1/dict_toftof[temperature_key][q_value]['e'][mask],
fit_kws={'xtol': 1e-9, 'ftol': 1e-9},
)
if plot:
# plot initial model, fit results and experimental data
fig1, ax1 = plt.subplots()
ax1.semilogy(xx[mask],
dict_toftof[temperature_key][q_value]['y'][mask],
'.-',
label='exp data')
ax1.semilogy(xx[mask], out.init_fit, '--', label='initial fit')
ax1.semilogy(xx[mask], out.best_fit, 'r-', label='best fit')
ax1.set_title(f'{q_value}, reduced chi_sq={out.redchi:.2f}')
ax1.set_xlabel(r"$\hbar \omega$ (meV)")
ax1.set_ylabel(r"S(Q, $\hbar \omega$) (arb. units)")
ax1.legend(); ax1.grid()
plt.show()
return out
def fit_S_meas_all_q(ini_vals, plot=True):
"""
Fit S_meas (convolution with resolution function) using lmfit
and plot experimental data, initial model and fit for all q-values
(One value of q per plot)
Parameters
----------
ini_vals: dictionary of initial guesses for the parameters.
For example, {'T': 350 , 'aD': 2, 'aL': 10, 'cst_bgd': 0.1, 'center': 0, 'gamma': 0.4}
Note that the temperature, T, is not refined
plot: boolean
If True, plots initial model, experimental data and fitting result
Returns
-------
dictionary of lmfit.model.ModelResult
Each key corresponds to a value of q. The value is the output of a fit using lmfit for a single value of q
"""
result_fit = {} # store fits for all spectra
temperature_key = str(ini_vals['T']) + 'K'
# Loop over q-values
for i, q_value in enumerate(dict_toftof[temperature_key]):
result_fit[str(q_value)] = build_and_fit_S_meas_single_q(q_value, ini_vals, plot=plot)
if plot:
fig3, ax3 = plt.subplots(nrows=3, ncols=2, sharex=True, figsize=(10, 10))
ax3[0, 0].plot([key for key in result_fit.keys()],
[result_fit[key].params['aD'].value for key in result_fit.keys()],
marker='o')
ax3[0, 0].set_ylabel('aD')
ax3[0, 1].plot([key for key in result_fit.keys()],
[result_fit[key].params['aL'].value for key in result_fit.keys()],
marker='o')
ax3[0, 1].set_ylabel('aL')
ax3[1, 0].plot([key for key in result_fit.keys()],
[result_fit[key].params['center'].value for key in result_fit.keys()],
marker='o')
ax3[1, 0].set_ylabel('center')
ax3[1, 1].plot([key for key in result_fit.keys()],
[result_fit[key].params['gamma'].value for key in result_fit.keys()],
marker='o')
ax3[1, 1].set_ylabel('gamma')
ax3[2, 0].plot([key for key in result_fit.keys()],
[result_fit[key].params['cst_bgd'].value for key in result_fit.keys()],
marker='o')
ax3[2, 0].set_ylabel('cst_bgd'); ax3[2, 0].set_xlabel('q')
ax3[2, 1].set_ylabel('reduced chi squared'); ax3[2, 1].set_xlabel('q values')
ax3[2, 1].bar(range(len(q_tof)),
[result_fit[key].redchi for key in result_fit.keys()],
align='center',
tick_label=list(result_fit.keys()))
plt.tight_layout()
for i in range(3):
for j in range(2):
ax3[i, j].grid()
return result_fit
[10]:
def dict_ref_params_for_a_temperature(result_fit):
"""
Creates a pandas.DataFrame to store the values and errors of the refined parameters at a given temperature.
Each row corresponds to a value of q.
Note that we replace NaN by zero.
Parameters
----------
result_fit : dictionary of lmfit.model.ModelResult for a given temperature
Each key corresponds to a value of q.
The value is the output of a fit using lmfit for the corresponding q
Returns
-------
pandas.DataFrame: stores the value and error of the refined parameters
"""
q_keys = result_fit.keys()
data_frame_one_temp = pd.DataFrame(
data= {"aD": [result_fit[q].params['aD'].value for q in q_keys],
"aD_err": [result_fit[q].params['aD'].stderr for q in q_keys],
"aL": [result_fit[q].params['aL'].value for q in q_keys],
"aL_err": [result_fit[q].params['aL'].stderr for q in q_keys],
"cst_bgd": [result_fit[q].params['cst_bgd'].value for q in q_keys],
"cst_bgd_err": [result_fit[q].params['cst_bgd'].stderr for q in q_keys],
"center": [result_fit[q].params['center'].value for q in q_keys],
"center_err": [result_fit[q].params['center'].stderr for q in q_keys],
"gamma": [result_fit[q].params['gamma'].value for q in q_keys],
"gamma_err": [result_fit[q].params['gamma'].stderr for q in q_keys],
"red_chi_squared": [result_fit[q].redchi for q in q_keys],
},
index=q_keys).fillna(0)
return data_frame_one_temp
Creating and defining parameters and functions to collect and display fitting results
[11]:
# This dictionary will store the value and error of the refined parameters for each temperature as a pandas dataframe.
dict_ref_params = {}
[12]:
def plot_ratio_coefficients(dict_to_plot):
"""
Plot ratios of aD and aL to compare with publication
Parameters
----------
dict_to_plot: select key of dictionary to plot: for example, dict_ref_params['350K']
Returns
-------
None
"""
std_err_ratio = np.sqrt((dict_to_plot['aD'].values**2 * dict_to_plot['aL_err'].values**2
+ dict_to_plot['aL'].values**2 * dict_to_plot['aD_err'].values**2)
/ (dict_to_plot['aD'].values + dict_to_plot['aL'].values)**4)
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(8, 4))
ax[0].errorbar(dict_to_plot.index,
dict_to_plot['aD'].values / (dict_to_plot['aD'].values + dict_to_plot['aL'].values),
std_err_ratio,
marker='o',
linestyle='--')
ax[0].set_ylabel('$a_D/(a_D+a_L)$')
ax[0].set_ylim((0, 1))
ax[1].errorbar(dict_to_plot.index,
dict_to_plot['aL'].values / (dict_to_plot['aD'].values + dict_to_plot['aL'].values),
std_err_ratio,
marker='o',
linestyle='--')
ax[1].set_ylabel('$a_L/(a_D+a_L$)')
ax[1].set_ylim((0, 1))#0.5))
for i in range(2):
ax[i].grid()
ax[i].set_xlabel(r'$Q (1/\AA)$')
for tick in ax[i].get_xticklabels():
tick.set_rotation(45)
plt.tight_layout()
plt.show()
return
Fitting at T = 350K
[13]:
ini_vals_350K = {'T': 350,
'aD': 1,
'aL': 40,
'cst_bgd': 0.04,
'center': -1e-7,
'gamma': 0.1}
fit350 = fit_S_meas_all_q(ini_vals_350K)
[14]:
for item in fit350.keys():
print(f'----------\nResult of fit for {item}:\n',
fit350[item].fit_report())
----------
Result of fit for q_0.6:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 227
# data points = 34
# variables = 5
chi-square = 51.6875996
reduced chi-square = 1.78233102
Akaike info crit = 24.2411508
Bayesian info crit = 31.8729534
R-squared = 0.94612305
## Warning: uncertainties could not be estimated:
aL: at boundary
[[Variables]]
T: 350 (fixed)
aD: 162.021246 (init = 1)
aL: 0.01000001 (init = 40)
cst_bgd: 0.32552634 (init = 0.04)
center: -0.05029700 (init = -1e-07)
gamma: 0.01002385 (init = 0.1)
----------
Result of fit for q_0.8:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 2544
# data points = 34
# variables = 5
chi-square = 7.78665625
reduced chi-square = 0.26850539
Akaike info crit = -40.1142658
Bayesian info crit = -32.4824632
R-squared = 0.99149584
## Warning: uncertainties could not be estimated:
cst_bgd: at boundary
gamma: at boundary
[[Variables]]
T: 350 (fixed)
aD: 140.600595 (init = 1)
aL: 94.2895752 (init = 40)
cst_bgd: 1.2922e-09 (init = 0.04)
center: -5.3771e-10 (init = -1e-07)
gamma: 0.01000000 (init = 0.1)
----------
Result of fit for q_1.0:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 437
# data points = 34
# variables = 5
chi-square = 41.0859028
reduced chi-square = 1.41675527
Akaike info crit = 16.4363543
Bayesian info crit = 24.0681570
R-squared = 0.95599024
## Warning: uncertainties could not be estimated:
gamma: at boundary
[[Variables]]
T: 350 (fixed)
aD: 140.215403 (init = 1)
aL: 104.529441 (init = 40)
cst_bgd: 0.05944927 (init = 0.04)
center: -2.0172e-09 (init = -1e-07)
gamma: 0.01000000 (init = 0.1)
----------
Result of fit for q_1.2:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 1301
# data points = 34
# variables = 5
chi-square = 15.9822260
reduced chi-square = 0.55111124
Akaike info crit = -15.6660321
Bayesian info crit = -8.03422946
R-squared = 0.98277193
## Warning: uncertainties could not be estimated:
cst_bgd: at boundary
gamma: at boundary
[[Variables]]
T: 350 (fixed)
aD: 136.150152 (init = 1)
aL: 123.231659 (init = 40)
cst_bgd: 5.3832e-09 (init = 0.04)
center: -1.8017e-09 (init = -1e-07)
gamma: 0.01000000 (init = 0.1)
----------
Result of fit for q_1.7:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 461
# data points = 34
# variables = 5
chi-square = 11.9454578
reduced chi-square = 0.41191234
Akaike info crit = -25.5643201
Bayesian info crit = -17.9325175
R-squared = 0.98616150
## Warning: uncertainties could not be estimated:
[[Variables]]
T: 350 (fixed)
aD: 134.012085 (init = 1)
aL: 40.4025544 (init = 40)
cst_bgd: 0.58316481 (init = 0.04)
center: -2.6425e-11 (init = -1e-07)
gamma: 0.03111282 (init = 0.1)
----------
Result of fit for q_1.9:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 247
# data points = 34
# variables = 5
chi-square = 5.77290980
reduced chi-square = 0.19906586
Akaike info crit = -50.2882653
Bayesian info crit = -42.6564627
R-squared = 0.99323979
[[Variables]]
T: 350 (fixed)
aD: 126.304360 +/- 4.05392517 (3.21%) (init = 1)
aL: 139.484223 +/- 274.572499 (196.85%) (init = 40)
cst_bgd: 0.52247309 +/- 0.13280326 (25.42%) (init = 0.04)
center: -0.00271709 +/- 0.00391600 (144.12%) (init = -1e-07)
gamma: 0.01000003 +/- 0.01838278 (183.83%) (init = 0.1)
[[Correlations]] (unreported correlations are < 0.100)
C(aL, gamma) = -0.999
C(aD, aL) = -0.701
C(aD, center) = 0.700
C(aD, gamma) = 0.662
C(aD, cst_bgd) = 0.476
C(cst_bgd, center) = 0.400
C(aL, center) = -0.399
C(center, gamma) = 0.371
C(cst_bgd, gamma) = -0.196
C(aL, cst_bgd) = 0.151
----------
Result of fit for q_2.3:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 422
# data points = 34
# variables = 5
chi-square = 12.6151137
reduced chi-square = 0.43500392
Akaike info crit = -23.7098075
Bayesian info crit = -16.0780049
R-squared = 0.98477413
## Warning: uncertainties could not be estimated:
gamma: at boundary
[[Variables]]
T: 350 (fixed)
aD: 127.214601 (init = 1)
aL: 139.725264 (init = 40)
cst_bgd: 0.73536362 (init = 0.04)
center: -5.5085e-09 (init = -1e-07)
gamma: 0.01000000 (init = 0.1)
----------
Result of fit for q_3.5:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 413
# data points = 34
# variables = 5
chi-square = 10.8341633
reduced chi-square = 0.37359184
Akaike info crit = -28.8843078
Bayesian info crit = -21.2525052
R-squared = 0.98448776
## Warning: uncertainties could not be estimated:
[[Variables]]
T: 350 (fixed)
aD: 117.247075 (init = 1)
aL: 36.9115245 (init = 40)
cst_bgd: 0.43955199 (init = 0.04)
center: -5.7454e-09 (init = -1e-07)
gamma: 0.05710292 (init = 0.1)
----------
Result of fit for q_3.9:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 359
# data points = 34
# variables = 5
chi-square = 14.7833730
reduced chi-square = 0.50977148
Akaike info crit = -18.3171523
Bayesian info crit = -10.6853496
R-squared = 0.97741417
## Warning: uncertainties could not be estimated:
[[Variables]]
T: 350 (fixed)
aD: 107.387591 (init = 1)
aL: 60.7418892 (init = 40)
cst_bgd: 0.71141647 (init = 0.04)
center: -3.4166e-09 (init = -1e-07)
gamma: 0.03121186 (init = 0.1)
Storing fitted parameters and quality factors
[15]:
dict_ref_params['350K'] = dict_ref_params_for_a_temperature(fit350)
dict_ref_params['350K']
[15]:
| aD | aD_err | aL | aL_err | cst_bgd | cst_bgd_err | center | center_err | gamma | gamma_err | red_chi_squared | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| q_0.6 | 162.021246 | 0.000000 | 0.010000 | 0.000000 | 3.255263e-01 | 0.000000 | -5.029700e-02 | 0.000000 | 0.010024 | 0.000000 | 1.782331 |
| q_0.8 | 140.600595 | 0.000000 | 94.289575 | 0.000000 | 1.292243e-09 | 0.000000 | -5.377085e-10 | 0.000000 | 0.010000 | 0.000000 | 0.268505 |
| q_1.0 | 140.215403 | 0.000000 | 104.529441 | 0.000000 | 5.944927e-02 | 0.000000 | -2.017207e-09 | 0.000000 | 0.010000 | 0.000000 | 1.416755 |
| q_1.2 | 136.150152 | 0.000000 | 123.231659 | 0.000000 | 5.383250e-09 | 0.000000 | -1.801730e-09 | 0.000000 | 0.010000 | 0.000000 | 0.551111 |
| q_1.7 | 134.012085 | 0.000000 | 40.402554 | 0.000000 | 5.831648e-01 | 0.000000 | -2.642497e-11 | 0.000000 | 0.031113 | 0.000000 | 0.411912 |
| q_1.9 | 126.304360 | 4.053925 | 139.484223 | 274.572499 | 5.224731e-01 | 0.132803 | -2.717089e-03 | 0.003916 | 0.010000 | 0.018383 | 0.199066 |
| q_2.3 | 127.214601 | 0.000000 | 139.725264 | 0.000000 | 7.353636e-01 | 0.000000 | -5.508479e-09 | 0.000000 | 0.010000 | 0.000000 | 0.435004 |
| q_3.5 | 117.247075 | 0.000000 | 36.911525 | 0.000000 | 4.395520e-01 | 0.000000 | -5.745414e-09 | 0.000000 | 0.057103 | 0.000000 | 0.373592 |
| q_3.9 | 107.387591 | 0.000000 | 60.741889 | 0.000000 | 7.114165e-01 | 0.000000 | -3.416569e-09 | 0.000000 | 0.031212 | 0.000000 | 0.509771 |
Plotting \(\frac{a_D}{a_D+a_L}\) and \(\frac{a_L}{a_D+a_L}\) at 350K
[16]:
plot_ratio_coefficients(dict_ref_params['350K'])
Tuning fits for some selected q-values (optional)
If the above fit is not satisfactory for only a few values of \(q\), the fit at these particular \(q\) can be rerun using the following method.
[17]:
dict_ref_params['350K']
[17]:
| aD | aD_err | aL | aL_err | cst_bgd | cst_bgd_err | center | center_err | gamma | gamma_err | red_chi_squared | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| q_0.6 | 162.021246 | 0.000000 | 0.010000 | 0.000000 | 3.255263e-01 | 0.000000 | -5.029700e-02 | 0.000000 | 0.010024 | 0.000000 | 1.782331 |
| q_0.8 | 140.600595 | 0.000000 | 94.289575 | 0.000000 | 1.292243e-09 | 0.000000 | -5.377085e-10 | 0.000000 | 0.010000 | 0.000000 | 0.268505 |
| q_1.0 | 140.215403 | 0.000000 | 104.529441 | 0.000000 | 5.944927e-02 | 0.000000 | -2.017207e-09 | 0.000000 | 0.010000 | 0.000000 | 1.416755 |
| q_1.2 | 136.150152 | 0.000000 | 123.231659 | 0.000000 | 5.383250e-09 | 0.000000 | -1.801730e-09 | 0.000000 | 0.010000 | 0.000000 | 0.551111 |
| q_1.7 | 134.012085 | 0.000000 | 40.402554 | 0.000000 | 5.831648e-01 | 0.000000 | -2.642497e-11 | 0.000000 | 0.031113 | 0.000000 | 0.411912 |
| q_1.9 | 126.304360 | 4.053925 | 139.484223 | 274.572499 | 5.224731e-01 | 0.132803 | -2.717089e-03 | 0.003916 | 0.010000 | 0.018383 | 0.199066 |
| q_2.3 | 127.214601 | 0.000000 | 139.725264 | 0.000000 | 7.353636e-01 | 0.000000 | -5.508479e-09 | 0.000000 | 0.010000 | 0.000000 | 0.435004 |
| q_3.5 | 117.247075 | 0.000000 | 36.911525 | 0.000000 | 4.395520e-01 | 0.000000 | -5.745414e-09 | 0.000000 | 0.057103 | 0.000000 | 0.373592 |
| q_3.9 | 107.387591 | 0.000000 | 60.741889 | 0.000000 | 7.114165e-01 | 0.000000 | -3.416569e-09 | 0.000000 | 0.031212 | 0.000000 | 0.509771 |
[18]:
# selected q-value for which to fit again
q_indx = [0, 1]
redo_q_keys = [list(fit350.keys())[q] for q in q_indx]
new_ini_vals = ini_vals_350K.copy()
stored_params = dict_ref_params['350K'].columns
data_frame_selected_qs = pd.DataFrame()
for indx, item in enumerate(redo_q_keys):
# store previous fitting result
old_fit_result = dict_ref_params['350K'].loc[item]
# define new initial parameters' values
new_ini_vals['aD'] = 2
new_ini_vals['aL'] = 20
new_ini_vals['gamma'] = 0.2
new_ini_vals['cst_bgd'] = 1
# rerun fitting
new_out = build_and_fit_S_meas_single_q(item, new_ini_vals, plot=True)
new_row = pd.DataFrame(
data = {"aD": [new_out.params['aD'].value],
"aD_err": [new_out.params['aD'].stderr],
"aL": [new_out.params['aL'].value],
"aL_err": [new_out.params['aL'].stderr],
"cst_bgd": [new_out.params['cst_bgd'].value],
"cst_bgd_err": [new_out.params['cst_bgd'].stderr],
"center": [new_out.params['center'].value],
"center_err": [new_out.params['center'].stderr],
"gamma": [new_out.params['gamma'].value],
"gamma_err": [new_out.params['gamma'].stderr],
"red_chi_squared": [new_out.redchi],
},
index=[item]).fillna(0)
data_frame_selected_qs = pd.concat([data_frame_selected_qs, new_row])
print((f'\nPrevious initial values: {ini_vals_350K}\n'),
(f'\nPrevious fit result at {item}:\n{old_fit_result}\n'),
('\n==================================================\n'),
(f'\nNew initial values: {new_ini_vals}\n'),
(f'\nNew fit result at {item}:\n{data_frame_selected_qs.loc[item]}')
)
Previous initial values: {'T': 350, 'aD': 1, 'aL': 40, 'cst_bgd': 0.04, 'center': -1e-07, 'gamma': 0.1}
Previous fit result at q_0.6:
aD 162.021246
aD_err 0.000000
aL 0.010000
aL_err 0.000000
cst_bgd 0.325526
cst_bgd_err 0.000000
center -0.050297
center_err 0.000000
gamma 0.010024
gamma_err 0.000000
red_chi_squared 1.782331
Name: q_0.6, dtype: float64
==================================================
New initial values: {'T': 350, 'aD': 2, 'aL': 20, 'cst_bgd': 1, 'center': -1e-07, 'gamma': 0.2}
New fit result at q_0.6:
aD 162.022131
aD_err 2.187066
aL 0.010001
aL_err 2.227643
cst_bgd 0.324623
cst_bgd_err 0.555146
center -0.003586
center_err 43.514908
gamma 0.152750
gamma_err 125.515161
red_chi_squared 1.782579
Name: q_0.6, dtype: float64
Previous initial values: {'T': 350, 'aD': 1, 'aL': 40, 'cst_bgd': 0.04, 'center': -1e-07, 'gamma': 0.1}
Previous fit result at q_0.8:
aD 1.406006e+02
aD_err 0.000000e+00
aL 9.428958e+01
aL_err 0.000000e+00
cst_bgd 1.292243e-09
cst_bgd_err 0.000000e+00
center -5.377085e-10
center_err 0.000000e+00
gamma 1.000000e-02
gamma_err 0.000000e+00
red_chi_squared 2.685054e-01
Name: q_0.8, dtype: float64
==================================================
New initial values: {'T': 350, 'aD': 2, 'aL': 20, 'cst_bgd': 1, 'center': -1e-07, 'gamma': 0.2}
New fit result at q_0.8:
aD 1.406006e+02
aD_err 0.000000e+00
aL 9.428956e+01
aL_err 0.000000e+00
cst_bgd 6.193712e-11
cst_bgd_err 0.000000e+00
center -6.281897e-10
center_err 0.000000e+00
gamma 1.000000e-02
gamma_err 0.000000e+00
red_chi_squared 2.685054e-01
Name: q_0.8, dtype: float64
If the new fitting results are better than the old ones, the dictionary containing the fitted parameters can be changed using the following method.
[19]:
for item in redo_q_keys:
dict_ref_params['350K'].loc[item,:] = data_frame_selected_qs.loc[item,:]
Fitting at T = 450K
[20]:
ini_vals_450K = {'T': 450,
'aD': 2,
'aL': 20,
'cst_bgd': 0.01,
'center': -1e-7,
'gamma': 0.5}
fit450 = fit_S_meas_all_q(ini_vals_450K)
/tmp/ipykernel_1950/3601744967.py:65: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`). Consider using `matplotlib.pyplot.close()`.
fig1, ax1 = plt.subplots()
[21]:
for key in fit450.keys():
print(fit450[key].params['gamma'].value)
0.2993277049065741
0.010000000067557524
0.010000000162895706
0.02255181713742438
0.20277187557712328
0.05329829058595026
0.04997755395595749
0.09754213986639626
0.10001211628251294
[22]:
for item in fit450.keys():
print(f'----------\nResult of fit for {item}:\n',
fit450[item].fit_report())
----------
Result of fit for q_0.6:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 187
# data points = 34
# variables = 5
chi-square = 43.7914165
reduced chi-square = 1.51004884
Akaike info crit = 18.6046283
Bayesian info crit = 26.2364309
R-squared = 0.95312794
[[Variables]]
T: 450 (fixed)
aD: 158.677519 +/- 4.73805081 (2.99%) (init = 2)
aL: 3.70476658 +/- 3.04405310 (82.17%) (init = 20)
cst_bgd: 8.6099e-05 +/- 1.27204820 (1477431.19%) (init = 0.01)
center: -1.0256e-08 +/- 0.06987671 (681320801.02%) (init = -1e-07)
gamma: 0.29932770 +/- 1.10032650 (367.60%) (init = 0.5)
[[Correlations]] (unreported correlations are < 0.100)
C(aD, gamma) = 0.918
C(cst_bgd, gamma) = -0.917
C(aD, cst_bgd) = -0.746
C(aD, aL) = -0.405
C(aL, cst_bgd) = -0.237
C(aL, center) = 0.185
C(aL, gamma) = -0.140
C(aD, center) = -0.113
----------
Result of fit for q_0.8:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 546
# data points = 34
# variables = 5
chi-square = 15.1673664
reduced chi-square = 0.52301263
Akaike info crit = -17.4452881
Bayesian info crit = -9.81348546
R-squared = 0.98294157
## Warning: uncertainties could not be estimated:
gamma: at boundary
[[Variables]]
T: 450 (fixed)
aD: 134.276380 (init = 2)
aL: 112.589524 (init = 20)
cst_bgd: 0.24954321 (init = 0.01)
center: -6.9180e-09 (init = -1e-07)
gamma: 0.01000000 (init = 0.5)
----------
Result of fit for q_1.0:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 3009
# data points = 34
# variables = 5
chi-square = 34.3359012
reduced chi-square = 1.18399659
Akaike info crit = 10.3342528
Bayesian info crit = 17.9660555
R-squared = 0.96183671
## Warning: uncertainties could not be estimated:
cst_bgd: at boundary
gamma: at boundary
[[Variables]]
T: 450 (fixed)
aD: 121.460581 (init = 2)
aL: 197.409880 (init = 20)
cst_bgd: 1.0383e-10 (init = 0.01)
center: -3.9375e-09 (init = -1e-07)
gamma: 0.01000000 (init = 0.5)
----------
Result of fit for q_1.2:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 434
# data points = 34
# variables = 5
chi-square = 14.7052511
reduced chi-square = 0.50707763
Akaike info crit = -18.4972997
Bayesian info crit = -10.8654971
R-squared = 0.98280484
## Warning: uncertainties could not be estimated:
[[Variables]]
T: 450 (fixed)
aD: 114.323599 (init = 2)
aL: 106.909694 (init = 20)
cst_bgd: 0.07078031 (init = 0.01)
center: -2.8608e-09 (init = -1e-07)
gamma: 0.02255182 (init = 0.5)
----------
Result of fit for q_1.7:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 129
# data points = 34
# variables = 5
chi-square = 17.6298751
reduced chi-square = 0.60792673
Akaike info crit = -12.3300307
Bayesian info crit = -4.69822812
R-squared = 0.97704487
[[Variables]]
T: 450 (fixed)
aD: 135.993697 +/- 5.13273875 (3.77%) (init = 2)
aL: 18.5453410 +/- 4.93325581 (26.60%) (init = 20)
cst_bgd: 0.74049209 +/- 0.59224950 (79.98%) (init = 0.01)
center: -1.1185e-08 +/- 0.01776411 (158816260.16%) (init = -1e-07)
gamma: 0.20277188 +/- 0.12636601 (62.32%) (init = 0.5)
[[Correlations]] (unreported correlations are < 0.100)
C(aD, gamma) = 0.957
C(aD, aL) = -0.954
C(aL, gamma) = -0.880
C(cst_bgd, gamma) = -0.850
C(aD, cst_bgd) = -0.707
C(aL, center) = -0.614
C(aD, center) = 0.549
C(aL, cst_bgd) = 0.519
C(center, gamma) = 0.506
C(cst_bgd, center) = -0.251
----------
Result of fit for q_1.9:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 472
# data points = 34
# variables = 5
chi-square = 11.9184640
reduced chi-square = 0.41098152
Akaike info crit = -25.6412388
Bayesian info crit = -18.0094362
R-squared = 0.98411107
## Warning: uncertainties could not be estimated:
[[Variables]]
T: 450 (fixed)
aD: 110.809424 (init = 2)
aL: 55.5261452 (init = 20)
cst_bgd: 1.05991021 (init = 0.01)
center: -5.2051e-09 (init = -1e-07)
gamma: 0.05329829 (init = 0.5)
----------
Result of fit for q_2.3:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 384
# data points = 34
# variables = 5
chi-square = 14.4682817
reduced chi-square = 0.49890627
Akaike info crit = -19.0496592
Bayesian info crit = -11.4178566
R-squared = 0.97918965
## Warning: uncertainties could not be estimated:
[[Variables]]
T: 450 (fixed)
aD: 99.8529875 (init = 2)
aL: 72.1356688 (init = 20)
cst_bgd: 0.99903951 (init = 0.01)
center: -1.4892e-09 (init = -1e-07)
gamma: 0.04997755 (init = 0.5)
----------
Result of fit for q_3.5:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 485
# data points = 34
# variables = 5
chi-square = 13.2723296
reduced chi-square = 0.45766654
Akaike info crit = -21.9830907
Bayesian info crit = -14.3512880
R-squared = 0.97573346
## Warning: uncertainties could not be estimated:
[[Variables]]
T: 450 (fixed)
aD: 99.3803260 (init = 2)
aL: 40.2196736 (init = 20)
cst_bgd: 1.56052431 (init = 0.01)
center: -3.6556e-09 (init = -1e-07)
gamma: 0.09754214 (init = 0.5)
----------
Result of fit for q_3.9:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 82
# data points = 34
# variables = 5
chi-square = 8.87675892
reduced chi-square = 0.30609514
Akaike info crit = -35.6594167
Bayesian info crit = -28.0276141
R-squared = 0.98261423
[[Variables]]
T: 450 (fixed)
aD: 98.0932671 +/- 7.27546336 (7.42%) (init = 2)
aL: 36.0073800 +/- 10.5143041 (29.20%) (init = 20)
cst_bgd: 1.44590678 +/- 0.24645269 (17.04%) (init = 0.01)
center: -0.00544586 +/- 0.00690306 (126.76%) (init = -1e-07)
gamma: 0.10001212 +/- 0.04095525 (40.95%) (init = 0.5)
[[Correlations]] (unreported correlations are < 0.100)
C(aD, aL) = -0.998
C(aD, gamma) = 0.984
C(aL, gamma) = -0.983
C(aD, center) = 0.828
C(aL, center) = -0.827
C(center, gamma) = 0.811
C(cst_bgd, gamma) = -0.718
C(aD, cst_bgd) = -0.611
C(aL, cst_bgd) = 0.597
C(cst_bgd, center) = -0.452
Storing fitted parameters
[23]:
dict_ref_params['450K'] = dict_ref_params_for_a_temperature(fit450)
dict_ref_params['450K']
[23]:
| aD | aD_err | aL | aL_err | cst_bgd | cst_bgd_err | center | center_err | gamma | gamma_err | red_chi_squared | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| q_0.6 | 158.677519 | 4.738051 | 3.704767 | 3.044053 | 8.609864e-05 | 1.272048 | -1.025607e-08 | 0.069877 | 0.299328 | 1.100326 | 1.510049 |
| q_0.8 | 134.276380 | 0.000000 | 112.589524 | 0.000000 | 2.495432e-01 | 0.000000 | -6.918045e-09 | 0.000000 | 0.010000 | 0.000000 | 0.523013 |
| q_1.0 | 121.460581 | 0.000000 | 197.409880 | 0.000000 | 1.038298e-10 | 0.000000 | -3.937475e-09 | 0.000000 | 0.010000 | 0.000000 | 1.183997 |
| q_1.2 | 114.323599 | 0.000000 | 106.909694 | 0.000000 | 7.078031e-02 | 0.000000 | -2.860767e-09 | 0.000000 | 0.022552 | 0.000000 | 0.507078 |
| q_1.7 | 135.993697 | 5.132739 | 18.545341 | 4.933256 | 7.404921e-01 | 0.592250 | -1.118532e-08 | 0.017764 | 0.202772 | 0.126366 | 0.607927 |
| q_1.9 | 110.809424 | 0.000000 | 55.526145 | 0.000000 | 1.059910e+00 | 0.000000 | -5.205118e-09 | 0.000000 | 0.053298 | 0.000000 | 0.410982 |
| q_2.3 | 99.852988 | 0.000000 | 72.135669 | 0.000000 | 9.990395e-01 | 0.000000 | -1.489175e-09 | 0.000000 | 0.049978 | 0.000000 | 0.498906 |
| q_3.5 | 99.380326 | 0.000000 | 40.219674 | 0.000000 | 1.560524e+00 | 0.000000 | -3.655621e-09 | 0.000000 | 0.097542 | 0.000000 | 0.457667 |
| q_3.9 | 98.093267 | 7.275463 | 36.007380 | 10.514304 | 1.445907e+00 | 0.246453 | -5.445864e-03 | 0.006903 | 0.100012 | 0.040955 | 0.306095 |
Plotting \(\frac{a_D}{a_D+a_L}\) and \(\frac{a_L}{a_D+a_L}\) at 450K
[24]:
plot_ratio_coefficients(dict_ref_params['450K'])
Fitting at T = 540K
[25]:
ini_vals_540K = {'T': 540,
'aD': 2,
'aL': 20, #10
'cst_bgd': 0.01,
'center': -1e-7,
'gamma': 0.4}
fit540 = fit_S_meas_all_q(ini_vals_540K)
[26]:
for item in fit540.keys():
print(f'----------\nResult of fit for {item}:\n',
fit540[item].fit_report())
----------
Result of fit for q_0.6:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 207
# data points = 34
# variables = 5
chi-square = 40.0521297
reduced chi-square = 1.38110792
Akaike info crit = 15.5699250
Bayesian info crit = 23.2017277
R-squared = 0.95629801
[[Variables]]
T: 540 (fixed)
aD: 158.547645 +/- 3.31754022 (2.09%) (init = 2)
aL: 1.13586531 +/- 6.28228601 (553.08%) (init = 20)
cst_bgd: 0.90628707 +/- 2.09175202 (230.80%) (init = 0.01)
center: -6.8205e-08 +/- 0.14557907 (213444758.97%) (init = -1e-07)
gamma: 0.42871318 +/- 5.40344561 (1260.39%) (init = 0.4)
[[Correlations]] (unreported correlations are < 0.100)
C(aL, cst_bgd) = -0.969
C(cst_bgd, gamma) = -0.955
C(aD, gamma) = 0.871
C(aL, gamma) = 0.869
C(aD, cst_bgd) = -0.756
C(aD, aL) = 0.610
C(center, gamma) = 0.163
C(cst_bgd, center) = -0.107
----------
Result of fit for q_0.8:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 260
# data points = 34
# variables = 5
chi-square = 19.4101642
reduced chi-square = 0.66931601
Akaike info crit = -9.05916462
Bayesian info crit = -1.42736200
R-squared = 0.97748690
[[Variables]]
T: 540 (fixed)
aD: 152.158615 +/- 3.96264939 (2.60%) (init = 2)
aL: 6.91754542 +/- 8.19579624 (118.48%) (init = 20)
cst_bgd: 0.33482953 +/- 2.72626626 (814.23%) (init = 0.01)
center: -7.3475e-09 +/- 0.04693234 (638749373.36%) (init = -1e-07)
gamma: 0.42587342 +/- 1.11870240 (262.68%) (init = 0.4)
[[Correlations]] (unreported correlations are < 0.100)
C(aL, cst_bgd) = -0.974
C(cst_bgd, gamma) = -0.952
C(aD, gamma) = 0.902
C(aL, gamma) = 0.873
C(aD, cst_bgd) = -0.777
C(aD, aL) = 0.643
C(aD, center) = 0.434
C(center, gamma) = 0.421
C(cst_bgd, center) = -0.294
C(aL, center) = 0.225
----------
Result of fit for q_1.0:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 490
# data points = 34
# variables = 5
chi-square = 20.8968702
reduced chi-square = 0.72058173
Akaike info crit = -6.54987834
Bayesian info crit = 1.08192428
R-squared = 0.97494468
## Warning: uncertainties could not be estimated:
gamma: at boundary
[[Variables]]
T: 540 (fixed)
aD: 114.190594 (init = 2)
aL: 205.967553 (init = 20)
cst_bgd: 0.92020046 (init = 0.01)
center: -1.3638e-09 (init = -1e-07)
gamma: 0.01000000 (init = 0.4)
----------
Result of fit for q_1.2:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 448
# data points = 34
# variables = 5
chi-square = 15.3307995
reduced chi-square = 0.52864826
Akaike info crit = -17.0808872
Bayesian info crit = -9.44908461
R-squared = 0.98123665
## Warning: uncertainties could not be estimated:
[[Variables]]
T: 540 (fixed)
aD: 103.745406 (init = 2)
aL: 123.363272 (init = 20)
cst_bgd: 0.89614028 (init = 0.01)
center: -2.2194e-09 (init = -1e-07)
gamma: 0.02339889 (init = 0.4)
----------
Result of fit for q_1.7:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 151
# data points = 34
# variables = 5
chi-square = 11.9950215
reduced chi-square = 0.41362143
Akaike info crit = -25.4235403
Bayesian info crit = -17.7917377
R-squared = 0.98229696
[[Variables]]
T: 540 (fixed)
aD: 121.896291 +/- 4.26929006 (3.50%) (init = 2)
aL: 31.8858848 +/- 3.58005066 (11.23%) (init = 20)
cst_bgd: 0.46858781 +/- 0.60929435 (130.03%) (init = 0.01)
center: -0.00552346 +/- 0.00793701 (143.70%) (init = -1e-07)
gamma: 0.21309504 +/- 0.06871882 (32.25%) (init = 0.4)
[[Correlations]] (unreported correlations are < 0.100)
C(aD, gamma) = 0.961
C(aD, aL) = -0.936
C(cst_bgd, gamma) = -0.876
C(aL, gamma) = -0.851
C(aD, cst_bgd) = -0.751
C(aL, cst_bgd) = 0.519
C(aD, center) = 0.446
C(aL, center) = -0.440
C(center, gamma) = 0.433
C(cst_bgd, center) = -0.253
----------
Result of fit for q_1.9:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 392
# data points = 34
# variables = 5
chi-square = 17.2774862
reduced chi-square = 0.59577539
Akaike info crit = -13.0165123
Bayesian info crit = -5.38470971
R-squared = 0.97324611
## Warning: uncertainties could not be estimated:
[[Variables]]
T: 540 (fixed)
aD: 84.2325105 (init = 2)
aL: 94.6015439 (init = 20)
cst_bgd: 2.31440952 (init = 0.01)
center: -3.3465e-09 (init = -1e-07)
gamma: 0.04122589 (init = 0.4)
----------
Result of fit for q_2.3:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 145
# data points = 34
# variables = 5
chi-square = 12.0183987
reduced chi-square = 0.41442754
Akaike info crit = -25.3573419
Bayesian info crit = -17.7255393
R-squared = 0.97930081
[[Variables]]
T: 540 (fixed)
aD: 63.0237050 +/- 32.8521185 (52.13%) (init = 2)
aL: 129.646254 +/- 117.148004 (90.36%) (init = 20)
cst_bgd: 2.26345187 +/- 0.27127280 (11.98%) (init = 0.01)
center: -0.00924788 +/- 0.00569512 (61.58%) (init = -1e-07)
gamma: 0.03691462 +/- 0.03594815 (97.38%) (init = 0.4)
[[Correlations]] (unreported correlations are < 0.100)
C(aL, gamma) = -0.999
C(aD, aL) = -0.998
C(aD, gamma) = 0.994
C(aD, center) = 0.955
C(aL, center) = -0.946
C(center, gamma) = 0.941
C(cst_bgd, gamma) = -0.570
C(aL, cst_bgd) = 0.534
C(aD, cst_bgd) = -0.496
C(cst_bgd, center) = -0.439
----------
Result of fit for q_3.5:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 78
# data points = 34
# variables = 5
chi-square = 13.4329791
reduced chi-square = 0.46320617
Akaike info crit = -21.5740224
Bayesian info crit = -13.9422197
R-squared = 0.96915486
[[Variables]]
T: 540 (fixed)
aD: 85.5216563 +/- 7.18528936 (8.40%) (init = 2)
aL: 44.0400079 +/- 9.27356864 (21.06%) (init = 20)
cst_bgd: 2.40985757 +/- 0.36477943 (15.14%) (init = 0.01)
center: -8.4728e-04 +/- 0.00745222 (879.55%) (init = -1e-07)
gamma: 0.12317551 +/- 0.04126871 (33.50%) (init = 0.4)
[[Correlations]] (unreported correlations are < 0.100)
C(aD, aL) = -0.995
C(aD, gamma) = 0.978
C(aL, gamma) = -0.969
C(aD, center) = 0.817
C(aL, center) = -0.817
C(center, gamma) = 0.795
C(cst_bgd, gamma) = -0.743
C(aD, cst_bgd) = -0.620
C(aL, cst_bgd) = 0.576
C(cst_bgd, center) = -0.444
----------
Result of fit for q_3.9:
[[Model]]
(Model(irf_gate) <function convolve at 0x7fe9b0304670> Model(S_meas_no_convol))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 108
# data points = 34
# variables = 5
chi-square = 11.8142365
reduced chi-square = 0.40738746
Akaike info crit = -25.9398782
Bayesian info crit = -18.3080756
R-squared = 0.97144293
[[Variables]]
T: 540 (fixed)
aD: 84.9276971 +/- 8.52714225 (10.04%) (init = 2)
aL: 40.8223414 +/- 10.4848622 (25.68%) (init = 20)
cst_bgd: 1.91641835 +/- 0.45973725 (23.99%) (init = 0.01)
center: -0.01962833 +/- 0.00441652 (22.50%) (init = -1e-07)
gamma: 0.12484801 +/- 0.05359118 (42.93%) (init = 0.4)
[[Correlations]] (unreported correlations are < 0.100)
C(aD, aL) = -0.997
C(aD, gamma) = 0.987
C(aL, gamma) = -0.981
C(cst_bgd, gamma) = -0.864
C(aD, cst_bgd) = -0.794
C(aL, cst_bgd) = 0.763
C(aD, center) = 0.359
C(aL, center) = -0.352
C(center, gamma) = 0.347
C(cst_bgd, center) = -0.224
Storing fitted parameters
[27]:
dict_ref_params['540K'] = dict_ref_params_for_a_temperature(fit540)
dict_ref_params['540K']
[27]:
| aD | aD_err | aL | aL_err | cst_bgd | cst_bgd_err | center | center_err | gamma | gamma_err | red_chi_squared | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| q_0.6 | 158.547645 | 3.317540 | 1.135865 | 6.282286 | 0.906287 | 2.091752 | -6.820457e-08 | 0.145579 | 0.428713 | 5.403446 | 1.381108 |
| q_0.8 | 152.158615 | 3.962649 | 6.917545 | 8.195796 | 0.334830 | 2.726266 | -7.347535e-09 | 0.046932 | 0.425873 | 1.118702 | 0.669316 |
| q_1.0 | 114.190594 | 0.000000 | 205.967553 | 0.000000 | 0.920200 | 0.000000 | -1.363848e-09 | 0.000000 | 0.010000 | 0.000000 | 0.720582 |
| q_1.2 | 103.745406 | 0.000000 | 123.363272 | 0.000000 | 0.896140 | 0.000000 | -2.219353e-09 | 0.000000 | 0.023399 | 0.000000 | 0.528648 |
| q_1.7 | 121.896291 | 4.269290 | 31.885885 | 3.580051 | 0.468588 | 0.609294 | -5.523458e-03 | 0.007937 | 0.213095 | 0.068719 | 0.413621 |
| q_1.9 | 84.232511 | 0.000000 | 94.601544 | 0.000000 | 2.314410 | 0.000000 | -3.346523e-09 | 0.000000 | 0.041226 | 0.000000 | 0.595775 |
| q_2.3 | 63.023705 | 32.852118 | 129.646254 | 117.148004 | 2.263452 | 0.271273 | -9.247881e-03 | 0.005695 | 0.036915 | 0.035948 | 0.414428 |
| q_3.5 | 85.521656 | 7.185289 | 44.040008 | 9.273569 | 2.409858 | 0.364779 | -8.472765e-04 | 0.007452 | 0.123176 | 0.041269 | 0.463206 |
| q_3.9 | 84.927697 | 8.527142 | 40.822341 | 10.484862 | 1.916418 | 0.459737 | -1.962833e-02 | 0.004417 | 0.124848 | 0.053591 | 0.407387 |
Plotting \(\frac{a_D}{a_D+a_L}\) and \(\frac{a_L}{a_D+a_L}\) at 540K
[28]:
plot_ratio_coefficients(dict_ref_params['540K'])
Plotting ratio of coefficients for all temperatures
[29]:
# Define errors for each ratio
std_err_ratio_350K = np.sqrt((dict_ref_params['350K']['aD'].values**2 * dict_ref_params['350K']['aL_err'].values**2
+ dict_ref_params['350K']['aL'].values**2 * dict_ref_params['350K']['aD_err'].values**2)
/ (dict_ref_params['350K']['aD'].values + dict_ref_params['350K']['aL'].values)**4)
std_err_ratio_450K = np.sqrt((dict_ref_params['450K']['aD'].values**2 * dict_ref_params['450K']['aL_err'].values**2
+ dict_ref_params['450K']['aL'].values**2 * dict_ref_params['450K']['aD_err'].values**2)
/ (dict_ref_params['450K']['aD'].values + dict_ref_params['450K']['aL'].values)**4)
std_err_ratio_540K = np.sqrt((dict_ref_params['540K']['aD'].values**2 * dict_ref_params['540K']['aL_err'].values**2
+ dict_ref_params['540K']['aL'].values**2 * dict_ref_params['540K']['aD_err'].values**2)
/ (dict_ref_params['540K']['aD'].values + dict_ref_params['540K']['aL'].values)**4)
[30]:
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(8, 4))
ax[0].errorbar(dict_ref_params['350K'].index,
dict_ref_params['350K']['aD'].values / (dict_ref_params['350K']['aD'].values + dict_ref_params['350K']['aL'].values),
std_err_ratio_350K,
label='350K',
marker='o',
linestyle='--')
ax[0].errorbar(dict_ref_params['450K'].index,
dict_ref_params['450K']['aD'].values / (dict_ref_params['450K']['aD'].values + dict_ref_params['450K']['aL'].values),
std_err_ratio_450K,
label='450K',
marker='x',
linestyle='--')
ax[0].errorbar(dict_ref_params['540K'].index,
dict_ref_params['540K']['aD'].values / (dict_ref_params['540K']['aD'].values + dict_ref_params['540K']['aL'].values),
std_err_ratio_540K,
label='540K',
marker='+',
linestyle='--')
ax[0].set_ylabel('$a_D/(a_D+a_L)$')
ax[0].set_ylim((0, 1))
ax[1].errorbar(dict_ref_params['350K'].index,
dict_ref_params['350K']['aL'].values / (dict_ref_params['350K']['aD'].values + dict_ref_params['350K']['aL'].values),
std_err_ratio_350K,
label='350K',
marker='o',
linestyle='--')
ax[1].errorbar(dict_ref_params['450K'].index,
dict_ref_params['450K']['aL'].values / (dict_ref_params['450K']['aD'].values + dict_ref_params['450K']['aL'].values),
std_err_ratio_450K,
label='450K',
marker='x',
linestyle='--')
ax[1].errorbar(dict_ref_params['540K'].index,
dict_ref_params['540K']['aL'].values / (dict_ref_params['540K']['aD'].values + dict_ref_params['540K']['aL'].values),
std_err_ratio_540K,
label='540K',
marker='+',
linestyle='--')
ax[1].set_ylabel('$a_L/(a_D+a_L$)')
ax[1].set_ylim((0, 0.5))
for i in range(2):
ax[i].grid()
ax[i].legend()
ax[i].set_xlabel(r'$Q (1/\AA)$')
for tick in ax[i].get_xticklabels():
tick.set_rotation(45)
fig.tight_layout()
plt.show()
Checking Q-dependence of \(\Gamma\) (width of Lorentzian)
[31]:
temperaturesK = [350, 450, 540]
fig = plt.figure()
ax = fig.add_subplot()
# T = 350K
scat0 = ax.scatter(
temperaturesK[0] * np.ones(len(q_tof)),
q_tof,
label='350K',
c=dict_ref_params['350K']['gamma'].values)
for i, txt in enumerate(dict_ref_params['350K']['gamma'].values):
ax.annotate(f"$\Gamma=${txt:.2f}",
(temperaturesK[0] * 1.01,
q_tof[i]))
# T = 450K
ax.scatter(
temperaturesK[1] * np.ones(len(q_tof)),
q_tof,
c=dict_ref_params['450K']['gamma'].values,
label='450K')
for i, txt in enumerate(dict_ref_params['450K']['gamma'].values):
ax.annotate(f"$\Gamma=${txt:.2f}",
(temperaturesK[1] * 1.01,
q_tof[i]))
# T = 540K
ax.scatter(
temperaturesK[2] * np.ones(len(q_tof)),
q_tof,
c=dict_ref_params['540K']['gamma'].values,
label='540K')
for i, txt in enumerate(dict_ref_params['540K']['gamma'].values):
ax.annotate(f"$\Gamma=${txt:.2f}",
(temperaturesK[2] * 1.01,
q_tof[i]))
ax.set_xlim((340, 580))
ax.grid()
ax.set_xlabel('T (K)')
ax.set_ylabel('q ($\AA^{-1}$)')
fig.colorbar(scat0, label=r'$\Gamma$')
plt.show()
\(\Gamma\) shows some \(q\)-dependences.
[ ]: