|
5 | 5 |
|
6 | 6 | """
|
7 | 7 |
|
| 8 | +from astropy.cosmology import z_at_value |
| 9 | +from astropy import units |
8 | 10 | import numpy as np
|
9 | 11 | from scipy import integrate
|
| 12 | +from skypy.galaxies.redshift import redshifts_from_comoving_density |
10 | 13 |
|
11 | 14 | __all__ = [
|
12 | 15 | 'colossus_mass_sampler',
|
@@ -72,3 +75,131 @@ def colossus_mass_sampler(redshift, model, mdef, m_min, m_max,
|
72 | 75 | n_uniform = np.random.uniform(size=size)
|
73 | 76 | masssample = np.interp(n_uniform, CDF, m)
|
74 | 77 | return masssample
|
| 78 | + |
| 79 | + |
| 80 | +@units.quantity_input(sky_area=units.sr) |
| 81 | +def colossus_mf_redshift(redshift, model, mdef, m_min, m_max, sky_area, |
| 82 | + cosmology, sigma8, ns, resolution=1000, noise=True): |
| 83 | + r'''Sample redshifts from a COLOSSUS halo mass function. |
| 84 | +
|
| 85 | + Sample the redshifts of dark matter halos following a mass function |
| 86 | + implemented in COLOSSUS [1]_ within given mass and redshift ranges and for |
| 87 | + a given area of the sky. |
| 88 | +
|
| 89 | + Parameters |
| 90 | + ---------- |
| 91 | + redshift : array_like |
| 92 | + Input redshift grid on which the mass function is evaluated. Halos are |
| 93 | + sampled over this redshift range. |
| 94 | + model : string |
| 95 | + Mass function model which is available in colossus. |
| 96 | + mdef : str |
| 97 | + Halo mass definition for spherical overdensities used by colossus. |
| 98 | + m_min, m_max : float |
| 99 | + Lower and upper bounds for the halo mass in units of Solar mass, Msun. |
| 100 | + sky_area : `~astropy.units.Quantity` |
| 101 | + Sky area over which halos are sampled. Must be in units of solid angle. |
| 102 | + cosmology : Cosmology |
| 103 | + Cosmology object to convert comoving density. |
| 104 | + sigma8 : float |
| 105 | + Cosmology parameter, amplitude of the (linear) power spectrum on the |
| 106 | + scale of 8 Mpc/h. |
| 107 | + ns : float |
| 108 | + Cosmology parameter, spectral index of scalar perturbation power |
| 109 | + spectrum. |
| 110 | + noise : bool, optional |
| 111 | + Poisson-sample the number of halos. Default is `True`. |
| 112 | +
|
| 113 | + Returns |
| 114 | + ------- |
| 115 | + redshifts : array_like |
| 116 | + Redshifts of the halo sample. |
| 117 | +
|
| 118 | + References |
| 119 | + ---------- |
| 120 | + .. [1] Diemer B., 2018, ApJS, 239, 35 |
| 121 | +
|
| 122 | + ''' |
| 123 | + from colossus.cosmology.cosmology import fromAstropy |
| 124 | + from colossus.lss.mass_function import massFunction |
| 125 | + |
| 126 | + # Set the cosmology in COLOSSUS |
| 127 | + fromAstropy(cosmology, sigma8, ns) |
| 128 | + |
| 129 | + # Integrate the mass function to get the number density of halos at each redshift |
| 130 | + def dndlnM(lnm, z): |
| 131 | + return massFunction(np.exp(lnm), z, 'M', 'dndlnM', mdef, model) |
| 132 | + lnmmin = np.log(m_min*cosmology.h) |
| 133 | + lnmmax = np.log(m_max*cosmology.h) |
| 134 | + density = [integrate.quad(dndlnM, lnmmin, lnmmax, args=(z))[0] for z in redshift] |
| 135 | + density = np.array(density) * np.power(cosmology.h, 3) |
| 136 | + |
| 137 | + # Sample halo redshifts and assign to bins |
| 138 | + return redshifts_from_comoving_density(redshift, density, sky_area, cosmology, noise) |
| 139 | + |
| 140 | + |
| 141 | +@units.quantity_input(sky_area=units.sr) |
| 142 | +def colossus_mf(redshift, model, mdef, m_min, m_max, sky_area, cosmology, |
| 143 | + sigma8, ns, resolution=1000, noise=True): |
| 144 | + r'''Sample halo redshifts and masses from a COLOSSUS mass function. |
| 145 | +
|
| 146 | + Sample the redshifts and masses of dark matter halos following a mass |
| 147 | + function implemented in COLOSSUS [1]_ within given mass and redshift ranges |
| 148 | + and for a given area of the sky. |
| 149 | +
|
| 150 | + Parameters |
| 151 | + ---------- |
| 152 | + redshift : array_like |
| 153 | + Defines the edges of a set of redshift bins for which the mass function |
| 154 | + is evaluated. Must be a monotonically-increasing one-dimensional array |
| 155 | + of values. Halo redshifts are sampled between the minimum and maximum |
| 156 | + values in this array. |
| 157 | + model : string |
| 158 | + Mass function model which is available in colossus. |
| 159 | + mdef : str |
| 160 | + Halo mass definition for spherical overdensities used by colossus. |
| 161 | + m_min, m_max : float |
| 162 | + Lower and upper bounds for the halo mass in units of Solar mass, Msun. |
| 163 | + sky_area : `~astropy.units.Quantity` |
| 164 | + Sky area over which halos are sampled. Must be in units of solid angle. |
| 165 | + cosmology : Cosmology |
| 166 | + Cosmology object to calculate comoving densities. |
| 167 | + sigma8 : float |
| 168 | + Cosmology parameter, amplitude of the (linear) power spectrum on the |
| 169 | + scale of 8 Mpc/h. |
| 170 | + ns : float |
| 171 | + Cosmology parameter, spectral index of scalar perturbation power |
| 172 | + spectrum. |
| 173 | + noise : bool, optional |
| 174 | + Poisson-sample the number of halos. Default is `True`. |
| 175 | +
|
| 176 | + Returns |
| 177 | + ------- |
| 178 | + redshift, mass : tuple of array_like |
| 179 | + Redshifts and masses of the halo sample. |
| 180 | +
|
| 181 | + References |
| 182 | + ---------- |
| 183 | + .. [1] Diemer B., 2018, ApJS, 239, 35 |
| 184 | +
|
| 185 | + ''' |
| 186 | + |
| 187 | + # Sample halo redshifts and assign to bins |
| 188 | + z = colossus_mf_redshift(redshift, model, mdef, m_min, m_max, sky_area, |
| 189 | + cosmology, sigma8, ns, resolution, noise) |
| 190 | + redshift_bin = np.digitize(z, redshift) |
| 191 | + |
| 192 | + # Calculate the redshift at the centre of each bin |
| 193 | + comoving_distance = cosmology.comoving_distance(redshift) |
| 194 | + d_mid = 0.5 * (comoving_distance[:-1] + comoving_distance[1:]) |
| 195 | + z_mid = [z_at_value(cosmology.comoving_distance, d) for d in d_mid] |
| 196 | + |
| 197 | + # Sample halo masses in each redshift bin |
| 198 | + m = np.empty_like(z) |
| 199 | + for i, zm in enumerate(z_mid): |
| 200 | + mask = redshift_bin == i + 1 |
| 201 | + size = np.count_nonzero(mask) |
| 202 | + m[mask] = colossus_mass_sampler(zm, model, mdef, m_min, m_max, |
| 203 | + cosmology, sigma8, ns, size, resolution) |
| 204 | + |
| 205 | + return z, m |
0 commit comments