Ultimate Pydicom Framework
Boost productivity using this python, library, working, dicom. Includes structured workflows, validation checks, and reusable patterns for scientific.
Ultimate PyDICOM Framework
Read, modify, and create medical imaging DICOM files using pydicom. This skill covers DICOM file parsing, pixel data extraction, metadata manipulation, anonymization, and building medical image processing pipelines for radiology and pathology applications.
When to Use This Skill
Choose Ultimate PyDICOM Framework when you need to:
- Read and parse DICOM files from CT, MRI, X-ray, or ultrasound modalities
- Extract pixel data for image analysis or machine learning preprocessing
- Anonymize patient information in DICOM files for research compliance
- Create or modify DICOM metadata tags for data management
Consider alternatives when:
- You need DICOM networking (C-STORE, C-FIND, C-MOVE) (use pynetdicom)
- You need 3D medical image analysis with registration (use SimpleITK or ANTs)
- You need deep learning on medical images specifically (use MONAI)
Quick Start
pip install pydicom numpy matplotlib
import pydicom import matplotlib.pyplot as plt # Read a DICOM file ds = pydicom.dcmread("ct_scan.dcm") # Access metadata print(f"Patient: {ds.PatientName}") print(f"Study: {ds.StudyDescription}") print(f"Modality: {ds.Modality}") print(f"Image size: {ds.Rows} x {ds.Columns}") print(f"Pixel spacing: {ds.PixelSpacing}") # Display pixel data pixel_array = ds.pixel_array plt.imshow(pixel_array, cmap="gray") plt.title(f"{ds.Modality}: {ds.SeriesDescription}") plt.colorbar(label="HU" if ds.Modality == "CT" else "Intensity") plt.savefig("dicom_image.png", dpi=150)
Core Concepts
DICOM Data Elements
| Tag | Keyword | Description |
|---|---|---|
| (0010,0010) | PatientName | Patient's full name |
| (0010,0020) | PatientID | Patient identifier |
| (0008,0060) | Modality | Imaging modality (CT, MR, US) |
| (0028,0010) | Rows | Image height in pixels |
| (0028,0011) | Columns | Image width in pixels |
| (0028,0030) | PixelSpacing | Physical pixel dimensions (mm) |
| (0020,0032) | ImagePositionPatient | 3D position of image origin |
| (0028,1052) | RescaleIntercept | Pixel value offset (for HU) |
| (0028,1053) | RescaleSlope | Pixel value scale factor |
CT Volume Reconstruction
import pydicom import numpy as np from pathlib import Path def load_ct_volume(directory): """Load and reconstruct a 3D CT volume from DICOM series.""" dicom_dir = Path(directory) slices = [] for dcm_file in sorted(dicom_dir.glob("*.dcm")): ds = pydicom.dcmread(str(dcm_file)) slices.append(ds) # Sort by ImagePositionPatient (z-coordinate) slices.sort(key=lambda s: float(s.ImagePositionPatient[2])) # Convert to Hounsfield Units volume = np.stack([s.pixel_array for s in slices]) slope = float(slices[0].RescaleSlope) intercept = float(slices[0].RescaleIntercept) volume_hu = volume * slope + intercept # Get physical dimensions pixel_spacing = [float(x) for x in slices[0].PixelSpacing] slice_thickness = float(slices[0].SliceThickness) spacing = [slice_thickness] + pixel_spacing print(f"Volume shape: {volume_hu.shape}") print(f"Voxel spacing: {spacing} mm") print(f"HU range: [{volume_hu.min():.0f}, {volume_hu.max():.0f}]") return volume_hu, spacing, slices[0] volume, spacing, ref_slice = load_ct_volume("./ct_series/")
DICOM Anonymization
import pydicom from pydicom.uid import generate_uid from datetime import datetime def anonymize_dicom(ds, new_patient_id="ANON001"): """Remove or replace patient-identifying information.""" # Tags to remove completely tags_to_remove = [ "PatientName", "PatientBirthDate", "PatientAddress", "PatientTelephoneNumbers", "ReferringPhysicianName", "InstitutionName", "InstitutionAddress", "PerformingPhysicianName", "OperatorsName" ] for tag in tags_to_remove: if hasattr(ds, tag): delattr(ds, tag) # Replace with anonymized values ds.PatientName = new_patient_id ds.PatientID = new_patient_id ds.StudyInstanceUID = generate_uid() ds.SeriesInstanceUID = generate_uid() ds.SOPInstanceUID = generate_uid() # Shift dates (preserve intervals but change absolute dates) if hasattr(ds, "StudyDate"): ds.StudyDate = "19000101" if hasattr(ds, "SeriesDate"): ds.SeriesDate = "19000101" return ds # Anonymize a file ds = pydicom.dcmread("patient_scan.dcm") ds_anon = anonymize_dicom(ds) ds_anon.save_as("anonymized_scan.dcm")
Configuration
| Parameter | Description | Default |
|---|---|---|
force | Read files without valid DICOM preamble | false |
stop_before_pixels | Read metadata only (skip pixel data) | false |
specific_tags | Read only specified tags | All tags |
transfer_syntax | Pixel data encoding | Auto-detected |
apply_rescale | Apply RescaleSlope/Intercept to pixels | true |
apply_voi_lut | Apply VOI lookup table for display | false |
Best Practices
-
Always apply RescaleSlope and RescaleIntercept for CT — Raw pixel values in CT DICOM files are stored values, not Hounsfield Units. Apply
HU = pixel_value * RescaleSlope + RescaleInterceptto get physically meaningful values. Without this, windowing and thresholding produce wrong results. -
Sort slices by ImagePositionPatient, not filename — DICOM filenames have no guaranteed order. Sort by the z-coordinate of
ImagePositionPatientto reconstruct volumes in the correct anatomical order. Filename sorting works sometimes but fails with some PACS exports. -
Use
stop_before_pixels=Truefor metadata-only operations — When you only need to read tags (for querying, sorting, or anonymization), skip pixel data loading withpydicom.dcmread(path, stop_before_pixels=True). This is 10-100x faster for large image files. -
Handle compressed transfer syntaxes explicitly — DICOM files may use JPEG, JPEG2000, or RLE compression. Install
pylibjpegorgdcmto decode compressed pixel data. Attempting to read compressed files without the handler raisesNotImplementedError. -
Validate UIDs after anonymization — After replacing
StudyInstanceUID,SeriesInstanceUID, andSOPInstanceUID, verify that all files in a series share the sameStudyInstanceUIDandSeriesInstanceUIDbut have uniqueSOPInstanceUID. Inconsistent UIDs cause PACS import failures.
Common Issues
Pixel data appears inverted or wrong contrast — DICOM uses PhotometricInterpretation to indicate if pixel values represent light-on-dark or dark-on-light. Check ds.PhotometricInterpretation — if it's MONOCHROME1, invert the image: pixel_array = pixel_array.max() - pixel_array. MONOCHROME2 is the normal convention.
Cannot read compressed DICOM files — Error: NotImplementedError: no handler for transfer syntax. Install compression handlers: pip install pylibjpeg pylibjpeg-libjpeg pylibjpeg-openjpeg. For JPEG-LS, install gdcm. Check the transfer syntax with ds.file_meta.TransferSyntaxUID.
Missing tags in some DICOM files — Not all DICOM files contain all tags. Always check with hasattr(ds, 'TagName') or if 'TagName' in ds before accessing. Modality-specific tags (e.g., SliceThickness for CT) may be absent in other modalities. Use .get('TagName', default) for safer access.
Reviews
No reviews yet. Be the first to review this template!
Similar Templates
Full-Stack Code Reviewer
Comprehensive code review skill that checks for security vulnerabilities, performance issues, accessibility, and best practices across frontend and backend code.
Test Suite Generator
Generates comprehensive test suites with unit tests, integration tests, and edge cases. Supports Jest, Vitest, Pytest, and Go testing.
Pro Architecture Workspace
Battle-tested skill for architectural, decision, making, framework. Includes structured workflows, validation checks, and reusable patterns for development.