def test_spherical_quadrature():
    """
    Testing spherical quadrature rule versus numerical integration.
    """

    b = 8  # 10

    # Create grids on the sphere
    x_gl = S2.meshgrid(b=b, grid_type='Gauss-Legendre')
    x_cc = S2.meshgrid(b=b, grid_type='Clenshaw-Curtis')
    x_soft = S2.meshgrid(b=b, grid_type='SOFT')
    x_gl = np.c_[x_gl[0][..., None], x_gl[1][..., None]]
    x_cc = np.c_[x_cc[0][..., None], x_cc[1][..., None]]
    x_soft = np.c_[x_soft[0][..., None], x_soft[1][..., None]]

    # Compute quadrature weights
    w_gl = S2.quadrature_weights(b=b, grid_type='Gauss-Legendre')
    w_cc = S2.quadrature_weights(b=b, grid_type='Clenshaw-Curtis')
    w_soft = S2.quadrature_weights(b=b, grid_type='SOFT')

    # Define a polynomial function, to be evaluated at one point or at an array of points
    def f1a(xs):
        xc = S2.change_coordinates(coords=xs, p_from='S', p_to='C')
        return xc[..., 0]**2 * xc[..., 1] - 1.4 * xc[..., 2] * xc[
            ..., 1]**3 + xc[..., 1] - xc[..., 2]**2 + 2.

    def f1(theta, phi):
        xs = np.array([theta, phi])
        return f1a(xs)

    # Obtain the "true" value of the integral of the function over the sphere, using scipy's numerical integration
    # routines
    i1 = S2.integrate(f1, normalize=False)

    # Compute the integral using the quadrature formulae
    # i1_gl_w = (w_gl * f1a(x_gl)).sum()
    i1_gl_w = S2.integrate_quad(f1a(x_gl),
                                grid_type='Gauss-Legendre',
                                normalize=False,
                                w=w_gl)
    print(i1_gl_w, i1, 'diff:', np.abs(i1_gl_w - i1))
    assert np.isclose(np.abs(i1_gl_w - i1), 0.0)

    # i1_cc_w = (w_cc * f1a(x_cc)).sum()
    i1_cc_w = S2.integrate_quad(f1a(x_cc),
                                grid_type='Clenshaw-Curtis',
                                normalize=False,
                                w=w_cc)
    print(i1_cc_w, i1, 'diff:', np.abs(i1_cc_w - i1))
    assert np.isclose(np.abs(i1_cc_w - i1), 0.0)

    i1_soft_w = (w_soft * f1a(x_soft)).sum()
    print(i1_soft_w, i1, 'diff:', np.abs(i1_soft_w - i1))
    print(i1_soft_w)
    print(i1)
Example #2
0
def test_S2FFT_NFFT():
    """
    Testing S2FFT NFFT
    """
    b = 8
    convention = 'Gauss-Legendre'
    #convention = 'Clenshaw-Curtis'
    x = S2.meshgrid(b=b, grid_type=convention)
    print(x[0].shape, x[1].shape)
    x = np.c_[x[0][..., None], x[1][..., None]]#.reshape(-1, 2)
    print(x.shape)
    x = x.reshape(-1, 2)
    w = S2.quadrature_weights(b=b, grid_type=convention).flatten()
    F = S2FFT_NFFT(L_max=b, x=x, w=w)

    for l in range(0, b):
        for m in range(-l, l + 1):
            #l = b; m = b
            f = sh(l, m, x[..., 0], x[..., 1], field='real', normalization='quantum', condon_shortley=True)
            #f2 = np.random.randn(*f.shape)
            print(f)

            f_hat = F.analyze(f)
            print(np.round(f_hat, 3))
            f_reconst = F.synthesize(f_hat)

            #print np.round(f, 3)
            print(np.round(f_reconst, 3))
            #print np.round(f/f_reconst, 3)
            print(np.abs(f-f_reconst).sum())
            assert np.isclose(np.abs(f-f_reconst).sum(), 0.)

            print(np.round(f_hat, 3))
            assert np.isclose(f_hat[l ** 2 + l + m], 1.)
            #assert False
