spectro-kernel 0.6.1__tar.gz → 0.7.0__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 (367) hide show
  1. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/.gitignore +6 -0
  2. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/CHANGELOG.md +283 -0
  3. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/PKG-INFO +18 -4
  4. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/README.md +12 -1
  5. spectro_kernel-0.7.0/docs/.drafts/README.md +7 -0
  6. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/concepts/algorithms.md +1 -1
  7. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/concepts/pipelines.md +6 -1
  8. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/contributing.md +3 -3
  9. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/getting-started.md +1 -1
  10. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/index.md +1 -1
  11. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/notebooks/be-star-variability.md +2 -2
  12. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/notebooks/claude-mcp-end-to-end.md +1 -1
  13. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/notebooks/full-reduction-walkthrough.md +30 -20
  14. spectro_kernel-0.7.0/docs/recipes/format.md +163 -0
  15. spectro_kernel-0.7.0/docs/recipes/index.md +125 -0
  16. spectro_kernel-0.7.0/docs/recipes/share.md +88 -0
  17. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/reference.md +1 -1
  18. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/tutorials/discover-the-catalogue.md +1 -1
  19. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/tutorials/first-spectrum.md +1 -1
  20. spectro_kernel-0.7.0/docs/tutorials/long-slit-reduction.md +299 -0
  21. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/usage/cli.md +20 -5
  22. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/usage/mcp.md +3 -2
  23. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/why.md +2 -2
  24. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/pyproject.toml +7 -4
  25. spectro_kernel-0.7.0/src/spectro_kernel/algorithms/activity/_bands.py +128 -0
  26. spectro_kernel-0.7.0/src/spectro_kernel/algorithms/activity/activity_index_caii_hk.py +313 -0
  27. spectro_kernel-0.7.0/src/spectro_kernel/algorithms/activity/activity_index_halpha.py +160 -0
  28. spectro_kernel-0.7.0/src/spectro_kernel/algorithms/activity/ccf_bisector.py +404 -0
  29. spectro_kernel-0.7.0/src/spectro_kernel/algorithms/catalogs/standard_star.py +426 -0
  30. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/continuum/normalize_edges.py +7 -2
  31. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/continuum/normalize_max.py +10 -1
  32. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/continuum/normalize_percentile.py +11 -4
  33. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/continuum/normalize_polynomial.py +11 -12
  34. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/continuum/normalize_region.py +7 -2
  35. spectro_kernel-0.7.0/src/spectro_kernel/algorithms/continuum/normalize_spline.py +286 -0
  36. spectro_kernel-0.7.0/src/spectro_kernel/algorithms/corrections/atmospheric_extinction.py +483 -0
  37. spectro_kernel-0.7.0/src/spectro_kernel/algorithms/corrections/deredden_interstellar.py +187 -0
  38. spectro_kernel-0.7.0/src/spectro_kernel/algorithms/io/read_fits.py +153 -0
  39. spectro_kernel-0.7.0/src/spectro_kernel/algorithms/kinematics/vsini_fourier.py +425 -0
  40. spectro_kernel-0.7.0/src/spectro_kernel/algorithms/nebular/balmer_decrement_extinction.py +333 -0
  41. spectro_kernel-0.7.0/src/spectro_kernel/algorithms/quality/measure_resolving_power.py +281 -0
  42. spectro_kernel-0.7.0/src/spectro_kernel/algorithms/smoothing/_kernel_uncertainty.py +122 -0
  43. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/smoothing/smooth_gaussian.py +28 -5
  44. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/smoothing/smooth_savgol.py +22 -5
  45. spectro_kernel-0.7.0/src/spectro_kernel/algorithms/stacking/stack.py +213 -0
  46. spectro_kernel-0.7.0/src/spectro_kernel/algorithms/timeseries/_light_curve.py +60 -0
  47. spectro_kernel-0.7.0/src/spectro_kernel/algorithms/timeseries/box_least_squares.py +265 -0
  48. spectro_kernel-0.7.0/src/spectro_kernel/algorithms/timeseries/phase_dispersion_minimization.py +226 -0
  49. spectro_kernel-0.7.0/src/spectro_kernel/algorithms/timeseries/temporal_variance_spectrum.py +287 -0
  50. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/transforms/combine_arithmetic.py +79 -9
  51. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/transforms/resample.py +23 -3
  52. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/cli.py +122 -5
  53. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/errors.py +4 -0
  54. spectro_kernel-0.7.0/src/spectro_kernel/io/fits.py +914 -0
  55. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/pipeline.py +97 -13
  56. spectro_kernel-0.7.0/src/spectro_kernel/presets/__init__.py +37 -0
  57. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/presets/catalog/analysis/balmer_quick.yaml +2 -0
  58. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/presets/catalog/analysis/embed_quick.yaml +2 -0
  59. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/presets/catalog/analysis/quality_report.yaml +2 -0
  60. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/presets/catalog/analysis/rv_quick.yaml +2 -0
  61. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/presets/catalog/analysis/snr_check.yaml +2 -0
  62. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/presets/catalog/analysis/time_series_overview.yaml +2 -0
  63. spectro_kernel-0.7.0/src/spectro_kernel/presets/catalog/reduction/full_reduction_easyspec.yaml +113 -0
  64. spectro_kernel-0.7.0/src/spectro_kernel/presets/loader.py +351 -0
  65. spectro_kernel-0.7.0/src/spectro_kernel/presets/preset.schema.json +65 -0
  66. spectro_kernel-0.7.0/src/spectro_kernel/presets/variables.py +265 -0
  67. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/types/enums.py +2 -0
  68. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/version.py +1 -1
  69. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_mcp/__main__.py +43 -2
  70. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_mcp/auto_tools.py +18 -6
  71. spectro_kernel-0.7.0/src/spectro_mcp/py.typed +0 -0
  72. spectro_kernel-0.7.0/tests/unit/test_activity_bisector.py +174 -0
  73. spectro_kernel-0.7.0/tests/unit/test_activity_caii_hk.py +144 -0
  74. spectro_kernel-0.7.0/tests/unit/test_activity_halpha.py +81 -0
  75. spectro_kernel-0.7.0/tests/unit/test_combine.py +236 -0
  76. spectro_kernel-0.7.0/tests/unit/test_flux_atmospheric_extinction.py +270 -0
  77. spectro_kernel-0.7.0/tests/unit/test_flux_balmer_decrement.py +170 -0
  78. spectro_kernel-0.7.0/tests/unit/test_flux_deredden_interstellar.py +134 -0
  79. spectro_kernel-0.7.0/tests/unit/test_flux_standard_star_reference.py +373 -0
  80. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_io.py +33 -0
  81. spectro_kernel-0.7.0/tests/unit/test_io_fits_zoo.py +476 -0
  82. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_mcp_http_entry.py +67 -2
  83. spectro_kernel-0.7.0/tests/unit/test_normalize_spline.py +124 -0
  84. spectro_kernel-0.7.0/tests/unit/test_presets.py +366 -0
  85. spectro_kernel-0.7.0/tests/unit/test_resolving_power.py +151 -0
  86. spectro_kernel-0.7.0/tests/unit/test_timeseries_bls.py +157 -0
  87. spectro_kernel-0.7.0/tests/unit/test_timeseries_pdm.py +133 -0
  88. spectro_kernel-0.7.0/tests/unit/test_timeseries_tvs.py +210 -0
  89. spectro_kernel-0.7.0/tests/unit/test_uncertainty_propagation.py +331 -0
  90. spectro_kernel-0.7.0/tests/unit/test_vsini_fourier.py +200 -0
  91. spectro_kernel-0.7.0/tools/docs/__init__.py +6 -0
  92. spectro_kernel-0.7.0/tools/docs/build.py +94 -0
  93. spectro_kernel-0.7.0/tools/docs/generate.py +27 -0
  94. spectro_kernel-0.7.0/tools/docs/generate_catalogue.py +485 -0
  95. spectro_kernel-0.7.0/tools/docs/generate_llms.py +134 -0
  96. spectro_kernel-0.7.0/tools/docs/generate_recipes.py +300 -0
  97. spectro_kernel-0.7.0/tools/docs/netlify.toml +20 -0
  98. spectro_kernel-0.6.1/docs/cookbook/bess-dashboard.md +0 -118
  99. spectro_kernel-0.6.1/docs/gen_catalogue.py +0 -124
  100. spectro_kernel-0.6.1/docs/tutorials/long-slit-reduction.md +0 -171
  101. spectro_kernel-0.6.1/src/spectro_kernel/algorithms/io/read_fits.py +0 -53
  102. spectro_kernel-0.6.1/src/spectro_kernel/algorithms/stacking/stack.py +0 -110
  103. spectro_kernel-0.6.1/src/spectro_kernel/io/fits.py +0 -345
  104. spectro_kernel-0.6.1/src/spectro_kernel/presets/__init__.py +0 -7
  105. spectro_kernel-0.6.1/src/spectro_kernel/presets/catalog/reduction/full_reduction_easyspec.yaml +0 -68
  106. spectro_kernel-0.6.1/src/spectro_kernel/presets/loader.py +0 -83
  107. spectro_kernel-0.6.1/tests/unit/test_combine.py +0 -118
  108. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/LICENSE +0 -0
  109. {spectro_kernel-0.6.1/docs → spectro_kernel-0.7.0/docs/.drafts}/notebooks/aurora-line-monitor.md +0 -0
  110. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/concepts/architecture.md +0 -0
  111. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/concepts/data-types.md +0 -0
  112. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/cookbook/multi-star-viewer.md +0 -0
  113. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/cookbook/web-playground.md +0 -0
  114. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/images/notebooks/alpha_cyg_ew_timeseries.png +0 -0
  115. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/images/notebooks/alpha_cyg_halpha_phase_stack.png +0 -0
  116. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/images/notebooks/alpha_cyg_halpha_timeseries.png +0 -0
  117. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/images/notebooks/alpha_cyg_overlay.png +0 -0
  118. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/images/notebooks/alpha_cyg_pc1_vs_phase.png +0 -0
  119. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/images/notebooks/alpha_cyg_pca_2d.png +0 -0
  120. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/images/notebooks/alpha_cyg_pca_3d.png +0 -0
  121. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/images/notebooks/alpha_cyg_periodogram.png +0 -0
  122. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/images/notebooks/alpha_cyg_phase_folded.png +0 -0
  123. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/images/notebooks/alpha_cyg_rv_timeseries.png +0 -0
  124. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/images/notebooks/alpha_cyg_similarity.png +0 -0
  125. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/images/notebooks/alpha_cyg_similarity_date.png +0 -0
  126. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/images/notebooks/alpha_dra_halpha_phase_stack.png +0 -0
  127. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/images/notebooks/alpha_dra_pc1_vs_phase.png +0 -0
  128. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/images/notebooks/alpha_dra_pca_2d.png +0 -0
  129. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/images/notebooks/alpha_dra_pca_3d.png +0 -0
  130. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/images/notebooks/alpha_dra_periodogram.png +0 -0
  131. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/images/notebooks/alpha_dra_phase_folded.png +0 -0
  132. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/images/notebooks/alpha_dra_rv_timeseries.png +0 -0
  133. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/images/notebooks/alpha_dra_similarity_date.png +0 -0
  134. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/images/notebooks/alpha_dra_similarity_phase.png +0 -0
  135. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/notebooks/alpha-cyg-time-series.md +0 -0
  136. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/notebooks/alpha-dra-binary-period.md +0 -0
  137. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/notebooks/exoplanet-transit-rv.md +0 -0
  138. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/notebooks/native-vs-easyspec-showdown.md +0 -0
  139. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/notebooks/your-first-sb2.md +0 -0
  140. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/tutorials/add-an-algorithm.md +0 -0
  141. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/tutorials/analyse-a-spectrum.md +0 -0
  142. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/docs/usage/library.md +0 -0
  143. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/__init__.py +0 -0
  144. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/adapters/__init__.py +0 -0
  145. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/adapters/easyspec.py +0 -0
  146. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/__init__.py +0 -0
  147. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/_common.py +0 -0
  148. {spectro_kernel-0.6.1/src/spectro_kernel/algorithms/classification → spectro_kernel-0.7.0/src/spectro_kernel/algorithms/activity}/__init__.py +0 -0
  149. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/advanced/__init__.py +0 -0
  150. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/advanced/aperture_photometry.py +0 -0
  151. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/advanced/disentangle_sb2.py +0 -0
  152. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/advanced/doppler_tomogram.py +0 -0
  153. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/catalogs/__init__.py +0 -0
  154. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/catalogs/gaia.py +0 -0
  155. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/catalogs/simbad.py +0 -0
  156. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/catalogs/vizier.py +0 -0
  157. {spectro_kernel-0.6.1/src/spectro_kernel/algorithms/embedding → spectro_kernel-0.7.0/src/spectro_kernel/algorithms/classification}/__init__.py +0 -0
  158. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/classification/classify_template_chi2.py +0 -0
  159. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/classification/pickles_atlas.py +0 -0
  160. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/continuum/__init__.py +0 -0
  161. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/continuum/compare_normalisations.py +0 -0
  162. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/continuum/subtract_continuum.py +0 -0
  163. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/corrections/__init__.py +0 -0
  164. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/corrections/air_vacuum.py +0 -0
  165. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/corrections/barycentric.py +0 -0
  166. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/corrections/doppler_shift.py +0 -0
  167. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/corrections/extinction_correct_easyspec.py +0 -0
  168. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/corrections/fit_telluric_scaling.py +0 -0
  169. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/corrections/flux_calibrate_easyspec.py +0 -0
  170. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/corrections/remove_telluric.py +0 -0
  171. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/corrections/response_from_standard.py +0 -0
  172. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/corrections/synth_telluric.py +0 -0
  173. {spectro_kernel-0.6.1/src/spectro_kernel/algorithms/kinematics → spectro_kernel-0.7.0/src/spectro_kernel/algorithms/embedding}/__init__.py +0 -0
  174. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/embedding/embed_band_power.py +0 -0
  175. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/embedding/embed_continuum_subtracted.py +0 -0
  176. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/embedding/embed_lick_indices.py +0 -0
  177. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/embedding/embed_log_lambda.py +0 -0
  178. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/embedding/embed_pretrained.py +0 -0
  179. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/embedding/embed_remote.py +0 -0
  180. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/embedding/embed_spectrum.py +0 -0
  181. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/embedding/embed_wavelets.py +0 -0
  182. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/exports/__init__.py +0 -0
  183. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/exports/_bess_contract.py +0 -0
  184. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/exports/export_csv.py +0 -0
  185. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/exports/export_fits.py +0 -0
  186. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/exports/export_fits_bess.py +0 -0
  187. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/exports/export_hdf5.py +0 -0
  188. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/exports/export_votable.py +0 -0
  189. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/extraction/__init__.py +0 -0
  190. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/extraction/boxcar.py +0 -0
  191. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/extraction/detect_trace.py +0 -0
  192. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/extraction/easyspec_extract.py +0 -0
  193. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/extraction/optimal.py +0 -0
  194. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/extraction/sky_lateral_bands.py +0 -0
  195. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/io/__init__.py +0 -0
  196. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/io/read_ascii.py +0 -0
  197. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/io/read_echelle.py +0 -0
  198. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/io/read_sdss.py +0 -0
  199. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/io/read_votable.py +0 -0
  200. {spectro_kernel-0.6.1/src/spectro_kernel/algorithms/nebular → spectro_kernel-0.7.0/src/spectro_kernel/algorithms/kinematics}/__init__.py +0 -0
  201. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/kinematics/rotation_curve.py +0 -0
  202. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/lines/__init__.py +0 -0
  203. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/lines/_line_flux.py +0 -0
  204. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/lines/_profiles.py +0 -0
  205. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/lines/catalogs.py +0 -0
  206. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/lines/compare_line_fits.py +0 -0
  207. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/lines/detect.py +0 -0
  208. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/lines/equivalent_width.py +0 -0
  209. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/lines/fit_gaussian.py +0 -0
  210. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/lines/fit_lorentzian.py +0 -0
  211. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/lines/fit_voigt.py +0 -0
  212. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/lines/vr_ratio.py +0 -0
  213. /spectro_kernel-0.6.1/src/spectro_kernel/py.typed → /spectro_kernel-0.7.0/src/spectro_kernel/algorithms/nebular/__init__.py +0 -0
  214. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/nebular/bpt_line_ratios.py +0 -0
  215. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/nebular/oiii_electron_temperature.py +0 -0
  216. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/nebular/sii_electron_density.py +0 -0
  217. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/quality/__init__.py +0 -0
  218. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/quality/compare_snr_methods.py +0 -0
  219. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/quality/snr_der.py +0 -0
  220. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/quality/snr_edge.py +0 -0
  221. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/quality/snr_linear_fit.py +0 -0
  222. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/quality/validate_bess_header.py +0 -0
  223. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/reduction/__init__.py +0 -0
  224. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/reduction/_easyspec_apply.py +0 -0
  225. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/reduction/_easyspec_helpers.py +0 -0
  226. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/reduction/bias_combine.py +0 -0
  227. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/reduction/clip_cosmic_rays.py +0 -0
  228. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/reduction/dark_combine.py +0 -0
  229. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/reduction/dark_subtract.py +0 -0
  230. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/reduction/denoise_2d.py +0 -0
  231. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/reduction/easyspec_bias.py +0 -0
  232. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/reduction/easyspec_cosmic_ray.py +0 -0
  233. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/reduction/easyspec_dark.py +0 -0
  234. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/reduction/easyspec_flat.py +0 -0
  235. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/reduction/easyspec_flat_normalize.py +0 -0
  236. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/reduction/easyspec_subtract_bias.py +0 -0
  237. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/reduction/easyspec_subtract_dark.py +0 -0
  238. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/reduction/extract_spectrum_sum.py +0 -0
  239. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/reduction/flat_combine.py +0 -0
  240. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/reduction/flat_normalize.py +0 -0
  241. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/reduction/geometry.py +0 -0
  242. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/reduction/subtract_sky_2d.py +0 -0
  243. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/reduction/wavelength_calibrate.py +0 -0
  244. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/rv/__init__.py +0 -0
  245. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/rv/cross_correlate.py +0 -0
  246. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/rv/fit_keplerian_orbit.py +0 -0
  247. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/rv/measure.py +0 -0
  248. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/rv/precision_bouchy.py +0 -0
  249. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/rv/redshift_lines.py +0 -0
  250. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/smoothing/__init__.py +0 -0
  251. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/smoothing/_nan_bridge.py +0 -0
  252. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/smoothing/compare_smoothings.py +0 -0
  253. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/stacking/__init__.py +0 -0
  254. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/stacking/merge_echelle_orders.py +0 -0
  255. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/timeseries/__init__.py +0 -0
  256. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/timeseries/lomb_scargle.py +0 -0
  257. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/timeseries/phase_fold.py +0 -0
  258. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/transforms/__init__.py +0 -0
  259. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/transforms/clip_sigma.py +0 -0
  260. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/transforms/extract_region.py +0 -0
  261. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/transforms/mask_range.py +0 -0
  262. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/transforms/resample_flux_conserving.py +0 -0
  263. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/viz/__init__.py +0 -0
  264. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/viz/plot_3d_surface.py +0 -0
  265. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/viz/plot_animation.py +0 -0
  266. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/viz/plot_dynamic_spectrum.py +0 -0
  267. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/viz/plot_plotly.py +0 -0
  268. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/wavelength_calibration/__init__.py +0 -0
  269. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/wavelength_calibration/arc_geometry.py +0 -0
  270. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/wavelength_calibration/easyspec_wavelength.py +0 -0
  271. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/wavelength_calibration/in_situ.py +0 -0
  272. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/wavelength_calibration/lamp_atlas.py +0 -0
  273. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/wavelength_calibration/match_lamp.py +0 -0
  274. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/wavelength_calibration/reidentify.py +0 -0
  275. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/algorithms/wavelength_calibration/solar.py +0 -0
  276. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/base.py +0 -0
  277. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/embeddings.py +0 -0
  278. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/io/__init__.py +0 -0
  279. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/io/ascii.py +0 -0
  280. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/io/votable.py +0 -0
  281. {spectro_kernel-0.6.1/src/spectro_mcp → spectro_kernel-0.7.0/src/spectro_kernel}/py.typed +0 -0
  282. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/registry.py +0 -0
  283. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/types/__init__.py +0 -0
  284. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/types/catalog.py +0 -0
  285. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/types/context.py +0 -0
  286. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/types/history.py +0 -0
  287. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/types/image.py +0 -0
  288. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/types/line.py +0 -0
  289. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/types/spectrum.py +0 -0
  290. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/types/timeseries.py +0 -0
  291. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_kernel/url_safety.py +0 -0
  292. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_mcp/__init__.py +0 -0
  293. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_mcp/auth.py +0 -0
  294. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_mcp/observability.py +0 -0
  295. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_mcp/server.py +0 -0
  296. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_mcp/session.py +0 -0
  297. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/src/spectro_mcp/url_safety.py +0 -0
  298. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/conftest.py +0 -0
  299. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/reference/conftest.py +0 -0
  300. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/reference/test_known_answers.py +0 -0
  301. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/reference/test_sun.py +0 -0
  302. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/reference/test_vega.py +0 -0
  303. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_aperture_photometry.py +0 -0
  304. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_barycentric_bjd.py +0 -0
  305. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_base.py +0 -0
  306. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_catalog_queries_mocked.py +0 -0
  307. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_classify_template_chi2.py +0 -0
  308. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_cli.py +0 -0
  309. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_combine_arithmetic.py +0 -0
  310. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_continuum.py +0 -0
  311. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_corrections.py +0 -0
  312. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_cross_correlate_extension.py +0 -0
  313. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_dark_flat_combine.py +0 -0
  314. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_denoise_2d.py +0 -0
  315. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_detect_lines_blind.py +0 -0
  316. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_detect_trace.py +0 -0
  317. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_disentangle_sb2.py +0 -0
  318. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_doppler_tomogram.py +0 -0
  319. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_easyspec_apply_staging.py +0 -0
  320. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_easyspec_sessions.py +0 -0
  321. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_easyspec_wrappers.py +0 -0
  322. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_embedding.py +0 -0
  323. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_embedding_pretrained.py +0 -0
  324. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_embedding_remote_lick.py +0 -0
  325. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_embedding_tier1.py +0 -0
  326. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_export_fits_bess.py +0 -0
  327. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_export_hdf5.py +0 -0
  328. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_extract_boxcar.py +0 -0
  329. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_extract_optimal.py +0 -0
  330. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_extract_spectrum_sum.py +0 -0
  331. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_flux_calibrate_easyspec.py +0 -0
  332. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_geometry_corrections.py +0 -0
  333. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_lamp_atlas_match.py +0 -0
  334. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_line_profiles.py +0 -0
  335. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_lines.py +0 -0
  336. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_mcp.py +0 -0
  337. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_mcp_param_guard.py +0 -0
  338. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_mcp_production.py +0 -0
  339. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_mcp_security.py +0 -0
  340. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_mcp_tools_extra.py +0 -0
  341. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_measure_arc_geometry.py +0 -0
  342. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_misc_algorithms.py +0 -0
  343. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_nebular_diagnostics.py +0 -0
  344. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_no_circular_imports.py +0 -0
  345. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_normalize_to_region.py +0 -0
  346. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_output_produces_contract.py +0 -0
  347. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_pipeline.py +0 -0
  348. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_quality.py +0 -0
  349. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_read_sdss.py +0 -0
  350. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_redshift_lines.py +0 -0
  351. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_registry.py +0 -0
  352. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_reidentify.py +0 -0
  353. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_resample_flux_conserving.py +0 -0
  354. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_response_from_standard.py +0 -0
  355. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_rotation_curve.py +0 -0
  356. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_rv_precision_bouchy.py +0 -0
  357. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_sky_lateral_bands.py +0 -0
  358. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_smoothing.py +0 -0
  359. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_timeseries.py +0 -0
  360. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_transforms.py +0 -0
  361. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_types.py +0 -0
  362. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_url_safety_kernel.py +0 -0
  363. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_validate_bess_header.py +0 -0
  364. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_viz.py +0 -0
  365. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_vr_ratio.py +0 -0
  366. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_wavelength_calibration_in_situ.py +0 -0
  367. {spectro_kernel-0.6.1 → spectro_kernel-0.7.0}/tests/unit/test_wavelength_calibration_solar.py +0 -0
