Example #1
0
def get_nvss_map(nside=None):
    map_filepath = os.path.join(DATA_PATH, 'NVSS', 'nvss_map_n512.fits')
    mask_filepath = os.path.join(DATA_PATH, 'NVSS', 'nvss_mask_n0512.fits')
    map, mask = hp.read_map(map_filepath), hp.read_map(mask_filepath)

    rotator = Rotator(coord=['G', 'C'])
    map = rotator.rotate_map_pixel(map)
    mask = rotator.rotate_map_pixel(mask)

    map, mask = tansform_map_and_mask_to_nside(map, mask, nside=nside)
    map = get_masked_map(map, mask)
    return map, mask
Example #2
0
def test_rotate_map_polarization_with_spectrum():
    """Rotation of reference frame should not change the angular power spectrum.
    In this test we create a map from a spectrum with a pure EE signal and check
    that the spectrum of this map and the spectrum of the same map rotated
    from Galactic to Ecliptic agrees.
    This test checks if the QU rotation is correct"""
    nside = 32
    cl = np.zeros((6, 96), dtype=np.double)
    # Set ell=1 for EE to 1
    cl[1][2] = 1
    gal2ecl = Rotator(coord=["G", "E"])
    m_original = hp.synfast(cl, nside=nside, new=True)
    cl_from_m_original = hp.anafast(m_original)
    m_rotated = gal2ecl.rotate_map_pixel(m_original)
    cl_from_m_rotated = hp.anafast(m_rotated)

    assert np.abs(cl_from_m_rotated - cl_from_m_original).sum() < 1e-2
Example #3
0
def test_rotate_map_polarization_with_spectrum():
    """Rotation of reference frame should not change the angular power spectrum.
    In this test we create a map from a spectrum with a pure EE signal and check
    that the spectrum of this map and the spectrum of the same map rotated
    from Galactic to Ecliptic agrees.
    This test checks if the QU rotation is correct"""
    nside = 32
    cl = np.zeros((6, 96), dtype=np.double)
    # Set ell=1 for EE to 1
    cl[1][2] = 1
    gal2ecl = Rotator(coord=["G", "E"])
    m_original = hp.synfast(cl, nside=nside, new=True)
    cl_from_m_original = hp.anafast(m_original)
    m_rotated = gal2ecl.rotate_map_pixel(m_original)
    cl_from_m_rotated = hp.anafast(m_rotated)

    assert np.abs(cl_from_m_rotated - cl_from_m_original).sum() < 1e-2
Example #4
0
def get_cmb_temperature_map(nside=None):
    filename = 'COM_CMB_IQU-smica_2048_R3.00_full.fits'

    # Read
    map = hp.read_map(os.path.join(DATA_PATH, 'Planck2018', filename),
                      field=cmb_columns_idx.I_STOKES)
    mask = hp.read_map(os.path.join(DATA_PATH, 'Planck2018', filename),
                       field=cmb_columns_idx.TMASK)

    # Rotate
    rotator = Rotator(coord=['G', 'C'])
    map = rotator.rotate_map_pixel(map)
    mask = rotator.rotate_map_pixel(mask)

    # Adjust
    map, mask = tansform_map_and_mask_to_nside(map, mask, nside=nside)

    map = get_masked_map(map, mask)
    mask = get_masked_map(mask, mask)
    return map, mask
Example #5
0
def test_rotate_dipole_and_back():
    """Rotate a smooth signal (dipole) from Galactic to Ecliptic and back"""
    nside = 64
    npix = hp.nside2npix(nside)
    pix = np.arange(npix)
    vec = np.array(hp.pix2vec(nside, pix))
    # dipole max is at North Pole
    dip_dir = np.array([0, 0, 1])
    m_gal = np.dot(vec.T, dip_dir)
    gal2ecl = Rotator(coord=["C", "E"])
    ecl2gal = Rotator(coord=["E", "C"])
    m_ecl = gal2ecl.rotate_map_pixel(m_gal)
    # Remove 10 deg along equator because dipole signal is so low that relative error is
    # too large
    cut_equator_deg = 5
    no_equator = hp.query_strip(
        nside, np.radians(90 + cut_equator_deg), np.radians(90 - cut_equator_deg)
    )
    np.testing.assert_allclose(
        m_gal[no_equator], ecl2gal.rotate_map_pixel(m_ecl)[no_equator], rtol=1e-3
    )
Example #6
0
def test_rotate_map_polarization():
    """Compare to a rotation from Galactic to Ecliptic of
    a map of pure Q polarization, the expected value was computed with HEALPix IDL:
    https://gist.github.com/zonca/401069e1c520e02eaff8cd86149d5900
    """
    nside = 32
    npix = hp.nside2npix(nside)
    QU_gal = np.zeros((2, npix), dtype=np.double)
    QU_gal[0, :npix // 2] = 1
    gal2ecl = Rotator(coord=["G", "E"])
    QU_ecl = gal2ecl.rotate_map_pixel(QU_gal)

    expected = hp.ma(
        hp.read_map(os.path.join(path, "data", "justq_gal2ecl.fits.gz"),
                    [0, 1]))

    expected.mask = expected == 0

    for i_pol, pol in enumerate("QU"):
        assert ((np.abs(expected[i_pol] - QU_ecl[i_pol]) < .05).sum() /
                np.logical_not(expected[i_pol].mask).sum()) > .9, (
                    pol + " comparison failed in rotate_map")
Example #7
0
def get_cmb_lensing_map(nside=None):
    folder_path = os.path.join(DATA_PATH, 'Planck2018/COM_Lensing_2048_R2.00')
    map_path = os.path.join(folder_path, 'dat_klm.fits')
    mask_path = os.path.join(folder_path, 'mask.fits')

    # Read
    klm = hp.read_alm(map_path)
    map = hp.alm2map(klm, nside)
    mask = hp.read_map(mask_path)

    # Rotate
    rotator = Rotator(coord=['G', 'C'])
    map = rotator.rotate_map_pixel(map)
    mask = rotator.rotate_map_pixel(mask)

    # Adjust
    mask = nmt.mask_apodization(mask, 0.2, apotype='C1')
    mask = hp.ud_grade(mask, nside_out=nside)
    mask[mask < 0.1] = 0  # Visualization purpose

    map = get_masked_map(map, mask)
    mask = get_masked_map(mask, mask)
    return map, mask
Example #8
0
def test_rotate_map_polarization():
    """Compare to a rotation from Galactic to Ecliptic of
    a map of pure Q polarization, the expected value was computed with HEALPix IDL:
    https://gist.github.com/zonca/401069e1c520e02eaff8cd86149d5900
    """
    nside = 32
    npix = hp.nside2npix(nside)
    QU_gal = np.zeros((2, npix), dtype=np.double)
    QU_gal[0, : npix // 2] = 1
    gal2ecl = Rotator(coord=["G", "E"])
    QU_ecl = gal2ecl.rotate_map_pixel(QU_gal)

    expected = hp.ma(
        hp.read_map(os.path.join(path, "data", "justq_gal2ecl.fits.gz"), [0, 1])
    )

    expected.mask = expected == 0

    for i_pol, pol in enumerate("QU"):
        assert (
            (np.abs(expected[i_pol] - QU_ecl[i_pol]) < .05).sum()
            / np.logical_not(expected[i_pol].mask).sum()
        ) > .9, (pol + " comparison failed in rotate_map")
Example #9
0
def test_rotate_dipole_and_back():
    """Rotate a smooth signal (dipole) from Galactic to Ecliptic and back"""
    nside = 64
    npix = hp.nside2npix(nside)
    pix = np.arange(npix)
    vec = np.array(hp.pix2vec(nside, pix))
    # dipole max is at North Pole
    dip_dir = np.array([0, 0, 1])
    m_gal = np.dot(vec.T, dip_dir)
    gal2ecl = Rotator(coord=["C", "E"])
    ecl2gal = Rotator(coord=["E", "C"])
    m_ecl = gal2ecl.rotate_map_pixel(m_gal)
    # Remove 10 deg along equator because dipole signal is so low that relative error is
    # too large
    cut_equator_deg = 5
    no_equator = hp.query_strip(nside, np.radians(90 + cut_equator_deg),
                                np.radians(90 - cut_equator_deg))
    np.testing.assert_allclose(m_gal[no_equator],
                               ecl2gal.rotate_map_pixel(m_ecl)[no_equator],
                               rtol=1e-3)
Example #10
0
def nenufar_ant_gain(freq, polar='NW', nside=64, time=None, normalize=True):
    """ Get NenuFAR elementary antenna gain with respect to the
        frequency ``freq``, the polarization ``polar`` and
        convert it to HEALPix representation with a given
        ``nside`` that defines pixel number. The map is initially
        in horizontal coordinates, conversion to equatorial
        coordinates requires to set the ``time`` at which the 
        computation should occur.

        :param freq:
            Frequency of the returned antenna gain. Its value
            must be comprised between 10 and 80 MHz, because
            available antenna models are constrained to these
            frequencies. If the frequency value exceeds 80 MHz,
            an extrapolation is made using polynomial fits.
        :type freq: `float` or :class:`~astropy.units.Quantity`
        :param polar:
            Antenna polarization to take into account (either
            ``'NW'`` or ``'NE'``).
        :type polar: `str`
        :param nside:
            HEALPix nside parameter, must be a power of 2, less
            than 2**30 (see :func:`~healpy.pixelfunc.nside2resol`
            for corresponding angular pixel resolution).
        :type nside: `int`
        :param time:
            Time at which the computation occurs, in order to
            have the right antenna gain pattern on the sky above
            NenuFAR. If ``None`` the map is not rotated to 
            equatorial coordinates.
        :type time: `str` or :class:`~astropy.time.Time`
        :param normalize:
            Returns the normalized gain or not.
        :type normalize: `bool`

        :returns:
            Sky map in HEALPix representation of normalized
            antenna gain.
        :rtype: :class:`~numpy.ndarray`

        :Example:
            Get the antenna gain and plot it (using
            :class:`~nenupy.astro.hpxsky.HpxSky`):

            >>> from nenupy.instru import nenufar_ant_gain
            >>> from nenupy.astro import HpxSky
            >>> ant_sky = HpxSky(resolution=0.5)
            >>> ant_sky.skymap = nenufar_ant_gain(
                    freq=60,
                    polar='NW',
                    nside=ant_sky.nside,
                    time='2020-04-01 12:00:00'
                )
            >>> ant_sky.plot()

            .. image:: ./_images/antgain.png
                :width: 800

        .. seealso::
            :class:`~nenupy.beam.hpxbeam.HpxABeam`
    """
    # Parameter checks
    if not isinstance(freq, Quantity):
        freq *= u.MHz
    freq = freq.to(u.MHz).value
    if polar.lower() not in ['nw', 'ne']:
        raise ValueError(
            'Polar should be either NW or NE'
        )
    polar = polar.upper()
    # Correspondance between polar/freq and field index in FITS
    gain_freqs = np.arange(10, 90, 10, dtype=int)
    count = 0
    cols = {}
    for p in ['NE', 'NW']:#['NW', 'NE']:
        for f in gain_freqs:
            cols['{}_{}'.format(p, f)] = count
            count += 1
    antgain_file = join(
        dirname(__file__),
        'NenuFAR_Ant_Hpx.fits',
    )
    if freq < 10:
        raise ValueError(
            'No antenna model < 10 MHz.'
        )
    elif freq > 80:
        log.warning(
            'NenuFAR antenna response is extrapolated > 80 MHz.'
        )
        # Will fit a polynomial along the high end of frequencies
        freq_to_fit = np.arange(40, 90, 10, dtype=int)
        gains = np.zeros((freq_to_fit.size, nside2npix(64)))
        # Construct the gain map (freqs, npix)
        for i, f in enumerate(freq_to_fit):
            gains[i, :] = read_map(
                filename=antgain_file,
                hdu=1,
                field=cols['{}_{}'.format(polar, f)],
                verbose=False,
                memmap=True,
                dtype=float
            )
        # Get the polynomial coefficients
        coeffs = np.polyfit(freq_to_fit, gains, 3)
        def poly(x, coeffs):
            """ Retrieve the polynomial from coefficients
            """
            na = np.newaxis
            order = coeffs.shape[0]
            poly = np.zeros((x.size, coeffs.shape[1]))
            for deg in range(order):
                poly += (x**deg)[:, na] * coeffs[order-deg-1, :][na, :]
            return poly
        gain = poly(np.array([freq]), coeffs).ravel()
    else:
        # Get Low and High ant gain bounding freq
        f_low = gain_freqs[gain_freqs <= freq].max()
        f_high = gain_freqs[gain_freqs >= freq].min()
        gain_low = read_map(
            filename=antgain_file,
            hdu=1,
            field=cols['{}_{}'.format(polar, f_low)],
            verbose=False,
            memmap=True,
            dtype=float
        )
        gain_high = read_map(
            filename=antgain_file,
            hdu=1,
            field=cols['{}_{}'.format(polar, f_high)],
            verbose=False,
            memmap=True,
            dtype=float
        )
        # Make interpolation
        if f_low != f_high:
            gain = gain_low * (f_high - freq)/10. +\
                gain_high * (freq - f_low)/10.
        else:
            gain = gain_low
    # Rotate the map to equatorial coordinates
    if time is not None:
        if not isinstance(time, Time):
            time = Time(time)
        altaz_origin = AltAz(
            0*u.deg,
            0*u.deg,
            location=nenufar_loc,
            obstime=time
        )
        radec_origin = altaz_origin.transform_to(ICRS)
        rot = Rotator(
            deg=True,
            rot=[radec_origin.ra.deg, radec_origin.dec.deg], 
            coord=['C', 'C'],
            inv=True
        )
        with _HiddenPrints():
            gain = rot.rotate_map_alms(gain)
    # Convert HEALPix map to required nside
    gain = ud_grade(gain, nside_out=nside)
    return gain / gain.max() if normalize else gain
Example #11
0
def test_rotator_eq():
    rot_1 = Rotator(coord=("G", "E"))
    assert rot_1 == rot_1.get_inverse().get_inverse()
Example #12
0
def test_rotate_vector():
    gal2ecl = Rotator(coord=("G", "E"))
    gal_vec = np.array([0.1, -0.1, 1])
    gal_vec_in_ecl = gal2ecl(*gal_vec)
    np.testing.assert_allclose(gal_vec, gal2ecl.I(gal_vec_in_ecl))
Example #13
0
def test_rotator_eq():
    rot_1 = Rotator(coord=("G", "E"))
    assert rot_1 == rot_1.get_inverse().get_inverse()
Example #14
0
def test_rotator_input_lengths_inv():
    with pytest.raises(ValueError):
        Rotator(coord=[("C", "E"), ("E", "G")],
                rot=[(0, 0, 90), (0, 90, 0)],
                inv=[True])
Example #15
0
def test_rotator_input_type():
    with pytest.raises(ValueError):
        Rotator(coord="CE", rot=[(0, 0, 90)])