@@ -110,3 +110,72 @@ def test__in_ndarray__out_ndarray():
110110 assert isinstance (result , np .ndarray )
111111 assert not isinstance (result , aa .Grid2D )
112112 assert not isinstance (result , aa .Grid2DIrregular )
113+
114+
115+ class MockGrid2DPassThroughObj :
116+ """
117+ Mimics the profile classes in **PyAutoGalaxy** whose `@to_grid` decorated methods
118+ delegate to another `@to_grid` decorated method, such that the value the decorator
119+ wraps up is already a `Grid2D`.
120+ """
121+
122+ def __init__ (self , over_sampled = None ):
123+ self .centre = (0.0 , 0.0 )
124+ self .over_sampled = over_sampled
125+
126+ @aa .decorators .to_grid
127+ def grid_2d_from (self , grid , * args , ** kwargs ):
128+ return aa .Grid2D (
129+ values = np .multiply (2.0 , grid .array ),
130+ mask = grid .mask ,
131+ over_sample_size = grid .over_sample_size ,
132+ over_sampled = self .over_sampled ,
133+ )
134+
135+
136+ def _mask_2x2 ():
137+ return aa .Mask2D (
138+ mask = [
139+ [True , True , True , True ],
140+ [True , False , False , True ],
141+ [True , False , False , True ],
142+ [True , True , True , True ],
143+ ],
144+ pixel_scales = (1.0 , 1.0 ),
145+ )
146+
147+
148+ def test__to_grid__does_not_materialise_over_sampled_of_wrapped_grid (monkeypatch ):
149+ """
150+ Reading the public `over_sampled` / `over_sampler` properties inside `to_grid`
151+ materialises them via a per-pixel Python loop, which dominates the runtime of
152+ deflection angle calculations. Only an explicitly set value may propagate.
153+ """
154+
155+ def _fail (self ):
156+ pytest .fail ("over_sampled materialised inside to_grid" )
157+
158+ def _fail_sampler (self ):
159+ pytest .fail ("over_sampler materialised inside to_grid" )
160+
161+ monkeypatch .setattr (aa .Grid2D , "over_sampled" , property (_fail ))
162+ monkeypatch .setattr (aa .Grid2D , "over_sampler" , property (_fail_sampler ))
163+
164+ grid_2d = aa .Grid2D .from_mask (mask = _mask_2x2 (), over_sample_size = 2 )
165+
166+ result = MockGrid2DPassThroughObj ().grid_2d_from (grid = grid_2d )
167+
168+ assert isinstance (result , aa .Grid2D )
169+ assert result ._over_sampled is None
170+ assert result ._over_sampler is None
171+
172+
173+ def test__to_grid__propagates_explicitly_set_over_sampled ():
174+ grid_2d = aa .Grid2D .from_mask (mask = _mask_2x2 (), over_sample_size = 2 )
175+
176+ sentinel = aa .Grid2DIrregular (values = [(1.0 , 2.0 ), (3.0 , 4.0 )])
177+
178+ result = MockGrid2DPassThroughObj (over_sampled = sentinel ).grid_2d_from (grid = grid_2d )
179+
180+ assert result ._over_sampled is sentinel
181+ assert result .over_sampled is sentinel
0 commit comments