Skip to main content

QUBE logo

PyPI Python Documentation Parallelization QML Method

📚 QUBE Documentation | Fisher Analysis API | Spectra API | Main Documentation

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.

Overview

QUBE provides two main analysis methods:

  • Fisher Matrix Analysis: Fast parameter forecasting and covariance estimation
  • QML Power Spectrum Estimation: Optimal power spectrum recovery from noisy data

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.

Key Features

Fisher Matrix Analysis

  • Fast parameter forecasting
  • Covariance matrix computation
  • Support for multiple field types (T, E, B)
  • Cross-correlation analysis
  • Instrumental noise modeling

QML Power Spectrum Estimation

  • Optimal power spectrum estimation
  • Noise bias correction
  • Cross-correlation support
  • Three output modes: deconvolved, decorrelated, convolved
  • Multipole binning for bandpower estimation

Multipole Binning

  • Native binned QML: Fisher and q-vector computed directly in bin space
  • Configurable via Python API (Bins class) or YAML (delta_ell, bin_lmins/bin_lmaxs)
  • Beam smoothing absorbed into binned derivatives for exact normalization
  • Default delta_ell=1 recovers standard per-multipole estimation
  • Custom non-uniform bins supported

Technical Features

  • MPI Parallelization: Distributed computation across multiple processes
  • Computation Basis: Harmonic and pixel basis with optional m-block compression and automatic field block-diagonal optimization
  • Instrumental Effects: Beam convolution and pixel window functions
  • Flexible Configuration: YAML-based parameter specification

Installation

Install from PyPI

pip install qube-qml

qube-qml is the distribution name on PyPI; the package is imported as qube.

To enable MPI parallelism (requires a system MPI implementation):

pip install qube-qml[mpi]

Or install the full CosmoForge umbrella (cosmocore + qube-qml + picslike):

pip install cosmoforge

Install from source

git clone https://github.com/ggalloni/CosmoForge.git
cd CosmoForge
uv sync --all-packages --all-extras --dev

Documentation

For detailed API documentation and examples:

Quick Start

Fisher Matrix Analysis

from qube import Fisher

# Initialize Fisher analysis
fisher = Fisher("config/fisher_params.yaml")

# Run Fisher computation
fisher.run()

# Get results
fisher_matrix = fisher.get_fisher_matrix()
covariance = fisher.get_covariance_matrix()

QML Power Spectrum Estimation

from qube import Spectra

# Initialize QML analysis
qml = Spectra("config/qml_params.yaml")

# Run QML computation
qml.run()

# Get power spectra
power_spectra = qml.get_power_spectra()
noise_bias = qml.get_noise_bias()

Reusing Fisher for QML

from qube import Fisher, Spectra

# Compute Fisher matrix once
fisher = Fisher("config/params.yaml")
fisher.run()

# Reuse for QML (more efficient)
qml = Spectra("config/params.yaml", fisher=fisher)
qml.run()

Binned Power Spectrum Estimation

from cosmocore import Bins
from qube import Fisher, Spectra

# Uniform bins of width 5
bins = Bins.fromdeltal(2, lmax, delta_ell=5)

# Or custom non-uniform bins (both bounds inclusive)
bins = Bins(lmins=[2, 10, 30], lmaxs=[9, 29, 64])

fisher = Fisher("config/params.yaml")
fisher.set_binning(bins)
fisher.run()

# Spectra inherits bins from Fisher
qml = Spectra("config/params.yaml", fisher=fisher)
qml.run()

cl_binned = qml.get_power_spectra()      # (nsims, nbins)
ell_eff = qml.get_effective_ells()        # inverse-variance window centroid
# ell_eff = qml.get_effective_ells(use_midpoint=True)  # cheap bin midpoint
errors = qml.get_error_bars()             # (nbins,)

In-Memory Inputs (no files)

Every input can be handed over as an array instead of a file path — for callers that already hold their maps, mask and noise covariance and should not have to round-trip them through disk. The config still supplies the scalars; an injected object wins over the corresponding path.

from qube import Fisher, Spectra

fisher = Fisher(
    params,
    mask=mask,             # (npix, nfields)
    noise_cov1=noise_cov,  # reduced (n_active, n_active)
    cls_data=cls,          # {label: C_ell}, physical C_ell
    fiducial_cls=cls,
    beam=beam,             # (>=3, lmax+1) T/E/B window functions
)
fisher.run()

# maps are a Spectra seam — Fisher never reads them
qml = Spectra(params, fisher=fisher, maps1=maps)
qml.run()
power_spectra = qml.get_power_spectra(mode="deconvolved")

Leave the out* paths unset and the run touches no disk at all.

Kwargs: mask, noise_cov1/noise_cov2, maps1/maps2, cls_data, fiducial_cls, beam. Each injected object is exactly what the corresponding reader would have returned. Two contracts are asymmetric — deliberately, because each mirrors what its reader does:

