Esempio n. 1
0
def process_splits(splits,
                   wins,
                   mask,
                   skip_splits=False,
                   do_fft_splits=False,
                   pixwin=False):
    assert wins.ndim > 2
    with np.errstate(divide='ignore', invalid='ignore'):
        coadd = (splits * wins).sum(axis=0) / wins.sum(axis=0)
    coadd[~np.isfinite(coadd)] = 0
    Ny, Nx = splits.shape[-2:]
    assert coadd.shape == (Ny, Nx)
    kcoadd = enmap.enmap(enmap.fft(coadd * mask, normalize='phys'), wins.wcs)

    if pixwin: pwin = tutils.get_pixwin(coadd.shape[-2:])
    else: pwin = 1
    kcoadd = kcoadd / pwin
    if not (skip_splits):
        #data = (splits-coadd)*mask # !!!! wins removed, was (splits-coadd)*wins*mask earlier
        data = (splits - coadd) * mask * wins / wins.sum(
            axis=0)  # !!!! wins removed, was (splits-coadd)*wins*mask earlier
        data[~np.isfinite(data)] = 0
        kdiffs = enmap.fft(data, normalize='phys')
        kdiffs = kdiffs / pwin
    else:
        kdiffs = None
    if do_fft_splits:
        ksplits = enmap.fft(splits * wins * mask, normalize='phys')
        ksplits = ksplits / pwin
        return kdiffs, kcoadd, ksplits
    else:
        return kdiffs, kcoadd
Esempio n. 2
0
def get_n2d_data(splits,ivars,mask_a,coadd_estimator=False,flattened=False,plot_fname=None,dtype=None):
    assert np.all(np.isfinite(splits))
    assert np.all(np.isfinite(ivars))
    assert np.all(np.isfinite(mask_a))

    if coadd_estimator:
        coadd,civars = get_coadd(splits,ivars,axis=1)
        data  = splits - coadd[:,None,...]
        del coadd
    else:
        data = splits

    assert np.all(np.isfinite(data))
    if flattened:
        # sivars = np.sqrt(ivars)
        sivars   = ((1./ivars) - (1./civars[:,None,...]))**-0.5
        sivars[~np.isfinite(sivars)] = 0
        ffts = enmap.fft(data*mask_a*sivars,normalize="phys")
        if plot_fname is not None: plot(plot_fname+"_fft_maps",data*mask_a*sivars,quantile=0)
        wmaps = mask_a + enmap.zeros(ffts.shape,mask_a.wcs,dtype=dtype) # WARNING: type
        del ivars, data, splits
    else:
        assert np.all(np.isfinite(data*mask_a*ivars))
        ffts = enmap.fft(data*mask_a*ivars,normalize="phys")
        if plot_fname is not None: plot(plot_fname+"_fft_maps",data*mask_a*ivars,quantile=0)
        wmaps = ivars * mask_a
        del ivars, data, splits
    n2d = get_n2d(ffts,wmaps,coadd_estimator=coadd_estimator,plot_fname=plot_fname,dtype=dtype)
    assert np.all(np.isfinite(n2d))
    return n2d
Esempio n. 3
0
 def test_fft(self):
     # Tests that ifft(ifft(imap))==imap, i.e. default normalizations are consistent
     shape, wcs = enmap.geometry(pos=(0, 0), shape=(3, 100, 100), res=0.01)
     imap = enmap.enmap(np.random.random(shape), wcs)
     assert np.all(
         np.isclose(
             imap,
             enmap.ifft(enmap.fft(imap, normalize='phy'),
                        normalize='phy').real))
     assert np.all(np.isclose(imap, enmap.ifft(enmap.fft(imap)).real))
Esempio n. 4
0
    def gather_patches_cos(self):
        """Assemble patch statistics for small scale lensing with cos filter.
        
        Compute the small scale (ell > 3000) temperature power at different 
        patches across the sky as well as the average amplitude of the 
        background temperature gradient (ell < 2000). For the small scale 
        statistics, also apply a filter in Fourier space such that:

        .. math::
            f_\\ell = \\cos(\\hat{\\ell}\\cdot\\hat{\\nabla T})

        """
        self._edge = 5  # Edge pixels to throw away
        p = self._p
        m_fft = enmap.fft(self.map_in)
        hp = np.zeros(self.map_in.shape)
        hp[np.where((self._lmod > self.lmin) & (self._lmod < self.lmax))] = 1.
        # Apply pre-whitening or Wiener/inverse variance filters, then top hat
        if self._aW and self.fid is not None:
            cs = CubicSpline(self.fid[0], self.fid[1])  # (ell, Cl)
            m_fft = m_fft / cs(self._lmod)
        self._Tss = enmap.ifft(m_fft * hp)
        self._dTy, self._dTx = gradient_flat(self.map_in, self.ldT)
        # Scale geometry for lower res map of patches
        pshp, pwcs = enmap.scale_geometry(self.map_in.shape, self.map_in.wcs,
                                          1. / self._p)
        if not self.savesteps:
            del self.map_in, m_fft
        self._T2patch = enmap.zeros(pshp, pwcs)
        self._dTxpatch = enmap.zeros(pshp, pwcs)
        self._dTypatch = enmap.zeros(pshp, pwcs)
        self._T_sub = np.zeros((pshp[-2], pshp[-1], p, p))
        for i in range(self._T2patch.shape[-2]):
            for j in range(self._T2patch.shape[-1]):
                self._dTypatch[i, j] = np.mean(self._dTy[i * p:(i + 1) * p,
                                                         j * p:(j + 1) * p])
                self._dTxpatch[i, j] = np.mean(self._dTx[i * p:(i + 1) * p,
                                                         j * p:(j + 1) * p])
                Tp = self._Tss[i * p:(i + 1) * p, j * p:(j + 1) * p]
                lsuby, lsubx = Tp.lmap()
                lsubmod = Tp.modlmap()
                lsubmod[0, 0] = 1.
                fl = 1.j*(lsubx*self._dTxpatch[i,j] + \
                            lsuby*self._dTypatch[i,j]) / \
                        (lsubmod * np.sqrt(self._dTxpatch[i,j]**2 + \
                                            self._dTypatch[i,j]**2))
                fl[0, 0] = 0.
                self._T_sub[i, j, :, :] = enmap.ifft(enmap.fft(Tp) * fl).real
                # Throw away pixels with edge effects
                self._T2patch[i, j] = np.var(self._T_sub[i, j, 5:-5, 5:-5])
        self._dT2patch = self._dTxpatch**2 + self._dTypatch**2
        if not self.savesteps:
            del self._dTypatch, self._dTxpatch, self._dTy, self._dTx, self._Tss
            del self._T_sub
