Source code for neurokit2.signal.signal_interpolate

# -*- coding: utf-8 -*-
import numpy as np
import scipy.interpolate


[docs]def signal_interpolate(x_values, y_values, x_new=None, method="quadratic"): """Interpolate a signal. Interpolate a signal using different methods. Parameters ---------- x_values : Union[list, np.array, pd.Series] The samples corresponding to the values to be interpolated. y_values : Union[list, np.array, pd.Series] The values to be interpolated. x_new : Union[list, np.array, pd.Series] or int The samples at which to interpolate the y_values. Samples before the first value in x_values or after the last value in x_values will be extrapolated. If an integer is passed, nex_x will be considered as the desired length of the interpolated signal between the first and the last values of x_values. No extrapolation will be done for values before or after the first and the last valus of x_values. method : str Method of interpolation. Can be 'linear', 'nearest', 'zero', 'slinear', 'quadratic', 'cubic', 'previous', 'next' or 'monotone_cubic'. 'zero', 'slinear', 'quadratic' and 'cubic' refer to a spline interpolation of zeroth, first, second or third order; 'previous' and 'next' simply return the previous or next value of the point) or as an integer specifying the order of the spline interpolator to use. See https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.PchipInterpolator.html for details on the 'monotone_cubic' method. Returns ------- array Vector of interpolated samples. Examples -------- >>> import numpy as np >>> import neurokit2 as nk >>> import matplotlib.pyplot as plt >>> >>> # Generate points >>> signal = nk.signal_simulate(duration=1, sampling_rate=10) >>> >>> # List all interpolation methods and interpolation parameters >>> interpolation_methods = ["zero", "linear", "quadratic", "cubic", 5, "nearest", "monotone_cubic"] >>> x_values = np.linspace(0, 1, num=10) >>> x_new = np.linspace(0, 1, num=1000) >>> >>> # Visualize all interpolations >>> fig, ax = plt.subplots() #doctest: +SKIP >>> ax.scatter(x_values, signal, label="original datapoints", zorder=3) #doctest: +SKIP >>> for im in interpolation_methods: ... signal_interpolated = nk.signal_interpolate(x_values, signal, x_new=x_new, method=im) ... ax.plot(x_new, signal_interpolated, label=im) #doctest: +SKIP >>> ax.legend(loc="upper left") #doctest: +SKIP """ # Sanity checks if len(x_values) != len(y_values): raise ValueError("NeuroKit error: signal_interpolate(): x_values and y_values must be of the same length.") if isinstance(x_new, int): if len(x_values) == x_new: return y_values else: if len(x_values) == len(x_new): return y_values monotone_cubic = isinstance(method, str) and method.lower() == "monotone_cubic" # bool if monotone_cubic: interpolation_function = scipy.interpolate.PchipInterpolator(x_values, y_values, extrapolate=True) else: interpolation_function = scipy.interpolate.interp1d( x_values, y_values, kind=method, bounds_error=False, fill_value=([y_values[0]], [y_values[-1]]) ) if isinstance(x_new, int): x_new = np.linspace(x_values[0], x_values[-1], x_new) interpolated = interpolation_function(x_new) if monotone_cubic: # Swap out the cubic extrapolation of out-of-bounds segments generated by # scipy.interpolate.PchipInterpolator for constant extrapolation akin to the behavior of # scipy.interpolate.interp1d with fill_value=([y_values[0]], [y_values[-1]]. interpolated[: x_values[0]] = interpolated[x_values[0]] interpolated[x_values[-1] :] = interpolated[x_values[-1]] return interpolated