Skip to main content

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)

Source distribution for ecg-interpreter 0.1.0
File Size Uploaded
ecg_interpreter-0.1.0.tar.gz 19.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ecg-interpreter 0.1.0
File Interpreter ABI Platform
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

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page