From 9303752cb75675c4231d569225b9f9b5b9bb0abb Mon Sep 17 00:00:00 2001 From: Jammy2211 Date: Fri, 30 Oct 2026 12:39:04 +0000 Subject: [PATCH] fix: area magnification sub-pixel area follows the generated sub-pixels Grid2D.from_mask caps over-sampling (e.g. to 2 under PYAUTO_SMALL_DATASETS=1), so deriving the sub-pixel area from the requested sub_size made source_plane_area_from (2/sub_size)^2 too small. area_magnification_from was unaffected (the factor cancels). Closes #686 Co-Authored-By: Claude Opus 5.5 --- autogalaxy/operate/lens_calc.py | 9 ++++++++- .../operate/test_area_magnification.py | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/autogalaxy/operate/lens_calc.py b/autogalaxy/operate/lens_calc.py index 7c39060f..113e3e40 100644 --- a/autogalaxy/operate/lens_calc.py +++ b/autogalaxy/operate/lens_calc.py @@ -823,7 +823,14 @@ def _sub_pixel_magnifications_from(self, mask: aa.Mask2D, sub_size: int): self.magnification_2d_via_hessian_from(grid=sub_pixel_centres) ) - sub_pixel_area = mask.pixel_scales[0] * mask.pixel_scales[1] / sub_size**2 + # From the sub-pixels actually generated, not `sub_size`: the over-sampling can be capped (e.g. to 2 + # under PYAUTO_SMALL_DATASETS=1), and the areas must still sum to the unmasked pixels' area. + sub_pixel_area = ( + mask.pixel_scales[0] + * mask.pixel_scales[1] + * grid.shape_slim + / sub_pixel_centres.shape[0] + ) return magnifications, sub_pixel_area diff --git a/test_autogalaxy/operate/test_area_magnification.py b/test_autogalaxy/operate/test_area_magnification.py index e0cb0dd7..a2e4788f 100644 --- a/test_autogalaxy/operate/test_area_magnification.py +++ b/test_autogalaxy/operate/test_area_magnification.py @@ -137,3 +137,20 @@ def test__a_mask_spanning_two_images_differs_from_each_image(): per_image = lens_calc.area_magnification_list_from(mask=mask, sub_size=4) assert all(abs(whole / mu - 1.0) > 0.01 for mu in per_image) + + +def test__source_plane_area__correct_when_over_sampling_is_capped(monkeypatch): + """ + `PYAUTO_SMALL_DATASETS=1` caps over-sampling at 2 whatever `sub_size` asks for; + the sub-pixel area must follow the sub-pixels actually generated. + """ + mask = _annulus_mask(inner=1.5, outer=2.0, pixel_scale=0.05) + lens_calc = _lens_calc() + + uncapped = lens_calc.source_plane_area_from(mask=mask, sub_size=4) + + monkeypatch.setenv("PYAUTO_SMALL_DATASETS", "1") + + capped = lens_calc.source_plane_area_from(mask=mask, sub_size=4) + + assert capped == pytest.approx(uncapped, rel=1.0e-3)