kinextract.asymmetric_least_squares_continuum

kinextract.asymmetric_least_squares_continuum(y: ndarray, base_mask: ndarray | None = None, lam: float = 10000000.0, p: float = 0.5, niter: int = 10, eps: float = 1e-06, return_weights: bool = False)[source]

Fit a smooth asymmetric-least-squares baseline to a spectrum (Eilers 2003).

The baseline z minimizes a weighted sum of squared residuals to y plus a roughness penalty lam * ||D z||^2 on the second difference of z, with asymmetric weights that penalize the baseline lying above the data (p) much less than lying below it (1 - p). Iterating this reweighted least squares drives the baseline toward the lower envelope of the data by an amount controlled by p, which is the desired behavior for continuum estimation when most deviations from the continuum are absorption (troughs), not emission (peaks). The linear system at each iteration is banded (bandwidth 4) and solved directly with scipy.linalg.solve_banded, which is O(n) per iteration.

Parameters:
  • y (ndarray) – 1-D flux array to fit the continuum baseline to.

  • base_mask (ndarray of bool, optional) – Boolean mask, same length as y; True marks pixels that participate in the fit as continuum (e.g. non-absorption-line, non-emission-line pixels). Pixels outside the mask get only the floor weight eps and thus barely constrain the baseline directly, but the roughness penalty still interpolates the baseline smoothly through them. Defaults to all pixels participating.

  • lam (float, optional) – Roughness-penalty strength. Larger values produce a smoother, stiffer baseline; smaller values let the baseline track the data more closely.

  • p (float, optional) – Asymmetry weight, in (0, 1). Small values (e.g. 0.001-0.01) push the baseline toward the upper envelope of the noise so that absorption troughs sit below it. A value of 0.5 is symmetric (ordinary smoothing spline).

  • niter (int, optional) – Number of asymmetric-reweighting iterations.

  • eps (float, optional) – Minimum weight floor applied everywhere, preventing the banded system from becoming singular where base_mask is False or where the reweighting would otherwise assign exactly zero weight.

  • return_weights (bool, optional) – If True, also return the final iteration’s weight vector and the precomputed penalty bands, e.g. for a caller that wants to inspect the converged fit’s effective degrees of freedom without re-running the ALS iteration from scratch.

Returns:

If return_weights is False (default), returns the fitted continuum baseline z as a 1-D ndarray the same length as y. If return_weights is True, returns (z, w_final, dtd_main, dtd_off1, dtd_off2) where w_final is the converged weight vector and dtd_main/dtd_off1/dtd_off2 are the precomputed lam * D'D band arrays.

Return type:

ndarray or tuple

Notes

The lam * D'D penalty bands depend only on lam and the array length, not on the data, so they are precomputed once by _als_dtd_bands outside the reweighting loop; only the diagonal weight vector w is rebuilt each iteration. If the banded solve fails (e.g. due to a degenerate mask), this falls back to a cubic smoothing spline through the unmasked, finite pixels, or to a constant (median) baseline if fewer than 6 good pixels remain.