Overview
Phase 1 (of 4) of generalising the shipped datacube shared-state likelihood machinery (#565, PyAutoFit#1307 — both closed; epic z_features/complete/analysis_shared_state.md) to imaging multi-dataset fitting: one Delaunay mesh shared and shifted across exposures of the same lens. This phase is design-only — its deliverable is a design note + locked API sketch posted on this issue; no source edits. Phases 2 (core library API), 3 (workspace example sections + parity test) and 4 (docs) have prompts in PyAutoMind but are deliberately un-issued until their predecessor nears shipping.
Plan
- Decide what is genuinely shareable for imaging multi-exposure fits: per-dataset PSFs + pixel offsets rule out sharing the curvature matrix
F and mapping matrix L; the candidate shared object is the source-plane Delaunay mesh geometry. Quantify the saving honestly (speed win vs consistency win).
- Lock the same-wavelength "one source reconstruction" semantics against the FactorGraph per-factor contract — a joint solve (
F = Σᵢ LᵢᵀWᵢLᵢ, D = Σᵢ Lᵢᵀdᵢ, one s) does not decompose into the per-factor likelihood sum.
- Confirm the different-wavelength case is "shared shifted mesh geometry only, independent per-dataset reconstructions" (colour differences).
- Design shift composition with
aa.DatasetModel: shifts known/fixed by default (PyAutoReduce target_pixel differences), optionally free per-frame (dy, dx) with Gaussian priors of width = the recorded registration residuals (floor ~0.1–0.3 px); simulator shifts default 0.
- Cover the
imaging_and_interferometer variant (imaging preloads meeting the existing PreloadsInterferometer).
- Deliverable: design note (options weighed, decision + rationale per question) + locked
PreloadsImaging / AnalysisImaging.shared_state_from API sketch for Phase 2 + example-section outline for Phase 3.
Detailed implementation plan
Affected Repositories
- PyAutoLens (primary — design decisions land here in Phase 2)
- PyAutoArray, autolens_workspace, autolens_workspace_test, autolens_profiling (downstream phases)
Branch Survey
| Repository |
Current Branch |
Dirty? |
| ./PyAutoArray |
main |
clean (worktree claims: kernel-forward-chunking, rect-adapt) |
| ./PyAutoLens |
main |
clean |
| ./autolens_workspace |
main |
1 modified file (worktree claim: markdown-example-renderings) |
| ./autolens_workspace_test |
main |
clean |
Suggested branch: none — design-only phase, no worktree. (Existing claims above only matter for Phases 2–3.)
Design questions to resolve (the work)
- What is shareable for imaging? Unlike the datacube (channel-invariant
uv/noise → share F = LᵀW̃L + mapper), imaging exposures have per-dataset PSFs and pixel offsets → neither F nor L is invariant. Candidate shared object: the source-plane Delaunay mesh geometry (image-mesh sparse grid traced once from the lead dataset), with each dataset building its own L_i by tracing its offset grid onto that shared mesh. Quantify what this actually saves before committing — if the shareable fraction is small, the honest answer may be "share the mesh for consistency, not speed" and the design should say so explicitly.
- Same-wavelength "one reconstruction" semantics. A genuinely joint solve does not decompose into
FactorGraphModel's per-factor likelihood sum — decide between: (a) a joint-inversion Analysis that owns all N same-λ datasets (one factor), (b) per-factor reconstructions with the mesh shared (N reconstructions on the same mesh — not literally one source), or (c) shared-state carrying the joint solve with per-factor likelihood contributions derived from it. Justify against the sub-task A contract ("shared object computed once, forwarded to factors").
- Different-wavelength semantics: confirm "share mesh geometry only" falls out of whichever mechanism Q2 picks.
- Shift mechanism.
aa.DatasetModel already provides per-dataset (y,x) offset (+ rotation) as optional free parameters (multi/features/dataset_offsets/). Design how DatasetModel offsets compose with the shared mesh (mesh built once in the source plane; each dataset's offset applies to its image-plane grid before tracing). Default = known/fixed from PyAutoReduce target_pixel differences; optional free (dy,dx) with Gaussian priors of width = registration residuals. Simulator support: per-dataset shifts, default 0.
- imaging_and_interferometer: how the shared mesh crosses the two dataset types (imaging preloads vs the existing
aa.PreloadsInterferometer).
- Preloads API shape:
PreloadsImaging fields (mesh/mapper geometry vs mapper_galaxy_dict reuse), what AnalysisImaging.shared_state_from returns, and JAX pytree registration (recompute inside the jitted region each eval — no instance memoisation).
Grounding (verified 2026-07-10)
- Only the interferometer consumer exists (
aa.PreloadsInterferometer, AnalysisInterferometer.shared_preloads/shared_state_from); no PreloadsImaging, nothing on AnalysisImaging.
- The
multi/ examples already use af.FactorGraphModel(*factors, use_jax=True) — the PyAutoFit#1308 mechanism applies directly.
aa.DatasetModel (autoarray/dataset/dataset_model.py) is the existing offset/rotation surface.
- Datacube consumer measured 2026-07-10 at 4.06× per-likelihood (sma × 4 ch) — the pattern being generalised works.
Key Files
PyAutoArray/autoarray/preloads/{abstract,interferometer}.py — the Preloads pattern to extend
PyAutoLens/autolens/interferometer/model/analysis.py — shared_state_from consumer pattern (PR#566)
PyAutoArray/autoarray/dataset/dataset_model.py — existing offset/rotation surface
autolens_workspace/scripts/multi/features/{same_wavelength,wavelength_dependence,imaging_and_interferometer,dataset_offsets}/ — Phase 3 targets
autolens_workspace_test/scripts/jax_likelihood_functions/datacube/shared_preloads.py — parity-test pattern
Process
- Consult
autolens_assistant/ (AGENTS.md → relevant skills//wiki/core/ pages) before locking the source-reconstruction design; PyAutoMemory lensing_wiki/methods_wiki for source-reconstruction + likelihood context.
- Output lands as a design-note comment on this issue; Phases 2–4 prompts get updated with the locked decisions before they are issued.
Original Prompt
Click to expand starting prompt (phase 1; parent prompt with the user's verbatim request + PyAutoReduce registration semantics is at PyAutoMind feature/autolens/multi_shared_state_examples.md → issued/)
See PyAutoMind/issued/multi_shared_state_examples_phase_1_design.md — the six design questions above are its verbatim core; the parent prompt issued/multi_shared_state_examples.md carries the original user request verbatim, the PyAutoReduce frame-products registration semantics (HST/JWST vs Keck, target_pixel, residual_reliable, data_units, PSF-tier provenance), and the use-case → example-script table.
Overview
Phase 1 (of 4) of generalising the shipped datacube shared-state likelihood machinery (#565, PyAutoFit#1307 — both closed; epic
z_features/complete/analysis_shared_state.md) to imaging multi-dataset fitting: one Delaunay mesh shared and shifted across exposures of the same lens. This phase is design-only — its deliverable is a design note + locked API sketch posted on this issue; no source edits. Phases 2 (core library API), 3 (workspace example sections + parity test) and 4 (docs) have prompts in PyAutoMind but are deliberately un-issued until their predecessor nears shipping.Plan
Fand mapping matrixL; the candidate shared object is the source-plane Delaunay mesh geometry. Quantify the saving honestly (speed win vs consistency win).F = Σᵢ LᵢᵀWᵢLᵢ,D = Σᵢ Lᵢᵀdᵢ, ones) does not decompose into the per-factor likelihood sum.aa.DatasetModel: shifts known/fixed by default (PyAutoReducetarget_pixeldifferences), optionally free per-frame (dy, dx) with Gaussian priors of width = the recorded registration residuals (floor ~0.1–0.3 px); simulator shifts default 0.imaging_and_interferometervariant (imaging preloads meeting the existingPreloadsInterferometer).PreloadsImaging/AnalysisImaging.shared_state_fromAPI sketch for Phase 2 + example-section outline for Phase 3.Detailed implementation plan
Affected Repositories
Branch Survey
Suggested branch: none — design-only phase, no worktree. (Existing claims above only matter for Phases 2–3.)
Design questions to resolve (the work)
uv/noise→ shareF = LᵀW̃L+ mapper), imaging exposures have per-dataset PSFs and pixel offsets → neitherFnorLis invariant. Candidate shared object: the source-plane Delaunay mesh geometry (image-mesh sparse grid traced once from the lead dataset), with each dataset building its ownL_iby tracing its offset grid onto that shared mesh. Quantify what this actually saves before committing — if the shareable fraction is small, the honest answer may be "share the mesh for consistency, not speed" and the design should say so explicitly.FactorGraphModel's per-factor likelihood sum — decide between: (a) a joint-inversion Analysis that owns all N same-λ datasets (one factor), (b) per-factor reconstructions with the mesh shared (N reconstructions on the same mesh — not literally one source), or (c) shared-state carrying the joint solve with per-factor likelihood contributions derived from it. Justify against the sub-task A contract ("shared object computed once, forwarded to factors").aa.DatasetModelalready provides per-dataset (y,x) offset (+ rotation) as optional free parameters (multi/features/dataset_offsets/). Design how DatasetModel offsets compose with the shared mesh (mesh built once in the source plane; each dataset's offset applies to its image-plane grid before tracing). Default = known/fixed from PyAutoReducetarget_pixeldifferences; optional free (dy,dx) with Gaussian priors of width = registration residuals. Simulator support: per-dataset shifts, default 0.aa.PreloadsInterferometer).PreloadsImagingfields (mesh/mapper geometry vsmapper_galaxy_dictreuse), whatAnalysisImaging.shared_state_fromreturns, and JAX pytree registration (recompute inside the jitted region each eval — no instance memoisation).Grounding (verified 2026-07-10)
aa.PreloadsInterferometer,AnalysisInterferometer.shared_preloads/shared_state_from); noPreloadsImaging, nothing onAnalysisImaging.multi/examples already useaf.FactorGraphModel(*factors, use_jax=True)— the PyAutoFit#1308 mechanism applies directly.aa.DatasetModel(autoarray/dataset/dataset_model.py) is the existing offset/rotation surface.Key Files
PyAutoArray/autoarray/preloads/{abstract,interferometer}.py— the Preloads pattern to extendPyAutoLens/autolens/interferometer/model/analysis.py—shared_state_fromconsumer pattern (PR#566)PyAutoArray/autoarray/dataset/dataset_model.py— existing offset/rotation surfaceautolens_workspace/scripts/multi/features/{same_wavelength,wavelength_dependence,imaging_and_interferometer,dataset_offsets}/— Phase 3 targetsautolens_workspace_test/scripts/jax_likelihood_functions/datacube/shared_preloads.py— parity-test patternProcess
autolens_assistant/(AGENTS.md → relevantskills//wiki/core/pages) before locking the source-reconstruction design; PyAutoMemorylensing_wiki/methods_wikifor source-reconstruction + likelihood context.Original Prompt
Click to expand starting prompt (phase 1; parent prompt with the user's verbatim request + PyAutoReduce registration semantics is at PyAutoMind feature/autolens/multi_shared_state_examples.md → issued/)
See
PyAutoMind/issued/multi_shared_state_examples_phase_1_design.md— the six design questions above are its verbatim core; the parent promptissued/multi_shared_state_examples.mdcarries the original user request verbatim, the PyAutoReduce frame-products registration semantics (HST/JWST vs Keck,target_pixel,residual_reliable,data_units, PSF-tier provenance), and the use-case → example-script table.