示例#1
0
文件: test_cmb.py 项目: pcampeti/pysm
def test_cmb_map_bandpass():

    nside = 32

    # pretend for testing that the Dust is CMB
    model = pysm.CMBMap(map_IQU="pysm_2/lensed_cmb.fits", nside=nside)

    freq = 100 * u.GHz

    expected_map = pysm.read_map("pysm_2/lensed_cmb.fits",
                                 field=0,
                                 nside=nside,
                                 unit=u.uK_CMB).to(
                                     u.uK_RJ,
                                     equivalencies=u.cmb_equivalencies(freq))

    print(
        "expected_scaling",
        (1 * u.K_CMB).to_value(u.K_RJ,
                               equivalencies=u.cmb_equivalencies(freq)),
    )

    freqs = np.array([98, 99, 100, 101, 102]) * u.GHz
    weights = np.ones(len(freqs))

    # just checking that the result is reasonably close
    # to the delta frequency at the center frequency

    assert_quantity_allclose(expected_map,
                             model.get_emission(freqs, weights)[0],
                             rtol=1e-3)
示例#2
0
def test_precomputed_alms(setup):

    alms, filename = setup

    nside = 64
    # we assume the original `alms` are in `K_CMB`
    ref_freq = 40 * u.GHz
    test_map_K_CMB = hp.alm2map(alms, nside=nside) << u.K_CMB

    alms_K_RJ = alms.to(u.K_RJ, equivalencies=u.cmb_equivalencies(ref_freq))
    filename_K_RJ = filename.replace(".fits", "_RJ.fits")
    hp.write_alm(filename_K_RJ, alms_K_RJ)

    precomputed_alms = PrecomputedAlms(
        filename=filename_K_RJ,
        nside=nside,
        input_units="K_RJ",
        input_reference_frequency=ref_freq,
    )
    m = precomputed_alms.get_emission(23 * u.GHz)

    assert_quantity_allclose(
        m,
        test_map_K_CMB.to(u.K_RJ,
                          equivalencies=u.cmb_equivalencies(23 * u.GHz)))

    freqs = np.array([1, 10, 100]) * u.GHz

    for freq in freqs:
        np.testing.assert_allclose(
            precomputed_alms.get_emission(freq),
            test_map_K_CMB.to(u.K_RJ, equivalencies=u.cmb_equivalencies(freq)))
示例#3
0
    def test_conversion(self):
        """ Here we test that the numerical value of the conversion is correct.
        The mathematical form is

        ..math::
        I_\nu = \frac{2 \nu^2 k T_{\rm RJ}}{c^2} \\
        I_\nu = T_{\rm CMB} B^\prime_\nu(T_{\rm CMB, 0})

        so, eliminating the flux in this equation:

        ..math::
        T_{\rm RJ} / T_{\rm CMB} = \frac{c^2}{2 \nu^2 k_B}B^\prime_\nu(T_{\rm CMB, 0})

        Here we calculate the RHS of this equation and compare it to the
        ratio of T_RJ and the result of its transformation to T_CMB.
        """
        equiv = {"equivalencies": units.cmb_equivalencies(self.freqs)}
        rj_from_cmb = self.T_CMB.to(units.K_RJ, **equiv)
        cmb_from_rj = self.T_RJ.to(units.K_CMB, **equiv)

        # check that the reverse transformation gives overall transformation of unity.
        reverse1 = rj_from_cmb.to(units.K_CMB, **equiv)
        reverse2 = cmb_from_rj.to(units.K_RJ, **equiv)

        np.testing.assert_almost_equal(1.0, self.T_CMB / reverse1, decimal=6)
        np.testing.assert_almost_equal(1.0, self.T_RJ / reverse2, decimal=6)
示例#4
0
    def __init__(
        self,
        filename,
        input_units="uK_CMB",
        input_reference_frequency=None,
        nside=None,
        target_shape=None,
        target_wcs=None,
        precompute_output_map=True,
        has_polarization=True,
        map_dist=None,
    ):
        """Generic component based on Precomputed Alms

        Load a set of Alms from a FITS file and generate maps at the requested
        resolution and frequency assuming the CMB black body spectrum.
        A single set of Alms is used for all frequencies requested by PySM,
        consider that PySM expects the output of components to be in uK_RJ.

        See more details at https://so-pysm-models.readthedocs.io/en/latest/so_pysm_models/models.html

        Parameters
        ----------
        filename : string
            Path to the input Alms in FITS format
        input_units : string
            Input unit strings as defined by pysm.convert_units, e.g. K_CMB, uK_RJ, MJysr
        input_reference_frequency: float
            If input units are K_RJ or Jysr, the reference frequency
        nside : int
            HEALPix NSIDE of the output maps
        precompute_output_map : bool
            If True (default), Alms are transformed into a map in the constructor,
            if False, the object only stores the Alms and generate the map at each
            call of the signal method, this is useful to generate maps convolved
            with different beams
        has_polarization : bool
            whether or not to simulate also polarization maps
            Default: True
        """

        super().__init__(nside=nside, map_dist=map_dist)
        self.shape = target_shape
        self.wcs = target_wcs
        self.filename = filename
        self.input_units = u.Unit(input_units)
        self.has_polarization = has_polarization

        alm = np.complex128(
            hp.read_alm(self.filename,
                        hdu=(1, 2, 3) if self.has_polarization else 1))

        self.equivalencies = (None if input_reference_frequency is None else
                              u.cmb_equivalencies(input_reference_frequency))
        if precompute_output_map:
            self.output_map = self.compute_output_map(alm)

        else:
            self.alm = alm
示例#5
0
    def get_emission(self,
                     freqs: u.GHz,
                     fwhm: [u.arcmin, None] = None,
                     weights=None) -> u.uK_RJ:
        """Return map in uK_RJ at given frequency or array of frequencies

        Parameters
        ----------
        freqs : list or ndarray
            Frequency or frequencies in GHz at which compute the signal
        fwhm : float (optional)
            Smooth the input alms before computing the signal, this can only be used
            if the class was initialized with `precompute_output_map` to False.
        output_units : str
            Output units, as defined in `pysm.convert_units`, by default this is
            "uK_RJ" as expected by PySM.

        Returns
        -------
        output_maps : ndarray
            Output maps array with the shape (num_freqs, 1 or 3 (I or IQU), npix)
        """

        try:
            nfreqs = len(freqs)
        except TypeError:
            nfreqs = 1
            freqs = freqs.reshape((1, ))

        try:
            output_map = self.output_map
        except AttributeError:
            if fwhm is None:
                alm = self.alm
            else:
                alm = hp.smoothalm(self.alm,
                                   fwhm=fwhm.to_value(u.radian),
                                   pol=True,
                                   inplace=False)

            output_map = self.compute_output_map(alm)

        convert_to_uK_RJ = (np.ones(len(freqs), dtype=np.double) *
                            u.uK_CMB).to_value(
                                u.uK_RJ,
                                equivalencies=u.cmb_equivalencies(freqs))

        if nfreqs == 1:
            scaling_factor = convert_to_uK_RJ[0]
        else:
            scaling_factor = np.trapz(convert_to_uK_RJ * weights,
                                      x=freqs.value)

        return output_map.value * scaling_factor << u.uK_RJ
示例#6
0
def test_bandpass_unit_conversion():
    freqs = np.array([250, 300, 350]) * u.GHz
    weights = np.ones(len(freqs))
    norm_weights = pysm.normalize_weights(freqs.value, weights)
    conversion_factor = pysm.utils.bandpass_unit_conversion(
        freqs, weights, "uK_CMB")

    each_factor = [(1 * u.uK_RJ).to_value(u.uK_CMB,
                                          equivalencies=u.cmb_equivalencies(f))
                   for f in freqs]
    expected_factor = np.trapz(each_factor * norm_weights, freqs.value)

    np.testing.assert_allclose(expected_factor, conversion_factor.value)