Example #3
0
    def __init__(self,
                 L_max,
                 grid_type='Gauss-Legendre',
                 field='real',
                 normalization='quantum',
                 condon_shortley='cs'):

        super().__init__()

        self.b = L_max + 1

        # Compute a grid of spatial sampling points and associated quadrature weights
        beta, alpha = S2.meshgrid(b=self.b, grid_type=grid_type)
        self.w = S2.quadrature_weights(b=self.b, grid_type=grid_type)
        self.spatial_grid_shape = beta.shape
        self.num_spatial_points = beta.size

        # Determine for which degree and order we want the spherical harmonics
        irreps = np.arange(
            self.b
        )  # TODO find out upper limit for exact integration for each grid type
        ls = [[ls] * (2 * ls + 1) for ls in irreps]
        ls = np.array([ll for sublist in ls
                       for ll in sublist])  # 0, 1, 1, 1, 2, 2, 2, 2, 2, ...
        ms = [list(range(-ls, ls + 1)) for ls in irreps]
        ms = np.array([mm for sublist in ms
                       for mm in sublist])  # 0, -1, 0, 1, -2, -1, 0, 1, 2, ...
        self.num_spectral_points = ms.size  # This equals sum_{l=0}^{b-1} 2l+1 = b^2

        # In one shot, sample the spherical harmonics at all spectral (l, m) and spatial (beta, alpha) coordinates
        self.Y = sh(ls[None, None, :],
                    ms[None, None, :],
                    beta[:, :, None],
                    alpha[:, :, None],
                    field=field,
                    normalization=normalization,
                    condon_shortley=condon_shortley == 'cs')

        # Convert to a matrix
        self.Ymat = self.Y.reshape(self.num_spatial_points,
                                   self.num_spectral_points)
Example #4
0
def naive_S2_conv_v2(f1, f2, alpha, beta, gamma, g_parameterization='EA323'):
    """
    Compute int_S^2 f1(x) f2(g^{-1} x)* dx,
    where x = (theta, phi) is a point on the sphere S^2,
    and g = (alpha, beta, gamma) is a point in SO(3) in Euler angle parameterization

    :param f1, f2: functions to be convolved
    :param alpha, beta, gamma: the rotation at which to evaluate the result of convolution
    :return:
    """

    theta, phi = S2.meshgrid(b=3, grid_type='Gauss-Legendre')
    w = S2.quadrature_weights(b=3, grid_type='Gauss-Legendre')

    print(theta.shape, phi.shape)
    s2_coords = np.c_[theta[..., None], phi[..., None]]
    print(s2_coords.shape)
    r3_coords = np.c_[theta[..., None], phi[..., None],
                      np.ones_like(theta)[..., None]]

    # g_inv = SO3.invert((alpha, beta, gamma), parameterization=g_parameterization)
    # g_inv = (-gamma, -beta, -alpha)
    g_inv = (alpha, beta, gamma)  # wrong

    ginvx = SO3.transform_r3(g=g_inv,
                             x=r3_coords,
                             g_parameterization=g_parameterization,
                             x_parameterization='S')
    print(ginvx.shape)
    g_inv_theta = ginvx[..., 0]
    g_inv_phi = ginvx[..., 1]
    g_inv_r = ginvx[..., 2]

    print(g_inv_theta, g_inv_phi, g_inv_r)

    f1_grid = f1(theta, phi)
    f2_grid = f2(g_inv_theta, g_inv_phi)

    print(f1_grid.shape, f2_grid.shape, w.shape)
    return np.sum(f1_grid * f2_grid * w)
Example #5
0
def check_orthogonality(L_max=3,
                        grid_type='Gauss-Legendre',
                        field='real',
                        normalization='quantum',
                        condon_shortley=True):

    theta, phi = S2.meshgrid(b=L_max + 1, grid_type=grid_type)
    w = S2.quadrature_weights(b=L_max + 1, grid_type=grid_type)

    for l in range(L_max):
        for m in range(-l, l + 1):
            for l2 in range(L_max):
                for m2 in range(-l2, l2 + 1):
                    Ylm = sh(l, m, theta, phi, field, normalization,
                             condon_shortley)
                    Ylm2 = sh(l2, m2, theta, phi, field, normalization,
                              condon_shortley)

                    dot_numerical = S2.integrate_quad(Ylm * Ylm2.conj(),
                                                      grid_type=grid_type,
                                                      normalize=False,
                                                      w=w)

                    dot_numerical2 = S2.integrate(
                        lambda t, p: sh(l, m, t, p, field, normalization, condon_shortley) * \
                                     sh(l2, m2, t, p, field, normalization, condon_shortley).conj(), normalize=False)

                    sqnorm_analytical = sh_squared_norm(l,
                                                        normalization,
                                                        normalized_haar=False)
                    dot_analytical = sqnorm_analytical * (l == l2 and m == m2)

                    print(l, m, l2, m2, field, normalization, condon_shortley,
                          dot_analytical, dot_numerical, dot_numerical2)
                    assert np.isclose(dot_numerical, dot_analytical)
                    assert np.isclose(dot_numerical2, dot_analytical)