Abstract base class for computation basis methods.
This class defines the interface for computation basis methods and provides
shared implementations for spherical harmonic evaluation and ell-to-mode
mapping.
Supports both single-field and multi-field configurations. For multi-field,
theta and phi are passed as tuples of arrays (one per component), and the
harmonic operator V is built as a block-diagonal matrix.
Parameters:
N (numpy.ndarray) – Noise covariance matrix of shape (n_pix_total, n_pix_total). The
basis takes ownership of this buffer; the in-place Cholesky factor
overwrites it during setup.
theta (numpy.ndarray or tuple of numpy.ndarray) – Colatitude angles for active pixels in radians. Single array for
single-field, tuple of arrays for multi-field.
phi (numpy.ndarray or tuple of numpy.ndarray) – Longitude angles for active pixels in radians. Single array for
single-field, tuple of arrays for multi-field.
lmax (int) – Maximum multipole for harmonic expansion.
beam (numpy.ndarray or None, optional) – Beam window function B_ℓ for ℓ=2 to lmax. Shape should be (lmax-1,).
If provided, the harmonic operator V is multiplied by beam factors
so that V_ℓm = B_ℓ × Y_ℓm. If None, no beam correction is applied.
spins (list of int or None, optional) – Spin weight for each component. Default is [0, 0, …] (all spin-0).
Use spin=2 for polarization (Q/U) fields, which doubles pixel count
and uses spin-weighted spherical harmonics for E/B decomposition.
N (numpy.ndarray) – Noise covariance matrix (n_pix_total, n_pix_total). The basis
takes ownership; _factorise_noise() overwrites this buffer
in place during setup.
theta (numpy.ndarray or tuple of numpy.ndarray) – Colatitude angles for active pixels in radians. Single array for
single-field, tuple of arrays for multi-field (one per component).
phi (numpy.ndarray or tuple of numpy.ndarray) – Longitude angles for active pixels in radians. Single array for
single-field, tuple of arrays for multi-field (one per component).
lmax_signal (int) – Signal-cov ceiling. The basis represents multipoles up to and
including this value.
beam (numpy.ndarray or None, optional) – Beam window function B_ℓ for ℓ=0..lmax_signal.
spins (list of int or None, optional) – Spin weight for each component (0 for scalar, 2 for polarization).
Default is [0, …] for all components. For spin-2 components,
theta/phi represent physical pixel locations but V is built for
(Q, U) → (E, B) transformation with doubled dimensions.
lmin_signal (list of int or None, optional) – Per-component signal-cov floor. Defaults to [2]*n_components.
Each entry must satisfy lmin_signal[i]>=|spins[i]|.
lmin (int or None, optional) – Inference window lower bound. Defaults to min(lmin_signal).
Together with lmax enables the switch optimisation:
S_fixed absorbs the signal contribution outside
[lmin,lmax].
lmax (int or None, optional) – Inference window upper bound. Defaults to lmax_signal.
Multipoles in (lmax,lmax_signal] are absorbed into S_fixed.
fiducial_C_ell (numpy.ndarray or None, optional) – Deprecated: Use S_fixed instead. Fiducial power spectrum for
fixed multipoles (ℓ outside [lmin,lmax]).
S_fixed (numpy.ndarray or None, optional) – Precomputed signal matrix for fixed multipoles outside
[lmin,lmax]. Recommended way to pass the fixed signal
contribution. Shape (n_pix_total,n_pix_total).
For HarmonicBasis: exact (N+S)^{-1} via the SMW formula.
For PixelBasis in pixel-direct mode: also exact (U is the
identity, so U@get_inverse(C_ell)@U.T equals the full
inverse).
For PixelBasis on a truncated compressed basis: the returned
matrix is U@get_inverse(C_ell)@U.T, which lives in the
kept subspace and is zero on the truncated complement. It is
not the inverse of the full pixel-space covariance; it is the
inverse of the restricted operator, lifted back to n_pix
dimensions. Use with care.
Callers who only need the basis-space inverse should use
get_inverse() instead — cheaper and equivalent in
basis-space algebra.
Return log|N+S|, the full pixel-space log determinant.
HarmonicBasis overrides this to compute it exactly via the SMW
formula. The default below applies to PixelBasis and is exact
only in pixel-direct mode (U is the identity, so the
basis-space logdet equals the full logdet).
On a truncated compressed pixel basis the full logdet cannot
be recovered from the kept quantities: the discarded complement
of N+S is needed and is not stored. The default falls
through to get_logdet(), which returns the logdet of the
restricted operator U^T(N+S)U — a different matrix, not
an approximation to log|N+S|. Callers that need the exact
full logdet on a truncated basis must arrange for it elsewhere.
Parameters:
C_ell (numpy.ndarray or dict) – Power spectrum (array for single-field, dict for multi-field).
Basis-projected noise consumed by the QML noise-bias sandwich.
Spectra computes Cov(w|noise)=Xget_noise_for_bias()X^T
where X is the basis’s natural inverse-equivalent
(A=(I+LambdaM)^{-T} for the harmonic basis;
C_c^{-1} for the pixel basis). The form of the returned
matrix is therefore basis-specific:
HarmonicBasis: VN_eff^{-1}NN_eff^{-1}V^T (the SMW
intermediate T from N_eff=N+S_fixed when the
switch optimisation is active; otherwise
VN^{-1}NN^{-1}V^T).
PixelBasis: U^TNU (raw noise projected once into the
eigenmode basis).
The two are not interchangeable. Callers must compose with the
basis’s own inverse-equivalent.
Pre-bake per-C_ell quantities for fast likelihood reuse.
Returns a BasisPrepared carrying the basis-specific
factor and the full log determinant. The factor is
consumable by quadratic_form_from_prepared() on the same
basis instance.
Parameters:
C_ell_dict (dict) – Multi-field power spectrum dict keyed by SpectrumKey.
Fast path for evaluating the quadratic form many times against
the same C_ell: caller calls prepare_for_basis() once
and reuses the resulting factor across simulations.
Parameters:
data (numpy.ndarray) – Pixel-space data, shape (n_pix,) or (n_pix,n_sims).
Direct harmonic space computation basis (Tegmark-like).
Transforms directly to n_modes dimensions via V. Fast and efficient
when n_modes << n_pix. No additional eigenvalue truncation.
The key operations are:
- Data projection: d̄ = P @ d where P = V
- Projected covariance: C̄ = V N V^T + Λ
- Projected inverse: V C^{-1} V^T = M - M K^{-1} M (via SMW)
Parameters:
N (numpy.ndarray) – Noise covariance matrix of shape (n_pix, n_pix). The basis takes
ownership of this buffer; _factorise_noise() overwrites it
in place during setup.
theta (numpy.ndarray) – Colatitude angles for active pixels in radians.
phi (numpy.ndarray) – Longitude angles for active pixels in radians.
lmax (int) – Maximum multipole for harmonic expansion.
beam (numpy.ndarray or None, optional) – Beam window function B_ℓ for ℓ=2 to lmax.
compress (bool, optional) – If True, use m-block compression for K inversion.
Approximates K as block-diagonal in azimuthal quantum number |m|,
giving ~lmax^2 speedup. Default is False.
delta_m (int, optional) – Bandwidth for m-block coupling. delta_m=0 means block-diagonal
(no coupling between different |m|). delta_m=lmax recovers exact
result. Default is 0.
N (numpy.ndarray) – Noise covariance matrix (n_pix_total, n_pix_total). The basis
takes ownership; _factorise_noise() overwrites this buffer
in place during setup.
theta (numpy.ndarray or tuple of numpy.ndarray) – Colatitude angles for active pixels in radians. Single array for
single-field, tuple of arrays for multi-field (one per component).
phi (numpy.ndarray or tuple of numpy.ndarray) – Longitude angles for active pixels in radians. Single array for
single-field, tuple of arrays for multi-field (one per component).
lmax_signal (int) – Signal-cov ceiling. The basis represents multipoles up to and
including this value.
beam (numpy.ndarray or None, optional) – Beam window function B_ℓ for ℓ=0..lmax_signal.
spins (list of int or None, optional) – Spin weight for each component (0 for scalar, 2 for polarization).
Default is [0, …] for all components. For spin-2 components,
theta/phi represent physical pixel locations but V is built for
(Q, U) → (E, B) transformation with doubled dimensions.
lmin_signal (list of int or None, optional) – Per-component signal-cov floor. Defaults to [2]*n_components.
Each entry must satisfy lmin_signal[i]>=|spins[i]|.
lmin (int or None, optional) – Inference window lower bound. Defaults to min(lmin_signal).
Together with lmax enables the switch optimisation:
S_fixed absorbs the signal contribution outside
[lmin,lmax].
lmax (int or None, optional) – Inference window upper bound. Defaults to lmax_signal.
Multipoles in (lmax,lmax_signal] are absorbed into S_fixed.
fiducial_C_ell (numpy.ndarray or None, optional) – Deprecated: Use S_fixed instead. Fiducial power spectrum for
fixed multipoles (ℓ outside [lmin,lmax]).
S_fixed (numpy.ndarray or None, optional) – Precomputed signal matrix for fixed multipoles outside
[lmin,lmax]. Recommended way to pass the fixed signal
contribution. Shape (n_pix_total,n_pix_total).
C_ell (numpy.ndarray or dict) – Power spectrum. Single-field: numpy.ndarray (spectra_list=None).
Multi-field: dict keyed by SpectrumKey (spectra_list required).
spectra_list (list[SpectrumKey] or None) – For multi-field, the list of SpectrumKey instances enumerating
the spectra to include. None for single-field.
symmetry_mode (SymmetryMode or None) – Forwarded to the per-ℓ derivative builder. None keeps the
SYMMETRIC default. Required as DIRECTIONAL when
spectra_list contains a CG cross-pair entry — the
builder otherwise rejects the mode=2 slot used by CG.
Compute harmonic-space covariance C̄ = V N V^T + Λ.
Parameters:
C_ell (numpy.ndarray or dict) – Power spectrum. Can be:
- numpy.ndarray: C_ell values for ell = 2 to lmax (single-field)
- dict: Multi-field with 2-tuple or 3-tuple keys
Get derivative diagonal for an auto-pair diagonal SpectrumKey.
Returns a 1D vector — the diagonal of ∂S/∂C_ℓ — for use in the
sparse-trace fast path. Valid only for key.comp_i==key.comp_j
and diagonal kinds (SS, GG, CC) — i.e. TT, EE, or BB.
Cross-component keys and GC/CG/SG/SC/GS/CS raise ValueError.
Compute V C^{-1} V^T efficiently using SMW formula.
Parameters:
C_ell (numpy.ndarray or dict) – Power spectrum. Can be array (single-field) or dict (multi-field).
field_groups (list of list of int or None, optional) – Independent field groups from _detect_field_blocks.
If provided and contains more than one group, exploits
field block-diagonal structure for faster K inversion.
w=(I+LambdaM)^{-T}(VN^{-1}d) — algebraically equivalent to
MK^{-1}d but never subtracts large nearly-equal matrices, so it
retains precision in the cosmic-variance-limited regime where the
legacy subtractive form y-MK^{-1}y cancelled.
Parameters:
data (numpy.ndarray) – Pixel-space data, shape (n_pix,) or (n_pix,n_sims).
C_ell (numpy.ndarray or dict) – Power spectrum (single-field array or multi-field dict).
C_c_inv (numpy.ndarray, optional) – Unused for harmonic basis; accepted for ABC signature parity.
stable_inner_inv (numpy.ndarray, optional) – Precomputed (I+LambdaM)^{-1}. If supplied, avoids
rebuilding it internally. Callers that weight several data
vectors with the same C_ell should build it once via
prepare_stable_inner_inv() and pass it in.
Build (I + Lambda M)^{-1} for the stable QML algebra.
This matrix appears identically in three places of the QML
algebra and replaces the unstable subtractive forms:
Projected inverse: V C^{-1} V^T = M @ (I + Lambda M)^{-1}
Data weighting: V C^{-1} d = (I + Lambda M)^{-1} @ V N^{-1} d
Noise bias matrix: A = I - M K^{-1} = (I + Lambda M)^{-1}
All three follow from the identity
M-MK^{-1}M=MK^{-1}Lambda^{-1}=M(I+LambdaM)^{-1}
and never subtract large nearly-equal matrices, so they remain
accurate in the cosmic-variance-limited regime where the legacy
SMW form loses precision (e.g. T at low ell with sub-uK
polarization noise).
Parameters:
C_ell (np.ndarray or dict) – Power spectrum (single-field array or multi-field dict).
lambda_matrix (np.ndarray, optional) – Pre-built full Lambda matrix. If None, built from C_ell.
Returns:
(I + Lambda M)^{-1}, n_modes_total x n_modes_total.
QML hot paths (Fisher trace, Spectra weighted-data) read only
_V_N_inv and _V_Ninv_VT. The remaining V consumers —
get_covariance/get_inverse,
to_basis, m-block compression, and PICSLike do_cross
with the harmonic basis — must not be invoked after this call.
Raises if m-block compression was requested at construction.
Computes:
- V: harmonic operator (n_modes × n_pix)
- V N^{-1}: precomputed for SMW
- V N^{-1} V^T: SMW kernel
- V N V^T: harmonic-space noise covariance
- log|N|: for determinant calculations
- Derivative diagonals: E_ℓ for all ℓ
When switch optimization is enabled (lswitch_high < lmax):
- V is built only for ℓ in [lswitch_low, lswitch_high]
- S_fixed is computed for ℓ > lswitch_high using fiducial C_ell
- N_eff = N + S_fixed is used instead of N
This dramatically reduces the SMW dimension.
Pixel-space compression with projector (Gjerløw-like).
Stays in n_pix space with projector P_h, then uses eigenvalue
decomposition to find optimal subspace. Compression: n_pix → dim.
The key operations are:
- Projector: P_h = V^T V (harmonic projector, n_pix × n_pix but rank n_modes)
- Eigendecomposition of compression matrix to find optimal modes
- Data compression: d_c = P @ d where P = U^T (dim × n_pix)
This approach is more flexible than HarmonicBasis because it allows
custom projectors to handle systematics (foreground deprojection, etc.).
Available compression bases (from Gjerløw et al. 2019):
harmonic: Pure harmonic projector P_h = V^T V. Selects modes based
purely on harmonic content, ignoring noise properties.
total_covariance: P_h C^{-1} P_h where C = N + S. Uses full
signal+noise covariance for optimal compression.
snr: S^{1/2} N^{-1} S^{1/2}. Signal-to-noise ratio matrix, prioritizing
modes with highest SNR.
Parameters:
N (numpy.ndarray) – Noise covariance matrix of shape (n_pix, n_pix). The basis takes
ownership of this buffer; _factorise_noise() overwrites it
in place during setup (V-based mode only; pixel-direct keeps it).
theta (numpy.ndarray) – Colatitude angles for active pixels in radians.
phi (numpy.ndarray) – Longitude angles for active pixels in radians.
lmax (int) – Maximum multipole for harmonic expansion.
beam (numpy.ndarray or None, optional) – Beam window function B_ℓ for ℓ=2 to lmax.
basis (str, default "noise_weighted") – Compression basis to use. Options:
- “harmonic”: P_h = V^T V (pure harmonic projector)
- “noise_weighted”: P_h N^{-1} P_h (inverse noise weighting)
- “total_covariance”: P_h C^{-1} P_h where C = N + S
- “snr”: S^{1/2} N^{-1} S^{1/2} (signal-to-noise ratio)
C_ell (numpy.ndarray or None, optional) – Power spectrum values for ell = 2 to lmax. Required for
“total_covariance” and “snr” bases.
epsilon (float, optional) – Eigenvalue threshold relative to maximum.
mode_fraction (float, optional) – Fraction of modes to keep.
N (numpy.ndarray) – Noise covariance matrix (n_pix_total, n_pix_total). The basis
takes ownership; _factorise_noise() overwrites this buffer
in place during setup.
theta (numpy.ndarray or tuple of numpy.ndarray) – Colatitude angles for active pixels in radians. Single array for
single-field, tuple of arrays for multi-field (one per component).
phi (numpy.ndarray or tuple of numpy.ndarray) – Longitude angles for active pixels in radians. Single array for
single-field, tuple of arrays for multi-field (one per component).
lmax_signal (int) – Signal-cov ceiling. The basis represents multipoles up to and
including this value.
beam (numpy.ndarray or None, optional) – Beam window function B_ℓ for ℓ=0..lmax_signal.
spins (list of int or None, optional) – Spin weight for each component (0 for scalar, 2 for polarization).
Default is [0, …] for all components. For spin-2 components,
theta/phi represent physical pixel locations but V is built for
(Q, U) → (E, B) transformation with doubled dimensions.
lmin_signal (list of int or None, optional) – Per-component signal-cov floor. Defaults to [2]*n_components.
Each entry must satisfy lmin_signal[i]>=|spins[i]|.
lmin (int or None, optional) – Inference window lower bound. Defaults to min(lmin_signal).
Together with lmax enables the switch optimisation:
S_fixed absorbs the signal contribution outside
[lmin,lmax].
lmax (int or None, optional) – Inference window upper bound. Defaults to lmax_signal.
Multipoles in (lmax,lmax_signal] are absorbed into S_fixed.
fiducial_C_ell (numpy.ndarray or None, optional) – Deprecated: Use S_fixed instead. Fiducial power spectrum for
fixed multipoles (ℓ outside [lmin,lmax]).
S_fixed (numpy.ndarray or None, optional) – Precomputed signal matrix for fixed multipoles outside
[lmin,lmax]. Recommended way to pass the fixed signal
contribution. Shape (n_pix_total,n_pix_total).
The selector configured at construction (compression_target kwarg).
Names the matrix that _apply_compression eigendecomposes:
"harmonic", "noise_weighted", "total_covariance", or
"snr". Returns the configured value regardless of whether
compression has actually been applied yet.
Returns one entry per component with eigenvalues and normalized
eigenvalues. For spin-2 components the result additionally contains
separate E- and B-mode eigenspectra.
C_ell (numpy.ndarray, dict, or None) – Power spectrum (required for “total_covariance” and “snr” bases).
Returns:
One dict per component with keys: component, spin,
label, eigenvalues, normalized_eigenvalues.
Spin-2 components additionally have E_eigenvalues,
E_normalized, B_eigenvalues, B_normalized.
C_ell (numpy.ndarray or dict) – Power spectrum. Single-field: numpy.ndarray. Multi-field: dict
keyed by SpectrumKey.
spectra_list (list[SpectrumKey] or None) – For multi-field, the list of SpectrumKey instances enumerating
the spectra to include. None for single-field.
symmetry_mode (SymmetryMode or None) – Forwarded to the per-ℓ derivative builder. None keeps the
SYMMETRIC default. Required as DIRECTIONAL when
spectra_list contains a CG cross-pair entry — the
builder otherwise rejects the mode=2 slot used by CG.
Build the binned derivative dC^b in a single Legendre/Wigner pass.
Mathematically equivalent to summing per-ℓ _get_derivative_direct
results with weights beam²(ℓ) over ℓ ∈ [bins.lmins[bin_idx],
bins.lmaxs[bin_idx]], but uses one compute_*_contribution call
instead of N (where N = bin width). The contribution functions
accumulate Σ_ℓcl[ell]×kernel[ell] per pixel pair on
ℓ-indexed arrays, so populating cl[ell]=beam²(ell) inside the
bin (zero elsewhere) yields the exact binned derivative.
Parameters:
key (SpectrumKey) – Identifies the spectrum (component pair + spin kind). Decomposed
into (comp_i,comp_j,mode) once at entry for the Numba
kernels below.
In pixel-direct mode this is the exact N+S; on a truncated
compressed basis it is U^T(N+S)U — the restriction of
the full covariance to the kept subspace.
Parameters:
C_ell (numpy.ndarray or dict) – Power spectrum (array for single-field, dict for multi-field).
Reconstruct full n_pixxn_pix inverse from the basis-space form.
Exact in pixel-direct mode (U is the identity). Lossy on a
truncated compressed pixel basis — the result lives in the kept
subspace and is zero on the truncated complement.
Compute the log determinant of the basis-space covariance.
In pixel-direct mode this equals the exact full log|N+S|.
On a truncated compressed basis it is the logdet of the
restricted operator U^T(N+S)U — not the full
log|N+S|; see get_full_logdet() for the ABC contract.
Parameters:
C_ell (numpy.ndarray or dict) – Power spectrum (array for single-field, dict for multi-field).
U^T N_raw U — raw noise projected into the eigenmode basis.
See ComputationBasis.get_noise_for_bias() for the cross-basis
contract. Use this for noise-bias computations:
Tr[C^{-1}NC^{-1}dS] requires the actual noise N, not the
effective N_eff that includes the absorbed high-ℓ signal.
Without switch optimization, N_eff = N and this is identical to
get_covariance(0).
In pixel-direct mode this is the exact (N+S)^{-1}; on a
truncated compressed basis it is (U^T(N+S)U)^{-1} —
the inverse of the restricted operator on the kept subspace.
Parameters:
C_ell (numpy.ndarray or dict) – Power spectrum (array for single-field, dict for multi-field).
Plot eigenvalue spectrum for compression threshold selection.
Creates one subplot per component. The y-axis shows eigenvalues
normalized by the maximum value, so values can be directly used as the
epsilon constructor kwarg of PixelBasis. For spin-2
components the E and B sub-spectra are shown as dashed curves when
show_eb_split is True.
fig (matplotlib.figure.Figure) – The figure containing the plot.
axes (numpy.ndarray) – 1-D array of Axes (length n_components).
Examples
>>> # Pick threshold by plotting first, then construct a compressed basis.>>> # The probe construction uses epsilon=0.0 to opt into the V-based>>> # path (keeps all modes) so plot_eigenvalue_spectrum has V to read.>>> ppc_probe=PixelBasis(... N,theta,phi,lmax_signal=100,epsilon=0.0,... )>>> ppc_probe.setup()>>> fig,axes=ppc_probe.plot_eigenvalue_spectrum(basis="noise_weighted")>>> # From the plot, decide threshold (e.g., 1e-4).>>> ppc=PixelBasis(... N,theta,phi,lmax_signal=100,... epsilon=1e-4,compression_target="noise_weighted",... )>>> ppc.setup()
Maps pixel space to the basis. In pixel-direct mode the
projector is the identity; in compressed mode it is U^T,
the transpose of the kept eigenvectors.
Raises:
RuntimeError – If compression has not been applied yet (V-based mode only).
In pixel-direct mode this equals the full pixel-space quadratic
form d^T(N+S)^{-1}d. On a truncated compressed basis it
is (U^Td)^T(U^T(N+S)U)^{-1}(U^Td) — the quadratic
form of the restricted operator on the kept subspace.
Parameters:
data (numpy.ndarray) – Pixel-space data vector of length n_pix.
C_ell (numpy.ndarray or dict) – Power spectrum (array for single-field, dict for multi-field).
In V-based mode: build V and P_h, optionally apply eigenvalue
compression. In direct mode (n_pix small enough that V is overkill):
skip V construction and rely on existing pixel-space machinery
(compute_signal_matrix, do_derivative_step).
Pixel-direct mode short-circuits the multiplication against the
identity projector (otherwise an n_pix×n_sims matmul against
an n_pix×n_pix identity, allocated and run on every call).
Log determinant. Semantics are basis-specific and intentionally
match what quadratic_form_from_prepared consumes:
HarmonicBasis: exact full pixel-space log|N+S| via SMW.
PixelBasis in pixel-direct mode: exact full log|N+S|
(U is the identity, so basis-space equals full-space).
PixelBasis on a truncated compressed basis: basis-space
log|U^T(N+S)U| — the logdet of the restricted
operator, NOT the full log|N+S|. Combine with
quadratic_form_from_prepared() (also basis-space) for
an internally-consistent basis-space likelihood.
Computation basis method:
- “harmonic”: Tegmark-like direct harmonic transformation
- “pixel”: Gjerløw-like pixel-space projector with eigenvalue truncation
- “auto”: Pick the cheaper path using a leading-order cost model.
Compares ~n_modes^3 (harmonic + sparse traces) vs
~(n_bins+1)*n_pix^3 (pixel-direct). Pass n_bins to refine
the estimate; defaults to lmax-1 (unbinned, worst case
for pixel-direct).
N (numpy.ndarray) – Noise covariance matrix. The basis takes ownership; the caller
should drop its reference after construction.
theta (numpy.ndarray) – Colatitude angles for active pixels in radians.
phi (numpy.ndarray) – Longitude angles for active pixels in radians.
lmax (int) – Maximum multipole for harmonic expansion.
**kwargs – Additional keyword arguments passed to the basis constructor
(beam, spins, basis, C_ell, epsilon, mode_fraction, fields,
lmin_signal, lmin, lmax, etc.). Arguments not accepted by the
chosen class are silently ignored.
Returns:
Configured basis instance (not yet set up — call .setup()).
Per-C_ell quantities pre-computed for fast likelihood evaluation.
Returned by ComputationBasis.prepare_for_basis(). The stored
factor is basis-specific in form but always usable as the
second argument of
ComputationBasis.quadratic_form_from_prepared().
Parameters:
factor (numpy.ndarray) – K Cholesky factor (harmonic) or basis-space inverse (pixel).
Log determinant. Semantics are basis-specific and intentionally
match what quadratic_form_from_prepared consumes:
HarmonicBasis: exact full pixel-space log|N+S| via SMW.
PixelBasis in pixel-direct mode: exact full log|N+S|
(U is the identity, so basis-space equals full-space).
PixelBasis on a truncated compressed basis: basis-space
log|U^T(N+S)U| — the logdet of the restricted
operator, NOT the full log|N+S|. Combine with
quadratic_form_from_prepared() (also basis-space) for
an internally-consistent basis-space likelihood.
Abstract base class for computation basis methods.
This class defines the interface for computation basis methods and provides
shared implementations for spherical harmonic evaluation and ell-to-mode
mapping.
Supports both single-field and multi-field configurations. For multi-field,
theta and phi are passed as tuples of arrays (one per component), and the
harmonic operator V is built as a block-diagonal matrix.
Parameters:
N (numpy.ndarray) – Noise covariance matrix of shape (n_pix_total, n_pix_total). The
basis takes ownership of this buffer; the in-place Cholesky factor
overwrites it during setup.
theta (numpy.ndarray or tuple of numpy.ndarray) – Colatitude angles for active pixels in radians. Single array for
single-field, tuple of arrays for multi-field.
phi (numpy.ndarray or tuple of numpy.ndarray) – Longitude angles for active pixels in radians. Single array for
single-field, tuple of arrays for multi-field.
lmax (int) – Maximum multipole for harmonic expansion.
beam (numpy.ndarray or None, optional) – Beam window function B_ℓ for ℓ=2 to lmax. Shape should be (lmax-1,).
If provided, the harmonic operator V is multiplied by beam factors
so that V_ℓm = B_ℓ × Y_ℓm. If None, no beam correction is applied.
spins (list of int or None, optional) – Spin weight for each component. Default is [0, 0, …] (all spin-0).
Use spin=2 for polarization (Q/U) fields, which doubles pixel count
and uses spin-weighted spherical harmonics for E/B decomposition.
n_pix
Total number of active pixels across all components.
N (numpy.ndarray) – Noise covariance matrix (n_pix_total, n_pix_total). The basis
takes ownership; _factorise_noise() overwrites this buffer
in place during setup.
theta (numpy.ndarray or tuple of numpy.ndarray) – Colatitude angles for active pixels in radians. Single array for
single-field, tuple of arrays for multi-field (one per component).
phi (numpy.ndarray or tuple of numpy.ndarray) – Longitude angles for active pixels in radians. Single array for
single-field, tuple of arrays for multi-field (one per component).
lmax_signal (int) – Signal-cov ceiling. The basis represents multipoles up to and
including this value.
beam (numpy.ndarray or None, optional) – Beam window function B_ℓ for ℓ=0..lmax_signal.
spins (list of int or None, optional) – Spin weight for each component (0 for scalar, 2 for polarization).
Default is [0, …] for all components. For spin-2 components,
theta/phi represent physical pixel locations but V is built for
(Q, U) → (E, B) transformation with doubled dimensions.
lmin_signal (list of int or None, optional) – Per-component signal-cov floor. Defaults to [2]*n_components.
Each entry must satisfy lmin_signal[i]>=|spins[i]|.
lmin (int or None, optional) – Inference window lower bound. Defaults to min(lmin_signal).
Together with lmax enables the switch optimisation:
S_fixed absorbs the signal contribution outside
[lmin,lmax].
lmax (int or None, optional) – Inference window upper bound. Defaults to lmax_signal.
Multipoles in (lmax,lmax_signal] are absorbed into S_fixed.
fiducial_C_ell (numpy.ndarray or None, optional) – Deprecated: Use S_fixed instead. Fiducial power spectrum for
fixed multipoles (ℓ outside [lmin,lmax]).
S_fixed (numpy.ndarray or None, optional) – Precomputed signal matrix for fixed multipoles outside
[lmin,lmax]. Recommended way to pass the fixed signal
contribution. Shape (n_pix_total,n_pix_total).
Compute weighted basis-space data for QML estimation.
Parameters:
data (numpy.ndarray) – Pixel-space data vector of shape (n_pix,) or (n_pix, n_sims).
C_ell (numpy.ndarray or dict) – Power spectrum (array for single-field, dict for multi-field).
C_c_inv (numpy.ndarray, optional) – Precomputed basis-space inverse. Used by PixelBasis only;
ignored by HarmonicBasis.
stable_inner_inv (numpy.ndarray, optional) – Precomputed (I+LambdaM)^{-1}, as returned by
HarmonicBasis.prepare_stable_inner_inv(). Used by
HarmonicBasis only; ignored by PixelBasis.
Returns:
Weighted basis-space data of shape (dim,) or (dim, n_sims).
Basis-projected noise consumed by the QML noise-bias sandwich.
Spectra computes Cov(w|noise)=Xget_noise_for_bias()X^T
where X is the basis’s natural inverse-equivalent
(A=(I+LambdaM)^{-T} for the harmonic basis;
C_c^{-1} for the pixel basis). The form of the returned
matrix is therefore basis-specific:
HarmonicBasis: VN_eff^{-1}NN_eff^{-1}V^T (the SMW
intermediate T from N_eff=N+S_fixed when the
switch optimisation is active; otherwise
VN^{-1}NN^{-1}V^T).
PixelBasis: U^TNU (raw noise projected once into the
eigenmode basis).
The two are not interchangeable. Callers must compose with the
basis’s own inverse-equivalent.
Return log|N+S|, the full pixel-space log determinant.
HarmonicBasis overrides this to compute it exactly via the SMW
formula. The default below applies to PixelBasis and is exact
only in pixel-direct mode (U is the identity, so the
basis-space logdet equals the full logdet).
On a truncated compressed pixel basis the full logdet cannot
be recovered from the kept quantities: the discarded complement
of N+S is needed and is not stored. The default falls
through to get_logdet(), which returns the logdet of the
restricted operator U^T(N+S)U — a different matrix, not
an approximation to log|N+S|. Callers that need the exact
full logdet on a truncated basis must arrange for it elsewhere.
Parameters:
C_ell (numpy.ndarray or dict) – Power spectrum (array for single-field, dict for multi-field).
For HarmonicBasis: exact (N+S)^{-1} via the SMW formula.
For PixelBasis in pixel-direct mode: also exact (U is the
identity, so U@get_inverse(C_ell)@U.T equals the full
inverse).
For PixelBasis on a truncated compressed basis: the returned
matrix is U@get_inverse(C_ell)@U.T, which lives in the
kept subspace and is zero on the truncated complement. It is
not the inverse of the full pixel-space covariance; it is the
inverse of the restricted operator, lifted back to n_pix
dimensions. Use with care.
Callers who only need the basis-space inverse should use
get_inverse() instead — cheaper and equivalent in
basis-space algebra.
Compute d^TC^{-1}d using a pre-baked factor from
prepare_for_basis().
Fast path for evaluating the quadratic form many times against
the same C_ell: caller calls prepare_for_basis() once
and reuses the resulting factor across simulations.
Parameters:
data (numpy.ndarray) – Pixel-space data, shape (n_pix,) or (n_pix,n_sims).
factor (numpy.ndarray) – Basis-specific pre-baked quantity:
BasisPrepared.factor from prepare_for_basis().
Pre-bake per-C_ell quantities for fast likelihood reuse.
Returns a BasisPrepared carrying the basis-specific
factor and the full log determinant. The factor is
consumable by quadratic_form_from_prepared() on the same
basis instance.
Parameters:
C_ell_dict (dict) – Multi-field power spectrum dict keyed by SpectrumKey.
Direct harmonic space computation basis (Tegmark-like).
Transforms directly to n_modes dimensions via V. Fast and efficient
when n_modes << n_pix. No additional eigenvalue truncation.
The key operations are:
- Data projection: d̄ = P @ d where P = V
- Projected covariance: C̄ = V N V^T + Λ
- Projected inverse: V C^{-1} V^T = M - M K^{-1} M (via SMW)
Parameters:
N (numpy.ndarray) – Noise covariance matrix of shape (n_pix, n_pix). The basis takes
ownership of this buffer; _factorise_noise() overwrites it
in place during setup.
theta (numpy.ndarray) – Colatitude angles for active pixels in radians.
phi (numpy.ndarray) – Longitude angles for active pixels in radians.
lmax (int) – Maximum multipole for harmonic expansion.
beam (numpy.ndarray or None, optional) – Beam window function B_ℓ for ℓ=2 to lmax.
compress (bool, optional) – If True, use m-block compression for K inversion.
Approximates K as block-diagonal in azimuthal quantum number |m|,
giving ~lmax^2 speedup. Default is False.
delta_m (int, optional) – Bandwidth for m-block coupling. delta_m=0 means block-diagonal
(no coupling between different |m|). delta_m=lmax recovers exact
result. Default is 0.
N (numpy.ndarray) – Noise covariance matrix (n_pix_total, n_pix_total). The basis
takes ownership; _factorise_noise() overwrites this buffer
in place during setup.
theta (numpy.ndarray or tuple of numpy.ndarray) – Colatitude angles for active pixels in radians. Single array for
single-field, tuple of arrays for multi-field (one per component).
phi (numpy.ndarray or tuple of numpy.ndarray) – Longitude angles for active pixels in radians. Single array for
single-field, tuple of arrays for multi-field (one per component).
lmax_signal (int) – Signal-cov ceiling. The basis represents multipoles up to and
including this value.
beam (numpy.ndarray or None, optional) – Beam window function B_ℓ for ℓ=0..lmax_signal.
spins (list of int or None, optional) – Spin weight for each component (0 for scalar, 2 for polarization).
Default is [0, …] for all components. For spin-2 components,
theta/phi represent physical pixel locations but V is built for
(Q, U) → (E, B) transformation with doubled dimensions.
lmin_signal (list of int or None, optional) – Per-component signal-cov floor. Defaults to [2]*n_components.
Each entry must satisfy lmin_signal[i]>=|spins[i]|.
lmin (int or None, optional) – Inference window lower bound. Defaults to min(lmin_signal).
Together with lmax enables the switch optimisation:
S_fixed absorbs the signal contribution outside
[lmin,lmax].
lmax (int or None, optional) – Inference window upper bound. Defaults to lmax_signal.
Multipoles in (lmax,lmax_signal] are absorbed into S_fixed.
fiducial_C_ell (numpy.ndarray or None, optional) – Deprecated: Use S_fixed instead. Fiducial power spectrum for
fixed multipoles (ℓ outside [lmin,lmax]).
S_fixed (numpy.ndarray or None, optional) – Precomputed signal matrix for fixed multipoles outside
[lmin,lmax]. Recommended way to pass the fixed signal
contribution. Shape (n_pix_total,n_pix_total).
QML hot paths (Fisher trace, Spectra weighted-data) read only
_V_N_inv and _V_Ninv_VT. The remaining V consumers —
get_covariance/get_inverse,
to_basis, m-block compression, and PICSLike do_cross
with the harmonic basis — must not be invoked after this call.
Raises if m-block compression was requested at construction.
Computes:
- V: harmonic operator (n_modes × n_pix)
- V N^{-1}: precomputed for SMW
- V N^{-1} V^T: SMW kernel
- V N V^T: harmonic-space noise covariance
- log|N|: for determinant calculations
- Derivative diagonals: E_ℓ for all ℓ
When switch optimization is enabled (lswitch_high < lmax):
- V is built only for ℓ in [lswitch_low, lswitch_high]
- S_fixed is computed for ℓ > lswitch_high using fiducial C_ell
- N_eff = N + S_fixed is used instead of N
This dramatically reduces the SMW dimension.
Build (I + Lambda M)^{-1} for the stable QML algebra.
This matrix appears identically in three places of the QML
algebra and replaces the unstable subtractive forms:
Projected inverse: V C^{-1} V^T = M @ (I + Lambda M)^{-1}
Data weighting: V C^{-1} d = (I + Lambda M)^{-1} @ V N^{-1} d
Noise bias matrix: A = I - M K^{-1} = (I + Lambda M)^{-1}
All three follow from the identity
M-MK^{-1}M=MK^{-1}Lambda^{-1}=M(I+LambdaM)^{-1}
and never subtract large nearly-equal matrices, so they remain
accurate in the cosmic-variance-limited regime where the legacy
SMW form loses precision (e.g. T at low ell with sub-uK
polarization noise).
Parameters:
C_ell (np.ndarray or dict) – Power spectrum (single-field array or multi-field dict).
lambda_matrix (np.ndarray, optional) – Pre-built full Lambda matrix. If None, built from C_ell.
Returns:
(I + Lambda M)^{-1}, n_modes_total x n_modes_total.
Compute V C^{-1} V^T efficiently using SMW formula.
Parameters:
C_ell (numpy.ndarray or dict) – Power spectrum. Can be array (single-field) or dict (multi-field).
field_groups (list of list of int or None, optional) – Independent field groups from _detect_field_blocks.
If provided and contains more than one group, exploits
field block-diagonal structure for faster K inversion.
Compute harmonic-space covariance C̄ = V N V^T + Λ.
Parameters:
C_ell (numpy.ndarray or dict) – Power spectrum. Can be:
- numpy.ndarray: C_ell values for ell = 2 to lmax (single-field)
- dict: Multi-field with 2-tuple or 3-tuple keys
w=(I+LambdaM)^{-T}(VN^{-1}d) — algebraically equivalent to
MK^{-1}d but never subtracts large nearly-equal matrices, so it
retains precision in the cosmic-variance-limited regime where the
legacy subtractive form y-MK^{-1}y cancelled.
Parameters:
data (numpy.ndarray) – Pixel-space data, shape (n_pix,) or (n_pix,n_sims).
C_ell (numpy.ndarray or dict) – Power spectrum (single-field array or multi-field dict).
C_c_inv (numpy.ndarray, optional) – Unused for harmonic basis; accepted for ABC signature parity.
stable_inner_inv (numpy.ndarray, optional) – Precomputed (I+LambdaM)^{-1}. If supplied, avoids
rebuilding it internally. Callers that weight several data
vectors with the same C_ell should build it once via
prepare_stable_inner_inv() and pass it in.
Get derivative diagonal for an auto-pair diagonal SpectrumKey.
Returns a 1D vector — the diagonal of ∂S/∂C_ℓ — for use in the
sparse-trace fast path. Valid only for key.comp_i==key.comp_j
and diagonal kinds (SS, GG, CC) — i.e. TT, EE, or BB.
Cross-component keys and GC/CG/SG/SC/GS/CS raise ValueError.
C_ell (numpy.ndarray or dict) – Power spectrum. Single-field: numpy.ndarray (spectra_list=None).
Multi-field: dict keyed by SpectrumKey (spectra_list required).
spectra_list (list[SpectrumKey] or None) – For multi-field, the list of SpectrumKey instances enumerating
the spectra to include. None for single-field.
symmetry_mode (SymmetryMode or None) – Forwarded to the per-ℓ derivative builder. None keeps the
SYMMETRIC default. Required as DIRECTIONAL when
spectra_list contains a CG cross-pair entry — the
builder otherwise rejects the mode=2 slot used by CG.
Harmonic basis construction for computation basis methods.
This module contains the HarmonicBasisBuilder class which encapsulates all
spherical harmonic operator (V), Lambda matrix, and derivative matrix
construction logic. It is an internal helper used by ComputationBasis and
its subclasses.
Builds and caches harmonic operator V, Lambda matrices, and derivative matrices.
This is an internal helper class owned by ComputationBasis. It groups all
the spherical harmonic basis construction code that was previously spread
across ComputationBasis methods.
Parameters:
parent (ComputationBasis) – Parent computation basis instance providing configuration. The following
attributes are read (all set during ComputationBasis.__init__):
_theta_tuple, _phi_tuple, _spins, n_components, lmax,
_lmin_smw, _lmax_smw, _n_modes_base, _n_modes_per_component,
_n_modes_per_component_list, n_modes, n_modes_total,
_mode_offsets, _pix_offsets, n_pix, _beam.
Pixel-projected compression (Gjerløw-like) for CMB Fisher matrix computation.
This module implements pixel-space compression with a harmonic projector P_h,
followed by eigenvalue decomposition to find the optimal subspace for compression.
Available compression bases (from Gjerløw et al. 2019):
- “harmonic”: Pure harmonic projector P_h = V^T V
- “noise_weighted”: P_h N^{-1} P_h (default) - inverse noise weighting
- “total_covariance”: P_h C^{-1} P_h where C = N + S - full covariance weighting
- “snr”: S^{1/2} N^{-1} S^{1/2} - signal-to-noise ratio matrix
Pixel-space compression with projector (Gjerløw-like).
Stays in n_pix space with projector P_h, then uses eigenvalue
decomposition to find optimal subspace. Compression: n_pix → dim.
The key operations are:
- Projector: P_h = V^T V (harmonic projector, n_pix × n_pix but rank n_modes)
- Eigendecomposition of compression matrix to find optimal modes
- Data compression: d_c = P @ d where P = U^T (dim × n_pix)
This approach is more flexible than HarmonicBasis because it allows
custom projectors to handle systematics (foreground deprojection, etc.).
Available compression bases (from Gjerløw et al. 2019):
harmonic: Pure harmonic projector P_h = V^T V. Selects modes based
purely on harmonic content, ignoring noise properties.
total_covariance: P_h C^{-1} P_h where C = N + S. Uses full
signal+noise covariance for optimal compression.
snr: S^{1/2} N^{-1} S^{1/2}. Signal-to-noise ratio matrix, prioritizing
modes with highest SNR.
Parameters:
N (numpy.ndarray) – Noise covariance matrix of shape (n_pix, n_pix). The basis takes
ownership of this buffer; _factorise_noise() overwrites it
in place during setup (V-based mode only; pixel-direct keeps it).
theta (numpy.ndarray) – Colatitude angles for active pixels in radians.
phi (numpy.ndarray) – Longitude angles for active pixels in radians.
lmax (int) – Maximum multipole for harmonic expansion.
beam (numpy.ndarray or None, optional) – Beam window function B_ℓ for ℓ=2 to lmax.
basis (str, default "noise_weighted") – Compression basis to use. Options:
- “harmonic”: P_h = V^T V (pure harmonic projector)
- “noise_weighted”: P_h N^{-1} P_h (inverse noise weighting)
- “total_covariance”: P_h C^{-1} P_h where C = N + S
- “snr”: S^{1/2} N^{-1} S^{1/2} (signal-to-noise ratio)
C_ell (numpy.ndarray or None, optional) – Power spectrum values for ell = 2 to lmax. Required for
“total_covariance” and “snr” bases.
epsilon (float, optional) – Eigenvalue threshold relative to maximum.
mode_fraction (float, optional) – Fraction of modes to keep.
dim
Number of modes kept after compression (initially n_pix).
N (numpy.ndarray) – Noise covariance matrix (n_pix_total, n_pix_total). The basis
takes ownership; _factorise_noise() overwrites this buffer
in place during setup.
theta (numpy.ndarray or tuple of numpy.ndarray) – Colatitude angles for active pixels in radians. Single array for
single-field, tuple of arrays for multi-field (one per component).
phi (numpy.ndarray or tuple of numpy.ndarray) – Longitude angles for active pixels in radians. Single array for
single-field, tuple of arrays for multi-field (one per component).
lmax_signal (int) – Signal-cov ceiling. The basis represents multipoles up to and
including this value.
beam (numpy.ndarray or None, optional) – Beam window function B_ℓ for ℓ=0..lmax_signal.
spins (list of int or None, optional) – Spin weight for each component (0 for scalar, 2 for polarization).
Default is [0, …] for all components. For spin-2 components,
theta/phi represent physical pixel locations but V is built for
(Q, U) → (E, B) transformation with doubled dimensions.
lmin_signal (list of int or None, optional) – Per-component signal-cov floor. Defaults to [2]*n_components.
Each entry must satisfy lmin_signal[i]>=|spins[i]|.
lmin (int or None, optional) – Inference window lower bound. Defaults to min(lmin_signal).
Together with lmax enables the switch optimisation:
S_fixed absorbs the signal contribution outside
[lmin,lmax].
lmax (int or None, optional) – Inference window upper bound. Defaults to lmax_signal.
Multipoles in (lmax,lmax_signal] are absorbed into S_fixed.
fiducial_C_ell (numpy.ndarray or None, optional) – Deprecated: Use S_fixed instead. Fiducial power spectrum for
fixed multipoles (ℓ outside [lmin,lmax]).
S_fixed (numpy.ndarray or None, optional) – Precomputed signal matrix for fixed multipoles outside
[lmin,lmax]. Recommended way to pass the fixed signal
contribution. Shape (n_pix_total,n_pix_total).
Maps pixel space to the basis. In pixel-direct mode the
projector is the identity; in compressed mode it is U^T,
the transpose of the kept eigenvectors.
Raises:
RuntimeError – If compression has not been applied yet (V-based mode only).
Pixel-direct mode short-circuits the multiplication against the
identity projector (otherwise an n_pix×n_sims matmul against
an n_pix×n_pix identity, allocated and run on every call).
In V-based mode: build V and P_h, optionally apply eigenvalue
compression. In direct mode (n_pix small enough that V is overkill):
skip V construction and rely on existing pixel-space machinery
(compute_signal_matrix, do_derivative_step).
U^T N_raw U — raw noise projected into the eigenmode basis.
See ComputationBasis.get_noise_for_bias() for the cross-basis
contract. Use this for noise-bias computations:
Tr[C^{-1}NC^{-1}dS] requires the actual noise N, not the
effective N_eff that includes the absorbed high-ℓ signal.
Without switch optimization, N_eff = N and this is identical to
get_covariance(0).
Build the binned derivative dC^b in a single Legendre/Wigner pass.
Mathematically equivalent to summing per-ℓ _get_derivative_direct
results with weights beam²(ℓ) over ℓ ∈ [bins.lmins[bin_idx],
bins.lmaxs[bin_idx]], but uses one compute_*_contribution call
instead of N (where N = bin width). The contribution functions
accumulate Σ_ℓcl[ell]×kernel[ell] per pixel pair on
ℓ-indexed arrays, so populating cl[ell]=beam²(ell) inside the
bin (zero elsewhere) yields the exact binned derivative.
Parameters:
key (SpectrumKey) – Identifies the spectrum (component pair + spin kind). Decomposed
into (comp_i,comp_j,mode) once at entry for the Numba
kernels below.
Returns one entry per component with eigenvalues and normalized
eigenvalues. For spin-2 components the result additionally contains
separate E- and B-mode eigenspectra.
C_ell (numpy.ndarray, dict, or None) – Power spectrum (required for “total_covariance” and “snr” bases).
Returns:
One dict per component with keys: component, spin,
label, eigenvalues, normalized_eigenvalues.
Spin-2 components additionally have E_eigenvalues,
E_normalized, B_eigenvalues, B_normalized.
Plot eigenvalue spectrum for compression threshold selection.
Creates one subplot per component. The y-axis shows eigenvalues
normalized by the maximum value, so values can be directly used as the
epsilon constructor kwarg of PixelBasis. For spin-2
components the E and B sub-spectra are shown as dashed curves when
show_eb_split is True.
fig (matplotlib.figure.Figure) – The figure containing the plot.
axes (numpy.ndarray) – 1-D array of Axes (length n_components).
Examples
>>> # Pick threshold by plotting first, then construct a compressed basis.>>> # The probe construction uses epsilon=0.0 to opt into the V-based>>> # path (keeps all modes) so plot_eigenvalue_spectrum has V to read.>>> ppc_probe=PixelBasis(... N,theta,phi,lmax_signal=100,epsilon=0.0,... )>>> ppc_probe.setup()>>> fig,axes=ppc_probe.plot_eigenvalue_spectrum(basis="noise_weighted")>>> # From the plot, decide threshold (e.g., 1e-4).>>> ppc=PixelBasis(... N,theta,phi,lmax_signal=100,... epsilon=1e-4,compression_target="noise_weighted",... )>>> ppc.setup()
In pixel-direct mode this is the exact (N+S)^{-1}; on a
truncated compressed basis it is (U^T(N+S)U)^{-1} —
the inverse of the restricted operator on the kept subspace.
Parameters:
C_ell (numpy.ndarray or dict) – Power spectrum (array for single-field, dict for multi-field).
In pixel-direct mode this is the exact N+S; on a truncated
compressed basis it is U^T(N+S)U — the restriction of
the full covariance to the kept subspace.
Parameters:
C_ell (numpy.ndarray or dict) – Power spectrum (array for single-field, dict for multi-field).
In pixel-direct mode this equals the full pixel-space quadratic
form d^T(N+S)^{-1}d. On a truncated compressed basis it
is (U^Td)^T(U^T(N+S)U)^{-1}(U^Td) — the quadratic
form of the restricted operator on the kept subspace.
Parameters:
data (numpy.ndarray) – Pixel-space data vector of length n_pix.
C_ell (numpy.ndarray or dict) – Power spectrum (array for single-field, dict for multi-field).
C_ell (numpy.ndarray or dict) – Power spectrum. Single-field: numpy.ndarray. Multi-field: dict
keyed by SpectrumKey.
spectra_list (list[SpectrumKey] or None) – For multi-field, the list of SpectrumKey instances enumerating
the spectra to include. None for single-field.
symmetry_mode (SymmetryMode or None) – Forwarded to the per-ℓ derivative builder. None keeps the
SYMMETRIC default. Required as DIRECTIONAL when
spectra_list contains a CG cross-pair entry — the
builder otherwise rejects the mode=2 slot used by CG.
Compute the log determinant of the basis-space covariance.
In pixel-direct mode this equals the exact full log|N+S|.
On a truncated compressed basis it is the logdet of the
restricted operator U^T(N+S)U — not the full
log|N+S|; see get_full_logdet() for the ABC contract.
Parameters:
C_ell (numpy.ndarray or dict) – Power spectrum (array for single-field, dict for multi-field).
Reconstruct full n_pixxn_pix inverse from the basis-space form.
Exact in pixel-direct mode (U is the identity). Lossy on a
truncated compressed pixel basis — the result lives in the kept
subspace and is zero on the truncated complement.
The selector configured at construction (compression_target kwarg).
Names the matrix that _apply_compression eigendecomposes:
"harmonic", "noise_weighted", "total_covariance", or
"snr". Returns the configured value regardless of whether
compression has actually been applied yet.