feat: kernel-density CDF meshes RectangularKernelAdaptDensity/Image#374
Merged
Conversation
…ants Opt-in adaptive rectangular meshes whose per-axis CDF transform is a smooth kernel-density CDF F(x) = sum_i w_i * Phi((x - x_i)/h) (Enzi et al. arXiv:2606.30620 RTU formulation) instead of the empirical point-rank CDF. Strictly monotone by construction, C-infinity in interp queries and traced point positions (no ranks, no sorts), duplicate-safe — so mass/shear gradients are smooth in every configuration, including imaging at pixelization over-sampling 1 and the interferometer sparse path where the empirical CDF makes the likelihood exactly piecewise-constant. Forward transform is evaluated exactly (unit square <-> data bounding box, matching the linear convention); inverse is a fixed n_knots table lookup whose queries are unit-grid constants, so gradients flow through the table values. Bandwidth defaults to the mesh pixel scale and is exposed as a mesh kwarg. Linear and spline meshes are untouched. Closes nothing; certification via autolens_workspace_test jax_grad scripts follows on the workspace leg (#373). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The bilinear interpolation mapper places reconstruction value (row r, col c) at node U_y=(n_y-r-1)/(n_y-3), U_x=(c-1)/(n_x-3) in unit CDF space (guard ring at the border, rows flipped by the mapper's row = n - i), but edges_transformed drew a uniform [0,1] partition — pcolormesh plots put flux up to ~1.5 mesh pixels from where the mapper scatters it (the "small offsets" of issue #372, confirmed by a delta-function reproduction). The edges are now the node midpoints pushed through the same CDF machinery (guard-safe denominator for degenerate n<=3 meshes; border guard cells clamp to the data span). Both consumers inherit the fix: the pcolormesh plot path and rectangular_rotated's warped-centre reconstruction; spline and linear CDFs share the upstream index convention. Plot geometry only — the mapper is untouched, so inversions and likelihoods are byte-identical. #372 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…/rectangular-kernel-cdf-mesh
This was referenced Jul 10, 2026
Collaborator
Author
|
Folded in |
This was referenced Jul 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds opt-in kernel-density-CDF variants of the adaptive rectangular meshes:
RectangularKernelAdaptDensity/RectangularKernelAdaptImage(issue #373). The per-axis transform is the smooth kernel CDFF(x) = Σᵢ wᵢ·Φ((x−xᵢ)/h)(Enzi et al. arXiv:2606.30620 RTU formulation) instead of the empirical point-rank CDF, which the 2026-07-09 JAX gradient audit proved makes the likelihood exactly piecewise-constant in mass/shear at pixelization over-sampling 1 and on the interferometer sparse path.Properties by construction: strictly monotone (no jitter hack), C^∞ in interp queries and traced-point positions (no ranks, no sorts, no argsort anywhere), duplicate-safe (no 1/Δknot terms). The forward transform is evaluated exactly and maps the data bounding box onto the unit square (matching the linear convention); the inverse is a fixed
n_knotstable lookup whose queries are unit-grid constants, so gradients flow smoothly through the table values.bandwidthdefaults to the mesh pixel scale and is exposed as a mesh kwarg. The linear and spline meshes are untouched.Function-level JAX sanity (local, x64): eager == JIT to 1e-13; AD grad matches central FD to ~5e-10 relative through both the bilinear-weights path and the inverse-table path.
API Changes
Added only — two new opt-in mesh classes (
aa.mesh.RectangularKernelAdaptDensity,aa.mesh.RectangularKernelAdaptImage), their interpolator, and additive default-Nonekwargs onAbstractMeshGeometry. No existing symbol removed, renamed, or changed in behaviour.See full details below.
Test Plan
pytest test_autoarray/— 892 passed (16 new tests intest_rectangular_kernel.py: monotonicity, bounding-box mapping, round-trip, duplicate safety, large-bandwidth limit, mapper shape/consistency vs linear, areas totals vs linear, interpolator/geometry plumbing)autolens_workspace_test/scripts/jax_grad/imaging_pixelization.pykernel variants at os_pix=1 AND 4 with strict FD on ALL params;interferometer.pysparse path; eager-vs-JIT; figure-of-merit parity within a few e-4 of the linear meshesFull API Changes (for automation & release notes)
Added
aa.mesh.RectangularKernelAdaptDensity(shape=, bandwidth=1.0, n_knots=64)— density-adaptive rectangular mesh with kernel-density CDF transform (opt-in).aa.mesh.RectangularKernelAdaptImage(shape=, weight_power=1.0, weight_floor=0.0, bandwidth=1.0, n_knots=64)— image-adaptive variant; adapt-image weights become the kernel weights.autoarray.inversion.mesh.interpolator.rectangular_kernel— new module:create_transforms_kernel(),adaptive_rectangular_mappings_weights_via_interpolation_from_kernel(),adaptive_rectangular_areas_from_kernel(),adaptive_rectangular_transformed_grid_from_kernel(),InterpolatorRectangularKernel,KERNEL_CDF_DEFAULT_BANDWIDTH,KERNEL_CDF_DEFAULT_KNOTS.Changed Signature (additive, backwards-compatible)
AbstractMeshGeometry.__init__(..., kernel_bandwidth=None, kernel_knots=None)— new optional kwargs;MeshGeometryRectangular.areas_transformed/edges_transformedroute through the kernel helpers whenkernel_bandwidthis set (mirrors the existingspline_degdispatch).Migration
Coordination note
Adjacent to #372 (rect-adapt, parked at sign-off): both touch
mesh_geometry/rectangular.pyin distinct hunks (itsedges_transformedbody vs this PR's dispatch branches) — clean merge in either order; if #372 lands first the kernel path inherits the corrected edges automatically.Merge gate: do not merge until the workspace-leg certification PR (jax_grad strict-FD assertions) is green — that is this task's success criterion.
🤖 Generated with Claude Code