Example #1
0
def test_modes_conjugate():
    tolerance = 1e-15
    np.random.seed(1234)
    for inplace in [False, True]:
        for s in range(-2, 2 + 1):
            ell_min = abs(s)
            ell_max = 8
            a = np.random.rand(3, 7,
                               sf.LM_total_size(ell_min, ell_max) *
                               2).view(complex)
            m = sf.Modes(a, spin_weight=s, ell_min=ell_min, ell_max=ell_max)
            g = m.grid()
            s = m.s
            ell_min = m.ell_min
            ell_max = m.ell_max
            shape = m.shape
            mbar = m.conjugate(inplace)
            gbar = mbar.grid()
            assert s == -mbar.s
            assert ell_min == mbar.ell_min
            assert ell_max == mbar.ell_max
            assert shape == mbar.shape
            assert np.allclose(g,
                               np.conjugate(gbar),
                               rtol=tolerance,
                               atol=tolerance)
Example #2
0
def test_modes_grid(ell_max, eps):
    ell_max = max(3, ell_max)
    np.random.seed(1234)
    wigner = sf.Wigner(ell_max)
    ϵ = 10 * (2 * ell_max + 1) * eps
    n_theta = n_phi = 2 * ell_max + 1

    rotors = quaternionic.array.from_spherical_coordinates(
        sf.theta_phi(n_theta, n_phi))

    for s in range(-2, 2 + 1):
        ell_min = abs(s)
        a1 = np.random.rand(11, sf.Ysize(ell_min, ell_max) * 2).view(complex)
        m1 = sf.Modes(a1, spin_weight=s, ell_min=ell_min, ell_max=ell_max)

        f1 = m1.grid(n_theta, n_phi)
        assert f1.shape == m1.shape[:-1] + rotors.shape[:-1]

        sYlm = np.zeros((sf.Ysize(0, ell_max), ) + rotors.shape[:-1],
                        dtype=complex)
        for i, Rs in enumerate(rotors):
            for j, R in enumerate(Rs):
                wigner.sYlm(s, R, out=sYlm[:, i, j])
        f2 = np.tensordot(m1.view(np.ndarray), sYlm, axes=([-1], [0]))
        assert f2.shape == m1.shape[:-1] + rotors.shape[:-1]

        assert np.allclose(
            f1.ndarray, f2, rtol=ϵ,
            atol=ϵ), f"max|f1-f2|={np.max(np.abs(f1.ndarray-f2))} > ϵ={ϵ}"
Example #3
0
def test_modes_squared_angular_momenta():
    tolerance = 1e-13
    np.random.seed(1234)
    L2 = sf.Modes.Lsquared
    Lz = sf.Modes.Lz
    Lp = sf.Modes.Lplus
    Lm = sf.Modes.Lminus
    R2 = sf.Modes.Rsquared
    Rz = sf.Modes.Rz
    Rp = sf.Modes.Rplus
    Rm = sf.Modes.Rminus
    for s in range(-2, 2 + 1):
        ell_min = abs(s)
        ell_max = 8
        a = np.random.rand(3, 7,
                           sf.LM_total_size(ell_min, ell_max) *
                           2).view(complex)
        m = sf.Modes(a, spin_weight=s, ell_min=ell_min, ell_max=ell_max)

        # Test L^2 = 0.5(L+L- + L-L+) + LzLz
        m1 = L2(m)
        m2 = 0.5 * (Lp(Lm(m)) + Lm(Lp(m))) + Lz(Lz(m))
        assert np.allclose(m1, m2, rtol=tolerance, atol=tolerance)

        # Test R^2 = 0.5(R+R- + R-R+) + RzRz
        m1 = R2(m)
        m2 = 0.5 * (Rp(Rm(m)) + Rm(Rp(m))) + Rz(Rz(m))
        assert np.allclose(m1, m2, rtol=tolerance, atol=tolerance)

        # Test L^2 = R^2
        m1 = L2(m)
        m2 = R2(m)
        assert np.allclose(m1, m2, rtol=tolerance, atol=tolerance)
