baselines 0.1.1

Baseline correction algorithms for signals, spectra, and images
Documentation
//! CPU backend helpers.

use crate::fit::FitReport;
use crate::morphology::{SnipParams, snip_into};
use crate::workspace::{validate_output, validate_signal};
use crate::{BaselineError, Result};

#[cfg(feature = "rayon")]
use rayon::prelude::*;

/// Runs SNIP independently for each contiguous spectrum in `input`.
pub fn snip_batch_into(
    input: &[f64],
    n_spectra: usize,
    n_points: usize,
    params: SnipParams,
    output: &mut [f64],
) -> Result<Vec<FitReport>> {
    validate_batch(input, n_spectra, n_points, output)?;

    #[cfg(feature = "rayon")]
    {
        input
            .par_chunks_exact(n_points)
            .zip(output.par_chunks_exact_mut(n_points))
            .map(|(spectrum, baseline)| snip_into(spectrum, params, baseline))
            .collect()
    }

    #[cfg(not(feature = "rayon"))]
    {
        let mut reports = Vec::with_capacity(n_spectra);
        for spectrum_index in 0..n_spectra {
            let start = spectrum_index * n_points;
            let end = start + n_points;
            reports.push(snip_into(
                &input[start..end],
                params,
                &mut output[start..end],
            )?);
        }
        Ok(reports)
    }
}

fn validate_batch(input: &[f64], n_spectra: usize, n_points: usize, output: &[f64]) -> Result<()> {
    if n_spectra == 0 || n_points == 0 {
        validate_signal(input)?;
    }
    let expected = n_spectra
        .checked_mul(n_points)
        .ok_or(BaselineError::InvalidParameter {
            name: "batch shape",
            reason: "n_spectra * n_points overflows usize",
        })?;
    validate_output("input", expected, input.len())?;
    validate_output("output", expected, output.len())
}