Skip to content

pydcm — DICOM workflows in Python

pydcm is one wheel that decodes every transfer syntax and reads every character set, then carries a workflow the whole way — volumes, NIfTI, SEG/RT/SR, radiomics, perfusion, WSI, waveforms, networking. This skill maps tasks → API and gives end-to-end recipes; it does not duplicate the per-function docs — get exact signatures from the API reference or help(pydcm.x).

Two ways to drive it

  • Python API (import pydcm) — for agents that write code. Returns native objects: NumPy arrays, Dataset, Volume, plain dicts. This is the richest surface and the default.
  • In-process MCP (python -m pydcm.mcp, ~79 tools) — for tool-calling agents. Same engine, JSON in/out, including live-object operations on in-memory DICOM (transforms, volumes, authoring) that a file-only CLI cannot express. See Agent / MCP server to wire it up.

Not a medical device. Decoded pixels, HU, dose, radiomic and perfusion values are for research and engineering only — never clinical/diagnostic use.

Capability map (task → API)

Task API
Read / write a file (any TS, any charset) pydcm.dcmread, Dataset.save_as, pydcm.dcmwrite
Decode pixels → NumPy / HU / Torch pydcm.decode(path, rescale=True, to_torch=…), ds.pixel_array
Build a 3-D volume (sorted, affine) pydcm.load_series(dir)Volume (.pixels, .affine, .to_nifti)
Build a 4-D stack (time / echo / phase) pydcm.load_4d(dir)Volume4D; DWI: pydcm.load_dwi
DICOM ↔ NIfTI / BIDS / DWI Volume.to_nifti, pydcm.from_nifti, pydcm.bids_sidecar, save_dwi
Volume → NRRD / MetaImage (3D Slicer · ITK) Volume.to_nrrd(path, gzip=…), Volume.to_metaimage(path, compress=…) (double-faithful LPS)
PyTorch dataset / DataLoader pydcm.DICOMDataset(dir, to_torch=True)
Preprocess (resample / normalize / window) pydcm.transforms.* (bit-exact spatial ops on arrays)
Radiomics (IBSI, + custom features) pydcm.radiomics(img, mask=…); @pydcm.radiomics.feature(...)
RT dose + DVH pydcm.read_rtdose, pydcm.write_rtdose, pydcm.dvhcalc
DCE-MRI perfusion (Ktrans / ve / vp) pydcm.dce.fit_series, dce.parker_aif, dce.write_param_maps
Whole-slide imaging pydcm.wsi (OpenSlide-style region/tile reads + write_slide)
Author / read SEG pydcm.write_seg, write_seg_from_prediction, pydcm.read_seg
Parametric map / SR / KOS / GSPS write_paramap, write_report/write_sr/sr_to_html, write_ko, write_pr
Semantic content of any object pydcm.content(path) → JSON (SEG / RT / PS / SR / waveform / OPV)
Waveforms (ECG / EEG) pydcm.waveforms
Ophthalmic visual field pydcm.opv
De-identify (PS3.15 Annex E) pydcm.deidentify, deidentify_series, clean_pixel_data
Validate (full conformance: element + IOD + SR) pydcm.validate, pydcm.iod_validate, pydcm.sr_validate
DICOMweb (QIDO/WADO/STOW/UPS/delete) pydcm.dicomweb
DIMSE (echo/store/find/get/move + N-services, SCU+SCP) pydcm.dimse
FHIR / HL7 bridges pydcm.fhir.imaging_study, pydcm.hl7
Encapsulated documents (PDF/CDA/STL/…) pydcm.write_encapsulated, read_encapsulated

Core loops (canonical recipes)

PACS → de-identified volume for a model

import pydcm
from pydcm import dicomweb
dicomweb.iter_study("https://pacs", study_uid)      # or pydcm.dimse for DIMSE
pydcm.deidentify_series(files, out_dir="deid/")     # de-identify BEFORE anything downstream
vol = pydcm.load_series("deid/")                    # sorted 3-D HU volume + affine
vol.to_nifti("ct.nii.gz")

Inference → segmentation object

logits = pydcm.transforms.sliding_window_inference(vol.pixels, (96,)*3, model)
pydcm.write_seg_from_prediction(logits.argmax(0), "ct_series/", segments, output="pred.dcm")
pydcm.validate("pred.dcm")                          # full conformance (element + IOD + SR) before egress

Dynamic series → perfusion maps

from pydcm import dce
maps = dce.fit_series("dce_study/", times_min, model="ext_tofts",
                      input="signal", tr_s=0.005, fa_deg=25.0, aif=dce.parker_aif(times_min))
dce.write_param_maps("dce_study/", maps)            # Ktrans / ve / vp as DICOM Parametric Maps

Deeper recipes by capability

Each capability has a task-focused how-to: NIfTI/BIDS/DWI · Preprocessing · Radiomics · Perfusion (DCE) · WSI · Segmentations · Parametric maps · Structured reports · RT dose & DVH · DIMSE · DICOMweb · Waveforms · Ophthalmic visual field · FHIR / HL7 · Agent / MCP server

Guardrails (do not skip)

  • De-identify before egress. Run deidentify / deidentify_series (and clean_pixel_data for burned-in PHI) before sending data anywhere; a batch shares one session so UIDs remap consistently across the study.
  • Validate authored objects (validate — element + IOD + SR in one call) before writing SEG / RT / SR / parametric maps out.
  • Use rescale=True for real-world values (HU for CT) — raw pixel_array is stored integers, not physical units.
  • Geometry is computed in the engine — trust Volume.affine / load_series ordering; don't re-derive it in Python.
  • Not a medical device — research/engineering only.

Going deeper

  • Exact signatures / types: API reference or help(pydcm.<name>).
  • As an MCP server: python -m pydcm.mcp (≈79 tools) — see Agent / MCP server.
  • Behaviour notes: divergences (deliberate choices, limits).
  • For a shell / no-Python agent, the command-line counterpart over the same imaging engine is a separate product.