kwarg contract
noise_cov1 reduced to active pixels
maps1 reduced to active pixels

noise_cov1/maps1 are reduced to the active (unmasked) pixels and ordered by the active-pixel index. You do not need a Fisher to learn that ordering — it is a pure function of the mask:

from cosmocore import active_pixel_index

index = active_pixel_index(mask)
maps = maps_full.reshape(nfields * npix, nsims)[index]
cov = cov_full[np.ix_(index, index)]

Worked example: notebooks/in_memory_inputs.ipynb, which drives the file adapter and the injection adapter over the same data and asserts they produce identical spectra. Rationale: ADR-0017.

Configuration

QUBE uses YAML configuration files:

Basic Configuration

# Data specification
nside: 32
lmax: 64
fields: "TEB"  # or "TQU"

# Input files
maskfile: "data/mask.fits"
inputclfile: "data/fiducial_cls.txt"
covmatfile1: "data/noise_cov1.bin"
covmatfile2: "data/noise_cov2.bin"  # for cross-correlation

# Analysis parameters
do_cross: false
remove_noise_bias: true

QML-Specific Parameters

# QML simulation parameters
nsims: 100
ssim: 0
zerofill: false

# Input maps
inputmapfile1: "data/maps1_{:04d}.fits"
inputmapfile2: "data/maps2_{:04d}.fits"
endname1: ".fits"
endname2: ".fits"

# Output files
outfisherfile: "output/fisher.dat"
outcovmatfile: "output/covariance.dat"
outerrfile: "output/errors.dat"

Binning Configuration

# Uniform bins (simplest)
delta_ell: 5

# Or custom bins (both bounds inclusive)
bin_lmins: [2, 10, 30]
bin_lmaxs: [9, 29, 64]

Beam Configuration

# Beam parameters
smoothing_type: file  # none, gaussian, cosine_legacy, cosine_npipe, file
fwhmarcmin: 5.0  # gaussian only
beam_file: "data/beam.fits"  # read only by smoothing_type: file
apply_pixwin: true

MPI Usage

Run analyses in parallel:

# Fisher analysis
mpirun -n 4 python -c "
from qube import Fisher
fisher = Fisher('config.yaml')
fisher.run()
"

# QML analysis
mpirun -n 8 python -c "
from qube import Spectra
qml = Spectra('config.yaml')
qml.run()
"

Analysis Pipeline

Fisher Matrix Pipeline

  1. Setup: Read parameters and initialize fields
  2. Geometry: Compute pixel pointing vectors
  3. Signal Matrix: Compute theoretical signal covariance
  4. Derivatives: Compute signal matrix derivatives
  5. Fisher Matrix: Assemble Fisher information matrix
  6. Inversion: Compute parameter covariance matrix

QML Pipeline

  1. Setup: Initialize fields and read Fisher matrix
  2. Maps: Read input simulation maps
  3. Renormalization: Apply Fisher matrix normalization
  4. E-operator: Compute quadratic estimator operators
  5. Estimation: Apply operators to data maps
  6. Reduction: Combine results across MPI processes
  7. Final Spectra: Apply Fisher matrix to get power spectra

API Reference

Fisher Class

class Fisher(Core):
    """Fisher matrix analysis implementation."""
    
    def run(self):
        """Execute complete Fisher analysis."""
        
    def get_fisher_matrix(self):
        """Get computed Fisher matrix."""
        
    def get_covariance_matrix(self):
        """Get parameter covariance matrix."""
        
    def write_outputs(self):
        """Write results to files."""

Spectra Class

class Spectra(Core):
    """QML power spectrum estimation implementation."""
    
    def run(self):
        """Execute complete QML analysis."""
        
    def get_power_spectra(self):
        """Get estimated power spectra."""
        
    def get_noise_bias(self):
        """Get noise bias estimates."""
        
    def compute_qml_spectra(self):
        """Main QML computation loop."""

Output Files

Persistence is opt-in (ADR-0015): each file below is written only when its corresponding out* path is set in the config; with the path unset (the default) nothing is written to disk.

Fisher Analysis Outputs

  • fisher.dat: Fisher information matrix
  • covariance.dat: Parameter covariance matrix
  • errors.dat: Parameter uncertainties
  • geometry.dat: Pixel geometry information

QML Analysis Outputs

  • spectra.dat: Estimated power spectra
  • noise_bias.dat: Noise bias estimates
  • covariance.dat: Spectrum covariance matrix

Performance Optimization

Memory Management

  • Efficient covariance matrix handling
  • In-place operations where possible
  • Memory-mapped file I/O for large datasets

Computational Efficiency

  • Numba JIT compilation for critical loops
  • Optimized BLAS/LAPACK operations
  • MPI load balancing

Scaling

