Skip to content

Commit 4e93ecc

Browse files
Jammy2211claude
authored andcommitted
feat: parameterize lens mass, source light, and lens light in simulator
Replace closure-based API (fn(grid) with baked-in Galaxy constants) with parameterized API (fn(grid, params) with dynamic array inputs). This allows the lens mass model, source light, and lens light parameters to be varied between realizations without recompilation under jax.jit. Also adds optional lens_light_fn/lens_light_params for lens-plane light evaluation, and renames macro_* -> lens_* for consistency. Ref: PyAutoLens#542 — feedback from Max (mwiet) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent a6e21b1 commit 4e93ecc

1 file changed

Lines changed: 53 additions & 26 deletions

File tree

autolens/lens/substructure_util.py

Lines changed: 53 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,9 @@ def traced_grids_via_scan(
7474
halo_params,
7575
halo_mask,
7676
scaling_matrix,
77-
macro_deflections_fn,
78-
macro_plane_mask,
77+
lens_mass_fn,
78+
lens_mass_params,
79+
lens_plane_mask,
7980
sheet_kappas,
8081
halo_profile_cls,
8182
):
@@ -89,7 +90,7 @@ def traced_grids_via_scan(
8990

9091
def scan_step(carry, plane_inputs):
9192
grid_0, defl_buffer, plane_idx = carry
92-
halo_p, halo_m, scaling_row, is_macro, sheet_kappa = plane_inputs
93+
halo_p, halo_m, scaling_row, is_lens, sheet_kappa = plane_inputs
9394

9495
scaled = jnp.einsum("p,pmd->md", scaling_row, defl_buffer)
9596
current_grid = grid_0 - scaled
@@ -98,12 +99,12 @@ def scan_step(carry, plane_inputs):
9899
current_grid, halo_p, halo_m
99100
)
100101

101-
macro_defl = macro_deflections_fn(current_grid)
102-
macro_defl = is_macro * macro_defl
102+
lens_defl = lens_mass_fn(current_grid, lens_mass_params)
103+
lens_defl = is_lens * lens_defl
103104

104105
sheet_defl = sheet_kappa * current_grid
105106

106-
total_defl = halo_defl + macro_defl + sheet_defl
107+
total_defl = halo_defl + lens_defl + sheet_defl
107108
defl_buffer = defl_buffer.at[plane_idx].set(total_defl)
108109

109110
return (grid_0, defl_buffer, plane_idx + 1), current_grid
@@ -112,7 +113,7 @@ def scan_step(carry, plane_inputs):
112113
halo_params,
113114
halo_mask,
114115
scaling_matrix,
115-
macro_plane_mask,
116+
lens_plane_mask,
116117
sheet_kappas,
117118
)
118119

@@ -128,15 +129,20 @@ def simulate_substructure(
128129
halo_params,
129130
halo_mask,
130131
scaling_matrix,
131-
macro_deflections_fn,
132-
macro_plane_mask,
132+
lens_mass_fn,
133+
lens_mass_params,
134+
lens_plane_mask,
133135
sheet_kappas,
134-
source_image_fn,
136+
source_light_fn,
137+
source_light_params,
135138
psf_kernel,
136139
exposure_time,
137140
background_sky_level,
138141
prng_key,
139142
halo_profile_cls,
143+
lens_light_fn=None,
144+
lens_light_params=None,
145+
lens_plane_idx=None,
140146
):
141147
import jax
142148
import jax.numpy as jnp
@@ -146,14 +152,19 @@ def simulate_substructure(
146152
halo_params=halo_params,
147153
halo_mask=halo_mask,
148154
scaling_matrix=scaling_matrix,
149-
macro_deflections_fn=macro_deflections_fn,
150-
macro_plane_mask=macro_plane_mask,
155+
lens_mass_fn=lens_mass_fn,
156+
lens_mass_params=lens_mass_params,
157+
lens_plane_mask=lens_plane_mask,
151158
sheet_kappas=sheet_kappas,
152159
halo_profile_cls=halo_profile_cls,
153160
)
154161

155-
source_grid = traced_grids[-1]
156-
image_1d = source_image_fn(source_grid)
162+
image_1d = source_light_fn(traced_grids[-1], source_light_params)
163+
164+
if lens_light_fn is not None:
165+
lens_image = lens_light_fn(traced_grids[lens_plane_idx], lens_light_params)
166+
image_1d = image_1d + lens_image
167+
157168
image_2d = image_1d.reshape(image_shape)
158169

159170
image_2d = jax.scipy.signal.fftconvolve(image_2d, psf_kernel, mode="same")
@@ -202,15 +213,20 @@ def batched_simulate_substructure(
202213
halo_params_batch,
203214
halo_mask_batch,
204215
scaling_matrix,
205-
macro_deflections_fn,
206-
macro_plane_mask,
216+
lens_mass_fn,
217+
lens_mass_params_batch,
218+
lens_plane_mask,
207219
sheet_kappas_batch,
208-
source_image_fn,
220+
source_light_fn,
221+
source_light_params_batch,
209222
psf_kernel,
210223
exposure_time,
211224
background_sky_level,
212225
prng_keys,
213226
halo_profile_cls,
227+
lens_light_fn=None,
228+
lens_light_params_batch=None,
229+
lens_plane_idx=None,
214230
):
215231
import jax
216232
import functools
@@ -220,23 +236,34 @@ def batched_simulate_substructure(
220236
grid=grid,
221237
image_shape=image_shape,
222238
scaling_matrix=scaling_matrix,
223-
macro_deflections_fn=macro_deflections_fn,
224-
macro_plane_mask=macro_plane_mask,
225-
source_image_fn=source_image_fn,
239+
lens_mass_fn=lens_mass_fn,
240+
lens_plane_mask=lens_plane_mask,
241+
source_light_fn=source_light_fn,
226242
psf_kernel=psf_kernel,
227243
exposure_time=exposure_time,
228244
background_sky_level=background_sky_level,
229245
halo_profile_cls=halo_profile_cls,
246+
lens_light_fn=lens_light_fn,
247+
lens_plane_idx=lens_plane_idx,
230248
)
231249

232-
def call(halo_params, halo_mask, sheet_kappas, prng_key):
250+
def call(hp, hm, sk, lmp, slp, llp, key):
233251
return single_fn(
234-
halo_params=halo_params,
235-
halo_mask=halo_mask,
236-
sheet_kappas=sheet_kappas,
237-
prng_key=prng_key,
252+
halo_params=hp,
253+
halo_mask=hm,
254+
sheet_kappas=sk,
255+
lens_mass_params=lmp,
256+
source_light_params=slp,
257+
lens_light_params=llp,
258+
prng_key=key,
238259
)
239260

240261
return jax.vmap(call)(
241-
halo_params_batch, halo_mask_batch, sheet_kappas_batch, prng_keys,
262+
halo_params_batch,
263+
halo_mask_batch,
264+
sheet_kappas_batch,
265+
lens_mass_params_batch,
266+
source_light_params_batch,
267+
lens_light_params_batch,
268+
prng_keys,
242269
)

0 commit comments

Comments
 (0)