Beispiel #1
0
def pre_setup(isotope, shift, reference_offset):
    spin_system = SpinSystem(
        sites=[Site(isotope=isotope, isotropic_chemical_shift=shift)])
    method = Method.parse_dict_with_units(
        dict(
            channels=[isotope],
            spectral_dimensions=[{
                "count":
                2048,
                "spectral_width":
                "25 kHz",
                "reference_offset":
                f"{reference_offset} Hz",
                "events": [{
                    "magnetic_flux_density": "9.4 T",
                    "transition_queries": [{
                        "ch1": {
                            "P": [-1]
                        }
                    }],
                }],
            }],
        ))
    sim = Simulator()
    sim.spin_systems.append(spin_system)
    sim.methods = [method]
    sim.run()
    x, y = sim.methods[0].simulation.to_list()
    return x[np.argmax(y)], abs(x[1] - x[0])
Beispiel #2
0
def test_method_exp_sim():
    spin_system = SpinSystem(sites=[
        Site(
            isotope="27Al",
            isotropic_chemical_shift=64.5,  # in ppm
            quadrupolar={
                "Cq": 3.22e6,
                "eta": 0.66
            },  # Cq is in Hz
        )
    ])

    data = cp.as_csdm(np.random.rand(1024, 512))
    method = ThreeQ_VAS(
        channels=["27Al"],
        magnetic_flux_density=7,
        spectral_dimensions=[
            {
                "count": 1024,
                "spectral_width": 5000,
                "reference_offset": -3e3
            },
            {
                "count": 512,
                "spectral_width": 10000,
                "reference_offset": 4e3
            },
        ],
        experiment=data,
    )

    sim = Simulator()
    sim.spin_systems = [spin_system]
    sim.methods = [method]
    sim.run()
Beispiel #3
0
def setup_test(spin_system, volume="octant", sw=25000, n_gamma=500):
    mth_kwargs = {
        "channels": [spin_system.sites[0].isotope.symbol],
        "spectral_dimensions": [{
            "count": 1024,
            "spectral_width": sw
        }],
    }

    data = []
    for angle in [0, 54.735, 90]:
        method = BlochDecaySpectrum(rotor_angle=angle * np.pi / 180,
                                    rotor_frequency=0,
                                    **mth_kwargs)
        sim = Simulator(spin_systems=[spin_system], methods=[method])
        sim.config.integration_volume = volume
        sim.config.number_of_gamma_angles = 1 if angle == 0 else n_gamma
        sim.run(auto_switch=False)

        res = sim.methods[0].simulation.y[0].components[0]
        res /= res.max()
        data.append(res)

    # plt.plot(data[0])
    # plt.plot(data[1], "--")
    # plt.plot(data[2], "-.")
    # plt.show()

    np.testing.assert_almost_equal(data[0], data[1], decimal=2)
    np.testing.assert_almost_equal(data[0], data[2], decimal=1.6)
Beispiel #4
0
def setup():
    site = Site(isotope="1H", shielding_symmetric={"zeta": -100, "eta": 0.3})
    spin_sys = SpinSystem(sites=[site, site], abundance=45)

    method = BlochDecaySpectrum(channels=["1H"])
    sim = Simulator(spin_systems=[spin_sys, spin_sys],
                    methods=[method, method])

    sim.run(method_index=0)
    sim.methods[0].simulation._timestamp = None

    processor = sp.SignalProcessor(operations=[
        sp.IFFT(),
        sp.apodization.Exponential(FWHM="2500 Hz"),
        sp.FFT(),
        sp.Scale(factor=20),
    ])
    processors = [processor] * 2

    application = {
        "com.github.DeepanshS.mrsimulator": {
            "foo": "This is some metadata"
        },
        "com.github.DeepanshS.mrsimulator-app": {
            "params": "The JSON string of params"
        },
    }

    return sim, processors, application
def test_empty_spin_sys_simulator():
    sim = Simulator()
    sim.methods = [
        BlochDecaySpectrum(channels=["1H"], spectral_dimensions=[{"count": 10}])
    ]
    sim.config.decompose_spectrum = "spin_system"
    sim.run()
    assert np.allclose(sim.methods[0].simulation.y[0].components[0], 0)
Beispiel #6
0
def process_spectrum(method):
    spin_system = setup_spin_system()

    sim = Simulator(spin_systems=[spin_system], methods=[method])
    sim.config.integration_volume = "hemisphere"
    sim.run()

    data = sim.methods[0].simulation.y[0].components[0]
    data /= data.max()
    return data
Beispiel #7
0
def bestfit(sim: Simulator, processors: list = None):
    """Return a list of best fit spectrum ordered relative to the methods in the
    simulator object.

    Args:
        Simulator sim: The simulator object.
        list processors: List of SignalProcessor objects ordered according to the
            methods in the simulator object.
    """
    processors = processors if isinstance(processors, list) else [processors]
    sim.run()

    return [
        proc.apply_operations(data=mth.simulation).real
        for mth, proc in zip(sim.methods, processors)
    ]
