def prepare_alm(alm=None, ainfo=None, lmax=None, pre=(), dtype=np.float64): """Set up alm and ainfo based on which ones of them are available.""" if alm is None: if ainfo is None: if lmax is None: raise ValueError("prepare_alm needs either alm, ainfo or lmax to be specified") ainfo = sharp.alm_info(lmax) alm = np.zeros(pre+(ainfo.nelem,), dtype=np.result_type(dtype,0j)) else: ainfo = sharp.alm_info(nalm=alm.shape[-1]) return alm, ainfo
def rand_alm(ps, ainfo=None, lmax=None, seed=None, dtype=np.complex128, m_major=True, return_ainfo=False): """This is a replacement for healpy.synalm. It generates the random numbers in l-major order before transposing to m-major order in order to allow generation of low-res and high-res maps that agree on large scales. It uses 2/3 of the memory of healpy.synalm, and has comparable speed.""" rtype = np.zeros([0],dtype=dtype).real.dtype ps = np.asarray(ps) if ainfo is None: ainfo = sharp.alm_info(min(lmax,ps.shape[-1]-1) or ps.shape[-1]-1) if ps.ndim == 1: wps = ps[None,None] elif ps.ndim == 2: wps = powspec.sym_expand(ps, scheme="diag") elif ps.ndim == 3: wps = ps else: raise ValuerError("power spectrum must be [nl], [nspec,nl] or [ncomp,ncomp,nl]") ncomp = wps.shape[0] ps12 = enmap.multi_pow(wps, 0.5) # Draw random gaussian numbers in chunks to save memory alm = np.empty([ncomp,ainfo.nelem],dtype=dtype) aflat = alm.reshape(-1).view(rtype) bsize = 0x10000 if seed != None: np.random.seed(seed) for i in range(0, aflat.size, bsize): aflat[i:i+bsize] = np.random.standard_normal(min(bsize,aflat.size-i)) # Transpose numbers to make them m-major. if m_major: ainfo.transpose_alm(alm,alm) # Scale alms by spectrum, taking into account which alms are complex ainfo.lmul(alm, (ps12/2**0.5).astype(rtype), alm) alm[:,:ainfo.lmax].imag = 0 alm[:,:ainfo.lmax].real *= 2**0.5 if ps.ndim == 1: alm = alm[0] if return_ainfo: return alm, ainfo else: return alm
def alm2map_pos(alm, pos, ainfo=None, oversample=2.0, spin=2, deriv=False, verbose=False): """Projects the given alms (with layout) on the specified pixel positions. alm[ncomp,nelem], pos[2,...] => res[ncomp,...]. It projects on a large cylindrical grid and then interpolates to the actual pixels. This is the general way of doing things, but not the fastest. Computing pos and interpolating takes a significant amount of time.""" alm_full = np.atleast_2d(alm) if ainfo is None: ainfo = sharp.alm_info(nalm=alm_full.shape[-1]) ashape, ncomp = alm_full.shape[:-2], alm_full.shape[-2] if deriv: # If we're computing derivatives, spin isn't allowed. # alm must be either [ntrans,nelem] or [nelem], # and the output will be [ntrans,2,ny,nx] or [2,ny,nx] ashape = ashape + (ncomp, ) ncomp = 2 tmap = make_projectable_map_by_pos(pos, ainfo.lmax, ashape + (ncomp, ), oversample, alm.real.dtype) alm2map_cyl(alm, tmap, ainfo=ainfo, spin=spin, deriv=deriv, direct=True, verbose=verbose) # Project down on our final pixels. This will result in a slight smoothing res = enmap.samewcs(tmap.at(pos[:2], mode="wrap"), pos) # Remove any extra dimensions we added if alm.ndim == alm_full.ndim - 1: res = res[0] return res
# to make interpolation easy. with dprint("construct imap"): ires = np.array([1,1./np.sin(R)])*res/args.supersample shape, wi = enmap.geometry(pos=[[np.pi/2-R,-np.pi],[np.pi/2,np.pi]], res=ires, proj="car") imap = enmap.zeros((ncomp,)+shape, wi) # Define SHT for interpolation pixels with dprint("construct sht"): minfo = curvedsky.map2minfo(imap) lmax_ideal = np.pi/res ps = ps[:,:,:lmax_ideal] lmax = ps.shape[-1] # We do not need all ms when centered on the pole. To reach 1e-10 relative # error up to R, we need mmax approx 9560*R in radians mmax = args.mmax or int(R*9560) ainfo = sharp.alm_info(lmax, mmax) sht = sharp.sht(minfo, ainfo) with dprint("curvedsky tot"): with dprint("rand alm"): alm = curvedsky.rand_alm(ps, ainfo=ainfo, seed=1, m_major=False) with dprint("alm2map"): sht.alm2map(alm[:1], imap[:1].reshape(1,-1)) if ncomp == 3: sht.alm2map(alm[1:3], imap[1:3,:].reshape(2,-1), spin=2) del alm # Make a test map to see if we can project between these with dprint("project"): omap = enmap.project(imap, omap.shape, omap.wcs, mode="constant", cval=np.nan) del imap
shape, wi = enmap.geometry(pos=[[np.pi / 2 - R, -np.pi], [np.pi / 2, np.pi]], res=ires, proj="car") imap = enmap.zeros((ncomp, ) + shape, wi) # Define SHT for interpolation pixels with dprint("construct sht"): minfo = curvedsky.map2minfo(imap) lmax_ideal = np.pi / res ps = ps[:, :, :lmax_ideal] lmax = ps.shape[-1] # We do not need all ms when centered on the pole. To reach 1e-10 relative # error up to R, we need mmax approx 9560*R in radians mmax = args.mmax or int(R * 9560) ainfo = sharp.alm_info(lmax, mmax) sht = sharp.sht(minfo, ainfo) with dprint("curvedsky tot"): with dprint("rand alm"): alm = curvedsky.rand_alm(ps, ainfo=ainfo, seed=1, m_major=False) with dprint("alm2map"): sht.alm2map(alm[:1], imap[:1].reshape(1, -1)) if ncomp == 3: sht.alm2map(alm[1:3], imap[1:3, :].reshape(2, -1), spin=2) del alm # Make a test map to see if we can project between these with dprint("project"): omap = enmap.project(imap, omap.shape, omap.wcs,
fields = [pixie.read_field(field) for field in sky] # Smooth to target beam if requested. We do this the simple # way, without repixelizing. This won't work around the poles if args.apply_beam: print "Applying beam" # We will apply a hardcoded gaussian for now l = np.arange(beam_lmax+1) beam = np.exp(-0.5*l*(l+1)*bsigma**2) bmat = np.zeros((3,3,len(beam))) for i in range(3): bmat[i,i] = beam # Smooth manually using full-sky geometry for field in fields: print field.name minfo = sharp.map_info_fejer1(field.map.shape[-2], field.map.shape[-1]) ainfo = sharp.alm_info(lmax=beam_lmax) sht = sharp.sht(minfo, ainfo) alm = np.zeros((3,ainfo.nelem),dtype=complex) print "T -> alm" sht.map2alm(field.map[:1].reshape(1,-1), alm[:1]) print "P -> alm" sht.map2alm(field.map[1:].reshape(2,-1), alm[1:], spin=2) print "lmul" alm = ainfo.lmul(alm, bmat) # And transform back again print "alm -> T" sht.alm2map(alm[:1], field.map[:1].reshape(1,-1)) print "alm -> P" sht.alm2map(alm[1:], field.map[1:].reshape(2,-1), spin=2) # Reapply spline filter print "Prefilter"
# Smooth to target beam if requested. We do this the simple # way, without repixelizing. This won't work around the poles if args.apply_beam: print "Applying beam" # We will apply a hardcoded gaussian for now l = np.arange(beam_lmax + 1) beam = np.exp(-0.5 * l * (l + 1) * bsigma**2) bmat = np.zeros((3, 3, len(beam))) for i in range(3): bmat[i, i] = beam # Smooth manually using full-sky geometry for field in fields: print field.name minfo = sharp.map_info_fejer1(field.map.shape[-2], field.map.shape[-1]) ainfo = sharp.alm_info(lmax=beam_lmax) sht = sharp.sht(minfo, ainfo) alm = np.zeros((3, ainfo.nelem), dtype=complex) print "T -> alm" sht.map2alm(field.map[:1].reshape(1, -1), alm[:1]) print "P -> alm" sht.map2alm(field.map[1:].reshape(2, -1), alm[1:], spin=2) print "lmul" alm = ainfo.lmul(alm, bmat) # And transform back again print "alm -> T" sht.alm2map(alm[:1], field.map[:1].reshape(1, -1)) print "alm -> P" sht.alm2map(alm[1:], field.map[1:].reshape(2, -1), spin=2) # Reapply spline filter print "Prefilter"