示例#7
0
def test_precomputed_alms_K_CMB(setup):

    alms, filename = setup

    nside = 64
    test_map = hp.alm2map(alms, nside=nside) << u.K_CMB
    precomputed_alms = PrecomputedAlms(filename=filename,
                                       nside=nside,
                                       input_units="K_CMB")

    freqs = np.array([1, 10, 100]) * u.GHz

    for freq in freqs:
        np.testing.assert_allclose(
            precomputed_alms.get_emission(freq),
            test_map.to(u.K_RJ, equivalencies=u.cmb_equivalencies(freq)))
示例#8
0
def get_noise_realization(nside, instrument, unit='uK_CMB'):
    """ Generate noise maps for the instrument

    Parameters
    ----------
    nside: int
        Desired output healpix nside.
    instrument:
        Object that provides the following as a key or an attribute.

        - **frequency** (required)
        - **depth_p** (required if ``noise=True``)
        - **depth_i** (required if ``noise=True``)

        They can be anything that is convertible to a float numpy array.
        If only one of ``depth_p`` or ``depth_i`` is provided, the other is
        inferred assuming that the former is sqrt(2) higher than the latter.
    unit: str
        Unit of the output. Only K_CMB and K_RJ (and multiples) are supported.
    sky: str of pysm.Sky
        Sky to observe. It can be a `pysm.Sky` or a tag to create one.
    noise: bool
        If true, add Gaussian, uncorrelated, isotropic noise.

    Returns
    -------
    observation: array
        Shape is ``(n_freq, 3, n_pix)``.
    """
    instrument = standardize_instrument(instrument)
    if not hasattr(instrument, 'depth_i'):
        instrument.depth_i = instrument.depth_p / np.sqrt(2)
    if not hasattr(instrument, 'depth_p'):
        instrument.depth_p = instrument.depth_i * np.sqrt(2)


    n_freq = len(instrument.frequency)
    n_pix = hp.nside2npix(nside)
    res = np.random.normal(size=(n_pix, 3, n_freq))
    depth = np.stack(
        (instrument.depth_i, instrument.depth_p, instrument.depth_p))
    depth *= u.arcmin * u.uK_CMB
    depth = depth.to(
        getattr(u, unit) * u.arcmin,
        equivalencies=u.cmb_equivalencies(instrument.frequency * u.GHz))
    res *= depth.value / hp.nside2resol(nside, True)
    return res.T
示例#9
0
    def signal(self):
        """
        Simulate CO signal
        """
        out = hp.ud_grade(map_in=self.planck_templatemap, nside_out=self.target_nside) << u.K_CMB

        if self.include_high_galactic_latitude_clouds:
            out += self.simulate_high_galactic_latitude_CO()

        if self.has_polarization:
            Q_map, U_map = self.simulate_polarized_emission(out)
            out = np.array([out, Q_map, U_map])

        convert_to_uK_RJ = (1 * u.K_CMB).to_value(
            self.output_units, equivalencies=u.cmb_equivalencies(self.line_frequency)
        )

        return out * convert_to_uK_RJ
示例#10
0
def test_precomputed_alms():
    alms_filename = get_pkg_data_filename(
        "data/fullskyUnlensedUnabberatedCMB_alm_set00_00000.fits.zip")
    save_name = get_pkg_data_filename("data/test_cmb_map.fits.zip")
    nside = 32
    # Make an IQU sim
    precomputed_alms = PrecomputedAlms(
        alms_filename,
        nside=nside,
        input_units="uK_CMB",
        has_polarization=True,
        #input_reference_frequency=148*u.GHz
    )
    simulated_map = precomputed_alms.get_emission(148 * u.GHz).to(
        u.uK_CMB, equivalencies=u.cmb_equivalencies(148 * u.GHz))
    expected_map = hp.read_map(save_name, field=(0, 1, 2)) << u.uK_CMB
    assert_quantity_allclose(simulated_map, expected_map)
    assert simulated_map.shape[0] == 3
示例#11
0
    def get_emission(self, freqs: u.GHz, weights=None) -> u.uK_RJ:

        nu = freqs.to(u.GHz)
        weights = normalize_weights(freqs, weights)

        if nu.isscalar:
            nu = nu.reshape(1)

        filename = utils.get_data_from_url(self.get_filename())
        m = self.read_map(filename, field=0, unit=u.uK_CMB)

        weights = (weights * u.uK_CMB).to_value(
            u.uK_RJ, equivalencies=u.cmb_equivalencies(nu))

        is_thermal = self.sz_type == "thermal"
        output = (get_sz_emission_numba(nu.value, weights, m.value, is_thermal)
                  << u.uK_RJ)

        # the output of out is always 2D, (IQU, npix)
        return output
示例#12
0
文件: test_cmb.py 项目: pcampeti/pysm
def test_cmb_map():

    nside = 32

    # pretend for testing that the Dust is CMB
    model = pysm.CMBMap(map_IQU="pysm_2/lensed_cmb.fits", nside=nside)

    freq = 100 * u.GHz

    expected_map = pysm.read_map("pysm_2/lensed_cmb.fits",
                                 field=(0, 1),
                                 nside=nside,
                                 unit=u.uK_CMB).to(
                                     u.uK_RJ,
                                     equivalencies=u.cmb_equivalencies(freq))

    simulated_map = model.get_emission(freq)
    for pol in [0, 1]:
        assert_quantity_allclose(expected_map[pol],
                                 simulated_map[pol],
                                 rtol=1e-5)
示例#13
0
def get_cmb_realization(nside, cl_path, beams, frequencies, seed=100):
    with h5py.File(f"{cl_path}", 'r') as f:
        cl_total = np.swapaxes(f['lensed_scalar'][...], 0, 1)
    cmb = hp.synfast(cl_total, nside, new=True, verbose=False)
    cmb = [hp.smoothing(cmb, fwhm=b / 60. * np.pi/180., verbose=False)[1:] * u.uK_CMB for b in beams]
    return np.array([c.to(u.uK_RJ, equivalencies=u.cmb_equivalencies(f)) for c, f in zip(cmb, frequencies)])
示例#14
0
def _rj2cmb(freqs):
    return (np.ones_like(freqs) * u.K_RJ).to(
        u.K_CMB, equivalencies=u.cmb_equivalencies(freqs * u.GHz)).value
示例#15
0
def _cmb2rj(freqs):
    return (np.ones_like(freqs) * u.K_CMB).to(
        u.K_RJ, equivalencies=u.cmb_equivalencies(freqs * u.GHz)).value
示例#16
0
def get_observation(instrument='', sky=None,
                    noise=False, nside=None, unit='uK_CMB'):
    """ Get a pre-defined instrumental configuration

    Parameters
    ----------
    instrument:
        It can be either a `str` (see :func:`get_instrument`) or an
        object that provides the following as a key or an attribute.

        - **frequency** (required)
        - **depth_p** (required if ``noise=True``)
        - **depth_i** (required if ``noise=True``)

        They can be anything that is convertible to a float numpy array.
        If only one of ``depth_p`` or ``depth_i`` is provided, the other is
        inferred assuming that the former is sqrt(2) higher than the latter.
    sky: str of pysm.Sky
        Sky to observe. It can be a `pysm.Sky` or a tag to create one.
    noise: bool
        If true, add Gaussian, uncorrelated, isotropic noise.
    nside: int
        Desired output healpix nside. It is optional if `sky` is a `pysm.Sky`,
        and required if it is a `str` or ``None``.
    unit: str
        Unit of the output. Only K_CMB and K_RJ (and multiples) are supported.

    Returns
    -------
    observation: array
        Shape is ``(n_freq, 3, n_pix)``
    """
    if isinstance(instrument, str):
        instrument = get_instrument(instrument)
    else:
        instrument = standardize_instrument(instrument)
    if nside is None:
        nside = sky.nside
    elif not isinstance(sky, str):
        try:
            assert nside == sky.nside, (
                "Mismatch between the value of the nside of the pysm.Sky "
                "argument and the one passed in the nside argument.")
        except AttributeError:
            raise ValueError("Either provide a pysm.Sky as sky argument "
                             " or specify the nside argument.")

    if noise:
        res = get_noise_realization(nside, instrument, unit)
    else:
        res = np.zeros((len(instrument.frequency), 3, hp.nside2npix(nside)))

    if sky is None or sky == '':
        return res

    if isinstance(sky, str):
        sky = get_sky(nside, sky)

    for res_freq, freq in zip(res, instrument.frequency):
        emission = sky.get_emission(freq * u.GHz).to(
            getattr(u, unit),
            equivalencies=u.cmb_equivalencies(freq * u.GHz))
        res_freq += emission.value

    return res
示例#17
0
def main(cfg_path: Path, log_level: int):
    logging.basicConfig(stream=sys.stdout,
                        level=log_level,
                        datefmt='%Y-%m-%d %H:%M',
                        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

    with open(cfg_path) as f:
        cfg = yaml.load(f, Loader=yaml.FullLoader)

    freqs = old_np.array(cfg['frequencies']) * u. GHz
    nside = cfg['nside']
    components = cfg['skymodel']['args']
    sensitivities = cfg['sensitivities']
    nmc = cfg['monte_carlo']
    beams = cfg['fwhm']
    outpath = cfg['hdf5_path']
    half_mission_noise = cfg['half_mission_noise']
    cosmo_path = cfg['cosmo_path']
    
    if half_mission_noise:
        sensitivities = [s * np.sqrt(2.) for s in sensitivities]
    
    logging.info(f"""
    Frequencies: {freqs!s}
    Nside: {nside:04d}
    Components: {components!s}
    Sensitivities: {sensitivities!s}
    Number of Monte Carlo Simulations: {nmc:05d}
    """)

    # Generate sky signal
    sky = pysm.Sky(nside=nside, **components)
    fgnd = (sky.get_emission(f) for f in freqs)
    fgnd = (hp.smoothing(s, fwhm=b / 60. * np.pi / 180., verbose=False)[None, 1:, ...] for b, s in zip(beams, fgnd))
    fgnd = np.concatenate(list(fgnd))

    # Make noise generator
    sens = np.array(sensitivities) * u.uK_CMB
    sens = np.array([w.to(u.uK_RJ, equivalencies=u.cmb_equivalencies(f)) for w, f in zip(sens, freqs)])
    noise_generator = WhiteNoise(sens=sens)

    cov = noise_generator.get_pix_var_map(nside)

    logging.info(f"Output path: {outpath}")

    with h5py.File(outpath, 'a') as f:
        f.attrs.update({'config': yaml.dump(cfg)})
        maps = f.require_group('maps')
        monte_carlo = maps.require_group('monte_carlo')
        components = maps.require_group('components')

        data_dset = monte_carlo.require_dataset('data', shape=(nmc, len(freqs), 2, hp.nside2npix(nside)), dtype=np.float32)

        cov_dset = monte_carlo.require_dataset('cov', shape=(nmc, len(freqs), 2, hp.nside2npix(nside)), dtype=np.float32)
        cov_dset[...] = cov.astype(np.float32)
        
        for imc in np.arange(nmc)[::2]:

            logging.info(f"Working on CMB MC: {imc:04d}")

            cmb = get_cmb_realization(nside, cosmo_path, beams, freqs, seed=imc)

            for j in range(imc, imc + 2):

                logging.info(f"Working on noise MC: {j:04d}")

                data = fgnd + cmb + noise_generator.map(nside, seed=j)

                logging.debug(f"Data shape: {data.shape!r}")

                data_dset[j] = data