A pure Python package for reading and writing DICOM data
—
Individual DICOM data element handling with comprehensive support for all Value Representations (VRs), proper type conversion, validation, and element manipulation within the DICOM standard framework.
The fundamental building block of DICOM datasets, representing individual data elements with tag, VR, and value components.
class DataElement:
"""
Represents a single DICOM data element with tag, VR, and value.
The basic unit of DICOM data storage containing a tag identifier,
Value Representation (VR), and the actual data value.
"""
def __init__(self, tag, VR, value, file_value_tell=None, is_undefined_length=False, already_converted=False):
"""
Initialize DataElement.
Parameters:
- tag: int or Tag - DICOM tag identifying the element
- VR: str - Value Representation (2-character string)
- value: Any - The element's value
- file_value_tell: int - File position of value (for lazy loading)
- is_undefined_length: bool - Whether element has undefined length
- already_converted: bool - Whether value has been converted from raw
"""
@property
def tag(self):
"""Tag: DICOM tag for this element."""
@property
def VR(self):
"""str: Value Representation for this element."""
@property
def value(self):
"""Any: The element's value."""
@value.setter
def value(self, val):
"""Set the element's value."""
@property
def keyword(self):
"""str: DICOM keyword for this element's tag."""
@property
def description(self):
"""str: DICOM description for this element's tag."""
@property
def repval(self):
"""str: String representation of the value for display."""
def __str__(self):
"""Return string representation of element."""
def __repr__(self):
"""Return detailed string representation of element."""
def __eq__(self, other):
"""Compare elements for equality."""
def __ne__(self, other):
"""Compare elements for inequality."""Represents unprocessed data elements as read from DICOM files, before value conversion and interpretation.
class RawDataElement:
"""
Represents raw data element before processing and value conversion.
Used during file reading to store element information before
the value is processed and converted to appropriate Python types.
"""
def __init__(self, tag, VR, length, value, value_tell, is_implicit_VR, is_little_endian):
"""
Initialize RawDataElement.
Parameters:
- tag: int - DICOM tag
- VR: str - Value Representation
- length: int - Value length in bytes
- value: bytes or file-like - Raw value data
- value_tell: int - File position of value
- is_implicit_VR: bool - Whether VR was implicit in file
- is_little_endian: bool - Byte order of source file
"""
@property
def tag(self):
"""int: DICOM tag."""
@property
def VR(self):
"""str: Value Representation."""
@property
def length(self):
"""int: Value length in bytes."""
@property
def value(self):
"""bytes or file-like: Raw value data."""
@property
def value_tell(self):
"""int: File position where value data starts."""
@property
def is_implicit_VR(self):
"""bool: Whether VR was implicit in source."""
@property
def is_little_endian(self):
"""bool: Byte order of source file."""Functions for converting between raw and processed data elements with proper value interpretation.
def convert_raw_data_element(raw_data_element):
"""
Convert RawDataElement to DataElement with processed value.
Parameters:
- raw_data_element: RawDataElement - Raw element to convert
Returns:
DataElement - Processed element with converted value
"""
def convert_value(VR, raw_value, encoding=None):
"""
Convert raw bytes to appropriate Python type based on VR.
Parameters:
- VR: str - Value Representation
- raw_value: bytes - Raw value data
- encoding: str - Character encoding for text VRs
Returns:
Any - Converted value in appropriate Python type
"""Functions for creating appropriate empty values and handling VR-specific requirements.
def empty_value_for_VR(VR, raw=False):
"""
Return appropriate empty value for given VR.
Parameters:
- VR: str - Value Representation
- raw: bool - Whether to return raw bytes or processed value
Returns:
Any - Appropriate empty value for the VR type
"""
def isMultiValue(VR):
"""
Check if VR can contain multiple values.
Parameters:
- VR: str - Value Representation
Returns:
bool - True if VR supports multiple values
"""
def can_contain_sequences(VR):
"""
Check if VR can contain sequence data.
Parameters:
- VR: str - Value Representation
Returns:
bool - True if VR can contain sequences
"""Convenience functions for creating data elements with proper validation and type handling.
def DataElementFactory(tag, VR, value):
"""
Factory function to create appropriate DataElement.
Parameters:
- tag: int, tuple, or str - DICOM tag or keyword
- VR: str - Value Representation
- value: Any - Element value
Returns:
DataElement - Created element with proper typing
"""
def create_element(tag, VR, value, validate=True):
"""
Create DataElement with validation.
Parameters:
- tag: int, tuple, or str - DICOM tag or keyword
- VR: str - Value Representation
- value: Any - Element value
- validate: bool - Whether to validate value against VR
Returns:
DataElement - Created and validated element
"""Functions for validating data elements according to DICOM standards and VR requirements.
def validate_element(data_element):
"""
Validate DataElement against DICOM standards.
Parameters:
- data_element: DataElement - Element to validate
Returns:
list - List of validation errors/warnings
"""
def validate_element_value(VR, value):
"""
Validate element value against VR requirements.
Parameters:
- VR: str - Value Representation
- value: Any - Value to validate
Returns:
bool - True if value is valid for VR
Raises:
ValueError - If value is invalid for VR
"""Utility functions for comparing and manipulating data elements.
def element_comparison_key(data_element):
"""
Generate comparison key for element sorting.
Parameters:
- data_element: DataElement - Element to generate key for
Returns:
tuple - Sortable comparison key
"""
def copy_element(data_element, deep=True):
"""
Create copy of DataElement.
Parameters:
- data_element: DataElement - Element to copy
- deep: bool - Whether to perform deep copy
Returns:
DataElement - Copied element
"""
def element_byte_size(data_element, encoding=None):
"""
Calculate byte size of element when serialized.
Parameters:
- data_element: DataElement - Element to measure
- encoding: str - Character encoding for text elements
Returns:
int - Size in bytes
"""from pydicom.dataelem import DataElement
from pydicom.tag import Tag
# Create element with tag as integer
patient_name_elem = DataElement(0x00100010, "PN", "Doe^John")
# Create element with Tag object
study_date_elem = DataElement(Tag(0x0008, 0x0020), "DA", "20231215")
# Create element with keyword (requires dictionary lookup)
patient_id_elem = DataElement("PatientID", "LO", "12345")
# Access element properties
print(f"Tag: {patient_name_elem.tag}")
print(f"VR: {patient_name_elem.VR}")
print(f"Value: {patient_name_elem.value}")
print(f"Keyword: {patient_name_elem.keyword}")
print(f"Description: {patient_name_elem.description}")from pydicom.dataelem import RawDataElement, convert_raw_data_element
# Create raw element (as typically done during file reading)
raw_elem = RawDataElement(
tag=0x00100010,
VR="PN",
length=8,
value=b"Doe^John",
value_tell=1024,
is_implicit_VR=False,
is_little_endian=True
)
# Convert to processed element
processed_elem = convert_raw_data_element(raw_elem)
print(f"Converted value: {processed_elem.value}")from pydicom.dataelem import DataElement, validate_element_value
# Create element
elem = DataElement(0x00100010, "PN", "Doe^John^Middle^^Dr")
# Validate element value
try:
is_valid = validate_element_value(elem.VR, elem.value)
print(f"Element is valid: {is_valid}")
except ValueError as e:
print(f"Validation error: {e}")
# Validate complete element
errors = validate_element(elem)
if errors:
print("Validation issues:")
for error in errors:
print(f" {error}")from pydicom.dataelem import empty_value_for_VR
# Get appropriate empty values for different VRs
empty_pn = empty_value_for_VR("PN") # ""
empty_da = empty_value_for_VR("DA") # ""
empty_ds = empty_value_for_VR("DS") # ""
empty_sq = empty_value_for_VR("SQ") # Sequence()
print(f"Empty PN: '{empty_pn}'")
print(f"Empty DA: '{empty_da}'")
print(f"Empty SQ type: {type(empty_sq)}")
# Raw empty values (bytes)
empty_raw = empty_value_for_VR("PN", raw=True) # b""from pydicom.dataelem import DataElement, element_comparison_key
# Create multiple elements
elements = [
DataElement(0x00200010, "SH", "Study1"), # Study ID
DataElement(0x00100010, "PN", "Patient"), # Patient Name
DataElement(0x00080020, "DA", "20231215"), # Study Date
]
# Sort elements by tag
sorted_elements = sorted(elements, key=element_comparison_key)
for elem in sorted_elements:
print(f"{elem.tag}: {elem.keyword} = {elem.value}")from pydicom.dataelem import DataElement, element_byte_size
# Create element with text value
elem = DataElement(0x00100010, "PN", "Doe^John^Middle")
# Calculate size when serialized
size = element_byte_size(elem, encoding="utf-8")
print(f"Element will occupy {size} bytes when written to file")
# Size includes tag, VR, length, and valuefrom pydicom.dataelem import DataElement, copy_element
# Create original element
original = DataElement(0x00100010, "PN", "Doe^John")
# Create shallow copy
shallow_copy = copy_element(original, deep=False)
# Create deep copy
deep_copy = copy_element(original, deep=True)
# Modify original
original.value = "Smith^Jane"
print(f"Original: {original.value}")
print(f"Shallow copy: {shallow_copy.value}") # May or may not change
print(f"Deep copy: {deep_copy.value}") # Won't changefrom pydicom.dataelem import DataElement
from pydicom.multival import MultiValue
# Create element with multiple values
# WindowCenter can have multiple values
window_centers = DataElement(0x00281050, "DS", ["200", "400", "600"])
# Access individual values
first_center = window_centers.value[0] # "200"
all_centers = list(window_centers.value)
print(f"Number of window centers: {len(window_centers.value)}")
print(f"Centers: {window_centers.value}")Install with Tessl CLI
npx tessl i tessl/pypi-pydicom