Frequently asked questions¶
Can I use the measurements clinically?¶
No. This is research and engineering software, not a medical device. In
schema 1.1.0 only the record-level P duration, PR, QRS and QT are
benchmark-validated (against IEC interval limits on LUDB) and the heart rate
and frontal axes indirectly validated (against GE 12SL), which is not a
clinical-performance claim; every other field is unvalidated. See
Limitations and intended use.
Why does ecg_record insist on lead names?¶
A mislabelled or transposed signal produces plausible but wrong numbers, and nothing downstream can detect that. Explicit names make the input contract checkable. In standard mode the rows may come in any order; see Preparing input signals.
My data is (n_samples, 12). What do I do?¶
Transpose it: ecg_record(signal.T, ...). The error
signal_lead_count_mismatch usually means the array is transposed.
Why is a value None?¶
Look at result.absence: unmeasurable(reason) means the pipeline could not
produce a trustworthy value, not_applicable(reason) means the input excludes
the quantity (for example the axis in limited mode), and NullAbsence means
no reason was recorded. See Absence states.
Why does the same signal get a different record_id after upgrading?¶
The id includes the library version, because a new version may measure
differently. Pass your own record_id= if you need ids that do not change.
How do I get a per-beat value for every lead?¶
Loop over record.axes["leads"] and call query_measurement for each lead, or
read the [beat][lead] matrix at
record.field("/measurements/intervals/<name>")["values"]. See
A table of values.
Which beat index should I use?¶
Beat indices are positions in record.axes["beats"] (zero-based, in time
order). Each beat has an id and a reference r_sample. There is no single
"representative" beat in the record; aggregate per-beat values yourself, for
example with a median over beats.
Does ecg-records diagnose rhythms or conditions?¶
No. Interpretation is the separate ecginterpret
distribution (pip install "ecg-records[interpret]"; 0.2.1 needs ecg-records
0.3 with the engine). It applies rule sets to a record and renders reports.
ECGFeatureExtractor().extract() raises ImportError about ecginterpret. Why?¶
The legacy extractor always included the interpretation. Use the record API
(ecg_record), which never needs interpretation. See the
migration guide.
ECGConfig(p_wave=ecgfeat.PWaveConfig()) fails. Is that a bug?¶
It was, from 0.1.0 to 0.3.1: the top-level ecgfeat.PWaveConfig named the
legacy engine's class. Since 0.3.2 it is the class ECGConfig.p_wave accepts.
P-wave settings are still fixed, so there is no reason to pass one. See
Configuration.
record.get("qrs_duration_ms", lead="V1") raises MeasurementSelectorError. Why?¶
qrs_duration_ms exists at two levels: the record-level value (no selector)
and one value per beat and lead (lead= and beat= together). There is no
lead-level value in the record; take the median over beats yourself with
record.to_rows() or record.to_dataframe("cells"). Fields that are stored
per lead only are the median_* fields of the median beat.
Can I read records without installing SciPy or the engine?¶
Reading, validating and querying records does not load the numerical engine. The package still depends on NumPy and SciPy at install time. Records are plain JSON with a published JSON Schema, so other languages can read them directly.
How big is a record?¶
About 29 kB for a 10 s, 12-lead, 10-beat summary record of schema 1.1, with a
contracted maximum of 30,000 bytes (schema 1.0: about 18 kB, at most 24,000). Longer recordings grow with the number of beats. For
very long recordings, move the dense matrices into an
NPZ sidecar.
How long can a recording be?¶
At least 1 second, with no fixed maximum. Processing time and record size grow with length; the pipeline is tuned and tested on 10-second, diagnostic-style recordings.
Where do I report problems?¶
Open an issue at https://github.com/humansys-lab/ecg-records/issues, ideally with the record (JSON) and, if you can share it, the signal.