Esempio n. 5
0
    def gather_patches_cos2(self):
        """Assemble patch statistics for small scale lensing with cos^2 filter.
        
        Compute the small scale (ell > 3000) temperature power at different 
        patches across the sky as well as the average amplitude of the 
        background temperature gradient (ell < 2000). For the small scale 
        statistics, also apply a filter in Fourier space such that:

        .. math::
            f_\\ell = \\cos^2(\\hat{\\ell}\\cdot\\hat{\\nabla T})

        """
        self._edge = 3  # Edge pixels to throw away
        p = self._p
        m_fft = enmap.fft(self.map_in)
        hp = np.zeros(self.map_in.shape)
        hp[np.where((self._lmod > self.lmin) & (self._lmod < self.lmax))] = 1.
        self._Tss = enmap.ifft(m_fft * hp)
        self._dTy, self._dTx = gradient_flat(self.map_in, self.ldT)
        # Scale geometry for lower res map of patches
        pshp, pwcs = enmap.scale_geometry(self.map_in.shape, self.map_in.wcs,
                                          1. / self._p)
        if not self.savesteps:
            del self.map_in, m_fft
        self._T2patch = enmap.zeros(pshp, pwcs)
        self._dTxpatch = enmap.zeros(pshp, pwcs)
        self._dTypatch = enmap.zeros(pshp, pwcs)
        self._T_sub = np.zeros((pshp[-2], pshp[-1], p, p))
        for i in range(self._T2patch.shape[-2]):
            for j in range(self._T2patch.shape[-1]):
                self._dTypatch[i, j] = np.mean(self._dTy[i * p:(i + 1) * p,
                                                         j * p:(j + 1) * p])
                self._dTxpatch[i, j] = np.mean(self._dTx[i * p:(i + 1) * p,
                                                         j * p:(j + 1) * p])
                Tp = self._Tss[i * p:(i + 1) * p, j * p:(j + 1) * p]
                lsuby, lsubx = Tp.lmap()
                lsubmod = Tp.modlmap()
                lsubmod[0, 0] = 1.  # Avoid divide by 0; set fl here to 0 later
                fl = (lsubx*self._dTxpatch[i,j] + \
                        lsuby*self._dTypatch[i,j])**2 / \
                    (lsubmod * np.sqrt(self._dTxpatch[i,j]**2 + \
                                        self._dTypatch[i,j]**2))**2
                fl[0, 0] = 0.
                self._T_sub[i, j, :, :] = enmap.ifft(enmap.fft(Tp) * fl).real
                # Throw away pixels with edge effects
                self._T2patch[i, j] = np.var(self._T_sub[i, j, 3:-3, 3:-3])
        self._dT2patch = self._dTxpatch**2 + self._dTypatch**2
        if not self.savesteps:
            del self._dTypatch, self._dTxpatch, self._dTy, self._dTx, self._Tss
            del self._T_sub
Esempio n. 6
0
def compute_ps(map1, map2, mask, beamf1, beamf2):
    """Compute the FFTs, multiply, bin
    """
    kmap1 = enmap.fft(map1 * mask, normalize="phys")
    kmap2 = enmap.fft(map2 * mask, normalize="phys")
    power = (kmap1 * np.conj(kmap2)).real

    bin_edges = np.arange(0, 8000, 40)
    centers = (bin_edges[1:] + bin_edges[:-1]) / 2.
    w2 = np.mean(mask**2.)
    modlmap = enmap.modlmap(map1.shape, map1.wcs)
    binned_power = bin(power / w2 / beamf1(modlmap) / beamf2(modlmap), modlmap,
                       bin_edges)
    return centers, binned_power
Esempio n. 7
0
def filter_weighted(imap, ivar, filter, tol=1e-4, ref=0.9):
    """Filter enmap imap with the given 2d fourier filter while
	weithing spatially with ivar"""
    filter = 1 - filter
    omap = enmap.ifft(filter * enmap.fft(imap * ivar)).real
    div = enmap.ifft(filter * enmap.fft(ivar)).real
    del filter
    # Avoid division by very low values
    div = np.maximum(div, np.percentile(ivar[::10, ::10], ref * 100) * tol)
    # omap = imap - rhs/div
    omap /= div
    del div
    omap *= -1
    omap += imap
    omap *= imap != 0
    return omap
Esempio n. 8
0
def inpaint_map_const_cov(imap,mask,union_sources_version=None,noise_pix = 20,hole_radius = 3.,plots=False):
    """

    Inpaints a map under the assumption of constant 2D Fourier covariance. This uses the average PS
    of the full map for the noise model at each source location and thus does not handle inhomogenity.
    Pros: no products needed other than map-maker outputs of map
    Cons: 

    imap -- (npol,Ny,Nx)
    ivar -- (Ny,Nx)
    """

    ras,decs = sints.get_act_mr3f_union_sources(version=union_sources_version)
    kmap = enmap.fft(mask*imap,normalize='phys')

    gtags = []
    gdicts = {}
    pcoords = []
    for i,(ra,dec) in enumerate(zip(ras,decs)):
        sel = reproject.cutout(ivar, ra=np.deg2rad(ra), dec=np.deg2rad(dec), pad=1, corner=False,npix=noise_pix,return_slice=True)
        if sel is None: continue
        civar = ivar[sel]
        if np.any(civar<=0): continue
        modrmap = civar.modrmap()
        modlmap = civar.modlmap()
        res = maps.resolution(civar.shape,civar.wcs)
        cimap = imap[sel]
        print(ra,dec)
        if plots: 
            for p in range(3): io.plot_img(cimap[p],os.environ['WORK']+"/cimap_%d_%s" % (p,str(i).zfill(2)))
            mimap = cimap.copy()
            mimap[...,modrmap<np.deg2rad(hole_radius/60.)] = np.nan
            for p in range(3): io.plot_img(mimap[p],os.environ['WORK']+"/masked_cimap_%d_%s" % (p,str(i).zfill(2)))
        
        scov = pixcov.scov_from_theory(modlmap,cmb_theory_fn,fn_beam,iau=False)
        ncov = pixcov.ncov_from_ivar(civar)
        pcov = scov + ncov
        gdicts[i] = pixcov.make_geometry(hole_radius=np.deg2rad(hole_radius/60.),n=noise_pix,deproject=True,iau=False,pcov=pcov,res=res)
        pcoords.append(np.array((dec,ra)))
        gtags.append(i)

    if len(gtags)>0: 
        pcoords = np.stack(pcoords).swapaxes(0,1)
        result = pixcov.inpaint(imap,pcoords,deproject=True,iau=False,geometry_tags=gtags,geometry_dicts=gdicts,verbose=True)

    if plots:
        for i,(ra,dec) in enumerate(zip(ras,decs)):
            sel = reproject.cutout(ivar, ra=np.deg2rad(ra), dec=np.deg2rad(dec), pad=1, corner=False,npix=noise_pix,return_slice=True)
            if sel is None: continue
            civar = ivar[sel]
            if np.any(civar<=0): continue
            modrmap = civar.modrmap()
            modlmap = civar.modlmap()
            res = maps.resolution(civar.shape,civar.wcs)
            cimap = result[sel]
            print("Inpainted ", ra,dec)
            if plots: 
                for p in range(3): io.plot_img(cimap[p],os.environ['WORK']+"/inpainted_cimap_%d_%s" % (p,str(i).zfill(2)))

    return result
Esempio n. 9
0
def cmbmap2alm(i, mtype, p, f, r):

    fmap = enmap.read_map(
        f.imap[mtype][i])  # load flatsky K-space combined map

    # FT
    print('2D ell filtering in F-space and assign to healpix map')
    alm = enmap.fft(fmap)

    # remove some Fourier modes
    shape, wcs = fmap.shape, fmap.wcs
    kmask = mask_kspace(shape, wcs, lmin=p.lcut, lmax=4000, lxcut=90, lycut=50)
    alm[kmask < 0.5] = 0

    # alm -> map
    fmap = enmap.ifft(alm).real

    # transform cmb map to healpix
    hpmap = enmap.to_healpix(fmap, nside=p.nside)

    # from map to alm
    hpmap = r.w * hpmap  # masking
    #hp.fitsfunc.write_map(f.omap[mtype][i],hpmap,overwrite=True)
    alm = curvedsky.utils.hp_map2alm(p.nside, p.lmax, p.lmax, hpmap)

    print("save to file")
    pickle.dump((alm),
                open(f.alm[mtype][i], "wb"),
                protocol=pickle.HIGHEST_PROTOCOL)
Esempio n. 10
0
def compute_ps(map1, map2, beamf1, beamf2):
    """Compute the FFTs, multiply, bin
    """
    if args.fft:
        kmap1 = enmap.fft(map1*mask, normalize="phys")
        kmap2 = enmap.fft(map2*mask, normalize="phys")
        power = (kmap1*np.conj(kmap2)).real
        bin_edges = np.arange(20,8000,40)
        centers = (bin_edges[1:] + bin_edges[:-1])/2.
        w2 = np.mean(mask**2.)
        modlmap = enmap.modlmap(map1.shape,map1.wcs)
        binned_power = bin(power/w2/beamf1(modlmap)/beamf2(modlmap),modlmap,bin_edges)
        return centers, binned_power
    else:
        ells,cls = pcalc.get_power_scalarXscalar(map1*mask, map2*mask,ret_dl=False)
        return ells,cls/beamf1(ells)/beamf2(ells)
