Skip to content

feat: persist the interferometer primary beam through analysis save and aggregator rebuild #654

Closed

Description

@Jammy2211

Overview

Follow-up of PyAutoArray#644 (primary beam; hub #35, @HRSAstro). The beam is saved nowhere by AnalysisInterferometer.save_attributes, so an aggregator-rebuilt Interferometer / FitInterferometer loses it and the likelihood changes. Persist it as a trailing PRIMARY_BEAM HDU and pass it back into both rebuild constructors.

Plan

  • interferometer_hdu_list_from: append the beam (native float64, masked pixels 0) as a trailing PRIMARY_BEAM HDU in both the in-memory and array-free layouts; legacy indices unchanged.
  • Aggregator _interferometer_from: detect the HDU by name (_has_hdu, never positional), pass primary_beam= into from_sparse_terms and aa.Interferometer.
  • PyAutoLens: docstring line + mirror round-trip test (reuses the autogalaxy functions, no source change).
  • Tests: beamed round trips (in-memory, array-free) with identical beam arrays and identical log_likelihood / log_evidence / figure_of_merit, differing from the beamless fit; beamless writes no extra HDU (count pinned at 4) and reloads primary_beam=None; old outputs without the HDU still load.
  • Tier: glance — merge mode: auto-merge on green if the Witness passes, post-merge summary (library-first: PyAutoGalaxy then PyAutoLens)
Detailed implementation plan

Affected Repositories

  • PyAutoGalaxy (primary)
  • PyAutoLens (docstring + mirror test)

Branch Survey

Repository Current Branch Dirty?
galaxy/PyAutoGalaxy main clean
lens/PyAutoLens main clean (feature/point-source-image-overlay claimed by another task: PR #780 awaiting /prm; this task touches only test + docstring, separate branch)

Suggested branch: feature/interferometer-primary-beam-persistence

Implementation Steps

See the prompt's "What" section (steps 1-4 with file:line anchors).

Key Files

  • autogalaxy/interferometer/model/analysis.py — interferometer_hdu_list_from (:76-218), save_attributes (:400-455)
  • autogalaxy/aggregator/interferometer/interferometer.py — _interferometer_from (:161-235), _has_hdu (:50-59)
  • test_autogalaxy/interferometer/model/test_analysis_interferometer.py — round-trip patterns (:148, :172-255, :258-285)
  • autolens/interferometer/model/analysis.py (:336-339), test_autolens/interferometer/model/test_analysis_interferometer.py (:220)

Original Prompt

Click to expand starting prompt

Persist the interferometer primary beam through analysis save and aggregator rebuild

Type: feature
Target: PyAutoGalaxy
Repos:

  • PyAutoGalaxy
  • PyAutoLens
    Difficulty: small
    Autonomy: safe
    Priority: medium
    Parent: complete/2026/10/interferometer-primary-beam.md
    Status: formalised
    Consequence: glance
    Witness: a test asserting an Interferometer with a primary beam saved by AnalysisInterferometer and rebuilt by the aggregator carries an identical primary_beam_slim
    Review-minutes: 3
    Unattended: ready
    Filed: 2026-10-21

What (survey of main 2026-10-21, PyAutoArray at 034a616f incl. #644/#645)

The beam is saved nowhere today. interferometer_hdu_list_from (autogalaxy/interferometer/model/analysis.py:76-218) writes one FITS: in-memory branch HDUs MASK, DATA, NOISE_MAP, UV_WAVELENGTHS (:117-126); array-free branch MASK, NUFFT_PRECISION_OPERATOR, DIRTY_IMAGE, DIRTY_BEAM, SPARSE_TERMS_SCALARS (:129-217). save_attributes (:400-455) writes image/dataset.fits and transformer_class. The aggregator _interferometer_from (autogalaxy/aggregator/interferometer/interferometer.py:161-235) rebuilds via from_sparse_terms (:206-213) or aa.Interferometer(...) (:215-231); _hdu() falls back to legacy positional indices, so a new HDU must be detected with _has_hdu. PyAutoLens reuses both functions (no source change). FitInterferometer passes the dataset's transformer and sparse_operator to DatasetInterface, so passing primary_beam= back into the constructor is sufficient.

  1. analysis.py: helper _primary_beam_native_from(dataset) → None or the float64 native array (masked pixels 0) of primary_beam_slim on real_space_mask; append it as a trailing PRIMARY_BEAM HDU in both branches (legacy indices 0-3 unchanged); docstrings.
  2. aggregator/interferometer/interferometer.py: _primary_beam_from(hdu_list) via _has_hdu; pass primary_beam= into from_sparse_terms and aa.Interferometer; docstrings.
  3. Tests in test_autogalaxy/interferometer/model/test_analysis_interferometer.py (extend the round-trip patterns at :148, :172-255, :258-285 with a Gaussian beam spanning ~0.3-1 on interferometer_7): (a) in-memory beamed round trip — PRIMARY_BEAM present, primary_beam_slim and transformer.primary_beam_slim identical, FitInterferometer.log_likelihood equal (rel 1e-10) for light-profile and pixelization galaxies, and different from the beamless fit; (b) array-free beamed round trip via from_stream(primary_beam=) — sparse_operator.primary_beam_slim identical, log_evidence / figure_of_merit equal; (c) beamless writes no PRIMARY_BEAM HDU, HDU count pinned at 4, reload gives primary_beam is None; (d) old outputs without the HDU still load with primary_beam=None for both layouts.
  4. PyAutoLens: docstring line at autolens/interferometer/model/analysis.py:336-339 and a mirror beamed round-trip test next to test_autolens/interferometer/model/test_analysis_interferometer.py:220 (optional, do it).

Not in scope: the pre-existing gap that an in-memory dataset with apply_sparse_operator comes back without the operator (likelihood still matches via the beamed transformer); the forced-numba fallback and repeated P=0 warning (PyAutoArray side, separate small prompt if wanted).

Activity

  1. Jammy2211 commented on Oct 21, 2026

    @Jammy2211
    CollaboratorAuthor

    Library PR created: #655 (head f7f6d79). Workspace impact: none. PyAutoLens docstring + mirror test deferred (checkout claimed by another task). Heart YELLOW acknowledged by the human 2026-10-21. Tier glance: auto-merge on green if the Witness passes.

  2. Jammy2211 commented on Oct 21, 2026

    @Jammy2211
    CollaboratorAuthor

    Shipped: #655 merged (glance tier, auto-merged on green: docs-build, unittest 3.12 / 3.13 / nojax all pass; Witness round-trip tests in-run). Pending release. Deferred follow-up: PyAutoLens docstring line + mirror round-trip test once its checkout claim clears.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions