Skip to content

feat(plot): interferometer plots on array-free datasets — natural-weighted dirty panels, inversion subplot fix (streaming phase 3) - #597

Merged
Jammy2211 merged 1 commit into
mainfrom
feature/streaming-p3-visualizer
Sep 30, 2026
Merged

Jammy2211 merged 1 commit into
mainfrom
feature/streaming-p3-visualizer

Conversation

@Jammy2211

@Jammy2211 Jammy2211 commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Streaming phase 3 (Mind epic streaming-visibilities; https://github.com/orgs/PyAutoLabs/discussions/13). Closes #596. Siblings: PyAutoLabs/PyAutoGalaxy#640, PyAutoLabs/PyAutoLens#761.

The go/no-go benchmark on the epic ledger settled why this continues: the in-memory sparse path runs out of memory at ~1e6 visibilities on a 16 GB laptop (its one-shot NUFFT precision build allocates ~3 kB per visibility), while from_stream stays at 1.5–1.8 GB to 5e7 and reaches 2e8 in ~40 min at chunk 65536. A streamed fit was usable only with visualization off; this PR makes the interferometer plots work on an array-free dataset, branching in place so filenames and call sites are unchanged and in-memory output is untouched.

  • aa.fit.fit_interferometer.dirty_model_image_natural_from(dataset, image) — the natural-weighted dirty image of a model image, Re(Fᴴ W F m)/Σw as one W̃ multiply on the real-space grid via sparse_operator.operated_matrix_slim_from; Σw from sparse_terms.sum_weights or the noise map. On an in-memory dataset it matches the transformer path at rel 3e-14 (witness) / 1e-10 (test).
  • Dataset plots: subplot_interferometer_dataset / subplot_interferometer_dirty_images draw a 1×2 "Dirty Image (Natural)" / "Dirty Beam (Natural)" on array-free datasets (same filenames); fits_interferometer guards the data reads and writes DIRTY_IMAGE_NATURAL / DIRTY_BEAM extensions on array-free.
  • Fit plots: subplot_fit_interferometer / subplot_fit_interferometer_dirty_images take an optional model_image and draw the natural dirty image / model / residual on array-free datasets; visibility-space panels are skipped, not approximated.
  • Inversion plots (live bug, in-memory too when a transformer is absent): _recon_array read mapped_reconstructed_operated_data_dict first, which raises InversionException on an array-free interferometer inversion, and the handlers caught only (AttributeError, KeyError), so subplot_of_mapper / subplot_mappings escaped. Array-free interferometer inversions (_is_array_free_interferometer: the class has a transformer attribute and it is None — imaging inversions are untouched) now read mapped_reconstructed_data_dict; exc.InversionException is caught in both handlers.

Witness (1e5 streamed NUFFT visibilities, 40×40 mask, pixelization-only, af.m.MockSearch with save_for_aggregator, visualization ON): ag writes 7 files (dataset.fits, dataset.png, fit.png, fit_dirty_images.fits, galaxies.png, galaxy_images.fits, inversion_0_0.png) on the array-free dataset and the same 7 in memory (natural vs classic EXTNAMEs); al writes 10 each. In-memory fit_dirty_images.fits arrays equal the fit's dirty_* exactly.

API Changes

Additive. New autoarray.fit.fit_interferometer.dirty_model_image_natural_from; subplot_fit_interferometer / subplot_fit_interferometer_dirty_images gain model_image=None; array-free datasets get a 1×2 natural dataset subplot and natural FITS extensions under the same filenames; subplot_of_mapper / subplot_mappings no longer raise on an array-free interferometer inversion. In-memory datasets and imaging inversions are byte-unchanged.
See full details below.

Test Plan

  • pytest test_autoarray — 1898 passed
  • New: array-free dataset subplots + fits EXTNAMEs; array-free fit subplots with/without model_image; subplot_of_mapper / subplot_mappings on an array-free inversion (titles recorded; red with _is_array_free_interferometer forced False); dirty_model_image_natural_from vs transformer path at rel 1e-10
  • Downstream suites on the same-named branches: test_autogalaxy 1293 passed, test_autolens 774 passed + 1 xfailed
  • CI green on unittest 3.12 / 3.13 / nojax

Heart RED override (development only)

Heart verdict at ship: RED (2026-09-30T18:32Z): release validation FAILED (stage integrate) (unrelated release-integrate leg) plus two canonical-checkout drift reasons from another session (PyAutoLens: on branch feature/point-solver-padding-backend (not main), PyAutoLens: 2 uncommitted source change(s)) — none caused by these branches. Live human authorization in-session 2026-09-30 for issue #596 and the three feature/streaming-p3-visualizer branches ("Authorize override for #596"): commit, push and the pending-release PRs only. Branch gates: test_autoarray 1898, test_autogalaxy 1293, test_autolens 776 + 1 xfailed; red-checks on the inversion-plot fix and the array-free tests; Codex (gpt-6-astra) review: FINDINGS (1): model-image composition for mixed galaxies, fixed in-branch + red-checked. Merge needs its own explicit human command with every check green.

Full API Changes (for automation & release notes)

Added

  • autoarray.fit.fit_interferometer.dirty_model_image_natural_from(dataset, image) -> Array2D — natural-weighted dirty model image W̃·m/Σw (needs a sparse_operator)

Changed Signature

  • autoarray.dataset.plot.interferometer_plots unchanged signatures; autoarray.fit.plot.fit_interferometer_plots.subplot_fit_interferometer(..., model_image=None) and subplot_fit_interferometer_dirty_images(..., model_image=None)

Changed Behaviour

  • subplot_interferometer_dataset / subplot_interferometer_dirty_images — on dataset.is_array_free, a 1×2 natural dirty image / beam under the same filename
  • fits_interferometer — guards data; writes DIRTY_IMAGE_NATURAL / DIRTY_BEAM on array-free
  • subplot_fit_interferometer / subplot_fit_interferometer_dirty_images — natural panels on array-free (model/residual when model_image given), visibility panels skipped
  • inversion_plots._recon_array — reads mapped_reconstructed_data_dict for array-free interferometer inversions; subplot_of_mapper / subplot_mappings catch exc.InversionException

Migration

  • None.

Generated by the PyAutoLabs agent workflow.

🤖 Generated with Claude Code

https://claude.ai/code/session_01JZZksyZ8LTA4LLxoZjQMNF

…ghted dirty panels, inversion subplot fix (streaming phase 3, #596)

dirty_model_image_natural_from(dataset, image) gives W~·m/Σw without a
transformer; the dataset and fit subplots branch on is_array_free to draw the
natural dirty image / beam / model / residual under the same filenames and
skip visibility-space panels; fits_interferometer guards data and writes the
natural extensions. inversion_plots._recon_array read the operated dict first
and the handlers missed InversionException, so subplot_of_mapper /
subplot_mappings escaped on a transformer-less interferometer inversion; fixed
without touching imaging inversions. In-memory output is unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JZZksyZ8LTA4LLxoZjQMNF
@Jammy2211

Copy link
Copy Markdown
Collaborator Author

Independent review (Codex gpt-6-astra) of the three branches before PR-open

  • P2 — Natural model/residual images omit ordinary light in mixed-component galaxies. autogalaxy/interferometer/fit_interferometer.py:438, autolens/interferometer/fit_interferometer.py:356.

    On an in-memory dataset after apply_sparse_operator(), put an ordinary Sersic and a linear Gaussian—or pixelization—in the same galaxy. galaxy_image_dict replaces that galaxy’s ordinary image with its linear reconstruction. Summing its values therefore omits the ordinary component: dirty_model_image_natural is too small, and dirty_residual_map_natural contains the omitted component’s dirty image.

    Classification: the dictionary overwrite is pre-existing; using it as the complete model introduces this defect into the new properties. Assemble the model from profile_image plus inversion.mapped_reconstructed_data.

    The added tests miss this: they use pixelization-only models and construct their Fourier reference from model_image_natural itself, rather than independently from fit.model_data.

FINDINGS (1)

Disposition: FINDINGS (1) — model_image_natural summed galaxy_image_dict, whose entries are overwritten by a galaxy's linear reconstruction, so a galaxy with both ordinary and linear light lost its ordinary component (reproduced: rel error 1.0 in ag, 1.14/1.31 in al); fixed in-branch as profile_image + inversion.mapped_reconstructed_data, with mixed-galaxy tests against an independent transformer reference from fit.model_data (rel ≤ 2e-14), red-checked. Test names: test__natural_dirty_images__galaxy_with_ordinary_and_linear_light__matches_model_data[linear_light_profile|pixelization] in both repos.

🤖 Generated with Claude Code

@Jammy2211
Jammy2211 merged commit c1d8581 into main Sep 30, 2026
3 checks passed
@Jammy2211
Jammy2211 deleted the feature/streaming-p3-visualizer branch September 30, 2026 19:18
@Jammy2211 Jammy2211 removed the pending-release PR queued for the next release build label Oct 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(interferometer): visualizer on array-free datasets — natural-weighted dirty panels, inversion subplot fix (streaming phase 3)

1 participant