@@ -67,6 +67,26 @@ def has(self, cls) -> bool:
6767 """
6868 raise NotImplementedError
6969
70+ @staticmethod
71+ def _binned_for_convolution (values , grid , psf , xp = np ):
72+ """
73+ Partially bin values evaluated on ``grid``'s over-sampled coordinates (per-pixel
74+ sizes k_i * s) down to the uniform s the oversampled Convolver requires — the
75+ k x s coupling. A no-op when the grid's sizes already equal s.
76+ """
77+ from autoarray .operators .over_sampling .over_sample_util import (
78+ binned_to_convolve_size_from ,
79+ )
80+
81+ values = values .array if hasattr (values , "array" ) else values
82+
83+ return binned_to_convolve_size_from (
84+ values = values ,
85+ sub_size = np .array (grid .over_sample_size ),
86+ convolve_over_sample_size = psf .convolve_over_sample_size ,
87+ xp = xp ,
88+ )
89+
7090 @staticmethod
7191 def _psf_evaluation_grids_from (grid , blurring_grid , psf ):
7292 """
@@ -163,8 +183,12 @@ def blurred_image_2d_from(
163183
164184 if convolution_mask is not None :
165185 blurred_image_2d = psf .convolved_image_from (
166- image = image_2d_not_operated ,
167- blurring_image = blurring_image_2d_not_operated ,
186+ image = self ._binned_for_convolution (
187+ image_2d_not_operated , grid , psf , xp = xp
188+ ),
189+ blurring_image = self ._binned_for_convolution (
190+ blurring_image_2d_not_operated , blurring_grid , psf , xp = xp
191+ ),
168192 mask = convolution_mask ,
169193 xp = xp ,
170194 )
@@ -247,14 +271,32 @@ def convolved_padded_image_2d_from(self, grid, psf: aa.Convolver, xp=np):
247271 origin = grid .origin ,
248272 )
249273
250- padded_grid = aa .Grid2D .from_mask (mask = padded_mask , over_sample_size = s )
274+ # The padded grid inherits the input grid's (possibly adaptive, k x s
275+ # coupled) evaluation sizes, padded with s in the border region.
276+ pad_width = (
277+ (padded_shape [0 ] - grid .mask .shape_native [0 ]) // 2 ,
278+ (padded_shape [1 ] - grid .mask .shape_native [1 ]) // 2 ,
279+ )
280+ over_sample_size = np .pad (
281+ np .array (grid .over_sample_size .native ),
282+ pad_width ,
283+ mode = "constant" ,
284+ constant_values = s ,
285+ )
286+ over_sample_size [over_sample_size == 0 ] = s
287+
288+ padded_grid = aa .Grid2D .from_mask (
289+ mask = padded_mask , over_sample_size = over_sample_size
290+ )
251291
252292 image_over_sampled = self .image_2d_from (
253293 grid = padded_grid .over_sampled , xp = xp , operated_only = False
254294 )
255295
256296 convolved = psf .convolved_image_from (
257- image = image_over_sampled ,
297+ image = self ._binned_for_convolution (
298+ image_over_sampled , padded_grid , psf , xp = xp
299+ ),
258300 blurring_image = None ,
259301 mask = padded_mask ,
260302 xp = xp ,
@@ -416,8 +458,12 @@ def blurred_image_2d_list_from(
416458
417459 if convolution_mask is not None :
418460 blurred_image_2d = psf .convolved_image_from (
419- image = image_2d_not_operated ,
420- blurring_image = blurring_image_2d_not_operated ,
461+ image = self ._binned_for_convolution (
462+ image_2d_not_operated , grid , psf
463+ ),
464+ blurring_image = self ._binned_for_convolution (
465+ blurring_image_2d_not_operated , blurring_grid , psf
466+ ),
421467 mask = convolution_mask ,
422468 )
423469 else :
@@ -584,6 +630,14 @@ def galaxy_blurred_image_2d_dict_from(
584630 galaxy_key
585631 ]
586632
633+ if convolution_mask is not None :
634+ image_2d_not_operated = self ._binned_for_convolution (
635+ image_2d_not_operated , grid , psf , xp = xp
636+ )
637+ blurring_image_2d_not_operated = self ._binned_for_convolution (
638+ blurring_image_2d_not_operated , blurring_grid , psf , xp = xp
639+ )
640+
587641 blurred_image_2d = psf .convolved_image_from (
588642 image = image_2d_not_operated ,
589643 blurring_image = blurring_image_2d_not_operated ,
0 commit comments