You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: derive numba PSF kernel y/x shifts from the correct kernel axes
Both numba PSF gathers in inversion_imaging_numba_util.py computed their
kernel half-widths from the transposed kernel axes -- the y shift from
kernel_native.shape[1] (the x axis) and the x shift from shape[0] (the y
axis):
kernel_shift_y = -(kernel_native.shape[1] // 2)
kernel_shift_x = -(kernel_native.shape[0] // 2)
For a square kernel the two are equal and nothing is observably wrong, which
is why every existing test passed. For a non-square odd PSF the gather is
mis-centred along both axes. This is reachable: kernels are validated as odd
per axis, never as square (exc.KernelException in operators/convolver.py:268
and structures/grids/uniform_2d.py:1153 both check parity only). With the
bounds guard from #456 in place the mis-centred reads are clipped rather than
reading uninitialized memory, so the failure mode is a silent wrong answer
rather than a crash.
In psf_precision_value_from the same variables also drive the pair-overlap
early-exit, so the transposition additionally dropped genuinely overlapping
image-pixel pairs on one axis while admitting non-overlapping ones on the
other. The swap corrects that test too; no separate change is needed.
Both sites are fixed together deliberately: they must agree on kernel
orientation, or the psf_weighted_data and psf_precision_operator paths would
disagree with each other.
Reproduced on the pre-fix source with a 3x5 kernel on a fully-unmasked 5x5
image: max|numba - numpy| = 1420.0, with the numba result being the numpy
result shifted; the square-kernel control matched to 0.0. Post-fix both
match to 0.0.
Tests:
- Parametrised the numba-vs-numpy equivalence test and the precision-operator
edge test over 3x3, 3x5, 5x3 and 5x7 kernels, so both orientations of
non-square are covered rather than only the wide one.
- Corrected the _reference_value helper in the precision-operator edge test,
which replicated the very transposition it was meant to catch and so was
not the independent reference its comment claimed.
- Added two direct orientation probes, one per gather, that read back which
pixel was actually gathered (single-tap kernel over a coordinate-encoding
map) instead of re-deriving the kernel walk.
Verified as a detector: against the unpatched source these fail 8 tests --
every non-square parametrisation plus both orientation probes -- while the
square-kernel cases still pass, which is precisely why the defect survived.
A repo-wide scan for half-width derivations confirms these were the only two
transposed sites; convolve_with_kernel_native, the numpy twin, the JAX
precision operator and array_2d_util resize centring were already correct.
Full test_autoarray suite: 1154 passed, 55 skipped.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KkZgzrxmQ9YQpSRVatEydp
0 commit comments