Overview
Behaviour-preserving consolidation sweep from the mined candidates in PyAutoMind/draft/refactor/pyautoreduce/consolidation_sweep.md (Refactor Agent: invariant witnessed by test_autoreduce; API guard none-expected). Public behaviour observable through the test suite is unchanged; no dial or output changes.
Plan
- Move the per-observatory single-exposure-time header knowledge (HST
EXPTIME vs Keck ITIME×COADDS) out of pipeline._psf onto InstrumentAdapter, where the adapter-boundary contract says it belongs — shrinking the if/elif chains the planned ground-based instruments would otherwise extend.
- Merge the two mathematically identical second-moment FWHM helpers (
psf/frame_combine._moment_fwhm, psf/starred_epsf._size_fwhm) into one shared psf/moments.py helper; leave the two genuinely different estimators (epsf._fwhm_of radial half-max diagnostic, nirc2_star._fwhm_arcsec equivalent-area) in place.
- Fold single-function
noise/jwst_rms.py into noise/rms.py (callers/tests updated).
- Rider: gitignore
prototypes/cache_inject/ (the inject-recovery prototype's fresh cache; FITS are never committed).
Detailed implementation plan
Affected Repositories
- PyAutoReduce (primary, only)
Branch Survey
| Repository |
Current Branch |
Dirty? |
| ./PyAutoReduce |
main @ 59beb04 |
clean (background prototype writing to untracked cache dir) |
Suggested branch: refactor/consolidation-sweep
Implementation Steps
autoreduce/instruments/adapter.py — max_single_exposure_seconds(headers) -> Optional[float]: HST max EXPTIME; Keck max ITIME×COADDS; JWST None (surface-brightness mosaics take no full-well cut). Loud on non-positive results for observatories that require it. The per-observatory explanatory comments move with the knowledge.
autoreduce/pipeline.py _psf — replace the hst/keck/else peak_max branches with one call: t = adapter.max_single_exposure_seconds(headers); peak_max = selection.saturation_fraction * adapter.saturation_dn / t if t else None.
- New
autoreduce/psf/moments.py — moment_fwhm(kernel) (second-moment 2.3548σ, non-negative clip); frame_combine and starred_epsf import it; private duplicates deleted.
noise/rms.py absorbs noise_map_from_error from noise/jwst_rms.py; pipeline._noise import updated; noise/jwst_rms.py deleted; tests touching it updated.
.gitignore — add prototypes/cache_inject/.
- Full suite must stay green unchanged (229 passed / 3 skipped baseline).
Key Files
autoreduce/instruments/adapter.py, autoreduce/pipeline.py
autoreduce/psf/moments.py (new), autoreduce/psf/frame_combine.py, autoreduce/psf/starred_epsf.py
autoreduce/noise/rms.py, autoreduce/noise/jwst_rms.py (removed)
Original Prompt
Click to expand starting prompt
See PyAutoMind/draft/refactor/pyautoreduce/consolidation_sweep.md (moves to active/ with this issue) — user request 2026-07-16 + mined candidates (including the checked-and-rejected list: mad_sigma already shared, combine dispatch already centralised, frames.py vs keck_frames.py divergence deliberate).
Autonomy: --auto, effective level safe (refactor cap): plan recorded here in lieu of the Plan-Mode hold per PyAutoBrain/AUTONOMY.md. Behaviour-preservation witness: test_autoreduce. Merge stays human.
Overview
Behaviour-preserving consolidation sweep from the mined candidates in
PyAutoMind/draft/refactor/pyautoreduce/consolidation_sweep.md(Refactor Agent: invariant witnessed bytest_autoreduce; API guard none-expected). Public behaviour observable through the test suite is unchanged; no dial or output changes.Plan
EXPTIMEvs KeckITIME×COADDS) out ofpipeline._psfontoInstrumentAdapter, where the adapter-boundary contract says it belongs — shrinking the if/elif chains the planned ground-based instruments would otherwise extend.psf/frame_combine._moment_fwhm,psf/starred_epsf._size_fwhm) into one sharedpsf/moments.pyhelper; leave the two genuinely different estimators (epsf._fwhm_ofradial half-max diagnostic,nirc2_star._fwhm_arcsecequivalent-area) in place.noise/jwst_rms.pyintonoise/rms.py(callers/tests updated).prototypes/cache_inject/(the inject-recovery prototype's fresh cache; FITS are never committed).Detailed implementation plan
Affected Repositories
Branch Survey
Suggested branch:
refactor/consolidation-sweepImplementation Steps
autoreduce/instruments/adapter.py—max_single_exposure_seconds(headers) -> Optional[float]: HST maxEXPTIME; Keck maxITIME×COADDS; JWSTNone(surface-brightness mosaics take no full-well cut). Loud on non-positive results for observatories that require it. The per-observatory explanatory comments move with the knowledge.autoreduce/pipeline.py_psf— replace the hst/keck/elsepeak_maxbranches with one call:t = adapter.max_single_exposure_seconds(headers); peak_max = selection.saturation_fraction * adapter.saturation_dn / t if t else None.autoreduce/psf/moments.py—moment_fwhm(kernel)(second-moment 2.3548σ, non-negative clip);frame_combineandstarred_epsfimport it; private duplicates deleted.noise/rms.pyabsorbsnoise_map_from_errorfromnoise/jwst_rms.py;pipeline._noiseimport updated;noise/jwst_rms.pydeleted; tests touching it updated..gitignore— addprototypes/cache_inject/.Key Files
autoreduce/instruments/adapter.py,autoreduce/pipeline.pyautoreduce/psf/moments.py(new),autoreduce/psf/frame_combine.py,autoreduce/psf/starred_epsf.pyautoreduce/noise/rms.py,autoreduce/noise/jwst_rms.py(removed)Original Prompt
Click to expand starting prompt
See
PyAutoMind/draft/refactor/pyautoreduce/consolidation_sweep.md(moves toactive/with this issue) — user request 2026-07-16 + mined candidates (including the checked-and-rejected list:mad_sigmaalready shared, combine dispatch already centralised,frames.pyvskeck_frames.pydivergence deliberate).Autonomy: --auto, effective level
safe(refactor cap): plan recorded here in lieu of the Plan-Mode hold perPyAutoBrain/AUTONOMY.md. Behaviour-preservation witness:test_autoreduce. Merge stays human.