Processing

Functions of ecgdatakit.processing.

ECG Cleaning

ecgdatakit.processing.clean_ecg(lead, method='default', *, fs=None, powerline=50.0, **kwargs)[source]

Clean an ECG lead signal.

Parameters:
  • lead (Lead | NDArray[double]) – Input ECG lead or 1-D signal array.

  • method (str) – Cleaning method: "default", "biosppy", "neurokit2", "combined", or "deepfade" (experimental, warns on use).

  • fs (int | None) – Sample rate in Hz. Required when lead is a numpy array.

  • powerline (float | None) – Power-line frequency in Hz (50 or 60) removed by "default", "neurokit2" and the NeuroKit2 stage of "combined". None disables the notch of "default". BioSPPy and DeepFADE have no power-line stage and ignore it. With "default", a notch that is not below the Nyquist frequency is skipped with a warning.

  • **kwargs –

    Extra arguments for "deepfade" only:

    • device (str): PyTorch device (default "cpu").

    • weights_path (str | Path): Override the bundled DeepFADE weights.

    • batch_size (int): Inference batch size (default 32).

Returns:

Cleaned lead (new object, original unchanged).

Return type:

Lead

Raises:
  • ValueError – Unknown method, or the backend rejects the signal (e.g. too short or containing NaN). Backend errors are never hidden.

  • TypeError – A keyword argument the selected method does not accept.

Filters

ecgdatakit.processing.lowpass(lead, cutoff, order=4, *, fs=None)[source]

Apply a Butterworth low-pass filter.

Parameters:
  • lead (Lead | NDArray[double]) – Input ECG lead or 1-D signal array.

  • cutoff (float) – Cutoff frequency in Hz.

  • order (int) – Filter order (default 4).

  • fs (int | None) – Sample rate in Hz. Required when lead is a numpy array.

Return type:

Lead

ecgdatakit.processing.highpass(lead, cutoff, order=4, *, fs=None)[source]

Apply a Butterworth high-pass filter.

Parameters:
  • lead (Lead | NDArray[double]) – Input ECG lead or 1-D signal array.

  • cutoff (float) – Cutoff frequency in Hz.

  • order (int) – Filter order (default 4).

  • fs (int | None) – Sample rate in Hz. Required when lead is a numpy array.

Return type:

Lead

ecgdatakit.processing.bandpass(lead, low, high, order=4, *, fs=None)[source]

Apply a Butterworth band-pass filter.

Parameters:
  • lead (Lead | NDArray[double]) – Input ECG lead or 1-D signal array.

  • low (float) – Lower cutoff frequency in Hz.

  • high (float) – Upper cutoff frequency in Hz.

  • order (int) – Filter order (default 4).

  • fs (int | None) – Sample rate in Hz. Required when lead is a numpy array.

Return type:

Lead

ecgdatakit.processing.notch(lead, freq=50.0, quality=30.0, *, fs=None)[source]

Apply an IIR notch (band-stop) filter.

Parameters:
  • lead (Lead | NDArray[double]) – Input ECG lead or 1-D signal array.

  • freq (float) – Center frequency to remove (default 50 Hz for mains hum).

  • quality (float) – Quality factor, higher means narrower notch (default 30).

  • fs (int | None) – Sample rate in Hz. Required when lead is a numpy array.

Return type:

Lead

ecgdatakit.processing.remove_baseline(lead, cutoff=0.5, order=2, *, fs=None)[source]

Remove baseline wander using a high-pass filter.

Parameters:
  • lead (Lead | NDArray[double]) – Input ECG lead or 1-D signal array.

  • cutoff (float) – Cutoff frequency in Hz (default 0.5 Hz).

  • order (int) – Filter order (default 2).

  • fs (int | None) – Sample rate in Hz. Required when lead is a numpy array.

Return type:

Lead

ecgdatakit.processing.diagnostic_filter(lead, notch_freq=50.0, *, fs=None)[source]

Apply AHA diagnostic-grade filtering: 0.05–150 Hz bandpass + notch.

Suitable for diagnostic ECG interpretation where full morphology (including ST segment) must be preserved.

The 150 Hz upper cutoff needs a sampling rate above 333 Hz. At lower rates (e.g. 180 or 250 Hz Holter recordings) it is lowered to 0.45 * fs and a warning is emitted. The notch is skipped with a warning when notch_freq is not below the Nyquist frequency.

Parameters:
  • lead (Lead | NDArray[double]) – Input ECG lead or 1-D signal array.

  • notch_freq (float | None) – Power-line frequency to notch out (50 or 60 Hz), None for no notch.

  • fs (int | None) – Sample rate in Hz. Required when lead is a numpy array.

