Skip to content

Keep Variance/InverseVariance uncertainty propagation in the array namespace - #975

Merged
mwcraig merged 3 commits into
astropy:mainfrom
mwcraig:fix-962-variance-wrappers
Aug 23, 2026
Merged

Keep Variance/InverseVariance uncertainty propagation in the array namespace#975
mwcraig merged 3 commits into
astropy:mainfrom
mwcraig:fix-962-variance-wrappers

Conversation

@mwcraig

@mwcraig mwcraig commented Aug 22, 2026

Copy link
Copy Markdown
Member

_VarianceUncertaintyWrapper and _InverseVarianceWrapper in ccdproc/_ccddata_wrapper_for_array_api.py were bare subclasses, so arithmetic on a CCDData carrying a VarianceUncertainty / InverseVariance went through astropy's default to_variance / from_variance hooks and the propagated uncertainty escaped to NumPy on JAX (and other non-NumPy backends).

This PR factors the four _propagate_add/subtract/multiply/divide overrides that _StdDevUncertaintyWrapper already had into a small _ArrayAPIPropagationMixin; each wrapper supplies namespace-aware hooks via _variance_hooks(xp):

  • StdDev: xp.square / xp.sqrt (unchanged behaviour)
  • Variance: identity / xp.asarray
  • InverseVariance: 1/x / 1/xp.asarray(x)

The two jax backend_xfail params on test_cosmicray_gain_correct (VarianceUncertainty and InverseVariance with gain_apply=True) are removed; under jax they go XPASS -> PASS.

Note: intermediates may still round-trip through NumPy inside astropy's _VariancePropagationMixin itself (it calls np.sqrt / np.abs and checks isinstance(correlation, np.ndarray)); that is upstream and tracked in #940. This PR only fixes the ccdproc-side wrapper so the result stays in the data's namespace.

Test matrix

backend pytest ccdproc
numpy 380 passed, 5 skipped
jax (JAX_ENABLE_X64=True) 368 passed, 10 skipped, 7 xpassed (same 7 XPASS as on main; 2 fewer xfails — the two removed here)
dask 370 passed, 15 skipped
dask + CCDPROC_ENFORCE_ESCAPE_BASELINE=1 370 passed, 15 skipped

ccdproc/tests/test_cosmicray.py under array-api-strict: 1 failed, 7 passed, 33 xfailed both before and after (pre-existing failure, unrelated).

Fixes #962

🤖 Generated with Claude Code

https://claude.ai/code/session_01DTN9DnPnLKK2u7knnMJ2gA

@codecov

codecov Bot commented Aug 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.88%. Comparing base (c37c0de) to head (00bfd12).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #975      +/-   ##
==========================================
+ Coverage   96.31%   96.88%   +0.56%     
==========================================
  Files           9        9              
  Lines        1684     1701      +17     
==========================================
+ Hits         1622     1648      +26     
+ Misses         62       53       -9     
Flag Coverage Δ
dask 95.99% <100.00%> (+0.57%) ⬆️
jax 96.10% <100.00%> (+0.57%) ⬆️
numpy 96.76% <100.00%> (+0.56%) ⬆️

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

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@mwcraig
mwcraig marked this pull request as ready for review August 22, 2026 18:24
@mwcraig
mwcraig force-pushed the fix-962-variance-wrappers branch from 088dc12 to 9549a1a Compare August 23, 2026 14:35
mwcraig and others added 2 commits August 23, 2026 13:08
…mespace

_VarianceUncertaintyWrapper and _InverseVarianceWrapper were bare
subclasses, so their propagation went through astropy's default
to_variance/from_variance hooks and the result escaped to NumPy on JAX
and other non-NumPy backends. Factor the four _propagate_* overrides
from _StdDevUncertaintyWrapper into a shared _ArrayAPIPropagationMixin
whose subclasses supply the namespace-aware hooks, and use it for all
three wrapper classes.

Remove the two jax backend_xfail markers in test_cosmicray.py that
covered this; they now pass outright.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DTN9DnPnLKK2u7knnMJ2gA
@mwcraig
mwcraig force-pushed the fix-962-variance-wrappers branch from 60d9004 to dccb3a5 Compare August 23, 2026 18:15
codecov reported the patch at 95% with one line missing:
`raise NotImplementedError` in `_ArrayAPIPropagationMixin._variance_hooks`.

That line is listed in `exclude_lines` in pyproject.toml, so it does not
show as missing when coverage is reported locally from the repository
root. CI does not apply the exclusion: tox runs `coverage xml` without
`--rcfile`, from a directory that has no pyproject.toml, so the report
uploaded to codecov is built with default settings. Confirmed by
regenerating the XML the same way, which reproduces codecov's missing
line list exactly.

Cover the line with a direct test rather than relying on the exclusion.
It is a real contract worth asserting -- a subclass that forgets to
override `_variance_hooks` should fail loudly instead of silently
propagating with the wrong variance conversions -- and it holds no
matter how the coverage report is generated.
@mwcraig
mwcraig merged commit d85524a into astropy:main Aug 23, 2026
19 checks passed
@mwcraig
mwcraig deleted the fix-962-variance-wrappers branch August 23, 2026 18:30
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.

Variance and InverseVariance uncertainty propagation escapes to numpy on jax (only the StdDev wrapper is array-API-aware)

1 participant