@@ -164,6 +164,12 @@ venv.bak/
164
164
  # Rope project settings
165
165
  .ropeproject
166
166
 
167
+ # documentation - generated by tools/docs/generate.py
168
+ docs/algorithms/
169
+ docs/recipes/catalogue/
170
+ docs/ai/
171
+ docs/llms.txt
172
+
167
173
  # mkdocs documentation
168
174
  /site
169
175
 
@@ -6,6 +6,289 @@ Until `1.0.0` the public API may change between minor versions.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.7.0] — 2026-09-26
10
+
11
+ The release that turns presets into **recipes** : a measurement written once,
12
+ with its conventions fixed and everything instrument-dependent declared as a
13
+ variable, so that observers with different spectrographs produce comparable
14
+ numbers. It also lands the bricks those recipes need for pro-am campaigns
15
+ (time-series line-profile analysis, the flux-calibration chain, stellar
16
+ activity and rotation indicators, resolving power, spline continuum) and a
17
+ FITS reader that copes with the amateur "zoo". Numerical changes are carried
18
+ by MAJOR bumps of the bricks concerned and listed below.
19
+
20
+ ### Added — recipes, variables and profiles (presets v2)
21
+
22
+ - A preset may declare a `variables` block (`type` among `str`, `int`,
23
+ `float`, `bool`, `path`, `list`; `default`, `required`, `description`,
24
+ `choices`) and reference them as `"${name}"` in step parameters. The
25
+ values come from a **profile** (`spectro pipeline <recipe> --profile
26
+ file.yaml`), from `--set name=value` (converted to the declared type),
27
+ from `PipelineBuilder().from_preset(name, variables={...})` /
28
+ `from_config(config, variables)`, or from the `variables` argument of
29
+ the MCP `run_preset` tool. Defaults fill the gaps ; a missing required
30
+ variable, an undeclared token or a value of the wrong type is refused
31
+ before anything runs, with the variable's description in the message.
32
+ A preset without `variables` is unchanged.
33
+ - `requires: ">=0.7, <1.0"` : the kernel range a recipe was validated for
34
+ (plain comparison operators) ; a recipe outside the range refuses to build.
35
+ - Standard metadata vocabulary : `kind` (`analysis`, `reduction`,
36
+ `campaign`, `template`), `status` (`draft`, `reviewed`, `reference`),
37
+ `references` (mandatory for a campaign recipe), `conventions`.
38
+ - **Discovery** : besides the bundled catalogue, the kernel lists recipes
39
+ from every directory in `SPECTRO_PRESET_PATH` and from installed
40
+ packages registering the `spectro_kernel.presets` entry point (a
41
+ `Path` to a directory of YAML files). `list_presets()` reports each
42
+ recipe's `source` ; a bundled name wins over an external one.
43
+ - **Validation** : `spectro preset validate <file-or-name>...` (also
44
+ `--profile` / `--set` to type-check values) reports every problem at
45
+ once : name not snake_case, missing or malformed version, missing
46
+ description, unknown `kind` / `status`, campaign recipe without
47
+ references, unsatisfied `requires`, unknown algorithm, unknown parameter,
48
+ required parameter neither set nor bound, undeclared token, unused
49
+ variable, `depends_on` matching no step. `spectro preset show <name>`
50
+ prints a recipe's variables and steps ; `spectro presets` shows the
51
+ source and the number of variables. Python : `validate_preset`,
52
+ `validate_preset_file`, `preset_sources`, `find_preset`.
53
+ - **Provenance** : every named pipeline built from a file or a config
54
+ closes its run with a `pipeline:<name>` `ProcessingStep` carrying the
55
+ recipe version, the bound variables, the kernel version and the source,
56
+ so a result states which recipe produced it. Ad-hoc pipelines assembled
57
+ in Python without a name are unchanged.
58
+ - The bundled `full_reduction_easyspec` template (2.0.0) replaces its
59
+ `__REPLACE__` placeholders by ten declared variables (`bias_dir`,
60
+ `dark_dir`, `flat_dir`, `science_path`, `exposure_seconds`, `airmass`,
61
+ `gain`, `readnoise`, `target_name`, `combine_method`) ; the six analysis
62
+ presets gain `kind` and `status` metadata. The preset file format is
63
+ published as `preset.schema.json`.
64
+ - The curated collection lives in a separate repository,
65
+ [spectro-kernel-recipes](https://github.com/matthieulel/spectro-kernel-recipes)
66
+ (`pip install spectro-kernel-recipes`), starting with `be_halpha_ew`,
67
+ `binary_rv_ccf`, `solar_long_slit` and `stellar_long_slit` (all `draft`).
68
+
69
+ ### Added — time-series line-profile analysis (category `timeseries`, `stacking`)
70
+
71
+ - **`temporal_variance_spectrum` v1.0.0** (scipy) — Fullerton, Gies & Bolton
72
+ 1996, ApJS 103, 475, §3 : N ≥ 3 continuum-normalised epochs in
73
+ `ctx.spectra`, resampled on the finest common grid over the overlap ;
74
+ per-epoch noise σ_ic from `uncertainty` or DER_SNR on a continuum window
75
+ (`continuum_lo` / `continuum_hi`) ; weights w_i = (σ_0/σ_ic)² with
76
+ σ_0 = [(1/N) Σ σ_ic⁻²]^(−1/2) ; (TVS)_j = (N−1)⁻¹ Σ_i w_i (S_ij − S̄_j)² ;
77
+ reported as (TVS)^{1/2} with the χ²_(N−1) significance threshold at
78
+ `confidence` (0.99). Writes `extras.tvs` and the `tvs_*` metrics, the
79
+ bounds of the longest significant run as `tvs_variable_lo_aa` /
80
+ `tvs_variable_hi_aa`. Caveat documented : the pixel-dependent
81
+ photon-noise term α_ij of the paper is not applied (uniform noise across
82
+ the profile). Tests : variability confined to |v| < 120 km/s → 71 % of
83
+ pixels flagged inside, 2.2 % beyond 200 km/s ; no variability → 1.2 %
84
+ above the 99 % threshold ; threshold exact to 1e-12.
85
+ - **`phase_dispersion_minimization` v1.0.0** (numpy) — Stellingwerf 1978,
86
+ ApJ 224, 953 : Θ = s²/σ² over M = N_b·N_c overlapping phase samples
87
+ (`n_bins` 10, `n_covers` 3), uniform frequency grid (`n_periods` 2000),
88
+ light-curve input exactly as `lomb_scargle`. `ctx.periodograms[key]`
89
+ carries Θ with `meta.lower_is_better` ; metrics `pdm_best_period_days`,
90
+ `pdm_theta_min`. No false-alarm probability on purpose
91
+ (Schwarzenberg-Czerny 1997, ApJ 489, 941). Tests : eclipse and sawtooth
92
+ signals at 3.7 d over 60 d recovered to 0.11 % ; pure noise → Θ ≈ 1.00.
93
+ - **`box_least_squares` v1.0.0** (astropy) — Kovács, Zucker & Mazeh 2002,
94
+ A&A 391, 369, wrapping `astropy.timeseries.BoxLeastSquares` ;
95
+ `duration_hours` list, `objective` likelihood / snr ; periodogram plus
96
+ `extras.bls_model` and the `bls_*` metrics. Without uncertainties the
97
+ noise is 1.4826·MAD (Rousseeuw & Croux 1993) instead of astropy's
98
+ implicit σ = 1 (which gave a 41-σ transit an SNR of 0.09). Tests :
99
+ P = 2.5 d, depth 1 %, 3 h box on a 30 d series → period to 0.012 %,
100
+ depth to 1.8 %, SNR 41.
101
+ - **`stack_spectra` 2.0.0 → 2.1.0** (additive) : `method: "weighted"`, the
102
+ Bevington & Robinson inverse-variance mean with the stack uncertainty
103
+ (Σ w)^(−1/2) ; weights from the `weights` parameter, else from every
104
+ spectrum's `uncertainty`, else from DER_SNR² (Tody 1993, IRAF `scombine`).
105
+ mean / median / sum are bit-identical to v2.0.0. Test : σ = 1 and 2 →
106
+ weights 4:1, output σ = 1/√1.25.
107
+
108
+ ### Added — flux-calibration chain (categories `correction`, `catalog`, `nebular`)
109
+
110
+ - **`atmospheric_extinction_correct` v1.0.0** (numpy) — F_0 = F·10^{0.4 k(λ) X}
111
+ (Hayes & Latham 1975, ApJ 197, 593 ; Hardie 1962). Built-in `curve`
112
+ `"kpno"`, the IRAF `onedstds$kpnoextinct.dat` mean extinction table
113
+ (3200–10400 Å, Tody 1986 ; all 82 nodes checked against the IRAF source,
114
+ the last four being CTIO values), or a user table in `ctx.extras`. Airmass from
115
+ `airmass`, else from the header / site with Kasten & Young 1989, Appl.
116
+ Opt. 28, 4735, eq. 3. Uncertainty scaled with the flux. Metrics
117
+ `airmass`, `k_mag_median`, `n_outside_curve`.
118
+ - **`deredden_interstellar` v1.0.0** (dust_extinction, optional extra
119
+ `reduction`) — F_0 = F / 10^{−0.4 A(λ)} with CCM89 (Cardelli, Clayton &
120
+ Mathis 1989, ApJ 345, 245 ; default), F99 (Fitzpatrick 1999, PASP 111,
121
+ 63) or G23 (Gordon et al. 2023, ApJ 950, 86) ; `ebv`, `rv` (3.1) ; fails
122
+ outside a law's validity range. Test : CCM89, R_V = 3.1, E(B−V) = 0.1 at
123
+ 5500 Å → factor 10^{0.4·0.31} = 1.330, checked against the package.
124
+ - **`standard_star_reference` v1.0.0** (astropy ; network, lazy) — loads a
125
+ CALSPEC standard (Bohlin, Gordon & Tremblay 2014, PASP 126, 711 ; Bohlin,
126
+ Hubeny & Rauch 2020, AJ 160, 21) by name or `filename` from the STScI
127
+ reference-atlas archive through the SSRF-guarded fetch with timeout and
128
+ size cap, or a Pickles 1998 (PASP 110, 863) template ; vacuum → air with
129
+ Morton 2000 (`to_air`) ; writes `extras.catalog_spectrum` (rename with
130
+ `output_key`, e.g. to `reference_spectrum` for `response_from_standard`).
131
+ Pickles templates are normalised to unity at 5556 Å by construction
132
+ (Pickles 1998, §3 and §5) and passed through unchanged ; the brick reports
133
+ `flux_at_5556_aa` so the caller can see it.
134
+ - **`balmer_decrement_extinction` v1.0.0** (scipy) — c(Hβ), E(B−V) and A_V
135
+ from the observed Hα/Hβ ratio against Case B 2.86 (Osterbrock & Ferland
136
+ 2006, Table 4.4, §7.2) with the CCM89 f(λ) ; negative extinction clamped
137
+ to 0 with a note ; metrics `balmer_ratio_observed`, `c_hbeta`,
138
+ `ebv_balmer`, `a_v_balmer`, `flux_halpha`, `flux_hbeta`.
139
+
140
+ ### Changed — uncertainties are now propagated (MAJOR bumps ; flux byte-identical)
141
+
142
+ Until now every one of these bricks copied the input `uncertainty` array
143
+ unchanged, which is wrong after any of them. Each now documents its rule ;
144
+ a spectrum without uncertainty is processed exactly as before.
145
+
146
+ - `smooth_gaussian` 1.0.1 → 2.0.0 and `smooth_savgol` 1.0.1 → 2.0.0 :
147
+ σ_out,i = sqrt(Σ_k w_k² σ²) with the very kernel applied (Gaussian
148
+ truncated at 4σ ; Savitzky-Golay coefficients incl. the edge polynomials).
149
+ White noise, sigma = 2 px → σ_out = 0.376 σ in the interior and 0.641 σ
150
+ at the first and last samples (the 'nearest' edge weights add before
151
+ squaring) ; window 11 / order 3 → 0.4555 σ. Both checked against the full
152
+ linear operator to 1e-9 and by Monte-Carlo. Correlated noise is not
153
+ tracked (documented).
154
+ - `normalize_polynomial` 1.1.1 → 2.0.0, `normalize_to_region` 1.0.1 →
155
+ 2.0.0, `normalize_max` 1.0.2 → 2.0.0, `normalize_percentile` 1.0.2 →
156
+ 2.0.0, `normalize_edges` 1.0.2 → 2.0.0 : σ_out = σ_in / |continuum|,
157
+ continuum treated as noise-free.
158
+ - `resample_linear` 1.0.1 → 2.0.0 : σ_out = sqrt(interp(σ²)) (linear
159
+ interpolation of the variance ; v1 interpolated σ itself).
160
+ - `combine_spectra_arithmetic` 1.0.1 → 2.0.0 : add/sub in quadrature ;
161
+ mul/div with the relative errors in quadrature when the reference
162
+ carries an uncertainty (Bevington & Robinson §3.2), else σ·|r| or σ/|r|.
163
+
164
+ ### Added — stellar activity, rotation, resolution, continuum (new category `activity`)
165
+
166
+ - **`activity_index_caii_hk` v1.0.0** (numpy, `activity`) — the Mount
167
+ Wilson S index, S = α (H + K)/(R + V) with the HKP-2 triangular 1.09 Å
168
+ H and K bands and the 20 Å R and V bands (Vaughan, Preston & Wilson 1978,
169
+ PASP 90, 267 ; Duncan et al. 1991, ApJS 76, 383), `alpha` 2.3 (échelle
170
+ convention, Lovis et al. 2011) with an optional linear calibration to the
171
+ Mount Wilson scale ; log R'_HK when `b_v` is given (Noyes et al. 1984,
172
+ ApJ 279, 763 ; Middelkoop 1982, A&A 107, 31). Fails outside 3890–4011 Å.
173
+ - **`activity_index_halpha` v1.0.0** (numpy, `activity`) — Gomes da Silva
174
+ et al. 2011, A&A 534, A30 (after Boisse et al. 2009, A&A 495, 959) : 1.6 Å
175
+ core at 6562.808 Å over the 6550.87 ± 5.375 Å and 6580.31 ± 4.375 Å
176
+ reference bands ; `halpha_index` and its error.
177
+ - **`ccf_bisector` v1.0.0** (numpy, `activity`) — bisector of the CCF
178
+ written by `cross_correlate_rv` (or of one line of the spectrum) after
179
+ Toner & Gray 1988, ApJ 334, 1008, and the bisector inverse slope BIS =
180
+ v_top(10–40 %) − v_bottom(55–90 %) of Queloz et al. 2001, A&A 379, 279 ;
181
+ `bis_kms`, `bisector_span_kms`, `extras.ccf_bisector`. Symmetric profile
182
+ → BIS = 0 within 0.01 km/s.
183
+ - **`vsini_fourier` v1.0.0** (scipy, `kinematics`) — v sin i from the first
184
+ zero of the Fourier transform of a line profile (Carroll 1933, MNRAS 93,
185
+ 478 ; Gray 2005, ch. 18) with q₁(ε) from Dravins, Lindegren & Nordlund
186
+ 1990, A&A 228, 203 (`epsilon` 0.6 → q₁ = 0.660) ; the first zero is
187
+ accepted only when the side lobe stands above the Fourier noise floor
188
+ (`metrics.fourier_noise_floor`, `fourier_sidelobe_ratio`), and unresolved,
189
+ emission or noise-dominated lines fail explicitly. Tests : 30, 80 and
190
+ 150 km/s recovered within 5 % at 0.5 % noise. Reference to the modern
191
+ recipe : Díaz, González, Levato & Grosso 2011, A&A 531, A143.
192
+ - **`measure_resolving_power` v1.0.0** (scipy, `quality`) — R = λ/FWHM from
193
+ Gaussian fits of the `n_lines` strongest isolated lamp / sky lines
194
+ (isolation by `min_separation_aa`), median and scatter of R, instrumental
195
+ FWHM in Å and km/s (Gray 2005, ch. 12 ; Tody 1986, IRAF `splot`). Test :
196
+ 12 lines of FWHM = λ/5000 → R = 5000 ± 2 %.
197
+ - **`normalize_spline` v1.0.0** (scipy, `continuum`) — the IRAF
198
+ `continuum` recipe (Tody 1986 ; Tody 1993) : iteratively clipped cubic
199
+ spline (`n_knots`, `low_reject` 2.0, `high_reject` 3.0, `niterate` 10,
200
+ `grow` 0), `extras.continuum_spline`, σ/continuum propagated ;
201
+ cross-references `normalize_polynomial`.
202
+
203
+ ### Changed — FITS reading and writing (`read_fits` 2.0.0 → 3.0.0, `io/fits.py`)
204
+
205
+ The reader now takes explicit, documented decisions on the FITS "zoo"
206
+ (audit items C6 / C7) ; 37 new tests in `test_io_fits_zoo.py`.
207
+
208
+ - `CD1_1` wins over `CDELT1` when both exist (Greisen & Calabretta 2002 ;
209
+ v2 preferred `CDELT1`), `PC1_1` scales `CDELT1` ; `CUNIT1` (or IRAF
210
+ `WAT1` units) in nm / µm / m converted to Å with the original label in
211
+ `meta["wavelength_unit_original"]` ; WAVE-LOG (Paper III) and IRAF
212
+ `DC-FLAG` handling unchanged.
213
+ - No dispersion keywords → 0-based pixel axis, `wavelength_unit="pixel"`,
214
+ `meta["wcs"]="none"` (v2 labelled the pixel index "Angstrom").
215
+ - A genuine 2-D image is refused unless the new `row` parameter selects a
216
+ row (v2 silently returned row 0) ; length-1 axes are squeezed ; IRAF
217
+ multispec / échelle markers redirect to `read_echelle_fits` ; 3-D cubes
218
+ are refused.
219
+ - Extension selection : a data-bearing PRIMARY wins over tables (v2
220
+ preferred any table) ; otherwise the first table with recognisable
221
+ wavelength / flux columns (incl. SDSS `loglam`) ; the new `hdu`
222
+ parameter (index or EXTNAME) overrides ; when nothing is readable the
223
+ error lists the HDUs found.
224
+ - `ERROR` / `ERR` / `ERRS` / `SIGMA` / `UNCERT(AINTY)` (1σ) and `IVAR`
225
+ (1/√ivar) image extensions and error / ivar table columns fill
226
+ `uncertainty` ; `MASK` extensions and `mask` / `and_mask` columns fill
227
+ `mask` ; `BUNIT` becomes the flux unit ; descending axes are kept and
228
+ flagged `meta["wavelength_descending"]`.
229
+ - `write_fits` : the linear layout now appends `ERROR` and `MASK`
230
+ extensions when the spectrum carries them, read back by `read_fits`
231
+ (round-trip tested) ; a spectrum without either is still a single HDU.
232
+
233
+
234
+ ### Documentation
235
+
236
+ - A new **Recipes** section (the recipe / profile idea, the format
237
+ reference, how to share a recipe) and a generated recipe catalogue with
238
+ one page per recipe plus `/ai/presets.json` ; the CLI, MCP, pipelines and
239
+ reduction-walkthrough pages updated accordingly.
240
+
241
+ - The long-slit tutorial is now worked on a **solar** spectrum (Fraunhofer
242
+ wavelength calibration, no lamp) with a **stellar** arc-lamp variant ;
243
+ the aurora example is gone. Its code samples were also corrected : the
244
+ 2-D reduction runs from Python (`spectro pipeline` loads 1-D spectra) and
245
+ the lamp hand-off uses the real `lamp_identifications` keys.
246
+ - The BeSS-dashboard cookbook page is removed ; the aurora line-monitor
247
+ notebook is parked in `docs/.drafts/` (not published) for a later return.
248
+
249
+ ## [0.6.2] — 2026-09-19
250
+
251
+ A documentation and web release : the docs move to a generated,
252
+ agent-readable site at https://docs.spectrokernel.io/, the landing page is
253
+ rebuilt around the open MCP server, and the server gains CORS so the web
254
+ playground can use it. No algorithm changes.
255
+
256
+ ### MCP server
257
+
258
+ - CORS for browser clients in HTTP mode : `SPECTRO_MCP_CORS_ORIGINS`
259
+ (default : the spectrokernel.io sites ; `*` or `none`), with the
260
+ `Mcp-Session-Id` header exposed, so the web playground on the landing
261
+ page can talk to the public server. Pre-flights are answered before the
262
+ API-key check.
263
+
264
+ ### Documentation — new build pipeline and hosting (no package change)
265
+
266
+ - The site is now built with **Zensical** (the Material for MkDocs team's
267
+ successor engine, reading the unchanged `mkdocs.yml`) and published at
268
+ **https://docs.spectrokernel.io/** by Netlify, which builds it from the
269
+ repository (base directory `tools/docs`, see `tools/docs/netlify.toml`) ;
270
+ pull requests get a deploy preview and GitHub Actions keeps a strict build
271
+ check. `mkdocs build` keeps working as a fallback.
272
+ - The algorithm catalogue is generated *before* the build by
273
+ `tools/docs/generate_catalogue.py` (Zensical runs no MkDocs plugin such as
274
+ `gen-files`) : one page per algorithm under `/algorithms/<category>/<name>/`
275
+ (summary, backend, version, context reads/writes, parameter table, Python /
276
+ CLI / MCP call examples, references, related algorithms), a category index,
277
+ and a navigation tree consumed by `literate-nav`.
278
+ - Machine-readable layer for agents and tooling : `/ai/algorithms.json`
279
+ (validated at build time against `/ai/schemas/algorithms.schema.json`,
280
+ schema version 1, stamped with the package version), a curated `/llms.txt`
281
+ derived from the navigation, and the Markdown source of every page served
282
+ next to its HTML (`<page>/index.md`). Netlify headers set the content types
283
+ and CORS on `/ai/*`.
284
+ - `tools/docs/build.py` reproduces the CI build locally (generators + strict
285
+ build + post-processing) ; `tools/docs/generate.py && zensical serve` for
286
+ live preview. Generated files (`docs/algorithms/`, `docs/ai/`,
287
+ `docs/llms.txt`) are git-ignored. `.readthedocs.yaml` and
288
+ `docs/gen_catalogue.py` are removed ; the `docs` extra now installs
289
+ `zensical`, `mkdocstrings[python]`, `mkdocs-material`,
290
+ `mkdocs-literate-nav`, `jsonschema`.
291
+
9
292
  ## [0.6.1] — 2026-09-19
10
293
 
11
294
  A correctness and hardening release driven by a full audit of the
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: spectro-kernel
3
- Version: 0.6.1
3
+ Version: 0.7.0
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
- Project-URL: Documentation, https://matthieulel.github.io/spectro-kernel/
6
+ Project-URL: Documentation, https://docs.spectrokernel.io/
7
7
  Project-URL: Source, https://github.com/matthieulel/spectro-kernel
8
8
  Project-URL: Issues, https://github.com/matthieulel/spectro-kernel/issues
9
9
  Project-URL: Changelog, https://github.com/matthieulel/spectro-kernel/blob/main/CHANGELOG.md
@@ -54,9 +54,12 @@ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
54
54
  Requires-Dist: pytest>=8.0; extra == 'dev'
55
55
  Requires-Dist: ruff>=0.5; extra == 'dev'
56
56
  Provides-Extra: docs
57
- Requires-Dist: mkdocs-gen-files>=0.5; extra == 'docs'
57
+ Requires-Dist: jsonschema>=4.0; extra == 'docs'
58
+ Requires-Dist: mkdocs-literate-nav>=0.6; extra == 'docs'
58
59
  Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
59
60
  Requires-Dist: mkdocstrings[python]>=0.26; extra == 'docs'
61
+ Requires-Dist: pyyaml>=6.0; extra == 'docs'
62
+ Requires-Dist: zensical>=0.0.62; extra == 'docs'
60
63
  Provides-Extra: embedding-ml
