Source code for spectrochempy.analysis.integration.integrate

# ======================================================================================
# Copyright (©) 2015-2025 LCS - Laboratoire Catalyse et Spectrochimie, Caen, France.
# CeCILL-B FREE SOFTWARE LICENSE AGREEMENT
# See full LICENSE agreement in the root directory.
# ======================================================================================
"""Integration methods."""

__all__ = ["simps", "trapz", "simpson", "trapezoid"]

__dataset_methods__ = ["simps", "trapz", "simpson", "trapezoid"]

import functools

import scipy.integrate

from spectrochempy.utils.decorators import deprecated


def _integrate_method(method):
    @functools.wraps(method)
    def wrapper(dataset, *args, **kwargs):
        # handle the various syntax to pass the axis
        if args:
            kwargs["dim"] = args[0]
            args = []

        axis, dim = dataset.get_axis(**kwargs)

        if kwargs.get("dim"):
            kwargs.pop("dim")

        data = method(dataset.data, x=dataset.coord(dim).data, axis=axis, **kwargs)

        if dataset.coord(dim).reversed:
            data *= -1

        new = dataset.copy()
        new._data = data

        del new._dims[axis]
        if (
            new._implements("NDDataset")
            and new._coordset
            and (dim in new._coordset.names)
        ):
            idx = new._coordset.names.index(dim)
            del new._coordset.coords[idx]

        new.title = "area"
        new.description = (
            f"Integration of NDDataset '{dataset.name}' along dim: '{dim}'."
        )

        if dataset.units is not None and dataset.coord(dim).units is not None:
            new._units = dataset.units * dataset.coord(dim).units
        elif dataset.units is not None:
            new._units = dataset.units
        elif dataset.coord(dim).units is not None:
            new._units = dataset.coord(dim).units
        new.history = [
            f"Dataset resulting from application of `{method.__name__}` method",
        ]

        return new

    return wrapper


[docs] @_integrate_method def trapezoid(dataset, **kwargs): r""" Integrate using the composite trapezoidal rule. Wrapper of `scpy.integrate.trapezoid`. Performs the integration along the last or given dimension. Parameters ---------- dataset : `NDDataset` Dataset to be integrated. **kwargs Additional keywords parameters. See Other Parameters. Returns ------- `~spectrochempy.core.dataset.ndataset.NDDataset` Definite integral as approximated by trapezoidal rule. Other Parameters ---------------- dim : `int` or `str`, optional, default: ``"x"`` Dimension along which to integrate. If an integer is provided, it is equivalent to the numpy axis parameter for `~numpy.ndarray`\ s. See Also -------- trapz : An alias of `trapezoid`. simpson : Integrate using the composite simpson rule. Example ------- >>> dataset = scp.read('irdata/nh4y-activation.spg') >>> dataset[:,1250.:1800.].trapezoid() NDDataset: [float64] a.u..cm^-1 (size: 55) """ return scipy.integrate.trapezoid(dataset.data, **kwargs)
@deprecated(replace="Trapezoid") def trapz(dataset, **kwargs): return trapezoid(dataset, **kwargs) trapz.__doc__ = f""" An alias of `trapezoid` kept for backwards compatibility. {trapezoid.__doc__}"""
[docs] @_integrate_method def simpson(dataset, *args, **kwargs): r""" Integrate using the composite Simpson's rule. Wrapper of `scpy.integrate.simpson`. Performs the integration along the last or given dimension. If there are an even number of samples, ``N``, then there are an odd number of intervals (``N-1``), but Simpson's rule requires an even number of intervals. The parameter 'even' controls how this is handled. Parameters ---------- dataset : `NDDataset` Dataset to be integrated. **kwargs Additional keywords parameters. See Other Parameters. Returns ------- `~spectrochempy.core.dataset.ndataset.NDDataset` Definite integral as approximated using the composite Simpson's rule. Other Parameters ---------------- dim : `int` or `str`, optional, default: ``"x"`` Dimension along which to integrate. If an integer is provided, it is equivalent to the `numpy.axis` parameter for `~numpy.ndarray`\ s. even : any of [``'avg'``, ``'first'``, ``'last'``\ }, optional, default: ``'avg'`` * ``'avg'`` : Average two results: 1) use the first N-2 intervals with a trapezoidal rule on the last interval and 2) use the last ``N-2`` intervals with a trapezoidal rule on the first interval. * ``'first'`` : Use Simpson's rule for the first ``N-2`` intervals with a trapezoidal rule on the last interval. * ``'last'`` : Use Simpson's rule for the last ``N-2`` intervals with a trapezoidal rule on the first interval. See Also -------- simps : An alias of simpson (Deprecated). trapezoid : Integrate using the composite simpson rule. Example -------- >>> dataset = scp.read('irdata/nh4y-activation.spg') >>> dataset[:,1250.:1800.].simpson() NDDataset: [float64] a.u..cm^-1 (size: 55) """ return scipy.integrate.simpson(dataset.data, **kwargs)
@deprecated(replace="simpson") def simps(dataset, **kwargs): return simpson(dataset, **kwargs) simps.__doc__ = f""" An alias of `simpson` kept for backwards compatibility. {trapezoid.__doc__}"""