diff --git a/bin/environment-local.yml b/bin/environment-local.yml index a20c5cf98..19f902936 100644 --- a/bin/environment-local.yml +++ b/bin/environment-local.yml @@ -7,7 +7,7 @@ dependencies: - cosmosis=3.24.* - dask=2024.5.* - dm-tree=0.1.* - - firecrown=1.7.* + - firecrown=1.14.* - fitsio=1.3.* - h5py=3.15.*=mpi_mpich_* - healpy=1.18.* diff --git a/bin/perlmutter-install.sh b/bin/perlmutter-install.sh index c65e8e621..1eaf1e67b 100755 --- a/bin/perlmutter-install.sh +++ b/bin/perlmutter-install.sh @@ -12,7 +12,9 @@ mamba activate ./conda # we manually install firecrown as we have to remove numcosmo to avoid clashes FIRECROWN_DIR=firecrown-tmp-${RANDOM} -git clone --branch v1.7.5 https://github.com/LSSTDESC/firecrown ${FIRECROWN_DIR} + +# TODO: check if this is still needed. +git clone --branch v1.14.0 https://github.com/LSSTDESC/firecrown ${FIRECROWN_DIR} cd ${FIRECROWN_DIR} sed -i '/numcosmo/d' setup.cfg pip install . diff --git a/txpipe/test/test_firecrown.py b/txpipe/test/test_firecrown.py new file mode 100644 index 000000000..36ac46dc8 --- /dev/null +++ b/txpipe/test/test_firecrown.py @@ -0,0 +1,31 @@ +from ..utils.theory import theory_3x2pt, fill_empty_sacc +import pyccl +import sacc +import numpy as np + + +def make_sacc(): + sacc_data = sacc.Sacc() + nbin_source = 2 + nbin_lens = 3 + z = np.linspace(0.0, 2.0, 200) + mu_source = [0.6, 1.0] + mu_lens = [0.2, 0.3, 0.4] + sigma = 0.1 + for i in range(nbin_source): + Nz = np.exp(-0.5 * ((z - mu_source[i]) / sigma) ** 2) + sacc_data.add_tracer("NZ", f"source_{i}", z, Nz) + for i in range(nbin_lens): + Nz = np.exp(-0.5 * ((z - mu_lens[i]) / sigma) ** 2) + sacc_data.add_tracer("NZ", f"lens_{i}", z, Nz) + return sacc_data + + + +def test_firecrown_theory(): + sacc_data = make_sacc() + ell_values = np.geomspace(10, 2000, 20) + fill_empty_sacc(sacc_data, ell_values=ell_values) + cosmo = pyccl.CosmologyVanillaLCDM() + theory_sacc = theory_3x2pt(cosmo, sacc_data) + print(theory_sacc.get_mean()) \ No newline at end of file diff --git a/txpipe/utils/theory.py b/txpipe/utils/theory.py index 0856d4185..be39598d7 100755 --- a/txpipe/utils/theory.py +++ b/txpipe/utils/theory.py @@ -2,7 +2,6 @@ import numpy as np import warnings import yaml -import pathlib # same convention as elsewhere SHEAR_SHEAR = 0 @@ -12,6 +11,27 @@ default_theory_model = str(pathlib.Path(__file__).parents[0] / "theory_model.py") +def _make_firecrown_build_parameters(sacc_data): + """Create Firecrown build parameters compatible with multiple versions. + + Firecrown >=1.14 expects a NamedParameters instance, while some legacy + likelihood scripts still access build parameters with dict-style syntax. + """ + try: + from firecrown.likelihood.likelihood import NamedParameters + except ImportError: + return {"sacc_data": sacc_data} + + class TxBuildParameters(NamedParameters): + def __getitem__(self, key): + return self.data[key] + + def get(self, key, default=None): + return self.data.get(key, default) + + return TxBuildParameters({"sacc_data": sacc_data}) + + def ccl_read_yaml(filename, **kwargs): import pyccl as ccl @@ -175,18 +195,18 @@ def theory_3x2pt( # Use the FireCrown machinery to compute the likelihood and as # a by-product the theory - build_parameters = { - "sacc_data": sacc_data, - } + build_parameters = _make_firecrown_build_parameters(sacc_data) # These stages are a copy of what is done inside the FireCrown connectors likelihood, tools = load_likelihood_from_script(theory_model, build_parameters) - systematic_params = {**make_bias_parameters(bias, sacc_data, cosmo)} + cosmo_params = {k: v for (k, v) in cosmo.to_dict().items() if isinstance(v, (int, float))} + params_values = {**make_bias_parameters(bias, sacc_data, cosmo), **cosmo_params} # Apply the systematics parameters - likelihood.update(ParamsMap(systematic_params)) - tools.update(ParamsMap(systematic_params)) - tools.prepare(cosmo) + params = ParamsMap(params_values) + likelihood.update(params) + tools.update(params) + tools.prepare() # Ask the likelihood for a theory vector. We don't want # to print the actual likelihood because for many applications diff --git a/txpipe/utils/theory_model.py b/txpipe/utils/theory_model.py index c76064bc5..e7a28b1ba 100644 --- a/txpipe/utils/theory_model.py +++ b/txpipe/utils/theory_model.py @@ -1,23 +1,46 @@ -import os import pathlib -import firecrown.likelihood.gauss_family.statistic.source.weak_lensing as wl -import firecrown.likelihood.gauss_family.statistic.source.number_counts as nc -from firecrown.likelihood.gauss_family.statistic.two_point import TwoPoint -from firecrown.likelihood.gauss_family.gaussian import ConstGaussian +try: + from firecrown.likelihood.weak_lensing import WeakLensing + from firecrown.likelihood.number_counts import LinearBiasSystematic, NumberCounts + from firecrown.likelihood.two_point import TwoPoint + from firecrown.likelihood.gaussian import ConstGaussian +except ImportError: + import firecrown.likelihood.gauss_family.statistic.source.weak_lensing as wl + import firecrown.likelihood.gauss_family.statistic.source.number_counts as nc + from firecrown.likelihood.gauss_family.statistic.two_point import TwoPoint + from firecrown.likelihood.gauss_family.gaussian import ConstGaussian + + WeakLensing = wl.WeakLensing + LinearBiasSystematic = nc.LinearBiasSystematic + NumberCounts = nc.NumberCounts + from firecrown.modeling_tools import ModelingTools import sacc -import pyccl as ccl import numpy as np +def _get_build_parameter(build_parameters, key): + """Read build parameters from either a dict-like object or NamedParameters.""" + try: + return build_parameters[key] + except (KeyError, TypeError): + pass + + data = getattr(build_parameters, "data", None) + if data is not None and key in data: + return data[key] + + raise KeyError(key) + + def build_likelihood(build_parameters): """ This is a generic 3x2pt theory model, but with only bias as a systematic. """ - sacc_data = build_parameters["sacc_data"] + sacc_data = _get_build_parameter(build_parameters, "sacc_data") # items in the build_parameters are supposed to be # just str, int, etc, not complicated parameters. @@ -41,10 +64,10 @@ def build_likelihood(build_parameters): for tracer_name in sacc_data.tracers.keys(): if tracer_name.startswith("source"): - tr = wl.WeakLensing(sacc_tracer=tracer_name) + tr = WeakLensing(sacc_tracer=tracer_name) elif tracer_name.startswith("lens"): - bias_systematic = nc.LinearBiasSystematic(sacc_tracer=tracer_name) - tr = nc.NumberCounts(sacc_tracer=tracer_name, systematics=[bias_systematic]) + bias_systematic = LinearBiasSystematic(sacc_tracer=tracer_name) + tr = NumberCounts(sacc_tracer=tracer_name, systematics=[bias_systematic]) else: raise ValueError(f"Unknown tracer in sacc file, non-3x2pt: {tracer_name}") sources[tracer_name] = tr