def powerspectrum_1D(self, k_vec, z1, z2, numz): r"""A vectorized routine for calculating the redshift space powerspectrum. Parameters ---------- k_vec: array_like The magnitude of the k-vector redshift: scalar Redshift at which to evaluate other parameters Returns ------- ps: array_like The redshift space power spectrum at the given k-vector and redshift. Note that this uses the same ps_vv as the realisation generator until the full dd, dv, vv calculation is ready. TODO: evaluate this using the same weight function in z as the data. """ c1 = self.cosmology.comoving_distance(z1) c2 = self.cosmology.comoving_distance(z2) # Construct an array of the redshifts on each slice of the cube. comoving_inv = cosmo.inverse_approx(self.cosmology.comoving_distance, z1, z2) da = np.linspace(c1, c2, numz + 1, endpoint=True) za = comoving_inv(da) # Calculate the bias and growth factors for each slice of the cube. mz = self.mean(za) bz = self.bias_z(za) fz = self.growth_rate(za) Dz = self.growth_factor(za) / self.growth_factor(self.ps_redshift) pz = self.prefactor(za) dfactor = np.mean(Dz * pz * bz) vfactor = np.mean(Dz * pz * fz) return self.ps_vv(k_vec) * dfactor * dfactor
def physical_grid(input_array, refinement=2, pad=5, order=2): r"""Project from freq, ra, dec into physical coordinates Parameters ---------- input_array: np.ndarray The freq, ra, dec map Returns ------- cube: np.ndarray The cube projected back into physical coordinates """ freq_axis = input_array.get_axis('freq') / 1.e6 ra_axis = input_array.get_axis('ra') dec_axis = input_array.get_axis('dec') nu_lower, nu_upper = freq_axis.min(), freq_axis.max() ra_fact = sp.cos(sp.pi * input_array.info['dec_centre'] / 180.0) thetax, thetay = np.ptp(ra_axis), np.ptp(dec_axis) thetax *= ra_fact (numz, numx, numy) = input_array.shape cosmology = cosmo.Cosmology() z1 = units.nu21 / nu_upper - 1.0 z2 = units.nu21 / nu_lower - 1.0 d1 = cosmology.proper_distance(z1) d2 = cosmology.proper_distance(z2) c1 = cosmology.comoving_distance(z1) c2 = cosmology.comoving_distance(z2) c_center = (c1 + c2) / 2. # Make cube pixelisation finer, such that angular cube will # have sufficient resolution on the closest face. phys_dim = np.array([c2 - c1, thetax * d2 * units.degree, thetay * d2 * units.degree]) # Note that the ratio of deltas in Ra, Dec in degrees may # be different than the Ra, Dec in physical coordinates due to # rounding onto this grid n = np.array([numz, int(d2 / d1 * numx), int(d2 / d1 * numy)]) # Enlarge cube size by `pad` in each dimension, so raytraced cube # sits exactly within the gridded points. phys_dim = phys_dim * (n + pad).astype(float) / n.astype(float) c1 = c_center - (c_center - c1) * (n[0] + pad) / float(n[0]) c2 = c_center + (c2 - c_center) * (n[0] + pad) / float(n[0]) n = n + pad # now multiply by scaling for a finer sub-grid n = refinement * n print "converting from obs. to physical coord refinement=%s, pad=%s" % \ (refinement, pad) print "(%d, %d, %d)->(%f to %f) x %f x %f (%d, %d, %d) (h^-1 cMpc)^3" % \ (numz, numx, numy, c1, c2, \ phys_dim[1], phys_dim[2], \ n[0], n[1], n[2]) # this is wasteful in memory, but numpy can be pickled phys_map_npy = np.zeros(n) phys_map = algebra.make_vect(phys_map_npy, axis_names=('freq', 'ra', 'dec')) #mask = np.ones_like(phys_map) mask = np.ones_like(phys_map_npy) # TODO: should this be more sophisticated? N-1 or N? info = {} info['axes'] = ('freq', 'ra', 'dec') info['type'] = 'vect' #info = {'freq_delta': abs(phys_dim[0])/float(n[0]), # 'freq_centre': abs(c2+c1)/2., info['freq_delta'] = abs(c2 - c1) / float(n[0] - 1) info['freq_centre'] = c1 + info['freq_delta'] * float(n[0] // 2) info['ra_delta'] = abs(phys_dim[1]) / float(n[1] - 1) #info['ra_centre'] = info['ra_delta'] * float(n[1] // 2) info['ra_centre'] = 0. info['dec_delta'] = abs(phys_dim[2]) / float(n[2] - 1) #info['dec_centre'] = info['dec_delta'] * float(n[2] // 2) info['dec_centre'] = 0. phys_map.info = info print info # same as np.linspace(c1, c2, n[0], endpoint=True) radius_axis = phys_map.get_axis("freq") x_axis = phys_map.get_axis("ra") y_axis = phys_map.get_axis("dec") # Construct an array of the redshifts on each slice of the cube. comoving_inv = cosmo.inverse_approx(cosmology.comoving_distance, z1, z2) za = comoving_inv(radius_axis) # redshifts on the constant-D spacing nua = units.nu21 / (1. + za) gridy, gridx = np.meshgrid(y_axis, x_axis) interpol_grid = np.zeros((3, n[1], n[2])) for i in range(n[0]): # nua[0] = nu_upper, nua[1] = nu_lower #print nua[i], freq_axis[0], freq_axis[-1], (nua[i] - freq_axis[0]) / \ # (freq_axis[-1] - freq_axis[0]) * numz interpol_grid[0, :, :] = (nua[i] - freq_axis[0]) / \ (freq_axis[-1] - freq_axis[0]) * numz proper_z = cosmology.proper_distance(za[i]) angscale = proper_z * units.degree interpol_grid[1, :, :] = gridx / angscale / thetax * numx + numx / 2 interpol_grid[2, :, :] = gridy / angscale / thetay * numy + numy / 2 phys_map_npy[i, :, :] = sp.ndimage.map_coordinates(input_array, interpol_grid, order=order) interpol_grid[1, :, :] = np.logical_or(interpol_grid[1, :, :] > numx, interpol_grid[1, :, :] < 0) interpol_grid[2, :, :] = np.logical_or(interpol_grid[1, :, :] > numy, interpol_grid[1, :, :] < 0) mask = np.logical_not(np.logical_or(interpol_grid[1, :, :], interpol_grid[2, :, :])) phys_map_npy *= mask return phys_map_npy, info
def realisation( self, z1, z2, thetax, thetay, numz, numx, numy, zspace=True, refinement=1, report_physical=False, density_only=False, no_mean=False, no_evolution=False, pad=5, ): r"""Simulate a redshift-space volume. Generates a 3D (angle-angle-redshift) volume from the given power spectrum. Currently only works with simply biased power spectra (i.e. vv_only). This routine uses a flat sky approximation, and so becomes inaccurate when a large volume of the sky is simulated. Parameters ---------- z1, z2 : scalar Lower and upper redshifts of the box. thetax, thetay : scalar The angular size (in degrees) of the box. numz : integer The number of bins in redshift. numx, numy : integer The number of angular pixels along each side. zspace : boolean, optional If True (default) redshift bins are equally spaced in redshift. Otherwise space equally in the scale factor (useful for generating an equal range in frequency). density_only: boolean no velocity contribution no_mean: boolean do not add the mean temperature no_evolution: boolean do not let b(z), D(z) etc. evolve: take their mean pad: integer number of pixels over which to pad the physical region for interpolation onto freq, ra, dec; match spline order? Returns ------- cube : np.ndarray The volume cube. """ d1 = self.cosmology.proper_distance(z1) d2 = self.cosmology.proper_distance(z2) c1 = self.cosmology.comoving_distance(z1) c2 = self.cosmology.comoving_distance(z2) c_center = (c1 + c2) / 2.0 # Make cube pixelisation finer, such that angular cube will # have sufficient resolution on the closest face. d = np.array([c2 - c1, thetax * d2 * units.degree, thetay * d2 * units.degree]) # Note that the ratio of deltas in Ra, Dec in degrees may # be different than the Ra, Dec in physical coordinates due to # rounding onto this grid n = np.array([numz, int(d2 / d1 * numx), int(d2 / d1 * numy)]) # Enlarge cube size by 1 in each dimension, so raytraced cube # sits exactly within the gridded points. d = d * (n + pad).astype(float) / n.astype(float) c1 = c_center - (c_center - c1) * (n[0] + pad) / float(n[0]) c2 = c_center + (c2 - c_center) * (n[0] + pad) / float(n[0]) n = n + pad # now multiply by scaling for a finer sub-grid n = refinement * n print "Generating cube: (%f to %f) x %f x %f (%d, %d, %d) (h^-1 cMpc)^3" % ( c1, c2, d[1], d[2], n[0], n[1], n[2], ) cube = self._realisation_dv(d, n) # TODO: this is probably unnecessary now (realisation used to change # shape through irfftn) n = cube[0].shape # Construct an array of the redshifts on each slice of the cube. comoving_inv = cosmo.inverse_approx(self.cosmology.comoving_distance, z1, z2) da = np.linspace(c1, c2, n[0], endpoint=True) za = comoving_inv(da) # Calculate the bias and growth factors for each slice of the cube. mz = self.mean(za) bz = self.bias_z(za) fz = self.growth_rate(za) Dz = self.growth_factor(za) / self.growth_factor(self.ps_redshift) pz = self.prefactor(za) # Construct the observable and velocity fields. if not no_evolution: df = cube[0] * (Dz * pz * bz)[:, np.newaxis, np.newaxis] vf = cube[1] * (Dz * pz * fz)[:, np.newaxis, np.newaxis] else: df = cube[0] * np.mean(Dz * pz * bz) vf = cube[1] * np.mean(Dz * pz * fz) # Construct the redshift space cube. rsf = df if not density_only: rsf += vf if not no_mean: rsf += mz[:, np.newaxis, np.newaxis] # Find the distances that correspond to a regular redshift # spacing (or regular spacing in a). if zspace: za = np.linspace(z1, z2, numz, endpoint=False) else: za = 1.0 / np.linspace(1.0 / (1 + z2), 1.0 / (1 + z1), numz, endpoint=False)[::-1] - 1.0 da = self.cosmology.proper_distance(za) xa = self.cosmology.comoving_distance(za) # Construct the angular offsets into cube tx = np.linspace(-thetax / 2.0, thetax / 2.0, numx) * units.degree ty = np.linspace(-thetay / 2.0, thetay / 2.0, numy) * units.degree # tgridx, tgridy = np.meshgrid(tx, ty) tgridy, tgridx = np.meshgrid(ty, tx) tgrid2 = np.zeros((3, numx, numy)) acube = np.zeros((numz, numx, numy)) # Iterate over redshift slices, constructing the coordinates # and interpolating into the 3d cube. Note that the multipliers scale # from 0 to 1, or from i=0 to i=N-1 for i in range(numz): tgrid2[0, :, :] = (xa[i] - c1) / (c2 - c1) * (n[0] - 1.0) tgrid2[1, :, :] = (tgridx * da[i]) / d[1] * (n[1] - 1.0) + 0.5 * (n[1] - 1.0) tgrid2[2, :, :] = (tgridy * da[i]) / d[2] * (n[2] - 1.0) + 0.5 * (n[2] - 1.0) # if(zi > numz - 2): # TODO: what order here?; do end-to-end P(k) study # acube[i,:,:] = scipy.ndimage.map_coordinates(rsf, tgrid2, order=2) acube[i, :, :] = scipy.ndimage.map_coordinates(rsf, tgrid2, order=1) if report_physical: return acube, rsf, (c1, c2, d[1], d[2]) else: return acube
from utils import cosmology from simulations import corr from utils.cosmology import Cosmology redshift = 1. cosmo = Cosmology() proper = cosmo.proper_distance(redshift) comoving = cosmo.comoving_distance(redshift) comoving_inv = cosmology.inverse_approx(cosmo.comoving_distance, 0.6, 1.) print proper, comoving, comoving_inv(2355.35909781)
def physical_grid(input_array, refinement=2, pad=5, order=2): r"""Project from freq, ra, dec into physical coordinates Parameters ---------- input_array: np.ndarray The freq, ra, dec map Returns ------- cube: np.ndarray The cube projected back into physical coordinates """ freq_axis = input_array.get_axis('freq') / 1.e6 ra_axis = input_array.get_axis('ra') dec_axis = input_array.get_axis('dec') nu_lower, nu_upper = freq_axis.min(), freq_axis.max() ra_fact = sp.cos(sp.pi * input_array.info['dec_centre'] / 180.0) thetax, thetay = np.ptp(ra_axis), np.ptp(dec_axis) thetax *= ra_fact (numz, numx, numy) = input_array.shape cosmology = cosmo.Cosmology() z1 = units.nu21 / nu_upper - 1.0 z2 = units.nu21 / nu_lower - 1.0 d1 = cosmology.proper_distance(z1) d2 = cosmology.proper_distance(z2) c1 = cosmology.comoving_distance(z1) c2 = cosmology.comoving_distance(z2) c_center = (c1 + c2) / 2. # Make cube pixelisation finer, such that angular cube will # have sufficient resolution on the closest face. phys_dim = np.array( [c2 - c1, thetax * d2 * units.degree, thetay * d2 * units.degree]) # Note that the ratio of deltas in Ra, Dec in degrees may # be different than the Ra, Dec in physical coordinates due to # rounding onto this grid n = np.array([numz, int(d2 / d1 * numx), int(d2 / d1 * numy)]) # Enlarge cube size by `pad` in each dimension, so raytraced cube # sits exactly within the gridded points. phys_dim = phys_dim * (n + pad).astype(float) / n.astype(float) c1 = c_center - (c_center - c1) * (n[0] + pad) / float(n[0]) c2 = c_center + (c2 - c_center) * (n[0] + pad) / float(n[0]) n = n + pad # now multiply by scaling for a finer sub-grid n = refinement * n print "converting from obs. to physical coord refinement=%s, pad=%s" % \ (refinement, pad) print "(%d, %d, %d)->(%f to %f) x %f x %f (%d, %d, %d) (h^-1 cMpc)^3" % \ (numz, numx, numy, c1, c2, \ phys_dim[1], phys_dim[2], \ n[0], n[1], n[2]) # this is wasteful in memory, but numpy can be pickled phys_map_npy = np.zeros(n) phys_map = algebra.make_vect(phys_map_npy, axis_names=('freq', 'ra', 'dec')) #mask = np.ones_like(phys_map) mask = np.ones_like(phys_map_npy) # TODO: should this be more sophisticated? N-1 or N? info = {} info['axes'] = ('freq', 'ra', 'dec') info['type'] = 'vect' #info = {'freq_delta': abs(phys_dim[0])/float(n[0]), # 'freq_centre': abs(c2+c1)/2., info['freq_delta'] = abs(c2 - c1) / float(n[0] - 1) info['freq_centre'] = c1 + info['freq_delta'] * float(n[0] // 2) info['ra_delta'] = abs(phys_dim[1]) / float(n[1] - 1) #info['ra_centre'] = info['ra_delta'] * float(n[1] // 2) info['ra_centre'] = 0. info['dec_delta'] = abs(phys_dim[2]) / float(n[2] - 1) #info['dec_centre'] = info['dec_delta'] * float(n[2] // 2) info['dec_centre'] = 0. phys_map.info = info print info # same as np.linspace(c1, c2, n[0], endpoint=True) radius_axis = phys_map.get_axis("freq") x_axis = phys_map.get_axis("ra") y_axis = phys_map.get_axis("dec") # Construct an array of the redshifts on each slice of the cube. comoving_inv = cosmo.inverse_approx(cosmology.comoving_distance, z1, z2) za = comoving_inv(radius_axis) # redshifts on the constant-D spacing nua = units.nu21 / (1. + za) gridy, gridx = np.meshgrid(y_axis, x_axis) interpol_grid = np.zeros((3, n[1], n[2])) for i in range(n[0]): # nua[0] = nu_upper, nua[1] = nu_lower #print nua[i], freq_axis[0], freq_axis[-1], (nua[i] - freq_axis[0]) / \ # (freq_axis[-1] - freq_axis[0]) * numz interpol_grid[0, :, :] = (nua[i] - freq_axis[0]) / \ (freq_axis[-1] - freq_axis[0]) * numz proper_z = cosmology.proper_distance(za[i]) angscale = proper_z * units.degree interpol_grid[1, :, :] = gridx / angscale / thetax * numx + numx / 2 interpol_grid[2, :, :] = gridy / angscale / thetay * numy + numy / 2 phys_map_npy[i, :, :] = sp.ndimage.map_coordinates(input_array, interpol_grid, order=order) interpol_grid[1, :, :] = np.logical_or(interpol_grid[1, :, :] > numx, interpol_grid[1, :, :] < 0) interpol_grid[2, :, :] = np.logical_or(interpol_grid[1, :, :] > numy, interpol_grid[1, :, :] < 0) mask = np.logical_not( np.logical_or(interpol_grid[1, :, :], interpol_grid[2, :, :])) phys_map_npy *= mask return phys_map_npy, info
def realisation(self, z1, z2, thetax, thetay, numz, numx, numy, zspace=True, refinement=1, report_physical=False, density_only=False, no_mean=False, no_evolution=False, pad=5): r"""Simulate a redshift-space volume. Generates a 3D (angle-angle-redshift) volume from the given power spectrum. Currently only works with simply biased power spectra (i.e. vv_only). This routine uses a flat sky approximation, and so becomes inaccurate when a large volume of the sky is simulated. Parameters ---------- z1, z2 : scalar Lower and upper redshifts of the box. thetax, thetay : scalar The angular size (in degrees) of the box. numz : integer The number of bins in redshift. numx, numy : integer The number of angular pixels along each side. zspace : boolean, optional If True (default) redshift bins are equally spaced in redshift. Otherwise space equally in the scale factor (useful for generating an equal range in frequency). density_only: boolean no velocity contribution no_mean: boolean do not add the mean temperature no_evolution: boolean do not let b(z), D(z) etc. evolve: take their mean pad: integer number of pixels over which to pad the physical region for interpolation onto freq, ra, dec; match spline order? Returns ------- cube : np.ndarray The volume cube. """ d1 = self.cosmology.proper_distance(z1) d2 = self.cosmology.proper_distance(z2) c1 = self.cosmology.comoving_distance(z1) c2 = self.cosmology.comoving_distance(z2) c_center = (c1 + c2) / 2. # Make cube pixelisation finer, such that angular cube will # have sufficient resolution on the closest face. d = np.array( [c2 - c1, thetax * d2 * units.degree, thetay * d2 * units.degree]) # Note that the ratio of deltas in Ra, Dec in degrees may # be different than the Ra, Dec in physical coordinates due to # rounding onto this grid n = np.array([numz, int(d2 / d1 * numx), int(d2 / d1 * numy)]) # Enlarge cube size by 1 in each dimension, so raytraced cube # sits exactly within the gridded points. d = d * (n + pad).astype(float) / n.astype(float) c1 = c_center - (c_center - c1) * (n[0] + pad) / float(n[0]) c2 = c_center + (c2 - c_center) * (n[0] + pad) / float(n[0]) n = n + pad # now multiply by scaling for a finer sub-grid n = refinement * n print "Generating cube: (%f to %f) x %f x %f (%d, %d, %d) (h^-1 cMpc)^3" % \ (c1, c2, d[1], d[2], n[0], n[1], n[2]) cube = self._realisation_dv(d, n) # TODO: this is probably unnecessary now (realisation used to change # shape through irfftn) n = cube[0].shape # Construct an array of the redshifts on each slice of the cube. comoving_inv = cosmo.inverse_approx(self.cosmology.comoving_distance, z1, z2) da = np.linspace(c1, c2, n[0], endpoint=True) za = comoving_inv(da) # Calculate the bias and growth factors for each slice of the cube. mz = self.mean(za) bz = self.bias_z(za) fz = self.growth_rate(za) Dz = self.growth_factor(za) / self.growth_factor(self.ps_redshift) pz = self.prefactor(za) # Construct the observable and velocity fields. if not no_evolution: df = cube[0] * (Dz * pz * bz)[:, np.newaxis, np.newaxis] vf = cube[1] * (Dz * pz * fz)[:, np.newaxis, np.newaxis] else: df = cube[0] * np.mean(Dz * pz * bz) vf = cube[1] * np.mean(Dz * pz * fz) # Construct the redshift space cube. rsf = df if not density_only: rsf += vf if not no_mean: rsf += mz[:, np.newaxis, np.newaxis] # Find the distances that correspond to a regular redshift # spacing (or regular spacing in a). if zspace: za = np.linspace(z1, z2, numz, endpoint=False) else: za = 1.0 / np.linspace( 1.0 / (1 + z2), 1.0 / (1 + z1), numz, endpoint=False)[::-1] - 1.0 da = self.cosmology.proper_distance(za) xa = self.cosmology.comoving_distance(za) # Construct the angular offsets into cube tx = np.linspace(-thetax / 2., thetax / 2., numx) * units.degree ty = np.linspace(-thetay / 2., thetay / 2., numy) * units.degree #tgridx, tgridy = np.meshgrid(tx, ty) tgridy, tgridx = np.meshgrid(ty, tx) tgrid2 = np.zeros((3, numx, numy)) acube = np.zeros((numz, numx, numy)) # Iterate over redshift slices, constructing the coordinates # and interpolating into the 3d cube. Note that the multipliers scale # from 0 to 1, or from i=0 to i=N-1 for i in range(numz): tgrid2[0, :, :] = (xa[i] - c1) / (c2 - c1) * (n[0] - 1.) tgrid2[1,:,:] = (tgridx * da[i]) / d[1] * (n[1] - 1.) + \ 0.5*(n[1] - 1.) tgrid2[2,:,:] = (tgridy * da[i]) / d[2] * (n[2] - 1.) + \ 0.5*(n[2] - 1.) #if(zi > numz - 2): # TODO: what order here?; do end-to-end P(k) study #acube[i,:,:] = scipy.ndimage.map_coordinates(rsf, tgrid2, order=2) acube[i, :, :] = scipy.ndimage.map_coordinates(rsf, tgrid2, order=1) if report_physical: return acube, rsf, (c1, c2, d[1], d[2]) else: return acube