Source code for dsf.modelling.cosmology

"""Cosmology construction utilities."""

from __future__ import annotations

from collections.abc import Mapping
from typing import Any

import pyccl as ccl

__all__ = ["make_ccl_cosmology"]


[docs] def make_ccl_cosmology( cosmology: Mapping[str, Any] | None = None, **kwargs: Any, ) -> ccl.Cosmology: """Construct a CCL cosmology, supporting Omega_m and S8 parameterizations. Args: cosmology: Optional mapping of fiducial cosmological parameters. **kwargs: Cosmological parameters overriding the fiducial values. Returns: CCL cosmology object. Raises: ValueError: If incompatible parameterizations are supplied. KeyError: If parameters required for conversion are missing. Notes: Omega_m is interpreted as Omega_c + Omega_b, assuming massless neutrinos. Keyword overrides may replace the fiducial density or amplitude parameterization. """ density_names = {"Omega_m", "Omega_c"} amplitude_names = {"S8", "sigma8", "A_s"} if cosmology is None and not (density_names | amplitude_names).intersection(kwargs): return ccl.CosmologyVanillaLCDM(**kwargs) values = dict(cosmology or {}) if len(density_names.intersection(kwargs)) > 1: raise ValueError("Omega_m and Omega_c cannot be supplied together.") if len(amplitude_names.intersection(kwargs)) > 1: raise ValueError("S8, sigma8, and A_s cannot be supplied together.") if "Omega_m" in kwargs: values.pop("Omega_c", None) elif "Omega_c" in kwargs: values.pop("Omega_m", None) if "S8" in kwargs: values.pop("sigma8", None) values.pop("A_s", None) elif "sigma8" in kwargs: values.pop("S8", None) values.pop("A_s", None) elif "A_s" in kwargs: values.pop("S8", None) values.pop("sigma8", None) values.update(kwargs) if "Omega_m" in values and "Omega_c" in values: raise ValueError("Omega_m and Omega_c cannot be supplied together.") amplitudes = amplitude_names.intersection(values) if len(amplitudes) > 1: raise ValueError("S8, sigma8, and A_s cannot be supplied together.") if "S8" in values: omega_m = values.get("Omega_m") if omega_m is None: omega_m = values["Omega_c"] + values["Omega_b"] if omega_m <= 0: raise ValueError("Omega_m must be positive for S8 conversion.") values["sigma8"] = values.pop("S8") * (0.3 / omega_m) ** 0.5 if "Omega_m" in values: values["Omega_c"] = values.pop("Omega_m") - values["Omega_b"] return ccl.Cosmology(**values)