pyreduce-astro 0.7b4__tar.gz → 0.8a2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/.gitignore +2 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/CHANGELOG.md +66 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/CLAUDE.md +37 -16
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/PKG-INFO +10 -4
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/README.md +7 -3
- pyreduce_astro-0.8a2/WhatsNew.md +94 -0
- pyreduce_astro-0.8a2/examples/andes_riz.py +167 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/andes_yjh_example.py +21 -33
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/crires_plus_example.py +0 -4
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/custom_instrument_example.py +0 -4
- pyreduce_astro-0.8a2/examples/debug_single_swath.py +139 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/harpn_example.py +0 -4
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/harps_example.py +0 -4
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/harps_gridsearch.py +1 -5
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/just_one_swath.py +11 -34
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/jwst_miri_example.py +0 -4
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/jwst_niriss_example.py +0 -4
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/lick_apf_example.py +0 -4
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/mcdonald_example.py +0 -4
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/metis_ifu_example.py +0 -4
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/metis_lss_example.py +0 -4
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/micado_example.py +0 -4
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/mosaic_nir.py +6 -14
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/mosaic_preset-slitfunc.py +32 -30
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/mosaic_vis.py +9 -14
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/neid_example.py +0 -4
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/nirspec_example.py +0 -4
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/toes_example.py +0 -4
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/uves_callfunc.py +13 -17
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/uves_example.py +0 -4
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/examples/xshooter_example.py +0 -4
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyproject.toml +7 -1
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/__main__.py +8 -6
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/cli.py +1 -1
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/combine_frames.py +15 -13
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/configuration.py +20 -4
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/continuum_normalization.py +24 -24
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/cwrappers.py +2 -2
- pyreduce_astro-0.8a2/pyreduce/echelle.py +18 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/estimate_background_scatter.py +42 -36
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/extract.py +650 -227
- pyreduce_astro-0.8a2/pyreduce/instruments/ANDES_RIZ/__init__.py +27 -0
- pyreduce_astro-0.8a2/pyreduce/instruments/ANDES_RIZ/config.yaml +89 -0
- pyreduce_astro-0.8a2/pyreduce/instruments/ANDES_RIZ/order_centers_r0.yaml +20 -0
- pyreduce_astro-0.8a2/pyreduce/instruments/ANDES_RIZ/order_centers_r1.yaml +20 -0
- pyreduce_astro-0.8a2/pyreduce/instruments/ANDES_RIZ/order_centers_r2.yaml +20 -0
- pyreduce_astro-0.8a2/pyreduce/instruments/ANDES_RIZ/settings.json +39 -0
- pyreduce_astro-0.8a2/pyreduce/instruments/ANDES_RIZ/wavecal_r0_HDF.npz +0 -0
- pyreduce_astro-0.8a2/pyreduce/instruments/ANDES_RIZ/wavecal_r1_HDF.npz +0 -0
- pyreduce_astro-0.8a2/pyreduce/instruments/ANDES_RIZ/wavecal_r2_HDF.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/ANDES_YJH/config.yaml +11 -3
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/ANDES_YJH/settings.json +1 -1
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/CRIRES_PLUS/__init__.py +3 -2
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/CRIRES_PLUS/settings.json +1 -1
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/HARPN/settings.json +1 -1
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/HARPS/settings.json +1 -1
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/JWST_MIRI/settings.json +1 -1
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/JWST_NIRISS/settings.json +1 -1
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/LICK_APF/settings.json +2 -2
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/MCDONALD/settings.json +1 -1
- pyreduce_astro-0.8a2/pyreduce/instruments/METIS_IFU/__init__.py +118 -0
- pyreduce_astro-0.8a2/pyreduce/instruments/METIS_IFU/config.yaml +63 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/METIS_IFU/settings.json +12 -18
- pyreduce_astro-0.8a2/pyreduce/instruments/METIS_LSS/settings.json +4 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/MICADO/settings.json +1 -1
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/MOSAIC/config.yaml +1 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/MOSAIC/settings.json +2 -2
- pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/settings_VIS3.json → pyreduce_astro-0.8a2/pyreduce/instruments/MOSAIC/settings_VIS1.json +1 -1
- pyreduce_astro-0.8a2/pyreduce/instruments/MOSAIC/settings_VIS2.json +4 -0
- pyreduce_astro-0.8a2/pyreduce/instruments/MOSAIC/settings_VIS3.json +4 -0
- pyreduce_astro-0.8a2/pyreduce/instruments/MOSAIC/settings_VIS4.json +4 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/MOSAIC/settings_nir.json +2 -6
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/NEID/settings.json +1 -1
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/NIRSPEC/settings.json +1 -1
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/NTE/settings.json +2 -2
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/settings.json +1 -1
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/XSHOOTER/settings.json +2 -2
- pyreduce_astro-0.8a2/pyreduce/instruments/defaults/atlas/lfc.fits +0 -0
- pyreduce_astro-0.8a2/pyreduce/instruments/defaults/atlas/lfc_list.txt +321 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/defaults/config.yaml +6 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/defaults/schema.json +19 -10
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/defaults/settings.json +3 -3
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/models.py +28 -7
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/pipeline.py +56 -91
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/rectify.py +66 -35
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/reduce.py +901 -563
- pyreduce_astro-0.8a2/pyreduce/slit_curve.py +942 -0
- pyreduce_astro-0.8a2/pyreduce/spectra.py +668 -0
- pyreduce_astro-0.8a2/pyreduce/tools/combine.py +184 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/trace.py +486 -757
- pyreduce_astro-0.8a2/pyreduce/trace_model.py +614 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/util.py +10 -103
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/wavelength_calibration.py +98 -71
- pyreduce_astro-0.8a2/tools/andes_hdf_to_wavecal.py +322 -0
- pyreduce_astro-0.8a2/tools/andes_plot_spectra.py +111 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/tools/create_wavelength_guess.py +10 -5
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/tools/mosaic_vis_bundle_plot.py +0 -4
- pyreduce_astro-0.8a2/tools/plot_extractmodel_comp.py +15 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/tools/plot_swath_debug.py +0 -3
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/uv.lock +283 -277
- pyreduce_astro-0.7b4/ANDES_plan.md +0 -377
- pyreduce_astro-0.7b4/examples/debug_single_swath.py +0 -233
- pyreduce_astro-0.7b4/pyreduce/echelle.py +0 -413
- pyreduce_astro-0.7b4/pyreduce/extraction_height.py +0 -77
- pyreduce_astro-0.7b4/pyreduce/instruments/METIS_IFU/__init__.py +0 -42
- pyreduce_astro-0.7b4/pyreduce/instruments/METIS_IFU/config.yaml +0 -62
- pyreduce_astro-0.7b4/pyreduce/instruments/METIS_LSS/settings.json +0 -4
- pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/settings_VIS1.json +0 -22
- pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/settings_VIS2.json +0 -22
- pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/settings_VIS4.json +0 -22
- pyreduce_astro-0.7b4/pyreduce/slit_curve.py +0 -671
- pyreduce_astro-0.7b4/pyreduce/tools/combine.py +0 -118
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/.gitattributes +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/.pre-commit-config.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/.python-version +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/.readthedocs.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/AGENTS.md +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/LICENSE +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/hatch_build.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/__init__.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/clib/__init__.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/clib/build_extract.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/clib/slit_func_2d_xi_zeta_bd.c +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/clib/slit_func_2d_xi_zeta_bd.h +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/clib/slit_func_bd.c +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/clib/slit_func_bd.h +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/clipnflip.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/datasets.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/ANDES_YJH/__init__.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/ANDES_YJH/order_centers_h.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/ANDES_YJH/order_centers_j.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/ANDES_YJH/order_centers_y.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/CRIRES_PLUS/config.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/CRIRES_PLUS/mask_det1.fits.gz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/CRIRES_PLUS/mask_det2.fits.gz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/CRIRES_PLUS/mask_det3.fits.gz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/CRIRES_PLUS/wavecal_J1228_det1.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/CRIRES_PLUS/wavecal_J1228_det2.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/CRIRES_PLUS/wavecal_J1228_det3.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/HARPN/__init__.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/HARPN/config.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/HARPN/wavecal_harpn_2D.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/HARPN/wavecal_harpn_fibB_2D.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/HARPS/__init__.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/HARPS/config.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/HARPS/mask_blue.fits.gz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/HARPS/mask_red.fits.gz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/HARPS/wavecal_blue_2D.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/HARPS/wavecal_blue_pol_2D.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/HARPS/wavecal_red_2D.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/HARPS/wavecal_red_pol_2D.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/JWST_MIRI/__init__.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/JWST_MIRI/config.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/JWST_MIRI/mask_lrs_slitless.fits.gz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/JWST_NIRISS/__init__.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/JWST_NIRISS/config.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/JWST_NIRISS/mask_gr700xd.fits.gz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/LICK_APF/__init__.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/LICK_APF/config.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/LICK_APF/mask_.fits.gz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/MCDONALD/__init__.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/MCDONALD/config.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/MCDONALD/mask.fits.gz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/MCDONALD/wavecal.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/METIS_LSS/__init__.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/METIS_LSS/config.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/METIS_LSS/wavecal_l_2D.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/METIS_LSS/wavecal_m_2D.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/MICADO/__init__.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/MICADO/config.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/MICADO/wavecal_HK_3arcsec_chip5.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/MOSAIC/__init__.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/MOSAIC/bundle_centers_nir.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/MOSAIC/bundle_centers_vis1.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/MOSAIC/bundle_centers_vis2.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/MOSAIC/bundle_centers_vis3.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/MOSAIC/bundle_centers_vis4.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/MOSAIC/mask_nir.fits.gz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/MOSAIC/mosaic_fiber_positions.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/NEID/__init__.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/NEID/config.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/NIRSPEC/__init__.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/NIRSPEC/config.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/NIRSPEC/mask_nirspec.fits.gz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/NIRSPEC/wavecal_K2.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/NTE/__init__.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/NTE/config.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/__init__.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/config.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/mask_blue.fits.gz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/mask_blue_binned_2_2.fits.gz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/mask_middle.fits.gz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/mask_middle_2x2_split.fits.gz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/mask_middle_binned_2_2.fits.gz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/mask_red.fits.gz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/mask_red_2x2.fits.gz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/mask_red_2x2_split.fits.gz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/mask_red_binned_2_2.fits.gz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/wavecal_blue_360nm_2D.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/wavecal_blue_390nm_2D.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/wavecal_blue_437nm_2D.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/wavecal_middle_2x2_2D.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/wavecal_middle_565nm_2D.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/wavecal_middle_580nm_2D.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/wavecal_middle_600nm_2D.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/wavecal_middle_665nm_2D.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/wavecal_middle_860nm_2D.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/wavecal_red_580nm_2D.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/wavecal_red_600nm_2D.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/wavecal_red_665nm_2D.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/wavecal_red_760nm_2D.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/UVES/wavecal_red_860nm_2D.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/XSHOOTER/__init__.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/XSHOOTER/config.yaml +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/XSHOOTER/mask_nir.fits.gz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/XSHOOTER/wavecal_nir.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/__init__.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/common.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/defaults/atlas/thar.fits +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/defaults/atlas/thar_list.txt +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/defaults/atlas/une.fits +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/filters.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/instruments/instrument_info.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/pyreduce/tools/__init__.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/tools/argon.line +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/tools/bpm_creator.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/tools/convert_wavecal.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/tools/download_files.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/tools/ipy_startup.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/tools/make_notebook.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/tools/neon.lin +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/tools/neon.line +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/tools/plot_1d_vs_2d_extraction.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/tools/pymultispec.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/tools/thar.npz +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/tools/wavecal_creator.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/tools/wavecal_creator_from_existing.py +0 -0
- {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a2}/tools/xshooter_nir.json +0 -0
|
@@ -1,6 +1,72 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## [0.8a2] - 2026-02-03
|
|
5
|
+
|
|
6
|
+
### Added
|
|
7
|
+
- `Trace` dataclass (trace_model.py) for unified trace data model
|
|
8
|
+
- `Spectrum`/`Spectra` classes (spectra.py) replacing legacy Echelle format
|
|
9
|
+
- `Trace.wlen(x)` method to evaluate wavelength polynomial
|
|
10
|
+
- Per-group wavelength calibration support
|
|
11
|
+
- LFC wavecal support for ANDES_RIZ
|
|
12
|
+
- docs/output_formats.md documenting new file formats
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- All pipeline steps use `list[Trace]` interface instead of array-based
|
|
16
|
+
- `extract()` takes `list[Trace]`, returns `list[Spectrum]`
|
|
17
|
+
- Renamed `nord`/`iord` to `ntrace`/`idx` for clarity
|
|
18
|
+
- Renamed `Trace.fiber` to `Trace.group`, added `fiber_idx` for per-fiber wavecal
|
|
19
|
+
- File format: traces.npz -> traces.fits (unified FITS format)
|
|
20
|
+
- Wavelength calibration stored in traces.fits instead of separate wavecal.npz
|
|
21
|
+
- Spectra use NaN masking instead of COLUMNS+MASK redundancy
|
|
22
|
+
|
|
23
|
+
### Removed
|
|
24
|
+
- `curvature_model.py` (curvature now stored in Trace)
|
|
25
|
+
- `echelle.py` functionality (deprecated, use spectra.py)
|
|
26
|
+
- Dead code from util.py
|
|
27
|
+
|
|
28
|
+
## [0.8a1] - 2026-02-03
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
- Charslit extraction backend with degree 1-5 curvature support
|
|
32
|
+
- ANDES_RIZ instrument configuration and settings
|
|
33
|
+
- `trace_by` config for separate tracing of illumination groups
|
|
34
|
+
- HDF-to-wavecal tool and reference files for ANDES_RIZ
|
|
35
|
+
- ANDES spectra plotting tool
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
- Curvature: use literal pixel extraction_height, not fractional
|
|
39
|
+
- Simplify extraction_height to single full-height value
|
|
40
|
+
- Move fiber selection default from hardcoded to config
|
|
41
|
+
- Update METIS_IFU for dynamic wavelength-based channels
|
|
42
|
+
- Use git URL for charslit optional dependency
|
|
43
|
+
|
|
44
|
+
### Removed
|
|
45
|
+
- PEP 723 inline metadata from examples (caused confusion with `uv run`)
|
|
46
|
+
|
|
47
|
+
### Fixed
|
|
48
|
+
- Fix curve_height to use new full-height format in plot_comparison
|
|
49
|
+
- Fix extraction_height to give exactly N rows
|
|
50
|
+
- Fix CRIRES_PLUS docstring (was incorrectly HARPS)
|
|
51
|
+
|
|
52
|
+
## [0.7] - 2026-01-25
|
|
53
|
+
|
|
54
|
+
First stable release of the 0.7 series!
|
|
55
|
+
|
|
56
|
+
### Changed
|
|
57
|
+
- Rename `OrderTracing` class to `Trace`, save file from `.orders.npz` to `.traces.npz`
|
|
58
|
+
- Store per-trace extraction heights in traces.npz
|
|
59
|
+
- Compute extraction heights for fiber bundles automatically
|
|
60
|
+
- CLI: consistent `-t/--target` option across all commands
|
|
61
|
+
- Allow explicit paths in settings `__inherits__` directive
|
|
62
|
+
|
|
63
|
+
### Fixed
|
|
64
|
+
- Limit trace overlay to column_range in science step plot
|
|
65
|
+
|
|
66
|
+
### Documentation
|
|
67
|
+
- Add WhatsNew.md summarizing 0.7 series improvements
|
|
68
|
+
- Update docs for traces.npz rename and mask convention
|
|
69
|
+
|
|
4
70
|
## [0.7b4] - 2026-01-22
|
|
5
71
|
|
|
6
72
|
### Added
|
|
@@ -19,7 +19,7 @@ uv run reduce download UVES
|
|
|
19
19
|
PYREDUCE_PLOT=0 uv run python examples/uves_example.py
|
|
20
20
|
|
|
21
21
|
# Or use CLI
|
|
22
|
-
uv run reduce run UVES HD132205 --steps bias,flat,trace,science
|
|
22
|
+
uv run reduce run UVES -t HD132205 --steps bias,flat,trace,science
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
## Package Structure
|
|
@@ -31,10 +31,11 @@ pyreduce/
|
|
|
31
31
|
├── reduce.py # Step class implementations
|
|
32
32
|
├── configuration.py # Config loading (settings JSON)
|
|
33
33
|
├── extract.py # Optimal extraction algorithm
|
|
34
|
+
├── trace_model.py # Trace dataclass (geometry, curvature, wavelength)
|
|
35
|
+
├── spectra.py # Spectrum/Spectra classes for I/O
|
|
34
36
|
├── trace.py # Order detection and tracing
|
|
35
37
|
├── wavelength_calibration.py # Wavelength solution fitting
|
|
36
38
|
├── combine_frames.py # Frame combination/calibration
|
|
37
|
-
├── echelle.py # Echelle spectrum I/O
|
|
38
39
|
├── util.py # Utilities, plotting helpers
|
|
39
40
|
├── cwrappers.py # CFFI C extension wrappers
|
|
40
41
|
│
|
|
@@ -68,7 +69,20 @@ This means:
|
|
|
68
69
|
- **Columns (x)** = wavelength/dispersion direction
|
|
69
70
|
- **Rows (y)** = spatial/cross-dispersion direction
|
|
70
71
|
- **Traces** are polynomial functions of x, giving y-position
|
|
71
|
-
- **`extraction_height`**
|
|
72
|
+
- **`extraction_height`** is the extraction aperture size (fraction of order separation, or pixels if >1.5)
|
|
73
|
+
|
|
74
|
+
## Spectral Order Numbers (Trace.m)
|
|
75
|
+
|
|
76
|
+
Each `Trace` has an `m` attribute representing the physical spectral (diffraction) order number - not a sequential index. Higher order numbers = shorter wavelengths.
|
|
77
|
+
|
|
78
|
+
**Assignment priority:**
|
|
79
|
+
1. `order_centers_{channel}.yaml` in instrument directory - traces matched by y-position during detection
|
|
80
|
+
2. `obase` from linelist file (`wavecal_*.npz`) - assigned as `m = obase + trace_index` during wavecal
|
|
81
|
+
3. Sequential fallback (legacy/MOSAIC mode)
|
|
82
|
+
|
|
83
|
+
**Why it matters:** The 2D wavelength polynomial fits `wavelength = P(x, m)`. Using physical order numbers enables accurate interpolation between orders. `Trace.wlen(x)` evaluates this polynomial at the trace's order number.
|
|
84
|
+
|
|
85
|
+
See `docs/wavecal_linelist.md` for details on wavelength calibration and order numbering.
|
|
72
86
|
|
|
73
87
|
## Pipeline Steps
|
|
74
88
|
|
|
@@ -79,8 +93,8 @@ The reduction pipeline consists of these steps (in typical order):
|
|
|
79
93
|
| `mask` | `Mask` | Load bad pixel mask for detector |
|
|
80
94
|
| `bias` | `Bias` | Combine bias frames into master bias |
|
|
81
95
|
| `flat` | `Flat` | Combine flat frames, subtract bias |
|
|
82
|
-
| `trace` | `
|
|
83
|
-
| `curvature` | `SlitCurvatureDetermination` | Measure slit curvature
|
|
96
|
+
| `trace` | `Trace` | Trace echelle order positions on flat |
|
|
97
|
+
| `curvature` | `SlitCurvatureDetermination` | Measure slit curvature (polynomial degree 1-5) |
|
|
84
98
|
| `scatter` | `BackgroundScatter` | Model inter-order scattered light |
|
|
85
99
|
| `norm_flat` | `NormalizeFlatField` | Normalize flat, extract blaze function |
|
|
86
100
|
| `wavecal_master` | `WavelengthCalibrationMaster` | Extract wavelength calibration spectrum |
|
|
@@ -237,12 +251,12 @@ pyreduce.reduce.main(
|
|
|
237
251
|
|
|
238
252
|
```bash
|
|
239
253
|
# Full pipeline
|
|
240
|
-
uv run reduce run UVES HD132205 --steps bias,flat,trace
|
|
254
|
+
uv run reduce run UVES -t HD132205 --steps bias,flat,trace
|
|
241
255
|
|
|
242
256
|
# Individual steps (top-level commands)
|
|
243
|
-
uv run reduce bias UVES HD132205
|
|
244
|
-
uv run reduce trace UVES HD132205
|
|
245
|
-
uv run reduce wavecal UVES HD132205
|
|
257
|
+
uv run reduce bias UVES -t HD132205
|
|
258
|
+
uv run reduce trace UVES -t HD132205
|
|
259
|
+
uv run reduce wavecal UVES -t HD132205
|
|
246
260
|
|
|
247
261
|
# Combine reduced spectra
|
|
248
262
|
uv run reduce combine --output combined.fits *.final.fits
|
|
@@ -261,15 +275,21 @@ uv run reduce list-steps
|
|
|
261
275
|
- `PYREDUCE_PLOT_DIR` - Save plots to directory as PNG files
|
|
262
276
|
- `PYREDUCE_PLOT_SHOW` - Display mode: `block` (default), `defer`, or `off`
|
|
263
277
|
- `PYREDUCE_PLOT_ANIMATION_SPEED` - Frame delay in seconds for extraction animation (default: 0.3)
|
|
278
|
+
- `PYREDUCE_USE_CHARSLIT` - Use charslit extraction backend instead of CFFI (default: 0)
|
|
279
|
+
- `PYREDUCE_USE_DELTAS` - Enable slitdelta correction with charslit backend (default: 1)
|
|
264
280
|
|
|
265
281
|
Plot modes: `block` shows each plot interactively; `defer` accumulates all plots and shows at end (useful with webagg backend); `off` disables display. Save and display are independent.
|
|
266
282
|
|
|
283
|
+
The charslit backend supports higher-degree curvature polynomials (up to degree 5) and per-row slitdelta corrections. It requires the optional `charslit` dependency.
|
|
284
|
+
|
|
267
285
|
## Development
|
|
268
286
|
|
|
269
287
|
### Commands
|
|
270
288
|
|
|
271
289
|
```bash
|
|
272
290
|
uv sync # Install dependencies
|
|
291
|
+
uv sync --extra charslit # Include charslit backend (from GitHub)
|
|
292
|
+
uv pip install -e ../CharSlit.git # Overlay local editable charslit for dev
|
|
273
293
|
uv run reduce-build # Compile C extensions
|
|
274
294
|
uv run reduce-clean # Remove compiled extensions
|
|
275
295
|
uv run pre-commit install # Setup hooks (once)
|
|
@@ -303,6 +323,9 @@ After a fresh clone or `rm -rf .venv`, run `uv sync && uv run reduce-build` to s
|
|
|
303
323
|
| `pyreduce/pipeline.py` | Fluent Pipeline API, `from_instrument()` |
|
|
304
324
|
| `pyreduce/reduce.py` | Step class implementations |
|
|
305
325
|
| `pyreduce/extract.py` | Optimal extraction algorithm |
|
|
326
|
+
| `pyreduce/trace_model.py` | Trace dataclass (pos, slit, wave, column_range) |
|
|
327
|
+
| `pyreduce/spectra.py` | Spectrum/Spectra classes for FITS I/O |
|
|
328
|
+
| `pyreduce/slit_curve.py` | Slit curvature fitting (degree 1-5) |
|
|
306
329
|
| `pyreduce/wavelength_calibration.py` | Wavelength solution fitting |
|
|
307
330
|
| `pyreduce/trace.py` | Order detection and tracing |
|
|
308
331
|
| `pyreduce/instruments/common.py` | Base Instrument class |
|
|
@@ -326,17 +349,15 @@ To release a new version (e.g., `0.7a6`):
|
|
|
326
349
|
|
|
327
350
|
3a. **sync** - run `uv sync` to get the new version into uv.lock
|
|
328
351
|
|
|
329
|
-
4. **
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
# dependencies = ["pyreduce-astro>=0.7a6"]
|
|
333
|
-
# ///
|
|
352
|
+
4. **Run unit tests** to catch issues before release:
|
|
353
|
+
```bash
|
|
354
|
+
uv run pytest -m unit
|
|
334
355
|
```
|
|
335
356
|
|
|
336
357
|
5. **Commit, tag, and push**:
|
|
337
358
|
```bash
|
|
338
|
-
git add -A && git commit -m "Release v0.
|
|
339
|
-
git tag v0.
|
|
359
|
+
git add -A && git commit -m "Release v0.8a1"
|
|
360
|
+
git tag v0.8a1
|
|
340
361
|
git push && git push --tags
|
|
341
362
|
```
|
|
342
363
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyreduce-astro
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8a2
|
|
4
4
|
Summary: A data reduction package for echelle spectrographs
|
|
5
5
|
Project-URL: Homepage, https://github.com/ivh/PyReduce
|
|
6
6
|
Project-URL: Documentation, https://pyreduce-astro.readthedocs.io
|
|
@@ -37,12 +37,18 @@ Requires-Dist: scikit-image>=0.22.0
|
|
|
37
37
|
Requires-Dist: scipy>=1.11.0
|
|
38
38
|
Requires-Dist: spectres>=2.2.0
|
|
39
39
|
Requires-Dist: tqdm>=4.66.0
|
|
40
|
+
Provides-Extra: charslit
|
|
41
|
+
Requires-Dist: charslit>=0.1.0; extra == 'charslit'
|
|
40
42
|
Description-Content-Type: text/markdown
|
|
41
43
|
|
|
42
44
|
[](https://github.com/ivh/PyReduce/actions/workflows/python-publish.yml)
|
|
43
45
|
[](https://pyreduce-astro.readthedocs.io/en/latest/?badge=latest)
|
|
44
46
|
[](https://www.python.org/downloads/)
|
|
45
47
|
|
|
48
|
+
# What's new?
|
|
49
|
+
|
|
50
|
+
Version 0.7 is a major overhaul with many improvements, please see [WhatsNew.md](WhatsNew.md) for the highlights. If the update breaks your existing setup, you are very welcome to file an issue, so we can assist you.
|
|
51
|
+
|
|
46
52
|
# PyReduce
|
|
47
53
|
|
|
48
54
|
A data reduction pipeline for echelle spectrographs (HARPS, UVES, XSHOOTER, CRIRES+, JWST/NIRISS, and more).
|
|
@@ -75,11 +81,11 @@ uv sync
|
|
|
75
81
|
uv run reduce download UVES
|
|
76
82
|
|
|
77
83
|
# Run reduction
|
|
78
|
-
uv run reduce run UVES HD132205 --steps bias,flat,trace,science
|
|
84
|
+
uv run reduce run UVES -t HD132205 --steps bias,flat,trace,science
|
|
79
85
|
|
|
80
86
|
# Or run individual steps
|
|
81
|
-
uv run reduce bias UVES HD132205
|
|
82
|
-
uv run reduce flat UVES HD132205
|
|
87
|
+
uv run reduce bias UVES -t HD132205
|
|
88
|
+
uv run reduce flat UVES -t HD132205
|
|
83
89
|
```
|
|
84
90
|
|
|
85
91
|
Or use the Python API:
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
[](https://pyreduce-astro.readthedocs.io/en/latest/?badge=latest)
|
|
3
3
|
[](https://www.python.org/downloads/)
|
|
4
4
|
|
|
5
|
+
# What's new?
|
|
6
|
+
|
|
7
|
+
Version 0.7 is a major overhaul with many improvements, please see [WhatsNew.md](WhatsNew.md) for the highlights. If the update breaks your existing setup, you are very welcome to file an issue, so we can assist you.
|
|
8
|
+
|
|
5
9
|
# PyReduce
|
|
6
10
|
|
|
7
11
|
A data reduction pipeline for echelle spectrographs (HARPS, UVES, XSHOOTER, CRIRES+, JWST/NIRISS, and more).
|
|
@@ -34,11 +38,11 @@ uv sync
|
|
|
34
38
|
uv run reduce download UVES
|
|
35
39
|
|
|
36
40
|
# Run reduction
|
|
37
|
-
uv run reduce run UVES HD132205 --steps bias,flat,trace,science
|
|
41
|
+
uv run reduce run UVES -t HD132205 --steps bias,flat,trace,science
|
|
38
42
|
|
|
39
43
|
# Or run individual steps
|
|
40
|
-
uv run reduce bias UVES HD132205
|
|
41
|
-
uv run reduce flat UVES HD132205
|
|
44
|
+
uv run reduce bias UVES -t HD132205
|
|
45
|
+
uv run reduce flat UVES -t HD132205
|
|
42
46
|
```
|
|
43
47
|
|
|
44
48
|
Or use the Python API:
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
## What's New in PyReduce 0.8 ?
|
|
2
|
+
|
|
3
|
+
### Unified Trace Data Model
|
|
4
|
+
|
|
5
|
+
The `Trace` dataclass now holds all trace-related data in one place: position polynomial, slit curvature, and wavelength calibration. Pipeline steps update traces in-place as they run, eliminating separate `.curve.npz` and `.wavecal.npz` files. All trace data is saved to a single `.traces.fits` file.
|
|
6
|
+
|
|
7
|
+
See [docs/redesign.md](docs/redesign.md) for details.
|
|
8
|
+
|
|
9
|
+
### New Spectra Format
|
|
10
|
+
|
|
11
|
+
Extracted spectra use a new per-trace FITS format with NaN masking, replacing the legacy Echelle class. Each spectrum row includes order number, group ID, and extraction metadata.
|
|
12
|
+
|
|
13
|
+
See [docs/output_formats.md](docs/output_formats.md) for the file format specification.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## What's New in PyReduce 0.7 ?
|
|
18
|
+
|
|
19
|
+
### Multi-Fiber Instrument Support
|
|
20
|
+
|
|
21
|
+
New `fibers` configuration in instrument YAML for IFU and multi-fiber spectrographs:
|
|
22
|
+
|
|
23
|
+
- **Named groups**: Define fiber ranges (e.g., science A/B, calibration) with merge strategies
|
|
24
|
+
- **Bundle patterns**: For repeating fiber bundles (e.g., 7 fibers per IFU target)
|
|
25
|
+
- **Per-order grouping**: For echelle instruments with fiber groups repeated across orders
|
|
26
|
+
- **Missing fiber handling**: `bundle_centers_file` assigns traces by proximity when fibers are broken
|
|
27
|
+
- Per-step trace selection (`science: [A, B]`, `wavecal: [cal]`, etc.)
|
|
28
|
+
|
|
29
|
+
See [docs/fiber_bundle_tracing.md](docs/fiber_bundle_tracing.md) for details.
|
|
30
|
+
|
|
31
|
+
### New Instruments
|
|
32
|
+
|
|
33
|
+
- **MOSAIC** (ELT) with multi-fiber bundle support, VIS quadrants (VIS1-VIS4)
|
|
34
|
+
- **ANDES_YJH** with multi-channel support
|
|
35
|
+
- **NEID** with multi-amplifier support
|
|
36
|
+
|
|
37
|
+
See [docs/instruments.md](docs/instruments.md) for the full list.
|
|
38
|
+
|
|
39
|
+
### Configuration Changes
|
|
40
|
+
|
|
41
|
+
- Instrument configs now use YAML (validated by Pydantic)
|
|
42
|
+
- Files reorganized into `instruments/{NAME}/` directories
|
|
43
|
+
- Settings cascade: defaults → instrument → runtime overrides
|
|
44
|
+
- **Per-channel settings**: `settings_{channel}.json` for channel-specific parameters
|
|
45
|
+
|
|
46
|
+
See [docs/configuration_file.md](docs/configuration_file.md) for details.
|
|
47
|
+
|
|
48
|
+
### Terminology Changes
|
|
49
|
+
|
|
50
|
+
- `mode` → `channel` (e.g., `mode="middle"` is now `channel="middle"`)
|
|
51
|
+
- `orders` step → `trace` step
|
|
52
|
+
- `OrderTracing` class → `Trace`, output `.orders.npz` → `.traces.npz`
|
|
53
|
+
- `extraction_width` → `extraction_height`
|
|
54
|
+
- Output files: `.ech` → `.fits`
|
|
55
|
+
- **Mask convention**: Now uses numpy standard (1=bad, 0=good)
|
|
56
|
+
|
|
57
|
+
### Plotting
|
|
58
|
+
|
|
59
|
+
- `PYREDUCE_PLOT_DIR` saves plots as PNG files
|
|
60
|
+
- `PYREDUCE_PLOT_SHOW=defer` accumulates plots for batch viewing
|
|
61
|
+
- Extraction animation with pause/step controls and residual panel
|
|
62
|
+
- Trace overlay on calibration plots
|
|
63
|
+
|
|
64
|
+
### New Pipeline API
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from pyreduce.pipeline import Pipeline
|
|
68
|
+
|
|
69
|
+
result = Pipeline.from_instrument(
|
|
70
|
+
instrument="UVES",
|
|
71
|
+
target="HD132205",
|
|
72
|
+
steps=("bias", "flat", "trace", "science"),
|
|
73
|
+
).run()
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The old `pyreduce.reduce.main()` still works but shows a deprecation warning. See [docs/examples.md](docs/examples.md) for more.
|
|
77
|
+
|
|
78
|
+
### New CLI
|
|
79
|
+
|
|
80
|
+
The old argparse CLI is replaced with a cleaner Click-based interface. See [docs/cli.md](docs/cli.md) for the full reference.
|
|
81
|
+
|
|
82
|
+
### Extraction Improvements
|
|
83
|
+
|
|
84
|
+
- **Preset slit function**: In some occasions it is useful to extract with a fixed slit function (e.g. from `norm_flat` step) for single-pass extraction (faster, more robust for faint sources)
|
|
85
|
+
- **Per-trace extraction heights**: Stored in traces file, computed automatically for fiber bundles
|
|
86
|
+
- Convergence based on spectrum change, outlier rejection improved.
|
|
87
|
+
|
|
88
|
+
### Installation & Build
|
|
89
|
+
|
|
90
|
+
- Now uses `uv` package manager (`uv sync`, `uv run reduce ...`), but `pip install pyreduce-astro` still works
|
|
91
|
+
- **Python 3.11+** required (3.13 recommended)
|
|
92
|
+
- Build system migrated from setuptools to Hatchling
|
|
93
|
+
|
|
94
|
+
See [docs/installation.md](docs/installation.md) for details.
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ANDES_RIZ instrument example: Step-by-step pipeline execution.
|
|
3
|
+
|
|
4
|
+
This example demonstrates running individual pipeline steps for the ANDES R-band
|
|
5
|
+
instrument with simulated PSF comparison data. Files are distinguished by:
|
|
6
|
+
- HDFMODEL header: selects channel (R0, R1, R2 = different optical models)
|
|
7
|
+
- SIMTYPE header: file type (flat_field, lfc, spectrum)
|
|
8
|
+
- FIBMODE header: even/odd fiber illumination pattern
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
PYREDUCE_PLOT=1 uv run python examples/andes_riz.py
|
|
12
|
+
|
|
13
|
+
Or import and run steps interactively:
|
|
14
|
+
from examples.andes_riz import pipe, flat_files, lfc_files
|
|
15
|
+
pipe.trace(flat_files)
|
|
16
|
+
pipe.run()
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import os
|
|
20
|
+
from os.path import join
|
|
21
|
+
|
|
22
|
+
from astropy.io import fits
|
|
23
|
+
|
|
24
|
+
from pyreduce import util
|
|
25
|
+
from pyreduce.combine_frames import combine_calibrate
|
|
26
|
+
from pyreduce.configuration import load_config
|
|
27
|
+
from pyreduce.instruments import instrument_info
|
|
28
|
+
from pyreduce.pipeline import Pipeline
|
|
29
|
+
|
|
30
|
+
# --- Configuration ---
|
|
31
|
+
instrument_name = "ANDES_RIZ"
|
|
32
|
+
target = "psf_comp"
|
|
33
|
+
night = ""
|
|
34
|
+
channel = "R0" # R0, R1, or R2 (different optical models)
|
|
35
|
+
|
|
36
|
+
# Plot settings
|
|
37
|
+
plot = int(os.environ.get("PYREDUCE_PLOT", "1"))
|
|
38
|
+
plot_dir = os.environ.get("PYREDUCE_PLOT_DIR")
|
|
39
|
+
if plot_dir:
|
|
40
|
+
util.set_plot_dir(plot_dir)
|
|
41
|
+
|
|
42
|
+
# Data location
|
|
43
|
+
data_dir = os.environ.get("REDUCE_DATA", os.path.expanduser("~/REDUCE_DATA"))
|
|
44
|
+
raw_dir = join(data_dir, "ANDES", "psf_comp_R")
|
|
45
|
+
output_dir = join(data_dir, "ANDES", "reduced", f"psf_comp_{channel}")
|
|
46
|
+
|
|
47
|
+
# --- Discover files ---
|
|
48
|
+
print(f"Discovering files in {raw_dir}...")
|
|
49
|
+
sorted_files = instrument_info.sort_files(
|
|
50
|
+
input_dir=raw_dir,
|
|
51
|
+
target=target,
|
|
52
|
+
night=night,
|
|
53
|
+
instrument=instrument_name,
|
|
54
|
+
channel=channel,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
if not sorted_files:
|
|
58
|
+
raise RuntimeError(f"No files found for channel {channel}")
|
|
59
|
+
|
|
60
|
+
# Extract file lists from sorted results
|
|
61
|
+
setting, files = sorted_files[0]
|
|
62
|
+
flat_files = list(files.get("flat", []))
|
|
63
|
+
trace_files = list(files.get("trace", []))
|
|
64
|
+
wavecal_files = list(files.get("wavecal_master", []))
|
|
65
|
+
|
|
66
|
+
print(f"Channel: {channel} ({setting['channel']})")
|
|
67
|
+
print(f"Flat files: {[os.path.basename(f) for f in flat_files]}")
|
|
68
|
+
print(f"Trace files: {[os.path.basename(f) for f in trace_files]}")
|
|
69
|
+
print(f"Wavecal files: {[os.path.basename(f) for f in wavecal_files]}")
|
|
70
|
+
|
|
71
|
+
# --- Create Pipeline ---
|
|
72
|
+
config = load_config(None, instrument_name, channel=channel)
|
|
73
|
+
pipe = Pipeline(
|
|
74
|
+
instrument=instrument_name,
|
|
75
|
+
output_dir=output_dir,
|
|
76
|
+
target=target,
|
|
77
|
+
channel=channel,
|
|
78
|
+
night=night,
|
|
79
|
+
config=config,
|
|
80
|
+
plot=plot,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
print(f"\nInstrument: {pipe.instrument.name}")
|
|
84
|
+
print(f"Output: {output_dir}")
|
|
85
|
+
|
|
86
|
+
# Show fiber config if present
|
|
87
|
+
if pipe.instrument.config.fibers:
|
|
88
|
+
fc = pipe.instrument.config.fibers
|
|
89
|
+
print(f"Fibers per order: {fc.fibers_per_order}")
|
|
90
|
+
print(f"Groups: {list(fc.groups.keys())}")
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def combine_lfc_with_flats(lfc_files, flat_files, output_path):
|
|
94
|
+
"""Combine LFC files with flat-field frames to add continuum."""
|
|
95
|
+
import numpy as np
|
|
96
|
+
|
|
97
|
+
print(f"Combining {len(lfc_files)} LFC + {len(flat_files)} flat files...")
|
|
98
|
+
|
|
99
|
+
# Combine LFC files
|
|
100
|
+
lfc_combined, head = combine_calibrate(
|
|
101
|
+
lfc_files,
|
|
102
|
+
pipe.instrument,
|
|
103
|
+
channel,
|
|
104
|
+
mask=None,
|
|
105
|
+
)
|
|
106
|
+
lfc_data = np.asarray(
|
|
107
|
+
lfc_combined.filled(0) if hasattr(lfc_combined, "filled") else lfc_combined
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
if flat_files:
|
|
111
|
+
# Combine flat files
|
|
112
|
+
flat_combined, _ = combine_calibrate(
|
|
113
|
+
flat_files,
|
|
114
|
+
pipe.instrument,
|
|
115
|
+
channel,
|
|
116
|
+
mask=None,
|
|
117
|
+
)
|
|
118
|
+
flat_data = np.asarray(
|
|
119
|
+
flat_combined.filled(0)
|
|
120
|
+
if hasattr(flat_combined, "filled")
|
|
121
|
+
else flat_combined
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
# Add flat continuum to LFC (scale flat to ~10% of LFC peak to not overwhelm lines)
|
|
125
|
+
lfc_peak = (
|
|
126
|
+
np.percentile(lfc_data[lfc_data > 0], 95) if np.any(lfc_data > 0) else 1
|
|
127
|
+
)
|
|
128
|
+
flat_peak = (
|
|
129
|
+
np.percentile(flat_data[flat_data > 0], 95) if np.any(flat_data > 0) else 1
|
|
130
|
+
)
|
|
131
|
+
scale = 0.1 * lfc_peak / flat_peak
|
|
132
|
+
combined = lfc_data + flat_data * scale
|
|
133
|
+
print(
|
|
134
|
+
f" LFC peak: {lfc_peak:.0f}, flat peak: {flat_peak:.0f}, scale: {scale:.4f}"
|
|
135
|
+
)
|
|
136
|
+
else:
|
|
137
|
+
combined = lfc_data
|
|
138
|
+
print(" No flats available, using LFC only")
|
|
139
|
+
|
|
140
|
+
fits.writeto(output_path, combined.astype(np.float32), head, overwrite=True)
|
|
141
|
+
print(f"Saved combined LFC+flat: {output_path}")
|
|
142
|
+
return output_path
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
if __name__ == "__main__":
|
|
146
|
+
# Combine LFC + flat files before extraction
|
|
147
|
+
lfc_combined_path = join(output_dir, "lfc_combined.fits")
|
|
148
|
+
if wavecal_files and flat_files:
|
|
149
|
+
combine_lfc_with_flats(wavecal_files, flat_files, lfc_combined_path)
|
|
150
|
+
elif wavecal_files:
|
|
151
|
+
# Fallback to LFC only if no flats
|
|
152
|
+
combine_lfc_with_flats(wavecal_files, [], lfc_combined_path)
|
|
153
|
+
|
|
154
|
+
print("\n=== Running pipeline ===")
|
|
155
|
+
# pipe.trace(trace_files)
|
|
156
|
+
# pipe.curvature(wavecal_files)
|
|
157
|
+
# Full wavecal: master -> init (MCMC line matching) -> finalize
|
|
158
|
+
pipe.wavelength_calibration([lfc_combined_path])
|
|
159
|
+
pipe.extract([lfc_combined_path])
|
|
160
|
+
|
|
161
|
+
results = pipe.run()
|
|
162
|
+
|
|
163
|
+
if "trace" in results:
|
|
164
|
+
traces = results["trace"] # list[Trace]
|
|
165
|
+
print(f"Traces found: {len(traces)}")
|
|
166
|
+
for t in traces[:3]:
|
|
167
|
+
print(f" m={t.m}, group={t.group}, columns={t.column_range}")
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
# /// script
|
|
2
|
-
# requires-python = ">=3.13"
|
|
3
|
-
# dependencies = ["pyreduce-astro>=0.7b4"]
|
|
4
|
-
# ///
|
|
5
1
|
"""
|
|
6
2
|
ANDES_YJH instrument example: Multi-fiber tracing with Pipeline API.
|
|
7
3
|
|
|
8
4
|
Demonstrates tracing fibers illuminated in separate flat field images
|
|
9
|
-
(even/odd pattern)
|
|
5
|
+
(even/odd pattern). The Pipeline trace() step handles merging traces
|
|
6
|
+
from multiple files.
|
|
10
7
|
|
|
11
8
|
The fiber config in ANDES_YJH/config.yaml handles:
|
|
12
9
|
- order_centers_file: assigns traces to spectral orders by y-position (channel-specific)
|
|
@@ -62,33 +59,25 @@ LOAD_TRACE = True # Set True to load traces from previous run
|
|
|
62
59
|
|
|
63
60
|
if LOAD_TRACE:
|
|
64
61
|
print("\nLoading traces from previous run...")
|
|
65
|
-
|
|
66
|
-
print(f" Loaded {len(
|
|
67
|
-
|
|
68
|
-
# Re-run organize with current config (picks up any config changes)
|
|
69
|
-
print("\nRe-organizing traces with current config...")
|
|
70
|
-
pipe.organize(traces, column_range)
|
|
62
|
+
trace_objects = pipe._run_step("trace", None, load_only=True) # list[Trace]
|
|
63
|
+
print(f" Loaded {len(trace_objects)} traces")
|
|
71
64
|
else:
|
|
72
|
-
# Trace
|
|
73
|
-
print(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
print(f" Found {len(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
print("Fiber groups:")
|
|
89
|
-
for name, traces_dict in group_traces.items():
|
|
90
|
-
n_traces = len(traces_dict)
|
|
91
|
-
print(f" {name}: {n_traces} traces")
|
|
65
|
+
# Trace both files together - the pipeline will organize by fiber config
|
|
66
|
+
print(
|
|
67
|
+
f"\nTracing fibers from {os.path.basename(file_even)} and {os.path.basename(file_odd)}..."
|
|
68
|
+
)
|
|
69
|
+
pipe.trace([file_even, file_odd])
|
|
70
|
+
results = pipe.run()
|
|
71
|
+
trace_objects = results["trace"] # list[Trace]
|
|
72
|
+
print(f" Found {len(trace_objects)} traces")
|
|
73
|
+
|
|
74
|
+
# Show trace info
|
|
75
|
+
print("\nTraces:")
|
|
76
|
+
fibers = {t.fiber for t in trace_objects}
|
|
77
|
+
print(f" Fibers: {sorted(fibers)}")
|
|
78
|
+
for fiber in sorted(fibers)[:3]:
|
|
79
|
+
count = sum(1 for t in trace_objects if t.fiber == fiber)
|
|
80
|
+
print(f" {fiber}: {count} traces")
|
|
92
81
|
|
|
93
82
|
# --- Create combined flat for extraction ---
|
|
94
83
|
print("\nCombining even/odd flats...")
|
|
@@ -108,6 +97,5 @@ print(f" Saved combined flat: {combined_file}")
|
|
|
108
97
|
|
|
109
98
|
# --- Extract using the science step ---
|
|
110
99
|
print("\nExtracting spectra (group A from fiber config)...")
|
|
111
|
-
pipe.instrument.config.fibers.use["science"] = ["
|
|
112
|
-
pipe.config["science"]["extraction_height"] = 60
|
|
100
|
+
pipe.instrument.config.fibers.use["science"] = ["ring2"]
|
|
113
101
|
pipe.extract([combined_file]).run()
|