Esempio n. 11
0
    def gather_patches_plain(self):
        """Assemble patch statistics relevant to lensing at small scales.

        Compute the small scale (ell > lmin) temperature power at different 
        patches across the sky as well as the average amplitude of the 
        background temperature gradient (ell < ldT).

        """
        self._edge = 0  # Not throwing away edge pixels
        m_fft = enmap.fft(self.map_in)
        hp = np.zeros(self.map_in.shape)
        hp[np.where((self._lmod > self.lmin) & (self._lmod < self.lmax))] = 1.
        self._Tss = enmap.ifft(m_fft * hp)
        self._dTy, self._dTx = gradient_flat(self.map_in, self.ldT)

        # Scale geometry for lower res map of patches
        pshp, pwcs = enmap.scale_geometry(self.map_in.shape, self.map_in.wcs,
                                          1. / self._p)
        if not self.savesteps:
            del self.map_in, m_fft
        self._T2patch = enmap.zeros(pshp, pwcs)
        self._dTxpatch = enmap.zeros(pshp, pwcs)
        self._dTypatch = enmap.zeros(pshp, pwcs)
        Trs = self._Tss[:pshp[-2] * self._p, :pshp[-1] * self._p].reshape(
            [pshp[-2], self._p, pshp[-1], self._p])
        dTxrs = self._dTx[:pshp[-2] * self._p, :pshp[-1] * self._p].reshape(
            [pshp[-2], self._p, pshp[-1], self._p])
        dTyrs = self._dTy[:pshp[-2] * self._p, :pshp[-1] * self._p].reshape(
            [pshp[-2], self._p, pshp[-1], self._p])
        self._T2patch[:, :] = np.var(Trs, axis=(1, 3))
        self._dTypatch[:, :] = np.mean(dTyrs, axis=(1, 3))
        self._dTxpatch[:, :] = np.mean(dTxrs, axis=(1, 3))
        self._dT2patch = self._dTxpatch**2 + self._dTypatch**2
        if not self.savesteps:
            del self._dTypatch, self._dTxpatch, self._dTy, self._dTx, self._Tss
Esempio n. 12
0
def gradient_flat(map_in, lmax=2000):
    """Return the gradient maps of map_in.
    
    Compute the gradient of the map_in in Fourier space. Simultaneously 
    low-pass the maps such that they only include modes ell < lmax.
    
    Parameters
    ----------
    map_in: ndmap, ndarray
        The input map.
    lmax: int
        The cutoff ell for low-passing the maps.
    
    Returns
    -------
    dy: ndmap, ndarray
        The gradient in the y-direction
    dx: ndmap, ndarray
        The gradient in the x-direction
    """
    ly, lx = map_in.lmap()
    lmod = map_in.modlmap()
    lp = enmap.zeros(map_in.shape)
    lp[np.where(lmod < lmax)] = 1.
    map_fft = enmap.fft(map_in)
    dx = enmap.ifft(map_fft*lp*lx*1j).real
    dy = enmap.ifft(map_fft*lp*ly*1j).real
    return dy, dx
Esempio n. 13
0
def sim_noise_oneoverf(ivar, apod, lknee=3000, lmin=50, alpha=-3.5):
    l = np.maximum(ivar.modlmap(), lmin)
    fscale = (1 + (l / lknee)**alpha)**0.5
    ref = np.mean(ivar[ivar != 0])
    sim = enmap.rand_gauss(ivar.shape, ivar.wcs, dtype=ivar.dtype)
    sim = enmap.ifft(enmap.fft(sim) * fscale).real * np.maximum(
        ivar, ref * 1e-3)**-0.5 * apod**2
    return sim
Esempio n. 14
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
Esempio n. 15
0
def powspec(map1, map2, taper, taper_order, modlmap, ellmin, ellmax,
            delta_ell):
    bin_edges = np.arange(ellmin, ellmax, delta_ell)
    binner = utils.bin2D(modlmap, bin_edges)

    kmap1 = enmap.fft(map1, normalize='phys')
    kmap2 = enmap.fft(map2, normalize='phys')

    # kmap1_ave = utils.bin2D(modlmap, bin_edges)
    # kmap2_ave = utils.bin2D(modlmap, bin_edges)

    # correct power spectra
    w = np.mean(taper**taper_order)

    p2d = (kmap1 * kmap2.conj()).real / w
    # p2d = ((kmap1-kmap1_ave) * (kmap2.conj()-kmap2_ave.conj())).real / w
    # p2d = abs((kmap1 * kmap2.conj()).real / w)
    centers, p1d = binner.bin(p2d)
    return centers, p1d
Esempio n. 16
0
def util_bin_FFT_CAR(map1, map2, mask, beam1, beam2, lmax=8000):
    """Compute the FFTs, multiply, bin

    Beams are multiplied at bin centers. This is the worst
    job you could do for calculating power spectra.
    """
    # beam_ells = np.arange(lmax+1)

    kmap1 = enmap.fft(map1 * mask, normalize="phys")
    kmap2 = enmap.fft(map2 * mask, normalize="phys")
    power = (kmap1 * np.conj(kmap2)).real

    bin_edges = np.arange(0, lmax, 40)
    centers = (bin_edges[1:] + bin_edges[:-1]) / 2.0
    w2 = np.mean(mask**2.0)
    modlmap = enmap.modlmap(map1.shape, map1.wcs)
    binned_power = util_bin_FFTspec_CAR(power / w2, modlmap, bin_edges)
    binned_power *= beam1[centers.astype(int)]
    binned_power *= beam2[centers.astype(int)]
    return centers, binned_power
Esempio n. 17
0
def beam_match(imap, f1, f2):
    """f1, f2 are fcodes instead of the actual frequency centers. It
    assumes that the first one (f1) has larger beam, so f2 will be matched
    to it.
    """
    from common import fwhms
    l = imap.modlmap()
    bmap_f1 = np.exp(-0.5 * l**2 * (fwhms[f1] * u.fwhm * u.arcmin)**2)
    bmap_f2 = np.exp(-0.5 * l**2 * (fwhms[f2] * u.fwhm * u.arcmin)**2)
    rmap = enmap.ifft(enmap.fft(imap) *
                      (bmap_f1 / np.maximum(bmap_f2, 1e-3))).real
    return rmap
def remove_lxly(fmap, lmin=100, lmax=4096, lxcut=90, lycut=50):

    alm = enmap.fft(fmap)
    shape, wcs = fmap.shape, fmap.wcs
    kmask = define_lmask(shape,
                         wcs,
                         lmin=lmin,
                         lmax=lmax,
                         lxcut=lxcut,
                         lycut=lycut)
    #print(np.shape(kmask),np.shape(alm))
    alm[kmask < 0.5] = 0
    fmap_fl = enmap.ifft(alm).real
    return fmap_fl
