| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- #!/usr/bin/env python3
- """
- Extract and display DICOM metadata in a readable format.
- Usage:
- python extract_metadata.py file.dcm
- python extract_metadata.py file.dcm --output metadata.txt
- python extract_metadata.py file.dcm --format json --output metadata.json
- """
- import argparse
- import sys
- import json
- from pathlib import Path
- try:
- import pydicom
- except ImportError:
- print("Error: pydicom is not installed. Install it with: pip install pydicom")
- sys.exit(1)
- def format_value(value):
- """Format DICOM values for display."""
- if isinstance(value, bytes):
- try:
- return value.decode('utf-8', errors='ignore')
- except:
- return str(value)
- elif isinstance(value, pydicom.multival.MultiValue):
- return ', '.join(str(v) for v in value)
- elif isinstance(value, pydicom.sequence.Sequence):
- return f"Sequence with {len(value)} item(s)"
- else:
- return str(value)
- def extract_metadata_text(ds, show_sequences=False):
- """Extract metadata as formatted text."""
- lines = []
- lines.append("=" * 80)
- lines.append("DICOM Metadata")
- lines.append("=" * 80)
- # File Meta Information
- if hasattr(ds, 'file_meta'):
- lines.append("\n[File Meta Information]")
- for elem in ds.file_meta:
- lines.append(f"{elem.name:40s} {format_value(elem.value)}")
- # Patient Information
- lines.append("\n[Patient Information]")
- patient_tags = ['PatientName', 'PatientID', 'PatientBirthDate',
- 'PatientSex', 'PatientAge', 'PatientWeight']
- for tag in patient_tags:
- if hasattr(ds, tag):
- value = getattr(ds, tag)
- lines.append(f"{tag:40s} {format_value(value)}")
- # Study Information
- lines.append("\n[Study Information]")
- study_tags = ['StudyInstanceUID', 'StudyDate', 'StudyTime',
- 'StudyDescription', 'AccessionNumber', 'StudyID']
- for tag in study_tags:
- if hasattr(ds, tag):
- value = getattr(ds, tag)
- lines.append(f"{tag:40s} {format_value(value)}")
- # Series Information
- lines.append("\n[Series Information]")
- series_tags = ['SeriesInstanceUID', 'SeriesNumber', 'SeriesDescription',
- 'Modality', 'SeriesDate', 'SeriesTime']
- for tag in series_tags:
- if hasattr(ds, tag):
- value = getattr(ds, tag)
- lines.append(f"{tag:40s} {format_value(value)}")
- # Image Information
- lines.append("\n[Image Information]")
- image_tags = ['SOPInstanceUID', 'InstanceNumber', 'ImageType',
- 'Rows', 'Columns', 'BitsAllocated', 'BitsStored',
- 'PhotometricInterpretation', 'SamplesPerPixel',
- 'PixelSpacing', 'SliceThickness', 'ImagePositionPatient',
- 'ImageOrientationPatient', 'WindowCenter', 'WindowWidth']
- for tag in image_tags:
- if hasattr(ds, tag):
- value = getattr(ds, tag)
- lines.append(f"{tag:40s} {format_value(value)}")
- # All other elements
- if show_sequences:
- lines.append("\n[All Elements]")
- for elem in ds:
- if elem.VR != 'SQ': # Skip sequences for brevity
- lines.append(f"{elem.name:40s} {format_value(elem.value)}")
- else:
- lines.append(f"{elem.name:40s} {format_value(elem.value)}")
- return '\n'.join(lines)
- def extract_metadata_json(ds):
- """Extract metadata as JSON."""
- metadata = {}
- # File Meta Information
- if hasattr(ds, 'file_meta'):
- metadata['file_meta'] = {}
- for elem in ds.file_meta:
- metadata['file_meta'][elem.keyword] = format_value(elem.value)
- # All data elements (excluding sequences for simplicity)
- metadata['dataset'] = {}
- for elem in ds:
- if elem.VR != 'SQ':
- metadata['dataset'][elem.keyword] = format_value(elem.value)
- return json.dumps(metadata, indent=2)
- def main():
- parser = argparse.ArgumentParser(
- description='Extract and display DICOM metadata',
- formatter_class=argparse.RawDescriptionHelpFormatter,
- epilog="""
- Examples:
- python extract_metadata.py file.dcm
- python extract_metadata.py file.dcm --output metadata.txt
- python extract_metadata.py file.dcm --format json --output metadata.json
- python extract_metadata.py file.dcm --show-sequences
- """
- )
- parser.add_argument('input', type=str, help='Input DICOM file')
- parser.add_argument('--output', '-o', type=str, help='Output file (default: print to console)')
- parser.add_argument('--format', type=str, choices=['text', 'json'], default='text',
- help='Output format (default: text)')
- parser.add_argument('--show-sequences', action='store_true',
- help='Include all data elements including sequences')
- args = parser.parse_args()
- # Validate input file exists
- input_path = Path(args.input)
- if not input_path.exists():
- print(f"Error: Input file '{args.input}' not found")
- sys.exit(1)
- try:
- # Read DICOM file
- ds = pydicom.dcmread(args.input)
- # Extract metadata
- if args.format == 'json':
- output = extract_metadata_json(ds)
- else:
- output = extract_metadata_text(ds, args.show_sequences)
- # Write or print output
- if args.output:
- with open(args.output, 'w') as f:
- f.write(output)
- print(f"✓ Metadata extracted to: {args.output}")
- else:
- print(output)
- except Exception as e:
- print(f"✗ Error: {e}")
- sys.exit(1)
- if __name__ == '__main__':
- main()
|