Metadata-Version: 2.5
Name: ecg2dcm
Version: 1.3.1
Summary: Convert resting ECG recordings (GE MUSE XML and other formats) to DICOM General ECG Waveform Storage
Project-URL: Homepage, https://github.com/HyeonhoonLee/ecg2dcm
Project-URL: Repository, https://github.com/HyeonhoonLee/ecg2dcm
Project-URL: Issues, https://github.com/HyeonhoonLee/ecg2dcm/issues
Author: Seoul National University Hospital
Maintainer-email: Hyung-Chul Lee <vital@snu.ac.kr>
License: MIT License
        
        Copyright (c) 2026 Seoul National University Hospital
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: CardioSoft,DICOM,ECG,GE MUSE,HL7 aECG,Philips,WFDB,electrocardiogram,interoperability,waveform
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Healthcare Industry
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
Requires-Python: >=3.10
Requires-Dist: numpy>=1.24
Requires-Dist: pydicom<3,>=2.4.4
Requires-Dist: tqdm>=4.60
Provides-Extra: philips
Requires-Dist: sierraecg>=0.4.0; extra == 'philips'
Provides-Extra: test
Requires-Dist: pytest>=7; extra == 'test'
Provides-Extra: validate
Requires-Dist: dicom-validator>=0.6; extra == 'validate'
Description-Content-Type: text/markdown

# ECG2DCM

Convert resting 12-lead ECG recordings to DICOM **General ECG Waveform Storage**
objects: GE MUSE XML first, and also GE CardioSoft, Philips Sierra, HL7 aECG,
Mortara ELI Link, Schiller SEMA and WFDB.

This is the implementation reported in *ECG2DCM: An open-source framework for
converting resting 12-lead electrocardiograms to DICOM waveform objects*. **Release v1.3.0
produced the results in that paper; v1.3.1 differs only in two code-meaning strings and in the
documentation.** MIT License.

```
pip install ecg2dcm            # add [philips] for Philips Sierra files, [validate] for dicom-validator
ecg2dcm-convert examples/synthetic_muse.xml -o out/
```

## What it writes

One DICOM object per recording, with

- the rhythm strip and the median (representative) beat as two multiplex
  groups of twelve channels, the four limb leads derived from I and II and
  marked as such with Channel Derivation Description (003A,020C);
- channel sources coded from CID 3001 "ECG Lead" (ISO/IEEE 11073-10101),
  units from UCUM, the acquisition context from TID 3401, filter settings in
  hertz with the pass-band edges on the right attributes;
- the global measurements (rates, PR, QRS, QT, QTc, P/QRS/T axes) as coded
  Waveform Annotations from TID 3713 and CID 3229, with the PR, QRS and QT
  intervals and the P wave also carried as sample-position segments on the
  median beat.

`docs/mapping/attribute_mapping.csv` lists every attribute with its source
element and mapping strategy; `docs/mapping/coded_values.csv` lists every code
with its governing context group. `docs/conformance.md` explains why the
General ECG IOD is used (the 12-Lead ECG IOD allows at most 13 channels across
all groups) and what the two levels of validation do and do not check.

## De-identification

On by default. Names and site identifiers become `Anonymized`, the patient ID
becomes a per-run surrogate, dates keep year and month with the day set to 01,
times become 00:00:00, and the birth date and free-text interpretation are
dropped. See `docs/deidentification.md`. Pass `--keep-identity` to write the
source values.

## Commands

**`ecg2dcm-convert`** converts any supported file or directory, detecting the
format from the content:

```
ecg2dcm-convert path/to/files -o out/ --recursive [--uid-root 1.2.3.4] [--keep-identity]
```

**`ecg2dcm`** is the batch command used for the study corpus. It walks a
directory of GE MUSE XML files, names each output from a regular expression on
the input file name, and writes the surrogate-ID table next to the output:

```
ecg2dcm --project_root . --data_root /data --ecg_xml_dir muse_xml --output_dir ecg_dcm \
        --filename_pattern "MUSE_(?P<examination_date>\d{8})_(?P<examination_time>\d{6})_(?P<seq>\d{5})" \
        --out_filename_pattern "ECG_DICOM_{examination_date}_{seq}"
```

`--out_filename_pattern` must contain exactly one `{...date...}` key and should
contain `{seq}` (appended automatically otherwise).

**UID root.** Study, Series and SOP Instance UIDs are issued under `--uid-root`.
The default is pydicom's registered root, a placeholder; issue UIDs under your
organisation's own OID before production use.

## Python API

```python
from ecg2dcm import parse, build, write, check_iod_constraints

rec = parse('record.xml')                 # any supported format -> EcgRecord
ds = build(rec, index=1)                  # pydicom FileDataset, de-identified
assert check_iod_constraints(ds) == []    # General ECG IOD content constraints
ds.save_as('record.dcm', write_like_original=False)
```

Each front end lives in `ecg2dcm/adapters/` and produces the same intermediate
representation (`ecg2dcm/ir.py`); `ecg2dcm/writer.py` is the only place DICOM
is written.

## Reproducing the paper

`analysis/` holds the scripts behind the reported tables. They read the
institution's export archive or the public PhysioNet mirrors and write only
aggregate tables.

| Script | Result |
|---|---|
| `supp_table9_device_profile.py` | device and software profile of the corpus (Supplementary Table 9, part 1) |
| `stratified_conversion.py` | whole-corpus conversion, attribute-level validation, required-attribute completeness and IOD content constraints, stratified by device and software (Supplementary Table 9, part 2) |
| `coverage_matrix.py`, `wfdb_header_coverage.py` | attribute coverage by source format (Supplementary Table 10) |
| `run_wfdb.py` | five open WFDB datasets, as distributed and with the acquisition instant supplied |
| `ecg_cxr_pairing.py` | ECG and chest radiograph pairing in MIMIC-IV-ECG and MIMIC-CXR |

Validation uses dicom-validator against the 2024b edition of the standard
(`pip install "ecg2dcm[validate]"`, then `dicom-validator` downloads the edition).

## Examples and tests

`examples/` contains a synthetic GE MUSE file (generated by
`make_synthetic_muse.py`; nothing in it comes from a patient) and one publicly
released, MIT-licensed teaching file, each with its converted DICOM object; see
`examples/ATTRIBUTION.md`. `pytest tests` converts both and checks the objects.

## History

Formerly distributed as `XML2DCM-ECG` (last version 1.1.10); that name is
unmaintained. `CHANGELOG.md` lists what changed in each release, including the
corrections made during peer review.