Return type:

Lead

ecgdatakit.processing.monitoring_filter(lead, notch_freq=50.0, *, fs=None)[source]

Apply monitoring-grade filtering: 0.67–40 Hz bandpass + notch.

Suitable for arrhythmia monitoring where baseline stability is more important than preserving fine morphology. As in diagnostic_filter(), the upper cutoff is lowered to 0.45 * fs at low sampling rates and an impossible notch is skipped, both with a warning.

Parameters:
  • lead (Lead | NDArray[double]) – Input ECG lead or 1-D signal array.

  • notch_freq (float | None) – Power-line frequency to notch out (50 or 60 Hz), None for no notch.

  • fs (int | None) – Sample rate in Hz. Required when lead is a numpy array.

Return type:

Lead

Resampling

ecgdatakit.processing.resample(lead, target_rate, *, fs=None)[source]

Resample a lead to a different sample rate.

Uses polyphase rational resampling (scipy.signal.resample_poly) which preserves signal content up to the Nyquist frequency of the lower sample rate. The signal is extended linearly at both ends (padtype="line") so a DC level or slow drift does not ring at the edges. Output length is ceil(n * target_rate / fs).

Parameters:
  • lead (Lead | NDArray[double]) – Input ECG lead or 1-D signal array (must be finite).

  • target_rate (int) – Desired output sample rate in Hz. A whole-number float such as 250.0 is accepted; the result is stored as an int.

  • fs (int | None) – Sample rate in Hz. Required when lead is a numpy array.

Return type:

Lead

Normalization

ecgdatakit.processing.normalize_minmax(data)[source]

Scale signal to the [-1, 1] range.

Overloads:
  • data (Lead) → Lead

  • data (list[Lead]) → list[Lead]

  • data (ECGRecord) → ECGRecord

  • data (list[ECGRecord]) → list[ECGRecord]

  • data (NDArray[np.float64]) → NDArray[np.float64]

Parameters:

data (Lead | list[Lead] | ECGRecord | list[ECGRecord] | NDArray[float64])

Return type:

Lead | list[Lead] | ECGRecord | list[ECGRecord] | NDArray[float64]

Normalization is applied per lead, per ECG.

Accepted inputs:

  • Lead — single lead.

  • list[Lead] — multiple leads (e.g. a 12-lead ECG).

  • ECGRecord — all leads and median beats in the record.

  • list[ECGRecord] — multiple records.

  • numpy array: 1-D (n_samples,), 2-D (n_leads, n_samples) or 3-D (n_ecgs, n_leads, n_samples); each row along the last axis is normalized independently and the result is float64.

Returns the same type as the input.

ecgdatakit.processing.normalize_zscore(data)[source]

Normalize signal to zero mean and unit variance (z-score).

Overloads:
  • data (Lead) → Lead

  • data (list[Lead]) → list[Lead]

  • data (ECGRecord) → ECGRecord

  • data (list[ECGRecord]) → list[ECGRecord]

  • data (NDArray[np.float64]) → NDArray[np.float64]

Parameters:

data (Lead | list[Lead] | ECGRecord | list[ECGRecord] | NDArray[float64])

Return type:

Lead | list[Lead] | ECGRecord | list[ECGRecord] | NDArray[float64]

Normalization is applied per lead, per ECG.

Accepted inputs:

  • Lead — single lead.

  • list[Lead] — multiple leads (e.g. a 12-lead ECG).

  • ECGRecord — all leads and median beats in the record.

  • list[ECGRecord] — multiple records.

  • numpy array: 1-D (n_samples,), 2-D (n_leads, n_samples) or 3-D (n_ecgs, n_leads, n_samples); each row along the last axis is normalized independently and the result is float64.

Returns the same type as the input.

ecgdatakit.processing.normalize_amplitude(data, target_mv=1.0)[source]

Scale signal so that its maximum absolute amplitude equals target_mv.

Overloads:
  • data (Lead), target_mv (float) → Lead

  • data (list[Lead]), target_mv (float) → list[Lead]

  • data (ECGRecord), target_mv (float) → ECGRecord

  • data (list[ECGRecord]), target_mv (float) → list[ECGRecord]

  • data (NDArray[np.float64]), target_mv (float) → NDArray[np.float64]

Parameters:
Return type:

Lead | list[Lead] | ECGRecord | list[ECGRecord] | NDArray[float64]

Normalization is applied per lead, per ECG.

