diff --git a/README.md b/README.md index 59f2a0de8..4edf08358 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,20 @@ See [Getting CMake](https://ccl.readthedocs.io/en/latest/source/installation.htm and [Installing SWIG](https://pypi.org/project/swig/) for instructions. Note that the code only supports Linux or Mac OS, but no Windows. +### Optional dependencies + +For extended functionality, install one of the optional extra groups: + +```bash +pip install pyccl[boltzmann] # Boltzmann codes: CAMB, CLASS (classy), ISiTGR +pip install pyccl[pt] # Perturbation theory: FAST-PT, velocileptors +pip install pyccl[emulators] # Emulators: BaccoEmu, MiraTitan, Dark Emulator +pip install pyccl[full] # All of the above +``` + +Without `pyccl[boltzmann]`, the default `transfer_function` is `'eisenstein_hu'`. +With `pyccl[boltzmann]` (or a full `conda` install), it defaults to `'boltzmann_camb'`. + Once you have the code installed, you can take it for a spin! ```python diff --git a/pyccl/boltzmann.py b/pyccl/boltzmann.py index 923f79cb8..e95a05d47 100644 --- a/pyccl/boltzmann.py +++ b/pyccl/boltzmann.py @@ -25,8 +25,16 @@ def get_camb_pk_lin(cosmo, *, nonlin=False): spectrum. If ``nonlin=True``, returns a tuple \ ``(pk_lin, pk_nonlin)``. """ - import camb - import camb.model + try: + import camb + import camb.model + except ImportError as e: + raise CCLError( + "CAMB is required to use the 'boltzmann_camb' transfer function " + "but could not be imported. Install it with:\n" + " pip install pyccl[boltzmann]\n" + "or: pip install camb" + ) from e # Get extra CAMB parameters that were specified extra_camb_params = {} @@ -222,8 +230,15 @@ def get_isitgr_pk_lin(cosmo): :class:`~pyccl.pk2d.Pk2D`: Power spectrum \ object. The linear power spectrum. """ - import isitgr # noqa: F811 - import isitgr.model + try: + import isitgr # noqa: F811 + import isitgr.model + except ImportError as e: + raise CCLError( + "ISiTGR is required to use the 'boltzmann_isitgr' transfer " + "function but could not be imported. Install it with: " + "pip install pyccl[boltzmann] or pip install isitgr" + ) from e # Get extra CAMB parameters that were specified extra_camb_params = {} @@ -396,7 +411,15 @@ def get_class_pk_lin(cosmo): :class:`~pyccl.pk2d.Pk2D`: Power spectrum object.\ The linear power spectrum. """ - import classy + try: + import classy + except ImportError as e: + raise CCLError( + "CLASS (classy) is required to use the 'boltzmann_class' transfer " + "function but could not be imported. Install it with:\n" + " pip install pyccl[boltzmann]\n" + "or: pip install classy" + ) from e params = { "output": "mPk", diff --git a/pyccl/cosmology.py b/pyccl/cosmology.py index 8ba4e2ef2..a31acf53e 100644 --- a/pyccl/cosmology.py +++ b/pyccl/cosmology.py @@ -77,6 +77,16 @@ class MatterPowerSpectra(Enum): 'emulator': lib.emulator_nlpk } +def _camb_available(): + try: + import camb # noqa: F401 + return True + except ImportError: + return False + + +_DEFAULT_TRANSFER_FUNCTION = 'boltzmann_camb' if _camb_available() else 'eisenstein_hu' + _TOP_LEVEL_MODULES = ("",) @@ -238,7 +248,7 @@ def __init__( Neff=None, m_nu=0., mass_split='normal', w0=-1., wa=0., T_CMB=DefaultParams.T_CMB, T_ncdm=DefaultParams.T_ncdm, - transfer_function='boltzmann_camb', + transfer_function=_DEFAULT_TRANSFER_FUNCTION, matter_power_spectrum='halofit', baryonic_effects=None, mg_parametrization=None, diff --git a/pyccl/tests/test_power_mu_sigma_sigma8norm.py b/pyccl/tests/test_power_mu_sigma_sigma8norm.py index 55fb1732d..3f078f8e7 100644 --- a/pyccl/tests/test_power_mu_sigma_sigma8norm.py +++ b/pyccl/tests/test_power_mu_sigma_sigma8norm.py @@ -39,9 +39,9 @@ def test_power_mu_sigma_sigma8norm(tf): assert np.allclose(pk_rat, gfac) with mock.patch.dict(sys.modules, {'isitgr': None}): - with pytest.raises(ModuleNotFoundError): + with pytest.raises(ccl.CCLError): get_isitgr_pk_lin(cosmo) - # Importing ccl without isitgr is fine. No ModuleNotFoundError triggered. + # Importing ccl without isitgr is fine. No error triggered. with mock.patch.dict(sys.modules, {'isitgr': None}): reload(ccl.boltzmann) diff --git a/pyproject.toml b/pyproject.toml index f78dfb4ae..f0dad2744 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,6 +42,11 @@ dev = [ "pytest-cov", ] +boltzmann = ["camb", "classy", "isitgr"] +pt = ["velocileptors", "fast-pt"] +emulators = ["baccoemu", "MiraTitanHMFemulator", "dark_emulator"] +full = ["camb", "classy", "isitgr", "velocileptors", "fast-pt", "baccoemu", "MiraTitanHMFemulator", "dark_emulator"] + [tool.setuptools.packages.find] include = ["pyccl*"] diff --git a/readthedocs/source/installation.rst b/readthedocs/source/installation.rst index b2125bd2e..33b58ad1f 100644 --- a/readthedocs/source/installation.rst +++ b/readthedocs/source/installation.rst @@ -43,6 +43,23 @@ Once you have ``CMake``, simply run: $ pip install pyccl +Installing with optional extras +-------------------------------- + +CCL supports four optional dependency groups installable as pip extras: + +.. code-block:: bash + + $ pip install pyccl[boltzmann] # CAMB, CLASS (classy), ISiTGR + $ pip install pyccl[pt] # FAST-PT and velocileptors + $ pip install pyccl[emulators] # BaccoEmu, MiraTitan HMF, Dark Emulator + $ pip install pyccl[full] # All of the above + +Without ``pyccl[boltzmann]``, the default ``transfer_function`` is +``'eisenstein_hu'``. With it (or a ``conda`` install), the default is +``'boltzmann_camb'``. + + Google Colab ============ @@ -61,6 +78,8 @@ To install ``pyccl`` on https://colab.research.google.com then one way is the fo Getting a Boltzmann Code ======================== +These packages are included in ``pip install pyccl[boltzmann]``. + In order to use CCL with a Boltzmann code, you will need the ``Python`` wrappers for either ``CLASS`` or ``CAMB``. @@ -112,6 +131,8 @@ should already be in your environment. Getting PT packages =================== +These packages are included in ``pip install pyccl[pt]``. + Getting FAST-PT --------------- @@ -142,6 +163,8 @@ See full instructions in the ``velocileptors`` Getting emulators ================= +These packages are included in ``pip install pyccl[emulators]``. + The following emulators with external dependencies are currently supported in CCL.