From 033753294cd7652bc8887e3cd856031b8b346525 Mon Sep 17 00:00:00 2001 From: Hugo Karas Date: Fri, 11 Aug 2023 11:52:03 +0200 Subject: [PATCH 1/6] Add basic RIDME example --- examples/basic/ex_fitting_ridme.py | 86 +++++++++++++++++++++++++++++ examples/data/example_ridme_1.DSC | 24 ++++++++ examples/data/example_ridme_1.DTA | Bin 0 -> 8640 bytes 3 files changed, 110 insertions(+) create mode 100644 examples/basic/ex_fitting_ridme.py create mode 100644 examples/data/example_ridme_1.DSC create mode 100644 examples/data/example_ridme_1.DTA diff --git a/examples/basic/ex_fitting_ridme.py b/examples/basic/ex_fitting_ridme.py new file mode 100644 index 00000000..0072e21d --- /dev/null +++ b/examples/basic/ex_fitting_ridme.py @@ -0,0 +1,86 @@ +# %% [markdown] +""" +Basic analysis of a RIDME signal +------------------------------------------------------------------------- + +Fit a simple RIDME signal with a model with a non-parametric +distribution and a stretched exponetial background, using Tikhonov regularization. +""" + +import numpy as np +import matplotlib.pyplot as plt +import deerlab as dl + + +# %% + +# File location +path = '../data/' +file = 'example_ridme_1.DTA' + +# Experimental parameters +tau1 = 0.4 # First inter-pulse delay, μs +tau2 = 4.2 # Second inter-pulse delay, μs +tmin = 0.28 # Acquisition deadtime, μs + +# Load the experimental data +t,Vexp = dl.deerload(path + file) + +# Pre-processing +Vexp = dl.correctphase(Vexp) # Phase correction +Vexp = Vexp/np.max(Vexp) # Rescaling (aesthetic) +t = t - t[0] # Account for zerotime +t = t + tmin + +# Distance vector +r = np.linspace(1.5,6,50) # nm + +# Construct the model +experimentmodel = dl.ex_ridme(tau1,tau2, pathways=[1]) +Vmodel = dl.dipolarmodel(t,r,Bmodel=dl.bg_strexp, experiment =experimentmodel) + +# Fit the model to the data +results = dl.fit(Vmodel,Vexp) + +# Print results summary +print(results) + +#%% + +# Extract fitted dipolar signal +Vfit = results.model + +# Extract fitted distance distribution +Pfit = results.P +Pci95 = results.PUncert.ci(95) +Pci50 = results.PUncert.ci(50) + +# Extract the unmodulated contribution +Bfcn = lambda mod,decay,stretch,reftime: results.P_scale*(1-mod)*dl.bg_strexp(t-reftime,decay,stretch) +Bfit = results.evaluate(Bfcn) +Bci = results.propagate(Bfcn).ci(95) + +plt.figure(figsize=[6,7]) +violet = '#4550e6' +plt.subplot(211) +# Plot experimental and fitted data +plt.plot(t,Vexp,'.',color='grey',label='Data') +plt.plot(t,Vfit,linewidth=3,color=violet,label='Fit') +plt.plot(t,Bfit,'--',linewidth=3,color=violet,label='Unmodulated contribution') +plt.fill_between(t,Bci[:,0],Bci[:,1],color=violet,alpha=0.3) +plt.legend(frameon=False,loc='best') +plt.xlabel('Time $t$ (μs)') +plt.ylabel('$V(t)$ (arb.u.)') +# Plot the distance distribution +plt.subplot(212) +plt.plot(r,Pfit,color=violet,linewidth=3,label='Fit') +plt.fill_between(r,Pci95[:,0],Pci95[:,1],alpha=0.3,color=violet,label='95%-Conf. Inter.',linewidth=0) +plt.fill_between(r,Pci50[:,0],Pci50[:,1],alpha=0.5,color=violet,label='50%-Conf. Inter.',linewidth=0) +plt.legend(frameon=False,loc='best') +plt.autoscale(enable=True, axis='both', tight=True) +plt.xlabel('Distance $r$ (nm)') +plt.ylabel('$P(r)$ (nm$^{-1}$)') +plt.tight_layout() +plt.show() + +# %% diff --git a/examples/data/example_ridme_1.DSC b/examples/data/example_ridme_1.DSC new file mode 100644 index 00000000..4429c2a4 --- /dev/null +++ b/examples/data/example_ridme_1.DSC @@ -0,0 +1,24 @@ +* Exported from Python using EasySpin, 2023-08-11 11:44:41 +#DESC 1.2 * DESCRIPTOR INFORMATION *********************** +DSRC MAN +BSEQ LIT +IKKF CPLX +IRFMT D +IIFMT D +XTYP IDX +YTYP NODATA +ZTYP NODATA +XPTS 540 +XMIN 280.0 +XWID 4312.000000000004 +* +************************************************************ +* +#SPL 1.2 * STANDARD PARAMETER LAYER +OPER +DATE 11/08/23 +TIME 11:44:41 +CMNT +SAMP +SFOR +MWFQ 3.405e+10 diff --git a/examples/data/example_ridme_1.DTA b/examples/data/example_ridme_1.DTA new file mode 100644 index 0000000000000000000000000000000000000000..102871cb71377bc8fc536afd02be05cd0d516a6a GIT binary patch literal 8640 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 Date: Fri, 11 Aug 2023 12:01:09 +0200 Subject: [PATCH 2/6] Change from deadtime to tmin --- examples/advanced/ex_comparing_uncertainties.py | 5 +++-- examples/advanced/ex_dipolarpathways_selection.py | 6 +++--- .../advanced/ex_extracting_gauss_constraints.py | 5 +++-- examples/advanced/ex_forcefield_fit.py | 5 +++-- examples/advanced/ex_global_twostates_parametric.py | 11 ++++++----- examples/advanced/ex_identifiability_analysis.py | 5 +++-- examples/advanced/ex_multigauss_fitting_4pdeer.py | 9 +++++---- examples/advanced/ex_profileanalysis.py | 5 +++-- examples/basic/ex_bootstrapping.py | 5 +++-- examples/basic/ex_fitting_4pdeer.py | 6 +++--- examples/basic/ex_fitting_4pdeer_compactness.py | 5 +++-- examples/basic/ex_fitting_4pdeer_gauss.py | 5 +++-- examples/basic/ex_fitting_5pdeer.py | 13 +++++++------ .../intermediate/ex_compactness_with_without.py | 5 +++-- examples/intermediate/ex_crossing_echoes_masking.py | 6 +++--- examples/intermediate/ex_fitting_4pdeer_pathways.py | 6 +++--- examples/intermediate/ex_fitting_5pdeer_pathways.py | 7 ++++--- examples/intermediate/ex_fitting_sparse_4pdeer.py | 5 +++-- examples/intermediate/ex_global_different_deer.py | 12 ++++++++---- examples/intermediate/ex_global_fitting_4pdeer.py | 7 ++++--- examples/intermediate/ex_multipathway_validation.py | 4 ++-- examples/intermediate/ex_selregparam.py | 5 +++-- 22 files changed, 81 insertions(+), 61 deletions(-) diff --git a/examples/advanced/ex_comparing_uncertainties.py b/examples/advanced/ex_comparing_uncertainties.py index 0d0ffd8e..1120456a 100644 --- a/examples/advanced/ex_comparing_uncertainties.py +++ b/examples/advanced/ex_comparing_uncertainties.py @@ -27,7 +27,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -deadtime = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Acquisition deadtime, μs # Load the experimental data t,Vexp = dl.deerload(path + file) @@ -35,7 +35,8 @@ # Pre-processing Vexp = dl.correctphase(Vexp) # Phase correction Vexp = Vexp/np.max(Vexp) # Rescaling (aesthetic) -t = t + deadtime # Account for deadtime +t = t - t[0] # Account for zerotime +t = t + tmin # Distance vector r = np.arange(2,6,0.05) # nm diff --git a/examples/advanced/ex_dipolarpathways_selection.py b/examples/advanced/ex_dipolarpathways_selection.py index 95b42182..066b9e20 100644 --- a/examples/advanced/ex_dipolarpathways_selection.py +++ b/examples/advanced/ex_dipolarpathways_selection.py @@ -25,7 +25,7 @@ # Experimental parameters tau1 = 0.5 # First inter-pulse delay, μs tau2 = 3.5 # Second inter-pulse delay, μs -deadtime = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Acquisition deadtime, μs # Load the experimental data t,Vexp = dl.deerload(path + file) @@ -33,8 +33,8 @@ # Pre-processing Vexp = dl.correctphase(Vexp) # Phase correction Vexp = Vexp/np.max(Vexp) # Rescaling (aesthetic) -t = t + deadtime # Account for deadtime - +t = t - t[0] # Account for zerotime +t = t + tmin # Construct the distance vector r = np.arange(2,5,0.05) diff --git a/examples/advanced/ex_extracting_gauss_constraints.py b/examples/advanced/ex_extracting_gauss_constraints.py index 87d94a5a..16c93df4 100644 --- a/examples/advanced/ex_extracting_gauss_constraints.py +++ b/examples/advanced/ex_extracting_gauss_constraints.py @@ -23,7 +23,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -deadtime = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Acquisition deadtime, μs # Load the experimental data t,Vexp = dl.deerload(path + file) @@ -31,7 +31,8 @@ # Pre-processing Vexp = dl.correctphase(Vexp) # Phase correction Vexp = Vexp/np.max(Vexp) # Rescaling (aesthetic) -t = t + deadtime # Account for deadtime +t = t - t[0] # Account for zerotime +t = t + tmin # Construct the dipolar signal model r = np.arange(2,6,0.02) diff --git a/examples/advanced/ex_forcefield_fit.py b/examples/advanced/ex_forcefield_fit.py index eae7bfb6..dfb8e11c 100644 --- a/examples/advanced/ex_forcefield_fit.py +++ b/examples/advanced/ex_forcefield_fit.py @@ -48,7 +48,7 @@ def forcefield_P(c0,c1,c2,c3): # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 5.0 # Second inter-pulse delay, μs -deadtime = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Acquisition deadtime, μs # Load the experimental data t,Vexp = dl.deerload(path + file) @@ -56,7 +56,8 @@ def forcefield_P(c0,c1,c2,c3): # Pre-processing Vexp = dl.correctphase(Vexp) # Phase correction Vexp = Vexp/np.max(Vexp) # Rescaling (aesthetic) -t = t + deadtime # Account for deadtime +t = t - t[0] # Account for zerotime +t = t + tmin # Construct the energy and distance distribution models forcefield_energymodel = dl.Model(forcefield_energy) diff --git a/examples/advanced/ex_global_twostates_parametric.py b/examples/advanced/ex_global_twostates_parametric.py index eb0b2726..a026e874 100644 --- a/examples/advanced/ex_global_twostates_parametric.py +++ b/examples/advanced/ex_global_twostates_parametric.py @@ -30,7 +30,7 @@ # Experimental parameters tau1 = 0.4 # First inter-pulse delay, μs tau2 = 4.5 # Second inter-pulse delay, μs -deadtime = 0.2 # Acquisition deadtime, μs +tmin = 0.2 # Acquisition deadtime, μs Vmodels, ts, Vexps = [], [], [] for file in files: @@ -39,10 +39,11 @@ t, Vexp = dl.deerload(path + file) # Pre-processing - Vexp = dl.correctphase(Vexp) # Phase correction - Vexp = Vexp / np.max(Vexp) # Rescaling (aesthetic) - t = t + deadtime # Account for deadtime - + Vexp = dl.correctphase(Vexp) # Phase correction + Vexp = Vexp / np.max(Vexp) # Rescaling (aesthetic) + t = t - t[0] # Account for zerotime + t = t + tmin + # Put the datasets into lists ts.append(t) Vexps.append(Vexp) diff --git a/examples/advanced/ex_identifiability_analysis.py b/examples/advanced/ex_identifiability_analysis.py index c874b47f..4e9c78bc 100644 --- a/examples/advanced/ex_identifiability_analysis.py +++ b/examples/advanced/ex_identifiability_analysis.py @@ -23,7 +23,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -deadtime = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Acquisition deadtime, μs # Load the experimental data t,Vexp = dl.deerload(path + file) @@ -31,7 +31,8 @@ # Pre-processing Vexp = dl.correctphase(Vexp) # Phase correction Vexp = Vexp/np.max(Vexp) # Rescaling (aesthetic) -t = t + deadtime # Account for deadtime +t = t - t[0] # Account for zerotime +t = t + tmin # Truncate the signal Vexp_truncated = Vexp[t<=2] diff --git a/examples/advanced/ex_multigauss_fitting_4pdeer.py b/examples/advanced/ex_multigauss_fitting_4pdeer.py index 073ea087..1d5bd458 100644 --- a/examples/advanced/ex_multigauss_fitting_4pdeer.py +++ b/examples/advanced/ex_multigauss_fitting_4pdeer.py @@ -24,15 +24,16 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -deadtime = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Acquisition deadtime, μs # Load the experimental data t, Vexp = dl.deerload(path + file) # Pre-processing -Vexp = dl.correctphase(Vexp) # Phase correction -Vexp = Vexp / np.max(Vexp) # Rescaling (aesthetic) -t = t + deadtime # Account for deadtime +Vexp = dl.correctphase(Vexp) # Phase correction +Vexp = Vexp / np.max(Vexp) # Rescaling (aesthetic) +t = t - t[0] # Account for zerotime +t = t + tmin # Maximal number of Gaussians in the models Nmax = 5 diff --git a/examples/advanced/ex_profileanalysis.py b/examples/advanced/ex_profileanalysis.py index b0469c4f..33b0d8b9 100644 --- a/examples/advanced/ex_profileanalysis.py +++ b/examples/advanced/ex_profileanalysis.py @@ -19,7 +19,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -deadtime = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Acquisition deadtime, μs # Load the experimental data t,Vexp = dl.deerload(path + file) @@ -27,7 +27,8 @@ # Pre-processing Vexp = dl.correctphase(Vexp) # Phase correction Vexp = Vexp/np.max(Vexp) # Rescaling (aesthetic) -t = t + deadtime # Account for deadtime +t = t - t[0] # Account for zerotime +t = t + tmin # Distance vector r = np.arange(2,5,0.05) # nm diff --git a/examples/basic/ex_bootstrapping.py b/examples/basic/ex_bootstrapping.py index ad921fc2..43378840 100644 --- a/examples/basic/ex_bootstrapping.py +++ b/examples/basic/ex_bootstrapping.py @@ -30,7 +30,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -deadtime = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Acquisition deadtime, μs # Load the experimental data t,Vexp = dl.deerload(path + file) @@ -38,7 +38,8 @@ # Pre-processing Vexp = dl.correctphase(Vexp) # Phase correction Vexp = Vexp/np.max(Vexp) # Rescaling (aesthetic) -t = t + deadtime # Account for deadtime +t = t - t[0] # Account for zerotime +t = t + tmin # Distance vector r = np.linspace(2,5,100) # nm diff --git a/examples/basic/ex_fitting_4pdeer.py b/examples/basic/ex_fitting_4pdeer.py index fb2791d6..dab16fa4 100644 --- a/examples/basic/ex_fitting_4pdeer.py +++ b/examples/basic/ex_fitting_4pdeer.py @@ -21,7 +21,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -deadtime = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Acquisition deadtime, μs # Load the experimental data t,Vexp = dl.deerload(path + file) @@ -29,8 +29,8 @@ # Pre-processing Vexp = dl.correctphase(Vexp) # Phase correction Vexp = Vexp/np.max(Vexp) # Rescaling (aesthetic) -t = t + deadtime # Account for deadtime - +t = t - t[0] # Account for zerotime +t = t + tmin # Distance vector r = np.arange(2.5,5,0.01) # nm diff --git a/examples/basic/ex_fitting_4pdeer_compactness.py b/examples/basic/ex_fitting_4pdeer_compactness.py index 488452c5..b9402b9a 100644 --- a/examples/basic/ex_fitting_4pdeer_compactness.py +++ b/examples/basic/ex_fitting_4pdeer_compactness.py @@ -23,7 +23,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -deadtime = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Acquisition deadtime, μs # Load the experimental data t,Vexp = dl.deerload(path + file) @@ -31,7 +31,8 @@ # Pre-processing Vexp = dl.correctphase(Vexp) # Phase correction Vexp = Vexp/np.max(Vexp) # Rescaling (aesthetic) -t = t + deadtime # Account for deadtime +t = t - t[0] # Account for zerotime +t = t + tmin # Distance vector r = np.arange(2,5,0.025) # nm diff --git a/examples/basic/ex_fitting_4pdeer_gauss.py b/examples/basic/ex_fitting_4pdeer_gauss.py index 67da3c42..69c76156 100644 --- a/examples/basic/ex_fitting_4pdeer_gauss.py +++ b/examples/basic/ex_fitting_4pdeer_gauss.py @@ -21,7 +21,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -deadtime = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Acquisition deadtime, μs # Load the experimental data t,Vexp = dl.deerload(path + file) @@ -29,7 +29,8 @@ # Pre-processing Vexp = dl.correctphase(Vexp) # Phase correction Vexp = Vexp/np.max(Vexp) # Rescaling (aesthetic) -t = t + deadtime # Account for deadtime +t = t - t[0] # Account for zerotime +t = t + tmin # Distance vector r = np.arange(1.5,6,0.01) # nm diff --git a/examples/basic/ex_fitting_5pdeer.py b/examples/basic/ex_fitting_5pdeer.py index 54a36e6b..d6023e28 100644 --- a/examples/basic/ex_fitting_5pdeer.py +++ b/examples/basic/ex_fitting_5pdeer.py @@ -29,16 +29,17 @@ file = 'example_5pdeer_1.DTA' # Experimental parameters (reversed 5pDEER) -tau1 = 3.9 # First inter-pulse delay, μs -tau2 = 3.7 # Second inter-pulse delay, μs -tau3 = 0.5 # Third inter-pulse delay, μs -deadtime = 0.3 # Acquisition deadtime, μs +tau1 = 3.9 # First inter-pulse delay, μs +tau2 = 3.7 # Second inter-pulse delay, μs +tau3 = 0.5 # Third inter-pulse delay, μs +tmin = 0.3 # Acquisition deadtime, μs # Load the experimental data t,Vexp = dl.deerload(path + file) Vexp = dl.correctphase(Vexp) # Phase correction -Vexp = Vexp/np.max(Vexp) # Rescaling (aesthetic) -t = t + deadtime # Account for deadtime +Vexp = Vexp/np.max(Vexp) # Rescaling (aesthetic) +t = t - t[0] # Account for zerotime +t = t + tmin # Distance vector r = np.arange(3,5,0.025) # nm diff --git a/examples/intermediate/ex_compactness_with_without.py b/examples/intermediate/ex_compactness_with_without.py index a8398878..a6c8a277 100644 --- a/examples/intermediate/ex_compactness_with_without.py +++ b/examples/intermediate/ex_compactness_with_without.py @@ -21,7 +21,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -deadtime = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Acquisition deadtime, μs # Load the experimental data t,Vexp = dl.deerload(path + file) @@ -29,7 +29,8 @@ # Pre-processing Vexp = dl.correctphase(Vexp) # Phase correction Vexp = Vexp/np.max(Vexp) # Rescaling (aesthetic) -t = t + deadtime # Account for deadtime +t = t - t[0] # Account for zerotime +t = t + tmin # Artifically truncate the signal Vexp = Vexp[t<=3] diff --git a/examples/intermediate/ex_crossing_echoes_masking.py b/examples/intermediate/ex_crossing_echoes_masking.py index db2cba66..67396249 100644 --- a/examples/intermediate/ex_crossing_echoes_masking.py +++ b/examples/intermediate/ex_crossing_echoes_masking.py @@ -32,10 +32,10 @@ # Experimental parameters tau1 = 0.5 # First inter-pulse time delay, μs tau2 = 4.5 # Second inter-pulse time delay, μs -t0 = 0.3 # Acquisition deadtime, μs +tmin = 0.3 # Acquisition deadtime, μs -# Adjust for the deadtime -t = t - t[0] + t0 +t = t - t[0] # Account for zerotime +t = t + tmin # Plot the real part of the raw data plt.figure(figsize=[6,4]) diff --git a/examples/intermediate/ex_fitting_4pdeer_pathways.py b/examples/intermediate/ex_fitting_4pdeer_pathways.py index 59d5d993..e7742ea6 100644 --- a/examples/intermediate/ex_fitting_4pdeer_pathways.py +++ b/examples/intermediate/ex_fitting_4pdeer_pathways.py @@ -20,7 +20,7 @@ # Experimental parameters tau1 = 0.5 # First inter-pulse delay, μs tau2 = 3.5 # Second inter-pulse delay, μs -deadtime = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Acquisition deadtime, μs # Load the experimental data t,Vexp = dl.deerload(path + file) @@ -28,8 +28,8 @@ # Pre-processing Vexp = dl.correctphase(Vexp) # Phase correction Vexp = Vexp/np.max(Vexp) # Rescaling (aesthetic) -t = t + deadtime # Account for deadtime - +t = t - t[0] # Account for zerotime +t = t + tmin # Distance vector r = np.arange(2.5,5.5,0.025) # nm diff --git a/examples/intermediate/ex_fitting_5pdeer_pathways.py b/examples/intermediate/ex_fitting_5pdeer_pathways.py index 2d11b555..f99085c2 100644 --- a/examples/intermediate/ex_fitting_5pdeer_pathways.py +++ b/examples/intermediate/ex_fitting_5pdeer_pathways.py @@ -21,14 +21,15 @@ tau1 = 3.7 # First inter-pulse delay, μs tau2 = 3.5 # Second inter-pulse delay, μs tau3 = 0.3 # Third inter-pulse delay, μs -deadtime = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Acquisition deadtime, μs # Load the experimental data t,Vexp = dl.deerload(path + file) Vexp = dl.correctphase(Vexp) # Phase correction Vexp = Vexp/np.max(Vexp) # Rescaling (aesthetic) -t = t + deadtime # Account for deadtime - +t = t - t[0] # Account for zerotime +t = t + tmin + # Distance vector r = np.arange(2.5,5.5,0.025) # nm diff --git a/examples/intermediate/ex_fitting_sparse_4pdeer.py b/examples/intermediate/ex_fitting_sparse_4pdeer.py index 47b8560b..43cb456a 100644 --- a/examples/intermediate/ex_fitting_sparse_4pdeer.py +++ b/examples/intermediate/ex_fitting_sparse_4pdeer.py @@ -24,7 +24,7 @@ # Experimental parameters tau1 = 0.400 # First inter-pulse delay, μs tau2 = 8.000 # Second inter-pulse delay, μs -deadtime = 0.482 # Acquisition deadtime, μs +tmin = 0.482 # Acquisition deadtime, μs # Load the experimental data and the grid of recorded timings (this depends on how the data were acquired) _,Vexp = dl.deerload(path + datafile) @@ -34,7 +34,8 @@ # Pre-processing Vexp = dl.correctphase(Vexp) # Phase correction Vexp = Vexp/np.max(Vexp) # Rescaling (aesthetic) -t = t + deadtime # Account for deadtime +t = t - t[0] # Account for zerotime +t = t + tmin # Distance vector r = np.arange(2,10,0.05) # nm diff --git a/examples/intermediate/ex_global_different_deer.py b/examples/intermediate/ex_global_different_deer.py index 7fa0115d..7e030ff9 100644 --- a/examples/intermediate/ex_global_different_deer.py +++ b/examples/intermediate/ex_global_different_deer.py @@ -21,23 +21,27 @@ # Experimental parameters (4pDEER) tau1_4p = 0.5 # First inter-pulse delay, μs tau2_4p = 3.5 # Second inter-pulse delay, μs -deadtime_4p = 0.1 # Acquisition deadtime, μs +tmin_4p = 0.1 # Acquisition deadtime, μs # Experimental parameters (reversed 5pDEER) tau1_5p = 2.9 # First inter-pulse delay, μs tau2_5p = 3.3 # Second inter-pulse delay, μs tau3_5p = 0.3 # Third inter-pulse delay, μs -deadtime_5p = 0.1 # Acquisition deadtime, μs +tmin_5p = 0.1 # Acquisition deadtime, μs # Load the experimental data (4pDEER) t4p,V4p = dl.deerload(path + file4p) V4p = dl.correctphase(V4p) # Phase correction V4p = V4p/np.max(V4p) # Rescaling (aesthetic) -t4p = t4p + deadtime_4p # Account for deadtime +t4p = t4p - t4p[0] # Account for zerotime +t4p = t4p + tmin_4p + # Load the experimental data (reversed 5pDEER) t5p,V5p = dl.deerload(path + file5p) V5p = dl.correctphase(V5p) # Phase correction V5p = V5p/np.max(V5p) # Rescaling (aesthetic) -t5p = t5p + deadtime_5p # Account for deadtime +t5p = t5p - t5p[0] # Account for zerotime +t5p = t5p + tmin_5p + # Run fit r = np.arange(2.5,6,0.05) diff --git a/examples/intermediate/ex_global_fitting_4pdeer.py b/examples/intermediate/ex_global_fitting_4pdeer.py index 9cc0cea9..e33fdacc 100644 --- a/examples/intermediate/ex_global_fitting_4pdeer.py +++ b/examples/intermediate/ex_global_fitting_4pdeer.py @@ -23,10 +23,10 @@ # Experimental parameters tau1s = [0.3, 0.5] # First inter-pulse delay, μs tau2s = [2.0, 4.0] # Second inter-pulse delay, μs -deadtimes = [0.1, 0.3] # Acquisition deadtime, μs +tmins = [0.1, 0.3] # Acquisition deadtime, μs Vmodels,ts,Vs = [],[],[] -for file, tau1, tau2, deadtime in zip(files, tau1s, tau2s, deadtimes): +for file, tau1, tau2, tmin in zip(files, tau1s, tau2s, tmins): # Load the experimental data t,Vexp = dl.deerload(path + file) @@ -34,7 +34,8 @@ # Pre-processing Vexp = dl.correctphase(Vexp) # Phase correction Vexp = Vexp/np.max(Vexp) # Rescaling (aesthetic) - t = t + deadtime # Account for deadtime + t = t - t[0] # Account for zerotime + t = t + tmin # Distance vector r = np.arange(1.5,7,0.05) # nm diff --git a/examples/intermediate/ex_multipathway_validation.py b/examples/intermediate/ex_multipathway_validation.py index 348e04e4..cf3deaac 100644 --- a/examples/intermediate/ex_multipathway_validation.py +++ b/examples/intermediate/ex_multipathway_validation.py @@ -27,7 +27,7 @@ file = "../data/experimental_mbp_protein_4pdeer.DTA" # Experiment information -t0 = 0.040 +tmin = 0.040 tau1 = 0.4 tau2 = 3.0 @@ -37,7 +37,7 @@ Vexp = Vexp[:-2] Vexp = dl.correctphase(Vexp) Vexp = Vexp/max(Vexp) -t = t- t[0] + t0 +t = t- t[0] + tmin # Define the distance vector r = np.arange(3,4.5,0.05) diff --git a/examples/intermediate/ex_selregparam.py b/examples/intermediate/ex_selregparam.py index e4f99958..cb79fab5 100644 --- a/examples/intermediate/ex_selregparam.py +++ b/examples/intermediate/ex_selregparam.py @@ -21,7 +21,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -deadtime = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Acquisition deadtime, μs # Load the experimental data t,Vexp = dl.deerload(path + file) @@ -29,7 +29,8 @@ # Pre-processing Vexp = dl.correctphase(Vexp) # Phase correction Vexp = Vexp/np.max(Vexp) # Rescaling (aesthetic) -t = t + deadtime # Account for deadtime +t = t - t[0] # Account for zerotime +t = t + tmin # Distance vector r = np.linspace(1.5,7,50) # nm From 07679c7948b6cb76450d3e2376bb0b48c2cbdf01 Mon Sep 17 00:00:00 2001 From: Hugo Karas Date: Fri, 11 Aug 2023 12:50:31 +0200 Subject: [PATCH 3/6] Change RIDME stretch value --- examples/data/example_ridme_1.DSC | 4 ++-- examples/data/example_ridme_1.DTA | Bin 8640 -> 8640 bytes 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/data/example_ridme_1.DSC b/examples/data/example_ridme_1.DSC index 4429c2a4..5f5002e4 100644 --- a/examples/data/example_ridme_1.DSC +++ b/examples/data/example_ridme_1.DSC @@ -1,4 +1,4 @@ -* Exported from Python using EasySpin, 2023-08-11 11:44:41 +* Exported from Python using EasySpin, 2023-08-11 12:49:46 #DESC 1.2 * DESCRIPTOR INFORMATION *********************** DSRC MAN BSEQ LIT @@ -17,7 +17,7 @@ XWID 4312.000000000004 #SPL 1.2 * STANDARD PARAMETER LAYER OPER DATE 11/08/23 -TIME 11:44:41 +TIME 12:49:46 CMNT SAMP SFOR diff --git a/examples/data/example_ridme_1.DTA b/examples/data/example_ridme_1.DTA index 102871cb71377bc8fc536afd02be05cd0d516a6a..b378fcc8810fb0ce5e2fb1018e6994e3898177a4 100644 GIT binary patch literal 8640 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 Date: Fri, 11 Aug 2023 16:44:57 +0200 Subject: [PATCH 4/6] Replaced all Acquisition Deadtime with Start time. --- examples/advanced/ex_comparing_uncertainties.py | 2 +- examples/advanced/ex_dipolarpathways_selection.py | 2 +- examples/advanced/ex_extracting_gauss_constraints.py | 2 +- examples/advanced/ex_forcefield_fit.py | 2 +- examples/advanced/ex_global_twostates_parametric.py | 2 +- examples/advanced/ex_identifiability_analysis.py | 2 +- examples/advanced/ex_long_threespin_analysis.py | 4 ++-- examples/advanced/ex_multigauss_fitting_4pdeer.py | 2 +- examples/advanced/ex_profileanalysis.py | 2 +- examples/basic/ex_bootstrapping.py | 4 ++-- examples/basic/ex_fitting_4pdeer.py | 2 +- examples/basic/ex_fitting_4pdeer_compactness.py | 2 +- examples/basic/ex_fitting_4pdeer_gauss.py | 2 +- examples/basic/ex_fitting_5pdeer.py | 2 +- examples/basic/ex_fitting_ridme.py | 2 +- examples/basic/ex_restraints_4pdeer.py | 2 +- examples/intermediate/ex_compactness_with_without.py | 2 +- examples/intermediate/ex_crossing_echoes_masking.py | 2 +- examples/intermediate/ex_fitting_4pdeer_pathways.py | 2 +- examples/intermediate/ex_fitting_5pdeer_pathways.py | 8 ++++---- examples/intermediate/ex_fitting_sparse_4pdeer.py | 2 +- examples/intermediate/ex_global_different_deer.py | 4 ++-- examples/intermediate/ex_global_fitting_4pdeer.py | 2 +- examples/intermediate/ex_selregparam.py | 2 +- 24 files changed, 30 insertions(+), 30 deletions(-) diff --git a/examples/advanced/ex_comparing_uncertainties.py b/examples/advanced/ex_comparing_uncertainties.py index 1120456a..2a34986f 100644 --- a/examples/advanced/ex_comparing_uncertainties.py +++ b/examples/advanced/ex_comparing_uncertainties.py @@ -27,7 +27,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -tmin = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Start time, μs # Load the experimental data t,Vexp = dl.deerload(path + file) diff --git a/examples/advanced/ex_dipolarpathways_selection.py b/examples/advanced/ex_dipolarpathways_selection.py index 066b9e20..57fb0e18 100644 --- a/examples/advanced/ex_dipolarpathways_selection.py +++ b/examples/advanced/ex_dipolarpathways_selection.py @@ -25,7 +25,7 @@ # Experimental parameters tau1 = 0.5 # First inter-pulse delay, μs tau2 = 3.5 # Second inter-pulse delay, μs -tmin = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Start time, μs # Load the experimental data t,Vexp = dl.deerload(path + file) diff --git a/examples/advanced/ex_extracting_gauss_constraints.py b/examples/advanced/ex_extracting_gauss_constraints.py index 16c93df4..759a82ac 100644 --- a/examples/advanced/ex_extracting_gauss_constraints.py +++ b/examples/advanced/ex_extracting_gauss_constraints.py @@ -23,7 +23,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -tmin = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Start time, μs # Load the experimental data t,Vexp = dl.deerload(path + file) diff --git a/examples/advanced/ex_forcefield_fit.py b/examples/advanced/ex_forcefield_fit.py index dfb8e11c..c65d4f61 100644 --- a/examples/advanced/ex_forcefield_fit.py +++ b/examples/advanced/ex_forcefield_fit.py @@ -48,7 +48,7 @@ def forcefield_P(c0,c1,c2,c3): # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 5.0 # Second inter-pulse delay, μs -tmin = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Start time, μs # Load the experimental data t,Vexp = dl.deerload(path + file) diff --git a/examples/advanced/ex_global_twostates_parametric.py b/examples/advanced/ex_global_twostates_parametric.py index a026e874..2f3bf934 100644 --- a/examples/advanced/ex_global_twostates_parametric.py +++ b/examples/advanced/ex_global_twostates_parametric.py @@ -30,7 +30,7 @@ # Experimental parameters tau1 = 0.4 # First inter-pulse delay, μs tau2 = 4.5 # Second inter-pulse delay, μs -tmin = 0.2 # Acquisition deadtime, μs +tmin = 0.2 # Start time, μs Vmodels, ts, Vexps = [], [], [] for file in files: diff --git a/examples/advanced/ex_identifiability_analysis.py b/examples/advanced/ex_identifiability_analysis.py index 4e9c78bc..6ef0fff8 100644 --- a/examples/advanced/ex_identifiability_analysis.py +++ b/examples/advanced/ex_identifiability_analysis.py @@ -23,7 +23,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -tmin = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Start time, μs # Load the experimental data t,Vexp = dl.deerload(path + file) diff --git a/examples/advanced/ex_long_threespin_analysis.py b/examples/advanced/ex_long_threespin_analysis.py index 7bc8bf6c..cdbde826 100644 --- a/examples/advanced/ex_long_threespin_analysis.py +++ b/examples/advanced/ex_long_threespin_analysis.py @@ -20,7 +20,7 @@ files = [f'../data/triradical_protein_deer_{dB}dB.DTA' for dB in [0,6,9]] # Experiment information -t0 = 0.280 # Acquisition deadtime, μs +t0 = 0.280 # Start time, μs tau1 = 0.40 # First interpulse delay, μs tau2 = 9.00 # Second interpulse delay, μs @@ -34,7 +34,7 @@ t,Vexp, descriptor = dl.deerload(file,full_output=True) t = t[:-80] Vexp = Vexp[:-80] - # Adjust the start time + # Adjust the Start time t = t - t[0] + t0 # Pre-processing diff --git a/examples/advanced/ex_multigauss_fitting_4pdeer.py b/examples/advanced/ex_multigauss_fitting_4pdeer.py index 1d5bd458..e2a5cf87 100644 --- a/examples/advanced/ex_multigauss_fitting_4pdeer.py +++ b/examples/advanced/ex_multigauss_fitting_4pdeer.py @@ -24,7 +24,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -tmin = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Start time, μs # Load the experimental data t, Vexp = dl.deerload(path + file) diff --git a/examples/advanced/ex_profileanalysis.py b/examples/advanced/ex_profileanalysis.py index 33b0d8b9..82d5fc42 100644 --- a/examples/advanced/ex_profileanalysis.py +++ b/examples/advanced/ex_profileanalysis.py @@ -19,7 +19,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -tmin = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Start time, μs # Load the experimental data t,Vexp = dl.deerload(path + file) diff --git a/examples/basic/ex_bootstrapping.py b/examples/basic/ex_bootstrapping.py index 43378840..de9a558f 100644 --- a/examples/basic/ex_bootstrapping.py +++ b/examples/basic/ex_bootstrapping.py @@ -30,7 +30,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -tmin = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Start time, μs # Load the experimental data t,Vexp = dl.deerload(path + file) @@ -38,7 +38,7 @@ # Pre-processing Vexp = dl.correctphase(Vexp) # Phase correction Vexp = Vexp/np.max(Vexp) # Rescaling (aesthetic) -t = t - t[0] # Account for zerotime +t = t - t[0] # Account for zerotime t = t + tmin # Distance vector diff --git a/examples/basic/ex_fitting_4pdeer.py b/examples/basic/ex_fitting_4pdeer.py index dab16fa4..38368f5e 100644 --- a/examples/basic/ex_fitting_4pdeer.py +++ b/examples/basic/ex_fitting_4pdeer.py @@ -21,7 +21,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -tmin = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Start time, μs # Load the experimental data t,Vexp = dl.deerload(path + file) diff --git a/examples/basic/ex_fitting_4pdeer_compactness.py b/examples/basic/ex_fitting_4pdeer_compactness.py index b9402b9a..b94f782b 100644 --- a/examples/basic/ex_fitting_4pdeer_compactness.py +++ b/examples/basic/ex_fitting_4pdeer_compactness.py @@ -23,7 +23,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -tmin = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Start time, μs # Load the experimental data t,Vexp = dl.deerload(path + file) diff --git a/examples/basic/ex_fitting_4pdeer_gauss.py b/examples/basic/ex_fitting_4pdeer_gauss.py index 69c76156..225827c2 100644 --- a/examples/basic/ex_fitting_4pdeer_gauss.py +++ b/examples/basic/ex_fitting_4pdeer_gauss.py @@ -21,7 +21,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -tmin = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Start time, μs # Load the experimental data t,Vexp = dl.deerload(path + file) diff --git a/examples/basic/ex_fitting_5pdeer.py b/examples/basic/ex_fitting_5pdeer.py index d6023e28..83d7519d 100644 --- a/examples/basic/ex_fitting_5pdeer.py +++ b/examples/basic/ex_fitting_5pdeer.py @@ -32,7 +32,7 @@ tau1 = 3.9 # First inter-pulse delay, μs tau2 = 3.7 # Second inter-pulse delay, μs tau3 = 0.5 # Third inter-pulse delay, μs -tmin = 0.3 # Acquisition deadtime, μs +tmin = 0.3 # Start time, μs # Load the experimental data t,Vexp = dl.deerload(path + file) diff --git a/examples/basic/ex_fitting_ridme.py b/examples/basic/ex_fitting_ridme.py index 0072e21d..f58ccfa6 100644 --- a/examples/basic/ex_fitting_ridme.py +++ b/examples/basic/ex_fitting_ridme.py @@ -21,7 +21,7 @@ # Experimental parameters tau1 = 0.4 # First inter-pulse delay, μs tau2 = 4.2 # Second inter-pulse delay, μs -tmin = 0.28 # Acquisition deadtime, μs +tmin = 0.28 # Start time, μs # Load the experimental data t,Vexp = dl.deerload(path + file) diff --git a/examples/basic/ex_restraints_4pdeer.py b/examples/basic/ex_restraints_4pdeer.py index 7696948c..90112ac6 100644 --- a/examples/basic/ex_restraints_4pdeer.py +++ b/examples/basic/ex_restraints_4pdeer.py @@ -28,7 +28,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -deadtime = 0.1 # Acquisition deadtime, μs +deadtime = 0.1 # Start time, μs # Load the experimental data t,Vexp = dl.deerload(path + file) diff --git a/examples/intermediate/ex_compactness_with_without.py b/examples/intermediate/ex_compactness_with_without.py index a6c8a277..0b836934 100644 --- a/examples/intermediate/ex_compactness_with_without.py +++ b/examples/intermediate/ex_compactness_with_without.py @@ -21,7 +21,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -tmin = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Start time, μs # Load the experimental data t,Vexp = dl.deerload(path + file) diff --git a/examples/intermediate/ex_crossing_echoes_masking.py b/examples/intermediate/ex_crossing_echoes_masking.py index 67396249..dd60009e 100644 --- a/examples/intermediate/ex_crossing_echoes_masking.py +++ b/examples/intermediate/ex_crossing_echoes_masking.py @@ -32,7 +32,7 @@ # Experimental parameters tau1 = 0.5 # First inter-pulse time delay, μs tau2 = 4.5 # Second inter-pulse time delay, μs -tmin = 0.3 # Acquisition deadtime, μs +tmin = 0.3 # Start time, μs t = t - t[0] # Account for zerotime t = t + tmin diff --git a/examples/intermediate/ex_fitting_4pdeer_pathways.py b/examples/intermediate/ex_fitting_4pdeer_pathways.py index e7742ea6..cef4d058 100644 --- a/examples/intermediate/ex_fitting_4pdeer_pathways.py +++ b/examples/intermediate/ex_fitting_4pdeer_pathways.py @@ -20,7 +20,7 @@ # Experimental parameters tau1 = 0.5 # First inter-pulse delay, μs tau2 = 3.5 # Second inter-pulse delay, μs -tmin = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Start time, μs # Load the experimental data t,Vexp = dl.deerload(path + file) diff --git a/examples/intermediate/ex_fitting_5pdeer_pathways.py b/examples/intermediate/ex_fitting_5pdeer_pathways.py index f99085c2..370a7d93 100644 --- a/examples/intermediate/ex_fitting_5pdeer_pathways.py +++ b/examples/intermediate/ex_fitting_5pdeer_pathways.py @@ -18,10 +18,10 @@ file = 'example_5pdeer_3.DTA' # Experimental parameters (reversed 5pDEER) -tau1 = 3.7 # First inter-pulse delay, μs -tau2 = 3.5 # Second inter-pulse delay, μs -tau3 = 0.3 # Third inter-pulse delay, μs -tmin = 0.1 # Acquisition deadtime, μs +tau1 = 3.7 # First inter-pulse delay, μs +tau2 = 3.5 # Second inter-pulse delay, μs +tau3 = 0.3 # Third inter-pulse delay, μs +tmin = 0.1 # Start time, μs # Load the experimental data t,Vexp = dl.deerload(path + file) diff --git a/examples/intermediate/ex_fitting_sparse_4pdeer.py b/examples/intermediate/ex_fitting_sparse_4pdeer.py index 43cb456a..68adaaa0 100644 --- a/examples/intermediate/ex_fitting_sparse_4pdeer.py +++ b/examples/intermediate/ex_fitting_sparse_4pdeer.py @@ -24,7 +24,7 @@ # Experimental parameters tau1 = 0.400 # First inter-pulse delay, μs tau2 = 8.000 # Second inter-pulse delay, μs -tmin = 0.482 # Acquisition deadtime, μs +tmin = 0.482 # Start time, μs # Load the experimental data and the grid of recorded timings (this depends on how the data were acquired) _,Vexp = dl.deerload(path + datafile) diff --git a/examples/intermediate/ex_global_different_deer.py b/examples/intermediate/ex_global_different_deer.py index 7e030ff9..ab7f0ab0 100644 --- a/examples/intermediate/ex_global_different_deer.py +++ b/examples/intermediate/ex_global_different_deer.py @@ -21,12 +21,12 @@ # Experimental parameters (4pDEER) tau1_4p = 0.5 # First inter-pulse delay, μs tau2_4p = 3.5 # Second inter-pulse delay, μs -tmin_4p = 0.1 # Acquisition deadtime, μs +tmin_4p = 0.1 # Start time, μs # Experimental parameters (reversed 5pDEER) tau1_5p = 2.9 # First inter-pulse delay, μs tau2_5p = 3.3 # Second inter-pulse delay, μs tau3_5p = 0.3 # Third inter-pulse delay, μs -tmin_5p = 0.1 # Acquisition deadtime, μs +tmin_5p = 0.1 # Start time, μs # Load the experimental data (4pDEER) t4p,V4p = dl.deerload(path + file4p) diff --git a/examples/intermediate/ex_global_fitting_4pdeer.py b/examples/intermediate/ex_global_fitting_4pdeer.py index e33fdacc..6e6e1c9b 100644 --- a/examples/intermediate/ex_global_fitting_4pdeer.py +++ b/examples/intermediate/ex_global_fitting_4pdeer.py @@ -23,7 +23,7 @@ # Experimental parameters tau1s = [0.3, 0.5] # First inter-pulse delay, μs tau2s = [2.0, 4.0] # Second inter-pulse delay, μs -tmins = [0.1, 0.3] # Acquisition deadtime, μs +tmins = [0.1, 0.3] # Start time, μs Vmodels,ts,Vs = [],[],[] for file, tau1, tau2, tmin in zip(files, tau1s, tau2s, tmins): diff --git a/examples/intermediate/ex_selregparam.py b/examples/intermediate/ex_selregparam.py index cb79fab5..417c284d 100644 --- a/examples/intermediate/ex_selregparam.py +++ b/examples/intermediate/ex_selregparam.py @@ -21,7 +21,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -tmin = 0.1 # Acquisition deadtime, μs +tmin = 0.1 # Start time, μs # Load the experimental data t,Vexp = dl.deerload(path + file) From 872510019f6e9fb3fda24c60e750840440d6d90c Mon Sep 17 00:00:00 2001 From: Hugo Karas Date: Fri, 11 Aug 2023 16:55:29 +0200 Subject: [PATCH 5/6] Missed one example --- examples/basic/ex_restraints_4pdeer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/basic/ex_restraints_4pdeer.py b/examples/basic/ex_restraints_4pdeer.py index 90112ac6..d58675f3 100644 --- a/examples/basic/ex_restraints_4pdeer.py +++ b/examples/basic/ex_restraints_4pdeer.py @@ -28,7 +28,7 @@ # Experimental parameters tau1 = 0.3 # First inter-pulse delay, μs tau2 = 4.0 # Second inter-pulse delay, μs -deadtime = 0.1 # Start time, μs +tmin = 0.1 # Start time, μs # Load the experimental data t,Vexp = dl.deerload(path + file) @@ -36,7 +36,7 @@ # Pre-processing Vexp = dl.correctphase(Vexp) # Phase correction Vexp = Vexp/np.max(Vexp) # Rescaling (aesthetic) -t = t + deadtime # Account for deadtime +t = t + tmin # Account for zerotime # Distance vector r = np.arange(2,6,0.05) # nm From 81474efb2b776f5d840ae4820d7b4bbd99ec9e70 Mon Sep 17 00:00:00 2001 From: Hugo Karas Date: Tue, 15 Aug 2023 10:00:09 +0200 Subject: [PATCH 6/6] Bug fix with propagate and evaluate functions The propagate and evaluate functions had a bug that stopped them working on functions. --- deerlab/fit.py | 13 ++++- deerlab/fitresult.py | 109 +++++++++++++++++++++++++++------------ test/test_model_class.py | 25 +++++++++ 3 files changed, 112 insertions(+), 35 deletions(-) diff --git a/deerlab/fit.py b/deerlab/fit.py index 967e08f9..b7929b8c 100644 --- a/deerlab/fit.py +++ b/deerlab/fit.py @@ -358,6 +358,8 @@ def fit(model_, y, *constants, par0=None, penalties=None, bootstrap=0, noiselvl= Fitted parameter vector ordered according to the model parameter indices. paramUncert : :ref:`UQResult` Uncertainty quantification of the parameter vector ordered according to the model parameter indices. + paramlist : list + List of the fitted parameter names ordered according to the model parameter indices. model : ndarray Fitted model response. regparam : scalar @@ -505,6 +507,15 @@ def bootstrap_fcn(ysim): FitResult_dict = {key: getattr(fitresults,key) for key in ['y','mask','param','paramUncert','model','cost','plot','residuals','stats','regparam','regparam_stats','__plot_inputs']} _paramlist = model._parameter_list('vector') + param_idx = [[] for _ in _paramlist] + idxprev = 0 + for islinear in [False,True]: + for n,param in enumerate(_paramlist): + if np.all(getattr(model,param).linear == islinear): + N = len(np.atleast_1d(getattr(model,param).idx)) + param_idx[n] = np.arange(idxprev,idxprev + N) + idxprev += N + # Enforce normalization of the linear parameters (if needed) for the final output FitResult_param_,FitResult_paramuq_ = FitResult_param.copy(),FitResult_paramuq.copy() if normalization: @@ -526,7 +537,7 @@ def _scale(x): noiselvl = noiselvl[0] # Generate FitResult object from all the dictionaries - fitresult = FitResult({**FitResult_param_,**FitResult_paramuq_, **FitResult_dict,'penweights':penweights,'noiselvl':noiselvl}) + fitresult = FitResult({**FitResult_param_,**FitResult_paramuq_, **FitResult_dict,'penweights':penweights,'noiselvl':noiselvl,'paramlist':_paramlist, '_param_idx':param_idx}) fitresult._summary = _print_fitresults(fitresult,model) diff --git a/deerlab/fitresult.py b/deerlab/fitresult.py index b36f064c..2dd55ab1 100644 --- a/deerlab/fitresult.py +++ b/deerlab/fitresult.py @@ -87,45 +87,76 @@ def _extarct_params_from_model(self, model): if callable(model): try: modelparam = model._parameter_list('vector') + function_type=False except AttributeError: + function_type=True modelparam = inspect.getfullargspec(model).args if not hasattr(self,'param'): raise ValueError('The fit object does not contain any fitted parameters.') - # Enforce model normalization - normfactor_keys = [] - for key in model._parameter_list(): - param = getattr(model,key) - if np.all(param.linear): - if param.normalization is not None: - normfactor_key = f'{key}_scale' - normfactor_keys.append(normfactor_key) - try: - model.addnonlinear(normfactor_key,lb=-np.inf,ub=np.inf,par0=1,description=f'Normalization factor of {key}') - getattr(model,normfactor_key).freeze(1) - except KeyError: - pass + # # Enforce model normalization + # normfactor_keys = [] + # for key in modelparam: + # param = getattr(model,key) + # if np.all(param.linear): + # if param.normalization is not None: + # normfactor_key = f'{key}_scale' + # normfactor_keys.append(normfactor_key) + # try: + # model.addnonlinear(normfactor_key,lb=-np.inf,ub=np.inf,par0=1,description=f'Normalization factor of {key}') + # getattr(model,normfactor_key).freeze(1) + # except KeyError: + # pass - # Get some basic information on the parameter vector - modelparam = model._parameter_list(order='vector') - param_idx = [[] for _ in model._parameter_list('vector')] - idxprev = 0 - for islinear in [False,True]: - for n,param in enumerate(model._parameter_list('vector')): - if np.all(getattr(model,param).linear == islinear): - N = len(np.atleast_1d(getattr(model,param).idx)) - param_idx[n] = np.arange(idxprev,idxprev + N) - idxprev += N - - params = {key : fitvalue if len(fitvalue)>1 else fitvalue[0] for key,fitvalue in zip(modelparam,[self.param[idx] for idx in param_idx])} + # # Get some basic information on the parameter vector + # modelparam = model._parameter_list(order='vector') + # param_idx = [[] for _ in model._parameter_list('vector')] + # idxprev = 0 + # for islinear in [False,True]: + # for n,param in enumerate(model._parameter_list('vector')): + # if np.all(getattr(model,param).linear == islinear): + # N = len(np.atleast_1d(getattr(model,param).idx)) + # param_idx[n] = np.arange(idxprev,idxprev + N) + # idxprev += N + + fitparams = {key : fitvalue if len(fitvalue)>1 else fitvalue[0] for key, fitvalue in zip(self.paramlist,[self.param[idx] for idx in self._param_idx])} # Check that all parameters are in the fit object for param in modelparam: - if not param in params: + if not param in fitparams: raise KeyError(f'The fit object does not contain the {param} parameter.') + + + params = {param : fitparams[param] for param in modelparam} + params_idx = [self._param_idx[self.paramlist.index(param)] for param in modelparam] + + return modelparam, params, params_idx + + def _extract_params_from_function(self,function): + """ + Extracts the fitted parameters from a callable function. + + Assumes that all parameters are length 1. + + """ + # Get the parameter names from the function definition + modelparam = inspect.getfullargspec(function).args + + fitparam_idx = self._param_idx + + # Get the parameter values from the fit object + fitparams = {param : self.param[i] for i,param in enumerate(self.paramlist)} + params = {param : fitparams[param] for param in modelparam} + params_idx = [fitparam_idx[self.paramlist.index(param)] for param in modelparam] + # fitparams = {key : fitvalue if len(fitvalue)>1 else fitvalue[0] for key, fitvalue in zip(modelparam,[self.param[idx] for idx in fitparam_idx])} + + + + + return modelparam, params, params_idx + - return modelparam, params, param_idx def evaluate(self, model, *constants): # ---------------------------------------------------------------------------- @@ -154,9 +185,14 @@ def evaluate(self, model, *constants): response : array_like Model response at the fitted parameter values. """ - - modelparam, params, _ = self._extarct_params_from_model(model) - parameters = {param: params[param] for param in modelparam} + try: + modelparam = model._parameter_list('vector') + modelparam, fitparams, fitparam_idx = self._extarct_params_from_model(model) + except AttributeError: + modelparam, fitparams, fitparam_idx = self._extract_params_from_function(model) + + + parameters = {param: fitparams[param] for param in modelparam} # Evaluate the input model response = model(*constants,**parameters) @@ -195,11 +231,16 @@ def propagate(self, model, *constants, lb=None, ub=None): Uncertainty quantification of the model's response. """ - modelparam,_, param_idx = self._extarct_params_from_model(model) - # Determine the indices of the subset of parameters the model depends on - subset = [param_idx[np.where(np.asarray(modelparam)==param)[0][0]] for param in modelparam] + try: + modelparam = model._parameter_list('vector') + modelparam, fitparams, fitparam_idx = self._extarct_params_from_model(model) + + except AttributeError: + modelparam, fitparams, fitparam_idx = self._extract_params_from_function(model) + + # Propagate the uncertainty from that subset to the model - modeluq = self.paramUncert.propagate(lambda param: model(*constants,*[param[s] for s in subset]),lb,ub) + modeluq = self.paramUncert.propagate(lambda param: model(*constants,*[param[s] for s in fitparam_idx]),lb,ub) return modeluq diff --git a/test/test_model_class.py b/test/test_model_class.py index d8802fba..b8f6b864 100644 --- a/test/test_model_class.py +++ b/test/test_model_class.py @@ -568,6 +568,31 @@ def test_fit_propagate_through_model(mock_data,mock_x,model_type,method): assert np.less_equal(ci_lower,ci_upper).all() # ================================================================ + +@pytest.mark.parametrize('method', ['bootstrap','moment']) +@pytest.mark.parametrize('model_type', ['parametric']) +def test_fit_propagate_through_function(mock_data,mock_x,model_type,method): + + model = _generate_model(model_type, fixed_axis=False) + + if method=='bootstrap': + results = fit(model,mock_data,mock_x, bootstrap=3) + else: + results = fit(model,mock_data,mock_x) + + if model_type=='parametric': + fun = lambda mean1,mean2,std1,std2,amp1,amp2: bigauss(mock_x,mean1,mean2,std1,std2,amp1,amp2) + response_ci = results.propagate(fun, lb=np.zeros_like(mock_x)).ci(95) + + ci_lower = response_ci[:,0] + ci_upper = response_ci[:,1] + + assert np.less_equal(ci_lower,ci_upper).all() + + + +# ================================================================ + def gauss_multiaxis(axis1,axis2,mean,std): return np.exp(-(axis1-mean)**2/std**2/2)