A pure Python package for reading and writing DICOM data
—
Specialized handling for DICOM Value Representations providing comprehensive support for dates, times, person names, numeric types, and validation functions with proper DICOM format compliance and type conversion capabilities.
Complete enumeration of DICOM Value Representations with validation and properties.
class VR:
"""
DICOM Value Representation enumeration.
Provides complete set of DICOM VR types with validation and properties
for proper handling of different data types in medical imaging.
"""
# String VRs
AE = "AE" # Application Entity
AS = "AS" # Age String
CS = "CS" # Code String
DA = "DA" # Date
DS = "DS" # Decimal String
DT = "DT" # Date Time
IS = "IS" # Integer String
LO = "LO" # Long String
LT = "LT" # Long Text
PN = "PN" # Person Name
SH = "SH" # Short String
ST = "ST" # Short Text
TM = "TM" # Time
UC = "UC" # Unlimited Characters
UI = "UI" # Unique Identifier
UR = "UR" # Universal Resource
UT = "UT" # Unlimited Text
# Numeric VRs
FL = "FL" # Floating Point Single
FD = "FD" # Floating Point Double
SL = "SL" # Signed Long
SS = "SS" # Signed Short
UL = "UL" # Unsigned Long
US = "US" # Unsigned Short
# Binary VRs
OB = "OB" # Other Byte
OD = "OD" # Other Double
OF = "OF" # Other Float
OL = "OL" # Other Long
OV = "OV" # Other Very Long
OW = "OW" # Other Word
UN = "UN" # Unknown
# Special VRs
AT = "AT" # Attribute Tag
SQ = "SQ" # SequenceSpecialized classes for DICOM date and time handling with validation and conversion.
class DA:
"""
DICOM Date (DA) Value Representation.
Handles DICOM date format (YYYYMMDD) with validation and conversion
to Python date objects for medical imaging workflows.
"""
def __init__(self, val):
"""
Initialize DICOM date.
Parameters:
- val: str, datetime.date, or datetime.datetime - Date value
Raises:
ValueError - If date format is invalid
"""
@property
def date(self):
"""datetime.date: Python date object."""
def __str__(self):
"""Return DICOM date string (YYYYMMDD)."""
def __eq__(self, other):
"""Compare dates for equality."""
def __lt__(self, other):
"""Compare dates for ordering."""
class TM:
"""
DICOM Time (TM) Value Representation.
Handles DICOM time format (HHMMSS.FFFFFF) with microsecond precision
and validation for medical imaging time stamps.
"""
def __init__(self, val):
"""
Initialize DICOM time.
Parameters:
- val: str, datetime.time, or datetime.datetime - Time value
Raises:
ValueError - If time format is invalid
"""
@property
def time(self):
"""datetime.time: Python time object."""
@property
def hour(self):
"""int: Hour component (0-23)."""
@property
def minute(self):
"""int: Minute component (0-59)."""
@property
def second(self):
"""int: Second component (0-59)."""
@property
def microsecond(self):
"""int: Microsecond component (0-999999)."""
def __str__(self):
"""Return DICOM time string."""
class DT:
"""
DICOM DateTime (DT) Value Representation.
Handles DICOM datetime format with timezone support and microsecond
precision for comprehensive temporal data in medical imaging.
"""
def __init__(self, val):
"""
Initialize DICOM datetime.
Parameters:
- val: str, datetime.datetime - DateTime value
Raises:
ValueError - If datetime format is invalid
"""
@property
def datetime(self):
"""datetime.datetime: Python datetime object."""
@property
def date(self):
"""datetime.date: Date component."""
@property
def time(self):
"""datetime.time: Time component."""
@property
def timezone(self):
"""datetime.timezone: Timezone information."""
def __str__(self):
"""Return DICOM datetime string."""Specialized numeric classes with configurable precision and overflow handling.
class DS:
"""
DICOM Decimal String (DS) Value Representation.
Handles decimal numbers in string format with configurable precision
and automatic conversion between decimal and float representations.
"""
def __init__(self, val, validation_mode=None):
"""
Initialize decimal string.
Parameters:
- val: str, int, float, or Decimal - Numeric value
- validation_mode: str - Validation mode ("raise", "warn", "ignore")
Raises:
ValueError - If value cannot be converted to valid DS
"""
@property
def real(self):
"""float: Real component (for compatibility)."""
@property
def imag(self):
"""float: Imaginary component (always 0)."""
def __float__(self):
"""Convert to float."""
def __int__(self):
"""Convert to int."""
def __str__(self):
"""Return string representation."""
class DSfloat(float):
"""
Decimal String as float subclass.
Float-based implementation of DS VR with automatic string formatting
and DICOM-compliant precision handling.
"""
def __new__(cls, val):
"""Create new DSfloat instance."""
def __str__(self):
"""Return DICOM-formatted string."""
class DSdecimal:
"""
Decimal String using Python Decimal for exact precision.
Decimal-based implementation providing exact decimal arithmetic
without floating-point precision issues.
"""
def __init__(self, val):
"""Initialize with Decimal precision."""
class IS:
"""
DICOM Integer String (IS) Value Representation.
Handles integer numbers in string format with overflow detection
and automatic conversion to Python integers.
"""
def __init__(self, val, validation_mode=None):
"""
Initialize integer string.
Parameters:
- val: str, int - Integer value
- validation_mode: str - Validation mode for overflow handling
Raises:
ValueError - If value cannot be converted to valid IS
"""
def __int__(self):
"""Convert to int."""
def __str__(self):
"""Return string representation."""
class ISfloat(float):
"""
Integer String as float subclass for overflow handling.
Float-based IS implementation that handles integer overflow
by converting to float representation when needed.
"""
def __new__(cls, val):
"""Create new ISfloat instance."""Complex person name handling with component access and internationalization support.
class PersonName:
"""
DICOM Person Name (PN) Value Representation.
Handles complex person names with support for alphabetic, ideographic,
and phonetic representations following DICOM standard formatting.
"""
def __init__(self, val, encodings=None, validation_mode=None):
"""
Initialize person name.
Parameters:
- val: str or bytes - Person name value
- encodings: list - Character encodings for name components
- validation_mode: str - Validation mode for name validation
Raises:
ValueError - If name format is invalid
"""
@property
def family_name(self):
"""str: Family name component."""
@property
def given_name(self):
"""str: Given name component."""
@property
def middle_name(self):
"""str: Middle name component."""
@property
def name_prefix(self):
"""str: Name prefix component (title)."""
@property
def name_suffix(self):
"""str: Name suffix component."""
@property
def alphabetic(self):
"""str: Alphabetic representation."""
@property
def ideographic(self):
"""str: Ideographic representation."""
@property
def phonetic(self):
"""str: Phonetic representation."""
@property
def components(self):
"""list: List of name components [family, given, middle, prefix, suffix]."""
def formatted(self, format_str="{family}, {given}"):
"""
Return formatted name string.
Parameters:
- format_str: str - Format template with component placeholders
Returns:
str - Formatted name
"""
def __str__(self):
"""Return string representation of person name."""
def __eq__(self, other):
"""Compare person names for equality."""Comprehensive validation functions for different VR types with configurable error handling.
def validate_value(VR, value, config=None):
"""
Validate value against VR requirements.
Parameters:
- VR: str - Value Representation
- value: Any - Value to validate
- config: dict - Validation configuration options
Returns:
Any - Validated/converted value
Raises:
ValueError - If value is invalid for VR type
"""
def validate_pn(value, encodings=None):
"""
Validate Person Name value.
Parameters:
- value: str or PersonName - Name value to validate
- encodings: list - Character encodings
Returns:
PersonName - Validated person name object
Raises:
ValueError - If name format is invalid
"""
def validate_date_time(VR, value):
"""
Validate date/time values (DA, TM, DT).
Parameters:
- VR: str - Value Representation ("DA", "TM", or "DT")
- value: str or datetime object - Value to validate
Returns:
Appropriate date/time object (DA, TM, or DT)
Raises:
ValueError - If date/time format is invalid
"""
def validate_ui(value):
"""
Validate Unique Identifier (UI) value.
Parameters:
- value: str - UID value to validate
Returns:
str - Validated UID string
Raises:
ValueError - If UID format is invalid
"""
def validate_length(VR, value):
"""
Validate value length against VR constraints.
Parameters:
- VR: str - Value Representation
- value: Any - Value to validate
Returns:
bool - True if length is valid
Raises:
ValueError - If length exceeds VR limits
"""Functions for querying VR properties and characteristics.
def is_string_VR(VR):
"""
Check if VR is string type.
Parameters:
- VR: str - Value Representation
Returns:
bool - True if VR is string type
"""
def is_text_VR(VR):
"""
Check if VR is text type (allows control chars).
Parameters:
- VR: str - Value Representation
Returns:
bool - True if VR is text type
"""
def is_binary_VR(VR):
"""
Check if VR is binary type.
Parameters:
- VR: str - Value Representation
Returns:
bool - True if VR is binary type
"""
def allows_multiple_values(VR):
"""
Check if VR allows multiple values.
Parameters:
- VR: str - Value Representation
Returns:
bool - True if VR supports multiple values
"""
def max_length(VR):
"""
Get maximum length for VR type.
Parameters:
- VR: str - Value Representation
Returns:
int - Maximum allowed length (None for unlimited)
"""Functions for converting between VR types and Python types.
def convert_text(value, encodings=None, VR=None):
"""
Convert bytes to text using appropriate encoding.
Parameters:
- value: bytes or str - Value to convert
- encodings: list - Character encodings to try
- VR: str - Target Value Representation
Returns:
str - Converted text value
"""
def convert_numbers(value, VR, is_little_endian=True):
"""
Convert binary data to numeric values.
Parameters:
- value: bytes - Binary numeric data
- VR: str - Numeric VR type (US, UL, SS, SL, FL, FD)
- is_little_endian: bool - Byte order
Returns:
tuple or single value - Converted numeric value(s)
"""
def convert_tag_to_int(value):
"""
Convert tag representation to integer.
Parameters:
- value: bytes, int, or Tag - Tag value
Returns:
int - Tag as 32-bit integer
"""from pydicom.valuerep import DA, TM, DT
import datetime
# Create DICOM dates
study_date = DA("20231215") # From string
today = DA(datetime.date.today()) # From date object
print(f"Study date: {study_date}")
print(f"Date object: {study_date.date}")
# Create DICOM times
scan_time = TM("143022.123456") # With microseconds
now_time = TM(datetime.datetime.now().time())
print(f"Scan time: {scan_time}")
print(f"Hour: {scan_time.hour}")
print(f"Minute: {scan_time.minute}")
print(f"Microsecond: {scan_time.microsecond}")
# Create DICOM datetimes
acquisition_dt = DT("20231215143022.123456+0100") # With timezone
print(f"Acquisition: {acquisition_dt}")
print(f"Datetime: {acquisition_dt.datetime}")
print(f"Timezone: {acquisition_dt.timezone}")from pydicom.valuerep import DS, IS, DSfloat, ISfloat
# Decimal strings
slice_thickness = DS("2.5")
window_width = DS(400.0)
print(f"Slice thickness: {slice_thickness}")
print(f"As float: {float(slice_thickness)}")
# Handle precision
pixel_spacing = DS("0.625000")
print(f"Pixel spacing: {pixel_spacing}")
# Integer strings
series_number = IS("3")
instance_number = IS(42)
print(f"Series: {series_number}")
print(f"As int: {int(series_number)}")
# Handle overflow with float fallback
large_value = ISfloat(2**32) # Larger than 32-bit int
print(f"Large value: {large_value}")from pydicom.valuerep import PersonName
# Simple person name
patient1 = PersonName("Doe^John^Middle^^Dr")
print(f"Full name: {patient1}")
print(f"Family: {patient1.family_name}")
print(f"Given: {patient1.given_name}")
print(f"Middle: {patient1.middle_name}")
print(f"Prefix: {patient1.name_prefix}")
# Formatted output
formatted = patient1.formatted("{prefix} {given} {middle} {family}")
print(f"Formatted: {formatted}")
# Multi-component name (alphabetic, ideographic, phonetic)
patient2 = PersonName("Yamada^Tarou=山田^太郎=ヤマダ^タロウ")
print(f"Alphabetic: {patient2.alphabetic}")
print(f"Ideographic: {patient2.ideographic}")
print(f"Phonetic: {patient2.phonetic}")from pydicom.valuerep import validate_value, validate_pn, validate_date_time, validate_ui
# Validate different VR types
try:
# Valid date
valid_date = validate_date_time("DA", "20231215")
print(f"Valid date: {valid_date}")
# Invalid date
validate_date_time("DA", "20231301") # Invalid month
except ValueError as e:
print(f"Date validation error: {e}")
# Validate person name
try:
valid_name = validate_pn("Doe^John")
print(f"Valid name: {valid_name}")
except ValueError as e:
print(f"Name validation error: {e}")
# Validate UID
try:
valid_uid = validate_ui("1.2.840.10008.1.2.1")
print(f"Valid UID: {valid_uid}")
# Invalid UID
validate_ui("invalid.uid.format")
except ValueError as e:
print(f"UID validation error: {e}")from pydicom.valuerep import is_string_VR, is_binary_VR, allows_multiple_values, max_length
# Check VR properties
vr_types = ["PN", "DA", "OB", "SQ", "US", "LT"]
for vr in vr_types:
print(f"\nVR: {vr}")
print(f" String VR: {is_string_VR(vr)}")
print(f" Binary VR: {is_binary_VR(vr)}")
print(f" Multi-value: {allows_multiple_values(vr)}")
print(f" Max length: {max_length(vr)}")from pydicom.valuerep import convert_text, convert_numbers
# Convert encoded text
encoded_text = b"Patient Name"
converted = convert_text(encoded_text, encodings=["iso8859", "utf-8"])
print(f"Converted text: {converted}")
# Convert binary numbers (little endian unsigned short)
binary_data = b"\x00\x01\x00\x02" # Two 16-bit values: 256, 512
numbers = convert_numbers(binary_data, "US", is_little_endian=True)
print(f"Converted numbers: {numbers}")
# Convert big endian
numbers_be = convert_numbers(binary_data, "US", is_little_endian=False)
print(f"Big endian numbers: {numbers_be}")from pydicom.valuerep import PersonName
# International names with encoding
encodings = ['iso8859', 'utf-8']
# Name with special characters
international_name = PersonName("Müller^Hans^Josef", encodings=encodings)
print(f"International name: {international_name}")
# Access components
components = international_name.components
print(f"Components: {components}")
# Empty components
partial_name = PersonName("Smith^^John") # Missing middle name
print(f"Family: '{partial_name.family_name}'")
print(f"Given: '{partial_name.given_name}'")
print(f"Middle: '{partial_name.middle_name}'") # Empty stringfrom pydicom.valuerep import validate_value
import pydicom.config
# Configure validation mode
pydicom.config.settings.reading_validation_mode = "warn" # or "raise", "ignore"
# Validate with different modes
test_values = [
("DS", "123.456789012345678"), # Too many digits
("IS", "999999999999"), # Potentially too large
("DA", "20231301"), # Invalid date
]
for vr, value in test_values:
try:
result = validate_value(vr, value)
print(f"VR {vr}, value '{value}': {result}")
except ValueError as e:
print(f"VR {vr}, value '{value}': ERROR - {e}")Install with Tessl CLI
npx tessl i tessl/pypi-pydicom