def growth_factor_fn(self, zmin=0.0, inverse=False): """ Calculate :math:`d(a) = D^+(a)/D^+(a=1)`, from Lukic et. al. 2007, eq. 7. Returns a function G(z). Parameters ---------- zmin : float, optional The minimum redshift of the function. Default 0.0 inverse: bool, optional Whether to return the inverse relationship [z(g)]. Default False. Returns ------- callable The normalised growth factor as a function of redshift, or redshift as a function of growth factor if ``inverse`` is True. """ growth = self._d_plus(zmin, True)/self._d_plus(0.0) if not inverse: s = _spline(self._zvec[::-1], growth[::-1]) else: s = _spline(growth, self._zvec) return s
def __init__(self, **model_parameters): super(Tinker08, self).__init__(**model_parameters) if self.delta_halo not in self.delta_virs: A_array = np.array([self.params["A_%s" % d] for d in self.delta_virs]) a_array = np.array([self.params["a_%s" % d] for d in self.delta_virs]) b_array = np.array([self.params["b_%s" % d] for d in self.delta_virs]) c_array = np.array([self.params["c_%s" % d] for d in self.delta_virs]) A_func = _spline(self.delta_virs, A_array) a_func = _spline(self.delta_virs, a_array) b_func = _spline(self.delta_virs, b_array) c_func = _spline(self.delta_virs, c_array) A_0 = A_func(self.delta_halo) a_0 = a_func(self.delta_halo) b_0 = b_func(self.delta_halo) c_0 = c_func(self.delta_halo) else: A_0 = self.params["A_%s" % (int(self.delta_halo))] a_0 = self.params["a_%s" % (int(self.delta_halo))] b_0 = self.params["b_%s" % (int(self.delta_halo))] c_0 = self.params["c_%s" % (int(self.delta_halo))] self.A = A_0 * (1 + self.z) ** (-self.params["A_exp"]) self.a = a_0 * (1 + self.z) ** (-self.params["a_exp"]) alpha = 10 ** (-(0.75 / np.log10(self.delta_halo / 75)) ** 1.2) self.b = b_0 * (1 + self.z) ** (-alpha) self.c = c_0
def __init__(self, **model_parameters): super(Tinker08, self).__init__(**model_parameters) if self.delta_halo not in self.delta_virs: A_array = np.array( [self.params["A_%s" % d] for d in self.delta_virs]) a_array = np.array( [self.params["a_%s" % d] for d in self.delta_virs]) b_array = np.array( [self.params["b_%s" % d] for d in self.delta_virs]) c_array = np.array( [self.params["c_%s" % d] for d in self.delta_virs]) A_func = _spline(self.delta_virs, A_array) a_func = _spline(self.delta_virs, a_array) b_func = _spline(self.delta_virs, b_array) c_func = _spline(self.delta_virs, c_array) A_0 = A_func(self.delta_halo) a_0 = a_func(self.delta_halo) b_0 = b_func(self.delta_halo) c_0 = c_func(self.delta_halo) else: A_0 = self.params["A_%s" % (int(self.delta_halo))] a_0 = self.params["a_%s" % (int(self.delta_halo))] b_0 = self.params["b_%s" % (int(self.delta_halo))] c_0 = self.params["c_%s" % (int(self.delta_halo))] self.A = A_0 * (1 + self.z)**(-self.params["A_exp"]) self.a = a_0 * (1 + self.z)**(-self.params["a_exp"]) alpha = 10**(-(0.75 / np.log10(self.delta_halo / 75))**1.2) self.b = b_0 * (1 + self.z)**(-alpha) self.c = c_0
def growth_factor_fn(self, zmin=0.0, inverse=False): """ Calculate :math:`d(a) = D^+(a)/D^+(a=1)`, from Lukic et. al. 2007, eq. 7. Returns a function G(z). Parameters ---------- zmin : float, optional The minimum redshift of the function. Default 0.0 inverse: bool, optional Whether to return the inverse relationship [z(g)]. Default False. Returns ------- callable The normalised growth factor as a function of redshift, or redshift as a function of growth factor if ``inverse`` is True. """ dp = self._d_plus(0.0, True) growth = dp / dp[-1] if not inverse: s = _spline(self._zvec[::-1], growth[::-1]) else: s = _spline(growth, self._zvec) return s
def __init__(self, **model_parameters): super(Tinker10, self).__init__(**model_parameters) if self.delta_halo not in self.delta_virs: beta_array = np.array([self.params["beta_%s" % d] for d in self.delta_virs]) gamma_array = np.array([self.params["gamma_%s" % d] for d in self.delta_virs]) phi_array = np.array([self.params["phi_%s" % d] for d in self.delta_virs]) eta_array = np.array([self.params["eta_%s" % d] for d in self.delta_virs]) beta_func = _spline(self.delta_virs, beta_array) gamma_func = _spline(self.delta_virs, gamma_array) phi_func = _spline(self.delta_virs, phi_array) eta_func = _spline(self.delta_virs, eta_array) beta_0 = beta_func(self.delta_halo) gamma_0 = gamma_func(self.delta_halo) phi_0 = phi_func(self.delta_halo) eta_0 = eta_func(self.delta_halo) else: beta_0 = self.params['beta_%s' % (int(self.delta_halo))] gamma_0 = self.params['gamma_%s' % (int(self.delta_halo))] phi_0 = self.params['phi_%s' % (int(self.delta_halo))] eta_0 = self.params['eta_%s' % (int(self.delta_halo))] self.beta = beta_0 * (1 + min(self.z, self.params["max_z"])) ** self.params["beta_exp"] self.phi = phi_0 * (1 + min(self.z, self.params["max_z"])) ** self.params['phi_exp'] self.eta = eta_0 * (1 + min(self.z, self.params["max_z"])) ** self.params['eta_exp'] self.gamma = gamma_0 * (1 + min(self.z, self.params["max_z"])) ** self.params['gamma_exp'] # # The normalisation only works with specific conditions # gamma > 0 if self.gamma <= 0: if self.terminate: raise ValueError("gamma must be > 0, got " + str(self.gamma)) else: self.gamma = 1e-3 # eta >-0.5 if self.eta <= -0.5: if self.terminate: raise ValueError("eta must be > -0.5, got " + str(self.eta)) else: self.eta = -0.499 # eta-phi >-0.5 if self.eta - self.phi <= -0.5: if self.terminate: raise ValueError("eta-phi must be >-0.5, got " + str(self.eta - self.phi)) else: self.phi = self.eta + 0.499 if self.beta <= 0: if self.terminate: raise ValueError("beta must be > 0, got " + str(self.beta)) else: self.beta = 1e-3
def __init__(self, **model_parameters): super(Tinker10, self).__init__(**model_parameters) if self.delta_halo not in self.delta_virs: beta_array = np.array([self.params["beta_%s"%d] for d in self.delta_virs]) gamma_array = np.array([self.params["gamma_%s"%d] for d in self.delta_virs]) phi_array = np.array([self.params["phi_%s"%d] for d in self.delta_virs]) eta_array = np.array([self.params["eta_%s"%d] for d in self.delta_virs]) beta_func = _spline(self.delta_virs, beta_array) gamma_func = _spline(self.delta_virs, gamma_array) phi_func = _spline(self.delta_virs, phi_array) eta_func = _spline(self.delta_virs, eta_array) beta_0 = beta_func(self.delta_halo) gamma_0 = gamma_func(self.delta_halo) phi_0 = phi_func(self.delta_halo) eta_0 = eta_func(self.delta_halo) else: beta_0 = self.params['beta_%s'%(int(self.delta_halo))] gamma_0 = self.params['gamma_%s'%(int(self.delta_halo))] phi_0 = self.params['phi_%s'%(int(self.delta_halo))] eta_0 = self.params['eta_%s'%(int(self.delta_halo))] self.beta = beta_0*(1 + min(self.z, self.params["max_z"]))**self.params["beta_exp"] self.phi = phi_0*(1 + min(self.z, self.params["max_z"]))**self.params['phi_exp'] self.eta = eta_0*(1 + min(self.z, self.params["max_z"]))**self.params['eta_exp'] self.gamma = gamma_0*(1 + min(self.z, self.params["max_z"]))**self.params['gamma_exp'] # # The normalisation only works with specific conditions # gamma > 0 if self.gamma <= 0: if self.terminate: raise ValueError("gamma must be > 0, got " + str(self.gamma)) else: self.gamma = 1e-3 # eta >-0.5 if self.eta <= -0.5: if self.terminate: raise ValueError("eta must be > -0.5, got " + str(self.eta)) else: self.eta = -0.499 # eta-phi >-0.5 if self.eta - self.phi <= -0.5: if self.terminate: raise ValueError("eta-phi must be >-0.5, got " + str(self.eta - self.phi)) else: self.phi = self.eta + 0.499 if self.beta <= 0: if self.terminate: raise ValueError("beta must be > 0, got " + str(self.beta)) else: self.beta = 1e-3
def create_flux_cts(cosmo, rsp, arf, z, dN, Tssarr, Lssarr, sample_m, xp, k, directory): global response response = rsp global ancillary ancillary = arf global mydirectory mydirectory = directory s = np.shape(Tssarr) flux_ipt, cts_ipt = np.zeros(s), np.zeros(s) Tip, fluxip, ctrip = create_it_flux_ctr(cosmo, z, \ dN, Tssarr, xp, k) expt = float(xp[5]) n = np.size(z) ni = float(xp[4]) ni_copy = ni i = 0 while i < n: ind = int(dN[i]) M = np.log10(sample_m[i, 0:ind]) T_scatter = 10 ** Tssarr[i, 0:ind] L_scatter = 10 ** Lssarr[i, 0:ind] if dN[i]/ni < ni_copy: ni = int(dN[i]/ni_copy) else: ni = ni_copy T_ip_z = Tip[i, 0:int(ind/ni)] fluxes_ip_z = fluxip[i, 0:int(ind/ni)] ctr_ip_z = ctrip[i, 0:int(ind/ni)] f1 = _spline(T_ip_z, fluxes_ip_z) f2 = _spline(T_ip_z, ctr_ip_z) flux_ipt[i, 0:ind] = f1(T_scatter) * L_scatter / 1e44 ctr_ipt = f2(T_scatter) * L_scatter / 1e44 cts_ipt[i, 0:ind] = ctr_ipt * expt ni = ni_copy i = i+1 return flux_ipt, cts_ipt
def growth_factor_fn(self, zmin=0.0, inverse=False): """ Return the growth factor as a callable function. Parameters ---------- zmin : float, optional The minimum redshift of the function. Default 0.0 inverse: bool, optional Whether to return the inverse relationship [z(g)]. Default False. Returns ------- callable The normalised growth factor as a function of redshift, or redshift as a function of growth factor if ``inverse`` is True. """ if not inverse: return self.growth_factor else: self._zvec = np.arange(zmin, self.params['zmax'], self.params['dz']) gf = self.growth_factor(self._zvec) return _spline(gf[::-1], self._zvec[::-1])
def create_rand_m(dN_bin, z_bin, h): mass_sampled_array = np.zeros(shape = (np.size(z_bin), int(np.max(dN_bin)))) start = time.time() n = np.size(z_bin) i = 0 while i < n: h.update(z=z_bin[i]) icdf = _spline((h.ngtm / h.ngtm[0])[::-1], np.log10(h.m[::-1]), k=3) N = int(dN_bin[i]) x = np.random.random(N) ind = int(dN_bin[i]) mass_sampled_array[i, 0:ind] = 10 ** icdf(x) i = i+1 end = time.time() print("Mass sampled finish", end-start) return mass_sampled_array
def sigma(self, r, order=0): if not isinstance(r, collections.Iterable): r = np.atleast_1d(r) if self.k.max() < 1 / r.min(): warnings.warn("Warning: Maximum r*k less than 1!") # # Need to re-define this because the integral needs to go exactly kr=1 # # or else the function 'jitters' sigma = np.zeros(len(r)) power = _spline(self.k, self.power) for i, rr in enumerate(r): k = np.logspace( np.log10(self.k[0]), min(np.log10(self.k.max()), np.log10(1.0 / rr)), max(100, len(self.k) - i), ) p = power(k) dlnk = np.log(k[1] / k[0]) integ = p * k**(3 + 2 * order) sigma[i] = (0.5 / (np.pi**2)) * intg.simps(integ, dx=dlnk) return np.sqrt(sigma)
def growth_factor_fn(self, zmin=0.0, inverse=False): """ Return the growth factor as a callable function. Parameters ---------- zmin : float, optional The minimum redshift of the function. Default 0.0 inverse: bool, optional Whether to return the inverse relationship [z(g)]. Default False. Returns ------- callable The normalised growth factor as a function of redshift, or redshift as a function of growth factor if ``inverse`` is True. """ if not inverse: return self.growth_factor else: self._zvec = np.arange(zmin, self.params["zmax"], self.params["dz"]) gf = self.growth_factor(self._zvec) return _spline(gf[::-1], self._zvec[::-1])
def _general_case(self, w, x): x = np.atleast_1d(x) xn_vec = np.linspace(0, x.max(), 1000) func = _spline(xn_vec, (xn_vec / (xn_vec**3 + 2))**1.5) g = np.array([func.integral(0, y) for y in x]) return ((x**3.0 + 2.0)**0.5) * (g / x**1.5)
def _prepare_mf(log_mmin, **mf_kwargs): h = hmf.MassFunction(Mmin=log_mmin, **mf_kwargs) mask = h.ngtm > 0 icdf = _spline((h.ngtm[mask] / h.ngtm[0])[::-1], np.log10(h.m[mask][::-1]), k=3) return icdf, h
def _general_case(self, w, x): x = np.atleast_1d(x) xn_vec = np.linspace(0, x.max(), 1000) func = _spline(xn_vec,(xn_vec / (xn_vec ** 3 + 2)) ** 1.5) g = np.array([func.integral(0,y) for y in x]) return ((x ** 3.0 + 2.0) ** 0.5) * (g / x ** 1.5)
def _get_spec( k: np.ndarray, delta_k: np.ndarray, sigma_8=None ) -> Tuple[float, float, float]: """ Calculate nonlinear wavenumber, effective spectral index and curvature of the power spectrum. Parameters ---------- k : array_like Wavenumbers delta_k : array_like Dimensionless power spectrum at `k` sigma_8 : scalar RMS linear density fluctuations in spheres of radius 8 Mpc/h at z=0. Not used any more at all! Returns ------- knl : float Non-linear wavenumber n_eff : float Effective spectral index n_curv : float Curvature of the spectrum """ # Initialize sigma spline def get_log_sigma2(lnr): R = np.exp(lnr) integrand = delta_k * np.exp(-((k * R) ** 2)) return np.log(_simps(integrand, np.log(k))) def get_sigma_abs(lnr): return np.abs(get_log_sigma2(lnr)) res = minimize( get_sigma_abs, x0=[1.0], options={"xatol": np.log(1.1)}, method="Nelder-Mead" ) if not res.success: warnings.warn( f"Could not determine non-linear scale! Failed with error: {res.message}. " f"Continuing with best-fit non-linear scale: r_nl={np.exp(res.x)}, with log_sigma^2 = {res.fun}" ) rnl = np.exp(res.x) knl = 1 / rnl lnr = np.linspace(np.log(0.75 * rnl), np.log(1.25 * rnl), 20) lnsig = [get_log_sigma2(r) for r in lnr] sig_of_r = _spline(lnr, lnsig, k=5) dev1, dev2 = sig_of_r.derivatives(np.log(rnl))[1:3] n_eff = -dev1 - 3.0 n_curv = -dev2 return knl, n_eff, n_curv
def test_mf_true(sample, true): """ Test how close the sample mass function is to the predicted one TODO: Test closeness to n-body mf """ spl = _spline(_np.log(true[:, 0]), _np.log(true[:, 1])) true_spl = _np.exp(spl(sample[:, 0])) err = _np.sqrt(_nanmean(_np.square((true_spl - sample[:, 1]) / true_spl))) return true_spl, err
def _q_convert(self, p, lin_cdf, log_cdf, logm, log_p): lin_icdf = _spline(lin_cdf, logm[:len(lin_cdf)]) # the log-space icdf must be done in double log space. log_icdf = _spline(np.log(-log_cdf)[::-1], logm[-len(log_cdf):][::-1]) tp = lin_cdf[-1] if np.isscalar(p): p = np.array(p) if not log_p: log_pc = np.log(-np.log(np.clip(p[p > tp], None, 1))) lin_pc = np.clip(p[p <= tp], 0, None) else: log_pc = np.log(-np.clip(p[p > np.log(tp)], None, 0)) lin_pc = np.exp(p[p <= np.log(tp)]) if len(log_pc) and len(lin_pc) > 0: return np.concatenate((lin_icdf(lin_pc), log_icdf(log_pc))) elif len(lin_pc) > 0: return lin_icdf(lin_pc) else: return log_icdf(log_pc)
def _q_convert(p, lin_cdf, log_cdf, logm, log_p): lin_icdf = _spline(lin_cdf, logm[:len(lin_cdf)]) # the log-space icdf must be done in double log space. log_icdf = _spline(np.log(-log_cdf)[::-1], logm[-len(log_cdf):][::-1]) tp = lin_cdf[-1] if np.isscalar(p): p = np.array(p) if not log_p: log_pc = np.log(-np.log(np.clip(p[p > tp], None, 1))) lin_pc = np.clip(p[p <= tp], 0, None) else: log_pc = np.log(-np.clip(p[p > np.log(tp)], None, 0)) lin_pc = np.exp(p[p <= np.log(tp)]) if len(log_pc) and len(lin_pc) > 0: return np.concatenate((lin_icdf(lin_pc), log_icdf(log_pc))) elif len(lin_pc) > 0: return lin_icdf(lin_pc) else: return log_icdf(log_pc)
def __init__(self, **model_parameters): super(Tinker08, self).__init__(**model_parameters) if not isinstance(self.mass_definition, md.SphericalOverdensity): raise ValueError( "The Tinker fitting function is a spherical-overdensity function." ) else: delta_halo = self.mass_definition.halo_overdensity_mean( self.z, self.cosmo) if delta_halo not in self.delta_virs: A_array = np.array( [self.params["A_%s" % d] for d in self.delta_virs]) a_array = np.array( [self.params["a_%s" % d] for d in self.delta_virs]) b_array = np.array( [self.params["b_%s" % d] for d in self.delta_virs]) c_array = np.array( [self.params["c_%s" % d] for d in self.delta_virs]) A_func = _spline(self.delta_virs, A_array) a_func = _spline(self.delta_virs, a_array) b_func = _spline(self.delta_virs, b_array) c_func = _spline(self.delta_virs, c_array) A_0 = A_func(delta_halo) a_0 = a_func(delta_halo) b_0 = b_func(delta_halo) c_0 = c_func(delta_halo) else: A_0 = self.params["A_%s" % (int(delta_halo))] a_0 = self.params["a_%s" % (int(delta_halo))] b_0 = self.params["b_%s" % (int(delta_halo))] c_0 = self.params["c_%s" % (int(delta_halo))] self.A = A_0 * (1 + self.z)**(-self.params["A_exp"]) self.a = a_0 * (1 + self.z)**(-self.params["a_exp"]) alpha = 10**(-((0.75 / np.log10(delta_halo / 75.0))**1.2)) self.b = b_0 * (1 + self.z)**(-alpha) self.c = c_0
def projected_corr_gal(r, xir, rlim, rp_out=None): """ Projected correlation function w(r_p). From Beutler 2011, eq 6. To integrate, we perform a substitution y = x - r_p. Parameters ---------- r : float array Array of scales, in [Mpc/h] xir : float array Array of xi(r), unitless """ if rp_out is None: rp_out = r lnr = np.log(r) lnxi = np.log(xir) p = np.zeros_like(rp_out) fit = _spline(r, xir, k=3) # [self.corr_gal > 0] maybe? f_peak = 0.01 a = 0 for i, rp in enumerate(rp_out): if a != 1.3 and i < len(r) - 1: # Get log slope at rp ydiff = (lnxi[i + 1] - lnxi[i]) / (lnr[i + 1] - lnr[i]) # if the slope is flatter than 1.3, it will converge faster, but to make sure, we cut at 1.3 a = max(1.3, -ydiff) theta = _get_theta(a) min_y = theta * f_peak ** 2 * rp # Get the upper limit for this rp ylim = rlim - rp # Set the y vector for this rp y = np.logspace(np.log(min_y), np.log(ylim), 1000, base=np.e) # Integrate integ_corr = fit(y + rp) integrand = (y + rp) * integ_corr / np.sqrt((y + 2 * rp) * y) p[i] = simps(integrand, y) * 2 return p
def _cumulativeNumberDensity(self, z): """Returns N > M (per cubic Mpc). """ h=self.cosmoModel['h'] dndlnM=self.mfunc.get_mass_function(self.cosmoModel, self.M, 1/(1+z)) / np.log(10) #/ h**3 dndM=dndlnM/self.M ngtm=integrate.cumtrapz(dndlnM[::-1], np.log(self.M), initial = 0)[::-1] MUpper=np.arange(np.log(self.M[-1]), np.log(10**18), np.log(self.M[1])-np.log(self.M[0])) extrapolator=_spline(np.log(self.M), np.log(dndlnM), k=1) MF_extr=extrapolator(MUpper) intUpper=integrate.simps(np.exp(MF_extr), dx=MUpper[2] - MUpper[1], even='first') ngtm=ngtm+intUpper return ngtm
def sigma(self, r, order=0): if not isinstance(r, collections.Iterable): r = np.atleast_1d(r) if self.k.max() < 1/r.min(): warnings.warn("Warning: Maximum r*k less than 1!") # # Need to re-define this because the integral needs to go exactly kr=1 # # or else the function 'jitters' sigma = np.zeros(len(r)) power = _spline(self.k, self.power) for i, rr in enumerate(r): k = np.logspace(np.log(self.k[0]), min(self.k.max(),np.log(1.0 / rr)), len(self.k)-i, base=np.e) p = power(k) dlnk = np.log(k[1] / k[0]) integ = p * k ** (3 + 2 * order) sigma[i] = (0.5 / (np.pi ** 2)) * intg.simps(integ, dx=dlnk) return np.sqrt(sigma)
def hmf_integral_gtm(M, dndm, mass_density=False): """ Cumulatively integrate dn/dm. Parameters ---------- M : array_like Array of masses. dndm : array_like Array of dn/dm (corresponding to M) mass_density : bool, `False` Whether to calculate mass density (or number density). Returns ------- ngtm : array_like Cumulative integral of dndm. Examples -------- Using a simple power-law mass function: >>> import numpy as np >>> m = np.logspace(10,18,500) >>> dndm = m**-2 >>> ngtm = hmf_integral_gtm(m,dndm) >>> np.allclose(ngtm,1/m) #1/m is the analytic integral to infinity. True The function always integrates to m=1e18, and extrapolates with a spline if data not provided: >>> m = np.logspace(10,12,500) >>> dndm = m**-2 >>> ngtm = hmf_integral_gtm(m,dndm) >>> np.allclose(ngtm,1/m) #1/m is the analytic integral to infinity. True """ # Eliminate NaN's m = M[np.logical_not(np.isnan(dndm))] dndm = dndm[np.logical_not(np.isnan(dndm))] dndlnm = m * dndm if len(m) < 4: raise NaNException("There are too few real numbers in dndm: len(dndm) = %s, #NaN's = %s" % (len(M), len(M) - len(dndm))) # Calculate the mass function (and its integral) from the highest M up to 10**18 if m[-1] < m[0] * 10 ** 18 / m[3]: m_upper = np.arange(np.log(m[-1]), np.log(10 ** 18), np.log(m[1]) - np.log(m[0])) mf_func = _spline(np.log(m), np.log(dndlnm), k=1) mf = mf_func(m_upper) if not mass_density: int_upper = intg.simps(np.exp(mf), dx=m_upper[2] - m_upper[1], even='first') else: int_upper = intg.simps(np.exp(m_upper + mf), dx=m_upper[2] - m_upper[1], even='first') else: int_upper = 0 # Calculate the cumulative integral (backwards) of [m*]dndlnm if not mass_density: ngtm = np.concatenate((intg.cumtrapz(dndlnm[::-1], dx=np.log(m[1]) - np.log(m[0]))[::-1], np.zeros(1))) else: ngtm = np.concatenate((intg.cumtrapz(m[::-1] * dndlnm[::-1], dx=np.log(m[1]) - np.log(m[0]))[::-1], np.zeros(1))) return (ngtm + int_upper)
def _get_spec(k, delta_k, sigma_8): """ Calculate nonlinear wavenumber, effective spectral index and curvature of the power spectrum. Parameters ---------- k : array_like Wavenumbers delta_k : array_like Dimensionless power spectrum at `k` sigma_8 : scalar RMS linear density fluctuations in spheres of radius 8 Mpc/h at z=0. Returns ------- rknl : float Non-linear wavenumber rneff : float Effective spectral index rncur : float Curvature of the spectrum """ # Initialize sigma spline if 0.6 < sigma_8 > 1.0: lnr = np.linspace(np.log(0.1), np.log(10.0), 500) lnsig = np.empty(500) else: # weird sigma_8 means we need a different range of r to go through 0. lnsig_old = None for r in [0.00001, 0.0001, 0.001, 0.01, 0.1, 1.0, 10.0, 100.0, 1000.0]: integrand = delta_k * np.exp(-((k * r) ** 2)) sigma2 = _simps(integrand, np.log(k)) lnsig1 = np.log(sigma2) if lnsig1 < 0: try: lnsig1 = float(lnsig_old) except TypeError: warnings.warn( "Lowest R not low enough in _get_spec. ln(sig) starts below 0: ", lnsig1, ) break lnsig_old = copy.copy(lnsig1) lnr = np.linspace(np.log(0.1 * r), np.log(r), 250) lnsig = np.empty(250) for i, r in enumerate(lnr): R = np.exp(r) integrand = delta_k * np.exp(-((k * R) ** 2)) sigma2 = _simps(integrand, np.log(k)) lnsig[i] = np.log(sigma2) r_of_sig = _spline(lnsig[::-1], lnr[::-1], k=5) rknl = 1.0 / np.exp(r_of_sig(0.0)) sig_of_r = _spline(lnr, lnsig, k=5) try: dev1, dev2 = sig_of_r.derivatives(np.log(1.0 / rknl))[1:3] except Exception: warnings.warn( "Requiring extra iterations to find derivatives of sigma at 1/rknl " "(this often happens at high redshift)." ) lnr = np.linspace(np.log(0.2 / rknl), np.log(5 / rknl), 100) lnsig = np.empty(100) for i, r in enumerate(lnr): R = np.exp(r) integrand = delta_k * np.exp(-((k * R) ** 2)) sigma2 = _simps(integrand, np.log(k)) lnsig[i] = np.log(sigma2) lnr = lnr[np.logical_not(np.isinf(lnsig))] lnsig = lnsig[np.logical_not(np.isinf(lnsig))] if len(lnr) < 2: raise Exception("Lots of things went wrong in halofit") sig_of_r = _spline(lnr, lnsig, k=5) dev1, dev2 = sig_of_r.derivatives(np.log(1.0 / rknl))[1:3] rneff = -dev1 - 3.0 rncur = -dev2 return rknl, rneff, rncur
def xi(r): s = _spline(self.r,self.corr_mm) return s(r)
def dlnss_dlnr(self, r): a3 = self.a3(r) sigma = self.sigma(a3) power = np.exp(_spline(self.lnk, self.lnp)(np.log(1 / a3))) return -power / (2 * np.pi ** 2 * sigma ** 2 * a3 ** 3)
def dlnss_dlnr(self, r): sigma = self.sigma(r) power = _spline(self.k, self.power)(1 / r) return -power / (2 * np.pi ** 2 * sigma ** 2 * r ** 3)
def hmf_integral_gtm(M, dndm, mass_density=False): """ Cumulatively integrate dn/dm. Parameters ---------- M : array_like Array of masses. dndm : array_like Array of dn/dm (corresponding to M) mass_density : bool, `False` Whether to calculate mass density (or number density). Returns ------- ngtm : array_like Cumulative integral of dndm. Examples -------- Using a simple power-law mass function: >>> import numpy as np >>> m = np.logspace(10,18,500) >>> dndm = m**-2 >>> ngtm = hmf_integral_gtm(m,dndm) >>> np.allclose(ngtm,1/m) #1/m is the analytic integral to infinity. True The function always integrates to m=1e18, and extrapolates with a spline if data not provided: >>> m = np.logspace(10,12,500) >>> dndm = m**-2 >>> ngtm = hmf_integral_gtm(m,dndm) >>> np.allclose(ngtm,1/m) #1/m is the analytic integral to infinity. True """ # Eliminate NaN's m = M[np.logical_not(np.isnan(dndm))] dndm = dndm[np.logical_not(np.isnan(dndm))] dndlnm = m * dndm if len(m) < 4: raise NaNException( "There are too few real numbers in dndm: len(dndm) = %s, #NaN's = %s" % (len(M), len(M) - len(dndm)) ) # Calculate the mass function (and its integral) from the highest M up to 10**18 if m[-1] < m[0] * 10 ** 18 / m[3]: m_upper = np.arange( np.log(m[-1]), np.log(10 ** 18), np.log(m[1]) - np.log(m[0]) ) mf_func = _spline(np.log(m), np.log(dndlnm), k=1) mf = mf_func(m_upper) if not mass_density: int_upper = intg.simps(np.exp(mf), dx=m_upper[2] - m_upper[1], even="first") else: int_upper = intg.simps( np.exp(m_upper + mf), dx=m_upper[2] - m_upper[1], even="first" ) else: int_upper = 0 # Calculate the cumulative integral (backwards) of [m*]dndlnm if not mass_density: ngtm = np.concatenate( ( intg.cumtrapz(dndlnm[::-1], dx=np.log(m[1]) - np.log(m[0]))[::-1], np.zeros(1), ) ) else: ngtm = np.concatenate( ( intg.cumtrapz(m[::-1] * dndlnm[::-1], dx=np.log(m[1]) - np.log(m[0]))[ ::-1 ], np.zeros(1), ) ) return ngtm + int_upper
def fsigma(self, rad): # https://arxiv.org/pdf/0803.2706.pdf """ this is the function giving f(sigma) All the paprameters mentioned here are taken for \Delta = 200 z is the redshift and redshift evolution has to be considered here It has to be noted that values provided in Tinker 2008 paper are wrt to mean background density. If we want to calculate the best fit parameter values wrt to critical background density, we have to change the corresponding delta_halo value and interpolate the values for the corresponding delta_halo values. """ z = self.z a = { # -- A "A_200": 1.858659e-01, "A_300": 1.995973e-01, "A_400": 2.115659e-01, "A_600": 2.184113e-01, "A_800": 2.480968e-01, "A_1200": 2.546053e-01, "A_1600": 2.600000e-01, "A_2400": 2.600000e-01, "A_3200": 2.600000e-01, # -- a "a_200": 1.466904, "a_300": 1.521782, "a_400": 1.559186, "a_600": 1.614585, "a_800": 1.869936, "a_1200": 2.128056, "a_1600": 2.301275, "a_2400": 2.529241, "a_3200": 2.661983, # --- b "b_200": 2.571104, "b_300": 2.254217, "b_400": 2.048674, "b_600": 1.869559, "b_800": 1.588649, "b_1200": 1.507134, "b_1600": 1.464374, "b_2400": 1.436827, "b_3200": 1.405210, # --- c "c_200": 1.193958, "c_300": 1.270316, "c_400": 1.335191, "c_600": 1.446266, "c_800": 1.581345, "c_1200": 1.795050, "c_1600": 1.965613, "c_2400": 2.237466, "c_3200": 2.439729 } A_exp = -0.14 a_exp = 0.06 delta_virs = np.array( [200, 300, 400, 600, 800, 1200, 1600, 2400, 3200]) dhalo = self.delta_halo() if dhalo not in delta_virs: A_array = np.array([a["A_%s" % d] for d in delta_virs]) a_array = np.array([a["a_%s" % d] for d in delta_virs]) b_array = np.array([a["b_%s" % d] for d in delta_virs]) c_array = np.array([a["c_%s" % d] for d in delta_virs]) A_intfunc = _spline(delta_virs, A_array) a_intfunc = _spline(delta_virs, a_array) b_intfunc = _spline(delta_virs, b_array) c_intfunc = _spline(delta_virs, c_array) A_0 = A_intfunc(dhalo) a_0 = a_intfunc(dhalo) b_0 = b_intfunc(dhalo) c_0 = c_intfunc(dhalo) else: A_0 = a["A_%s" % (int(dhalo))] a_0 = a["a_%s" % (int(dhalo))] b_0 = a["b_%s" % (int(dhalo))] c_0 = a["c_%s" % (int(dhalo))] s = self.sigma(rad) A = A_0 * (1 + z)**A_exp a = a_0 * (1 + z)**a_exp alpha = 10**(-(0.75 / np.log10(dhalo / 75.))**1.2) b = b_0 * (1 + z)**alpha return A * ((s / b)**-a + 1) * np.exp(-c_0 / s**2)
def _prepare_mf(log_mmin, **mf_kwargs): h = hmf.MassFunction(Mmin=log_mmin, **mf_kwargs) mask = h.ngtm>0 icdf = _spline((h.ngtm[mask] / h.ngtm[0])[::-1], np.log10(h.m[mask][::-1]), k=3) return icdf, h
def dlnss_dlnr(self, r): a3 = self.a3(r) sigma = self.sigma(a3) power = _spline(self.k, self.power)(1 / a3) return -power / (2 * np.pi ** 2 * sigma ** 2 * a3 ** 3)
def dlnss_dlnr(self, r): a3 = self.a3(r) sigma = self.sigma(a3) power = _spline(self.k, self.power)(1 / a3) return -power / (2 * np.pi**2 * sigma**2 * a3**3)
def _get_spec(k, delta_k, sigma_8): """ Calculate nonlinear wavenumber, effective spectral index and curvature of the power spectrum. Parameters ---------- k : array_like Wavenumbers delta_k : array_like Dimensionless power spectrum at `k` sigma_8 : scalar RMS linear density fluctuations in spheres of radius 8 Mpc/h at z=0. Returns ------- rknl : float Non-linear wavenumber rneff : float Effective spectral index rncur : float Curvature of the spectrum """ ## Initialize sigma spline if sigma_8 < 1.0 and sigma_8 > 0.6: lnr = np.linspace(np.log(0.1), np.log(10.0), 500) lnsig = np.empty(500) for i, r in enumerate(lnr): R = np.exp(r) integrand = delta_k * np.exp(-(k * R)**2) sigma2 = _simps(integrand, np.log(k)) lnsig[i] = np.log(sigma2) else: ## weird sigma_8 means we need a different range of r to go through 0. for r in [0.00001, 0.0001, 0.001, 0.01, 0.1, 1.0, 10.0, 100.0, 1000.0]: integrand = delta_k * np.exp(-(k * r)**2) sigma2 = _simps(integrand, np.log(k)) lnsig1 = np.log(sigma2) if lnsig1 < 0: try: lnsig1 = lnsig_old except: print( "WARNING: LOWEST R NOT LOW ENOUGH IN _GET_SPEC. ln(sig) starts below 0: ", lnsig1) break lnsig_old = (lnsig1).copy() lnr = np.linspace(np.log(0.1 * r), np.log(r), 250) lnsig = np.empty(250) for i, r in enumerate(lnr): R = np.exp(r) integrand = delta_k * np.exp(-(k * R)**2) sigma2 = _simps(integrand, np.log(k)) lnsig[i] = np.log(sigma2) r_of_sig = _spline(lnsig[::-1], lnr[::-1], k=5) rknl = 1.0 / np.exp(r_of_sig(0.0)) sig_of_r = _spline(lnr, lnsig, k=5) try: dev1, dev2 = sig_of_r.derivatives(np.log(1.0 / rknl))[1:3] except Exception as e: print("WARNING: ", e) lnr = np.linspace(np.log(0.2 / rknl), np.log(5 / rknl), 100) lnsig = np.empty(100) for i, r in enumerate(lnr): R = np.exp(r) integrand = delta_k * np.exp(-(k * R)**2) sigma2 = _simps(integrand, np.log(k)) lnsig[i] = np.log(sigma2) lnr = lnr[np.logical_not(np.isinf(lnsig))] lnsig = lnsig[np.logical_not(np.isinf(lnsig))] if len(lnr) < 2: raise Exception("Lots of things went wrong in halofit") sig_of_r = _spline(lnr, lnsig, k=5) dev1, dev2 = sig_of_r.derivatives(np.log(1.0 / rknl))[1:3] rneff = -dev1 - 3.0 rncur = -dev2 return rknl, rneff, rncur
def _get_spec(k, delta_k, sigma_8): """ Calculate nonlinear wavenumber, effective spectral index and curvature of the power spectrum. Parameters ---------- k : array_like Wavenumbers delta_k : array_like Dimensionless power spectrum at `k` sigma_8 : scalar RMS linear density fluctuations in spheres of radius 8 Mpc/h at z=0. Returns ------- rknl : float Non-linear wavenumber rneff : float Effective spectral index rncur : float Curvature of the spectrum """ # Initialize sigma spline if sigma_8 < 1.0 and sigma_8 > 0.6: lnr = np.linspace(np.log(0.1), np.log(10.0), 500) lnsig = np.empty(500) for i, r in enumerate(lnr): R = np.exp(r) integrand = delta_k * np.exp(-(k * R) ** 2) sigma2 = _simps(integrand, np.log(k)) lnsig[i] = np.log(sigma2) else: # # weird sigma_8 means we need a different range of r to go through 0. for r in [0.00001, 0.0001, 0.001, 0.01, 0.1, 1.0, 10.0, 100.0, 1000.0]: integrand = delta_k * np.exp(-(k * r) ** 2) sigma2 = _simps(integrand, np.log(k)) lnsig1 = np.log(sigma2) if lnsig1 < 0: try: lnsig1 = lnsig_old except: print "WARNING: LOWEST R NOT LOW ENOUGH IN _GET_SPEC. ln(sig) starts below 0: ", lnsig1 break lnsig_old = copy.copy(lnsig1) lnr = np.linspace(np.log(0.1 * r), np.log(r), 250) lnsig = np.empty(250) for i, r in enumerate(lnr): R = np.exp(r) integrand = delta_k * np.exp(-(k * R) ** 2) sigma2 = _simps(integrand, np.log(k)) lnsig[i] = np.log(sigma2) r_of_sig = _spline(lnsig[::-1], lnr[::-1], k=5) rknl = 1.0 / np.exp(r_of_sig(0.0)) sig_of_r = _spline(lnr, lnsig, k=5) try: dev1, dev2 = sig_of_r.derivatives(np.log(1.0 / rknl))[1:3] except Exception as e: print "HALOFIT WARNING: Requiring extra iterations to find derivatives of sigma at 1/rknl (this often happens at high redshift)." lnr = np.linspace(np.log(0.2 / rknl), np.log(5 / rknl), 100) lnsig = np.empty(100) for i, r in enumerate(lnr): R = np.exp(r) integrand = delta_k * np.exp(-(k * R) ** 2) sigma2 = _simps(integrand, np.log(k)) lnsig[i] = np.log(sigma2) lnr = lnr[np.logical_not(np.isinf(lnsig))] lnsig = lnsig[np.logical_not(np.isinf(lnsig))] if len(lnr) < 2: raise Exception("Lots of things went wrong in halofit") sig_of_r = _spline(lnr, lnsig, k=5) dev1, dev2 = sig_of_r.derivatives(np.log(1.0 / rknl))[1:3] rneff = -dev1 - 3.0 rncur = -dev2 return rknl, rneff, rncur
def r_a3(self, rmin, rmax): r = np.logspace(np.log(rmin), np.log(rmax), 200, base=np.e) a3 = self.a3(r) s = _spline(a3, r) return s
def update(self, H0, Om0, Ob0, sigma8, ns): """Recalculate cluster counts for the updated cosmological parameters given. Args: H0 (:obj:`float`): The Hubble constant at redshift 0, in km/s/Mpc. Om0 (:obj:`float`): Dimensionless total (dark + baryonic) matter density parameter at redshift 0. Ob0 (:obj:`float`): Dimensionless baryon matter density parameter at redshift 0. sigma8 (:obj:`float`): Defines the amplitude of the matter power spectrum. ns (:obj:`float`): Scalar spectral index of matter power spectrum. """ self._get_new_cosmo(H0, Om0, Ob0, sigma8, ns) self._doClusterCount() # For quick Q, fRel calc (these are in MockSurvey rather than SelFn as used by drawSample) self.theta500Splines=[] self.fRelSplines=[] self.Ez=ccl.h_over_h0(self.cosmoModel,self.a) self.Ez2=np.power(self.Ez, 2) self.DAz=ccl.angular_diameter_distance(self.cosmoModel,self.a) self.criticalDensity=ccl.physical_constants.RHO_CRITICAL*(self.Ez*self.cosmoModel['h'])**2 for k in range(len(self.z)): # NOTE: Q fit uses theta500, as does fRel (hardcoded M500 - T relation in there) # This bit here may not be strictly necessary, since we don't need to map on to binning if self.delta != 500 or self.rhoType != "critical": interpLim_minLog10M500c=np.log10(self.mdef.translate_mass(self.cosmoModel, self.M.min(), self.a[k], self._M500cDef)) interpLim_maxLog10M500c=np.log10(self.mdef.translate_mass(self.cosmoModel, self.M.max(), self.a[k], self._M500cDef)) else: interpLim_minLog10M500c=self.log10M.min() interpLim_maxLog10M500c=self.log10M.max() zk=self.z[k] interpPoints=100 fitM500s=np.power(10, np.linspace(interpLim_minLog10M500c, interpLim_maxLog10M500c, interpPoints)) fitTheta500s=np.zeros(len(fitM500s)) fitFRels=np.zeros(len(fitM500s)) criticalDensity=self.criticalDensity[k] DA=self.DAz[k] Ez=self.Ez[k] R500Mpc=np.power((3*fitM500s)/(4*np.pi*500*criticalDensity), 1.0/3.0) fitTheta500s=np.degrees(np.arctan(R500Mpc/DA))*60.0 fitFRels=signals.calcFRel(zk, fitM500s, Ez) tckLog10MToTheta500=interpolate.splrep(np.log10(fitM500s), fitTheta500s) tckLog10MToFRel=interpolate.splrep(np.log10(fitM500s), fitFRels) self.theta500Splines.append(tckLog10MToTheta500) self.fRelSplines.append(tckLog10MToFRel) # Stuff to enable us to draw mock samples (see drawSample) # Interpolators here need to be updated each time we change cosmology if self.enableDrawSample == True: # For drawing from overall z distribution zSum=self.clusterCount.sum(axis = 1) pz=np.cumsum(zSum)/self.numClusters self.zRoller=_spline(pz, self.z, k = 3) # For drawing from each log10M distribution at each point on z grid # And quick fRel, Q calc using interpolation # And we may as well have E(z), DA on the z grid also self.log10MRollers=[] for i in range(len(self.z)): ngtm=self._cumulativeNumberDensity(self.z[i]) mask=ngtm > 0 self.log10MRollers.append(_spline((ngtm[mask] / ngtm[0])[::-1], np.log10(self.M[mask][::-1]), k=3))
def dlnr_dlnm(self, r): a3 = self.a3(r) xi = r / a3 drda = _spline(a3, r).derivative()(a3) return xi / 3 / drda
def __init__(self, **model_parameters): super().__init__(**model_parameters) if self.mass_definition is not None: if not isinstance(self.mass_definition, md.SphericalOverdensity): raise ValueError( "The Tinker10 fitting function is a spherical-overdensity function." ) else: delta_halo = self.mass_definition.halo_overdensity_mean( self.z, self.cosmo) else: delta_halo = 200 self.delta_halo = delta_halo if int(delta_halo) not in self.delta_virs: beta_array = np.array( [self.params["beta_%s" % d] for d in self.delta_virs]) gamma_array = np.array( [self.params["gamma_%s" % d] for d in self.delta_virs]) phi_array = np.array( [self.params["phi_%s" % d] for d in self.delta_virs]) eta_array = np.array( [self.params["eta_%s" % d] for d in self.delta_virs]) beta_func = _spline(self.delta_virs, beta_array) gamma_func = _spline(self.delta_virs, gamma_array) phi_func = _spline(self.delta_virs, phi_array) eta_func = _spline(self.delta_virs, eta_array) beta_0 = beta_func(delta_halo) gamma_0 = gamma_func(delta_halo) phi_0 = phi_func(delta_halo) eta_0 = eta_func(delta_halo) else: beta_0 = self.params["beta_%s" % (int(delta_halo))] gamma_0 = self.params["gamma_%s" % (int(delta_halo))] phi_0 = self.params["phi_%s" % (int(delta_halo))] eta_0 = self.params["eta_%s" % (int(delta_halo))] self.beta = ( beta_0 * (1 + min(self.z, self.params["max_z"]))**self.params["beta_exp"]) self.phi = ( phi_0 * (1 + min(self.z, self.params["max_z"]))**self.params["phi_exp"]) self.eta = ( eta_0 * (1 + min(self.z, self.params["max_z"]))**self.params["eta_exp"]) self.gamma = ( gamma_0 * (1 + min(self.z, self.params["max_z"]))**self.params["gamma_exp"]) # # The normalisation only works with specific conditions # gamma > 0 if self.gamma <= 0: if self.terminate: raise ValueError("gamma must be > 0, got " + str(self.gamma)) else: self.gamma = 1e-3 # eta >-0.5 if self.eta <= -0.5: if self.terminate: raise ValueError("eta must be > -0.5, got " + str(self.eta)) else: self.eta = -0.499 # eta-phi >-0.5 if self.eta - self.phi <= -0.5: if self.terminate: raise ValueError("eta-phi must be >-0.5, got " + str(self.eta - self.phi)) else: self.phi = self.eta + 0.499 if self.beta <= 0: if self.terminate: raise ValueError("beta must be > 0, got " + str(self.beta)) else: self.beta = 1e-3