feat(interferometer): fits and save_attributes on array-free datasets (streaming phase 2) - #758
Conversation
… (streaming phase 2, PyAutoGalaxy#638) Mirror the autogalaxy guards in FitInterferometer (profile_visibilities None or a typed DatasetException without a transformer; profile_subtracted_visibilities None without data; inversion_with_data returns the inversion) and write dataset.fits through autogalaxy's interferometer_hdu_list_from, skipping transformer_class.json when there is no transformer. The aggregator loader is autogalaxy's and needs no change. 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 this branch pair before PR-open
FINDINGS (3) Disposition: FINDINGS (3) — #1 FITS header cards truncate float64 scalars (reproduced: 1.2345678901234567e+20 → 1.23456789012345e+20): fixed in-branch with a lossless 🤖 Generated with Claude Code |
Summary
PyAutoLens half of streaming phase 2 (Mind epic
streaming-visibilities; https://github.com/orgs/PyAutoLabs/discussions/13). Pairs with PyAutoLabs/PyAutoGalaxy#639 (issue PyAutoLabs/PyAutoGalaxy#638); requires PyAutoLabs/PyAutoArray#593 (phase 1). CI on this branch resolves the same-named PyAutoGalaxy branch.FitInterferometer.profile_visibilitiesreturnsNoneon an array-free dataset when the tracer has no ordinary light profile and raises a typedDatasetExceptionwhen it does;profile_subtracted_visibilitiesevaluates it first, then returnsNonewithout data;inversion_with_datareturns the inversion itself without data. In-memory fits unchanged.AnalysisInterferometer.save_attributeswritesdataset.fitsthrough autogalaxy'sinterferometer_hdu_list_from(array-free datasets persist theirSparseTermsas FITS extensions) and writestransformer_class.jsononly when a transformer exists. The aggregator loader is autogalaxy's (imported), so reload needs no change here.Witness (same setup as the PyAutoGalaxy PR, with an Isothermal lens + pixelized source):
log_evidence−315436.25588951 in memory, identical array-free and after aggregator reload (rel 0.0); array-free vs in-memory rel 1.9e-16; jit vs numpy rel 2.6e-14;dataset.fits80,640 B (vs 4.8 MB of visibilities).API Changes
Behaviour on array-free datasets only:
profile_visibilities/profile_subtracted_visibilitiesmay returnNoneor raiseaa.exc.DatasetException;save_attributeswrites EXTNAME-tagged HDUs (same arrays as before for in-memory datasets) and skipstransformer_class.jsonwithout a transformer.See full details below.
Test Plan
pytest test_autolens— 770 passed, 1 xfailedjax.jit); lens light on an array-free dataset raises; tracer save → reload round trip with EXTNAME assertionsHeart RED override (development only)
Heart verdict at ship: RED, exact reason
release validation FAILED (stage integrate)(2026-09-30T12:42Z, unrelated). Live human authorization in-session 2026-09-30 for issue PyAutoLabs/PyAutoGalaxy#638 and both branches ("Authorize override for #638"): commit, push, pending-release PRs only. Branch gates:test_autolens770 passed + 1 xfailed,test_autogalaxy1287 passed, round-trip red-check, Codex review: FINDINGS (3): #1 + #3 fixed in-branch (red-checked), #2 pre-existing → bug draft filed. Merge needs its own explicit human command with every check green.Full API Changes (for automation & release notes)
Changed Behaviour
FitInterferometer.profile_visibilities/profile_subtracted_visibilities—Noneon an array-free dataset with no ordinary light profile;aa.exc.DatasetExceptionwith one;inversion_with_datareturns the inversion itself when the fit has no dataAnalysisInterferometer.save_attributes— usesautogalaxy.interferometer.model.analysis.interferometer_hdu_list_from;transformer_class.jsononly when a transformer existsMigration
Generated by the PyAutoLabs agent workflow.
🤖 Generated with Claude Code
https://claude.ai/code/session_01JZZksyZ8LTA4LLxoZjQMNF