Ejemplo n.º 1
0
    def test_pospix(self):
        # Posmap separable and non-separable on CAR
        for res in [6,12,24]:
            shape,wcs = enmap.fullsky_geometry(res=np.deg2rad(res/60.),proj='car')
            posmap1 = enmap.posmap(shape,wcs)
            posmap2 = enmap.posmap(shape,wcs,separable=True)
            assert np.all(np.isclose(posmap1,posmap2))

        # Pixmap plain
        pres = 0.5
        shape,wcs = enmap.geometry(pos=(0,0),shape=(30,30),res=pres*u.degree,proj='plain')
        yp,xp = enmap.pixshapemap(shape,wcs)
        assert np.all(np.isclose(yp,pres*u.degree))
        assert np.all(np.isclose(xp,pres*u.degree))
        yp,xp = enmap.pixshape(shape,wcs)
        parea = enmap.pixsize(shape,wcs)
        assert np.isclose(parea,(pres*u.degree)**2)
        assert np.isclose(yp,pres*u.degree)
        assert np.isclose(xp,pres*u.degree)
        pmap = enmap.pixsizemap(shape,wcs)
        assert np.all(np.isclose(pmap,(pres*u.degree)**2))

        # Pixmap CAR
        pres = 0.1
        dec_cut = 89.5 # pixsizemap is not accurate near the poles currently
        shape,wcs = enmap.band_geometry(dec_cut=dec_cut*u.degree,res=pres*u.degree,proj='car')
        # Current slow and general but inaccurate near the poles implementation
        pmap = enmap.pixsizemap(shape,wcs)
        # Fast CAR-specific pixsizemap implementation
        dra, ddec = wcs.wcs.cdelt*u.degree
        dec = enmap.posmap([shape[-2],1],wcs)[0,:,0]
        area = np.abs(dra*(np.sin(np.minimum(np.pi/2.,dec+ddec/2))-np.sin(np.maximum(-np.pi/2.,dec-ddec/2))))
        Nx = shape[-1]
        pmap2 = enmap.ndmap(area[...,None].repeat(Nx,axis=-1),wcs)
        assert np.all(np.isclose(pmap,pmap2))
Ejemplo n.º 2
0
def apod_C2(input_mask, radius):
    r"""
    Apodizes an input mask over a radius in degrees.

    A sharp mask will cause complicated mode coupling and ringing. One solution
    is to smooth out the sharp edges. This function applies the C2 apodisation
    as defined in 0903.2350_.

    .. _0903.2350: https://arxiv.org/abs/0903.2350

    Parameters
    ----------
    input_mask: enmap
        The input mask (must have all pixel values be non-negative).
    radius: float
        Apodization radius in degrees.

    Returns
    -------
    result : enmap
        The apodized mask.

    """
    if radius == 0:
        return input_mask
    else:
        dist = get_distance(input_mask)
        id = np.where(dist > radius)
        win = dist / radius - np.sin(2 * np.pi * dist / radius) / (2 * np.pi)
        win[id] = 1

    return enmap.ndmap(win, input_mask.wcs)
Ejemplo n.º 3
0
    def _enmapify(self, data):
        """Promote a numpy.ndarray to an enmap.ndmap by attaching
        wcs=self.geom[1].  In sensible cases (e.g. data is an ndarray
        or ndmap) this will not cause a copy of the underlying data
        array.

        """
        return enmap.ndmap(data, wcs=self.geom[1])
Ejemplo n.º 4
0
 def get_map(self,weights=None):
     if self.verbose: print("Calculating histogram...")
     if self.curved:
         return np.histogram(self.pixs,bins=self.shape,weights=weights,range=[0,self.shape],density=False)[0].astype(np.float32)
     else:
         Ny,Nx = self.shape[-2:]
         return enmap.ndmap(np.histogram2d(self.pixs[0,:],self.pixs[1,:],
                                           bins=self.shape,weights=weights,
                                           range=[[0,Ny],[0,Nx]],density=False)[0],self.wcs)
