emantis 1.2.2__tar.gz → 1.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. {emantis-1.2.2 → emantis-1.3.0}/PKG-INFO +14 -42
  2. {emantis-1.2.2 → emantis-1.3.0}/README.rst +6 -35
  3. {emantis-1.2.2 → emantis-1.3.0}/pyproject.toml +36 -32
  4. emantis-1.3.0/src/emantis/__init__.py +37 -0
  5. emantis-1.3.0/src/emantis/_base.py +355 -0
  6. emantis-1.3.0/src/emantis/_cli.py +183 -0
  7. emantis-1.3.0/src/emantis/_gp_emulation.py +2532 -0
  8. emantis-1.3.0/src/emantis/_io.py +637 -0
  9. emantis-1.3.0/src/emantis/_read_data.py +392 -0
  10. emantis-1.3.0/src/emantis/_shipped.py +123 -0
  11. emantis-1.3.0/src/emantis/_transformers.py +234 -0
  12. emantis-1.3.0/src/emantis/_types.py +153 -0
  13. emantis-1.3.0/src/emantis/_utils.py +379 -0
  14. emantis-1.3.0/src/emantis/_utils_inputs.py +229 -0
  15. emantis-1.3.0/src/emantis/custom_emulators.py +85 -0
  16. emantis-1.3.0/src/emantis/data/fitted_emulators/halo_mass_function_fR_1000c_res_corr_False.h5 +0 -0
  17. emantis-1.3.0/src/emantis/data/fitted_emulators/halo_mass_function_fR_1000c_res_corr_True.h5 +0 -0
  18. emantis-1.3.0/src/emantis/data/fitted_emulators/halo_mass_function_fR_200c_res_corr_False.h5 +0 -0
  19. emantis-1.3.0/src/emantis/data/fitted_emulators/halo_mass_function_fR_200c_res_corr_True.h5 +0 -0
  20. emantis-1.3.0/src/emantis/data/fitted_emulators/halo_mass_function_fR_500c_res_corr_False.h5 +0 -0
  21. emantis-1.3.0/src/emantis/data/fitted_emulators/halo_mass_function_fR_500c_res_corr_True.h5 +0 -0
  22. emantis-1.3.0/src/emantis/data/fitted_emulators/halo_mass_function_fR_b0.2_res_corr_False.h5 +0 -0
  23. emantis-1.3.0/src/emantis/data/fitted_emulators/halo_mass_function_fR_b0.2_res_corr_True.h5 +0 -0
  24. emantis-1.3.0/src/emantis/data/fitted_emulators/halo_mass_function_wCDM_1000c_res_corr_False.h5 +0 -0
  25. emantis-1.3.0/src/emantis/data/fitted_emulators/halo_mass_function_wCDM_1000c_res_corr_True.h5 +0 -0
  26. emantis-1.3.0/src/emantis/data/fitted_emulators/halo_mass_function_wCDM_200c_res_corr_False.h5 +0 -0
  27. emantis-1.3.0/src/emantis/data/fitted_emulators/halo_mass_function_wCDM_200c_res_corr_True.h5 +0 -0
  28. emantis-1.3.0/src/emantis/data/fitted_emulators/halo_mass_function_wCDM_500c_res_corr_False.h5 +0 -0
  29. emantis-1.3.0/src/emantis/data/fitted_emulators/halo_mass_function_wCDM_500c_res_corr_True.h5 +0 -0
  30. emantis-1.3.0/src/emantis/data/fitted_emulators/halo_mass_function_wCDM_b0.2_res_corr_False.h5 +0 -0
  31. emantis-1.3.0/src/emantis/data/fitted_emulators/halo_mass_function_wCDM_b0.2_res_corr_True.h5 +0 -0
  32. emantis-1.3.0/src/emantis/data/fitted_emulators/matter_power_spectrum_nl_boost_wCDM.h5 +0 -0
  33. emantis-1.3.0/src/emantis/data/fitted_emulators/matter_power_spectrum_nl_mg_boost_fR_v1.h5 +0 -0
  34. emantis-1.3.0/src/emantis/data/fitted_emulators/matter_power_spectrum_nl_mg_boost_fR_v2.h5 +0 -0
  35. emantis-1.3.0/src/emantis/data/fitted_emulators/sigma8_LCDM.h5 +0 -0
  36. emantis-1.3.0/src/emantis/data/fitted_emulators/sigma8_wCDM.h5 +0 -0
  37. emantis-1.3.0/src/emantis/data/halo_mass_function/halo_mass_function_fR_emu_v2_emulation_config.toml +20 -0
  38. emantis-1.3.0/src/emantis/data/halo_mass_function/halo_mass_function_wCDM_emu_v2_emulation_config.toml +20 -0
  39. emantis-1.3.0/src/emantis/data/matter_power_spectrum_nl_boost/matter_power_spectrum_nl_boost_wCDM_emu_v2_emulation_config.toml +23 -0
  40. emantis-1.3.0/src/emantis/data/matter_power_spectrum_nl_mg_boost/matter_power_spectrum_nl_mg_boost_fR_emu_v1_emulation_config.toml +21 -0
  41. emantis-1.3.0/src/emantis/data/matter_power_spectrum_nl_mg_boost/matter_power_spectrum_nl_mg_boost_fR_emu_v2_emulation_config.toml +21 -0
  42. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/data/sigma8/cosmo_params_LCDM.txt +1 -1
  43. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/data/sigma8/cosmo_params_LCDM_config.toml +1 -1
  44. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/data/sigma8/cosmo_params_wCDM.txt +1 -1
  45. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/data/sigma8/cosmo_params_wCDM_config.toml +1 -1
  46. emantis-1.3.0/src/emantis/data/sigma8/sigma8_LCDM_emulation_config.toml +14 -0
  47. emantis-1.3.0/src/emantis/data/sigma8/sigma8_wCDM_emulation_config.toml +14 -0
  48. emantis-1.3.0/src/emantis/exceptions.py +98 -0
  49. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/halo_mass_function.py +67 -108
  50. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/matter_power_spectrum.py +150 -160
  51. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/powerspectrum_matter.py +3 -23
  52. emantis-1.3.0/tests/conftest.py +162 -0
  53. emantis-1.3.0/tests/test_cli.py +131 -0
  54. emantis-1.3.0/tests/test_cross_validation.py +84 -0
  55. emantis-1.3.0/tests/test_error_propagation.py +416 -0
  56. emantis-1.3.0/tests/test_gp_emulation.py +230 -0
  57. emantis-1.3.0/tests/test_inputs.py +187 -0
  58. emantis-1.3.0/tests/test_pca_transformer.py +87 -0
  59. emantis-1.3.0/tests/test_save_load.py +161 -0
  60. emantis-1.3.0/tests/test_shipped_emulators.py +311 -0
  61. emantis-1.2.2/src/emantis/__init__.py +0 -34
  62. emantis-1.2.2/src/emantis/_cli.py +0 -80
  63. emantis-1.2.2/src/emantis/_gp_emulation.py +0 -2305
  64. emantis-1.2.2/src/emantis/_read_data.py +0 -191
  65. emantis-1.2.2/src/emantis/_transformers.py +0 -266
  66. emantis-1.2.2/src/emantis/_types.py +0 -107
  67. emantis-1.2.2/src/emantis/_utils.py +0 -145
  68. emantis-1.2.2/src/emantis/_utils_inputs.py +0 -160
  69. emantis-1.2.2/src/emantis/data/halo_mass_function/halo_mass_function_fR_emu_v2_emulation_config.toml +0 -24
  70. emantis-1.2.2/src/emantis/data/halo_mass_function/halo_mass_function_wCDM_emu_v2_emulation_config.toml +0 -24
  71. emantis-1.2.2/src/emantis/data/matter_power_spectrum_nl_boost/matter_power_spectrum_nl_boost_wCDM_emu_v2_emulation_config.toml +0 -30
  72. emantis-1.2.2/src/emantis/data/matter_power_spectrum_nl_mg_boost/matter_power_spectrum_nl_mg_boost_fR_emu_v1_emulation_config.toml +0 -28
  73. emantis-1.2.2/src/emantis/data/matter_power_spectrum_nl_mg_boost/matter_power_spectrum_nl_mg_boost_fR_emu_v2_emulation_config.toml +0 -28
  74. emantis-1.2.2/src/emantis/data/sigma8/sigma8_LCDM_emulation_config.toml +0 -13
  75. emantis-1.2.2/src/emantis/data/sigma8/sigma8_wCDM_emulation_config.toml +0 -13
  76. emantis-1.2.2/src/emantis/exceptions.py +0 -36
  77. emantis-1.2.2/tests/test_halo_mass_function.py +0 -235
  78. emantis-1.2.2/tests/test_matter_power_spectrum.py +0 -416
  79. {emantis-1.2.2 → emantis-1.3.0}/COPYING +0 -0
  80. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/data/cosmo_params_fR_emu_v1.txt +0 -0
  81. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/data/cosmo_params_fR_emu_v1_config.toml +0 -0
  82. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/data/cosmo_params_fR_emu_v2.txt +0 -0
  83. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/data/cosmo_params_fR_emu_v2_config.toml +0 -0
  84. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/data/cosmo_params_wCDM_emu_v2.txt +0 -0
  85. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/data/cosmo_params_wCDM_emu_v2_config.toml +0 -0
  86. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/data/fofr_matter_power_boost/cosmo_params.txt +0 -0
  87. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/data/fofr_matter_power_boost/kbins.h5 +0 -0
  88. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/data/fofr_matter_power_boost/power_boosts_train.h5 +0 -0
  89. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/data/halo_mass_function/halo_mass_function_fR_emu_v2_data.h5 +0 -0
  90. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/data/halo_mass_function/halo_mass_function_wCDM_emu_v2_data.h5 +0 -0
  91. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/data/matter_power_spectrum_nl_boost/matter_power_spectrum_nl_boost_wCDM_emu_v2_data.h5 +0 -0
  92. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/data/matter_power_spectrum_nl_mg_boost/matter_power_spectrum_nl_mg_boost_fR_emu_v1_data.h5 +0 -0
  93. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/data/matter_power_spectrum_nl_mg_boost/matter_power_spectrum_nl_mg_boost_fR_emu_v2_data.h5 +0 -0
  94. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/data/sigma8/sigma8_LCDM_data.txt +0 -0
  95. {emantis-1.2.2 → emantis-1.3.0}/src/emantis/data/sigma8/sigma8_wCDM_data.txt +0 -0
@@ -1,27 +1,28 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: emantis
3
- Version: 1.2.2
3
+ Version: 1.3.0
4
4
  Summary: A cosmological emulator for nonlinear large-scale structure formation studies in alternative dark energy and gravity theories.
5
5
  Keywords: cosmology,emulator,large-scale structure,dark energy,modified gravity
6
- Author-Email: =?utf-8?q?I=C3=B1igo_S=C3=A1ez_Casares?= <inigo.saez-casares@obspm.fr>
7
- License: GPL-3.0-or-later
6
+ Author-Email: Iñigo Sáez-Casares <inigo.saez-casares@obspm.fr>
7
+ License-Expression: GPL-3.0-or-later
8
8
  Classifier: Programming Language :: Python :: 3
9
- Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
10
9
  Classifier: Operating System :: OS Independent
11
10
  Classifier: Intended Audience :: Science/Research
12
11
  Classifier: Topic :: Scientific/Engineering :: Physics
13
12
  Project-URL: repository, https://gitlab.obspm.fr/e-mantis/e-mantis.git
14
13
  Project-URL: documentation, https://e-mantis.pages.obspm.fr/e-mantis/index.html
15
- Requires-Python: <3.15,>=3.10
14
+ Requires-Python: >=3.10
16
15
  Requires-Dist: h5py<4.0,>=3.8
17
- Requires-Dist: scikit-learn<2,>=1
16
+ Requires-Dist: scikit-learn<2,>=1.5
18
17
  Requires-Dist: numpy<3.0,>=1.24
19
18
  Requires-Dist: pydantic<3.0,>=2.6
20
19
  Requires-Dist: tomli<3,>=2; python_version < "3.11"
21
20
  Requires-Dist: joblib<2.0.0,>=1.3.2
21
+ Requires-Dist: scipy<2,>=1.15
22
+ Requires-Dist: threadpoolctl<4,>=3
22
23
  Description-Content-Type: text/x-rst
23
24
 
24
- |DOI|_ |PyPI|_ |release|_ |pipeline|_
25
+ |DOI|_ |PyPI|_ |release|_ |pipeline|_ |coverage|_
25
26
 
26
27
  .. |DOI| image:: https://zenodo.org/badge/DOI/10.5281/zenodo.7738362.svg
27
28
  .. _DOI: https://doi.org/10.5281/zenodo.7738362
@@ -35,6 +36,9 @@ Description-Content-Type: text/x-rst
35
36
  .. |pipeline| image:: https://gitlab.obspm.fr/e-mantis/e-mantis/badges/main/pipeline.svg
36
37
  .. _pipeline: https://gitlab.obspm.fr/e-mantis/e-mantis/-/commits/main
37
38
 
39
+ .. |coverage| image:: https://gitlab.obspm.fr/e-mantis/e-mantis/badges/main/coverage.svg
40
+ .. _coverage: https://gitlab.obspm.fr/e-mantis/e-mantis/-/commits/main
41
+
38
42
  e-MANTIS: Emulator for Multiple observable ANalysis in extended cosmological TheorIeS
39
43
  =====================================================================================
40
44
 
