def test_schechter(): from skypy.utils.random import schechter from skypy.utils.special import gammaincc def schechter_cdf_gen(alpha, x_min, x_max): a = gammaincc(alpha + 1, x_min) b = gammaincc(alpha + 1, x_max) return lambda x: (a - gammaincc(alpha + 1, x)) / (a - b) # Test the schechter function, sampling dimensionless x values alpha = -1.3 x_min = 1e-10 x_max = 1e2 x = schechter(alpha, x_min, x_max, size=1000) assert np.all(x >= x_min) assert np.all(x <= x_max) # Test the distribution of galaxy properties follows the right distribution cdf = schechter_cdf_gen(alpha, x_min, x_max) _, p = kstest(x, cdf) assert p > 0.01 # Test output shape when scale is a scalar scale = 5 samples = schechter(alpha, x_min, x_max, scale=scale) assert np.shape(samples) == np.shape(scale) # Test output shape when scale is an array scale = np.random.uniform(size=10) samples = schechter(alpha, x_min, x_max, scale=scale) assert np.shape(samples) == np.shape(scale)
def subhalo_mass_sampler(halo_mass, nsubhalos, alpha, beta, x, m_min, resolution=100): r'''Subhalo mass sampler. This function samples the original, unstriped masses of subhaloes from the subhalo mass function of their parent halo with a constant mass stripping factor given by equation (1) in [1]_ and the upper subhalo mass limit from [2]_. Parameters ----------- halo_mass : (nm, ) array_like The mass of the halo parent, in units of solar mass. nsubhalos: (nm, ) array_like Array of the number of subhalos assigned to parent halos with mass `halo_mass`. alpha, beta : float Parameters that determines the subhalo Schechter function. Its the amplitude is defined by equation 2 in [1]. x : float Parameter that accounts for the added mass of the original, unstripped subhalos. m_min : float Original mass of the least massive subhalo, in units of solar mass. Current stripped mass is given by :math:`m_{min} / x`. resolution: int, optional Resolution of the inverse transform sampling spline. Default is 100. Returns -------- sample: (nh, ) array_like List of original masses drawn from the subhalo mass function for each parent halo, in units of solar mass. The length corresponds to the total number of subhalos for all parent halos, i.e. `np.sum(nsubhalos)`. Examples --------- >>> import numpy as np >>> from skypy.halo import mass This example samples 100 subhalos for a parent halo of mass 1.0E12 Msun: >>> halo, min_sh = 1.0e12, 1.0e6 >>> alpha, beta, gamma_M = 1.9, 1.0, 0.3 >>> x = 3 >>> nsh = 100 >>> sh = mass.subhalo_mass_sampler(halo, nsh, alpha, beta, x, min_sh) References ---------- .. [1] Vale, A. and Ostriker, J.P. (2004), arXiv: astro-ph/0402500. .. [2] Vale, A. and Ostriker, J.P. (2004), arXiv: astro-ph/0511816. ''' halo_mass = np.atleast_1d(halo_mass) nsubhalos = np.atleast_1d(nsubhalos) subhalo_list = [] for M, n in zip(halo_mass, nsubhalos): x_min = m_min / (x * beta * M) x_max = 0.5 / (x * beta) subhalo_mass = schechter(alpha, x_min, x_max, resolution, size=n, scale=x * beta * M) subhalo_list.append(subhalo_mass) return np.concatenate(subhalo_list)
def test_schechter_gamma(): from skypy.utils.random import schechter # when alpha > 0, x_min ≈ 0, x_max ≈ ∞, distribution is gamma # n.b. if alpha < 0 the distribution becomes too steep to resolve accurately alpha = np.random.uniform(0, 2) x_min = 1e-20 x_max = 1e+20 scale = 2.5 x = schechter(alpha, x_min, x_max, resolution=100000, size=1000, scale=scale) _, p = kstest(x, 'gamma', args=(alpha+1, 0, scale)) assert p > 0.01
def press_schechter(n, m_star, size=None, x_min=0.00305, x_max=1100.0, resolution=100): """Sampling from Press-Schechter mass function (1974). Masses following the Press-Schechter mass function following the Press et al. [1]_ formalism. Parameters ---------- n : float or int The n parameter in the Press-Schechter mass function. m_star : float or int Factors parameterising the characteristic mass. size: int, optional Output shape of luminosity samples. x_min, x_max : float or int, optional Lower and upper bounds in units of M*. resolution : int, optional Resolution of the inverse transform sampling spline. Default is 100. Returns ------- mass : array_like Drawn masses from the Press-Schechter mass function. Examples -------- >>> import skypy.halo.mass as mass >>> n, m_star = 1, 1e9 >>> sample = mass.press_schechter(n, m_star, size=1000, x_min=1e-10, ... x_max=1e2, resolution=1000) References ---------- .. [1] Press, W. H. and Schechter, P., APJ, (1974). """ alpha = -0.5 * (n + 9.0) / (n + 3.0) x_sample = schechter(alpha, x_min, x_max, resolution=resolution, size=size) return m_star * np.power(x_sample, 3.0 / (n + 3.0))
def test_schechter(): # Test the schechter function, sampling dimensionless x values alpha = -1.3 x_min = 1e-10 x_max = 1e2 def calc_cdf(x): a = special.upper_incomplete_gamma(alpha + 1, x_min) b = special.upper_incomplete_gamma(alpha + 1, x) c = special.upper_incomplete_gamma(alpha + 1, x_min) d = special.upper_incomplete_gamma(alpha + 1, x_max) return (a - b) / (c - d) sample = random.schechter(alpha, x_min=x_min, x_max=x_max, resolution=100, size=1000) # Test the distribution of galaxy properties follows the right distribution p_value = scipy.stats.kstest(sample, calc_cdf)[1] assert p_value > 0.01
def herbel_luminosities(redshift, alpha, a_m, b_m, size=None, x_min=0.00305, x_max=1100.0, resolution=100): r"""Model of Herbel et al (2017) Luminosities following the Schechter luminosity function following the Herbel et al. [1]_ model. Parameters ---------- redshift : (nz,) array-like The redshift values at which to sample luminosities. alpha : float or int The alpha parameter in the Schechter luminosity function. a_m, b_m : float or int Factors parameterising the characteristic absolute magnitude M_* as a linear function of redshift according to Equation 3.3 in [1]_. size: int, optional Output shape of luminosity samples. If size is None and redshift is a scalar, a single sample is returned. If size is None and redshift is an array, an array of samples is returned with the same shape as redshift. x_min, x_max : float or int, optional Lower and upper luminosity bounds in units of L*. resolution : int, optional Resolution of the inverse transform sampling spline. Default is 100. Returns ------- luminosity : array_like Drawn luminosities from the Schechter luminosity function. Notes ----- The Schechter luminosity function is given as .. math:: \Phi(L, z) = \frac{\Phi_\star(z)}{L_\star(z)} \left(\frac{L}{L_\star(z)}\right)^\alpha /exp\left(-\frac{L}{L_\star(z)}\right) \;. Here the luminosity is defined as .. math:: L = 10^{-0.4M} \;, with absolute magnitude :math:`M`. Furthermore, Herbel et al. [1]_ introduced .. math:: \Phi_\star(z) = b_\phi \exp(a_\phi z) \;, M_\star(z) = a_M z + b_M \;. Now we have to rescale the Schechter function by the comoving element and get .. math:: \phi(L,z) = \frac{d_H d_M^2}{E(z)} \Phi(L,z)\;. Examples -------- >>> import skypy.galaxy.luminosity as lum Sample 100 luminosity values at redshift z = 1.0 with a_m = -0.9408582, b_m = -20.40492365, alpha = -1.3. >>> luminosities = lum.herbel_luminosities(1.0, -1.3, -0.9408582, ... -20.40492365, size=100) Sample a luminosity value for every redshift in an array z with a_m = -0.9408582, b_m = -20.40492365, alpha = -1.3. >>> z = np.linspace(0,2, 100) >>> luminosities = lum.herbel_luminosities(z, -1.3, -0.9408582, ... -20.40492365) References ---------- .. [1] Herbel J., Kacprzak T., Amara A. et al., 2017, Journal of Cosmology and Astroparticle Physics, Issue 08, article id. 035 (2017) """ if size is None and np.shape(redshift): size = np.shape(redshift) luminosity_star = _calculate_luminosity_star(redshift, a_m, b_m) x_sample = schechter(alpha, x_min, x_max, resolution=100, size=size) return luminosity_star * x_sample
def schechter_smf(alpha, m_star, x_min, x_max, resolution=100, size=None): r""" Stellar masses following the Schechter mass function [1]_. Parameters ---------- alpha : float The alpha parameter in the Schechter stellar mass function. m_star : (nm,) array-like Characteristic stellar mass M_*. size: int, optional Output shape of stellar mass samples. If size is None and m_star is a scalar, a single sample is returned. If size is None and m_star is an array, an array of samples is returned with the same shape as m_star. x_min, x_max : float Lower and upper bounds for the random variable x in units of M_*. resolution : int, optional Resolution of the inverse transform sampling spline. Default is 100. Returns ------- stellar mass : (nm,) array_like Drawn stellar masses from the Schechter stellar mass function in units of the solar mass. Notes ----- The stellar mass probability distribution (pdf) follows a Schechter profile of the form .. math:: \Phi(M) = \frac{1}{M_*} \left(\frac{M}{M_*}\right)^\alpha \exp\left(-\frac{M}{M_*}\right) \;. From this pdf one can sample the stellar masses. Examples -------- >>> from skypy.galaxy import stellar_mass Sample 100 stellar masses values at redshift z = 1.0 with alpha = -1.4, m_star = 10**10.67, x_min = 0.0002138 and x_max = 213.8 >>> masses = stellar_mass.schechter_smf(-1.4, 10**10.67, 0.0002138, ... 213.8, size=100) References ---------- .. [1] Mo, H., Van den Bosch, F., & White, S. (2010). Galaxy Formation and Evolution. Cambridge: Cambridge University Press. doi:10.1017/CBO9780511807244 """ if size is None and np.shape(m_star): size = np.shape(m_star) x_sample = schechter(alpha, x_min, x_max, resolution=resolution, size=size) return m_star * x_sample