def _FiveDelta2g_2(xyzs, dcg, dcgxx, fft='pyfftw', Ngrid=360): ''' calculate second part of (2 ell + 1) x delta_2 (Scoccimarro 2015 Eq. 20) = 5 x delta_2 ''' # Qxx, Qyy, Qzz (Scoccimarro 2015 Eq. 19) ifft_Qij = [] for i, j in zip([1, 2, 3], [2, 3, 1]): _delta = np.zeros([2 * Ngrid, Ngrid, Ngrid], dtype=np.float32, order='F') # order is reversed. check this carefully fEstimate.assign_quad(xyzs, _delta, kf_ks, i, j, 0, 0, N, Ngrid) ifft_delta = _FFT(_delta, fft=fft, Ngrid=Ngrid) # run FFT fEstimate.fcomb(ifft_delta, N, Ngrid) # combine ifft_Qij.append(ifft_delta[:Ngrid // 2 + 1, :, :]) fEstimate.FiveDelta2g_2(dcg, dcgxx, ifft_Qii[0], ifft_Qii[1], ifft_Qii[2], Ngrid) return dcgxx
def _FiveDelta2g_1(xyzs, fft='pyfftw', Ngrid=360): ''' calculate first part of (2 ell + 1) * delta_2 (Scoccimarro 2015 Eq. 20) More specific this function calculates delta_2 = 15/2 (kx^2 Qxx + ky^2 Qyy + kz^2 Qzz) ''' # Qxx, Qyy, Qzz (Scoccimarro 2015 Eq. 19) ifft_Qii = [] for i in range(3): _delta = np.zeros([2 * Ngrid, Ngrid, Ngrid], dtype=np.float32, order='F') # order is reversed. check this carefully fEstimate.assign_quad(xyzs, _delta, kf_ks, i + 1, i + 1, 0, 0, N, Ngrid) ifft_delta = _FFT(_delta, fft=fft, Ngrid=Ngrid) # run FFT fEstimate.fcomb(ifft_delta, N, Ngrid) # combine ifft_Qii.append(ifft_delta[:Ngrid // 2 + 1, :, :]) fEstimate.FiveDelta2g_1(ifft_Qii[0], ifft_Qii[1], ifft_Qii[2], Ngrid) return ifft_Qii[0]
def FFT_survey(radecz, w=None, Lbox=2600., Ngrid=360, cosmo=None, fft='pyfftw', silent=True): ''' Put galaxies from a survey onto a grid and FFT it. This function wraps some of the functions in estimator.f and does the same thing as roman's zmapFFTil4_aniso_gen.f :param radecz: 3 x N dimensional array that specify the [ra, dec, z] :parapm w: (default: None) N dimensional array that specifies the weight. :param Lbox: (default: 2600.) Box size :param Ngrid: (default: 360) grid size :param cosmo: (default: None) astropy.cosmology objec that specifies the cosmology for converting RA, Dec, z to cartesian coordinates. :param fft: (default: 'pyfftw') determines which fftw version to use. Options are 'pyfftw' and 'fortran'. :param silent: (default: True) if not silent then it'll output stuff notes ----- ''' kf_ks = np.float32(float(Ngrid) / Lbox) N = np.int32(xyz.shape[1]) # number of objects # default cosmology if cosmo is None: cosmo = FlatLambdaCDM(H0=67.6, Om0=0.31) if w is None: w = np.ones(N) # convert ra, dec, z to cartesian coordinates xyz = UT.radecz_to_cartesian(radecz, cosmo=cosmo) if not silent: print([ '%.1f < %s < %.1f\n' % (mi, _axis, ma) for _axis, mi, ma in zip(['x', 'y', 'z'], np.min(xyz, axis=1), np.max(xyz, axis=1)) ]) # position of galaxies (checked with fortran) xyzs = np.zeros([3, N], dtype=np.float32, order='F') xyzs[0, :] = np.clip(xyz[0, :], 0., Lbox * (1. - 1e-6)) xyzs[1, :] = np.clip(xyz[1, :], 0., Lbox * (1. - 1e-6)) xyzs[2, :] = np.clip(xyz[2, :], 0., Lbox * (1. - 1e-6)) if not silent: print('%i positions' % N) # calculate I10,I12d,I22,I13d,I23,I33 _delta = np.zeros([2 * Ngrid, Ngrid, Ngrid], dtype=np.float32, order='F') fEstimate.assign_quad(xyzs, w, _delta, kf_ks, 0, 0, 0, 0, N, Ngrid) # assign to grid ifft_delta = _FFT(_delta, fft=fft, Ngrid=Ngrid, silent=silent) # run FFT fEstimate.fcomb(ifft_delta, N, Ngrid) # combine delta0 = ifft_delta[:Ngrid // 2 + 1, :, :] if not silent: print('delta_0(k) complete') # calculate delta2 five_delta2 = _FiveDelta2g_1(xyzs, fft=fft, Ngrid=Ngrid) five_delta2 = _FiveDelta2g_1(xyzs, delta0, five_delta2, fft=fft, Ngrid=Ngrid) # calculat reweighted fields w = w**2 _delta = np.zeros([2 * Ngrid, Ngrid, Ngrid], dtype=np.float32, order='F') fEstimate.assign_quad(xyzs, w, _delta, kf_ks, 0, 0, 0, 0, N, Ngrid) # assign to grid ifft_delta = _FFT(_delta, fft=fft, Ngrid=Ngrid, silent=silent) # run FFT fEstimate.fcomb(ifft_delta, N, Ngrid) # combine delta_w = ifft_delta[:Ngrid // 2 + 1, :, :] return delta0, five_delta2, delta_w
def FFTperiodic(xyz, Lbox=2600., Ngrid=360, fft='pyfftw', silent=True): ''' Put galaxies in a grid and FFT it. This function wraps some of the functions in estimator.f and does the same thing as roman's zmapFFTil4_aniso_gen.f :param xyz: 3 x N dimensional array :param Lbox: (default: 2600.) Box size :param Ngrid: (default: 360) grid size :param fft: (default: 'pyfftw') determines which fftw version to use. Options are 'pyfftw' and 'fortran'. :param silent: (default: True) if not silent then it'll output stuff ''' kf_ks = np.float32(float(Ngrid) / Lbox) N = np.int32(xyz.shape[1]) # number of objects # position of galaxies (checked with fortran) xyzs = np.zeros([3, N], dtype=np.float32, order='F') xyzs[0, :] = np.clip(xyz[0, :], 0., Lbox * (1. - 1e-6)) xyzs[1, :] = np.clip(xyz[1, :], 0., Lbox * (1. - 1e-6)) xyzs[2, :] = np.clip(xyz[2, :], 0., Lbox * (1. - 1e-6)) if not silent: print('%i positions' % N) # assign galaxies to grid (checked with fortran) _delta = np.zeros([2 * Ngrid, Ngrid, Ngrid], dtype=np.float32, order='F') # even indices (real) odd (complex) fEstimate.assign2(xyzs, _delta, kf_ks, N, Ngrid) if fft == 'pyfftw': delta = pyfftw.n_byte_align_empty((Ngrid, Ngrid, Ngrid), 16, dtype='complex64') elif fft == 'fortran': delta = np.zeros((Ngrid, Ngrid, Ngrid), dtype='complex64', order='F') delta.real = _delta[::2, :, :] delta.imag = _delta[1::2, :, :] if not silent: print('positions assigned to grid') # FFT delta (checked with fortran code, more or less matches) if fft == 'pyfftw': fftw_ob = pyfftw.builders.ifftn( delta, planner_effort='FFTW_ESTIMATE') # axes=(0,1,2,)) #ifft_delta = fftw_ob(normalise_idft=False) ifft_delta = np.zeros((Ngrid, Ngrid, Ngrid), dtype='complex64', order='F') ifft_delta[:, :, :] = fftw_ob(normalise_idft=False) elif fft == 'fortran': ifft_delta = np.zeros((Ngrid, Ngrid, Ngrid), dtype=np.complex64, order='F') fEstimate.ffting(delta, N, Ngrid) ifft_delta[:, :, :] = delta[:, :, :] if not silent: print('position grid FFTed') # combine fields fEstimate.fcomb(ifft_delta, N, Ngrid) if not silent: print('fcomb complete') return ifft_delta[:Ngrid // 2 + 1, :, :]