Пример #1
0
def euclid_nzs(num_dens):
    '''
    euclid num density = 30 arcmin^-2 = 108,000 deg^-2
    In steradians: A steradian is (180/π)^2 square degrees, or 3282.8 deg^2
    So Euclid number density 
    = 108,000 * 3282.8 = 354,543,086 galaxies per steradian
    
    '''
    nz = 1000
    # zmin , zmax = 0., 3.
    # z = np.linspace(zmin, zmax, nz)
    pz = ccl.PhotoZGaussian(sigma_z0=0.05)
    dNdz_true = ccl.dNdzSmail(alpha=1.3, beta=1.5, z0=0.65)
    dNdz_obs = ccl.dNdz_tomog(z=z,
                              zmin=zmin,
                              zmax=zmax,
                              pz_func=pz,
                              dNdz_func=dNdz_true)
    # scale to the given number density
    dNdz_obs = dNdz_obs / dNdz_obs.sum() * num_dens
    nzs = []
    for i in range(nbins):
        # calculate the number density of galaxies per steradian per bin
        zmin_i, zmax_i = i * (2. / nbins), (i + 1) * (2. / nbins)
        mask = (z > zmin_i) & (z < zmax_i)
        nzs.append(dNdz_obs[mask].sum())

    return nzs
Пример #2
0
def euclid_nzs(num_dens):
    """
    Calculate the (AVERAGE?!) number density of sub-sample galaxies per redshift bin

    num_dens = 354,543,086 galaxies per steradian
    
    Euclid num density = 30 arcmin^-2 = 108,000 deg^-2     (arcmin^2 to deg^2 = 60^2)
    In steradians: A steradian is (180/π)^2 square degrees, or 3282.8 deg^2
    So Euclid number density 
    = 108,000 * 3282.8 = 354,543,086 galaxies per steradian

    Returns
        nzs --- list --- (AVERAGE?!) number density of galaxies in redshift bin
    
    """

    # zmin , zmax = 0., 3.
    # z = np.linspace(zmin, zmax, nz)
    pz = ccl.PhotoZGaussian(sigma_z0=0.05)
    dNdz_true = ccl.dNdzSmail(alpha=1.3, beta=1.5, z0=0.65)
    dNdz_obs = ccl.dNdz_tomog(z=z,
                              zmin=zmin,
                              zmax=zmax,
                              pz_func=pz,
                              dNdz_func=dNdz_true)
    # scale to the given number density of 30 per arcmin squared
    dNdz_obs = dNdz_obs / dNdz_obs.sum() * num_dens
    nzs = []
    for i in range(nbins):
        # calculate the number density of galaxies per steradian per bin
        zmin_i, zmax_i = i * (2. / nbins), (i + 1) * (2. / nbins)
        mask = (z > zmin_i) & (z < zmax_i)
        nzs.append(dNdz_obs[mask].sum())

    return nzs
def euclid_nzs(num_dens):
    """
    Calculate the (AVERAGE?!) number density of sub-sample galaxies per redshift bin

    num_dens = 354,543,086 galaxies per steradian
    
    Euclid num density = 30 arcmin^-2 = 108,000 deg^-2     (arcmin^2 to deg^2 = 60^2)
    In steradians: A steradian is (180/π)^2 square degrees, or 3282.8 deg^2
    So Euclid number density 
    = 108,000 * 3282.8 = 354,543,086 galaxies per steradian

    Returns
        nzs --- list --- (AVERAGE?!) number density of galaxies in redshift bin
    
    """

    # integrate over whole z range and
    # scale to the given number density of 30 per arcmin squared 
    dNdz_obs = ccl.dNdz_tomog(z=z, zmin=zmin, zmax=zmax, pz_func=pz, dNdz_func = dNdz_true)
    dNdz_obs = dNdz_obs/dNdz_obs.sum() * num_dens
    nzs = []
    for i in range(nbins):
        # calculate the number density of galaxies per steradian per bin
        zmin_i, zmax_i = i*(2./nbins), (i+1)*(2./nbins)
        mask = (z>zmin_i)&(z<zmax_i)
        nzs.append(dNdz_obs[mask].sum())

    return nzs
Пример #4
0
def euclid_ccl(Omega_c, sigma8=0.83):
    """
    Generate C_ell as function of ell for a given Omega_c and Sigma8

    Inputs
        Omega_c -- float: CDM density 
        Sigma_8 -- float: sigma_8

    Assumed global variables
        z -- np.array: samples of z
        ells -- np.array: samples of ell
        dNdz_true -- ccl.dNdzSmail: dNdz distribution
        pz -- ccl.PhotoZGaussian: PhotoZ error
        nbins -- the amount of tomographic redshift bins

    Outputs
        Cls -- np.array, shape (nbins*(nbins-1)/2 + nbins, len(ell)): 
                Cross/Auto correlation shear spectra for the tomographic bins
        dNdzs -- np.array, shape (nbins,len(z):
                dNdz per redshift bin, for all redshifts

    """

    cosmo_fid = ccl.Cosmology(Omega_c=Omega_c,
                              Omega_b=0.045,
                              h=0.71,
                              sigma8=sigma8,
                              n_s=0.963)

    dNdzs = np.zeros((nbins, z.size))
    shears = []

    for i in range(nbins):
        # edges of 1 equal width redshift bins, between 0 and 2
        zmin, zmax = i * (2. / nbins), (i + 1) * (2. / nbins)
        # generate dNdz per bin
        dNdzs[i, :] = ccl.dNdz_tomog(z=z,
                                     zmin=zmin,
                                     zmax=zmax,
                                     pz_func=pz,
                                     dNdz_func=dNdz_true)
        # calculate the shear per bin
        gal_shapes = ccl.WeakLensingTracer(cosmo_fid, dndz=(z, dNdzs[i, :]))
        shears.append(gal_shapes)

    print('Shears calculated, calculating power spectra now...')
    # calculate nbin*(nbin+1)/2 = 1 spectra from the shears
    Cls = []
    for i in range(nbins):
        for j in range(0, i + 1):
            Cls.append(ccl.angular_cl(cosmo_fid, shears[i], shears[j], ells))

    return np.array(Cls), dNdzs
Пример #5
0
def euclid_ccl(Omega_c, sigma8):
    """
    Generate C_ell as function of ell for a given Omega_c and Sigma8
    Assumes a redshift distribution given by
        z^alpha * exp(z/z0)^beta
        with alpha=1.3, beta = 1.5 and z0 = 0.65

    Assumes photo-z error is Gaussian with a bias is 0.05(1+z)
    """

    cosmo_fid = ccl.Cosmology(Omega_c=Omega_c,
                              Omega_b=0.045,
                              h=0.71,
                              sigma8=sigma8,
                              n_s=0.963)

    ell = np.logspace(np.log10(100), np.log10(6000), 10)

    pz = ccl.PhotoZGaussian(sigma_z0=0.05)
    dNdz_true = ccl.dNdzSmail(alpha=1.3, beta=1.5, z0=0.65)

    dNdzs = np.zeros((nbins, z.size))
    shears = []

    for i in range(nbins):
        # edges of nbins equal width redshift bins, between 0 and 2
        zmin, zmax = i * (2. / nbins), (i + 1) * (2. / nbins)
        # generate dNdz per bin
        dNdzs[i, :] = ccl.dNdz_tomog(z=z,
                                     zmin=zmin,
                                     zmax=zmax,
                                     pz_func=pz,
                                     dNdz_func=dNdz_true)
        # calculate the shear per bin
        gal_shapes = ccl.WeakLensingTracer(cosmo_fid, dndz=(z, dNdzs[i, :]))
        shears.append(gal_shapes)

    # calculate nbin*(nbin+1)/2 spectra from the shears
    Cls = []
    bin_indices = [
    ]  # list of length nbin*(nbin+1)/2 containing tuples with the indices of the bins
    for i in range(nbins):
        for j in range(0, i + 1):
            bin_indices.append((i, j))
            Cls.append(ccl.angular_cl(cosmo_fid, shears[i], shears[j], ell))

    return ell, np.array(Cls), dNdzs, bin_indices