Example #4
0
def test_wigner_evaluate(horner, ell_max_slow, eps):
    import time

    ell_max = max(3, ell_max_slow)
    np.random.seed(1234)
    ϵ = 10 * (2 * ell_max + 1) * eps
    n_theta = n_phi = 2 * ell_max + 1
    max_s = 2
    wigner = sf.Wigner(ell_max, mp_max=max_s)

    max_error = 0.0
    total_time = 0.0
    for rotors in [
            quaternionic.array.from_spherical_coordinates(
                sf.theta_phi(n_theta, n_phi)),
            quaternionic.array(np.random.rand(n_theta, n_phi, 4)).normalized
    ]:

        for s in range(-max_s, max_s + 1):
            ell_min = abs(s)

            a1 = np.random.rand(7,
                                sf.Ysize(ell_min, ell_max) * 2).view(complex)
            a1[:,
               sf.Yindex(ell_min, -ell_min, ell_min):sf.
               Yindex(abs(s), -abs(s), ell_min)] = 0.0

            m1 = sf.Modes(a1, spin_weight=s, ell_min=ell_min, ell_max=ell_max)

            t1 = time.perf_counter()
            f1 = wigner.evaluate(m1, rotors, horner=horner)
            t2 = time.perf_counter()
            assert f1.shape == m1.shape[:-1] + rotors.shape[:-1]
            # print(f"Evaluation for s={s} took {t2-t1:.4f} seconds")
            # print(f1.shape)

            sYlm = np.zeros((sf.Ysize(0, ell_max), ) + rotors.shape[:-1],
                            dtype=complex)
            for i, Rs in enumerate(rotors):
                for j, R in enumerate(Rs):
                    wigner.sYlm(s, R, out=sYlm[:, i, j])
            f2 = np.tensordot(m1.view(np.ndarray), sYlm, axes=([-1], [0]))
            assert f2.shape == m1.shape[:-1] + rotors.shape[:-1]

            assert np.allclose(f1, f2, rtol=ϵ, atol=ϵ), (
                f"max|f1-f2|={np.max(np.abs(f1-f2))} > ϵ={ϵ}\n\n"
                f"s = {s}\n\nrotors = {rotors.tolist()}\n\n"
                # f"f1 = {f1.tolist()}\n\nf2 = {f2.tolist()}"
            )

            max_error = max(np.max(np.abs(f1 - f2)), max_error)
            total_time += t2 - t1

    print()
    print(f"\tmax_error[{horner}] = {max_error}")
    print(f"\ttotal_time[{horner}] = {total_time}")
Example #5
0
def test_modes_real():
    tolerance = 1e-14
    np.random.seed(1234)
    for inplace in [False, True]:
        s = 0
        ell_min = abs(s)
        ell_max = 8
        a = np.random.rand(3, 7,
                           sf.LM_total_size(ell_min, ell_max) *
                           2).view(complex)
        # Test success with spin_weight==0
        m = sf.Modes(a, spin_weight=s, ell_min=ell_min, ell_max=ell_max)
        g = m.grid()
        s = m.s
        ell_min = m.ell_min
        ell_max = m.ell_max
        shape = m.shape
        mreal = m._real_func(inplace)
        greal = mreal.grid()
        assert s == mreal.s
        assert ell_min == mreal.ell_min
        assert ell_max == mreal.ell_max
        assert shape == mreal.shape
        assert np.allclose(greal,
                           np.real(greal) + 0.0j,
                           rtol=tolerance,
                           atol=tolerance)
        assert np.allclose(np.real(g),
                           np.real(greal),
                           rtol=tolerance,
                           atol=tolerance)
        assert np.allclose(np.zeros_like(g, dtype=float),
                           np.imag(greal),
                           rtol=tolerance,
                           atol=tolerance)
        # Test failure with s!=0
        for s in [-3, -2, -1, 1, 2, 3]:
            m = sf.Modes(a, spin_weight=s, ell_min=ell_min, ell_max=ell_max)
            with pytest.raises(ValueError):
                mreal = m._real_func(inplace)
Example #6
0
def test_modes_imag():
    tolerance = 1e-14
    np.random.seed(1234)
    for inplace in [False, True]:
        s = 0
        ell_min = abs(s)
        ell_max = 8
        a = np.random.rand(3, 7,
                           sf.LM_total_size(ell_min, ell_max) *
                           2).view(complex)
        # Test success with spin_weight==0
        m = sf.Modes(a, spin_weight=s, ell_min=ell_min, ell_max=ell_max)
        g = m.grid()
        s = m.s
        ell_min = m.ell_min
        ell_max = m.ell_max
        shape = m.shape
        mimag = m._imag_func(inplace)
        gimag = mimag.grid()
        assert s == mimag.s
        assert ell_min == mimag.ell_min
        assert ell_max == mimag.ell_max
        assert shape == mimag.shape
        assert np.allclose(gimag,
                           np.real(gimag),
                           rtol=tolerance,
                           atol=tolerance)  # gimag is purely real
        assert np.allclose(np.array(np.imag(g.ndarray), dtype=complex),
                           gimag.ndarray,
                           rtol=tolerance,
                           atol=tolerance)  # imag(g) == gimag
        assert np.allclose(np.imag(gimag.ndarray),
                           np.zeros_like(g.ndarray, dtype=float),
                           rtol=tolerance,
                           atol=tolerance)  # imag(gimag) == 0
        # Test failure with s!=0
        for s in [-3, -2, -1, 1, 2, 3]:
            m = sf.Modes(a, spin_weight=s, ell_min=ell_min, ell_max=ell_max)
            with pytest.raises(ValueError):
                mimag = m._imag_func(inplace)
Example #7
0
def test_modes_ufuncs():
    for s1 in range(-2, 2 + 1):
        ell_min1 = abs(s1)
        ell_max1 = 8
        a1 = np.random.rand(11,
                            sf.LM_total_size(ell_min1, ell_max1) *
                            2).view(complex)
        m1 = sf.Modes(a1, spin_weight=s1, ell_min=ell_min1, ell_max=ell_max1)
        positivem1 = +m1
        assert np.array_equal(m1.view(np.ndarray), positivem1.view(np.ndarray))
        negativem1 = -m1
        assert np.array_equal(-(m1.view(np.ndarray)),
                              negativem1.view(np.ndarray))