61
64
  Requires-Dist: torch>=2.2; extra == 'embedding-ml'
62
65
  Provides-Extra: embedding-remote
@@ -197,6 +200,7 @@ by environment variable (none of these affect stdio mode) :
197
200
  | `SPECTRO_MCP_ALLOW_KEY_IN_URL` | unset | `1` also accepts the key as `?api_key=…` in the URL (for claude.ai / Claude Desktop connectors, which cannot set headers); the parameter is scrubbed before access logging. `Authorization: Bearer <key>` is always accepted. |
198
201
  | `SPECTRO_MCP_RATE_PER_MINUTE` | `0` (off) | Sliding-window request limit per API key (per client IP when auth is off). |
199
202
  | `SPECTRO_MCP_TRUSTED_PROXY` | unset | `1` behind a load balancer: trust `X-Forwarded-For` for the client IP. |
203
+ | `SPECTRO_MCP_CORS_ORIGINS` | spectrokernel.io sites | Comma-separated browser origins allowed to call the server (`*` for any, `none` to disable). The `Mcp-Session-Id` header is exposed to browsers. |
200
204
  | `SPECTRO_MCP_MAX_SESSIONS` | `200` | Cap on live in-memory sessions; the least recently used one is evicted. |
201
205
  | `SPECTRO_MCP_MAX_PIXELS` | `32000000` | Refuse downloaded FITS files with more data elements than this (256 MB as float64); `0` disables. |