@@ -74,44 +78,12 @@ Or you can directly clone our public `repository <https://gitlab.obspm.fr/e-mant
74
78
 
75
79
  It requires a python version >= 3.10.
76
80
 
77
- Post-installation
78
- -----------------
79
-
80
- The emulators shipped with e-MANTIS need to be trained before they can provide predictions.
81
- This will be done automatically and on-the-fly the first time you use each emulator.
82
-
83
- Alternatively, we provide a CLI utility to train all emulators at once::
84
-
85
- emantis-train
86
-
87
- This should not take more than a couple of minutes.
88
-
89
- The trained emulators are saved to disk, using the pickle protocol, ready for future usage.
90
- Major changes in the versions of python, e-MANTIS, or some of its main dependencies, such as numpy, scipy, or scikit-learn, might break the compatibility with previously trained emulators.
91
- In such case, the emulators will be retrained automatically on-the-fly.
92
- You can also retrain them manually using the CLI utility.
93
-
94
81
  Documentation and usage
95
82
  -----------------------
96
83
 
97
84
  The up-to-date documentation for this project (with code examples and a detailed API) is available `here <https://e-mantis.pages.obspm.fr/e-mantis>`_.
98
85
 
99
- Licence
86
+ License
100
87
  -------
101
88
 
102
- Copyright (C) 2023 Iñigo Sáez-Casares
103
-
104
- inigo.saez-casares@obspm.fr
105
-
106
- This program is free software: you can redistribute it and/or modify
107
- it under the terms of the GNU General Public License as published by
108
- the Free Software Foundation, either version 3 of the License, or
109
- (at your option) any later version.
110
-
111
- This program is distributed in the hope that it will be useful,
112
- but WITHOUT ANY WARRANTY; without even the implied warranty of
113
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
114
- GNU General Public License for more details.
115
-
116
- You should have received a copy of the GNU General Public License
117
- along with this program. If not, see https://www.gnu.org/licenses/.
89
+ e-MANTIS is distributed under the GNU General Public License v3.0 or later (GPL-3.0-or-later).
@@ -1,4 +1,4 @@
1
- |DOI|_ |PyPI|_ |release|_ |pipeline|_
1
+ |DOI|_ |PyPI|_ |release|_ |pipeline|_ |coverage|_
2
2
 
3
3
  .. |DOI| image:: https://zenodo.org/badge/DOI/10.5281/zenodo.7738362.svg
4
4
  .. _DOI: https://doi.org/10.5281/zenodo.7738362
@@ -12,6 +12,9 @@
12
12
  .. |pipeline| image:: https://gitlab.obspm.fr/e-mantis/e-mantis/badges/main/pipeline.svg
13
13
  .. _pipeline: https://gitlab.obspm.fr/e-mantis/e-mantis/-/commits/main
14
14
 
15
+ .. |coverage| image:: https://gitlab.obspm.fr/e-mantis/e-mantis/badges/main/coverage.svg
16
+ .. _coverage: https://gitlab.obspm.fr/e-mantis/e-mantis/-/commits/main
17
+
15
18
  e-MANTIS: Emulator for Multiple observable ANalysis in extended cosmological TheorIeS
16
19
  =====================================================================================
17
20
 
@@ -51,44 +54,12 @@ Or you can directly clone our public `repository <https://gitlab.obspm.fr/e-mant
51
54
 
52
55
  It requires a python version >= 3.10.
53
56
 
54
- Post-installation
55
- -----------------
56
-
57
- The emulators shipped with e-MANTIS need to be trained before they can provide predictions.
58
- This will be done automatically and on-the-fly the first time you use each emulator.
59
-
60
- Alternatively, we provide a CLI utility to train all emulators at once::
61
-
62
- emantis-train
63
-
64
- This should not take more than a couple of minutes.
65
-
66
- The trained emulators are saved to disk, using the pickle protocol, ready for future usage.
67
- Major changes in the versions of python, e-MANTIS, or some of its main dependencies, such as numpy, scipy, or scikit-learn, might break the compatibility with previously trained emulators.
68
- In such case, the emulators will be retrained automatically on-the-fly.
69
- You can also retrain them manually using the CLI utility.
70
-
71
57
  Documentation and usage
72
58
  -----------------------
73
59
 
74
60
  The up-to-date documentation for this project (with code examples and a detailed API) is available `here <https://e-mantis.pages.obspm.fr/e-mantis>`_.
75
61
 
76
- Licence
62
+ License
77
63
  -------
78
64
 
79
- Copyright (C) 2023 Iñigo Sáez-Casares
80
-
81
- inigo.saez-casares@obspm.fr
82
-
83
- This program is free software: you can redistribute it and/or modify
84
- it under the terms of the GNU General Public License as published by
85
- the Free Software Foundation, either version 3 of the License, or
86
- (at your option) any later version.
87
-
88
- This program is distributed in the hope that it will be useful,
89
- but WITHOUT ANY WARRANTY; without even the implied warranty of
90
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
91
- GNU General Public License for more details.
92
-
93
- You should have received a copy of the GNU General Public License
94
- along with this program. If not, see https://www.gnu.org/licenses/.
65
+ e-MANTIS is distributed under the GNU General Public License v3.0 or later (GPL-3.0-or-later).
@@ -1,23 +1,25 @@
1
1
  [project]
