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.