fix(hilbert): support offset-centre circular masks#313
Merged
Conversation
Previously Hilbert image-mesh raised PixelizationException for offset-centre circular masks whose centres didn't land on a pixel half-integer, and would have silently sampled the wrong region of the image for those that slipped through. This commit fixes both halves of the bug. - Mask2D.is_circular rewritten to be quantization-robust: bbox square within one pixel, geometric centre pixel unmasked, and a reference circular mask reconstructed from the inferred centre+radius must match the input within rim quantization tolerance. The new predicate correctly accepts offset circles and rejects annular and square masks that previously false-passed. - Mask2D.circular_radius now derives the radius from the bbox extent rather than the central row count. Numerically identical for centred masks; correct for offset centres. - hilbert.image_and_grid_from now translates Hilbert sample points by mask_centre, so the curve actually probes the masked region of the image. For masks centred at the origin (every current test/smoke case) the shift is a no-op and likelihoods are bit-identical. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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
Fixes a user-reported bug where
Hilbertimage-mesh raisedPixelizationExceptionfor circular masks with offset centres (e.g. lens systems whose mask centre is not at the field-of-view origin). The bug had two compounding halves:Mask2D.is_circularreturnedFalsefor genuinely circular offset masks due to pixel-quantization asymmetry, and even if the check were bypassed the Hilbert sampler always probed the image around(0, 0)rather than the mask centre.API Changes
Mask2D.is_circularis now quantization-robust and correctly distinguishes filled discs from annular and square masks (previously annular masks were false-positives).Mask2D.circular_radiusderives the radius from the bbox extent. Numerically identical for centred masks.hilbert.image_and_grid_fromgains an optionalmask_centre=(0.0, 0.0)parameter and translates the Hilbert sample points by it. For masks centred at the origin (every current test/smoke case) this is a no-op.See full details below.
Test Plan
test_autoarray/mask/test_mask_2d.pycover offset centres (5 parametrised positions), annular masks, square unmasked regions, andcircular_radiusfor offset centres.test_autoarray/inversion/pixelization/image_mesh/test_hilbert.pyasserts that the resulting mesh points lie inside the mask's circle for an offset-centre mask.[-1.02590674, -1.70984456]), confirming Delaunay-Hilbert smoke tests will produce unchanged likelihoods.Full API Changes (for automation & release notes)
Changed Behaviour
Mask2D.is_circular— algorithm rewritten. Now returnsTruefor offset-centre circular masks (was: returnedFalsewhen centre offset caused pixel-quantization asymmetry). Now returnsFalsefor annular masks (was: returnedTruebecause central row/column counts were symmetric).Mask2D.circular_radius— computed from the bounding-box extent of the unmasked region (was: from the unmasked-pixel count in a single guessed central row). Numerically identical for centred masks; correct rather than spurious for offset centres.Changed Signature
autoarray.inversion.mesh.image_mesh.hilbert.image_and_grid_from(image, mask, mask_radius, pixel_scales, hilbert_length, mask_centre=(0.0, 0.0))— new trailing keywordmask_centre, defaults to(0.0, 0.0)so existing callers are unaffected.Migration
None required. All changes are either additive (new optional kwarg with backward-compatible default) or strictly bug-fix behaviour. Workspaces and tests using centred masks see no numerical change.
🤖 Generated with Claude Code