Example #8
0
def test_modes_norm():
    tolerance = 1e-15
    np.random.seed(1234)
    for s in range(-2, 2 + 1):
        ell_min = abs(s)
        ell_max = 8
        a = np.random.rand(3, 7,
                           sf.LM_total_size(ell_min, ell_max) *
                           2).view(complex)
        m = sf.Modes(a, spin_weight=s, ell_min=ell_min, ell_max=ell_max)
        mmbar = m.multiply(m.conjugate())
        norm = np.sqrt(2 * math.sqrt(np.pi) *
                       mmbar[..., 0].view(np.ndarray).real)
        assert np.allclose(norm, m.norm(), rtol=tolerance, atol=tolerance)
Example #9
0
def test_modes_copying_and_pickling(copier):
    for s in range(-2, 2 + 1):
        ell_min = abs(s)
        ell_max = 8
        a = np.random.rand(3, 7,
                           sf.LM_total_size(ell_min, ell_max) *
                           2).view(complex)
        m = sf.Modes(a, spin_weight=s, ell_min=ell_min, ell_max=ell_max)
        c = copier(m)
        assert m is not c
        assert np.array_equal(c, m)
        assert isinstance(c, type(m))
        assert c.s == m.s
        assert c.ell_min == m.ell_min
        assert c.ell_max == m.ell_max
Example #10
0
def test_wigner_rotate_composition(horner, Rs, ell_max_slow, eps):
    import time
    ell_min = 0
    ell_max = max(3, ell_max_slow)
    np.random.seed(1234)
    ϵ = (10 * (2 * ell_max + 1))**2 * eps
    wigner = sf.Wigner(ell_max)
    skipping = 5

    print()
    max_error = 0.0
    total_time = 0.0
    Rs = Rs[::skipping]
    for i, R1 in enumerate(Rs):
        # print(f"\tR1[{i+1}] of {len(Rs)}")
        for j, R2 in enumerate(Rs):
            for spin_weight in range(-2, 2 + 1):
                a1 = np.random.rand(7,
                                    sf.Ysize(ell_min, ell_max) *
                                    2).view(complex)
                a1[:,
                   sf.Yindex(ell_min, -ell_min, ell_min):sf.
                   Yindex(abs(spin_weight), -abs(spin_weight), ell_min)] = 0.0
                m1 = sf.Modes(a1,
                              spin_weight=spin_weight,
                              ell_min=ell_min,
                              ell_max=ell_max)

                t1 = time.perf_counter()
                fA = wigner.rotate(wigner.rotate(m1, R1, horner=horner),
                                   R2,
                                   horner=horner)
                fB = wigner.rotate(m1, R1 * R2, horner=horner)
                t2 = time.perf_counter()

                max_error = max(np.max(np.abs(fA - fB)), max_error)
                total_time += t2 - t1

                # import warnings
                # warnings.warn("Eliminating assert for debugging")
                assert np.allclose(
                    fA, fB, rtol=ϵ, atol=ϵ
                ), f"{np.max(np.abs(fA-fB))} > {ϵ} for R1={R1} R2={R2}"

    print(f"\tmax_error[{horner}] = {max_error}")
    print(f"\ttotal_time[{horner}] = {total_time}")
Example #11
0
def test_modes_grid():
    for s in range(-2, 2 + 1):
        ell_min = abs(s)
        ell_max = 8
        a = np.random.rand(3, 7,
                           sf.LM_total_size(ell_min, ell_max) *
                           2).view(complex)
        m = sf.Modes(a, spin_weight=s, ell_min=ell_min, ell_max=ell_max)
        n = 2 * ell_max + 1
        for n_theta, n_phi in [[None, None], [n, None], [None, n], [n, n],
                               [n + 1, n], [n, n + 1], [n + 1, n + 1]]:
            g = m.grid(n_theta=n_theta, n_phi=n_phi)
            assert g.dtype == complex
            assert g.shape[:-2] == a.shape[:-1]
            if n_theta is None:
                n_theta = n
            if n_phi is None:
                n_phi = n
            assert g.shape[-2:] == (n_theta, n_phi)
Example #12
0
def test_wigner_evaluate_vs_spinsfast(horner, ell_max, eps):
    import time

    ell_max = max(3, ell_max)
    np.random.seed(1234)
    ϵ = ell_max * (2 * ell_max + 1) * eps
    n_theta = n_phi = 2 * ell_max + 1
    max_s = 2
    wigner = sf.Wigner(ell_max, mp_max=max_s)

    rotors = quaternionic.array.from_spherical_coordinates(
        sf.theta_phi(n_theta, n_phi))

    max_error = 0.0
    total_time = 0.0
    for s in range(-max_s, max_s + 1):
        ell_min = abs(s)

        a1 = np.random.rand(7, sf.Ysize(ell_min, ell_max) * 2).view(complex)
        m1 = sf.Modes(a1, spin_weight=s, ell_min=ell_min, ell_max=ell_max)

        t1 = time.perf_counter()
        f1 = wigner.evaluate(m1, rotors, horner=horner)
        t2 = time.perf_counter()
        assert f1.shape == m1.shape[:-1] + rotors.shape[:-1]

        f2 = m1.grid(n_theta, n_phi, use_spinsfast=True)
        assert f2.shape == m1.shape[:-1] + rotors.shape[:-1]

        assert np.allclose(f1, f2.ndarray, rtol=ϵ, atol=ϵ), (
            f"max|f1-f2|={np.max(np.abs(f1-f2.ndarray))} > ϵ={ϵ}\n\n"
            f"s = {s}\n\nrotors = {rotors.tolist()}\n\n"
            # f"f1 = {f1.tolist()}\n\nf2 = {f2.tolist()}"
        )

        max_error = max(np.max(np.abs(f1 - f2.ndarray)), max_error)
        total_time += t2 - t1

    print()
    print(f"\tmax_error[{horner}] = {max_error}")
    print(f"\ttotal_time[{horner}] = {total_time}")
