pyreduce-astro 0.7b2__tar.gz → 0.7b3__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 (192) hide show
  1. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/.gitignore +2 -0
  2. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/CHANGELOG.md +16 -0
  3. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/CLAUDE.md +5 -2
  4. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/PKG-INFO +15 -1
  5. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/README.md +14 -0
  6. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/examples/aj_example.py +1 -1
  7. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/examples/crires_plus_example.py +1 -1
  8. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/examples/custom_instrument_example.py +1 -1
  9. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/examples/harpn_example.py +1 -1
  10. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/examples/harps_example.py +1 -1
  11. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/examples/harps_gridsearch.py +1 -1
  12. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/examples/just_one_swath.py +1 -1
  13. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/examples/jwst_miri_example.py +1 -1
  14. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/examples/jwst_niriss_example.py +1 -1
  15. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/examples/lick_apf_example.py +1 -1
  16. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/examples/mcdonald_example.py +1 -1
  17. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/examples/metis_ifu_example.py +1 -1
  18. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/examples/metis_lss_example.py +1 -1
  19. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/examples/micado_example.py +10 -12
  20. pyreduce_astro-0.7b3/examples/mosaic_example.py +171 -0
  21. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/examples/neid_example.py +1 -1
  22. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/examples/nirspec_example.py +1 -1
  23. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/examples/toes_example.py +1 -1
  24. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/examples/uves_callfunc.py +18 -9
  25. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/examples/uves_example.py +1 -1
  26. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/examples/xshooter_example.py +5 -5
  27. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyproject.toml +7 -1
  28. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/__main__.py +19 -1
  29. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/combine_frames.py +3 -0
  30. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/continuum_normalization.py +2 -0
  31. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/cwrappers.py +4 -1
  32. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/estimate_background_scatter.py +1 -0
  33. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/extract.py +71 -23
  34. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/JWST_NIRISS/__init__.py +2 -2
  35. pyreduce_astro-0.7b3/pyreduce/instruments/MOSAIC/__init__.py +12 -0
  36. pyreduce_astro-0.7b3/pyreduce/instruments/MOSAIC/config.yaml +48 -0
  37. pyreduce_astro-0.7b3/pyreduce/instruments/MOSAIC/mosaic_fiber_positions.npz +0 -0
  38. pyreduce_astro-0.7b3/pyreduce/instruments/MOSAIC/settings.json +30 -0
  39. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/XSHOOTER/settings.json +6 -7
  40. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/common.py +41 -19
  41. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/defaults/settings.json +5 -5
  42. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/pipeline.py +8 -1
  43. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/rectify.py +9 -9
  44. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/reduce.py +69 -33
  45. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/slit_curve.py +22 -20
  46. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/tools/combine.py +1 -0
  47. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/trace.py +49 -43
  48. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/util.py +43 -5
  49. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/wavelength_calibration.py +2 -0
  50. pyreduce_astro-0.7b3/tools/make_notebook.py +47 -0
  51. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/uv.lock +413 -38
  52. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/.gitattributes +0 -0
  53. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/.pre-commit-config.yaml +0 -0
  54. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/.python-version +0 -0
  55. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/.readthedocs.yaml +0 -0
  56. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/AGENTS.md +0 -0
  57. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/ANDES_plan.md +0 -0
  58. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/LICENSE +0 -0
  59. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/hatch_build.py +0 -0
  60. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/__init__.py +0 -0
  61. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/cli.py +0 -0
  62. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/clib/__init__.py +0 -0
  63. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/clib/build_extract.py +0 -0
  64. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/clib/slit_func_2d_xi_zeta_bd.c +0 -0
  65. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/clib/slit_func_2d_xi_zeta_bd.h +0 -0
  66. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/clib/slit_func_bd.c +0 -0
  67. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/clib/slit_func_bd.h +0 -0
  68. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/clipnflip.py +0 -0
  69. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/configuration.py +0 -0
  70. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/datasets.py +0 -0
  71. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/echelle.py +0 -0
  72. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/extraction_height.py +0 -0
  73. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/AJ/__init__.py +0 -0
  74. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/AJ/config.yaml +0 -0
  75. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/AJ/settings.json +0 -0
  76. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/ANDES/__init__.py +0 -0
  77. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/ANDES/config.yaml +0 -0
  78. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/ANDES/settings.json +0 -0
  79. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/CRIRES_PLUS/__init__.py +0 -0
  80. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/CRIRES_PLUS/config.yaml +0 -0
  81. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/CRIRES_PLUS/mask_det1.fits.gz +0 -0
  82. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/CRIRES_PLUS/mask_det2.fits.gz +0 -0
  83. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/CRIRES_PLUS/mask_det3.fits.gz +0 -0
  84. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/CRIRES_PLUS/settings.json +0 -0
  85. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/CRIRES_PLUS/wavecal_J1228_det1.npz +0 -0
  86. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/CRIRES_PLUS/wavecal_J1228_det2.npz +0 -0
  87. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/CRIRES_PLUS/wavecal_J1228_det3.npz +0 -0
  88. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/HARPN/__init__.py +0 -0
  89. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/HARPN/config.yaml +0 -0
  90. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/HARPN/settings.json +0 -0
  91. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/HARPN/wavecal_harpn_2D.npz +0 -0
  92. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/HARPS/__init__.py +0 -0
  93. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/HARPS/config.yaml +0 -0
  94. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/HARPS/mask_blue.fits.gz +0 -0
  95. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/HARPS/mask_red.fits.gz +0 -0
  96. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/HARPS/settings.json +0 -0
  97. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/HARPS/wavecal_blue_2D.npz +0 -0
  98. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/HARPS/wavecal_blue_pol_2D.npz +0 -0
  99. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/HARPS/wavecal_red_2D.npz +0 -0
  100. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/HARPS/wavecal_red_pol_2D.npz +0 -0
  101. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/JWST_MIRI/__init__.py +0 -0
  102. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/JWST_MIRI/config.yaml +0 -0
  103. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/JWST_MIRI/mask_lrs_slitless.fits.gz +0 -0
  104. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/JWST_MIRI/settings.json +0 -0
  105. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/JWST_NIRISS/config.yaml +0 -0
  106. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/JWST_NIRISS/mask_gr700xd.fits.gz +0 -0
  107. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/JWST_NIRISS/settings.json +0 -0
  108. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/LICK_APF/__init__.py +0 -0
  109. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/LICK_APF/config.yaml +0 -0
  110. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/LICK_APF/mask_.fits.gz +0 -0
  111. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/LICK_APF/settings.json +0 -0
  112. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/MCDONALD/__init__.py +0 -0
  113. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/MCDONALD/config.yaml +0 -0
  114. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/MCDONALD/mask.fits.gz +0 -0
  115. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/MCDONALD/settings.json +0 -0
  116. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/MCDONALD/wavecal.npz +0 -0
  117. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/METIS_IFU/__init__.py +0 -0
  118. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/METIS_IFU/config.yaml +0 -0
  119. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/METIS_IFU/settings.json +0 -0
  120. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/METIS_LSS/__init__.py +0 -0
  121. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/METIS_LSS/config.yaml +0 -0
  122. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/METIS_LSS/settings.json +0 -0
  123. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/METIS_LSS/wavecal_l_2D.npz +0 -0
  124. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/METIS_LSS/wavecal_m_2D.npz +0 -0
  125. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/MICADO/__init__.py +0 -0
  126. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/MICADO/config.yaml +0 -0
  127. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/MICADO/settings.json +0 -0
  128. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/MICADO/wavecal_HK_3arcsec_chip5.npz +0 -0
  129. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/NEID/__init__.py +0 -0
  130. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/NEID/config.yaml +0 -0
  131. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/NEID/settings.json +0 -0
  132. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/NIRSPEC/__init__.py +0 -0
  133. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/NIRSPEC/config.yaml +0 -0
  134. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/NIRSPEC/mask_nirspec.fits.gz +0 -0
  135. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/NIRSPEC/settings.json +0 -0
  136. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/NIRSPEC/wavecal_K2.npz +0 -0
  137. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/NTE/__init__.py +0 -0
  138. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/NTE/config.yaml +0 -0
  139. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/NTE/settings.json +0 -0
  140. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/__init__.py +0 -0
  141. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/config.yaml +0 -0
  142. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/mask_blue.fits.gz +0 -0
  143. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/mask_blue_binned_2_2.fits.gz +0 -0
  144. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/mask_middle.fits.gz +0 -0
  145. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/mask_middle_2x2_split.fits.gz +0 -0
  146. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/mask_middle_binned_2_2.fits.gz +0 -0
  147. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/mask_red.fits.gz +0 -0
  148. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/mask_red_2x2.fits.gz +0 -0
  149. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/mask_red_2x2_split.fits.gz +0 -0
  150. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/mask_red_binned_2_2.fits.gz +0 -0
  151. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/settings.json +0 -0
  152. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/wavecal_blue_360nm_2D.npz +0 -0
  153. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/wavecal_blue_390nm_2D.npz +0 -0
  154. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/wavecal_blue_437nm_2D.npz +0 -0
  155. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/wavecal_middle_2x2_2D.npz +0 -0
  156. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/wavecal_middle_565nm_2D.npz +0 -0
  157. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/wavecal_middle_580nm_2D.npz +0 -0
  158. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/wavecal_middle_600nm_2D.npz +0 -0
  159. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/wavecal_middle_665nm_2D.npz +0 -0
  160. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/wavecal_middle_860nm_2D.npz +0 -0
  161. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/wavecal_red_580nm_2D.npz +0 -0
  162. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/wavecal_red_600nm_2D.npz +0 -0
  163. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/wavecal_red_665nm_2D.npz +0 -0
  164. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/wavecal_red_760nm_2D.npz +0 -0
  165. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/UVES/wavecal_red_860nm_2D.npz +0 -0
  166. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/XSHOOTER/__init__.py +0 -0
  167. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/XSHOOTER/config.yaml +0 -0
  168. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/XSHOOTER/mask_nir.fits.gz +0 -0
  169. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/XSHOOTER/wavecal_nir.npz +0 -0
  170. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/__init__.py +0 -0
  171. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/defaults/atlas/thar.fits +0 -0
  172. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/defaults/atlas/thar_list.txt +0 -0
  173. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/defaults/atlas/une.fits +0 -0
  174. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/defaults/config.yaml +0 -0
  175. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/defaults/schema.json +0 -0
  176. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/filters.py +0 -0
  177. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/instrument_info.py +0 -0
  178. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/instruments/models.py +0 -0
  179. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/pyreduce/tools/__init__.py +0 -0
  180. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/tools/argon.line +0 -0
  181. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/tools/bpm_creator.py +0 -0
  182. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/tools/convert_wavecal.py +0 -0
  183. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/tools/create_wavelength_guess.py +0 -0
  184. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/tools/download_files.py +0 -0
  185. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/tools/ipy_startup.py +0 -0
  186. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/tools/neon.lin +0 -0
  187. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/tools/neon.line +0 -0
  188. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/tools/pymultispec.py +0 -0
  189. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/tools/thar.npz +0 -0
  190. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/tools/wavecal_creator.py +0 -0
  191. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/tools/wavecal_creator_from_existing.py +0 -0
  192. {pyreduce_astro-0.7b2 → pyreduce_astro-0.7b3}/tools/xshooter_nir.json +0 -0
