pyreduce-astro 0.7b2__tar.gz → 0.7b4__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.7b2 → pyreduce_astro-0.7b4}/.gitignore +2 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/CHANGELOG.md +43 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/CLAUDE.md +10 -6
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/PKG-INFO +15 -1
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/README.md +14 -0
- pyreduce_astro-0.7b4/examples/andes_yjh_example.py +113 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/examples/crires_plus_example.py +2 -2
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/examples/custom_instrument_example.py +2 -2
- pyreduce_astro-0.7b4/examples/debug_single_swath.py +233 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/examples/harpn_example.py +2 -2
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/examples/harps_example.py +1 -1
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/examples/harps_gridsearch.py +2 -2
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/examples/just_one_swath.py +15 -3
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/examples/jwst_miri_example.py +2 -2
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/examples/jwst_niriss_example.py +2 -2
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/examples/lick_apf_example.py +2 -2
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/examples/mcdonald_example.py +2 -2
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/examples/metis_ifu_example.py +2 -2
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/examples/metis_lss_example.py +2 -2
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/examples/micado_example.py +10 -12
- pyreduce_astro-0.7b4/examples/mosaic_nir.py +96 -0
- pyreduce_astro-0.7b4/examples/mosaic_preset-slitfunc.py +141 -0
- pyreduce_astro-0.7b4/examples/mosaic_vis.py +92 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/examples/neid_example.py +1 -1
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/examples/nirspec_example.py +2 -2
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/examples/toes_example.py +2 -2
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/examples/uves_callfunc.py +20 -11
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/examples/uves_example.py +2 -2
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/examples/xshooter_example.py +6 -7
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyproject.toml +7 -1
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/__main__.py +29 -11
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/cli.py +2 -2
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/clib/slit_func_2d_xi_zeta_bd.c +152 -118
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/clib/slit_func_2d_xi_zeta_bd.h +2 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/clib/slit_func_bd.c +2 -5
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/combine_frames.py +39 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/configuration.py +18 -4
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/continuum_normalization.py +2 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/cwrappers.py +254 -23
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/estimate_background_scatter.py +24 -23
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/extract.py +353 -207
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/extraction_height.py +14 -14
- pyreduce_astro-0.7b4/pyreduce/instruments/ANDES_YJH/__init__.py +14 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/ANDES_YJH/config.yaml +113 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/ANDES_YJH/order_centers_h.yaml +9 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/ANDES_YJH/order_centers_j.yaml +21 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/ANDES_YJH/order_centers_y.yaml +9 -0
- {pyreduce_astro-0.7b2/pyreduce/instruments/AJ → pyreduce_astro-0.7b4/pyreduce/instruments/ANDES_YJH}/settings.json +4 -3
- pyreduce_astro-0.7b4/pyreduce/instruments/CRIRES_PLUS/mask_det1.fits.gz +0 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/CRIRES_PLUS/mask_det2.fits.gz +0 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/CRIRES_PLUS/mask_det3.fits.gz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/CRIRES_PLUS/settings.json +0 -2
- pyreduce_astro-0.7b4/pyreduce/instruments/HARPN/wavecal_harpn_fibB_2D.npz +0 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/HARPS/mask_blue.fits.gz +0 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/HARPS/mask_red.fits.gz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/HARPS/settings.json +1 -2
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/JWST_MIRI/mask_lrs_slitless.fits.gz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/JWST_NIRISS/__init__.py +2 -2
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/JWST_NIRISS/mask_gr700xd.fits.gz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/LICK_APF/mask_.fits.gz +0 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/MCDONALD/mask.fits.gz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/METIS_IFU/settings.json +1 -4
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/MICADO/settings.json +1 -4
- pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/__init__.py +38 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/bundle_centers_nir.yaml +92 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/bundle_centers_vis1.yaml +69 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/bundle_centers_vis2.yaml +72 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/bundle_centers_vis3.yaml +87 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/bundle_centers_vis4.yaml +87 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/config.yaml +61 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/mask_nir.fits.gz +0 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/mosaic_fiber_positions.npz +0 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/settings.json +25 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/settings_VIS1.json +22 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/settings_VIS2.json +22 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/settings_VIS3.json +22 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/settings_VIS4.json +22 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/settings_nir.json +22 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/NEID/settings.json +0 -1
- pyreduce_astro-0.7b4/pyreduce/instruments/NIRSPEC/mask_nirspec.fits.gz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/NTE/settings.json +0 -2
- pyreduce_astro-0.7b4/pyreduce/instruments/UVES/mask_blue.fits.gz +0 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/UVES/mask_blue_binned_2_2.fits.gz +0 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/UVES/mask_middle.fits.gz +0 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/UVES/mask_middle_2x2_split.fits.gz +0 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/UVES/mask_middle_binned_2_2.fits.gz +0 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/UVES/mask_red.fits.gz +0 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/UVES/mask_red_2x2.fits.gz +0 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/UVES/mask_red_2x2_split.fits.gz +0 -0
- pyreduce_astro-0.7b4/pyreduce/instruments/UVES/mask_red_binned_2_2.fits.gz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/UVES/settings.json +2 -2
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/XSHOOTER/mask_nir.fits.gz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/XSHOOTER/settings.json +7 -9
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/common.py +44 -19
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/defaults/schema.json +50 -142
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/defaults/settings.json +12 -14
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/models.py +99 -2
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/pipeline.py +213 -20
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/rectify.py +12 -12
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/reduce.py +431 -155
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/slit_curve.py +32 -100
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/tools/combine.py +1 -0
- pyreduce_astro-0.7b4/pyreduce/trace.py +1709 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/util.py +43 -5
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/wavelength_calibration.py +2 -0
- pyreduce_astro-0.7b4/tools/make_notebook.py +47 -0
- pyreduce_astro-0.7b4/tools/mosaic_vis_bundle_plot.py +66 -0
- pyreduce_astro-0.7b4/tools/plot_1d_vs_2d_extraction.py +162 -0
- pyreduce_astro-0.7b4/tools/plot_swath_debug.py +64 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/uv.lock +413 -38
- pyreduce_astro-0.7b2/examples/aj_example.py +0 -209
- pyreduce_astro-0.7b2/pyreduce/instruments/AJ/__init__.py +0 -9
- pyreduce_astro-0.7b2/pyreduce/instruments/AJ/config.yaml +0 -51
- pyreduce_astro-0.7b2/pyreduce/instruments/ANDES/__init__.py +0 -100
- pyreduce_astro-0.7b2/pyreduce/instruments/ANDES/config.yaml +0 -72
- pyreduce_astro-0.7b2/pyreduce/instruments/ANDES/settings.json +0 -16
- pyreduce_astro-0.7b2/pyreduce/instruments/CRIRES_PLUS/mask_det1.fits.gz +0 -0
- pyreduce_astro-0.7b2/pyreduce/instruments/CRIRES_PLUS/mask_det2.fits.gz +0 -0
- pyreduce_astro-0.7b2/pyreduce/instruments/CRIRES_PLUS/mask_det3.fits.gz +0 -0
- pyreduce_astro-0.7b2/pyreduce/instruments/HARPS/mask_blue.fits.gz +0 -0
- pyreduce_astro-0.7b2/pyreduce/instruments/HARPS/mask_red.fits.gz +0 -0
- pyreduce_astro-0.7b2/pyreduce/instruments/MCDONALD/mask.fits.gz +0 -0
- pyreduce_astro-0.7b2/pyreduce/instruments/NIRSPEC/mask_nirspec.fits.gz +0 -0
- pyreduce_astro-0.7b2/pyreduce/instruments/UVES/mask_blue.fits.gz +0 -0
- pyreduce_astro-0.7b2/pyreduce/instruments/UVES/mask_blue_binned_2_2.fits.gz +0 -0
- pyreduce_astro-0.7b2/pyreduce/instruments/UVES/mask_middle.fits.gz +0 -0
- pyreduce_astro-0.7b2/pyreduce/instruments/UVES/mask_middle_2x2_split.fits.gz +0 -0
- pyreduce_astro-0.7b2/pyreduce/instruments/UVES/mask_middle_binned_2_2.fits.gz +0 -0
- pyreduce_astro-0.7b2/pyreduce/instruments/UVES/mask_red.fits.gz +0 -0
- pyreduce_astro-0.7b2/pyreduce/instruments/UVES/mask_red_2x2.fits.gz +0 -0
- pyreduce_astro-0.7b2/pyreduce/instruments/UVES/mask_red_2x2_split.fits.gz +0 -0
- pyreduce_astro-0.7b2/pyreduce/instruments/UVES/mask_red_binned_2_2.fits.gz +0 -0
- pyreduce_astro-0.7b2/pyreduce/trace.py +0 -979
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/.gitattributes +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/.pre-commit-config.yaml +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/.python-version +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/.readthedocs.yaml +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/AGENTS.md +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/ANDES_plan.md +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/LICENSE +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/hatch_build.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/__init__.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/clib/__init__.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/clib/build_extract.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/clib/slit_func_bd.h +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/clipnflip.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/datasets.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/echelle.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/CRIRES_PLUS/__init__.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/CRIRES_PLUS/config.yaml +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/CRIRES_PLUS/wavecal_J1228_det1.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/CRIRES_PLUS/wavecal_J1228_det2.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/CRIRES_PLUS/wavecal_J1228_det3.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/HARPN/__init__.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/HARPN/config.yaml +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/HARPN/settings.json +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/HARPN/wavecal_harpn_2D.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/HARPS/__init__.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/HARPS/config.yaml +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/HARPS/wavecal_blue_2D.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/HARPS/wavecal_blue_pol_2D.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/HARPS/wavecal_red_2D.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/HARPS/wavecal_red_pol_2D.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/JWST_MIRI/__init__.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/JWST_MIRI/config.yaml +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/JWST_MIRI/settings.json +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/JWST_NIRISS/config.yaml +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/JWST_NIRISS/settings.json +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/LICK_APF/__init__.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/LICK_APF/config.yaml +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/LICK_APF/settings.json +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/MCDONALD/__init__.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/MCDONALD/config.yaml +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/MCDONALD/settings.json +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/MCDONALD/wavecal.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/METIS_IFU/__init__.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/METIS_IFU/config.yaml +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/METIS_LSS/__init__.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/METIS_LSS/config.yaml +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/METIS_LSS/settings.json +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/METIS_LSS/wavecal_l_2D.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/METIS_LSS/wavecal_m_2D.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/MICADO/__init__.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/MICADO/config.yaml +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/MICADO/wavecal_HK_3arcsec_chip5.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/NEID/__init__.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/NEID/config.yaml +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/NIRSPEC/__init__.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/NIRSPEC/config.yaml +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/NIRSPEC/settings.json +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/NIRSPEC/wavecal_K2.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/NTE/__init__.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/NTE/config.yaml +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/UVES/__init__.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/UVES/config.yaml +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/UVES/wavecal_blue_360nm_2D.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/UVES/wavecal_blue_390nm_2D.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/UVES/wavecal_blue_437nm_2D.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/UVES/wavecal_middle_2x2_2D.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/UVES/wavecal_middle_565nm_2D.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/UVES/wavecal_middle_580nm_2D.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/UVES/wavecal_middle_600nm_2D.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/UVES/wavecal_middle_665nm_2D.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/UVES/wavecal_middle_860nm_2D.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/UVES/wavecal_red_580nm_2D.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/UVES/wavecal_red_600nm_2D.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/UVES/wavecal_red_665nm_2D.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/UVES/wavecal_red_760nm_2D.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/UVES/wavecal_red_860nm_2D.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/XSHOOTER/__init__.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/XSHOOTER/config.yaml +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/XSHOOTER/wavecal_nir.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/__init__.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/defaults/atlas/thar.fits +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/defaults/atlas/thar_list.txt +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/defaults/atlas/une.fits +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/defaults/config.yaml +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/filters.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/instruments/instrument_info.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/pyreduce/tools/__init__.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/tools/argon.line +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/tools/bpm_creator.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/tools/convert_wavecal.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/tools/create_wavelength_guess.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/tools/download_files.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/tools/ipy_startup.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/tools/neon.lin +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/tools/neon.line +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/tools/pymultispec.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/tools/thar.npz +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/tools/wavecal_creator.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/tools/wavecal_creator_from_existing.py +0 -0
- {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b4}/tools/xshooter_nir.json +0 -0
|
@@ -1,6 +1,49 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## [0.7b4] - 2026-01-22
|
|
5
|
+
|
|
6
|
+
### Added
|
|
7
|
+
- Per-channel settings support via `settings_{channel}.json` files
|
|
8
|
+
- Fiber grouping configuration for multi-fiber instruments (bundle_centers, fiber_groups)
|
|
9
|
+
- `preset_slitfunc` parameter for single-pass extraction using pre-computed slit function
|
|
10
|
+
- `noise_relative` parameter for trace threshold scaling
|
|
11
|
+
- `extraction_reject` threshold parameter for outlier rejection
|
|
12
|
+
- ANDES_YJH instrument with multi-channel support
|
|
13
|
+
- MOSAIC VIS quadrant support (VIS1-VIS4 channels) and NIR settings
|
|
14
|
+
- HARPN fiber B wavecal file
|
|
15
|
+
- Extraction residual panel in ProgressPlot
|
|
16
|
+
- `tools/plot_swath_debug.py` for analyzing extraction debug data
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
- **Mask convention**: Switch to numpy convention (True/1=bad) on Python side; C code uses inverted (1=good)
|
|
20
|
+
- Extraction convergence now based on spectrum change with global RMS for rejection
|
|
21
|
+
- Improved outlier rejection using 6*sigma instead of MAD in 2D extraction
|
|
22
|
+
- Norm_flat step saves slit function with metadata for reuse
|
|
23
|
+
- Refactor Pipeline trace API: add `trace_raw()` and `organize()` methods
|
|
24
|
+
- Remove `extraction_cutoff` parameter (dead code)
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
- `smooth_spectrum` normalization (port from cr2res)
|
|
28
|
+
- Masked array handling in swath debug plotting
|
|
29
|
+
- Minimum 4 iterations enforced in curved extraction
|
|
30
|
+
|
|
31
|
+
## [0.7b3] - 2026-01-11
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
- MOSAIC instrument support with fiber group detection and curvature step
|
|
35
|
+
- Extraction animation controls: pause/step buttons and speed control (`PYREDUCE_PLOT_ANIMATION_SPEED`)
|
|
36
|
+
- `--plot-dir` and `--plot-show` CLI options for flexible plot output
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
- Rename `orders` to `traces` in rectify and slit_curve modules for consistency
|
|
40
|
+
- Downgrade extraction max-iterations message from ERROR to WARNING
|
|
41
|
+
- Only warn about missing files for steps that are actually requested
|
|
42
|
+
|
|
43
|
+
### Fixed
|
|
44
|
+
- Handle channel mismatch gracefully in CLI
|
|
45
|
+
- Curvature plotting index error when peaks need int casting
|
|
46
|
+
|
|
4
47
|
## [0.7b2] - 2026-01-09
|
|
5
48
|
|
|
6
49
|
### Changed
|
|
@@ -31,7 +31,7 @@ pyreduce/
|
|
|
31
31
|
├── reduce.py # Step class implementations
|
|
32
32
|
├── configuration.py # Config loading (settings JSON)
|
|
33
33
|
├── extract.py # Optimal extraction algorithm
|
|
34
|
-
├──
|
|
34
|
+
├── trace.py # Order detection and tracing
|
|
35
35
|
├── wavelength_calibration.py # Wavelength solution fitting
|
|
36
36
|
├── combine_frames.py # Frame combination/calibration
|
|
37
37
|
├── echelle.py # Echelle spectrum I/O
|
|
@@ -158,7 +158,7 @@ Defines HOW to reduce - algorithm parameters per step:
|
|
|
158
158
|
"degree": 4,
|
|
159
159
|
"noise": 100,
|
|
160
160
|
"min_cluster": 500,
|
|
161
|
-
"
|
|
161
|
+
"filter_y": 120
|
|
162
162
|
},
|
|
163
163
|
"norm_flat": {
|
|
164
164
|
"extraction_height": 0.5,
|
|
@@ -217,7 +217,7 @@ pipe = Pipeline(
|
|
|
217
217
|
)
|
|
218
218
|
pipe.bias(bias_files)
|
|
219
219
|
pipe.flat(flat_files)
|
|
220
|
-
pipe.
|
|
220
|
+
pipe.trace()
|
|
221
221
|
pipe.extract(science_files)
|
|
222
222
|
result = pipe.run()
|
|
223
223
|
```
|
|
@@ -257,8 +257,12 @@ uv run reduce list-steps
|
|
|
257
257
|
## Environment Variables
|
|
258
258
|
|
|
259
259
|
- `REDUCE_DATA` - Base data directory (default: `~/REDUCE_DATA`)
|
|
260
|
-
- `PYREDUCE_PLOT` - Override plot level (0, 1, 2)
|
|
261
|
-
- `PYREDUCE_PLOT_DIR` - Save plots to directory
|
|
260
|
+
- `PYREDUCE_PLOT` - Override plot level (0=off, 1=basic, 2=detailed)
|
|
261
|
+
- `PYREDUCE_PLOT_DIR` - Save plots to directory as PNG files
|
|
262
|
+
- `PYREDUCE_PLOT_SHOW` - Display mode: `block` (default), `defer`, or `off`
|
|
263
|
+
- `PYREDUCE_PLOT_ANIMATION_SPEED` - Frame delay in seconds for extraction animation (default: 0.3)
|
|
264
|
+
|
|
265
|
+
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.
|
|
262
266
|
|
|
263
267
|
## Development
|
|
264
268
|
|
|
@@ -300,7 +304,7 @@ After a fresh clone or `rm -rf .venv`, run `uv sync && uv run reduce-build` to s
|
|
|
300
304
|
| `pyreduce/reduce.py` | Step class implementations |
|
|
301
305
|
| `pyreduce/extract.py` | Optimal extraction algorithm |
|
|
302
306
|
| `pyreduce/wavelength_calibration.py` | Wavelength solution fitting |
|
|
303
|
-
| `pyreduce/
|
|
307
|
+
| `pyreduce/trace.py` | Order detection and tracing |
|
|
304
308
|
| `pyreduce/instruments/common.py` | Base Instrument class |
|
|
305
309
|
| `pyreduce/instruments/models.py` | Pydantic config models |
|
|
306
310
|
| `pyreduce/clib/*.c` | C code for slit function decomposition |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyreduce-astro
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7b4
|
|
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
|
|
@@ -94,6 +94,20 @@ Pipeline.from_instrument(
|
|
|
94
94
|
).run()
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
+
## Plotting
|
|
98
|
+
|
|
99
|
+
Control plotting with environment variables:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Save plots to files (headless/CI)
|
|
103
|
+
PYREDUCE_PLOT=1 PYREDUCE_PLOT_DIR=/tmp/plots PYREDUCE_PLOT_SHOW=off uv run reduce run ...
|
|
104
|
+
|
|
105
|
+
# Show all plots at end (browser via webagg)
|
|
106
|
+
MPLBACKEND=webagg PYREDUCE_PLOT=1 PYREDUCE_PLOT_SHOW=defer uv run reduce run ...
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
See [How To](https://pyreduce-astro.readthedocs.io/en/latest/howto.html#plot-modes) for details.
|
|
110
|
+
|
|
97
111
|
## Documentation
|
|
98
112
|
|
|
99
113
|
Full documentation at [ReadTheDocs](https://pyreduce-astro.readthedocs.io/).
|
|
@@ -53,6 +53,20 @@ Pipeline.from_instrument(
|
|
|
53
53
|
).run()
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
+
## Plotting
|
|
57
|
+
|
|
58
|
+
Control plotting with environment variables:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# Save plots to files (headless/CI)
|
|
62
|
+
PYREDUCE_PLOT=1 PYREDUCE_PLOT_DIR=/tmp/plots PYREDUCE_PLOT_SHOW=off uv run reduce run ...
|
|
63
|
+
|
|
64
|
+
# Show all plots at end (browser via webagg)
|
|
65
|
+
MPLBACKEND=webagg PYREDUCE_PLOT=1 PYREDUCE_PLOT_SHOW=defer uv run reduce run ...
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
See [How To](https://pyreduce-astro.readthedocs.io/en/latest/howto.html#plot-modes) for details.
|
|
69
|
+
|
|
56
70
|
## Documentation
|
|
57
71
|
|
|
58
72
|
Full documentation at [ReadTheDocs](https://pyreduce-astro.readthedocs.io/).
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# /// script
|
|
2
|
+
# requires-python = ">=3.13"
|
|
3
|
+
# dependencies = ["pyreduce-astro>=0.7b4"]
|
|
4
|
+
# ///
|
|
5
|
+
"""
|
|
6
|
+
ANDES_YJH instrument example: Multi-fiber tracing with Pipeline API.
|
|
7
|
+
|
|
8
|
+
Demonstrates tracing fibers illuminated in separate flat field images
|
|
9
|
+
(even/odd pattern) using the Pipeline's trace_raw() and organize() methods.
|
|
10
|
+
|
|
11
|
+
The fiber config in ANDES_YJH/config.yaml handles:
|
|
12
|
+
- order_centers_file: assigns traces to spectral orders by y-position (channel-specific)
|
|
13
|
+
- groups: organizes fibers into logical groups (A, cal, B) within each order
|
|
14
|
+
- merge: average - averages fiber traces within each group
|
|
15
|
+
|
|
16
|
+
ANDES_YJH has three channels: Y, J, H (selected by BAND header in files).
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import os
|
|
20
|
+
|
|
21
|
+
import numpy as np
|
|
22
|
+
|
|
23
|
+
from pyreduce.configuration import load_config
|
|
24
|
+
from pyreduce.pipeline import Pipeline
|
|
25
|
+
|
|
26
|
+
# --- Configuration ---
|
|
27
|
+
instrument_name = "ANDES_YJH"
|
|
28
|
+
channel = "J" # Y, J, or H
|
|
29
|
+
data_dir = os.environ.get("REDUCE_DATA", os.path.expanduser("~/REDUCE_DATA"))
|
|
30
|
+
raw_dir = os.path.join(data_dir, "ANDES", channel)
|
|
31
|
+
output_dir = os.path.join(data_dir, "ANDES", "reduced", channel)
|
|
32
|
+
|
|
33
|
+
# Input files (even and odd illuminated flats)
|
|
34
|
+
# File selection is header-based:
|
|
35
|
+
# BAND header determines channel (Y, J, H)
|
|
36
|
+
# SIMTYPE='flat_field' → flat, SIMTYPE='spectrum' → science
|
|
37
|
+
# FIBMODE='even' → even flat, FIBMODE='odd' → odd flat
|
|
38
|
+
file_even = os.path.join(raw_dir, f"{channel}_FF_even_1s.fits")
|
|
39
|
+
file_odd = os.path.join(raw_dir, f"{channel}_FF_odd_1s.fits")
|
|
40
|
+
|
|
41
|
+
# Plot settings
|
|
42
|
+
plot = int(os.environ.get("PYREDUCE_PLOT", "1"))
|
|
43
|
+
|
|
44
|
+
# --- Create Pipeline ---
|
|
45
|
+
config = load_config(None, instrument_name)
|
|
46
|
+
pipe = Pipeline(
|
|
47
|
+
instrument=instrument_name,
|
|
48
|
+
channel=channel,
|
|
49
|
+
output_dir=output_dir,
|
|
50
|
+
target="ANDES_fiber_test",
|
|
51
|
+
config=config,
|
|
52
|
+
plot=plot,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
print(f"Instrument: {pipe.instrument.name}")
|
|
56
|
+
fibers_config = pipe.instrument.config.fibers
|
|
57
|
+
print(f"Per-order grouping: {fibers_config.per_order}")
|
|
58
|
+
print(f"Groups: {list(fibers_config.groups.keys())}")
|
|
59
|
+
|
|
60
|
+
# --- Trace or load from previous run ---
|
|
61
|
+
LOAD_TRACE = True # Set True to load traces from previous run
|
|
62
|
+
|
|
63
|
+
if LOAD_TRACE:
|
|
64
|
+
print("\nLoading traces from previous run...")
|
|
65
|
+
traces, column_range = pipe._run_step("trace", None, load_only=True)
|
|
66
|
+
print(f" Loaded {len(traces)} traces")
|
|
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)
|
|
71
|
+
else:
|
|
72
|
+
# Trace each flat independently
|
|
73
|
+
print(f"\nTracing even fibers from {os.path.basename(file_even)}...")
|
|
74
|
+
traces_even, cr_even = pipe.trace_raw([file_even])
|
|
75
|
+
print(f" Found {len(traces_even)} traces")
|
|
76
|
+
|
|
77
|
+
print(f"\nTracing odd fibers from {os.path.basename(file_odd)}...")
|
|
78
|
+
traces_odd, cr_odd = pipe.trace_raw([file_odd])
|
|
79
|
+
print(f" Found {len(traces_odd)} traces")
|
|
80
|
+
|
|
81
|
+
# Organize into fiber groups
|
|
82
|
+
print("\nOrganizing traces into fiber groups...")
|
|
83
|
+
pipe.organize(traces_even, cr_even, traces_odd, cr_odd)
|
|
84
|
+
|
|
85
|
+
# Access organized groups
|
|
86
|
+
if "trace_groups" in pipe._data and pipe._data["trace_groups"][0]:
|
|
87
|
+
group_traces, group_cr = pipe._data["trace_groups"]
|
|
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")
|
|
92
|
+
|
|
93
|
+
# --- Create combined flat for extraction ---
|
|
94
|
+
print("\nCombining even/odd flats...")
|
|
95
|
+
img_even, head = pipe.instrument.load_fits(file_even, channel=channel, extension=0)
|
|
96
|
+
img_odd, _ = pipe.instrument.load_fits(file_odd, channel=channel, extension=0)
|
|
97
|
+
img_combined = np.asarray(img_even, dtype=np.float64) + np.asarray(
|
|
98
|
+
img_odd, dtype=np.float64
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
# Save combined flat to file for the science step
|
|
102
|
+
from astropy.io import fits
|
|
103
|
+
|
|
104
|
+
combined_file = os.path.join(output_dir, "combined_flat.fits")
|
|
105
|
+
os.makedirs(output_dir, exist_ok=True)
|
|
106
|
+
fits.writeto(combined_file, img_combined.astype(np.float32), head, overwrite=True)
|
|
107
|
+
print(f" Saved combined flat: {combined_file}")
|
|
108
|
+
|
|
109
|
+
# --- Extract using the science step ---
|
|
110
|
+
print("\nExtracting spectra (group A from fiber config)...")
|
|
111
|
+
pipe.instrument.config.fibers.use["science"] = ["ring1"]
|
|
112
|
+
pipe.config["science"]["extraction_height"] = 60
|
|
113
|
+
pipe.extract([combined_file]).run()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# /// script
|
|
2
2
|
# requires-python = ">=3.13"
|
|
3
|
-
# dependencies = ["pyreduce-astro>=0.
|
|
3
|
+
# dependencies = ["pyreduce-astro>=0.7b4"]
|
|
4
4
|
# ///
|
|
5
5
|
"""
|
|
6
6
|
Simple usage example for PyReduce
|
|
@@ -48,5 +48,5 @@ Pipeline.from_instrument(
|
|
|
48
48
|
base_dir=base_dir,
|
|
49
49
|
input_dir=input_dir,
|
|
50
50
|
output_dir=output_dir,
|
|
51
|
-
#
|
|
51
|
+
# trace_range=(0, 4),
|
|
52
52
|
).run()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# /// script
|
|
2
2
|
# requires-python = ">=3.13"
|
|
3
|
-
# dependencies = ["pyreduce-astro>=0.
|
|
3
|
+
# dependencies = ["pyreduce-astro>=0.7b4"]
|
|
4
4
|
# ///
|
|
5
5
|
"""
|
|
6
6
|
Simple usage example for PyReduce
|
|
@@ -73,7 +73,7 @@ pipe = Pipeline.from_files(
|
|
|
73
73
|
channel=channel,
|
|
74
74
|
night=night,
|
|
75
75
|
config=config,
|
|
76
|
-
#
|
|
76
|
+
# trace_range=trace_range,
|
|
77
77
|
steps=steps,
|
|
78
78
|
plot=1,
|
|
79
79
|
)
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# /// script
|
|
2
|
+
# requires-python = ">=3.13"
|
|
3
|
+
# dependencies = ["pyreduce-astro>=0.7b4"]
|
|
4
|
+
# ///
|
|
5
|
+
"""
|
|
6
|
+
Debug script for extracting a single swath from a specific trace.
|
|
7
|
+
|
|
8
|
+
Manually loads traces from NPZ, cuts out one swath, runs extraction,
|
|
9
|
+
and saves all intermediate outputs for inspection.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
from os.path import join
|
|
14
|
+
|
|
15
|
+
import numpy as np
|
|
16
|
+
from astropy.io import fits
|
|
17
|
+
|
|
18
|
+
from pyreduce.cwrappers import slitfunc_curved
|
|
19
|
+
from pyreduce.extract import fix_parameters, make_bins
|
|
20
|
+
from pyreduce.util import make_index
|
|
21
|
+
|
|
22
|
+
# === Configuration ===
|
|
23
|
+
# Which trace and swath to extract
|
|
24
|
+
TRACE_INDEX = 4 # 5th trace (0-indexed), i.e. 5th fiber bundle center
|
|
25
|
+
SWATH_INDEX = 2 # 3rd swath (0-indexed)
|
|
26
|
+
|
|
27
|
+
# Extraction parameters
|
|
28
|
+
EXTRACTION_HEIGHT = 0.5 # fraction of order spacing
|
|
29
|
+
OSAMPLE = 1
|
|
30
|
+
LAMBDA_SF = 0.1
|
|
31
|
+
LAMBDA_SP = 0
|
|
32
|
+
MAXITER = 20
|
|
33
|
+
GAIN = 1.0
|
|
34
|
+
|
|
35
|
+
# === Data paths ===
|
|
36
|
+
data_dir = os.environ.get("REDUCE_DATA", os.path.expanduser("~/REDUCE_DATA"))
|
|
37
|
+
base_dir = join(data_dir, "MOSAIC", "REF_E2E", "NIR")
|
|
38
|
+
output_dir = join(data_dir, "MOSAIC", "reduced", "NIR")
|
|
39
|
+
|
|
40
|
+
flat_file = join(
|
|
41
|
+
base_dir,
|
|
42
|
+
"E2E_FLAT_DIT_20s_MOSAIC_2Cam_c01",
|
|
43
|
+
"E2E_FLAT_DIT_20s_MOSAIC_2Cam_c01_STATIC_FOCAL_PLANE.fits",
|
|
44
|
+
)
|
|
45
|
+
trace_file = join(output_dir, "MOSAIC_NIR.ord_default.npz")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def load_traces(trace_file):
|
|
49
|
+
"""Load traces and column ranges from NPZ."""
|
|
50
|
+
import warnings
|
|
51
|
+
|
|
52
|
+
data = np.load(trace_file, allow_pickle=True)
|
|
53
|
+
if "traces" in data:
|
|
54
|
+
traces = data["traces"]
|
|
55
|
+
elif "orders" in data:
|
|
56
|
+
warnings.warn(
|
|
57
|
+
f"Trace file {trace_file} uses old key 'orders'. "
|
|
58
|
+
"Re-run the trace step to update the file format.",
|
|
59
|
+
DeprecationWarning,
|
|
60
|
+
stacklevel=2,
|
|
61
|
+
)
|
|
62
|
+
traces = data["orders"]
|
|
63
|
+
else:
|
|
64
|
+
raise KeyError("Trace file missing 'traces' key")
|
|
65
|
+
column_range = data["column_range"]
|
|
66
|
+
print(f"Loaded {len(traces)} traces from {trace_file}")
|
|
67
|
+
return traces, column_range
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def load_image(flat_file):
|
|
71
|
+
"""Load and prepare the flat field image."""
|
|
72
|
+
with fits.open(flat_file) as hdul:
|
|
73
|
+
img = hdul[0].data.astype(float)
|
|
74
|
+
print(f"Loaded image {img.shape} from {flat_file}")
|
|
75
|
+
return img
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def extract_single_swath(
|
|
79
|
+
img,
|
|
80
|
+
trace_coef,
|
|
81
|
+
column_range,
|
|
82
|
+
swath_index,
|
|
83
|
+
extraction_height,
|
|
84
|
+
p1=None,
|
|
85
|
+
p2=None,
|
|
86
|
+
):
|
|
87
|
+
"""
|
|
88
|
+
Extract a single swath from one trace.
|
|
89
|
+
|
|
90
|
+
Returns the swath image, extraction results, and metadata.
|
|
91
|
+
"""
|
|
92
|
+
nrow, ncol = img.shape
|
|
93
|
+
xlow, xhigh = column_range
|
|
94
|
+
|
|
95
|
+
# Evaluate trace polynomial
|
|
96
|
+
x = np.arange(ncol)
|
|
97
|
+
ycen = np.polyval(trace_coef, x)
|
|
98
|
+
|
|
99
|
+
# Get extraction height in pixels
|
|
100
|
+
ylow, yhigh = extraction_height
|
|
101
|
+
|
|
102
|
+
# Create swath bins
|
|
103
|
+
nbin, bins_start, bins_end = make_bins(None, xlow, xhigh, ycen)
|
|
104
|
+
nswath = 2 * nbin - 1
|
|
105
|
+
print(f"Order has {nswath} swaths, extracting swath {swath_index}")
|
|
106
|
+
|
|
107
|
+
if swath_index >= nswath:
|
|
108
|
+
raise ValueError(f"Swath index {swath_index} >= number of swaths {nswath}")
|
|
109
|
+
|
|
110
|
+
# Get this swath's column range
|
|
111
|
+
ibeg = bins_start[swath_index]
|
|
112
|
+
iend = bins_end[swath_index]
|
|
113
|
+
print(f"Swath columns: {ibeg} - {iend} (width={iend - ibeg})")
|
|
114
|
+
|
|
115
|
+
# Cut out swath from image
|
|
116
|
+
ycen_int = np.floor(ycen).astype(int)
|
|
117
|
+
index = make_index(ycen_int - ylow, ycen_int + yhigh, ibeg, iend)
|
|
118
|
+
swath_img = img[index].copy()
|
|
119
|
+
swath_ycen = ycen[ibeg:iend]
|
|
120
|
+
|
|
121
|
+
# Fractional y offset within each pixel
|
|
122
|
+
swath_ycen_frac = swath_ycen - np.floor(swath_ycen)
|
|
123
|
+
|
|
124
|
+
print(f"Swath image shape: {swath_img.shape}")
|
|
125
|
+
print(f"Swath ycen range: {swath_ycen.min():.1f} - {swath_ycen.max():.1f}")
|
|
126
|
+
|
|
127
|
+
# Get curvature for this swath
|
|
128
|
+
swath_p1 = p1[ibeg:iend] if p1 is not None else 0
|
|
129
|
+
swath_p2 = p2[ibeg:iend] if p2 is not None else 0
|
|
130
|
+
|
|
131
|
+
# Run extraction
|
|
132
|
+
yrange = (ylow, yhigh)
|
|
133
|
+
spec, slitf, model, unc, mask, info = slitfunc_curved(
|
|
134
|
+
swath_img,
|
|
135
|
+
swath_ycen_frac,
|
|
136
|
+
swath_p1,
|
|
137
|
+
swath_p2,
|
|
138
|
+
lambda_sp=LAMBDA_SP,
|
|
139
|
+
lambda_sf=LAMBDA_SF,
|
|
140
|
+
osample=OSAMPLE,
|
|
141
|
+
yrange=yrange,
|
|
142
|
+
maxiter=MAXITER,
|
|
143
|
+
gain=GAIN,
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
"swath_img": swath_img,
|
|
148
|
+
"spec": spec,
|
|
149
|
+
"slitf": slitf,
|
|
150
|
+
"model": model,
|
|
151
|
+
"unc": unc,
|
|
152
|
+
"mask": mask,
|
|
153
|
+
"info": info,
|
|
154
|
+
"ycen": swath_ycen_frac,
|
|
155
|
+
"ibeg": ibeg,
|
|
156
|
+
"iend": iend,
|
|
157
|
+
"yrange": yrange,
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def main():
|
|
162
|
+
# Check files exist
|
|
163
|
+
for fpath in [flat_file, trace_file]:
|
|
164
|
+
if not os.path.exists(fpath):
|
|
165
|
+
raise FileNotFoundError(f"File not found: {fpath}")
|
|
166
|
+
|
|
167
|
+
# Load data
|
|
168
|
+
img = load_image(flat_file)
|
|
169
|
+
traces, column_range = load_traces(trace_file)
|
|
170
|
+
nrow, ncol = img.shape
|
|
171
|
+
ntrace = len(traces)
|
|
172
|
+
|
|
173
|
+
print(f"\nImage: {nrow} x {ncol}")
|
|
174
|
+
print(f"Traces: {ntrace}")
|
|
175
|
+
print(f"Extracting trace {TRACE_INDEX}, swath {SWATH_INDEX}\n")
|
|
176
|
+
|
|
177
|
+
# Fix extraction parameters
|
|
178
|
+
xwd, cr, traces = fix_parameters(
|
|
179
|
+
EXTRACTION_HEIGHT, column_range, traces, nrow, ncol, ntrace
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# Get the specific trace
|
|
183
|
+
trace_coef = traces[TRACE_INDEX]
|
|
184
|
+
trace_cr = cr[TRACE_INDEX]
|
|
185
|
+
trace_xwd = xwd[TRACE_INDEX]
|
|
186
|
+
|
|
187
|
+
print(f"Trace {TRACE_INDEX}:")
|
|
188
|
+
print(f" Column range: {trace_cr}")
|
|
189
|
+
print(f" Extraction height: {trace_xwd} (below, above)")
|
|
190
|
+
|
|
191
|
+
# Extract single swath
|
|
192
|
+
result = extract_single_swath(
|
|
193
|
+
img,
|
|
194
|
+
trace_coef,
|
|
195
|
+
trace_cr,
|
|
196
|
+
SWATH_INDEX,
|
|
197
|
+
trace_xwd,
|
|
198
|
+
p1=None, # No curvature correction
|
|
199
|
+
p2=None,
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
# Save outputs
|
|
203
|
+
out_file = join(output_dir, f"debug_swath_t{TRACE_INDEX}_s{SWATH_INDEX}.npz")
|
|
204
|
+
os.makedirs(output_dir, exist_ok=True)
|
|
205
|
+
np.savez(
|
|
206
|
+
out_file,
|
|
207
|
+
swath_img=result["swath_img"],
|
|
208
|
+
spec=result["spec"],
|
|
209
|
+
slitf=result["slitf"],
|
|
210
|
+
model=result["model"],
|
|
211
|
+
unc=result["unc"],
|
|
212
|
+
mask=result["mask"],
|
|
213
|
+
ycen=result["ycen"],
|
|
214
|
+
ibeg=result["ibeg"],
|
|
215
|
+
iend=result["iend"],
|
|
216
|
+
yrange=result["yrange"],
|
|
217
|
+
trace_index=TRACE_INDEX,
|
|
218
|
+
swath_index=SWATH_INDEX,
|
|
219
|
+
)
|
|
220
|
+
print(f"\nSaved results to: {out_file}")
|
|
221
|
+
|
|
222
|
+
# Print summary
|
|
223
|
+
print("\n=== Extraction Results ===")
|
|
224
|
+
print(f"Spectrum shape: {result['spec'].shape}")
|
|
225
|
+
print(f"Slitfunction shape: {result['slitf'].shape}")
|
|
226
|
+
print(f"Model shape: {result['model'].shape}")
|
|
227
|
+
print(f"Chi-squared: {result['info'][1]:.3f}")
|
|
228
|
+
print(f"Iterations: {result['info'][0]}")
|
|
229
|
+
print(f"Masked pixels: {result['mask'].sum()}")
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
if __name__ == "__main__":
|
|
233
|
+
main()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# /// script
|
|
2
2
|
# requires-python = ">=3.13"
|
|
3
|
-
# dependencies = ["pyreduce-astro>=0.
|
|
3
|
+
# dependencies = ["pyreduce-astro>=0.7b4"]
|
|
4
4
|
# ///
|
|
5
5
|
"""
|
|
6
6
|
Simple usage example for PyReduce
|
|
@@ -43,6 +43,6 @@ Pipeline.from_instrument(
|
|
|
43
43
|
base_dir=base_dir,
|
|
44
44
|
input_dir=input_dir,
|
|
45
45
|
output_dir=output_dir,
|
|
46
|
-
#
|
|
46
|
+
# trace_range=(0, 25),
|
|
47
47
|
plot=1,
|
|
48
48
|
).run()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# /// script
|
|
2
2
|
# requires-python = ">=3.13"
|
|
3
|
-
# dependencies = ["pyreduce-astro>=0.
|
|
3
|
+
# dependencies = ["pyreduce-astro>=0.7b4"]
|
|
4
4
|
# ///
|
|
5
5
|
import os.path
|
|
6
6
|
|
|
@@ -71,7 +71,7 @@ kwargs_comb["nstep"] = 0
|
|
|
71
71
|
kwargs["plot"] = False
|
|
72
72
|
|
|
73
73
|
|
|
74
|
-
for key in ["extraction_method", "extraction_height"
|
|
74
|
+
for key in ["extraction_method", "extraction_height"]:
|
|
75
75
|
del kwargs_comb[key]
|
|
76
76
|
del kwargs[key]
|
|
77
77
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# /// script
|
|
2
2
|
# requires-python = ">=3.13"
|
|
3
|
-
# dependencies = ["pyreduce-astro>=0.
|
|
3
|
+
# dependencies = ["pyreduce-astro>=0.7b4"]
|
|
4
4
|
# ///
|
|
5
5
|
import matplotlib.pyplot as plt
|
|
6
6
|
import numpy as np
|
|
@@ -15,8 +15,20 @@ hdu = fits.open(input_dir + "uves_middle.flat.fits")
|
|
|
15
15
|
img = hdu[0].data
|
|
16
16
|
nrow, ncol = img.shape
|
|
17
17
|
|
|
18
|
+
import warnings
|
|
19
|
+
|
|
18
20
|
data = np.load(input_dir + "uves_middle.ord_default.npz", allow_pickle=True)
|
|
19
|
-
|
|
21
|
+
if "traces" in data:
|
|
22
|
+
traces = data["traces"]
|
|
23
|
+
elif "orders" in data:
|
|
24
|
+
warnings.warn(
|
|
25
|
+
"Trace file uses old key 'orders'. Re-run the trace step to update.",
|
|
26
|
+
DeprecationWarning,
|
|
27
|
+
stacklevel=1,
|
|
28
|
+
)
|
|
29
|
+
traces = data["orders"]
|
|
30
|
+
else:
|
|
31
|
+
raise KeyError("Trace file missing 'traces' key")
|
|
20
32
|
column_range = data["column_range"]
|
|
21
33
|
|
|
22
34
|
i = 5
|
|
@@ -24,7 +36,7 @@ ix = np.arange(ncol)
|
|
|
24
36
|
|
|
25
37
|
ylow, yhigh = 50, 50
|
|
26
38
|
ibeg, iend = 1500, 2000
|
|
27
|
-
ycen = np.polyval(
|
|
39
|
+
ycen = np.polyval(traces[i], ix)
|
|
28
40
|
ycen_int = ycen.astype(int)
|
|
29
41
|
# yrange = extract.get_y_scale(ycen, [400, 600], [5, 5], nrow)
|
|
30
42
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# /// script
|
|
2
2
|
# requires-python = ">=3.13"
|
|
3
|
-
# dependencies = ["pyreduce-astro>=0.
|
|
3
|
+
# dependencies = ["pyreduce-astro>=0.7b4"]
|
|
4
4
|
# ///
|
|
5
5
|
"""
|
|
6
6
|
Simple usage example for PyReduce
|
|
@@ -41,6 +41,6 @@ Pipeline.from_instrument(
|
|
|
41
41
|
base_dir=base_dir,
|
|
42
42
|
input_dir=input_dir,
|
|
43
43
|
output_dir=output_dir,
|
|
44
|
-
#
|
|
44
|
+
# trace_range=(0, 25),
|
|
45
45
|
plot=1,
|
|
46
46
|
).run()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# /// script
|
|
2
2
|
# requires-python = ">=3.13"
|
|
3
|
-
# dependencies = ["pyreduce-astro>=0.
|
|
3
|
+
# dependencies = ["pyreduce-astro>=0.7b4"]
|
|
4
4
|
# ///
|
|
5
5
|
"""
|
|
6
6
|
Simple usage example for PyReduce
|
|
@@ -41,6 +41,6 @@ Pipeline.from_instrument(
|
|
|
41
41
|
base_dir=base_dir,
|
|
42
42
|
input_dir=input_dir,
|
|
43
43
|
output_dir=output_dir,
|
|
44
|
-
#
|
|
44
|
+
# trace_range=(0, 25),
|
|
45
45
|
plot=0,
|
|
46
46
|
).run()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# /// script
|
|
2
2
|
# requires-python = ">=3.13"
|
|
3
|
-
# dependencies = ["pyreduce-astro>=0.
|
|
3
|
+
# dependencies = ["pyreduce-astro>=0.7b4"]
|
|
4
4
|
# ///
|
|
5
5
|
"""
|
|
6
6
|
Simple usage example for PyReduce
|
|
@@ -41,6 +41,6 @@ Pipeline.from_instrument(
|
|
|
41
41
|
base_dir=base_dir,
|
|
42
42
|
input_dir=input_dir,
|
|
43
43
|
output_dir=output_dir,
|
|
44
|
-
#
|
|
44
|
+
# trace_range=(0, 25),
|
|
45
45
|
plot=1,
|
|
46
46
|
).run()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# /// script
|
|
2
2
|
# requires-python = ">=3.13"
|
|
3
|
-
# dependencies = ["pyreduce-astro>=0.
|
|
3
|
+
# dependencies = ["pyreduce-astro>=0.7b4"]
|
|
4
4
|
# ///
|
|
5
5
|
"""
|
|
6
6
|
Simple usage example for PyReduce
|
|
@@ -52,6 +52,6 @@ Pipeline.from_instrument(
|
|
|
52
52
|
input_dir=input_dir,
|
|
53
53
|
output_dir=output_dir,
|
|
54
54
|
configuration=config,
|
|
55
|
-
#
|
|
55
|
+
# trace_range=(0, 25),
|
|
56
56
|
plot=2,
|
|
57
57
|
).run()
|