Example #13
0
def test_wigner_rotate_vector(horner, special_angles, Rs, eps):
    """Rotating a vector == rotating the mode-representation of that vector

    Note that the wigner.rotate function rotates the *basis* in which the modes are
    represented, so we rotate the modes by the inverse of the rotation we apply to
    the vector.

    """
    ell_min = 1
    ell_max = 1
    wigner = sf.Wigner(ell_max, ell_min=ell_min)

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

    for theta in special_angles[special_angles >= 0]:
        for phi in special_angles:
            v = nhat(theta, phi)
            vₗₘ = sf.Modes(sf.vector_as_ell_1_modes(v.vector),
                           ell_min=ell_min,
                           ell_max=ell_max,
                           spin_weight=0)
            for R in Rs:
                vprm1 = (R * v * R.conjugate()).vector
                vₗₙ = wigner.rotate(
                    vₗₘ, R.conjugate(),
                    horner=horner).ndarray[1:]  # See note above
                vprm2 = sf.vector_from_ell_1_modes(vₗₙ).real
                assert np.allclose(vprm1, vprm2, atol=5 * eps,
                                   rtol=0), (f"\ntheta: {theta}\n"
                                             f"phi: {phi}\n"
                                             f"R: {R}\n"
                                             f"v: {v}\n"
                                             f"vprm1: {vprm1}\n"
                                             f"vprm2: {vprm2}\n"
                                             f"vprm1-vprm2: {vprm1-vprm2}\n")
Example #14
0
def test_modes_grid_variants(ell_max, eps):
    ell_max = max(3, ell_max)
    s_max = 2
    np.random.seed(1234)
    ϵ = 10 * (2 * ell_max + 1) * eps
    n_theta = n_phi = 2 * ell_max + 1

    rotors = quaternionic.array.from_spherical_coordinates(
        sf.theta_phi(n_theta, n_phi))

    for s in range(-s_max, s_max + 1):
        ell_min = abs(s)
        a1 = np.random.rand(2, sf.Ysize(ell_min, ell_max) * 2).view(complex)
        m1 = sf.Modes(a1, spin_weight=s, ell_min=ell_min, ell_max=ell_max)

        fA = m1.grid(n_theta, n_phi, use_spinsfast=True)
        fB = m1.grid(n_theta, n_phi, use_spinsfast=False)
        assert np.allclose(fA.ndarray, fB.ndarray, rtol=ϵ, atol=ϵ), (
            f"fA = np.array({fA.ndarray.tolist()})\n\n"
            f"fB = np.array({fB.ndarray.tolist()})\n\n"
            "\n"
            f"max|fA-fB|={np.max(np.abs(fA.ndarray-fB.ndarray))} > ϵ={ϵ}; s={s}"
        )