def euclid_ccl(Omega_c, Omega_b=0.045, sigma8=0.83, n_s=0.963, h=0.71, mps='halofit'):
    """
    Generate C_ell as function of ell for a given Omega_c and Sigma8

    Inputs
        Omega_c -- float: CDM density 
        Sigma_8 -- float: sigma_8
        mps     -- string: model to use for matter power spectrum

    Assumed global variables
        z -- np.array: samples of z
        ells -- np.array: samples of ell
        dNdz_true -- ccl.dNdzSmail: dNdz distribution
        pz -- ccl.PhotoZGaussian: PhotoZ error
        nbins -- the amount of tomographic redshift bins

    Outputs
        Cls -- np.array, shape (nbins*(nbins-1)/2 + nbins, len(ell)): 
                Cross/Auto correlation shear spectra for the tomographic bins
        dNdzs -- np.array, shape (nbins,len(z):
                dNdz per redshift bin, for all redshifts

    """

    cosmo_fid = ccl.Cosmology(Omega_c=Omega_c, Omega_b=Omega_b, h=h, sigma8=sigma8, n_s=n_s, matter_power_spectrum=mps)

    dNdzs = np.zeros((nbins, z.size))
    shears = []
    
    for i in range(nbins):
        # edges of 2 redshift bins
        zmin_b, zmax_b = zbins[i]
        print (f'Redshift bin {i}: {zmin_b} - {zmax_b}')
        # generate dNdz per bin
        dNdzs[i,:] = ccl.dNdz_tomog(z=z, zmin=zmin_b, zmax=zmax_b, pz_func=pz, dNdz_func = dNdz_true)
        # calculate the shear per bin
        gal_shapes = ccl.WeakLensingTracer(cosmo_fid, dndz=(z, dNdzs[i,:]))
        shears.append(gal_shapes)
        
    # calculate nbin*(nbin+1)/2 = 3 spectra from the shears
    Cls = []
    for i in range(nbins):
        for j in range(0,i+1):
            Cls.append(ccl.angular_cl(cosmo_fid, shears[i], shears[j], ells))
     
    return np.array(Cls), dNdzs
Пример #7
0
def euclid_nzs(num_dens):
    '''
    Calculate integrated number density per bin, scale to given num_dens

    Euclid num density = 30 arcmin^-2
    '''
    nz = 1000
    zmin , zmax = 0., 3.
    z = np.linspace(zmin, zmax,nz)
    pz = ccl.PhotoZGaussian(sigma_z0=0.05)
    dNdz_true = ccl.dNdzSmail(alpha = 1.3, beta = 1.5, z0=0.65)
    dNdz_obs = ccl.dNdz_tomog(z=z, zmin=zmin, zmax=zmax, pz_func=pz, dNdz_func = dNdz_true)
    # scale to the given number density
    dNdz_obs = dNdz_obs*num_dens/dNdz_obs.sum()
    nzs = []
    for i in range(10):
        zmin_i, zmax_i = i*.2 , (i+1)*.2
        mask = (z>zmin_i)&(z<zmax_i)
        nzs.append(dNdz_obs[mask].sum()) #*num_dens)
     
    return nzs
Пример #8
0
def check_lsst_specs(cosmo):
    """
    Check that lsst_specs functions can be run.
    """
    # Types of scale factor input (scalar, list, array)
    a_scl = 0.5
    a_lst = [0.2, 0.4, 0.6, 0.8, 1.]
    a_arr = np.linspace(0.2, 1., 5)
    
    # Types of redshift input
    z_scl = 0.5
    z_lst = [0., 0.5, 1., 1.5, 2.]
    z_arr = np.array(z_lst)
    
    # p(z) function for dNdz_tomog
    def pz1(z_ph, z_s, args):
        return np.exp(- (z_ph - z_s)**2. / 2.)
    
    # Lambda function p(z) function for dNdz_tomog
    pz2 = lambda z_ph, z_s, args: np.exp(-(z_ph - z_s)**2. / 2.)
    
    # PhotoZFunction classes
    PZ1 = ccl.PhotoZFunction(pz1)
    PZ2 = ccl.PhotoZFunction(pz2)
    
    # bias_clustering
    assert_( all_finite(ccl.bias_clustering(cosmo, a_scl)) )
    assert_( all_finite(ccl.bias_clustering(cosmo, a_lst)) )
    assert_( all_finite(ccl.bias_clustering(cosmo, a_arr)) )
    
    # dNdz_tomog, PhotoZFunction
    # sigmaz_clustering
    assert_( all_finite(ccl.sigmaz_clustering(z_scl)) )
    assert_( all_finite(ccl.sigmaz_clustering(z_lst)) )
    assert_( all_finite(ccl.sigmaz_clustering(z_arr)) )
    
    # sigmaz_sources
    assert_( all_finite(ccl.sigmaz_sources(z_scl)) )
    assert_( all_finite(ccl.sigmaz_sources(z_lst)) )
    assert_( all_finite(ccl.sigmaz_sources(z_arr)) )
    
    # dNdz_tomog
    zmin = 0.
    zmax = 1.
    assert_( all_finite(ccl.dNdz_tomog(z_scl, 'nc', zmin, zmax, PZ1)) )
    assert_( all_finite(ccl.dNdz_tomog(z_lst, 'nc', zmin, zmax, PZ1)) )
    assert_( all_finite(ccl.dNdz_tomog(z_arr, 'nc', zmin, zmax, PZ1)) )
    
    assert_( all_finite(ccl.dNdz_tomog(z_scl, 'nc', zmin, zmax, PZ2)) )
    assert_( all_finite(ccl.dNdz_tomog(z_lst, 'nc', zmin, zmax, PZ2)) )
    assert_( all_finite(ccl.dNdz_tomog(z_arr, 'nc', zmin, zmax, PZ2)) )
    
    assert_( all_finite(ccl.dNdz_tomog(z_scl, 'wl_fid', zmin, zmax, PZ1)) )
    assert_( all_finite(ccl.dNdz_tomog(z_lst, 'wl_fid', zmin, zmax, PZ1)) )
    assert_( all_finite(ccl.dNdz_tomog(z_arr, 'wl_fid', zmin, zmax, PZ1)) )
    
    assert_( all_finite(ccl.dNdz_tomog(z_scl, 'wl_fid', zmin, zmax, PZ2)) )
    assert_( all_finite(ccl.dNdz_tomog(z_lst, 'wl_fid', zmin, zmax, PZ2)) )
    assert_( all_finite(ccl.dNdz_tomog(z_arr, 'wl_fid', zmin, zmax, PZ2)) )
    
    # Argument checking of dNdz_tomog
    # Wrong dNdz_type
    assert_raises(ValueError, ccl.dNdz_tomog, z_scl, 'nonsense', zmin, zmax, PZ1)
    
    # Wrong function type
    assert_raises(TypeError, ccl.dNdz_tomog, z_scl, 'nc', zmin, zmax, pz1)
    assert_raises(TypeError, ccl.dNdz_tomog, z_scl, 'nc', zmin, zmax, z_arr)
    assert_raises(TypeError, ccl.dNdz_tomog, z_scl, 'nc', zmin, zmax, None)
