Published! See the Technical Note and please cite it if you find this work useful. DOI: https://doi.org/10.1016/j.prro.2021.02.003
Convert DICOM images and RT structures into NIfTI files, NumPy arrays, and SimpleITK image handles — and convert prediction masks back into RT structures.
pip install DicomRTToolFor the interactive image viewer (requires matplotlib):
pip install "DicomRTTool[viewer]"Supported Python versions: 3.10, 3.11, 3.12, 3.13.
from pathlib import Path
from DicomRTTool.ReaderWriter import DicomReaderWriter, ROIAssociationClass
dicom_path = Path("/path/to/dicom")
reader = DicomReaderWriter(description="Examples", arg_max=True)
reader.walk_through_folders(dicom_path)
# Inspect available ROIs.
all_rois = reader.return_rois(print_rois=True)
# Define target ROIs with optional name aliases.
contour_names = ["tumor"]
associations = [ROIAssociationClass("tumor", ["tumor_mr", "tumor_ct"])]
reader.set_contour_names_and_associations(
contour_names=contour_names,
associations=associations,
)
# Load images and masks for the first index that contains all target ROIs.
reader.set_index(reader.indexes_with_contours[0])
reader.get_images_and_mask()
image_numpy = reader.ArrayDicom # NumPy image array
mask_numpy = reader.mask # NumPy mask array
image_handle = reader.dicom_handle # SimpleITK Image
mask_handle = reader.annotation_handle # SimpleITK Imagefrom pydicom.tag import Tag
plan_keys = {"MyNamedRTPlan": Tag((0x300a, 0x002))}
image_keys = {"MyPatientName": "0010|0010"}
reader = DicomReaderWriter(
description="Examples",
arg_max=True,
plan_pydicom_string_keys=plan_keys,
image_sitk_string_keys=image_keys,
)DicomReaderWriter instances can be reused across multiple corpora; call
the appropriate reset method before walking a fresh folder tree or
swapping target ROIs:
reader.reset() # wipe everything (images, RTs, masks, cached UIDs)
reader.reset_rts() # clear ROI bookkeeping only; keep loaded images
reader.reset_mask() # re-allocate an empty mask after changing Contour_Namesimport numpy as np
# 4-channel one-hot prediction matching the loaded image shape:
# (slices, rows, cols, num_classes + 1) — channel 0 is background.
predictions = np.zeros((*reader.ArrayDicom.shape, 3), dtype=np.float32)
# ... populate `predictions` from your model ...
reader.prediction_array_to_RT(
prediction_array=predictions,
output_dir="/path/to/output",
ROI_Names=["organ_a", "organ_b"],
)- Python 3.10+ required (3.8 / 3.9 are end-of-life).
- Public state-reset API:
reset(),reset_rts(),reset_mask()— replaces the v3__reset__/__reset_mask__/__reset_RTs__accessors. - Deprecated v3 names removed:
down_folder→walk_through_folders,where_are_RTs→where_is_ROI,with_annotations→prediction_array_to_RT, plus the__set_iteration__and__set_description__setters renamed toset_iteration/set_description. SeeCHANGELOG.mdfor the full list and migration notes. - Excel → CSV for both bulk-export helpers, dropping the
openpyxldependency:characterize_data_to_excelis nowcharacterize_data_to_csv, andwrite_parallel(excel_file=…)is nowwrite_parallel(index_file=…)accepting a.csvpath. struct_pydicom_string_keysplumbing finally works — historically the parameter was accepted but the values never reached the parsed RT records.- Architecture: the original
ReaderWriter.pygod-class has been partly extracted into a new internal_internal/package. The publicDicomReaderWriterAPI is unchanged. - Hermetic test suite: every DICOM file the tests need is generated in a tmp directory at session start from analytical primitives. No external corpus, no network, no caches — the full suite runs in ~6 seconds and validates against analytically-known volume truth.
- Tooling: ruff replaces flake8; PyPI Trusted Publishing replaces the PYPI_TOKEN secret; CI matrix expanded to ubuntu + windows × four Python versions; pre-commit config added.
If you find this code useful, please reference the publication and the GitHub page.