Ejemplo n.º 5
0
def filter_riseset(imap, ivar, riseset, filter, tol=1e-4, ref=0.9):
    """Filter enmap imap with the given 2d fourier filter while
	weighting spatially with ivar and allowing for rise vs set-dependent
	pickup. riseset should be a map with values between -1 and 1 that determines
	the balance between rising and setting scans, with 0 meaning equal weight from both.
	Overall this is only a marginal improvement over filter_weighted depsite being
	quite a bit heaver, and it only helps a bit for the pa7 residual stripe issue it
	was invented to deal with, so it probably isn't worth using.
	"""
    # We model the map as m = Pa+n, where a is [2] is the rising and setting pickup in
    # a single pixel, and P is the map's response to this pickup, which is
    # P = [x,1-x]*filter, where x=(1-riseset)/2. Given this we can solve for a as:
    # a = (P'N"P)"P'N"m, where N" is ivar. Written out this becomes, for a single pixel.
    # rhs = ifft(filter*fft([x,1-x]*ivar*imap))
    # div = ifft(filter*fft([x,1-x]*ivar*[x,1-x]*ifft(filter)
    # Hm.... The problem here is that we're assuming that there's nothing in the other pixels.
    # That's not what we did in filter_weighted. Let's just do something simple for now.
    x = (1 - riseset) / 2
    x1x = np.array([x, 1 - x])
    del x
    # Broadcast to imap shape
    x1x = x1x[(slice(None), ) + (None, ) * (imap.ndim - 2)]
    print(imap.shape, x1x.shape)
    filter = 1 - filter
    rhs = enmap.ifft(filter * enmap.fft(x1x * ivar * imap)).real
    div = enmap.ifft(filter *
                     enmap.fft(x1x[:, None] * x1x[None, :] * ivar)).real
    del filter
    # Avoid division by very low values
    ref = np.percentile(ivar[::10, ::10], ref * 100) * tol
    for i in range(2):
        div[i, i] = np.maximum(div[i, i], ref)
    # Solve the system
    rhs = np.moveaxis(rhs, 0, -1)
    div = np.moveaxis(div, (0, 1), (-2, -1))
    omap = np.linalg.solve(div, rhs)
    del rhs, div
    omap = np.sum(x1x * np.moveaxis(omap, -1, 0), 0)
    del x1x
    omap = enmap.ndmap(omap, imap.wcs)
    omap *= -1
    omap += imap
    omap *= imap != 0
    return omap
Ejemplo n.º 6
0
def getActpolCmbFgSim(beamfileDict,
                      shape, wcs,
                      iterationNum, cmbDir, freqs, psa,
                      cmbSet = 0, \
                      doBeam = True, applyWindow = True, verbose = True, cmbMaptype = 'LensedCMB',
                      foregroundSeed = 0, simType = 'cmb', foregroundPowerFile = None, applyModulation = True):

    nTQUs = len('TQU')
    firstTime = True

    output = enmap.empty((
        len(freqs),
        nTQUs,
    ) + shape[-2:], wcs)

    if simType == 'cmb':

        filename = cmbDir + "/fullsky%s_alm_set%02d_%05d.fits" % (
            cmbMaptype, cmbSet, iterationNum)
        if verbose:
            print('getActpolCmbFgSim(): loading CMB a_lms from %s' % filename)
        import healpy
        almTebFullskyOnecopy = np.complex128(
            healpy.fitsfunc.read_alm(filename, hdu=(1, 2, 3)))

        #Now tile the same for all the frequencies requested (i.e. CMB is same at all frequencies).
        #The beam convolution happens below.
        almTebFullsky = np.tile(almTebFullskyOnecopy, (len(freqs), 1, 1))

        if verbose:
            print('getActpolCmbFgSim(): done')

    elif simType == 'foregrounds':
        outputFreqs = ['f090', 'f150']

        foregroundPowers \
            = powspec.read_spectrum(os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                                 '../data/',
                                                 foregroundPowerFile),
                                ncol = 3,
                                expand = 'row')

        if verbose:
            print('getActpolCmbFgSim(): getting foreground a_lms')
        almTFullsky90and150 = curvedsky.rand_alm(foregroundPowers,
                                                 seed=foregroundSeed)

        almTebFullsky = np.zeros((
            len(freqs),
            nTQUs,
        ) + (len(almTFullsky90and150[-1]), ),
                                 dtype=np.complex128)

        for fi, freq in enumerate(freqs):
            if freq in outputFreqs:
                almTebFullsky[fi, 'TQU'.index('T'), :]  \
                    = almTFullsky90and150[outputFreqs.index(freq), :]

    #Convolve with beam on full sky
    for fi, freq in enumerate(freqs):
        if doBeam:
            beamFile = beamfileDict[psa + '_' + freq]
            if verbose:
                print('getActpolCmbFgSim(): applying beam from %s' % beamFile)
            beamData = (np.loadtxt(beamFile))[:, 1]
        else:
            if verbose:
                print('getActpolCmbFgSim(): not convolving with beam')
            beamData = np.repeat(1., almTebFullsky.shape[-1])

        import healpy

        #couldn't quickly figure out how to vectorize this so loop from 0 to 2.
        for tqui in range(nTQUs):
            almTebFullsky[fi, tqui] = healpy.sphtfunc.almxfl(
                almTebFullsky[fi, tqui].copy(), beamData)

        #These lines stolen from curvedsky.rand_map
        #doing all freqs at once gives error:
        #sharp.pyx in sharp.execute_dp (cython/sharp.c:12118)()
        #ValueError: ndarray is not C-contiguous
        #so loop over all freqs once for now.

    curvedsky.alm2map(almTebFullsky, output, spin=[0, 2], verbose=True)

    # outputThisfreq   = enmap.empty(( nTQUs,)+shape[-2:], wcs)
    # curvedsky.alm2map(almTebFullsky[fi,:,:], outputThisfreq, spin = [0,2],  verbose = True)
    # output[fi,...] = outputThisfreq

    # curvedsky.alm2map(almTebFullsky[fi,:,:], output[fi,:,:,:], spin = [0,2],  verbose = True)

    if applyModulation:
        from pixell import aberration
        for fi, freq in enumerate(freqs):

            print('applying modulation for frequency %s' % freq)
            output, A = aberration.boost_map(output,
                                             aberration.dir_equ,
                                             aberration.beta,
                                             return_modulation=True,
                                             aberrate=False,
                                             freq=freqStrToValGhz[freq] * 1e9)

    if applyWindow:
        from pixell import fft

        #The axes along which to FFT
        axes = [-2, -1]
        if verbose:
            print('getActpolCmbFgSim(): applying pixel window function')

        nfreq = len(freqs)
        for idx in range(nfreq):
            fd = fft.fft(output[idx], axes=axes)
            wy, wx = enmap.calc_window(fd.shape)
            twoDWindow = wy[:, None]**1 * wx[None, :]**1

            #Careful, this is quietly multiplying an array with shape [N_freq, N_TQU, N_y, N_x] with one of shape [N_y, N_x]
            fd *= twoDWindow

            output[idx] = (fft.ifft(fd, axes=axes, normalize=True)).real
            del fd
        if verbose:
            print('getActpolCmbFgSim(): done')

    return enmap.ndmap(output, wcs)
