In the design of DeerLab seems to be some redundancy and invariability issues related to how the dipolar pathway amplitudes are defined and handled.
Scale invariability of dipolar pathways
In experiment models (except ex_4pdeer
) where the unmodulated contribution is parametrized (Lam0
), the absolute values of the pathway amplitudes result in a scale-invariant response in DeerLab. For example the simulations for V1
and V2
here
V1= dl.dipolarkernel(t,r,dl.ex_5pdeer([0.8, 0.4, 0.2, 4]))@P
V2= dl.dipolarkernel(t,r,dl.ex_5pdeer([0.4, 0.2, 0.1, 4]))@P
np.array_equal(V1,V2)
>> True
will result in exactly the same signal. The reason behind this is the default behavior of dipolarkernel
, which normalizes the dipolar kernel after calculations (controlled by the option renormalize
). BTW there is an additional option called renormpaths
which has no effect on the output and will be deprecated in a future PR).
As expected by setting renormalize=False
the scale-invariability of the dipolar pathways is lifted
V1= dl.dipolarkernel(t,r,dl.ex_5pdeer([0.8, 0.4, 0.2, 4]),renormalize=False)@P
V2= dl.dipolarkernel(t,r,dl.ex_5pdeer([0.4, 0.2, 0.1, 4]),renormalize=False)@P
np.array_equal(V1,V2)
>> False
Redundancy with V0
Setting renormalize=False
reveals a second issue: the absolute values of the pathway amplitudes and the dipolar signals scale 'V0' become redundant. For example the simulations for V1
and V2
here
V0 = 1
V1= V0*dl.dipolarkernel(t,r,dl.ex_5pdeer([0.8, 0.4, 0.2, 4]),renormalize=False)@P
V0 = 2
V2= V0*dl.dipolarkernel(t,r,dl.ex_5pdeer([0.4, 0.2, 0.1, 4]),renormalize=False)@P
np.array_equal(V1,V2)
>> True
the signals are again equal. Only by reinstating the kernel normalization can these be distinguished again.
Summary
- Normalization of the dipolar kernel (i.e. enforcing
K(0,r)=1
) is required for V0
in the separation V(t)=V0*Vintra(t)*Vinter(t)
to be distinguishable.
- Under normalization, pathway amplitudes in models of the form
V0*(Lam0 + sum_i lam_i*Vintra_i)
exhibit scale invariability.
The question now is: what is the optimal and correct way to treat this?
On one hand, pathway amplitudes are probabilistic quantities so it would make sense to think of them as being confined to a range [0,1]. On the other hand, we could imagine them relative contributions to V0
, i.e. such that the sum over all dipolar pathways equals V0
. This second interpretation might be more efficient due to the fact that the ex_4pdeer
does not suffer from the issues described here, as the contributions are also define in a relative way.
This requires further discussion.
Here is a full working example with a graphical representation of these issues:
import deerlab as dl
import numpy as np
import matplotlib.pyplot as plt
t = np.linspace(-0.1,7,200)
r = np.linspace(2,6,200)
P = dl.dd_gauss(r,[3,0.2])
def V5pdeer_default(lam):
K = dl.dipolarkernel(t,r,dl.ex_5pdeer([lam[0],lam[1],lam[2],4.23]),lambda lam:dl.bg_hom3d(t,50,lam),renormpaths=False)
return K@P
def V5pdeer(lam):
K = dl.dipolarkernel(t,r,dl.ex_5pdeer([lam[0],lam[1],lam[2],4.23]),lambda lam:dl.bg_hom3d(t,50,lam),renormalize=False,renormpaths=False)
return K@P
plt.figure(figsize=[7,6])
plt.subplot(221)
plt.plot(t,V5pdeer_default([0.8,0.6,0.4]),'-',linewidth=2)
plt.plot(t,V5pdeer_default([0.4,0.3,0.2]),'--',linewidth=2)
plt.xlabel('t [us]')
plt.ylabel('V(t)')
plt.title('$V_0$=1, Kernel normalized')
plt.legend(['[$\Lambda_0$,$\lambda_1$,$\lambda_2$]','$\\frac{1}{2}$[$\Lambda_0$,$\lambda_1$,$\lambda_2$]'])
plt.subplot(222)
plt.plot(t,V5pdeer([0.8,0.6,0.4]),'-',linewidth=2)
plt.plot(t,V5pdeer([0.4,0.3,0.2]),'--',linewidth=2)
plt.xlabel('t [us]')
plt.ylabel('V(t)')
plt.title('$V_0$=1, Kernel not normalized')
plt.subplot(223)
V0 = 2
plt.plot(t,V5pdeer_default([0.8,0.6,0.4]),'-',linewidth=2)
plt.plot(t,V0*V5pdeer_default([0.4,0.3,0.2]),'--',linewidth=2)
plt.xlabel('t [us]')
plt.ylabel('V(t)')
plt.title('$V_0$=2, Kernel normalized')
plt.subplot(224)
V0 = 2
plt.plot(t,V5pdeer([0.8,0.6,0.4]),'-',linewidth=2)
plt.plot(t,V0*V5pdeer([0.4,0.3,0.2]),'--',linewidth=2)
plt.xlabel('t [us]')
plt.ylabel('V(t)')
plt.title('$V_0$=2, Kernel not normalized')
plt.tight_layout()
plt.show()