Skip to main content

ecgdeli-py

A faithful, numerically validated Python port of ECGdeli (KIT-IBT) — the open-source ECG delineation toolbox for MATLAB. It covers the full filtering and processing pipeline: fiducial-point detection and wave delineation for P, QRS and T.

Unofficial community port. Not affiliated with, endorsed by, or maintained by KIT-IBT. The algorithms are theirs (see citation); the Python translation is independent. Please report issues with this port here — not against the upstream MATLAB repository.

ECGdeli delineation of the bundled record, lead II — P/QRS/T peaks as dots, on/off boundaries as dashed lines

import ecgdeli

filtered = ecgdeli.filter_ecg(signal, fs=1000)   # band-pass → notch → isoline
ann = ecgdeli.annotate(filtered, fs=1000)        # 1-D → single lead; 2-D (n, leads) → per lead
ann.n_beats                                      # 197

lead = ann.leads[1]                              # per-lead FPT (0-based, indexes signal directly)
lead.r_peak, lead.qrs_on, lead.t_off, lead.p_on  # np.ndarray[int] sample positions per beat
signal[lead.r_peak]                              # R-peak amplitudes — no ±1 shift needed

The figure above is produced by examples/annotate_example_ecg.py, which filters, delineates, and plots ECGdeli's own bundled record using only the public API.

Status: stable (v1.0.0). The full filtering and P/QRS/T delineation pipeline, the 0-based public API, and the p_morphology feature layer. Parity is validated bit-for-bit against MATLAB R2026a across the corpus, and the delineation is validated clinically against the QTDB and LUDB cardiologist annotations (see docs/CLINICAL.md). The design decisions are in docs/DESIGN.md and the full bug register in docs/PARITY.md.


What "faithful" means here

ECGdeli's MATLAB source contains dozens of real defects (B1–B48 in the register). This port replicates them bit-for-bit by default — that is what gives every result an objective MATLAB ground truth. Fixes are opt-in and individually documented:

ecgdeli.set_fidelity("matlab")   # default: bug-for-bug compatible
ecgdeli.set_fidelity("fixed")    # opt-in: documented corrections applied

Whether "fixed" is genuinely better is answered with evidence — delineation metrics against the QTDB and LUDB cardiologist annotations in both modes (docs/CLINICAL.md). The rationale is decision D1 in docs/DESIGN.md; the register is docs/PARITY.md.

Indexing: the API is 0-based

signal[fpt.r_peak] works — that is the whole point. The subtlety is that 0 is ECGdeli's "not detected" sentinel, so a naive −1 shift would turn it into -1, which NumPy reads as the last sample: a loud failure quietly becomes a plausible number. The public FPT instead carries a validity mask and safe accessors, and fpt.to_matlab() returns the raw 1-based table. See D4 and "Indexing and the FPT sentinels" in docs/DESIGN.md.


How it was validated

The port was validated bit-for-bit against ECGdeli MATLAB R2026a across the corpus and clinically against QTDB/LUDB cardiologist annotations. The MATLAB generation rig has since been retired; the permanent regression net is now a pure-Python characterization oracle — the current pipeline output, frozen over one record per (db, fs) in both fidelity modes and re-checked by tests/test_regression.py. Refresh it with make oracle. The committed Tier-1 goldens under tests/goldens/ remain as fast per-stage regression fixtures.


Quick start

git clone https://github.com/xdandys/ecgdeli-py
cd ecgdeli-py
uv sync

make ci                   # ruff + mypy --strict + pytest

Nothing above needs MATLAB or the network: the Tier-1 goldens and the example ECG the API tests use (examples/data/) are committed.


Layout

The src/ecgdeli package layout (the faithful core/ transliteration, compat.py, fpt.py) is documented in docs/DESIGN.md. The rest of the tree:

docs/
  DESIGN.md         the design decisions (D1, D3, D4, fidelity policy)
  PARITY.md         the bug register (B1-B48) and deviation log
  CLINICAL.md       the clinical-validation report
tools/
  corpus.toml       the human-reviewed corpus SPEC (which records, and why)
  corpus.lock.toml  the machine-written evidence (resolved IDs + SHA-256s)
  freeze_oracle.py  freezes the Python characterization oracle (the regression net)
examples/
  data/             the bundled example ECG (ECGdeli's own `s0273lre` record)

The upstream ECGdeli MATLAB source is not vendored. The port was made from KIT-IBT/ECGdeli at commit c3738612 (2025-05-27); clone it separately if you want to cross-check against the original.

ecgdeli depends only on numpy, scipy and pywavelets. wfdb is a dev dependency: it fetches the corpus and is never imported by the library.


Authorship

Most of this port was written by an AI model (Claude Opus 4.8), under human direction and review. The parity gate and the docs/PARITY.md full-database comparison are how that work was held to the MATLAB original.


License and citation

GPL-3.0-or-later, inherited from ECGdeli. The algorithms are KIT-IBT's — if you use this in research, please cite their paper:

Pilia N., Nagel C., Lenis G., Becker S., Dössel O., Loewe A. ECGdeli — An open source ECG delineation toolbox for MATLAB. SoftwareX 13:100639 (2021). doi:10.1016/j.softx.2020.100639

Test data is redistributed from open-access PhysioNet databases under ODC-BY 1.0 / CC-BY 4.0; see tests/ATTRIBUTION.md.

Metadata

Release files for ecgdeli 1.0.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 ecgdeli 1.0.0
File Size Uploaded
ecgdeli-1.0.0.tar.gz 587.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ecgdeli 1.0.0
File Interpreter ABI Platform
ecgdeli-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 742.0 kB

Release files / ecgdeli-1.0.0.tar.gz

Download URL ecgdeli-1.0.0.tar.gz
Size 587.5 kB
Tags Source
SHA-256 checksum
How to use checksums
056f8d8f3d1c30650587e5c9400b655785ed4a7e3e568a4d4f835c00990e4424
BLAKE2b-256 checksum
How to use checksums
151beeab81e8a71fac12c77a149396e23fc87469391a279435dbc023571872f0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.13

Release files / ecgdeli-1.0.0-py3-none-any.whl

Download URL ecgdeli-1.0.0-py3-none-any.whl
Size 154.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
04bebb90706e548cb7944d38ded21f97ba36a6dce40363c5d9fe5ba1b9982d49
BLAKE2b-256 checksum
How to use checksums
4d80764995450802406797a88dd97755089e887a22b7f65bf5ff04c0167b37ca
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.13

Release history Release notifications | RSS feed

This release

1.0.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