Esempio n. 1
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.
        """
        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
Esempio n. 2
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
Esempio n. 3
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
Esempio n. 5
0
    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
Esempio n. 6
0
    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
Esempio n. 7
0
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
Esempio n. 8
0
    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])
Esempio n. 9
0
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
Esempio n. 10
0
    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)
Esempio n. 13
0
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
Esempio n. 14
0
    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)
Esempio n. 15
0
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
Esempio n. 16
0
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
Esempio n. 17
0
    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)
Esempio n. 18
0
    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)
Esempio n. 19
0
    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
Esempio n. 20
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
Esempio n. 21
0
    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
Esempio n. 22
0
File: filters.py Progetto: gjsun/hmf
    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)
Esempio n. 23
0
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)
Esempio n. 24
0
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
Esempio n. 25
0
 def xi(r):
     s = _spline(self.r,self.corr_mm)
     return s(r)
Esempio n. 26
0
 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)
Esempio n. 27
0
 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)
Esempio n. 28
0
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)
Esempio n. 30
0
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
Esempio n. 31
0
 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)
Esempio n. 32
0
 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)
Esempio n. 33
0
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
Esempio n. 34
0
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
Esempio n. 35
0
 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
Esempio n. 36
0
    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))
Esempio n. 37
0
 def dlnr_dlnm(self, r):
     a3 = self.a3(r)
     xi = r / a3
     drda = _spline(a3, r).derivative()(a3)
     return xi / 3 / drda
Esempio n. 38
0
    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