systole.detection.interpolate_clipping#

systole.detection.interpolate_clipping(signal: List | ndarray, min_threshold: float | None = 0.0, max_threshold: float | None = 255.0, kind: str = 'cubic') ndarray[source]#

Interoplate clipping artefacts.

This function removes all data points greather/lower or equalling the provided thresholds and re-creates the missing segments using interpolation (default is “cubic”).

Parameters:
signal

The PPG signal.

min_threshold, max_thresholdfloat | None

Minimum and maximum thresholds for clipping artefacts. If None, no correction os provided for the given threshold. Defaults to min_threshold=0.0 and max_threshold=255.0, which corresponds to the expected values when reading data from the Nonin 3012LP Xpod USB pulse oximeter together with Nonin 8000SM ‘soft-clip’ fingertip sensors.

kind

Specifies the kind of interpolation to perform(see

scipy.interpolate.interp1d()).

Returns:
clean_signal

Interpolated signal.

Notes

Correct signal segment greather/smaller or equalling the recording threshold using cubic spline interpolation. Adapted from [1].

Warning

If clipping artefact is found at the edge of the signal, this function will decrement/increment the first/last value to allow interpolation.

The first and last values are corrected for interpolation by adding/substracting the median step observed in the time series.

References

Examples

>>> import matplotlib.pyplot as plt
>>> from systole import import_ppg
>>> from systole.detection import interpolate_clipping
>>> df = import_ppg()
>>> # Create lower and upper clipping artefacts
>>> df.ppg.loc[df.ppg<=50] = 50
>>> df.ppg.loc[df.ppg>=230] = 230
>>> # Correct clipping artefacts
>>> clean_signal = interpolate_clipping(df.ppg.to_numpy(), min_threshold=50, max_threshold=230)
>>> # Plot
>>> plt.plot(df.time, clean_signal, color='#F15854', label="Corrected signal")
>>> plt.plot(df.time, df.ppg, color='#5DA5DA', label="Clipping artefacts")
>>> plt.axhline(y=50, linestyle='--', color='k')
>>> plt.axhline(y=230, linestyle='--', color='k')
>>> plt.xlabel('Time (s)')
>>> plt.ylabel('PPG level (a.u)')
>>> plt.xlim(10, 40)
>>> plt.legend()
../../_images/systole-detection-interpolate_clipping-1.png