Component System Integration
Overview
OpenHCS subsystems consume component information through standardized interfaces driven by component configuration. This eliminates hardcoded assumptions about component names and enables consistent behavior across orchestrator, compiler, pattern discovery, UI, and cache systems.
# All subsystems use the same component interfaces
from openhcs.constants import AllComponents, VariableComponents, GroupBy, MULTIPROCESSING_AXIS
# Orchestrator caches all components
orchestrator.cache_component_keys(list(AllComponents))
# Compiler partitions by multiprocessing axis
axis_values = orchestrator.get_component_keys(MULTIPROCESSING_AXIS)
# UI populates with user-selectable components
component_selector.populate_options(list(VariableComponents))
Component configuration serves as the single source of truth for dimensional structure across all subsystems.
Lazy Export System
Component enums are created dynamically when first accessed to avoid circular imports and reflect current configuration.
# openhcs/constants/constants.py
def __getattr__(name):
"""Lazy enum creation."""
if name in ('AllComponents', 'VariableComponents', 'GroupBy'):
all_components, vc, gb = _create_enums()
globals()['AllComponents'] = all_components
globals()['VariableComponents'] = vc
globals()['GroupBy'] = gb
return globals()[name]
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
This ensures enums reflect the current component configuration and are created only when needed.
Orchestrator Integration
The orchestrator uses AllComponents for caching and provides component keys to all subsystems.
# Orchestrator caches all components for fast access
orchestrator.cache_component_keys(list(AllComponents))
# Subsystems request component keys generically
axis_values = orchestrator.get_component_keys(MULTIPROCESSING_AXIS)
available_channels = orchestrator.get_component_keys(VariableComponents.CHANNEL)
This provides consistent component key resolution across all subsystems.
Compiler Integration
The compiler uses MULTIPROCESSING_AXIS for dynamic task partitioning.
# Compiler partitions tasks by multiprocessing axis
from openhcs.constants import MULTIPROCESSING_AXIS
axis_name = MULTIPROCESSING_AXIS.value
filter_kwargs = {f"{axis_name}_filter": axis_values[:5]}
compiled_contexts = PipelineCompiler.compile_pipelines(
orchestrator, pipeline_definition, **filter_kwargs
)
This enables the same compilation logic to work with any multiprocessing axis.
UI Integration
UI components populate dynamically with user-selectable components.
# UI populates with user-selectable components
component_options = list(VariableComponents)
groupby_options = list(GroupBy)
# Component selection dialog uses current group_by
available_components = orchestrator.get_component_keys(self.current_group_by)
# Dynamic component type handling
component_type = self.current_group_by.value
display_name = self._get_component_display_name(selected_component)
This ensures UI components adapt to the available component structure dynamically.
Common Gotchas:
Don’t use
GroupBy.NONEwith dict patterns - validation will failComponent keys are cached on initialization - call
clear_component_cache()if input directory changesDict pattern keys must match actual component values, not enum names