Skip to content

Commit a0a492d

Browse files
Jammy2211claude
authored andcommitted
feat: PreloadsImaging + shared source-plane mesh fields on AbstractPreloads
The imaging sibling of PreloadsInterferometer (PyAutoArray#379): AbstractPreloads gains source_plane_mesh_grid + image_plane_mesh_grid (dataset-type-agnostic, so either dataset type can lead an imaging+interferometer graph). PreloadsImaging documents the imaging invariance contract: mesh geometry is shareable across exposures under one lens model; mapper / curvature matrix / blurred mapping matrix / regularization matrix are NOT (per-exposure PSFs + offsets; regularization may be data-adaptive). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent d547fe7 commit a0a492d

6 files changed

Lines changed: 91 additions & 2 deletions

File tree

autoarray/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from .settings import Settings
3030
from .inversion.inversion.abstract import AbstractInversion
3131
from .preloads import AbstractPreloads
32+
from .preloads import PreloadsImaging
3233
from .preloads import PreloadsInterferometer
3334
from .inversion.regularization.abstract import AbstractRegularization
3435
from .inversion.inversion.factory import inversion_from as Inversion

autoarray/preloads/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
from .abstract import AbstractPreloads
2+
from .imaging import PreloadsImaging
23
from .interferometer import PreloadsInterferometer

autoarray/preloads/abstract.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
class AbstractPreloads:
2-
def __init__(self, curvature_matrix=None, mapper_galaxy_dict=None):
2+
def __init__(
3+
self,
4+
curvature_matrix=None,
5+
mapper_galaxy_dict=None,
6+
source_plane_mesh_grid=None,
7+
image_plane_mesh_grid=None,
8+
):
39
"""
410
Container for quantities that are *preloaded* into a fit / inversion: computed once and
511
injected so that repeated evaluations reuse them instead of recomputing them.
@@ -42,7 +48,24 @@ def __init__(self, curvature_matrix=None, mapper_galaxy_dict=None):
4248
plane); when invariant across evaluations it is built once and reused here, so the
4349
`mapper` (and therefore the `mapping_matrix` and `regularization_matrix`) is not rebuilt.
4450
Stored opaquely — the consumer (e.g. PyAutoLens's `TracerToInversion`) populates and
45-
interprets it.
51+
interprets it. Valid ONLY when the datasets sharing it have identical grids (e.g. the
52+
channels of a datacube) — a mapper embeds a dataset's own data-grid mappings.
53+
source_plane_mesh_grid
54+
The pre-computed source-plane mesh geometry (e.g. the ray-traced centres a Delaunay
55+
triangulation is built over), for consumers whose datasets share a lens model but NOT
56+
their grids (e.g. multi-exposure imaging with per-exposure pixel offsets and PSFs).
57+
Unlike `mapper_galaxy_dict`, this preloads only the mesh: each dataset still builds its
58+
own mapper by mapping its own (offset) data grid onto this shared mesh. Stored opaquely
59+
in the consumer's plane-grouped structure (PyAutoLens: the `traced_mesh_grid_pg_list`
60+
of the lead dataset). The mapping matrix, curvature matrix, blurred mapping matrix and
61+
regularization matrix are all deliberately NOT preloadable this way — offsets/PSFs make
62+
the first three per-dataset, and regularization may be data-adaptive.
63+
image_plane_mesh_grid
64+
The image-plane counterpart of `source_plane_mesh_grid` (the mesh centres before
65+
ray-tracing, in the lead dataset's frame), carried alongside it as metadata for
66+
downstream consumers (e.g. mapper plotting). Same opaque plane-grouped structure.
4667
"""
4768
self.curvature_matrix = curvature_matrix
4869
self.mapper_galaxy_dict = mapper_galaxy_dict
70+
self.source_plane_mesh_grid = source_plane_mesh_grid
71+
self.image_plane_mesh_grid = image_plane_mesh_grid

autoarray/preloads/imaging.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
from autoarray.preloads.abstract import AbstractPreloads
2+
3+
4+
class PreloadsImaging(AbstractPreloads):
5+
def __init__(self, source_plane_mesh_grid=None, image_plane_mesh_grid=None):
6+
"""
7+
Preloaded quantities for an imaging fit / inversion (see `AbstractPreloads`).
8+
9+
This is the consumer-facing preloads container for imaging data — for example the object
10+
returned by `AnalysisImaging.shared_state_from` for the multi-exposure shared-state path,
11+
where exposures of the same lens (at the same or different wavelengths, with per-exposure
12+
pixel offsets) share one source-plane mesh.
13+
14+
The invariance contract differs from the datacube (`PreloadsInterferometer`) case, whose
15+
channels share a single real-space grid and can therefore preload the whole mapper and
16+
curvature matrix. Imaging exposures have per-exposure PSFs and pixel offsets, so:
17+
18+
- the source-plane mesh geometry IS shareable (a pure function of the shared lens model and
19+
the lead exposure's image-mesh) — preloaded here;
20+
- the mapper, mapping matrix, blurred mapping matrix and curvature matrix are NOT (each
21+
exposure maps its own offset grid onto the shared mesh and blurs with its own PSF);
22+
- the regularization matrix is NOT (regularization may adapt to per-exposure data).
23+
24+
Parameters
25+
----------
26+
source_plane_mesh_grid
27+
The shared source-plane mesh geometry, traced once from the lead exposure. See
28+
`AbstractPreloads`.
29+
image_plane_mesh_grid
30+
Its image-plane counterpart in the lead exposure's frame. See `AbstractPreloads`.
31+
"""
32+
super().__init__(
33+
source_plane_mesh_grid=source_plane_mesh_grid,
34+
image_plane_mesh_grid=image_plane_mesh_grid,
35+
)

test_autoarray/preloads/__init__.py

Whitespace-only changes.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import autoarray as aa
2+
3+
4+
def test__abstract_preloads__all_fields_default_none():
5+
preloads = aa.AbstractPreloads()
6+
7+
assert preloads.curvature_matrix is None
8+
assert preloads.mapper_galaxy_dict is None
9+
assert preloads.source_plane_mesh_grid is None
10+
assert preloads.image_plane_mesh_grid is None
11+
12+
13+
def test__preloads_imaging__carries_mesh_geometry_only():
14+
preloads = aa.PreloadsImaging(
15+
source_plane_mesh_grid=[["mesh"]], image_plane_mesh_grid=[["image_mesh"]]
16+
)
17+
18+
assert preloads.source_plane_mesh_grid == [["mesh"]]
19+
assert preloads.image_plane_mesh_grid == [["image_mesh"]]
20+
assert preloads.curvature_matrix is None
21+
assert preloads.mapper_galaxy_dict is None
22+
23+
24+
def test__preloads_interferometer__mesh_fields_available_via_abstract():
25+
preloads = aa.PreloadsInterferometer(curvature_matrix="F")
26+
27+
assert preloads.curvature_matrix == "F"
28+
assert preloads.source_plane_mesh_grid is None
29+
assert preloads.image_plane_mesh_grid is None

0 commit comments

Comments
 (0)