Ejemplo n.º 1
0
def test_SWSH_conjugation(special_angles, ell_max):
    # {s}Y{l,m}.conjugate() = (-1.)**(s+m) {-s}Y{l,-m}
    indices1 = sf.LM_range(0, ell_max)
    indices2 = np.array([[ell, -m] for ell, m in indices1])
    neg1_to_m = np.array([(-1.)**m for ell, m in indices1])
    for iota in special_angles:
        for phi in special_angles:
            R = quaternion.from_spherical_coords(iota, phi)
            for s in range(1-ell_max, ell_max):
                assert np.allclose(sf.SWSH(R, s, indices1),
                                   (-1.)**s * neg1_to_m * np.conjugate(sf.SWSH(R, -s, indices2)),
                                   atol=1e-15, rtol=1e-15)
Ejemplo n.º 2
0
def test_SWSH_signatures(Rs):
    """There are two ways to call the SWSH function: with an array of Rs, or with an array of (ell,m) values.  This
    test ensures that the results are the same in both cases."""
    s_max = 5
    ss = np.arange(-s_max, s_max + 1)
    ell_max = 5
    ell_ms = sf.LM_range(0, ell_max)
    SWSHs1 = np.empty((Rs.size, ss.size, ell_ms.size // 2), dtype=np.complex)
    SWSHs2 = np.empty_like(SWSHs1)
    for i_s, s in enumerate(ss):
        for i_ellm, (ell, m) in enumerate(ell_ms):
            SWSHs1[:, i_s, i_ellm] = sf.SWSH(Rs, s, [ell, m])
    for i_s, s in enumerate(ss):
        for i_R, R in enumerate(Rs):
            SWSHs2[i_R, i_s, :] = sf.SWSH(R, s, ell_ms)
    assert np.array_equal(SWSHs1, SWSHs2)
Ejemplo n.º 3
0
def test_vector_as_ell_1_modes(special_angles):
    indices = np.array([[1, -1], [1, 0], [1, 1]])

    def nhat(theta, phi):
        return np.array([
            math.sin(theta) * math.cos(phi),
            math.sin(theta) * math.sin(phi),
            math.cos(theta)
        ])

    np.random.seed(123)
    for rep in range(1000):
        vector = np.random.uniform(-1, 1, size=(3, ))
        vec_ell_m = sf.vector_as_ell_1_modes(vector)
        assert np.allclose(vector,
                           sf.vector_from_ell_1_modes(vec_ell_m),
                           atol=1.0e-16,
                           rtol=1.0e-15)
        for theta in special_angles:
            for phi in special_angles:
                dot1 = np.dot(vector, nhat(theta, phi))
                dot2 = np.dot(
                    vec_ell_m,
                    sf.SWSH(quaternion.from_spherical_coords(theta, phi), 0,
                            indices)).real
                assert abs(dot1 - dot2) < 1e-15
Ejemplo n.º 4
0
def test_SWSH_spin_behavior(Rs, special_angles, ell_max):
    # We expect that the SWSHs behave according to
    # sYlm( R * exp(gamma*z/2) ) = sYlm(R) * exp(-1j*s*gamma)
    # See http://moble.github.io/spherical_functions/SWSHs.html#fn:2
    # for a more detailed explanation
    # print("")
    for i, R in enumerate(Rs):
        # print("\t{0} of {1}: R = {2}".format(i, len(Rs), R))
        for gamma in special_angles:
            for ell in range(ell_max + 1):
                for s in range(-ell, ell + 1):
                    LM = np.array([[ell, m] for m in range(-ell, ell + 1)])
                    Rgamma = R * np.quaternion(math.cos(gamma / 2.), 0, 0, math.sin(gamma / 2.))
                    sYlm1 = sf.SWSH(Rgamma, s, LM)
                    sYlm2 = sf.SWSH(R, s, LM) * cmath.exp(-1j * s * gamma)
                    # print(R, gamma, ell, s, np.max(np.abs(sYlm1-sYlm2)))
                    assert np.allclose(sYlm1, sYlm2, atol=ell ** 6 * precision_SWSH, rtol=ell ** 6 * precision_SWSH)
Ejemplo n.º 5
0
def test_SWSH_values(special_angles, ell_max):
    for iota in special_angles:
        for phi in special_angles:
            for ell in range(ell_max + 1):
                for s in range(-ell, ell + 1):
                    for m in range(-ell, ell + 1):
                        R = quaternion.from_euler_angles(phi, iota, 0)
                        assert abs(sf.SWSH(R, s, np.array([[ell, m]]))
                                   - slow_sYlm(s, ell, m, iota, phi)) < ell_max ** 6 * precision_SWSH
Ejemplo n.º 6
0
def test_SWSH_WignerD_expression(special_angles, ell_max):
    for iota in special_angles:
        for phi in special_angles:
            for ell in range(ell_max + 1):
                for s in range(-ell, ell + 1):
                    R = quaternion.from_euler_angles(phi, iota, 0)
                    LM = np.array([[ell, m] for m in range(-ell, ell + 1)])
                    Y = sf.SWSH(R, s, LM)
                    LMS = np.array([[ell, m, -s] for m in range(-ell, ell + 1)])
                    D = (-1.) ** (s) * math.sqrt((2 * ell + 1) / (4 * np.pi)) * sf.Wigner_D_element(R.a, R.b, LMS)
                    assert np.allclose(Y, D, atol=ell ** 6 * precision_SWSH, rtol=ell ** 6 * precision_SWSH)
Ejemplo n.º 7
0
def test_SWSH_grid(special_angles, ell_max):
    LM = sf.LM_range(0, ell_max)

    # Test flat array arrangement
    R_grid = np.array([quaternion.from_euler_angles(alpha, beta, gamma).normalized()
                       for alpha in special_angles
                       for beta in special_angles
                       for gamma in special_angles])
    for s in range(-ell_max + 1, ell_max):
        values_explicit = np.array([sf.SWSH(R, s, LM) for R in R_grid])
        values_grid = sf.SWSH_grid(R_grid, s, ell_max)
        assert np.array_equal(values_explicit, values_grid)

    # Test nested array arrangement
    R_grid = np.array([[[quaternion.from_euler_angles(alpha, beta, gamma)
                         for alpha in special_angles]
                        for beta in special_angles]
                       for gamma in special_angles])
    for s in range(-ell_max + 1, ell_max):
        values_explicit = np.array([[[sf.SWSH(R, s, LM) for R in R1] for R1 in R2] for R2 in R_grid])
        values_grid = sf.SWSH_grid(R_grid, s, ell_max)
        assert np.array_equal(values_explicit, values_grid)
Ejemplo n.º 8
0
def swsh(s, modes, theta, phi, psi=0):
    """
    Return a value of a spin-weighted spherical harmonic of spin-weight s. 
    If passed a list of several modes, then a numpy array is returned with 
    SWSH values of each mode for the given point.
    
    For one mode:       swsh(s,[(l,m)],theta,phi,psi=0)
    For several modes:  swsh(s,[(l1,m1),(l2,m2),(l3,m3),...],theta,phi,psi=0)
    """
    import spherical_functions as sf
    import quaternion as qt

    return sf.SWSH(qt.from_spherical_coords(theta, phi), s, modes) * np.exp(
        1j * s * psi
    )
Ejemplo n.º 9
0
def test_constant_as_ell_0_mode(special_angles):
    indices = np.array([[0, 0]])
    np.random.seed(123)
    for imaginary_part in [0.0,
                           1.0j]:  # Test both real and imaginary constants
        for rep in range(1000):
            constant = np.random.uniform(
                -1, 1) + imaginary_part * np.random.uniform(-1, 1)
            const_ell_m = sf.constant_as_ell_0_mode(constant)
            assert abs(constant -
                       sf.constant_from_ell_0_mode(const_ell_m)) < 1e-15
            for theta in special_angles:
                for phi in special_angles:
                    dot = np.dot(
                        const_ell_m,
                        sf.SWSH(quaternion.from_spherical_coords(theta, phi),
                                0, indices))
                    assert abs(constant - dot) < 1e-15