Skip to main content

Enterprise-grade medical-imaging pipeline: ingest, de-identify, convert, and QC DICOM for 3D Slicer and ITK-SNAP.

Project description

dicom-forge

CI Python Docs License

An enterprise-grade medical-imaging pipeline that prepares DICOM for 3D Slicer and ITK-SNAP.

dicom-forge takes a folder of DICOM, de-identifies it, runs quality control, and converts it into the formats clinical-research viewers load natively — NIfTI (.nii.gz), NRRD (.nrrd), and Slicer's segmentation format (.seg.nrrd). Every run produces a serialisable audit record.

It is the headless core of a two-repo system; its companion, slicer-forge, wraps it in a 3D Slicer extension GUI.

📌 New here? Read the project showcase for the big picture — the problem, the architecture, who it's for, and the engineering highlights.


Why this exists

Real imaging pipelines separate a testable, headless core from a thin GUI. 3D Slicer itself is built this way: ITK/VTK do the work, the GUI is a shell on top. dicom-forge is that core — so the logic is unit-tested in CI without needing Slicer installed, and the same code runs from the command line, from Python, or inside Slicer's Python console.

Features

  • Ingestion — recursive DICOM discovery, series grouping, geometry-aware slice ordering (handles oblique acquisitions), rescale-slope/intercept applied (CT in HU).
  • De-identification — three escalating levels modelled on the DICOM PS3.15 Basic Profile, with deterministic salted-hash pseudonymisation of PatientID.
  • Quality control — slice count, geometry consistency, slice-spacing regularity, and intensity statistics, split into blocking errors vs. non-blocking warnings.
  • Conversion — geometry-preserving export to NIfTI / NRRD via SimpleITK (the ITK core shared with Slicer & ITK-SNAP).
  • Segmentation — write Slicer-native .seg.nrrd label maps with named, coloured segments.
  • Typed & validated — Pydantic models everywhere, py.typed, strict mypy.
  • Two interfaces — a Rich CLI (dicomforge) and a clean Python API.
  • Native ITK pre-flight — a companion C++/ITK CLI, dicom-probe, reads a series through ITK's own GDCM path (the engine under Slicer/ITK-SNAP) and reports the true volume geometry as JSON.

Installation

pip install dicom-anvil            # core (ingest, de-id, QC)
pip install "dicom-anvil[convert]" # + SimpleITK/pynrrd/nibabel for conversion

Names: the package installs as dicom-anvil (the PyPI name dicom-forge was already taken) and imports as dicomforge; the repository stays dicom-forge.

The conversion stack (SimpleITK et al.) is an optional extra so the core stays lightweight and CI-friendly. Calling a conversion function without it raises a clear MissingDependencyError telling you exactly what to install.

Quick start

Command line

# List the series in a folder
dicomforge inspect ./study

# Run QC and print a report
dicomforge qc ./study

# Full pipeline: de-identify -> QC -> convert to Slicer NRRD
dicomforge convert ./study ./out/patient01 --format nrrd --deid-level moderate

Python

from dicomforge import run_pipeline, PipelineConfig, OutputFormat

result = run_pipeline(
    "./study",
    "./out/patient01",
    config=PipelineConfig(output_format=OutputFormat.NRRD),
)
print(result.qc.passed)                 # True / False
print(result.conversion.output_path)    # ./out/patient01.nrrd
print(result.model_dump_json(indent=2)) # full audit record

Pipeline order (and why it matters)

ingest ──> de-identify ──> QC ──> convert

De-identification runs before conversion, so any file written to disk is already free of direct identifiers. De-id is performed in memory — your source DICOM is never modified.

⚠️ De-identification is risk reduction, not a legal guarantee. Burned-in pixel annotations and private vendor tags can still carry PHI. Always review output before releasing it outside a controlled environment.

Development

python -m venv .venv && . .venv/Scripts/activate   # Windows
pip install -e ".[dev,convert]"
pytest                      # run the suite (synthetic DICOM, no real data needed)
ruff check . && mypy        # lint + type-check

License

PolyForm Noncommercial License 1.0.0 © Angela Hudson

Noncommercial use — personal, research, educational, and other noncommercial purposes as defined by the license — is free. Any commercial use requires a separate license from the copyright holder. See LICENSE for the full terms, or open an issue to ask about commercial licensing.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dicom_anvil-0.1.1.tar.gz (41.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dicom_anvil-0.1.1-py3-none-any.whl (26.6 kB view details)

Uploaded Python 3

File details

Details for the file dicom_anvil-0.1.1.tar.gz.

File metadata

  • Download URL: dicom_anvil-0.1.1.tar.gz
  • Upload date:
  • Size: 41.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dicom_anvil-0.1.1.tar.gz
Algorithm Hash digest
SHA256 3d50644d08841d66fefd3f28dd9e2545f3702c641bab94e2fc2ee68bdd70f391
MD5 a1eceba95c95470f90fc1f0391e6fd1d
BLAKE2b-256 210d7c21efac95ceddb90f387b145f6fce820f6ef307b9b41f64e2b9299a55a2

See more details on using hashes here.

Provenance

The following attestation bundles were made for dicom_anvil-0.1.1.tar.gz:

Publisher: release.yml on DaCameraGirl/dicom-forge

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dicom_anvil-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: dicom_anvil-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 26.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dicom_anvil-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 600e0788408746d6952f526da0603e11e7b13efb8c04aabc5cfbef280a7da86e
MD5 e6d6c3f8484e545abe2b50d80329953d
BLAKE2b-256 0aa6745d72dcb60179e1c72e6b2d7def43d0f44feffc2d36497ab8de1593aa52

See more details on using hashes here.

Provenance

The following attestation bundles were made for dicom_anvil-0.1.1-py3-none-any.whl:

Publisher: release.yml on DaCameraGirl/dicom-forge

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page