diff --git a/deerlab/dipolarkernel.py b/deerlab/dipolarkernel.py index c975f9e4..33d815f1 100644 --- a/deerlab/dipolarkernel.py +++ b/deerlab/dipolarkernel.py @@ -130,7 +130,7 @@ def dipolarkernel(t, r, *, pathways=None, mod=None, bg=None, method='fresnel', e Requires the ``'grid'`` or ``'integral'`` methods. excbandwidth : scalar, optional - Excitation bandwidth of the pulses in MHz to account for limited excitation bandwidth [5]_. + Excitation bandwidth of the pulses in MHz to account for limited excitation bandwidth. If not specified, an infinite excitation bandwidth is used. Requires the ``'grid'`` or ``'integral'`` methods. diff --git a/deerlab/dipolarmodel.py b/deerlab/dipolarmodel.py index fec3691c..96645812 100644 --- a/deerlab/dipolarmodel.py +++ b/deerlab/dipolarmodel.py @@ -770,6 +770,8 @@ def ex_4pdeer(tau1, tau2, pathways=[1,2,3,4], pulselength=0.016): The middle table summarizes all detectable modulated dipolar pathways `p` along their dipolar phase accumulation factors `\mathbf{s}_p`, harmonics `\delta_p` and refocusing times `t_{\mathrm{ref},p}`. The most commonly encountered pathways are highlighted in color. The bottom panel shows a decomposition of the dipolar signal into the individual intramolecular contributions (shown as colored lines). + + The dipolar time axis is defined such that `t=0` right after the second observer pulse. .. figure:: ../images/ex_4pdeer_pathways.png :width: 350px @@ -1048,6 +1050,8 @@ def ex_ridme(tau1, tau2, pathways=[1,2,3,4], pulselength=0.016): The middle table summarizes all detectable modulated dipolar pathways `p` along their dipolar phase accumulation factors `\mathbf{s}_p`, harmonics `\delta_p` and refocusing times `t_{\mathrm{ref},p}`. The most commonly encountered pathways are highlighted in color. The bottom panel shows a decomposition of the dipolar signal into the individual intramolecular contributions (shown as colored lines). + + The dipolar time axis is defined such that `t=0` right after the second pulse. (Note that the model does not account for any relaxation-induced effects) @@ -1058,18 +1062,18 @@ def ex_ridme(tau1, tau2, pathways=[1,2,3,4], pulselength=0.016): ---------- tau1 : float scalar - 1st static interpulse delay `\tau_1`. + 1st static interpulse delay `\tau_1`. tau2 : float scalar - 2nd static interpulse delay `\tau_2`. + 2nd static interpulse delay `\tau_2`. pathways : array_like, optional Pathways to include in the model. The pathways are specified as a list of pathways labels `p`. By default, pathways 1-4 are included as shown in the table above. - pulselength : float scalar, optional - Length of the longest microwave pulse in the sequence in microseconds. Used to determine the uncertainty in the - boundaries of the pathway refocusing times. + pulselength : float scalar, optional + Length of the longest microwave pulse in the sequence, in microseconds. Used to determine + the uncertainty in the boundaries of the pathway refocusing times. Returns ------- @@ -1079,25 +1083,25 @@ def ex_ridme(tau1, tau2, pathways=[1,2,3,4], pulselength=0.016): """ # Theoretical refocusing times - def reftimes(tau1,tau2): - tref = [ 0, - tau2, - -tau1, - tau2-tau1] + def reftimes(tau1, tau2): + tref = [tau1, + tau1+tau2, + 0, + tau2] # Sort according to pathways order if pathways is not None: tref = [tref[pathway-1] for pathway in pathways] return tref # Pulse delays - delays = [tau1,tau2] + delays = [tau1, tau2] # Theoretical dipolar harmonics - harmonics = [ 1, 1, 1, 1] + harmonics = [1, 1, 1, 1] # Pathway labels - pathwaylabels = np.arange(1,len(harmonics)+1) + pathwaylabels = np.arange(1, len(harmonics)+1) # Sort according to pathways order if pathways is not None: - _checkpathways(pathways,Nmax=len(harmonics)) + _checkpathways(pathways, Nmax=len(harmonics)) harmonics = [harmonics[pathway-1] for pathway in pathways] pathwaylabels = [pathwaylabels[pathway-1] for pathway in pathways] diff --git a/docsrc/source/changelog.rst b/docsrc/source/changelog.rst index 1fa8c24d..6c1e71cd 100644 --- a/docsrc/source/changelog.rst +++ b/docsrc/source/changelog.rst @@ -26,6 +26,8 @@ Release Notes Release ``v1.0.2`` - July 2023 ------------------------------------------ +- |api| : The definition of the dipolar time axis for RIDME has changed to match the one for 4-pulse DEER (:pr:`436`). + - |fix| : Fixes errors in documentation (:pr:`429`). * Changes the file name of figures 'modelling*.png` to `modeling*.png`. To keep all spelling consistent with American english. diff --git a/docsrc/source/dipolar_guide_modeling.rst b/docsrc/source/dipolar_guide_modeling.rst index f8a421e0..7de10601 100644 --- a/docsrc/source/dipolar_guide_modeling.rst +++ b/docsrc/source/dipolar_guide_modeling.rst @@ -27,10 +27,12 @@ The time range The time range depends the expected range of distances, but is typically beteen about 0.5 and several microseconds. If you are planning to use this model to fit experimental data, the time vector should be the same as the one used in the experiment. Otherwise, to construct a time vector, use the ``linspace`` or ``arange`` functions from NumPy: :: # time from 0.2 µs to 3.0 µs with a resolution of 0.01 µs, 321 points - t = np.linspace(0.2,3.0,321) # start, stop, number of points - t = np.arange(0.2,3.0,0.01) # start, stop, step size + t = np.linspace(0.2, 3.0, 321) # start, stop, number of points + t = np.arange(0.2, 3.0, 0.01) # start, stop, step size -Note that DeerLab interprets ``t`` such that its zero point is right at the end of the preceding pulse (e.g. right after the second observer pulse in 4-pulse DEER) rather than at the refocusing point of the signal (after `\tau_1` after the second observer pulse). +Note that DeerLab's definition of ``t`` depends on the type of dipolar experiment, and it might differ from how the time is conventionally defined in the literature or in experimental acquired data. + +For example, for 4-pulse DEER and 5-pulse RIDME, ``t`` in DeerLab is defined such that it is zero right at the end of the second observer pulse rather than at the refocusing point of the main dipolar signal (after `\tau_1` after the second observer pulse). Make sure to check the time definition in the :ref:`list of experiment models `. The distance range ************************* diff --git a/docsrc/source/images/ex_ridme_pathways.png b/docsrc/source/images/ex_ridme_pathways.png index 0ca0d190..a536a409 100644 Binary files a/docsrc/source/images/ex_ridme_pathways.png and b/docsrc/source/images/ex_ridme_pathways.png differ diff --git a/docsrc/source/images/ex_ridme_pathways.svg b/docsrc/source/images/ex_ridme_pathways.svg index ff105f26..22e66745 100644 --- a/docsrc/source/images/ex_ridme_pathways.svg +++ b/docsrc/source/images/ex_ridme_pathways.svg @@ -1,19 +1,22 @@ + inkscape:version="1.2.2 (732a01da63, 2022-12-09)" + sodipodi:docname="ex_ridme_pathways.svg" + inkscape:export-filename="ex_ridme_pathways.png" + inkscape:export-xdpi="600" + inkscape:export-ydpi="600" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> - - - + inkscape:window-maximized="1" + inkscape:showpageshadow="2" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" /> @@ -99,7 +96,7 @@ image/svg+xml - + @@ -162,50 +159,11 @@ id="tspan396846-0-1-3-3-5-7">(−1,+1, 0, −1,+1) - 1 - tp δp ττ2-τ1 + id="tspan11058-4-7-4-5-5-16-4" /> (−1,−1, 0, +1,−1) - 0 (−1,−1, 0, +1,+1) - τ2 t + tref,p + 0 + τ1+τ2 + τ1 diff --git a/test/test_dipolarmodel.py b/test/test_dipolarmodel.py index 585502cd..d90317b3 100644 --- a/test/test_dipolarmodel.py +++ b/test/test_dipolarmodel.py @@ -326,7 +326,7 @@ def test_fit_Pnonparametric_normalization(V1path): # ---------------------------------------------------------------------- tdeer = np.linspace(-0.5,5,300) tsifter = np.linspace(-2,4,300) -tridme = np.linspace(-1,3,300) +tridme = np.linspace(0,3,300) tau1,tau2,tau3 = 1,2,3 @fixture(scope='module') def V3pdeer(Pr,Bfcn): @@ -345,7 +345,7 @@ def Vsifter(Pr,Bfcn): return 1e5*dipolarkernel(tsifter,r,pathways=[{'amp':0.3},{'amp':0.5,'reftime':tau2-tau1,'harmonic':1},{'amp':0.1,'reftime':2*tau2,'harmonic':1/2},{'amp':0.1,'reftime':-2*tau1,'harmonic':1/2}],bg=Bfcn)@Pr @fixture(scope='module') def Vridme(Pr,Bfcn): - return 1e5*dipolarkernel(tridme,r,pathways=[{'amp':0.3},{'amp':0.5,'reftime':0},{'amp':0.1,'reftime':tau2},{'amp':0.1,'reftime':-tau1}],bg=Bfcn)@Pr + return 1e5*dipolarkernel(tridme,r,pathways=[{'amp':0.3},{'amp':0.5,'reftime':tau1},{'amp':0.1,'reftime':tau1+tau2},{'amp':0.1,'reftime':0}],bg=Bfcn)@Pr # ---------------------------------------------------------------------- # ====================================================================== @@ -502,14 +502,14 @@ def test_ex_ridme_type(): # ====================================================================== # ====================================================================== -def test_ex_ridme_fit(Vridme,Pr): +def test_ex_ridme_fit(Vridme, Pr): "Check the RIDME experimental model in fitting." - experiment = ex_ridme(tau1,tau2, pathways=[1,2,3]) - Vmodel = dipolarmodel(tridme,r,Bmodel=bg_hom3d,experiment=experiment) - result = fit(Vmodel,Vridme,ftol=1e-4) + experiment = ex_ridme(tau1, tau2, pathways=[1,2,3]) + Vmodel = dipolarmodel(tridme, r, Bmodel=bg_hom3d, experiment=experiment) + result = fit(Vmodel, Vridme, ftol=1e-4) - assert np.allclose(Vridme,result.model,rtol=1e-3) and ovl(result.P/1e5,Pr)>0.975 + assert np.allclose(Vridme, result.model, rtol=1e-3) and ovl(result.P/1e5, Pr)>0.975 # ====================================================================== # ======================================================================