@@ -393,3 +393,71 @@ def test__convolve_bin_segment_ids_from__divisibility_guard():
393393 util .over_sample .convolve_bin_segment_ids_from (
394394 sub_size = np .array ([4 , 3 ]), convolve_over_sample_size = 2
395395 )
396+
397+
398+ def _reference_grid_2d_slim_over_sampled_via_mask_from (mask_2d , pixel_scales , sub_size , origin = (0.0 , 0.0 )):
399+ """The per-pixel construction `grid_2d_slim_over_sampled_via_mask_from`
400+ replaced on 2026-09-08 (one linspace + meshgrid + stack per unmasked
401+ pixel). Kept verbatim as the oracle: the vectorised routine must return
402+ exactly these values in exactly this order."""
403+ H , W = mask_2d .shape
404+ sy , sx = pixel_scales
405+ oy , ox = origin
406+ rows , cols = np .nonzero (~ mask_2d )
407+ sub_arr = np .asarray (sub_size )
408+ sub_arr = np .full (rows .size , sub_arr , dtype = int ) if sub_arr .size == 1 else sub_arr
409+ valid = sub_arr > 0
410+ rows , cols , sub_arr = rows [valid ], cols [valid ], sub_arr [valid ]
411+ if sub_arr .size == 0 :
412+ return np .empty ((0 , 2 ), dtype = float )
413+ cy , cx = (H - 1 ) / 2.0 , (W - 1 ) / 2.0
414+ y_pix = (cy - rows ) * sy + oy
415+ x_pix = (cols - cx ) * sx + ox
416+ coords_list = []
417+ for i , s in enumerate (sub_arr ):
418+ dy , dx = sy / s , sx / s
419+ y_off = np .linspace (+ sy / 2 - dy / 2 , - sy / 2 + dy / 2 , s )
420+ x_off = np .linspace (- sx / 2 + dx / 2 , + sx / 2 - dx / 2 , s )
421+ y_sub , x_sub = np .meshgrid (y_off , x_off , indexing = "ij" )
422+ coords_list .append (np .stack ([y_pix [i ] + y_sub .ravel (), x_pix [i ] + x_sub .ravel ()], axis = 1 ))
423+ return np .vstack (coords_list )
424+
425+
426+ @pytest .mark .parametrize ("seed" , [0 , 1 , 2 ])
427+ def test__grid_2d_slim_over_sampled_via_mask_from__matches_per_pixel_reference (seed ):
428+ rng = np .random .default_rng (seed )
429+ mask_2d = rng .random ((7 , 9 )) < 0.4
430+ pixel_scales = (0.7 , 0.3 )
431+ origin = (0.25 , - 0.5 )
432+
433+ # uniform sub-size (the single-broadcast branch)
434+ for sub_size in (1 , 2 , 3 ):
435+ grid = aa .util .over_sample .grid_2d_slim_over_sampled_via_mask_from (
436+ mask_2d = mask_2d , pixel_scales = pixel_scales , sub_size = sub_size , origin = origin
437+ )
438+ ref = _reference_grid_2d_slim_over_sampled_via_mask_from (mask_2d , pixel_scales , sub_size , origin )
439+ assert grid .shape == ref .shape
440+ assert grid == pytest .approx (ref , abs = 0.0 )
441+
442+ # per-pixel sub-sizes including zeros (skipped pixels) and mixed sizes (the block-start branch)
443+ n_unmasked = int ((~ mask_2d ).sum ())
444+ sub_size = rng .integers (0 , 5 , size = n_unmasked )
445+ grid = aa .util .over_sample .grid_2d_slim_over_sampled_via_mask_from (
446+ mask_2d = mask_2d , pixel_scales = pixel_scales , sub_size = sub_size , origin = origin
447+ )
448+ ref = _reference_grid_2d_slim_over_sampled_via_mask_from (mask_2d , pixel_scales , sub_size , origin )
449+ assert grid .shape == ref .shape
450+ assert grid == pytest .approx (ref , abs = 0.0 )
451+
452+
453+ def test__grid_2d_slim_over_sampled_via_mask_from__all_masked_or_all_zero_sub_size ():
454+ mask_2d = np .full ((3 , 3 ), True )
455+ grid = aa .util .over_sample .grid_2d_slim_over_sampled_via_mask_from (
456+ mask_2d = mask_2d , pixel_scales = (1.0 , 1.0 ), sub_size = 2
457+ )
458+ assert grid .shape == (0 , 2 )
459+ mask_2d = np .full ((3 , 3 ), False )
460+ grid = aa .util .over_sample .grid_2d_slim_over_sampled_via_mask_from (
461+ mask_2d = mask_2d , pixel_scales = (1.0 , 1.0 ), sub_size = np .zeros (9 , dtype = int )
462+ )
463+ assert grid .shape == (0 , 2 )
0 commit comments