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
Browse filesBrowse the repository at this point in the historyBrowse files
authored and
Jammy2211
committed
fix: widen scalar pixel_scales / shape_native at the two sites #464 missed
PyAutoArray#464 (`8298d74e`) replaced `type(x) is float` with
`validate.is_concrete_scalar` in `convert_pixel_scales_1d` and
`convert_pixel_scales_2d`, so any concrete real scalar widens to the tuple form
both functions promise. Re-running that prompt's repro found the sweep did not
reach every site of the same defect. Two were still live on main.
`Mask1D.__init__` hand-rolled its own widening and never routed through
`convert_pixel_scales_1d`, so it still carried the original exact-type check.
`Mask1D(mask=..., pixel_scales=1)` stored the bare `1`, and the mask's geometry
then raised `TypeError: 'int' object is not subscriptable` — #464's exact
reported symptom, on a public constructor. `Mask2D.__init__` already called
`convert_pixel_scales_2d`, and `Grid1D.uniform` reaches the chokepoint too, so
this was a 1D/2D divergence rather than a design choice. It now makes the same
call `Mask2D` makes.
That also brings `validate.validate_pixel_scales` to `Mask1D`, which is a
deliberate contract change: `Mask1D` now rejects `0`, negative and `nan` pixel
scales exactly as `Mask2D` already did. No test constructed one that way and all
12 library call sites pass real scales, so nothing needed adjusting to suit it.
`convert_shape_native_1d` kept `type(shape_native) is int`, which `8298d74e`
listed as not-fixed-there. `Array1D.full` is its sole caller and does
`shape_native[0]` on the result, so `Array1D.full(shape_native=np.int32(5))`
raised `IndexError: invalid index to scalar variable`. It now tests
`validate.is_concrete_integer` and casts to a Python `int`.
`is_concrete_integer` is new, beside `is_concrete_scalar`: `shape_native` counts
pixels rather than measuring them, so `is_concrete_scalar` is the wrong predicate
there — it would silently widen a `float`, which is a mistake worth surfacing.
`bool` exclusion and tracer-safety carry over unchanged, so both functions stay
safe inside a `jax.jit`; verified by compiling and running one.
Also tightened #464's own widening tests. `np.float64(1.0) == (1.0,)`
NumPy-broadcasts to `array([True])`, which is truthy, so their value-only
assertions passed on an unwidened NumPy scalar and tested nothing. Asserting
tuple-ness before the value makes them fail on the pre-#464 source (confirmed by
reverting it), where four of the six parametrisations previously passed
vacuously. The new tests here assert the same way for the same reason.
Not fixed here, needing its own change: tuple entries are still returned
unnormalised, so `convert_pixel_scales_2d((1, 1))` keeps its ints and
contradicts the `Tuple[float, float]` annotation. That alters return values on
paths which work today.
Validation: 1201 passed / 0 failed on the full test_autoarray suite. The 3
pre-existing pynufft failures `8298d74e` baselined no longer occur, so there was
nothing to baseline against. Every new assertion that claims regression coverage
was confirmed to fail without the source change; the boundary tests (tuple
unchanged, float/bool not widened, tracer passthrough) pass either way by design,
mirroring the ones #464 shipped.
Downstream blast radius is nil: PyAutoGalaxy and PyAutoLens only re-export
`Mask1D` and construct none, and neither uses `Array1D.full`/`zeros`/`ones`.
Closes#484
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fj1HoQa4hZPmbyyBYNJX62
0 commit comments