Skip to content

pol gradient fixes + tests to main (v1.3.2)#307

Merged
achael merged 15 commits into
mainfrom
fix/main-pol-grad
Jun 16, 2026
Merged

pol gradient fixes + tests to main (v1.3.2)#307
achael merged 15 commits into
mainfrom
fix/main-pol-grad

Conversation

@achael

@achael achael commented Jun 16, 2026

Copy link
Copy Markdown
Owner

What & why

Patches a latent bug in the polarimetric imager gradients on main,
mirroring the dev fix in #306, and fixes several further latent
pol-gradient bugs uncovered while adding test coverage. Ships an interim
gradient-validation suite and wires it into CI.

Core fix (mirrors #306)

  • physical_grad_slots separates the physical-gradient mask from the
    solve mask, centralizing the mcv/vcv cross-coupling (one solved pol DOF
    drives BOTH rho and psi). Fixes IP imaging when V!=0 (and the IV analog).
  • mcv_grad/vcv_grad: add the off-diagonal Jacobian terms (dpsi/dm',
    drho/dv'); return 3-wide and assign to outarr[1:4] so the Stokes-I log
    Jacobian survives. Same preservation for the polcv path.
  • stv_pol_grad (ptv): first-row/col back-neighbor masking (corner was
    ~4x off vs finite differences).

Further latent bugs fixed (found via the new tests; all pre-existing, all in never-exercised Stokes-I / V-flux slots)

These paths are already correct on dev -- its gradient test coverage caught
them; this PR backports the equivalent fixes to main.

  • chisqgrad_m: restore dropped mimage*exp(-2i*chi) factor (was a
    TypeError from np.real( * ...)).
  • smgrad / svfluxgrad: outgrad / gradoutout -> gradout (NameError).
  • make_chisq_dict: pass the Stokes-I row to chisq for standard data
    terms in pol mode (the gradient path was already correct).

#233 port

  • NumPy >= 1.24 fixes (dtype=object on ragged diag arrays, np.float ->
    float) so the diagonalized closures build.

Tests + CI

  • tests/test_gradients_main_tmp.py: interim gradient suite (71 tests) --
    nfft-vs-direct, analytic-vs-FD for all intensity/pol chi^2 terms and
    regularizers, and the mcv/vcv/polcv transforms vs FD (isolated +
    end-to-end through the Imager objective). Temporary; delete when dev
    lands on main.
  • CI test job on py3.8 + py3.11 running the suite (pynfft absent in CI
    -> nfft cases skip, direct-FT cases run).
  • Drop the *test* gitignore rule (it hid top-level tests/).

Version

  • Bump to 1.3.2.

How to test

python3 -m pytest tests/test_gradients_main_tmp.py
System python (has pynfft): 71 pass. Without pynfft: 44 pass + 12 nfft-skip.

Design decisions

  • Interim suite is intentionally gradient-only; broader coverage comes
    from dev.
  • Pol fixtures build Q/U/V manually instead of add_random_pol, avoiding a
    scipy-version-fragile scattering path (and the rect-image scattering bug).
  • nfft gated on pynfft (what main's nfft ttype actually uses).

achael added 15 commits June 16, 2026 12:01
Pre-existing bugs in pol-gradient slots that only run when Stokes I is
solved together with polarization (normally I is held fixed, so these
never executed). Found while building gradient tests:
- chisqgrad_m: restore dropped mimage*exp(-2i*chi) factor in dchi2/dI
  (was `np.real(  * ...)` -> TypeError)
- smgrad: outgrad -> gradout (NameError)
- svfluxgrad: gradoutout -> gradout (NameError)
- make_chisq_dict: pass the Stokes-I row to chisq for standard data
  terms in pol mode, matching the (already-correct) gradient path
Start of tests/test_gradients_main_tmp.py — a temporary suite validating
main's gradients before dev replaces main (mirrors PR #306's gradient
tests against main's API). This commit: fixtures + tolerances + nfft gate,
and intensity chi^2 gradient-vs-FD checks for all DATATERMS (direct+nfft).
The two diagonalized-closure cases fail until the #233 NumPy>=1.24
chisqdata fix is ported (next commit).

Also drop the `*test*` gitignore rule (it hid the top-level tests/ dir)
and replace it with an explicit .pytest_cache/ ignore.
main's diag-closure chisqdata/chisqgrad crash on NumPy >= 1.24:
- np.array() on ragged per-timestamp matrices -> add dtype=object in the
  six chisqdata_{cphase,logcamp}_diag{,_fft,_nfft} builders
- np.float (removed in 1.24) -> float in the six diag-gradient normalizers

Mirrors dev's #233 (minus dev's unrelated nfft block_diag restructure).
Unblocks the cphase_diag / logcamp_diag gradient tests (now passing).
Adds to test_gradients_main_tmp.py:
- intensity chi^2 nfft-vs-direct agreement (value + relative-L2 gradient)
- intensity regularizer gradient vs FD
- pol chi^2 gradient vs central FD (all 4 slots; vvis EVPA slot == 0),
  direct + nfft, plus pol chi^2 nfft-vs-direct agreement
- pol regularizer gradient vs central FD (all 8 REGULARIZERS_POL)

51 passing. logamp uses debias=False (noise-free obs); pol fixtures use a
square grid (add_random_pol scattering rect bug on main).
Completes test_gradients_main_tmp.py:
- boundary FD for ptv/vtv/tv (pins the #306 first-row/col mask fix)
- transform_gradients chain-rule vs FD for mcv/vcv/polcv, incl. the
  off-diagonal cross-terms and log-I-slot preservation
- end-to-end objective FD (objgrad vs FD of objfunc) sampling the pol DOF
  block for IP/mcv, IV/vcv, IQUV/polcv x {direct, nfft}

Full suite: 71 passing.
- gate nfft cases on pynfft (what main's nfft ttype actually uses), not
  the unrelated `nfft` PyPI package
- build pol fixtures manually (smooth + jittered Q/U/V) instead of
  add_random_pol, whose scattering phase screen calls scipy.integrate.quad
  in a way that breaks on newer scipy (and on rectangular grids); pol
  fixtures return to 32x48 rect

71 pass (system, with pynfft); 44 pass + 12 nfft-skip without pynfft.
Add a test job to .github/workflows/ci.yml running only
tests/test_gradients_main_tmp.py on Python 3.8 and 3.11. pynfft is not
installed in CI, so the nfft cases skip and the direct-FT cases run.
@achael achael self-assigned this Jun 16, 2026
@achael achael requested a review from rohandahale June 16, 2026 12:46
@achael achael marked this pull request as ready for review June 16, 2026 12:46
@achael achael added the bug label Jun 16, 2026

@rohandahale rohandahale left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I reviewed and ran the gradient tests locally and all of them pass. Looks good to merge!

@achael achael merged commit c8c7a89 into main Jun 16, 2026
3 checks passed
@achael achael deleted the fix/main-pol-grad branch June 17, 2026 09:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants