Step-by-step clinical ECG interpretation library
Project description
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ecg_interpreter-0.1.0.tar.gz.
File metadata
- Download URL: ecg_interpreter-0.1.0.tar.gz
- Upload date:
- Size: 19.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8e8f8a6603ff7dde93e433a0fcd58b9b2be2f091f85a28c085caac1042cea1bd
|
|
| MD5 |
f64682775073f4b47e7663133dd06700
|
|
| BLAKE2b-256 |
0a88de4575dd6d7044ef070736b02c58db18ac3bce4d95e8f6036ddff6f6fa6e
|
File details
Details for the file ecg_interpreter-0.1.0-py3-none-any.whl.
File metadata
- Download URL: ecg_interpreter-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9eec9933b52258b616fb31aafad17dab4568bef020ca33687bada4481fee1d90
|
|
| MD5 |
ced25b78ccec0ca1ead434945097240a
|
|
| BLAKE2b-256 |
059e1db5e1226b5705b754f9d4f4c040d5f809702cc1b0709c8606120ed7fe8a
|