Back to Claude Scientific Skills

ECG and cardiac processing

skills/neurokit2/references/ecg_cardiac.md

2.55.06.7 KB
Original Source

ECG and cardiac processing

Checked 2026-07-23 against NeuroKit2 0.2.13 stable source/runtime, the live ECG API, and current psychophysiology measurement guidance.

Acquisition contract

Record lead/configuration, electrode placement, reference/ground, hardware gain and filters, ADC resolution/range, physical unit, native sampling rate, timestamp clock, posture/task, medication and relevant population variables, and artifact annotations. Do not infer millivolts from a column named ECG.

Sampling must support the intended endpoint. Rate/R-peak timing and P–QRS–T morphology have different bandwidth and precision needs. Psychophysiology guidance commonly uses at least 125 Hz and regards 500 Hz as conservative for HRV timing, but this is not a universal validation threshold. Validate the complete acquisition and detector on representative signals; morphology/delineation often uses 250–1000 Hz.

ecg_process() in stable 0.2.13

python
signals, info = nk.ecg_process(
    ecg,
    sampling_rate=250,
    method="neurokit",
)

The stable source performs:

  1. signal_sanitize() (index reset only);
  2. ecg_clean() with the selected method;
  3. ecg_peaks(..., correct_artifacts=True);
  4. interpolated rate;
  5. default ecg_quality(..., method="averageQRS");
  6. DWT delineation; and
  7. atrial/ventricular phase.

The pinned default probe observed these 19 columns:

text
ECG_Raw, ECG_Clean, ECG_Rate, ECG_Quality, ECG_R_Peaks,
ECG_P_Peaks, ECG_P_Onsets, ECG_P_Offsets, ECG_Q_Peaks,
ECG_R_Onsets, ECG_R_Offsets, ECG_S_Peaks, ECG_T_Peaks,
ECG_T_Onsets, ECG_T_Offsets, ECG_Phase_Atrial,
ECG_Phase_Completion_Atrial, ECG_Phase_Ventricular,
ECG_Phase_Completion_Ventricular

This is a verified default schema, not a universal promise. Persist list(signals.columns) and sorted(info).

info is a flat dict. In the default pinned run it included corrected and uncorrected R-peaks, ECG_fixpeaks_* diagnostics, sampling rate, methods, and delineated wave indices. It is not nested under an ECG key.

Cleaning and R-peak methods

High-level methods documented for ecg_process() include neurokit, pantompkins1985, hamilton2002, elgendi2010, and engzeemod2012. ecg_clean() and lower-level peak detection expose additional methods. A cleaning method and detector encode different assumptions; do not select whichever produces the expected group effect.

For custom control:

python
clean = nk.ecg_clean(ecg, sampling_rate=250, method="neurokit")
markers, peak_info = nk.ecg_peaks(
    clean,
    sampling_rate=250,
    method="neurokit",
    correct_artifacts=False,
)

Validate:

  • R-peak precision, false positives, missed beats, and ectopy;
  • performance during motion, changing rate, and low-amplitude QRS;
  • lead polarity and possible inversion;
  • filter edge regions and discontinuities; and
  • failure modes by participant, condition, device, and population.

Peak correction

ecg_process() always requests Lipponen–Tarvainen correction in 0.2.13. Inspect:

python
uncorrected = info["ECG_R_Peaks_Uncorrected"]
corrected = info["ECG_R_Peaks"]
categories = {
    key: info.get(f"ECG_fixpeaks_{key}", [])
    for key in ["ectopic", "missed", "extra", "longshort"]
}

Correction can improve a tachogram but can also alter HRV. Report corrected proportions, categories, thresholds/method, excluded segments, and sensitivity with uncorrected or alternative policies. Do not assume an algorithm can distinguish ectopic from erroneous detection without waveform review or appropriate labels.

ECG quality is method-dependent

python
quality = nk.ecg_quality(
    clean,
    rpeaks=peak_info["ECG_R_Peaks"],
    sampling_rate=250,
    method="averageQRS",
)

Stable options include averageQRS, templatematch, zhao2018, dissimilarity, and ho2025.

  • averageQRS: continuous array scaled 0–1 by this implementation.
  • templatematch: continuous morphology-template correlation; it is relative to the recording.
  • zhao2018: one classification string (Unacceptable, Barely acceptable, or Excellent).
  • dissimilarity: direction/scale differs from similarity scores.
  • ho2025: beat/interval-oriented quality based on detector agreement.

There is no universal >0.6 acceptance rule across these methods. A quality output is not device validation. Define thresholds on independent labeled data and preserve the method name and scale.

Delineation return order

python
delineation_signals, waves = nk.ecg_delineate(
    clean,
    rpeaks=peak_info["ECG_R_Peaks"],
    sampling_rate=250,
    method="dwt",
)

The first object is a same-length marker DataFrame; the second is a dict of wave sample indices. Stable methods include peak, prominence, cwt, and dwt. Missing wave indices may be NaN. Validate every wave endpoint needed for an interval/morphology claim; R-peak accuracy does not validate P/T delineation.

ECG_Phase_Atrial and ECG_Phase_Ventricular are binary phase labels; completion columns are fractions from 0 to 1. Their validity depends on delineation. For cardiac-locked stimuli, characterize trigger latency/jitter independently of software phase estimates.

ecg_eventrelated() and ecg_intervalrelated() inspect available columns. Their output columns are conditional. Use explicit dispatch and save observed columns:

python
features = nk.ecg_analyze(
    epochs,
    sampling_rate=250,
    method="event-related",
)

ECG-derived respiration

ecg_rsp() takes a heart-rate series, not raw/clean ECG:

python
edr = nk.ecg_rsp(signals["ECG_Rate"], sampling_rate=250, method="vangent2019")

EDR is a proxy and depends on ECG morphology/rate modulation. It is not interchangeable with a calibrated respiration sensor for RSA, tidal volume, or respiratory diagnosis.

Bounded pipeline

bash
python skills/neurokit2/scripts/ecg_hrv_pipeline.py \
  --input deidentified.csv --column ECG --root . --deidentified \
  --sampling-rate 250 --method neurokit --domains time \
  --signals-output ecg_processed.csv --output ecg_report.json

The helper rejects missing/non-finite samples instead of silently interpolating them, reports observed schemas and correction categories, and gates longer HRV domains.

Sources checked 2026-07-23