Esempio n. 19
0
def smooth_ps_gauss(ps2d, lsigma=200):
    """Smooth a 2d power spectrum to the target resolution in l. Simple
	gaussian smoothing avoids ringing."""
    # This hasn't been tested in isolation, but breaks when used in smooth_ps_mixed
    # First get our pixel size in l
    ly, lx = enmap.laxes(ps2d.shape, ps2d.wcs)
    ires = np.array([ly[1], lx[1]])
    sigma_pix = np.abs(lsigma / ires)
    fmap = enmap.fft(ps2d)
    ky = np.fft.fftfreq(ps2d.shape[-2]) * sigma_pix[0]
    kx = np.fft.fftfreq(ps2d.shape[-1]) * sigma_pix[1]
    kr2 = ky[:, None]**2 + kx[None, :]**2
    fmap *= np.exp(-0.5 * kr2)
    return enmap.ifft(fmap).real
Esempio n. 20
0
def filter_fast(map, vk_mask=None, hk_mask=None, normalize="phys", inv_pixwin_lxly=None):

    """Filter the map in Fourier space removing modes in a horizontal and vertical band
    defined by hk_mask and vk_mask. This is a faster version that what is implemented in pspy
    We also include an option for removing the pixel window function
    
    Parameters
    ---------
    map: ``so_map``
        the map to be filtered
    vk_mask: list with 2 elements
        format is fourier modes [-lx,+lx]
    hk_mask: list with 2 elements
        format is fourier modes [-ly,+ly]
    normalize: string
        optional normalisation of the Fourier transform
    inv_pixwin_lxly: 2d array
        the inverse of the pixel window function in fourier space
    """

    lymap, lxmap = map.data.lmap()
    ly, lx = lymap[:,0], lxmap[0,:]

   # filtered_map = map.copy()
    ft = enmap.fft(map.data, normalize=normalize)
    
    if vk_mask is not None:
        id_vk = np.where((lx > vk_mask[0]) & (lx < vk_mask[1]))
    if hk_mask is not None:
        id_hk = np.where((ly > hk_mask[0]) & (ly < hk_mask[1]))

    if map.ncomp == 1:
        if vk_mask is not None:
            ft[: , id_vk] = 0.
        if hk_mask is not None:
            ft[id_hk , :] = 0.
    
    if map.ncomp == 3:
        for i in range(3):
            if vk_mask is not None:
                ft[i, : , id_vk] = 0.
            if hk_mask is not None:
                ft[i, id_hk , :] = 0.

    if inv_pixwin_lxly is not None:
        ft  *= inv_pixwin_lxly
        
    map.data[:] = np.real(enmap.ifft(ft, normalize=normalize))
    return map
Esempio n. 21
0
def process_map(imap, box=None, deconvolve=False, freq=None, smooth=None):
    if deconvolve:
        fwhm = fwhms[freq]
        l = imap.modlmap()
        bmap = np.exp(-0.5*l**2*(fwhm*u.fwhm*u.arcmin)**2)
        bmap = np.maximum(bmap, 1e-3)
        fmap = enmap.fft(imap)
        omap = enmap.ifft(fmap/bmap).real
    else:
        omap = imap
    if smooth is not None:
        omap = enmap.smooth_gauss(omap, smooth*u.fwhm*u.arcmin)
    if box is not None: omap = omap.submap(box)
    if args.comp == 0: return np.log10(omap[0])
    if args.comp == 12: return np.sum(omap[1:]**2, axis=0)**0.5
    else: return omap[args.comp]
Esempio n. 22
0
def get_filtered_map(map, binary, vk_mask, hk_mask, normalize=False):
    """Filter the map in Fourier space removing modes in a horizontal and vertical band
    defined by hk_mask and vk_mask. Note that we mutliply the maps by a binary mask before
    doing this operation in order to remove pathological pixels

    Parameters
    ---------
    orig_map: ``so_map``
        the map to be filtered
    binary:  ``so_map``
        a binary mask removing pathological pixels
    vk_mask: list with 2 elements
        format is fourier modes [-lx,+lx]
    hk_mask: list with 2 elements
        format is fourier modes [-ly,+ly]
    """

    if map.ncomp == 1:
        map.data *= binary.data
    else:
        map.data[:] *= binary.data

    lymap, lxmap = map.data.lmap()
    ly, lx = lymap[:, 0], lxmap[0, :]

    # filtered_map = map.copy()
    ft = enmap.fft(map.data, normalize=normalize)

    if vk_mask is not None:
        id_vk = np.where((lx > vk_mask[0]) & (lx < vk_mask[1]))
    if hk_mask is not None:
        id_hk = np.where((ly > hk_mask[0]) & (ly < hk_mask[1]))

    if map.ncomp == 1:
        if vk_mask is not None:
            ft[:, id_vk] = 0.0
        if hk_mask is not None:
            ft[id_hk, :] = 0.0

    if map.ncomp == 3:
        if vk_mask is not None:
            ft[:, :, id_vk] = 0.0
        if hk_mask is not None:
            ft[:, id_hk, :] = 0.0

    map.data[:] = np.real(enmap.ifft(ft, normalize=normalize))
    return map
Esempio n. 23
0
def smooth_ps_grid(ps, res, alpha=4, log=False, ndof=2):
    """Smooth a 2d power spectrum to the target resolution in l"""
    # First get our pixel size in l
    lx, ly = enmap.laxes(ps.shape, ps.wcs)
    ires   = np.array([lx[1],ly[1]])
    smooth = np.abs(res/ires)
    # We now know how many pixels to somoth by in each direction,
    # so perform the actual smoothing
    if log: ps = np.log(ps)
    fmap  = enmap.fft(ps)
    ky    = np.fft.fftfreq(ps.shape[-2])
    kx    = np.fft.fftfreq(ps.shape[-1])
    fmap /= 1 + np.abs(2*ky[:,None]*smooth[0])**alpha
    fmap /= 1 + np.abs(2*kx[None,:]*smooth[1])**alpha
    ps    = enmap.ifft(fmap).real
    if log: ps = np.exp(ps)*log_smooth_corrections[ndof]
    return ps