def test_read_write_methods():
    for item in methods:
        kwargs = {
            "channels": ["93Nb"],
            "spectral_dimensions": [{
                "count": 1024,
                "spectral_width": 100
            } for _ in range(item.ndim)],
        }

        if item.__name__ == "SSB2D":
            kwargs["rotor_frequency"] = 1e3

        fn1 = item(**kwargs)

        # Parse against self
        assert_parsing(item, fn1)

        # Parse against Method class
        assert_parsing(Method, fn1)

        # Parse against Method1D/Method2D classes
        mth_d = Method1D if item.ndim == 1 else Method2D
        assert_parsing(mth_d, fn1)

        # save test
        sim = Simulator(spin_systems=[sys], methods=[fn1])

        # save/load with units
        sim.run()
        sim.save("test.mrsim")
        sim2 = Simulator.load("test.mrsim")
        check_sim_save(sim, sim2, "with units")

        # save/load with out units
        sim.run()
        sim.save("test.mrsim", with_units=False)
        sim2 = Simulator.load("test.mrsim", parse_units=False)
        check_sim_save(sim, sim2, "without units")

        # save/load methods
        sim.run()
        sim.export_methods("test.mrmtd")
        sim2 = sim.copy()
        sim2.load_methods("test.mrmtd")
        check_methods_save_load(sim, sim2)

        # save/load spin systems
        sim.run()
        sim.export_spin_systems("test.mrsys")
        sim2 = sim.copy()
        sim2.load_spin_systems("test.mrsys")
        assert sim.spin_systems == sim2.spin_systems

    os.remove("test.mrsim")
    os.remove("test.mrsys")
    os.remove("test.mrmtd")
Beispiel #9
0
def test_two_site_no_coupling_test():
    site1 = Site(
        isotope="29Si",
        isotropic_chemical_shift=10,
        shielding_symmetric={
            "zeta": 5,
            "eta": 0
        },
    )
    site2 = Site(
        isotope="29Si",
        isotropic_chemical_shift=-10,
        shielding_symmetric={
            "zeta": -5,
            "eta": 0
        },
    )

    iso_two_site = [SpinSystem(sites=[site1, site2])]
    iso_single_sites = [SpinSystem(sites=[site1]), SpinSystem(sites=[site2])]

    sim1 = Simulator()
    sim1.spin_systems += iso_two_site
    sim1.methods += [
        BlochDecaySpectrum(
            channels=["29Si"],
            spectral_dimensions=[dict(count=2048, spectral_width=25000)],
        )
    ]
    sim1.run()

    sim2 = Simulator()
    sim2.spin_systems += iso_single_sites
    sim2.methods += [
        BlochDecaySpectrum(
            channels=["29Si"],
            spectral_dimensions=[dict(count=2048, spectral_width=25000)],
        )
    ]
    sim2.run()

    data1 = (sim1.methods[0].simulation / 2).y[0].components
    data2 = sim2.methods[0].simulation.y[0].components
    assert np.allclose(data1, data2)
def setup():
    site = Site(isotope="1H", shielding_symmetric={"zeta": -100, "eta": 0.3})
    spin_sys = SpinSystem(sites=[site, site], abundance=45)

    method = BlochDecaySpectrum(channels=["1H"])
    sim = Simulator(spin_systems=[spin_sys, spin_sys],
                    methods=[method, method])

    sim.run(method_index=0)

    processor = sp.SignalProcessor(operations=[
        sp.IFFT(),
        sp.apodization.Exponential(FWHM="2500 Hz"),
        sp.FFT(),
        sp.Scale(factor=20),
    ])
    processors = [processor] * 2

    return sim, processors
Beispiel #11
0
def generate_shielding_kernel(zeta_,
                              eta_,
                              angle,
                              freq,
                              n_sidebands,
                              to_ppm=True):
    method = BlochDecaySpectrum(
        channels=["29Si"],
        magnetic_flux_density=9.4,
        spectral_dimensions=[
            dict(count=96, spectral_width=208.33 * 96, reference_offset=0)
        ],
        rotor_angle=angle,
        rotor_frequency=freq,
    )
    if to_ppm:
        larmor_frequency = -method.channels[
            0].gyromagnetic_ratio * 9.4  # in MHz
        zeta_ /= larmor_frequency

    spin_systems = [
        SpinSystem(sites=[
            Site(isotope="29Si", shielding_symmetric={
                "zeta": z,
                "eta": e
            })
        ]) for z, e in zip(zeta_, eta_)
    ]

    sim = Simulator()
    sim.spin_systems = spin_systems
    sim.methods = [method]
    sim.config.decompose_spectrum = "spin_system"
    sim.config.number_of_sidebands = n_sidebands
    sim.run(pack_as_csdm=False)
    sim_lineshape = sim.methods[0].simulation.real
    sim_lineshape = np.asarray(sim_lineshape).reshape(4, 4, 96)
    sim_lineshape = sim_lineshape / sim_lineshape[0, 0].sum()
    sim_lineshape[0, :, :] /= 2.0
    sim_lineshape[:, 0, :] /= 2.0
    sim_lineshape.shape = (16, 96)
    return sim_lineshape
