qube-qml 1.0.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.
@@ -0,0 +1,70 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+ htmlcov/
9
+ coverage.xml
10
+ src/graphify-out/
11
+
12
+ # Virtual environments
13
+ .venv
14
+ *inputs/
15
+ *outputs/
16
+ *logs/
17
+ *slurms/
18
+ *plots/
19
+ .coverage
20
+
21
+ # Ignore maps/templates except in test directories
22
+ *maps/
23
+ *templates/
24
+ !**/tests/data/**/maps/
25
+ !**/tests/data/**/templates/
26
+
27
+ # Test intermediate artifacts (regenerated during test runs)
28
+ **/tests/data/**/cov_matrix.dat
29
+ **/tests/data/**/errors.dat
30
+ **/tests/data/**/fisher.dat
31
+ **/tests/data/**/geometry.dat
32
+ **/tests/data/**/invCOV*.bin
33
+ **/tests/data/**/reduced_NCVM*.bin
34
+ # Exception: keep Fortran reference files for validation tests
35
+ !**/tests/data/**/fortran_reference/**
36
+
37
+ run_*.py
38
+ /src/*/.library
39
+ /.claude
40
+ /papers
41
+ /sync_to_cluster.sh
42
+
43
+ # Fortran reference/build directories
44
+ /src/*/.fortran
45
+
46
+ # Generated output files in test data
47
+ **/tests/data/**/output_*.bin
48
+ **/tests/data/**/output_*.dat
49
+ **/tests/data/**/*.png
50
+ *.png
51
+ !logos/*.png
52
+ !docs/source/_static/*.png
53
+ !src/**/logos/*.png
54
+ /src/cosmoforge.picslike/tests/data/nside8/B/fortran_reference/theory_spectra
55
+ /src/cosmoforge.qube/benchmarks/sims/bench_T*
56
+ /src/cosmoforge.qube/benchmarks/sims/bench_QU*
57
+ /src/cosmoforge.qube/benchmarks/sims/bench_mpi*
58
+
59
+ # Heavy benchmark fixtures (kept locally, synced to cluster manually)
60
+ /src/cosmoforge.qube/benchmarks/data/
61
+
62
+ src/cosmoforge.qube/scripts/qml_vs_pcl_results.json
63
+ /src/cosmoforge.qube/benchmarks/results
64
+ /src/cosmoforge.qube/benchmarks/sims
65
+ *.json
66
+
67
+ # Local git worktrees
68
+ .worktrees/
69
+ /src/cosmoforge.qube/benchmarks/results
70
+ /src/cosmoforge.qube/benchmarks/sbatch
@@ -0,0 +1,503 @@
1
+ Metadata-Version: 2.4
2
+ Name: qube-qml
3
+ Version: 1.0.0
4
+ Summary: QUBE: Quadratic maximum likelihood UnBiased Estimator
5
+ Author-email: Giacomo Galloni <giacomo.galloni@unife.it>
6
+ Classifier: Development Status :: 4 - Beta
7
+ Classifier: Intended Audience :: Science/Research
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: MacOS
10
+ Classifier: Operating System :: POSIX :: Linux
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Topic :: Scientific/Engineering :: Astronomy
16
+ Classifier: Topic :: Scientific/Engineering :: Physics
17
+ Requires-Python: <3.14,>=3.11
18
+ Requires-Dist: cosmocore
19
+ Requires-Dist: tqdm>=4.67.1
20
+ Provides-Extra: mpi
21
+ Requires-Dist: cosmocore[mpi]; extra == 'mpi'
22
+ Provides-Extra: pcl
23
+ Requires-Dist: pymaster>=2.6; extra == 'pcl'
24
+ Description-Content-Type: text/markdown
25
+
26
+ <p align="center">
27
+ <img src="https://raw.githubusercontent.com/ggalloni/CosmoForge/master/src/cosmoforge.qube/logos/QUBE_logo.png" alt="QUBE logo" width="40%"/>
28
+ </p>
29
+
30
+ [![PyPI](https://img.shields.io/pypi/v/qube-qml?include_prereleases)](https://pypi.org/project/qube-qml/)
31
+ [![Python](https://img.shields.io/pypi/pyversions/qube-qml)](https://pypi.org/project/qube-qml/)
32
+ [![Documentation](https://img.shields.io/badge/docs-qube-blue.svg)](https://cosmoforge.readthedocs.io/en/latest/api/qube.html)
33
+ [![Parallelization](https://img.shields.io/badge/MPI-parallel-orange.svg)](https://www.mpi-forum.org/)
34
+ [![QML Method](https://img.shields.io/badge/method-QML-red.svg)](https://en.wikipedia.org/wiki/Maximum_likelihood_estimation)
35
+
36
+ > **📚 [QUBE Documentation](https://cosmoforge.readthedocs.io/en/latest/api/qube.html) | [Fisher Analysis API](https://cosmoforge.readthedocs.io/en/latest/api/qube/fisher.html) | [Spectra API](https://cosmoforge.readthedocs.io/en/latest/api/qube/spectra.html) | [Main Documentation](https://cosmoforge.readthedocs.io/en/latest/)**
37
+
38
+ QUBE: Quadratic maximum likelihood UnBiased Estimator is the analysis engine of CosmoForge, implementing Fisher matrix analysis and Quadratic Maximum Likelihood (QML) power spectrum estimation for any spin-0 or spin-2 field on the sphere. Applications include CMB temperature and polarization, galaxy surveys, 21 cm intensity mapping, and any other signal that can be described by angular power spectra.
39
+
40
+ ## Overview
41
+
42
+ QUBE provides two main analysis methods:
43
+
44
+ - **Fisher Matrix Analysis**: Fast parameter forecasting and covariance estimation
45
+ - **QML Power Spectrum Estimation**: Optimal power spectrum recovery from noisy data
46
+
47
+ Both methods support MPI parallelization for large-scale analyses and can handle spin-0 and spin-2 data (e.g. temperature and polarization) with realistic instrumental effects.
48
+
49
+ ## Key Features
50
+
51
+ ### Fisher Matrix Analysis
52
+
53
+ - Fast parameter forecasting
54
+ - Covariance matrix computation
55
+ - Support for multiple field types (T, E, B)
56
+ - Cross-correlation analysis
57
+ - Instrumental noise modeling
58
+
59
+ ### QML Power Spectrum Estimation
60
+
61
+ - Optimal power spectrum estimation
62
+ - Noise bias correction
63
+ - Cross-correlation support
64
+ - Three output modes: deconvolved, decorrelated, convolved
65
+ - Multipole binning for bandpower estimation
66
+
67
+ ### Multipole Binning
68
+
69
+ - Native binned QML: Fisher and q-vector computed directly in bin space
70
+ - Configurable via Python API (`Bins` class) or YAML (`delta_ell`, `bin_lmins`/`bin_lmaxs`)
71
+ - Beam smoothing absorbed into binned derivatives for exact normalization
72
+ - Default `delta_ell=1` recovers standard per-multipole estimation
73
+ - Custom non-uniform bins supported
74
+
75
+ ### Technical Features
76
+
77
+ - **MPI Parallelization**: Distributed computation across multiple processes
78
+ - **Computation Basis**: Harmonic and pixel basis with optional m-block compression and automatic field block-diagonal optimization
79
+ - **Instrumental Effects**: Beam convolution and pixel window functions
80
+ - **Flexible Configuration**: YAML-based parameter specification
81
+
82
+ ## Installation
83
+
84
+ QUBE is part of CosmoForge and installs automatically:
85
+
86
+ ```bash
87
+ pip install -e /path/to/CosmoForge
88
+ ```
89
+
90
+ For MPI support:
91
+
92
+ ```bash
93
+ pip install mpi4py
94
+ ```
95
+
96
+ ## Documentation
97
+
98
+ For detailed API documentation and examples:
99
+
100
+ - **[Fisher Analysis](https://cosmoforge.readthedocs.io/en/latest/api/qube/fisher.html)** - Fisher matrix computation and parameter forecasting
101
+ - **[Spectra Analysis](https://cosmoforge.readthedocs.io/en/latest/api/qube/spectra.html)** - QML power spectrum estimation
102
+ - **[Main Scripts](https://cosmoforge.readthedocs.io/en/latest/api/qube/main_fisher.html)** - Command-line interfaces for analysis
103
+ - **[Mock Data Generation](https://cosmoforge.readthedocs.io/en/latest/api/qube/produce_mock_inputs.html)** - Mock data generation utilities
104
+
105
+ ## Quick Start
106
+
107
+ ### Fisher Matrix Analysis
108
+
109
+ ```python
110
+ from qube import Fisher
111
+
112
+ # Initialize Fisher analysis
113
+ fisher = Fisher("config/fisher_params.yaml")
114
+
115
+ # Run Fisher computation
116
+ fisher.run()
117
+
118
+ # Get results
119
+ fisher_matrix = fisher.get_fisher_matrix()
120
+ covariance = fisher.get_covariance_matrix()
121
+ ```
122
+
123
+ ### QML Power Spectrum Estimation
124
+
125
+ ```python
126
+ from qube import Spectra
127
+
128
+ # Initialize QML analysis
129
+ qml = Spectra("config/qml_params.yaml")
130
+
131
+ # Run QML computation
132
+ qml.run()
133
+
134
+ # Get power spectra
135
+ power_spectra = qml.get_power_spectra()
136
+ noise_bias = qml.get_noise_bias()
137
+ ```
138
+
139
+ ### Reusing Fisher for QML
140
+
141
+ ```python
142
+ from qube import Fisher, Spectra
143
+
144
+ # Compute Fisher matrix once
145
+ fisher = Fisher("config/params.yaml")
146
+ fisher.run()
147
+
148
+ # Reuse for QML (more efficient)
149
+ qml = Spectra("config/params.yaml", fisher=fisher)
150
+ qml.run()
151
+ ```
152
+
153
+ ### Binned Power Spectrum Estimation
154
+
155
+ ```python
156
+ from cosmocore import Bins
157
+ from qube import Fisher, Spectra
158
+
159
+ # Uniform bins of width 5
160
+ bins = Bins.fromdeltal(2, lmax, delta_ell=5)
161
+
162
+ # Or custom non-uniform bins (both bounds inclusive)
163
+ bins = Bins(lmins=[2, 10, 30], lmaxs=[9, 29, 64])
164
+
165
+ fisher = Fisher("config/params.yaml")
166
+ fisher.set_binning(bins)
167
+ fisher.run()
168
+
169
+ # Spectra inherits bins from Fisher
170
+ qml = Spectra("config/params.yaml", fisher=fisher)
171
+ qml.run()
172
+
173
+ cl_binned = qml.get_power_spectra() # (nsims, nbins)
174
+ ell_eff = qml.get_effective_ells() # bin midpoints
175
+ errors = qml.get_error_bars() # (nbins,)
176
+ ```
177
+
178
+ ## Configuration
179
+
180
+ QUBE uses YAML configuration files:
181
+
182
+ ### Basic Configuration
183
+
184
+ ```yaml
185
+ # Data specification
186
+ nside: 32
187
+ lmax: 64
188
+ fields: "TEB" # or "TQU"
189
+
190
+ # Input files
191
+ maskfile: "data/mask.fits"
192
+ inputclfile: "data/fiducial_cls.txt"
193
+ covmatfile1: "data/noise_cov1.bin"
194
+ covmatfile2: "data/noise_cov2.bin" # for cross-correlation
195
+
196
+ # Analysis parameters
197
+ do_cross: false
198
+ remove_noise_bias: true
199
+ calibration: 1.0
200
+ ```
201
+
202
+ ### QML-Specific Parameters
203
+
204
+ ```yaml
205
+ # QML simulation parameters
206
+ nsims: 100
207
+ ssim: 0
208
+ zerofill: false
209
+
210
+ # Input maps
211
+ inputmapfile1: "data/maps1_{:04d}.fits"
212
+ inputmapfile2: "data/maps2_{:04d}.fits"
213
+ endname1: ".fits"
214
+ endname2: ".fits"
215
+
216
+ # Output files
217
+ outfisherfile: "output/fisher.dat"
218
+ outcovmatfile: "output/covariance.dat"
219
+ outerrfile: "output/errors.dat"
220
+ ```
221
+
222
+ ### Binning Configuration
223
+
224
+ ```yaml
225
+ # Uniform bins (simplest)
226
+ delta_ell: 5
227
+
228
+ # Or custom bins (both bounds inclusive)
229
+ bin_lmins: [2, 10, 30]
230
+ bin_lmaxs: [9, 29, 64]
231
+ ```
232
+
233
+ ### Beam Configuration
234
+
235
+ ```yaml
236
+ # Beam parameters
237
+ smoothing_type: gaussian # none, gaussian, cosine_legacy, cosine_npipe, file
238
+ fwhmarcmin: 5.0
239
+ beam_file: "data/beam.fits"
240
+ apply_pixwin: true
241
+ smooth_pol: true
242
+ ```
243
+
244
+ ## MPI Usage
245
+
246
+ Run analyses in parallel:
247
+
248
+ ```bash
249
+ # Fisher analysis
250
+ mpirun -n 4 python -c "
251
+ from qube import Fisher
252
+ fisher = Fisher('config.yaml')
253
+ fisher.run()
254
+ "
255
+
256
+ # QML analysis
257
+ mpirun -n 8 python -c "
258
+ from qube import Spectra
259
+ qml = Spectra('config.yaml')
260
+ qml.run()
261
+ "
262
+ ```
263
+
264
+ ## Analysis Pipeline
265
+
266
+ ### Fisher Matrix Pipeline
267
+
268
+ 1. **Setup**: Read parameters and initialize fields
269
+ 2. **Geometry**: Compute pixel pointing vectors
270
+ 3. **Signal Matrix**: Compute theoretical signal covariance
271
+ 4. **Derivatives**: Compute signal matrix derivatives
272
+ 5. **Fisher Matrix**: Assemble Fisher information matrix
273
+ 6. **Inversion**: Compute parameter covariance matrix
274
+
275
+ ### QML Pipeline
276
+
277
+ 1. **Setup**: Initialize fields and read Fisher matrix
278
+ 2. **Maps**: Read input simulation maps
279
+ 3. **Renormalization**: Apply Fisher matrix normalization
280
+ 4. **E-operator**: Compute quadratic estimator operators
281
+ 5. **Estimation**: Apply operators to data maps
282
+ 6. **Reduction**: Combine results across MPI processes
283
+ 7. **Final Spectra**: Apply Fisher matrix to get power spectra
284
+
285
+ ## API Reference
286
+
287
+ ### Fisher Class
288
+
289
+ ```python
290
+ class Fisher(Core):
291
+ """Fisher matrix analysis implementation."""
292
+
293
+ def run(self):
294
+ """Execute complete Fisher analysis."""
295
+
296
+ def get_fisher_matrix(self):
297
+ """Get computed Fisher matrix."""
298
+
299
+ def get_covariance_matrix(self):
300
+ """Get parameter covariance matrix."""
301
+
302
+ def write_outputs(self):
303
+ """Write results to files."""
304
+ ```
305
+
306
+ ### Spectra Class
307
+
308
+ ```python
309
+ class Spectra(Core):
310
+ """QML power spectrum estimation implementation."""
311
+
312
+ def run(self):
313
+ """Execute complete QML analysis."""
314
+
315
+ def get_power_spectra(self):
316
+ """Get estimated power spectra."""
317
+
318
+ def get_noise_bias(self):
319
+ """Get noise bias estimates."""
320
+
321
+ def compute_qml_spectra(self):
322
+ """Main QML computation loop."""
323
+ ```
324
+
325
+ ## Output Files
326
+
327
+ ### Fisher Analysis Outputs
328
+
329
+ - `fisher.dat`: Fisher information matrix
330
+ - `covariance.dat`: Parameter covariance matrix
331
+ - `errors.dat`: Parameter uncertainties
332
+ - `geometry.dat`: Pixel geometry information
333
+
334
+ ### QML Analysis Outputs
335
+
336
+ - `spectra.dat`: Estimated power spectra
337
+ - `noise_bias.dat`: Noise bias estimates
338
+ - `covariance.dat`: Spectrum covariance matrix
339
+
340
+ ## Performance Optimization
341
+
342
+ ### Memory Management
343
+
344
+ - Efficient covariance matrix handling
345
+ - In-place operations where possible
346
+ - Memory-mapped file I/O for large datasets
347
+
348
+ ### Computational Efficiency
349
+
350
+ - Numba JIT compilation for critical loops
351
+ - Optimized BLAS/LAPACK operations
352
+ - MPI load balancing
353
+
354
+ ### Scaling
355
+
356
+ Typical performance scaling:
357
+
358
+ ```text
359
+ Processes Speed-up (Fisher) Speed-up (QML)
360
+ 1 1.0x 1.0x
361
+ 2 1.8x 1.9x
362
+ 4 3.5x 3.7x
363
+ 8 6.8x 7.2x
364
+ 16 12.5x 14.1x
365
+ ```
366
+
367
+ ## Testing
368
+
369
+ Run the test suite (from the repository root):
370
+
371
+ ```bash
372
+ uv run pytest src/cosmoforge.qube/tests/ -s
373
+ ```
374
+
375
+ Specific tests:
376
+
377
+ ```bash
378
+ uv run pytest src/cosmoforge.qube/tests/test_fisher.py -s
379
+ uv run pytest src/cosmoforge.qube/tests/test_spectra.py -s
380
+ uv run pytest src/cosmoforge.qube/tests/test_signal_covmat.py -s
381
+ ```
382
+
383
+ ## Examples
384
+
385
+ ### Mock Data Generation
386
+
387
+ ```python
388
+ from qube.scripts.generate_mock_data import generate_cmb_maps
389
+
390
+ # Generate mock CMB maps
391
+ generate_cmb_maps(
392
+ nside=32,
393
+ lmax=64,
394
+ nsims=100,
395
+ output_dir="mock_data/",
396
+ fiducial_cls="fiducial_cls.txt"
397
+ )
398
+ ```
399
+
400
+ ### Parameter Forecasting
401
+
402
+ ```python
403
+ from qube import Fisher
404
+ import numpy as np
405
+
406
+ # Run Fisher analysis
407
+ fisher = Fisher("forecast_config.yaml")
408
+ fisher.run()
409
+
410
+ # Get parameter uncertainties
411
+ cov_matrix = fisher.get_covariance_matrix()
412
+ param_errors = np.sqrt(np.diag(cov_matrix))
413
+
414
+ print(f"Parameter uncertainties: {param_errors}")
415
+ ```
416
+
417
+ ## Advanced Usage
418
+
419
+ ### Custom Analysis
420
+
421
+ ```python
422
+ from qube import Spectra
423
+ from cosmocore import FieldCollection
424
+
425
+ # Custom field setup
426
+ fields = create_custom_fields()
427
+ collection = FieldCollection(params, fields)
428
+
429
+ # Custom analysis
430
+ qml = Spectra(params_file, fisher=None)
431
+ qml.collection = collection
432
+ qml.run()
433
+ ```
434
+
435
+ ### Cross-Validation
436
+
437
+ ```python
438
+ # Split data for cross-validation
439
+ qml1 = Spectra("config_half1.yaml")
440
+ qml2 = Spectra("config_half2.yaml")
441
+
442
+ qml1.run()
443
+ qml2.run()
444
+
445
+ # Compare results
446
+ spectra1 = qml1.get_power_spectra()
447
+ spectra2 = qml2.get_power_spectra()
448
+ ```
449
+
450
+ ## Troubleshooting
451
+
452
+ ### Common Issues
453
+
454
+ 1. **Memory errors**: Reduce nside or use more MPI processes
455
+ 2. **Convergence issues**: Check mask coverage and noise levels
456
+ 3. **MPI hanging**: Ensure consistent configuration across processes
457
+
458
+ ### Debug Mode
459
+
460
+ Enable detailed logging:
461
+
462
+ ```yaml
463
+ feedback: 4 # Maximum verbosity
464
+ ```
465
+
466
+ ### Performance Profiling
467
+
468
+ ```python
469
+ import cProfile
470
+
471
+ def run_analysis():
472
+ qml = Spectra("config.yaml")
473
+ qml.run()
474
+
475
+ cProfile.run('run_analysis()', 'profile_output.prof')
476
+ ```
477
+
478
+ ## Contributing
479
+
480
+ See the main CosmoForge README for contribution guidelines.
481
+
482
+ ## Citation
483
+
484
+ If you use QUBE (as part of CosmoForge) in your research, please cite:
485
+
486
+ > Galloni, G. & Pagano, L., *CosmoForge I: A unified framework for QML power spectrum estimation and pixel-based likelihood analysis*, in preparation (2026).
487
+
488
+ ```bibtex
489
+ @article{GalloniPagano_CosmoForgeI,
490
+ author = {Galloni, G. and Pagano, L.},
491
+ title = {{CosmoForge I}: A unified framework for {QML} power spectrum estimation and pixel-based likelihood analysis},
492
+ year = {2026},
493
+ note = {in preparation}
494
+ }
495
+ ```
496
+
497
+ This entry will be updated with the arXiv identifier and journal reference once available.
498
+
499
+ ## References
500
+
501
+ - Quadratic Maximum Likelihood: Tegmark (1997), Phys. Rev. D 55, 5895
502
+ - Bandpower estimation: Bond, Jaffe & Knox (1998), Phys. Rev. D 57, 2117
503
+ - Binned QML: Bilbao-Ahedo et al. (2021), arXiv:2104.08528