2
2
  authors = [
3
- { name = "Iñigo Sáez Casares", email = "inigo.saez-casares@obspm.fr" },
3
+ { name = "Iñigo Sáez-Casares", email = "inigo.saez-casares@obspm.fr" },
4
4
  ]
5
- requires-python = "<3.15,>=3.10"
5
+ license = "GPL-3.0-or-later"
6
+ requires-python = ">=3.10"
6
7
  dependencies = [
7
8
  "h5py <4.0,>=3.8",
8
- "scikit-learn <2,>=1",
9
+ "scikit-learn >=1.5,<2",
9
10
  "numpy <3.0,>=1.24",
10
11
  "pydantic <3.0,>=2.6",
11
12
  "tomli <3,>=2; python_version < '3.11'",
12
13
  "joblib <2.0.0,>=1.3.2",
14
+ "scipy>=1.15,<2",
15
+ "threadpoolctl <4,>=3",
13
16
  ]
14
17
  name = "emantis"
15
- version = "1.2.2"
18
+ version = "1.3.0"
16
19
  description = "A cosmological emulator for nonlinear large-scale structure formation studies in alternative dark energy and gravity theories."
17
20
  readme = "README.rst"
18
21
  classifiers = [
19
22
  "Programming Language :: Python :: 3",
20
- "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
21
23
  "Operating System :: OS Independent",
22
24
  "Intended Audience :: Science/Research",
23
25
  "Topic :: Scientific/Engineering :: Physics",
@@ -30,9 +32,6 @@ keywords = [
30
32
  "modified gravity",
31
33
  ]
32
34
 
33
- [project.license]
34
- text = "GPL-3.0-or-later"
35
-
36
35
  [project.urls]
37
36
  repository = "https://gitlab.obspm.fr/e-mantis/e-mantis.git"
38
37
  documentation = "https://e-mantis.pages.obspm.fr/e-mantis/index.html"
@@ -40,24 +39,6 @@ documentation = "https://e-mantis.pages.obspm.fr/e-mantis/index.html"
40
39
  [project.scripts]
41
40
  emantis-train = "emantis._cli:train_all_emulators"
42
41
 
43
- [tool.pdm.build]
44
- includes = []
45
- excludes = [
46
- "src/emantis/data/emulator_storage*",
47
- ]
48
-
49
- [tool.uv]
50
- default-groups = [
51
- "dev",
52
- "docs",
53
- ]
54
-
55
- [tool.pytest.ini_options]
56
- addopts = "-vv --cov"
57
-
58
- [tool.pydocstyle]
59
- convention = "numpy"
60
-
61
42
  [build-system]
62
43
  requires = [
63
44
  "pdm-backend",
@@ -68,16 +49,39 @@ build-backend = "pdm.backend"
68
49
  dev = [
69
50
  "ipython",
70
51
  "matplotlib",
71
- "jupyterlab <4.0,>=3.6",
72
- "pytest>=8.4.1",
73
- "pytest-cov>=6",
74
- "pytest-pydocstyle>=2.4.0",
52
+ "jupyterlab",
75
53
  "pre-commit>=4.5.0",
76
54
  ]
77
55
  docs = [
78
- "sphinx",
56
+ "sphinx>=7,<9",
79
57
  "sphinx-copybutton",
80
- "sphinx-rtd-theme",
81
58
  "myst-nb",
82
59
  "sphinx-multiversion>=0.2.4",
60
+ "furo>=2025.9.25",
61
+ ]
62
+ test = [
63
+ "pytest>=8.4.1",
64
+ "pytest-cov>=6",
65
+ "pytest-sugar>=1.0",
66
+ ]
67
+
68
+ [tool.uv]
69
+ default-groups = [
70
+ "dev",
71
+ "docs",
72
+ "test",
73
+ ]
74
+
75
+ [tool.pytest.ini_options]
76
+ addopts = "-vv --strict-markers"
77
+
78
+ [tool.coverage.run]
79
+ source = [
80
+ "emantis",
81
+ ]
82
+
83
+ [tool.coverage.paths]
84
+ source = [
85
+ "src/emantis",
86
+ "*/site-packages/emantis",
83
87
  ]
@@ -0,0 +1,37 @@
1
+ """Emulators of the large-scale structure formation in alternative cosmologies.
2
+
3
+ e-MANTIS provides theoretical predictions for the nonlinear large-scale structure
4
+ formation in alternative dark energy and gravity theories.
5
+ It uses Gaussian processes to interpolate between the outputs
6
+ of high resolution cosmological N-body simulations.
7
+ It supports multiple cosmological models and observables,
8
+ and is divided into modules, each one focusing on a type of observable.
9
+
10
+ Available modules
11
+ -----------------
12
+ matter_power_spectrum
13
+ Emulators for the matter power spectrum.
14
+ halo_mass_function
15
+ Emulator for the halo mass function.
16
+ custom_emulators
17
+ Build, save and load your own emulators.
18
+ powerspectrum_matter
19
+ Emulators for the matter power spectrum.
20
+ Deprecated, use matter_power_spectrum instead.
21
+ """
22
+
23
+ from importlib.metadata import version
24
+
25
+ from emantis import custom_emulators, halo_mass_function, matter_power_spectrum
26
+ from emantis.custom_emulators import load_emulator
27
+ from emantis.powerspectrum_matter import FofrBoost
28
+
29
+ __version__ = version("emantis")
30
+
31
+ __all__ = [
32
+ "FofrBoost",
33
+ "custom_emulators",
34
+ "halo_mass_function",
35
+ "load_emulator",
36
+ "matter_power_spectrum",
37
+ ]
@@ -0,0 +1,355 @@
1
+ """Base classes of the e-MANTIS emulators."""
2
+
3
+ import sys
4
+ from collections.abc import Sequence
5
+
6
+ import numpy as np
7
+ import numpy.typing as npt
8
+
9
+ from emantis import _utils_inputs
10
+
11
+
12
+ class _BaseEmulator:
13
+ """A base emulator class meant to be inherited.
14
+
15
+ Parameters
16
+ ----------
17
+ params_range : dict or None, default=None
18
+ A dict. with the emulation range of each input parameter.
19
+ If ``None``, the emulator only accepts input parameters in the form of an array
20
+ and it will never check if the requested input parameters
21
+ are within the emulation range.
22
+ WARNING: the order of the parameters in the dict matters.
23
+ random_seed: int or None, default=None
24
+ The random seed passed to the random generators used during training.
25
+ n_jobs: int, default=1
26
+ Maximum number of independent processes used to fit the emulator
27
+ (training and cross-validation). A value of -1 uses all available cores.
28
+ name : str, default='e-MANTIS'
29
+ Name of the emulator, used as prefix of the verbose messages.
30
+ verbose : bool, default=True
31
+ If ``True``, print messages to the standard output
32
+ (e.g. when the emulator is trained or loaded).
33
+
34
+ Attributes
35
+ ----------
36
+ random_seed : int or None
37
+ The random seed passed to the random generators used during training.
38
+ n_jobs : int
39
+ Maximum number of independent processes used to fit the emulator
40
+ (see the `n_jobs` parameter).
41
+ verbose : bool
42
+ If ``True``, print messages to the standard output
43
+ (e.g. when the emulator is trained or loaded).
44
+ _name : str
45
+ Name of the emulator, used as prefix of the verbose messages.
46
+
47
+ """
48
+
49
+ def __init__(
50
+ self,
51
+ params_range: dict[str, dict[str, float]] | None = None,
52
+ random_seed: int | None = None,
53
+ n_jobs: int = 1,
54
+ name: str = "e-MANTIS",
55
+ verbose: bool = True,
56
+ ) -> None:
57
+ # Get params names and range.
58
+ self._params_range = params_range
59
+
60
+ # Set random seed.
61
+ self.random_seed = random_seed
62
+
63
+ # Number of jobs.
64
+ self.n_jobs = n_jobs
65
+
66
+ # Name, used as prefix of the verbose messages.
67
+ self._name = name
68
+
69
+ # Verbosity.
70
+ self.verbose = verbose
71
+
72
+ @property
73
+ def params_range(self) -> dict | None:
74
+ """Dict or None: The emulation range of each input parameter, if given."""
75
+ return self._params_range
76
+
77
+ def range(self, parameter: str) -> tuple[float, float]:
78
+ """Give the emulation range of an input parameter.
79
+
80
+ Parameters
81
+ ----------
82
+ parameter : str
83
+ The name of the parameter.
84
+
85
+ Returns
86
+ -------
87
+ min_value, max_value : float
88
+ The minimum and maximum of the emulation range.
89
+
90
+ Raises
91
+ ------
92
+ ValueError
93
+ If `parameter` is not an input parameter of this emulator.
94
+
95
+ """
96
+ if self.params_range is None:
97
+ raise ValueError(
98
+ f"Unknown variable: {parameter}.\n"
99
+ "Note: the params_range dict was not provided"
100
+ " at the initialization of this instance,"
101
+ " therefore the parameter names are not known."
102
+ )
103
+ if parameter not in self.params_range:
104
+ raise ValueError(f"Unknown variable: {parameter}.")
105
+ return (
106
+ self.params_range[parameter]["min_value"],
107
+ self.params_range[parameter]["max_value"],
108
+ )
109
+
110
+ def _print(self, message: str) -> None:
111
+ """Print a message prefixed by the emulator name, if verbose is ``True``.
112
+
113
+ Parameters
114
+ ----------
115
+ message : str
116
+ The message to print.
117
+
118
+ """
119
+ if self.verbose:
120
+ # Messages pending on stderr (e.g. the progress of joblib) come first,
121
+ # also where the two streams are shown separately (e.g. Jupyter).
122
+ sys.stderr.flush()
123
+ print(f"{self._name}: {message}", flush=True)
124
+
125
+ def _format_input_params_to_array(
126
+ self,
127
+ input_params: dict[str, float | list[float] | npt.NDArray] | npt.NDArray,
128
+ ) -> npt.NDArray:
129
+ """Convert the input parameters to a validated 2-D array.
130
+
131
+ An array of shape (n_params,) (one model) or (n_samples, n_params)
132
+ is reshaped to 2-D. If this instance has a `params_range`, the number
133
+ of columns and the range of each parameter are checked, the columns
134
+ being ordered as `params_range`.
135
+
136
+ A dict must have one entry per parameter of `params_range`, whose names
137
+ and ranges are checked. Each entry has either one value, or the same
138
+ number of values `n_samples` as every other entry with more than one value;
139
+ single values are repeated for all samples.
140
+
141
+ Parameters
142
+ ----------
143
+ input_params : dict or ndarray of shape (n_params,) or (n_samples, n_params)
144
+ The input parameters.
145
+
146
+ Returns
147
+ -------
148
+ params_array : ndarray of shape (n_samples, n_params)
149
+ Array containing the input parameters, where `n_params` is the number
150
+ of parameters and `n_samples` the number of inputs per parameter.
151
+
152
+ Raises
153
+ ------
154
+ TypeError
155
+ If `input_params` is a dict, but this instance was not initialized with
156
+ a `params_range` dict, or if it is neither a dict nor an array.
157
+ ValueError
158
+ If an array has more than two dimensions or the wrong number of columns,
159
+ or if the number of values in `input_params` for different
160
+ parameters is not compatible.
161
+
162
+ """
163
+ if isinstance(input_params, np.ndarray):
164
+ params_array = input_params
165
+
166
+ # Ensure correct array shape.
167
+ if params_array.ndim == 1:
168
+ params_array = params_array.reshape(1, -1)
169
+ elif params_array.ndim != 2:
170
+ raise ValueError(
171
+ "Array `params` must have shape (n_params,) or"
172
+ f" (n_samples, n_params), got shape {params_array.shape}."
173
+ )
174
+
175
+ # Check each parameter range if necessary.
176
+ if self.params_range is not None:
177
+ # Check number of parameters (columns).
178
+ if params_array.shape[1] != len(self.params_range):
179
+ raise ValueError(
180
+ f"Array `params` has {params_array.shape[1]} columns,"
181
+ f" but this emulator expects {len(self.params_range)}"
182
+ f" parameters, in this order: {list(self.params_range)}."
183
+ )
184
+
185
+ # Loop over all parameters.
186
+ for i, param_name in enumerate(self.params_range):
187
+ _utils_inputs.check_emulation_range(
188
+ params_array[:, i],
189
+ self.params_range[param_name]["min_value"],
190
+ self.params_range[param_name]["max_value"],
191
+ param_name,
192
+ )
193
+
194
+ elif isinstance(input_params, dict):
195
+ if self.params_range is None:
196
+ raise TypeError(
197
+ "This instance only accepts the 'params' argument"
198
+ " in the form of an array, since the 'params_range' argument"
199
+ " was not provided when instantiated."
200
+ )
201
+
202
+ # First check names (and range) of input parameters.
203
+ self._check_input_params_dict(input_params)
204
+
205
+ # Each parameter must have either 1 value or the same number
206
+ # of values n_samples as every other parameter with > 1 value.
207
+ arrays = {
208
+ param_name: _utils_inputs.format_input_to_1d_array(
209
+ input_params[param_name], param_name
210
+ )
211
+ for param_name in input_params
212
+ }
213
+ n_values = {name: array.shape[0] for name, array in arrays.items()}
214
+ lengths = set(n_values.values()) - {1}
215
+ if len(lengths) > 1:
216
+ raise ValueError(
217
+ "Input parameters must have either one value or the same"
218
+ f" number of values. Got: {n_values}."
219
+ )
220
+ n_samples: int = lengths.pop() if lengths else 1
221
+
222
+ # Gather the parameters in an array, in the order of params_range.
223
+ # A single value is broadcast to all the samples.
224
+ params_array = np.zeros((n_samples, len(self.params_range)))
225
+ for i, param_name in enumerate(self.params_range):
226
+ params_array[:, i] = arrays[param_name]
227
+ else:
228
+ raise TypeError("Argument 'params' must be a dict or a ndarray.")
229
+
230
+ return params_array
231
+
232
+ def _check_input_params_dict(
233
+ self,
234
+ input_params_dict: dict[str, float | list[float] | npt.NDArray],
235
+ check_range: bool = True,
236
+ ) -> None:
237
+ """Check input parameter dict.
238
+
239
+ Check that the input parameters have valid names,
240
+ and that all the required parameters have been provided.
241
+
242
+ Can also check the range of the input parameters (see `required_params_range`).
243
+
244
+ Parameters
245
+ ----------
246
+ input_params_dict : dict
247
+ A dictionary with the input parameters.
248
+ check_range : bool, default=True
249
+ If ``True`` check that the input parameters are within
250
+ the allowed emulation range.
251
+
252
+ Raises
253
+ ------
254
+ TypeError
255
+ If this instance was not initialized with a `params_range` dict.
256
+ KeyError
257
+ If the keys of `input_params_dict` do not match
258
+ those of the attribute `params_range`.
259
+
260
+ """
261
+ if self.params_range is None:
262
+ raise TypeError(
263
+ "This instance only accepts the 'params' argument"
264
+ " in the form of an array, since the 'params_range' argument"
265
+ " was not provided when instantiated."
266
+ )
267
+
268
+ # Check that all the provided parameter names are valid.
269
+ for param in input_params_dict:
270
+ if param not in self.params_range:
271
+ raise KeyError(f"The provided parameter '{param}' is not supported.")
272
+
273
+ # Check that all the required parameters
274
+ # have been provided.
275
+ for param in self.params_range:
276
+ if param not in input_params_dict:
277
+ raise KeyError(f"The parameter '{param}' is missing.")
278
+
279
+ # Check emulation range.
280
+ if check_range:
281
+ # Loop over input parameters.
282
+ for param_name in input_params_dict:
283
+ _utils_inputs.check_emulation_range(
284
+ input_params_dict[param_name],
285
+ self.params_range[param_name]["min_value"],
286
+ self.params_range[param_name]["max_value"],
287
+ param_name,
288
+ )
289
+
290
+
291
+ class _CompositeEmulator(_BaseEmulator):
292
+ """An emulator made of other emulators, its inner emulators.
293
+
294
+ The runtime options `random_seed`, `n_jobs` and `verbose` are those of the
295
+ inner emulators: the getters read the first one, and the setters set all of them.
296
+ Nothing is stored here. A subclass defines :py:meth:`_inner_emulators`,
297
+ and creates its inner emulators before calling ``super().__init__``,
298
+ because the base class sets the runtime options.
299
+ """
300
+
301
+ def _inner_emulators(self) -> Sequence[_BaseEmulator]:
302
+ """Return the inner emulators.
303
+
304
+ Returns
305
+ -------
306
+ emulators : sequence of _BaseEmulator
307
+ The inner emulators. The first one gives the values of the options.
308
+
309
+ Raises
310
+ ------
311
+ NotImplementedError
312
+ Always: subclasses define it.
313
+
314
+ """
315
+ raise NotImplementedError
316
+
317
+ @property
318
+ def random_seed(self) -> int | None:
319
+ """Int or None: The random seed passed to the random generators of training.
320
+
321
+ Setting it sets it on every inner emulator.
322
+ """
323
+ return self._inner_emulators()[0].random_seed
324
+
325
+ @random_seed.setter
326
+ def random_seed(self, value: int | None) -> None:
327
+ for emulator in self._inner_emulators():
328
+ emulator.random_seed = value
329
+
330
+ @property
331
+ def n_jobs(self) -> int:
332
+ """int: Maximum number of independent processes used to fit the emulator.
333
+
334
+ Used for training and cross-validation. A value of -1 uses all available cores.
335
+ Setting it sets it on every inner emulator.
336
+ """
337
+ return self._inner_emulators()[0].n_jobs
338
+
339
+ @n_jobs.setter
340
+ def n_jobs(self, value: int) -> None:
341
+ for emulator in self._inner_emulators():
342
+ emulator.n_jobs = value
343
+
344
+ @property
345
+ def verbose(self) -> bool:
346
+ """bool: If ``True``, print messages to the standard output.
347
+
348
+ Setting it sets it on every inner emulator.
349
+ """
350
+ return self._inner_emulators()[0].verbose
351
+
352
+ @verbose.setter
353
+ def verbose(self, value: bool) -> None:
354
+ for emulator in self._inner_emulators():
355
+ emulator.verbose = value