ECG signal integrity analysis — an upstream quality gate for clinical ECG pipelines
Project description
ecg-integrity
ECG signal integrity validation — an upstream quality gate for clinical ECG pipelines.
Built by Axium. Part of the signal integrity infrastructure layer for cardiac AI.
What it does
ecg-integrity analyzes raw ECG signals and returns a structured integrity score before any diagnostic model, algorithm, or regulatory submission touches the data. It detects 7 clinically-relevant artifact types, scores each lead independently, and classifies the overall signal into a three-zone usability label.
Garbage-in, garbage-out is a data problem. This is the solution.
The 7 failure modes detected
| # | Failure Mode | Clinical Impact |
|---|---|---|
| 1 | Baseline wander | Shifts ST segment, distorts morphology |
| 2 | Powerline interference (50/60 Hz) | Obscures low-amplitude features |
| 3 | EMG artifact (muscle noise) | Broadband noise masking signal |
| 4 | Electrode motion artifact | Transient distortion, mimics arrhythmia |
| 5 | Saturation / clipping | Irrecoverable amplitude data loss |
| 6 | Lead disconnection | Partial or complete signal loss |
| 7 | Flatline / dropout | Zero-signal or near-zero variance segments |
Scoring model
score = clamp(1.0 − Σ(weightᵢ × severityᵢ), worst_floor, 1.0)
Each failure mode has a severity-weighted penalty and a worst-case floor. Critical modes (lead disconnection, flatline) cap the score regardless of other artifacts.
Three-zone output
| Score | Label | Meaning |
|---|---|---|
| ≥ 0.85 | PASS | Safe to use — proceed to AI model or analysis |
| 0.60 – 0.84 | REVIEW | Usable with caution — log for audit |
| < 0.60 | FAIL | Discard — re-acquire if possible |
Thresholds by clinical context
| Use case | Recommended threshold |
|---|---|
| FDA-cleared diagnostic ECG | ≥ 0.85 |
| Real-time bedside monitoring | ≥ 0.80 |
| Ambulatory / Holter monitoring | ≥ 0.75 |
| Research / dataset curation | ≥ 0.70 |
| Screening / wellness wearable | ≥ 0.60 |
Installation
Core (CSV input, CLI, scoring):
pip install ecg-integrity
With WFDB support (PhysioNet / MIT-BIH):
pip install "ecg-integrity[wfdb]"
With EDF support:
pip install "ecg-integrity[edf]"
With HTML report generation:
pip install "ecg-integrity[report]"
Everything:
pip install "ecg-integrity[wfdb,edf,report]"
Requires Python ≥ 3.11.
CLI usage
Single recording
ecg-integrity analyze \
--input recording.csv \
--fs 500 \
--output report.json \
--html report.html
Options:
--fs— sampling rate in Hz (required for CSV; inferred for EDF/WFDB)--line-freq— AC line frequency,50or60(default:60)--output— save result as JSON--html— save self-contained HTML report--no-header— CSV has no header row--leads— override lead names
Exit codes: 0 = PASS, 1 = REVIEW or FAIL (CI-friendly).
Batch processing
ecg-integrity batch \
--input-dir recordings/ \
--fs 500 \
--pattern "*.csv" \
--html batch_report.html \
--output batch_results.json
Options:
--recursive— search subdirectories--pattern— file glob filter (repeatable)
Python API
Quick start
import numpy as np
from ecg_integrity import run_detectors, aggregate_results
# Load your signal however you want
signal = np.loadtxt("lead_I.csv")
# Run all 7 detectors on one lead
detections = run_detectors(signal, fs=500, line_freq=60)
# Score a multi-lead recording
scores = aggregate_results({
"lead_I": run_detectors(signal_I, fs=500),
"lead_II": run_detectors(signal_II, fs=500),
})
print(scores.aggregate_score) # 0.9241
print(scores.usability_label) # "PASS"
print(scores.confidence_interval) # (0.89, 0.96)
print(scores.to_dict()) # full JSON-serializable result
Load ECG files directly
from ecg_integrity import load
# CSV
ecg = load("recording.csv", fs=500)
# EDF (requires pip install "ecg-integrity[edf]")
ecg = load("recording.edf")
# PhysioNet / WFDB (requires pip install "ecg-integrity[wfdb]")
ecg = load("mit-bih/100")
print(ecg.signals.shape) # (samples, leads)
print(ecg.lead_names) # ["MLII", "V5"]
print(ecg.fs) # 360.0
Inspect individual failure modes
from ecg_integrity import run_detectors
detections = run_detectors(signal, fs=500)
for result in detections:
if result.detected:
print(f"{result.mode.value}") # "powerline_interference"
print(f" severity: {result.severity:.2f}") # 0.73
print(f" confidence: {result.confidence:.2f}")
JSON response structure
{
"aggregate_score": 0.87,
"confidence_interval": [0.81, 0.93],
"usability_label": "PASS",
"dominant_failure_modes": ["powerline_interference"],
"per_lead_scores": {
"lead_I": { "score": 0.91, "worst_floor": 0.20, "confidence": 0.94 },
"lead_II": { "score": 0.83, "worst_floor": 0.20, "confidence": 0.88 }
},
"source_file": "recording.csv",
"fs": 500.0
}
Supported file formats
| Format | Extension | Extra install |
|---|---|---|
| CSV / TSV / TXT | .csv, .txt |
— (core) |
| European Data Format | .edf |
pip install "ecg-integrity[edf]" |
| PhysioNet / WFDB | .hea / record name |
pip install "ecg-integrity[wfdb]" |
Validated on MIT-BIH Arrhythmia Database
The scoring thresholds and failure mode weights are grounded in the MIT-BIH Arrhythmia Database (PhysioNet). To load and analyze a record:
from ecg_integrity import load, run_detectors, aggregate_results
ecg = load("mitdb/100", fs=None) # fs inferred from header
lead_detections = {
name: run_detectors(ecg.signals[:, i], fs=ecg.fs)
for i, name in enumerate(ecg.lead_names)
}
result = aggregate_results(lead_detections)
print(result.usability_label) # "PASS" | "REVIEW" | "FAIL"
Who this is for
Medical device companies validating ECG pipelines before FDA submission.
Wearable OEMs filtering low-quality signals before feeding downstream models.
Research labs curating clean datasets from large ECG databases.
Clinical AI vendors adding a quality gate upstream of diagnostic inference.
Architecture
ecg_integrity/
├── io/ # File loading — CSV, EDF, WFDB (PhysioNet)
├── preprocessing/ # Bandpass filter, notch filter, normalization
├── features/ # Single-pass FFT — 11 time + frequency domain features
├── models/
│ ├── detectors.py # 7 artifact detectors
│ ├── scoring.py # Severity-weighted integrity scoring engine
│ └── batch.py # Batch runner with error resilience
├── explain/ # HTML report generation
├── schemas/ # Pydantic-compatible data types
└── utils/ # RMS, moving statistics, Welch PSD
All three delivery forms share one core:
ecg_integrity (this package)
│
├── REST API — wrap in FastAPI for SaaS
├── SDK — compile with Cython for embedded/offline use
└── Certification harness — test battery for FDA audit support
Development
git clone https://github.com/axium-health/ecg-integrity
cd ecg-integrity
pip install -e ".[wfdb,edf,report,dev]"
pytest
164 tests, 160 passing (4 skipped — optional scipy dependency).
License
MIT — see LICENSE.
About Axium
Axium builds signal integrity infrastructure for clinical ECG AI. ecg-integrity is the open-source core of the Axium platform — the upstream quality gate that runs before any diagnostic model, regulatory submission, or clinical decision.
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_integrity-0.1.0.tar.gz.
File metadata
- Download URL: ecg_integrity-0.1.0.tar.gz
- Upload date:
- Size: 8.4 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
615fd30c7fd3a77ec84503bb42c10c75a243544501b8cc562bd872d36af5875c
|
|
| MD5 |
6c4796a8ebffc2012998277e575af45f
|
|
| BLAKE2b-256 |
6eca633a2ee83328538cae132288710cd74ff7491fc8b66f2cd656ed96710a0e
|
File details
Details for the file ecg_integrity-0.1.0-py3-none-any.whl.
File metadata
- Download URL: ecg_integrity-0.1.0-py3-none-any.whl
- Upload date:
- Size: 34.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea57e4179741a9ca0d15702bb2e05961650fe5700451574833e6b7e09e27692f
|
|
| MD5 |
c3d6b2f4519e92396bf284edb8569297
|
|
| BLAKE2b-256 |
75868a8eaed4aeab9d5652a879bcb14b01fb76a20f6c5556c4790df8898a50c3
|