wavedet
A Python port of wavedet, the wavelet-based ECG delineator from
ecg-kit (GPL-2.0, upstream dead since 2020-02). It marks
P/QRS/T onsets, peaks, and offsets. Nothing else from the kit is ported.
from wavedet import delineate
d = delineate(signal, fs=250) # 1-D → single lead
d = delineate(signal_12lead, fs=500) # 2-D (n, leads) → SLR multilead fusion
d.qrs, d.qrs_on, d.t_off, d.p_on # np.ndarray[float], NaN = not found
d.per_lead[0].t_off # single-lead results retained
Parity
The goal is output parity with the MATLAB original, not per-function parity. The pass/fail bar,
per mark type per record: ≥99% of marks bit-identical to MATLAB, 100% within ±1 sample, and an
identical NaN pattern. tests/test_parity.py is that gate; it runs offline against committed
goldens, so it stays runnable without MATLAB. PARITY.md reports the full-database
comparison — the whole of QTDB + LUDB against MATLAB, with per-fiducial deviations and the
wavelet-transform ulp that is the root cause of every divergence.
Development
uv run ruff check
uv run ruff format --check
uv run mypy src/
uv run pytest # gate against committed goldens
The goldens and the signals they were made from are both committed, so the gate needs neither
MATLAB nor network. Because the gate is bit-exact and the wavelet transform's dot products route
through BLAS, conftest.py pins OpenBLAS to a fixed, CPU-independent kernel
(OPENBLAS_CORETYPE=Prescott); without it the last ~1e-14 — and so a few knife-edge marks — would
vary by host CPU. uv run pytest --full-oracle additionally runs the port over the whole of
QTDB + LUDB as a robustness sweep (downloads the databases via wfdb; no goldens).
Scope
Ported: single-lead wavedet, and SLR multilead (per-lead delineation fused by a k-nearest-neighbour rule; needs ≥3 leads).
Not ported: the VCG/3D spatial loop (delineate3D, delineateP3D, twave3D, optimline).
It is dead code upstream and cannot be fed. Reaching it needs three commented-out regions of
wavedet_3D.m restored, and even then there is no input path: leadsynth_flag is hardcoded to 0,
and leadcalc.m — the Dower/Levkov transform that would synthesize the orthogonal XYZ leads it
requires — is absent from the kit entirely. Leads I/II/III are not a substitute, since III = II − I
makes the loop rank-2 and degenerates optimline's fit. optimline also depends on lsqnonlin,
which has no bit-identical scipy equivalent, so its marks could not clear the parity gate anyway.
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 PARITY.md full-database comparison are how that work was held to the MATLAB original.
License
GPL-2.0-only, inherited from ecg-kit. Its LICENSE.txt is the plain GPL-2 text with no "or later"
grant, so this derived work cannot relicense upward.
Metadata
Release files for wavedet 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 | |
|---|---|---|---|
| wavedet-0.1.0.tar.gz | 142.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| wavedet-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 212.3 kB
Release files / wavedet-0.1.0.tar.gz
| Download URL | wavedet-0.1.0.tar.gz |
|---|---|
| Size | 142.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2b8a170f65a68143cd0cbd8818b49d54138b3c214551399fe49a044bbd7b03a2
|
|
BLAKE2b-256 checksum How to use checksums |
5ad07be30dd6a1c1ce8a60a2a2cf2f96670b91ae8484745d9d490c4971bd011d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.13
|
Release files / wavedet-0.1.0-py3-none-any.whl
| Download URL | wavedet-0.1.0-py3-none-any.whl |
|---|---|
| Size | 69.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
315d64ac0277912b3e53d1c0ef00d601d54364c04b46c3d1770c3011a7e1a1cd
|
|
BLAKE2b-256 checksum How to use checksums |
cd66c8ab458e71765128ca2f01626526e5e576921a014618c399040c1b0aa45e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.13
|