Command line¶
Installing the package provides the ecg-record command. Every subcommand
reads and writes the same records as the Python API.
ecg-record {measure,summary,table,plot,examples,validate,query,resolve,select,batch} ...
Wherever a file argument accepts -, the command reads from standard input or
writes to standard output. Results go to standard output as JSON. Errors go to
standard error as one JSON line, {"error": "<ExceptionType>", "message": "..."},
and set a non-zero exit code.
measure¶
Measure a signal file and write a record.
ecg-record measure ptbxl/records500/00000/00001_hr.hea -o rec.json # rate and leads from the file
ecg-record measure ecg.npy --sampling-rate 500 --lead-names standard_12 -o ecg.record.json
ecg-record measure study.edf --start 60 --end 70 -o window.json # a 10 s window
| Option | Default | Meaning |
|---|---|---|
signal (positional) |
any file read_signal reads (WFDB .hea/.dat/.mat, EDF/BDF, CSV/TSV, NPY/NPZ); - reads NPY/NPZ bytes from stdin |
|
--sampling-rate HZ |
from the file | needed only when the file does not say (NPY, CSV without a time column, stdin) |
--lead-names NAME ... |
from the file | one name per row, in row order, or standard_12; needed only when the file does not say |
--amplitude-unit {mV,uV} |
mV |
unit of CSV/NPY samples |
--input-mode {standard_12,limited} |
standard_12 |
use limited for 1–8 channels |
--start S, --end S |
whole file | measure a window (seconds) |
--method METHOD |
default |
default or legacy_dxl_inspired |
--profile {summary,all,debug} |
summary |
record profile |
--config FILE |
JSON file with configuration | |
--sidecar FILE |
write dense matrices to this NPZ sidecar; it must be in the same directory as -o |
|
-o, --output FILE |
- (stdout) |
record path |
Files are written atomically (temporary file, then rename). With --sidecar,
the sidecar is written first, so the record never points at a missing
sidecar. The record is followed by a newline; otherwise the bytes are the same
as dumps_record.
# two channels, all measurements, dense matrices in a sidecar
ecg-record measure holter.npz --sampling-rate 250 --lead-names II V5 \
--input-mode limited --profile all \
--sidecar out/holter.dense.npz -o out/holter.record.json
summary, table, plot, examples¶
ecg-record summary rec.json # or a signal file: measured on the fly
ecg-record table rec1.json rec2.json -o global.csv # one row of record-level values per record
ecg-record table rec.json --kind long -o cells.parquet # one row per published cell (needs pandas+pyarrow)
ecg-record plot ptbxl/00001_hr.hea --kind paper -o ecg.png # paper | record | beat | median | rhythm | st | quality
ecg-record plot rec.json --signal ptbxl/00001_hr.hea --kind median -o median.png
ecg-record examples # list the bundled example ECGs
ecg-record examples lbbb -o lbbb.npz # export one as NPZ (signal, sampling_rate, lead_names)
validate¶
ecg-record validate ecg.record.json # strict (default)
ecg-record validate ecg.record.json --level schema
Prints {"record_id": "...", "schema_version": "1.1.0", "valid": true}. An
invalid record exits with code 3 and the validation error on stderr.
query¶
ecg-record query ecg.record.json qrs_duration_ms --lead V1 --beat 3
ecg-record query ecg.record.json heart_rate_bpm
Prints one JSON object with the same members as
MeasurementResult: name, lead,
beat, value, unit, absence, address, provenance, validation.
resolve¶
ecg-record resolve ecg.record.json 'ecg-record:rec-…@1.1.0#/quality/record'
Prints {"address": "...", "node_kind": "record", "value": {...}}. Quote the
address in the shell because it contains #.
select¶
Export several values in one call. The query file is a JSON array of
{"name", "lead", "beat"} objects, or an object with a queries array:
[
{"name": "heart_rate_bpm"},
{"name": "qrs_duration_ms", "lead": "V1", "beat": 0},
{"name": "qt_interval_ms", "lead": "V5", "beat": 0}
]
ecg-record select ecg.record.json --queries queries.json # JSON to stdout
ecg-record select ecg.record.json --queries queries.json --format jsonl -o values.jsonl
batch¶
Measure many signals from a JSON Lines manifest, a directory or a glob, in parallel worker processes.
ecg-record batch manifest.jsonl --output-dir records --jobs 4
ecg-record batch 'ptbxl/records500/**/*.hea' --output-dir records --jobs 12 --table records/global.csv
A directory or glob makes one item per signal file (WFDB records by their
header), with the file name as id; --table also writes one row of
record-level values per successful record (CSV, or Parquet for .parquet).
Each manifest line describes one item:
{"id": "p001", "signal": "signals/p001.npy", "sampling_rate": 500, "lead_names": ["I", "II", "III", "aVR", "aVL", "aVF", "V1", "V2", "V3", "V4", "V5", "V6"]}
{"id": "p002", "signal": "signals/p002.npz", "sampling_rate": 250, "lead_names": ["II", "V5"], "input_mode": "limited", "profile": "all", "output": "limited/p002.json"}
| Member | Required | Meaning |
|---|---|---|
id |
yes | non-empty string, echoed in the status line |
signal |
yes | any signal file measure accepts, relative to the manifest's directory |
sampling_rate, lead_names |
when the file does not say | as for measure |
amplitude_unit, input_mode, method, profile, start_s, end_s |
no | as for measure |
config |
no | configuration JSON file, relative to the manifest's directory |
output |
no | record path under --output-dir; default <id>.json |
Unknown members are rejected. Outputs must stay inside --output-dir and be
unique. Batch items cannot read stdin.
For every item, in manifest order, one status line goes to stdout. For the
manifest above plus a third item (p003) whose signal file does not exist:
{"id": "p001", "output": "/abs/path/records/p001.json"}
{"id": "p002", "output": "/abs/path/records/limited/p002.json"}
{"error": "FileNotFoundError", "id": "p003", "message": "[Errno 2] No such file or directory: 'signals/missing.npy'"}
A failed item does not stop the others (unless --fail-fast); its error is
reported in its status line.
--jobs Nmeasures up to N items concurrently in worker processes (--threadsuses threads, as 0.1 did; the interpreter lock makes them much slower). Statuses stay in manifest order.--fail-faststops after the first failed item.- The exit code is 0 when every item succeeded and 4 when any failed.
Exit codes¶
| Code | Meaning |
|---|---|
| 0 | success |
| 2 | invalid configuration or arguments (ConfigurationError) |
| 3 | invalid input or record (ECGInputError and its subclasses, ValueError) |
| 4 | batch: at least one item failed |
| 5 | file system error (OSError) |
| 70 | internal error, including ComputationInvariantError |
Invalid command-line syntax (missing required options, unknown choices) is
reported by argparse with exit code 2.