Skip to content

normalize_spline

Normalise the continuum with an IRAF-style iteratively clipped cubic spline.

Category Continuum
Backend scipy - implemented here on top of scipy primitives
Version 2.0.0
Reads ctx.spectrum (a Spectrum1D)
Writes spectrum, metrics.continuum_rms, metrics.n_rejected, metrics.n_iterations, metrics.continuum_median, extras.continuum_spline

Least-squares cubic spline (IRAF function=spline3) with n_knots equally spaced interior knots (IRAF order = n_knots + 1 pieces), refitted up to niterate times after rejecting samples below −low_reject·σ or above +high_reject·σ of the residual (σ over the kept samples) plus grow neighbours on each side ; a threshold ≤ 0 disables that side, as in IRAF. Stops early when no new sample is rejected. Knots left without data by the rejection are dropped. Writes ctx.spectrum = F / S(λ) (flux_unit 'normalized'), the uncertainty as σ / |S(λ)|, meta['continuum_method'] = 'spline3', extras['continuum_spline'] = {'continuum', 'knots', 'kept'} with the continuum on the input axis, and metrics continuum_rms (RMS of F/S − 1 over the kept samples), n_rejected, n_iterations and continuum_median. Keep n_knots small (5–15 across an optical spectrum) so broad features (Balmer wings, molecular bands) are treated as lines, not continuum ; increase it only to follow a blaze ripple. Compared with normalize_polynomial (one global polynomial, same asymmetric clip), the spline is more flexible — better on wavy responses, more prone to bending into wide lines. Descending wavelength axes are sorted internally ; duplicate wavelengths are fitted once. Fails when the finite samples cannot constrain the requested spline. v2.0.0: masked samples (Spectrum1D.mask) are excluded from the fit and from continuum_rms / n_rejected like non-finite ones ; the output keeps their flux, divided like every other sample, and carries the mask through.

Parameters

Parameter Default Required Description
n_knots 10 - Number of equally spaced interior knots (IRAF spline3 order − 1).
low_reject 2.0 - Rejection threshold below the fit, in σ (IRAF low_reject) ; ≤ 0 disables.
high_reject 3.0 - Rejection threshold above the fit, in σ (IRAF high_reject) ; ≤ 0 disables.
niterate 10 - Maximum number of fit-reject iterations (IRAF niterate).
grow 0 - Number of neighbouring pixels rejected on each side of a rejected one (IRAF grow).

Use it

from spectro_kernel import run_algorithm

output = run_algorithm("normalize_spline", ctx, {
    "n_knots": 10,
    "low_reject": 2.0,
    "high_reject": 3.0,
    "niterate": 10,
    "grow": 0
})
spectro run normalize_spline --input spectrum.fits \
  --param n_knots=10 \
  --param low_reject=2.0 \
  --param high_reject=3.0 \
  --param niterate=10 \
  --param grow=0
{
  "tool": "normalize_spline",
  "arguments": {
    "session_id": "<session_id>",
    "params": {
      "n_knots": 10,
      "low_reject": 2.0,
      "high_reject": 3.0,
      "niterate": 10,
      "grow": 0
    }
  }
}

Every algorithm is an MCP tool of the same name; describe_algorithm returns this page's metadata as JSON.

References

  • Tody 1986, Proc. SPIE 627, 733 — the IRAF data reduction and analysis system.
  • Tody 1993, ASP Conf. Ser. 52, 173 — IRAF in the nineties ; onedspec.continuum (function=spline3, order, low_reject, high_reject, niterate, grow).
  • scipy.interpolate.LSQUnivariateSpline — least-squares spline engine.
  • compare_normalisations - Run every continuum-normalisation method on ctx.spectrum and collect them.
  • normalize_edges - Normalise a spectrum using a continuum fitted only on its line-free edges.
  • normalize_max - Normalise a spectrum by dividing the flux by its maximum value.
  • normalize_percentile - Normalise a spectrum by dividing the flux by a high percentile of itself.
  • normalize_polynomial - Normalise the continuum to unity with a sigma-clipped polynomial fit.
  • normalize_to_region - Divide the flux by its NaN-safe mean over [wave_lo, wave_hi].
  • subtract_continuum - Subtract a sigma-clipped polynomial continuum, leaving the line residual.