def test_simulator_2():
    sim = Simulator()
    sim.spin_systems = [
        SpinSystem(
            sites=[Site(isotope="1H"),
                   Site(isotope="23Na")],
            couplings=[Coupling(site_index=[0, 1], isotropic_j=15)],
        )
    ]
    sim.methods = [
        BlochDecaySpectrum(
            channels=["1H"],
            spectral_dimensions=[{
                "count": 10
            }],
            experiment=cp.as_csdm(np.arange(10)),
        )
    ]
    sim.name = "test"
    sim.label = "test0"
    sim.description = "testing-testing 1.2.3"

    sim.run()

    # save
    sim.save("test_sim_save.temp")
    sim_load = Simulator.load("test_sim_save.temp")

    sim_load_data = sim_load.methods[0].simulation
    sim_data = sim.methods[0].simulation
    sim_load_data._timestamp = ""
    assert sim_load_data.dict() == sim_data.dict()

    sim_load.methods[0].simulation = None
    sim.methods[0].simulation = None
    assert sim_load.spin_systems == sim.spin_systems
    assert sim_load.methods == sim.methods
    assert sim_load.name == sim.name
    assert sim_load.description == sim.description

    os.remove("test_sim_save.temp")
Beispiel #13
0
def LMFIT_min_function(params: Parameters,
                       sim: Simulator,
                       processors: list = None,
                       sigma: list = None):
    """The simulation routine to calculate the vector difference between simulation and
    experiment based on the parameters update.

    Args:
        params: Parameters object containing parameters for OLS minimization.
        sim: Simulator object.
        processors: A list of PostSimulator objects corresponding to the methods in the
            Simulator object.
        sigma: A list of standard deviations corresponding to the experiments in the
            Simulator.methods attribute
    Returns:
        Array of the differences between the simulation and the experimental data.
    """
    processors = processors if isinstance(processors, list) else [processors]
    sigma = [1.0 for _ in sim.methods] if sigma is None else sigma
    sigma = sigma if isinstance(sigma, list) else [sigma]

    update_mrsim_obj_from_params(params, sim, processors)

    sim.run()

    processed_data = [
        item.apply_operations(data=data.simulation)
        for item, data in zip(processors, sim.methods)
    ]

    diff = np.asarray([])
    for processed_datum, mth, sigma_ in zip(processed_data, sim.methods,
                                            sigma):
        datum = 0
        for decomposed_datum in processed_datum.y:
            datum += decomposed_datum.components[0].real

        exp_data = get_correct_data_order(mth)
        diff = np.append(diff, (exp_data - datum) / sigma_)
    return diff
Beispiel #14
0
    def kernel(self, supersampling=1):
        """
        Return the NMR nuclear shielding anisotropic line-shape kernel.

        Args:
            supersampling: An integer. Each cell is supersampled by the factor
                    `supersampling` along every dimension.
        Returns:
            A numpy array containing the line-shape kernel.
        """
        args_ = deepcopy(self.method_args)
        method = BlochDecaySpectrum.parse_dict_with_units(args_)
        isotope = args_["channels"][0]
        zeta, eta = self._get_zeta_eta(supersampling)

        x_csdm = self.inverse_kernel_dimension[0]
        if x_csdm.coordinates.unit.physical_type == "frequency":
            # convert zeta to ppm if given in frequency units.
            zeta /= self.larmor_frequency  # zeta in ppm

            for dim_i in self.inverse_kernel_dimension:
                if dim_i.origin_offset.value == 0:
                    dim_i.origin_offset = f"{abs(self.larmor_frequency)} MHz"

        spin_systems = [
            SpinSystem(sites=[
                dict(isotope=isotope, shielding_symmetric=dict(zeta=z, eta=e))
            ]) for z, e in zip(zeta, eta)
        ]

        sim = Simulator()
        sim.config.number_of_sidebands = self.number_of_sidebands
        sim.config.decompose_spectrum = "spin_system"

        sim.spin_systems = spin_systems
        sim.methods = [method]
        sim.run(pack_as_csdm=False)

        amp = sim.methods[0].simulation.real
        return self._averaged_kernel(amp, supersampling)
Beispiel #15
0
    spectral_dimensions=spectral_dims,
    experiment=experiment,  # add the measurement to the method.
)

# Optimize the script by pre-setting the transition pathways for each spin system from
# the method.
for sys in spin_systems:
    sys.transition_pathways = MAS_CT.get_transition_pathways(sys)

# %%
# **Guess Model Spectrum**

# Simulation
# ----------
sim = Simulator(spin_systems=spin_systems, methods=[MAS_CT])
sim.run()

# Post Simulation Processing
# --------------------------
processor = sp.SignalProcessor(operations=[
    sp.IFFT(),
    sp.apodization.Exponential(FWHM="100 Hz"),
    sp.FFT(),
    sp.Scale(factor=200),
])
processed_dataset = processor.apply_operations(
    dataset=sim.methods[0].simulation).real

# Plot of the guess Spectrum
# --------------------------
plt.figure(figsize=(4.25, 3.0))
dimension = {
    "magnetic_flux_density": "9.4 T",
    "rotor_frequency": "0 kHz",
    "rotor_angle": "54.735 deg",
    "number_of_points": 2048,
    "spectral_width": "25 kHz",
    "reference_offset": "0 Hz",
    "isotope": "1H",
}

sim = Simulator()
sim.isotopomers = [Isotopomer.parse_dict_with_units(item) for item in isotopomers]
sim.dimensions = [Dimension.parse_dict_with_units(dimension)]

freq1, amp1 = sim.run(one_d_spectrum)

# spinning sideband simulation
# set the rotor frequency to 1000 Hz
sim.dimensions[0].rotor_frequency = 1000
freq2, amp2 = sim.run(one_d_spectrum)

fig, ax = plt.subplots(1, 2, figsize=(6, 3))
ax[0].plot(freq1, amp1, linewidth=1.0, color="k")
ax[0].set_xlabel(f"frequency ratio / {freq2.unit}")
ax[0].grid(color="gray", linestyle="--", linewidth=0.5, alpha=0.5)
ax[0].set_title("Static")
ax[1].plot(freq2, amp2, linewidth=1.0, color="k")
ax[1].set_xlabel(f"frequency ratio / {freq2.unit}")
ax[1].grid(color="gray", linestyle="--", linewidth=0.5, alpha=0.5)
ax[1].set_title("MAS")
Beispiel #17
0
def SSB2D_setup(ist, vr, method_type):
    sites = [
        Site(
            isotope=ist,
            isotropic_chemical_shift=29,
            shielding_symmetric={
                "zeta": -70,
                "eta": 0.000
            },
        ),
        Site(
            isotope=ist,
            isotropic_chemical_shift=44,
            shielding_symmetric={
                "zeta": -96,
                "eta": 0.166
            },
        ),
        Site(
            isotope=ist,
            isotropic_chemical_shift=57,
            shielding_symmetric={
                "zeta": -120,
                "eta": 0.168
            },
        ),
    ]
    spin_systems = [SpinSystem(sites=[s]) for s in sites]

    B0 = 11.7
    if method_type == "PASS":
        method = SSB2D(
            channels=[ist],
            magnetic_flux_density=B0,  # in T
            rotor_frequency=vr,
            spectral_dimensions=[
                {
                    "count": 32,
                    "spectral_width": 32 * vr,  # in Hz
                    "label": "Anisotropic dimension",
                },
                # The last spectral dimension block is the direct-dimension
                {
                    "count": 2048,
                    "spectral_width": 2e4,  # in Hz
                    "reference_offset": 5e3,  # in Hz
                    "label": "Fast MAS dimension",
                },
            ],
        )
    else:
        method = Method2D(
            channels=[ist],
            magnetic_flux_density=B0,  # in T
            spectral_dimensions=[
                {
                    "count": 64,
                    "spectral_width": 8e4,  # in Hz
                    "label": "Anisotropic dimension",
                    "events": [{
                        "rotor_angle": 90 * 3.14159 / 180
                    }],
                },
                # The last spectral dimension block is the direct-dimension
                {
                    "count": 2048,
                    "spectral_width": 2e4,  # in Hz
                    "reference_offset": 5e3,  # in Hz
                    "label": "Fast MAS dimension",
                },
            ],
            affine_matrix=[[1, -1], [0, 1]],
        )
    sim = Simulator()
    sim.spin_systems = spin_systems  # add spin systems
    sim.methods = [method]  # add the method.
    sim.run()

    data_ssb = sim.methods[0].simulation
    dim_ssb = data_ssb.x[0].coordinates.value

    if method_type == "PASS":
        bloch = BlochDecaySpectrum(
            channels=[ist],
            magnetic_flux_density=B0,  # in T
            rotor_frequency=vr,  # in Hz
            spectral_dimensions=[
                {
                    "count": 32,
                    "spectral_width": 32 * vr,  # in Hz
                    "reference_offset": 0,  # in Hz
                    "label": "MAS dimension",
                },
            ],
        )
    else:
        bloch = BlochDecaySpectrum(
            channels=[ist],
            magnetic_flux_density=B0,  # in T
            rotor_frequency=vr,  # in Hz
            rotor_angle=90 * 3.14159 / 180,
            spectral_dimensions=[
                {
                    "count": 64,
                    "spectral_width": 8e4,  # in Hz
                    "reference_offset": 0,  # in Hz
                    "label": "MAS dimension",
                },
            ],
        )

    for i in range(3):
        iso = spin_systems[i].sites[0].isotropic_chemical_shift
        sys = spin_systems[i].copy()
        sys.sites[0].isotropic_chemical_shift = 0
        sim2 = Simulator()
        sim2.spin_systems = [sys]  # add spin systems
        sim2.methods = [bloch]  # add the method.
        sim2.run()

        index = np.where(dim_ssb < iso)[0][-1]

        one_d_section = data_ssb.y[0].components[0][:, index]
        one_d_section /= one_d_section.max()

        one_d_sim = sim2.methods[0].simulation.y[0].components[0]
        one_d_sim /= one_d_sim.max()

        np.testing.assert_almost_equal(one_d_section, one_d_sim, decimal=6)
