pyreduce-astro 0.7b4__tar.gz → 0.8a1__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.
Files changed (232) hide show
  1. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/.gitignore +2 -0
  2. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/CHANGELOG.md +42 -0
  3. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/CLAUDE.md +22 -15
  4. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/PKG-INFO +10 -4
  5. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/README.md +7 -3
  6. pyreduce_astro-0.8a1/WhatsNew.md +78 -0
  7. pyreduce_astro-0.8a1/examples/andes_riz.py +170 -0
  8. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/andes_yjh_example.py +5 -10
  9. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/crires_plus_example.py +0 -4
  10. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/custom_instrument_example.py +0 -4
  11. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/debug_single_swath.py +2 -6
  12. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/harpn_example.py +0 -4
  13. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/harps_example.py +0 -4
  14. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/harps_gridsearch.py +0 -4
  15. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/just_one_swath.py +1 -5
  16. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/jwst_miri_example.py +0 -4
  17. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/jwst_niriss_example.py +0 -4
  18. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/lick_apf_example.py +0 -4
  19. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/mcdonald_example.py +0 -4
  20. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/metis_ifu_example.py +0 -4
  21. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/metis_lss_example.py +0 -4
  22. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/micado_example.py +0 -4
  23. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/mosaic_nir.py +0 -4
  24. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/mosaic_preset-slitfunc.py +1 -5
  25. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/mosaic_vis.py +5 -6
  26. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/neid_example.py +0 -4
  27. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/nirspec_example.py +0 -4
  28. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/toes_example.py +0 -4
  29. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/uves_callfunc.py +7 -11
  30. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/uves_example.py +0 -4
  31. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/examples/xshooter_example.py +0 -4
  32. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyproject.toml +7 -1
  33. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/__main__.py +8 -6
  34. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/combine_frames.py +5 -1
  35. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/configuration.py +20 -4
  36. pyreduce_astro-0.8a1/pyreduce/curvature_model.py +194 -0
  37. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/cwrappers.py +2 -2
  38. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/estimate_background_scatter.py +7 -6
  39. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/extract.py +464 -142
  40. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_RIZ/__init__.py +15 -0
  41. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_RIZ/config.yaml +89 -0
  42. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_RIZ/order_centers_r0.yaml +20 -0
  43. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_RIZ/order_centers_r1.yaml +20 -0
  44. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_RIZ/order_centers_r2.yaml +20 -0
  45. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_RIZ/settings.json +30 -0
  46. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_RIZ/wavecal_r0_HDF.npz +0 -0
  47. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_RIZ/wavecal_r1_HDF.npz +0 -0
  48. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_RIZ/wavecal_r2_HDF.npz +0 -0
  49. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/ANDES_YJH/config.yaml +9 -0
  50. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/ANDES_YJH/settings.json +1 -1
  51. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/CRIRES_PLUS/__init__.py +3 -2
  52. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/CRIRES_PLUS/settings.json +1 -1
  53. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPN/settings.json +1 -1
  54. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPS/settings.json +1 -1
  55. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/JWST_MIRI/settings.json +1 -1
  56. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/JWST_NIRISS/settings.json +1 -1
  57. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/LICK_APF/settings.json +2 -2
  58. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/MCDONALD/settings.json +1 -1
  59. pyreduce_astro-0.8a1/pyreduce/instruments/METIS_IFU/__init__.py +118 -0
  60. pyreduce_astro-0.8a1/pyreduce/instruments/METIS_IFU/config.yaml +63 -0
  61. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/METIS_IFU/settings.json +12 -18
  62. pyreduce_astro-0.8a1/pyreduce/instruments/METIS_LSS/settings.json +4 -0
  63. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/MICADO/settings.json +1 -1
  64. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/MOSAIC/config.yaml +1 -0
  65. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/MOSAIC/settings.json +1 -1
  66. pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/settings_VIS3.json → pyreduce_astro-0.8a1/pyreduce/instruments/MOSAIC/settings_VIS1.json +1 -1
  67. pyreduce_astro-0.8a1/pyreduce/instruments/MOSAIC/settings_VIS2.json +4 -0
  68. pyreduce_astro-0.8a1/pyreduce/instruments/MOSAIC/settings_VIS3.json +4 -0
  69. pyreduce_astro-0.8a1/pyreduce/instruments/MOSAIC/settings_VIS4.json +4 -0
  70. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/MOSAIC/settings_nir.json +1 -2
  71. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/NEID/settings.json +1 -1
  72. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/NIRSPEC/settings.json +1 -1
  73. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/NTE/settings.json +2 -2
  74. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/settings.json +1 -1
  75. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/XSHOOTER/settings.json +2 -2
  76. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/defaults/config.yaml +6 -0
  77. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/defaults/schema.json +19 -10
  78. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/defaults/settings.json +3 -3
  79. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/models.py +14 -1
  80. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/pipeline.py +53 -26
  81. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/rectify.py +8 -6
  82. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/reduce.py +363 -89
  83. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/slit_curve.py +369 -135
  84. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/trace.py +218 -23
  85. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/util.py +10 -3
  86. pyreduce_astro-0.8a1/tools/andes_hdf_to_wavecal.py +322 -0
  87. pyreduce_astro-0.8a1/tools/andes_plot_spectra.py +111 -0
  88. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/tools/mosaic_vis_bundle_plot.py +0 -4
  89. pyreduce_astro-0.8a1/tools/plot_extractmodel_comp.py +15 -0
  90. pyreduce_astro-0.8a1/trace_spectrum_redesign.md +452 -0
  91. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/uv.lock +283 -277
  92. pyreduce_astro-0.7b4/ANDES_plan.md +0 -377
  93. pyreduce_astro-0.7b4/pyreduce/extraction_height.py +0 -77
  94. pyreduce_astro-0.7b4/pyreduce/instruments/METIS_IFU/__init__.py +0 -42
  95. pyreduce_astro-0.7b4/pyreduce/instruments/METIS_IFU/config.yaml +0 -62
  96. pyreduce_astro-0.7b4/pyreduce/instruments/METIS_LSS/settings.json +0 -4
  97. pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/settings_VIS1.json +0 -22
  98. pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/settings_VIS2.json +0 -22
  99. pyreduce_astro-0.7b4/pyreduce/instruments/MOSAIC/settings_VIS4.json +0 -22
  100. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/.gitattributes +0 -0
  101. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/.pre-commit-config.yaml +0 -0
  102. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/.python-version +0 -0
  103. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/.readthedocs.yaml +0 -0
  104. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/AGENTS.md +0 -0
  105. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/LICENSE +0 -0
  106. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/hatch_build.py +0 -0
  107. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/__init__.py +0 -0
  108. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/cli.py +0 -0
  109. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/clib/__init__.py +0 -0
  110. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/clib/build_extract.py +0 -0
  111. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/clib/slit_func_2d_xi_zeta_bd.c +0 -0
  112. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/clib/slit_func_2d_xi_zeta_bd.h +0 -0
  113. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/clib/slit_func_bd.c +0 -0
  114. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/clib/slit_func_bd.h +0 -0
  115. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/clipnflip.py +0 -0
  116. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/continuum_normalization.py +0 -0
  117. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/datasets.py +0 -0
  118. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/echelle.py +0 -0
  119. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/ANDES_YJH/__init__.py +0 -0
  120. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/ANDES_YJH/order_centers_h.yaml +0 -0
  121. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/ANDES_YJH/order_centers_j.yaml +0 -0
  122. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/ANDES_YJH/order_centers_y.yaml +0 -0
  123. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/CRIRES_PLUS/config.yaml +0 -0
  124. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/CRIRES_PLUS/mask_det1.fits.gz +0 -0
  125. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/CRIRES_PLUS/mask_det2.fits.gz +0 -0
  126. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/CRIRES_PLUS/mask_det3.fits.gz +0 -0
  127. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/CRIRES_PLUS/wavecal_J1228_det1.npz +0 -0
  128. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/CRIRES_PLUS/wavecal_J1228_det2.npz +0 -0
  129. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/CRIRES_PLUS/wavecal_J1228_det3.npz +0 -0
  130. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPN/__init__.py +0 -0
  131. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPN/config.yaml +0 -0
  132. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPN/wavecal_harpn_2D.npz +0 -0
  133. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPN/wavecal_harpn_fibB_2D.npz +0 -0
  134. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPS/__init__.py +0 -0
  135. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPS/config.yaml +0 -0
  136. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPS/mask_blue.fits.gz +0 -0
  137. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPS/mask_red.fits.gz +0 -0
  138. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPS/wavecal_blue_2D.npz +0 -0
  139. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPS/wavecal_blue_pol_2D.npz +0 -0
  140. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPS/wavecal_red_2D.npz +0 -0
  141. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPS/wavecal_red_pol_2D.npz +0 -0
  142. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/JWST_MIRI/__init__.py +0 -0
  143. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/JWST_MIRI/config.yaml +0 -0
  144. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/JWST_MIRI/mask_lrs_slitless.fits.gz +0 -0
  145. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/JWST_NIRISS/__init__.py +0 -0
  146. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/JWST_NIRISS/config.yaml +0 -0
  147. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/JWST_NIRISS/mask_gr700xd.fits.gz +0 -0
  148. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/LICK_APF/__init__.py +0 -0
  149. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/LICK_APF/config.yaml +0 -0
  150. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/LICK_APF/mask_.fits.gz +0 -0
  151. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/MCDONALD/__init__.py +0 -0
  152. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/MCDONALD/config.yaml +0 -0
  153. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/MCDONALD/mask.fits.gz +0 -0
  154. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/MCDONALD/wavecal.npz +0 -0
  155. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/METIS_LSS/__init__.py +0 -0
  156. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/METIS_LSS/config.yaml +0 -0
  157. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/METIS_LSS/wavecal_l_2D.npz +0 -0
  158. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/METIS_LSS/wavecal_m_2D.npz +0 -0
  159. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/MICADO/__init__.py +0 -0
  160. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/MICADO/config.yaml +0 -0
  161. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/MICADO/wavecal_HK_3arcsec_chip5.npz +0 -0
  162. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/MOSAIC/__init__.py +0 -0
  163. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/MOSAIC/bundle_centers_nir.yaml +0 -0
  164. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/MOSAIC/bundle_centers_vis1.yaml +0 -0
  165. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/MOSAIC/bundle_centers_vis2.yaml +0 -0
  166. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/MOSAIC/bundle_centers_vis3.yaml +0 -0
  167. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/MOSAIC/bundle_centers_vis4.yaml +0 -0
  168. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/MOSAIC/mask_nir.fits.gz +0 -0
  169. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/MOSAIC/mosaic_fiber_positions.npz +0 -0
  170. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/NEID/__init__.py +0 -0
  171. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/NEID/config.yaml +0 -0
  172. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/NIRSPEC/__init__.py +0 -0
  173. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/NIRSPEC/config.yaml +0 -0
  174. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/NIRSPEC/mask_nirspec.fits.gz +0 -0
  175. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/NIRSPEC/wavecal_K2.npz +0 -0
  176. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/NTE/__init__.py +0 -0
  177. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/NTE/config.yaml +0 -0
  178. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/__init__.py +0 -0
  179. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/config.yaml +0 -0
  180. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/mask_blue.fits.gz +0 -0
  181. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/mask_blue_binned_2_2.fits.gz +0 -0
  182. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/mask_middle.fits.gz +0 -0
  183. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/mask_middle_2x2_split.fits.gz +0 -0
  184. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/mask_middle_binned_2_2.fits.gz +0 -0
  185. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/mask_red.fits.gz +0 -0
  186. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/mask_red_2x2.fits.gz +0 -0
  187. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/mask_red_2x2_split.fits.gz +0 -0
  188. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/mask_red_binned_2_2.fits.gz +0 -0
  189. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_blue_360nm_2D.npz +0 -0
  190. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_blue_390nm_2D.npz +0 -0
  191. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_blue_437nm_2D.npz +0 -0
  192. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_middle_2x2_2D.npz +0 -0
  193. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_middle_565nm_2D.npz +0 -0
  194. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_middle_580nm_2D.npz +0 -0
  195. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_middle_600nm_2D.npz +0 -0
  196. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_middle_665nm_2D.npz +0 -0
  197. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_middle_860nm_2D.npz +0 -0
  198. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_red_580nm_2D.npz +0 -0
  199. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_red_600nm_2D.npz +0 -0
  200. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_red_665nm_2D.npz +0 -0
  201. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_red_760nm_2D.npz +0 -0
  202. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_red_860nm_2D.npz +0 -0
  203. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/XSHOOTER/__init__.py +0 -0
  204. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/XSHOOTER/config.yaml +0 -0
  205. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/XSHOOTER/mask_nir.fits.gz +0 -0
  206. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/XSHOOTER/wavecal_nir.npz +0 -0
  207. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/__init__.py +0 -0
  208. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/common.py +0 -0
  209. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/defaults/atlas/thar.fits +0 -0
  210. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/defaults/atlas/thar_list.txt +0 -0
  211. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/defaults/atlas/une.fits +0 -0
  212. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/filters.py +0 -0
  213. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/instruments/instrument_info.py +0 -0
  214. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/tools/__init__.py +0 -0
  215. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/tools/combine.py +0 -0
  216. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/pyreduce/wavelength_calibration.py +0 -0
  217. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/tools/argon.line +0 -0
  218. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/tools/bpm_creator.py +0 -0
  219. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/tools/convert_wavecal.py +0 -0
  220. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/tools/create_wavelength_guess.py +0 -0
  221. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/tools/download_files.py +0 -0
  222. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/tools/ipy_startup.py +0 -0
  223. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/tools/make_notebook.py +0 -0
  224. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/tools/neon.lin +0 -0
  225. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/tools/neon.line +0 -0
  226. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/tools/plot_1d_vs_2d_extraction.py +0 -0
  227. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/tools/plot_swath_debug.py +0 -0
  228. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/tools/pymultispec.py +0 -0
  229. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/tools/thar.npz +0 -0
  230. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/tools/wavecal_creator.py +0 -0
  231. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/tools/wavecal_creator_from_existing.py +0 -0
  232. {pyreduce_astro-0.7b4 → pyreduce_astro-0.8a1}/tools/xshooter_nir.json +0 -0
