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(andclean_pixel_datafor 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=Truefor real-world values (HU for CT) — rawpixel_arrayis stored integers, not physical units. - Geometry is computed in the engine — trust
Volume.affine/load_seriesordering; 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.