Beispiel #18
0
def test_MQMAS_spin_5halves():
    spin_system = SpinSystem(sites=[
        Site(
            isotope="27Al",
            isotropic_chemical_shift=64.5,  # in ppm
            quadrupolar={
                "Cq": 3.22e6,
                "eta": 0.66
            },  # Cq is in Hz
        )
    ])

    method = ThreeQ_VAS(
        channels=["27Al"],
        magnetic_flux_density=7,
        spectral_dimensions=[
            {
                "count": 1024,
                "spectral_width": 5000,
                "reference_offset": -3e3
            },
            {
                "count": 512,
                "spectral_width": 10000,
                "reference_offset": 4e3
            },
        ],
    )

    sim = Simulator()
    sim.spin_systems = [spin_system]
    sim.methods = [method]
    sim.run()

    data = sim.methods[0].simulation
    dat = data.y[0].components[0]
    index = np.where(dat == dat.max())[0]

    # The isotropic coordinate of this peak is given by
    # v_iso = -(17/31)*iso_shift + 8e6/93 * (vq/v0)^2 * (eta^2 / 3 + 1)
    # ref: D. Massiot et al. / Solid State Nuclear Magnetic Resonance 6 (1996) 73-83
    spin = method.channels[0].spin
    v0 = method.channels[0].gyromagnetic_ratio * 7 * 1e6
    vq = 3 * 3.22e6 / (2 * spin * (2 * spin - 1))
    v_iso = -(17 / 31) * 64.5 - (8e6 / 93) * (vq / v0)**2 * ((0.66**2) / 3 + 1)

    # the coordinate from spectrum along the iso dimension must be equal to v_iso
    v_iso_spectrum = data.x[1].coordinates[index[0]].value
    np.testing.assert_almost_equal(v_iso, v_iso_spectrum, decimal=2)

    # The projection onto the  MAS dimension should be the 1D block decay central
    # transition spectrum
    mas_slice = data.sum(axis=1).y[0].components[0]

    # MAS spectrum
    method = BlochDecayCTSpectrum(
        channels=["27Al"],
        magnetic_flux_density=7,
        rotor_frequency=1e9,
        spectral_dimensions=[{
            "count": 512,
            "spectral_width": 10000,
            "reference_offset": 4e3
        }],
    )

    sim = Simulator()
    sim.spin_systems = [spin_system]
    sim.methods = [method]
    sim.config.integration_volume = "hemisphere"
    sim.run()

    data = sim.methods[0].simulation.y[0].components[0]
    assert np.allclose(data / data.max(), mas_slice / mas_slice.max())
Beispiel #19
0
def test_MQMAS():
    site = Site(
        isotope="87Rb",
        isotropic_chemical_shift=-9,
        shielding_symmetric={
            "zeta": 100,
            "eta": 0
        },
        quadrupolar={
            "Cq": 3.5e6,
            "eta": 0.36,
            "beta": 70 / 180 * np.pi
        },
    )
    spin_system = SpinSystem(sites=[site])

    method = Method2D(
        channels=["87Rb"],
        magnetic_flux_density=9.4,
        spectral_dimensions=[
            {
                "count": 128,
                "spectral_width": 20000,
                "events": [{
                    "transition_query": [{
                        "P": [-3],
                        "D": [0]
                    }]
                }],
            },
            {
                "count": 128,
                "spectral_width": 20000,
                "events": [{
                    "transition_query": [{
                        "P": [-1],
                        "D": [0]
                    }]
                }],
            },
        ],
    )

    sim = Simulator()
    sim.spin_systems = [spin_system]
    sim.methods = [method]
    sim.config.integration_volume = "hemisphere"
    sim.run()

    # process
    k = 21 / 27  # shear factor
    processor = sp.SignalProcessor(operations=[
        sp.IFFT(dim_index=1),
        aft.Shear(factor=-k, dim_index=1, parallel=0),
        aft.Scale(factor=1 + k, dim_index=1),
        sp.FFT(dim_index=1),
    ])
    processed_data = processor.apply_operations(
        data=sim.methods[0].simulation).real

    # Since there is a single site, after the shear and scaling transformations, there
    # should be a single perak along the isotropic dimension at index 70.
    # The isotropic coordinate of this peak is given by
    # w_iso = (17.8)*iso_shift + 1e6/8 * (vq/v0)^2 * (eta^2 / 3 + 1)
    # ref: D. Massiot et al. / Solid State Nuclear Magnetic Resonance 6 (1996) 73-83
    iso_slice = processed_data[40, :]
    assert np.argmax(iso_slice.y[0].components[0]) == 70

    # calculate the isotropic coordinate
    spin = method.channels[0].spin
    w0 = method.channels[0].gyromagnetic_ratio * 9.4 * 1e6
    wq = 3 * 3.5e6 / (2 * spin * (2 * spin - 1))
    w_iso = -9 * 17 / 8 + 1e6 / 8 * (wq / w0)**2 * ((0.36**2) / 3 + 1)

    # the coordinate from spectrum
    w_iso_spectrum = processed_data.x[1].coordinates[70].value
    np.testing.assert_almost_equal(w_iso, w_iso_spectrum, decimal=2)

    # The projection onto the  MAS dimension should be the 1D block decay central
    # transition spectrum
    mas_slice = processed_data.sum(axis=1).y[0].components[0]

    # MAS spectrum
    method = BlochDecayCTSpectrum(
        channels=["87Rb"],
        magnetic_flux_density=9.4,
        rotor_frequency=1e9,
        spectral_dimensions=[{
            "count": 128,
            "spectral_width": 20000
        }],
    )

    sim = Simulator()
    sim.spin_systems = [spin_system]
    sim.methods = [method]
    sim.config.integration_volume = "hemisphere"
    sim.run()

    data = sim.methods[0].simulation.y[0].components[0]
    np.testing.assert_almost_equal(data / data.max(),
                                   mas_slice / mas_slice.max(),
                                   decimal=2,
                                   err_msg="not equal")
