spectro-kernel 0.8.0__tar.gz → 0.8.1__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 (379) hide show
  1. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/CHANGELOG.md +30 -0
  2. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/PKG-INFO +2 -1
  3. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/pyproject.toml +1 -0
  4. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/reduction/easyspec_subtract_bias.py +6 -1
  5. spectro_kernel-0.8.1/src/spectro_kernel/algorithms/reduction/subtract_bias.py +122 -0
  6. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/version.py +1 -1
  7. spectro_kernel-0.8.1/tests/unit/test_subtract_bias.py +172 -0
  8. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/.gitignore +0 -0
  9. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/AGENTS.md +0 -0
  10. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/LICENSE +0 -0
  11. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/README.md +0 -0
  12. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/.drafts/README.md +0 -0
  13. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/.drafts/notebooks/aurora-line-monitor.md +0 -0
  14. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/concepts/algorithms.md +0 -0
  15. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/concepts/architecture.md +0 -0
  16. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/concepts/data-types.md +0 -0
  17. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/concepts/pipelines.md +0 -0
  18. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/contributing.md +0 -0
  19. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/cookbook/multi-star-viewer.md +0 -0
  20. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/cookbook/web-playground.md +0 -0
  21. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/getting-started.md +0 -0
  22. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/images/notebooks/alpha_cyg_ew_timeseries.png +0 -0
  23. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/images/notebooks/alpha_cyg_halpha_phase_stack.png +0 -0
  24. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/images/notebooks/alpha_cyg_halpha_timeseries.png +0 -0
  25. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/images/notebooks/alpha_cyg_overlay.png +0 -0
  26. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/images/notebooks/alpha_cyg_pc1_vs_phase.png +0 -0
  27. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/images/notebooks/alpha_cyg_pca_2d.png +0 -0
  28. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/images/notebooks/alpha_cyg_pca_3d.png +0 -0
  29. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/images/notebooks/alpha_cyg_periodogram.png +0 -0
  30. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/images/notebooks/alpha_cyg_phase_folded.png +0 -0
  31. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/images/notebooks/alpha_cyg_rv_timeseries.png +0 -0
  32. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/images/notebooks/alpha_cyg_similarity.png +0 -0
  33. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/images/notebooks/alpha_cyg_similarity_date.png +0 -0
  34. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/images/notebooks/alpha_dra_halpha_phase_stack.png +0 -0
  35. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/images/notebooks/alpha_dra_pc1_vs_phase.png +0 -0
  36. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/images/notebooks/alpha_dra_pca_2d.png +0 -0
  37. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/images/notebooks/alpha_dra_pca_3d.png +0 -0
  38. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/images/notebooks/alpha_dra_periodogram.png +0 -0
  39. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/images/notebooks/alpha_dra_phase_folded.png +0 -0
  40. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/images/notebooks/alpha_dra_rv_timeseries.png +0 -0
  41. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/images/notebooks/alpha_dra_similarity_date.png +0 -0
  42. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/images/notebooks/alpha_dra_similarity_phase.png +0 -0
  43. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/index.md +0 -0
  44. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/notebooks/alpha-cyg-time-series.md +0 -0
  45. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/notebooks/alpha-dra-binary-period.md +0 -0
  46. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/notebooks/be-star-variability.md +0 -0
  47. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/notebooks/claude-mcp-end-to-end.md +0 -0
  48. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/notebooks/exoplanet-transit-rv.md +0 -0
  49. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/notebooks/full-reduction-walkthrough.md +0 -0
  50. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/notebooks/native-vs-easyspec-showdown.md +0 -0
  51. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/notebooks/your-first-sb2.md +0 -0
  52. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/recipes/format.md +0 -0
  53. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/recipes/index.md +0 -0
  54. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/recipes/share.md +0 -0
  55. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/reference/python.md +0 -0
  56. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/tutorials/add-an-algorithm.md +0 -0
  57. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/tutorials/analyse-a-spectrum.md +0 -0
  58. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/tutorials/discover-the-catalogue.md +0 -0
  59. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/tutorials/first-spectrum.md +0 -0
  60. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/tutorials/long-slit-reduction.md +0 -0
  61. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/usage/cli.md +0 -0
  62. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/usage/library.md +0 -0
  63. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/usage/mcp.md +0 -0
  64. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/validation/.nav.md +0 -0
  65. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/validation/index.md +0 -0
  66. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/docs/why.md +0 -0
  67. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/examples/mcp_client.py +0 -0
  68. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/examples/quickstart.py +0 -0
  69. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/examples/recipe_with_profile.py +0 -0
  70. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/examples/wavelength_calibration.py +0 -0
  71. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/__init__.py +0 -0
  72. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/adapters/__init__.py +0 -0
  73. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/adapters/easyspec.py +0 -0
  74. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/__init__.py +0 -0
  75. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/_common.py +0 -0
  76. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/activity/__init__.py +0 -0
  77. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/activity/_bands.py +0 -0
  78. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/activity/activity_index_caii_hk.py +0 -0
  79. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/activity/activity_index_halpha.py +0 -0
  80. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/activity/ccf_bisector.py +0 -0
  81. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/advanced/__init__.py +0 -0
  82. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/advanced/aperture_photometry.py +0 -0
  83. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/advanced/disentangle_sb2.py +0 -0
  84. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/advanced/doppler_tomogram.py +0 -0
  85. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/catalogs/__init__.py +0 -0
  86. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/catalogs/gaia.py +0 -0
  87. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/catalogs/simbad.py +0 -0
  88. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/catalogs/standard_star.py +0 -0
  89. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/catalogs/vizier.py +0 -0
  90. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/classification/__init__.py +0 -0
  91. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/classification/classify_template_chi2.py +0 -0
  92. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/classification/pickles_atlas.py +0 -0
  93. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/continuum/__init__.py +0 -0
  94. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/continuum/compare_normalisations.py +0 -0
  95. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/continuum/normalize_edges.py +0 -0
  96. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/continuum/normalize_max.py +0 -0
  97. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/continuum/normalize_percentile.py +0 -0
  98. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/continuum/normalize_polynomial.py +0 -0
  99. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/continuum/normalize_region.py +0 -0
  100. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/continuum/normalize_spline.py +0 -0
  101. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/continuum/subtract_continuum.py +0 -0
  102. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/corrections/__init__.py +0 -0
  103. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/corrections/air_vacuum.py +0 -0
  104. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/corrections/atmospheric_extinction.py +0 -0
  105. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/corrections/barycentric.py +0 -0
  106. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/corrections/deredden_interstellar.py +0 -0
  107. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/corrections/doppler_shift.py +0 -0
  108. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/corrections/extinction_correct_easyspec.py +0 -0
  109. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/corrections/fit_telluric_scaling.py +0 -0
  110. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/corrections/flux_calibrate_easyspec.py +0 -0
  111. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/corrections/remove_telluric.py +0 -0
  112. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/corrections/response_from_standard.py +0 -0
  113. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/corrections/synth_telluric.py +0 -0
  114. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/embedding/__init__.py +0 -0
  115. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/embedding/embed_band_power.py +0 -0
  116. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/embedding/embed_continuum_subtracted.py +0 -0
  117. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/embedding/embed_lick_indices.py +0 -0
  118. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/embedding/embed_log_lambda.py +0 -0
  119. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/embedding/embed_pretrained.py +0 -0
  120. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/embedding/embed_remote.py +0 -0
  121. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/embedding/embed_spectrum.py +0 -0
  122. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/embedding/embed_wavelets.py +0 -0
  123. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/exports/__init__.py +0 -0
  124. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/exports/_bess_contract.py +0 -0
  125. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/exports/export_csv.py +0 -0
  126. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/exports/export_fits.py +0 -0
  127. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/exports/export_fits_bess.py +0 -0
  128. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/exports/export_hdf5.py +0 -0
  129. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/exports/export_votable.py +0 -0
  130. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/extraction/__init__.py +0 -0
  131. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/extraction/_aperture.py +0 -0
  132. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/extraction/boxcar.py +0 -0
  133. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/extraction/detect_trace.py +0 -0
  134. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/extraction/easyspec_extract.py +0 -0
  135. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/extraction/optimal.py +0 -0
  136. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/extraction/sky_lateral_bands.py +0 -0
  137. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/io/__init__.py +0 -0
  138. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/io/read_ascii.py +0 -0
  139. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/io/read_echelle.py +0 -0
  140. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/io/read_fits.py +0 -0
  141. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/io/read_sdss.py +0 -0
  142. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/io/read_votable.py +0 -0
  143. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/kinematics/__init__.py +0 -0
  144. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/kinematics/rotation_curve.py +0 -0
  145. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/kinematics/vsini_fourier.py +0 -0
  146. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/lines/__init__.py +0 -0
  147. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/lines/_line_flux.py +0 -0
  148. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/lines/_profiles.py +0 -0
  149. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/lines/catalogs.py +0 -0
  150. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/lines/compare_line_fits.py +0 -0
  151. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/lines/detect.py +0 -0
  152. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/lines/equivalent_width.py +0 -0
  153. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/lines/fit_gaussian.py +0 -0
  154. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/lines/fit_lorentzian.py +0 -0
  155. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/lines/fit_voigt.py +0 -0
  156. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/lines/vr_ratio.py +0 -0
  157. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/nebular/__init__.py +0 -0
  158. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/nebular/balmer_decrement_extinction.py +0 -0
  159. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/nebular/bpt_line_ratios.py +0 -0
  160. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/nebular/oiii_electron_temperature.py +0 -0
  161. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/nebular/sii_electron_density.py +0 -0
  162. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/quality/__init__.py +0 -0
  163. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/quality/compare_snr_methods.py +0 -0
  164. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/quality/measure_resolving_power.py +0 -0
  165. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/quality/snr_der.py +0 -0
  166. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/quality/snr_edge.py +0 -0
  167. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/quality/snr_linear_fit.py +0 -0
  168. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/quality/validate_bess_header.py +0 -0
  169. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/reduction/__init__.py +0 -0
  170. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/reduction/_easyspec_apply.py +0 -0
  171. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/reduction/_easyspec_helpers.py +0 -0
  172. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/reduction/bias_combine.py +0 -0
  173. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/reduction/clip_cosmic_rays.py +0 -0
  174. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/reduction/dark_combine.py +0 -0
  175. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/reduction/dark_subtract.py +0 -0
  176. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/reduction/denoise_2d.py +0 -0
  177. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/reduction/easyspec_bias.py +0 -0
  178. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/reduction/easyspec_cosmic_ray.py +0 -0
  179. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/reduction/easyspec_dark.py +0 -0
  180. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/reduction/easyspec_flat.py +0 -0
  181. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/reduction/easyspec_flat_normalize.py +0 -0
  182. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/reduction/easyspec_subtract_dark.py +0 -0
  183. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/reduction/extract_spectrum_sum.py +0 -0
  184. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/reduction/flat_combine.py +0 -0
  185. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/reduction/flat_normalize.py +0 -0
  186. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/reduction/geometry.py +0 -0
  187. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/reduction/subtract_sky_2d.py +0 -0
  188. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/reduction/wavelength_calibrate.py +0 -0
  189. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/rv/__init__.py +0 -0
  190. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/rv/cross_correlate.py +0 -0
  191. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/rv/fit_keplerian_orbit.py +0 -0
  192. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/rv/measure.py +0 -0
  193. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/rv/precision_bouchy.py +0 -0
  194. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/rv/redshift_lines.py +0 -0
  195. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/smoothing/__init__.py +0 -0
  196. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/smoothing/_kernel_uncertainty.py +0 -0
  197. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/smoothing/_nan_bridge.py +0 -0
  198. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/smoothing/compare_smoothings.py +0 -0
  199. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/smoothing/smooth_gaussian.py +0 -0
  200. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/smoothing/smooth_savgol.py +0 -0
  201. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/stacking/__init__.py +0 -0
  202. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/stacking/merge_echelle_orders.py +0 -0
  203. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/stacking/stack.py +0 -0
  204. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/timeseries/__init__.py +0 -0
  205. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/timeseries/_light_curve.py +0 -0
  206. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/timeseries/box_least_squares.py +0 -0
  207. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/timeseries/lomb_scargle.py +0 -0
  208. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/timeseries/phase_dispersion_minimization.py +0 -0
  209. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/timeseries/phase_fold.py +0 -0
  210. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/timeseries/temporal_variance_spectrum.py +0 -0
  211. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/transforms/__init__.py +0 -0
  212. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/transforms/clip_sigma.py +0 -0
  213. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/transforms/combine_arithmetic.py +0 -0
  214. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/transforms/extract_region.py +0 -0
  215. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/transforms/mask_range.py +0 -0
  216. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/transforms/resample.py +0 -0
  217. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/transforms/resample_flux_conserving.py +0 -0
  218. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/viz/__init__.py +0 -0
  219. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/viz/plot_3d_surface.py +0 -0
  220. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/viz/plot_animation.py +0 -0
  221. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/viz/plot_dynamic_spectrum.py +0 -0
  222. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/viz/plot_plotly.py +0 -0
  223. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/wavelength_calibration/__init__.py +0 -0
  224. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/wavelength_calibration/arc_geometry.py +0 -0
  225. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/wavelength_calibration/easyspec_wavelength.py +0 -0
  226. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/wavelength_calibration/in_situ.py +0 -0
  227. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/wavelength_calibration/lamp_atlas.py +0 -0
  228. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/wavelength_calibration/match_lamp.py +0 -0
  229. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/wavelength_calibration/reidentify.py +0 -0
  230. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/algorithms/wavelength_calibration/solar.py +0 -0
  231. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/base.py +0 -0
  232. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/cli.py +0 -0
  233. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/embeddings.py +0 -0
  234. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/errors.py +0 -0
  235. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/io/__init__.py +0 -0
  236. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/io/ascii.py +0 -0
  237. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/io/fits.py +0 -0
  238. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/io/votable.py +0 -0
  239. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/pipeline.py +0 -0
  240. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/presets/__init__.py +0 -0
  241. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/presets/catalog/analysis/balmer_quick.yaml +0 -0
  242. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/presets/catalog/analysis/embed_quick.yaml +0 -0
  243. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/presets/catalog/analysis/quality_report.yaml +0 -0
  244. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/presets/catalog/analysis/rv_quick.yaml +0 -0
  245. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/presets/catalog/analysis/snr_check.yaml +0 -0
  246. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/presets/catalog/analysis/time_series_overview.yaml +0 -0
  247. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/presets/catalog/reduction/full_reduction_easyspec.yaml +0 -0
  248. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/presets/loader.py +0 -0
  249. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/presets/preset.schema.json +0 -0
  250. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/presets/variables.py +0 -0
  251. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/py.typed +0 -0
  252. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/registry.py +0 -0
  253. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/registry_export.py +0 -0
  254. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/types/__init__.py +0 -0
  255. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/types/catalog.py +0 -0
  256. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/types/context.py +0 -0
  257. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/types/enums.py +0 -0
  258. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/types/history.py +0 -0
  259. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/types/image.py +0 -0
  260. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/types/line.py +0 -0
  261. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/types/spectrum.py +0 -0
  262. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/types/timeseries.py +0 -0
  263. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_kernel/url_safety.py +0 -0
  264. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_mcp/__init__.py +0 -0
  265. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_mcp/__main__.py +0 -0
  266. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_mcp/auth.py +0 -0
  267. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_mcp/auto_tools.py +0 -0
  268. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_mcp/observability.py +0 -0
  269. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_mcp/py.typed +0 -0
  270. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_mcp/resources.py +0 -0
  271. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_mcp/server.py +0 -0
  272. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_mcp/session.py +0 -0
  273. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/src/spectro_mcp/url_safety.py +0 -0
  274. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/conftest.py +0 -0
  275. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/reference/cases.py +0 -0
  276. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/reference/conftest.py +0 -0
  277. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/reference/test_known_answers.py +0 -0
  278. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/reference/test_sun.py +0 -0
  279. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/reference/test_validation_cases.py +0 -0
  280. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/reference/test_vega.py +0 -0
  281. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_activity_bisector.py +0 -0
  282. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_activity_caii_hk.py +0 -0
  283. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_activity_halpha.py +0 -0
  284. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_aperture_photometry.py +0 -0
  285. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_barycentric_bjd.py +0 -0
  286. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_base.py +0 -0
  287. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_catalog_queries_mocked.py +0 -0
  288. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_classify_template_chi2.py +0 -0
  289. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_cli.py +0 -0
  290. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_combine.py +0 -0
  291. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_combine_arithmetic.py +0 -0
  292. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_continuum.py +0 -0
  293. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_corrections.py +0 -0
  294. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_cross_correlate_extension.py +0 -0
  295. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_dark_flat_combine.py +0 -0
  296. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_denoise_2d.py +0 -0
  297. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_detect_lines_blind.py +0 -0
  298. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_detect_trace.py +0 -0
  299. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_disentangle_sb2.py +0 -0
  300. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_docs_generators.py +0 -0
  301. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_doppler_tomogram.py +0 -0
  302. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_easyspec_apply_staging.py +0 -0
  303. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_easyspec_sessions.py +0 -0
  304. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_easyspec_wrappers.py +0 -0
  305. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_embedding.py +0 -0
  306. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_embedding_pretrained.py +0 -0
  307. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_embedding_remote_lick.py +0 -0
  308. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_embedding_tier1.py +0 -0
  309. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_examples_run.py +0 -0
  310. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_export_fits_bess.py +0 -0
  311. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_export_hdf5.py +0 -0
  312. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_extract_boxcar.py +0 -0
  313. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_extract_optimal.py +0 -0
  314. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_extract_spectrum_sum.py +0 -0
  315. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_extraction_centring.py +0 -0
  316. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_flux_atmospheric_extinction.py +0 -0
  317. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_flux_balmer_decrement.py +0 -0
  318. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_flux_calibrate_easyspec.py +0 -0
  319. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_flux_deredden_interstellar.py +0 -0
  320. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_flux_standard_star_reference.py +0 -0
  321. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_geometry_corrections.py +0 -0
  322. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_io.py +0 -0
  323. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_io_fits_zoo.py +0 -0
  324. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_lamp_atlas_match.py +0 -0
  325. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_line_profiles.py +0 -0
  326. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_lines.py +0 -0
  327. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_mask_honoured.py +0 -0
  328. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_mcp.py +0 -0
  329. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_mcp_http_entry.py +0 -0
  330. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_mcp_param_guard.py +0 -0
  331. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_mcp_production.py +0 -0
  332. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_mcp_resources.py +0 -0
  333. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_mcp_security.py +0 -0
  334. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_mcp_tools_extra.py +0 -0
  335. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_measure_arc_geometry.py +0 -0
  336. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_misc_algorithms.py +0 -0
  337. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_nebular_diagnostics.py +0 -0
  338. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_no_circular_imports.py +0 -0
  339. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_normalize_spline.py +0 -0
  340. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_normalize_to_region.py +0 -0
  341. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_output_produces_contract.py +0 -0
  342. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_pipeline.py +0 -0
  343. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_presets.py +0 -0
  344. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_quality.py +0 -0
  345. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_read_sdss.py +0 -0
  346. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_redshift_lines.py +0 -0
  347. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_registry.py +0 -0
  348. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_reidentify.py +0 -0
  349. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_resample_flux_conserving.py +0 -0
  350. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_resolving_power.py +0 -0
  351. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_response_from_standard.py +0 -0
  352. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_rotation_curve.py +0 -0
  353. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_rv_precision_bouchy.py +0 -0
  354. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_sky_lateral_bands.py +0 -0
  355. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_smoothing.py +0 -0
  356. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_timeseries.py +0 -0
  357. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_timeseries_bls.py +0 -0
  358. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_timeseries_pdm.py +0 -0
  359. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_timeseries_tvs.py +0 -0
  360. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_transforms.py +0 -0
  361. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_types.py +0 -0
  362. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_uncertainty_propagation.py +0 -0
  363. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_url_safety_kernel.py +0 -0
  364. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_validate_bess_header.py +0 -0
  365. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_viz.py +0 -0
  366. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_vr_ratio.py +0 -0
  367. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_vsini_fourier.py +0 -0
  368. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_wavelength_calibration_in_situ.py +0 -0
  369. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tests/unit/test_wavelength_calibration_solar.py +0 -0
  370. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tools/docs/__init__.py +0 -0
  371. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tools/docs/build.py +0 -0
  372. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tools/docs/generate.py +0 -0
  373. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tools/docs/generate_catalogue.py +0 -0
  374. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tools/docs/generate_cli.py +0 -0
  375. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tools/docs/generate_llms.py +0 -0
  376. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tools/docs/generate_mcp.py +0 -0
  377. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tools/docs/generate_recipes.py +0 -0
  378. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tools/docs/generate_validation.py +0 -0
  379. {spectro_kernel-0.8.0 → spectro_kernel-0.8.1}/tools/docs/netlify.toml +0 -0
@@ -6,6 +6,36 @@ Until `1.0.0` the public API may change between minor versions.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.8.1] — 2026-09-26
10
+
11
+ One native brick, the last of the September audit's "trivial and already requested"
12
+ gaps (item 1 of its catalogue table), plus the documentation hook for the published
13
+ recipe collection. No existing brick changes its numbers.
14
+
15
+ ### Added
16
+
17
+ - **`subtract_bias`** (preprocessing, 1.0.0, numpy) — the zero-level correction of
18
+ standard CCD reduction (Howell 2006, *Handbook of CCD Astronomy*, ch. 4 ; Massey
19
+ 1997, *A User's Guide to CCD Reductions with IRAF*) : `science − master_bias` in
20
+ float64 on `ctx.image`, master frame read from `ctx.extras['master_bias']` as written
21
+ by `bias_combine`, or a constant `bias_level` (overscan mean) when no bias frames
22
+ exist. No exposure-time scaling (a bias carries no dark current). Negative pixels are
23
+ kept unless `clip_negative=True` ; metrics `bias_median`, `median_after`,
24
+ `n_negative`, `n_clipped`. Native counterpart of `subtract_bias_easyspec`, which
25
+ AuroreX asked for after the BZERO staging bug of the easyspec wrappers (fixed in
26
+ 0.2.1) : the native path never stages a FITS file. Tests : exact recovery of a
27
+ synthetic truth under a gradient bias, integer-ADU input, constant level, precedence
28
+ of `bias_level` over the frame, clipping count, three failure paths, chaining after
29
+ `bias_combine`.
30
+ - `subtract_bias_easyspec` 1.0.1 → 1.0.2 : `long_description` cross-references the
31
+ native brick (docstring only).
32
+
33
+ ### Documentation
34
+
35
+ - The `docs` extra now installs `spectro-kernel-recipes>=0.2.0` (published on PyPI on
36
+ 2026-09-26), so the online recipe catalogue lists the ten campaign recipes next to the
37
+ seven bundled ones. No runtime change.
38
+
9
39
  ## [0.8.0] — 2026-09-26
10
40
 
11
41
  The "exactness" release : the four method corrections the September audit
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: spectro-kernel
3
- Version: 0.8.0
3
+ Version: 0.8.1
4
4
  Summary: A shared catalogue of astronomical spectroscopy algorithms, composable into reproducible pipelines, usable as a Python library, a CLI, or an MCP server.
5
5
  Project-URL: Homepage, https://github.com/matthieulel/spectro-kernel
6
6
  Project-URL: Documentation, https://docs.spectrokernel.io/
@@ -59,6 +59,7 @@ Requires-Dist: mkdocs-literate-nav>=0.6; extra == 'docs'
59
59
  Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
60
60
  Requires-Dist: mkdocstrings[python]>=0.26; extra == 'docs'
61
61
  Requires-Dist: pyyaml>=6.0; extra == 'docs'
62
+ Requires-Dist: spectro-kernel-recipes>=0.2.0; extra == 'docs'
62
63
  Requires-Dist: zensical>=0.0.62; extra == 'docs'
63
64
  Provides-Extra: embedding-ml
64
65
  Requires-Dist: torch>=2.2; extra == 'embedding-ml'
@@ -70,6 +70,7 @@ docs = [
70
70
  "mkdocs-literate-nav>=0.6", # fallback engine's nav plugin (Zensical has it built in)
71
71
  "jsonschema>=4.0", # validates docs/ai/algorithms.json at build time
72
72
  "pyyaml>=6.0",
73
+ "spectro-kernel-recipes>=0.2.0", # the campaign collection, so the online catalogue lists its recipes
73
74
  ]
74
75
  all = [
75
76
  "spectro-kernel[catalogs,viz,storage,reduction,mcp,monitoring,embedding-wavelets,embedding-remote]",
@@ -22,7 +22,7 @@ from ._easyspec_helpers import easyspec_session, silent_easyspec
22
22
  @register_algorithm(
23
23
  "subtract_bias_easyspec",
24
24
  category=AlgorithmCategory.PREPROCESSING,
25
- version="1.0.1",
25
+ version="1.0.2",
26
26
  )
27
27
  class SubtractBiasEasyspec(BaseAlgorithm):
28
28
  """Subtract a master bias from a single science frame via ``cleaning.debias``.
@@ -37,6 +37,11 @@ class SubtractBiasEasyspec(BaseAlgorithm):
37
37
  references = [
38
38
  "easyspec.cleaning.cleaning.debias.",
39
39
  ]
40
+ long_description = (
41
+ "Wrapper of easyspec's ``debias`` (temporary FITS staging, negative pixels "
42
+ "clipped to zero by default). ``subtract_bias`` is the native numpy counterpart: "
43
+ "same arithmetic on ``ctx.image`` in float64, no staging, no clipping unless asked."
44
+ )
40
45
  default_params = {
41
46
  "target_path": None,
42
47
  "master_bias_path": None,
@@ -0,0 +1,122 @@
1
+ """Algorithm: subtract a master bias (or a constant bias level) from the working image."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import math
6
+ from typing import Any
7
+
8
+ import numpy as np
9
+
10
+ from ...base import AlgorithmOutput, BaseAlgorithm
11
+ from ...errors import InvalidParameterError
12
+ from ...registry import register_algorithm
13
+ from ...types import AlgorithmCategory, ImageFrame, WorkContext
14
+
15
+
16
+ @register_algorithm("subtract_bias", category=AlgorithmCategory.PREPROCESSING, version="1.0.0")
17
+ class SubtractBias(BaseAlgorithm):
18
+ """Subtract the master bias (or a constant bias level) from ``ctx.image``.
19
+
20
+ The zero-level correction of standard CCD reduction (Howell 2006, ch. 4):
21
+ ``science - master_bias`` pixel by pixel, in float64, with no exposure-time
22
+ scaling (a bias frame carries no dark current). The master bias is read from
23
+ ``ctx.extras['master_bias']`` as written by ``bias_combine``; a constant
24
+ ``bias_level`` (for instance the overscan mean) can be subtracted instead
25
+ when no bias frames were taken.
26
+ """
27
+
28
+ backend = "numpy"
29
+ references = [
30
+ "Howell 2006 — Handbook of CCD Astronomy, 2nd ed., ch. 4 (bias frames, zero level).",
31
+ "Massey 1997 — A User's Guide to CCD Reductions with IRAF (NOAO), zero-level correction.",
32
+ ]
33
+ long_description = (
34
+ "Native counterpart of ``subtract_bias_easyspec``: the same arithmetic without the "
35
+ "easyspec staging (no temporary FITS, no clipping unless ``clip_negative`` is set), "
36
+ "so integer-ADU frames and BZERO-scaled files are handled in float64 end to end. "
37
+ "Precedence: an explicit ``bias_level`` wins over the master frame stored in "
38
+ "``ctx.extras[bias_key]``; with neither available the brick fails. Negative pixels "
39
+ "are kept by default because clipping biases the sky statistics of faint frames; "
40
+ "``clip_negative=True`` reproduces the easyspec ``pad_with_zeros`` behaviour. "
41
+ "Companion of ``dark_subtract`` (which scales by exposure time) and "
42
+ "``flat_normalize``."
43
+ )
44
+ default_params = {"bias_key": "master_bias", "bias_level": None, "clip_negative": False}
45
+ param_descriptions = {
46
+ "bias_key": "Key in ctx.extras where the master bias (an ImageFrame) is stored.",
47
+ "bias_level": (
48
+ "Constant bias level in ADU to subtract instead of a master frame "
49
+ "(e.g. the overscan mean); takes precedence over the master frame when set."
50
+ ),
51
+ "clip_negative": "Set the pixels that become negative after subtraction to zero.",
52
+ }
53
+ input_requirements = ["image"]
54
+ output_produces = [
55
+ "image",
56
+ "metrics.bias_median",
57
+ "metrics.median_after",
58
+ "metrics.n_negative",
59
+ "metrics.n_clipped",
60
+ ]
61
+
62
+ def run(self, ctx: WorkContext, params: dict[str, Any]) -> AlgorithmOutput:
63
+ image = ctx.image
64
+ if image is None:
65
+ return AlgorithmOutput.fail("subtract_bias: no image in the WorkContext.")
66
+
67
+ level = params.get("bias_level")
68
+ key = str(params["bias_key"])
69
+ if level is not None:
70
+ try:
71
+ level = float(level)
72
+ except (TypeError, ValueError) as exc:
73
+ raise InvalidParameterError(
74
+ f"bias_level must be a number in ADU, got {level!r}."
75
+ ) from exc
76
+ if not math.isfinite(level):
77
+ raise InvalidParameterError("bias_level must be finite.")
78
+ bias: np.ndarray | float = level
79
+ source = "constant"
80
+ bias_median = level
81
+ else:
82
+ master = ctx.extras.get(key)
83
+ if not isinstance(master, ImageFrame):
84
+ return AlgorithmOutput.fail(
85
+ f"No master bias in ctx.extras[{key!r}] and no bias_level given; "
86
+ "run bias_combine on the bias frames first."
87
+ )
88
+ if master.data.shape != image.data.shape:
89
+ return AlgorithmOutput.fail(
90
+ f"Shape mismatch: science {image.data.shape} "
91
+ f"vs master bias {master.data.shape}."
92
+ )
93
+ bias = master.data.astype(np.float64)
94
+ source = f"extras[{key}]"
95
+ bias_median = float(np.nanmedian(master.data))
96
+
97
+ data = image.data.astype(np.float64) - bias
98
+ n_negative = int(np.count_nonzero(data < 0))
99
+ n_clipped = 0
100
+ if bool(params["clip_negative"]):
101
+ n_clipped = n_negative
102
+ data = np.where(data < 0, 0.0, data)
103
+
104
+ out = image.copy()
105
+ out.data = data
106
+ out.meta["bias_subtracted"] = True
107
+ out.meta["bias_source"] = source
108
+ out.meta["bias_median"] = bias_median
109
+ ctx.image = out
110
+ return AlgorithmOutput.ok(
111
+ metrics={
112
+ "bias_median": bias_median,
113
+ "median_after": float(np.nanmedian(data)),
114
+ "n_negative": n_negative,
115
+ "n_clipped": n_clipped,
116
+ },
117
+ message=(
118
+ f"Bias subtracted from {source} (median level {bias_median:.2f} ADU"
119
+ + (f", {n_clipped} negative pixels clipped to 0" if n_clipped else "")
120
+ + ")."
121
+ ),
122
+ )
@@ -1,3 +1,3 @@
1
1
  """Single source of truth for the package version."""
2
2
 
3
- __version__ = "0.8.0"
3
+ __version__ = "0.8.1"
@@ -0,0 +1,172 @@
1
+ """Tests for the native ``subtract_bias`` brick (Howell 2006, ch. 4 zero-level correction).
2
+
3
+ The right answer is analytic: a science frame built as ``truth + bias`` must give
4
+ back ``truth`` exactly once the same bias is subtracted (pure float64 arithmetic,
5
+ no scaling, no clipping), whatever the input dtype.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import numpy as np
11
+ import pytest
12
+
13
+ from spectro_kernel import WorkContext, run_algorithm
14
+ from spectro_kernel.types import ImageFrame
15
+
16
+ SHAPE = (8, 16)
17
+
18
+
19
+ def _gradient_bias() -> np.ndarray:
20
+ rows, cols = SHAPE
21
+ # A pedestal of 300 ADU with a mild column gradient, as a real bias structure.
22
+ return 300.0 + np.linspace(0.0, 4.0, cols)[None, :] * np.ones((rows, 1))
23
+
24
+
25
+ def _truth() -> np.ndarray:
26
+ rng = np.random.default_rng(0)
27
+ return rng.uniform(50.0, 5000.0, size=SHAPE)
28
+
29
+
30
+ def test_master_frame_recovers_truth_exactly():
31
+ truth, bias = _truth(), _gradient_bias()
32
+ ctx = WorkContext(image=ImageFrame(data=truth + bias, frame_type="science"))
33
+ ctx.extras["master_bias"] = ImageFrame(data=bias, frame_type="bias")
34
+
35
+ out = run_algorithm("subtract_bias", ctx)
36
+
37
+ assert out.success
38
+ np.testing.assert_allclose(ctx.image.data, truth, rtol=0, atol=1e-9)
39
+ assert ctx.image.data.dtype == np.float64
40
+ assert ctx.image.meta["bias_subtracted"] is True
41
+ assert ctx.image.meta["bias_source"] == "extras[master_bias]"
42
+ assert out.metrics["bias_median"] == pytest.approx(float(np.median(bias)))
43
+ assert out.metrics["median_after"] == pytest.approx(float(np.median(truth)))
44
+ assert out.metrics["n_negative"] == 0
45
+ assert out.metrics["n_clipped"] == 0
46
+ # The input frame is not modified in place.
47
+ assert ctx.image is not None
48
+
49
+
50
+ def test_integer_adu_input_does_not_wrap():
51
+ # A 16-bit camera frame below the bias level in places: uint16 arithmetic would wrap.
52
+ science = np.full(SHAPE, 1000, dtype=np.uint16)
53
+ bias = np.full(SHAPE, 1010.0)
54
+ ctx = WorkContext(image=ImageFrame(data=science, frame_type="science"))
55
+ ctx.extras["master_bias"] = ImageFrame(data=bias, frame_type="bias")
56
+
57
+ out = run_algorithm("subtract_bias", ctx)
58
+
59
+ assert out.success
60
+ np.testing.assert_allclose(ctx.image.data, -10.0)
61
+ assert out.metrics["n_negative"] == science.size
62
+ assert out.metrics["n_clipped"] == 0
63
+
64
+
65
+ def test_constant_level_when_no_master_frame():
66
+ truth = _truth()
67
+ ctx = WorkContext(image=ImageFrame(data=truth + 250.5, frame_type="science"))
68
+
69
+ out = run_algorithm("subtract_bias", ctx, {"bias_level": 250.5})
70
+
71
+ assert out.success
72
+ np.testing.assert_allclose(ctx.image.data, truth, rtol=0, atol=1e-9)
73
+ assert ctx.image.meta["bias_source"] == "constant"
74
+ assert out.metrics["bias_median"] == pytest.approx(250.5)
75
+
76
+
77
+ def test_explicit_level_takes_precedence_over_master_frame():
78
+ truth = _truth()
79
+ ctx = WorkContext(image=ImageFrame(data=truth + 100.0, frame_type="science"))
80
+ ctx.extras["master_bias"] = ImageFrame(data=np.full(SHAPE, 999.0), frame_type="bias")
81
+
82
+ out = run_algorithm("subtract_bias", ctx, {"bias_level": "100"}) # CLI-style string
83
+
84
+ assert out.success
85
+ np.testing.assert_allclose(ctx.image.data, truth, rtol=0, atol=1e-9)
86
+ assert ctx.image.meta["bias_source"] == "constant"
87
+
88
+
89
+ def test_clip_negative_zeroes_and_counts():
90
+ science = np.array([[5.0, 20.0, 30.0], [40.0, 3.0, 60.0]])
91
+ ctx = WorkContext(image=ImageFrame(data=science, frame_type="science"))
92
+
93
+ out = run_algorithm("subtract_bias", ctx, {"bias_level": 10.0, "clip_negative": True})
94
+
95
+ assert out.success
96
+ np.testing.assert_allclose(ctx.image.data, [[0.0, 10.0, 20.0], [30.0, 0.0, 50.0]])
97
+ assert out.metrics["n_negative"] == 2
98
+ assert out.metrics["n_clipped"] == 2
99
+ assert "2 negative pixels clipped" in out.message
100
+
101
+
102
+ def test_no_scaling_by_exposure_time():
103
+ # Unlike dark_subtract, EXPTIME must be ignored: a bias carries no dark current.
104
+ truth, bias = _truth(), _gradient_bias()
105
+ ctx = WorkContext(
106
+ image=ImageFrame(data=truth + bias, header={"EXPTIME": 600.0}, frame_type="science")
107
+ )
108
+ ctx.extras["master_bias"] = ImageFrame(data=bias, header={"EXPTIME": 0.0}, frame_type="bias")
109
+
110
+ out = run_algorithm("subtract_bias", ctx)
111
+
112
+ assert out.success
113
+ np.testing.assert_allclose(ctx.image.data, truth, rtol=0, atol=1e-9)
114
+
115
+
116
+ def test_chains_after_bias_combine():
117
+ truth = _truth()
118
+ rng = np.random.default_rng(1)
119
+ bias_frames = [
120
+ ImageFrame(data=300.0 + rng.normal(0.0, 2.0, size=SHAPE), frame_type="bias")
121
+ for _ in range(5)
122
+ ]
123
+ master = np.median(np.stack([f.data for f in bias_frames]), axis=0)
124
+ ctx = WorkContext(images=bias_frames, image=ImageFrame(data=truth + master))
125
+
126
+ assert run_algorithm("bias_combine", ctx, {"method": "median"}).success
127
+ out = run_algorithm("subtract_bias", ctx)
128
+
129
+ assert out.success
130
+ np.testing.assert_allclose(ctx.image.data, truth, rtol=0, atol=1e-9)
131
+ assert [s.algorithm for s in ctx.history] == ["bias_combine", "subtract_bias"]
132
+ assert ctx.history[-1].success
133
+
134
+
135
+ def test_fails_without_master_frame_or_level():
136
+ ctx = WorkContext(image=ImageFrame(data=_truth()))
137
+ out = run_algorithm("subtract_bias", ctx, raise_on_error=False)
138
+ assert not out.success
139
+ assert "bias_combine" in out.error
140
+ assert ctx.history[-1].success is False
141
+
142
+
143
+ def test_fails_on_shape_mismatch():
144
+ ctx = WorkContext(image=ImageFrame(data=_truth()))
145
+ ctx.extras["master_bias"] = ImageFrame(data=np.zeros((4, 4)), frame_type="bias")
146
+ out = run_algorithm("subtract_bias", ctx, raise_on_error=False)
147
+ assert not out.success
148
+ assert "Shape mismatch" in out.error
149
+
150
+
151
+ def test_fails_without_image_and_on_bad_level():
152
+ out = run_algorithm("subtract_bias", WorkContext(), raise_on_error=False)
153
+ assert not out.success
154
+
155
+ ctx = WorkContext(image=ImageFrame(data=_truth()))
156
+ out = run_algorithm("subtract_bias", ctx, {"bias_level": "overscan"}, raise_on_error=False)
157
+ assert not out.success
158
+ assert "bias_level" in out.error
159
+
160
+ out = run_algorithm("subtract_bias", ctx, {"bias_level": float("nan")}, raise_on_error=False)
161
+ assert not out.success
162
+ assert "finite" in out.error
163
+
164
+
165
+ def test_custom_extras_key():
166
+ truth, bias = _truth(), _gradient_bias()
167
+ ctx = WorkContext(image=ImageFrame(data=truth + bias))
168
+ ctx.extras["zero"] = ImageFrame(data=bias, frame_type="bias")
169
+ out = run_algorithm("subtract_bias", ctx, {"bias_key": "zero"})
170
+ assert out.success
171
+ np.testing.assert_allclose(ctx.image.data, truth, rtol=0, atol=1e-9)
172
+ assert ctx.image.meta["bias_source"] == "extras[zero]"
File without changes
File without changes
File without changes