Esempio n. 24
0
def get_pol_powers(tmap, qmap, umap, kbeam, mask_w2):
    f = lambda x: enmap.fft(x, normalize='phys')
    p = lambda x, y: (x * y.conj()).real / mask_w2 / kbeam**2
    kt = f(tmap)
    kq = -f(qmap)
    ku = f(umap)
    tt = p(kt, kt)
    tu = p(kt, ku)
    tq = p(kt, kq)
    qq = p(kq, kq)
    uu = p(ku, ku)
    qu = p(kq, ku)
    p2d = np.array([[tt, tq, tu], [tq, qq, qu], [tu, qu, uu]])
    p2d[~np.isfinite(p2d)] = 0

    rp2d = enmap.enmap(
        maps.rotate_pol_power(tmap.shape, tmap.wcs, p2d, iau=False), tmap.wcs)
    return rp2d[0, 0], rp2d[1, 1], rp2d[2, 2]
Esempio n. 25
0
def map_act_hist(patches, numerics, wf, masks, apo_masks, \
                 negbins, posbins) :#{{{

    # @TODO: check final pixel count!
    # @TODO check changing cmb or noise power changes variance as expected. it will.
    # @TODO plot histogram with and without cmb
    # @TODO plot histogram with and without WF

    # maps are sub-divided into six patches; analyze each separately and then get the PDF of the whole map
    dat_tot = np.array([])
    for i in range(numerics['n_patch']):
        patch = patches[i]
        mask = copy.deepcopy(apo_masks[i])
        patch *= mask  #apply mask
        modlmap = patch.modlmap(
        )  #map of |\vec{ell}| in 2D Fourier domain for the patch
        Fell2d = interp1d(wf[:, 0],
                          wf[:, 1],
                          bounds_error=False,
                          fill_value=0.)(
                              modlmap)  #get filter in 2D Fourier domain
        kmap = enmap.fft(patch,
                         normalize="phys")  #FFT the patch to 2D Fourier domain
        kfilt = kmap * Fell2d
        patch_filt = enmap.ifft(kfilt, normalize="phys").real
        # point source mask (different for each patch)
        newMask = copy.deepcopy(masks[i])
        newMask[363, :] = 1.
        newMask[:, 2181] = 1.
        la = np.where(newMask < 0.1)
        mask[la] = 0.
        ### pick out unmasked data
        loc2 = np.where(mask > 0.9)
        dat = patch_filt[loc2]  #*fraction
        dat_tot = np.append(dat_tot, np.ravel(dat))

    # histogram the unmasked data
    histneg, bin_edgesneg = np.histogram(dat_tot, negbins)
    histpos, bin_edgespos = np.histogram(dat_tot, posbins[::-1])
    histall = np.concatenate((histneg, histpos))
    PDFpatch = histall / float(len(dat_tot))
    return PDFpatch
Esempio n. 26
0
def kspace_filter_fast(map, vk_mask=None, hk_mask=None, normalize="phys"):
    """Filter the map in Fourier space removing modes in a horizontal and vertical band
    defined by hk_mask and vk_mask. This is a faster version that what is implemented in pspy
    
    Parameters
    ---------
    map: ``so_map``
        the map to be filtered
    vk_mask: list with 2 elements
        format is fourier modes [-lx,+lx]
    hk_mask: list with 2 elements
        format is fourier modes [-ly,+ly]
    """

    lymap, lxmap = map.data.lmap()
    ly, lx = lymap[:,0], lxmap[0,:]

   # filtered_map = map.copy()
    ft = enmap.fft(map.data, normalize=normalize)
    
    if vk_mask is not None:
        id_vk = np.where((lx > vk_mask[0]) & (lx < vk_mask[1]))
    if hk_mask is not None:
        id_hk = np.where((ly > hk_mask[0]) & (ly < hk_mask[1]))

    if map.ncomp == 1:
        if vk_mask is not None:
            ft[: , id_vk] = 0.
        if hk_mask is not None:
            ft[id_hk , :] = 0.
    
    if map.ncomp == 3:
        for i in range(3):
            if vk_mask is not None:
                ft[i, : , id_vk] = 0.
            if hk_mask is not None:
                ft[i, id_hk , :] = 0.

    map.data[:] = np.real(enmap.ifft(ft, normalize=normalize))
    return map
Esempio n. 27
0
def deconvolve_pixwin_CAR(orig_map, binary, inv_pixwin_lxly, norm=0):
    """Deconvolve the two dimensional CAR pixel window function

    Parameters
    ---------
    orig_map: ``so_map``
        the map to be filtered
    binary:  ``so_map``
        a binary mask removing pathological pixels
    inv_pixwin_lxly: 2d array
        the inverse of the pixel window function in fourier space
    norm: integer
        everytime we do a FFT + IFFT operation we get a normalisation cst to take care of
        this is counting the number of occurence of it, note that we could correct directly by
        using normalize="physical", but dividing the map by a number is slow so we prefer to do it later
        in the code.
    """
    orig_map.data *= binary.data
    ft = enmap.fft(orig_map.data, normalize=False)
    ft *= inv_pixwin_lxly
    orig_map.data = enmap.ifft(ft, normalize=False).real
    norm += 1

    return norm, orig_map
