Skip to content

Multi-spectrum bandpower window function - #53

Merged
ggalloni merged 2 commits into
masterfrom
feat/multi-spectrum-bandpower-window
Jul 20, 2026
Merged

Multi-spectrum bandpower window function#53
ggalloni merged 2 commits into
masterfrom
feat/multi-spectrum-bandpower-window

Conversation

@ggalloni

Copy link
Copy Markdown
Owner

What changed

Lifts the single-spectrum restriction on Fisher.get_bandpower_window_function so multi-spectrum (TEB/TQU) runs can convolve per-ℓ theory into expected bandpowers. Both the binned Fisher and the per-ℓ Fisher are block-ordered spectrum-major, so the sum-over-ℓ operator Q becomes block-diagonal (np.kron with the identity) — bit-identical to the previous Q when nspectra == 1. This is the prerequisite for the bandpower-shape / effective-ell work (ADR-0019), whose effective multipoles differ per spectrum and therefore cannot be served for TEB without it.

Public surface

  • Fisher.get_bandpower_window_function() no longer raises NotImplementedError for nspectra > 1; returns a window of shape (nspectra·n_bins, nspectra·n_ell) (was (n_bins, n_ell), still that for a single spectrum). Rows/cols are block-ordered spectrum-major, matching get_bandpower_slices.
  • Spectra.convolve_theory_for_inference() now accepts a flat (nspectra·n_ell,) per-ℓ array or a label-keyed dict {"TT": …, "EE": …} of per-ℓ theory. Single-spectrum output is numerically unchanged.

Checklist

  • docs/source/changelog.rst updated under Unreleased (Added).
  • ADR added or amended — governed by the already-merged ADR-0019 (PR docs: ADR-0019 — the bandpower shape function lives in the binning operator #52); no new ADR needed.
  • CONTEXT.md updated if this introduces or sharpens a domain term — no new term.
  • Doc-drift sweep done — tutorial basic_usage.rst no longer calls the method single-spectrum-only; sphinx build clean (no new warnings).
  • Tests pass per package (uv run pytest src/cosmoforge.qube/tests/ -s → 178 passed, 8 skipped).

Lift the single-spectrum guard on Fisher.get_bandpower_window_function so
TEB/TQU runs can convolve per-ℓ theory into expected bandpowers. Both the
binned Fisher and the per-ℓ Fisher are block-ordered spectrum-major, so Q
becomes block-diagonal (np.kron with the identity) and is bit-identical to
the previous Q when nspectra == 1. The window is now
(nspectra·n_bins, nspectra·n_ell).

Spectra.convolve_theory_for_inference accepts either a flat spectrum-major
per-ℓ array or a label-keyed dict; the spectrum-label ordering is factored
into a shared _spectrum_labels() helper reused by _make_convolve_theory.

Prerequisite for the bandpower-shape / effective-ell work (ADR-0019), whose
effective multipoles differ per spectrum and so cannot be served for TEB
without this.

Closes #49
Copilot AI review requested due to automatic review settings July 20, 2026 18:37

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends CosmoForge’s QML inference utilities to support multi-spectrum (e.g., TEB/TQU) workflows when mapping per-ℓ theory to expected binned bandpowers. It removes the prior single-spectrum limitation by making the bandpower window function and the per-ℓ theory convolution operate on spectrum-major, block-ordered flattened vectors (or a label-keyed dict), which is a prerequisite for ADR-0019 follow-on work (effective multipoles per spectrum).

Changes:

  • Generalizes Fisher.get_bandpower_window_function() to return a (nspectra·n_bins, nspectra·n_ell) window for nspectra > 1 using a block-diagonal sum-over-ℓ operator.
  • Extends Spectra.convolve_theory_for_inference() to accept either a flat (nspectra·n_ell,) spectrum-major vector or a label-keyed dict of per-ℓ theory arrays.
  • Adds multi-spectrum tests validating window shape/linearity/normalization and dict-vs-flat convolution equivalence, and updates docs + changelog accordingly.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/cosmoforge.qube/qube/fisher.py Lifts the single-spectrum guard and builds a block-diagonal Q so the bandpower window supports nspectra > 1.
src/cosmoforge.qube/qube/spectra.py Adds spectrum-label resolution helper and extends per-ℓ theory convolution to accept multi-spectrum flat vectors or label-keyed dicts.
src/cosmoforge.qube/tests/test_binning.py Adds multi-spectrum unit tests for the bandpower window function and dict-input convolution path.
docs/source/tutorials/basic_usage.rst Updates tutorial guidance to reflect multi-spectrum support in convolve_theory_for_inference().
docs/source/changelog.rst Adds an Unreleased changelog entry describing the new multi-spectrum window + theory-convolution inputs.

Comment on lines +1683 to +1684
cl_theory : np.ndarray or dict
Per-ℓ theory C_ℓ. Accepted formats:

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 79580ce — parameter annotated np.ndarray | dict.

Comment on lines +1753 to +1758
def _to_perell(arr: np.ndarray, what: str) -> np.ndarray:
"""Trim one per-ℓ array to ℓ=lmin..lmax (accepts n_ell or lmax+1)."""
if arr.size == n_ell:
return arr
if arr.size >= lmax + 1:
return arr[lmin : lmax + 1]

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 79580ce — added an ndim != 1 guard in _to_perell so a size-matching 2D entry (e.g. (n_ell, 1)) raises early; covered by test_convolve_theory_dict_rejects_2d_entry.

@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.66667% with 3 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (master@16b19b0). Learn more about missing BASE report.
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
src/cosmoforge.qube/qube/spectra.py 90.90% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##             master      #53   +/-   ##
=========================================
  Coverage          ?   92.14%           
=========================================
  Files             ?        5           
  Lines             ?     1082           
  Branches          ?        0           
=========================================
  Hits              ?      997           
  Misses            ?       85           
  Partials          ?        0           
Flag Coverage Δ
mpi 92.14% <91.66%> (?)
nompi 86.78% <91.66%> (?)
qube 92.14% <91.66%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/cosmoforge.qube/qube/fisher.py 96.61% <100.00%> (ø)
src/cosmoforge.qube/qube/spectra.py 87.43% <90.90%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Annotate the parameter as np.ndarray | dict to match the accepted forms,
and reject non-1D per-ℓ arrays inside the dict path: a (n_ell, 1) entry
whose size matches would previously slip past the size check and corrupt
the spectrum-major concatenation. The ndim guard lives in _to_perell so
every array routed through it is covered.
@ggalloni
ggalloni merged commit 334aad4 into master Jul 20, 2026
19 checks passed
@ggalloni
ggalloni deleted the feat/multi-spectrum-bandpower-window branch July 20, 2026 18:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants