CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pydicom

A pure Python package for reading and writing DICOM data

Pending
Overview
Eval results
Files

sequences-collections.mddocs/

Sequences and Collections

Management of DICOM sequences and multi-value elements providing comprehensive support for nested datasets, proper validation, type-constrained collections, and hierarchical DICOM data structures used in medical imaging workflows.

Capabilities

Sequence Class

List-like container for datasets in DICOM sequences with specialized functionality for nested data structures.

class Sequence(list):
    """
    DICOM Sequence container for nested datasets.
    
    List-like container that holds Dataset objects in DICOM sequences,
    providing standard list operations plus DICOM-specific functionality
    for handling nested medical imaging data structures.
    """
    
    def __init__(self, iterable=None):
        """
        Initialize sequence.
        
        Parameters:
        - iterable: list or None - Initial sequence items (Dataset objects)
        """
    
    def append(self, item):
        """
        Add dataset to sequence.
        
        Parameters:
        - item: Dataset - Dataset to add to sequence
        
        Raises:
        TypeError - If item is not a Dataset
        """
    
    def insert(self, index, item):
        """
        Insert dataset at specific position.
        
        Parameters:
        - index: int - Position to insert at
        - item: Dataset - Dataset to insert
        
        Raises:
        TypeError - If item is not a Dataset
        """
    
    def extend(self, items):
        """
        Extend sequence with multiple datasets.
        
        Parameters:
        - items: iterable - Datasets to add
        
        Raises:
        TypeError - If any item is not a Dataset
        """
    
    def __setitem__(self, index, value):
        """
        Set dataset at index.
        
        Parameters:
        - index: int - Index to set
        - value: Dataset - Dataset to set
        
        Raises:
        TypeError - If value is not a Dataset
        """
    
    def __str__(self):
        """Return string representation of sequence."""
    
    def __repr__(self):
        """Return detailed representation of sequence."""

MultiValue Class

Container for multiple values in single data element with type constraints and validation.

class MultiValue(list):
    """
    Container for multiple values in DICOM data elements.
    
    Type-constrained list that ensures all values are of the same type,
    providing validation and conversion for multi-value DICOM elements.
    """
    
    def __init__(self, type_constructor, iterable=None):
        """
        Initialize multi-value container.
        
        Parameters:
        - type_constructor: callable - Function to construct/validate element type
        - iterable: list or None - Initial values
        
        Raises:
        TypeError - If any initial value doesn't match type constructor
        """
    
    def append(self, value):
        """
        Add value to multi-value container.
        
        Parameters:
        - value: Any - Value to add (will be validated/converted)
        
        Raises:
        TypeError - If value cannot be converted to required type
        """
    
    def insert(self, index, value):
        """
        Insert value at specific position.
        
        Parameters:
        - index: int - Position to insert at
        - value: Any - Value to insert (will be validated/converted)
        
        Raises:
        TypeError - If value cannot be converted to required type
        """
    
    def extend(self, values):
        """
        Extend with multiple values.
        
        Parameters:
        - values: iterable - Values to add (all will be validated/converted)
        
        Raises:
        TypeError - If any value cannot be converted to required type
        """
    
    def __setitem__(self, index, value):
        """
        Set value at index.
        
        Parameters:
        - index: int - Index to set
        - value: Any - Value to set (will be validated/converted)
        
        Raises:
        TypeError - If value cannot be converted to required type
        """
    
    @property
    def type_constructor(self):
        """callable: Type constructor function for validation."""
    
    def __str__(self):
        """Return string representation suitable for DICOM."""
    
    def __repr__(self):
        """Return detailed representation."""

ConstrainedList Base Class

Base class for type-constrained lists providing validation framework.

class ConstrainedList(list):
    """
    Base class for type-constrained list implementations.
    
    Provides framework for creating lists that enforce type constraints
    on their elements, used as foundation for MultiValue and similar classes.
    """
    
    def __init__(self, type_constructor, iterable=None):
        """
        Initialize constrained list.
        
        Parameters:
        - type_constructor: callable - Type validation/conversion function
        - iterable: list or None - Initial items
        """
    
    def _validate_item(self, value):
        """
        Validate and convert item using type constructor.
        
        Parameters:
        - value: Any - Value to validate/convert
        
        Returns:
        Any - Validated/converted value
        
        Raises:
        TypeError - If value cannot be converted
        """
    
    def _validate_iterable(self, iterable):
        """
        Validate all items in iterable.
        
        Parameters:
        - iterable: list - Items to validate
        
        Returns:
        list - Validated items
        
        Raises:
        TypeError - If any item cannot be converted
        """

Sequence Utility Functions

Functions for working with sequences and validating sequence structures.

def is_sequence(value):
    """
    Check if value is a DICOM sequence.
    
    Parameters:
    - value: Any - Value to check
    
    Returns:
    bool - True if value is Sequence instance
    """

def validate_sequence(sequence):
    """
    Validate sequence structure and contents.
    
    Parameters:
    - sequence: Sequence - Sequence to validate
    
    Returns:
    list - Validation errors/warnings
    """

def sequence_delimiter():
    """
    Get sequence delimiter data element.
    
    Returns:
    DataElement - Sequence delimiter element
    """

def item_delimiter():
    """
    Get item delimiter data element.
    
    Returns:
    DataElement - Item delimiter element
    """

MultiValue Creation Functions

Factory functions for creating multi-value containers with appropriate type constructors.

def create_multivalue(VR, values):
    """
    Create MultiValue container for VR type.
    
    Parameters:
    - VR: str - Value Representation
    - values: list - Initial values
    
    Returns:
    MultiValue - Container with appropriate type constructor
    """

def multivalue_from_string(VR, value_string, separator="\\"):
    """
    Create MultiValue from delimited string.
    
    Parameters:
    - VR: str - Value Representation
    - value_string: str - Delimited string of values
    - separator: str - Value separator (usually backslash)
    
    Returns:
    MultiValue - Container with parsed values
    """

def string_from_multivalue(multivalue, separator="\\"):
    """
    Convert MultiValue to delimited string.
    
    Parameters:
    - multivalue: MultiValue - Container to convert
    - separator: str - Value separator
    
    Returns:
    str - Delimited string representation
    """

Sequence Navigation Functions

Functions for navigating and manipulating nested sequence structures.

def find_datasets_in_sequence(sequence, condition):
    """
    Find datasets in sequence matching condition.
    
    Parameters:
    - sequence: Sequence - Sequence to search
    - condition: callable - Function that returns True for matching datasets
    
    Returns:
    list - Matching datasets
    """

def walk_sequence_tree(sequence, visit_func):
    """
    Walk through nested sequence tree structure.
    
    Parameters:
    - sequence: Sequence - Root sequence to walk
    - visit_func: callable - Function called for each dataset
    """

def flatten_sequence(sequence, max_depth=None):
    """
    Flatten nested sequences into single list.
    
    Parameters:
    - sequence: Sequence - Sequence to flatten
    - max_depth: int - Maximum nesting depth to flatten
    
    Returns:
    list - Flattened list of datasets
    """

Collection Validation Functions

Functions for validating collection contents and structure.

def validate_multivalue(multivalue):
    """
    Validate MultiValue container contents.
    
    Parameters:
    - multivalue: MultiValue - Container to validate
    
    Returns:
    list - Validation errors/warnings
    """

def check_collection_consistency(collection):
    """
    Check collection for internal consistency.
    
    Parameters:
    - collection: Sequence or MultiValue - Collection to check
    
    Returns:
    bool - True if collection is consistent
    """

def collection_statistics(collection):
    """
    Get statistics about collection contents.
    
    Parameters:
    - collection: Sequence or MultiValue - Collection to analyze
    
    Returns:
    dict - Statistics (count, types, sizes, etc.)
    """

Usage Examples

Creating and Using Sequences

from pydicom import Dataset, Sequence
from pydicom.sequence import Sequence

# Create empty sequence
referenced_images = Sequence()

# Add datasets to sequence
for i in range(3):
    item = Dataset()
    item.ReferencedSOPClassUID = "1.2.840.10008.5.1.4.1.1.2"  # CT Image Storage
    item.ReferencedSOPInstanceUID = f"1.2.3.4.5.{i}"
    referenced_images.append(item)

# Create dataset with sequence
dataset = Dataset()
dataset.PatientName = "Test Patient"
dataset.ReferencedImageSequence = referenced_images

# Access sequence items
print(f"Number of referenced images: {len(dataset.ReferencedImageSequence)}")

for i, item in enumerate(dataset.ReferencedImageSequence):
    print(f"Image {i}: {item.ReferencedSOPInstanceUID}")

Working with Nested Sequences

from pydicom import Dataset, Sequence

# Create nested sequence structure
main_dataset = Dataset()

# Create sequence of study records
study_sequence = Sequence()

for study_num in range(2):
    study_item = Dataset()
    study_item.StudyInstanceUID = f"1.2.3.{study_num}"
    study_item.StudyDescription = f"Study {study_num + 1}"
    
    # Create nested sequence of series within each study
    series_sequence = Sequence()
    
    for series_num in range(3):
        series_item = Dataset()
        series_item.SeriesInstanceUID = f"1.2.3.{study_num}.{series_num}"
        series_item.SeriesDescription = f"Series {series_num + 1}"
        series_item.Modality = "CT"
        
        series_sequence.append(series_item)
    
    study_item.SeriesSequence = series_sequence
    study_sequence.append(study_item)

main_dataset.StudySequence = study_sequence

# Navigate nested structure
for study in main_dataset.StudySequence:
    print(f"Study: {study.StudyDescription}")
    for series in study.SeriesSequence:
        print(f"  Series: {series.SeriesDescription} ({series.Modality})")

MultiValue Elements

from pydicom.multival import MultiValue
from pydicom.valuerep import DS, IS

# Create multi-value numeric elements
# Window Centers - multiple DS values
window_centers = MultiValue(DS, ["200", "400", "600"])
print(f"Window Centers: {window_centers}")
print(f"First center: {window_centers[0]}")
print(f"All centers: {list(window_centers)}")

# Image Position Patient - three DS values for x, y, z
image_position = MultiValue(DS, ["-125.0", "-125.0", "100.0"])
print(f"Image Position: {image_position}")

# Instance Numbers - multiple IS values
instance_numbers = MultiValue(IS, ["1", "2", "3", "4", "5"])
print(f"Instance Numbers: {instance_numbers}")

# Add values to existing MultiValue
window_centers.append("800")
print(f"Updated centers: {window_centers}")

# Slice through MultiValue
first_three = window_centers[:3]
print(f"First three centers: {first_three}")

String-based MultiValue Creation

from pydicom.multival import multivalue_from_string, string_from_multivalue
from pydicom.valuerep import DS

# Create from delimited string (standard DICOM format)
pixel_spacing_str = "0.625\\0.625"  # Backslash-delimited
pixel_spacing = multivalue_from_string("DS", pixel_spacing_str)
print(f"Pixel Spacing: {pixel_spacing}")
print(f"X spacing: {pixel_spacing[0]}")
print(f"Y spacing: {pixel_spacing[1]}")

# Convert back to string
spacing_str = string_from_multivalue(pixel_spacing)
print(f"String representation: '{spacing_str}'")

# Multiple window values
window_values_str = "200\\400\\600\\800"
window_values = multivalue_from_string("DS", window_values_str)
print(f"Window values: {window_values}")

Sequence Manipulation

from pydicom import Dataset, Sequence

# Create sequence
procedure_sequence = Sequence()

# Add multiple items
procedures = [
    {"CodeValue": "P001", "CodeMeaning": "CT Head"},
    {"CodeValue": "P002", "CodeMeaning": "CT Chest"},
    {"CodeValue": "P003", "CodeMeaning": "CT Abdomen"}
]

for proc in procedures:
    item = Dataset()
    item.CodeValue = proc["CodeValue"]
    item.CodingSchemeDesignator = "LOCAL"
    item.CodeMeaning = proc["CodeMeaning"]
    procedure_sequence.append(item)

# Insert item at specific position
new_proc = Dataset()
new_proc.CodeValue = "P001.5"
new_proc.CodingSchemeDesignator = "LOCAL"
new_proc.CodeMeaning = "CT Neck"
procedure_sequence.insert(1, new_proc)

# Remove item
del procedure_sequence[0]

# Iterate and modify
for i, proc in enumerate(procedure_sequence):
    proc.SequenceNumber = i + 1
    print(f"{proc.SequenceNumber}: {proc.CodeMeaning}")

Complex Sequence Structures

from pydicom import Dataset, Sequence

# Create structured report-style sequence
measurement_sequence = Sequence()

# Measurement 1: Length
length_item = Dataset()
length_item.ConceptNameCodeSequence = Sequence()
concept = Dataset()
concept.CodeValue = "410668003"
concept.CodingSchemeDesignator = "SCT"
concept.CodeMeaning = "Length"
length_item.ConceptNameCodeSequence.append(concept)

# Add measured value
length_item.MeasuredValueSequence = Sequence()
value_item = Dataset()
value_item.NumericValue = "25.4"
value_item.MeasurementUnitsCodeSequence = Sequence()
unit = Dataset()
unit.CodeValue = "mm"
unit.CodingSchemeDesignator = "UCUM"
unit.CodeMeaning = "millimeter"
value_item.MeasurementUnitsCodeSequence.append(unit)
length_item.MeasuredValueSequence.append(value_item)

measurement_sequence.append(length_item)

# Measurement 2: Area
area_item = Dataset()
area_item.ConceptNameCodeSequence = Sequence()
concept2 = Dataset()
concept2.CodeValue = "42798000"
concept2.CodingSchemeDesignator = "SCT"
concept2.CodeMeaning = "Area"
area_item.ConceptNameCodeSequence.append(concept2)

area_item.MeasuredValueSequence = Sequence()
value_item2 = Dataset()
value_item2.NumericValue = "15.8"
value_item2.MeasurementUnitsCodeSequence = Sequence()
unit2 = Dataset()
unit2.CodeValue = "mm2"
unit2.CodingSchemeDesignator = "UCUM"
unit2.CodeMeaning = "square millimeter"
value_item2.MeasurementUnitsCodeSequence.append(unit2)
area_item.MeasuredValueSequence.append(value_item2)

measurement_sequence.append(area_item)

print(f"Number of measurements: {len(measurement_sequence)}")
for i, measurement in enumerate(measurement_sequence):
    concept_name = measurement.ConceptNameCodeSequence[0].CodeMeaning
    value = measurement.MeasuredValueSequence[0].NumericValue
    unit = measurement.MeasuredValueSequence[0].MeasurementUnitsCodeSequence[0].CodeMeaning
    print(f"Measurement {i+1}: {concept_name} = {value} {unit}")

Sequence Validation and Search

from pydicom import Dataset, Sequence

# Create sequence with validation
def validate_image_reference(dataset):
    """Validate that dataset has required image reference elements."""
    required = ['ReferencedSOPClassUID', 'ReferencedSOPInstanceUID']
    return all(hasattr(dataset, attr) for attr in required)

# Create sequence
ref_sequence = Sequence()

# Add valid items
valid_item = Dataset()
valid_item.ReferencedSOPClassUID = "1.2.840.10008.5.1.4.1.1.2"
valid_item.ReferencedSOPInstanceUID = "1.2.3.4.5"
ref_sequence.append(valid_item)

# Add another valid item
valid_item2 = Dataset()
valid_item2.ReferencedSOPClassUID = "1.2.840.10008.5.1.4.1.1.1"
valid_item2.ReferencedSOPInstanceUID = "1.2.3.4.6"
ref_sequence.append(valid_item2)

# Validate all items
valid_items = [validate_image_reference(item) for item in ref_sequence]
print(f"All items valid: {all(valid_items)}")

# Search for specific items
def find_ct_images(dataset):
    """Find CT image references."""
    ct_class_uid = "1.2.840.10008.5.1.4.1.1.2"
    return dataset.ReferencedSOPClassUID == ct_class_uid

ct_references = [item for item in ref_sequence if find_ct_images(item)]
print(f"Found {len(ct_references)} CT image references")

MultiValue Type Safety

from pydicom.multival import MultiValue
from pydicom.valuerep import DS, IS

# Type-safe multi-value container
try:
    # Create DS MultiValue
    measurements = MultiValue(DS, ["1.5", "2.3", "4.7"])
    print(f"Measurements: {measurements}")
    
    # Add valid value
    measurements.append("3.8")  # String that converts to DS
    measurements.append(5.2)    # Float that converts to DS
    print(f"After additions: {measurements}")
    
    # Try to add invalid value
    measurements.append("invalid")  # This will raise an error
    
except (ValueError, TypeError) as e:
    print(f"Type validation error: {e}")

# Ensure consistent types
window_levels = MultiValue(IS, [100, 200, 300])
print(f"Window levels: {window_levels}")
print(f"Type of first element: {type(window_levels[0])}")

Install with Tessl CLI

npx tessl i tessl/pypi-pydicom

docs

configuration-utilities.md

data-elements.md

dataset-manipulation.md

file-operations.md

index.md

pixel-data-processing.md

sequences-collections.md

tags-and-uids.md

value-representations.md

tile.json