Typical performance scaling:

Processes    Speed-up (Fisher)    Speed-up (QML)
1           1.0x                 1.0x
2           1.8x                 1.9x
4           3.5x                 3.7x
8           6.8x                 7.2x
16          12.5x                14.1x

Testing

Run the test suite (from the repository root):

uv run pytest src/cosmoforge.qube/tests/ -s

Specific tests:

uv run pytest src/cosmoforge.qube/tests/test_fisher.py -s
uv run pytest src/cosmoforge.qube/tests/test_spectra.py -s
uv run pytest src/cosmoforge.qube/tests/test_signal_covmat.py -s

Examples

Mock Data Generation

from qube.scripts.generate_mock_data import generate_cmb_maps

# Generate mock CMB maps
generate_cmb_maps(
    nside=32,
    lmax=64,
    nsims=100,
    output_dir="mock_data/",
    fiducial_cls="fiducial_cls.txt"
)

Parameter Forecasting

from qube import Fisher
import numpy as np

# Run Fisher analysis
fisher = Fisher("forecast_config.yaml")
fisher.run()

# Get parameter uncertainties
cov_matrix = fisher.get_covariance_matrix()
param_errors = np.sqrt(np.diag(cov_matrix))

print(f"Parameter uncertainties: {param_errors}")

Advanced Usage

Custom Analysis

from qube import Spectra
from cosmocore import FieldCollection

# Custom field setup
fields = create_custom_fields()
collection = FieldCollection(params, fields)

# Custom analysis
qml = Spectra(params, fisher=None)
qml.collection = collection
qml.run()

Cross-Validation

# Split data for cross-validation
qml1 = Spectra("config_half1.yaml")
qml2 = Spectra("config_half2.yaml")

qml1.run()
qml2.run()

# Compare results
spectra1 = qml1.get_power_spectra()
spectra2 = qml2.get_power_spectra()

Troubleshooting

Common Issues

  1. Memory errors: Reduce nside or use more MPI processes
  2. Convergence issues: Check mask coverage and noise levels
  3. MPI hanging: Ensure consistent configuration across processes

Debug Mode

Enable detailed logging:

feedback: 4  # Maximum verbosity

Performance Profiling

import cProfile

def run_analysis():
    qml = Spectra("config.yaml")
    qml.run()

cProfile.run('run_analysis()', 'profile_output.prof')

Contributing

See the main CosmoForge README for contribution guidelines.

Citation

If you use QUBE (as part of CosmoForge) in your research, please cite:

Galloni, G. & Pagano, L., CosmoForge. I. A unified framework for quadratic maximum likelihood power spectrum estimation and pixel-based likelihood analysis, A&A (2026), doi:10.1051/0004-6361/202661478, arXiv:2605.21149.

If you apply a pixel-space filter (pixel_filter= or cosmocore.filters), please also cite:

Galloni, G., CosmoForge. II. An exact treatment of arbitrary linear filters in quadratic maximum-likelihood power spectrum estimation, arXiv:2610.18012 (2026).

BibTeX entries for both are on the citation page of the documentation.

References

  • Quadratic Maximum Likelihood: Tegmark (1997), Phys. Rev. D 55, 5895
  • Bandpower estimation: Bond, Jaffe & Knox (1998), Phys. Rev. D 57, 2117
  • Binned QML: Bilbao-Ahedo et al. (2021), arXiv:2104.08528

Metadata

Release files for qube-qml 1.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for qube-qml 1.3.0
File Size Uploaded Provenance Actions
qube_qml-1.3.0.tar.gz 52.3 kB With provenance Details for qube_qml-1.3.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for qube-qml 1.3.0
File Interpreter ABI Platform Actions
qube_qml-1.3.0-py3-none-any.whl Python 3 none any Details for qube_qml-1.3.0-py3-none-any.whl

Total release size: 107.3 kB

Release files / qube_qml-1.3.0.tar.gz

Download URL qube_qml-1.3.0.tar.gz
Size 52.3 kB
Tags Source
SHA-256 checksum
How to use checksums
ef6b9b6f4fd4acd95418b3a6adae0618a33cc531c26d425e2c8038b7e4b0999b
BLAKE2b-256 checksum
How to use checksums
10162283808d50da7a01820fe63b673c4ad250c3eb57c2e9d6836d909f4d57ee
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.

Transparency log

Release files / qube_qml-1.3.0-py3-none-any.whl

Download URL qube_qml-1.3.0-py3-none-any.whl
Size 55.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7bf2eb52e0efbee73adb33b7b64112be63de71d711edffa53ec8da81b10e8673
BLAKE2b-256 checksum
How to use checksums
68c751ee32058f5e71906914a0045150c67cb4835db266bbbc30fd6060623612
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.

Transparency log

Security for qube-qml 1.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for qube_qml-1.3.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page