Accepted inputs:

  • Lead — single lead.

  • list[Lead] — multiple leads (e.g. a 12-lead ECG).

  • ECGRecord — all leads and median beats in the record.

  • list[ECGRecord] — multiple records.

  • numpy array: 1-D (n_samples,), 2-D (n_leads, n_samples) or 3-D (n_ecgs, n_leads, n_samples); each row along the last axis is normalized independently and the result is float64.

Returns the same type as the input.

The scaling is a pure gain on the physical signal, so the lead keeps its units and scaling metadata. For a lead in a known voltage unit (units for physical leads, resolution_unit for raw leads) the peak of the physical signal becomes target_mv millivolts, expressed in that unit (e.g. 1000 for a "uV" lead). Without a known unit, and for numpy input, the peak becomes target_mv in the signal’s own units.

Parameters:
Return type:

Lead | list[Lead] | ECGRecord | list[ECGRecord] | NDArray[float64]

R-Peak Detection

ecgdatakit.processing.detect_r_peaks(lead, method='pan_tompkins', *, fs=None)[source]

Detect R-peak locations in an ECG lead.

Parameters:
  • lead (Lead | NDArray[double]) – Input ECG lead or raw signal array (typically Lead II). Any polarity is accepted: on leads where the QRS is mainly negative (aVR, often V1) the peak is placed on the dominant deflection.

  • method (str) – Detection algorithm: "pan_tompkins" (default) or "shannon_energy".

  • fs (int | None) – Sample rate in Hz. Required when lead is a numpy array.

Returns:

Sorted, unique sample indices of the detected R-peaks. Exactly constant runs of 2 s or more (padding, disconnected lead) are skipped and the stretches between them are processed separately; stretches shorter than 1 s between such runs are not analysed. The indices refer to the full signal, so consecutive peaks on either side of a skipped run are one RR interval apart in rr_intervals() (for example 10 s of ECG, 5 s flat, 10 s of ECG gives one interval longer than 5 s, such as 5.76 s).

Return type:

NDArray[int_]

Raises:

ValueError – Unknown method, non-positive sample rate, signal that is not 1-D, shorter than 1 s, or containing NaN or infinite values.

ecgdatakit.processing.heart_rate(lead, peaks=None, *, fs=None)[source]

Compute average heart rate in beats per minute.

Parameters:
  • lead (Lead | NDArray[double]) – Input ECG lead or raw signal array.

  • peaks (NDArray[int_] | None) – Pre-detected R-peak indices. Detected automatically if None.

  • fs (int | None) – Sample rate in Hz. Required when lead is a numpy array.

Returns:

60000 / mean RR in bpm, or nan when fewer than two peaks are available. With automatic detection, an interval spanning a skipped flat run (see detect_r_peaks()) is included and lowers the result.

Return type:

float

ecgdatakit.processing.rr_intervals(lead, peaks=None, *, fs=None)[source]

Compute RR intervals in milliseconds.

Parameters:
  • lead (Lead | NDArray[double]) – Input ECG lead or raw signal array.

  • peaks (NDArray[int_] | None) – Pre-detected R-peak indices (strictly increasing). Detected automatically if None.

  • fs (int | None) – Sample rate in Hz. Required when lead is a numpy array.

Returns:

RR intervals in ms; empty when fewer than two peaks are available. The interval between the last beat before and the first beat after a skipped flat run (see detect_r_peaks()) spans the whole gap; remove such intervals before HRV analysis.

Return type:

NDArray[double]

Raises:

ValueError – If peaks is not a 1-D array of non-negative, strictly increasing indices.

ecgdatakit.processing.instantaneous_heart_rate(lead, peaks=None, *, fs=None)[source]

Compute instantaneous heart rate at each beat in bpm.

Parameters:
  • lead (Lead | NDArray[double]) – Input ECG lead or raw signal array.

  • peaks (NDArray[int_] | None) – Pre-detected R-peak indices. Detected automatically if None.

  • fs (int | None) – Sample rate in Hz. Required when lead is a numpy array.

Return type:

NDArray[double]

Heart Rate Variability

ecgdatakit.processing.time_domain(rr_ms)[source]

Compute time-domain HRV metrics from RR intervals.

Parameters:

rr_ms (NDArray[double]) – RR intervals in milliseconds (1-D, positive, finite).

Returns:

  • mean_rr (ms): mean interval; nan if empty.

  • sdnn (ms): sample standard deviation (ddof=1); needs 2 intervals.

  • rmssd (ms): root mean square of successive differences; needs 2.

  • sdsd (ms): standard deviation (ddof=1) of successive differences; needs 3.

  • nn50_count, nn20_count: successive differences strictly greater than 50 ms / 20 ms.

  • pnn50, pnn20 (%): counts divided by the number of successive differences; needs 2 intervals.

  • hr_mean (bpm): mean of 60000 / rr; nan if empty.

  • hr_std (bpm): sample standard deviation of 60000 / rr; needs 2.

Return type:

dict

Raises:

ValueError – If rr_ms is not 1-D or contains NaN, infinite or non-positive values.

ecgdatakit.processing.frequency_domain(rr_ms, method='welch', interp_fs=4.0)[source]

Compute frequency-domain HRV metrics from RR intervals.

RR intervals are placed at their beat times, interpolated (cubic) to a uniform series at interp_fs Hz, mean-removed, and the power spectral density is estimated with Welch’s method (segments of up to 256 samples, 64 s at 4 Hz). Band powers integrate the PSD over the Task Force bands: VLF 0–0.04 Hz, LF 0.04–0.15 Hz, HF 0.15–0.40 Hz, total 0–0.40 Hz.

The Task Force recommends at least 1 min of data for HF and 2 min for LF (5 min for short-term analysis). A UserWarning is issued when the recording is shorter than 2 min (LF unreliable) or 1 min (LF and HF unreliable). VLF from recordings shorter than 5 min should not be interpreted.

Parameters:
  • rr_ms (NDArray[double]) – RR intervals in milliseconds (1-D, positive, finite).

  • method (str) – PSD method. Only "welch" is supported.

  • interp_fs (float) – Interpolation sampling rate in Hz (default 4.0); must be above 0.8 Hz so the HF band lies below the Nyquist frequency.

Returns:

vlf_power, lf_power, hf_power, total_power in ms², and lf_hf_ratio (dimensionless). All values are nan when fewer than 4 intervals are given; lf_hf_ratio is nan when HF power is zero.

Return type:

dict

Raises:

ValueError – Unknown method, interp_fs not above 0.8 Hz or not finite, or invalid rr_ms.

ecgdatakit.processing.poincare(rr_ms)[source]

Compute Poincaré plot descriptors (SD1, SD2).

SD1 = std(RR[n+1] - RR[n]) / sqrt(2) and SD2 = std(RR[n+1] + RR[n]) / sqrt(2) (sample standard deviations).

Parameters:

rr_ms (NDArray[double]) – RR intervals in milliseconds (1-D, positive, finite).

Returns:

sd1 and sd2 in ms, sd1_sd2_ratio. All nan when fewer than 3 intervals are given; the ratio is nan when SD2 is 0.

Return type:

dict

Raises:

ValueError – If rr_ms is not 1-D or contains NaN, infinite or non-positive values.

Transforms & Segmentation

ecgdatakit.processing.power_spectrum(lead, method='welch', nperseg=None, *, fs=None)[source]

Compute the power spectral density of an ECG lead.

Parameters:
  • lead (Lead | NDArray[double]) – Input ECG lead or raw signal array.

  • method (str) – "welch" (default) for Welch’s averaged periodogram, or "periodogram" for a single periodogram of the whole signal.

  • nperseg (int | None) – Segment length for Welch’s method. Defaults to min(256, len(samples)). Not used by "periodogram".

  • fs (int | None) – Sample rate in Hz. Required when lead is a numpy array.

Returns:

(frequencies, power) arrays.

Return type:

tuple[NDArray[double], NDArray[double]]

ecgdatakit.processing.fft(lead, *, fs=None)[source]

Compute the single-sided FFT amplitude spectrum.

Bins are scaled so a sinusoid of amplitude A reads A: interior bins are doubled, the DC bin (and the Nyquist bin for an even length) are not.

Parameters:
  • lead (Lead | NDArray[double]) – Input ECG lead or raw signal array.

  • fs (int | None) – Sample rate in Hz. Required when lead is a numpy array.

Returns:

(frequencies, magnitudes) arrays (positive frequencies only).

Return type:

tuple[NDArray[double], NDArray[double]]

ecgdatakit.processing.segment_beats(lead, peaks=None, before=0.2, after=0.4, *, fs=None)[source]

Segment individual heartbeats around R-peaks.

Parameters:
  • lead (Lead | NDArray[double]) – Input ECG lead or raw signal array.

  • peaks (NDArray[int_] | None) – R-peak sample indices (integers, or whole-number floats). Detected with detect_r_peaks() and its default method if None.

  • before (float) – Seconds before R-peak to include (default 0.2).

  • after (float) – Seconds after R-peak to include (default 0.4).

  • fs (int | None) – Sample rate in Hz. Required when lead is a numpy array.

Returns:

One Lead per beat, labelled "{label}_beat_{i}". Beats whose window runs past either end of the signal are skipped.

Return type:

list[Lead]

ecgdatakit.processing.average_beat(lead, peaks=None, before=0.2, after=0.4, *, fs=None)[source]

