"""Test the relative change in polarization."""
import mrfmsim.formula.polarization as pol
import numpy as np
from mrfmsim.component import Sample
import pytest
[docs]
@pytest.fixture
def sample_e():
"""Electron sample."""
return Sample(spin="e", temperature=0.001, T1=1.0, T2=1.0, spin_density=10.0)
[docs]
@pytest.fixture
def sample_h():
"""Nucleus sample."""
return Sample(spin="1H", temperature=4.2, T1=10, T2=5e-6, spin_density=49.0)
[docs]
def test_rel_dpol_sat_steadystate(sample_e):
"""Test the rel_dpol_sat *absolute* tolerance.
Sample -> e -> electron spin, J = 1/2, high field limit
"""
p1 = pol.rel_dpol_sat_steadystate(0.0, 0.0, sample_e.dB_sat, sample_e.dB_hom)
# depolarized
p2 = pol.rel_dpol_sat_steadystate(0.0, 1.0, sample_e.dB_sat, sample_e.dB_hom)
# polarized
p3 = pol.rel_dpol_sat_steadystate(100.0, 1.0e-3, sample_e.dB_sat, sample_e.dB_hom)
assert pytest.approx([0.0, -1.0, 0.0], abs=1e-10) == [p1, p2, p3]
[docs]
def test_rel_dpol_ibm_cyclic(sample_h):
"""Test rpol_arp_ibm.
Sample -> proton spin -> rpol_arp_ibm() limiting cases
Sample -> h -> proton spin
"""
# on resonance
n1 = pol.rel_dpol_ibm_cyclic(0.0, 2.0e6, sample_h.Gamma)
# below resonance
n2 = pol.rel_dpol_ibm_cyclic(-100.0, 2.0e6, sample_h.Gamma)
# above resonance
n3 = pol.rel_dpol_ibm_cyclic(100.0, 2.0e6, sample_h.Gamma)
assert pytest.approx([n1, n2, n3], abs=1e-10) == [-1.0, 0.0, 0.0]
[docs]
def test_rel_dpol_nut(sample_h):
"""Test rel_dpol_nut.
Sample -> proton spin -> rpol_nut(), on resonance pulses
Sample -> h -> proton spin
"""
Gamma = 0.0425774805964 # gyromagnetic ratio in MHz/mT
rabi = 1.0 / (Gamma) # Rabi period in microseconds for 1 mT
# pi/2 pulse
rpol_090 = pol.rel_dpol_nut(0.0, 1.0, sample_h.Gamma, 0.25 * rabi * 1.0e-6)
# pi pulse
rpol_180 = pol.rel_dpol_nut(0.0, 1.0, sample_h.Gamma, 0.50 * rabi * 1.0e-6)
assert pytest.approx([rpol_090, rpol_180], abs=1e-10) == [-1.0, -2.0]
[docs]
def test_rel_dpol_arp(sample_h):
"""Test rel_dpol_arp.
if f_fm is close to infinity, the relative change in polarization
is -2.0
if b1 and the modulation frequency is small and b_offset is large
the spin does not flip therefore the relative change in polarization
is close to 0.0 (off-resonance case)
"""
rpol_180 = pol.rel_dpol_arp(0.0, 1.0, 1e10, sample_h.Gamma)
assert np.isclose(rpol_180, -2.0)
rpol_0 = pol.rel_dpol_arp(10000.0, 0.1, 0.1, sample_h.Gamma)
assert pytest.approx(0.0, abs=5e-10) == rpol_0
[docs]
def test_rel_dpol_periodic_irrad_cont(sample_e):
"""Test rel_dpol_periodic_irrad in the continuous case.
When the if t_off is 0, the intermittent irradiation becomes continuous
irradiation. This should be the same as rel_dpol_sat
When t_on is 0, the signal should vanish
"""
# continuous
rpol_cont = pol.rel_dpol_periodic_irrad(
0,
1.0,
sample_e.dB_sat,
sample_e.dB_hom,
sample_e.T1,
t_on=10 * sample_e.T1,
t_off=0,
)
rpol = pol.rel_dpol_sat_steadystate(0, 1.0, sample_e.dB_sat, sample_e.dB_hom)
assert pytest.approx(rpol_cont) == rpol
[docs]
def test_rel_dpol_periodic_irrad_no_irrad(sample_e):
"""Test rel_dpol_periodic_irrad in no irradiation case.
When t_on is 0, the signal should vanish
"""
rpol_0 = pol.rel_dpol_periodic_irrad(
0, 1.0, sample_e.dB_sat, sample_e.dB_hom, sample_e.T1, t_on=0, t_off=2e-4
)
assert rpol_0 == 0.0
[docs]
def test_rel_dpol_periodic_irrad_off_res(sample_e):
"""Test rel_dpol_periodic_irrad off-resonance case.
When is it off-resonance (B_offset is large), the signal is 0
"""
# off-resonance case
rpol_off_res = pol.rel_dpol_periodic_irrad(
10000,
0.5,
sample_e.dB_sat,
sample_e.dB_hom,
sample_e.T1,
t_on=4e-5,
t_off=2e-4,
)
assert pytest.approx(rpol_off_res, abs=5e-10) == 0.0
[docs]
def test_rel_dpol_sat_td(sample_e):
"""Test rel_dpol_sat_td when offset is 0.
When the offset is 0, the result should be 0
Here we construct a 1D grid size of 3, and
extended grid size of 5
"""
Bzx = np.random.rand(3)
ext_B_offset = np.zeros([5])
rpol = pol.rel_dpol_sat_td(
Bzx, 1.0, ext_B_offset, 1, sample_e.Gamma, sample_e.T2, 2000
)
assert np.array_equal(rpol, [0, 0, 0])
[docs]
def test_rel_dpol_sat_td_symmetry(sample_e):
"""Test rel_dpol_sat_td is symmetric around the initial and final offset.
Here we construct a 1D grid size of 3, and an extended grid size of 5
"""
Bzx = np.random.rand(3)
ext_B_offset_a = np.array([2, 0, 0, 0, 2])
ext_B_offset_b = np.array([0, 2, 2, 2, 0])
rpol_a = pol.rel_dpol_sat_td(
Bzx, 1.0, ext_B_offset_a, 1, sample_e.Gamma, sample_e.T2, 2000
)
rpol_b = pol.rel_dpol_sat_td(
Bzx, 1.0, ext_B_offset_b, 1, sample_e.Gamma, sample_e.T2, 2000
)
assert np.array_equal(rpol_a, rpol_b)
[docs]
def test_rel_dpol_sat_td_without_td(sample_e):
"""Test rel_dpol_sat_td completely saturate spins if no td component.
Here we construct a 1D grid size of 3 and an extended grid size of 5
"""
Bzx = np.zeros(3)
ext_B_offset = np.random.rand(5)
rpol = pol.rel_dpol_sat_td(
Bzx, 1.0, ext_B_offset, 1, sample_e.Gamma, sample_e.T2, 2000
)
assert np.array_equal(rpol, [-1, -1, -1])
[docs]
def test_rel_dol_sat_td_smallsteps(sample_e):
"""Test rel_dol_sat_td_smallsteps.
Small steps approximation should have the same result as regular
when Bzx stays the same, given that delta_B_offset has the same
sign as Bzx.
"""
Bzx = np.ones(3)
ext_Bzx = np.ones(5)
ext_B_offset = np.random.rand(1) * np.array([1, 2, 3, 4, 5])
rpol_td = pol.rel_dpol_sat_td(
Bzx, 1.0, ext_B_offset, 1, sample_e.Gamma, sample_e.T2, 2000.0
)
rpol_smallsteps = pol.rel_dpol_sat_td_smallsteps(
1.0, ext_Bzx, ext_B_offset, 1, sample_e.Gamma, sample_e.T2, 2000.0
)
assert np.array_equal(rpol_td, rpol_smallsteps)
[docs]
def test_rel_dpol_multipulse_no_pol(sample_e):
"""Test rel_dpol_multipulse when relative polarization is 0."""
rpol = pol.rel_dpol_multipulse(0, sample_e.T1, 1.0)
assert rpol == 0
[docs]
def test_rel_dpol_multipulse_short(sample_e):
"""Test rel_dpol_multipulse when the pulse time difference is short.
Because the time between pulses is short and the equation ignores
relaxation during pulses,
"""
rpol = pol.rel_dpol_multipulse(-1, sample_e.T1, 0.001)
assert pytest.approx(rpol, abs=0.001) == -1
[docs]
def test_rel_dpol_multipulse_long(sample_e):
"""Test rel_dpol_multipulse when the time between pulses is long.
In this case, the final polarization should be
relaxed to 1 and the chang in polarization is 0.
"""
rpol = pol.rel_dpol_multipulse(-0.5, sample_e.T1, 500.0)
assert pytest.approx(rpol, abs=0.001) == 0