Repository navigation
test: re-pin knife-edge positions_threshold pins after the exact grid transform (PyAutoArray#519) #721
Description
Overview
PyAutoLens main is RED (pyauto-heart readiness --json reason PyAutoLens: CI failure). Two tests in test_autolens/analysis/test_result.py pin a point-solver quantity on an exactly mirror-symmetric fixture, and PyAutoArray#519 moved them. Bisected: #519's rotation-matrix rewrite of transform_grid_2d_to_reference_frame (commit f45b30b0) is the sole mover — it made the transform an exact identity at angle 0, so the on-axis deflection is now exactly 0.0 instead of 6.1e-17, the solver hits an exact tie, and the tie-break selects the other branch.
The new values are the more accurate branch (exact transform, exact on-axis zero). Nothing in the library is wrong. This is a test-only re-pin plus a comment recording the sensitivity, opened as a corrective PR so PyAutoLens main goes green again.
Plan
- Re-pin the four literals in
test_autolens/analysis/test_result.pyat the existing1.0e-4tolerances. - Add a short comment above each pin explaining the mirror symmetry, the sub-ULP tie-break, PyAutoArray#519 as the cause, and the
1e-15flip-back sensitivity. - No library change; no tolerance change.
- Follow-up (filed separately): move the fixture off the symmetry axis so the pin is stable rather than branch-selected.
Detailed implementation plan
Affected Repositories
- PyAutoLens (primary)
Branch Survey
| Repository | Current Branch | Dirty? |
|---|---|---|
| ./PyAutoLens | main | clean (README.md only, unrelated) |
Suggested branch: feature/positions-threshold-repin
Implementation Steps
test_autolens/analysis/test_result.py::test__positions_threshold_from—0.0019501455→0.0019534291;0.0097507278035→0.0097671455155. Keep1.0e-4.test_autolens/analysis/test_result.py::test__positions_likelihood_from__mass_centre_radial_distance_min—positions[1](1.00097656e00, -5.63818622e-04)→(1.00097656e00, 5.63818622e-04).positions[0]unchanged. Keep1.0e-4.- Add the knife-edge comment above each pin.
pytest test_autolens -n 4 -q;ruff check/ruff format --check.
Key Files
test_autolens/analysis/test_result.py— the only file changed.
Measurements
| quantity | pre-#519 | post-#519 |
|---|---|---|
positions_threshold_from() |
0.0019501455607163743 |
0.0019534291030939357 |
positions_threshold_from(factor=5.0) |
0.009750727803581872 |
0.009767145515469679 |
positions[1] |
(1.0009765625, -5.638186222554754e-04) |
(1.0009765625, 5.638186222554754e-04) |
| transform error at angle 0 | 8.9e-16 |
0.0 (exact identity) |
on-axis alpha_x |
6.1e-17 |
0.0 |
A 1e-15 nudge of the lens centre in x flips the threshold back to the old value; a 1e-6 nudge moves it by a factor of 86.
Original Prompt
Click to expand starting prompt
Re-pin the knife-edge positions_threshold tests after PyAutoArray#519's exact grid transform
Type: bug
Target: autolens
Repos:
- @PyAutoLens
Themes: - point-source
- testing
Difficulty: small
Autonomy: supervised
Priority: high
Status: draft
Filed: 2026-09-03
Symptom
PyAutoLens main is RED (pyauto-heart readiness --json reason PyAutoLens: CI failure).
Two tests in test_autolens/analysis/test_result.py fail against the current library mains:
test__positions_threshold_from—positions_threshold_from()returns
0.0019534291030939357, pinned at0.0019501455607163743;positions_threshold_from(factor=5.0)
returns0.009767145515469679, pinned at0.009750727803581872.test__positions_likelihood_from__mass_centre_radial_distance_min—positions[1]returns
(1.0009765625, 0.0005638186222554754), pinned at(1.00097656e00, -5.63818622e-04); the x
component has flipped sign and its magnitude is bit-identical.positions[0]is unchanged at
(-1.0009765625, 0.0005638186222554754).
Bisect attribution
Bisected across the day's PyAutoArray/PyAutoGalaxy merges with detached scratch worktrees, holding
PyAutoLens fixed:
| PyAutoArray | PyAutoGalaxy | result | positions_threshold_from() |
|---|---|---|---|
main |
main |
FAIL | 0.0019534291030939357 |
62feb7eb^ |
main |
PASS | 0.0019501455607163743 |
main |
50599c2c |
FAIL | — |
main |
2c729217 |
FAIL | — |
main |
8d152b15 |
FAIL | — |
62feb7eb^ |
8d152b15 |
PASS | — |
PyAutoArray#519's rotation-matrix rewrite of transform_grid_2d_to_reference_frame (commit
f45b30b0) is the sole mover. The three PyAutoGalaxy merges are bit-neutral.
Accuracy verdict
The fixture is exactly mirror-symmetric: the Isothermal lens centre is (0.1, 0.0), the
SersicSph source is at (0.0, 0.0), ell_comps=(0.0, 0.0) — both lie on x = 0. The new
transform is an exact identity at angle 0 (measured error 0.0; the old polar
cos/sin-of-arctan2 form carried 8.9e-16). Consequently the on-axis deflection alpha_x is now
exactly 0.0 where it was 6.1e-17. The point solver therefore hits an exact tie and its
tie-break selects the other branch, sending both images to the same side of the axis.
The new values are the more accurate branch — they come from an exact transform and an exact
on-axis zero. Nothing in the library is wrong; the pinned quantity is a knife-edge, not a physical
constant.
Knife-edge numbers
- pre-docs(api): sync mass.rst with full al.mp namespace + add lmp / lmp_linear sections #519 transform error at angle 0:
8.9e-16; post-docs(api): sync mass.rst with full al.mp namespace + add lmp / lmp_linear sections #519:0.0(exact identity). - on-axis
alpha_x: pre6.1e-17, post0.0. - nudging the lens centre in x by
1e-15flipspositions_threshold_from()straight back to the
old value0.0019501455607163743. - nudging by
1e-6moves the threshold by a factor of 86. - the
positions[1].xflip is a sign change only:5.638186222554754e-04is bit-identical either
way, and is itself a grid-step artefact.
Fix
Test-only re-pin. Update the four literals in test_autolens/analysis/test_result.py
(0.0019501455 → 0.0019534291, 0.0097507278035 → 0.0097671455155, positions[1] x sign) at
the existing 1.0e-4 tolerances, and add a comment above each pin recording that the fixture is
exactly mirror-symmetric, that the branch is decided by sub-ULP tie-breaking, that PyAutoArray#519's
exact identity transform selected the other branch, and that a 1e-15 centre nudge flips it back.
No library change.
Follow-up suggestion
File separately: move the fixture off the symmetry axis (a small x offset on the lens centre, or a
non-zero ell_comps) so the pin measures a stable physical quantity rather than a solver
tie-break. As it stands the test will keep re-breaking on any floating-point-level change anywhere
in the transform/deflection chain.
Activity
Jammy2211 commentedon Sep 3, 2026
Bisect
PyAutoLensheld fixed at6fbab3b52; PyAutoArray/PyAutoGalaxy swapped in detached scratch worktrees.62feb7eb^is the commit before PyAutoArray#519's merge;f45b30b0inside it is the rotation-matrix rewrite oftransform_grid_2d_to_reference_frame.positions_threshold_from()mainmain0.001953429103093935762feb7eb^main0.0019501455607163743main50599c2cmain2c729217main8d152b1562feb7eb^8d152b15PyAutoArray#519 is the sole mover: the failure follows PyAutoArray alone and is indifferent to every PyAutoGalaxy merge of the day (
50599c2c,2c729217,8d152b15are all bit-neutral).Mechanism, measured:
transform_grid_2d_to_reference_frameis an exact identity at angle 0 (error0.0); pre-docs(api): sync mass.rst with full al.mp namespace + add lmp / lmp_linear sections #519 it carried8.9e-16.alpha_x: post0.0, pre6.1e-17.Isothermalcentre(0.1, 0.0),ell_comps=(0.0, 0.0),SersicSphsource(0.0, 0.0)— both onx = 0), so the exact zero puts the point solver on an exact tie and the tie-break sends both images to the same side.1e-15flips the threshold straight back to the pre-docs(api): sync mass.rst with full al.mp namespace + add lmp / lmp_linear sections #519 value.1e-6moves the threshold by a factor of 86.So the pinned quantity is a solver tie-break, not a physical constant, and the new values are the more accurate branch.
Jammy2211 commentedon Sep 3, 2026
Library PR created — corrective re-pin at PR-open
PR: #722 (
pending-release)Test-only.
test_autolens/analysis/test_result.py— the four literals re-pinned to the exact-transform branch at the existing1.0e-4tolerances, with a comment above each pin recording the mirror symmetry, the sub-ULP tie-break, PyAutoArray#519 as the cause, and the1e-15flip-back. No library change.Gate evidence on the current library
mains (PyAutoArray7968d671, PyAutoGalaxya647aa32):pytest test_autolens/analysis/test_result.py -q→ 14 passedpytest test_autolens -n 4 -q→ 610 passed, 1 xfailedMerge first so PyAutoLens main goes green; then
/prm.Heart is RED and was human-acknowledged for PR-open on 2026-09-03; exact reasons from
pyauto-heart readiness --json: "PyAutoLens: CI failure" (this PR is the human-authorized corrective PR for that reason); "release validation FAILED (stage integrate)"; "PyAutoArray: open PR 11d old". Never merge without the human.Generated by Claude Code
Jammy2211 commentedon Sep 3, 2026
Shipped
PR #722 — MERGED (
c6c2a06a9), test-only.Cause. PyAutoArray#519 (
f45b30b0) made the grid transform an exact identity at angle 0 — therotation that previously left an 8.9e-16 residual now returns the input bit-for-bit. On the symmetry
axis the deflection is therefore exactly
0.0rather than a denormal, and the position solver'stie-break picks the other branch. The two
test_result.pypins moved by that flip, and by nothing else:positions_threshold_from()0.0019501455607 → 0.0019534291031 (+1.7e-3 relative)positions[1].x— sign flip with bit-identical magnitudeEvidence. A 6-cell bisect matrix across the candidate commits isolates PyAutoArray#519
f45b30b0;PyAutoGalaxy #599/#602/#603 are bit-neutral. It is a genuine knife edge: a 1e-15 x-nudge of the fixture
flips the branch back, and a 1e-6 nudge moves the threshold by ×86. A pre-existing
Isothermal.axis_ratio()clip at 0.99999 gives a 1.7e-6 bias against
IsothermalSph— real, but unrelated to this move.test_autolens: 610 passed, 1 xfailed.Follow-up filed: move the fixture off the symmetry axis so the pin stops sitting on a tie-break
(
PyAutoMind draft/bug/autolens/positions_threshold_fixture_off_axis.md).Record:
PyAutoMind complete/2026/09/positions-threshold-repin.md. PyAutoLens is pending-release.