Component System

OpenHCS uses a dynamic component system to organize microscopy data processing across different dimensions. The system provides two main enums - AllComponents and VariableComponents - that serve different purposes in the processing pipeline.

Understanding Component Types

OpenHCS distinguishes between components that are available for user configuration and those used for internal operations:

AllComponents: Complete component set including the multiprocessing axis VariableComponents: User-selectable components excluding the multiprocessing axis GroupBy: VariableComponents with an additional NONE option for routing

from openhcs.constants import AllComponents, VariableComponents, GroupBy

# AllComponents includes all dimensions
list(AllComponents)  # [SITE, CHANNEL, Z_INDEX, WELL]

# VariableComponents excludes multiprocessing axis (WELL by default)
list(VariableComponents)  # [SITE, CHANNEL, Z_INDEX]

# GroupBy adds NONE option to VariableComponents
list(GroupBy)  # [SITE, CHANNEL, Z_INDEX, NONE]

Dynamic Enum Generation

Components are created dynamically from configuration when first accessed:

# Enums are generated lazily from ComponentConfiguration
from openhcs.constants import get_openhcs_config

config = get_openhcs_config()
# Configuration determines:
# - All available components (SITE, CHANNEL, Z_INDEX, WELL)
# - Multiprocessing axis (WELL)
# - Remaining components for user selection (SITE, CHANNEL, Z_INDEX)

The configuration drives which components are available and how they’re filtered for different use cases.

When to Use Each Component Type

AllComponents: Internal Operations

Use AllComponents for operations that need access to the complete dimensional space:

# Cache addressing requires full component set
orchestrator.cache_component_keys([AllComponents.WELL, AllComponents.SITE])

# Getting component keys for any dimension
axis_values = orchestrator.get_component_keys(MULTIPROCESSING_AXIS)  # Dynamic axis
sites = orchestrator.get_component_keys(AllComponents.SITE)

When to use AllComponents: - Cache operations and full-space addressing - Orchestrator component key operations - Internal system operations that need complete dimensional access

VariableComponents: User Configuration

Use VariableComponents for step configuration and user-facing operations:

from openhcs.core.steps.function_step import FunctionStep
from openhcs.core.pipeline_config import LazyStepMaterializationConfig

# Step configuration with user-selectable components
step = FunctionStep(
    func=(normalize_images, {}),
    variable_components=[VariableComponents.SITE, VariableComponents.CHANNEL],
    materialization_config=LazyStepMaterializationConfig()
)

When to use VariableComponents: - Step configuration in pipelines - UI component dropdowns and selectors - User-facing configuration options - Pattern discovery and grouping operations

GroupBy: Function Routing

Use GroupBy for dictionary function patterns and conditional routing:

# Route different channels to different functions
step = FunctionStep(
    func={
        '1': (analyze_nuclei, {}),     # Channel 1 → nuclei analysis
        '2': (analyze_neurites, {})    # Channel 2 → neurite analysis
    },
    group_by=GroupBy.CHANNEL,
    variable_components=[VariableComponents.SITE]
)

# No grouping option
step = FunctionStep(
    func=(process_all_data, {}),
    group_by=GroupBy.NONE,
    variable_components=[VariableComponents.SITE]
)

See also

Pattern Grouping and Special Output Path Resolution

Comprehensive explanation of how group_by works for both dict and list patterns, including special output namespacing

GroupBy properties:

# Access underlying component value
assert GroupBy.CHANNEL.component == "channel"
assert GroupBy.NONE.component is None

# String value for pattern operations
component_string = GroupBy.CHANNEL.value  # "channel"

Multiprocessing Axis

The multiprocessing axis determines how parallel processing is partitioned:

from openhcs.constants import MULTIPROCESSING_AXIS

# Get multiprocessing axis component (WELL by default)
axis = MULTIPROCESSING_AXIS  # Returns the configured multiprocessing component

# Use in orchestrator operations
wells_to_process = orchestrator.get_component_keys(MULTIPROCESSING_AXIS)

Key characteristics: - Excluded from VariableComponents (not user-selectable) - Included in AllComponents (available for internal operations) - Used by compiler and orchestrator for task partitioning - Configurable through ComponentConfiguration

Practical Usage Examples

Step Configuration

from openhcs.core.steps.function_step import FunctionStep
from openhcs.processing.backends.processors.numpy_processor import create_composite

# Process each site separately, combining channels
composite_step = FunctionStep(
    func=create_composite,
    variable_components=[VariableComponents.SITE],
    name="create_composite"
)

Cache Operations

# Cache all component types for fast access
orchestrator.cache_component_keys(list(AllComponents))

# Get cached component keys for current multiprocessing axis
from openhcs.constants import MULTIPROCESSING_AXIS
available_axis_values = orchestrator.get_component_keys(MULTIPROCESSING_AXIS)

Pattern Discovery

# Group patterns by component for organization
if group_by and group_by != GroupBy.NONE:
    component_string = group_by.value
    grouped_patterns = pattern_discovery.group_patterns_by_component(
        patterns, component=component_string
    )

UI Component Population

# Populate dropdown with user-selectable components
component_options = list(VariableComponents)

# Populate GroupBy selector with NONE option
groupby_options = list(GroupBy)

Integration with Configuration

The component system integrates with OpenHCS configuration for customization:

from openhcs.core.components.framework import ComponentConfigurationFactory

# Custom component configuration
config = ComponentConfigurationFactory.create_configuration(
    component_enum=MyCustomEnum,
    multiprocessing_axis=MyCustomEnum.BATCH,
    default_variable=[MyCustomEnum.SAMPLE],
    default_group_by=MyCustomEnum.CONDITION
)

This enables different microscopy setups to define their own component dimensions while maintaining the same processing patterns.

Performance Characteristics

  • Lazy Loading: Enums created only when first accessed

  • Caching: Enum instances cached to avoid recreation

  • Memory Overhead: Minimal - single enum instances per component set

  • Access Time: O(1) after initial creation

The lazy loading ensures minimal startup overhead while caching provides fast subsequent access.