Пример #9
0
def check_redshifts(cosmo):
    """
    Check that redshift functions can be run and produce finite values.
    """
    # Types of scale factor input (scalar, list, array)
    a_scl = 0.5
    a_lst = [0.2, 0.4, 0.6, 0.8, 1.]
    a_arr = np.linspace(0.2, 1., 5)

    # Types of redshift input
    z_scl = 0.5
    z_lst = [0., 0.5, 1., 1.5, 2.]
    z_arr = np.array(z_lst)

    # p(z) function for dNdz_tomog
    def pz1(z_ph, z_s, args):
        return np.exp(-(z_ph - z_s)**2. / 2.)

    # Lambda function p(z) function for dNdz_tomog
    pz2 = lambda z_ph, z_s, args: np.exp(-(z_ph - z_s)**2. / 2.)

    # PhotoZFunction classes
    PZ1 = ccl.PhotoZFunction(pz1)
    PZ2 = ccl.PhotoZFunction(pz2)
    PZ3 = ccl.PhotoZGaussian(sigma_z0=0.1)

    # dNdz (in terms of true redshift) function for dNdz_tomog
    def dndz1(z, args):
        return z**1.24 * np.exp(-(z / 0.51)**1.01)

    # dNdzFunction classes
    dNdZ1 = ccl.dNdzFunction(dndz1)
    dNdZ2 = ccl.dNdzSmail(alpha=1.24, beta=1.01, z0=0.51)

    # Check that dNdz_tomog is finite with the various combinations
    # of PhotoZ and dNdz functions
    zmin = 0.
    zmax = 1.

    assert_(all_finite(ccl.dNdz_tomog(z_scl, zmin, zmax, PZ1, dNdZ1)))
    assert_(all_finite(ccl.dNdz_tomog(z_lst, zmin, zmax, PZ1, dNdZ1)))
    assert_(all_finite(ccl.dNdz_tomog(z_arr, zmin, zmax, PZ1, dNdZ1)))

    assert_(all_finite(ccl.dNdz_tomog(z_scl, zmin, zmax, PZ2, dNdZ1)))
    assert_(all_finite(ccl.dNdz_tomog(z_lst, zmin, zmax, PZ2, dNdZ1)))
    assert_(all_finite(ccl.dNdz_tomog(z_arr, zmin, zmax, PZ2, dNdZ1)))

    assert_(all_finite(ccl.dNdz_tomog(z_scl, zmin, zmax, PZ3, dNdZ1)))
    assert_(all_finite(ccl.dNdz_tomog(z_lst, zmin, zmax, PZ3, dNdZ1)))
    assert_(all_finite(ccl.dNdz_tomog(z_arr, zmin, zmax, PZ3, dNdZ1)))

    assert_(all_finite(ccl.dNdz_tomog(z_scl, zmin, zmax, PZ1, dNdZ2)))
    assert_(all_finite(ccl.dNdz_tomog(z_lst, zmin, zmax, PZ1, dNdZ2)))
    assert_(all_finite(ccl.dNdz_tomog(z_arr, zmin, zmax, PZ1, dNdZ2)))

    assert_(all_finite(ccl.dNdz_tomog(z_scl, zmin, zmax, PZ2, dNdZ2)))
    assert_(all_finite(ccl.dNdz_tomog(z_lst, zmin, zmax, PZ2, dNdZ2)))
    assert_(all_finite(ccl.dNdz_tomog(z_arr, zmin, zmax, PZ2, dNdZ2)))

    assert_(all_finite(ccl.dNdz_tomog(z_scl, zmin, zmax, PZ3, dNdZ2)))
    assert_(all_finite(ccl.dNdz_tomog(z_lst, zmin, zmax, PZ3, dNdZ2)))
    assert_(all_finite(ccl.dNdz_tomog(z_arr, zmin, zmax, PZ3, dNdZ2)))

    # Wrong function type
    assert_raises(TypeError, ccl.dNdz_tomog, z_scl, zmin, zmax, pz1, z_arr)
    assert_raises(TypeError, ccl.dNdz_tomog, z_scl, zmin, zmax, z_arr, dNdZ1)
    assert_raises(TypeError, ccl.dNdz_tomog, z_scl, zmin, zmax, None, None)
Пример #10
0
def test_redshift_analytic():
    """
    Compare the redshift functions to an analytic toy case.
    """
    # Redshift input
    z_lst = [0., 0.5, 1., 1.5, 2.]

    # p(z) function for which we can calculate and analytic dNdz_tomog
    # when pairs with the toy dndz_ana below
    def pz_ana(z_ph, z_s, args):
        return (np.exp(- (z_ph - z_s)**2. / 2. / 0.1**2) / np.sqrt(2.
                * np.pi) / 0.1)

    # PhotoZFunction class
    PZ_ana = ccl.PhotoZFunction(pz_ana)
        
    # Introduce an unrealistic, simple true function for dNdz for which
    # we can calculate dNdz_tomog analytically for comparison.
    def dndz_ana(z, args):
        if ((z>=0.) and (z<=1.0)): 
            return 1.0
        else:
            return 0. 
	
    # import math erf and erfc functions:
    from math import erf, erfc
    
    # Return the analytic result for dNdz_tomog using 
    # dndz_ana with a Gaussian p(z,z'), to which we compare.
    
    # This is obtained by analytically evaluating (in pseudo-latex):
    # \frac{ dndz_ana(z) \int_{zpmin}^{zpmax} dz_p pz_ana(z_p, z_s)}
    # {\int_{0}^{1} dz_s dndz_ana(z_s) \int_{zpmin}^{zpmax} dz_p 
    # pz_ana(z_p, z_s)}
    # (which we did using Wolfram Mathematica)
    
    def dNdz_tomog_analytic(z, sigz, zmin, zmax):
        if ( (z>=0.) and (z<=1.0) ):
            return (erf((z-zmin) / np.sqrt(2.)/sigz) - erf((z-zmax)/
                    np.sqrt(2.)/sigz)) / (-1. + (-np.exp(-(zmax-1)**2 
                    / 2. / sigz**2) + np.exp(-zmax**2 / 2. / sigz**2) + 
                    np.exp(-(zmin-1)**2 / 2. / sigz**2) - np.exp(
                    -zmin**2 / 2 /sigz**2)) * np.sqrt(2. / np.pi)*sigz 
                    + erf( (zmax-1) / np.sqrt(2.) /  sigz) + erfc( 
                    (zmin-1.)/np.sqrt(2.)/sigz) + zmax * (erf(zmax/
                    np.sqrt(2.)/sigz) - erf( (zmax-1.) / np.sqrt(2.)/
                    sigz)) + zmin * ( erf( (zmin-1.)/np.sqrt(2.)
		            / sigz) - erf(zmin/np.sqrt(2.)/sigz)))
        else:
            return 0.
        
    # dNdzFunction class
    dNdZ_ana = ccl.dNdzFunction(dndz_ana)
    
    # Check that for the analytic case introduced above, we get the 
    # correct value.
    zmin = 0.
    zmax = 1.
    # math erf funcs are not vectorized so loop over z values
    for z in z_lst:
        assert_allclose(ccl.dNdz_tomog(z, zmin, zmax, PZ_ana, 
		               dNdZ_ana), dNdz_tomog_analytic(z, 0.1, zmin, 
		               zmax), rtol=TOLERANCE)       
