def __signal_postprocessing__(self, patch, signal_idx, alm_patch, save_map, oshape, owcs, apply_window=True): signal = self.get_template(patch, shape=oshape, wcs=owcs) signal = signal if len(alm_patch.shape) > 1 else signal[0, ...] curvedsky.alm2map(alm_patch, signal, spin=[0, 2], verbose=True) if apply_window: print('apply window') axes = [-2, -1] for idx in range(signal.shape[0]): kmap = pfft.fft(signal[idx], axes=axes) wy, wx = enmap.calc_window(kmap.shape) wind = wy[:, None]**1 * wx[None, :]**1 kmap *= wind signal[idx] = (pfft.ifft(kmap, axes=axes, normalize=True)).real del kmap if save_map: self.signals[signal_idx] = signal.copy() self.manage_cache(self.signals, self.max_cached) return signal
maps = d["maps_%s_%s" % (sv, ar)] nsplit[sv] = len(maps) cal = d["cal_%s_%s" % (sv, ar)] print("%s split of survey: %s, array %s" % (nsplit[sv], sv, ar)) if deconvolve_pixwin: # ok so this is a bit overcomplicated because we need to take into account CAR and HEALPIX # for CAR the pixel window function deconvolution is done in Fourier space and take into account # the anisotropy if the pixwin # In HEALPIX it's a simple 1d function in multipole space # we also need to take account the case where we have projected Planck into a CAR pixellisation since # the native pixel window function of Planck need to be deconvolved if win_T.pixel == "CAR": wy, wx = enmap.calc_window(win_T.data.shape) inv_pixwin_lxly = (wy[:, None] * wx[None, :])**(-1) pixwin_l[sv] = np.ones(2 * lmax) if sv == "Planck": print("Deconvolve Planck pixel window function") # we include this special case for Planck projected in CAR taking into account the Planck native pixellisation # we should check if the projection doesn't include an extra pixel window inv_pixwin_lxly = None pixwin_l[sv] = hp.pixwin(2048) elif win_T.pixel == "HEALPIX": pixwin_l[sv] = hp.pixwin(win_T.nside) else: inv_pixwin_lxly = None
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)
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
def kfilter_map(m, apo, kx_cut, ky_cut, unpixwin=True, legacy_steve=False): r"""Apply a k-space filter on a map. By default, we do not reproduce the output of Steve's code. We do offer this functionality: set the optional flag `legacy_steve=True` to offset the mask and the map by one pixel in each dimension. You should filter both in temperature and polarization. Parameters ---------- m : enmap Input map which this function will filter. apo : enmap This map is a smooth tapering of the edges of the map, to be multiplied into the map prior to filtering. The filtered map is divided by the nonzero pixels of this map at the end. This is required because maps of actual data are unlikely to be periodic, which will induce ringing when one applies a k-space filter. To solve this, we taper the edges of the map to zero prior to filtering. See :py:func:`nawrapper.ps.rectangular_apodization` kx_cut : float We cut modes with wavenumber :math:`|k_x| < k_x^{\mathrm{cut}}`. ky_cut : float We cut modes with wavenumber :math:`|k_y| < k_y^{\mathrm{cut}}`. unpixwin : bool Correct for the CAR pixel window if True. legacy_steve : bool Use a slightly different filter if True, to reproduce Steve's pipeline. Steve's k-space filter as of June 2019 had a bug where two k-space modes (the most positive cut mode in x and most negative cut mode in y) were not cut. This has a very small effect on the spectrum, but for reproducibility purposes we offer this behavior. By default we do not use this. To reproduce Steve's code behavior you should set `legacy_steve=True`. Returns ------- result : enmap The map with the specified k-space filter applied. """ alm = enmap.fft(m * apo, normalize=True) if unpixwin: # remove pixel window in Fourier space wy, wx = enmap.calc_window(m.shape) alm /= wy[:, np.newaxis] alm /= wx[np.newaxis, :] ly, lx = enmap.lmap(alm.shape, alm.wcs) kfilter_x = np.abs(lx) >= kx_cut kfilter_y = np.abs(ly) >= ky_cut if legacy_steve: # Steve's kspace filter appears to do this cut_x_k = np.unique(lx[(np.abs(lx) <= kx_cut)]) cut_y_k = np.unique(ly[(np.abs(ly) <= ky_cut)]) # keep most negative kx and most positive ky kfilter_x[np.isclose(lx, cut_x_k[0])] = True kfilter_y[np.isclose(ly, cut_y_k[-1])] = True result = enmap.ifft(alm * kfilter_x * kfilter_y, normalize=True).real result[apo > 0.0] = result[apo > 0.0] / apo[apo > 0.0] return result
def get_pixwin(shape): wy, wx = enmap.calc_window(shape) wind = wy[:, None] * wx[None, :] return wind
maps = d["maps_%s_%s" % (sv, ar)] nsplit[sv] = len(maps) cal = d["cal_%s_%s" % (sv, ar)] print("%s split of survey: %s, array %s" % (nsplit[sv], sv, ar)) if deconvolve_pixwin: # ok so this is a bit overcomplicated because we need to take into account CAR and HEALPIX # for CAR the pixel window function deconvolution is done in Fourier space and take into account # the anisotropy if the pixwin # In HEALPIX it's a simple 1d function in multipole space # we also need to take account the case where we have projected Planck into a CAR pixellisation since # the native pixel window function of Planck need to be deconvolved if window_tuple[0].pixel == "CAR": wy, wx = enmap.calc_window(window_tuple[0].data.shape) inv_pixwin_lxly = (wy[:, None] * wx[None, :])**(-1) inv_pixwin_lxly = inv_pixwin_lxly.astype(np.float32) pixwin_l[sv] = np.ones(2 * lmax) if sv == "Planck": print("Deconvolve Planck pixel window function") # we include this special case for Planck projected in CAR taking into account the Planck native pixellisation # we should check if the projection doesn't include an extra pixel window inv_pixwin_lxly = None pixwin_l[sv] = hp.pixwin(2048) elif window_tuple[0].pixel == "HEALPIX": pixwin_l[sv] = hp.pixwin(window_tuple[0].nside) else: inv_pixwin_lxly = None