Example #15
0
def test_modes_derivatives_on_grids():
    # Test various SWSH-derivative expressions on grids
    tolerance = 2e-14
    np.random.seed(1234)
    for s in range(-2, 2 + 1):
        ell_min = 0
        ell_max = abs(s) + 5
        zeros = lambda: np.zeros(sf.LM_total_size(ell_min, ell_max),
                                 dtype=complex)
        for ell in range(abs(s), ell_max + 1):
            for m in range(-ell, ell + 1):
                sYlm = sf.Modes(zeros(),
                                spin_weight=s,
                                ell_min=ell_min,
                                ell_max=ell_max)
                sYlm[sYlm.index(ell, m)] = 1.0
                g_sYlm = sYlm.grid()
                n_theta, n_phi = g_sYlm.shape[-2:]

                # Test Lsquared {s}Y{l,m} = l * (l+1) * {s}Y{l,m}
                L2_sYlm = sYlm.Lsquared()
                g_L2_sYlm = L2_sYlm.grid(n_theta, n_phi)
                factor = ell * (ell + 1)
                assert np.allclose(g_L2_sYlm,
                                   factor * g_sYlm,
                                   rtol=tolerance,
                                   atol=tolerance)

                # Test Lz {s}Y{l,m} = m * {s}Y{l,m}
                Lz_sYlm = sYlm.Lz()
                g_Lz_sYlm = Lz_sYlm.grid(n_theta, n_phi)
                factor = m
                assert np.allclose(g_Lz_sYlm,
                                   factor * g_sYlm,
                                   rtol=tolerance,
                                   atol=tolerance)

                # Test Lplus {s}Y{l,m} = sqrt((l-m)*(l+m+1)) {s}Y{l,m+1}
                invalid = abs(m + 1) > ell
                sYlmp1 = sf.Modes(zeros(),
                                  spin_weight=s,
                                  ell_min=ell_min,
                                  ell_max=ell_max)
                if invalid:
                    with pytest.raises(ValueError):
                        sYlmp1.index(ell, m + 1)
                else:
                    sYlmp1[sYlmp1.index(ell, m + 1)] = 1.0
                g_sYlmp1 = sYlmp1.grid(n_theta, n_phi)
                Lp_sYlm = sYlm.Lplus()
                g_Lp_sYlm = Lp_sYlm.grid(n_theta, n_phi)
                factor = 0.0 if invalid else math.sqrt(
                    (ell - m) * (ell + m + 1))
                assert np.allclose(g_Lp_sYlm,
                                   factor * g_sYlmp1,
                                   rtol=tolerance,
                                   atol=tolerance)

                # Test Lminus {s}Y{l,m} = sqrt((l+m)*(l-m+1)) * {s}Y{l,m-1}
                invalid = abs(m - 1) > ell
                sYlmm1 = sf.Modes(zeros(),
                                  spin_weight=s,
                                  ell_min=ell_min,
                                  ell_max=ell_max)
                if invalid:
                    with pytest.raises(ValueError):
                        sYlmm1.index(ell, m - 1)
                else:
                    sYlmm1[sYlmm1.index(ell, m - 1)] = 1.0
                g_sYlmm1 = sYlmm1.grid(n_theta, n_phi)
                Lm_sYlm = sYlm.Lminus()
                g_Lm_sYlm = Lm_sYlm.grid(n_theta, n_phi)
                factor = 0.0 if invalid else math.sqrt(
                    (ell + m) * (ell - m + 1))
                assert np.allclose(g_Lm_sYlm,
                                   factor * g_sYlmm1,
                                   rtol=tolerance,
                                   atol=tolerance)

                # Test Rsquared {s}Y{l,m} = l * (l+1) * {s}Y{l,m}
                R2_sYlm = sYlm.Rsquared()
                g_R2_sYlm = R2_sYlm.grid(n_theta, n_phi)
                factor = ell * (ell + 1)
                assert np.allclose(g_R2_sYlm,
                                   factor * g_sYlm,
                                   rtol=tolerance,
                                   atol=tolerance)

                # Test Rz {s}Y{l,m} = -s * {s}Y{l,m}
                Rz_sYlm = sYlm.Rz()
                g_Rz_sYlm = Rz_sYlm.grid(n_theta, n_phi)
                factor = -s
                assert np.allclose(g_Rz_sYlm,
                                   factor * g_sYlm,
                                   rtol=tolerance,
                                   atol=tolerance)

                # Test Rplus {s}Y{l,m} = sqrt((l+s)(l-s+1)) {s-1}Y{l,m}
                invalid = abs(s - 1) > ell
                sm1Ylm = sf.Modes(zeros(),
                                  spin_weight=s - 1,
                                  ell_min=ell_min,
                                  ell_max=ell_max)
                if invalid:
                    with pytest.raises(ValueError):
                        sm1Ylm.index(ell, m)
                else:
                    sm1Ylm[sm1Ylm.index(ell, m)] = 1.0
                g_sm1Ylm = sm1Ylm.grid(n_theta, n_phi)
                Rp_sYlm = sYlm.Rplus()
                g_Rp_sYlm = Rp_sYlm.grid(n_theta, n_phi)
                factor = 0.0 if invalid else math.sqrt(
                    (ell + s) * (ell - s + 1))
                assert np.allclose(g_Rp_sYlm,
                                   factor * g_sm1Ylm,
                                   rtol=tolerance,
                                   atol=tolerance)

                # Test Rminus {s}Y{l,m} = sqrt((l-s)(l+s+1)) {s+1}Y{l,m}
                invalid = abs(s + 1) > ell
                sp1Ylm = sf.Modes(zeros(),
                                  spin_weight=s + 1,
                                  ell_min=ell_min,
                                  ell_max=ell_max)
                if invalid:
                    with pytest.raises(ValueError):
                        sp1Ylm.index(ell, m)
                else:
                    sp1Ylm[sp1Ylm.index(ell, m)] = 1.0
                Rm_sYlm = sYlm.Rminus()
                g_sp1Ylm = sp1Ylm.grid(n_theta, n_phi)
                g_Rm_sYlm = Rm_sYlm.grid(n_theta, n_phi)
                factor = 0.0 if invalid else math.sqrt(
                    (ell - s) * (ell + s + 1))
                assert np.allclose(g_Rm_sYlm,
                                   factor * g_sp1Ylm,
                                   rtol=tolerance,
                                   atol=tolerance)

                # Test eth {s}Y{l,m} = sqrt((l-s)(l+s+1)) {s+1}Y{l,m}
                invalid = abs(s + 1) > ell
                sp1Ylm = sf.Modes(zeros(),
                                  spin_weight=s + 1,
                                  ell_min=ell_min,
                                  ell_max=ell_max)
                if invalid:
                    with pytest.raises(ValueError):
                        sp1Ylm.index(ell, m)
                else:
                    sp1Ylm[sp1Ylm.index(ell, m)] = 1.0
                eth_sYlm = sYlm.eth
                g_sp1Ylm = sp1Ylm.grid(n_theta, n_phi)
                g_eth_sYlm = eth_sYlm.grid(n_theta, n_phi)
                factor = 0.0 if invalid else math.sqrt(
                    (ell - s) * (ell + s + 1))
                assert np.allclose(g_eth_sYlm,
                                   factor * g_sp1Ylm,
                                   rtol=tolerance,
                                   atol=tolerance)

                # Test ethbar {s}Y{l,m} = -sqrt((l+s)(l-s+1)) {s-1}Y{l,m}
                invalid = abs(s - 1) > ell
                sm1Ylm = sf.Modes(zeros(),
                                  spin_weight=s - 1,
                                  ell_min=ell_min,
                                  ell_max=ell_max)
                if invalid:
                    with pytest.raises(ValueError):
                        sm1Ylm.index(ell, m)
                else:
                    sm1Ylm[sm1Ylm.index(ell, m)] = 1.0
                g_sm1Ylm = sm1Ylm.grid(n_theta, n_phi)
                ethbar_sYlm = sYlm.ethbar
                g_ethbar_sYlm = ethbar_sYlm.grid(n_theta, n_phi)
                factor = 0.0 if invalid else -math.sqrt(
                    (ell + s) * (ell - s + 1))
                assert np.allclose(g_ethbar_sYlm,
                                   factor * g_sm1Ylm,
                                   rtol=tolerance,
                                   atol=tolerance)

                # Test ethbar eth sYlm = -(l-s)(l+s+1) sYlm
                ethbar_eth_sYlm = sYlm.eth.ethbar
                g_ethbar_eth_sYlm = ethbar_eth_sYlm.grid(n_theta, n_phi)
                factor = 0.0 if (abs(s + 1) > ell or
                                 abs(s) > ell) else -(ell - s) * (ell + s + 1)
                assert np.allclose(g_ethbar_eth_sYlm,
                                   factor * g_sYlm,
                                   rtol=tolerance,
                                   atol=tolerance)