@@ -21,3 +21,5 @@ docs/_build/
21
21
  debug/
22
22
  idl/
23
23
  logs/
24
+ *.ipynb
25
+ tmp/*
@@ -1,6 +1,22 @@
1
1
  # Changelog
2
2
 
3
3
 
4
+ ## [0.7b3] - 2026-01-11
5
+
6
+ ### Added
7
+ - MOSAIC instrument support with fiber group detection and curvature step
8
+ - Extraction animation controls: pause/step buttons and speed control (`PYREDUCE_PLOT_ANIMATION_SPEED`)
9
+ - `--plot-dir` and `--plot-show` CLI options for flexible plot output
10
+
11
+ ### Changed
12
+ - Rename `orders` to `traces` in rectify and slit_curve modules for consistency
13
+ - Downgrade extraction max-iterations message from ERROR to WARNING
14
+ - Only warn about missing files for steps that are actually requested
15
+
16
+ ### Fixed
17
+ - Handle channel mismatch gracefully in CLI
18
+ - Curvature plotting index error when peaks need int casting
19
+
4
20
  ## [0.7b2] - 2026-01-09
5
21
 
6
22
  ### Changed
@@ -257,8 +257,11 @@ uv run reduce list-steps
257
257
  ## Environment Variables
258
258
 
259
259
  - `REDUCE_DATA` - Base data directory (default: `~/REDUCE_DATA`)
260
- - `PYREDUCE_PLOT` - Override plot level (0, 1, 2)
261
- - `PYREDUCE_PLOT_DIR` - Save plots to directory instead of displaying
260
+ - `PYREDUCE_PLOT` - Override plot level (0=off, 1=basic, 2=detailed)
261
+ - `PYREDUCE_PLOT_DIR` - Save plots to directory as PNG files
262
+ - `PYREDUCE_PLOT_SHOW` - Display mode: `block` (default), `defer`, or `off`
263
+
264
+ Plot modes: `block` shows each plot interactively; `defer` accumulates all plots and shows at end (useful with webagg backend); `off` disables display. Save and display are independent.
262
265
 
263
266
  ## Development
264
267
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyreduce-astro
3
- Version: 0.7b2
3
+ Version: 0.7b3
4
4
  Summary: A data reduction package for echelle spectrographs
5
5
  Project-URL: Homepage, https://github.com/ivh/PyReduce
6
6
  Project-URL: Documentation, https://pyreduce-astro.readthedocs.io
@@ -94,6 +94,20 @@ Pipeline.from_instrument(
94
94
  ).run()
95
95
  ```
96
96
 
97
+ ## Plotting
98
+
99
+ Control plotting with environment variables:
100
+
101
+ ```bash
102
+ # Save plots to files (headless/CI)
103
+ PYREDUCE_PLOT=1 PYREDUCE_PLOT_DIR=/tmp/plots PYREDUCE_PLOT_SHOW=off uv run reduce run ...
104
+
105
+ # Show all plots at end (browser via webagg)
106
+ MPLBACKEND=webagg PYREDUCE_PLOT=1 PYREDUCE_PLOT_SHOW=defer uv run reduce run ...
107
+ ```
108
+
109
+ See [How To](https://pyreduce-astro.readthedocs.io/en/latest/howto.html#plot-modes) for details.
110
+
97
111
  ## Documentation
98
112
 
99
113
  Full documentation at [ReadTheDocs](https://pyreduce-astro.readthedocs.io/).
@@ -53,6 +53,20 @@ Pipeline.from_instrument(
53
53
  ).run()
54
54
  ```
55
55
 
56
+ ## Plotting
57
+
58
+ Control plotting with environment variables:
59
+
60
+ ```bash
61
+ # Save plots to files (headless/CI)
62
+ PYREDUCE_PLOT=1 PYREDUCE_PLOT_DIR=/tmp/plots PYREDUCE_PLOT_SHOW=off uv run reduce run ...
63
+
64
+ # Show all plots at end (browser via webagg)
65
+ MPLBACKEND=webagg PYREDUCE_PLOT=1 PYREDUCE_PLOT_SHOW=defer uv run reduce run ...
66
+ ```
67
+
68
+ See [How To](https://pyreduce-astro.readthedocs.io/en/latest/howto.html#plot-modes) for details.
69
+
56
70
  ## Documentation
57
71
 
58
72
  Full documentation at [ReadTheDocs](https://pyreduce-astro.readthedocs.io/).
@@ -1,6 +1,6 @@
1
1
  # /// script
2
2
  # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b2"]
3
+ # dependencies = ["pyreduce-astro>=0.7b3"]
4
4
  # ///
5
5
  """
6
6
  AJ instrument example: Fiber bundle tracing with direct function calls.
@@ -1,6 +1,6 @@
1
1
  # /// script
2
2
  # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b2"]
3
+ # dependencies = ["pyreduce-astro>=0.7b3"]
4
4
  # ///
5
5
  """
6
6
  Simple usage example for PyReduce
@@ -1,6 +1,6 @@
1
1
  # /// script
2
2
  # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b2"]
3
+ # dependencies = ["pyreduce-astro>=0.7b3"]
4
4
  # ///
5
5
  """
6
6
  Simple usage example for PyReduce
@@ -1,6 +1,6 @@
1
1
  # /// script
2
2
  # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b2"]
3
+ # dependencies = ["pyreduce-astro>=0.7b3"]
4
4
  # ///
5
5
  """
6
6
  Simple usage example for PyReduce
@@ -1,6 +1,6 @@
1
1
  # /// script
2
2
  # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b2"]
3
+ # dependencies = ["pyreduce-astro>=0.7b3"]
4
4
  # ///
5
5
  """
6
6
  Simple usage example for PyReduce
@@ -1,6 +1,6 @@
1
1
  # /// script
2
2
  # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b2"]
3
+ # dependencies = ["pyreduce-astro>=0.7b3"]
4
4
  # ///
5
5
  import os.path
6
6
 
@@ -1,6 +1,6 @@
1
1
  # /// script
2
2
  # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b2"]
3
+ # dependencies = ["pyreduce-astro>=0.7b3"]
4
4
  # ///
5
5
  import matplotlib.pyplot as plt
6
6
  import numpy as np
@@ -1,6 +1,6 @@
1
1
  # /// script
2
2
  # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b2"]
3
+ # dependencies = ["pyreduce-astro>=0.7b3"]
4
4
  # ///
5
5
  """
6
6
  Simple usage example for PyReduce
@@ -1,6 +1,6 @@
1
1
  # /// script
2
2
  # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b2"]
3
+ # dependencies = ["pyreduce-astro>=0.7b3"]
4
4
  # ///
5
5
  """
6
6
  Simple usage example for PyReduce
@@ -1,6 +1,6 @@
1
1
  # /// script
2
2
  # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b2"]
3
+ # dependencies = ["pyreduce-astro>=0.7b3"]
4
4
  # ///
5
5
  """
6
6
  Simple usage example for PyReduce
@@ -1,6 +1,6 @@
1
1
  # /// script
2
2
  # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b2"]
3
+ # dependencies = ["pyreduce-astro>=0.7b3"]
4
4
  # ///
5
5
  """
6
6
  Simple usage example for PyReduce
@@ -1,6 +1,6 @@
1
1
  # /// script
2
2
  # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b2"]
3
+ # dependencies = ["pyreduce-astro>=0.7b3"]
4
4
  # ///
5
5
  """
6
6
  Simple usage example for PyReduce
@@ -1,6 +1,6 @@
1
1
  # /// script
2
2
  # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b2"]
3
+ # dependencies = ["pyreduce-astro>=0.7b3"]
4
4
  # ///
5
5
  """
6
6
  Simple usage example for PyReduce
@@ -1,13 +1,14 @@
1
1
  # /// script
2
2
  # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b2"]
3
+ # dependencies = ["pyreduce-astro>=0.7b3"]
4
4
  # ///
5
5
  """
6
6
  Simple usage example for PyReduce
7
7
  Loads a ScopeSim simulated MICADO dataset (with updated spectral layout and updated line lists), and runs the full extraction.
8
8
  """
9
9
 
10
- import pyreduce
10
+ from pyreduce.configuration import get_configuration_for_instrument
11
+ from pyreduce.pipeline import Pipeline
11
12
 
12
13
  # define parameters
13
14
  instrument = "MICADO"
@@ -40,7 +41,7 @@ base_dir = "/media/data/Dropbox/Dropbox/WORKING/iMICADO/Working/WORKING_PyReduce
40
41
  input_dir = "raw_new/HK/"
41
42
  output_dir = "reduced_new/"
42
43
 
43
- config = pyreduce.configuration.get_configuration_for_instrument(instrument)
44
+ config = get_configuration_for_instrument(instrument)
44
45
 
45
46
 
46
47
  # Configuring parameters of individual steps here overwrites those defined in the settings_MICADO.json file.
@@ -56,19 +57,16 @@ config = pyreduce.configuration.get_configuration_for_instrument(instrument)
56
57
 
57
58
  # NOTE: micado.thar_master.fits (created and controlled by wavecal_master) is NOT overwritten if any parameter in the steps in or before it are changed. Thus it has to be deleted before running PyReduce again.
58
59
 
59
- pyreduce.reduce.main(
60
+ Pipeline.from_instrument(
60
61
  instrument,
61
62
  target,
62
- night,
63
- channel,
64
- steps,
63
+ night=night,
64
+ channel=channel,
65
+ steps=steps,
65
66
  base_dir=base_dir,
66
67
  input_dir=input_dir,
67
68
  output_dir=output_dir,
68
69
  configuration=config,
69
- order_range=(
70
- 3,
71
- 4,
72
- ), # for MICADO, when one order is on the detector (currently detector 5 of the HK band)
70
+ order_range=(3, 4),
73
71
  plot=1,
74
- )
72
+ ).run()
@@ -0,0 +1,171 @@
1
+ # /// script
2
+ # requires-python = ">=3.13"
3
+ # dependencies = ["pyreduce-astro>=0.7b3"]
4
+ # ///
5
+ """
6
+ MOSAIC NIR spectrograph example.
7
+
8
+ Demonstrates fiber bundle tracing and extraction on simulated E2E data.
9
+ After tracing all fibers, identifies the central fiber in each group of 7
10
+ and extracts only those 90 traces.
11
+ """
12
+
13
+ import os
14
+ from os.path import join
15
+
16
+ import numpy as np
17
+
18
+ from pyreduce import util
19
+ from pyreduce.configuration import load_config
20
+ from pyreduce.instruments.instrument_info import load_instrument
21
+ from pyreduce.reduce import (
22
+ OrderTracing,
23
+ ScienceExtraction,
24
+ SlitCurvatureDetermination,
25
+ )
26
+
27
+ # Parameters
28
+ instrument_name = "MOSAIC"
29
+ target = "MOSAIC_NIR"
30
+ night = ""
31
+ channel = "NIR"
32
+ order_range = None
33
+ plot = 1
34
+
35
+ # Handle plot environment variables
36
+ if "PYREDUCE_PLOT" in os.environ:
37
+ plot = int(os.environ["PYREDUCE_PLOT"])
38
+ plot_dir = os.environ.get("PYREDUCE_PLOT_DIR")
39
+ util.set_plot_dir(plot_dir)
40
+
41
+ # Data location
42
+ data_dir = os.environ.get("REDUCE_DATA", os.path.expanduser("~/REDUCE_DATA"))
43
+ base_dir = join(data_dir, "MOSAIC", "REF_E2E", "NIR")
44
+ output_dir = join(data_dir, "MOSAIC", "reduced", "NIR")
45
+
46
+ os.makedirs(output_dir, exist_ok=True)
47
+
48
+ # File paths (simulated data)
49
+ flat_file = join(
50
+ base_dir,
51
+ "E2E_FLAT_DIT_20s_MOSAIC_2Cam_c01",
52
+ "E2E_FLAT_DIT_20s_MOSAIC_2Cam_c01_STATIC_FOCAL_PLANE.fits",
53
+ )
54
+ thar_file = join(
55
+ base_dir,
56
+ "E2E_ThAr_DIT_20s_MOSAIC_2Cam_c01",
57
+ "E2E_ThAr_DIT_20s_MOSAIC_2Cam_c01_STATIC_FOCAL_PLANE.fits",
58
+ )
59
+
60
+ # Verify files exist
61
+ for fpath in [flat_file, thar_file]:
62
+ if not os.path.exists(fpath):
63
+ raise FileNotFoundError(f"Data file not found: {fpath}")
64
+
65
+ print(f"FLAT: {flat_file}")
66
+ print(f"ThAr: {thar_file}")
67
+
68
+ # Load instrument and configuration
69
+ instrument = load_instrument(instrument_name)
70
+ config = load_config(None, instrument_name, 0)
71
+
72
+ # Common step arguments
73
+ step_args = (instrument, channel, target, night, output_dir, order_range)
74
+
75
+
76
+ def step_config(name):
77
+ """Get step config with plot level override."""
78
+ cfg = config.get(name, {}).copy()
79
+ cfg["plot"] = plot
80
+ return cfg
81
+
82
+
83
+ print("\n=== TRACE ===")
84
+ trace_step = OrderTracing(*step_args, **step_config("trace"))
85
+ # traces, column_range = trace_step.run([flat_file])
86
+ traces, column_range = trace_step.load()
87
+ print(f"Found {len(traces)} traces (expected ~630)")
88
+
89
+ # --- STEP 3: Identify group centers from gap pattern ---
90
+ print("\n=== IDENTIFY GROUP CENTERS ===")
91
+
92
+ # Evaluate all traces at detector center (x=2048)
93
+ x_center = 2048
94
+ traced_y = np.array([np.polyval(o, x_center) for o in traces])
95
+ print(f"Traced y-positions at x={x_center}: {traced_y[0]:.1f} to {traced_y[-1]:.1f}")
96
+
97
+ # Sort traces by y position
98
+ sort_idx = np.argsort(traced_y)
99
+ sorted_y = traced_y[sort_idx]
100
+
101
+ # Compute gaps between consecutive traces
102
+ gaps = np.diff(sorted_y)
103
+
104
+ # Inter-group gaps are ~2x larger than intra-group gaps.
105
+ # Use median gap as the intra-group spacing estimate (robust to outliers).
106
+ median_gap = np.median(gaps)
107
+ threshold = 1.5 * median_gap # Between 1x (intra) and 2x (inter)
108
+ print(f"Median gap: {median_gap:.2f} px, threshold: {threshold:.2f} px")
109
+
110
+ # Find group boundaries (where gap exceeds threshold)
111
+ is_group_boundary = gaps > threshold
112
+
113
+ # Assign group IDs: increment at each boundary
114
+ group_ids = np.zeros(len(sorted_y), dtype=int)
115
+ group_ids[1:] = np.cumsum(is_group_boundary)
116
+
117
+ n_groups = group_ids.max() + 1
118
+ print(f"Identified {n_groups} groups")
119
+
120
+ # For each group, find the center trace (middle element)
121
+ center_trace_indices = []
122
+ group_sizes = []
123
+
124
+ for g in range(n_groups):
125
+ group_mask = group_ids == g
126
+ group_orig_indices = sort_idx[group_mask]
127
+ group_y_values = traced_y[group_orig_indices]
128
+
129
+ # Sort by y within group to find center
130
+ within_sort = np.argsort(group_y_values)
131
+ center_idx = len(within_sort) // 2 # Middle element
132
+ center_trace_indices.append(group_orig_indices[within_sort[center_idx]])
133
+ group_sizes.append(len(group_orig_indices))
134
+
135
+ center_trace_indices = np.array(center_trace_indices)
136
+ group_sizes = np.array(group_sizes)
137
+
138
+ # Report group size distribution
139
+ size_counts = {sz: (group_sizes == sz).sum() for sz in sorted(set(group_sizes))}
140
+ print(f"Group sizes: {size_counts}")
141
+
142
+ # Extract only the center traces
143
+ center_traces = traces[center_trace_indices]
144
+ center_column_range = column_range[center_trace_indices]
145
+ print(f"\nUsing {len(center_traces)} group center traces for extraction")
146
+
147
+ center_trace = (center_traces, center_column_range)
148
+
149
+ print("\n=== CURVATURE ===")
150
+ curve_step = SlitCurvatureDetermination(*step_args, **step_config("curvature"))
151
+ # curvature = curve_step.run([thar_file], center_trace)
152
+ curvature = curve_step.load()
153
+ print("Curvature determination complete")
154
+
155
+ science_step = ScienceExtraction(*step_args, **step_config("science"))
156
+
157
+ print("\n=== EXTRACT ThAr ===")
158
+ try:
159
+ thar_spec = science_step.run([thar_file], center_trace, curvature=curvature)
160
+ print("ThAr extraction complete")
161
+ except Exception as e:
162
+ print(f"ThAr extraction failed: {e}")
163
+ thar_spec = None
164
+
165
+ print("\n=== EXTRACT FLAT ===")
166
+ try:
167
+ flat_spec = science_step.run([flat_file], center_trace, curvature=curvature)
168
+ print("FLAT extraction complete")
169
+ except Exception as e:
170
+ print(f"FLAT extraction failed: {e}")
171
+ flat_spec = None
@@ -1,6 +1,6 @@
1
1
  # /// script
2
2
  # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b2"]
3
+ # dependencies = ["pyreduce-astro>=0.7b3"]
4
4
  # ///
5
5
  """
6
6
  NEID reduction example
@@ -1,6 +1,6 @@
1
1
  # /// script
2
2
  # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b2"]
3
+ # dependencies = ["pyreduce-astro>=0.7b3"]
4
4
  # ///
5
5
  """
6
6
  Simple usage example for PyReduce
@@ -1,6 +1,6 @@
1
1
  # /// script
2
2
  # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b2"]
3
+ # dependencies = ["pyreduce-astro>=0.7b3"]
4
4
  # ///
5
5
  import numpy as np
6
6
 
@@ -1,6 +1,6 @@
1
1
  # /// script
2
2
  # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b2"]
3
+ # dependencies = ["pyreduce-astro>=0.7b3"]
4
4
  # ///
5
5
  """
6
6
  Example showing direct function calls for each step.
@@ -111,28 +111,27 @@ mask = mask_step.run()
111
111
  # Step 2: Bias
112
112
  print("\n=== BIAS ===")
113
113
  bias_step = Bias(*step_args, **step_config("bias"))
114
- bias = bias_step.run(bias_files, mask)
114
+ bias = bias_step.run(bias_files, mask=mask)
115
115
 
116
116
  # Step 3: Flat
117
117
  print("\n=== FLAT ===")
118
118
  flat_step = Flat(*step_args, **step_config("flat"))
119
- flat = flat_step.run(flat_files, bias, mask)
119
+ flat = flat_step.run(flat_files, bias=bias, mask=mask)
120
120
 
121
121
  # Step 4: Order tracing
122
122
  print("\n=== TRACE ===")
123
123
  orders_step = OrderTracing(*step_args, **step_config("trace"))
124
- orders = orders_step.run(order_files, mask, bias)
124
+ orders = orders_step.run(order_files, mask=mask, bias=bias)
125
125
 
126
126
  # Step 5: Curvature
127
127
  print("\n=== CURVATURE ===")
128
128
  curvature_step = SlitCurvatureDetermination(*step_args, **step_config("curvature"))
129
- curvature = curvature_step.run(curvature_files, orders, mask, bias)
129
+ curvature = curvature_step.run(curvature_files, orders, mask=mask, bias=bias)
130
130
 
131
131
  # Step 6: Normalize flat
132
132
  print("\n=== NORM_FLAT ===")
133
133
  norm_flat_step = NormalizeFlatField(*step_args, **step_config("norm_flat"))
134
- scatter = None # Optional background scatter
135
- norm_flat = norm_flat_step.run(flat, orders, scatter, curvature)
134
+ norm_flat = norm_flat_step.run(flat, orders)
136
135
 
137
136
  # Step 7: Wavelength calibration (three sub-steps)
138
137
  print("\n=== WAVECAL ===")
@@ -140,7 +139,12 @@ wavecal_master_step = WavelengthCalibrationMaster(
140
139
  *step_args, **step_config("wavecal_master")
141
140
  )
142
141
  wavecal_master = wavecal_master_step.run(
143
- wavecal_files, orders, mask, curvature, bias, norm_flat
142
+ wavecal_files,
143
+ orders,
144
+ mask=mask,
145
+ curvature=curvature,
146
+ bias=bias,
147
+ norm_flat=norm_flat,
144
148
  )
145
149
 
146
150
  # wavecal_init: load existing linelist (from instrument defaults or previous run)
@@ -158,7 +162,12 @@ wave, coef, linelist = wavecal
158
162
  print("\n=== SCIENCE ===")
159
163
  science_step = ScienceExtraction(*step_args, **step_config("science"))
160
164
  science = science_step.run(
161
- science_files, bias, orders, norm_flat, curvature, scatter, mask
165
+ science_files,
166
+ orders,
167
+ bias=bias,
168
+ norm_flat=norm_flat,
169
+ curvature=curvature,
170
+ mask=mask,
162
171
  )
163
172
 
164
173
  # Step 9: Continuum normalization
@@ -1,6 +1,6 @@
1
1
  # /// script
2
2
  # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b2"]
3
+ # dependencies = ["pyreduce-astro>=0.7b3"]
4
4
  # ///
5
5
  """
6
6
  Simple usage example for PyReduce
@@ -1,6 +1,6 @@
1
1
  # /// script
2
2
  # requires-python = ">=3.13"
3
- # dependencies = ["pyreduce-astro>=0.7b2"]
3
+ # dependencies = ["pyreduce-astro>=0.7b3"]
4
4
  # ///
5
5
  """
6
6
  Simple usage example for PyReduce
@@ -19,10 +19,10 @@ channel = "NIR"
19
19
  steps = (
20
20
  # "bias",
21
21
  # "flat",
22
- # "trace",
23
- # "scatter",
24
- # "norm_flat",
25
- # "curvature",
22
+ "trace",
23
+ "scatter",
24
+ "norm_flat",
25
+ "curvature",
26
26
  "wavecal",
27
27
  "science",
28
28
  # "continuum",
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pyreduce-astro"
3
- version = "0.7b2"
3
+ version = "0.7b3"
4
4
  requires-python = ">=3.13"
5
5
  description = "A data reduction package for echelle spectrographs"
6
6
  readme = "README.md"
@@ -56,6 +56,12 @@ dev = [
56
56
  "myst-parser",
57
57
  "setuptools",
58
58
  ]
59
+ ipynb = [
60
+ "ipykernel>=7.1.0",
61
+ "jupyter-client>=8.8.0",
62
+ "jupytext>=1.18.1",
63
+ "nbconvert>=7.16.6",
64
+ ]
59
65
 
60
66
  [project.urls]
61
67
  Homepage = "https://github.com/ivh/PyReduce"
@@ -59,8 +59,17 @@ def cli():
59
59
  @click.option(
60
60
  "--output-dir", "-o", default="reduced", help="Output directory relative to base"
61
61
  )
62
+ @click.option("--plot", "-p", default=0, help="Plot level: 0=none, 1=basic, 2=detailed")
62
63
  @click.option(
63
- "--plot", "-p", default=0, help="Plot level (0=none, 1=save, 2=interactive)"
64
+ "--plot-dir",
65
+ default=None,
66
+ help="Save plots to this directory as PNG files",
67
+ )
68
+ @click.option(
69
+ "--plot-show",
70
+ type=click.Choice(["block", "defer", "off"]),
71
+ default=None,
72
+ help="Display mode: block (interactive), defer (show all at end), off",
64
73
  )
65
74
  @click.option(
66
75
  "--order-range",
@@ -83,6 +92,8 @@ def run(
83
92
  input_dir,
84
93
  output_dir,
85
94
  plot,
95
+ plot_dir,
96
+ plot_show,
86
97
  order_range,
87
98
  settings,
88
99
  ):
@@ -90,9 +101,15 @@ def run(
90
101
 
91
102
  INSTRUMENT: Name of the instrument (e.g., UVES, HARPS, XSHOOTER)
92
103
  """
104
+ import os
105
+
93
106
  from .configuration import get_configuration_for_instrument, load_settings_override
94
107
  from .reduce import main as reduce_main
95
108
 
109
+ # CLI args override env vars for plot settings
110
+ if plot_show is not None:
111
+ os.environ["PYREDUCE_PLOT_SHOW"] = plot_show
112
+
96
113
  # Parse steps
97
114
  if steps:
98
115
  steps = tuple(s.strip() for s in steps.split(","))
@@ -123,6 +140,7 @@ def run(
123
140
  configuration=config,
124
141
  order_range=order_range,
125
142
  plot=plot,
143
+ plot_dir=plot_dir,
126
144
  )
127
145
  except FileNotFoundError as e:
128
146
  raise click.ClickException(str(e)) from None
@@ -630,6 +630,7 @@ def combine_calibrate(
630
630
  )
631
631
 
632
632
  if plot: # pragma: no cover
633
+ plt.figure()
633
634
  title = "Master"
634
635
  if plot_title is not None:
635
636
  title = f"{plot_title}\n{title}"
@@ -695,6 +696,7 @@ def combine_polynomial(
695
696
  bhead["EXPTIME"] = np.sum(exptimes)
696
697
 
697
698
  if plot:
699
+ plt.figure()
698
700
  title = "Master"
699
701
  if plot_title is not None:
700
702
  title = f"{plot_title}\n{title}"
@@ -844,6 +846,7 @@ def combine_bias(
844
846
  nbad = 0
845
847
 
846
848
  if plot: # pragma: no cover
849
+ plt.figure()
847
850
  title = "Master Bias"
848
851
  if plot_title is not None:
849
852
  title = f"{plot_title}\n{title}"