Esempio n. 28
0
dm = sints.PlanckHybrid(region=mask)
for qid in qids:


    split = enmap.read_map("%ssplit_%s.fits" % (froot,qid))
    #io.hplot(enmap.downgrade(split,4),"split_%s" % qid)

    arrayname = arraynames[qid]
    wts = dm.get_splits_ivar(arrayname)[0,:,0,...]

    coadd,_ = noise.get_coadd(split[:,0,...],wts,axis=0) * mask

    pl = io.Plotter(xyscale='linlog',xlabel='l',ylabel='C')

    kmap = enmap.fft(coadd,normalize='phys')
    p2d = np.real(kmap*kmap.conj())/w2
    cents,p1d = binner.bin(p2d)
    pl.add(cents,p1d,label='sim power')
    
    kcoadd = enmap.enmap(np.load("%skcoadd_%s.npy" % (kroot,qid)),wcs)
    p2d = np.real(kcoadd*kcoadd.conj())/w2
    cents,p1d = binner.bin(p2d)
    pl.add(cents,p1d,label='sim power 2')


    p2d = enmap.enmap(np.load("%stilec_hybrid_covariance_%s_%s.npy" % (kroot,qid,qid)),wcs)
    cents,p1d = binner.bin(p2d)
    pl.add(cents,p1d,label='sim cov')

