1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
|
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
"""
.. Interpolation (see parent package :mod:`sigima.algorithms.signal`)
"""
from __future__ import annotations
import numpy as np
import scipy.interpolate
from sigima.enums import Interpolation1DMethod
from sigima.tools.checks import check_1d_arrays
@check_1d_arrays(x_sorted=True)
def interpolate(
x: np.ndarray,
y: np.ndarray,
xnew: np.ndarray,
method: Interpolation1DMethod,
fill_value: float | None = None,
) -> np.ndarray:
"""Interpolate data.
Args:
x: X data
y: Y data
xnew: New X data
method: Interpolation method
fill_value: Fill value. Defaults to None.
This value is used to fill in for requested points outside of the
X data range. It is only used if the method argument is 'linear',
'cubic' or 'pchip'.
Returns:
Interpolated Y data
"""
interpolator_extrap = None
if method == Interpolation1DMethod.LINEAR:
# Linear interpolation using NumPy's interp function:
ynew = np.interp(xnew, x, y, left=fill_value, right=fill_value)
elif method == Interpolation1DMethod.SPLINE:
# Spline using 1-D interpolation with SciPy's interpolate package:
# pylint: disable=unbalanced-tuple-unpacking
knots, coeffs, degree = scipy.interpolate.splrep(x, y, s=0)
ynew = scipy.interpolate.splev(xnew, (knots, coeffs, degree), der=0)
elif method == Interpolation1DMethod.QUADRATIC:
# Quadratic interpolation using NumPy's polyval function:
coeffs = np.polyfit(x, y, 2)
ynew = np.polyval(coeffs, xnew)
elif method == Interpolation1DMethod.CUBIC:
# Cubic interpolation using SciPy's Akima1DInterpolator class:
interpolator_extrap = scipy.interpolate.Akima1DInterpolator(x, y)
elif method == Interpolation1DMethod.BARYCENTRIC:
# Barycentric interpolation using SciPy's BarycentricInterpolator class:
interpolator = scipy.interpolate.BarycentricInterpolator(x, y)
ynew = interpolator(xnew)
elif method == Interpolation1DMethod.PCHIP:
# PCHIP interpolation using SciPy's PchipInterpolator class:
interpolator_extrap = scipy.interpolate.PchipInterpolator(x, y)
else:
raise ValueError(f"Invalid interpolation method {method}")
if interpolator_extrap is not None:
ynew = interpolator_extrap(xnew, extrapolate=fill_value is None)
if fill_value is not None:
ynew[xnew < x[0]] = fill_value
ynew[xnew > x[-1]] = fill_value
return ynew
|