pyreduce-astro 0.7b3__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 (255) hide show
  1. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/.gitignore +2 -0
  2. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/CHANGELOG.md +69 -0
  3. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/CLAUDE.md +27 -19
  4. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/PKG-INFO +10 -4
  5. {pyreduce_astro-0.7b3 → 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.8a1/examples/andes_yjh_example.py +108 -0
  9. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/examples/crires_plus_example.py +1 -5
  10. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/examples/custom_instrument_example.py +1 -5
  11. pyreduce_astro-0.8a1/examples/debug_single_swath.py +229 -0
  12. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/examples/harpn_example.py +1 -5
  13. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/examples/harps_example.py +0 -4
  14. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/examples/harps_gridsearch.py +1 -5
  15. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/examples/just_one_swath.py +15 -7
  16. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/examples/jwst_miri_example.py +1 -5
  17. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/examples/jwst_niriss_example.py +1 -5
  18. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/examples/lick_apf_example.py +1 -5
  19. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/examples/mcdonald_example.py +1 -5
  20. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/examples/metis_ifu_example.py +1 -5
  21. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/examples/metis_lss_example.py +1 -5
  22. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/examples/micado_example.py +1 -5
  23. pyreduce_astro-0.8a1/examples/mosaic_nir.py +92 -0
  24. pyreduce_astro-0.8a1/examples/mosaic_preset-slitfunc.py +137 -0
  25. pyreduce_astro-0.8a1/examples/mosaic_vis.py +91 -0
  26. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/examples/neid_example.py +0 -4
  27. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/examples/nirspec_example.py +1 -5
  28. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/examples/toes_example.py +1 -5
  29. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/examples/uves_callfunc.py +9 -13
  30. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/examples/uves_example.py +1 -5
  31. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/examples/xshooter_example.py +1 -6
  32. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyproject.toml +7 -1
  33. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/__main__.py +18 -16
  34. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/cli.py +2 -2
  35. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/clib/slit_func_2d_xi_zeta_bd.c +152 -118
  36. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/clib/slit_func_2d_xi_zeta_bd.h +2 -0
  37. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/clib/slit_func_bd.c +2 -5
  38. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/combine_frames.py +40 -0
  39. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/configuration.py +38 -8
  40. pyreduce_astro-0.8a1/pyreduce/curvature_model.py +194 -0
  41. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/cwrappers.py +251 -23
  42. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/estimate_background_scatter.py +26 -25
  43. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/extract.py +734 -314
  44. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_RIZ/__init__.py +15 -0
  45. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_RIZ/config.yaml +89 -0
  46. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_RIZ/order_centers_r0.yaml +20 -0
  47. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_RIZ/order_centers_r1.yaml +20 -0
  48. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_RIZ/order_centers_r2.yaml +20 -0
  49. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_RIZ/settings.json +30 -0
  50. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_RIZ/wavecal_r0_HDF.npz +0 -0
  51. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_RIZ/wavecal_r1_HDF.npz +0 -0
  52. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_RIZ/wavecal_r2_HDF.npz +0 -0
  53. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_YJH/__init__.py +14 -0
  54. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_YJH/config.yaml +122 -0
  55. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_YJH/order_centers_h.yaml +9 -0
  56. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_YJH/order_centers_j.yaml +21 -0
  57. pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_YJH/order_centers_y.yaml +9 -0
  58. {pyreduce_astro-0.7b3/pyreduce/instruments/AJ → pyreduce_astro-0.8a1/pyreduce/instruments/ANDES_YJH}/settings.json +5 -4
  59. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/CRIRES_PLUS/__init__.py +3 -2
  60. pyreduce_astro-0.8a1/pyreduce/instruments/CRIRES_PLUS/mask_det1.fits.gz +0 -0
  61. pyreduce_astro-0.8a1/pyreduce/instruments/CRIRES_PLUS/mask_det2.fits.gz +0 -0
  62. pyreduce_astro-0.8a1/pyreduce/instruments/CRIRES_PLUS/mask_det3.fits.gz +0 -0
  63. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/CRIRES_PLUS/settings.json +1 -3
  64. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPN/settings.json +1 -1
  65. pyreduce_astro-0.8a1/pyreduce/instruments/HARPN/wavecal_harpn_fibB_2D.npz +0 -0
  66. pyreduce_astro-0.8a1/pyreduce/instruments/HARPS/mask_blue.fits.gz +0 -0
  67. pyreduce_astro-0.8a1/pyreduce/instruments/HARPS/mask_red.fits.gz +0 -0
  68. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPS/settings.json +2 -3
  69. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/JWST_MIRI/mask_lrs_slitless.fits.gz +0 -0
  70. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/JWST_MIRI/settings.json +1 -1
  71. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/JWST_NIRISS/mask_gr700xd.fits.gz +0 -0
  72. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/JWST_NIRISS/settings.json +1 -1
  73. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/LICK_APF/mask_.fits.gz +0 -0
  74. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/LICK_APF/settings.json +2 -2
  75. pyreduce_astro-0.8a1/pyreduce/instruments/MCDONALD/mask.fits.gz +0 -0
  76. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/MCDONALD/settings.json +1 -1
  77. pyreduce_astro-0.8a1/pyreduce/instruments/METIS_IFU/__init__.py +118 -0
  78. pyreduce_astro-0.8a1/pyreduce/instruments/METIS_IFU/config.yaml +63 -0
  79. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/METIS_IFU/settings.json +12 -21
  80. pyreduce_astro-0.8a1/pyreduce/instruments/METIS_LSS/settings.json +4 -0
  81. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/MICADO/settings.json +2 -5
  82. pyreduce_astro-0.8a1/pyreduce/instruments/MOSAIC/__init__.py +38 -0
  83. pyreduce_astro-0.8a1/pyreduce/instruments/MOSAIC/bundle_centers_nir.yaml +92 -0
  84. pyreduce_astro-0.8a1/pyreduce/instruments/MOSAIC/bundle_centers_vis1.yaml +69 -0
  85. pyreduce_astro-0.8a1/pyreduce/instruments/MOSAIC/bundle_centers_vis2.yaml +72 -0
  86. pyreduce_astro-0.8a1/pyreduce/instruments/MOSAIC/bundle_centers_vis3.yaml +87 -0
  87. pyreduce_astro-0.8a1/pyreduce/instruments/MOSAIC/bundle_centers_vis4.yaml +87 -0
  88. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/MOSAIC/config.yaml +16 -2
  89. pyreduce_astro-0.8a1/pyreduce/instruments/MOSAIC/mask_nir.fits.gz +0 -0
  90. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/MOSAIC/settings.json +6 -11
  91. pyreduce_astro-0.8a1/pyreduce/instruments/MOSAIC/settings_VIS1.json +22 -0
  92. pyreduce_astro-0.8a1/pyreduce/instruments/MOSAIC/settings_VIS2.json +4 -0
  93. pyreduce_astro-0.8a1/pyreduce/instruments/MOSAIC/settings_VIS3.json +4 -0
  94. pyreduce_astro-0.8a1/pyreduce/instruments/MOSAIC/settings_VIS4.json +4 -0
  95. pyreduce_astro-0.8a1/pyreduce/instruments/MOSAIC/settings_nir.json +21 -0
  96. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/NEID/settings.json +1 -2
  97. pyreduce_astro-0.8a1/pyreduce/instruments/NIRSPEC/mask_nirspec.fits.gz +0 -0
  98. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/NIRSPEC/settings.json +1 -1
  99. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/NTE/settings.json +2 -4
  100. pyreduce_astro-0.8a1/pyreduce/instruments/UVES/mask_blue.fits.gz +0 -0
  101. pyreduce_astro-0.8a1/pyreduce/instruments/UVES/mask_blue_binned_2_2.fits.gz +0 -0
  102. pyreduce_astro-0.8a1/pyreduce/instruments/UVES/mask_middle.fits.gz +0 -0
  103. pyreduce_astro-0.8a1/pyreduce/instruments/UVES/mask_middle_2x2_split.fits.gz +0 -0
  104. pyreduce_astro-0.8a1/pyreduce/instruments/UVES/mask_middle_binned_2_2.fits.gz +0 -0
  105. pyreduce_astro-0.8a1/pyreduce/instruments/UVES/mask_red.fits.gz +0 -0
  106. pyreduce_astro-0.8a1/pyreduce/instruments/UVES/mask_red_2x2.fits.gz +0 -0
  107. pyreduce_astro-0.8a1/pyreduce/instruments/UVES/mask_red_2x2_split.fits.gz +0 -0
  108. pyreduce_astro-0.8a1/pyreduce/instruments/UVES/mask_red_binned_2_2.fits.gz +0 -0
  109. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/settings.json +3 -3
  110. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/XSHOOTER/mask_nir.fits.gz +0 -0
  111. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/XSHOOTER/settings.json +3 -4
  112. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/common.py +3 -0
  113. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/defaults/config.yaml +6 -0
  114. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/defaults/schema.json +69 -152
  115. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/defaults/settings.json +10 -12
  116. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/models.py +112 -2
  117. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/pipeline.py +234 -21
  118. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/rectify.py +16 -14
  119. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/reduce.py +675 -161
  120. pyreduce_astro-0.8a1/pyreduce/slit_curve.py +905 -0
  121. pyreduce_astro-0.8a1/pyreduce/trace.py +1904 -0
  122. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/util.py +10 -3
  123. pyreduce_astro-0.8a1/tools/andes_hdf_to_wavecal.py +322 -0
  124. pyreduce_astro-0.8a1/tools/andes_plot_spectra.py +111 -0
  125. pyreduce_astro-0.8a1/tools/mosaic_vis_bundle_plot.py +62 -0
  126. pyreduce_astro-0.8a1/tools/plot_1d_vs_2d_extraction.py +162 -0
  127. pyreduce_astro-0.8a1/tools/plot_extractmodel_comp.py +15 -0
  128. pyreduce_astro-0.8a1/tools/plot_swath_debug.py +64 -0
  129. pyreduce_astro-0.8a1/trace_spectrum_redesign.md +452 -0
  130. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/uv.lock +283 -277
  131. pyreduce_astro-0.7b3/ANDES_plan.md +0 -377
  132. pyreduce_astro-0.7b3/examples/aj_example.py +0 -209
  133. pyreduce_astro-0.7b3/examples/mosaic_example.py +0 -171
  134. pyreduce_astro-0.7b3/pyreduce/extraction_height.py +0 -77
  135. pyreduce_astro-0.7b3/pyreduce/instruments/AJ/__init__.py +0 -9
  136. pyreduce_astro-0.7b3/pyreduce/instruments/AJ/config.yaml +0 -51
  137. pyreduce_astro-0.7b3/pyreduce/instruments/ANDES/__init__.py +0 -100
  138. pyreduce_astro-0.7b3/pyreduce/instruments/ANDES/config.yaml +0 -72
  139. pyreduce_astro-0.7b3/pyreduce/instruments/ANDES/settings.json +0 -16
  140. pyreduce_astro-0.7b3/pyreduce/instruments/CRIRES_PLUS/mask_det1.fits.gz +0 -0
  141. pyreduce_astro-0.7b3/pyreduce/instruments/CRIRES_PLUS/mask_det2.fits.gz +0 -0
  142. pyreduce_astro-0.7b3/pyreduce/instruments/CRIRES_PLUS/mask_det3.fits.gz +0 -0
  143. pyreduce_astro-0.7b3/pyreduce/instruments/HARPS/mask_blue.fits.gz +0 -0
  144. pyreduce_astro-0.7b3/pyreduce/instruments/HARPS/mask_red.fits.gz +0 -0
  145. pyreduce_astro-0.7b3/pyreduce/instruments/MCDONALD/mask.fits.gz +0 -0
  146. pyreduce_astro-0.7b3/pyreduce/instruments/METIS_IFU/__init__.py +0 -42
  147. pyreduce_astro-0.7b3/pyreduce/instruments/METIS_IFU/config.yaml +0 -62
  148. pyreduce_astro-0.7b3/pyreduce/instruments/METIS_LSS/settings.json +0 -4
  149. pyreduce_astro-0.7b3/pyreduce/instruments/MOSAIC/__init__.py +0 -12
  150. pyreduce_astro-0.7b3/pyreduce/instruments/NIRSPEC/mask_nirspec.fits.gz +0 -0
  151. pyreduce_astro-0.7b3/pyreduce/instruments/UVES/mask_blue.fits.gz +0 -0
  152. pyreduce_astro-0.7b3/pyreduce/instruments/UVES/mask_blue_binned_2_2.fits.gz +0 -0
  153. pyreduce_astro-0.7b3/pyreduce/instruments/UVES/mask_middle.fits.gz +0 -0
  154. pyreduce_astro-0.7b3/pyreduce/instruments/UVES/mask_middle_2x2_split.fits.gz +0 -0
  155. pyreduce_astro-0.7b3/pyreduce/instruments/UVES/mask_middle_binned_2_2.fits.gz +0 -0
  156. pyreduce_astro-0.7b3/pyreduce/instruments/UVES/mask_red.fits.gz +0 -0
  157. pyreduce_astro-0.7b3/pyreduce/instruments/UVES/mask_red_2x2.fits.gz +0 -0
  158. pyreduce_astro-0.7b3/pyreduce/instruments/UVES/mask_red_2x2_split.fits.gz +0 -0
  159. pyreduce_astro-0.7b3/pyreduce/instruments/UVES/mask_red_binned_2_2.fits.gz +0 -0
  160. pyreduce_astro-0.7b3/pyreduce/slit_curve.py +0 -741
  161. pyreduce_astro-0.7b3/pyreduce/trace.py +0 -985
  162. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/.gitattributes +0 -0
  163. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/.pre-commit-config.yaml +0 -0
  164. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/.python-version +0 -0
  165. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/.readthedocs.yaml +0 -0
  166. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/AGENTS.md +0 -0
  167. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/LICENSE +0 -0
  168. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/hatch_build.py +0 -0
  169. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/__init__.py +0 -0
  170. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/clib/__init__.py +0 -0
  171. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/clib/build_extract.py +0 -0
  172. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/clib/slit_func_bd.h +0 -0
  173. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/clipnflip.py +0 -0
  174. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/continuum_normalization.py +0 -0
  175. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/datasets.py +0 -0
  176. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/echelle.py +0 -0
  177. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/CRIRES_PLUS/config.yaml +0 -0
  178. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/CRIRES_PLUS/wavecal_J1228_det1.npz +0 -0
  179. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/CRIRES_PLUS/wavecal_J1228_det2.npz +0 -0
  180. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/CRIRES_PLUS/wavecal_J1228_det3.npz +0 -0
  181. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPN/__init__.py +0 -0
  182. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPN/config.yaml +0 -0
  183. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPN/wavecal_harpn_2D.npz +0 -0
  184. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPS/__init__.py +0 -0
  185. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPS/config.yaml +0 -0
  186. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPS/wavecal_blue_2D.npz +0 -0
  187. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPS/wavecal_blue_pol_2D.npz +0 -0
  188. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPS/wavecal_red_2D.npz +0 -0
  189. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/HARPS/wavecal_red_pol_2D.npz +0 -0
  190. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/JWST_MIRI/__init__.py +0 -0
  191. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/JWST_MIRI/config.yaml +0 -0
  192. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/JWST_NIRISS/__init__.py +0 -0
  193. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/JWST_NIRISS/config.yaml +0 -0
  194. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/LICK_APF/__init__.py +0 -0
  195. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/LICK_APF/config.yaml +0 -0
  196. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/MCDONALD/__init__.py +0 -0
  197. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/MCDONALD/config.yaml +0 -0
  198. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/MCDONALD/wavecal.npz +0 -0
  199. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/METIS_LSS/__init__.py +0 -0
  200. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/METIS_LSS/config.yaml +0 -0
  201. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/METIS_LSS/wavecal_l_2D.npz +0 -0
  202. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/METIS_LSS/wavecal_m_2D.npz +0 -0
  203. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/MICADO/__init__.py +0 -0
  204. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/MICADO/config.yaml +0 -0
  205. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/MICADO/wavecal_HK_3arcsec_chip5.npz +0 -0
  206. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/MOSAIC/mosaic_fiber_positions.npz +0 -0
  207. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/NEID/__init__.py +0 -0
  208. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/NEID/config.yaml +0 -0
  209. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/NIRSPEC/__init__.py +0 -0
  210. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/NIRSPEC/config.yaml +0 -0
  211. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/NIRSPEC/wavecal_K2.npz +0 -0
  212. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/NTE/__init__.py +0 -0
  213. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/NTE/config.yaml +0 -0
  214. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/__init__.py +0 -0
  215. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/config.yaml +0 -0
  216. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_blue_360nm_2D.npz +0 -0
  217. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_blue_390nm_2D.npz +0 -0
  218. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_blue_437nm_2D.npz +0 -0
  219. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_middle_2x2_2D.npz +0 -0
  220. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_middle_565nm_2D.npz +0 -0
  221. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_middle_580nm_2D.npz +0 -0
  222. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_middle_600nm_2D.npz +0 -0
  223. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_middle_665nm_2D.npz +0 -0
  224. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_middle_860nm_2D.npz +0 -0
  225. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_red_580nm_2D.npz +0 -0
  226. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_red_600nm_2D.npz +0 -0
  227. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_red_665nm_2D.npz +0 -0
  228. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_red_760nm_2D.npz +0 -0
  229. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/UVES/wavecal_red_860nm_2D.npz +0 -0
  230. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/XSHOOTER/__init__.py +0 -0
  231. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/XSHOOTER/config.yaml +0 -0
  232. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/XSHOOTER/wavecal_nir.npz +0 -0
  233. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/__init__.py +0 -0
  234. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/defaults/atlas/thar.fits +0 -0
  235. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/defaults/atlas/thar_list.txt +0 -0
  236. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/defaults/atlas/une.fits +0 -0
  237. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/filters.py +0 -0
  238. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/instruments/instrument_info.py +0 -0
  239. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/tools/__init__.py +0 -0
  240. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/tools/combine.py +0 -0
  241. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/pyreduce/wavelength_calibration.py +0 -0
  242. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/tools/argon.line +0 -0
  243. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/tools/bpm_creator.py +0 -0
  244. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/tools/convert_wavecal.py +0 -0
  245. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/tools/create_wavelength_guess.py +0 -0
  246. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/tools/download_files.py +0 -0
  247. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/tools/ipy_startup.py +0 -0
  248. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/tools/make_notebook.py +0 -0
  249. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/tools/neon.lin +0 -0
  250. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/tools/neon.line +0 -0
  251. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/tools/pymultispec.py +0 -0
  252. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/tools/thar.npz +0 -0
  253. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/tools/wavecal_creator.py +0 -0
  254. {pyreduce_astro-0.7b3 → pyreduce_astro-0.8a1}/tools/wavecal_creator_from_existing.py +0 -0
  255. {pyreduce_astro-0.7b3 → 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,75 @@
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
+
46
+ ## [0.7b4] - 2026-01-22
47
+
48
+ ### Added
49
+ - Per-channel settings support via `settings_{channel}.json` files
50
+ - Fiber grouping configuration for multi-fiber instruments (bundle_centers, fiber_groups)
51
+ - `preset_slitfunc` parameter for single-pass extraction using pre-computed slit function
52
+ - `noise_relative` parameter for trace threshold scaling
53
+ - `extraction_reject` threshold parameter for outlier rejection
54
+ - ANDES_YJH instrument with multi-channel support
55
+ - MOSAIC VIS quadrant support (VIS1-VIS4 channels) and NIR settings
56
+ - HARPN fiber B wavecal file
57
+ - Extraction residual panel in ProgressPlot
58
+ - `tools/plot_swath_debug.py` for analyzing extraction debug data
59
+
60
+ ### Changed
61
+ - **Mask convention**: Switch to numpy convention (True/1=bad) on Python side; C code uses inverted (1=good)
62
+ - Extraction convergence now based on spectrum change with global RMS for rejection
63
+ - Improved outlier rejection using 6*sigma instead of MAD in 2D extraction
64
+ - Norm_flat step saves slit function with metadata for reuse
65
+ - Refactor Pipeline trace API: add `trace_raw()` and `organize()` methods
66
+ - Remove `extraction_cutoff` parameter (dead code)
67
+
68
+ ### Fixed
69
+ - `smooth_spectrum` normalization (port from cr2res)
70
+ - Masked array handling in swath debug plotting
71
+ - Minimum 4 iterations enforced in curved extraction
72
+
4
73
  ## [0.7b3] - 2026-01-11
5
74
 
6
75
  ### 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,7 +31,8 @@ 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_orders.py # Order detection and tracing
34
+ ├── curvature_model.py # SlitCurvature dataclass for curvature data
35
+ ├── trace.py # Order detection and tracing
35
36
  ├── wavelength_calibration.py # Wavelength solution fitting
36
37
  ├── combine_frames.py # Frame combination/calibration
37
38
  ├── echelle.py # Echelle spectrum I/O
@@ -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 |
@@ -158,7 +159,7 @@ Defines HOW to reduce - algorithm parameters per step:
158
159
  "degree": 4,
159
160
  "noise": 100,
160
161
  "min_cluster": 500,
161
- "filter_size": 120
162
+ "filter_y": 120
162
163
  },
163
164
  "norm_flat": {
164
165
  "extraction_height": 0.5,
@@ -217,7 +218,7 @@ pipe = Pipeline(
217
218
  )
218
219
  pipe.bias(bias_files)
219
220
  pipe.flat(flat_files)
220
- pipe.trace_orders()
221
+ pipe.trace()
221
222
  pipe.extract(science_files)
222
223
  result = pipe.run()
223
224
  ```
@@ -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
@@ -260,15 +261,22 @@ uv run reduce list-steps
260
261
  - `PYREDUCE_PLOT` - Override plot level (0=off, 1=basic, 2=detailed)
261
262
  - `PYREDUCE_PLOT_DIR` - Save plots to directory as PNG files
262
263
  - `PYREDUCE_PLOT_SHOW` - Display mode: `block` (default), `defer`, or `off`
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)
263
267
 
264
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.
265
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
+
266
272
  ## Development
267
273
 
268
274
  ### Commands
269
275
 
270
276
  ```bash
271
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
272
280
  uv run reduce-build # Compile C extensions
273
281
  uv run reduce-clean # Remove compiled extensions
274
282
  uv run pre-commit install # Setup hooks (once)
@@ -302,8 +310,10 @@ After a fresh clone or `rm -rf .venv`, run `uv sync && uv run reduce-build` to s
302
310
  | `pyreduce/pipeline.py` | Fluent Pipeline API, `from_instrument()` |
303
311
  | `pyreduce/reduce.py` | Step class implementations |
304
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) |
305
315
  | `pyreduce/wavelength_calibration.py` | Wavelength solution fitting |
306
- | `pyreduce/trace_orders.py` | Order detection and tracing |
316
+ | `pyreduce/trace.py` | Order detection and tracing |
307
317
  | `pyreduce/instruments/common.py` | Base Instrument class |
308
318
  | `pyreduce/instruments/models.py` | Pydantic config models |
309
319
  | `pyreduce/clib/*.c` | C code for slit function decomposition |
@@ -325,17 +335,15 @@ To release a new version (e.g., `0.7a6`):
325
335
 
326
336
  3a. **sync** - run `uv sync` to get the new version into uv.lock
327
337
 
328
- 4. **Update example headers** - all `examples/*.py` have PEP 723 metadata:
329
- ```python
330
- # /// script
331
- # dependencies = ["pyreduce-astro>=0.7a6"]
332
- # ///
338
+ 4. **Run unit tests** to catch issues before release:
339
+ ```bash
340
+ uv run pytest -m unit
333
341
  ```
334
342
 
335
343
  5. **Commit, tag, and push**:
336
344
  ```bash
337
- git add -A && git commit -m "Release v0.7a6"
338
- git tag v0.7a6
345
+ git add -A && git commit -m "Release v0.8a1"
346
+ git tag v0.8a1
339
347
  git push && git push --tags
340
348
  ```
341
349
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyreduce-astro
3
- Version: 0.7b3
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())}")
@@ -0,0 +1,108 @@
1
+ """
2
+ ANDES_YJH instrument example: Multi-fiber tracing with Pipeline API.
3
+
4
+ Demonstrates tracing fibers illuminated in separate flat field images
5
+ (even/odd pattern) using the Pipeline's trace_raw() and organize() methods.
6
+
7
+ The fiber config in ANDES_YJH/config.yaml handles:
8
+ - order_centers_file: assigns traces to spectral orders by y-position (channel-specific)
9
+ - groups: organizes fibers into logical groups (A, cal, B) within each order
10
+ - merge: average - averages fiber traces within each group
11
+
12
+ ANDES_YJH has three channels: Y, J, H (selected by BAND header in files).
13
+ """
14
+
15
+ import os
16
+
17
+ import numpy as np
18
+
19
+ from pyreduce.configuration import load_config
20
+ from pyreduce.pipeline import Pipeline
21
+
22
+ # --- Configuration ---
23
+ instrument_name = "ANDES_YJH"
24
+ channel = "J" # Y, J, or H
25
+ data_dir = os.environ.get("REDUCE_DATA", os.path.expanduser("~/REDUCE_DATA"))
26
+ raw_dir = os.path.join(data_dir, "ANDES", channel)
27
+ output_dir = os.path.join(data_dir, "ANDES", "reduced", channel)
28
+
29
+ # Input files (even and odd illuminated flats)
30
+ # File selection is header-based:
31
+ # BAND header determines channel (Y, J, H)
32
+ # SIMTYPE='flat_field' → flat, SIMTYPE='spectrum' → science
33
+ # FIBMODE='even' → even flat, FIBMODE='odd' → odd flat
34
+ file_even = os.path.join(raw_dir, f"{channel}_FF_even_1s.fits")
35
+ file_odd = os.path.join(raw_dir, f"{channel}_FF_odd_1s.fits")
36
+
37
+ # Plot settings
38
+ plot = int(os.environ.get("PYREDUCE_PLOT", "1"))
39
+
40
+ # --- Create Pipeline ---
41
+ config = load_config(None, instrument_name)
42
+ pipe = Pipeline(
43
+ instrument=instrument_name,
44
+ channel=channel,
45
+ output_dir=output_dir,
46
+ target="ANDES_fiber_test",
47
+ config=config,
48
+ plot=plot,
49
+ )
50
+
51
+ print(f"Instrument: {pipe.instrument.name}")
52
+ fibers_config = pipe.instrument.config.fibers
53
+ print(f"Per-order grouping: {fibers_config.per_order}")
54
+ print(f"Groups: {list(fibers_config.groups.keys())}")
55
+
56
+ # --- Trace or load from previous run ---
57
+ LOAD_TRACE = True # Set True to load traces from previous run
58
+
59
+ if LOAD_TRACE:
60
+ print("\nLoading traces from previous run...")
61
+ traces, column_range, heights = pipe._run_step("trace", None, load_only=True)
62
+ print(f" Loaded {len(traces)} traces")
63
+
64
+ # Re-run organize with current config (picks up any config changes)
65
+ print("\nRe-organizing traces with current config...")
66
+ pipe.organize(traces, column_range)
67
+ else:
68
+ # Trace each flat independently
69
+ print(f"\nTracing even fibers from {os.path.basename(file_even)}...")
70
+ traces_even, cr_even, _ = pipe.trace_raw([file_even])
71
+ print(f" Found {len(traces_even)} traces")
72
+
73
+ print(f"\nTracing odd fibers from {os.path.basename(file_odd)}...")
74
+ traces_odd, cr_odd, _ = pipe.trace_raw([file_odd])
75
+ print(f" Found {len(traces_odd)} traces")
76
+
77
+ # Organize into fiber groups
78
+ print("\nOrganizing traces into fiber groups...")
79
+ pipe.organize(traces_even, cr_even, traces_odd, cr_odd)
80
+
81
+ # Access organized groups
82
+ if "trace_groups" in pipe._data and pipe._data["trace_groups"][0]:
83
+ group_traces, group_cr, group_heights = pipe._data["trace_groups"]
84
+ print("Fiber groups:")
85
+ for name, traces_dict in group_traces.items():
86
+ n_traces = len(traces_dict)
87
+ print(f" {name}: {n_traces} traces")
88
+
89
+ # --- Create combined flat for extraction ---
90
+ print("\nCombining even/odd flats...")
91
+ img_even, head = pipe.instrument.load_fits(file_even, channel=channel, extension=0)
92
+ img_odd, _ = pipe.instrument.load_fits(file_odd, channel=channel, extension=0)
93
+ img_combined = np.asarray(img_even, dtype=np.float64) + np.asarray(
94
+ img_odd, dtype=np.float64
95
+ )
96
+
97
+ # Save combined flat to file for the science step
98
+ from astropy.io import fits
99
+
100
+ combined_file = os.path.join(output_dir, "combined_flat.fits")
101
+ os.makedirs(output_dir, exist_ok=True)
102
+ fits.writeto(combined_file, img_combined.astype(np.float32), head, overwrite=True)
103
+ print(f" Saved combined flat: {combined_file}")
104
+
105
+ # --- Extract using the science step ---
106
+ print("\nExtracting spectra (group A from fiber config)...")
107
+ pipe.instrument.config.fibers.use["science"] = ["ring2"]
108
+ pipe.extract([combined_file]).run()
@@ -1,7 +1,3 @@
1
- # /// script
2
- # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b3"]
4
- # ///
5
1
  """
6
2
  Simple usage example for PyReduce
7
3
  Loads a CRIRES+ dataset, and runs the extraction
@@ -48,5 +44,5 @@ Pipeline.from_instrument(
48
44
  base_dir=base_dir,
49
45
  input_dir=input_dir,
50
46
  output_dir=output_dir,
51
- # order_range=(0, 4),
47
+ # trace_range=(0, 4),
52
48
  ).run()
@@ -1,7 +1,3 @@
1
- # /// script
2
- # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b3"]
4
- # ///
5
1
  """
6
2
  Simple usage example for PyReduce
7
3
  Loads a sample UVES dataset, and runs the full extraction
@@ -73,7 +69,7 @@ pipe = Pipeline.from_files(
73
69
  channel=channel,
74
70
  night=night,
75
71
  config=config,
76
- # order_range=order_range,
72
+ # trace_range=trace_range,
77
73
  steps=steps,
78
74
  plot=1,
79
75
  )