Skip to main content

Peak Detection

This page documents the absorption-line detection step of the AstroSpectro pipeline: the PeakDetector class finds local flux minima in a normalised spectrum and links them to a small vocabulary of six reference lines. Its output seeds the line-based features computed by the feature engineering step. The page describes the code; it quotes no run-level result.

Scope

PeakDetector is deliberately minimal. It only answers "is there a significant minimum near this reference wavelength, and how deep is it?". Line widths, equivalent widths, indices and molecular bands are computed afterwards by FeatureEngineer (see Feature Engineering).


Why this step exists​

Spectral classification relies on a handful of lines whose strength changes with temperature and luminosity. Rather than fitting every line, the pipeline first locates the minimum nearest to each expected position, so that downstream measurements (full width at half maximum, equivalent width) start from the right pixel even when the line is shifted by a few ångströms.

Pipeline position​


Algorithm​

  1. Mask non-finite wavelength/flux pairs so that indices stay aligned.
  2. Invert the flux (-flux): absorption minima become positive peaks.
  3. Detect peaks with scipy.signal.find_peaks(inverted_flux, prominence=prominence). Only the prominence criterion is used — no width or height constraint.
  4. Associate: for each reference line, keep the detected peak within ± window Å of the reference wavelength that has the highest prominence. If none exists, the line is reported as unmatched (None).

Reference lines​

The vocabulary is a hard-coded dictionary (PeakDetector.target_lines), in this order:

KeyReference λ (Å)Role in the code comment
Hα6563.0Balmer series (hot A/F stars)
Hβ4861.0Balmer series
CaII K3933.0Calcium
CaII H3968.0Calcium
Mg_b5175.0Magnesium triplet, approximate centre (cooler G/K stars)
Na_D5893.0Sodium doublet, approximate centre (cooler G/K stars)
Not a NIST table

These wavelengths are rounded, hard-coded values in the module; the code does not read a NIST list or any external line database. Mg b and Na D are blend centres, not individual components. The more precise rest wavelengths used elsewhere (e.g. Hα 6562.8 Å, Ca II K 3933.7 Å) live in SpectralLineLibrary inside feature_engineering.py and are used for the feature measurements, not for peak association.

Parameters​

ParameterPeakDetector defaultValue used by ProcessingPipelineMeaning
prominence0.850.15Minimum prominence of an inverted peak, in normalised-flux units
window28 Å8 ÅHalf-width of the association window around each reference wavelength

The class defaults and the values actually used in production differ. ProcessingPipeline.__init__ defaults to prominence=0.15, window=8, and MasterPipeline.process_data() instantiates it without overriding them, so a standard run uses 0.15 and 8 Å. The docstring example PeakDetector(prominence=0.85, window=28) describes the standalone class defaults only.

A lower prominence yields more candidate minima (more noise-driven matches in low-SNR spectra); a wider window tolerates larger offsets but can pick a neighbouring feature. The repository does not record a sensitivity study of these two values.


Outputs​

analyze_spectrum(wavelength, flux) returns a dictionary with the same keys and order as target_lines: (detected_wavelength, prominence) or None.

# src/pipeline/peak_detector.py
from pipeline.peak_detector import PeakDetector, matches_to_dataframe, matches_to_series

detector = PeakDetector(prominence=0.15, window=8)
matches = detector.analyze_spectrum(wavelength, flux_norm)
matches["Hβ"] # (λ_detected, prominence) or None
matches_to_dataframe(matches) # index = line; columns lambda_A, prominence, matched
matches_to_series(matches, order=["Hα", "Hβ"], prefix="match_")
HelperReturns
matches_to_dataframeOne row per line: lambda_A, prominence, matched (boolean); NaN when unmatched
matches_to_seriesA single row with match_<line>_wl and match_<line>_prom per line, NaN when unmatched. Used by the processing pipeline to produce the match_* columns

Limitations​

  • Six lines only; no molecular bands or metal lines are detected here.
  • Association keeps one peak per line, chosen by prominence rather than by proximity.
  • Results depend on the flux normalisation upstream (see Preprocessing).