Source code for biopsykit.signals.ecg.hrv_extraction._hrv_extraction

from collections.abc import Callable, Sequence
from typing import ClassVar

import neurokit2 as nk
import pandas as pd
from tpcp import Algorithm
from typing_extensions import Self


[docs]class HrvExtraction(Algorithm): _action_methods = "extract" HRV_TYPES: ClassVar[list[str]] = ["hrv_time", "hrv_frequency", "hrv_nonlinear"] HRV_METHODS: ClassVar[dict[str, Callable]] = { "hrv_time": nk.hrv_time, "hrv_nonlinear": nk.hrv_nonlinear, "hrv_frequency": nk.hrv_frequency, } hrv_types: Sequence[str] hrv_extracted_: pd.DataFrame # TODO Outlier Correction Algorithm Injection (Lipponen2019) def __init__(self, hrv_types: str | Sequence[str] = "default"): """Initialize new ``HrvExtraction`` algorithm instance. This algorithm extracts heart rate variability (HRV) features from the R-peak data using the NeuroKit2 library. Parameters ---------- hrv_types : str or sequence of str, optional The types of HRV features to extract. Options are: * "default": Extracts the default HRV features (time- and frequency-domain). * "all": Extracts all available HRV features (time, frequency, and nonlinear). * "time" or "hrv_time": Extracts time-domain HRV features. * "frequency" or "hrv_frequency": Extracts frequency-domain HRV features. * "nonlinear" or "hrv_nonlinear": Extracts nonlinear HRV features. Default: "default" """ self.hrv_types = hrv_types super().__init__() def _sanitize_hrv_types(self): """Sanitize the hrv_types parameter to ensure it is a list of valid types.""" if isinstance(self.hrv_types, str): if self.hrv_types == "default": self.hrv_types = ["hrv_time", "hrv_frequency"] elif self.hrv_types == "all": self.hrv_types = self.HRV_TYPES else: self.hrv_types = [self.hrv_types] elif not isinstance(self.hrv_types, Sequence): raise TypeError("hrv_types must be a string or a sequence of strings.") self.hrv_types = [ f"hrv_{hrv_type}" if not hrv_type.startswith("hrv_") else hrv_type for hrv_type in self.hrv_types ] for hrv_type in self.hrv_types: if hrv_type not in self.HRV_TYPES: raise TypeError(f"Invalid hrv_type: {hrv_type}. Must be one of {self.HRV_TYPES}.")
[docs] def extract(self, *, rpeaks: pd.DataFrame, sampling_rate_hz: float) -> Self: """Extract heart rate variability (HRV) features from the R-peak data. Parameters ---------- rpeaks : :class:`~pandas.DataFrame` The R-peak data. The DataFrame contains the R-peak locations, with the index representing the heartbeat IDs and the column "r_peak_sample" containing the R-peak samples. sampling_rate_hz : float The sampling rate of the ECG signal in Hz. """ self._sanitize_hrv_types() hrv_methods = {key: self.HRV_METHODS[key] for key in self.hrv_types if key in self.HRV_METHODS} # compute HRV parameters hrv_data = [hrv_methods[key](rpeaks["r_peak_sample"], sampling_rate=sampling_rate_hz) for key in hrv_methods] hrv_data = pd.concat(hrv_data, axis=1) if "HRV_MeanNN" in hrv_data.columns: # compute HRV_MeanHR from HRV_MeanNN (in ms) hrv_data = hrv_data.assign(HRV_MeanHR=60_000 / hrv_data["HRV_MeanNN"]) # reorder columns to have HRV_MeanHR as the first column cols = hrv_data.columns.tolist() cols.insert(0, cols.pop(cols.index("HRV_MeanHR"))) hrv_data = hrv_data[cols] self.hrv_extracted_ = hrv_data return self