feat(plot): interferometer plots on array-free datasets — natural-weighted dirty panels, inversion subplot fix (streaming phase 3) - #597
Conversation
…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
Independent review (Codex gpt-6-astra) of the three branches before PR-open
FINDINGS (1) Disposition: FINDINGS (1) — 🤖 Generated with Claude Code |
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_streamstays 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)/Σwas one W̃ multiply on the real-space grid viasparse_operator.operated_matrix_slim_from;Σwfromsparse_terms.sum_weightsor the noise map. On an in-memory dataset it matches the transformer path at rel 3e-14 (witness) / 1e-10 (test).subplot_interferometer_dataset/subplot_interferometer_dirty_imagesdraw a 1×2 "Dirty Image (Natural)" / "Dirty Beam (Natural)" on array-free datasets (same filenames);fits_interferometerguards thedatareads and writesDIRTY_IMAGE_NATURAL/DIRTY_BEAMextensions on array-free.subplot_fit_interferometer/subplot_fit_interferometer_dirty_imagestake an optionalmodel_imageand draw the natural dirty image / model / residual on array-free datasets; visibility-space panels are skipped, not approximated._recon_arrayreadmapped_reconstructed_operated_data_dictfirst, which raisesInversionExceptionon an array-free interferometer inversion, and the handlers caught only(AttributeError, KeyError), sosubplot_of_mapper/subplot_mappingsescaped. Array-free interferometer inversions (_is_array_free_interferometer: the class has atransformerattribute and it isNone— imaging inversions are untouched) now readmapped_reconstructed_data_dict;exc.InversionExceptionis caught in both handlers.Witness (1e5 streamed NUFFT visibilities, 40×40 mask, pixelization-only,
af.m.MockSearchwithsave_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-memoryfit_dirty_images.fitsarrays equal the fit'sdirty_*exactly.API Changes
Additive. New
autoarray.fit.fit_interferometer.dirty_model_image_natural_from;subplot_fit_interferometer/subplot_fit_interferometer_dirty_imagesgainmodel_image=None; array-free datasets get a 1×2 natural dataset subplot and natural FITS extensions under the same filenames;subplot_of_mapper/subplot_mappingsno 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 passedmodel_image;subplot_of_mapper/subplot_mappingson an array-free inversion (titles recorded; red with_is_array_free_interferometerforced False);dirty_model_image_natural_fromvs transformer path at rel 1e-10test_autogalaxy1293 passed,test_autolens774 passed + 1 xfailedHeart 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 threefeature/streaming-p3-visualizerbranches ("Authorize override for #596"): commit, push and the pending-release PRs only. Branch gates:test_autoarray1898,test_autogalaxy1293,test_autolens776 + 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 imageW̃·m/Σw(needs asparse_operator)Changed Signature
autoarray.dataset.plot.interferometer_plotsunchanged signatures;autoarray.fit.plot.fit_interferometer_plots.subplot_fit_interferometer(..., model_image=None)andsubplot_fit_interferometer_dirty_images(..., model_image=None)Changed Behaviour
subplot_interferometer_dataset/subplot_interferometer_dirty_images— ondataset.is_array_free, a 1×2 natural dirty image / beam under the same filenamefits_interferometer— guardsdata; writesDIRTY_IMAGE_NATURAL/DIRTY_BEAMon array-freesubplot_fit_interferometer/subplot_fit_interferometer_dirty_images— natural panels on array-free (model/residual whenmodel_imagegiven), visibility panels skippedinversion_plots._recon_array— readsmapped_reconstructed_data_dictfor array-free interferometer inversions;subplot_of_mapper/subplot_mappingscatchexc.InversionExceptionMigration
Generated by the PyAutoLabs agent workflow.
🤖 Generated with Claude Code
https://claude.ai/code/session_01JZZksyZ8LTA4LLxoZjQMNF