Пример #11
0
def test_redshift_numerical():
    """
    Compare the redshift functions to a high precision integral.
    """
    # Redshift input
    z_lst = [0., 0.5, 1., 1.5, 2.]
                
     # p(z) function for dNdz_tomog
    def pz1(z_ph, z_s, args):
        return np.exp(- (z_ph - z_s)**2. / 2.)

    # Lambda function p(z) function for dNdz_tomog
    pz2 = lambda z_ph, z_s, args: np.exp(-(z_ph - z_s)**2. / 2.)
    
    # Set up a function equivalent to the PhotoZGaussian
    def pz3(z_ph, z_s, sigz):
        sig = sigz*(1.+ z_s)
        return (np.exp(- (z_ph - z_s)**2. / 2. / sig**2) / np.sqrt(2.
		        *np.pi) / sig)

    # PhotoZFunction classes
    PZ1 = ccl.PhotoZFunction(pz1)
    PZ2 = ccl.PhotoZFunction(pz2)
    PZ3 = ccl.PhotoZGaussian(sigma_z0=0.1)
    
    # dNdz (in terms of true redshift) function for dNdz_tomog
    def dndz1(z, args):
        return z**1.24 * np.exp(- (z / 0.51)**1.01)
    
    # dNdzFunction classes
    dNdZ1 = ccl.dNdzFunction(dndz1)
    dNdZ2 = ccl.dNdzSmail(alpha = 1.24, beta = 1.01, z0 = 0.51)
    
    # Do the integral in question directly in numpy at high precision
    zmin = 0.
    zmax = 1.
    zp = np.linspace(zmin, zmax, 10000)
    zs = np.linspace(0., 5., 10000) # Assume any dNdz does not extend 
    # above z=5
    denom_zp_1 =np.asarray([np.trapz(pz1(zp, z, []), zp) for z in zs])
    denom_zp_2 =np.asarray([np.trapz(pz2(zp, z, []), zp) for z in zs])
    denom_zp_3 =np.asarray([np.trapz(pz3(zp, z, 0.1), zp) for z in zs])
    np_dndz_1 = ([ dndz1(z, []) * np.trapz(pz1(zp, z, []), zp) / 
                 np.trapz(dndz1(zs, []) * denom_zp_1, zs) for z in 
                 z_lst])
    np_dndz_2 = ([ dndz1(z, []) * np.trapz(pz2(zp, z, []), zp) / 
                 np.trapz(dndz1(zs, []) * denom_zp_2, zs) for z in 
                 z_lst])
    np_dndz_3 = ([ dndz1(z, []) * np.trapz(pz3(zp, z, 0.1), zp) / 
                 np.trapz(dndz1(zs, []) * denom_zp_3, zs) for z in 
                 z_lst])
    
    # Check that for the analytic case introduced above, we get the 
    # correct value.
    for i in range(0, len(z_lst)):
        assert_allclose(ccl.dNdz_tomog(z_lst[i], zmin, zmax, PZ1, 
		               dNdZ1), np_dndz_1[i], rtol=TOLERANCE) 
        assert_allclose(ccl.dNdz_tomog(z_lst[i], zmin, zmax, PZ1, 
		               dNdZ2), np_dndz_1[i], rtol=TOLERANCE)  
        assert_allclose(ccl.dNdz_tomog(z_lst[i], zmin, zmax, PZ2, 
		               dNdZ1), np_dndz_2[i], rtol=TOLERANCE) 
        assert_allclose(ccl.dNdz_tomog(z_lst[i], zmin, zmax, PZ2, 
		               dNdZ2), np_dndz_2[i], rtol=TOLERANCE)  
        assert_allclose(ccl.dNdz_tomog(z_lst[i], zmin, zmax, PZ3, 
		               dNdZ1), np_dndz_3[i], rtol=TOLERANCE) 
        assert_allclose(ccl.dNdz_tomog(z_lst[i], zmin, zmax, PZ3, 
		               dNdZ2), np_dndz_3[i], rtol=TOLERANCE)  
# ###############
# Can also compute C_ell for galaxy counts, galaxy lensing and CMB lensing
# for autocorrelations or any cross-correlation

z_pz = np.linspace(0.3, 3., 3)  # Define the edges of the photo-z bins.
# array([0.3 , 1.65, 3.  ]) AKA 2 bins
pz = ccl.PhotoZGaussian(sigma_z0=0.05)

def dndz(z,args) :
    return z**2*np.exp(-(z/0.5)**1.5)

redshift_dist=ccl.dNdzFunction(dndz)

# galaxy counts
dNdz_nc = [ccl.dNdz_tomog(z=z, zmin=z_pz[zi], zmax=z_pz[zi+1], pz_func=pz
	, dNdz_func=redshift_dist) for zi in range(0, len(z_pz)-1)]
# galaxy lensing
dNdz_len = [ccl.dNdz_tomog(z=z, zmin=z_pz[zi], zmax=z_pz[zi+1], pz_func=pz
	, dNdz_func=redshift_dist) for zi in range(0, len(z_pz)-1)]

# assume linear bias
bias = 2.*np.ones(len(z))

gal_counts = ([ccl.NumberCountsTracer(cosmo, has_rsd=False,
      dndz=(z, dNdz_nc[zi]), bias=(z, bias))  for zi in range(0, len(z_pz)-1)])

gal_lens = ([ccl.WeakLensingTracer(cosmo, dndz=(z, dNdz_len[zi]))
      for zi in range(0, len(z_pz)-1)])

# tracer objects for CMB lensing
cmb_lens = [ccl.CMBLensingTracer(cosmo, z_source=1089.)]