Example #16
0
def test_modes_derivative_commutators():
    tolerance = 1e-13
    np.random.seed(1234)
    # Note that post-fix operators are in the opposite order compared
    # to prefixed commutators, so we pull the post-fix operators out
    # as functions to make things look right.
    np.random.seed(1234)
    L2 = sf.Modes.Lsquared
    Lz = sf.Modes.Lz
    Lp = sf.Modes.Lplus
    Lm = sf.Modes.Lminus
    R2 = sf.Modes.Rsquared
    Rz = sf.Modes.Rz
    Rp = sf.Modes.Rplus
    Rm = sf.Modes.Rminus
    eth = lambda modes: modes.eth
    ethbar = lambda modes: modes.ethbar
    for s in range(-2, 2 + 1):
        ell_min = abs(s)
        ell_max = 8
        a = np.random.rand(3, 7,
                           sf.LM_total_size(ell_min, ell_max) *
                           2).view(complex)
        m = sf.Modes(a, spin_weight=s, ell_min=ell_min, ell_max=ell_max)
        # Test [Ri, Lj] = 0
        for R in [Rz, Rp, Rm]:
            for L in [Lz, Lp, Lm]:
                assert np.max(np.abs(L(R(m)) - R(L(m)))) < tolerance
        # Test [L2, Lj] = 0
        for L in [Lz, Lp, Lm]:
            assert np.max(np.abs(L2(L(m)) - L(L2(m)))) < 5 * tolerance
        # Test [R2, Rj] = 0
        for R in [Rz, Rp, Rm]:
            assert np.max(np.abs(R2(R(m)) - R(R2(m)))) < 5 * tolerance
        # Test [Lz, Lp] = Lp
        assert np.allclose(Lz(Lp(m)) - Lp(Lz(m)),
                           Lp(m),
                           rtol=tolerance,
                           atol=tolerance)
        # Test [Lz, Lm] = -Lm
        assert np.allclose(Lz(Lm(m)) - Lm(Lz(m)),
                           -Lm(m),
                           rtol=tolerance,
                           atol=tolerance)
        # Test [Lp, Lm] = 2Lz
        assert np.allclose(Lp(Lm(m)) - Lm(Lp(m)),
                           2 * Lz(m),
                           rtol=tolerance,
                           atol=tolerance)
        # Test [Rz, Rp] = Rp
        assert np.allclose(Rz(Rp(m)) - Rp(Rz(m)),
                           Rp(m),
                           rtol=tolerance,
                           atol=tolerance)
        # Test [Rz, Rm] = -Rm
        assert np.allclose(Rz(Rm(m)) - Rm(Rz(m)),
                           -Rm(m),
                           rtol=tolerance,
                           atol=tolerance)
        # Test [Rp, Rm] = 2Rz
        assert np.allclose(Rp(Rm(m)) - Rm(Rp(m)),
                           2 * Rz(m),
                           rtol=tolerance,
                           atol=tolerance)
        # Test [ethbar, eth] = 2s
        assert np.allclose(ethbar(eth(m)) - eth(ethbar(m)),
                           2 * m.s * m,
                           rtol=tolerance,
                           atol=tolerance)
