From 554345f6824e586e48490c0815319134a58f98c4 Mon Sep 17 00:00:00 2001 From: carlosggarcia Date: Thu, 21 Nov 2024 14:11:19 +0000 Subject: [PATCH 01/28] covNG: first commit --- tjpcov/covariance_fourier_cNG.py | 189 +++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 tjpcov/covariance_fourier_cNG.py diff --git a/tjpcov/covariance_fourier_cNG.py b/tjpcov/covariance_fourier_cNG.py new file mode 100644 index 00000000..bc573a5e --- /dev/null +++ b/tjpcov/covariance_fourier_cNG.py @@ -0,0 +1,189 @@ +import os + +# import healpy as hp +import numpy as np +import pyccl as ccl + +from .covariance_builder import CovarianceFourier + + +class FouriercNGHaloModel(CovarianceFourier): + """Class to compute the CellxCell Halo Model cNG Covariance.""" + + cov_type = "cNG" + + def __init__(self, config): + """Initialize the class with a config file or dictionary. + + Args: + config (dict or str): If dict, it returns the configuration + dictionary directly. If string, it asumes a YAML file and + parses it. + """ + super().__init__(config) + + self.cNG_conf = self.config.get("cNG", {}) + + def get_covariance_block( + self, + tracer_comb1, + tracer_comb2, + integration_method=None, + include_b_modes=True, + ): + """Compute a single cNG covariance matrix for a given pair of C_ell. + + If outdir is set, it will save the covariance to a file called + cng_tr1_tr2_tr3_tr4.npz. This file will be read and its output returned + if found. + + Blocks of the B-modes are assumed 0 so far. + + Args: + tracer_comb1 (list): List of the pair of tracer names of C_ell^1 + tracer_comb2 (list): List of the pair of tracer names of C_ell^2 + integration_method (str, optional): integration method to be + used for the Limber integrals. Possibilities: 'qag_quad' (GSL's + qag method backed up by quad when it fails) and 'spline' + (the integrand is splined and then integrated analytically). If + given, it will take priority over the specified in the + configuration file through config['cNG']['integration_method']. + Elsewise, it will use 'qag_quad'. + include_b_modes (bool, optional): If True, return the full cNG with + zeros in for B-modes (if any). If False, return the non-zero + block. This option cannot be modified through the configuration + file to avoid breaking the compatibility with the NaMaster + covariance. Defaults to True. + + Returns: + array: Super sample covariance matrix for a pair of C_ell. + """ + fname = "cng_{}_{}_{}_{}.npz".format(*tracer_comb1, *tracer_comb2) + fname = os.path.join(self.io.outdir, fname) + if os.path.isfile(fname): + cf = np.load(fname) + return cf["cov" if include_b_modes else "cov_nob"] + + if integration_method is None: + integration_method = self.cNG_conf.get( + "integration_method", "qag_quad" + ) + + tr = {} + tr[1], tr[2] = tracer_comb1 + tr[3], tr[4] = tracer_comb2 + + cosmo = self.get_cosmology() + mass_def = ccl.halos.MassDef200m + hmf = ccl.halos.MassFuncTinker08(mass_def=mass_def) + hbf = ccl.halos.HaloBiasTinker10(mass_def=mass_def) + cM = ccl.halos.ConcentrationDuffy08(mass_def=mass_def) + nfw = ccl.halos.HaloProfileNFW( + mass_def=mass_def, concentration=cM, fourier_analytic=True + ) + hmc = ccl.halos.HMCalculator( + mass_function=hmf, halo_bias=hbf, mass_def=mass_def + ) + + # Get range of redshifts. z_min = 0 for compatibility with the limber + # integrals + sacc_file = self.io.get_sacc_file() + z_max = [] + for i in range(4): + tr_sacc = sacc_file.tracers[tr[i + 1]] + z = tr_sacc.z + # z, nz = tr_sacc.z, tr_sacc.nz + # z_min.append(z[np.where(nz > 0)[0][0]]) + # z_max.append(z[np.where(np.cumsum(nz)/np.sum(nz) > 0.999)[0][0]]) + z_max.append(z.max()) + + z_max = np.min(z_max) + + # Array of a. + # Use the a's in the pk spline + na = ccl.ccllib.get_pk_spline_na(cosmo.cosmo) + a, _ = ccl.ccllib.get_pk_spline_a(cosmo.cosmo, na, 0) + # Cut the array for efficiency + sel = 1 / a < z_max + 1 + # Include the next node so that z_max is in the range + sel[np.sum(~sel) - 1] = True + a = a[sel] + + bias1 = self.bias_lens.get(tr[1], 1) + bias2 = self.bias_lens.get(tr[2], 1) + bias3 = self.bias_lens.get(tr[3], 1) + bias4 = self.bias_lens.get(tr[4], 1) + + ccl_tracers, _ = self.get_tracer_info() + + s = self.io.get_sacc_file() + isnc = {} + for i in range(1, 5): + isnc[i] = (s.tracers[tr[i]].quantity == "galaxy_density") or ( + "lens" in tr[i] + ) + + masks = self.get_masks_dict(tr, {}) + # TODO: This should be unified with the other classes in + # CovarianceBuilder. + fsky = np.mean(masks[1] * masks[2] * masks[3] * masks[4]) + + # Tk3D = b1*b2*b3*b4 * T_234h (NFW) + T_1h (HOD) + + if lk_arr is None: + lk_arr = cosmo.get_pk_spline_lk() + if a_arr is None: + a_arr = cosmo.get_pk_spline_a() + + + tkk = ccl.halos.halomod_trispectrum_1h(cosmo, hmc, np.exp(lk_arr), + a_arr, prof=nfw) + + tkk += ccl.halos.halomod_trispectrum_2h_22(cosmo, hmc, np.exp(lk_arr), + a_arr, prof=nfw) + + tkk += ccl.halos.halomod_trispectrum_2h_13(cosmo, hmc, np.exp(lk_arr), + a_arr, prof=nfw) + + tkk += ccl.halos.halomod_trispectrum_3h(cosmo, hmc, np.exp(lk_arr), + a_arr, prof=nfw) + + tkk *= bias1 * bias2 * bias3 * bias4 + + # TODO: Commented out for now to avoid having to specify HOD params + # tkk += halomod_trispectrum_4h(cosmo, hmc, np.exp(lk_arr), a_arr, + # prof=prof, + # prof2=prof2, + # prof3=prof3, + # prof4=prof4, + # p_of_k_a=None) + + tk3D = ccl.tk3d.Tk3D(a_arr=a_arr, lk_arr=lk_arr, tkk_arr=tkk) + + + ell = self.get_ell_eff() + cov_cng = ccl.covariances.angular_cl_cov_cNG( + cosmo, + tracer1=ccl_tracers[tr[1]], + tracer2=ccl_tracers[tr[2]], + tracer3=ccl_tracers[tr[3]], + tracer4=ccl_tracers[tr[4]], + ell=ell, + t_of_kk_a=tk3D, + integration_method=integration_method, + fsky=fsky, + ) + + nbpw = ell.size + ncell1 = self.get_tracer_comb_ncell(tracer_comb1) + ncell2 = self.get_tracer_comb_ncell(tracer_comb2) + cov_full = np.zeros((nbpw, ncell1, nbpw, ncell2)) + cov_full[:, 0, :, 0] = cov_cng + cov_full = cov_full.reshape((nbpw * ncell1, nbpw * ncell2)) + + np.savez_compressed(fname, cov=cov_full, cov_nob=cov_cng) + + if not include_b_modes: + return cov_cng + + return cov_full From 25ee2ac1ada657df9cb02e84dfc622a4ce4ba692 Mon Sep 17 00:00:00 2001 From: carlosggarcia Date: Thu, 21 Nov 2024 14:15:21 +0000 Subject: [PATCH 02/28] removed unused lines --- tjpcov/covariance_fourier_cNG.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tjpcov/covariance_fourier_cNG.py b/tjpcov/covariance_fourier_cNG.py index bc573a5e..66f55bce 100644 --- a/tjpcov/covariance_fourier_cNG.py +++ b/tjpcov/covariance_fourier_cNG.py @@ -116,13 +116,6 @@ def get_covariance_block( ccl_tracers, _ = self.get_tracer_info() - s = self.io.get_sacc_file() - isnc = {} - for i in range(1, 5): - isnc[i] = (s.tracers[tr[i]].quantity == "galaxy_density") or ( - "lens" in tr[i] - ) - masks = self.get_masks_dict(tr, {}) # TODO: This should be unified with the other classes in # CovarianceBuilder. From 02a8308cbe9b041d4e452b3a9a18812e8ad3991c Mon Sep 17 00:00:00 2001 From: carlosggarcia Date: Thu, 21 Nov 2024 14:17:35 +0000 Subject: [PATCH 03/28] unified a and k arrays --- tjpcov/covariance_fourier_cNG.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tjpcov/covariance_fourier_cNG.py b/tjpcov/covariance_fourier_cNG.py index 66f55bce..3f03a6de 100644 --- a/tjpcov/covariance_fourier_cNG.py +++ b/tjpcov/covariance_fourier_cNG.py @@ -102,12 +102,15 @@ def get_covariance_block( # Array of a. # Use the a's in the pk spline na = ccl.ccllib.get_pk_spline_na(cosmo.cosmo) - a, _ = ccl.ccllib.get_pk_spline_a(cosmo.cosmo, na, 0) + a_arr, _ = ccl.ccllib.get_pk_spline_a(cosmo.cosmo, na, 0) # Cut the array for efficiency - sel = 1 / a < z_max + 1 + sel = 1 / a_arr < z_max + 1 # Include the next node so that z_max is in the range sel[np.sum(~sel) - 1] = True - a = a[sel] + a_arr = a_arr[sel] + + # Array of k + lk_arr = cosmo.cosmo.get_pk_spline_lk() bias1 = self.bias_lens.get(tr[1], 1) bias2 = self.bias_lens.get(tr[2], 1) @@ -123,10 +126,6 @@ def get_covariance_block( # Tk3D = b1*b2*b3*b4 * T_234h (NFW) + T_1h (HOD) - if lk_arr is None: - lk_arr = cosmo.get_pk_spline_lk() - if a_arr is None: - a_arr = cosmo.get_pk_spline_a() tkk = ccl.halos.halomod_trispectrum_1h(cosmo, hmc, np.exp(lk_arr), From 13f2bff047137994d813602b5b1584fcad5176e3 Mon Sep 17 00:00:00 2001 From: carlosggarcia Date: Fri, 22 Nov 2024 10:48:51 +0000 Subject: [PATCH 04/28] covNG: added all terms. 1h with galaxy bias. Probably not good enough. --- tjpcov/covariance_fourier_cNG.py | 35 +++++++++++++++++++------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/tjpcov/covariance_fourier_cNG.py b/tjpcov/covariance_fourier_cNG.py index 3f03a6de..f076537f 100644 --- a/tjpcov/covariance_fourier_cNG.py +++ b/tjpcov/covariance_fourier_cNG.py @@ -3,6 +3,7 @@ # import healpy as hp import numpy as np import pyccl as ccl +import warnings from .covariance_builder import CovarianceFourier @@ -125,13 +126,7 @@ def get_covariance_block( fsky = np.mean(masks[1] * masks[2] * masks[3] * masks[4]) # Tk3D = b1*b2*b3*b4 * T_234h (NFW) + T_1h (HOD) - - - - tkk = ccl.halos.halomod_trispectrum_1h(cosmo, hmc, np.exp(lk_arr), - a_arr, prof=nfw) - - tkk += ccl.halos.halomod_trispectrum_2h_22(cosmo, hmc, np.exp(lk_arr), + tkk = ccl.halos.halomod_trispectrum_2h_22(cosmo, hmc, np.exp(lk_arr), a_arr, prof=nfw) tkk += ccl.halos.halomod_trispectrum_2h_13(cosmo, hmc, np.exp(lk_arr), @@ -140,15 +135,27 @@ def get_covariance_block( tkk += ccl.halos.halomod_trispectrum_3h(cosmo, hmc, np.exp(lk_arr), a_arr, prof=nfw) + # tkk *= bias1 * bias2 * bias3 * bias4 + + tkk += ccl.halos.halomod_trispectrum_4h(cosmo, hmc, np.exp(lk_arr), + a_arr, prof=nfw) + + + # TODO: Use HOD for the 1h term when using galaxy clustering + tkk += ccl.halos.halomod_trispectrum_1h(cosmo, hmc, np.exp(lk_arr), + a_arr, prof=nfw) + tkk *= bias1 * bias2 * bias3 * bias4 - # TODO: Commented out for now to avoid having to specify HOD params - # tkk += halomod_trispectrum_4h(cosmo, hmc, np.exp(lk_arr), a_arr, - # prof=prof, - # prof2=prof2, - # prof3=prof3, - # prof4=prof4, - # p_of_k_a=None) + s = self.io.get_sacc_file() + isnc = [] + for i in range(1, 5): + isnc[i] = (s.tracers[tr[i]].quantity == "galaxy_density") or ( + "lens" in tr[i] + ) + if any(isnc): + warnings.warn("Using linear galaxy bias with 1h term. This should " + "be checked. HOD version need implementation.") tk3D = ccl.tk3d.Tk3D(a_arr=a_arr, lk_arr=lk_arr, tkk_arr=tkk) From a674167fe6c40bf94df805d6d2087d3d4699f501 Mon Sep 17 00:00:00 2001 From: carlosggarcia Date: Fri, 22 Nov 2024 12:09:56 +0000 Subject: [PATCH 05/28] covNG: added tests. super slow --- tests/data/conf_covariance_cNG.yaml | 45 ++++++ tests/test_covariance_fourier_cNG.py | 213 +++++++++++++++++++++++++++ tjpcov/__init__.py | 2 + tjpcov/covariance_fourier_cNG.py | 2 +- 4 files changed, 261 insertions(+), 1 deletion(-) create mode 100644 tests/data/conf_covariance_cNG.yaml create mode 100644 tests/test_covariance_fourier_cNG.py diff --git a/tests/data/conf_covariance_cNG.yaml b/tests/data/conf_covariance_cNG.yaml new file mode 100644 index 00000000..a85f92e6 --- /dev/null +++ b/tests/data/conf_covariance_cNG.yaml @@ -0,0 +1,45 @@ +tjpcov: + # sacc input file + sacc_file: ./tests/benchmarks/32_DES_tjpcov_bm/cls_cov.fits + + # 'set' from parameters OR pass CCL cosmology object OR yaml file + cosmo: 'set' + + # Setting mask OR fsky approximation + mask_file: + DESgc__0: ./tests/benchmarks/32_DES_tjpcov_bm/catalogs/mask_DESgc__0.fits.gz + DESwl__0: ./tests/benchmarks/32_DES_tjpcov_bm/catalogs/DESwlMETACAL_mask_zbin0_ns32.fits.gz + DESwl__1: ./tests/benchmarks/32_DES_tjpcov_bm/catalogs/DESwlMETACAL_mask_zbin1_ns32.fits.gz + + mask_names: + DESgc__0: mask_DESgc0 + DESwl__0: mask_DESwl0 + DESwl__1: mask_DESwl1 + + outdir: ./tests/tmp/ + + # Survey params: + # 5 lens bins + Ngal_DESgc__0: 26 + + Ngal_DESwl__0: 26 + Ngal_DESwl__1: 26 + # # constant bin sigma_e + sigma_e_DESwl__0: 0.26 + sigma_e_DESwl__1: 0.26 + + # linear bias for lenses constant for redshift bin (example notebook) + bias_DESgc__0: 1.48 + + # IA: 0.5 + +parameters: + # Not used for while (read by ccl.cosmo): + Omega_c: 0.2640 + Omega_b: 0.0493 + h: 0.6736 + n_s: 0.9649 + sigma8: 0.8111 + w0: -1 + wa: 0 + transfer_function: 'boltzmann_camb' diff --git a/tests/test_covariance_fourier_cNG.py b/tests/test_covariance_fourier_cNG.py new file mode 100644 index 00000000..17090430 --- /dev/null +++ b/tests/test_covariance_fourier_cNG.py @@ -0,0 +1,213 @@ +#!/usr/bin/python3 +import os +import shutil + +import healpy as hp +import numpy as np +import pyccl as ccl +import pytest +import sacc +import yaml + +from tjpcov.covariance_fourier_cNG import FouriercNGHaloModel + +ROOT = "./tests/benchmarks/32_DES_tjpcov_bm/" +INPUT_YML_cNG = "./tests/data/conf_covariance_cNG.yaml" +OUTDIR = "./tests/tmp/" +NSIDE = 32 + + +def setup_module(): + os.makedirs(OUTDIR, exist_ok=True) + + +def teardown_module(): + shutil.rmtree(OUTDIR) + + +@pytest.fixture(autouse=True) +def teardown_test(): + clean_outdir() + + +def clean_outdir(): + os.system(f"rm -f {OUTDIR}*") + + +@pytest.fixture +def sacc_file(): + return sacc.Sacc.load_fits(ROOT + "cls_cov.fits") + + +@pytest.fixture +def cov_fcNG(): + return FouriercNGHaloModel(INPUT_YML_cNG) + + +def get_config(): + with open(INPUT_YML_cNG) as f: + config = yaml.safe_load(f) + return config + + +def get_halo_model(cosmo): + md = ccl.halos.MassDef200m + mf = ccl.halos.MassFuncTinker08(mass_def=md) + hb = ccl.halos.HaloBiasTinker10(mass_def=md) + hmc = ccl.halos.HMCalculator(mass_function=mf, halo_bias=hb, mass_def=md) + + return hmc + + +def get_NFW_profile(): + md = ccl.halos.MassDef200m + cm = ccl.halos.ConcentrationDuffy08(mass_def=md) + pNFW = ccl.halos.HaloProfileNFW(mass_def=md, concentration=cm) + + return pNFW + +def get_fsky(tr1, tr2, tr3, tr4): + config = get_config() + mf = config["tjpcov"]["mask_file"] + + area = hp.nside2pixarea(32) + m1 = hp.read_map(mf[tr1]) + m2 = hp.read_map(mf[tr2]) + m3 = hp.read_map(mf[tr3]) + m4 = hp.read_map(mf[tr4]) + + return np.mean(m1*m2*m3*m4) + + +def test_smoke(): + FouriercNGHaloModel(INPUT_YML_cNG) + + +@pytest.mark.parametrize( + "tracer_comb1,tracer_comb2", + [ + (("DESgc__0", "DESgc__0"), ("DESgc__0", "DESgc__0")), + (("DESgc__0", "DESwl__0"), ("DESwl__0", "DESwl__0")), + (("DESgc__0", "DESgc__0"), ("DESwl__0", "DESwl__0")), + (("DESwl__0", "DESwl__0"), ("DESwl__0", "DESwl__0")), + (("DESwl__0", "DESwl__0"), ("DESwl__1", "DESwl__1")), + ], +) +def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): + # TJPCov covariance + cosmo = cov_fcNG.get_cosmology() + s = cov_fcNG.io.get_sacc_file() + ell, _ = s.get_ell_cl("cl_00", "DESgc__0", "DESgc__0") + + cov_cNG = cov_fcNG.get_covariance_block( + tracer_comb1=tracer_comb1, + tracer_comb2=tracer_comb2, + include_b_modes=False, + ) + + # Check saved file + covf = np.load( + OUTDIR + "cng_{}_{}_{}_{}.npz".format(*tracer_comb1, *tracer_comb2) + ) + assert ( + np.max(np.abs((covf["cov_nob"] + 1e-100) / (cov_cNG + 1e-100) - 1)) + < 1e-10 + ) + + # CCL covariance + na = ccl.ccllib.get_pk_spline_na(cosmo.cosmo) + a_arr, _ = ccl.ccllib.get_pk_spline_a(cosmo.cosmo, na, 0) + + bias1 = bias2 = bias3 = bias4 = 1 + if "gc" in tracer_comb1[0]: + bias1 = cov_fcNG.bias_lens[tracer_comb1[0]] + + if "gc" in tracer_comb1[1]: + bias2 = cov_fcNG.bias_lens[tracer_comb1[1]] + + if "gc" in tracer_comb2[0]: + bias3 = cov_fcNG.bias_lens[tracer_comb2[0]] + + if "gc" in tracer_comb2[0]: + bias4 = cov_fcNG.bias_lens[tracer_comb2[1]] + + hmc = get_halo_model(cosmo) + nfw_profile = get_NFW_profile() + tkk_cNG = ccl.halos.halomod_Tk3D_cNG( + cosmo, + hmc, + prof=nfw_profile, + ) + + ccl_tracers, _ = cov_fcNG.get_tracer_info() + tr1 = ccl_tracers[tracer_comb1[0]] + tr2 = ccl_tracers[tracer_comb1[1]] + tr3 = ccl_tracers[tracer_comb2[0]] + tr4 = ccl_tracers[tracer_comb2[1]] + + fsky = get_fsky(tr1, tr2, tr3, tr4) + + cov_ccl = ccl.covariances.angular_cl_cov_cNG( + cosmo, + tracer1=tr1, + tracer2=tr2, + tracer3=tr3, + tracer4=tr4, + ell=ell, + t_of_kk_a=tkk_cNG, + fsky=fsky + ) + + assert np.max(np.fabs(np.diag(cov_cNG/ cov_ccl - 1))) < 1e-5 + assert np.max(np.fabs(cov_cNG / cov_ccl - 1)) < 1e-3 + + # Check you get zeroed B-modes + cov_cNG_zb = cov_fcNG.get_covariance_block( + tracer_comb1=tracer_comb1, + tracer_comb2=tracer_comb2, + include_b_modes=True, + ) + # Check saved + assert ( + np.max(np.abs((covf["cov"] + 1e-100) / (cov_cNG_zb + 1e-100) - 1)) + < 1e-10 + ) + + ix1 = s.indices(tracers=tracer_comb1) + ix2 = s.indices(tracers=tracer_comb2) + ncell1 = int(ix1.size / ell.size) + ncell2 = int(ix2.size / ell.size) + + # The covariance will have all correlations, including when EB == BE + if (ncell1 == 3) and (tracer_comb1[0] == tracer_comb1[1]): + ncell1 += 1 + if (ncell2 == 3) and (tracer_comb2[0] == tracer_comb2[1]): + ncell2 += 1 + + assert cov_cNG_zb.shape == (ell.size * ncell1, ell.size * ncell2) + # Check the blocks + cov_cNG_zb = cov_cNG_zb.reshape((ell.size, ncell1, ell.size, ncell2)) + # Check the reshape has the correct ordering + assert cov_cNG_zb[:, 0, :, 0].flatten() == pytest.approx( + cov_cNG.flatten(), rel=1e-10 + ) + assert np.all(cov_cNG_zb[:, 1::, :, 1::] == 0) + + # Check get_cNG_cov reads file + covf = np.load( + OUTDIR + "cng_{}_{}_{}_{}.npz".format(*tracer_comb1, *tracer_comb2) + ) + cov_cNG = cov_fcNG.get_covariance_block( + tracer_comb1=tracer_comb1, + tracer_comb2=tracer_comb2, + include_b_modes=False, + ) + assert np.all(covf["cov_nob"] == cov_cNG) + + cov_cNG_zb = cov_fcNG.get_covariance_block( + tracer_comb1=tracer_comb1, + tracer_comb2=tracer_comb2, + include_b_modes=True, + ) + + assert np.all(covf["cov"] == cov_cNG_zb) diff --git a/tjpcov/__init__.py b/tjpcov/__init__.py index 01461d65..663e51c9 100644 --- a/tjpcov/__init__.py +++ b/tjpcov/__init__.py @@ -15,6 +15,8 @@ def covariance_from_name(name): from .covariance_fourier_gaussian_nmt import FourierGaussianNmt as Cov elif name == "FourierSSCHaloModel": from .covariance_fourier_ssc import FourierSSCHaloModel as Cov + elif name == "FourierSSCHaloModel": + from .covariance_fourier_cNG import FouriercNGHaloModel as Cov elif name == "ClusterCountsSSC": from .covariance_cluster_counts_ssc import ClusterCountsSSC as Cov elif name == "ClusterCountsGaussian": diff --git a/tjpcov/covariance_fourier_cNG.py b/tjpcov/covariance_fourier_cNG.py index f076537f..6bb0f666 100644 --- a/tjpcov/covariance_fourier_cNG.py +++ b/tjpcov/covariance_fourier_cNG.py @@ -111,7 +111,7 @@ def get_covariance_block( a_arr = a_arr[sel] # Array of k - lk_arr = cosmo.cosmo.get_pk_spline_lk() + lk_arr = cosmo.get_pk_spline_lk() bias1 = self.bias_lens.get(tr[1], 1) bias2 = self.bias_lens.get(tr[2], 1) From 8be34e755c6c6af459a0d891d4a2f0af9eb15731 Mon Sep 17 00:00:00 2001 From: carlosggarcia Date: Fri, 22 Nov 2024 16:44:20 +0000 Subject: [PATCH 06/28] cNG: fixed typo --- tjpcov/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tjpcov/__init__.py b/tjpcov/__init__.py index 663e51c9..3407f797 100644 --- a/tjpcov/__init__.py +++ b/tjpcov/__init__.py @@ -15,7 +15,7 @@ def covariance_from_name(name): from .covariance_fourier_gaussian_nmt import FourierGaussianNmt as Cov elif name == "FourierSSCHaloModel": from .covariance_fourier_ssc import FourierSSCHaloModel as Cov - elif name == "FourierSSCHaloModel": + elif name == "FouriercNGHaloModel": from .covariance_fourier_cNG import FouriercNGHaloModel as Cov elif name == "ClusterCountsSSC": from .covariance_cluster_counts_ssc import ClusterCountsSSC as Cov From 6fc92b6b7c2b2ff8ac56dac019dfaf55422a9604 Mon Sep 17 00:00:00 2001 From: carlosggarcia Date: Fri, 22 Nov 2024 16:53:41 +0000 Subject: [PATCH 07/28] cNG: multiply biases 234h terms only --- tjpcov/covariance_fourier_cNG.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tjpcov/covariance_fourier_cNG.py b/tjpcov/covariance_fourier_cNG.py index 6bb0f666..98b1bebc 100644 --- a/tjpcov/covariance_fourier_cNG.py +++ b/tjpcov/covariance_fourier_cNG.py @@ -135,18 +135,16 @@ def get_covariance_block( tkk += ccl.halos.halomod_trispectrum_3h(cosmo, hmc, np.exp(lk_arr), a_arr, prof=nfw) - # tkk *= bias1 * bias2 * bias3 * bias4 tkk += ccl.halos.halomod_trispectrum_4h(cosmo, hmc, np.exp(lk_arr), a_arr, prof=nfw) + tkk *= bias1 * bias2 * bias3 * bias4 # TODO: Use HOD for the 1h term when using galaxy clustering tkk += ccl.halos.halomod_trispectrum_1h(cosmo, hmc, np.exp(lk_arr), a_arr, prof=nfw) - tkk *= bias1 * bias2 * bias3 * bias4 - s = self.io.get_sacc_file() isnc = [] for i in range(1, 5): From 34cd954193dcceda5a1f862d00c9b4b9352c23ef Mon Sep 17 00:00:00 2001 From: paulrogozenski Date: Tue, 26 Nov 2024 16:29:33 -0500 Subject: [PATCH 08/28] initial hod implementation for cNG --- tjpcov/covariance_fourier_cNG.py | 55 ++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/tjpcov/covariance_fourier_cNG.py b/tjpcov/covariance_fourier_cNG.py index 98b1bebc..82235a6b 100644 --- a/tjpcov/covariance_fourier_cNG.py +++ b/tjpcov/covariance_fourier_cNG.py @@ -25,6 +25,33 @@ def __init__(self, config): self.cNG_conf = self.config.get("cNG", {}) + self.HOD_dict = { + "log10Mmin_0": None, + "log10Mmin_p": None, + "siglnM_0": None, + "siglnM_p": None, + "log10M0_0": None, + "log10M0_p": None, + "log10M1_0": None, + "log10M1_p": None, + "alpha_0": None, + "alpha_p": None, + "fc_0": None, + "fc_p": None, + "bg_0": None, + "bg_p": None, + "bmax_0": None, + "bmax_p": None, + "a_pivot": None, + "ns_independent": None, + "is_number_counts": None + } + + for key in HOD_dict.keys(): + self.HOD_dict[key] = self.config["HOD"].get(key, None) + if self.HOD_dict[key] is None: + raise ValueError("You need to set "+key+" in the HOD header for cNG calculation") + def get_covariance_block( self, tracer_comb1, @@ -57,7 +84,7 @@ def get_covariance_block( covariance. Defaults to True. Returns: - array: Super sample covariance matrix for a pair of C_ell. + array: Connected NG covariance matrix for a pair of C_ell. """ fname = "cng_{}_{}_{}_{}.npz".format(*tracer_comb1, *tracer_comb2) fname = os.path.join(self.io.outdir, fname) @@ -86,6 +113,29 @@ def get_covariance_block( mass_function=hmf, halo_bias=hbf, mass_def=mass_def ) + hod = ccl.halos.HaloProfileHOD( + mass_def=mass_def, concentration=cM, + log10Mmin_0=self.HOD_dict["log10Mmin_0"], + log10Mmin_p=self.HOD_dict["log10Mmin_p"], + siglnM_0=self.HOD_dict["siglnM_0"], + siglnM_p=self.HOD_dict["siglnM_p"], + log10M0_0=self.HOD_dict["log10M0_0"], + log10M0_p=self.HOD_dict["log10M0_p"], + log10M1_0=self.HOD_dict["log10M1_0"], + log10M1_p=self.HOD_dict["log10M1_p"], + alpha_0=self.HOD_dict["alpha_0"], + alpha_p=self.HOD_dict["alpha_p"], + fc_0=self.HOD_dict["fc_0"], + fc_p=self.HOD_dict["fc_p"], + bg_0=self.HOD_dict["bg_0"], + bg_p=self.HOD_dict["bg_p"], + bmax_0=self.HOD_dict["bmax_0"], + bmax_p=self.HOD_dict["bmax_p"], + a_pivot=self.HOD_dict["a_pivot"], + ns_independent=self.HOD_dict["ns_independent"], + is_number_counts=self.HOD_dict["is_number_counts"] + ) + # Get range of redshifts. z_min = 0 for compatibility with the limber # integrals sacc_file = self.io.get_sacc_file() @@ -141,9 +191,8 @@ def get_covariance_block( tkk *= bias1 * bias2 * bias3 * bias4 - # TODO: Use HOD for the 1h term when using galaxy clustering tkk += ccl.halos.halomod_trispectrum_1h(cosmo, hmc, np.exp(lk_arr), - a_arr, prof=nfw) + a_arr, prof=hod) s = self.io.get_sacc_file() isnc = [] From aacbca87efbab20a9421356389b92f58b3b0d472 Mon Sep 17 00:00:00 2001 From: paulrogozenski Date: Wed, 27 Nov 2024 16:17:37 -0500 Subject: [PATCH 09/28] added HOD parameters to cNG tests --- tests/data/conf_covariance_cNG.yaml | 21 +++++++++++++++++++++ tjpcov/covariance_fourier_cNG.py | 4 ++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/tests/data/conf_covariance_cNG.yaml b/tests/data/conf_covariance_cNG.yaml index a85f92e6..569a934a 100644 --- a/tests/data/conf_covariance_cNG.yaml +++ b/tests/data/conf_covariance_cNG.yaml @@ -43,3 +43,24 @@ parameters: w0: -1 wa: 0 transfer_function: 'boltzmann_camb' +HOD: + # automatically creates massdef and concentration objects + log10Mmin_0: 12.0 + log10Mmin_p: 0.0 + siglnM_0: 0.4 + siglnM_p: 0.0 + log10M0_0: 7.0 + log10M0_p: 0.0 + log10M1_0: 13.3 + log10M1_p: 0.0 + alpha_0: 1.0 + alpha_p: 0.0 + fc_0: 1.0 + fc_p: 0.0 + bg_0: 1.0 + bg_p: 0.0 + bmax_0: 1.0 + bmax_p: 0.0 + a_pivot: 1.0 + ns_independent: False + is_number_counts: True \ No newline at end of file diff --git a/tjpcov/covariance_fourier_cNG.py b/tjpcov/covariance_fourier_cNG.py index 82235a6b..629971db 100644 --- a/tjpcov/covariance_fourier_cNG.py +++ b/tjpcov/covariance_fourier_cNG.py @@ -47,7 +47,7 @@ def __init__(self, config): "is_number_counts": None } - for key in HOD_dict.keys(): + for key in self.HOD_dict.keys(): self.HOD_dict[key] = self.config["HOD"].get(key, None) if self.HOD_dict[key] is None: raise ValueError("You need to set "+key+" in the HOD header for cNG calculation") @@ -176,7 +176,7 @@ def get_covariance_block( fsky = np.mean(masks[1] * masks[2] * masks[3] * masks[4]) # Tk3D = b1*b2*b3*b4 * T_234h (NFW) + T_1h (HOD) - tkk = ccl.halos.halomod_trispectrum_2h_22(cosmo, hmc, np.exp(lk_arr), + tkk = ccl.halos.pk_4pt.halomod_trispectrum_2h_22(cosmo, hmc, np.exp(lk_arr), a_arr, prof=nfw) tkk += ccl.halos.halomod_trispectrum_2h_13(cosmo, hmc, np.exp(lk_arr), From 2406b8aa6ab846fba22dfb038f95e6124c9e1d75 Mon Sep 17 00:00:00 2001 From: paulrogozenski Date: Wed, 27 Nov 2024 16:26:24 -0500 Subject: [PATCH 10/28] black reformatting --- tests/test_covariance_fourier_cNG.py | 7 +++-- tjpcov/covariance_fourier_cNG.py | 45 +++++++++++++++++----------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/tests/test_covariance_fourier_cNG.py b/tests/test_covariance_fourier_cNG.py index 17090430..006b7b67 100644 --- a/tests/test_covariance_fourier_cNG.py +++ b/tests/test_covariance_fourier_cNG.py @@ -66,6 +66,7 @@ def get_NFW_profile(): return pNFW + def get_fsky(tr1, tr2, tr3, tr4): config = get_config() mf = config["tjpcov"]["mask_file"] @@ -76,7 +77,7 @@ def get_fsky(tr1, tr2, tr3, tr4): m3 = hp.read_map(mf[tr3]) m4 = hp.read_map(mf[tr4]) - return np.mean(m1*m2*m3*m4) + return np.mean(m1 * m2 * m3 * m4) def test_smoke(): @@ -155,10 +156,10 @@ def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): tracer4=tr4, ell=ell, t_of_kk_a=tkk_cNG, - fsky=fsky + fsky=fsky, ) - assert np.max(np.fabs(np.diag(cov_cNG/ cov_ccl - 1))) < 1e-5 + assert np.max(np.fabs(np.diag(cov_cNG / cov_ccl - 1))) < 1e-5 assert np.max(np.fabs(cov_cNG / cov_ccl - 1)) < 1e-3 # Check you get zeroed B-modes diff --git a/tjpcov/covariance_fourier_cNG.py b/tjpcov/covariance_fourier_cNG.py index 629971db..0c41b417 100644 --- a/tjpcov/covariance_fourier_cNG.py +++ b/tjpcov/covariance_fourier_cNG.py @@ -44,13 +44,17 @@ def __init__(self, config): "bmax_p": None, "a_pivot": None, "ns_independent": None, - "is_number_counts": None + "is_number_counts": None, } for key in self.HOD_dict.keys(): self.HOD_dict[key] = self.config["HOD"].get(key, None) if self.HOD_dict[key] is None: - raise ValueError("You need to set "+key+" in the HOD header for cNG calculation") + raise ValueError( + "You need to set " + + key + + " in the HOD header for cNG calculation" + ) def get_covariance_block( self, @@ -114,7 +118,8 @@ def get_covariance_block( ) hod = ccl.halos.HaloProfileHOD( - mass_def=mass_def, concentration=cM, + mass_def=mass_def, + concentration=cM, log10Mmin_0=self.HOD_dict["log10Mmin_0"], log10Mmin_p=self.HOD_dict["log10Mmin_p"], siglnM_0=self.HOD_dict["siglnM_0"], @@ -133,7 +138,7 @@ def get_covariance_block( bmax_p=self.HOD_dict["bmax_p"], a_pivot=self.HOD_dict["a_pivot"], ns_independent=self.HOD_dict["ns_independent"], - is_number_counts=self.HOD_dict["is_number_counts"] + is_number_counts=self.HOD_dict["is_number_counts"], ) # Get range of redshifts. z_min = 0 for compatibility with the limber @@ -176,23 +181,28 @@ def get_covariance_block( fsky = np.mean(masks[1] * masks[2] * masks[3] * masks[4]) # Tk3D = b1*b2*b3*b4 * T_234h (NFW) + T_1h (HOD) - tkk = ccl.halos.pk_4pt.halomod_trispectrum_2h_22(cosmo, hmc, np.exp(lk_arr), - a_arr, prof=nfw) + tkk = ccl.halos.pk_4pt.halomod_trispectrum_2h_22( + cosmo, hmc, np.exp(lk_arr), a_arr, prof=nfw + ) - tkk += ccl.halos.halomod_trispectrum_2h_13(cosmo, hmc, np.exp(lk_arr), - a_arr, prof=nfw) + tkk += ccl.halos.halomod_trispectrum_2h_13( + cosmo, hmc, np.exp(lk_arr), a_arr, prof=nfw + ) - tkk += ccl.halos.halomod_trispectrum_3h(cosmo, hmc, np.exp(lk_arr), - a_arr, prof=nfw) + tkk += ccl.halos.halomod_trispectrum_3h( + cosmo, hmc, np.exp(lk_arr), a_arr, prof=nfw + ) - tkk += ccl.halos.halomod_trispectrum_4h(cosmo, hmc, np.exp(lk_arr), - a_arr, prof=nfw) + tkk += ccl.halos.halomod_trispectrum_4h( + cosmo, hmc, np.exp(lk_arr), a_arr, prof=nfw + ) tkk *= bias1 * bias2 * bias3 * bias4 - tkk += ccl.halos.halomod_trispectrum_1h(cosmo, hmc, np.exp(lk_arr), - a_arr, prof=hod) + tkk += ccl.halos.halomod_trispectrum_1h( + cosmo, hmc, np.exp(lk_arr), a_arr, prof=hod + ) s = self.io.get_sacc_file() isnc = [] @@ -201,12 +211,13 @@ def get_covariance_block( "lens" in tr[i] ) if any(isnc): - warnings.warn("Using linear galaxy bias with 1h term. This should " - "be checked. HOD version need implementation.") + warnings.warn( + "Using linear galaxy bias with 1h term. This should " + "be checked. HOD version need implementation." + ) tk3D = ccl.tk3d.Tk3D(a_arr=a_arr, lk_arr=lk_arr, tkk_arr=tkk) - ell = self.get_ell_eff() cov_cng = ccl.covariances.angular_cl_cov_cNG( cosmo, From 774a44c3b0de466b3162c115dbb4f84c9ab408f3 Mon Sep 17 00:00:00 2001 From: paulrogozenski Date: Wed, 27 Nov 2024 16:27:23 -0500 Subject: [PATCH 11/28] black reformatting --- tjpcov/covariance_fourier_cNG.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tjpcov/covariance_fourier_cNG.py b/tjpcov/covariance_fourier_cNG.py index 0c41b417..4b77f380 100644 --- a/tjpcov/covariance_fourier_cNG.py +++ b/tjpcov/covariance_fourier_cNG.py @@ -193,7 +193,6 @@ def get_covariance_block( cosmo, hmc, np.exp(lk_arr), a_arr, prof=nfw ) - tkk += ccl.halos.halomod_trispectrum_4h( cosmo, hmc, np.exp(lk_arr), a_arr, prof=nfw ) From 7d4619a9f1c93e2051a20e71576384f3c420b18b Mon Sep 17 00:00:00 2001 From: paulrogozenski Date: Wed, 27 Nov 2024 16:52:39 -0500 Subject: [PATCH 12/28] notes for more accurate testing of cNG approximation --- tests/test_covariance_fourier_cNG.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/test_covariance_fourier_cNG.py b/tests/test_covariance_fourier_cNG.py index 006b7b67..9b6b3d89 100644 --- a/tests/test_covariance_fourier_cNG.py +++ b/tests/test_covariance_fourier_cNG.py @@ -71,7 +71,8 @@ def get_fsky(tr1, tr2, tr3, tr4): config = get_config() mf = config["tjpcov"]["mask_file"] - area = hp.nside2pixarea(32) + # TODO: do we need the hp area? + # area = hp.nside2pixarea(32) m1 = hp.read_map(mf[tr1]) m2 = hp.read_map(mf[tr2]) m3 = hp.read_map(mf[tr3]) @@ -119,6 +120,10 @@ def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): na = ccl.ccllib.get_pk_spline_na(cosmo.cosmo) a_arr, _ = ccl.ccllib.get_pk_spline_a(cosmo.cosmo, na, 0) + # TODO: Need to make 1h TK3D object with HOD + # & weight non-HOD TK3D object with gbias factors + # & combine together before call to + # angular_cl_cov_cNG for proper comparison bias1 = bias2 = bias3 = bias4 = 1 if "gc" in tracer_comb1[0]: bias1 = cov_fcNG.bias_lens[tracer_comb1[0]] @@ -131,7 +136,7 @@ def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): if "gc" in tracer_comb2[0]: bias4 = cov_fcNG.bias_lens[tracer_comb2[1]] - + hmc = get_halo_model(cosmo) nfw_profile = get_NFW_profile() tkk_cNG = ccl.halos.halomod_Tk3D_cNG( From ecd7f0b9a33987f3ee188fa459639fd24d1531cb Mon Sep 17 00:00:00 2001 From: paulrogozenski Date: Fri, 13 Dec 2024 15:41:21 -0500 Subject: [PATCH 13/28] Tests created and pass locally --- tests/test_covariance_fourier_cNG.py | 108 +++++++++++++++++++++++++-- tjpcov/covariance_fourier_cNG.py | 45 +++++------ 2 files changed, 119 insertions(+), 34 deletions(-) diff --git a/tests/test_covariance_fourier_cNG.py b/tests/test_covariance_fourier_cNG.py index 9b6b3d89..60de56dd 100644 --- a/tests/test_covariance_fourier_cNG.py +++ b/tests/test_covariance_fourier_cNG.py @@ -50,6 +50,37 @@ def get_config(): return config +def get_hod_model(): + obj = FouriercNGHaloModel(INPUT_YML_cNG) + mass_def = ccl.halos.MassDef200m + cM = ccl.halos.ConcentrationDuffy08(mass_def=mass_def) + hod = ccl.halos.HaloProfileHOD( + mass_def=mass_def, + concentration=cM, + log10Mmin_0=obj.HOD_dict["log10Mmin_0"], + log10Mmin_p=obj.HOD_dict["log10Mmin_p"], + siglnM_0=obj.HOD_dict["siglnM_0"], + siglnM_p=obj.HOD_dict["siglnM_p"], + log10M0_0=obj.HOD_dict["log10M0_0"], + log10M0_p=obj.HOD_dict["log10M0_p"], + log10M1_0=obj.HOD_dict["log10M1_0"], + log10M1_p=obj.HOD_dict["log10M1_p"], + alpha_0=obj.HOD_dict["alpha_0"], + alpha_p=obj.HOD_dict["alpha_p"], + fc_0=obj.HOD_dict["fc_0"], + fc_p=obj.HOD_dict["fc_p"], + bg_0=obj.HOD_dict["bg_0"], + bg_p=obj.HOD_dict["bg_p"], + bmax_0=obj.HOD_dict["bmax_0"], + bmax_p=obj.HOD_dict["bmax_p"], + a_pivot=obj.HOD_dict["a_pivot"], + ns_independent=obj.HOD_dict["ns_independent"], + is_number_counts=obj.HOD_dict["is_number_counts"], + ) + + return hod + + def get_halo_model(cosmo): md = ccl.halos.MassDef200m mf = ccl.halos.MassFuncTinker08(mass_def=md) @@ -115,15 +146,29 @@ def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): np.max(np.abs((covf["cov_nob"] + 1e-100) / (cov_cNG + 1e-100) - 1)) < 1e-10 ) - # CCL covariance na = ccl.ccllib.get_pk_spline_na(cosmo.cosmo) a_arr, _ = ccl.ccllib.get_pk_spline_a(cosmo.cosmo, na, 0) - - # TODO: Need to make 1h TK3D object with HOD - # & weight non-HOD TK3D object with gbias factors - # & combine together before call to - # angular_cl_cov_cNG for proper comparison + tr = {} + tr[1], tr[2] = tracer_comb1 + tr[3], tr[4] = tracer_comb2 + z_max = [] + for i in range(4): + tr_sacc = s.tracers[tr[i + 1]] + z = tr_sacc.z + z_max.append(z.max()) + # Divide by zero errors happen when default a_arr used for 1h term + z_max = np.min(z_max) + + # Array of a. + # Use the a's in the pk spline + na = ccl.ccllib.get_pk_spline_na(cosmo.cosmo) + a_arr, _ = ccl.ccllib.get_pk_spline_a(cosmo.cosmo, na, 0) + # Cut the array for efficiency + sel = 1 / a_arr < z_max + 1 + # Include the next node so that z_max is in the range + sel[np.sum(~sel) - 1] = True + a_arr = a_arr[sel] bias1 = bias2 = bias3 = bias4 = 1 if "gc" in tracer_comb1[0]: bias1 = cov_fcNG.bias_lens[tracer_comb1[0]] @@ -136,13 +181,34 @@ def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): if "gc" in tracer_comb2[0]: bias4 = cov_fcNG.bias_lens[tracer_comb2[1]] - + + biases = bias1 * bias2 * bias3 * bias4 + hmc = get_halo_model(cosmo) nfw_profile = get_NFW_profile() + hod = get_hod_model() + prof_2pt = ccl.halos.profiles_2pt.Profile2ptHOD() + tkk_cNG = ccl.halos.halomod_Tk3D_cNG( cosmo, hmc, prof=nfw_profile, + separable_growth=True, + a_arr=a_arr, + ) + tkk_1h_nfw = ccl.halos.halomod_Tk3D_1h( + cosmo, + hmc, + prof=nfw_profile, + a_arr=a_arr, + ) + tkk_1h_hod = ccl.halos.halomod_Tk3D_1h( + cosmo, + hmc, + prof=hod, + prof12_2pt=prof_2pt, + prof34_2pt=prof_2pt, + a_arr=a_arr, ) ccl_tracers, _ = cov_fcNG.get_tracer_info() @@ -151,7 +217,7 @@ def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): tr3 = ccl_tracers[tracer_comb2[0]] tr4 = ccl_tracers[tracer_comb2[1]] - fsky = get_fsky(tr1, tr2, tr3, tr4) + fsky = get_fsky(*tracer_comb1, *tracer_comb2) cov_ccl = ccl.covariances.angular_cl_cov_cNG( cosmo, @@ -164,6 +230,32 @@ def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): fsky=fsky, ) + cov_ccl_1h_nfw = ccl.covariances.angular_cl_cov_cNG( + cosmo, + tracer1=tr1, + tracer2=tr2, + tracer3=tr3, + tracer4=tr4, + ell=ell, + t_of_kk_a=tkk_1h_nfw, + fsky=fsky, + ) + + cov_ccl_1h_hod = ccl.covariances.angular_cl_cov_cNG( + cosmo, + tracer1=tr1, + tracer2=tr2, + tracer3=tr3, + tracer4=tr4, + ell=ell, + t_of_kk_a=tkk_1h_hod, + fsky=fsky, + ) + # An unfortunately messy way to to calculate the 234h terms + # with an NFW Profile and only the 1h term with an HOD + # using current CCL infrastructure. + cov_ccl = biases * (cov_ccl - cov_ccl_1h_nfw) + cov_ccl_1h_hod + assert np.max(np.fabs(np.diag(cov_cNG / cov_ccl - 1))) < 1e-5 assert np.max(np.fabs(cov_cNG / cov_ccl - 1)) < 1e-3 diff --git a/tjpcov/covariance_fourier_cNG.py b/tjpcov/covariance_fourier_cNG.py index 4b77f380..267ae035 100644 --- a/tjpcov/covariance_fourier_cNG.py +++ b/tjpcov/covariance_fourier_cNG.py @@ -3,7 +3,6 @@ # import healpy as hp import numpy as np import pyccl as ccl -import warnings from .covariance_builder import CovarianceFourier @@ -104,17 +103,19 @@ def get_covariance_block( tr = {} tr[1], tr[2] = tracer_comb1 tr[3], tr[4] = tracer_comb2 - cosmo = self.get_cosmology() mass_def = ccl.halos.MassDef200m hmf = ccl.halos.MassFuncTinker08(mass_def=mass_def) hbf = ccl.halos.HaloBiasTinker10(mass_def=mass_def) cM = ccl.halos.ConcentrationDuffy08(mass_def=mass_def) + prof_2pt = ccl.halos.profiles_2pt.Profile2ptHOD() nfw = ccl.halos.HaloProfileNFW( mass_def=mass_def, concentration=cM, fourier_analytic=True ) hmc = ccl.halos.HMCalculator( - mass_function=hmf, halo_bias=hbf, mass_def=mass_def + mass_function=hmf, + halo_bias=hbf, + mass_def=mass_def, ) hod = ccl.halos.HaloProfileHOD( @@ -148,10 +149,8 @@ def get_covariance_block( for i in range(4): tr_sacc = sacc_file.tracers[tr[i + 1]] z = tr_sacc.z - # z, nz = tr_sacc.z, tr_sacc.nz - # z_min.append(z[np.where(nz > 0)[0][0]]) - # z_max.append(z[np.where(np.cumsum(nz)/np.sum(nz) > 0.999)[0][0]]) z_max.append(z.max()) + # Divide by zero errors happen when default a_arr used for 1h term z_max = np.min(z_max) @@ -179,10 +178,10 @@ def get_covariance_block( # TODO: This should be unified with the other classes in # CovarianceBuilder. fsky = np.mean(masks[1] * masks[2] * masks[3] * masks[4]) - # Tk3D = b1*b2*b3*b4 * T_234h (NFW) + T_1h (HOD) + tkk = ccl.halos.pk_4pt.halomod_trispectrum_2h_22( - cosmo, hmc, np.exp(lk_arr), a_arr, prof=nfw + cosmo, hmc, np.exp(lk_arr), a_arr, prof=nfw, separable_growth=True ) tkk += ccl.halos.halomod_trispectrum_2h_13( @@ -190,33 +189,28 @@ def get_covariance_block( ) tkk += ccl.halos.halomod_trispectrum_3h( - cosmo, hmc, np.exp(lk_arr), a_arr, prof=nfw + cosmo, hmc, np.exp(lk_arr), a_arr, prof=nfw, separable_growth=True ) tkk += ccl.halos.halomod_trispectrum_4h( - cosmo, hmc, np.exp(lk_arr), a_arr, prof=nfw + cosmo, hmc, np.exp(lk_arr), a_arr, prof=nfw, separable_growth=True ) tkk *= bias1 * bias2 * bias3 * bias4 tkk += ccl.halos.halomod_trispectrum_1h( - cosmo, hmc, np.exp(lk_arr), a_arr, prof=hod + cosmo, + hmc, + np.exp(lk_arr), + a_arr, + prof=hod, + prof12_2pt=prof_2pt, + prof34_2pt=prof_2pt, ) - s = self.io.get_sacc_file() - isnc = [] - for i in range(1, 5): - isnc[i] = (s.tracers[tr[i]].quantity == "galaxy_density") or ( - "lens" in tr[i] - ) - if any(isnc): - warnings.warn( - "Using linear galaxy bias with 1h term. This should " - "be checked. HOD version need implementation." - ) - - tk3D = ccl.tk3d.Tk3D(a_arr=a_arr, lk_arr=lk_arr, tkk_arr=tkk) - + tk3D = ccl.tk3d.Tk3D( + a_arr=a_arr, lk_arr=lk_arr, tkk_arr=tkk, is_logt=False + ) ell = self.get_ell_eff() cov_cng = ccl.covariances.angular_cl_cov_cNG( cosmo, @@ -236,7 +230,6 @@ def get_covariance_block( cov_full = np.zeros((nbpw, ncell1, nbpw, ncell2)) cov_full[:, 0, :, 0] = cov_cng cov_full = cov_full.reshape((nbpw * ncell1, nbpw * ncell2)) - np.savez_compressed(fname, cov=cov_full, cov_nob=cov_cng) if not include_b_modes: From a7d1a008b2ed4e92297960494cdab82616e873fc Mon Sep 17 00:00:00 2001 From: paulrogozenski <43966955+paulrogozenski@users.noreply.github.com> Date: Fri, 13 Dec 2024 13:45:45 -0700 Subject: [PATCH 14/28] Linters fix --- tjpcov/clusters_helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tjpcov/clusters_helpers.py b/tjpcov/clusters_helpers.py index eba73e66..bb4b619f 100644 --- a/tjpcov/clusters_helpers.py +++ b/tjpcov/clusters_helpers.py @@ -142,7 +142,7 @@ def two_fast_algorithm(self, z1, z2): print( err, f"""\n - Value you tried to interpolate: {max(r1,r2)} Mpc, + Value you tried to interpolate: {max(r1,r2)} Mpc, Input r {r1}, {r2} Valid range range: [{self.r_grid[self.idx_min]}, {self.r_grid[self.idx_max]}] From cc2e71cd22440b94bb5c0639f70444f97ceae9d8 Mon Sep 17 00:00:00 2001 From: paulrogozenski <43966955+paulrogozenski@users.noreply.github.com> Date: Fri, 13 Dec 2024 13:46:44 -0700 Subject: [PATCH 15/28] Linters fix --- tjpcov/clusters_helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tjpcov/clusters_helpers.py b/tjpcov/clusters_helpers.py index bb4b619f..604f3cfe 100644 --- a/tjpcov/clusters_helpers.py +++ b/tjpcov/clusters_helpers.py @@ -142,7 +142,7 @@ def two_fast_algorithm(self, z1, z2): print( err, f"""\n - Value you tried to interpolate: {max(r1,r2)} Mpc, + Value you tried to interpolate: {max(r1, r2)} Mpc, Input r {r1}, {r2} Valid range range: [{self.r_grid[self.idx_min]}, {self.r_grid[self.idx_max]}] From a494da0af77d80c89f47bba48b30194ed9b6d419 Mon Sep 17 00:00:00 2001 From: paulrogozenski Date: Mon, 16 Dec 2024 12:23:30 -0500 Subject: [PATCH 16/28] change to spline integration method for testing (more stable) --- tests/test_covariance_fourier_cNG.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test_covariance_fourier_cNG.py b/tests/test_covariance_fourier_cNG.py index 60de56dd..eaa2bd90 100644 --- a/tests/test_covariance_fourier_cNG.py +++ b/tests/test_covariance_fourier_cNG.py @@ -136,6 +136,7 @@ def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): tracer_comb1=tracer_comb1, tracer_comb2=tracer_comb2, include_b_modes=False, + integration_method="spline", ) # Check saved file @@ -228,6 +229,7 @@ def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): ell=ell, t_of_kk_a=tkk_cNG, fsky=fsky, + integration_method="spline", ) cov_ccl_1h_nfw = ccl.covariances.angular_cl_cov_cNG( @@ -239,6 +241,7 @@ def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): ell=ell, t_of_kk_a=tkk_1h_nfw, fsky=fsky, + integration_method="spline", ) cov_ccl_1h_hod = ccl.covariances.angular_cl_cov_cNG( @@ -250,6 +253,7 @@ def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): ell=ell, t_of_kk_a=tkk_1h_hod, fsky=fsky, + integration_method="spline", ) # An unfortunately messy way to to calculate the 234h terms # with an NFW Profile and only the 1h term with an HOD From 55307005a108f1863a53daf623c15b8d5cc34ede Mon Sep 17 00:00:00 2001 From: paulrogozenski Date: Mon, 16 Dec 2024 12:39:46 -0500 Subject: [PATCH 17/28] change to spline integration method for testing (more stable) --- tests/test_covariance_fourier_cNG.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/test_covariance_fourier_cNG.py b/tests/test_covariance_fourier_cNG.py index eaa2bd90..cb6a3193 100644 --- a/tests/test_covariance_fourier_cNG.py +++ b/tests/test_covariance_fourier_cNG.py @@ -131,12 +131,12 @@ def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): cosmo = cov_fcNG.get_cosmology() s = cov_fcNG.io.get_sacc_file() ell, _ = s.get_ell_cl("cl_00", "DESgc__0", "DESgc__0") - + integration_method = "spline" cov_cNG = cov_fcNG.get_covariance_block( tracer_comb1=tracer_comb1, tracer_comb2=tracer_comb2, include_b_modes=False, - integration_method="spline", + integration_method=integration_method, ) # Check saved file @@ -229,7 +229,7 @@ def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): ell=ell, t_of_kk_a=tkk_cNG, fsky=fsky, - integration_method="spline", + integration_method=integration_method, ) cov_ccl_1h_nfw = ccl.covariances.angular_cl_cov_cNG( @@ -241,7 +241,7 @@ def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): ell=ell, t_of_kk_a=tkk_1h_nfw, fsky=fsky, - integration_method="spline", + integration_method=integration_method, ) cov_ccl_1h_hod = ccl.covariances.angular_cl_cov_cNG( @@ -253,7 +253,7 @@ def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): ell=ell, t_of_kk_a=tkk_1h_hod, fsky=fsky, - integration_method="spline", + integration_method=integration_method, ) # An unfortunately messy way to to calculate the 234h terms # with an NFW Profile and only the 1h term with an HOD @@ -268,6 +268,7 @@ def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): tracer_comb1=tracer_comb1, tracer_comb2=tracer_comb2, include_b_modes=True, + integration_method=integration_method, ) # Check saved assert ( @@ -303,6 +304,7 @@ def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): tracer_comb1=tracer_comb1, tracer_comb2=tracer_comb2, include_b_modes=False, + integration_method=integration_method, ) assert np.all(covf["cov_nob"] == cov_cNG) @@ -310,6 +312,7 @@ def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): tracer_comb1=tracer_comb1, tracer_comb2=tracer_comb2, include_b_modes=True, + integration_method=integration_method, ) assert np.all(covf["cov"] == cov_cNG_zb) From 8e76abcd6c0d1b10bfffd256cce7b56383a1b52d Mon Sep 17 00:00:00 2001 From: paulrogozenski Date: Tue, 17 Dec 2024 10:34:45 -0500 Subject: [PATCH 18/28] refactoring to allow reading in of fsky directly with tests --- tests/data/conf_covariance_cNG_fsky.yaml | 69 +++++ tests/test_covariance_fourier_cNG_fsky.py | 309 ++++++++++++++++++++++ tjpcov/covariance_fourier_cNG.py | 14 +- tjpcov/covariance_fourier_cNG_fsky.py | 34 +++ 4 files changed, 425 insertions(+), 1 deletion(-) create mode 100644 tests/data/conf_covariance_cNG_fsky.yaml create mode 100644 tests/test_covariance_fourier_cNG_fsky.py create mode 100644 tjpcov/covariance_fourier_cNG_fsky.py diff --git a/tests/data/conf_covariance_cNG_fsky.yaml b/tests/data/conf_covariance_cNG_fsky.yaml new file mode 100644 index 00000000..4dab1689 --- /dev/null +++ b/tests/data/conf_covariance_cNG_fsky.yaml @@ -0,0 +1,69 @@ +tjpcov: + # sacc input file + sacc_file: ./tests/benchmarks/32_DES_tjpcov_bm/cls_cov.fits + + # 'set' from parameters OR pass CCL cosmology object OR yaml file + cosmo: 'set' + + # Setting mask OR fsky approximation + mask_file: + DESgc__0: ./tests/benchmarks/32_DES_tjpcov_bm/catalogs/mask_DESgc__0.fits.gz + DESwl__0: ./tests/benchmarks/32_DES_tjpcov_bm/catalogs/DESwlMETACAL_mask_zbin0_ns32.fits.gz + DESwl__1: ./tests/benchmarks/32_DES_tjpcov_bm/catalogs/DESwlMETACAL_mask_zbin1_ns32.fits.gz + + mask_names: + DESgc__0: mask_DESgc0 + DESwl__0: mask_DESwl0 + DESwl__1: mask_DESwl1 + + outdir: ./tests/tmp/ + + # Survey params: + # 5 lens bins + Ngal_DESgc__0: 26 + + Ngal_DESwl__0: 26 + Ngal_DESwl__1: 26 + # # constant bin sigma_e + sigma_e_DESwl__0: 0.26 + sigma_e_DESwl__1: 0.26 + + # linear bias for lenses constant for redshift bin (example notebook) + bias_DESgc__0: 1.48 + + # IA: 0.5 + +parameters: + # Not used for while (read by ccl.cosmo): + Omega_c: 0.2640 + Omega_b: 0.0493 + h: 0.6736 + n_s: 0.9649 + sigma8: 0.8111 + w0: -1 + wa: 0 + transfer_function: 'boltzmann_camb' +HOD: + # automatically creates massdef and concentration objects + log10Mmin_0: 12.0 + log10Mmin_p: 0.0 + siglnM_0: 0.4 + siglnM_p: 0.0 + log10M0_0: 7.0 + log10M0_p: 0.0 + log10M1_0: 13.3 + log10M1_p: 0.0 + alpha_0: 1.0 + alpha_p: 0.0 + fc_0: 1.0 + fc_p: 0.0 + bg_0: 1.0 + bg_p: 0.0 + bmax_0: 1.0 + bmax_p: 0.0 + a_pivot: 1.0 + ns_independent: False + is_number_counts: True + +GaussianFsky: + fsky: 0.05 \ No newline at end of file diff --git a/tests/test_covariance_fourier_cNG_fsky.py b/tests/test_covariance_fourier_cNG_fsky.py new file mode 100644 index 00000000..385a91f9 --- /dev/null +++ b/tests/test_covariance_fourier_cNG_fsky.py @@ -0,0 +1,309 @@ +#!/usr/bin/python3 +import os +import shutil + +import numpy as np +import pyccl as ccl +import pytest +import sacc +import yaml + +from tjpcov.covariance_fourier_cNG_fsky import FouriercNGHaloModelFsky + +ROOT = "./tests/benchmarks/32_DES_tjpcov_bm/" +INPUT_YML_cNG = "./tests/data/conf_covariance_cNG.yaml" +OUTDIR = "./tests/tmp/" +NSIDE = 32 + + +def setup_module(): + os.makedirs(OUTDIR, exist_ok=True) + + +def teardown_module(): + shutil.rmtree(OUTDIR) + + +@pytest.fixture(autouse=True) +def teardown_test(): + clean_outdir() + + +def clean_outdir(): + os.system(f"rm -f {OUTDIR}*") + + +@pytest.fixture +def sacc_file(): + return sacc.Sacc.load_fits(ROOT + "cls_cov.fits") + + +@pytest.fixture +def cov_fcNG(): + return FouriercNGHaloModelFsky(INPUT_YML_cNG) + + +def get_config(): + with open(INPUT_YML_cNG) as f: + config = yaml.safe_load(f) + return config + + +def get_hod_model(): + obj = FouriercNGHaloModelFsky(INPUT_YML_cNG) + mass_def = ccl.halos.MassDef200m + cM = ccl.halos.ConcentrationDuffy08(mass_def=mass_def) + hod = ccl.halos.HaloProfileHOD( + mass_def=mass_def, + concentration=cM, + log10Mmin_0=obj.HOD_dict["log10Mmin_0"], + log10Mmin_p=obj.HOD_dict["log10Mmin_p"], + siglnM_0=obj.HOD_dict["siglnM_0"], + siglnM_p=obj.HOD_dict["siglnM_p"], + log10M0_0=obj.HOD_dict["log10M0_0"], + log10M0_p=obj.HOD_dict["log10M0_p"], + log10M1_0=obj.HOD_dict["log10M1_0"], + log10M1_p=obj.HOD_dict["log10M1_p"], + alpha_0=obj.HOD_dict["alpha_0"], + alpha_p=obj.HOD_dict["alpha_p"], + fc_0=obj.HOD_dict["fc_0"], + fc_p=obj.HOD_dict["fc_p"], + bg_0=obj.HOD_dict["bg_0"], + bg_p=obj.HOD_dict["bg_p"], + bmax_0=obj.HOD_dict["bmax_0"], + bmax_p=obj.HOD_dict["bmax_p"], + a_pivot=obj.HOD_dict["a_pivot"], + ns_independent=obj.HOD_dict["ns_independent"], + is_number_counts=obj.HOD_dict["is_number_counts"], + ) + + return hod + + +def get_halo_model(cosmo): + md = ccl.halos.MassDef200m + mf = ccl.halos.MassFuncTinker08(mass_def=md) + hb = ccl.halos.HaloBiasTinker10(mass_def=md) + hmc = ccl.halos.HMCalculator(mass_function=mf, halo_bias=hb, mass_def=md) + + return hmc + + +def get_NFW_profile(): + md = ccl.halos.MassDef200m + cm = ccl.halos.ConcentrationDuffy08(mass_def=md) + pNFW = ccl.halos.HaloProfileNFW(mass_def=md, concentration=cm) + + return pNFW + + +def get_fsky(tr1, tr2, tr3, tr4): + config = get_config() + fsky = config["GaussianFsky"].get("fsky", None) + return fsky + + +def test_smoke(): + FouriercNGHaloModelFsky(INPUT_YML_cNG) + + +@pytest.mark.parametrize( + "tracer_comb1,tracer_comb2", + [ + (("DESgc__0", "DESgc__0"), ("DESgc__0", "DESgc__0")), + (("DESgc__0", "DESwl__0"), ("DESwl__0", "DESwl__0")), + (("DESgc__0", "DESgc__0"), ("DESwl__0", "DESwl__0")), + (("DESwl__0", "DESwl__0"), ("DESwl__0", "DESwl__0")), + (("DESwl__0", "DESwl__0"), ("DESwl__1", "DESwl__1")), + ], +) +def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): + # TJPCov covariance + cosmo = cov_fcNG.get_cosmology() + s = cov_fcNG.io.get_sacc_file() + ell, _ = s.get_ell_cl("cl_00", "DESgc__0", "DESgc__0") + integration_method = "spline" + cov_cNG = cov_fcNG.get_covariance_block( + tracer_comb1=tracer_comb1, + tracer_comb2=tracer_comb2, + include_b_modes=False, + integration_method=integration_method, + ) + + # Check saved file + covf = np.load( + OUTDIR + "cng_{}_{}_{}_{}.npz".format(*tracer_comb1, *tracer_comb2) + ) + assert ( + np.max(np.abs((covf["cov_nob"] + 1e-100) / (cov_cNG + 1e-100) - 1)) + < 1e-10 + ) + # CCL covariance + na = ccl.ccllib.get_pk_spline_na(cosmo.cosmo) + a_arr, _ = ccl.ccllib.get_pk_spline_a(cosmo.cosmo, na, 0) + tr = {} + tr[1], tr[2] = tracer_comb1 + tr[3], tr[4] = tracer_comb2 + z_max = [] + for i in range(4): + tr_sacc = s.tracers[tr[i + 1]] + z = tr_sacc.z + z_max.append(z.max()) + # Divide by zero errors happen when default a_arr used for 1h term + z_max = np.min(z_max) + + # Array of a. + # Use the a's in the pk spline + na = ccl.ccllib.get_pk_spline_na(cosmo.cosmo) + a_arr, _ = ccl.ccllib.get_pk_spline_a(cosmo.cosmo, na, 0) + # Cut the array for efficiency + sel = 1 / a_arr < z_max + 1 + # Include the next node so that z_max is in the range + sel[np.sum(~sel) - 1] = True + a_arr = a_arr[sel] + bias1 = bias2 = bias3 = bias4 = 1 + if "gc" in tracer_comb1[0]: + bias1 = cov_fcNG.bias_lens[tracer_comb1[0]] + + if "gc" in tracer_comb1[1]: + bias2 = cov_fcNG.bias_lens[tracer_comb1[1]] + + if "gc" in tracer_comb2[0]: + bias3 = cov_fcNG.bias_lens[tracer_comb2[0]] + + if "gc" in tracer_comb2[0]: + bias4 = cov_fcNG.bias_lens[tracer_comb2[1]] + + biases = bias1 * bias2 * bias3 * bias4 + + hmc = get_halo_model(cosmo) + nfw_profile = get_NFW_profile() + hod = get_hod_model() + prof_2pt = ccl.halos.profiles_2pt.Profile2ptHOD() + + tkk_cNG = ccl.halos.halomod_Tk3D_cNG( + cosmo, + hmc, + prof=nfw_profile, + separable_growth=True, + a_arr=a_arr, + ) + tkk_1h_nfw = ccl.halos.halomod_Tk3D_1h( + cosmo, + hmc, + prof=nfw_profile, + a_arr=a_arr, + ) + tkk_1h_hod = ccl.halos.halomod_Tk3D_1h( + cosmo, + hmc, + prof=hod, + prof12_2pt=prof_2pt, + prof34_2pt=prof_2pt, + a_arr=a_arr, + ) + + ccl_tracers, _ = cov_fcNG.get_tracer_info() + tr1 = ccl_tracers[tracer_comb1[0]] + tr2 = ccl_tracers[tracer_comb1[1]] + tr3 = ccl_tracers[tracer_comb2[0]] + tr4 = ccl_tracers[tracer_comb2[1]] + + fsky = get_fsky(*tracer_comb1, *tracer_comb2) + + cov_ccl = ccl.covariances.angular_cl_cov_cNG( + cosmo, + tracer1=tr1, + tracer2=tr2, + tracer3=tr3, + tracer4=tr4, + ell=ell, + t_of_kk_a=tkk_cNG, + fsky=fsky, + integration_method=integration_method, + ) + + cov_ccl_1h_nfw = ccl.covariances.angular_cl_cov_cNG( + cosmo, + tracer1=tr1, + tracer2=tr2, + tracer3=tr3, + tracer4=tr4, + ell=ell, + t_of_kk_a=tkk_1h_nfw, + fsky=fsky, + integration_method=integration_method, + ) + + cov_ccl_1h_hod = ccl.covariances.angular_cl_cov_cNG( + cosmo, + tracer1=tr1, + tracer2=tr2, + tracer3=tr3, + tracer4=tr4, + ell=ell, + t_of_kk_a=tkk_1h_hod, + fsky=fsky, + integration_method=integration_method, + ) + # An unfortunately messy way to to calculate the 234h terms + # with an NFW Profile and only the 1h term with an HOD + # using current CCL infrastructure. + cov_ccl = biases * (cov_ccl - cov_ccl_1h_nfw) + cov_ccl_1h_hod + + assert np.max(np.fabs(np.diag(cov_cNG / cov_ccl - 1))) < 1e-5 + assert np.max(np.fabs(cov_cNG / cov_ccl - 1)) < 1e-3 + + # Check you get zeroed B-modes + cov_cNG_zb = cov_fcNG.get_covariance_block( + tracer_comb1=tracer_comb1, + tracer_comb2=tracer_comb2, + include_b_modes=True, + integration_method=integration_method, + ) + # Check saved + assert ( + np.max(np.abs((covf["cov"] + 1e-100) / (cov_cNG_zb + 1e-100) - 1)) + < 1e-10 + ) + + ix1 = s.indices(tracers=tracer_comb1) + ix2 = s.indices(tracers=tracer_comb2) + ncell1 = int(ix1.size / ell.size) + ncell2 = int(ix2.size / ell.size) + + # The covariance will have all correlations, including when EB == BE + if (ncell1 == 3) and (tracer_comb1[0] == tracer_comb1[1]): + ncell1 += 1 + if (ncell2 == 3) and (tracer_comb2[0] == tracer_comb2[1]): + ncell2 += 1 + + assert cov_cNG_zb.shape == (ell.size * ncell1, ell.size * ncell2) + # Check the blocks + cov_cNG_zb = cov_cNG_zb.reshape((ell.size, ncell1, ell.size, ncell2)) + # Check the reshape has the correct ordering + assert cov_cNG_zb[:, 0, :, 0].flatten() == pytest.approx( + cov_cNG.flatten(), rel=1e-10 + ) + assert np.all(cov_cNG_zb[:, 1::, :, 1::] == 0) + + # Check get_cNG_cov reads file + covf = np.load( + OUTDIR + "cng_{}_{}_{}_{}.npz".format(*tracer_comb1, *tracer_comb2) + ) + cov_cNG = cov_fcNG.get_covariance_block( + tracer_comb1=tracer_comb1, + tracer_comb2=tracer_comb2, + include_b_modes=False, + integration_method=integration_method, + ) + assert np.all(covf["cov_nob"] == cov_cNG) + + cov_cNG_zb = cov_fcNG.get_covariance_block( + tracer_comb1=tracer_comb1, + tracer_comb2=tracer_comb2, + include_b_modes=True, + integration_method=integration_method, + ) + + assert np.all(covf["cov"] == cov_cNG_zb) diff --git a/tjpcov/covariance_fourier_cNG.py b/tjpcov/covariance_fourier_cNG.py index 267ae035..f7b907fc 100644 --- a/tjpcov/covariance_fourier_cNG.py +++ b/tjpcov/covariance_fourier_cNG.py @@ -55,6 +55,18 @@ def __init__(self, config): + " in the HOD header for cNG calculation" ) + def _get_fsky(self, masks={}): + """Returns the fractional sky area from the mean survey masks. + + Args: + masks (:obj:`dict`): dictionary containing the survey + masks of the relevant tracers. + Returns: + - (:obj:`float`): fractional sky area. + """ + fsky = np.mean(masks[1] * masks[2] * masks[3] * masks[4]) + return fsky + def get_covariance_block( self, tracer_comb1, @@ -177,7 +189,7 @@ def get_covariance_block( masks = self.get_masks_dict(tr, {}) # TODO: This should be unified with the other classes in # CovarianceBuilder. - fsky = np.mean(masks[1] * masks[2] * masks[3] * masks[4]) + fsky = self._get_fsky(self, masks=masks) # Tk3D = b1*b2*b3*b4 * T_234h (NFW) + T_1h (HOD) tkk = ccl.halos.pk_4pt.halomod_trispectrum_2h_22( diff --git a/tjpcov/covariance_fourier_cNG_fsky.py b/tjpcov/covariance_fourier_cNG_fsky.py new file mode 100644 index 00000000..791ede9d --- /dev/null +++ b/tjpcov/covariance_fourier_cNG_fsky.py @@ -0,0 +1,34 @@ +from .covariance_fourier_cNG import FouriercNGHaloModel + + +class FouriercNGHaloModelFsky(FouriercNGHaloModel): + """Class to compute the CellxCell Halo Model cNG Covariance.""" + + cov_type = "cNG" + + def __init__(self, config): + """Initialize the class with a config file or dictionary. + + Args: + config (dict or str): If dict, it returns the configuration + dictionary directly. If string, it asumes a YAML file and + parses it. + """ + super().__init__(config) + + self.fsky = self.config["GaussianFsky"].get("fsky", None) + if self.fsky is None: + raise ValueError( + "You need to set fsky for FouriercNGHaloModelFsky" + ) + + def _get_fsky(self, masks={}): + """Returns the fractional sky area from user input. + + Args: + masks (:obj:`dict`): dictionary containing the survey + masks of the relevant tracers (empty in this case). + Returns: + - (:obj:`float`): fractional sky area. + """ + return self.fsky From fa6d3c4cb8c6bb7b5c6b0afaf1d8d7d317d5f403 Mon Sep 17 00:00:00 2001 From: paulrogozenski Date: Tue, 17 Dec 2024 10:35:54 -0500 Subject: [PATCH 19/28] refactoring to allow reading in of fsky directly with tests --- tjpcov/covariance_fourier_cNG.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tjpcov/covariance_fourier_cNG.py b/tjpcov/covariance_fourier_cNG.py index f7b907fc..b012099c 100644 --- a/tjpcov/covariance_fourier_cNG.py +++ b/tjpcov/covariance_fourier_cNG.py @@ -189,7 +189,7 @@ def get_covariance_block( masks = self.get_masks_dict(tr, {}) # TODO: This should be unified with the other classes in # CovarianceBuilder. - fsky = self._get_fsky(self, masks=masks) + fsky = self._get_fsky(masks=masks) # Tk3D = b1*b2*b3*b4 * T_234h (NFW) + T_1h (HOD) tkk = ccl.halos.pk_4pt.halomod_trispectrum_2h_22( From 1760ec3aef28bf5fa7e1503774c4bce6399fca60 Mon Sep 17 00:00:00 2001 From: paulrogozenski Date: Tue, 17 Dec 2024 10:51:25 -0500 Subject: [PATCH 20/28] refactoring to allow reading in of fsky directly with tests --- tests/test_covariance_fourier_cNG_fsky.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_covariance_fourier_cNG_fsky.py b/tests/test_covariance_fourier_cNG_fsky.py index 385a91f9..12381199 100644 --- a/tests/test_covariance_fourier_cNG_fsky.py +++ b/tests/test_covariance_fourier_cNG_fsky.py @@ -11,7 +11,7 @@ from tjpcov.covariance_fourier_cNG_fsky import FouriercNGHaloModelFsky ROOT = "./tests/benchmarks/32_DES_tjpcov_bm/" -INPUT_YML_cNG = "./tests/data/conf_covariance_cNG.yaml" +INPUT_YML_cNG = "./tests/data/conf_covariance_cNG_fsky.yaml" OUTDIR = "./tests/tmp/" NSIDE = 32 From 59fa8b41312baced84fc43337512b4004e23ee94 Mon Sep 17 00:00:00 2001 From: paulrogozenski Date: Thu, 19 Dec 2024 15:04:47 -0500 Subject: [PATCH 21/28] _get_fsky refactoring and added HOD generalization for computing the 1h term regardless of whether the tracer is a numbercounts tracer or not --- tests/data/conf_covariance_cNG.yaml | 3 +- tests/data/conf_covariance_cNG_fsky.yaml | 1 - tests/test_covariance_fourier_cNG.py | 2 +- tests/test_covariance_fourier_cNG_fsky.py | 2 +- tjpcov/covariance_fourier_cNG.py | 51 ++++++++++++++++++++--- tjpcov/covariance_fourier_cNG_fsky.py | 4 +- 6 files changed, 50 insertions(+), 13 deletions(-) diff --git a/tests/data/conf_covariance_cNG.yaml b/tests/data/conf_covariance_cNG.yaml index 569a934a..6dd0922a 100644 --- a/tests/data/conf_covariance_cNG.yaml +++ b/tests/data/conf_covariance_cNG.yaml @@ -62,5 +62,4 @@ HOD: bmax_0: 1.0 bmax_p: 0.0 a_pivot: 1.0 - ns_independent: False - is_number_counts: True \ No newline at end of file + ns_independent: False \ No newline at end of file diff --git a/tests/data/conf_covariance_cNG_fsky.yaml b/tests/data/conf_covariance_cNG_fsky.yaml index 4dab1689..7daddc47 100644 --- a/tests/data/conf_covariance_cNG_fsky.yaml +++ b/tests/data/conf_covariance_cNG_fsky.yaml @@ -63,7 +63,6 @@ HOD: bmax_p: 0.0 a_pivot: 1.0 ns_independent: False - is_number_counts: True GaussianFsky: fsky: 0.05 \ No newline at end of file diff --git a/tests/test_covariance_fourier_cNG.py b/tests/test_covariance_fourier_cNG.py index cb6a3193..aee0b4e5 100644 --- a/tests/test_covariance_fourier_cNG.py +++ b/tests/test_covariance_fourier_cNG.py @@ -75,7 +75,7 @@ def get_hod_model(): bmax_p=obj.HOD_dict["bmax_p"], a_pivot=obj.HOD_dict["a_pivot"], ns_independent=obj.HOD_dict["ns_independent"], - is_number_counts=obj.HOD_dict["is_number_counts"], + is_number_counts=True, ) return hod diff --git a/tests/test_covariance_fourier_cNG_fsky.py b/tests/test_covariance_fourier_cNG_fsky.py index 12381199..19c4a757 100644 --- a/tests/test_covariance_fourier_cNG_fsky.py +++ b/tests/test_covariance_fourier_cNG_fsky.py @@ -74,7 +74,7 @@ def get_hod_model(): bmax_p=obj.HOD_dict["bmax_p"], a_pivot=obj.HOD_dict["a_pivot"], ns_independent=obj.HOD_dict["ns_independent"], - is_number_counts=obj.HOD_dict["is_number_counts"], + is_number_counts=True, ) return hod diff --git a/tjpcov/covariance_fourier_cNG.py b/tjpcov/covariance_fourier_cNG.py index b012099c..a6b17e2c 100644 --- a/tjpcov/covariance_fourier_cNG.py +++ b/tjpcov/covariance_fourier_cNG.py @@ -43,7 +43,7 @@ def __init__(self, config): "bmax_p": None, "a_pivot": None, "ns_independent": None, - "is_number_counts": None, + "is_number_counts": True, } for key in self.HOD_dict.keys(): @@ -55,15 +55,16 @@ def __init__(self, config): + " in the HOD header for cNG calculation" ) - def _get_fsky(self, masks={}): + def _get_fsky(self, tr=None): """Returns the fractional sky area from the mean survey masks. Args: masks (:obj:`dict`): dictionary containing the survey - masks of the relevant tracers. + tracers to obtain the survey mask. Returns: - (:obj:`float`): fractional sky area. """ + masks = self.get_masks_dict(tr, {}) fsky = np.mean(masks[1] * masks[2] * masks[3] * masks[4]) return fsky @@ -153,6 +154,29 @@ def get_covariance_block( ns_independent=self.HOD_dict["ns_independent"], is_number_counts=self.HOD_dict["is_number_counts"], ) + hod_no_numbercounts = ccl.halos.HaloProfileHOD( + mass_def=mass_def, + concentration=cM, + log10Mmin_0=self.HOD_dict["log10Mmin_0"], + log10Mmin_p=self.HOD_dict["log10Mmin_p"], + siglnM_0=self.HOD_dict["siglnM_0"], + siglnM_p=self.HOD_dict["siglnM_p"], + log10M0_0=self.HOD_dict["log10M0_0"], + log10M0_p=self.HOD_dict["log10M0_p"], + log10M1_0=self.HOD_dict["log10M1_0"], + log10M1_p=self.HOD_dict["log10M1_p"], + alpha_0=self.HOD_dict["alpha_0"], + alpha_p=self.HOD_dict["alpha_p"], + fc_0=self.HOD_dict["fc_0"], + fc_p=self.HOD_dict["fc_p"], + bg_0=self.HOD_dict["bg_0"], + bg_p=self.HOD_dict["bg_p"], + bmax_0=self.HOD_dict["bmax_0"], + bmax_p=self.HOD_dict["bmax_p"], + a_pivot=self.HOD_dict["a_pivot"], + ns_independent=self.HOD_dict["ns_independent"], + is_number_counts=False, + ) # Get range of redshifts. z_min = 0 for compatibility with the limber # integrals @@ -186,10 +210,9 @@ def get_covariance_block( ccl_tracers, _ = self.get_tracer_info() - masks = self.get_masks_dict(tr, {}) # TODO: This should be unified with the other classes in # CovarianceBuilder. - fsky = self._get_fsky(masks=masks) + fsky = self._get_fsky(tr=tr) # Tk3D = b1*b2*b3*b4 * T_234h (NFW) + T_1h (HOD) tkk = ccl.halos.pk_4pt.halomod_trispectrum_2h_22( @@ -210,12 +233,28 @@ def get_covariance_block( tkk *= bias1 * bias2 * bias3 * bias4 + isnc = {} + for i in range(1, 5): + isnc[i] = ( + sacc_file.tracers[tr[i]].quantity == "galaxy_density" + ) or ("lens" in tr[i]) + + # Choose using the HOD with or without number_counts = True + # based on the results of isnc + + prof1 = hod if isnc[1] else hod_no_numbercounts + prof2 = hod if isnc[2] else hod_no_numbercounts + prof3 = hod if isnc[3] else hod_no_numbercounts + prof4 = hod if isnc[4] else hod_no_numbercounts tkk += ccl.halos.halomod_trispectrum_1h( cosmo, hmc, np.exp(lk_arr), a_arr, - prof=hod, + prof=prof1, + prof2=prof2, + prof3=prof3, + prof4=prof4, prof12_2pt=prof_2pt, prof34_2pt=prof_2pt, ) diff --git a/tjpcov/covariance_fourier_cNG_fsky.py b/tjpcov/covariance_fourier_cNG_fsky.py index 791ede9d..aeec8a25 100644 --- a/tjpcov/covariance_fourier_cNG_fsky.py +++ b/tjpcov/covariance_fourier_cNG_fsky.py @@ -22,12 +22,12 @@ def __init__(self, config): "You need to set fsky for FouriercNGHaloModelFsky" ) - def _get_fsky(self, masks={}): + def _get_fsky(self, tr=None): """Returns the fractional sky area from user input. Args: masks (:obj:`dict`): dictionary containing the survey - masks of the relevant tracers (empty in this case). + tracers to obtain the survey mask (irrelevant in this case). Returns: - (:obj:`float`): fractional sky area. """ From 1f17ae5be5ba6144a6714fa8bdaaf0f13da75f99 Mon Sep 17 00:00:00 2001 From: paulrogozenski Date: Fri, 24 Jan 2025 12:04:49 -0500 Subject: [PATCH 22/28] nfw profile for weaklensing 1h Trispectrum terms, reformatted tests accordingly --- new_sacc.yml | 83 +++++++++ tests/Untitled.ipynb | 170 ++++++++++++++++++ ...ng_DESgc__0_DESgc__0_DESgc__0_DESgc__0.npz | Bin 0 -> 3228 bytes tests/test_covariance_fourier_cNG.py | 105 ++++++----- tests/test_covariance_fourier_cNG_fsky.py | 105 ++++++----- tjpcov/covariance_fourier_cNG.py | 33 +--- 6 files changed, 373 insertions(+), 123 deletions(-) create mode 100644 new_sacc.yml create mode 100644 tests/Untitled.ipynb create mode 100644 tests/cng_DESgc__0_DESgc__0_DESgc__0_DESgc__0.npz diff --git a/new_sacc.yml b/new_sacc.yml new file mode 100644 index 00000000..bea9a84f --- /dev/null +++ b/new_sacc.yml @@ -0,0 +1,83 @@ +tjpcov: + sacc_file: ./new_sacc.sacc + + cosmo: ./tjpcov_ymls/fid_cov.yaml + + cov_type: [FourierGaussianFsky] + + # Survey params: + # 5 lens bins + Ngal_lens0: 2.25 + Ngal_lens1: 3.098 + Ngal_lens2: 3.071 + Ngal_lens3: 2.595 + Ngal_lens4: 1.998 + + # 5 source bins + # {% for i in range(5) %} + # Ngal_src{{ i }}: {{2}} # arc_min^2 + # {% endfor %} + Ngal_src0: 2.036 + Ngal_src1: 1.964 + Ngal_src2: 1.973 + Ngal_src3: 1.987 + Ngal_src4: 2.023 + + # constant bin sigma_z + {% for i in range(5) %} + sigma_z_lens{{ i }}: {{ 0.03 }} + {% endfor %} + + + + # constant bin sigma_z + {% for i in range(5) %} + sigma_z_src{{ i }}: {{ 0.05 }} + {% endfor %} + + + # constant bin sigma_e + {% for i in range(5) %} + sigma_e_src{{ i }}: {{ 0.26 }} + {% endfor %} + + # linear bias for lenses constant for redshift bin (example notebook) + + {% for i, val in [(0, 1.23885511), (1, 1.3781005), (2, 1.52472019), (3, 1.67665752), (4, 1.83243479)] %} + bias_lens{{ i }}: {{ val }} + {% endfor %} + + IA: 1.0 + + lmax: 2000 + lmin: 20 + binning_scheme: log + nonlimber: False + +GaussianFsky: + fsky: 0.42 + +# includes some default values from CCL +# https://ccl.readthedocs.io/en/latest/api/pyccl.halos.profiles.hod.html +HOD: + # automatically creates massdef and concentration objects + log10Mmin_0: 12.0 + log10Mmin_p: 0.0 + siglnM_0: 0.4 + siglnM_p: 0.0 + log10M0_0: 7.0 + log10M0_p: 0.0 + log10M1_0: 13.3 + log10M1_p: 0.0 + alpha_0: 1.0 + alpha_p: 0.0 + fc_0: 1.0 + fc_p: 0.0 + bg_0: 1.0 + bg_p: 0.0 + bmax_0: 1.0 + bmax_p: 0.0 + a_pivot: 1.0 + ns_independent: False + is_number_counts: True + diff --git a/tests/Untitled.ipynb b/tests/Untitled.ipynb new file mode 100644 index 00000000..552ca000 --- /dev/null +++ b/tests/Untitled.ipynb @@ -0,0 +1,170 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "4a94c812", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "import pyccl\n", + "\n", + "cosmo = pyccl.CosmologyVanillaLCDM()\n", + "mass_def = pyccl.halos.massdef.MassDef('vir', rho_type='matter')\n", + "concentration = pyccl.halos.concentration.duffy08.ConcentrationDuffy08(mass_def=mass_def)\n", + "halo_bias = pyccl.halos.hbias.tinker10.HaloBiasTinker10(mass_def=mass_def)\n", + "hmf = pyccl.halos.hmfunc.tinker08.MassFuncTinker08(mass_def=mass_def)\n", + "\n", + "NFW_profile = pyccl.halos.profiles.nfw.HaloProfileNFW(mass_def=mass_def, concentration=concentration)\n", + "HOD_profile = pyccl.halos.profiles.hod.HaloProfileHOD(mass_def=mass_def, concentration=concentration, is_number_counts=True)\n", + "HOD_profile_false = pyccl.halos.profiles.hod.HaloProfileHOD(mass_def=mass_def, concentration=concentration, is_number_counts=False)\n", + "\n", + "hmc = pyccl.halos.halo_model.HMCalculator(mass_function=hmf, halo_bias=halo_bias, mass_def=mass_def)\n", + "prof_2pt = pyccl.halos.profiles_2pt.Profile2ptHOD()\n", + "\n", + "z_max = 0.2\n", + "na = pyccl.ccllib.get_pk_spline_na(cosmo.cosmo)\n", + "a_arr, _ = pyccl.ccllib.get_pk_spline_a(cosmo.cosmo, na, 0)\n", + "# Cut the array for efficiency\n", + "sel = 1 / a_arr < z_max + 1\n", + "# Include the next node so that z_max is in the range\n", + "sel[np.sum(~sel) - 1] = True\n", + "a_arr = a_arr[sel]\n", + "\n", + "lk_arr = cosmo.get_pk_spline_lk()\n", + "\n", + "tkk_nfw = pyccl.halos.pk_4pt.halomod_trispectrum_1h(cosmo, hmc, np.exp(lk_arr), a_arr, prof=NFW_profile)\n", + "tkk_hod_nc = pyccl.halos.pk_4pt.halomod_trispectrum_1h(cosmo, hmc, np.exp(lk_arr), a_arr, prof=HOD_profile, prof12_2pt=prof_2pt, prof34_2pt=prof_2pt)\n", + "tkk_hod_no_nc = pyccl.halos.pk_4pt.halomod_trispectrum_1h(cosmo, hmc, np.exp(lk_arr), a_arr, prof=HOD_profile_false, prof12_2pt=prof_2pt, prof34_2pt=prof_2pt)\n", + "tkk_hod_no_nc_no2pthod = pyccl.halos.pk_4pt.halomod_trispectrum_1h(cosmo, hmc, np.exp(lk_arr), a_arr, prof=HOD_profile_false)\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "dd586346", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABLoAAAJjCAYAAAALeXi9AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAACCAklEQVR4nOzdfVxUdf7//+cAMhACeZEgiYCuiYaZYnlVqamYpdZn19WysAst/VEWWVuxVqK1mm4plRfVplKZ6aZp7a6ZWHm1WhlJl2ZtqahBaKsgpiBwfn/4ZbZxuJiBGYY5PO6327ntzvu8zznvM0Pn5Xmd9/t9LIZhGAIAAAAAAAB8nJ+3GwAAAAAAAAC4A4kuAAAAAAAAmAKJLgAAAAAAAJgCiS4AAAAAAACYAokuAAAAAAAAmAKJLgAAAAAAAJgCiS4AAAAAAACYAokuAAAAAAAAmAKJLgAAAAAAAJgCia5aZGZmymKxKCgoSAcOHHBYP3DgQCUkJNiVxcbGymKxVLkUFxdr9erVslgsWrVqlcP+unfvLovFovfee89hXceOHdWzZ0+H8ueee06tWrVSWVmZNm/eLIvFotWrV1d5Pvfcc48sFotD+ZkzZ7R48WL17dtX4eHhCg4OVpcuXfTII4/ol19+qfK8K8/Jz89PoaGh+t3vfqc//vGPWr16tSoqKqo8vrtNnTpV3bt3b5BjuZPFYtE999zj7WY0aitWrFBGRoa3mwFUi/hAfPCm2NhYjRgxwtvNaNTWr1+v9PR0bzcDgAs++OAD3XHHHYqPj1dISIguvPBCXX/99crOzq7T/n766Selp6crJyfH5W1ri5vudNtttyk2NrbKdb+NZ+7+fqT6fUdAY0Wiy0klJSV69NFHna7fv39/7dy502E577zzbDcBH374od02//3vf/Xll18qJCTEYd2hQ4f0448/atCgQQ7HWrNmja6//noFBATU6dx+/fVXDR06VFOmTFGPHj30xhtvaP369UpOTtZLL72kHj16aO/evQ7bdejQQTt37tSOHTu0bt06PfLIIzp16pT++Mc/auDAgSosLKxTe1zx1ltv6Q9/+IPHj4OGR6ILvoL4QHxA47R+/XrNmDHD280A4ILFixdr//79uu+++7R+/Xo9++yzKigoUJ8+ffTBBx+4vL+ffvpJM2bM8Okkzm/jmbu/H8kc3xFwrrr9y7cJuuaaa7RixQo9+OCDTj0hPv/889WnT58q17Vu3VoJCQnavHmzXfmWLVsUEBCgCRMmONzIVH4+90bm559/1vbt2/XQQw+5cDb27r//fm3ZskUrV67U2LFjbeWDBg3S6NGjdfnll+sPf/iDPv/8c/n7+9vWBwcHO5zjxIkTtWzZMt1xxx266667quyV4C67du3SgQMHuJGpRnl5ucrKymS1Wr3dFMDUiA/EB7MyDEOnT59WcHCwt5sCoIlYuHCh2rRpY1d2zTXX6He/+51mzZqlq6++2kst845z4xnfD+AcenQ56aGHHlKrVq308MMPu2V/gwYN0t69e5WXl2cr27x5sy677DJde+21ys7O1okTJ+zW+fv768orr7Tbz9q1a9W8eXMNGTKkTu3Iz8/X0qVLNWzYMLubmEoXXXSRHn74YX399ddat26dU/u8/fbbde211+rNN9+scjhPpYULF8rPz08FBQW2smeeeUYWi0V33323rayiokItWrTQAw88YLf9mjVr1LlzZ1188cXVHqOyy/Ebb7yhadOmKSoqSmFhYRoyZIhDL4TY2FjddtttDvsYOHCgBg4c6LDPFStW6OGHH1bbtm3VvHlzjRw5Uj///LNOnDihu+66S61bt1br1q11++23q7i4uMr2vfjii7roootktVrVtWtXrVy50qFOfn6+Jk2apHbt2ikwMFBxcXGaMWOGysrKbHX2798vi8WiuXPn6sknn1RcXJysVqvDDfFvVVRU6Pnnn9ell16q4OBg2833O++8Y1dn7ty5io+Pl9VqVZs2bTR+/HgdOnSoXt9dbb/HwIED9a9//UsHDhywG9pVafHixerevbuaN2+u0NBQxcfH689//nO15wp4EvHBN+LD9u3bNXjwYIWGhuq8885Tv3799K9//avWNldeX59++mnNmzdPcXFxat68ufr27auPPvrIru6517xK5w5JqdznX//6V82ZM0exsbEKDg7WwIED9d133+nMmTN65JFHFBUVpfDwcP3f//2f3XfxW2vXrtUll1yioKAgdejQQc8995xDnaKiIj344IOKi4tTYGCgLrzwQqWmpurkyZN29SqH1b/wwgvq0qWLrFarXnnllRq/nxUrVqhv375q3ry5mjdvrksvvVRLliyxq7N06VJ1795dQUFBatmypf7v//5Pe/bsqdd3V9vvcdttt2nhwoW286pc9u/fL0l688031bt3b4WHh+u8885Thw4ddMcdd9R4rgA879wkjiQ1b95cXbt21cGDB21llcO3a7oGVsZO6Wz8qbwOuDqk+cyZM7XeR0jOXeuks1MfdO7cWVarVV26dNGrr75a7bHPjWfOfj9Sw35HQGNDostJoaGhevTRR/Xee+851S3UMAyVlZXZLb+dl6Tyyftvn9p/+OGHGjBggPr37y+LxaJt27bZrevZs6fCw8PtjrNmzRqNGDHCoddORUWFw/HLyspkGIZdvQ8//FBlZWW64YYbqj2XynVZWVm1nnelUaNGyTAMu3M415AhQ2QYht5//31b2aZNmxQcHGx3rE8//VTHjx93uFlbs2aN00/r//znP+vAgQN6+eWX9dJLL+n777/XyJEjVV5e7vQ5VbXPgoICZWZm6plnntHmzZt100036Q9/+IPCw8P1xhtv6KGHHtJrr71WZRLmnXfe0XPPPaeZM2dq9erViomJ0U033WQ3D0B+fr4uv/xyvffee3r88cf17rvvasKECZo9e7buvPNOh30+99xz+uCDD/T000/r3XffVXx8fLXtv+2223Tffffpsssu06pVq7Ry5UqNGjXKdhMgSf/f//f/6eGHH9bQoUP1zjvv6IknntCGDRvUr18/HT16tF7fXU2/x6JFi9S/f39FRkbaDe2SpJUrVyolJUUDBgzQ2rVrtW7dOt1///0ON2xAQyE+NP74sGXLFl199dUqLCzUkiVL9MYbbyg0NFQjR450umfZwoULlZWVpYyMDL3++us6efKkrr322noNw1y4cKH+/e9/a+HChXr55Zf17bffauTIkZowYYKOHDmipUuXau7cudq0aZMmTpzosH1OTo5SU1N1//33a+3aterXr5/uu+8+Pf3007Y6v/76qwYMGKBXXnlF9957r9599109/PDDyszMtP0Wv7Vu3TotXrxYjz/+uN577z2HBOpvPf7447r55psVFRWlzMxMrV27VrfeeqtdEnP27NmaMGGCLr74Yr311lt69tln9cUXX6hv3776/vvv6/Xd1fR7PPbYYxo9erQk2cWRtm3baufOnRo7dqw6dOiglStX6l//+pcef/xxuwdIABqPwsJCffbZZw4Pt2u7Bvbs2VPLli2TJD366KO260BV19OaOHMf4ey1LjMzU7fffru6dOmiNWvW6NFHH9UTTzxR7b8fnLnfqe77acjvCGh0DNRo2bJlhiRj165dRklJidGhQwejV69eRkVFhWEYhjFgwADj4osvttsmJibGkOSwTJs2zVbnv//9r+Hn52fcddddhmEYxtGjRw2LxWJs2LDBMAzDuPzyy40HH3zQMAzDyM3NNSQZDz30kN1xjh49agQEBBhr1qyxlX344YdVHvvcpdJTTz1lSLIdtyqnTp0yJBnDhw+3lVV13r/17rvvGpKMOXPmVFvHMAyjXbt2xh133GEYhmGUlJQYISEhxsMPP2xIMg4cOGAYhmH85S9/MZo1a2YUFxfbtsvJyTEkGdnZ2TXuv/L7uPbaa+3K//73vxuSjJ07d9rKYmJijFtvvdVhHwMGDDAGDBjgsM+RI0fa1UtNTTUkGffee69d+Q033GC0bNnSrkySERwcbOTn59vKysrKjPj4eON3v/udrWzSpElG8+bNbd9FpaefftqQZHz99deGYRjGvn37DElGx44djdLS0hq+kbO2bt3q8Dd5rj179hiSjJSUFLvyjz/+2JBk/PnPf7aVufrdOfN7XHfddUZMTIzDPu+55x7j/PPPr+UMAc8jPvhOfOjTp4/Rpk0b48SJE7aysrIyIyEhwWjXrp3tN6tK5fW1W7duRllZma38k08+MSQZb7zxht25//aaV+nWW2+1u55V7rN79+5GeXm5rTwjI8OQZIwaNcpu+8r4UlhYaCuLiYkxLBaLkZOTY1d36NChRlhYmHHy5EnDMAxj9uzZhp+fn7Fr1y67eqtXrzYkGevXr7eVSTLCw8ON//73v9V+H5V+/PFHw9/f37j55purrXPs2DEjODjY4Zqfm5trWK1WY9y4cbYyV787Z36Pu+++2+5vulJlDD1+/Hit5wnA+26++WYjICDA+PTTT21lzl4Dd+3aZUgyli1b5vJxnf13q7PXuvLyciMqKsro2bOnXdzZv3+/0axZM4d/9zp7v1PV92MYDfMdAY0VPbpcEBgYqCeffFKffvqp/v73v9dY94orrtCuXbvslpSUFNv6Fi1aqHv37rYn9lu2bJG/v7/69+8vSRowYIBt2Fl186+8/fbbCgwM1DXXXONw/Dlz5jgcf9euXRozZkydz7+qt3FVxzjnCXF1Bg8erE2bNkmSduzYoV9//VVTp05V69atbU/tN23apL59+yokJMS23Zo1axQbG1vlW8aqMmrUKLvPl1xyiSTVOHSmNue+7apLly6SpOuuu86h/L///a/D8MXBgwcrIiLC9tnf319jx47Vf/7zH9vQwH/+858aNGiQoqKi7HpeDB8+XNLZv5vfGjVqlJo1a1Zr2999911JshsCdK7Kv7tzhyRefvnl6tKli11PC1fV5/e4/PLLdfz4cd100016++2369WzDHAX4kPjjQ8nT57Uxx9/rNGjR6t58+a2ev7+/kpOTtahQ4eqHIJyruuuu85uHjJ3xJFrr71Wfn7/+6dYTXFEknJzc+3KL774Yod54caNG6eioiJ99tlnks7GkYSEBF166aV2cWTYsGGyWCwO88FdffXVatGiRa1tz8rKUnl5eY1xZOfOnTp16pRDHImOjtbVV19drzhSn9+jcpjOmDFj9Pe//12HDx+uczsAeNZjjz2m119/XfPnz1diYqLdOmeuge5Q279bnb3W7d27Vz/99JPGjRtnFzdjYmLUr18/h+M6c79T0/cjNdx3BDQ2JLpcdOONN6pnz56aNm2azpw5U2298PBw9erVy26JioqyqzNo0CB99913+umnn/Thhx8qMTHR9o/wAQMGaPfu3SosLNSHH36ogIAAXXHFFXbbr169WsOHD9d5553ncPwOHTo4HL9Xr1664IIL7Oq1b99ekrRv375qz6VyXXR0dA3fjL3KC/+553yuIUOGKDc3V99//702bdqkHj16qE2bNrr66qu1adMmnTp1Sjt27HAYlrJ69WqXJhlu1aqV3efKoTynTp1yeh/natmypd3nwMDAGstPnz5tVx4ZGemwz8qyX375RdLZyaT/8Y9/qFmzZnZLZdfkc5M8bdu2dartR44ckb+/f5VtqFTZhqr2GRUVZVtfF/X5PZKTk7V06VLbxJxt2rRR7969XRo6BXgC8cE5DR0fjh07JsMwqr2WSXLqeubLceSLL75wiCOhoaEyDKNecUSS2rVrV22dxhpHrrrqKq1bt05lZWUaP3682rVrp4SEBL3xxht1bg8A95sxY4aefPJJ/eUvf9E999zjsN6Za6A71Ha9cfZaV/m/NbX7t2q736nt+6ntWO78joDGhkSXiywWi+bMmaMffvhBL730Ur329dt5WDZv3qwBAwbY1lXetGzdutU2SeBvn0QXFhbq/fffr/cbpQYNGqSAgIAaJxKuXDd06FCn9/vOO+/IYrHoqquuqrHe4MGDJZ19Kp+VlWU7xuDBg/X+++9r69atKikpsbuR2bNnj/bs2eP2t2kFBQWppKTEodxTPYby8/OrLasMqK1bt1ZSUlKVvS927dqlCRMm2G3vbK+KCy64QOXl5VW2oVJlG347IXaln376Sa1bt7Z9bujv7vbbb9eOHTtUWFiof/3rXzIMQyNGjKhXzwqgvogPzmno+NCiRQv5+flVey2TZHc9q4/GGke6detWbRx57LHH7LZ3JY5Icng5yW815jhy/fXX6/3331dhYaE2b96sdu3aady4cbb5IAF414wZM5Senq709PRqXzjkzDWwITh7rausV1O7K9V2v+PM91PbsRryOwIaGomuOhgyZIiGDh2qmTNnVvs2PWdcddVV8vf31+rVq/X111/bvW0oPDxcl156qV555RXt37/fYVjKP/7xD1ksFofhc66KjIzUHXfcoffee6/KCXm/++47zZkzRxdffHGNExL/1rJly/Tuu+/qpptusvUIqE7btm3VtWtXrVmzRtnZ2bYbmaFDh+rIkSOaN2+ewsLCbMMMpLPdeKOiohxeXV9fsbGx+uKLL+zKvvvuO6eGtNTF+++/r59//tn2uby8XKtWrVLHjh1tT8hHjBihr776Sh07dqyyB0ZtPSKqUzn0cfHixdXWqXw98fLly+3Kd+3apT179thuQiXPfHdWq7XWJ/MhISEaPny4pk2bptLSUn399dd1Ph7gDsSHmnkjPoSEhKh3795666237K4pFRUVWr58udq1a6eLLrrIqfbXJjY2Vt99951dwuaXX37Rjh073LL/c3399df6/PPP7cpWrFih0NBQ21CXESNG6IcfflCrVq2qjCO/faOhK5KSkuTv719jHOnbt6+Cg4Md4sihQ4f0wQcfOMQRd393zvTyslqtGjBggObMmSNJ2r17d52PB8A9nnjiCaWnp+vRRx/V9OnTq63nzDXQHb1va+Psta5z585q27at3njjDbth/AcOHHC41tV0v+Ps9yM1nu8IaGgB3m6Ar5ozZ44SExNVUFBQ5RsunBEWFqaePXtq3bp18vPzs82/UmnAgAHKyMiQ5Dj/yurVqzV06FCFhobW6di/NW/ePO3du1e33HKLtm7dqpEjR8pqteqjjz7S008/rdDQUK1Zs8ZuLgzp7MWw8lXep06d0o8//qh169bpn//8pwYMGKAXXnjBqeMPHjxYzz//vIKDg23fQVxcnOLi4rRx40aNGjVKAQH/+1NdvXq1fv/737s0J4wzkpOTdcsttyglJUV/+MMfdODAAc2dO9dhOI+7tG7dWldffbUee+wxhYSEaNGiRfr222+1cuVKW52ZM2cqKytL/fr107333qvOnTvr9OnT2r9/v9avX68XXnihxmEj1bnyyiuVnJysJ598Uj///LPtzWy7d+/WeeedpylTpqhz586666679Pzzz8vPz0/Dhw/X/v379dhjjyk6Olr333+/bX+e+O66deumt956S4sXL1ZiYqL8/PzUq1cv3Xnnnba/lbZt2yo/P1+zZ89WeHi43Q0v4C3Eh8YXH2bPnq2hQ4dq0KBBevDBBxUYGKhFixbpq6++0htvvOG2eJKcnKwXX3xRt9xyi+6880798ssvmjt3rsLCwtyy/3NFRUVp1KhRSk9PV9u2bbV8+XJlZWVpzpw5tmGrqampWrNmja666irdf//9uuSSS1RRUaHc3Fxt3LhRDzzwgHr37u3ysWNjY/XnP/9ZTzzxhE6dOqWbbrpJ4eHh+uabb3T06FHNmDFD559/vh577DH9+c9/1vjx43XTTTfpl19+0YwZMxQUFGR3g+aJ765bt26Szv43OXz4cPn7++uSSy7Rk08+qUOHDmnw4MFq166djh8/rmeffVbNmjWz6z0JoOE988wzevzxx3XNNdfouuuus8WSSr9N/DhzDezYsaOCg4P1+uuvq0uXLmrevLmioqLq/LC4Ks5e6/z8/PTEE09o4sSJ+r//+z/deeedOn78uNLT0x2GGFYXz1z5fhrTdwQ0OG/OhO8LfvtWrXONGzfOkFTlW7Wuu+46p/b/0EMPGZKMXr16Oaxbt26dIckIDAy0vRXDMAyjuLjYCAoKqvLNGJVvB3nzzTerPF51byAqLS01Fi5caPTu3dto3ry5YbVajc6dOxsPPfSQcfToUYf6AwYMsHtLV0hIiNGhQwdj9OjRxptvvmn3FqnavP3224YkY+jQoXbld955pyHJeO6552xl//nPfwxJxocffujUvqv7Pirf2vTb77CiosKYO3eu0aFDByMoKMjo1auX8cEHH1T75sBz91nd38r06dMNScaRI0dsZZKMu+++21i0aJHRsWNHo1mzZkZ8fLzx+uuvO5zDkSNHjHvvvdeIi4szmjVrZrRs2dJITEw0pk2bZnvTWOX5/PWvf3XqezGMs29+mT9/vpGQkGAEBgYa4eHhRt++fY1//OMfdnXmzJljXHTRRUazZs2M1q1bG7fccotx8OBBu33V97ur6vf473//a4wePdo4//zzDYvFYvu7feWVV4xBgwYZERERRmBgoBEVFWWMGTPG+OKLL5w+d8AdiA++FR+2bdtmXH311UZISIgRHBxs9OnTx+56V52arq+SjOnTp9uVvfLKK0aXLl2MoKAgo2vXrsaqVauqfXPguft0Jb5U/i2tXr3auPjii43AwEAjNjbWmDdvnkM7i4uLjUcffdTo3Lmz7XrfrVs34/7777d7+29lbHLFq6++alx22WVGUFCQ0bx5c6NHjx4Of38vv/yycckll9iOff3119veGvxb9fnuKtv/29+jpKTEmDhxonHBBRfY4si+ffuMf/7zn8bw4cONCy+80AgMDDTatGljXHvttca2bdtcOncA7nduDDl3qeTKNfCNN94w4uPjjWbNmlV53a6OK/9uNQznr3Uvv/yy0alTJyMwMNC46KKLjKVLl9pd62qKZ85+Pw31HQGNlcUwnHz9ERqNv//977r55pv1888/O0xYa3Zz587V008/rby8PIceBADQ1BEfiA8A0BTExsYqISFB//znP73dFLdzVzwz83cE1IZEFwAAAADAZ5DEqR3fEZoy5ugCAAAAADQJhmGovLy8xjr+/v5unw8YQMOhRxcAAAAAoEnYvHmzw4tczrVs2TLddtttDdMgAG7n5+0GAAA8Z/bs2brssssUGhqqNm3a6IYbbtDevXud3v7f//63AgICdOmll3qukQCARoGYgaYgMTFRu3btqnEZOXKkt5sJNHqVb+SOioqSxWLRunXrat1my5YtSkxMVFBQkDp06ODwJu7MzExZLBaH5fTp0y61jaGLAGBiW7Zs0d13363LLrtMZWVlmjZtmpKSkvTNN98oJCSkxm0LCws1fvx4DR48WD///HMDtRgA4C3EDDQFoaGh6tWrl7ebAfi8kydPqnv37rr99tv1hz/8odb6+/bt07XXXqs777xTy5cv17///W+lpKToggsusNs+LCzM4SFLUFCQS21j6CIANCFHjhxRmzZttGXLFl111VU11r3xxhvVqVMn+fv7a926dcrJyWmYRgIAGgViBgDAGRaLRWvXrtUNN9xQbZ2HH35Y77zzjvbs2WMr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Wrp0qc6cOaOjR4+qbdu2ys/Pd2mfVSHRBQAAAAAAAB08eFBhYWG2z1artcb6FovF7rNhGA5llR577DHl5+erT58+MgxDERERuu222zR37lz5+/vXaZ9VYegiAAAAAAAAFBYWZrdUl+hq3bq1/P39HXpaFRQUOPTIqhQcHKylS5fq119/1f79+5Wbm6vY2FiFhoaqdevWkqTIyEiX9lkVEl0AAAAAAABwWmBgoBITE5WVlWVXnpWVpX79+tW4bbNmzdSuXTv5+/tr5cqVGjFihPz8zqan+vbt67DPjRs31rrP32LoIgAAAAAAAFwydepUJScnq1evXurbt69eeukl5ebmavLkyZKktLQ0HT58WK+++qok6bvvvtMnn3yi3r1769ixY5o3b56++uorvfLKK7Z93nfffbrqqqs0Z84cXX/99Xr77be1adMmbd++3el2kegCAAAAAACAS8aOHatffvlFM2fOVF5enhISErR+/XrFxMRIkvLy8pSbm2urX15ermeeeUZ79+5Vs2bNNGjQIO3YsUOxsbG2Ov369dPKlSv16KOP6rHHHlPHjh21atUq9e7d2+l2kegCAAAAAACAy1JSUpSSklLluszMTLvPXbp00e7du2vd5+jRozV69Og6t4k5ugAAAAAAAGAKJLoAAAAAAABgCiS6AAAAAAAAYAokugAAAAAAAGAKJLoAAAAAAABgCiS6AAAAAAAAYAokugAAAAAAAGAKJLoAAAAAAABgCiS6AAAAAAAAYAouJ7q2bt2qkSNHKioqShaLRevWrbNbbxiG0tPTFRUVpeDgYA0cOFBff/21XZ2SkhJNmTJFrVu3VkhIiEaNGqVDhw7Z1Tl27JiSk5MVHh6u8PBwJScn6/jx4y6fIADAe4gZAABnETMAAO7gcqLr5MmT6t69uxYsWFDl+rlz52revHlasGCBdu3apcjISA0dOlQnTpyw1UlNTdXatWu1cuVKbd++XcXFxRoxYoTKy8ttdcaNG6ecnBxt2LBBGzZsUE5OjpKTk+twigAAbyFmAACcRcwAALhDgKsbDB8+XMOHD69ynWEYysjI0LRp0/T73/9ekvTKK68oIiJCK1as0KRJk1RYWKglS5botdde05AhQyRJy5cvV3R0tDZt2qRhw4Zpz5492rBhgz766CP17t1bkvS3v/1Nffv21d69e9W5c+e6ni8AoAER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AAAAAABoUOf/p1QBAZ7tp1RWVipJio6OtiufPn260tPTHeofPXpU5eXlioiIsCuPiIhQfn5+jcdq166djhw5orKyMqWnp2vixIm2dfn5+XXa52+R6AIAAAAAAIAOHjyosLAw22er1VpjfYvFYvfZMAyHsnNt27ZNxcXF+uijj/TII4/od7/7nW666aZ67fO3SHQBAAAAAABAYWFhdomu6rRu3Vr+/v4OPa0KCgocemSdKy4uTpLUrVs3/fzzz0pPT7cluiIjI+u0z99iji4AAAAAAAA4LTAwUImJicrKyrIrz8rKUr9+/Zzej2EYdvOA9e3b12GfGzdudGmf9OgCAAAAAACAS6ZOnark5GT16tVLffv21UsvvaTc3FxNnjxZkpSWlqbDhw/r1VdflSQtXLhQ7du3V3x8vCRp+/btevrppzVlyhTbPu+77z5dddVVmjNnjq6//nq9/fbb2rRpk7Zv3+50u0h0AQAAAAAAwCVjx47VL7/8opkzZyovL08JCQlav369YmJiJEl5eXnKzc211a+oqFBaWpr27dungIAAdezYUU899ZQmTZpkq9OvXz+tXLlSjz76qB577DF17NhRq1atUu/evZ1uF4kuAAAAAAAAuCwlJUUpKSlVrsvMzLT7PGXKFLveW9UZPXq0Ro8eXec2MUcXAAAAAAAATIFEFwAAAAAAAEyBRBcAAAAAAABMgUQXAAAAAAAATIFEFwAAAAAAAEyBRBcAAAAAAABMgUQXAAAAAAAATIFEFwAAAAAAAEyBRBcAAAAAAABMgUQXADQBixYtUlxcnIKCgpSYmKht27bVWL+kpETTpk1TTEyMrFarOnbsqKVLlzZQawEA3kTMAAD4sgBvNwAA4FmrVq1SamqqFi1apP79++vFF1/U8OHD9c0336h9+/ZVbjNmzBj9/PPPWrJkiX73u9+poKBAZWVlDdxyAEBDI2YAAHwdiS4A8EFFRUV2n61Wq6xWa5V1582bpwkTJmjixImSpIyMDL333ntavHixZs+e7VB/w4YN2rJli3788Ue1bNlSkhQbG+veEwAANBhiBgCgKSHRBQBuEravRAEBFo8eo6ysRJIUHR1tVz59+nSlp6c71C8tLVV2drYeeeQRu/KkpCTt2LGjymO888476tWrl+bOnavXXntNISEhGjVqlJ544gkFBwe750QAoIkjZgAA4Bkk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v6SkRBdccIGmTZum7t27V7vfsLAw5eXl2S1BQUFOt4tEFwAAAAAAAFwyb948TZgwQRMnTlSXLl2UkZGh6Oho25yK54qNjdWzzz6r8ePHKzw8vNr9WiwWRUZG2i2uINEFAAAAAAAAFRUV2S0lJSVV1istLVV2draSkpLsypOSkrRjx456taG4uFgxMTFq166dRowYod27d7u0vdsnowcAAAAAAIB7BH+TpwC/QI8eo6yiVJIUHR1tVz59+vQqX/Bx9OhRlZeXKyIiwq48IiJC+fn5dW5HfHy8MjMz1a1bNxUVFenZZ59V//799fnnn6tTp05O7YNEFwAAAAAAAHTw4EGFhYXZPlut1hrrWywWu8+GYTiUuaJPnz7q06eP7XP//v3Vs2dPPf/883ruueec2geJLgAAAAAAACgsLMwu0VWd1q1by9/f36H3VkFBgUMvr/rw8/PTZZddpu+//975bdx2dAAAAAAAAJheYGCgEhMTlZWVZVeelZWlfv36ue04hmEoJydHbdu2dXobenQBAAAAAADAJVOnTlVycrJ69eqlvn376qWXXlJubq4mT54sSUpLS9Phw4f16quv2rbJycmRdHbC+SNHjignJ0eBgYHq2rWrJGnGjBnq06ePOnXqpKKiIj333HPKycnRwoULnW4XiS4AAAAAAAC4ZOzYsfrll180c+ZM5eXlKSEhQevXr1dMTIwkKS8vT7m5uXbb9OjRw/b/s7OztWLFCsXExGj//v2SpOPHj+uuu+5Sfn6+wsPD1aNHD23dulWXX3650+1i6CIANAGLFi1SXFycgoKClJiYqG3btlVbd/v27erfv79atWql4OBgxcfHa/78+Q3YWgCANxEzAADOSklJ0f79+1VSUqLs7GxdddVVtnWZmZnavHmzXX3DMByWyiSXJM2fP18HDhxQSUmJCgoK9N5776lv374utYkeXQBgcqtWrVJqaqoWLVqk/v3768UXX9Tw4cP1zTffqH379g71Q0JCdM899+iSSy5RSEiItm/frkmTJikkJER33XWXF84AANBQiBkAAF9Hjy4AMLl58+ZpwoQJmjhxorp06aKMjAxFR0dr8eLFVdbv0aOHbrrpJl188cWKjY3VLbfcomHDhtX4RB8AYA7EDACAryPRBQA+qKioyG4pKSmpsl5paamys7OVlJRkV56UlKQdO3Y4dazdu3dr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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, axs = plt.subplots(1, 3, figsize=(12, 6), constrained_layout=True)\n", + "ctrf = axs[0].contourf(tkk_nfw[0]/tkk_hod_nc[0])\n", + "cbar = fig.colorbar(ctrf, ax=axs[0])\n", + "ctrf = axs[1].contourf(tkk_nfw[0]/tkk_hod_no_nc[0])\n", + "cbar = fig.colorbar(ctrf, ax=axs[1])\n", + "ctrf = axs[2].contourf(tkk_hod_no_nc[0]/tkk_hod_no_nc_no2pthod[0])\n", + "cbar = fig.colorbar(ctrf, ax=axs[2])\n", + "axs[0].set_title(\"NFW/HOD w/ number counts\")\n", + "axs[1].set_title(\"NFW/HOD w/o number counts\")\n", + "axs[2].set_title(\"2pt_hod/2pt\")\n", + "#print(tkk_hod_no_nc_no2pthod[0]/tkk_hod_no_nc[0])\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "d442d4eb", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[1.00223502e+00 1.00223502e+00 1.00223502e+00 ... 7.92927257e+03\n", + " 8.14150586e+03 8.36389810e+03]\n", + " [1.00223502e+00 1.00223502e+00 1.00223502e+00 ... 7.92927257e+03\n", + " 8.14150586e+03 8.36389810e+03]\n", + " [1.00223502e+00 1.00223502e+00 1.00223502e+00 ... 7.92927257e+03\n", + " 8.14150586e+03 8.36389810e+03]\n", + " ...\n", + " [7.92927257e+03 7.92927257e+03 7.92927257e+03 ... 1.46979173e+08\n", + " 1.50845442e+08 1.54941619e+08]\n", + " [8.14150586e+03 8.14150586e+03 8.14150586e+03 ... 1.50845442e+08\n", + " 1.54764729e+08 1.58984428e+08]\n", + " [8.36389810e+03 8.36389810e+03 8.36389810e+03 ... 1.54941619e+08\n", + " 1.58984428e+08 1.63261414e+08]]\n" + ] + }, + { + "data": { + "image/png": "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HSpjjNs+nKlv374yxujDDz+0xtavX6/AwEC399q+fbuOHj3qET5TUlIqfPTxiSee0L59+/SPf/xD8+fP1969ezVkyBAVFRVVeJ9Ke81Dhw4pOTlZzz//vDZu3Khbb71VN954o5xOp5YuXaoJEybozTffLLWEeeeddzRnzhw988wzevvtt9WiRQvdeuutbucDycnJ0ZVXXqm1a9fq6aef1vvvv69Ro0ZpxowZuvfeez1ec86cOfroo4/03HPP6f3331fbtm3L3P4777xTY8aM0RVXXKHly5dr2bJlGjp0qBVqJOn//b//p4kTJ6pfv35655139Oc//1kffPCBunfvrsOHD5/X2pX35/HKK6+oR48eCgsLc/upiiQtW7ZMDzzwgOLj47Vy5UqtWrVKjz76qEcABQB4H/KU9+epTZs26ZprrpHL5dKCBQu0dOlSBQUFaciQIRX+ZtnLL7+s1NRUJSUl6Z///KeOHz+ugQMHntfPMF9++WX93//9n15++WX94x//0Ndff60hQ4Zo1KhR+vnnn/X6669r1qxZWr9+ve655x6P52dkZGjs2LF69NFHtXLlSnXv3l1jxozRc889Z8357bffFB8fr0WLFumRRx7R+++/r4kTJyo5Odn6s/i9VatWad68eXr66ae1du1ajwL1955++mnddtttioiIUHJyslauXKmRI0e6lZgzZszQqFGj1KFDB61YsUIvvviiPv/8c8XFxWnv3r3ntXbl/Xk89dRTuummmyTJLXeFh4crLS1Nw4cPV6tWrbRs2TK99957evrpp90OuAI4RwaoJQsXLjSSzLZt20x+fr5p1aqV6dKliykuLjbGGBMfH286dOjg9pwWLVoYSR63yZMnW3N+/fVXU69ePXPfffcZY4w5fPiwcTgc5oMPPjDGGHPllVea8ePHG2OMycrKMpLMhAkT3N7n8OHDxtfX16SkpFhjGzZsKPW9z7yV+Otf/2okWe9bmhMnThhJZsCAAdZYafv9e++//76RZGbOnFnmHGOMad68ubn77ruNMcbk5+ebhg0bmokTJxpJZt++fcYYY/7yl7+Y+vXrm7y8POt5GRkZRpJJT08v9/VL1mPgwIFu4//617+MJJOWlmaNtWjRwowcOdLjNeLj4018fLzHaw4ZMsRt3tixY40k88gjj7iNX3/99SYkJMRtTJIJDAw0OTk51lhhYaFp27at+eMf/2iNjR492jRq1MhaixLPPfeckWT27NljjDEmMzPTSDKXXnqpKSgoKGdFTtu8ebPH38kzffXVV0aSeeCBB9zGP/30UyPJPPHEE9ZYZdeuIn8egwYNMi1atPB4zYceeshcdNFFZ9lDAIA3IU/VnTzVrVs306xZM3Ps2DFrrLCw0ERHR5vmzZtbf2alKckjHTt2NIWFhdb4Z599ZiSZpUuXuu377zNCiZEjR7p9/pe8ZqdOnUxRUZE1npSUZCSZoUOHuj2/JI+5XC5rrEWLFsbhcJiMjAy3uf369TPBwcHm+PHjxhhjZsyYYerVq2e2bdvmNu/tt982ksyaNWusMUnG6XSaX3/9tcz1KPH9998bHx8fc9ttt5U558iRIyYwMNAjI2VlZRl/f38zYsQIa6yya1eRP48HH3zQ7e90iZLMefTo0bPuJ4DK4Rtd8Ap+fn569tlntX37dv3rX/8qd+5VV12lbdu2ud0eeOAB6/HGjRurU6dO1hHITZs2ycfHRz169JAkxcfHWz87K+t8EqtXr5afn5+uvfZaj/efOXOmx/tv27ZNw4YNO+f9L+3qQmUxZxzxKkufPn20fv16SdLWrVv122+/ady4cWratKl1FHL9+vWKi4tTw4YNreelpKSoZcuWpV41qTRDhw51u3/ZZZdJUrk/BTibM6/e065dO0nSoEGDPMZ//fVXj58v9unTR6GhodZ9Hx8fDR8+XN99953108B///vf6t27tyIiItyOJA8YMEDS6b83vzd06FDVr1//rNv+/vvvS5LbTxrOVPL37syfJF555ZVq166d25HjyjqfP48rr7xSR48e1a233qrVq1ef1zfLcGHavHmzhgwZooiICDkcjgr/jOj31q5dq27duikoKEgXX3yxbrzxRmVmZlb9xgI2RJ7y3jx1/Phxffrpp7rpppvUqFEja56Pj48SExN14MCBUk+of6ZBgwa5nYesKnLXwIEDVa/ef/+zsLzcJUlZWVlu4x06dPA4L9yIESOUm5urHTt2SDqdu6Kjo3X55Ze75a7+/fvL4XB4nA/ummuuUePGjc+67ampqSoqKio3d6WlpenEiRMeuSsyMlLXXHPNeeWu8/nzuOKKKyRJw4YN07/+9S8dPHjwnLcDFwZyVsVRdMFr3HLLLercubMmT56sU6dOlTnP6XSqS5cubreIiAi3Ob1799a3336rH3/8URs2bFBsbKwVKuLj47Vz5065XC5t2LBBvr6+uuqqq9ye//bbb2vAgAFq0KCBx/u3atXK4/27dOmiiy++2G3eJZdcIknl/sNR8lhkZGQ5K+Ou5IPzzH0+U9++fZWVlaW9e/dq/fr1iomJUbNmzXTNNddo/fr1OnHihLZu3erxNfu33367UidNbdKkidv9kp8mnDhxosKvcaaQkBC3+35+fuWOnzx50m08LCzM4zVLxkouQf7TTz/p3XffVf369d1uJefROLPkCQ8Pr9C2//zzz/Lx8Sl1G0qUbENprxkREVHqZdIr6nz+PBITE/X6669bJ85t1qyZunbtWqmfguDCdvz4cXXq1Elz5849p+d///33uu6663TNNdcoIyNDa9eu1eHDh3XDDTdU8ZYC9kWeqpiazlNHjhyRMabMz35JFfr8r8u56/PPP/fIXUFBQTLGnFfukqTmzZuXOcdbc1fPnj21atUqFRYW6o477lDz5s0VHR2tpUuXnvP2wN7IWRVH0QWv4XA4NHPmTP3nP//R/Pnzz+u1fn9eiY0bNyo+Pt56rCSEbd682Tqp6u+PrLlcLn344YfnfYWc3r17y9fXt9ymveSxfv36Vfh133nnHTkcDvXs2bPceX369JF0+ihjamqq9R59+vTRhx9+qM2bNys/P98tmH311Vf66quvqvzqQAEBAcrPz/cYr65vDOXk5JQ5VhJImjZtqoSEhFKPJm/btk2jRo1ye35FjxJffPHFKioqKnUbSpRsw+9P8Fvixx9/VNOmTa37Nb12d911l7Zu3SqXy6X33ntPxhgNHjz4vI4U48IxYMAAPfvss2UGpoKCAk2YMEF/+MMf1LBhQ3Xt2tXtKP6OHTtUVFSkZ599Vpdeeqk6d+6s8ePHa9euXeX+BzuA/yJPVUxN56nGjRurXr16ZX72S3L7/D8f3pq7OnbsWGbueuqpp9yeX5ncJcnjYj6/582567rrrtOHH34ol8uljRs3qnnz5hoxYoR1/lTg98hZFUfRBa/St29f9evXT88880yZV9OriJ49e8rHx0dvv/229uzZ43b1FKfTqcsvv1yLFi3SDz/84PE1+3fffVcOh8Pj53OVFRYWprvvvltr164t9QSj3377rWbOnKkOHTqUe4LV31u4cKHef/993XrrrdYRzrKEh4erffv2SklJUXp6uhXM+vXrp59//lmzZ89WcHCw9bVp6fTX7CMiIsq83Pi5atmypT7//HO3sW+//bZCX9E/Fx9++KF++ukn635RUZGWL1+uSy+91DriN3jwYO3evVuXXnppqUeUz3aEtywlP32cN29emXOuueYaSdLixYvdxrdt26avvvrKCtVS9aydv7//WY80NmzYUAMGDNDkyZNVUFCgPXv2nPP7ASXuuusu/d///Z+WLVumzz//XDfffLOuvfZa60TAXbp0kY+PjxYuXKiioiK5XC69+eabSkhIqNBPhwGcRp4qX23kqZL/6FyxYoXbZ3BxcbEWL16s5s2b609/+lOFtv9sWrZsqW+//datsPnll1+0devWKnn9M+3Zs0e7du1yG1uyZImCgoKsn24OHjxY//nPf9SkSZNSc9fvr2hYGQkJCfLx8Sk3d8XFxSkwMNAjdx04cEAfffSRR+6q6rWryLe8/P39FR8fr5kzZ0qSdu7cec7vhwsXOeu/fGt7A4AzzZw5U7GxsTp06JDb5ZgrIzg4WJ07d9aqVatUr14963wSJeLj45WUlCTJ83wSb7/9tvr166egoKBzeu/fmz17tr755hvdfvvt1m+q/f399cknn+i5555TUFCQUlJS3H7bL53+ICy5NPGJEyf0/fffa9WqVfr3v/+t+Ph4vfrqqxV6/z59+uill15SYGCgtQZRUVGKiorSunXrNHToUPn6/vefgbfffls33HBDpc5xURGJiYm6/fbb9cADD+jGG2/Uvn37NGvWLI+fJ1SVpk2b6pprrtFTTz2lhg0b6pVXXtHXX3+tZcuWWXOeeeYZpaamqnv37nrkkUfUpk0bnTx5Uj/88IPWrFmjV199tdyvwZfl6quvVmJiop599ln99NNP1pWmdu7cqQYNGujhhx9WmzZtdN999+mll15SvXr1NGDAAP3www966qmnFBkZqUcffdR6vepYu44dO2rFihWaN2+eYmNjVa9ePXXp0kX33nuv9XclPDxcOTk5mjFjhpxOp1uAB87Ff/7zHy1dulQHDhywiuTx48frgw8+0MKFCzV9+nS1bNlS69at080336zRo0erqKhIcXFxWrNmTS1vPVD3kKe8L0/NmDFD/fr1U+/evTV+/Hj5+fnplVde0e7du7V06dIqy1+JiYl67bXXdPvtt+vee+/VL7/8olmzZik4OLhKXv9MERERGjp0qKZOnarw8HAtXrxYqampmjlzpvWz1bFjxyolJUU9e/bUo48+qssuu0zFxcXKysrSunXr9Nhjj6lr166Vfu+WLVvqiSee0J///GedOHFCt956q5xOp7788ksdPnxY06ZN00UXXaSnnnpKTzzxhO644w7deuut+uWXXzRt2jQFBARoypQp1utVx9p17NhR0un/Tw4YMEA+Pj667LLL9Oyzz+rAgQPq06ePmjdvrqNHj+rFF19U/fr13b49CVQEOesMtXoqfFzQfn+VoDONGDHCSCr1KkGDBg2q0OtPmDDBSDJdunTxeGzVqlVGkvHz87OuBmOMMXl5eSYgIMAsXLjQ4zklVwl66623Sn2/sq6oUlBQYF5++WXTtWtX06hRI+Pv72/atGljJkyYYA4fPuwxPz4+3u2qQw0bNjStWrUyN910k3nrrbfcropzNqtXrzaSTL9+/dzG7733XiPJzJkzxxr77rvvjCSzYcOGCr12WetRchWa369hcXGxmTVrlmnVqpUJCAgwXbp0MR999FGZVw488zXL+rsyZcoUI8n8/PPP1pgk8+CDD5pXXnnFXHrppaZ+/fqmbdu25p///KfHPvz888/mkUceMVFRUaZ+/fomJCTExMbGmsmTJ1tXTirZn7/97W8VWhdjjCkqKjIvvPCCiY6ONn5+fsbpdJq4uDjz7rvvus2ZOXOm+dOf/mTq169vmjZtam6//Xazf/9+t9c637Ur7c/j119/NTfddJO56KKLjMPhsP7eLlq0yPTu3duEhoYaPz8/ExERYYYNG2Y+//zzCu87UEKSWblypXW/5AqgDRs2dLv5+vqaYcOGGWOMyc7ONq1btzb/+7//a3bs2GE2bdpk4uPjTZ8+fcq9GhlwISNP1a089fHHH5trrrnGNGzY0AQGBppu3bq55YOylJdHJJkpU6a4jS1atMi0a9fOBAQEmPbt25vly5eXeeXAM1+zMnms5O/S22+/bTp06GD8/PxMy5YtzezZsz22My8vzzz55JOmTZs2Vj7q2LGjefTRR92ull2S5SrjjTfeMFdccYUJCAgwjRo1MjExMR5///7xj3+Yyy67zHrv6667zrrK9u+dz9qVbP/v/zzy8/PNPffcYy6++GIrd2VmZpp///vfZsCAAeYPf/iD8fPzM82aNTMDBw40H3/8caX2HRcmclb5HMZU8JIjwAXg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kyZN1KBBA11++eVKT0+3HjfGaOrUqYqIiFBgYKB69eqlPXv2uL1Gfn6+Hn74YTVt2lQNGzbU0KFDdeDAgerYXAAAgDqDnAUAAFC2Ki+6jhw5oh49eqh+/fp6//339eWXX+r555/XRRddZM2ZNWuWZs+erblz52rbtm0KCwtTv379dOzYMWvO2LFjtXLlSi1btkxbtmxRXl6eBg8erKKioqreZAAAgDqBnAUAAFA+36p+wZkzZyoyMlILFy60xlq2bGn9b2OMkpKSNHnyZN1www2SpEWLFik0NFRLlizR6NGj5XK5tGDBAr355pvq27evJGnx4sWKjIzU+vXr1b9//6rebAAAAK9HzgIAAChflX+j65133lGXLl108803q1mzZoqJidHf//536/HMzEzl5OQoISHBGvP391d8fLy2bt0qSUpPT9epU6fc5kRERCg6Otqac6b8/Hzl5ua63QAAAOyEnAUAAFC+Ki+6vv/+e82bN0+tW7fW2rVrdf/99+uRRx7RG2+8IUnKycmRJIWGhro9LzQ01HosJydHfn5+aty4cZlzzjRjxgw5nU7rFhkZWdW7BgAAUKvIWQAAAOWr8qKruLhYnTt31vTp0xUTE6PRo0fr3nvv1bx589zmORwOt/vGGI+xM5U3Z9KkSXK5XNZt//7957cjAAAAXoacBQAAUL4qL7rCw8PVvn17t7F27dopKytLkhQWFiZJHkcMDx06ZB19DAsLU0FBgY4cOVLmnDP5+/srODjY7QYAAGAn5CwAAIDyVXnR1aNHD33zzTduY99++61atGghSYqKilJYWJhSU1OtxwsKCrRp0yZ1795dkhQbG6v69eu7zcnOztbu3butOQAAABcachYAAED5qvyqi48++qi6d++u6dOna9iwYfrss880f/58zZ8/X9Lpr9KPHTtW06dPV+vWrdW6dWtNnz5dDRo00IgRIyRJTqdTo0aN0mOPPaYmTZooJCRE48ePV8eOHa2rAwEAAFxoyFkAAADlq/Ki64orrtDKlSs1adIkPfPMM4qKilJSUpJuu+02a86ECRN04sQJPfDAAzpy5Ii6du2qdevWKSgoyJrzwgsvyNfXV8OGDdOJEyfUp08fJScny8fHp6o3GQAAoE4gZwEAAJTPYYwxtb0R1SE3N1dOp1N9w0fLt55fbW8OAABVrrC4QOuzX5PL5aq1cyaV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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, axs = plt.subplots(1, 2, figsize=(12, 6), constrained_layout=True)\n", + "ctrf = axs[0].contourf(tkk_hod_no_nc_no2pthod[0]/tkk_hod_nc[0])\n", + "cbar = fig.colorbar(ctrf, ax=axs[0])\n", + "ctrf = axs[1].contourf(tkk_hod_no_nc_no2pthod[0]/tkk_hod_no_nc[0])\n", + "cbar = fig.colorbar(ctrf, ax=axs[1])\n", + "#ctrf = axs[2].contourf(tkk_hod_nc[0]/tkk_hod_no_nc[0])\n", + "#cbar = fig.colorbar(ctrf, ax=axs[2])\n", + "axs[0].set_title(\"NFW/HOD w/ number counts\")\n", + "axs[1].set_title(\"NFW/HOD w/o number counts\")\n", + "#axs[2].set_title(\"HOD w/ number counts/HOD w/o number counts\")\n", + "print(tkk_hod_no_nc_no2pthod[0]/tkk_hod_no_nc[0])\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "84f5d020", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "forecasting", + "language": "python", + "name": "forecasting" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/tests/cng_DESgc__0_DESgc__0_DESgc__0_DESgc__0.npz b/tests/cng_DESgc__0_DESgc__0_DESgc__0_DESgc__0.npz new file mode 100644 index 0000000000000000000000000000000000000000..059e6aea72829b98aa71f209abf8c133ac83f172 GIT binary patch literal 3228 zcmeH~`#%%2X@2Tw`_Ij%>-9 zAq!>4baFcxGMA;9U@7VKb(Ky`|$oeKA+d)^Lcz;pI<(o$K&~VA>Cx< zAOHYBVZG}C#wrxDzy4j@0BV51t5HyF1VIL%3P{@6v0fbc?^@s`vB)84J87~*HOmY% zU7e4hG|DnVerTn4W3t*Q2YlNTCXezMwFZ3isA}h^n-6g&71Wz}h>xdH3kC6@7UA5R z|5>suJ0TU?%&f5Sg$ww!%Z-0>ZBZ$(>&TG0%SnnJZ7yfp2CmekRXj?|gTXRHAI8Sn zgVW3J64MwyNn-L>8Qrdg3N%Z7QgbS7N)yWMhnGuE>}|PH4EJxel$&y^Q<7Ufoj&Bb zEbozmwfBi1AryLQ#iAEszJak?%sv6FHXK}hviY2pRjhob^M=sO{Fl%yzsRntU851x zFYBtgcG`xKyTT0nUSh+aTn~yp^1)|ip3X!6%w5CBrUYXwqk|cAk|Qwxd{7*hZuHJRZBEqaFA!|?)lc}{1E+t{-HmlO<94P^ zAKnbo0CMuLRFTm5t?ZKPu(|egdgn|m61%Iw43Q0%3%T67%(qZ^hp~7VW6)o@He+om z*Lv9O@$=+mPEY>l`XezeYo-OIJJ2NKtfStbqU%6ss#8NchC9}_Wd3maRpG7SzD@ay7;XD6WI_aBw?ZhndX$Pp>v$kgLbR)?luN|_N zUY>LS@{>0q-YVbFrvq)=BQYM;vU~Piurn|I9AkI|isKEXdkuFW>E3DEA{P7)ieScfdF#aZp$mZy^UowyNy5XDpBX0$+ znCVQYE%uAwmnctR0B0BU`RaMnCUX5F+lKQ-<=&M_q*S$f;Y*{)JJBPg;Y;#Rf$CYN z1G@E|?27w9D|w_RIkgs{=xWl{n4Le2R$^t((yPJp-S15iz{@O4PDwz!85x)3xW>)y z65ob3dBG{7(12YkZ3vXkmm0<4HT8%{9rwnNj zeG7C{WLsvJ=w}E~uT&FI{}>IjcaZ8(bQ>PR8Ga^-OoYg*`Au@fDM3+>&ct@r?%kFP z+k*CYi(P^TGu;&S(v}P&UbjWhP7lRDdR~RxZs}Q=D}QSnUuX50<}ga*$BA;cq5%*W z9Y4iU5E7JyVJ9T)_2(m1c=P0RphxMF+I&iUAaD9iI0+d9>-LTK#=!?*816TpE0??$`Cx$UC6C0*6VC-ZQAp zXz8r!ZqI656i7KaR3-f5VD&y3BG}HPWj4C6U7_=4Z{P)wV`Uyhp*^$MRVqZLpDoNW z@HsU;1MIQ-Wr?ebCGh*(-!9*}a7JS=FEnCnQ$K>_s4a6()c2PKxb;60-aI4oOG$w9 zinhbCOZLQ?+^DgA3*?2z8Nvs+n)|C5>!O1!Enpp{Ea8*b;W*_8)7!w2Gy)?+7C>(9 zCD6reRM?s!{~`0mqE&8G^}WR@BJZx<)J(|K4z?K^{Fywtn!jY~*YZ{w!5ELpIKQ^f zZeF4RjZk^N^f*!cQy#DHzz6Tr7INoGU- l&Iw4je>W-q!?b Date: Fri, 24 Jan 2025 12:11:35 -0500 Subject: [PATCH 23/28] nfw profile for weaklensing 1h Trispectrum terms, reformatted tests accordingly --- new_sacc.yml | 83 --------- tests/Untitled.ipynb | 170 ------------------ ...ng_DESgc__0_DESgc__0_DESgc__0_DESgc__0.npz | Bin 3228 -> 0 bytes 3 files changed, 253 deletions(-) delete mode 100644 new_sacc.yml delete mode 100644 tests/Untitled.ipynb delete mode 100644 tests/cng_DESgc__0_DESgc__0_DESgc__0_DESgc__0.npz diff --git a/new_sacc.yml b/new_sacc.yml deleted file mode 100644 index bea9a84f..00000000 --- a/new_sacc.yml +++ /dev/null @@ -1,83 +0,0 @@ -tjpcov: - sacc_file: ./new_sacc.sacc - - cosmo: ./tjpcov_ymls/fid_cov.yaml - - cov_type: [FourierGaussianFsky] - - # Survey params: - # 5 lens bins - Ngal_lens0: 2.25 - Ngal_lens1: 3.098 - Ngal_lens2: 3.071 - Ngal_lens3: 2.595 - Ngal_lens4: 1.998 - - # 5 source bins - # {% for i in range(5) %} - # Ngal_src{{ i }}: {{2}} # arc_min^2 - # {% endfor %} - Ngal_src0: 2.036 - Ngal_src1: 1.964 - Ngal_src2: 1.973 - Ngal_src3: 1.987 - Ngal_src4: 2.023 - - # constant bin sigma_z - {% for i in range(5) %} - sigma_z_lens{{ i }}: {{ 0.03 }} - {% endfor %} - - - - # constant bin sigma_z - {% for i in range(5) %} - sigma_z_src{{ i }}: {{ 0.05 }} - {% endfor %} - - - # constant bin sigma_e - {% for i in range(5) %} - sigma_e_src{{ i }}: {{ 0.26 }} - {% endfor %} - - # linear bias for lenses constant for redshift bin (example notebook) - - {% for i, val in [(0, 1.23885511), (1, 1.3781005), (2, 1.52472019), (3, 1.67665752), (4, 1.83243479)] %} - bias_lens{{ i }}: {{ val }} - {% endfor %} - - IA: 1.0 - - lmax: 2000 - lmin: 20 - binning_scheme: log - nonlimber: False - -GaussianFsky: - fsky: 0.42 - -# includes some default values from CCL -# https://ccl.readthedocs.io/en/latest/api/pyccl.halos.profiles.hod.html -HOD: - # automatically creates massdef and concentration objects - log10Mmin_0: 12.0 - log10Mmin_p: 0.0 - siglnM_0: 0.4 - siglnM_p: 0.0 - log10M0_0: 7.0 - log10M0_p: 0.0 - log10M1_0: 13.3 - log10M1_p: 0.0 - alpha_0: 1.0 - alpha_p: 0.0 - fc_0: 1.0 - fc_p: 0.0 - bg_0: 1.0 - bg_p: 0.0 - bmax_0: 1.0 - bmax_p: 0.0 - a_pivot: 1.0 - ns_independent: False - is_number_counts: True - diff --git a/tests/Untitled.ipynb b/tests/Untitled.ipynb deleted file mode 100644 index 552ca000..00000000 --- a/tests/Untitled.ipynb +++ /dev/null @@ -1,170 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "4a94c812", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "\n", - "import pyccl\n", - "\n", - "cosmo = pyccl.CosmologyVanillaLCDM()\n", - "mass_def = pyccl.halos.massdef.MassDef('vir', rho_type='matter')\n", - "concentration = pyccl.halos.concentration.duffy08.ConcentrationDuffy08(mass_def=mass_def)\n", - "halo_bias = pyccl.halos.hbias.tinker10.HaloBiasTinker10(mass_def=mass_def)\n", - "hmf = pyccl.halos.hmfunc.tinker08.MassFuncTinker08(mass_def=mass_def)\n", - "\n", - "NFW_profile = pyccl.halos.profiles.nfw.HaloProfileNFW(mass_def=mass_def, concentration=concentration)\n", - "HOD_profile = pyccl.halos.profiles.hod.HaloProfileHOD(mass_def=mass_def, concentration=concentration, is_number_counts=True)\n", - "HOD_profile_false = pyccl.halos.profiles.hod.HaloProfileHOD(mass_def=mass_def, concentration=concentration, is_number_counts=False)\n", - "\n", - "hmc = pyccl.halos.halo_model.HMCalculator(mass_function=hmf, halo_bias=halo_bias, mass_def=mass_def)\n", - "prof_2pt = pyccl.halos.profiles_2pt.Profile2ptHOD()\n", - "\n", - "z_max = 0.2\n", - "na = pyccl.ccllib.get_pk_spline_na(cosmo.cosmo)\n", - "a_arr, _ = pyccl.ccllib.get_pk_spline_a(cosmo.cosmo, na, 0)\n", - "# Cut the array for efficiency\n", - "sel = 1 / a_arr < z_max + 1\n", - "# Include the next node so that z_max is in the range\n", - "sel[np.sum(~sel) - 1] = True\n", - "a_arr = a_arr[sel]\n", - "\n", - "lk_arr = cosmo.get_pk_spline_lk()\n", - "\n", - "tkk_nfw = pyccl.halos.pk_4pt.halomod_trispectrum_1h(cosmo, hmc, np.exp(lk_arr), a_arr, prof=NFW_profile)\n", - "tkk_hod_nc = pyccl.halos.pk_4pt.halomod_trispectrum_1h(cosmo, hmc, np.exp(lk_arr), a_arr, prof=HOD_profile, prof12_2pt=prof_2pt, prof34_2pt=prof_2pt)\n", - "tkk_hod_no_nc = pyccl.halos.pk_4pt.halomod_trispectrum_1h(cosmo, hmc, np.exp(lk_arr), a_arr, prof=HOD_profile_false, prof12_2pt=prof_2pt, prof34_2pt=prof_2pt)\n", - "tkk_hod_no_nc_no2pthod = pyccl.halos.pk_4pt.halomod_trispectrum_1h(cosmo, hmc, np.exp(lk_arr), a_arr, prof=HOD_profile_false)\n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "dd586346", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAABLoAAAJjCAYAAAALeXi9AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAACCAklEQVR4nOzdfVxUdf7//+cAMhACeZEgiYCuiYaZYnlVqamYpdZn19WysAst/VEWWVuxVqK1mm4plRfVplKZ6aZp7a6ZWHm1WhlJl2ZtqahBaKsgpiBwfn/4ZbZxuJiBGYY5PO6327ntzvu8zznvM0Pn5Xmd9/t9LIZhGAIAAAAAAAB8nJ+3GwAAAAAAAAC4A4kuAAAAAAAAmAKJLgAAAAAAAJgCiS4AAAAAAACYAokuAAAAAAAAmAKJLgAAAAAAAJgCiS4AAAAAAACYAokuAAAAAAAAmAKJLgAAAAAAAJgCia5aZGZmymKxKCgoSAcOHHBYP3DgQCUkJNiVxcbGymKxVLkUFxdr9erVslgsWrVqlcP+unfvLovFovfee89hXceOHdWzZ0+H8ueee06tWrVSWVmZNm/eLIvFotWrV1d5Pvfcc48sFotD+ZkzZ7R48WL17dtX4eHhCg4OVpcuXfTII4/ol19+qfK8K8/Jz89PoaGh+t3vfqc//vGPWr16tSoqKqo8vrtNnTpV3bt3b5BjuZPFYtE999zj7WY0aitWrFBGRoa3mwFUi/hAfPCm2NhYjRgxwtvNaNTWr1+v9PR0bzcDgAs++OAD3XHHHYqPj1dISIguvPBCXX/99crOzq7T/n766Selp6crJyfH5W1ri5vudNtttyk2NrbKdb+NZ+7+fqT6fUdAY0Wiy0klJSV69NFHna7fv39/7dy502E577zzbDcBH374od02//3vf/Xll18qJCTEYd2hQ4f0448/atCgQQ7HWrNmja6//noFBATU6dx+/fVXDR06VFOmTFGPHj30xhtvaP369UpOTtZLL72kHj16aO/evQ7bdejQQTt37tSOHTu0bt06PfLIIzp16pT++Mc/auDAgSosLKxTe1zx1ltv6Q9/+IPHj4OGR6ILvoL4QHxA47R+/XrNmDHD280A4ILFixdr//79uu+++7R+/Xo9++yzKigoUJ8+ffTBBx+4vL+ffvpJM2bM8Okkzm/jmbu/H8kc3xFwrrr9y7cJuuaaa7RixQo9+OCDTj0hPv/889WnT58q17Vu3VoJCQnavHmzXfmWLVsUEBCgCRMmONzIVH4+90bm559/1vbt2/XQQw+5cDb27r//fm3ZskUrV67U2LFjbeWDBg3S6NGjdfnll+sPf/iDPv/8c/n7+9vWBwcHO5zjxIkTtWzZMt1xxx266667quyV4C67du3SgQMHuJGpRnl5ucrKymS1Wr3dFMDUiA/EB7MyDEOnT59WcHCwt5sCoIlYuHCh2rRpY1d2zTXX6He/+51mzZqlq6++2kst845z4xnfD+AcenQ56aGHHlKrVq308MMPu2V/gwYN0t69e5WXl2cr27x5sy677DJde+21ys7O1okTJ+zW+fv768orr7Tbz9q1a9W8eXMNGTKkTu3Iz8/X0qVLNWzYMLubmEoXXXSRHn74YX399ddat26dU/u8/fbbde211+rNN9+scjhPpYULF8rPz08FBQW2smeeeUYWi0V33323rayiokItWrTQAw88YLf9mjVr1LlzZ1188cXVHqOyy/Ebb7yhadOmKSoqSmFhYRoyZIhDL4TY2FjddtttDvsYOHCgBg4c6LDPFStW6OGHH1bbtm3VvHlzjRw5Uj///LNOnDihu+66S61bt1br1q11++23q7i4uMr2vfjii7roootktVrVtWtXrVy50qFOfn6+Jk2apHbt2ikwMFBxcXGaMWOGysrKbHX2798vi8WiuXPn6sknn1RcXJysVqvDDfFvVVRU6Pnnn9ell16q4OBg2833O++8Y1dn7ty5io+Pl9VqVZs2bTR+/HgdOnSoXt9dbb/HwIED9a9//UsHDhywG9pVafHixerevbuaN2+u0NBQxcfH689//nO15wp4EvHBN+LD9u3bNXjwYIWGhuq8885Tv3799K9//avWNldeX59++mnNmzdPcXFxat68ufr27auPPvrIru6517xK5w5JqdznX//6V82ZM0exsbEKDg7WwIED9d133+nMmTN65JFHFBUVpfDwcP3f//2f3XfxW2vXrtUll1yioKAgdejQQc8995xDnaKiIj344IOKi4tTYGCgLrzwQqWmpurkyZN29SqH1b/wwgvq0qWLrFarXnnllRq/nxUrVqhv375q3ry5mjdvrksvvVRLliyxq7N06VJ1795dQUFBatmypf7v//5Pe/bsqdd3V9vvcdttt2nhwoW286pc9u/fL0l688031bt3b4WHh+u8885Thw4ddMcdd9R4rgA879wkjiQ1b95cXbt21cGDB21llcO3a7oGVsZO6Wz8qbwOuDqk+cyZM7XeR0jOXeuks1MfdO7cWVarVV26dNGrr75a7bHPjWfOfj9Sw35HQGNDostJoaGhevTRR/Xee+851S3UMAyVlZXZLb+dl6Tyyftvn9p/+OGHGjBggPr37y+LxaJt27bZrevZs6fCw8PtjrNmzRqNGDHCoddORUWFw/HLyspkGIZdvQ8//FBlZWW64YYbqj2XynVZWVm1nnelUaNGyTAMu3M415AhQ2QYht5//31b2aZNmxQcHGx3rE8//VTHjx93uFlbs2aN00/r//znP+vAgQN6+eWX9dJLL+n777/XyJEjVV5e7vQ5VbXPgoICZWZm6plnntHmzZt100036Q9/+IPCw8P1xhtv6KGHHtJrr71WZRLmnXfe0XPPPaeZM2dq9erViomJ0U033WQ3D0B+fr4uv/xyvffee3r88cf17rvvasKECZo9e7buvPNOh30+99xz+uCDD/T000/r3XffVXx8fLXtv+2223Tffffpsssu06pVq7Ry5UqNGjXKdhMgSf/f//f/6eGHH9bQoUP1zjvv6IknntCGDRvUr18/HT16tF7fXU2/x6JFi9S/f39FRkbaDe2SpJUrVyolJUUDBgzQ2rVrtW7dOt1///0ON2xAQyE+NP74sGXLFl199dUqLCzUkiVL9MYbbyg0NFQjR450umfZwoULlZWVpYyMDL3++us6efKkrr322noNw1y4cKH+/e9/a+HChXr55Zf17bffauTIkZowYYKOHDmipUuXau7cudq0aZMmTpzosH1OTo5SU1N1//33a+3aterXr5/uu+8+Pf3007Y6v/76qwYMGKBXXnlF9957r9599109/PDDyszMtP0Wv7Vu3TotXrxYjz/+uN577z2HBOpvPf7447r55psVFRWlzMxMrV27VrfeeqtdEnP27NmaMGGCLr74Yr311lt69tln9cUXX6hv3776/vvv6/Xd1fR7PPbYYxo9erQk2cWRtm3baufOnRo7dqw6dOiglStX6l//+pcef/xxuwdIABqPwsJCffbZZw4Pt2u7Bvbs2VPLli2TJD366KO260BV19OaOHMf4ey1LjMzU7fffru6dOmiNWvW6NFHH9UTTzxR7b8fnLnfqe77acjvCGh0DNRo2bJlhiRj165dRklJidGhQwejV69eRkVFhWEYhjFgwADj4osvttsmJibGkOSwTJs2zVbnv//9r+Hn52fcddddhmEYxtGjRw2LxWJs2LDBMAzDuPzyy40HH3zQMAzDyM3NNSQZDz30kN1xjh49agQEBBhr1qyxlX344YdVHvvcpdJTTz1lSLIdtyqnTp0yJBnDhw+3lVV13r/17rvvGpKMOXPmVFvHMAyjXbt2xh133GEYhmGUlJQYISEhxsMPP2xIMg4cOGAYhmH85S9/MZo1a2YUFxfbtsvJyTEkGdnZ2TXuv/L7uPbaa+3K//73vxuSjJ07d9rKYmJijFtvvdVhHwMGDDAGDBjgsM+RI0fa1UtNTTUkGffee69d+Q033GC0bNnSrkySERwcbOTn59vKysrKjPj4eON3v/udrWzSpElG8+bNbd9FpaefftqQZHz99deGYRjGvn37DElGx44djdLS0hq+kbO2bt3q8Dd5rj179hiSjJSUFLvyjz/+2JBk/PnPf7aVufrdOfN7XHfddUZMTIzDPu+55x7j/PPPr+UMAc8jPvhOfOjTp4/Rpk0b48SJE7aysrIyIyEhwWjXrp3tN6tK5fW1W7duRllZma38k08+MSQZb7zxht25//aaV+nWW2+1u55V7rN79+5GeXm5rTwjI8OQZIwaNcpu+8r4UlhYaCuLiYkxLBaLkZOTY1d36NChRlhYmHHy5EnDMAxj9uzZhp+fn7Fr1y67eqtXrzYkGevXr7eVSTLCw8ON//73v9V+H5V+/PFHw9/f37j55purrXPs2DEjODjY4Zqfm5trWK1WY9y4cbYyV787Z36Pu+++2+5vulJlDD1+/Hit5wnA+26++WYjICDA+PTTT21lzl4Dd+3aZUgyli1b5vJxnf13q7PXuvLyciMqKsro2bOnXdzZv3+/0axZM4d/9zp7v1PV92MYDfMdAY0VPbpcEBgYqCeffFKffvqp/v73v9dY94orrtCuXbvslpSUFNv6Fi1aqHv37rYn9lu2bJG/v7/69+8vSRowYIBt2Fl186+8/fbbCgwM1DXXXONw/Dlz5jgcf9euXRozZkydz7+qt3FVxzjnCXF1Bg8erE2bNkmSduzYoV9//VVTp05V69atbU/tN23apL59+yokJMS23Zo1axQbG1vlW8aqMmrUKLvPl1xyiSTVOHSmNue+7apLly6SpOuuu86h/L///a/D8MXBgwcrIiLC9tnf319jx47Vf/7zH9vQwH/+858aNGiQoqKi7HpeDB8+XNLZv5vfGjVqlJo1a1Zr2999911JshsCdK7Kv7tzhyRefvnl6tKli11PC1fV5/e4/PLLdfz4cd100016++2369WzDHAX4kPjjQ8nT57Uxx9/rNGjR6t58+a2ev7+/kpOTtahQ4eqHIJyruuuu85uHjJ3xJFrr71Wfn7/+6dYTXFEknJzc+3KL774Yod54caNG6eioiJ99tlnks7GkYSEBF166aV2cWTYsGGyWCwO88FdffXVatGiRa1tz8rKUnl5eY1xZOfOnTp16pRDHImOjtbVV19drzhSn9+jcpjOmDFj9Pe//12HDx+uczsAeNZjjz2m119/XfPnz1diYqLdOmeuge5Q279bnb3W7d27Vz/99JPGjRtnFzdjYmLUr18/h+M6c79T0/cjNdx3BDQ2JLpcdOONN6pnz56aNm2azpw5U2298PBw9erVy26JioqyqzNo0CB99913+umnn/Thhx8qMTHR9o/wAQMGaPfu3SosLNSHH36ogIAAXXHFFXbbr169WsOHD9d5553ncPwOHTo4HL9Xr1664IIL7Oq1b99ekrRv375qz6VyXXR0dA3fjL3KC/+553yuIUOGKDc3V99//702bdqkHj16qE2bNrr66qu1adMmnTp1Sjt27HAYlrJ69WqXJhlu1aqV3efKoTynTp1yeh/natmypd3nwMDAGstPnz5tVx4ZGemwz8qyX375RdLZyaT/8Y9/qFmzZnZLZdfkc5M8bdu2dartR44ckb+/f5VtqFTZhqr2GRUVZVtfF/X5PZKTk7V06VLbxJxt2rRR7969XRo6BXgC8cE5DR0fjh07JsMwqr2WSXLqeubLceSLL75wiCOhoaEyDKNecUSS2rVrV22dxhpHrrrqKq1bt05lZWUaP3682rVrp4SEBL3xxht1bg8A95sxY4aefPJJ/eUvf9E999zjsN6Za6A71Ha9cfZaV/m/NbX7t2q736nt+6ntWO78joDGhkSXiywWi+bMmaMffvhBL730Ur329dt5WDZv3qwBAwbY1lXetGzdutU2SeBvn0QXFhbq/fffr/cbpQYNGqSAgIAaJxKuXDd06FCn9/vOO+/IYrHoqquuqrHe4MGDJZ19Kp+VlWU7xuDBg/X+++9r69atKikpsbuR2bNnj/bs2eP2t2kFBQWppKTEodxTPYby8/OrLasMqK1bt1ZSUlKVvS927dqlCRMm2G3vbK+KCy64QOXl5VW2oVJlG347IXaln376Sa1bt7Z9bujv7vbbb9eOHTtUWFiof/3rXzIMQyNGjKhXzwqgvogPzmno+NCiRQv5+flVey2TZHc9q4/GGke6detWbRx57LHH7LZ3JY5Icng5yW815jhy/fXX6/3331dhYaE2b96sdu3aady4cbb5IAF414wZM5Senq709PRqXzjkzDWwITh7rausV1O7K9V2v+PM91PbsRryOwIaGomuOhgyZIiGDh2qmTNnVvs2PWdcddVV8vf31+rVq/X111/bvW0oPDxcl156qV555RXt37/fYVjKP/7xD1ksFofhc66KjIzUHXfcoffee6/KCXm/++47zZkzRxdffHGNExL/1rJly/Tuu+/qpptusvUIqE7btm3VtWtXrVmzRtnZ2bYbmaFDh+rIkSOaN2+ewsLCbMMMpLPdeKOiohxeXV9fsbGx+uKLL+zKvvvuO6eGtNTF+++/r59//tn2uby8XKtWrVLHjh1tT8hHjBihr776Sh07dqyyB0ZtPSKqUzn0cfHixdXWqXw98fLly+3Kd+3apT179thuQiXPfHdWq7XWJ/MhISEaPny4pk2bptLSUn399dd1Ph7gDsSHmnkjPoSEhKh3795666237K4pFRUVWr58udq1a6eLLrrIqfbXJjY2Vt99951dwuaXX37Rjh073LL/c3399df6/PPP7cpWrFih0NBQ21CXESNG6IcfflCrVq2qjCO/faOhK5KSkuTv719jHOnbt6+Cg4Md4sihQ4f0wQcfOMQRd393zvTyslqtGjBggObMmSNJ2r17d52PB8A9nnjiCaWnp+vRRx/V9OnTq63nzDXQHb1va+Psta5z585q27at3njjDbth/AcOHHC41tV0v+Ps9yM1nu8IaGgB3m6Ar5ozZ44SExNVUFBQ5RsunBEWFqaePXtq3bp18vPzs82/UmnAgAHKyMiQ5Dj/yurVqzV06FCFhobW6di/NW/ePO3du1e33HKLtm7dqpEjR8pqteqjjz7S008/rdDQUK1Zs8ZuLgzp7MWw8lXep06d0o8//qh169bpn//8pwYMGKAXXnjBqeMPHjxYzz//vIKDg23fQVxcnOLi4rRx40aNGjVKAQH/+1NdvXq1fv/737s0J4wzkpOTdcsttyglJUV/+MMfdODAAc2dO9dhOI+7tG7dWldffbUee+wxhYSEaNGiRfr222+1cuVKW52ZM2cqKytL/fr107333qvOnTvr9OnT2r9/v9avX68XXnihxmEj1bnyyiuVnJysJ598Uj///LPtzWy7d+/WeeedpylTpqhz586666679Pzzz8vPz0/Dhw/X/v379dhjjyk6Olr333+/bX+e+O66deumt956S4sXL1ZiYqL8/PzUq1cv3Xnnnba/lbZt2yo/P1+zZ89WeHi43Q0v4C3Eh8YXH2bPnq2hQ4dq0KBBevDBBxUYGKhFixbpq6++0htvvOG2eJKcnKwXX3xRt9xyi+6880798ssvmjt3rsLCwtyy/3NFRUVp1KhRSk9PV9u2bbV8+XJlZWVpzpw5tmGrqampWrNmja666irdf//9uuSSS1RRUaHc3Fxt3LhRDzzwgHr37u3ysWNjY/XnP/9ZTzzxhE6dOqWbbrpJ4eHh+uabb3T06FHNmDFD559/vh577DH9+c9/1vjx43XTTTfpl19+0YwZMxQUFGR3g+aJ765bt26Szv43OXz4cPn7++uSSy7Rk08+qUOHDmnw4MFq166djh8/rmeffVbNmjWz6z0JoOE988wzevzxx3XNNdfouuuus8WSSr9N/DhzDezYsaOCg4P1+uuvq0uXLmrevLmioqLq/LC4Ks5e6/z8/PTEE09o4sSJ+r//+z/deeedOn78uNLT0x2GGFYXz1z5fhrTdwQ0OG/OhO8LfvtWrXONGzfOkFTlW7Wuu+46p/b/0EMPGZKMXr16Oaxbt26dIckIDAy0vRXDMAyjuLjYCAoKqvLNGJVvB3nzzTerPF51byAqLS01Fi5caPTu3dto3ry5YbVajc6dOxsPPfSQcfToUYf6AwYMsHtLV0hIiNGhQwdj9OjRxptvvmn3FqnavP3224YkY+jQoXbld955pyHJeO6552xl//nPfwxJxocffujUvqv7Pirf2vTb77CiosKYO3eu0aFDByMoKMjo1auX8cEHH1T75sBz91nd38r06dMNScaRI0dsZZKMu+++21i0aJHRsWNHo1mzZkZ8fLzx+uuvO5zDkSNHjHvvvdeIi4szmjVrZrRs2dJITEw0pk2bZnvTWOX5/PWvf3XqezGMs29+mT9/vpGQkGAEBgYa4eHhRt++fY1//OMfdnXmzJljXHTRRUazZs2M1q1bG7fccotx8OBBu33V97ur6vf473//a4wePdo4//zzDYvFYvu7feWVV4xBgwYZERERRmBgoBEVFWWMGTPG+OKLL5w+d8AdiA++FR+2bdtmXH311UZISIgRHBxs9OnTx+56V52arq+SjOnTp9uVvfLKK0aXLl2MoKAgo2vXrsaqVauqfXPguft0Jb5U/i2tXr3auPjii43AwEAjNjbWmDdvnkM7i4uLjUcffdTo3Lmz7XrfrVs34/7777d7+29lbHLFq6++alx22WVGUFCQ0bx5c6NHjx4Of38vv/yycckll9iOff3119veGvxb9fnuKtv/29+jpKTEmDhxonHBBRfY4si+ffuMf/7zn8bw4cONCy+80AgMDDTatGljXHvttca2bdtcOncA7nduDDl3qeTKNfCNN94w4uPjjWbNmlV53a6OK/9uNQznr3Uvv/yy0alTJyMwMNC46KKLjKVLl9pd62qKZ85+Pw31HQGNlcUwnHz9ERqNv//977r55pv1888/O0xYa3Zz587V008/rby8PIceBADQ1BEfiA8A0BTExsYqISFB//znP73dFLdzVzwz83cE1IZEFwAAAADAZ5DEqR3fEZoy5ugCAAAAADQJhmGovLy8xjr+/v5unw8YQMOhRxcAAAAAoEnYvHmzw4tczrVs2TLddtttDdMgAG7n5+0GAAA8Z/bs2brssssUGhqqNm3a6IYbbtDevXud3v7f//63AgICdOmll3qukQCARoGYgaYgMTFRu3btqnEZOXKkt5sJNHqVb+SOioqSxWLRunXrat1my5YtSkxMVFBQkDp06ODwJu7MzExZLBaH5fTp0y61jaGLAGBiW7Zs0d13363LLrtMZWVlmjZtmpKSkvTNN98oJCSkxm0LCws1fvx4DR48WD///HMDtRgA4C3EDDQFoaGh6tWrl7ebAfi8kydPqnv37rr99tv1hz/8odb6+/bt07XXXqs777xTy5cv17///W+lpKToggsusNs+LCzM4SFLUFCQS21j6CIANCFHjhxRmzZttGXLFl111VU11r3xxhvVqVMn+fv7a926dcrJyWmYRgIAGgViBgDAGRaLRWvXrtUNN9xQbZ2HH35Y77zzjvbs2WMr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Wrp0qc6cOaOjR4+qbdu2ys/Pd2mfVSHRBQAAAAAAAB08eFBhYWG2z1artcb6FovF7rNhGA5llR577DHl5+erT58+MgxDERERuu222zR37lz5+/vXaZ9VYegiAAAAAAAAFBYWZrdUl+hq3bq1/P39HXpaFRQUOPTIqhQcHKylS5fq119/1f79+5Wbm6vY2FiFhoaqdevWkqTIyEiX9lkVEl0AAAAAAABwWmBgoBITE5WVlWVXnpWVpX79+tW4bbNmzdSuXTv5+/tr5cqVGjFihPz8zqan+vbt67DPjRs31rrP32LoIgAAAAAAAFwydepUJScnq1evXurbt69eeukl5ebmavLkyZKktLQ0HT58WK+++qok6bvvvtMnn3yi3r1769ixY5o3b56++uorvfLKK7Z93nfffbrqqqs0Z84cXX/99Xr77be1adMmbd++3el2kegCAAAAAACAS8aOHatffvlFM2fOVF5enhISErR+/XrFxMRIkvLy8pSbm2urX15ermeeeUZ79+5Vs2bNNGjQIO3YsUOxsbG2Ov369dPKlSv16KOP6rHHHlPHjh21atUq9e7d2+l2kegCAAAAAACAy1JSUpSSklLluszMTLvPXbp00e7du2vd5+jRozV69Og6t4k5ugAAAAAAAGAKJLoAAAAAAABgCiS6AAAAAAAAYAokugAAAAAAAGAKJLoAAAAAAABgCiS6AAAAAAAAYAokugAAAAAAAGAKJLoAAAAAAABgCiS6AAAAAAAAYAouJ7q2bt2qkSNHKioqShaLRevWrbNbbxiG0tPTFRUVpeDgYA0cOFBff/21XZ2SkhJNmTJFrVu3VkhIiEaNGqVDhw7Z1Tl27JiSk5MVHh6u8PBwJScn6/jx4y6fIADAe4gZAABnETMAAO7gcqLr5MmT6t69uxYsWFDl+rlz52revHlasGCBdu3apcjISA0dOlQnTpyw1UlNTdXatWu1cuVKbd++XcXFxRoxYoTKy8ttdcaNG6ecnBxt2LBBGzZsUE5OjpKTk+twigAAbyFmAACcRcwAALhDgKsbDB8+XMOHD69ynWEYysjI0LRp0/T73/9ekvTKK68oIiJCK1as0KRJk1RYWKglS5botdde05AhQyRJy5cvV3R0tDZt2qRhw4Zpz5492rBhgz766CP17t1bkvS3v/1Nffv21d69e9W5c+e6ni8AoAER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AAAAAABoUOf/p1QBAZ7tp1RWVipJio6OtiufPn260tPTHeofPXpU5eXlioiIsCuPiIhQfn5+jcdq166djhw5orKyMqWnp2vixIm2dfn5+XXa52+R6AIAAAAAAIAOHjyosLAw22er1VpjfYvFYvfZMAyHsnNt27ZNxcXF+uijj/TII4/od7/7nW666aZ67fO3SHQBAAAAAABAYWFhdomu6rRu3Vr+/v4OPa0KCgocemSdKy4uTpLUrVs3/fzzz0pPT7cluiIjI+u0z99iji4AAAAAAAA4LTAwUImJicrKyrIrz8rKUr9+/Zzej2EYdvOA9e3b12GfGzdudGmf9OgCAAAAAACAS6ZOnark5GT16tVLffv21UsvvaTc3FxNnjxZkpSWlqbDhw/r1VdflSQtXLhQ7du3V3x8vCRp+/btevrppzVlyhTbPu+77z5dddVVmjNnjq6//nq9/fbb2rRpk7Zv3+50u0h0AQAAAAAAwCVjx47VL7/8opkzZyovL08JCQlav369YmJiJEl5eXnKzc211a+oqFBaWpr27dungIAAdezYUU899ZQmTZpkq9OvXz+tXLlSjz76qB577DF17NhRq1atUu/evZ1uF4kuAAAAAAAAuCwlJUUpKSlVrsvMzLT7PGXKFLveW9UZPXq0Ro8eXec2MUcXAAAAAAAATIFEFwAAAAAAAEyBRBcAAAAAAABMgUQXAAAAAAAATIFEFwAAAAAAAEyBRBcAAAAAAABMgUQXAAAAAAAATIFEFwAAAAAAAEyBRBcAAAAAAABMgUQXADQBixYtUlxcnIKCgpSYmKht27bVWL+kpETTpk1TTEyMrFarOnbsqKVLlzZQawEA3kTMAAD4sgBvNwAA4FmrVq1SamqqFi1apP79++vFF1/U8OHD9c0336h9+/ZVbjNmzBj9/PPPWrJkiX73u9+poKBAZWVlDdxyAEBDI2YAAHwdiS4A8EFFRUV2n61Wq6xWa5V1582bpwkTJmjixImSpIyMDL333ntavHixZs+e7VB/w4YN2rJli3788Ue1bNlSkhQbG+veEwAANBhiBgCgKSHRBQBuEravRAEBFo8eo6ysRJIUHR1tVz59+nSlp6c71C8tLVV2drYeeeQRu/KkpCTt2LGjymO888476tWrl+bOnavXXntNISEhGjVqlJ544gkFBwe750QAoIkjZgAA4Bkk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v6SkRBdccIGmTZum7t27V7vfsLAw5eXl2S1BQUFOt4tEFwAAAAAAAFwyb948TZgwQRMnTlSXLl2UkZGh6Oho25yK54qNjdWzzz6r8ePHKzw8vNr9WiwWRUZG2i2uINEFAAAAAAAAFRUV2S0lJSVV1istLVV2draSkpLsypOSkrRjx456taG4uFgxMTFq166dRowYod27d7u0vdsnowcAAAAAAIB7BH+TpwC/QI8eo6yiVJIUHR1tVz59+vQqX/Bx9OhRlZeXKyIiwq48IiJC+fn5dW5HfHy8MjMz1a1bNxUVFenZZ59V//799fnnn6tTp05O7YNEFwAAAAAAAHTw4EGFhYXZPlut1hrrWywWu8+GYTiUuaJPnz7q06eP7XP//v3Vs2dPPf/883ruueec2geJLgAAAAAAACgsLMwu0VWd1q1by9/f36H3VkFBgUMvr/rw8/PTZZddpu+//975bdx2dAAAAAAAAJheYGCgEhMTlZWVZVeelZWlfv36ue04hmEoJydHbdu2dXobenQBAAAAAADAJVOnTlVycrJ69eqlvn376qWXXlJubq4mT54sSUpLS9Phw4f16quv2rbJycmRdHbC+SNHjignJ0eBgYHq2rWrJGnGjBnq06ePOnXqpKKiIj333HPKycnRwoULnW4XiS4AAAAAAAC4ZOzYsfrll180c+ZM5eXlKSEhQevXr1dMTIwkKS8vT7m5uXbb9OjRw/b/s7OztWLFCsXExGj//v2SpOPHj+uuu+5Sfn6+wsPD1aNHD23dulWXX3650+1i6CIANAGLFi1SXFycgoKClJiYqG3btlVbd/v27erfv79atWql4OBgxcfHa/78+Q3YWgCANxEzAADOSklJ0f79+1VSUqLs7GxdddVVtnWZmZnavHmzXX3DMByWyiSXJM2fP18HDhxQSUmJCgoK9N5776lv374utYkeXQBgcqtWrVJqaqoWLVqk/v3768UXX9Tw4cP1zTffqH379g71Q0JCdM899+iSSy5RSEiItm/frkmTJikkJER33XWXF84AANBQiBkAAF9Hjy4AMLl58+ZpwoQJmjhxorp06aKMjAxFR0dr8eLFVdbv0aOHbrrpJl188cWKjY3VLbfcomHDhtX4RB8AYA7EDACAryPRBQA+qKioyG4pKSmpsl5paamys7OVlJRkV56UlKQdO3Y4dazdu3dr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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "fig, axs = plt.subplots(1, 3, figsize=(12, 6), constrained_layout=True)\n", - "ctrf = axs[0].contourf(tkk_nfw[0]/tkk_hod_nc[0])\n", - "cbar = fig.colorbar(ctrf, ax=axs[0])\n", - "ctrf = axs[1].contourf(tkk_nfw[0]/tkk_hod_no_nc[0])\n", - "cbar = fig.colorbar(ctrf, ax=axs[1])\n", - "ctrf = axs[2].contourf(tkk_hod_no_nc[0]/tkk_hod_no_nc_no2pthod[0])\n", - "cbar = fig.colorbar(ctrf, ax=axs[2])\n", - "axs[0].set_title(\"NFW/HOD w/ number counts\")\n", - "axs[1].set_title(\"NFW/HOD w/o number counts\")\n", - "axs[2].set_title(\"2pt_hod/2pt\")\n", - "#print(tkk_hod_no_nc_no2pthod[0]/tkk_hod_no_nc[0])\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "d442d4eb", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[[1.00223502e+00 1.00223502e+00 1.00223502e+00 ... 7.92927257e+03\n", - " 8.14150586e+03 8.36389810e+03]\n", - " [1.00223502e+00 1.00223502e+00 1.00223502e+00 ... 7.92927257e+03\n", - " 8.14150586e+03 8.36389810e+03]\n", - " [1.00223502e+00 1.00223502e+00 1.00223502e+00 ... 7.92927257e+03\n", - " 8.14150586e+03 8.36389810e+03]\n", - " ...\n", - " [7.92927257e+03 7.92927257e+03 7.92927257e+03 ... 1.46979173e+08\n", - " 1.50845442e+08 1.54941619e+08]\n", - " [8.14150586e+03 8.14150586e+03 8.14150586e+03 ... 1.50845442e+08\n", - " 1.54764729e+08 1.58984428e+08]\n", - " [8.36389810e+03 8.36389810e+03 8.36389810e+03 ... 1.54941619e+08\n", - " 1.58984428e+08 1.63261414e+08]]\n" - ] - }, - { - "data": { - "image/png": "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HSpjjNs+nKlv374yxujDDz+0xtavX6/AwEC399q+fbuOHj3qET5TUlIqfPTxiSee0L59+/SPf/xD8+fP1969ezVkyBAVFRVVeJ9Ke81Dhw4pOTlZzz//vDZu3Khbb71VN954o5xOp5YuXaoJEybozTffLLWEeeeddzRnzhw988wzevvtt9WiRQvdeuutbucDycnJ0ZVXXqm1a9fq6aef1vvvv69Ro0ZpxowZuvfeez1ec86cOfroo4/03HPP6f3331fbtm3L3P4777xTY8aM0RVXXKHly5dr2bJlGjp0qBVqJOn//b//p4kTJ6pfv35655139Oc//1kffPCBunfvrsOHD5/X2pX35/HKK6+oR48eCgsLc/upiiQtW7ZMDzzwgOLj47Vy5UqtWrVKjz76qEcABQB4H/KU9+epTZs26ZprrpHL5dKCBQu0dOlSBQUFaciQIRX+ZtnLL7+s1NRUJSUl6Z///KeOHz+ugQMHntfPMF9++WX93//9n15++WX94x//0Ndff60hQ4Zo1KhR+vnnn/X6669r1qxZWr9+ve655x6P52dkZGjs2LF69NFHtXLlSnXv3l1jxozRc889Z8357bffFB8fr0WLFumRRx7R+++/r4kTJyo5Odn6s/i9VatWad68eXr66ae1du1ajwL1955++mnddtttioiIUHJyslauXKmRI0e6lZgzZszQqFGj1KFDB61YsUIvvviiPv/8c8XFxWnv3r3ntXbl/Xk89dRTuummmyTJLXeFh4crLS1Nw4cPV6tWrbRs2TK99957evrpp90OuAI4RwaoJQsXLjSSzLZt20x+fr5p1aqV6dKliykuLjbGGBMfH286dOjg9pwWLVoYSR63yZMnW3N+/fVXU69ePXPfffcZY4w5fPiwcTgc5oMPPjDGGHPllVea8ePHG2OMycrKMpLMhAkT3N7n8OHDxtfX16SkpFhjGzZsKPW9z7yV+Otf/2okWe9bmhMnThhJZsCAAdZYafv9e++//76RZGbOnFnmHGOMad68ubn77ruNMcbk5+ebhg0bmokTJxpJZt++fcYYY/7yl7+Y+vXrm7y8POt5GRkZRpJJT08v9/VL1mPgwIFu4//617+MJJOWlmaNtWjRwowcOdLjNeLj4018fLzHaw4ZMsRt3tixY40k88gjj7iNX3/99SYkJMRtTJIJDAw0OTk51lhhYaFp27at+eMf/2iNjR492jRq1MhaixLPPfeckWT27NljjDEmMzPTSDKXXnqpKSgoKGdFTtu8ebPH38kzffXVV0aSeeCBB9zGP/30UyPJPPHEE9ZYZdeuIn8egwYNMi1atPB4zYceeshcdNFFZ9lDAIA3IU/VnTzVrVs306xZM3Ps2DFrrLCw0ERHR5vmzZtbf2alKckjHTt2NIWFhdb4Z599ZiSZpUuXuu377zNCiZEjR7p9/pe8ZqdOnUxRUZE1npSUZCSZoUOHuj2/JI+5XC5rrEWLFsbhcJiMjAy3uf369TPBwcHm+PHjxhhjZsyYYerVq2e2bdvmNu/tt982ksyaNWusMUnG6XSaX3/9tcz1KPH9998bHx8fc9ttt5U558iRIyYwMNAjI2VlZRl/f38zYsQIa6yya1eRP48HH3zQ7e90iZLMefTo0bPuJ4DK4Rtd8Ap+fn569tlntX37dv3rX/8qd+5VV12lbdu2ud0eeOAB6/HGjRurU6dO1hHITZs2ycfHRz169JAkxcfHWz87K+t8EqtXr5afn5+uvfZaj/efOXOmx/tv27ZNw4YNO+f9L+3qQmUxZxzxKkufPn20fv16SdLWrVv122+/ady4cWratKl1FHL9+vWKi4tTw4YNreelpKSoZcuWpV41qTRDhw51u3/ZZZdJUrk/BTibM6/e065dO0nSoEGDPMZ//fVXj58v9unTR6GhodZ9Hx8fDR8+XN99953108B///vf6t27tyIiItyOJA8YMEDS6b83vzd06FDVr1//rNv+/vvvS5LbTxrOVPL37syfJF555ZVq166d25HjyjqfP48rr7xSR48e1a233qrVq1ef1zfLcGHavHmzhgwZooiICDkcjgr/jOj31q5dq27duikoKEgXX3yxbrzxRmVmZlb9xgI2RJ7y3jx1/Phxffrpp7rpppvUqFEja56Pj48SExN14MCBUk+of6ZBgwa5nYesKnLXwIEDVa/ef/+zsLzcJUlZWVlu4x06dPA4L9yIESOUm5urHTt2SDqdu6Kjo3X55Ze75a7+/fvL4XB4nA/ummuuUePGjc+67ampqSoqKio3d6WlpenEiRMeuSsyMlLXXHPNeeWu8/nzuOKKKyRJw4YN07/+9S8dPHjwnLcDFwZyVsVRdMFr3HLLLercubMmT56sU6dOlTnP6XSqS5cubreIiAi3Ob1799a3336rH3/8URs2bFBsbKwVKuLj47Vz5065XC5t2LBBvr6+uuqqq9ye//bbb2vAgAFq0KCBx/u3atXK4/27dOmiiy++2G3eJZdcIknl/sNR8lhkZGQ5K+Ou5IPzzH0+U9++fZWVlaW9e/dq/fr1iomJUbNmzXTNNddo/fr1OnHihLZu3erxNfu33367UidNbdKkidv9kp8mnDhxosKvcaaQkBC3+35+fuWOnzx50m08LCzM4zVLxkouQf7TTz/p3XffVf369d1uJefROLPkCQ8Pr9C2//zzz/Lx8Sl1G0qUbENprxkREVHqZdIr6nz+PBITE/X6669bJ85t1qyZunbtWqmfguDCdvz4cXXq1Elz5849p+d///33uu6663TNNdcoIyNDa9eu1eHDh3XDDTdU8ZYC9kWeqpiazlNHjhyRMabMz35JFfr8r8u56/PPP/fIXUFBQTLGnFfukqTmzZuXOcdbc1fPnj21atUqFRYW6o477lDz5s0VHR2tpUuXnvP2wN7IWRVH0QWv4XA4NHPmTP3nP//R/Pnzz+u1fn9eiY0bNyo+Pt56rCSEbd682Tqp6u+PrLlcLn344YfnfYWc3r17y9fXt9ymveSxfv36Vfh133nnHTkcDvXs2bPceX369JF0+ihjamqq9R59+vTRhx9+qM2bNys/P98tmH311Vf66quvqvzqQAEBAcrPz/cYr65vDOXk5JQ5VhJImjZtqoSEhFKPJm/btk2jRo1ye35FjxJffPHFKioqKnUbSpRsw+9P8Fvixx9/VNOmTa37Nb12d911l7Zu3SqXy6X33ntPxhgNHjz4vI4U48IxYMAAPfvss2UGpoKCAk2YMEF/+MMf1LBhQ3Xt2tXtKP6OHTtUVFSkZ599Vpdeeqk6d+6s8ePHa9euXeX+BzuA/yJPVUxN56nGjRurXr16ZX72S3L7/D8f3pq7OnbsWGbueuqpp9yeX5ncJcnjYj6/582567rrrtOHH34ol8uljRs3qnnz5hoxYoR1/lTg98hZFUfRBa/St29f9evXT88880yZV9OriJ49e8rHx0dvv/229uzZ43b1FKfTqcsvv1yLFi3SDz/84PE1+3fffVcOh8Pj53OVFRYWprvvvltr164t9QSj3377rWbOnKkOHTqUe4LV31u4cKHef/993XrrrdYRzrKEh4erffv2SklJUXp6uhXM+vXrp59//lmzZ89WcHCw9bVp6fTX7CMiIsq83Pi5atmypT7//HO3sW+//bZCX9E/Fx9++KF++ukn635RUZGWL1+uSy+91DriN3jwYO3evVuXXnppqUeUz3aEtywlP32cN29emXOuueYaSdLixYvdxrdt26avvvrKCtVS9aydv7//WY80NmzYUAMGDNDkyZNVUFCgPXv2nPP7ASXuuusu/d///Z+WLVumzz//XDfffLOuvfZa60TAXbp0kY+PjxYuXKiioiK5XC69+eabSkhIqNBPhwGcRp4qX23kqZL/6FyxYoXbZ3BxcbEWL16s5s2b609/+lOFtv9sWrZsqW+//datsPnll1+0devWKnn9M+3Zs0e7du1yG1uyZImCgoKsn24OHjxY//nPf9SkSZNSc9fvr2hYGQkJCfLx8Sk3d8XFxSkwMNAjdx04cEAfffSRR+6q6rWryLe8/P39FR8fr5kzZ0qSdu7cec7vhwsXOeu/fGt7A4AzzZw5U7GxsTp06JDb5ZgrIzg4WJ07d9aqVatUr14963wSJeLj45WUlCTJ83wSb7/9tvr166egoKBzeu/fmz17tr755hvdfvvt1m+q/f399cknn+i5555TUFCQUlJS3H7bL53+ICy5NPGJEyf0/fffa9WqVfr3v/+t+Ph4vfrqqxV6/z59+uill15SYGCgtQZRUVGKiorSunXrNHToUPn6/vefgbfffls33HBDpc5xURGJiYm6/fbb9cADD+jGG2/Uvn37NGvWLI+fJ1SVpk2b6pprrtFTTz2lhg0b6pVXXtHXX3+tZcuWWXOeeeYZpaamqnv37nrkkUfUpk0bnTx5Uj/88IPWrFmjV199tdyvwZfl6quvVmJiop599ln99NNP1pWmdu7cqQYNGujhhx9WmzZtdN999+mll15SvXr1NGDAAP3www966qmnFBkZqUcffdR6vepYu44dO2rFihWaN2+eYmNjVa9ePXXp0kX33nuv9XclPDxcOTk5mjFjhpxOp1uAB87Ff/7zHy1dulQHDhywiuTx48frgw8+0MKFCzV9+nS1bNlS69at080336zRo0erqKhIcXFxWrNmTS1vPVD3kKe8L0/NmDFD/fr1U+/evTV+/Hj5+fnplVde0e7du7V06dIqy1+JiYl67bXXdPvtt+vee+/VL7/8olmzZik4OLhKXv9MERERGjp0qKZOnarw8HAtXrxYqampmjlzpvWz1bFjxyolJUU9e/bUo48+qssuu0zFxcXKysrSunXr9Nhjj6lr166Vfu+WLVvqiSee0J///GedOHFCt956q5xOp7788ksdPnxY06ZN00UXXaSnnnpKTzzxhO644w7deuut+uWXXzRt2jQFBARoypQp1utVx9p17NhR0un/Tw4YMEA+Pj667LLL9Oyzz+rAgQPq06ePmjdvrqNHj+rFF19U/fr13b49CVQEOesMtXoqfFzQfn+VoDONGDHCSCr1KkGDBg2q0OtPmDDBSDJdunTxeGzVqlVGkvHz87OuBmOMMXl5eSYgIMAsXLjQ4zklVwl66623Sn2/sq6oUlBQYF5++WXTtWtX06hRI+Pv72/atGljJkyYYA4fPuwxPz4+3u2qQw0bNjStWrUyN910k3nrrbfcropzNqtXrzaSTL9+/dzG7733XiPJzJkzxxr77rvvjCSzYcOGCr12WetRchWa369hcXGxmTVrlmnVqpUJCAgwXbp0MR999FGZVw488zXL+rsyZcoUI8n8/PPP1pgk8+CDD5pXXnnFXHrppaZ+/fqmbdu25p///KfHPvz888/mkUceMVFRUaZ+/fomJCTExMbGmsmTJ1tXTirZn7/97W8VWhdjjCkqKjIvvPCCiY6ONn5+fsbpdJq4uDjz7rvvus2ZOXOm+dOf/mTq169vmjZtam6//Xazf/9+t9c637Ur7c/j119/NTfddJO56KKLjMPhsP7eLlq0yPTu3duEhoYaPz8/ExERYYYNG2Y+//zzCu87UEKSWblypXW/5AqgDRs2dLv5+vqaYcOGGWOMyc7ONq1btzb/+7//a3bs2GE2bdpk4uPjTZ8+fcq9GhlwISNP1a089fHHH5trrrnGNGzY0AQGBppu3bq55YOylJdHJJkpU6a4jS1atMi0a9fOBAQEmPbt25vly5eXeeXAM1+zMnms5O/S22+/bTp06GD8/PxMy5YtzezZsz22My8vzzz55JOmTZs2Vj7q2LGjefTRR92ull2S5SrjjTfeMFdccYUJCAgwjRo1MjExMR5///7xj3+Yyy67zHrv6667zrrK9u+dz9qVbP/v/zzy8/PNPffcYy6++GIrd2VmZpp///vfZsCAAeYPf/iD8fPzM82aNTMDBw40H3/8caX2HRcmclb5HMZU8JIjwAXg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kyZN1KBBA11++eVKT0+3HjfGaOrUqYqIiFBgYKB69eqlPXv2uL1Gfn6+Hn74YTVt2lQNGzbU0KFDdeDAgerYXAAAgDqDnAUAAFC2Ki+6jhw5oh49eqh+/fp6//339eWXX+r555/XRRddZM2ZNWuWZs+erblz52rbtm0KCwtTv379dOzYMWvO2LFjtXLlSi1btkxbtmxRXl6eBg8erKKioqreZAAAgDqBnAUAAFA+36p+wZkzZyoyMlILFy60xlq2bGn9b2OMkpKSNHnyZN1www2SpEWLFik0NFRLlizR6NGj5XK5tGDBAr355pvq27evJGnx4sWKjIzU+vXr1b9//6rebAAAAK9HzgIAAChflX+j65133lGXLl108803q1mzZoqJidHf//536/HMzEzl5OQoISHBGvP391d8fLy2bt0qSUpPT9epU6fc5kRERCg6Otqac6b8/Hzl5ua63QAAAOyEnAUAAFC+Ki+6vv/+e82bN0+tW7fW2rVrdf/99+uRRx7RG2+8IUnKycmRJIWGhro9LzQ01HosJydHfn5+aty4cZlzzjRjxgw5nU7rFhkZWdW7BgAAUKvIWQAAAOWr8qKruLhYnTt31vTp0xUTE6PRo0fr3nvv1bx589zmORwOt/vGGI+xM5U3Z9KkSXK5XNZt//7957cjAAAAXoacBQAAUL4qL7rCw8PVvn17t7F27dopKytLkhQWFiZJHkcMDx06ZB19DAsLU0FBgY4cOVLmnDP5+/srODjY7QYAAGAn5CwAAIDyVXnR1aNHD33zzTduY99++61atGghSYqKilJYWJhSU1OtxwsKCrRp0yZ1795dkhQbG6v69eu7zcnOztbu3butOQAAABcachYAAED5qvyqi48++qi6d++u6dOna9iwYfrss880f/58zZ8/X9Lpr9KPHTtW06dPV+vWrdW6dWtNnz5dDRo00IgRIyRJTqdTo0aN0mOPPaYmTZooJCRE48ePV8eOHa2rAwEAAFxoyFkAAADlq/Ki64orrtDKlSs1adIkPfPMM4qKilJSUpJuu+02a86ECRN04sQJPfDAAzpy5Ii6du2qdevWKSgoyJrzwgsvyNfXV8OGDdOJEyfUp08fJScny8fHp6o3GQAAoE4gZwEAAJTPYYwxtb0R1SE3N1dOp1N9w0fLt55fbW8OAABVrrC4QOuzX5PL5aq1cyaV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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "fig, axs = plt.subplots(1, 2, figsize=(12, 6), constrained_layout=True)\n", - "ctrf = axs[0].contourf(tkk_hod_no_nc_no2pthod[0]/tkk_hod_nc[0])\n", - "cbar = fig.colorbar(ctrf, ax=axs[0])\n", - "ctrf = axs[1].contourf(tkk_hod_no_nc_no2pthod[0]/tkk_hod_no_nc[0])\n", - "cbar = fig.colorbar(ctrf, ax=axs[1])\n", - "#ctrf = axs[2].contourf(tkk_hod_nc[0]/tkk_hod_no_nc[0])\n", - "#cbar = fig.colorbar(ctrf, ax=axs[2])\n", - "axs[0].set_title(\"NFW/HOD w/ number counts\")\n", - "axs[1].set_title(\"NFW/HOD w/o number counts\")\n", - "#axs[2].set_title(\"HOD w/ number counts/HOD w/o number counts\")\n", - "print(tkk_hod_no_nc_no2pthod[0]/tkk_hod_no_nc[0])\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "84f5d020", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "forecasting", - "language": "python", - "name": "forecasting" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.4" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/tests/cng_DESgc__0_DESgc__0_DESgc__0_DESgc__0.npz b/tests/cng_DESgc__0_DESgc__0_DESgc__0_DESgc__0.npz deleted file mode 100644 index 059e6aea72829b98aa71f209abf8c133ac83f172..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3228 zcmeH~`#%%2X@2Tw`_Ij%>-9 zAq!>4baFcxGMA;9U@7VKb(Ky`|$oeKA+d)^Lcz;pI<(o$K&~VA>Cx< zAOHYBVZG}C#wrxDzy4j@0BV51t5HyF1VIL%3P{@6v0fbc?^@s`vB)84J87~*HOmY% zU7e4hG|DnVerTn4W3t*Q2YlNTCXezMwFZ3isA}h^n-6g&71Wz}h>xdH3kC6@7UA5R z|5>suJ0TU?%&f5Sg$ww!%Z-0>ZBZ$(>&TG0%SnnJZ7yfp2CmekRXj?|gTXRHAI8Sn zgVW3J64MwyNn-L>8Qrdg3N%Z7QgbS7N)yWMhnGuE>}|PH4EJxel$&y^Q<7Ufoj&Bb zEbozmwfBi1AryLQ#iAEszJak?%sv6FHXK}hviY2pRjhob^M=sO{Fl%yzsRntU851x zFYBtgcG`xKyTT0nUSh+aTn~yp^1)|ip3X!6%w5CBrUYXwqk|cAk|Qwxd{7*hZuHJRZBEqaFA!|?)lc}{1E+t{-HmlO<94P^ zAKnbo0CMuLRFTm5t?ZKPu(|egdgn|m61%Iw43Q0%3%T67%(qZ^hp~7VW6)o@He+om z*Lv9O@$=+mPEY>l`XezeYo-OIJJ2NKtfStbqU%6ss#8NchC9}_Wd3maRpG7SzD@ay7;XD6WI_aBw?ZhndX$Pp>v$kgLbR)?luN|_N zUY>LS@{>0q-YVbFrvq)=BQYM;vU~Piurn|I9AkI|isKEXdkuFW>E3DEA{P7)ieScfdF#aZp$mZy^UowyNy5XDpBX0$+ znCVQYE%uAwmnctR0B0BU`RaMnCUX5F+lKQ-<=&M_q*S$f;Y*{)JJBPg;Y;#Rf$CYN z1G@E|?27w9D|w_RIkgs{=xWl{n4Le2R$^t((yPJp-S15iz{@O4PDwz!85x)3xW>)y z65ob3dBG{7(12YkZ3vXkmm0<4HT8%{9rwnNj zeG7C{WLsvJ=w}E~uT&FI{}>IjcaZ8(bQ>PR8Ga^-OoYg*`Au@fDM3+>&ct@r?%kFP z+k*CYi(P^TGu;&S(v}P&UbjWhP7lRDdR~RxZs}Q=D}QSnUuX50<}ga*$BA;cq5%*W z9Y4iU5E7JyVJ9T)_2(m1c=P0RphxMF+I&iUAaD9iI0+d9>-LTK#=!?*816TpE0??$`Cx$UC6C0*6VC-ZQAp zXz8r!ZqI656i7KaR3-f5VD&y3BG}HPWj4C6U7_=4Z{P)wV`Uyhp*^$MRVqZLpDoNW z@HsU;1MIQ-Wr?ebCGh*(-!9*}a7JS=FEnCnQ$K>_s4a6()c2PKxb;60-aI4oOG$w9 zinhbCOZLQ?+^DgA3*?2z8Nvs+n)|C5>!O1!Enpp{Ea8*b;W*_8)7!w2Gy)?+7C>(9 zCD6reRM?s!{~`0mqE&8G^}WR@BJZx<)J(|K4z?K^{Fywtn!jY~*YZ{w!5ELpIKQ^f zZeF4RjZk^N^f*!cQy#DHzz6Tr7INoGU- l&Iw4je>W-q!?b Date: Fri, 24 Jan 2025 12:24:32 -0500 Subject: [PATCH 24/28] CCL requirement to latest version --- environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/environment.yml b/environment.yml index b909c26e..7f25261d 100644 --- a/environment.yml +++ b/environment.yml @@ -14,7 +14,7 @@ dependencies: # - scipy - scipy<1.12 # <1.12 to avoid bug in CCL<3.1 (not in pypy) with simpson integration - pyyaml - - pyccl>=3.0.0 + - pyccl>=3.2 - sacc>=0.12 - namaster>2 - camb From 821cb7c38c17e51e03e76c01c8dba9774a7343d2 Mon Sep 17 00:00:00 2001 From: paulrogozenski Date: Fri, 24 Jan 2025 13:12:15 -0500 Subject: [PATCH 25/28] reformatting to unify fsky parameter into main tjpcov yaml header --- tests/data/conf_covariance_cNG_fsky.yaml | 15 +-------------- .../conf_covariance_gaussian_fsky_fourier.yaml | 2 -- .../data/conf_covariance_gaussian_fsky_real.yaml | 2 -- tests/data/conf_covariance_ssc_fsky.yaml | 4 +--- tests/test_covariance_fourier_cNG_fsky.py | 2 +- tests/test_covariance_gaussian_fsky.py | 2 +- tjpcov/__init__.py | 2 ++ tjpcov/covariance_fourier_cNG_fsky.py | 2 +- tjpcov/covariance_fourier_ssc_fsky.py | 2 +- tjpcov/covariance_gaussian_fsky.py | 2 +- 10 files changed, 9 insertions(+), 26 deletions(-) diff --git a/tests/data/conf_covariance_cNG_fsky.yaml b/tests/data/conf_covariance_cNG_fsky.yaml index 7daddc47..52f275a3 100644 --- a/tests/data/conf_covariance_cNG_fsky.yaml +++ b/tests/data/conf_covariance_cNG_fsky.yaml @@ -5,17 +5,6 @@ tjpcov: # 'set' from parameters OR pass CCL cosmology object OR yaml file cosmo: 'set' - # Setting mask OR fsky approximation - mask_file: - DESgc__0: ./tests/benchmarks/32_DES_tjpcov_bm/catalogs/mask_DESgc__0.fits.gz - DESwl__0: ./tests/benchmarks/32_DES_tjpcov_bm/catalogs/DESwlMETACAL_mask_zbin0_ns32.fits.gz - DESwl__1: ./tests/benchmarks/32_DES_tjpcov_bm/catalogs/DESwlMETACAL_mask_zbin1_ns32.fits.gz - - mask_names: - DESgc__0: mask_DESgc0 - DESwl__0: mask_DESwl0 - DESwl__1: mask_DESwl1 - outdir: ./tests/tmp/ # Survey params: @@ -32,6 +21,7 @@ tjpcov: bias_DESgc__0: 1.48 # IA: 0.5 + fsky: 0.05 parameters: # Not used for while (read by ccl.cosmo): @@ -63,6 +53,3 @@ HOD: bmax_p: 0.0 a_pivot: 1.0 ns_independent: False - -GaussianFsky: - fsky: 0.05 \ No newline at end of file diff --git a/tests/data/conf_covariance_gaussian_fsky_fourier.yaml b/tests/data/conf_covariance_gaussian_fsky_fourier.yaml index d8defc91..8ac480da 100644 --- a/tests/data/conf_covariance_gaussian_fsky_fourier.yaml +++ b/tests/data/conf_covariance_gaussian_fsky_fourier.yaml @@ -27,6 +27,4 @@ tjpcov: {% endfor %} IA: 0.5 - -GaussianFsky: fsky: 0.3 diff --git a/tests/data/conf_covariance_gaussian_fsky_real.yaml b/tests/data/conf_covariance_gaussian_fsky_real.yaml index 521bca8e..e46f2a68 100644 --- a/tests/data/conf_covariance_gaussian_fsky_real.yaml +++ b/tests/data/conf_covariance_gaussian_fsky_real.yaml @@ -26,8 +26,6 @@ tjpcov: {% endfor %} IA: 0.5 - -GaussianFsky: fsky: 0.3 ProjectedReal: diff --git a/tests/data/conf_covariance_ssc_fsky.yaml b/tests/data/conf_covariance_ssc_fsky.yaml index e49033ac..58b80bd0 100644 --- a/tests/data/conf_covariance_ssc_fsky.yaml +++ b/tests/data/conf_covariance_ssc_fsky.yaml @@ -21,6 +21,7 @@ tjpcov: bias_DESgc__0: 1.48 # IA: 0.5 + fsky: 0.05 parameters: # Not used for while (read by ccl.cosmo): @@ -32,6 +33,3 @@ parameters: w0: -1 wa: 0 transfer_function: 'boltzmann_camb' - -GaussianFsky: - fsky: 0.05 diff --git a/tests/test_covariance_fourier_cNG_fsky.py b/tests/test_covariance_fourier_cNG_fsky.py index 41adce4b..966838c7 100644 --- a/tests/test_covariance_fourier_cNG_fsky.py +++ b/tests/test_covariance_fourier_cNG_fsky.py @@ -98,7 +98,7 @@ def get_NFW_profile(): def get_fsky(tr1, tr2, tr3, tr4): config = get_config() - fsky = config["GaussianFsky"].get("fsky", None) + fsky = config["tjpcov"].get("fsky", None) return fsky diff --git a/tests/test_covariance_gaussian_fsky.py b/tests/test_covariance_gaussian_fsky.py index 315a62db..5d3c1f68 100644 --- a/tests/test_covariance_gaussian_fsky.py +++ b/tests/test_covariance_gaussian_fsky.py @@ -58,7 +58,7 @@ def test_smoke(): # Check it raises an error if fsky is not given config = get_config() - config["GaussianFsky"] = {} + config["tjpcov"].pop("fsky") with pytest.raises(ValueError): FourierGaussianFsky(config) diff --git a/tjpcov/__init__.py b/tjpcov/__init__.py index 08511eb4..e79211e8 100644 --- a/tjpcov/__init__.py +++ b/tjpcov/__init__.py @@ -19,6 +19,8 @@ def covariance_from_name(name): from .covariance_fourier_cNG import FouriercNGHaloModel as Cov elif name == "FourierSSCHaloModelFsky": from .covariance_fourier_ssc_fsky import FourierSSCHaloModelFsky as Cov + elif name == "FouriercNGHaloModelFsky": + from .covariance_fourier_cNG_fsky import FouriercNGHaloModelFsky as Cov elif name == "ClusterCountsSSC": from .covariance_cluster_counts_ssc import ClusterCountsSSC as Cov elif name == "ClusterCountsGaussian": diff --git a/tjpcov/covariance_fourier_cNG_fsky.py b/tjpcov/covariance_fourier_cNG_fsky.py index aeec8a25..bf2630ab 100644 --- a/tjpcov/covariance_fourier_cNG_fsky.py +++ b/tjpcov/covariance_fourier_cNG_fsky.py @@ -16,7 +16,7 @@ def __init__(self, config): """ super().__init__(config) - self.fsky = self.config["GaussianFsky"].get("fsky", None) + self.fsky = self.config["tjpcov"].get("fsky", None) if self.fsky is None: raise ValueError( "You need to set fsky for FouriercNGHaloModelFsky" diff --git a/tjpcov/covariance_fourier_ssc_fsky.py b/tjpcov/covariance_fourier_ssc_fsky.py index 30b74cef..c58ab6e1 100644 --- a/tjpcov/covariance_fourier_ssc_fsky.py +++ b/tjpcov/covariance_fourier_ssc_fsky.py @@ -22,7 +22,7 @@ def __init__(self, config): """ super().__init__(config) - self.fsky = self.config["GaussianFsky"].get("fsky", None) + self.fsky = self.config["tjpcov"].get("fsky", None) if self.fsky is None: raise ValueError( "You need to set fsky for FourierSSCHaloModelFsky" diff --git a/tjpcov/covariance_gaussian_fsky.py b/tjpcov/covariance_gaussian_fsky.py index 80fcc363..6adc2d4b 100644 --- a/tjpcov/covariance_gaussian_fsky.py +++ b/tjpcov/covariance_gaussian_fsky.py @@ -24,7 +24,7 @@ def __init__(self, config): """ super().__init__(config) - self.fsky = self.config["GaussianFsky"].get("fsky", None) + self.fsky = self.config["tjpcov"].get("fsky", None) if self.fsky is None: raise ValueError("You need to set fsky for FourierGaussianFsky") From 03dc53965b46c841b96371c9b585f2040f1c9c31 Mon Sep 17 00:00:00 2001 From: paulrogozenski Date: Mon, 27 Jan 2025 08:32:12 -0500 Subject: [PATCH 26/28] debugging of refactored code --- tests/test_covariance_fourier_cNG.py | 16 ++++++++++++++++ tests/test_covariance_fourier_cNG_fsky.py | 16 ++++++++++++++++ tjpcov/covariance_fourier_cNG.py | 19 ++++++++++++++++--- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/tests/test_covariance_fourier_cNG.py b/tests/test_covariance_fourier_cNG.py index ca3f11ec..92a23815 100644 --- a/tests/test_covariance_fourier_cNG.py +++ b/tests/test_covariance_fourier_cNG.py @@ -228,6 +228,20 @@ def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): ) if calculate_with_hod: + + prof_2pt_hod = ccl.halos.profiles_2pt.Profile2ptHOD() + prof_2pt_avg = ccl.halos.profiles_2pt.Profile2pt() + HOD = ccl.halos.HaloProfileHOD + if isinstance(prof1, HOD) and isinstance(prof2, HOD): + prof12_2pt = prof_2pt_hod + else: + prof12_2pt = prof_2pt_avg + + if isinstance(prof3, HOD) and isinstance(prof4, HOD): + prof34_2pt = prof_2pt_hod + else: + prof34_2pt = prof_2pt_avg + tkk_1h_nfw = ccl.halos.halomod_Tk3D_1h( cosmo, hmc, @@ -241,6 +255,8 @@ def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): prof2=prof2, prof3=prof3, prof4=prof4, + prof12_2pt=prof12_2pt, + prof34_2pt=prof34_2pt, a_arr=a_arr, ) cov_ccl_1h_nfw = ccl.covariances.angular_cl_cov_cNG( diff --git a/tests/test_covariance_fourier_cNG_fsky.py b/tests/test_covariance_fourier_cNG_fsky.py index 966838c7..6df49c46 100644 --- a/tests/test_covariance_fourier_cNG_fsky.py +++ b/tests/test_covariance_fourier_cNG_fsky.py @@ -219,6 +219,20 @@ def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): ) if calculate_with_hod: + + prof_2pt_hod = ccl.halos.profiles_2pt.Profile2ptHOD() + prof_2pt_avg = ccl.halos.profiles_2pt.Profile2pt() + HOD = ccl.halos.HaloProfileHOD + if isinstance(prof1, HOD) and isinstance(prof2, HOD): + prof12_2pt = prof_2pt_hod + else: + prof12_2pt = prof_2pt_avg + + if isinstance(prof3, HOD) and isinstance(prof4, HOD): + prof34_2pt = prof_2pt_hod + else: + prof34_2pt = prof_2pt_avg + tkk_1h_nfw = ccl.halos.halomod_Tk3D_1h( cosmo, hmc, @@ -232,6 +246,8 @@ def test_get_covariance_block(cov_fcNG, tracer_comb1, tracer_comb2): prof2=prof2, prof3=prof3, prof4=prof4, + prof12_2pt=prof12_2pt, + prof34_2pt=prof34_2pt, a_arr=a_arr, ) cov_ccl_1h_nfw = ccl.covariances.angular_cl_cov_cNG( diff --git a/tjpcov/covariance_fourier_cNG.py b/tjpcov/covariance_fourier_cNG.py index 0295e7d9..824ecd22 100644 --- a/tjpcov/covariance_fourier_cNG.py +++ b/tjpcov/covariance_fourier_cNG.py @@ -120,7 +120,6 @@ def get_covariance_block( hmf = ccl.halos.MassFuncTinker08(mass_def=mass_def) hbf = ccl.halos.HaloBiasTinker10(mass_def=mass_def) cM = ccl.halos.ConcentrationDuffy08(mass_def=mass_def) - prof_2pt = ccl.halos.profiles_2pt.Profile2ptHOD() nfw = ccl.halos.HaloProfileNFW( mass_def=mass_def, concentration=cM, fourier_analytic=True ) @@ -221,6 +220,20 @@ def get_covariance_block( prof2 = hod if isnc[2] else nfw prof3 = hod if isnc[3] else nfw prof4 = hod if isnc[4] else nfw + + prof_2pt_hod = ccl.halos.profiles_2pt.Profile2ptHOD() + prof_2pt_avg = ccl.halos.profiles_2pt.Profile2pt() + HOD = ccl.halos.HaloProfileHOD + if isinstance(prof1, HOD) and isinstance(prof2, HOD): + prof12_2pt = prof_2pt_hod + else: + prof12_2pt = prof_2pt_avg + + if isinstance(prof3, HOD) and isinstance(prof4, HOD): + prof34_2pt = prof_2pt_hod + else: + prof34_2pt = prof_2pt_avg + tkk += ccl.halos.halomod_trispectrum_1h( cosmo, hmc, @@ -230,8 +243,8 @@ def get_covariance_block( prof2=prof2, prof3=prof3, prof4=prof4, - prof12_2pt=prof_2pt, - prof34_2pt=prof_2pt, + prof12_2pt=prof12_2pt, + prof34_2pt=prof34_2pt, ) tk3D = ccl.tk3d.Tk3D( From fee0e9d9b50e30e319dc6531126b3a336d1f9641 Mon Sep 17 00:00:00 2001 From: carlosggarcia Date: Tue, 28 Jan 2025 10:49:38 +0000 Subject: [PATCH 27/28] cNG: skip slow tests in CI --- tests/test_covariance_fourier_cNG.py | 2 ++ tests/test_covariance_fourier_cNG_fsky.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tests/test_covariance_fourier_cNG.py b/tests/test_covariance_fourier_cNG.py index 92a23815..81d9228c 100644 --- a/tests/test_covariance_fourier_cNG.py +++ b/tests/test_covariance_fourier_cNG.py @@ -16,6 +16,7 @@ OUTDIR = "./tests/tmp/" NSIDE = 32 +IN_GITHUB_ACTIONS = os.getenv("GITHUB_ACTIONS") == "true" def setup_module(): os.makedirs(OUTDIR, exist_ok=True) @@ -115,6 +116,7 @@ def test_smoke(): FouriercNGHaloModel(INPUT_YML_cNG) +@pytest.mark.skipif(IN_GITHUB_ACTIONS, reason="Test too slow for Github Actions.") @pytest.mark.parametrize( "tracer_comb1,tracer_comb2", [ diff --git a/tests/test_covariance_fourier_cNG_fsky.py b/tests/test_covariance_fourier_cNG_fsky.py index 6df49c46..e00bdde8 100644 --- a/tests/test_covariance_fourier_cNG_fsky.py +++ b/tests/test_covariance_fourier_cNG_fsky.py @@ -15,6 +15,7 @@ OUTDIR = "./tests/tmp/" NSIDE = 32 +IN_GITHUB_ACTIONS = os.getenv("GITHUB_ACTIONS") == "true" def setup_module(): os.makedirs(OUTDIR, exist_ok=True) @@ -106,6 +107,7 @@ def test_smoke(): FouriercNGHaloModelFsky(INPUT_YML_cNG) +@pytest.mark.skipif(IN_GITHUB_ACTIONS, reason="Test too slow for Github Actions.") @pytest.mark.parametrize( "tracer_comb1,tracer_comb2", [ From 9dc12a28536bd36e217ec0b5af19661f54120c17 Mon Sep 17 00:00:00 2001 From: carlosggarcia Date: Tue, 28 Jan 2025 10:53:49 +0000 Subject: [PATCH 28/28] blacked --- tests/test_covariance_fourier_cNG.py | 5 ++++- tests/test_covariance_fourier_cNG_fsky.py | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/test_covariance_fourier_cNG.py b/tests/test_covariance_fourier_cNG.py index 81d9228c..7171afb7 100644 --- a/tests/test_covariance_fourier_cNG.py +++ b/tests/test_covariance_fourier_cNG.py @@ -18,6 +18,7 @@ IN_GITHUB_ACTIONS = os.getenv("GITHUB_ACTIONS") == "true" + def setup_module(): os.makedirs(OUTDIR, exist_ok=True) @@ -116,7 +117,9 @@ def test_smoke(): FouriercNGHaloModel(INPUT_YML_cNG) -@pytest.mark.skipif(IN_GITHUB_ACTIONS, reason="Test too slow for Github Actions.") +@pytest.mark.skipif( + IN_GITHUB_ACTIONS, reason="Test too slow for Github Actions." +) @pytest.mark.parametrize( "tracer_comb1,tracer_comb2", [ diff --git a/tests/test_covariance_fourier_cNG_fsky.py b/tests/test_covariance_fourier_cNG_fsky.py index e00bdde8..a02b7797 100644 --- a/tests/test_covariance_fourier_cNG_fsky.py +++ b/tests/test_covariance_fourier_cNG_fsky.py @@ -17,6 +17,7 @@ IN_GITHUB_ACTIONS = os.getenv("GITHUB_ACTIONS") == "true" + def setup_module(): os.makedirs(OUTDIR, exist_ok=True) @@ -107,7 +108,9 @@ def test_smoke(): FouriercNGHaloModelFsky(INPUT_YML_cNG) -@pytest.mark.skipif(IN_GITHUB_ACTIONS, reason="Test too slow for Github Actions.") +@pytest.mark.skipif( + IN_GITHUB_ACTIONS, reason="Test too slow for Github Actions." +) @pytest.mark.parametrize( "tracer_comb1,tracer_comb2", [