
Pydicom
- 41 installs
- 16 repo stars
- Updated August 4, 2026
- jackspace/claudeskillz
Read, write, and modify DICOM medical images - extract pixel data, edit metadata/tags, anonymize, and convert formats.
About
A pure-Python library for reading, writing, and manipulating DICOM medical imaging files. A developer uses it to extract pixel data, edit metadata, anonymize scans, or process CT/MRI/X-ray datasets.
- Read/write DICOM with metadata and pixel-array access
- Anonymization, compression handling, and format conversion
Pydicom by the numbers
- 41 all-time installs (skills.sh)
- Ranked #995 of 2,064 Data Science & ML skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/jackspace/claudeskillz --skill pydicomAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 41 |
|---|---|
| repo stars | ★ 16 |
| Last updated | August 4, 2026 |
| Repository | jackspace/claudeskillz ↗ |
What it does
Read, write, and modify DICOM medical images - extract pixel data, edit metadata/tags, anonymize, and convert formats.
Files
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:
pip install pydicom
pip install pillow # For image format conversion
pip install numpy # For pixel array manipulation
pip install matplotlib # For visualizationFor handling compressed DICOM files, additional packages may be needed:
pip install pylibjpeg pylibjpeg-libjpeg pylibjpeg-openjpeg # JPEG compression
pip install python-gdcm # Alternative compression handlerCore Workflows
Reading DICOM Files
Read a DICOM file using pydicom.dcmread():
import pydicom
# Read a DICOM file
ds = pydicom.dcmread('path/to/file.dcm')
# Access metadata
print(f"Patient Name: {ds.PatientName}")
print(f"Study Date: {ds.StudyDate}")
print(f"Modality: {ds.Modality}")
# Display all elements
print(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 pydicom
import numpy as np
import matplotlib.pyplot as plt
# Read DICOM file
ds = pydicom.dcmread('image.dcm')
# Get pixel array (requires numpy)
pixel_array = ds.pixel_array
# Image information
print(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_lut
windowed_image = apply_voi_lut(pixel_array, ds)
else:
windowed_image = pixel_array
# Display image
plt.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_array
plt.imshow(rgb_image)
elif ds.PhotometricInterpretation == 'YBR_FULL':
from pydicom.pixel_data_handlers.util import convert_color_space
rgb_image = convert_color_space(ds.pixel_array, 'YBR_FULL', 'RGB')
plt.imshow(rgb_image)Multi-frame images (videos/series):
# For multi-frame DICOM files
if 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 frame
plt.imshow(frames[0], cmap='gray')Converting DICOM to Image Formats
Use the provided dicom_to_image.py script or convert manually:
from PIL import Image
import pydicom
import numpy as np
ds = pydicom.dcmread('input.dcm')
pixel_array = ds.pixel_array
# Normalize to 0-255 range
if pixel_array.dtype != np.uint8:
pixel_array = ((pixel_array - pixel_array.min()) /
(pixel_array.max() - pixel_array.min()) * 255).astype(np.uint8)
# Save as PNG
image = 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 pydicom
from datetime import datetime
ds = pydicom.dcmread('input.dcm')
# Modify existing elements
ds.PatientName = "Doe^John"
ds.StudyDate = datetime.now().strftime('%Y%m%d')
ds.StudyDescription = "Modified Study"
# Add new elements
ds.SeriesNumber = 1
ds.SeriesDescription = "New Series"
# Remove elements
if hasattr(ds, 'PatientComments'):
delattr(ds, 'PatientComments')
# Or using del
if 'PatientComments' in ds:
del ds.PatientComments
# Save modified file
ds.save_as('modified.dcm')Anonymizing DICOM Files
Remove or replace patient identifiable information:
import pydicom
from datetime import datetime
ds = 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 data
for 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 relationships
if hasattr(ds, 'StudyDate'):
# Shift dates by a random offset
ds.StudyDate = '20000101'
# Keep pixel data intact
ds.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 pydicom
from pydicom.dataset import Dataset, FileDataset
from datetime import datetime
import numpy as np
# Create file meta information
file_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 instance
ds = FileDataset('new_dicom.dcm', {}, file_meta=file_meta, preamble=b"\0" * 128)
# Add required DICOM elements
ds.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.StudyDate
ds.ContentTime = ds.StudyTime
# Add image-specific elements
ds.SamplesPerPixel = 1
ds.PhotometricInterpretation = "MONOCHROME2"
ds.Rows = 512
ds.Columns = 512
ds.BitsAllocated = 16
ds.BitsStored = 16
ds.HighBit = 15
ds.PixelRepresentation = 0
# Create pixel data
pixel_array = np.random.randint(0, 4096, (512, 512), dtype=np.uint16)
ds.PixelData = pixel_array.tobytes()
# Add required UIDs
ds.SOPClassUID = pydicom.uid.CTImageStorage
ds.SOPInstanceUID = file_meta.MediaStorageSOPInstanceUID
ds.SeriesInstanceUID = pydicom.uid.generate_uid()
ds.StudyInstanceUID = pydicom.uid.generate_uid()
# Save the file
ds.save_as('new_dicom.dcm')Compression and Decompression
Handle compressed DICOM files:
import pydicom
# Read compressed DICOM file
ds = pydicom.dcmread('compressed.dcm')
# Check transfer syntax
print(f"Transfer Syntax: {ds.file_meta.TransferSyntaxUID}")
print(f"Transfer Syntax Name: {ds.file_meta.TransferSyntaxUID.name}")
# Decompress and save as uncompressed
ds.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 pydicom
ds = pydicom.dcmread('file.dcm')
# Access sequences
if 'ReferencedStudySequence' in ds:
for item in ds.ReferencedStudySequence:
print(f"Referenced SOP Instance UID: {item.ReferencedSOPInstanceUID}")
# Create a sequence
from pydicom.sequence import Sequence
sequence_item = Dataset()
sequence_item.ReferencedSOPClassUID = pydicom.uid.CTImageStorage
sequence_item.ReferencedSOPInstanceUID = pydicom.uid.generate_uid()
ds.ReferencedImageSequence = Sequence([sequence_item])Processing DICOM Series
Work with multiple related DICOM files:
import pydicom
import numpy as np
from pathlib import Path
# Read all DICOM files in a directory
dicom_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 number
slices.sort(key=lambda x: float(x.ImagePositionPatient[2]))
# Or: slices.sort(key=lambda x: int(x.InstanceNumber))
# Create 3D volume
volume = np.stack([s.pixel_array for s in slices])
print(f"Volume shape: {volume.shape}") # (num_slices, rows, columns)
# Get spacing information for proper scaling
pixel_spacing = slices[0].PixelSpacing # [row_spacing, col_spacing]
slice_thickness = slices[0].SliceThickness
print(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.dcmdicom_to_image.py
Convert DICOM files to common image formats (PNG, JPEG, TIFF).
python scripts/dicom_to_image.py input.dcm output.png
python scripts/dicom_to_image.py input.dcm output.jpg --format JPEGextract_metadata.py
Extract and display DICOM metadata in a readable format.
python scripts/extract_metadata.py file.dcm
python scripts/extract_metadata.py file.dcm --output metadata.txtReference 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:
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
1. Always check for required attributes before accessing them using hasattr() or get() 2. Preserve file metadata when modifying files by using save_as() with write_like_original=True 3. Use Transfer Syntax UIDs to understand compression format before processing pixel data 4. Handle exceptions when reading files from untrusted sources 5. Apply proper windowing (VOI LUT) for medical image visualization 6. Maintain spatial information (pixel spacing, slice thickness) when processing 3D volumes 7. Verify anonymization thoroughly before sharing medical data 8. 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
{
"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.",
"references": {
"files": [
"references/common_tags.md",
"references/transfer_syntaxes.md"
]
},
"content": "### Reading DICOM Files\r\n\r\nRead a DICOM file using `pydicom.dcmread()`:\r\n\r\n```python\r\nimport pydicom\r\n\r\nds = pydicom.dcmread('path/to/file.dcm')\r\n\r\nprint(f\"Patient Name: {ds.PatientName}\")\r\nprint(f\"Study Date: {ds.StudyDate}\")\r\nprint(f\"Modality: {ds.Modality}\")\r\n\r\nprint(ds)\r\n```\r\n\r\n**Key points:**\r\n- `dcmread()` returns a `Dataset` object\r\n- Access data elements using attribute notation (e.g., `ds.PatientName`) or tag notation (e.g., `ds[0x0010, 0x0010]`)\r\n- Use `ds.file_meta` to access file metadata like Transfer Syntax UID\r\n- Handle missing attributes with `getattr(ds, 'AttributeName', default_value)` or `hasattr(ds, 'AttributeName')`\r\n\r\n### Working with Pixel Data\r\n\r\nExtract and manipulate image data from DICOM files:\r\n\r\n```python\r\nimport pydicom\r\nimport numpy as np\r\nimport matplotlib.pyplot as plt\r\n\r\nds = pydicom.dcmread('image.dcm')\r\n\r\npixel_array = ds.pixel_array\r\n\r\nprint(f\"Shape: {pixel_array.shape}\")\r\nprint(f\"Data type: {pixel_array.dtype}\")\r\nprint(f\"Rows: {ds.Rows}, Columns: {ds.Columns}\")\r\n\r\nif hasattr(ds, 'WindowCenter') and hasattr(ds, 'WindowWidth'):\r\n from pydicom.pixel_data_handlers.util import apply_voi_lut\r\n windowed_image = apply_voi_lut(pixel_array, ds)\r\nelse:\r\n windowed_image = pixel_array\r\n\r\nplt.imshow(windowed_image, cmap='gray')\r\nplt.title(f\"{ds.Modality} - {ds.StudyDescription}\")\r\nplt.axis('off')\r\nplt.show()\r\n```\r\n\r\n**Working with color images:**\r\n\r\n```python\r\nif ds.PhotometricInterpretation == 'RGB':\r\n rgb_image = ds.pixel_array\r\n plt.imshow(rgb_image)\r\nelif ds.PhotometricInterpretation == 'YBR_FULL':\r\n from pydicom.pixel_data_handlers.util import convert_color_space\r\n rgb_image = convert_color_space(ds.pixel_array, 'YBR_FULL', 'RGB')\r\n plt.imshow(rgb_image)\r\n```\r\n\r\n**Multi-frame images (videos/series):**\r\n\r\n```python\r\nif hasattr(ds, 'NumberOfFrames') and ds.NumberOfFrames > 1:\r\n frames = ds.pixel_array # Shape: (num_frames, rows, columns)\r\n print(f\"Number of frames: {frames.shape[0]}\")\r\n\r\n # Display specific frame\r\n plt.imshow(frames[0], cmap='gray')\r\n```\r\n\r\n### Converting DICOM to Image Formats\r\n\r\nUse the provided `dicom_to_image.py` script or convert manually:\r\n\r\n```python\r\nfrom PIL import Image\r\nimport pydicom\r\nimport numpy as np\r\n\r\nds = pydicom.dcmread('input.dcm')\r\npixel_array = ds.pixel_array\r\n\r\nif pixel_array.dtype != np.uint8:\r\n pixel_array = ((pixel_array - pixel_array.min()) /\r\n (pixel_array.max() - pixel_array.min()) * 255).astype(np.uint8)\r\n\r\nimage = Image.fromarray(pixel_array)\r\nimage.save('output.png')\r\n```\r\n\r\nUse the script: `python scripts/dicom_to_image.py input.dcm output.png`\r\n\r\n### Modifying Metadata\r\n\r\nModify DICOM data elements:\r\n\r\n```python\r\nimport pydicom\r\nfrom datetime import datetime\r\n\r\nds = pydicom.dcmread('input.dcm')\r\n\r\nds.PatientName = \"Doe^John\"\r\nds.StudyDate = datetime.now().strftime('%Y%m%d')\r\nds.StudyDescription = \"Modified Study\"\r\n\r\nds.SeriesNumber = 1\r\nds.SeriesDescription = \"New Series\"\r\n\r\nif hasattr(ds, 'PatientComments'):\r\n delattr(ds, 'PatientComments')\r\nif 'PatientComments' in ds:\r\n del ds.PatientComments\r\n\r\nds.save_as('modified.dcm')\r\n```\r\n\r\n### Anonymizing DICOM Files\r\n\r\nRemove or replace patient identifiable information:\r\n\r\n```python\r\nimport pydicom\r\nfrom datetime import datetime\r\n\r\nds = pydicom.dcmread('input.dcm')\r\n\r\ntags_to_anonymize = [\r\n 'PatientName', 'PatientID', 'PatientBirthDate',\r\n 'PatientSex', 'PatientAge', 'PatientAddress',\r\n 'InstitutionName', 'InstitutionAddress',\r\n 'ReferringPhysicianName', 'PerformingPhysicianName',\r\n 'OperatorsName', 'StudyDescription', 'SeriesDescription',\r\n]\r\n\r\nfor tag in tags_to_anonymize:\r\n if hasattr(ds, tag):\r\n if tag in ['PatientName', 'PatientID']:\r\n setattr(ds, tag, 'ANONYMOUS')\r\n elif tag == 'PatientBirthDate':\r\n setattr(ds, tag, '19000101')\r\n else:\r\n delattr(ds, tag)\r\n\r\nif hasattr(ds, 'StudyDate'):\r\n # Shift dates by a random offset\r\n ds.StudyDate = '20000101'\r\n\r\nds.save_as('anonymized.dcm')\r\n```\r\n\r\nUse the provided script: `python scripts/anonymize_dicom.py input.dcm output.dcm`\r\n\r\n### Writing DICOM Files\r\n\r\nCreate DICOM files from scratch:\r\n\r\n```python\r\nimport pydicom\r\nfrom pydicom.dataset import Dataset, FileDataset\r\nfrom datetime import datetime\r\nimport numpy as np\r\n\r\nfile_meta = Dataset()\r\nfile_meta.MediaStorageSOPClassUID = pydicom.uid.generate_uid()\r\nfile_meta.MediaStorageSOPInstanceUID = pydicom.uid.generate_uid()\r\nfile_meta.TransferSyntaxUID = pydicom.uid.ExplicitVRLittleEndian\r\n\r\nds = FileDataset('new_dicom.dcm', {}, file_meta=file_meta, preamble=b\"\\0\" * 128)\r\n\r\nds.PatientName = \"Test^Patient\"\r\nds.PatientID = \"123456\"\r\nds.Modality = \"CT\"\r\nds.StudyDate = datetime.now().strftime('%Y%m%d')\r\nds.StudyTime = datetime.now().strftime('%H%M%S')\r\nds.ContentDate = ds.StudyDate\r\nds.ContentTime = ds.StudyTime\r\n\r\nds.SamplesPerPixel = 1\r\nds.PhotometricInterpretation = \"MONOCHROME2\"\r\nds.Rows = 512\r\nds.Columns = 512\r\nds.BitsAllocated = 16\r\nds.BitsStored = 16\r\nds.HighBit = 15\r\nds.PixelRepresentation = 0\r\n\r\npixel_array = np.random.randint(0, 4096, (512, 512), dtype=np.uint16)\r\nds.PixelData = pixel_array.tobytes()\r\n\r\nds.SOPClassUID = pydicom.uid.CTImageStorage\r\nds.SOPInstanceUID = file_meta.MediaStorageSOPInstanceUID\r\nds.SeriesInstanceUID = pydicom.uid.generate_uid()\r\nds.StudyInstanceUID = pydicom.uid.generate_uid()\r\n\r\nds.save_as('new_dicom.dcm')\r\n```\r\n\r\n### Compression and Decompression\r\n\r\nHandle compressed DICOM files:\r\n\r\n```python\r\nimport pydicom\r\n\r\nds = pydicom.dcmread('compressed.dcm')\r\n\r\nprint(f\"Transfer Syntax: {ds.file_meta.TransferSyntaxUID}\")\r\nprint(f\"Transfer Syntax Name: {ds.file_meta.TransferSyntaxUID.name}\")\r\n\r\nds.decompress()\r\nds.save_as('uncompressed.dcm', write_like_original=False)\r\n\r\nds_uncompressed = pydicom.dcmread('uncompressed.dcm')\r\nds_uncompressed.compress(pydicom.uid.JPEGBaseline8Bit)\r\nds_uncompressed.save_as('compressed_jpeg.dcm')\r\n```\r\n\r\n**Common transfer syntaxes:**\r\n- `ExplicitVRLittleEndian` - Uncompressed, most common\r\n- `JPEGBaseline8Bit` - JPEG lossy compression\r\n- `JPEGLossless` - JPEG lossless compression\r\n- `JPEG2000Lossless` - JPEG 2000 lossless\r\n- `RLELossless` - Run-Length Encoding lossless\r\n\r\nSee `references/transfer_syntaxes.md` for complete list.\r\n\r\n### Working with DICOM Sequences\r\n\r\nHandle nested data structures:\r\n\r\n```python\r\nimport pydicom\r\n\r\nds = pydicom.dcmread('file.dcm')\r\n\r\nif 'ReferencedStudySequence' in ds:\r\n for item in ds.ReferencedStudySequence:\r\n print(f\"Referenced SOP Instance UID: {item.ReferencedSOPInstanceUID}\")\r\n\r\nfrom pydicom.sequence import Sequence\r\n\r\nsequence_item = Dataset()\r\nsequence_item.ReferencedSOPClassUID = pydicom.uid.CTImageStorage\r\nsequence_item.ReferencedSOPInstanceUID = pydicom.uid.generate_uid()\r\n\r\nds.ReferencedImageSequence = Sequence([sequence_item])\r\n```\r\n\r\n### Processing DICOM Series\r\n\r\nWork with multiple related DICOM files:\r\n\r\n```python\r\nimport pydicom\r\nimport numpy as np\r\nfrom pathlib import Path\r\n\r\ndicom_dir = Path('dicom_series/')\r\nslices = []\r\n\r\nfor file_path in dicom_dir.glob('*.dcm'):\r\n ds = pydicom.dcmread(file_path)\r\n slices.append(ds)\r\n\r\nslices.sort(key=lambda x: float(x.ImagePositionPatient[2]))\r\n\r\nvolume = np.stack([s.pixel_array for s in slices])\r\nprint(f\"Volume shape: {volume.shape}\") # (num_slices, rows, columns)",
"name": "pydicom",
"id": "scientific-pkg-pydicom",
"sections": {
"Common Issues and Solutions": "**Issue: \"Unable to decode pixel data\"**\r\n- Solution: Install additional compression handlers: `pip install pylibjpeg pylibjpeg-libjpeg python-gdcm`\r\n\r\n**Issue: \"AttributeError\" when accessing tags**\r\n- Solution: Check if attribute exists with `hasattr(ds, 'AttributeName')` or use `ds.get('AttributeName', default)`\r\n\r\n**Issue: Incorrect image display (too dark/bright)**\r\n- Solution: Apply VOI LUT windowing: `apply_voi_lut(pixel_array, ds)` or manually adjust with `WindowCenter` and `WindowWidth`\r\n\r\n**Issue: Memory issues with large series**\r\n- Solution: Process files iteratively, use memory-mapped arrays, or downsample images",
"Best Practices": "1. **Always check for required attributes** before accessing them using `hasattr()` or `get()`\r\n2. **Preserve file metadata** when modifying files by using `save_as()` with `write_like_original=True`\r\n3. **Use Transfer Syntax UIDs** to understand compression format before processing pixel data\r\n4. **Handle exceptions** when reading files from untrusted sources\r\n5. **Apply proper windowing** (VOI LUT) for medical image visualization\r\n6. **Maintain spatial information** (pixel spacing, slice thickness) when processing 3D volumes\r\n7. **Verify anonymization** thoroughly before sharing medical data\r\n8. **Use UIDs correctly** - generate new UIDs when creating new instances, preserve them when modifying",
"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.",
"Installation": "Install pydicom and common dependencies:\r\n\r\n```bash\r\npip install pydicom\r\npip install pillow # For image format conversion\r\npip install numpy # For pixel array manipulation\r\npip install matplotlib # For visualization\r\n```\r\n\r\nFor handling compressed DICOM files, additional packages may be needed:\r\n\r\n```bash\r\npip install pylibjpeg pylibjpeg-libjpeg pylibjpeg-openjpeg # JPEG compression\r\npip install python-gdcm # Alternative compression handler\r\n```",
"Core Workflows": "pixel_spacing = slices[0].PixelSpacing # [row_spacing, col_spacing]\r\nslice_thickness = slices[0].SliceThickness\r\nprint(f\"Voxel size: {pixel_spacing[0]}x{pixel_spacing[1]}x{slice_thickness} mm\")\r\n```",
"When to Use This Skill": "Use this skill when working with:\r\n- Medical imaging files (CT, MRI, X-ray, ultrasound, PET, etc.)\r\n- DICOM datasets requiring metadata extraction or modification\r\n- Pixel data extraction and image processing from medical scans\r\n- DICOM anonymization for research or data sharing\r\n- Converting DICOM files to standard image formats\r\n- Compressed DICOM data requiring decompression\r\n- DICOM sequences and structured reports\r\n- Multi-slice volume reconstruction\r\n- PACS (Picture Archiving and Communication System) integration",
"Helper Scripts": "This skill includes utility scripts in the `scripts/` directory:\r\n\r\n### anonymize_dicom.py\r\nAnonymize DICOM files by removing or replacing Protected Health Information (PHI).\r\n\r\n```bash\r\npython scripts/anonymize_dicom.py input.dcm output.dcm\r\n```\r\n\r\n### dicom_to_image.py\r\nConvert DICOM files to common image formats (PNG, JPEG, TIFF).\r\n\r\n```bash\r\npython scripts/dicom_to_image.py input.dcm output.png\r\npython scripts/dicom_to_image.py input.dcm output.jpg --format JPEG\r\n```\r\n\r\n### extract_metadata.py\r\nExtract and display DICOM metadata in a readable format.\r\n\r\n```bash\r\npython scripts/extract_metadata.py file.dcm\r\npython scripts/extract_metadata.py file.dcm --output metadata.txt\r\n```",
"Documentation": "Official pydicom documentation: https://pydicom.github.io/pydicom/dev/\r\n- User Guide: https://pydicom.github.io/pydicom/dev/guides/user/index.html\r\n- Tutorials: https://pydicom.github.io/pydicom/dev/tutorials/index.html\r\n- API Reference: https://pydicom.github.io/pydicom/dev/reference/index.html\r\n- Examples: https://pydicom.github.io/pydicom/dev/auto_examples/index.html",
"Reference Materials": "Detailed reference information is available in the `references/` directory:\r\n\r\n- **common_tags.md**: Comprehensive list of commonly used DICOM tags organized by category (Patient, Study, Series, Image, etc.)\r\n- **transfer_syntaxes.md**: Complete reference of DICOM transfer syntaxes and compression formats"
}
}---
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.
---
# 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:
```bash
pip install pydicom
pip install pillow # For image format conversion
pip install numpy # For pixel array manipulation
pip install matplotlib # For visualization
```
For handling compressed DICOM files, additional packages may be needed:
```bash
pip install pylibjpeg pylibjpeg-libjpeg pylibjpeg-openjpeg # JPEG compression
pip install python-gdcm # Alternative compression handler
```
## Core Workflows
### Reading DICOM Files
Read a DICOM file using `pydicom.dcmread()`:
```python
import pydicom
# Read a DICOM file
ds = pydicom.dcmread('path/to/file.dcm')
# Access metadata
print(f"Patient Name: {ds.PatientName}")
print(f"Study Date: {ds.StudyDate}")
print(f"Modality: {ds.Modality}")
# Display all elements
print(ds)
```
**Key points:**
- `dcmread()` returns a `Dataset` object
- Access data elements using attribute notation (e.g., `ds.PatientName`) or tag notation (e.g., `ds[0x0010, 0x0010]`)
- Use `ds.file_meta` to access file metadata like Transfer Syntax UID
- Handle missing attributes with `getattr(ds, 'AttributeName', default_value)` or `hasattr(ds, 'AttributeName')`
### Working with Pixel Data
Extract and manipulate image data from DICOM files:
```python
import pydicom
import numpy as np
import matplotlib.pyplot as plt
# Read DICOM file
ds = pydicom.dcmread('image.dcm')
# Get pixel array (requires numpy)
pixel_array = ds.pixel_array
# Image information
print(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_lut
windowed_image = apply_voi_lut(pixel_array, ds)
else:
windowed_image = pixel_array
# Display image
plt.imshow(windowed_image, cmap='gray')
plt.title(f"{ds.Modality} - {ds.StudyDescription}")
plt.axis('off')
plt.show()
```
**Working with color images:**
```python
# RGB images have shape (rows, columns, 3)
if ds.PhotometricInterpretation == 'RGB':
rgb_image = ds.pixel_array
plt.imshow(rgb_image)
elif ds.PhotometricInterpretation == 'YBR_FULL':
from pydicom.pixel_data_handlers.util import convert_color_space
rgb_image = convert_color_space(ds.pixel_array, 'YBR_FULL', 'RGB')
plt.imshow(rgb_image)
```
**Multi-frame images (videos/series):**
```python
# For multi-frame DICOM files
if 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 frame
plt.imshow(frames[0], cmap='gray')
```
### Converting DICOM to Image Formats
Use the provided `dicom_to_image.py` script or convert manually:
```python
from PIL import Image
import pydicom
import numpy as np
ds = pydicom.dcmread('input.dcm')
pixel_array = ds.pixel_array
# Normalize to 0-255 range
if pixel_array.dtype != np.uint8:
pixel_array = ((pixel_array - pixel_array.min()) /
(pixel_array.max() - pixel_array.min()) * 255).astype(np.uint8)
# Save as PNG
image = 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:
```python
import pydicom
from datetime import datetime
ds = pydicom.dcmread('input.dcm')
# Modify existing elements
ds.PatientName = "Doe^John"
ds.StudyDate = datetime.now().strftime('%Y%m%d')
ds.StudyDescription = "Modified Study"
# Add new elements
ds.SeriesNumber = 1
ds.SeriesDescription = "New Series"
# Remove elements
if hasattr(ds, 'PatientComments'):
delattr(ds, 'PatientComments')
# Or using del
if 'PatientComments' in ds:
del ds.PatientComments
# Save modified file
ds.save_as('modified.dcm')
```
### Anonymizing DICOM Files
Remove or replace patient identifiable information:
```python
import pydicom
from datetime import datetime
ds = 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 data
for 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 relationships
if hasattr(ds, 'StudyDate'):
# Shift dates by a random offset
ds.StudyDate = '20000101'
# Keep pixel data intact
ds.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:
```python
import pydicom
from pydicom.dataset import Dataset, FileDataset
from datetime import datetime
import numpy as np
# Create file meta information
file_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 instance
ds = FileDataset('new_dicom.dcm', {}, file_meta=file_meta, preamble=b"\0" * 128)
# Add required DICOM elements
ds.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.StudyDate
ds.ContentTime = ds.StudyTime
# Add image-specific elements
ds.SamplesPerPixel = 1
ds.PhotometricInterpretation = "MONOCHROME2"
ds.Rows = 512
ds.Columns = 512
ds.BitsAllocated = 16
ds.BitsStored = 16
ds.HighBit = 15
ds.PixelRepresentation = 0
# Create pixel data
pixel_array = np.random.randint(0, 4096, (512, 512), dtype=np.uint16)
ds.PixelData = pixel_array.tobytes()
# Add required UIDs
ds.SOPClassUID = pydicom.uid.CTImageStorage
ds.SOPInstanceUID = file_meta.MediaStorageSOPInstanceUID
ds.SeriesInstanceUID = pydicom.uid.generate_uid()
ds.StudyInstanceUID = pydicom.uid.generate_uid()
# Save the file
ds.save_as('new_dicom.dcm')
```
### Compression and Decompression
Handle compressed DICOM files:
```python
import pydicom
# Read compressed DICOM file
ds = pydicom.dcmread('compressed.dcm')
# Check transfer syntax
print(f"Transfer Syntax: {ds.file_meta.TransferSyntaxUID}")
print(f"Transfer Syntax Name: {ds.file_meta.TransferSyntaxUID.name}")
# Decompress and save as uncompressed
ds.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 common
- `JPEGBaseline8Bit` - JPEG lossy compression
- `JPEGLossless` - JPEG lossless compression
- `JPEG2000Lossless` - JPEG 2000 lossless
- `RLELossless` - Run-Length Encoding lossless
See `references/transfer_syntaxes.md` for complete list.
### Working with DICOM Sequences
Handle nested data structures:
```python
import pydicom
ds = pydicom.dcmread('file.dcm')
# Access sequences
if 'ReferencedStudySequence' in ds:
for item in ds.ReferencedStudySequence:
print(f"Referenced SOP Instance UID: {item.ReferencedSOPInstanceUID}")
# Create a sequence
from pydicom.sequence import Sequence
sequence_item = Dataset()
sequence_item.ReferencedSOPClassUID = pydicom.uid.CTImageStorage
sequence_item.ReferencedSOPInstanceUID = pydicom.uid.generate_uid()
ds.ReferencedImageSequence = Sequence([sequence_item])
```
### Processing DICOM Series
Work with multiple related DICOM files:
```python
import pydicom
import numpy as np
from pathlib import Path
# Read all DICOM files in a directory
dicom_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 number
slices.sort(key=lambda x: float(x.ImagePositionPatient[2]))
# Or: slices.sort(key=lambda x: int(x.InstanceNumber))
# Create 3D volume
volume = np.stack([s.pixel_array for s in slices])
print(f"Volume shape: {volume.shape}") # (num_slices, rows, columns)
# Get spacing information for proper scaling
pixel_spacing = slices[0].PixelSpacing # [row_spacing, col_spacing]
slice_thickness = slices[0].SliceThickness
print(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).
```bash
python scripts/anonymize_dicom.py input.dcm output.dcm
```
### dicom_to_image.py
Convert DICOM files to common image formats (PNG, JPEG, TIFF).
```bash
python scripts/dicom_to_image.py input.dcm output.png
python scripts/dicom_to_image.py input.dcm output.jpg --format JPEG
```
### extract_metadata.py
Extract and display DICOM metadata in a readable format.
```bash
python scripts/extract_metadata.py file.dcm
python 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: `pip install pylibjpeg pylibjpeg-libjpeg python-gdcm`
**Issue: "AttributeError" when accessing tags**
- Solution: Check if attribute exists with `hasattr(ds, 'AttributeName')` or use `ds.get('AttributeName', default)`
**Issue: Incorrect image display (too dark/bright)**
- Solution: Apply VOI LUT windowing: `apply_voi_lut(pixel_array, ds)` or manually adjust with `WindowCenter` and `WindowWidth`
**Issue: Memory issues with large series**
- Solution: Process files iteratively, use memory-mapped arrays, or downsample images
## Best Practices
1. **Always check for required attributes** before accessing them using `hasattr()` or `get()`
2. **Preserve file metadata** when modifying files by using `save_as()` with `write_like_original=True`
3. **Use Transfer Syntax UIDs** to understand compression format before processing pixel data
4. **Handle exceptions** when reading files from untrusted sources
5. **Apply proper windowing** (VOI LUT) for medical image visualization
6. **Maintain spatial information** (pixel spacing, slice thickness) when processing 3D volumes
7. **Verify anonymization** thoroughly before sharing medical data
8. **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