Пример #1
0
def test_MAF_lineshape_kernel():
    for dim in anisotropic_dims:
        ns_obj = ShieldingPALineshape(
            anisotropic_dimension=dim,
            inverse_dimension=inverse_dimension,
            channel="29Si",
            magnetic_flux_density="9.4 T",
            rotor_angle="90 deg",
            rotor_frequency="14 kHz",
            number_of_sidebands=1,
        )
        zeta, eta = ns_obj._get_zeta_eta(supersampling=1)
        K = ns_obj.kernel(supersampling=1)
        sim_lineshape = generate_shielding_kernel(zeta, eta, np.pi / 2, 14000,
                                                  1).T
        assert np.allclose(K, sim_lineshape, rtol=1.0e-3, atol=1e-3)

        ns_obj = MAF(
            anisotropic_dimension=dim,
            inverse_dimension=inverse_dimension,
            channel="29Si",
            magnetic_flux_density="9.4 T",
        )
        zeta, eta = ns_obj._get_zeta_eta(supersampling=1)
        K = ns_obj.kernel(supersampling=1)
        sim_lineshape = generate_shielding_kernel(zeta, eta, np.pi / 2, 14000,
                                                  1).T

        assert np.allclose(K, sim_lineshape, rtol=1.0e-3, atol=1e-3)

        _ = TSVDCompression(K, s=np.arange(96))
        assert _.truncation_index == 15
Пример #2
0
def test_spinning_sidebands_kernel():
    # 1
    for dim in anisotropic_dims:
        ns_obj = ShieldingPALineshape(
            anisotropic_dimension=dim,
            inverse_dimension=inverse_dimension,
            channel="29Si",
            magnetic_flux_density="9.4 T",
            rotor_angle="54.735 deg",
            rotor_frequency="100 Hz",
            number_of_sidebands=96,
        )
        zeta, eta = ns_obj._get_zeta_eta(supersampling=1)
        K = ns_obj.kernel(supersampling=1)
        sim_lineshape = generate_shielding_kernel(zeta, eta,
                                                  0.9553059660790962, 100,
                                                  96).T

        assert np.allclose(K, sim_lineshape, rtol=1.0e-3, atol=1e-3)

        # 2
        ns_obj = ShieldingPALineshape(
            anisotropic_dimension=dim,
            inverse_dimension=inverse_dimension_ppm,
            channel="29Si",
            magnetic_flux_density="9.4 T",
            rotor_angle="54.735 deg",
            rotor_frequency="100 Hz",
            number_of_sidebands=96,
        )
        zeta, eta = ns_obj._get_zeta_eta(supersampling=1)
        K = ns_obj.kernel(supersampling=1)
        sim_lineshape = generate_shielding_kernel(zeta,
                                                  eta,
                                                  0.9553059660790962,
                                                  100,
                                                  96,
                                                  to_ppm=False).T

        assert np.allclose(K, sim_lineshape, rtol=1.0e-3, atol=1e-3)

        # 3
        ns_obj = SpinningSidebands(
            anisotropic_dimension=dim,
            inverse_dimension=inverse_dimension,
            channel="29Si",
            magnetic_flux_density="9.4 T",
        )
        zeta, eta = ns_obj._get_zeta_eta(supersampling=1)
        K = ns_obj.kernel(supersampling=1)
        sim_lineshape = generate_shielding_kernel(zeta, eta,
                                                  0.9553059660790962, 208.33,
                                                  96).T

        assert np.allclose(K, sim_lineshape, rtol=1.0e-3, atol=1e-3)

        _ = TSVDCompression(K, s=np.arange(96))
        assert _.truncation_index == 15
Пример #3
0
# Here, ``lineshape`` is an instance of the
# :class:`~mrinversion.kernel.nmr.ShieldingPALineshape` class. The required
# arguments of this class are the `anisotropic_dimension`, `inverse_dimension`, and
# `channel`. We have already defined the first two arguments in the previous
# sub-section. The value of the `channel` argument is the nucleus observed in the MAF
# experiment. In this example, this value is '29Si'.
# The remaining arguments, such as the `magnetic_flux_density`, `rotor_angle`,
# and `rotor_frequency`, are set to match the conditions under which the 2D MAF
# spectrum was acquired. The value of the `number_of_sidebands` argument is the number
# of sidebands calculated for each line-shape within the kernel. Unless, you have a lot
# of spinning sidebands in your MAF dataset, four sidebands should be enough.
#
# Once the ShieldingPALineshape instance is created, use the
# :meth:`~mrinversion.kernel.nmr.ShieldingPALineshape.kernel` method of the
# instance to generate the MAF line-shape kernel.
K = lineshape.kernel(supersampling=1)
print(K.shape)

# %%
# The kernel ``K`` is a NumPy array of shape (128, 625), where the axes with 128 and
# 625 points are the anisotropic dimension and the features (x-y coordinates)
# corresponding to the :math:`25\times 25` `x`-`y` grid, respectively.

# %%
# Data Compression
# ''''''''''''''''
#
# Data compression is optional but recommended. It may reduce the size of the
# inverse problem and, thus, further computation time.
new_system = TSVDCompression(K, data_object_truncated)
compressed_K = new_system.compressed_K
Пример #4
0
# is the same as the physical rotor frequency. For other measurements like the extended
# chemical shift modulation sequences (XCS) [#f3]_, or its variants, the effective
# anisotropic modulation frequency is lower than the physical rotor frequency and
# should be set appropriately.
#
# The argument `number_of_sidebands` is the maximum number of computed
# sidebands in the kernel. For most two-dimensional isotropic v.s pure
# anisotropic spinning-sideband correlation measurements, the sampling along the
# sideband dimension is the rotor or the effective anisotropic modulation
# frequency. Therefore, the value of the `number_of_sidebands` argument is
# usually the number of points along the sideband dimension.
# In this example, this value is 32.
#
# Once the ShieldingPALineshape instance is created, use the kernel()
# method to generate the spinning sideband lineshape kernel.
K = sidebands.kernel(supersampling=2)
print(K.shape)

# %%
# The kernel ``K`` is a NumPy array of shape (32, 625), where the axes with 32 and
# 625 points are the spinning sidebands dimension and the features (x-y coordinates)
# corresponding to the :math:`25\times 25` `x`-`y` grid, respectively.

# %%
# Data Compression
# ''''''''''''''''
#
# Data compression is optional but recommended. It may reduce the size of the
# inverse problem and, thus, further computation time.
new_system = TSVDCompression(K, data_object_truncated)
compressed_K = new_system.compressed_K
Пример #5
0
def test_01():
    domain = "https://sandbox.zenodo.org/record/1065347/files"
    filename = f"{domain}/8lnwmg0dr7y6egk40c2orpkmmugh9j7c.csdf"
    data_object = cp.load(filename)
    data_object = data_object.real
    _ = [item.to("ppm", "nmr_frequency_ratio") for item in data_object.dimensions]

    data_object = data_object.T
    data_object_truncated = data_object[:, 155:180]

    anisotropic_dimension = data_object_truncated.dimensions[0]
    inverse_dimensions = [
        cp.LinearDimension(count=25, increment="400 Hz", label="x"),
        cp.LinearDimension(count=25, increment="400 Hz", label="y"),
    ]

    lineshape = ShieldingPALineshape(
        anisotropic_dimension=anisotropic_dimension,
        inverse_dimension=inverse_dimensions,
        channel="29Si",
        magnetic_flux_density="9.4 T",
        rotor_angle="87.14°",
        rotor_frequency="14 kHz",
        number_of_sidebands=4,
    )
    K = lineshape.kernel(supersampling=2)

    new_system = TSVDCompression(K, data_object_truncated)
    compressed_K = new_system.compressed_K
    compressed_s = new_system.compressed_s

    assert new_system.truncation_index == 87

    s_lasso = SmoothLasso(
        alpha=2.07e-7, lambda1=7.85e-6, inverse_dimension=inverse_dimensions
    )
    s_lasso.fit(K=compressed_K, s=compressed_s)
    f_sol = s_lasso.f

    residuals = s_lasso.residuals(K=K, s=data_object_truncated)

    # assert np.allclose(residuals.mean().value, 0.00048751)
    np.testing.assert_almost_equal(residuals.std().value, 0.00336372, decimal=2)

    f_sol /= f_sol.max()
    [item.to("ppm", "nmr_frequency_ratio") for item in f_sol.dimensions]

    Q4_region = f_sol[0:8, 0:8, 3:18]
    Q4_region.description = "Q4 region"

    Q3_region = f_sol[0:8, 11:22, 8:20]
    Q3_region.description = "Q3 region"

    # Analysis
    int_Q4 = stats.integral(Q4_region)  # volume of the Q4 distribution
    mean_Q4 = stats.mean(Q4_region)  # mean of the Q4 distribution
    std_Q4 = stats.std(Q4_region)  # standard deviation of the Q4 distribution

    int_Q3 = stats.integral(Q3_region)  # volume of the Q3 distribution
    mean_Q3 = stats.mean(Q3_region)  # mean of the Q3 distribution
    std_Q3 = stats.std(Q3_region)  # standard deviation of the Q3 distribution

    np.testing.assert_almost_equal(
        (100 * int_Q4 / (int_Q4 + int_Q3)).value, 60.45388973909665, decimal=1
    )

    np.testing.assert_almost_equal(
        np.asarray([mean_Q4[0].value, mean_Q4[1].value, mean_Q4[2].value]),
        np.asarray([8.604842824865958, 9.05845796147297, -103.6976331077773]),
        decimal=0,
    )

    np.testing.assert_almost_equal(
        np.asarray([mean_Q3[0].value, mean_Q3[1].value, mean_Q3[2].value]),
        np.asarray([10.35036818411856, 79.02481579085152, -90.58326773441284]),
        decimal=0,
    )

    np.testing.assert_almost_equal(
        np.asarray([std_Q4[0].value, std_Q4[1].value, std_Q4[2].value]),
        np.asarray([4.525457744683861, 4.686253809896416, 5.369228151035292]),
        decimal=0,
    )

    np.testing.assert_almost_equal(
        np.asarray([std_Q3[0].value, std_Q3[1].value, std_Q3[2].value]),
        np.asarray([6.138761032132587, 7.837190479891721, 4.210912435356488]),
        decimal=0,
    )