Beispiel #20
0
def test_ThreeQ_VAS_spin_3halves():
    site = Site(
        isotope="87Rb",
        isotropic_chemical_shift=-9,
        shielding_symmetric={
            "zeta": 100,
            "eta": 0
        },
        quadrupolar={
            "Cq": 3.5e6,
            "eta": 0.36,
            "beta": 70 / 180 * np.pi
        },
    )
    spin_system = SpinSystem(sites=[site])

    method = ThreeQ_VAS(
        channels=["87Rb"],
        magnetic_flux_density=9.4,
        spectral_dimensions=[
            {
                "count": 1024,
                "spectral_width": 20000
            },
            {
                "count": 512,
                "spectral_width": 20000
            },
        ],
    )
    sim = Simulator()
    sim.spin_systems = [spin_system]
    sim.methods = [method]
    sim.config.integration_volume = "hemisphere"
    sim.run()

    data = sim.methods[0].simulation
    dat = data.y[0].components[0]
    index = np.where(dat == dat.max())[0]

    # The isotropic coordinate of this peak is given by
    # v_iso = (17/8)*iso_shift + 1e6/8 * (vq/v0)^2 * (eta^2 / 3 + 1)
    # ref: D. Massiot et al. / Solid State Nuclear Magnetic Resonance 6 (1996) 73-83
    spin = method.channels[0].spin
    v0 = method.channels[0].gyromagnetic_ratio * 9.4 * 1e6
    vq = (3 * 3.5e6) / (2 * spin * (2 * spin - 1))
    v_iso = -9 * 17 / 8 + 1e6 / 8 * ((vq / v0)**2) * ((0.36**2) / 3 + 1)

    # the coordinate from spectrum along the iso dimension must be equal to v_iso
    v_iso_spectrum = data.x[1].coordinates[index[0]].value
    np.testing.assert_almost_equal(v_iso, v_iso_spectrum, decimal=2)

    # The projection onto the  MAS dimension should be the 1D block decay central
    # transition spectrum
    mas_slice = data.sum(axis=1).y[0].components[0]

    # MAS spectrum
    method = BlochDecayCTSpectrum(
        channels=["87Rb"],
        magnetic_flux_density=9.4,
        rotor_frequency=1e9,
        spectral_dimensions=[{
            "count": 512,
            "spectral_width": 20000
        }],
    )

    sim = Simulator()
    sim.spin_systems = [spin_system]
    sim.methods = [method]
    sim.config.integration_volume = "hemisphere"
    sim.run()

    data = sim.methods[0].simulation.y[0].components[0]
    assert np.allclose(data / data.max(), mas_slice / mas_slice.max())
def simulator(method, j_coup, dipole):
    system = coupled_spin_system(j_coup, dipole)
    sim = Simulator(spin_systems=[system], methods=[method])
    sim.run()
    return sim.methods[0].simulation.real.y[0].components[0]
Beispiel #22
0
def test_2D():
    site_Ni = Site(
        isotope="2H",
        isotropic_chemical_shift=-97,  # in ppm
        shielding_symmetric=dict(
            zeta=-551,
            eta=0.12,
            alpha=62 * np.pi / 180,
            beta=114 * np.pi / 180,
            gamma=171 * np.pi / 180,
        ),
        quadrupolar=dict(Cq=77.2e3, eta=0.9),  # Cq in Hz
    )
    spin_system = SpinSystem(sites=[site_Ni])

    data = []
    for angle, n_gamma in zip([0, np.pi / 4], [1, 500]):
        shifting_d = Method(
            name="Shifting-d",
            channels=["2H"],
            magnetic_flux_density=9.395,  # in T
            rotor_frequency=0,  # in Hz
            rotor_angle=angle,  # in Hz
            spectral_dimensions=[
                SpectralDimension(
                    count=512,
                    spectral_width=2.5e5,  # in Hz
                    label="Quadrupolar frequency",
                    events=[
                        SpectralEvent(
                            transition_queries=[{
                                "ch1": {
                                    "P": [-1]
                                }
                            }],
                            freq_contrib=["Quad1_2"],
                        ),
                        MixingEvent(query="NoMixing"),
                    ],
                ),
                SpectralDimension(
                    count=256,
                    spectral_width=2e5,  # in Hz
                    reference_offset=2e4,  # in Hz
                    label="Paramagnetic shift",
                    events=[
                        SpectralEvent(
                            transition_queries=[{
                                "ch1": {
                                    "P": [-1]
                                }
                            }],
                            freq_contrib=["Shielding1_0", "Shielding1_2"],
                        )
                    ],
                ),
            ],
        )

        sim = Simulator(spin_systems=[spin_system], methods=[shifting_d])
        sim.config.integration_volume = "hemisphere"
        sim.config.number_of_gamma_angles = n_gamma
        sim.run(auto_switch=False)

        res = sim.methods[0].simulation.y[0].components[0]
        data.append(res / res.max())

    # _, ax = plt.subplots(1, 2)
    # ax[0].imshow(data[0].real)
    # ax[1].imshow(data[1].real)
    # plt.show()

    np.testing.assert_almost_equal(data[0], data[1], decimal=1.8)
Beispiel #23
0
def test_DAS():
    B0 = 11.7
    das = Method2D(
        channels=["17O"],
        magnetic_flux_density=B0,  # in T
        spectral_dimensions=[
            {
                "count":
                912,
                "spectral_width":
                5e3,  # in Hz
                "reference_offset":
                0,  # in Hz
                "label":
                "DAS isotropic dimension",
                "events": [
                    {
                        "fraction": 0.5,
                        "rotor_angle": 37.38 * 3.14159 / 180
                    },
                    {
                        "fraction": 0.5,
                        "rotor_angle": 79.19 * 3.14159 / 180
                    },
                ],
            },
            # The last spectral dimension block is the direct-dimension
            {
                "count": 2048,
                "spectral_width": 2e4,  # in Hz
                "reference_offset": 0,  # in Hz
                "label": "MAS dimension",
                "events": [{
                    "rotor_angle": 54.735 * 3.14159 / 180
                }],
            },
        ],
    )

    sim = Simulator()
    sim.spin_systems = spin_systems  # add spin systems
    sim.methods = [das]  # add the method.
    sim.config.decompose_spectrum = "spin_system"
    sim.run(pack_as_csdm=False)

    data_das = sim.methods[0].simulation
    data_das_coords_ppm = das.spectral_dimensions[0].coordinates_ppm()

    # Bloch decay central transition method
    bloch = BlochDecayCentralTransitionSpectrum(
        channels=["17O"],
        magnetic_flux_density=B0,  # in T
        rotor_frequency=1e9,  # in Hz
        rotor_angle=54.735 * 3.14159 / 180,
        spectral_dimensions=[
            {
                "count": 2048,
                "spectral_width": 2e4,  # in Hz
                "reference_offset": 0,  # in Hz
                "label": "MAS dimension",
            },
        ],
    )

    sim = Simulator()
    sim.spin_systems = spin_systems
    sim.methods = [bloch]
    sim.config.decompose_spectrum = "spin_system"
    sim.run(pack_as_csdm=False)

    data_bloch = sim.methods[0].simulation

    larmor_freq = das.channels[0].gyromagnetic_ratio * B0 * 1e6
    spin = das.channels[0].spin
    for i, sys in enumerate(spin_systems):
        for site in sys.sites:
            Cq = site.quadrupolar.Cq
            eta = site.quadrupolar.eta
            iso = site.isotropic_chemical_shift
            factor1 = -(3 / 40) * (Cq / larmor_freq)**2
            factor2 = (spin * (spin + 1) - 3 / 4) / (spin**2 *
                                                     (2 * spin - 1)**2)
            factor3 = 1 + (eta**2) / 3
            iso_obs = factor1 * factor2 * factor3 * 1e6 + iso

            # get the index where there is a signal
            id1 = data_das[i] / data_das[i].max()
            index = np.where(id1 == id1.max())[0]
            iso_spectrum = data_das_coords_ppm[
                index[0]]  # x[1].coords[index[0]]

            # test for the position of isotropic peaks.
            np.testing.assert_almost_equal(iso_obs, iso_spectrum, decimal=1)

            # test for the spectrum across the isotropic peaks.
            data_bloch_i = data_bloch[i] / data_bloch[i].max()
            assert np.allclose(id1[index[0]], data_bloch_i)
            "count": 256,
            "spectral_width": 5e3,  # in Hz
            "reference_offset": -2.5e3,  # in Hz
            "label": "Isotropic dimension",
        },
        # The last spectral dimension block is the direct-dimension
        {
            "count": 256,
            "spectral_width": 2e4,  # in Hz
            "reference_offset": 0,  # in Hz
            "label": "MAS dimension",
        },
    ],
)
sim.methods = [method]  # add the method.
sim.run()  # Run the simulation

# %%
# The plot of the simulation.
data = sim.methods[0].simulation
ax = plt.subplot(projection="csdm")
cb = ax.imshow(data / data.max(), aspect="auto", cmap="gist_ncar_r")
plt.colorbar(cb)
ax.invert_xaxis()
ax.invert_yaxis()
plt.tight_layout()
plt.show()

# %%
# Add post-simulation signal processing.
processor = sp.SignalProcessor(
def test_read_write_methods():
    def assert_parsing(method, fn1):
        fn2 = method.parse_dict_with_units(fn1.json())
        assert fn1 == fn2, f"Error with {method} parse with units."

        fn3 = method(**fn1.json(units=False))
        assert fn1 == fn3, f"Error with {method} parse with units."

        event_error = "Event objects are immutable for"
        serialize = fn1.json()
        ent = serialize["spectral_dimensions"][0]["events"]
        ent[0]["transition_query"][0]["ch1"]["P"] = [-100]

        if method not in [Method, Method1D, Method2D]:
            with pytest.raises(ImmutableEventError,
                               match=f".*{event_error}.*"):
                method.parse_dict_with_units(serialize)

            with pytest.raises(ImmutableEventError,
                               match=f".*{event_error}.*"):
                method(**serialize)

            with pytest.raises(ImmutableEventError,
                               match=f".*{event_error}.*"):
                ent.append({"transition_query": [{"ch1": {"P": [-100]}}]})
                method.parse_dict_with_units(serialize)

    def check_sim_save(sim1, sim2, message):
        for mth in sim2.methods:
            mth.simulation._timestamp = ""
            _ = [
                item.to("ppm", "nmr_frequency_ratio")
                for item in mth.simulation.x
            ]

        data1 = sim.methods[0].simulation.copy()
        sim.methods[0].simulation = None
        data2 = sim2.methods[0].simulation.copy()
        sim2.methods[0].simulation = None

        assert data1 == data2, f"data saved and loaded is not equal: type {message}."
        assert sim == sim2, f".mrsim saved and loaded is not equal: type {message}."

    for item in methods:
        kwargs = {
            "channels": ["93Nb"],
            "spectral_dimensions": [{
                "count": 1024,
                "spectral_width": 100
            } for _ in range(item.ndim)],
        }

        if item.__name__ == "SSB2D":
            kwargs["rotor_frequency"] = 1e3

        fn1 = item(**kwargs)

        # Parse against self
        assert_parsing(item, fn1)

        # Parse against Method class
        assert_parsing(Method, fn1)

        # Parse against Method1D/Method2D classes
        mth_d = Method1D if item.ndim == 1 else Method2D
        assert_parsing(mth_d, fn1)

        # save test
        sim = Simulator(spin_systems=[sys], methods=[fn1])

        # save/load with units
        sim.run()
        sim.save("test.mrsim")
        sim2 = Simulator.load("test.mrsim")
        check_sim_save(sim, sim2, "with units")

        # save/load with out units
        sim.run()
        sim.save("test.mrsim", with_units=False)
        sim2 = Simulator.load("test.mrsim", parse_units=False)
        check_sim_save(sim, sim2, "without units")

    os.remove("test.mrsim")
Beispiel #26
0
def setup_simulation(site, affine_matrix, class_id=0):

    isotope = site.isotope.symbol
    spin_system = [SpinSystem(sites=[site])]

    method_C = method_class[class_id]

    method = method_C(
        channels=[isotope],
        magnetic_flux_density=7,  # in T
        rotor_angle=54.735 * np.pi / 180,
        spectral_dimensions=[
            {
                "count": 512,
                "spectral_width": 4e4,  # in Hz
                "reference_offset": -3e3,  # in Hz
            },
            {
                "count": 1024,
                "spectral_width": 1e4,  # in Hz
                "reference_offset": -4e3,  # in Hz
            },
        ],
        affine_matrix=affine_matrix,
    )

    method_1 = Method(
        channels=[isotope],
        magnetic_flux_density=7,  # in T
        rotor_angle=54.735 * np.pi / 180,
        rotor_frequency=np.inf,
        spectral_dimensions=[
            {
                "count": 1024,
                "spectral_width": 1e4,  # in Hz
                "reference_offset": -4e3,  # in Hz
                "events": [
                    {
                        "fraction": 27 / 17,
                        "freq_contrib": ["Quad2_0"],
                        "transition_queries": [{"ch1": {"P": [-1], "D": [0]}}],
                    },
                    {
                        "fraction": 1,
                        "freq_contrib": ["Quad2_4"],
                        "transition_queries": [{"ch1": {"P": [-1], "D": [0]}}],
                    },
                ],
            }
        ],
    )

    sim = Simulator()
    sim.spin_systems = spin_system  # add the spin-system
    sim.methods = [method, method_1]  # add the method

    # run the simulation
    sim.config.number_of_sidebands = 1
    sim.run()

    csdm_data1 = sim.methods[0].simulation.real.sum(axis=1)
    csdm_data2 = sim.methods[1].simulation.real
    csdm_data1 /= csdm_data1.max()
    csdm_data2 /= csdm_data2.max()

    np.testing.assert_almost_equal(
        csdm_data1.y[0].components, csdm_data2.y[0].components, decimal=3
    )