baselines 0.1.1

Baseline correction algorithms for signals, spectra, and images
Documentation

baselines

baselines is a Rust crate for baseline correction of signals, spectra, and row-major two-dimensional surfaces. It is an independent Rust implementation inspired by the baseline correction literature and by the public behavior of pybaselines.

use baselines::prelude::*;

let y = vec![1.0, 1.1, 4.2, 1.2, 1.0];
let estimated = baseline(&y)?;
let corrected = correct(&y)?;
# Ok::<(), baselines::BaselineError>(())

Select one of the common methods without configuring parameters:

use baselines::prelude::*;

let estimated = baseline_with(&y, Method::Arpls)?;
# Ok::<(), baselines::BaselineError>(())

Scope

The crate starts with CPU f64 implementations and public entry points for the current one-dimensional pybaselines.Baseline algorithm families: polynomial, Whittaker, morphology, penalized spline, smoothing, classification, optimizer, and miscellaneous methods. Two-dimensional support is staged under baselines::two_d; all pinned pybaselines.Baseline2D 1.2.1 families now have first-pass native Rust implementations.

Algorithms are organized by family module. Core data types such as Fit1D, Fit2D, and row-major matrix views are available at the crate root. The smallest Rust API is baseline(&y) or correct(&y). Use baseline_with(&y, Method::Arpls) to select a common algorithm with its documented defaults. For parameter tuning, start from Baseline::new(&y) for 1D data or Baseline2D::row_major(&data, rows, cols) for row-major 2D data. The explicit family modules and parameter structs remain public for advanced workflows and for users who prefer free functions.

Golden fixtures generated from a pinned pybaselines release check the one-dimensional algorithms with algorithm-specific tolerances. GPU support is feature-gated behind gpu-wgpu; the experimental WGPU path provides batched f32 morphology kernels for moving minimum, moving maximum, opening, and the top-hat baseline primitive.

See docs/PARITY.md for the current pybaselines parity matrix, 2D tolerance ledger, and known limits.

See docs/performance/ for checked-in benchmark records, including the 2026-05-24 full Criterion baseline and the measured BEADS optimization result.

Visual examples

The crate includes ruviz examples for inspecting generated baselines as PNGs:

cargo run --example ruviz_1d
cargo run --example ruviz_2d
cargo run --example ruviz_lam_effects

The examples write images to docs/assets/ruviz/. The generated PNGs are tracked for Markdown preview and excluded from Cargo packages. The 1D example plots observed spectra, AsLS/arPLS baselines, and corrected signals. The 2D example writes heatmaps for the observed surface, fitted AsLS baseline, true synthetic baseline, and corrected surface.

ruviz_lam_effects mirrors the upstream Whittaker gallery example from pybaselines for arPLS lambda selection, using the same synthetic signal, exponential baseline, noise scale, and lambda values. The noise is generated by a small deterministic Rust generator rather than NumPy's bit generator, so the shape and parameters match the gallery example but the exact noise samples do not.

See docs/GALLERY.md for the generated-output index and runnable source files, or open the gallery page in generated Rust docs. See docs/PYBASELINES_EXAMPLES.md or the reference_examples rustdoc page for the upstream gallery coverage matrix.

API style

Use the method-chain API when you need to tune a fit:

use baselines::prelude::*;

let fit = Baseline::new(&y)
    .arpls()
    .lambda(1.0e6)
    .max_iter(50)
    .tol(1.0e-3)
    .fit()?;
# Ok::<(), baselines::BaselineError>(())

Use Baseline::new_xy(&x, &y)? for nonuniform x grids or x-coordinate masks:

use baselines::prelude::*;

let fit = Baseline::new_xy(&x, &y)?
    .asls()
    .lambda(1.0e6)
    .exclude_range(125.0, 180.0)
    .baseline_mask(&trusted_baseline_points)?
    .fit()?;
# Ok::<(), baselines::BaselineError>(())

Use the lower-level family modules when you want to pass a complete params struct, reuse workspaces, or compare directly against existing code:

use baselines::whittaker::{AslsParams, asls};

let fit = asls(&y, AslsParams::default())?;
# Ok::<(), baselines::BaselineError>(())

See docs/API.md for more examples.

Python and WebAssembly

The repository contains thin bindings over the same simple API:

import numpy as np
import baselines_rs

y = np.array([1.0, 1.1, 4.2, 1.2, 1.0])
corrected = baselines_rs.correct(y, method="arpls")

Build the Python wheel with maturin build --release from bindings/python. Build the browser package with wasm-pack build --target web from bindings/wasm. The planned distribution names are baselines-rs on PyPI and baselines-wasm on npm.

Feature flags

  • gpu-wgpu enables the experimental CubeCL/WGPU morphology backend.
  • rayon parallelizes supported batch CPU operations, currently backend::cpu::snip_batch_into.
  • faer exposes the reserved faer backend boundary; the public algorithms still use the in-crate solvers in this release.
  • std is retained for feature compatibility. The crate currently requires the standard library even when default features are disabled.

Attribution

This project does not copy implementation code from pybaselines. The Python project is used as a documentation and behavioral reference, and golden fixtures should record the pybaselines version that generated them.

Please cite the original algorithm papers as appropriate. See NOTICE.md and CITATION.cff for project-level attribution.