@@ -98,7 +98,7 @@ def test__data_weight_total_for_pix_from__multi_pixel_mappings__sums_weights_per
9898 assert data_weight_total_for_pix == pytest .approx ([1.2 , 0.7 , 0.3 , 1.4 , 4.4 ], 1.0e-4 )
9999
100100
101- def test__adaptive_pixel_signals_from___matches_util (grid_2d_7x7 , image_7x7 ):
101+ def test__adaptive_pixel_signals_from___matches_util (grid_2d_7x7 ):
102102 pixels = 6
103103 signal_scale = 2.0
104104 interpolator = aa .m .MockInterpolator (
@@ -110,11 +110,15 @@ def test__adaptive_pixel_signals_from___matches_util(grid_2d_7x7, image_7x7):
110110
111111 over_sampler = aa .OverSampler (mask = grid_2d_7x7 .mask , sub_size = 1 )
112112
113+ # The adapt image is defined on the data's own mask, as it is for a real fit.
114+
115+ adapt_data = aa .Array2D (values = np .ones (9 ), mask = grid_2d_7x7 .mask )
116+
113117 mapper = aa .m .MockMapper (
114118 source_plane_data_grid = grid_2d_7x7 ,
115119 over_sampler = over_sampler ,
116120 interpolator = interpolator ,
117- adapt_data = image_7x7 ,
121+ adapt_data = adapt_data ,
118122 parameters = pixels ,
119123 )
120124
@@ -127,12 +131,56 @@ def test__adaptive_pixel_signals_from___matches_util(grid_2d_7x7, image_7x7):
127131 pix_indexes_for_sub_slim_index = interpolator .mappings ,
128132 pix_size_for_sub_slim_index = interpolator .sizes ,
129133 slim_index_for_sub_slim_index = over_sampler .slim_for_sub_slim ,
130- adapt_data = np .array (image_7x7 ),
134+ adapt_data = np .array (adapt_data ),
131135 )
132136
133137 assert (pixel_signals == pixel_signals_util ).all ()
134138
135139
140+ def test__pixel_signals_from__adapt_data_on_a_different_mask__raises_clear_exception (
141+ grid_2d_7x7 ,
142+ ):
143+ """
144+ An adapt image defined on a different mask to the data cannot be indexed by the data's slim indexes.
145+
146+ The usual cause is a stale adapt-image cache being reused after the dataset's mask changed, and before
147+ this guard it surfaced as a bare `IndexError` several frames deep in `adaptive_pixel_signals_from`,
148+ which reads as an off-by-one rather than a mask mismatch (PyAutoGalaxy#516).
149+ """
150+ interpolator = aa .m .MockInterpolator (
151+ mappings = np .array ([[1 ], [1 ], [4 ], [0 ], [0 ], [3 ], [0 ], [0 ], [3 ]]),
152+ sizes = np .array ([1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ]),
153+ weights = np .ones (9 ),
154+ )
155+
156+ over_sampler = aa .OverSampler (mask = grid_2d_7x7 .mask , sub_size = 1 )
157+
158+ # The data has 9 unmasked pixels, the adapt image only 8.
159+
160+ adapt_mask = np .full (fill_value = True , shape = (7 , 7 ))
161+ adapt_mask [2 :5 , 2 :5 ] = False
162+ adapt_mask [2 , 2 ] = True
163+
164+ adapt_data = aa .Array2D (
165+ values = np .ones (8 ),
166+ mask = aa .Mask2D (mask = adapt_mask , pixel_scales = 1.0 ),
167+ )
168+
169+ mapper = aa .m .MockMapper (
170+ source_plane_data_grid = grid_2d_7x7 ,
171+ over_sampler = over_sampler ,
172+ interpolator = interpolator ,
173+ adapt_data = adapt_data ,
174+ parameters = 6 ,
175+ )
176+
177+ with pytest .raises (aa .exc .InversionException ) as e :
178+ mapper .pixel_signals_from (signal_scale = 2.0 )
179+
180+ assert "8 pixels" in str (e .value )
181+ assert "9 pixels" in str (e .value )
182+
183+
136184def test__mapped_to_source_from__delaunay_mapper__matches_mapping_matrix_util (
137185 grid_2d_7x7 ,
138186):
0 commit comments