Example #17
0
def test_modes_multiplication():
    tolerance = 1e-13
    np.random.seed(1234)
    # Test without truncation
    for i_mul, mul in enumerate([
            np.multiply, lambda a, b: a.multiply(b),
            lambda a, b: a.multiply(b, truncator=max)
    ]):
        for s1 in range(-2, 2 + 1):
            ell_min1 = abs(s1)
            ell_max1 = 8
            a1 = np.random.rand(3, 7,
                                sf.LM_total_size(ell_min1, ell_max1) *
                                2).view(complex)
            m1 = sf.Modes(a1,
                          spin_weight=s1,
                          ell_min=ell_min1,
                          ell_max=ell_max1)
            # Check scalar multiplications
            s = np.random.rand()
            m1s = mul(m1, s)
            assert m1.s == s1
            assert m1s.ell_max == m1.ell_max
            g1s = m1s.grid()
            n_theta, n_phi = g1s.shape[-2:]
            g1 = m1.grid(n_theta, n_phi)
            assert np.allclose(g1 * s, g1s, rtol=tolerance, atol=tolerance)
            if mul is np.multiply:
                sm1 = mul(s, m1)
                assert sm1.s == s1
                assert sm1.ell_max == m1.ell_max
                sg1 = sm1.grid()
                n_theta, n_phi = sg1.shape[-2:]
                g1 = m1.grid(n_theta, n_phi)
                assert np.allclose(s * g1, sg1, rtol=tolerance, atol=tolerance)
            # Check scalar-array multiplications
            s = np.random.rand(3, 7)
            m1s = mul(m1, s)
            assert m1.s == s1
            assert m1s.ell_max == m1.ell_max
            g1s = m1s.grid()
            n_theta, n_phi = g1s.shape[-2:]
            g1 = m1.grid(n_theta, n_phi)
            assert np.allclose(g1 * s, g1s, rtol=tolerance, atol=tolerance)
            if mul is np.multiply:
                sm1 = mul(s, m1)
                assert sm1.s == s1
                assert sm1.ell_max == m1.ell_max
                sg1 = sm1.grid()
                n_theta, n_phi = sg1.shape[-2:]
                g1 = m1.grid(n_theta, n_phi)
                assert np.allclose(s * g1, sg1, rtol=tolerance, atol=tolerance)
            # Check spin-weighted multiplications
            for s2 in range(-s1, s1 + 1):
                ell_min2 = ell_min1 + 1
                ell_max2 = ell_max1 - 1
                a2 = np.random.rand(3, 7,
                                    sf.LM_total_size(ell_min2, ell_max2) *
                                    2).view(complex)
                m2 = sf.Modes(a2,
                              spin_weight=s2,
                              ell_min=ell_min2,
                              ell_max=ell_max2)
                m1m2 = mul(m1, m2)
                assert m1m2.s == s1 + s2
                if i_mul == 2:
                    assert m1m2.ell_max == max(m1.ell_max, m2.ell_max)
                else:
                    assert m1m2.ell_max == m1.ell_max + m2.ell_max
                    g12 = m1m2.grid()
                    n_theta, n_phi = g12.shape[-2:]
                    g1 = m1.grid(n_theta, n_phi)
                    g2 = m2.grid(n_theta, n_phi)
                    assert np.allclose(g1 * g2,
                                       g12,
                                       rtol=tolerance,
                                       atol=tolerance)
Example #18
0
def test_modes_subtraction():
    tolerance = 1e-14
    np.random.seed(1234)
    for s1 in range(-2, 2 + 1):
        ell_min1 = abs(s1)
        ell_max1 = 8
        a1 = np.random.rand(3, 7, sf.LM_total_size(ell_min1, ell_max1) * 2)
        a2 = np.random.rand(*a1.shape)
        a1 = a1.view(complex)
        a2 = a2.view(complex)
        m1 = sf.Modes(a1, spin_weight=s1, ell_min=ell_min1, ell_max=ell_max1)
        m2 = sf.Modes(a2, spin_weight=s1, ell_min=ell_min1, ell_max=ell_max1)
        m1m2 = m1 - m2
        assert m1m2.s == s1
        assert m1m2.ell_max == m1.ell_max
        assert np.array_equal(m1m2, m1.subtract(m2))
        assert np.array_equal(m1m2, m1.view(np.ndarray) - m2.view(np.ndarray))
        for s2 in range(-s1, s1 + 1):
            ell_min2 = ell_min1 + 1
            ell_max2 = ell_max1 - 1
            a2 = np.random.rand(3, 7,
                                sf.LM_total_size(ell_min2, ell_max2) *
                                2).view(complex)
            m2 = sf.Modes(a2,
                          spin_weight=s2,
                          ell_min=ell_min2,
                          ell_max=ell_max2)
            if s1 != s2:
                # Don't allow addition of non-zero data
                with pytest.raises(ValueError):
                    m1m2 = m1.subtract(m2)
                # Do allow subtraction with various forms of 0, for convenience
                for m3 in [
                        m1.subtract(0),
                        m1.subtract(np.zeros(1)),
                        m1.subtract(np.zeros((1, ))),
                        m1.subtract(np.zeros((7, ))),
                        m1.subtract(np.zeros((3, 7))),
                        m1 - 0,
                        m1 - np.zeros(1),
                        m1 - np.zeros((1, )),
                        m1 - np.zeros((7, )),
                        m1 - np.zeros((3, 7)),
                ]:
                    assert m3.s == s1
                    assert m3.ell_min == m1.ell_min
                    assert m3.ell_max == m1.ell_max
                    assert np.array_equal(m1, m3)
                for m3 in [
                        0 - m1,
                        np.zeros(1) - m1,
                        np.zeros((1, )) - m1,
                        np.zeros((7, )) - m1,
                        np.zeros((3, 7)) - m1,
                ]:
                    assert m3.s == s1
                    assert m3.ell_min == m1.ell_min
                    assert m3.ell_max == m1.ell_max
                    assert np.array_equal(-m1, m3)
            else:
                m1m2 = m1.subtract(m2)
                assert m1m2.s == s1
                assert m1m2.ell_max == m1.ell_max
                i1 = sf.LM_total_size(0, min(ell_min1, ell_min2) - 1)
                i2 = sf.LM_total_size(0, max(ell_min1, ell_min2) - 1)
                i3 = sf.LM_total_size(0, min(ell_max1, ell_max2))
                i4 = sf.LM_total_size(0, max(ell_max1, ell_max2))
                assert np.array_equiv(m1m2[..., :i1], 0.0)
                assert np.array_equal(m1m2[..., i1:i2], a1[..., :i2 - i1])
                assert np.array_equal(m1m2[..., i1:i2],
                                      m1.view(np.ndarray)[..., i1:i2])
                assert np.array_equal(
                    m1m2[..., i2:i3],
                    m1.view(np.ndarray)[..., i2:i3] -
                    m2.view(np.ndarray)[..., i2:i3])
                assert np.array_equal(m1m2[..., i3:i4],
                                      m1.view(np.ndarray)[..., i3:i4])
                g12 = m1m2.grid()
                n_theta, n_phi = g12.shape[-2:]
                g1 = m1.grid(n_theta, n_phi)
                g2 = m2.grid(n_theta, n_phi)
                assert np.allclose(g1 - g2,
                                   g12,
                                   rtol=tolerance,
                                   atol=tolerance)
Example #19
0
def test_modes_creation():
    for s in range(-2, 2 + 1):
        ell_min = abs(s)
        ell_max = 8

        # Test successful creation with real data of the right shape
        a = np.random.rand(3, 7, sf.LM_total_size(ell_min, ell_max) * 2)
        m = sf.Modes(a, spin_weight=s, ell_min=ell_min, ell_max=ell_max)
        assert m.s == s
        assert m.ell_min == 0  # NOTE: This is hard coded!!!
        assert m.ell_max == ell_max
        assert np.array_equal(a.view(complex),
                              m[..., sf.LM_total_size(0, ell_min - 1):])
        assert np.all(m[..., :sf.LM_total_size(0, abs(s) - 1)] == 0.0)
        m = sf.Modes(a, spin_weight=s, ell_min=ell_min)  # ell_max is deduced!
        assert m.s == s
        assert m.ell_min == 0  # NOTE: This is hard coded!!!
        assert m.ell_max == ell_max
        assert np.array_equal(a.view(complex),
                              m[..., sf.LM_total_size(0, ell_min - 1):])
        assert np.all(m[..., :sf.LM_total_size(0, abs(s) - 1)] == 0.0)

        # Test successful creation with complex data of the right shape
        a = a.view(complex)
        m = sf.Modes(a, spin_weight=s, ell_min=ell_min, ell_max=ell_max)
        assert m.s == s
        assert m.ell_min == 0  # NOTE: This is hard coded!!!
        assert m.ell_max == ell_max
        assert np.array_equal(a, m[..., sf.LM_total_size(0, ell_min - 1):])
        assert np.all(m[..., :sf.LM_total_size(0, abs(s) - 1)] == 0.0)
        m = sf.Modes(a, spin_weight=s, ell_min=ell_min)  # ell_max is deduced!
        assert m.s == s
        assert m.ell_min == 0  # NOTE: This is hard coded!!!
        assert m.ell_max == ell_max
        assert np.array_equal(a, m[..., sf.LM_total_size(0, ell_min - 1):])
        assert np.all(m[..., :sf.LM_total_size(0, abs(s) - 1)] == 0.0)

        # Test failed creation with complex data of inconsistent shape
        if ell_min != 0:
            with pytest.raises(ValueError):
                m = sf.Modes(a, spin_weight=s)
        with pytest.raises(ValueError):
            m = sf.Modes(a,
                         spin_weight=s,
                         ell_min=ell_min - 1,
                         ell_max=ell_max)
        with pytest.raises(ValueError):
            m = sf.Modes(a,
                         spin_weight=s,
                         ell_min=ell_min + 1,
                         ell_max=ell_max)
        with pytest.raises(ValueError):
            m = sf.Modes(a,
                         spin_weight=s,
                         ell_min=ell_min,
                         ell_max=ell_max - 1)
        with pytest.raises(ValueError):
            m = sf.Modes(a,
                         spin_weight=s,
                         ell_min=ell_min,
                         ell_max=ell_max + 1)

        # Test failed creation with complex data of impossible shape
        with pytest.raises(ValueError):
            m = sf.Modes(a[..., 1:], spin_weight=s, ell_min=ell_min)

        # Test successful creation with complex data containing extraneous data at ell<abs(s)
        a = np.random.rand(3, 7, sf.LM_total_size(0, ell_max) * 2)
        a = a.view(complex)
        m = sf.Modes(a, spin_weight=s)
        assert m.s == s
        assert m.ell_min == 0  # NOTE: This is hard coded!!!
        assert m.ell_max == ell_max
        assert np.all(m[..., :sf.LM_total_size(0, abs(s) - 1)] == 0.0)