Esempio n. 29
0
def fitQ(config):
    """Calculates the filter mismatch function Q on a grid of scale sizes (given in terms of theta500 in 
    arcmin), for each tile in the map. The results are initially cached (with a separate .fits table for each
    tile) under the selFn directory, before being combined into a single file at the end of a nemo run.
    Use GNFWParams (in config.parDict) if you want to specify a different cluster profile shape.
    
    Args:
        config (:obj:`startUp.NemoConfig`): A NemoConfig object.
    
    Note:
        See :obj:`loadQ` for how to load in the output of this routine.
        
    """

    if config.parDict['GNFWParams'] == 'default':
        GNFWParams = gnfw._default_params
    else:
        GNFWParams = config.parDict['GNFWParams']

    # Spin through the filter kernels
    photFilterLabel = config.parDict['photFilter']
    filterList = config.parDict['mapFilters']
    for f in filterList:
        if f['label'] == photFilterLabel:
            ref = f

    # M, z ranges for Q calc
    # NOTE: ref filter that sets scale we compare to must ALWAYS come first
    # To safely (numerically, at least) apply Q at z ~ 0.01, we need to go to theta500 ~ 500 arcmin (< 10 deg)
    MRange = [ref['params']['M500MSun']]
    zRange = [ref['params']['z']]
    # This should cover theta500Arcmin range fairly evenly without using too crazy masses
    #minTheta500Arcmin=0.5
    #maxTheta500Arcmin=20.0
    minTheta500Arcmin = 0.1
    maxTheta500Arcmin = 500.0
    numPoints = 50
    #theta500Arcmin_wanted=np.logspace(np.log10(1e-1), np.log10(500), 50)
    theta500Arcmin_wanted = np.logspace(np.log10(minTheta500Arcmin),
                                        np.log10(maxTheta500Arcmin), numPoints)
    zRange_wanted = np.zeros(numPoints)
    zRange_wanted[np.less(theta500Arcmin_wanted, 3.0)] = 2.0
    zRange_wanted[np.logical_and(np.greater(theta500Arcmin_wanted, 3.0),
                                 np.less(theta500Arcmin_wanted, 6.0))] = 1.0
    zRange_wanted[np.logical_and(np.greater(theta500Arcmin_wanted, 6.0),
                                 np.less(theta500Arcmin_wanted, 10.0))] = 0.5
    zRange_wanted[np.logical_and(np.greater(theta500Arcmin_wanted, 10.0),
                                 np.less(theta500Arcmin_wanted, 20.0))] = 0.1
    zRange_wanted[np.logical_and(np.greater(theta500Arcmin_wanted, 20.0),
                                 np.less(theta500Arcmin_wanted, 30.0))] = 0.05
    zRange_wanted[np.greater(theta500Arcmin_wanted, 30.0)] = 0.01
    MRange_wanted = []
    for theta500Arcmin, z in zip(theta500Arcmin_wanted, zRange_wanted):
        Ez = astCalc.Ez(z)
        Hz = astCalc.Ez(z) * astCalc.H0
        G = 4.301e-9  # in MSun-1 km2 s-2 Mpc
        criticalDensity = (3 * np.power(Hz, 2)) / (8 * np.pi * G)
        R500Mpc = np.tan(np.radians(theta500Arcmin / 60.0)) * astCalc.da(z)
        M500 = (4 / 3.0) * np.pi * np.power(R500Mpc, 3) * 500 * criticalDensity
        MRange_wanted.append(M500)
    MRange = MRange + MRange_wanted
    zRange = zRange + zRange_wanted.tolist()

    # Here we save the fit for each tile separately...
    # completeness.tidyUp will put them into one file at the end of a nemo run
    for tileName in config.tileNames:
        tileQTabFileName = config.selFnDir + os.path.sep + "QFit#%s.fits" % (
            tileName)
        if os.path.exists(tileQTabFileName) == True:
            print("... already done Q fit for tile %s ..." % (tileName))
            continue
        print("... fitting Q in tile %s ..." % (tileName))

        # Load reference scale filter
        foundFilt = False
        for filt in config.parDict['mapFilters']:
            if filt['label'] == config.parDict['photFilter']:
                foundFilt = True
                break
        if foundFilt == False:
            raise Exception("couldn't find filter that matches photFilter")
        filterClass = eval('filters.%s' % (filt['class']))
        filterObj=filterClass(filt['label'], config.unfilteredMapsDictList, filt['params'], \
                              tileName = tileName,
                              diagnosticsDir = config.diagnosticsDir+os.path.sep+tileName)
        filterObj.loadFilter()

        # Real space kernel or Fourier space filter?
        if issubclass(filterObj.__class__,
                      filters.RealSpaceMatchedFilter) == True:
            realSpace = True
        else:
            realSpace = False

        # Set-up the beams
        beamsDict = {}
        for mapDict in config.parDict['unfilteredMaps']:
            obsFreqGHz = mapDict['obsFreqGHz']
            beamsDict[obsFreqGHz] = mapDict['beamFileName']

        # A bit clunky but gets map pixel scale and shrinks map size we'll use for inserting signals
        # NOTE: 5 deg is too small for the largest very low-z clusters: it's better to add a z cut and ignore those
        # NOTE: 5 deg fell over (ringing) for tiles_v2 RE6_10_0, but 10 deg worked fine
        extMap = np.zeros(filterObj.shape)
        wcs = filterObj.wcs
        RADeg, decDeg = wcs.getCentreWCSCoords()
        clipDict = astImages.clipImageSectionWCS(extMap, wcs, RADeg, decDeg,
                                                 10.0)
        wcs = clipDict['wcs']
        extMap = clipDict['data']

        # Input signal maps to which we will apply filter(s)
        # We do this once and store in a dictionary for speed
        theta500Arcmin = []
        signalMapDict = {}
        signalMap = np.zeros(extMap.shape)
        degreesMap = np.ones(signalMap.shape, dtype=float) * 1e6
        degreesMap, xBounds, yBounds = nemoCython.makeDegreesDistanceMap(
            degreesMap, wcs, RADeg, decDeg, 10.0)
        for z, M500MSun in zip(zRange, MRange):
            key = '%.2f_%.2f' % (z, np.log10(M500MSun))
            signalMaps = []
            fSignalMaps = []
            y0 = 2e-4
            for obsFreqGHz in list(beamsDict.keys()):
                if mapDict['obsFreqGHz'] is not None:  # Normal case
                    amplitude = maps.convertToDeltaT(y0, obsFreqGHz)
                else:  # TILe-C case
                    amplitude = y0
                # NOTE: Q is to adjust for mismatched filter shape
                # Yes, this should have the beam in it (certainly for TILe-C)
                signalMap = makeArnaudModelSignalMap(
                    z,
                    M500MSun,
                    degreesMap,
                    wcs,
                    beamsDict[obsFreqGHz],
                    amplitude=amplitude,
                    convolveWithBeam=True,
                    GNFWParams=config.parDict['GNFWParams'])
                if realSpace == True:
                    signalMaps.append(signalMap)
                else:
                    signalMaps.append(enmap.fft(signalMap))
            signalMaps = np.array(signalMaps)
            signalMapDict[key] = signalMaps
            theta500Arcmin.append(
                calcTheta500Arcmin(z, M500MSun, fiducialCosmoModel))
        theta500Arcmin = np.array(theta500Arcmin)

        # Filter maps with the ref kernel
        # NOTE: keep only unique values of Q, theta500Arcmin (or interpolation routines will fail)
        Q = []
        QTheta500Arcmin = []
        count = 0
        for z, M500MSun in zip(zRange, MRange):
            key = '%.2f_%.2f' % (z, np.log10(M500MSun))
            filteredSignal = filterObj.applyFilter(signalMapDict[key])
            peakFilteredSignal = filteredSignal.max()
            if peakFilteredSignal not in Q:
                Q.append(peakFilteredSignal)
                QTheta500Arcmin.append(theta500Arcmin[count])
            count = count + 1
        Q = np.array(Q)
        Q = Q / Q[0]

        # Sort and do spline fit... save .fits table of theta, Q
        QTab = atpy.Table()
        QTab.add_column(atpy.Column(Q, 'Q'))
        QTab.add_column(atpy.Column(QTheta500Arcmin, 'theta500Arcmin'))
        QTab.sort('theta500Arcmin')
        QTab.meta['NEMOVER'] = nemo.__version__
        QTab.write(tileQTabFileName, overwrite=True)
        #rank_QTabDict[tileName]=QTab

        # Fit with spline
        tck = interpolate.splrep(QTab['theta500Arcmin'], QTab['Q'])

        # Plot
        plotSettings.update_rcParams()
        plt.figure(figsize=(9, 6.5))
        ax = plt.axes([0.12, 0.11, 0.86, 0.88])
        #plt.tick_params(axis='both', which='major', labelsize=15)
        #plt.tick_params(axis='both', which='minor', labelsize=15)
        thetaArr = np.linspace(0, 500, 100000)
        plt.plot(thetaArr, interpolate.splev(thetaArr, tck), 'k-')
        plt.plot(QTheta500Arcmin, Q, 'D', ms=8)
        #plt.xlim(0, 9)
        plt.ylim(0, 1.9)
        #plt.xlim(0, thetaArr.max())
        #plt.xlim(0, 15)
        plt.xlim(0.1, 500)
        plt.semilogx()
        plt.xlabel("$\\theta_{\\rm 500c}$ (arcmin)")
        plt.ylabel("$Q$ ($M_{\\rm 500c}$, $z$)")
        plt.savefig(config.diagnosticsDir + os.path.sep + tileName +
                    os.path.sep + "QFit_%s.pdf" % (tileName))
        plt.savefig(config.diagnosticsDir + os.path.sep + tileName +
                    os.path.sep + "QFit_%s.png" % (tileName))
        plt.close()
        print("... Q fit finished [tileName = %s, rank = %d] ..." %
              (tileName, config.rank))
Esempio n. 30
0
def pow(x,y=None):
    k = enmap.fft(x,normalize='phys')
    ky = enmap.fft(y,normalize='phys') if y is not None else k
    p = (k*ky.conj()).real
    cents,p1d = binner.bin(p)
    return p,cents,p1d