fastcmb 0.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.
- fastcmb-0.3.0/LICENSE +21 -0
- fastcmb-0.3.0/PKG-INFO +264 -0
- fastcmb-0.3.0/README.md +230 -0
- fastcmb-0.3.0/pyproject.toml +48 -0
- fastcmb-0.3.0/setup.cfg +4 -0
- fastcmb-0.3.0/src/fastcmb/__init__.py +23 -0
- fastcmb-0.3.0/src/fastcmb/camb_oracle.py +134 -0
- fastcmb-0.3.0/src/fastcmb/cobaya.py +133 -0
- fastcmb-0.3.0/src/fastcmb/compress.py +148 -0
- fastcmb-0.3.0/src/fastcmb/emulator.py +247 -0
- fastcmb-0.3.0/src/fastcmb/gp.py +305 -0
- fastcmb-0.3.0/src/fastcmb/metric.py +66 -0
- fastcmb-0.3.0/src/fastcmb/online.py +363 -0
- fastcmb-0.3.0/src/fastcmb.egg-info/PKG-INFO +264 -0
- fastcmb-0.3.0/src/fastcmb.egg-info/SOURCES.txt +21 -0
- fastcmb-0.3.0/src/fastcmb.egg-info/dependency_links.txt +1 -0
- fastcmb-0.3.0/src/fastcmb.egg-info/requires.txt +13 -0
- fastcmb-0.3.0/src/fastcmb.egg-info/top_level.txt +1 -0
- fastcmb-0.3.0/tests/test_camb_oracle.py +36 -0
- fastcmb-0.3.0/tests/test_cobaya.py +55 -0
- fastcmb-0.3.0/tests/test_compress.py +42 -0
- fastcmb-0.3.0/tests/test_emulator.py +168 -0
- fastcmb-0.3.0/tests/test_gp.py +63 -0
fastcmb-0.3.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Salih Yeşil
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
fastcmb-0.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fastcmb
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: An online emulator of Boltzmann codes: CMB spectra in milliseconds, with the code as the fallback.
|
|
5
|
+
Author: Salih Yeşil
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/salihyesil59/fastcmb
|
|
8
|
+
Project-URL: Source, https://github.com/salihyesil59/fastcmb
|
|
9
|
+
Project-URL: Issues, https://github.com/salihyesil59/fastcmb/issues
|
|
10
|
+
Keywords: cosmology,CMB,emulator,Gaussian process,CAMB,MCMC,Boltzmann code
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Astronomy
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: numpy>=2.0
|
|
24
|
+
Requires-Dist: scipy
|
|
25
|
+
Provides-Extra: camb
|
|
26
|
+
Requires-Dist: camb>=1.5; extra == "camb"
|
|
27
|
+
Provides-Extra: cobaya
|
|
28
|
+
Requires-Dist: cobaya>=3.5; extra == "cobaya"
|
|
29
|
+
Requires-Dist: camb>=1.5; extra == "cobaya"
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pytest; extra == "dev"
|
|
32
|
+
Requires-Dist: camb>=1.5; extra == "dev"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# fastcmb
|
|
36
|
+
|
|
37
|
+
fastcmb is an online emulator for Boltzmann codes, aimed at CMB analyses.
|
|
38
|
+
It sits in front of CAMB, or any other code, and works one point at a
|
|
39
|
+
time:
|
|
40
|
+
|
|
41
|
+
- It predicts the spectra together with the error of that prediction,
|
|
42
|
+
measured in units of `ln L`.
|
|
43
|
+
- If the predicted error is below the tolerance, it returns the
|
|
44
|
+
prediction. This takes about 6 ms.
|
|
45
|
+
- Otherwise it runs the code and adds the point to its training set.
|
|
46
|
+
|
|
47
|
+
There is nothing to train in advance: the emulator learns while the
|
|
48
|
+
chain runs.
|
|
49
|
+
|
|
50
|
+
The package itself depends only on numpy and scipy. Three integrations
|
|
51
|
+
are available:
|
|
52
|
+
|
|
53
|
+
| Where | How |
|
|
54
|
+
|---|---|
|
|
55
|
+
| **CosmoFit** | `theory: {background: ..., fastcmb: ...}` in place of `camb` (built in, with `pip install "cosmofit[fast]"`) |
|
|
56
|
+
| **cobaya** | the theory `fastcmb.cobaya.FastCAMB` in place of `camb` |
|
|
57
|
+
| **anything else** | call a `CMBEmulator` |
|
|
58
|
+
|
|
59
|
+
## Install
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pip install "fastcmb[camb]" # with CAMB as the oracle
|
|
63
|
+
pip install "fastcmb[cobaya]" # and the cobaya theory
|
|
64
|
+
pip install "cosmofit[fast]" # CosmoFit, with fastcmb and CAMB
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The emulator alone (`pip install fastcmb`) needs only numpy and scipy;
|
|
68
|
+
the oracle is then a code of your own. From a clone, `pip install -e ".[dev]"`
|
|
69
|
+
installs the tests' dependencies as well.
|
|
70
|
+
|
|
71
|
+
## Use
|
|
72
|
+
|
|
73
|
+
### Python
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
from fastcmb import CAMBOracle, CMBEmulator
|
|
77
|
+
|
|
78
|
+
emulator = CMBEmulator(CAMBOracle(lmax=2508, lens_potential_accuracy=4),
|
|
79
|
+
tolerance=0.05, training_file="emu/lcdm")
|
|
80
|
+
|
|
81
|
+
result = emulator({"H0": 67.4, "ombh2": 0.0224, "omch2": 0.120,
|
|
82
|
+
"ln1e10As": 3.044, "ns": 0.965, "tau": 0.054})
|
|
83
|
+
|
|
84
|
+
result.Cl["tt"], result.Cl["pp"], result.sigma8, result.emulated
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
`result` contains the following:
|
|
88
|
+
|
|
89
|
+
- `Cl` holds `ell`, `tt`, `te`, `ee` and `bb`, starting at `l = 0`. These
|
|
90
|
+
are `C_l` in muK².
|
|
91
|
+
- `pp` is `[L(L+1)]² C_L / 2π`.
|
|
92
|
+
|
|
93
|
+
Any code can serve as the oracle. It is a function that takes a
|
|
94
|
+
parameter dict and returns `{"Cl": ..., "sigma8": ..., "sigma8_cb": ...}`
|
|
95
|
+
in these conventions, or `None` when the point cannot be computed.
|
|
96
|
+
`CAMBOracle` takes the parameters as cobaya names them (`H0` or
|
|
97
|
+
`cosmomc_theta`, `ombh2`, `omch2`, `ln1e10As`/`logA` or `As`, `ns`, `tau`,
|
|
98
|
+
and optionally `mnu`, `nnu`, `omk`, `w`, `wa`).
|
|
99
|
+
|
|
100
|
+
`emulator(params, loose_tolerance=1.0)` also answers with a prediction
|
|
101
|
+
whose error is above the tolerance but below 1, marked
|
|
102
|
+
`result.approximate`. A sampler can use it to reject a proposal that is
|
|
103
|
+
clearly worse than the current point without running the code, and ask
|
|
104
|
+
again without `loose_tolerance` for one it might accept. CosmoFit's MCMC
|
|
105
|
+
does this with `screen: true`.
|
|
106
|
+
|
|
107
|
+
### cobaya
|
|
108
|
+
|
|
109
|
+
```yaml
|
|
110
|
+
theory:
|
|
111
|
+
fastcmb.cobaya.FastCAMB:
|
|
112
|
+
tolerance: 0.05
|
|
113
|
+
lens_potential_accuracy: 4
|
|
114
|
+
training_file: chains/emu/lcdm
|
|
115
|
+
params:
|
|
116
|
+
logA: ... # or As
|
|
117
|
+
ns: ...
|
|
118
|
+
H0: ... # or cosmomc_theta
|
|
119
|
+
ombh2: ...
|
|
120
|
+
omch2: ...
|
|
121
|
+
tau: ...
|
|
122
|
+
sigma8: # derived
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The theory provides `Cl` in cobaya's units and `ell_factor` conventions,
|
|
126
|
+
so cobaya's CMB likelihoods read it as they would read `camb`.
|
|
127
|
+
|
|
128
|
+
### CosmoFit
|
|
129
|
+
|
|
130
|
+
```yaml
|
|
131
|
+
theory:
|
|
132
|
+
background:
|
|
133
|
+
fastcmb:
|
|
134
|
+
tolerance: 0.05
|
|
135
|
+
training_file: chains/emu/lcdm
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The theory takes every `camb` option and parameter, and dark sectors
|
|
139
|
+
beyond ΛCDM: CPL and other dark energies, early dark energy, and
|
|
140
|
+
Hu–Sawicki f(R) when CAMB is MGCAMB. Their parameters become inputs of
|
|
141
|
+
the emulator, together with the distance to last scattering, along which
|
|
142
|
+
they trade off against `h`.
|
|
143
|
+
|
|
144
|
+
## Options
|
|
145
|
+
|
|
146
|
+
| | default | |
|
|
147
|
+
|---|---|---|
|
|
148
|
+
| `tolerance` | 0.05 | largest predicted `ln L` error the emulator answers with |
|
|
149
|
+
| `sigma8_tolerance` | 1e-3 | largest predicted relative error of `sigma8` |
|
|
150
|
+
| `min_train` | 30 | points computed by the code before the first fit |
|
|
151
|
+
| `retrain_fraction` | 0.1 | refit once the new points are this fraction of those fitted on |
|
|
152
|
+
| `max_train` | 800 | most points fitted on (the latest) |
|
|
153
|
+
| `training_file` | none | keeps the points, so parallel chains and later runs share them |
|
|
154
|
+
| `check_every` | 200 | after N predictions the code runs as well, to measure the error; the interval doubles while checks pass, up to 10 N |
|
|
155
|
+
|
|
156
|
+
## How it works
|
|
157
|
+
|
|
158
|
+
1. **Transformation.**
|
|
159
|
+
- `tt`, `ee`, `bb` and `pp` are emulated as `ln C_l`.
|
|
160
|
+
- `te` is emulated as the correlation `C_TE / sqrt(C_TT C_EE)`.
|
|
161
|
+
2. **Compression.** Each block is reduced with PCA. The number of
|
|
162
|
+
components is chosen so that the PCA error in `ln L` stays below 0.01
|
|
163
|
+
(`compress.py`).
|
|
164
|
+
3. **Gaussian process.**
|
|
165
|
+
- The mean is quadratic in the inputs.
|
|
166
|
+
- The four components that carry the most likelihood each get their
|
|
167
|
+
own kernel, and the remaining components share one (`gp.py`).
|
|
168
|
+
- Hyperparameters are fitted by maximum likelihood on 200 of the
|
|
169
|
+
points. Each refit tries both the previous values and a fresh
|
|
170
|
+
start, and it reruns whenever half the training set is new.
|
|
171
|
+
4. **Error.**
|
|
172
|
+
- Each kernel's predictive variance is projected onto `ln L` with an
|
|
173
|
+
idealized Planck Fisher weight (`metric.py`).
|
|
174
|
+
- Variances are computed in order of their bound and only while they
|
|
175
|
+
can still change the decision. This keeps the result an upper
|
|
176
|
+
bound (`online.py`).
|
|
177
|
+
5. **Decision.** The prediction is used, or the code runs and the point
|
|
178
|
+
is learned (`emulator.py`).
|
|
179
|
+
|
|
180
|
+
## Benchmarks
|
|
181
|
+
|
|
182
|
+
The test case is ΛCDM on Planck 2018 lite + lowE + lensing, with
|
|
183
|
+
CosmoFit's MCMC running 4 chains in one process:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
python benchmarks/chain.py --max-time 3600 --output chains/lcdm
|
|
187
|
+
python benchmarks/validate_chain.py chains/lcdm # chain points re-checked with CAMB
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
One hour, starting with no training points, on an idle machine (CAMB
|
|
191
|
+
0.45 s per point):
|
|
192
|
+
|
|
193
|
+
| | v0.2 |
|
|
194
|
+
|---|---|
|
|
195
|
+
| evaluations | 131 203 |
|
|
196
|
+
| CAMB calls | 1 545 (897 learned, 648 checks) |
|
|
197
|
+
| emulated | 98.8% |
|
|
198
|
+
| equivalent with CAMB alone | 16.5 h |
|
|
199
|
+
| speed-up | 16.5× |
|
|
200
|
+
| `R - 1` after the hour | 0.36 |
|
|
201
|
+
|
|
202
|
+
Accuracy against CAMB, on 60 points drawn from the chain:
|
|
203
|
+
|
|
204
|
+
- `|Δ ln L|` has a median of 0.004 and a maximum of 0.02.
|
|
205
|
+
- The posterior agrees with Planck's: `H0` = 67.39 ± 0.51 and
|
|
206
|
+
`n_s` = 0.9639 ± 0.0041.
|
|
207
|
+
|
|
208
|
+
Compared with v0.1 on the same machine:
|
|
209
|
+
|
|
210
|
+
- Evaluations in the first hour went from 54 000 to 131 000.
|
|
211
|
+
- A prediction takes 6 ms instead of 16 ms.
|
|
212
|
+
- A refit takes 4–7 s instead of 58 s.
|
|
213
|
+
|
|
214
|
+
The speed-up grows with the length of the run, because CAMB runs less
|
|
215
|
+
and less often once the emulator has learned the posterior.
|
|
216
|
+
|
|
217
|
+
Starting from a trained emulator (the hour above), 20 minutes:
|
|
218
|
+
|
|
219
|
+
| | 1 process | 4 processes (`processes: 4`) |
|
|
220
|
+
|---|---|---|
|
|
221
|
+
| MCMC steps | 10 080 | 26 880 |
|
|
222
|
+
| CAMB calls (first process) | 93 | 40 |
|
|
223
|
+
| `R - 1` | 13.9 | **0.026** |
|
|
224
|
+
| `\|Δ ln L\|` vs CAMB, max | 0.016 | 0.011 |
|
|
225
|
+
|
|
226
|
+
Several processes share their points through `training_file`, so give
|
|
227
|
+
it whenever a run has more than one.
|
|
228
|
+
|
|
229
|
+
### Beyond ΛCDM
|
|
230
|
+
|
|
231
|
+
The same chain with a dark sector, through CosmoFit (`--dark-energy`
|
|
232
|
+
`cpl`, `ede` or `hu_sawicki`; `--bao` adds DESI BAO), 4 processes sharing
|
|
233
|
+
a training file, run until `R - 1 < 0.02`:
|
|
234
|
+
|
|
235
|
+
| | CPL + DESI BAO | EDE | Hu–Sawicki f(R) |
|
|
236
|
+
|---|---|---|---|
|
|
237
|
+
| sampled beyond ΛCDM | `w0`, `wa` | `f_ede`, `log10 z_c` | `log10 \|f_R0\|` |
|
|
238
|
+
| wall time | 33 min | 39 min | 59 min |
|
|
239
|
+
| `R - 1` | 0.019 | 0.019 | 0.016 |
|
|
240
|
+
| code calls / evaluations, per process | 133 / 18 044 | 426 / 20 201 | 157 / 5 688 |
|
|
241
|
+
| `\|Δ ln L\|` vs the code, median / max | — | 0.015 / 0.10 | 0.003 / 0.032 |
|
|
242
|
+
| speed-up | — | 8.6× | 8.3× |
|
|
243
|
+
|
|
244
|
+
f(R) runs through MGCAMB, roughly ten times slower than CAMB per point.
|
|
245
|
+
The CPL run was not re-checked against CAMB point by point; the analysis
|
|
246
|
+
below does that for CPL with more data.
|
|
247
|
+
|
|
248
|
+
## Analyses
|
|
249
|
+
|
|
250
|
+
[`analysis/cpl_vs_lcdm/`](https://github.com/salihyesil59/fastcmb/tree/main/analysis/cpl_vs_lcdm) fits ΛCDM and CPL
|
|
251
|
+
(`w0`, `wa`) with CosmoFit to the full Planck 2018 likelihoods (plik_lite,
|
|
252
|
+
lowE, lensing), DESI DR2 BAO, cosmic chronometers and, in turn, Pantheon+,
|
|
253
|
+
Union3 and DES-SN5YR: six runs to `R - 1 < 0.01`, all six ΛCDM parameters
|
|
254
|
+
sampled. The notebook compares the models (Δχ², AIC, BIC), shows which data
|
|
255
|
+
carry the signal, and checks the emulator against CAMB.
|
|
256
|
+
|
|
257
|
+
| | Pantheon+ | Union3 | DES-SN5YR (Dovekie) |
|
|
258
|
+
|---|---|---|---|
|
|
259
|
+
| `w0` | −0.843 ± 0.054 | −0.677 ± 0.090 | −0.809 ± 0.056 |
|
|
260
|
+
| `wa` | −0.59 ± 0.20 | −1.04 ± 0.30 | −0.70 ± 0.22 |
|
|
261
|
+
| preference for CPL | 2.6σ | 3.5σ | 3.1σ |
|
|
262
|
+
|
|
263
|
+
Each run took 15–52 min. CAMB ran at 272 (ΛCDM) and 642 (CPL) points
|
|
264
|
+
over all six runs, and `|Δ ln L|` against CAMB is at most 0.015.
|
fastcmb-0.3.0/README.md
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
# fastcmb
|
|
2
|
+
|
|
3
|
+
fastcmb is an online emulator for Boltzmann codes, aimed at CMB analyses.
|
|
4
|
+
It sits in front of CAMB, or any other code, and works one point at a
|
|
5
|
+
time:
|
|
6
|
+
|
|
7
|
+
- It predicts the spectra together with the error of that prediction,
|
|
8
|
+
measured in units of `ln L`.
|
|
9
|
+
- If the predicted error is below the tolerance, it returns the
|
|
10
|
+
prediction. This takes about 6 ms.
|
|
11
|
+
- Otherwise it runs the code and adds the point to its training set.
|
|
12
|
+
|
|
13
|
+
There is nothing to train in advance: the emulator learns while the
|
|
14
|
+
chain runs.
|
|
15
|
+
|
|
16
|
+
The package itself depends only on numpy and scipy. Three integrations
|
|
17
|
+
are available:
|
|
18
|
+
|
|
19
|
+
| Where | How |
|
|
20
|
+
|---|---|
|
|
21
|
+
| **CosmoFit** | `theory: {background: ..., fastcmb: ...}` in place of `camb` (built in, with `pip install "cosmofit[fast]"`) |
|
|
22
|
+
| **cobaya** | the theory `fastcmb.cobaya.FastCAMB` in place of `camb` |
|
|
23
|
+
| **anything else** | call a `CMBEmulator` |
|
|
24
|
+
|
|
25
|
+
## Install
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pip install "fastcmb[camb]" # with CAMB as the oracle
|
|
29
|
+
pip install "fastcmb[cobaya]" # and the cobaya theory
|
|
30
|
+
pip install "cosmofit[fast]" # CosmoFit, with fastcmb and CAMB
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The emulator alone (`pip install fastcmb`) needs only numpy and scipy;
|
|
34
|
+
the oracle is then a code of your own. From a clone, `pip install -e ".[dev]"`
|
|
35
|
+
installs the tests' dependencies as well.
|
|
36
|
+
|
|
37
|
+
## Use
|
|
38
|
+
|
|
39
|
+
### Python
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from fastcmb import CAMBOracle, CMBEmulator
|
|
43
|
+
|
|
44
|
+
emulator = CMBEmulator(CAMBOracle(lmax=2508, lens_potential_accuracy=4),
|
|
45
|
+
tolerance=0.05, training_file="emu/lcdm")
|
|
46
|
+
|
|
47
|
+
result = emulator({"H0": 67.4, "ombh2": 0.0224, "omch2": 0.120,
|
|
48
|
+
"ln1e10As": 3.044, "ns": 0.965, "tau": 0.054})
|
|
49
|
+
|
|
50
|
+
result.Cl["tt"], result.Cl["pp"], result.sigma8, result.emulated
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`result` contains the following:
|
|
54
|
+
|
|
55
|
+
- `Cl` holds `ell`, `tt`, `te`, `ee` and `bb`, starting at `l = 0`. These
|
|
56
|
+
are `C_l` in muK².
|
|
57
|
+
- `pp` is `[L(L+1)]² C_L / 2π`.
|
|
58
|
+
|
|
59
|
+
Any code can serve as the oracle. It is a function that takes a
|
|
60
|
+
parameter dict and returns `{"Cl": ..., "sigma8": ..., "sigma8_cb": ...}`
|
|
61
|
+
in these conventions, or `None` when the point cannot be computed.
|
|
62
|
+
`CAMBOracle` takes the parameters as cobaya names them (`H0` or
|
|
63
|
+
`cosmomc_theta`, `ombh2`, `omch2`, `ln1e10As`/`logA` or `As`, `ns`, `tau`,
|
|
64
|
+
and optionally `mnu`, `nnu`, `omk`, `w`, `wa`).
|
|
65
|
+
|
|
66
|
+
`emulator(params, loose_tolerance=1.0)` also answers with a prediction
|
|
67
|
+
whose error is above the tolerance but below 1, marked
|
|
68
|
+
`result.approximate`. A sampler can use it to reject a proposal that is
|
|
69
|
+
clearly worse than the current point without running the code, and ask
|
|
70
|
+
again without `loose_tolerance` for one it might accept. CosmoFit's MCMC
|
|
71
|
+
does this with `screen: true`.
|
|
72
|
+
|
|
73
|
+
### cobaya
|
|
74
|
+
|
|
75
|
+
```yaml
|
|
76
|
+
theory:
|
|
77
|
+
fastcmb.cobaya.FastCAMB:
|
|
78
|
+
tolerance: 0.05
|
|
79
|
+
lens_potential_accuracy: 4
|
|
80
|
+
training_file: chains/emu/lcdm
|
|
81
|
+
params:
|
|
82
|
+
logA: ... # or As
|
|
83
|
+
ns: ...
|
|
84
|
+
H0: ... # or cosmomc_theta
|
|
85
|
+
ombh2: ...
|
|
86
|
+
omch2: ...
|
|
87
|
+
tau: ...
|
|
88
|
+
sigma8: # derived
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The theory provides `Cl` in cobaya's units and `ell_factor` conventions,
|
|
92
|
+
so cobaya's CMB likelihoods read it as they would read `camb`.
|
|
93
|
+
|
|
94
|
+
### CosmoFit
|
|
95
|
+
|
|
96
|
+
```yaml
|
|
97
|
+
theory:
|
|
98
|
+
background:
|
|
99
|
+
fastcmb:
|
|
100
|
+
tolerance: 0.05
|
|
101
|
+
training_file: chains/emu/lcdm
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The theory takes every `camb` option and parameter, and dark sectors
|
|
105
|
+
beyond ΛCDM: CPL and other dark energies, early dark energy, and
|
|
106
|
+
Hu–Sawicki f(R) when CAMB is MGCAMB. Their parameters become inputs of
|
|
107
|
+
the emulator, together with the distance to last scattering, along which
|
|
108
|
+
they trade off against `h`.
|
|
109
|
+
|
|
110
|
+
## Options
|
|
111
|
+
|
|
112
|
+
| | default | |
|
|
113
|
+
|---|---|---|
|
|
114
|
+
| `tolerance` | 0.05 | largest predicted `ln L` error the emulator answers with |
|
|
115
|
+
| `sigma8_tolerance` | 1e-3 | largest predicted relative error of `sigma8` |
|
|
116
|
+
| `min_train` | 30 | points computed by the code before the first fit |
|
|
117
|
+
| `retrain_fraction` | 0.1 | refit once the new points are this fraction of those fitted on |
|
|
118
|
+
| `max_train` | 800 | most points fitted on (the latest) |
|
|
119
|
+
| `training_file` | none | keeps the points, so parallel chains and later runs share them |
|
|
120
|
+
| `check_every` | 200 | after N predictions the code runs as well, to measure the error; the interval doubles while checks pass, up to 10 N |
|
|
121
|
+
|
|
122
|
+
## How it works
|
|
123
|
+
|
|
124
|
+
1. **Transformation.**
|
|
125
|
+
- `tt`, `ee`, `bb` and `pp` are emulated as `ln C_l`.
|
|
126
|
+
- `te` is emulated as the correlation `C_TE / sqrt(C_TT C_EE)`.
|
|
127
|
+
2. **Compression.** Each block is reduced with PCA. The number of
|
|
128
|
+
components is chosen so that the PCA error in `ln L` stays below 0.01
|
|
129
|
+
(`compress.py`).
|
|
130
|
+
3. **Gaussian process.**
|
|
131
|
+
- The mean is quadratic in the inputs.
|
|
132
|
+
- The four components that carry the most likelihood each get their
|
|
133
|
+
own kernel, and the remaining components share one (`gp.py`).
|
|
134
|
+
- Hyperparameters are fitted by maximum likelihood on 200 of the
|
|
135
|
+
points. Each refit tries both the previous values and a fresh
|
|
136
|
+
start, and it reruns whenever half the training set is new.
|
|
137
|
+
4. **Error.**
|
|
138
|
+
- Each kernel's predictive variance is projected onto `ln L` with an
|
|
139
|
+
idealized Planck Fisher weight (`metric.py`).
|
|
140
|
+
- Variances are computed in order of their bound and only while they
|
|
141
|
+
can still change the decision. This keeps the result an upper
|
|
142
|
+
bound (`online.py`).
|
|
143
|
+
5. **Decision.** The prediction is used, or the code runs and the point
|
|
144
|
+
is learned (`emulator.py`).
|
|
145
|
+
|
|
146
|
+
## Benchmarks
|
|
147
|
+
|
|
148
|
+
The test case is ΛCDM on Planck 2018 lite + lowE + lensing, with
|
|
149
|
+
CosmoFit's MCMC running 4 chains in one process:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
python benchmarks/chain.py --max-time 3600 --output chains/lcdm
|
|
153
|
+
python benchmarks/validate_chain.py chains/lcdm # chain points re-checked with CAMB
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
One hour, starting with no training points, on an idle machine (CAMB
|
|
157
|
+
0.45 s per point):
|
|
158
|
+
|
|
159
|
+
| | v0.2 |
|
|
160
|
+
|---|---|
|
|
161
|
+
| evaluations | 131 203 |
|
|
162
|
+
| CAMB calls | 1 545 (897 learned, 648 checks) |
|
|
163
|
+
| emulated | 98.8% |
|
|
164
|
+
| equivalent with CAMB alone | 16.5 h |
|
|
165
|
+
| speed-up | 16.5× |
|
|
166
|
+
| `R - 1` after the hour | 0.36 |
|
|
167
|
+
|
|
168
|
+
Accuracy against CAMB, on 60 points drawn from the chain:
|
|
169
|
+
|
|
170
|
+
- `|Δ ln L|` has a median of 0.004 and a maximum of 0.02.
|
|
171
|
+
- The posterior agrees with Planck's: `H0` = 67.39 ± 0.51 and
|
|
172
|
+
`n_s` = 0.9639 ± 0.0041.
|
|
173
|
+
|
|
174
|
+
Compared with v0.1 on the same machine:
|
|
175
|
+
|
|
176
|
+
- Evaluations in the first hour went from 54 000 to 131 000.
|
|
177
|
+
- A prediction takes 6 ms instead of 16 ms.
|
|
178
|
+
- A refit takes 4–7 s instead of 58 s.
|
|
179
|
+
|
|
180
|
+
The speed-up grows with the length of the run, because CAMB runs less
|
|
181
|
+
and less often once the emulator has learned the posterior.
|
|
182
|
+
|
|
183
|
+
Starting from a trained emulator (the hour above), 20 minutes:
|
|
184
|
+
|
|
185
|
+
| | 1 process | 4 processes (`processes: 4`) |
|
|
186
|
+
|---|---|---|
|
|
187
|
+
| MCMC steps | 10 080 | 26 880 |
|
|
188
|
+
| CAMB calls (first process) | 93 | 40 |
|
|
189
|
+
| `R - 1` | 13.9 | **0.026** |
|
|
190
|
+
| `\|Δ ln L\|` vs CAMB, max | 0.016 | 0.011 |
|
|
191
|
+
|
|
192
|
+
Several processes share their points through `training_file`, so give
|
|
193
|
+
it whenever a run has more than one.
|
|
194
|
+
|
|
195
|
+
### Beyond ΛCDM
|
|
196
|
+
|
|
197
|
+
The same chain with a dark sector, through CosmoFit (`--dark-energy`
|
|
198
|
+
`cpl`, `ede` or `hu_sawicki`; `--bao` adds DESI BAO), 4 processes sharing
|
|
199
|
+
a training file, run until `R - 1 < 0.02`:
|
|
200
|
+
|
|
201
|
+
| | CPL + DESI BAO | EDE | Hu–Sawicki f(R) |
|
|
202
|
+
|---|---|---|---|
|
|
203
|
+
| sampled beyond ΛCDM | `w0`, `wa` | `f_ede`, `log10 z_c` | `log10 \|f_R0\|` |
|
|
204
|
+
| wall time | 33 min | 39 min | 59 min |
|
|
205
|
+
| `R - 1` | 0.019 | 0.019 | 0.016 |
|
|
206
|
+
| code calls / evaluations, per process | 133 / 18 044 | 426 / 20 201 | 157 / 5 688 |
|
|
207
|
+
| `\|Δ ln L\|` vs the code, median / max | — | 0.015 / 0.10 | 0.003 / 0.032 |
|
|
208
|
+
| speed-up | — | 8.6× | 8.3× |
|
|
209
|
+
|
|
210
|
+
f(R) runs through MGCAMB, roughly ten times slower than CAMB per point.
|
|
211
|
+
The CPL run was not re-checked against CAMB point by point; the analysis
|
|
212
|
+
below does that for CPL with more data.
|
|
213
|
+
|
|
214
|
+
## Analyses
|
|
215
|
+
|
|
216
|
+
[`analysis/cpl_vs_lcdm/`](https://github.com/salihyesil59/fastcmb/tree/main/analysis/cpl_vs_lcdm) fits ΛCDM and CPL
|
|
217
|
+
(`w0`, `wa`) with CosmoFit to the full Planck 2018 likelihoods (plik_lite,
|
|
218
|
+
lowE, lensing), DESI DR2 BAO, cosmic chronometers and, in turn, Pantheon+,
|
|
219
|
+
Union3 and DES-SN5YR: six runs to `R - 1 < 0.01`, all six ΛCDM parameters
|
|
220
|
+
sampled. The notebook compares the models (Δχ², AIC, BIC), shows which data
|
|
221
|
+
carry the signal, and checks the emulator against CAMB.
|
|
222
|
+
|
|
223
|
+
| | Pantheon+ | Union3 | DES-SN5YR (Dovekie) |
|
|
224
|
+
|---|---|---|---|
|
|
225
|
+
| `w0` | −0.843 ± 0.054 | −0.677 ± 0.090 | −0.809 ± 0.056 |
|
|
226
|
+
| `wa` | −0.59 ± 0.20 | −1.04 ± 0.30 | −0.70 ± 0.22 |
|
|
227
|
+
| preference for CPL | 2.6σ | 3.5σ | 3.1σ |
|
|
228
|
+
|
|
229
|
+
Each run took 15–52 min. CAMB ran at 272 (ΛCDM) and 642 (CPL) points
|
|
230
|
+
over all six runs, and `|Δ ln L|` against CAMB is at most 0.015.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "fastcmb"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "An online emulator of Boltzmann codes: CMB spectra in milliseconds, with the code as the fallback."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [{ name = "Salih Yeşil" }]
|
|
14
|
+
keywords = ["cosmology", "CMB", "emulator", "Gaussian process", "CAMB", "MCMC", "Boltzmann code"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
|
+
"Intended Audience :: Science/Research",
|
|
18
|
+
"Operating System :: OS Independent",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Topic :: Scientific/Engineering :: Astronomy",
|
|
24
|
+
"Topic :: Scientific/Engineering :: Physics",
|
|
25
|
+
]
|
|
26
|
+
dependencies = [
|
|
27
|
+
"numpy>=2.0",
|
|
28
|
+
"scipy",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
Homepage = "https://github.com/salihyesil59/fastcmb"
|
|
33
|
+
Source = "https://github.com/salihyesil59/fastcmb"
|
|
34
|
+
Issues = "https://github.com/salihyesil59/fastcmb/issues"
|
|
35
|
+
|
|
36
|
+
[project.optional-dependencies]
|
|
37
|
+
camb = ["camb>=1.5"]
|
|
38
|
+
cobaya = ["cobaya>=3.5", "camb>=1.5"]
|
|
39
|
+
dev = ["pytest", "camb>=1.5"]
|
|
40
|
+
|
|
41
|
+
[tool.setuptools.dynamic]
|
|
42
|
+
version = { attr = "fastcmb.__version__" }
|
|
43
|
+
|
|
44
|
+
[tool.setuptools.packages.find]
|
|
45
|
+
where = ["src"]
|
|
46
|
+
|
|
47
|
+
[tool.pytest.ini_options]
|
|
48
|
+
testpaths = ["tests"]
|
fastcmb-0.3.0/setup.cfg
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""
|
|
2
|
+
fastcmb: an online emulator of Boltzmann codes for CMB analyses.
|
|
3
|
+
|
|
4
|
+
:class:`CMBEmulator` wraps a Boltzmann code -- an *oracle*, such as
|
|
5
|
+
:class:`CAMBOracle` -- and answers with a Gaussian-process prediction
|
|
6
|
+
wherever its error, in units of the log-likelihood, is below a
|
|
7
|
+
tolerance; elsewhere the code runs, and the point is learned. It needs
|
|
8
|
+
only numpy and scipy, and fits in any analysis code:
|
|
9
|
+
|
|
10
|
+
* CosmoFit: ``theory: {background: ..., fastcmb: ...}`` in place of
|
|
11
|
+
``camb`` (built into CosmoFit, with ``fastcmb`` installed);
|
|
12
|
+
* cobaya: the theory ``fastcmb.cobaya.FastCAMB`` in place of ``camb``;
|
|
13
|
+
* anything else: call a :class:`CMBEmulator`.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from .camb_oracle import CAMBOracle
|
|
17
|
+
from .emulator import CMBEmulator, Result
|
|
18
|
+
from .gp import GP
|
|
19
|
+
from .online import OnlineEmulator
|
|
20
|
+
|
|
21
|
+
__all__ = ["GP", "CAMBOracle", "CMBEmulator", "OnlineEmulator", "Result", "__version__"]
|
|
22
|
+
|
|
23
|
+
__version__ = "0.3.0"
|