Ejemplo n.º 7
0
def read_data(fnames,
              sel=None,
              pixbox=None,
              box=None,
              geometry=None,
              comp=0,
              split=0,
              unit="flux",
              dtype=np.float32,
              beam_rmax=5 * utils.degree,
              beam_res=2 * utils.arcsec,
              deconv_pixwin=True,
              apod=15 * utils.arcmin,
              mask=None,
              ivscale=[1, 0.5, 0.5]):
    """Read multi-frequency data for a single split of a single component, preparing it for
	analysis."""
    # Read in our data files and harmonize
    br = np.arange(0, beam_rmax, beam_res)
    data = bunch.Bunch(maps=[],
                       ivars=[],
                       beams=[],
                       freqs=[],
                       l=None,
                       bls=[],
                       names=[],
                       beam_profiles=[])
    for ifile in fnames:
        d = mapdata.read(ifile,
                         sel=sel,
                         pixbox=pixbox,
                         box=box,
                         geometry=geometry)
        # The 0 here is just selecting the first split. That is, we don't support splits
        data.maps.append(d.maps[split].astype(dtype)[comp])
        data.ivars.append(d.ivars[split].astype(dtype) * ivscale[comp])
        data.freqs.append(d.freq)
        if data.l is None: data.l = d.maps[0].modlmap()
        data.beams.append(
            enmap.ndmap(
                np.interp(data.l, np.arange(len(d.beam)),
                          d.beam / np.max(d.beam)),
                d.maps[0].wcs).astype(dtype))
        data.names.append(".".join(os.path.basename(ifile).split(".")[:-1]))
        data.bls.append(d.beam)
        data.beam_profiles.append(
            np.array([br, curvedsky.harm2profile(d.beam, br)]).astype(dtype))

    data.maps = enmap.enmap(data.maps)
    data.ivars = enmap.enmap(data.ivars)
    data.beams = enmap.enmap(data.beams)
    data.freqs = np.array(data.freqs)
    if unit == "uK":
        data.fconvs = np.full(len(data.freqs), 1.0, dtype)
    elif unit == "flux":
        data.fconvs = (utils.dplanck(data.freqs * 1e9, utils.T_cmb) /
                       1e3).astype(dtype)  # uK -> mJy/sr
    else:
        raise ValueError("Unrecognized unit '%s'" % str(unit))
    data.n = len(data.freqs)

    # Apply the unit
    data.maps *= data.fconvs[:, None, None]
    data.ivars /= data.fconvs[:, None, None]**2

    if mask is not None:
        mask_map = 1 - enmap.read_map(mask, sel=sel, pixbox=pixbox, box=box)
        data.ivars *= mask_map
        del mask_map

    # Should generalize this to handle internal map edges and frequency differences
    mask = enmap.shrink_mask(enmap.grow_mask(data.ivars > 0, 1 * utils.arcmin),
                             1 * utils.arcmin)
    apod_map = enmap.apod_mask(mask, apod)
    data.apod = apod_map
    data.fapod = np.mean(apod_map**2)
    data.maps *= apod_map
    data.ivars *= apod_map**2

    # Get the pixel window and optionall deconvolve it
    data.wy, data.wx = [
        w.astype(dtype) for w in enmap.calc_window(data.maps.shape)
    ]
    if deconv_pixwin:
        data.maps = enmap.ifft(
            enmap.fft(data.maps) / data.wy[:, None] / data.wx[None, :]).real

    return data
Ejemplo n.º 8
0
 def unzip(self, x):
     return enmap.ndmap(x.reshape(self.shape), self.wcs)