Skip to content

fix: name the contract when V-dependent consumers run after release_pixel_projector - #47

Merged
ggalloni merged 3 commits into
masterfrom
fix/harmonic-basis-released-v-guard
Jul 14, 2026
Merged

fix: name the contract when V-dependent consumers run after release_pixel_projector#47
ggalloni merged 3 commits into
masterfrom
fix/harmonic-basis-released-v-guard

Conversation

@ggalloni

Copy link
Copy Markdown
Owner

Closes #18HarmonicBasis: V-dependent consumers raise opaque numpy error after release_pixel_projector().

The bug

HarmonicBasis.release_pixel_projector() drops the pixel projector V. Its docstring already documented the contract: get_covariance, get_inverse, to_basis, m-block compression and PICSLike harmonic do_cross must not be invoked afterwards. The contract was documented but never enforced. _V_N_VT reads self._V lazily, so a post-release caller passed None into matrix_mult and got:

ValueError: matmul: Input operand 0 does not have enough dimensions (has 0, ...)

Reproduced before fixing — the new test failed with exactly that numpy error on get_covariance, get_inverse and to_basis, and projector silently returned None. This is a diagnosability fix, not a correctness one: nothing computed the wrong answer, the error just pointed at the wrong place.

The fix

Every V read on the harmonic path funnels through the _V accessor, so a single guard there covers all five consumers rather than five hand-written guards. release_pixel_projector() flips a flag; _V raises a RuntimeError that names the contract and says to skip the release if those consumers are needed downstream:

The pixel projector V was dropped by release_pixel_projector(); get_covariance, get_inverse, to_basis, the projector property, m-block compression and PICSLike do_cross all read V and are unsupported afterwards. Skip release_pixel_projector() if any of them are needed downstream.

Release also drops any materialised _V_N_VT cache, so get_covariance fails the contract check deterministically instead of silently serving a primed cache — and frees an n_modes² buffer, which is what the method is for.

Scope notes

  • The Fisher hot path reads only _V_N_inv and _V_Ninv_VT, so it is unaffected. All existing Fisher and PICSLike tests pass unmodified.
  • get_full_inverse and get_full_logdet turned out to be V-free too — they work fine after release and are not part of the contract. The tests now pin that down so the guard can't creep over them.
  • PixelBasis is untouched; release is a no-op there.
  • Release stays one-way and _V_N_VT stays lazy, per the issue's out-of-scope list.

Verification

Reproduced the failing path end-to-end (build harmonic basis → release_pixel_projector() → call each consumer, mirroring what qube/fisher.py then picslike.py do to a shared basis manager), not just via the suite. All three suites green: cosmocore 539 passed, qube 172 passed / 10 skipped, picslike 99 passed / 2 skipped.

…r release_pixel_projector

HarmonicBasis.release_pixel_projector() drops V, and its docstring already
documented that get_covariance, get_inverse, to_basis, m-block compression
and PICSLike do_cross must not run afterwards. The contract was documented
but not enforced: _V_N_VT reads _V lazily, so a post-release caller passed
None into matrix_mult and got 'ValueError: Input operand 0 does not have
enough dimensions' — an unrelated linear-algebra error.

Every V read on the harmonic path funnels through the _V accessor, so one
guard there covers all of them. release_pixel_projector now flips a flag and
drops any materialised _V_N_VT cache, so get_covariance fails the contract
check instead of silently serving a primed cache.

The Fisher hot path reads only _V_N_inv and _V_Ninv_VT and is unaffected;
get_full_inverse and get_full_logdet are V-free too and keep working after
release, which the tests now pin down.
@codecov

codecov Bot commented Jul 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.63%. Comparing base (a757c9a) to head (1bdc663).

Additional details and impacted files
@@            Coverage Diff             @@
##           master      #47      +/-   ##
==========================================
+ Coverage   92.58%   92.63%   +0.05%     
==========================================
  Files          40       40              
  Lines        5084     5092       +8     
==========================================
+ Hits         4707     4717      +10     
+ Misses        377      375       -2     
Flag Coverage Δ
cosmocore 92.29% <100.00%> (+0.07%) ⬆️
mpi 92.55% <100.00%> (+0.05%) ⬆️
nompi 91.20% <100.00%> (+0.05%) ⬆️
picslike 96.83% <ø> (ø)
qube 92.02% <ø> (ø)

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

Files with missing lines Coverage Δ
...c/cosmoforge.cosmocore/cosmocore/basis/harmonic.py 92.92% <100.00%> (+0.61%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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 improves diagnosability in cosmocore by enforcing the already-documented post-HarmonicBasis.release_pixel_projector() contract: V-dependent consumers now fail with a clear, contract-naming RuntimeError instead of an opaque NumPy matmul error.

Changes:

  • Add a single guarded accessor for the pixel projector (_V) that raises a descriptive RuntimeError after release_pixel_projector().
  • Ensure any materialized _V_N_VT cache is dropped on release so post-release V consumers fail deterministically and memory is freed.
  • Add regression tests covering post-release failures for key V consumers and confirming V-free consumers still work; document the behavior in the changelog.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/cosmoforge.cosmocore/cosmocore/basis/harmonic.py Enforces the post-release contract via a guarded _V accessor and clears _V_N_VT cache on release.
src/cosmoforge.cosmocore/tests/test_harmonic_basis.py Adds tests asserting V-dependent consumers raise post-release and V-free hot-path consumers remain usable.
docs/source/changelog.rst Notes the clearer post-release RuntimeError behavior for harmonic V consumers.

Comment thread src/cosmoforge.cosmocore/cosmocore/basis/harmonic.py Outdated
@ggalloni
ggalloni marked this pull request as ready for review July 14, 2026 13:57
@ggalloni
ggalloni merged commit 956b356 into master Jul 14, 2026
21 checks passed
@ggalloni
ggalloni deleted the fix/harmonic-basis-released-v-guard branch July 14, 2026 14:01
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.

HarmonicBasis: V-dependent consumers raise opaque numpy error after release_pixel_projector()

2 participants