Compute the ensemble-averaged heartbeat (template).

Parameters:
  • lead (Lead | NDArray[double]) – Input ECG lead or raw signal array.

  • peaks (NDArray[int_] | None) – R-peak sample indices. Detected with detect_r_peaks() and its default method if None.

  • before (float) – Seconds before R-peak (default 0.2).

  • after (float) – Seconds after R-peak (default 0.4).

  • fs (int | None) – Sample rate in Hz. Required when lead is a numpy array.

Returns:

Averaged beat labelled "{label}_avg".

Return type:

Lead

Raises:

ValueError – If no complete beat is available to average.

Signal Quality

ecgdatakit.processing.signal_quality_index(lead, *, fs=None)[source]

Compute a composite signal quality index (SQI) in the range [0, 1].

Mean of four sub-scores: kurtosis, power ratio, R-peak regularity and baseline stability (see the module documentation for definitions and thresholds).

Parameters:
  • lead (Lead | NDArray[double]) – Input ECG lead or raw signal array (at least 1 s).

  • fs (int | None) – Sample rate in Hz. Required when lead is a numpy array.

Returns:

Score between 0.0 (unusable) and 1.0 (excellent).

Return type:

float

Raises:

ValueError – Signal shorter than 1 s, not 1-D, or containing NaN or infinite values.

ecgdatakit.processing.classify_quality(lead, *, fs=None)[source]

Classify signal quality as a human-readable category.

Parameters:
  • lead (Lead | NDArray[double]) – Input ECG lead or raw signal array.

  • fs (int | None) – Sample rate in Hz. Required when lead is a numpy array.

Returns:

"excellent" (SQI > 0.8), "acceptable" (0.5–0.8), or "unacceptable" (< 0.5).

Return type:

str

ecgdatakit.processing.snr_estimate(lead, *, fs=None)[source]

Estimate signal-to-noise ratio in dB.

The noise floor is the mean power spectral density (Welch, 1 s segments) above 100 Hz, assumed white and extrapolated over the 1–40 Hz ECG band. The SNR is the 1–40 Hz power divided by that extrapolated noise power.

Limits: only broadband noise that reaches above 100 Hz (EMG, electronic noise) is measured. Baseline wander, powerline interference and in-band motion artefacts are not counted, and recordings low-pass filtered below 100 Hz by the device read as noise-free.

Parameters:
  • lead (Lead | NDArray[double]) – Input ECG lead or raw signal array (at least 1 s).

  • fs (int | None) – Sample rate in Hz. Required when lead is a numpy array.

Returns:

Estimated SNR in dB. nan when the sample rate is 200 Hz or lower (no band above 100 Hz); inf when no noise is measured.

Return type:

float

Lead Derivation

ecgdatakit.processing.derive_lead_iii(lead_i, lead_ii, *, fs=None)[source]

Derive Lead III from Leads I and II (Einthoven’s law: III = II - I).

Parameters:
Return type:

Lead

ecgdatakit.processing.derive_augmented(lead_i, lead_ii, *, fs=None)[source]

Derive augmented limb leads aVR, aVL, aVF from Leads I and II.

Parameters:
Returns:

[aVR, aVL, aVF] in that order.

Return type:

list[Lead]

ecgdatakit.processing.derive_standard_12(lead_i, lead_ii, v1, v2, v3, v4, v5, v6, *, fs=None)[source]

Assemble a full 12-lead ECG, deriving III, aVR, aVL, aVF.

Parameters:
  • lead_i (Lead | NDArray[double]) – Limb leads I and II.

  • lead_ii (Lead | NDArray[double]) – Limb leads I and II.

  • v1..v6 (Lead | NDArray[np.float64]) – Precordial leads.

  • fs (int | None) – Sample rate in Hz. Required when passing numpy arrays.

  • v1 (Lead | NDArray[float64])

  • v2 (Lead | NDArray[float64])

  • v3 (Lead | NDArray[float64])

  • v4 (Lead | NDArray[float64])

  • v5 (Lead | NDArray[float64])

  • v6 (Lead | NDArray[float64])

Returns:

12 leads in standard order: I, II, III, aVR, aVL, aVF, V1–V6. When the limb leads had to be converted to physical values (see the module notes), I, II and V1–V6 are returned converted as well, so all 12 leads share one scale.

Return type:

list[Lead]

ecgdatakit.processing.find_lead(leads, label)[source]

Find a lead by label (case-insensitive).

Parameters:
  • leads (list[Lead]) – List of leads to search.

  • label (str) – Lead label to find (e.g., “II”, “avl”, “V1”).

Return type:

Lead | None