Skill v1.0.0
currentAutomated scan100/100version: "1.0.0" name: pydicom description: Python library for working with DICOM (Digital Imaging and Communications in Medicine) files. Use this skill when reading, writing, or modifying medical imaging data in DICOM format, extracting pixel data from medical images (CT, MRI, X-ray, ultrasound), anonymizing DICOM files, working with DICOM metadata and tags, converting DICOM images to other formats, handling compressed DICOM data, or processing medical imaging datasets. Applies to tasks involving medical image analysis, PACS systems, radiology workflows, and healthcare imaging applications. license: https://github.com/pydicom/pydicom/blob/main/LICENSE tags: [scientific-skills, pydicom, computer-vision, writing, git, python, clinical] metadata: skill-author: K-Dense Inc.
Pydicom
Overview
Pydicom is a pure Python package for working with DICOM files, the standard format for medical imaging data. This skill provides guidance on reading, writing, and manipulating DICOM files, including working with pixel data, metadata, and various compression formats.
When to Use This Skill
Use this skill when working with:
- Medical imaging files (CT, MRI, X-ray, ultrasound, PET, etc.)
- DICOM datasets requiring metadata extraction or modification
- Pixel data extraction and image processing from medical scans
- DICOM anonymization for research or data sharing
- Converting DICOM files to standard image formats
- Compressed DICOM data requiring decompression
- DICOM sequences and structured reports
- Multi-slice volume reconstruction
- PACS (Picture Archiving and Communication System) integration
Installation
Install pydicom and common dependencies:
uv pip install pydicomuv pip install pillow # For image format conversionuv pip install numpy # For pixel array manipulationuv pip install matplotlib # For visualization
For handling compressed DICOM files, additional packages may be needed:
uv pip install pylibjpeg pylibjpeg-libjpeg pylibjpeg-openjpeg # JPEG compressionuv pip install python-gdcm # Alternative compression handler
Core Workflows
Reading DICOM Files
Read a DICOM file using pydicom.dcmread():
import pydicom# Read a DICOM fileds = pydicom.dcmread('path/to/file.dcm')# Access metadataprint(f"Patient Name: {ds.PatientName}")print(f"Study Date: {ds.StudyDate}")print(f"Modality: {ds.Modality}")# Display all elementsprint(ds)
Key points:
dcmread()returns aDatasetobject- Access data elements using attribute notation (e.g.,
ds.PatientName) or tag notation (e.g.,ds[0x0010, 0x0010]) - Use
ds.file_metato access file metadata like Transfer Syntax UID - Handle missing attributes with
getattr(ds, 'AttributeName', default_value)orhasattr(ds, 'AttributeName')
Working with Pixel Data
Extract and manipulate image data from DICOM files:
import pydicomimport numpy as npimport matplotlib.pyplot as plt# Read DICOM fileds = pydicom.dcmread('image.dcm')# Get pixel array (requires numpy)pixel_array = ds.pixel_array# Image informationprint(f"Shape: {pixel_array.shape}")print(f"Data type: {pixel_array.dtype}")print(f"Rows: {ds.Rows}, Columns: {ds.Columns}")# Apply windowing for display (CT/MRI)if hasattr(ds, 'WindowCenter') and hasattr(ds, 'WindowWidth'):from pydicom.pixel_data_handlers.util import apply_voi_lutwindowed_image = apply_voi_lut(pixel_array, ds)else:windowed_image = pixel_array# Display imageplt.imshow(windowed_image, cmap='gray')plt.title(f"{ds.Modality} - {ds.StudyDescription}")plt.axis('off')plt.show()
Working with color images:
# RGB images have shape (rows, columns, 3)if ds.PhotometricInterpretation == 'RGB':rgb_image = ds.pixel_arrayplt.imshow(rgb_image)elif ds.PhotometricInterpretation == 'YBR_FULL':from pydicom.pixel_data_handlers.util import convert_color_spacergb_image = convert_color_space(ds.pixel_array, 'YBR_FULL', 'RGB')plt.imshow(rgb_image)
Multi-frame images (videos/series):
# For multi-frame DICOM filesif hasattr(ds, 'NumberOfFrames') and ds.NumberOfFrames > 1:frames = ds.pixel_array # Shape: (num_frames, rows, columns)print(f"Number of frames: {frames.shape[0]}")# Display specific frameplt.imshow(frames[0], cmap='gray')
Converting DICOM to Image Formats
Use the provided dicom_to_image.py script or convert manually:
from PIL import Imageimport pydicomimport numpy as npds = pydicom.dcmread('input.dcm')pixel_array = ds.pixel_array# Normalize to 0-255 rangeif pixel_array.dtype != np.uint8:pixel_array = ((pixel_array - pixel_array.min()) /(pixel_array.max() - pixel_array.min()) * 255).astype(np.uint8)# Save as PNGimage = Image.fromarray(pixel_array)image.save('output.png')
Use the script: python scripts/dicom_to_image.py input.dcm output.png
Modifying Metadata
Modify DICOM data elements:
import pydicomfrom datetime import datetimeds = pydicom.dcmread('input.dcm')# Modify existing elementsds.PatientName = "Doe^John"ds.StudyDate = datetime.now().strftime('%Y%m%d')ds.StudyDescription = "Modified Study"# Add new elementsds.SeriesNumber = 1ds.SeriesDescription = "New Series"# Remove elementsif hasattr(ds, 'PatientComments'):delattr(ds, 'PatientComments')# Or using delif 'PatientComments' in ds:del ds.PatientComments# Save modified fileds.save_as('modified.dcm')
Anonymizing DICOM Files
Remove or replace patient identifiable information:
import pydicomfrom datetime import datetimeds = pydicom.dcmread('input.dcm')# Tags commonly containing PHI (Protected Health Information)tags_to_anonymize = ['PatientName', 'PatientID', 'PatientBirthDate','PatientSex', 'PatientAge', 'PatientAddress','InstitutionName', 'InstitutionAddress','ReferringPhysicianName', 'PerformingPhysicianName','OperatorsName', 'StudyDescription', 'SeriesDescription',]# Remove or replace sensitive datafor tag in tags_to_anonymize:if hasattr(ds, tag):if tag in ['PatientName', 'PatientID']:setattr(ds, tag, 'ANONYMOUS')elif tag == 'PatientBirthDate':setattr(ds, tag, '19000101')else:delattr(ds, tag)# Update dates to maintain temporal relationshipsif hasattr(ds, 'StudyDate'):# Shift dates by a random offsetds.StudyDate = '20000101'# Keep pixel data intactds.save_as('anonymized.dcm')
Use the provided script: python scripts/anonymize_dicom.py input.dcm output.dcm
Writing DICOM Files
Create DICOM files from scratch:
import pydicomfrom pydicom.dataset import Dataset, FileDatasetfrom datetime import datetimeimport numpy as np# Create file meta informationfile_meta = Dataset()file_meta.MediaStorageSOPClassUID = pydicom.uid.generate_uid()file_meta.MediaStorageSOPInstanceUID = pydicom.uid.generate_uid()file_meta.TransferSyntaxUID = pydicom.uid.ExplicitVRLittleEndian# Create the FileDataset instanceds = FileDataset('new_dicom.dcm', {}, file_meta=file_meta, preamble=b"\0" * 128)# Add required DICOM elementsds.PatientName = "Test^Patient"ds.PatientID = "123456"ds.Modality = "CT"ds.StudyDate = datetime.now().strftime('%Y%m%d')ds.StudyTime = datetime.now().strftime('%H%M%S')ds.ContentDate = ds.StudyDateds.ContentTime = ds.StudyTime# Add image-specific elementsds.SamplesPerPixel = 1ds.PhotometricInterpretation = "MONOCHROME2"ds.Rows = 512ds.Columns = 512ds.BitsAllocated = 16ds.BitsStored = 16ds.HighBit = 15ds.PixelRepresentation = 0# Create pixel datapixel_array = np.random.randint(0, 4096, (512, 512), dtype=np.uint16)ds.PixelData = pixel_array.tobytes()# Add required UIDsds.SOPClassUID = pydicom.uid.CTImageStorageds.SOPInstanceUID = file_meta.MediaStorageSOPInstanceUIDds.SeriesInstanceUID = pydicom.uid.generate_uid()ds.StudyInstanceUID = pydicom.uid.generate_uid()# Save the fileds.save_as('new_dicom.dcm')
Compression and Decompression
Handle compressed DICOM files:
import pydicom# Read compressed DICOM fileds = pydicom.dcmread('compressed.dcm')# Check transfer syntaxprint(f"Transfer Syntax: {ds.file_meta.TransferSyntaxUID}")print(f"Transfer Syntax Name: {ds.file_meta.TransferSyntaxUID.name}")# Decompress and save as uncompressedds.decompress()ds.save_as('uncompressed.dcm', write_like_original=False)# Or compress when saving (requires appropriate encoder)ds_uncompressed = pydicom.dcmread('uncompressed.dcm')ds_uncompressed.compress(pydicom.uid.JPEGBaseline8Bit)ds_uncompressed.save_as('compressed_jpeg.dcm')
Common transfer syntaxes:
ExplicitVRLittleEndian- Uncompressed, most commonJPEGBaseline8Bit- JPEG lossy compressionJPEGLossless- JPEG lossless compressionJPEG2000Lossless- JPEG 2000 losslessRLELossless- Run-Length Encoding lossless
See references/transfer_syntaxes.md for complete list.
Working with DICOM Sequences
Handle nested data structures:
import pydicomds = pydicom.dcmread('file.dcm')# Access sequencesif 'ReferencedStudySequence' in ds:for item in ds.ReferencedStudySequence:print(f"Referenced SOP Instance UID: {item.ReferencedSOPInstanceUID}")# Create a sequencefrom pydicom.sequence import Sequencesequence_item = Dataset()sequence_item.ReferencedSOPClassUID = pydicom.uid.CTImageStoragesequence_item.ReferencedSOPInstanceUID = pydicom.uid.generate_uid()ds.ReferencedImageSequence = Sequence([sequence_item])
Processing DICOM Series
Work with multiple related DICOM files:
import pydicomimport numpy as npfrom pathlib import Path# Read all DICOM files in a directorydicom_dir = Path('dicom_series/')slices = []for file_path in dicom_dir.glob('*.dcm'):ds = pydicom.dcmread(file_path)slices.append(ds)# Sort by slice location or instance numberslices.sort(key=lambda x: float(x.ImagePositionPatient[2]))# Or: slices.sort(key=lambda x: int(x.InstanceNumber))# Create 3D volumevolume = np.stack([s.pixel_array for s in slices])print(f"Volume shape: {volume.shape}") # (num_slices, rows, columns)# Get spacing information for proper scalingpixel_spacing = slices[0].PixelSpacing # [row_spacing, col_spacing]slice_thickness = slices[0].SliceThicknessprint(f"Voxel size: {pixel_spacing[0]}x{pixel_spacing[1]}x{slice_thickness} mm")
Helper Scripts
This skill includes utility scripts in the scripts/ directory:
anonymize_dicom.py
Anonymize DICOM files by removing or replacing Protected Health Information (PHI).
python scripts/anonymize_dicom.py input.dcm output.dcm
dicom_to_image.py
Convert DICOM files to common image formats (PNG, JPEG, TIFF).
python scripts/dicom_to_image.py input.dcm output.pngpython scripts/dicom_to_image.py input.dcm output.jpg --format JPEG
extract_metadata.py
Extract and display DICOM metadata in a readable format.
python scripts/extract_metadata.py file.dcmpython scripts/extract_metadata.py file.dcm --output metadata.txt
Reference Materials
Detailed reference information is available in the references/ directory:
- common_tags.md: Comprehensive list of commonly used DICOM tags organized by category (Patient, Study, Series, Image, etc.)
- transfer_syntaxes.md: Complete reference of DICOM transfer syntaxes and compression formats
Common Issues and Solutions
Issue: "Unable to decode pixel data"
- Solution: Install additional compression handlers:
uv pip install pylibjpeg pylibjpeg-libjpeg python-gdcm
Issue: "AttributeError" when accessing tags
- Solution: Check if attribute exists with
hasattr(ds, 'AttributeName')or useds.get('AttributeName', default)
Issue: Incorrect image display (too dark/bright)
- Solution: Apply VOI LUT windowing:
apply_voi_lut(pixel_array, ds)or manually adjust withWindowCenterandWindowWidth
Issue: Memory issues with large series
- Solution: Process files iteratively, use memory-mapped arrays, or downsample images
Best Practices
- Always check for required attributes before accessing them using
hasattr()orget() - Preserve file metadata when modifying files by using
save_as()withwrite_like_original=True - Use Transfer Syntax UIDs to understand compression format before processing pixel data
- Handle exceptions when reading files from untrusted sources
- Apply proper windowing (VOI LUT) for medical image visualization
- Maintain spatial information (pixel spacing, slice thickness) when processing 3D volumes
- Verify anonymization thoroughly before sharing medical data
- Use UIDs correctly - generate new UIDs when creating new instances, preserve them when modifying
Documentation
Official pydicom documentation: https://pydicom.github.io/pydicom/dev/
- User Guide: https://pydicom.github.io/pydicom/dev/guides/user/index.html
- Tutorials: https://pydicom.github.io/pydicom/dev/tutorials/index.html
- API Reference: https://pydicom.github.io/pydicom/dev/reference/index.html
- Examples: https://pydicom.github.io/pydicom/dev/auto_examples/index.html