Skip to content

Commit d3638da

Browse files
committed
feat: xp-ify BrightnessZeroth — fixes AdaptSplitZeroth under JAX
BrightnessZeroth's pixel_signals_from call dropped the xp backend (the same bug class as the ExponentialKernel fix), raising TracerArrayConversionError under jax.jit/jax.grad on every mesh — including through AdaptSplitZeroth, whose zeroth leg routes through it. With xp threaded, AdaptSplitZeroth is FD-certified on the KNN meshes (8.2e-8 max rel err, jit-consistent to 3e-16). Standalone BrightnessZeroth traces and differentiates but is a supplement by design (weights vanish on high-signal pixels, leaving the system singular alone) — documented in the docstring. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013FSqnkgZv97PU9JdkCcthy
1 parent e3e277f commit d3638da

2 files changed

Lines changed: 17 additions & 10 deletions

File tree

autoarray/inversion/regularization/adapt_split_zeroth.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,11 @@ def __init__(
6060
6161
A full description of regularization and this matrix can be found in the parent `AbstractRegularization` class.
6262
63-
**JAX & gradient support** (2026-07 gradient sweep): not currently
64-
JAX-differentiable on either gradient-capable mesh family — the split
65-
leg is structurally incompatible with the rectangular meshes (shape
66-
error) and the zeroth/adapt legs hit numpy-on-traced-array operations
67-
on the Delaunay mesh family (``TracerArrayConversionError``).
63+
**JAX & gradient support** (xp-ported 2026-07-26): FD-certified on
64+
the Delaunay mesh family (KNN meshes, 8.2e-8 max rel err) — the
65+
zeroth leg's dropped-``xp`` call site in ``BrightnessZeroth`` was the
66+
blocker. Still structurally incompatible with the rectangular meshes
67+
(the split leg's shape mismatch, as ``ConstantSplit``).
6868
6969
Parameters
7070
----------

autoarray/inversion/regularization/brightness_zeroth.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,15 @@ def __init__(
8282
8383
A full description of regularization and this matrix can be found in the parent `AbstractRegularization` class.
8484
85-
**JAX & gradient support** (2026-07 gradient sweep): not yet xp-ported —
86-
the pixel-signal thresholding applies numpy operations to traced
87-
arrays, raising ``TracerArrayConversionError`` under ``jax.jit`` /
88-
``jax.grad`` on every mesh.
85+
**JAX & gradient support** (xp-ported 2026-07-26): the pixel-signals
86+
call now threads ``xp`` (it previously dropped the backend, raising
87+
``TracerArrayConversionError`` under ``jax.jit`` / ``jax.grad``), so
88+
the scheme is JAX-differentiable — the weights and diagonal matrix
89+
are smooth functions of the pixel signals, FD-certified through
90+
``AdaptSplitZeroth`` (8.2e-8 on the KNN meshes). Standalone use
91+
under-regularizes high-signal pixels (weights → 0 where the source
92+
is) and can leave the linear system singular — it is a supplement to
93+
a smoothing scheme by design, not a standalone regularization.
8994
9095
Parameters
9196
----------
@@ -120,7 +125,9 @@ def regularization_weights_from(self, linear_obj: LinearObj, xp=np) -> np.ndarra
120125
-------
121126
The regularization weights.
122127
"""
123-
pixel_signals = linear_obj.pixel_signals_from(signal_scale=self.signal_scale)
128+
pixel_signals = linear_obj.pixel_signals_from(
129+
signal_scale=self.signal_scale, xp=xp
130+
)
124131

125132
return brightness_zeroth_regularization_weights_from(
126133
coefficient=self.coefficient, pixel_signals=pixel_signals

0 commit comments

Comments
 (0)