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".Nonedisables 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:
- 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.
- ecgdatakit.processing.highpass(lead, cutoff, order=4, *, fs=None)[source]
Apply a Butterworth high-pass filter.
- ecgdatakit.processing.bandpass(lead, low, high, order=4, *, fs=None)[source]
Apply a Butterworth band-pass filter.
- Parameters:
- Return type:
- ecgdatakit.processing.notch(lead, freq=50.0, quality=30.0, *, fs=None)[source]
Apply an IIR notch (band-stop) filter.
- Parameters:
- Return type:
- ecgdatakit.processing.remove_baseline(lead, cutoff=0.5, order=2, *, fs=None)[source]
Remove baseline wander using a high-pass filter.
- 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 * fsand a warning is emitted. The notch is skipped with a warning when notch_freq is not below the Nyquist frequency.
- 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 to0.45 * fsat low sampling rates and an impossible notch is skipped, both with a warning.
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 isceil(n * target_rate / fs).- Parameters:
- Return type:
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 (
unitsfor physical leads,resolution_unitfor 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.
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:
- 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:
- Returns:
60000 / mean RRin bpm, ornanwhen fewer than two peaks are available. With automatic detection, an interval spanning a skipped flat run (seedetect_r_peaks()) is included and lowers the result.- Return type:
- ecgdatakit.processing.rr_intervals(lead, peaks=None, *, fs=None)[source]
Compute RR intervals in milliseconds.
- Parameters:
- 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:
- 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.
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;nanif 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 of60000 / rr;nanif empty.hr_std(bpm): sample standard deviation of60000 / rr; needs 2.
- Return type:
- 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
UserWarningis 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:
- Returns:
vlf_power,lf_power,hf_power,total_powerin ms², andlf_hf_ratio(dimensionless). All values arenanwhen fewer than 4 intervals are given;lf_hf_ratioisnanwhen HF power is zero.- Return type:
- 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)andSD2 = 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:
sd1andsd2in ms,sd1_sd2_ratio. Allnanwhen fewer than 3 intervals are given; the ratio isnanwhen SD2 is 0.- Return type:
- 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 tomin(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:
- 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.
- 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 withdetect_r_peaks()and its default method ifNone.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:
- 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 withdetect_r_peaks()and its default method ifNone.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:
- 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:
- Returns:
Score between 0.0 (unusable) and 1.0 (excellent).
- Return type:
- 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.
- 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:
- Returns:
Estimated SNR in dB.
nanwhen the sample rate is 200 Hz or lower (no band above 100 Hz);infwhen no noise is measured.- Return type:
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).
- ecgdatakit.processing.derive_augmented(lead_i, lead_ii, *, fs=None)[source]
Derive augmented limb leads aVR, aVL, aVF from Leads I and II.
- 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:
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: