ecg-interpreter
A Python library for step-by-step clinical ECG interpretation.
Given a raw ECG signal (CSV, NumPy array, or PhysioNet WFDB file), the library extracts all clinically relevant parameters and produces a structured diagnosis — rate, rhythm, intervals, blocks, ischemia, and more.
Installation
pip install ecg-interpreter
For PhysioNet WFDB file support:
pip install "ecg-interpreter[wfdb]"
Quick Start
From a CSV file
from ecg_interpreter import ECGSignalProcessor, ECGInterpreter
processor = ECGSignalProcessor(sampling_rate=500)
params = processor.process_csv("ecg.csv", signal_col="lead_II")
interpreter = ECGInterpreter()
result = interpreter.interpret(params, patient_sex="male")
interpreter.print_full_report(result)
From a NumPy array
import numpy as np
from ecg_interpreter import ECGSignalProcessor, ECGInterpreter
signal = np.loadtxt("ecg_raw.txt") # 1D array of voltage samples
processor = ECGSignalProcessor(sampling_rate=360)
params = processor.process_array(signal)
interpreter = ECGInterpreter()
result = interpreter.interpret(params)
interpreter.print_full_report(result)
From a PhysioNet WFDB record
import wfdb
from ecg_interpreter import ECGSignalProcessor, ECGInterpreter
# Download MIT-BIH record 100
wfdb.dl_database('mitdb', './data', records=['100'])
processor = ECGSignalProcessor()
params = processor.process_wfdb('./data/100', channel=0)
interpreter = ECGInterpreter()
result = interpreter.interpret(params)
interpreter.print_full_report(result)
Sample Output
════════════════════════════════════════════════════════════
ECG INTERPRETATION
════════════════════════════════════════════════════════════
[Step 1] Heart Rate
→ Heart rate = 90 bpm
→ Normal Rate (90 bpm) ✓
[Step 2] Rhythm
→ RR mean = 666 ms, std = 5 ms, CV = 0.75%
→ Regular rhythm ✓
[Step 3] PR Interval
→ PR interval = 160 ms (normal: 120–200 ms)
→ Normal PR (160 ms) ✓
[Step 4] QRS Duration
→ QRS duration = 80 ms (normal: 60–100 ms)
→ Normal QRS duration (80 ms) ✓
[Step 5] QTc Interval
→ QTc = 420 ms (threshold: ≤440 ms for male)
→ Normal QTc (420 ms) ✓
[Step 6] AV Blocks
→ No AV block detected ✓
[Step 7] Bundle Branch Block
→ No bundle branch block ✓
[Step 8] ST Segment & Ischemia
→ Mean ST level = +0.148 mV (normal: -0.05 to +0.1 mV)
→ ST Elevation (+0.148 mV) 🔴 — STEMI suspect!
Confirm with 12-lead ECG immediately
[Step 9] Other Patterns
→ No additional patterns detected ✓
[Overall] CRITICAL: STEMI
[Urgency] CRITICAL
════════════════════════════════════════════════════════════
ECG INTERPRETATION SUMMARY
════════════════════════════════════════════════════════════
Heart Rate : 90 bpm
PR interval : 160 ms
QRS duration : 80 ms
QTc : 420 ms
ST level : +0.148 mV
────────────────────────────────────────────────────────────
Rate : Normal Rate (90 bpm) ✓
Rhythm : Regular rhythm ✓
PR : Normal PR (160 ms) ✓
QRS : Normal QRS duration (80 ms) ✓
QTc : Normal QTc (420 ms) ✓
AV Block : No AV block detected ✓
BBB : No bundle branch block ✓
ST/Ischemia : ST Elevation (+0.148 mV) 🔴 — STEMI suspect!
Other : No additional patterns detected ✓
────────────────────────────────────────────────────────────
OVERALL : CRITICAL: STEMI
URGENCY : CRITICAL
════════════════════════════════════════════════════════════
Accessing Individual Fields
print(result.heart_rate) # 90.0
print(result.rate_interpretation) # "Normal Rate (90 bpm) ✓"
print(result.rhythm_interpretation) # "Regular rhythm ✓"
print(result.pr_interpretation) # "Normal PR (160 ms) ✓"
print(result.qrs_interpretation) # "Normal QRS duration (80 ms) ✓"
print(result.qtc_interpretation) # "Normal QTc (420 ms) ✓"
print(result.av_block) # "No AV block detected ✓"
print(result.bundle_branch_block) # "No bundle branch block ✓"
print(result.st_interpretation) # "ST Elevation (+0.148 mV) 🔴 ..."
print(result.stemi_flag) # True
print(result.ischemia_flag) # True
print(result.urgency) # "critical"
print(result.overall_interpretation) # "CRITICAL: STEMI"
print(result.summary) # full formatted summary string
Normal Reference Ranges
| Parameter | Normal Range |
|---|---|
| Heart Rate | 60 – 100 bpm |
| PR interval | 120 – 200 ms |
| QRS duration | 60 – 100 ms |
| QTc (male) | ≤ 440 ms |
| QTc (female) | ≤ 460 ms |
| ST level | -0.05 to +0.10 mV |
What It Detects
Rate
| Finding | Threshold |
|---|---|
| Severe Bradycardia | < 40 bpm 🔴 |
| Moderate Bradycardia | 40 – 49 bpm ⚠⚠ |
| Mild Bradycardia | 50 – 59 bpm ⚠ |
| Normal | 60 – 100 bpm ✓ |
| Mild Tachycardia | 101 – 120 bpm ⚠ |
| Moderate Tachycardia | 121 – 150 bpm ⚠⚠ |
| Severe Tachycardia | > 150 bpm 🔴 |
Rhythm
| Finding | Detection Method |
|---|---|
| Regular | RR CV < 10% |
| Mildly irregular | RR CV 10–20% |
| Atrial Fibrillation | RR CV > 20% |
| Atrial Flutter | Regular rate ~150 bpm |
Intervals
| Finding | Criteria |
|---|---|
| 1st degree AV block | PR > 200 ms |
| Short PR / WPW | PR < 120 ms |
| Incomplete BBB | QRS 100–119 ms |
| Complete BBB | QRS ≥ 120 ms |
| Prolonged QTc | QTc > 440/460 ms |
| Critical QTc | QTc > 500 ms 🔴 |
AV Blocks
| Block | Detection Criteria |
|---|---|
| 1st degree | PR > 200 ms |
| 2nd degree Mobitz II | PR > 200 ms + dropped beats + slow rate |
| 2nd degree Mobitz I (Wenckebach) | PR > 200 ms + mildly irregular RR |
| 3rd degree (Complete) | HR < 45 bpm + wide QRS escape rhythm |
ST Segment / Ischemia
| Finding | ST Level |
|---|---|
| Normal | -0.05 to +0.10 mV |
| ST Depression / Ischemia | ≤ -0.05 mV ⚠⚠ |
| ST Elevation / STEMI suspect | ≥ +0.10 mV 🔴 |
Other Patterns
| Pattern | Criteria |
|---|---|
| WPW | Short PR (< 120 ms) + Wide QRS (≥ 120 ms) |
| Long QT Syndrome | QTc > 440/460 ms |
| Short QT Syndrome | QTc < 340 ms |
Signal Processing Pipeline
Raw Signal
↓
Bandpass Filter (0.5 – 40 Hz)
↓
R-peak Detection (Pan-Tompkins)
↓
Fiducial Points (P, Q, S, T)
↓
Interval Calculation (PR, QRS, QT, QTc)
↓
ST Segment Measurement
↓
ECGParameters
↓
ECGInterpreter (9 steps)
↓
ECGResult
Key algorithms
Bandpass filter: 4th-order Butterworth (0.5–40 Hz)
- 0.5 Hz highpass → removes baseline wander
- 40 Hz lowpass → removes EMG and high-frequency noise
R-peak detection: Pan-Tompkins inspired
- Differentiate + Square → amplifies steep QRS slopes
- Moving window integration → smooths QRS complex
- Adaptive threshold (50% of signal max) + 200 ms refractory period
QTc correction: Bazett formula
QTc = QT / √(RR in seconds)
A-a gradient (if PaO2 available):
PAO2 = FiO2 × (760 - 47) - PaCO2 / 0.8
A-a = PAO2 - PaO2
CSV Format
The library accepts any CSV with at least one voltage column:
time, lead_II
0.000, 0.12
0.002, 0.15
0.004, 0.23
...
If a time column is provided, the sampling rate is inferred automatically.
Supported Input Formats
| Format | Method | Notes |
|---|---|---|
| NumPy array | process_array(signal) |
Raw voltage samples |
| CSV file | process_csv(path, signal_col) |
Any column name |
| PhysioNet WFDB | process_wfdb(path, channel) |
Requires pip install wfdb |
Requirements
- Python ≥ 3.8
- numpy ≥ 1.21
- pandas ≥ 1.3
- scipy ≥ 1.7
Optional:
- wfdb ≥ 4.0 — for PhysioNet WFDB file support
Limitations
- Designed for single-lead analysis. Multi-lead features (axis calculation, STEMI territory localization, LBBB vs RBBB morphology) require 12-lead input — planned for v0.2.
- R-peak detection works best on clean signals. Very noisy or artifact-heavy recordings may need pre-processing.
- This library is for research and educational purposes only. It is not a medical device and should not be used as the sole basis for clinical decisions.
Roadmap
- v0.2 — 12-lead support (axis, STEMI territory, LBBB vs RBBB)
- v0.3 — Anion Gap + Delta-Delta integration with ABG interpreter
- v0.4 — ML-based arrhythmia classification (AF, VT, VF)
- v0.5 — REST API wrapper
License
MIT
Release files for ecg-interpreter 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ecg_interpreter-0.1.0.tar.gz | 19.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ecg_interpreter-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size:35.8 kB
Release files / ecg_interpreter-0.1.0.tar.gz
| Download URL | ecg_interpreter-0.1.0.tar.gz |
|---|---|
| Size | 19.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8e8f8a6603ff7dde93e433a0fcd58b9b2be2f091f85a28c085caac1042cea1bd
|
|
BLAKE2b-256 checksum How to use checksums |
0a88de4575dd6d7044ef070736b02c58db18ac3bce4d95e8f6036ddff6f6fa6e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.9
|
Release files / ecg_interpreter-0.1.0-py3-none-any.whl
| Download URL | ecg_interpreter-0.1.0-py3-none-any.whl |
|---|---|
| Size | 16.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9eec9933b52258b616fb31aafad17dab4568bef020ca33687bada4481fee1d90
|
|
BLAKE2b-256 checksum How to use checksums |
059e1db5e1226b5705b754f9d4f4c040d5f809702cc1b0709c8606120ed7fe8a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.9
|