pyreduce-astro 0.7b4__tar.gz → 0.8a2__tar.gz

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