@@ -23,3 +23,5 @@ idl/
23
23
  logs/
24
24
  *.ipynb
25
25
  tmp/*
26
+ .obsidian/
27
+ uv.toml
@@ -1,6 +1,48 @@
1
1
  # Changelog
2
2
 
3
3
 
4
+ ## [0.8a1] - 2026-02-03
5
+
6
+ ### Added
7
+ - Charslit extraction backend with degree 1-5 curvature support
8
+ - ANDES_RIZ instrument configuration and settings
9
+ - `trace_by` config for separate tracing of illumination groups
10
+ - HDF-to-wavecal tool and reference files for ANDES_RIZ
11
+ - ANDES spectra plotting tool
12
+
13
+ ### Changed
14
+ - Curvature: use literal pixel extraction_height, not fractional
15
+ - Simplify extraction_height to single full-height value
16
+ - Move fiber selection default from hardcoded to config
17
+ - Update METIS_IFU for dynamic wavelength-based channels
18
+ - Use git URL for charslit optional dependency
19
+
20
+ ### Removed
21
+ - PEP 723 inline metadata from examples (caused confusion with `uv run`)
22
+
23
+ ### Fixed
24
+ - Fix curve_height to use new full-height format in plot_comparison
25
+ - Fix extraction_height to give exactly N rows
26
+ - Fix CRIRES_PLUS docstring (was incorrectly HARPS)
27
+
28
+ ## [0.7] - 2026-01-25
29
+
30
+ First stable release of the 0.7 series!
31
+
32
+ ### Changed
33
+ - Rename `OrderTracing` class to `Trace`, save file from `.orders.npz` to `.traces.npz`
34
+ - Store per-trace extraction heights in traces.npz
35
+ - Compute extraction heights for fiber bundles automatically
36
+ - CLI: consistent `-t/--target` option across all commands
37
+ - Allow explicit paths in settings `__inherits__` directive
38
+
39
+ ### Fixed
40
+ - Limit trace overlay to column_range in science step plot
41
+
42
+ ### Documentation
43
+ - Add WhatsNew.md summarizing 0.7 series improvements
44
+ - Update docs for traces.npz rename and mask convention
45
+
4
46
  ## [0.7b4] - 2026-01-22
5
47
 
6
48
  ### 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,6 +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
+ ├── curvature_model.py # SlitCurvature dataclass for curvature data
34
35
  ├── trace.py # Order detection and tracing
35
36
  ├── wavelength_calibration.py # Wavelength solution fitting
36
37
  ├── combine_frames.py # Frame combination/calibration
@@ -68,7 +69,7 @@ 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`** refers to pixels above/below each trace (in y)
72
+ - **`extraction_height`** is the extraction aperture size (fraction of order separation, or pixels if >1.5)
72
73
 
73
74
  ## Pipeline Steps
74
75
 
@@ -79,8 +80,8 @@ The reduction pipeline consists of these steps (in typical order):
79
80
  | `mask` | `Mask` | Load bad pixel mask for detector |
80
81
  | `bias` | `Bias` | Combine bias frames into master bias |
81
82
  | `flat` | `Flat` | Combine flat frames, subtract bias |
82
- | `trace` | `OrderTracing` | Trace echelle order positions on flat |
83
- | `curvature` | `SlitCurvatureDetermination` | Measure slit curvature from arc lamp |
83
+ | `trace` | `Trace` | Trace echelle order positions on flat |
84
+ | `curvature` | `SlitCurvatureDetermination` | Measure slit curvature (polynomial degree 1-5) |
84
85
  | `scatter` | `BackgroundScatter` | Model inter-order scattered light |
85
86
  | `norm_flat` | `NormalizeFlatField` | Normalize flat, extract blaze function |
86
87
  | `wavecal_master` | `WavelengthCalibrationMaster` | Extract wavelength calibration spectrum |
@@ -237,12 +238,12 @@ pyreduce.reduce.main(
237
238
 
238
239
  ```bash
239
240
  # Full pipeline
240
- uv run reduce run UVES HD132205 --steps bias,flat,trace
241
+ uv run reduce run UVES -t HD132205 --steps bias,flat,trace
241
242
 
242
243
  # 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
244
+ uv run reduce bias UVES -t HD132205
245
+ uv run reduce trace UVES -t HD132205
246
+ uv run reduce wavecal UVES -t HD132205
246
247
 
247
248
  # Combine reduced spectra
248
249
  uv run reduce combine --output combined.fits *.final.fits
@@ -261,15 +262,21 @@ uv run reduce list-steps
261
262
  - `PYREDUCE_PLOT_DIR` - Save plots to directory as PNG files
262
263
  - `PYREDUCE_PLOT_SHOW` - Display mode: `block` (default), `defer`, or `off`
263
264
  - `PYREDUCE_PLOT_ANIMATION_SPEED` - Frame delay in seconds for extraction animation (default: 0.3)
265
+ - `PYREDUCE_USE_CHARSLIT` - Use charslit extraction backend instead of CFFI (default: 0)
266
+ - `PYREDUCE_USE_DELTAS` - Enable slitdelta correction with charslit backend (default: 1)
264
267
 
265
268
  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
269
 
270
+ The charslit backend supports higher-degree curvature polynomials (up to degree 5) and per-row slitdelta corrections. It requires the optional `charslit` dependency.
271
+
267
272
  ## Development
268
273
 
269
274
  ### Commands
270
275
 
271
276
  ```bash
272
277
  uv sync # Install dependencies
278
+ uv sync --extra charslit # Include charslit backend (from GitHub)
279
+ uv pip install -e ../CharSlit.git # Overlay local editable charslit for dev
273
280
  uv run reduce-build # Compile C extensions
274
281
  uv run reduce-clean # Remove compiled extensions
275
282
  uv run pre-commit install # Setup hooks (once)
@@ -303,6 +310,8 @@ After a fresh clone or `rm -rf .venv`, run `uv sync && uv run reduce-build` to s
303
310
  | `pyreduce/pipeline.py` | Fluent Pipeline API, `from_instrument()` |
304
311
  | `pyreduce/reduce.py` | Step class implementations |
305
312
  | `pyreduce/extract.py` | Optimal extraction algorithm |
313
+ | `pyreduce/curvature_model.py` | SlitCurvature dataclass, save/load |
314
+ | `pyreduce/slit_curve.py` | Slit curvature fitting (degree 1-5) |
306
315
  | `pyreduce/wavelength_calibration.py` | Wavelength solution fitting |
307
316
  | `pyreduce/trace.py` | Order detection and tracing |
308
317
  | `pyreduce/instruments/common.py` | Base Instrument class |
@@ -326,17 +335,15 @@ To release a new version (e.g., `0.7a6`):
326
335
 
327
336
  3a. **sync** - run `uv sync` to get the new version into uv.lock
328
337
 
329
- 4. **Update example headers** - all `examples/*.py` have PEP 723 metadata:
330
- ```python
331
- # /// script
332
- # dependencies = ["pyreduce-astro>=0.7a6"]
333
- # ///
338
+ 4. **Run unit tests** to catch issues before release:
339
+ ```bash
340
+ uv run pytest -m unit
334
341
  ```
335
342
 
336
343
  5. **Commit, tag, and push**:
337
344
  ```bash
338
- git add -A && git commit -m "Release v0.7a6"
339
- git tag v0.7a6
345
+ git add -A && git commit -m "Release v0.8a1"
346
+ git tag v0.8a1
340
347
  git push && git push --tags
341
348
  ```
342
349
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyreduce-astro
3
- Version: 0.7b4
3
+ Version: 0.8a1
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
  [![CI](https://github.com/ivh/PyReduce/actions/workflows/python-publish.yml/badge.svg)](https://github.com/ivh/PyReduce/actions/workflows/python-publish.yml)
43
45
  [![Documentation Status](https://readthedocs.org/projects/pyreduce-astro/badge/?version=latest)](https://pyreduce-astro.readthedocs.io/en/latest/?badge=latest)
44
46
  [![Python 3.13+](https://img.shields.io/badge/python-3.13+-blue.svg)](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
  [![Documentation Status](https://readthedocs.org/projects/pyreduce-astro/badge/?version=latest)](https://pyreduce-astro.readthedocs.io/en/latest/?badge=latest)
3
3
  [![Python 3.13+](https://img.shields.io/badge/python-3.13+-blue.svg)](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,78 @@
1
+ ## What's New in PyReduce 0.7 ?
2
+
3
+ ### Multi-Fiber Instrument Support
4
+
5
+ New `fibers` configuration in instrument YAML for IFU and multi-fiber spectrographs:
6
+
7
+ - **Named groups**: Define fiber ranges (e.g., science A/B, calibration) with merge strategies
8
+ - **Bundle patterns**: For repeating fiber bundles (e.g., 7 fibers per IFU target)
9
+ - **Per-order grouping**: For echelle instruments with fiber groups repeated across orders
10
+ - **Missing fiber handling**: `bundle_centers_file` assigns traces by proximity when fibers are broken
11
+ - Per-step trace selection (`science: [A, B]`, `wavecal: [cal]`, etc.)
12
+
13
+ See [docs/fiber_bundle_tracing.md](docs/fiber_bundle_tracing.md) for details.
14
+
15
+ ### New Instruments
16
+
17
+ - **MOSAIC** (ELT) with multi-fiber bundle support, VIS quadrants (VIS1-VIS4)
18
+ - **ANDES_YJH** with multi-channel support
19
+ - **NEID** with multi-amplifier support
20
+
21
+ See [docs/instruments.md](docs/instruments.md) for the full list.
22
+
23
+ ### Configuration Changes
24
+
25
+ - Instrument configs now use YAML (validated by Pydantic)
26
+ - Files reorganized into `instruments/{NAME}/` directories
27
+ - Settings cascade: defaults → instrument → runtime overrides
28
+ - **Per-channel settings**: `settings_{channel}.json` for channel-specific parameters
29
+
30
+ See [docs/configuration_file.md](docs/configuration_file.md) for details.
31
+
32
+ ### Terminology Changes
33
+
34
+ - `mode` → `channel` (e.g., `mode="middle"` is now `channel="middle"`)
35
+ - `orders` step → `trace` step
36
+ - `OrderTracing` class → `Trace`, output `.orders.npz` → `.traces.npz`
37
+ - `extraction_width` → `extraction_height`
38
+ - Output files: `.ech` → `.fits`
39
+ - **Mask convention**: Now uses numpy standard (1=bad, 0=good)
40
+
41
+ ### Plotting
42
+
43
+ - `PYREDUCE_PLOT_DIR` saves plots as PNG files
44
+ - `PYREDUCE_PLOT_SHOW=defer` accumulates plots for batch viewing
45
+ - Extraction animation with pause/step controls and residual panel
46
+ - Trace overlay on calibration plots
47
+
48
+ ### New Pipeline API
49
+
50
+ ```python
51
+ from pyreduce.pipeline import Pipeline
52
+
53
+ result = Pipeline.from_instrument(
54
+ instrument="UVES",
55
+ target="HD132205",
56
+ steps=("bias", "flat", "trace", "science"),
57
+ ).run()
58
+ ```
59
+
60
+ The old `pyreduce.reduce.main()` still works but shows a deprecation warning. See [docs/examples.md](docs/examples.md) for more.
61
+
62
+ ### New CLI
63
+
64
+ The old argparse CLI is replaced with a cleaner Click-based interface. See [docs/cli.md](docs/cli.md) for the full reference.
65
+
66
+ ### Extraction Improvements
67
+
68
+ - **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)
69
+ - **Per-trace extraction heights**: Stored in traces file, computed automatically for fiber bundles
70
+ - Convergence based on spectrum change, outlier rejection improved.
71
+
72
+ ### Installation & Build
73
+
74
+ - Now uses `uv` package manager (`uv sync`, `uv run reduce ...`), but `pip install pyreduce-astro` still works
75
+ - **Python 3.11+** required (3.13 recommended)
76
+ - Build system migrated from setuptools to Hatchling
77
+
78
+ See [docs/installation.md](docs/installation.md) for details.
@@ -0,0 +1,170 @@
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
+ pipe.extract([lfc_combined_path])
158
+
159
+ results = pipe.run()
160
+
161
+ if "trace" in results:
162
+ traces, column_range, *_ = results["trace"]
163
+ print(f"Traces found: {len(traces)}")
164
+
165
+ if "trace_groups" in results and results["trace_groups"]:
166
+ group_traces, group_cr, group_heights = results["trace_groups"]
167
+ print(f"Fiber groups: {list(group_traces.keys())}")
168
+ for name, traces_dict in group_traces.items():
169
+ if isinstance(traces_dict, dict):
170
+ print(f" {name}: orders {list(traces_dict.keys())}")
@@ -1,7 +1,3 @@
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
 
@@ -62,7 +58,7 @@ LOAD_TRACE = True # Set True to load traces from previous run
62
58
 
63
59
  if LOAD_TRACE:
64
60
  print("\nLoading traces from previous run...")
65
- traces, column_range = pipe._run_step("trace", None, load_only=True)
61
+ traces, column_range, heights = pipe._run_step("trace", None, load_only=True)
66
62
  print(f" Loaded {len(traces)} traces")
67
63
 
68
64
  # Re-run organize with current config (picks up any config changes)
@@ -71,11 +67,11 @@ if LOAD_TRACE:
71
67
  else:
72
68
  # Trace each flat independently
73
69
  print(f"\nTracing even fibers from {os.path.basename(file_even)}...")
74
- traces_even, cr_even = pipe.trace_raw([file_even])
70
+ traces_even, cr_even, _ = pipe.trace_raw([file_even])
75
71
  print(f" Found {len(traces_even)} traces")
76
72
 
77
73
  print(f"\nTracing odd fibers from {os.path.basename(file_odd)}...")
78
- traces_odd, cr_odd = pipe.trace_raw([file_odd])
74
+ traces_odd, cr_odd, _ = pipe.trace_raw([file_odd])
79
75
  print(f" Found {len(traces_odd)} traces")
80
76
 
81
77
  # Organize into fiber groups
@@ -84,7 +80,7 @@ else:
84
80
 
85
81
  # Access organized groups
86
82
  if "trace_groups" in pipe._data and pipe._data["trace_groups"][0]:
87
- group_traces, group_cr = pipe._data["trace_groups"]
83
+ group_traces, group_cr, group_heights = pipe._data["trace_groups"]
88
84
  print("Fiber groups:")
89
85
  for name, traces_dict in group_traces.items():
90
86
  n_traces = len(traces_dict)
@@ -108,6 +104,5 @@ print(f" Saved combined flat: {combined_file}")
108
104
 
109
105
  # --- Extract using the science step ---
110
106
  print("\nExtracting spectra (group A from fiber config)...")
111
- pipe.instrument.config.fibers.use["science"] = ["ring1"]
112
- pipe.config["science"]["extraction_height"] = 60
107
+ pipe.instrument.config.fibers.use["science"] = ["ring2"]
113
108
  pipe.extract([combined_file]).run()
@@ -1,7 +1,3 @@
1
- # /// script
2
- # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b4"]
4
- # ///
5
1
  """
6
2
  Simple usage example for PyReduce
7
3
  Loads a CRIRES+ dataset, and runs the extraction
@@ -1,7 +1,3 @@
1
- # /// script
2
- # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b4"]
4
- # ///
5
1
  """
6
2
  Simple usage example for PyReduce
7
3
  Loads a sample UVES dataset, and runs the full extraction
@@ -1,7 +1,3 @@
1
- # /// script
2
- # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b4"]
4
- # ///
5
1
  """
6
2
  Debug script for extracting a single swath from a specific trace.
7
3
 
@@ -42,7 +38,7 @@ flat_file = join(
42
38
  "E2E_FLAT_DIT_20s_MOSAIC_2Cam_c01",
43
39
  "E2E_FLAT_DIT_20s_MOSAIC_2Cam_c01_STATIC_FOCAL_PLANE.fits",
44
40
  )
45
- trace_file = join(output_dir, "MOSAIC_NIR.ord_default.npz")
41
+ trace_file = join(output_dir, "MOSAIC_NIR.traces.npz")
46
42
 
47
43
 
48
44
  def load_traces(trace_file):
@@ -186,7 +182,7 @@ def main():
186
182
 
187
183
  print(f"Trace {TRACE_INDEX}:")
188
184
  print(f" Column range: {trace_cr}")
189
- print(f" Extraction height: {trace_xwd} (below, above)")
185
+ print(f" Extraction height: {trace_xwd}")
190
186
 
191
187
  # Extract single swath
192
188
  result = extract_single_swath(
@@ -1,7 +1,3 @@
1
- # /// script
2
- # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b4"]
4
- # ///
5
1
  """
6
2
  Simple usage example for PyReduce
7
3
  Loads a HARPS-N dataset, and runs the extraction
@@ -1,7 +1,3 @@
1
- # /// script
2
- # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b4"]
4
- # ///
5
1
  """
6
2
  Simple usage example for PyReduce
7
3
  Loads a sample HARPS dataset, and runs the full extraction
@@ -1,7 +1,3 @@
1
- # /// script
2
- # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b4"]
4
- # ///
5
1
  import os.path
6
2
 
7
3
  import matplotlib.pyplot as plt
@@ -1,7 +1,3 @@
1
- # /// script
2
- # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b4"]
4
- # ///
5
1
  import matplotlib.pyplot as plt
6
2
  import numpy as np
7
3
  from astropy.io import fits
@@ -17,7 +13,7 @@ nrow, ncol = img.shape
17
13
 
18
14
  import warnings
19
15
 
20
- data = np.load(input_dir + "uves_middle.ord_default.npz", allow_pickle=True)
16
+ data = np.load(input_dir + "uves_middle.traces.npz", allow_pickle=True)
21
17
  if "traces" in data:
22
18
  traces = data["traces"]
23
19
  elif "orders" in data:
@@ -1,7 +1,3 @@
1
- # /// script
2
- # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b4"]
4
- # ///
5
1
  """
6
2
  Simple usage example for PyReduce
7
3
  Loads a JWST MIRI dataset, and runs the extraction
@@ -1,7 +1,3 @@
1
- # /// script
2
- # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b4"]
4
- # ///
5
1
  """
6
2
  Simple usage example for PyReduce
7
3
  Loads a sample JWST NIRISS dataset, and runs the extraction
@@ -1,7 +1,3 @@
1
- # /// script
2
- # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b4"]
4
- # ///
5
1
  """
6
2
  Simple usage example for PyReduce
7
3
  Loads a Lick APF dataset, and runs the extraction
@@ -1,7 +1,3 @@
1
- # /// script
2
- # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b4"]
4
- # ///
5
1
  """
6
2
  Simple usage example for PyReduce
7
3
  Loads a McDonald Observatory dataset, and runs the extraction
@@ -1,7 +1,3 @@
1
- # /// script
2
- # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b4"]
4
- # ///
5
1
  """
6
2
  Simple usage example for PyReduce
7
3
  Loads a simulated METIS dataset, and runs the full extraction
@@ -1,7 +1,3 @@
1
- # /// script
2
- # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b4"]
4
- # ///
5
1
  """
6
2
  Simple usage example for PyReduce
7
3
  Loads a simulated METIS dataset, and runs the full extraction