def test_models(doctest_namespace): cz_model = CzjzekDistribution(0.5) doctest_namespace["cz_model"] = cz_model S0 = {"Cq": 1e6, "eta": 0.3} ext_cz_model = ExtCzjzekDistribution(S0, eps=0.35) doctest_namespace["ext_cz_model"] = ext_cz_model
def test_czjzek_distribution(): sigma = 0.5 # numerical Czjzek distribution count_ = COUNT zeta, eta = CzjzekDistribution(sigma).rvs(size=count_) # eta projection e_hist, ran_e = np.histogram(eta, bins=15, range=[0, 1]) e_vector = e_hist / count_ e_range = (ran_e[1:] + ran_e[:-1]) / 2 # zeta projection z_hist, ran_z = np.histogram(zeta, bins=20, range=[-20, 20]) z_vector = z_hist / count_ z_range = (ran_z[1:] + ran_z[:-1]) / 2 # czjzek distribution from analytical formula sigma_ = 2 * sigma V, e = np.meshgrid(z_range, e_range) denom = (2 * np.pi) ** 0.5 * sigma_**5 res = (V**4 * e) * (1 - e**2 / 9) / denom res *= np.exp(-(V**2 * (1 + (e**2 / 3))) / (2 * sigma_**2)) res /= res.sum() eta_pro = res.sum(axis=1) zeta_pro = res.sum(axis=0) # eta test message = "failed to compare eta projection for Czjzek distribution" np.testing.assert_almost_equal(e_vector, eta_pro, decimal=2, err_msg=message) # zeta test message = "failed to compare zeta projection for Czjzek distribution" np.testing.assert_almost_equal(z_vector, zeta_pro, decimal=2, err_msg=message)
def test_czjzek_pdf(): sigma = 0.5 z_range = np.arange(100) * 30 / 100 - 15 e_range = np.arange(21) / 20 # czjzek distribution from analytical formula sigma_ = 2 * sigma V, e = np.meshgrid(z_range, e_range) denom = (2 * np.pi) ** 0.5 * sigma_**5 res = (V**4 * e) * (1 - e**2 / 9) / denom res *= np.exp(-(V**2 * (1 + (e**2 / 3))) / (2 * sigma_**2)) res /= res.sum() _, _, amp = CzjzekDistribution(sigma).pdf([z_range, e_range]) error = "Czjzek analytical is not equal to numerical" np.testing.assert_almost_equal(res, amp, decimal=2, err_msg=error)
# %% # Generate probability distribution # --------------------------------- # The range of isotropic chemical shifts, the quadrupolar coupling constant, and # asymmetry parameters used in generating a 3D grid. iso_r = np.arange(101) / 1.5 + 30 # in ppm Cq_r = np.arange(100) / 4 # in MHz eta_r = np.arange(10) / 9 # The 3D mesh grid over which the distribution amplitudes are evaluated. iso, Cq, eta = np.meshgrid(iso_r, Cq_r, eta_r, indexing="ij") # The 2D amplitude grid of Cq and eta is sampled from the Czjzek distribution model. Cq_dist, e_dist, amp = CzjzekDistribution(sigma=1).pdf(pos=[Cq_r, eta_r]) # The 1D amplitude grid of isotropic chemical shifts is sampled from a Gaussian model. iso_amp = multivariate_normal(mean=58, cov=[4]).pdf(iso_r) # The 3D amplitude grid is generated as an uncorrelated distribution of the above two # distribution, which is the product of the two distributions. pdf = np.repeat(amp, iso_r.size).reshape(eta_r.size, Cq_r.size, iso_r.size) pdf *= iso_amp pdf = pdf.T # %% # The two-dimensional projections from this three-dimensional distribution are shown # below. _, ax = plt.subplots(1, 3, figsize=(9, 3))
def test_czjzek_polar(): x, y = CzjzekDistribution(sigma=0.5, polar=True).rvs(size=COUNT) x1, y1 = x_y_from_zeta_eta(*x_y_to_zeta_eta(x, y)) np.testing.assert_almost_equal(x, x1) np.testing.assert_almost_equal(y, y1)
# sphinx_gallery_thumbnail_number = 4 # %% # Symmetric shielding tensor # -------------------------- # # Create the Czjzek distribution # '''''''''''''''''''''''''''''' # # First, create a distribution of the zeta and eta parameters of the shielding tensors # using the :ref:`czjzek_distribution` model as follows. # The range of zeta and eta coordinates over which the distribution is sampled. z_range = np.arange(100) - 50 # in ppm e_range = np.arange(21) / 20 z_dist, e_dist, amp = CzjzekDistribution(sigma=3.1415).pdf( pos=[z_range, e_range]) # %% # Here ``z_range`` and ``e_range`` are the coordinates along the :math:`\zeta` and # :math:`\eta` dimensions that form a two-dimensional :math:`\zeta`-:math:`\eta` grid. # The argument `sigma` of the CzjzekDistribution class is the standard deviation of the # second-rank tensor parameters used in generating the distribution, and `pos` hold the # one-dimensional arrays of :math:`\zeta` and :math:`\eta` coordinates, respectively. # # The following is the contour plot of the Czjzek distribution. plt.figure(figsize=(4.25, 3.0)) plt.contourf(z_dist, e_dist, amp, levels=10) plt.xlabel(r"$\zeta$ / ppm") plt.ylabel(r"$\eta$") plt.tight_layout() plt.show()