Repository navigation
fix: single-image recovery blind to inf-padded JAX solver output #771
Description
Overview
Result.image_plane_multiple_image_positions in autolens/analysis/result.py triggers the inward-walk single-image recovery when multiple_images.shape[0] <= 1. Under a JAX-backed analysis (xp=jnp) the point solver returns a static-shape array padded with (inf, inf) rows (remove_infinities defaults to xp is np since #759), so the shape test is never true and recovery can never fire. Since PyAutoLens#765 (discussion https://github.com/orgs/PyAutoLabs/discussions/30) a 1-image JAX solve then raises PositionsException at PositionsLH construction, so JAX SLaM chains could error where they used to run. Padded rows are also written into the cached files/multiple_image_positions.json.
Plan
- Count finite solver rows (not array length) before deciding whether the single-image recovery runs.
- When two or more finite images exist, return only the finite rows, so downstream consumers and the cached JSON are clean.
- Apply the same finite-row count inside the inward-walk recovery loop.
- Unit tests: padded 1-image array triggers recovery; padded 2-image array returns exactly the 2 finite rows; unpadded numpy output unchanged. Witness: padded-1-image test fails on main, passes with the fix.
Detailed implementation plan
Affected Repositories
- PyAutoLens (primary)
Branch Survey
| Repository | Current Branch | Dirty? |
|---|---|---|
| ./PyAutoLens | main | clean |
Suggested branch: feature/padded-single-image-recovery
Implementation Steps
- In
autolens/analysis/result.pyimage_plane_multiple_image_positions(theif multiple_images.shape[0] <= 1:block), computefinite = np.isfinite(np.asarray(multiple_images)).all(axis=1); iffinite.sum() <= 1callimage_plane_multiple_image_positions_for_single_image_from(); else returnaa.Grid2DIrregular(values=np.asarray(multiple_images)[finite]). Keep the zero-images comment accurate and extend it to explain inf padding. - In
image_plane_multiple_image_positions_for_single_image_from, apply the same finite-row count to themultiple_images.shape[0] > 1test and return only finite rows. - Tests in
test_autolens/analysis/test_result.py: monkeypatchPointSolver.solveto return (a) 1 finite row + inf rows → recovery helper called; (b) 2 finite rows + inf rows → exactly the 2 finite rows; (c) unpadded 2-row numpy array → unchanged. - Witness: run test (a) on unfixed source (fails) and with the fix (passes).
- Run
python -m pytest test_autolens/analysis -qand the fulltest_autolenssuite.
Key Files
autolens/analysis/result.py—image_plane_multiple_image_positions,image_plane_multiple_image_positions_for_single_image_fromtest_autolens/analysis/test_result.py— new tests
Pin risk: none for finite inputs (numpy solver output contains no non-finite rows, so the filter is the identity).
Links: PyAutoLens#765, https://github.com/orgs/PyAutoLabs/discussions/30
Original Prompt
Click to expand starting prompt
PyAutoLens: single-image recovery in Result.image_plane_multiple_image_positions_from is blind to inf-padded JAX solver output
Type: bug
Target: PyAutoLens
Repos:
- PyAutoLens
Difficulty: medium
Autonomy: safe
Priority: normal
Memory: wiki/galaxies/sources/massive-ellipticals.md; wiki/lensing/sources/dark-matter-substructure.md; wiki/galaxies/sources/light-profile-fitting.md
Status: formalised
Consequence: judge
Witness: a new test in test_autolens feedingimage_plane_multiple_image_positions_froma 1-image array padded with inf rows fails on main and passes with the fix
Review-minutes: 20
Unattended: ready
PyAutoLens: single-image recovery in Result.image_plane_multiple_image_positions_from is blind to inf-padded JAX solver output.
Found while reviewing community PR PyAutoLens#765 (@samlange04, discussion https://github.com/orgs/PyAutoLabs/discussions/23 sibling report #30). In autolens/analysis/result.py (around line 138) the inward-walk recovery for a single-image solve tests multiple_images.shape[0] <= 1. With a JAX-backed analysis the point solver (xp=jnp, remove_infinities defaults to xp is np since #759) returns a static-shape array padded with (inf, inf) rows (20 rows), so the shape test is always false and the recovery can never fire under JAX. After #765 (which drops non-finite rows at PositionsLH construction and raises PositionsException when fewer than 2 finite rows remain) a 1-image JAX solve now raises at construction instead of silently scoring zero penalty. Fail-loud is better than silent zero, but SLaM chains on JAX could start erroring where they used to run.
Fix: count finite rows (np.isfinite(...).all(axis=1).sum()) before the <= 1 check, or strip non-finite rows before it, so the recovery path triggers for padded output exactly as it does for the numpy solver. Add a unit test feeding a padded 1-image array and asserting the recovery path runs (and a 2-image padded array does not). Not yet reproduced with a real 1-image JAX solve; severity unknown. Check that the cached files/multiple_image_positions.json written from padded positions still round-trips.
Activity
Jammy2211 commentedon Oct 7, 2026
Library PR created: #772. Finite-row count in both the top-level solve and the inward walk; witness: 3 of 4 new tests fail on main, all pass with the fix; test_autolens/analysis 101 passed, full test_autolens 831 passed / 1 xfailed. No public API change, no workspace impact; pin risk none for finite (NumPy) inputs. Awaiting human /prm.
Jammy2211 commentedon Oct 7, 2026
Shipped: merged in #772 as 384e86e (pending release). Closing.