202
206
  | `SPECTRO_MCP_DOWNLOAD_BUDGET_S` | `120` | Wall-clock budget for one URL download (on top of the 256 MiB cap). |
@@ -206,6 +210,16 @@ by environment variable (none of these affect stdio mode) :
206
210
  | `SPECTRO_MCP_S3_BUCKET`, `SPECTRO_MCP_S3_ENDPOINT`, … | unset | Presigned-URL uploads (`request_upload_url`). |
207
211
  | `SENTRY_DSN` | unset | Error reporting. |
208
212
 
213
+ ## Recipes and profiles
214
+
215
+ A recipe (preset) is a measurement written once with its conventions fixed;
216
+ what depends on your instrument is a variable, bound by a profile at run
217
+ time: `spectro pipeline be_halpha_ew --input obs.fits --profile my_setup.yaml`.
218
+ Generic recipes ship with the kernel; campaign recipes live in the curated
219
+ [spectro-kernel-recipes](https://github.com/matthieulel/spectro-kernel-recipes)
220
+ collection (`pip install spectro-kernel-recipes`). See the
221
+ [Recipes](https://docs.spectrokernel.io/recipes/) documentation.
222
+
209
223
  ## Architecture
210
224
 
211
225
  ```
@@ -234,7 +248,7 @@ from the registry. Build it locally with:
234
248
 
235
249
  ```bash
236
250
  uv pip install -e ".[docs,all]"
237
- mkdocs serve # live preview at http://127.0.0.1:8000
251
+ python tools/docs/generate.py && zensical serve # live preview at http://127.0.0.1:8000
238
252
  ```
239
253
 
240
254
  Every algorithm declares its **provenance** — a `backend` (the library it leans on) and
@@ -111,6 +111,7 @@ by environment variable (none of these affect stdio mode) :
111
111
  | `SPECTRO_MCP_ALLOW_KEY_IN_URL` | unset | `1` also accepts the key as `?api_key=…` in the URL (for claude.ai / Claude Desktop connectors, which cannot set headers); the parameter is scrubbed before access logging. `Authorization: Bearer <key>` is always accepted. |
112
112
  | `SPECTRO_MCP_RATE_PER_MINUTE` | `0` (off) | Sliding-window request limit per API key (per client IP when auth is off). |
113
113
  | `SPECTRO_MCP_TRUSTED_PROXY` | unset | `1` behind a load balancer: trust `X-Forwarded-For` for the client IP. |
114
+ | `SPECTRO_MCP_CORS_ORIGINS` | spectrokernel.io sites | Comma-separated browser origins allowed to call the server (`*` for any, `none` to disable). The `Mcp-Session-Id` header is exposed to browsers. |
114
115
  | `SPECTRO_MCP_MAX_SESSIONS` | `200` | Cap on live in-memory sessions; the least recently used one is evicted. |
115
116
  | `SPECTRO_MCP_MAX_PIXELS` | `32000000` | Refuse downloaded FITS files with more data elements than this (256 MB as float64); `0` disables. |
116
117
  | `SPECTRO_MCP_DOWNLOAD_BUDGET_S` | `120` | Wall-clock budget for one URL download (on top of the 256 MiB cap). |
@@ -120,6 +121,16 @@ by environment variable (none of these affect stdio mode) :
120
121
  | `SPECTRO_MCP_S3_BUCKET`, `SPECTRO_MCP_S3_ENDPOINT`, … | unset | Presigned-URL uploads (`request_upload_url`). |
121
122
  | `SENTRY_DSN` | unset | Error reporting. |
122
123
 
124
+ ## Recipes and profiles
125
+
126
+ A recipe (preset) is a measurement written once with its conventions fixed;
127
+ what depends on your instrument is a variable, bound by a profile at run
128
+ time: `spectro pipeline be_halpha_ew --input obs.fits --profile my_setup.yaml`.
129
+ Generic recipes ship with the kernel; campaign recipes live in the curated
130
+ [spectro-kernel-recipes](https://github.com/matthieulel/spectro-kernel-recipes)
131
+ collection (`pip install spectro-kernel-recipes`). See the
132
+ [Recipes](https://docs.spectrokernel.io/recipes/) documentation.
133
+
123
134
  ## Architecture
124
135
 
125
136
  ```
@@ -148,7 +159,7 @@ from the registry. Build it locally with:
148
159
 
149
160
  ```bash
150
161
  uv pip install -e ".[docs,all]"
151
- mkdocs serve # live preview at http://127.0.0.1:8000
162
+ python tools/docs/generate.py && zensical serve # live preview at http://127.0.0.1:8000
152
163
  ```
153
164
 
154
165
  Every algorithm declares its **provenance** — a `backend` (the library it leans on) and
@@ -0,0 +1,7 @@
1
+ # Drafts (not published)
2
+
3
+ Pages parked here are excluded from the site: both Zensical and MkDocs skip
4
+ dot-directories. Move a page back under `docs/` (and add it to the `nav` in
5
+ `mkdocs.yml`) to publish it again.
6
+
7
+ - `notebooks/aurora-line-monitor.md` - parked on 2026-09-19, to be reinstated later.
@@ -103,7 +103,7 @@ principle](../why.md#the-principle-we-do-not-reinvent). Every algorithm declares
103
103
  - its **`references`** - the literature for the method, or the wrapped library.
104
104
 
105
105
  Both are visible in `spectro describe <name>`, in the
106
- [catalogue](../catalogue.md), and in every MCP tool description. Nothing is a black box:
106
+ [catalogue](../algorithms/index.md), and in every MCP tool description. Nothing is a black box:
107
107
  you can always see what an algorithm stands on and where the method comes from.
108
108
 
109
109
  ## Naming conventions
@@ -90,7 +90,12 @@ spectro pipeline balmer_quick --input obs.fits # run one
90
90
  ```
91
91
 
92
92
  Presets are why an analysis can be cited and reproduced: *"this measurement used the
93
- `balmer_quick` v1.0.0 preset"* is a precise, checkable statement.
93
+ `balmer_quick` v1.0.0 preset"* is a precise, checkable statement. Since v0.7.0 a
94
+ preset can declare **variables** (the instrument- or observer-dependent values)
95
+ that a **profile** supplies at run time, and every run closes with a
96
+ `pipeline:<name>` record in the history naming the recipe, its version and the
97
+ bound values. The [Recipes](../recipes/index.md) section explains the idea and
98
+ the [format](../recipes/format.md) page is the reference.
94
99
 
95
100
  ## Reproducibility {#reproducibility}
96
101
 
@@ -57,10 +57,10 @@ CI runs the same checks on every pull request; keep `main` green.
57
57
 
58
58
  ```bash
59
59
  uv pip install -e ".[docs,all]"
60
- mkdocs serve # live preview at http://127.0.0.1:8000
61
- mkdocs build # static build into site/
60
+ python tools/docs/generate.py && zensical serve # live preview at http://127.0.0.1:8000
61
+ python tools/docs/build.py # what CI runs: generators + strict build into site/
62
62
  ```
63
63
 
64
- The [algorithm catalogue](catalogue.md) page is *generated* from the registry at build
64
+ The [algorithm catalogue](algorithms/index.md) page is *generated* from the registry at build
65
65
  time - you never edit it by hand. Add a docstring and metadata to your algorithm and the
66
66
  catalogue page documents it automatically.
@@ -114,4 +114,4 @@ The agent now sees every algorithm as a tool. See [As an MCP server](usage/mcp.m
114
114
  catalogue](tutorials/discover-the-catalogue.md).
115
115
  - Understand the moving parts → [Concepts: architecture](concepts/architecture.md).
116
116
  - A guided, end-to-end analysis → [Tutorial: analyse a spectrum](tutorials/analyse-a-spectrum.md).
117
- - Browse everything available → [Algorithm catalogue](catalogue.md).
117
+ - Browse everything available → [Algorithm catalogue](algorithms/index.md).
@@ -49,7 +49,7 @@ through MCP, you can do from a terminal, and vice-versa.
49
49
  your first analysis in five minutes.
50
50
  - :material-sitemap: **[Concepts](concepts/architecture.md)** - the architecture,
51
51
  the data types, the registry, the pipelines.
52
- - :material-book-open-variant: **[Algorithm catalogue](catalogue.md)** - every
52
+ - :material-book-open-variant: **[Algorithm catalogue](algorithms/index.md)** - every
53
53
  algorithm, auto-generated from the code.
54
54
  - :material-school: **[Tutorials](tutorials/first-spectrum.md)** - from *"I captured a
55
55
  spectrum of a star, now what?"* all the way to writing your own algorithm.
@@ -63,8 +63,8 @@ natural answer; today the cleanest path is the Python snippet above.)
63
63
 
64
64
  ## Going further
65
65
 
66
- - Replace the synthetic spectra with real BeSS extractions - see the
67
- [BeSS cookbook page](../cookbook/bess-dashboard.md).
66
+ - Replace the synthetic spectra with real BeSS extractions: `read_fits` reads
67
+ them directly (see [As a Python library](../usage/library.md)).
68
68
  - Add `compare_normalisations` (Tier 2+) before stacking when continuum
69
69
  variations between nights are suspect.
70
70
  - Couple it with `lomb_scargle` on a per-epoch line-strength metric to look for
@@ -136,7 +136,7 @@ beyond `spectro-mcp --http`.
136
136
  workflows (e.g. "always run `compare_normalisations` before measuring a
137
137
  line").
138
138
  - Wrap the agent in a periodic task (cron + a Claude API call) for nightly
139
- monitoring - Be-star variability alerts, aurora amplitude history,
139
+ monitoring - Be-star variability alerts, solar line monitoring,
140
140
  exoplanet RV drift.
141
141
  - Pair with the [web playground](../cookbook/web-playground.md) for human-in-the-loop
142
142
  debugging when the agent picks the wrong tool.
@@ -109,30 +109,40 @@ run_algorithm(
109
109
  # → ctx.spectrum.flux is now in erg/s/cm²/Å.
110
110
  ```
111
111
 
112
- ## The same as a preset
112
+ ## The same as a recipe
113
+
114
+ The whole chain (steps 1-3, the file-driven portion) is the bundled recipe
115
+ `full_reduction_easyspec`. Everything that depends on your night is a
116
+ variable of the recipe; you supply the values with a profile:
117
+
118
+ ```yaml
119
+ # night_2026-06-09.yaml
120
+ bias_dir: /data/biases
121
+ dark_dir: /data/darks
122
+ flat_dir: /data/flats
123
+ science_path: /data/science/alf_cyg_001.fits
124
+ exposure_seconds: 300
125
+ airmass: 1.18
126
+ target_name: alf Cyg
127
+ ```
128
+
129
+ ```bash
130
+ spectro preset show full_reduction_easyspec # the variables and their meaning
131
+ spectro pipeline full_reduction_easyspec --profile night_2026-06-09.yaml
132
+ ```
113
133
 
114
- The whole chain (steps 1-3 - the parameter-free, file-driven portion) is
115
- templated in the bundled preset
116
- [`full_reduction_easyspec`](https://github.com/matthieulel/spectro-kernel/blob/main/src/spectro_kernel/presets/catalog/reduction/full_reduction_easyspec.yaml).
117
- It is a *template*: the `__REPLACE__` placeholders are the runtime paths you fill
118
- in before building the pipeline. A typical usage:
134
+ Or from Python:
119
135
 
120
136
  ```python
121
- from spectro_kernel import PipelineBuilder, WorkContext
122
- from spectro_kernel.presets import load_preset
123
-
124
- config = load_preset("full_reduction_easyspec")
125
- for step in config["steps"]:
126
- p = step["params"]
127
- for key, value in p.items():
128
- if isinstance(value, str) and value.startswith("__REPLACE_WITH_BIAS_DIR__"):
129
- p[key] = "/data/biases"
130
- elif isinstance(value, str) and value.startswith("__REPLACE_WITH_DARK_DIR__"):
131
- p[key] = "/data/darks"
132
- # … etc.
133
-
134
- pipeline = PipelineBuilder().from_config(config).build()
137
+ import yaml
138
+
139
+ from spectro_kernel import WorkContext
140
+ from spectro_kernel.pipeline import PipelineBuilder
141
+
142
+ profile = yaml.safe_load(open("night_2026-06-09.yaml"))
143
+ pipeline = PipelineBuilder().from_preset("full_reduction_easyspec", profile).build()
135
144
  result = pipeline.execute(WorkContext())
145
+ print(result.history[-1]) # pipeline:full_reduction_easyspec v2.0.0, the bound variables
136
146
  ```
137
147
 
138
148
  Steps 4-6 (wavelength + extinction + flux) stay separate calls because their