Overview
Phase 2a of the extra-galaxies parity task (phase 1, point_source, shipped as autolens_workspace#374 / PR#376).
autogalaxy_workspace/scripts/multi_galaxy/ has no features/ folder at all — its README ends with a one-line "standard single-galaxy features apply per-galaxy here" pointer. This adds one, with a full extra_galaxies worked example in the style of imaging/features/extra_galaxies.
Phase 2 was split by repo: multi-galaxy-imaging-parity (autolens_workspace#370) is in flight and rewriting autolens_workspace/scripts/multi_galaxy/ wholesale, so the autolens half is deferred to phase 2b and written against that merged result. This repo has zero contention with it.
Plan
- Create
scripts/multi_galaxy/features/ (README + __init__.py) — the folder does not exist yet.
- Add
features/extra_galaxies/ with README.md, __init__.py, simulator.py, modeling.py, mirroring imaging/features/extra_galaxies.
- Show both levers, as the imaging example does: noise-scaling the companions out, and modeling their light with fixed centres (
SersicSph Option A, MGE Option B commented).
- What is new versus imaging is the base model: two co-equal blended galaxies via the
galaxy_0, galaxy_1, … loop, plus a lower tier of sub-dominant extra galaxies. That contrast is the point of the example.
- Add a
# Folders section to scripts/multi_galaxy/README.md.
Detailed implementation plan
Affected Repositories
- autogalaxy_workspace (primary)
Branch Survey
| Repository |
Current Branch |
Dirty? |
| ./autogalaxy_workspace |
main |
clean |
Suggested branch: feature/extra-galaxies-multi-galaxy
Implementation Steps
-
scripts/multi_galaxy/features/extra_galaxies/simulator.py — the co-equal pair from multi_galaxy/simulator.py (Sersic bulges at (0.0, -0.75) / (0.0, 0.75)) plus two faint companions further out. Writes data/psf/noise_map.fits, galaxies.json, galaxy_centres.json, extra_galaxies_centres.json and mask_extra_galaxies.fits to dataset/multi_galaxy/extra_galaxies/.
-
scripts/multi_galaxy/features/extra_galaxies/modeling.py — larger mask to admit the companions (the imaging example uses 6.0" against multi_galaxy/modeling.py's 3.0"), noise-scaling fit first, then the modeling fit with one mge_model_from per co-equal galaxy plus an extra_galaxies collection of fixed-centre lp_linear.SersicSph (Option A) / MGE (Option B, commented).
-
features/README.md + features/extra_galaxies/README.md + both __init__.py.
-
scripts/multi_galaxy/README.md — add # Folders.
-
smoke_tests.txt — add the new modeling.py (multi_galaxy scripts are smoke-enabled here).
-
Regenerate notebooks + navigator via generate.py autogalaxy.
Conventions (autogalaxy differs from autolens)
- Centres file is
galaxy_centres.json, not main_lens_centres.json.
- Light-only: no mass model, so no
IsothermalSph tier — companions are fitted or noise-scaled purely photometrically.
features/README.md should carry the existing "Scaling Relations (not applicable in autogalaxy)" framing from imaging/features/extra_galaxies/README.md, so the autolens scaling-relation tier is not implied to transfer.
Known traps
should_simulate tests directory existence only — rm -rf dataset/multi_galaxy/extra_galaxies before any validation run.
PYAUTO_TEST_MODE=1 and =2 share the output/test_mode/ namespace, so a bypass run silently resumes a reduced-iterations run — rm -rf output/test_mode before trusting a bypass result. (Hit in phase 1.)
- Navigator root-name trap:
check_navigator.py strips a leading <root.name>/ prefix and CI clones the workspace as workspace/, so a literal autogalaxy_workspace/scripts/... reference passes locally and fails in CI. Use the wildcard autogalaxy_workspace/*/... form; reproduce CI by cloning into a dir named workspace.
- Bulk-edit rule: never whole-file write a file not fully read; run
scripts/check_sizes.sh.
Key Files
scripts/multi_galaxy/features/extra_galaxies/** — new
scripts/multi_galaxy/features/README.md, __init__.py — new folder
scripts/multi_galaxy/README.md — # Folders
smoke_tests.txt
scripts/imaging/features/extra_galaxies/{README.md,modeling.py,simulator.py} — prose + API source
scripts/multi_galaxy/{simulator,modeling}.py — co-equal pair conventions
Acceptance
- Simulator writes the dataset + all four metadata files from a clean folder.
modeling.py runs under PYAUTO_TEST_MODE=2 / PYAUTO_SMALL_DATASETS=1; added to smoke_tests.txt.
run_smoke.py green; check_sizes.sh clean; notebooks + navigator regenerated.
cluster/ untouched.
Original Prompt
Click to expand starting prompt
Phase 2a — extra_galaxies feature: multi_galaxy (autogalaxy_workspace)
Type: docs
Target: autogalaxy_workspace
Repos:
- autogalaxy_workspace
Difficulty: medium
Autonomy: supervised
Priority: normal
Status: draft
Parent: draft/docs/workspaces/extra_galaxies_feature_parity.md
Phase 2a of the extra-galaxies parity task. Phase 1 (point_source) shipped as
autolens_workspace#374 / PR#376.
Adopt same style and approach for documenting extra galaxies in multi_galaxy,
do same in autogalaxy_workspace.
Human decision 2026-07-29: full worked example (own simulator + own simulated dataset),
not a cross-link — matching autolens_workspace's sibling tier
multi_galaxy/features/scaling_galaxies/, which gets full-example treatment.
Split decision 2026-07-30: phase 2 was split by repo. multi-galaxy-imaging-parity
(autolens_workspace#370) is actively in flight in another session and rewrites
autolens_workspace/scripts/multi_galaxy/ wholesale — 2,959 insertions across
start_here/modeling/fit/simulator plus 3 new scripts, including adding a faint extra
galaxy + mask_extra_galaxies.fits to multi_galaxy/simulator.py and an
__Extra Galaxies Noise Scaling__ section to the core scripts. The autolens half of this
task must be written against that merged result, so it is deferred to phase 2b. The
autogalaxy half has zero contention (#370 does not touch autogalaxy_workspace) and runs
now.
Scope
autogalaxy_workspace/scripts/multi_galaxy/ has no features/ folder at all. Create:
scripts/multi_galaxy/features/{README.md, __init__.py}
scripts/multi_galaxy/features/extra_galaxies/{README.md, __init__.py, simulator.py, modeling.py}
Plus: add a # Folders section to scripts/multi_galaxy/README.md (it currently has none —
its last line is a one-liner pointing at imaging/features).
The shape of the example
Light-only. PyAutoGalaxy has no mass, so unlike the point-source phase (mass-only) and
like the autogalaxy imaging example, extra galaxies here are faint companions whose light
blends with the co-equal pair. Both levers exist and both should be shown, as
autogalaxy_workspace/scripts/imaging/features/extra_galaxies/modeling.py does:
- Noise scaling —
mask_extra_galaxies.fits + dataset.apply_noise_scaling(mask=...),
then fit the pair without the extras in the model.
- Modeling — extras in the model as
ag.lp_linear.SersicSph with bulge.centre fixed
to the loaded centre (Option A), with the ag.model_util.mge_model_from(centre_fixed=...)
MGE variant shown commented-out as Option B. Both are the established autogalaxy
convention — keep them.
What is new relative to the imaging example is the base model: two co-equal blended
galaxies via the galaxy_0, galaxy_1, ... loop over galaxy_centres.json
(multi_galaxy/modeling.py:109-122, one mge_model_from per galaxy), plus a lower tier of
extra galaxies at fixed centres. That contrast — co-equal subjects and sub-dominant
perturbers in one model — is the point of the example, and the prose should say so.
Conventions to match (autogalaxy differs from autolens)
- The main pair's centres file is
galaxy_centres.json, not autolens's
main_lens_centres.json (multi_galaxy/simulator.py:143-145).
- The main pair sits at
(0.0, -0.75) / (0.0, 0.75) with Sersic bulges, and
modeling.py uses mask_radius=3.0. A larger mask is needed to admit the extra galaxies —
the imaging example uses 6.0" for exactly this reason.
- Imports are
ag. / aplt.; scripts open with from autogalaxy import jax_wrapper then the
commented setup_notebook line.
- Dataset path is
Path("dataset", "multi_galaxy", <name>).
- The new
features/README.md should carry the autogalaxy-specific
"Scaling Relations (not applicable in autogalaxy)" framing already written in
scripts/imaging/features/extra_galaxies/README.md:18-47 — do not imply the autolens
scaling-relation tier transfers.
Constraints / known traps
- The new
modeling.py should join smoke_tests.txt — multi_galaxy scripts are smoke-enabled
in this repo (autogalaxy_workspace/smoke_tests.txt:6-7).
should_simulate tests directory EXISTENCE only — rm -rf dataset/multi_galaxy/extra_galaxies
before any validation run ([[feedback_should_simulate_existence_only]]).
PYAUTO_TEST_MODE=1 and =2 share the output/test_mode/ namespace, so a bypass run
silently resumes a reduced-iterations run. rm -rf output/test_mode before trusting a
bypass result ([[feedback_autofit_cache_resume_pyauto_test_mode]]).
- Workspace bulk-edit rule: never whole-file
Write a file not fully read; run
scripts/check_sizes.sh before committing.
- Navigator root-name trap —
check_navigator.py strips a leading <root.name>/ prefix
and CI clones the workspace as workspace/, so a literal autogalaxy_workspace/scripts/...
reference passes locally and fails in CI. Use the wildcard autogalaxy_workspace/*/...
form. Reproduce CI by cloning into a dir named workspace and passing --root workspace
([[reference_docs_ci_gotchas_workspace_assistant]]).
Acceptance
simulator.py writes its dataset + galaxy_centres.json + extra_galaxies_centres.json +
mask_extra_galaxies.fits from a clean dataset folder.
modeling.py runs under PYAUTO_TEST_MODE=2 / PYAUTO_SMALL_DATASETS=1 and is added to
smoke_tests.txt.
python .github/scripts/run_smoke.py green; scripts/check_sizes.sh clean.
- Every new folder has a
README.md + __init__.py; multi_galaxy/README.md gains a
# Folders section (README ref-drift is CI-gated).
- Notebooks + navigator catalogue regenerated via PyAutoHands
generate.py autogalaxy.
cluster/ untouched.
Overview
Phase 2a of the extra-galaxies parity task (phase 1,
point_source, shipped as autolens_workspace#374 / PR#376).autogalaxy_workspace/scripts/multi_galaxy/has nofeatures/folder at all — its README ends with a one-line "standard single-galaxy features apply per-galaxy here" pointer. This adds one, with a fullextra_galaxiesworked example in the style ofimaging/features/extra_galaxies.Phase 2 was split by repo:
multi-galaxy-imaging-parity(autolens_workspace#370) is in flight and rewritingautolens_workspace/scripts/multi_galaxy/wholesale, so the autolens half is deferred to phase 2b and written against that merged result. This repo has zero contention with it.Plan
scripts/multi_galaxy/features/(README +__init__.py) — the folder does not exist yet.features/extra_galaxies/withREADME.md,__init__.py,simulator.py,modeling.py, mirroringimaging/features/extra_galaxies.SersicSphOption A, MGE Option B commented).galaxy_0,galaxy_1, … loop, plus a lower tier of sub-dominant extra galaxies. That contrast is the point of the example.# Folderssection toscripts/multi_galaxy/README.md.Detailed implementation plan
Affected Repositories
Branch Survey
Suggested branch:
feature/extra-galaxies-multi-galaxyImplementation Steps
scripts/multi_galaxy/features/extra_galaxies/simulator.py— the co-equal pair frommulti_galaxy/simulator.py(Sersic bulges at(0.0, -0.75)/(0.0, 0.75)) plus two faint companions further out. Writesdata/psf/noise_map.fits,galaxies.json,galaxy_centres.json,extra_galaxies_centres.jsonandmask_extra_galaxies.fitstodataset/multi_galaxy/extra_galaxies/.scripts/multi_galaxy/features/extra_galaxies/modeling.py— larger mask to admit the companions (the imaging example uses 6.0" againstmulti_galaxy/modeling.py's 3.0"), noise-scaling fit first, then the modeling fit with onemge_model_fromper co-equal galaxy plus anextra_galaxiescollection of fixed-centrelp_linear.SersicSph(Option A) / MGE (Option B, commented).features/README.md+features/extra_galaxies/README.md+ both__init__.py.scripts/multi_galaxy/README.md— add# Folders.smoke_tests.txt— add the newmodeling.py(multi_galaxy scripts are smoke-enabled here).Regenerate notebooks + navigator via
generate.py autogalaxy.Conventions (autogalaxy differs from autolens)
galaxy_centres.json, notmain_lens_centres.json.IsothermalSphtier — companions are fitted or noise-scaled purely photometrically.features/README.mdshould carry the existing "Scaling Relations (not applicable in autogalaxy)" framing fromimaging/features/extra_galaxies/README.md, so the autolens scaling-relation tier is not implied to transfer.Known traps
should_simulatetests directory existence only —rm -rf dataset/multi_galaxy/extra_galaxiesbefore any validation run.PYAUTO_TEST_MODE=1and=2share theoutput/test_mode/namespace, so a bypass run silently resumes a reduced-iterations run —rm -rf output/test_modebefore trusting a bypass result. (Hit in phase 1.)check_navigator.pystrips a leading<root.name>/prefix and CI clones the workspace asworkspace/, so a literalautogalaxy_workspace/scripts/...reference passes locally and fails in CI. Use the wildcardautogalaxy_workspace/*/...form; reproduce CI by cloning into a dir namedworkspace.scripts/check_sizes.sh.Key Files
scripts/multi_galaxy/features/extra_galaxies/**— newscripts/multi_galaxy/features/README.md,__init__.py— new folderscripts/multi_galaxy/README.md—# Folderssmoke_tests.txtscripts/imaging/features/extra_galaxies/{README.md,modeling.py,simulator.py}— prose + API sourcescripts/multi_galaxy/{simulator,modeling}.py— co-equal pair conventionsAcceptance
modeling.pyruns underPYAUTO_TEST_MODE=2/PYAUTO_SMALL_DATASETS=1; added tosmoke_tests.txt.run_smoke.pygreen;check_sizes.shclean; notebooks + navigator regenerated.cluster/untouched.Original Prompt
Click to expand starting prompt
Phase 2a — extra_galaxies feature: multi_galaxy (autogalaxy_workspace)
Type: docs
Target: autogalaxy_workspace
Repos:
Difficulty: medium
Autonomy: supervised
Priority: normal
Status: draft
Parent: draft/docs/workspaces/extra_galaxies_feature_parity.md
Phase 2a of the extra-galaxies parity task. Phase 1 (point_source) shipped as
autolens_workspace#374 / PR#376.
Human decision 2026-07-29: full worked example (own simulator + own simulated dataset),
not a cross-link — matching
autolens_workspace's sibling tiermulti_galaxy/features/scaling_galaxies/, which gets full-example treatment.Split decision 2026-07-30: phase 2 was split by repo.
multi-galaxy-imaging-parity(autolens_workspace#370) is actively in flight in another session and rewrites
autolens_workspace/scripts/multi_galaxy/wholesale — 2,959 insertions acrossstart_here/modeling/fit/simulatorplus 3 new scripts, including adding a faint extragalaxy +
mask_extra_galaxies.fitstomulti_galaxy/simulator.pyand an__Extra Galaxies Noise Scaling__section to the core scripts. The autolens half of thistask must be written against that merged result, so it is deferred to phase 2b. The
autogalaxy half has zero contention (#370 does not touch autogalaxy_workspace) and runs
now.
Scope
autogalaxy_workspace/scripts/multi_galaxy/has nofeatures/folder at all. Create:scripts/multi_galaxy/features/{README.md, __init__.py}scripts/multi_galaxy/features/extra_galaxies/{README.md, __init__.py, simulator.py, modeling.py}Plus: add a
# Folderssection toscripts/multi_galaxy/README.md(it currently has none —its last line is a one-liner pointing at
imaging/features).The shape of the example
Light-only. PyAutoGalaxy has no mass, so unlike the point-source phase (mass-only) and
like the autogalaxy imaging example, extra galaxies here are faint companions whose light
blends with the co-equal pair. Both levers exist and both should be shown, as
autogalaxy_workspace/scripts/imaging/features/extra_galaxies/modeling.pydoes:mask_extra_galaxies.fits+dataset.apply_noise_scaling(mask=...),then fit the pair without the extras in the model.
ag.lp_linear.SersicSphwithbulge.centrefixedto the loaded centre (Option A), with the
ag.model_util.mge_model_from(centre_fixed=...)MGE variant shown commented-out as Option B. Both are the established autogalaxy
convention — keep them.
What is new relative to the imaging example is the base model: two co-equal blended
galaxies via the
galaxy_0,galaxy_1, ... loop overgalaxy_centres.json(
multi_galaxy/modeling.py:109-122, onemge_model_fromper galaxy), plus a lower tier ofextra galaxies at fixed centres. That contrast — co-equal subjects and sub-dominant
perturbers in one model — is the point of the example, and the prose should say so.
Conventions to match (autogalaxy differs from autolens)
galaxy_centres.json, not autolens'smain_lens_centres.json(multi_galaxy/simulator.py:143-145).(0.0, -0.75)/(0.0, 0.75)withSersicbulges, andmodeling.pyusesmask_radius=3.0. A larger mask is needed to admit the extra galaxies —the imaging example uses 6.0" for exactly this reason.
ag./aplt.; scripts open withfrom autogalaxy import jax_wrapperthen thecommented
setup_notebookline.Path("dataset", "multi_galaxy", <name>).features/README.mdshould carry the autogalaxy-specific"Scaling Relations (not applicable in autogalaxy)" framing already written in
scripts/imaging/features/extra_galaxies/README.md:18-47— do not imply the autolensscaling-relation tier transfers.
Constraints / known traps
modeling.pyshould joinsmoke_tests.txt— multi_galaxy scripts are smoke-enabledin this repo (
autogalaxy_workspace/smoke_tests.txt:6-7).should_simulatetests directory EXISTENCE only —rm -rf dataset/multi_galaxy/extra_galaxiesbefore any validation run ([[feedback_should_simulate_existence_only]]).
PYAUTO_TEST_MODE=1and=2share theoutput/test_mode/namespace, so a bypass runsilently resumes a reduced-iterations run.
rm -rf output/test_modebefore trusting abypass result ([[feedback_autofit_cache_resume_pyauto_test_mode]]).
Writea file not fully read; runscripts/check_sizes.shbefore committing.check_navigator.pystrips a leading<root.name>/prefixand CI clones the workspace as
workspace/, so a literalautogalaxy_workspace/scripts/...reference passes locally and fails in CI. Use the wildcard
autogalaxy_workspace/*/...form. Reproduce CI by cloning into a dir named
workspaceand passing--root workspace([[reference_docs_ci_gotchas_workspace_assistant]]).
Acceptance
simulator.pywrites its dataset +galaxy_centres.json+extra_galaxies_centres.json+mask_extra_galaxies.fitsfrom a clean dataset folder.modeling.pyruns underPYAUTO_TEST_MODE=2/PYAUTO_SMALL_DATASETS=1and is added tosmoke_tests.txt.python .github/scripts/run_smoke.pygreen;scripts/check_sizes.shclean.README.md+__init__.py;multi_galaxy/README.mdgains a# Folderssection (README ref-drift is CI-gated).generate.py autogalaxy.cluster/untouched.