Step
Overview
A Step is a single processing operation that can be applied to images. It is a key component of the EZStitcher architecture.
For an overview of the complete architecture, see Architecture Overview.
EZStitcher provides several types of steps:
Base Step: The foundation for all step types, providing core functionality
Pre-defined Steps: Steps for common operations (ZFlatStep, FocusStep, CompositeStep)
Task-specific Steps: Steps for specific tasks (PositionGenerationStep, ImageStitchingStep)
The base Step class provides:
Image loading and saving
Processing function application
Variable component handling (e.g., channels, z-indices)
Group-by functionality for processing related images together
Creating a Basic Step
from ezstitcher.core.steps import Step
from ezstitcher.core.image_processor import ImageProcessor as IP
# Create a basic processing step
step = Step(
name="Image Enhancement",
func=IP.stack_percentile_normalize,
variable_components=['channel'],
group_by='channel',
input_dir=orchestrator.workspace_path, # Specify input_dir for the first step
# output_dir is automatically determined
)
Step Parameters
For detailed API documentation, see Steps.
name: Human-readable name for the stepfunc: The processing function(s) to apply (see Function Handling)variable_components: Components that vary across files (e.g., ‘z_index’, ‘channel’)group_by: How to group files for processing (e.g., ‘channel’, ‘site’)input_dir: The input directory (optional, can inherit from pipeline)output_dir: The output directory (optional, can inherit from pipeline)well_filter: Wells to process (optional, can inherit from pipeline)
For practical examples of how to use these parameters in different scenarios, see:
Basic Usage - Basic examples of step parameters
Intermediate Usage - Examples of variable_components and group_by
Advanced Usage - Advanced examples of func parameter
Best Practices - Best practices for step parameters
Processing Arguments
Processing arguments are passed directly with the function using the tuple pattern (func, kwargs). For detailed information about function patterns and usage, see Function Handling.
# Pass arguments to a function
step = Step(
name="Z-Stack Flattening",
func=(IP.create_projection, {'method': 'max_projection'}),
variable_components=['z_index'],
input_dir=orchestrator.workspace_path
)
This pattern can be used with:
Single functions (function-single, function-with-arguments)
Lists of functions (function-lists, function-lists-with-arguments)
Dictionaries of functions (function-dictionaries, function-dictionary-tuples)
Mixed function types (function-mixed-types)
Note
Always use the tuple pattern (func, kwargs) to pass arguments to processing functions.
This is the recommended approach for all function arguments.
Step Initialization Best Practices
When initializing steps, it’s important to follow best practices for directory specification.
Steps can specify input and output directories. For detailed information about directory structure, see Directory Structure.
Variable Components
The variable_components parameter specifies which components will be grouped together for processing. It determines how images are organized into stacks before being passed to the processing function.
Key concept: Images that share the same values for all components except the variable component will be grouped together into a stack.
In most cases, you don’t need to set this explicitly as it defaults to ['site'], but there are specific cases where you should change it.
For practical examples of how to use variable_components in different scenarios, see:
Intermediate Usage - Examples for Z-stack processing and channel compositing
Advanced Usage - Advanced examples with custom functions
# IMPORTANT: For Z-stack flattening, use ZFlatStep instead of raw Step with variable_components
# This is the recommended approach for Z-stack flattening
from ezstitcher.core.steps import ZFlatStep
# Maximum intensity projection (default)
step = ZFlatStep() # Uses max_projection by default
# With specific projection method
step = ZFlatStep(method="mean") # Uses mean_projection
# IMPORTANT: For channel compositing, use CompositeStep instead of raw Step with variable_components
# This is the recommended approach for channel compositing
from ezstitcher.core.steps import CompositeStep
# Without weights (equal weighting for all channels)
step = CompositeStep() # Equal weights for all channels
# With custom weights (70% channel 1, 30% channel 2)
step = CompositeStep(weights=[0.7, 0.3]) # Custom channel weights
# For most other operations, the default 'site' is appropriate
# This groups images with the same channel, z_index, etc. but different site values
# The function will receive a stack of images with varying site values
step = Step(
name="Enhance Images",
func=stack(IP.sharpen)
# variable_components defaults to ['site']
)
Group By
The group_by parameter is specifically designed for use with function dictionaries in Step. It specifies what component the keys in your function dictionary correspond to.
For practical examples of how to use group_by in different scenarios, see:
Intermediate Usage - Examples for channel-specific processing
Advanced Usage - Advanced examples with dictionaries of functions
# When using a dictionary of channel-specific functions
step = Step(
name="Channel-Specific Processing",
func={"1": process_dapi, "2": process_calcein},
# variable_components defaults to ['site']
group_by='channel' # Keys "1" and "2" correspond to channel values
)
Key concept: The group_by parameter tells the Step what the keys in the function dictionary represent.
In this example:
- group_by='channel' means the keys in the function dictionary (“1” and “2”) correspond to channel values
- Images with channel=”1” will be processed by process_dapi
- Images with channel=”2” will be processed by process_calcein
Parameter Relationships and Constraints:
group_byis only needed when using a dictionary of functions. It’s not needed for single functions or lists of functions.group_byshould NEVER be the same asvariable_components:This is a critical rule that must be followed to avoid logical errors. When
variable_components=['channel'], it means we’re processing each channel separately. Whengroup_by='channel', it means we’re grouping functions by channel. If these were the same, it would create a logical contradiction in how the images are processed.# CORRECT: variable_components and group_by are different step = Step( name="Channel-Specific Processing", func={"1": process_dapi, "2": process_calcein}, variable_components=['site'], # Process each site separately group_by='channel' # Keys "1" and "2" correspond to channel values ) # INCORRECT: variable_components and group_by are the same # This will lead to logical errors and should never be done step = Step( name="Incorrect Setup", func={"1": process_dapi, "2": process_calcein}, variable_components=['channel'], # Process each channel separately group_by='channel' # Keys "1" and "2" correspond to channel values )
group_byis typically only set whenvariable_componentsis left at its default value of['site']:# Typical pattern: variable_components defaults to ['site'], group_by is set to 'channel' step = Step( name="Channel-Specific Processing", func={"1": process_dapi, "2": process_calcein}, # variable_components defaults to ['site'] group_by='channel' # Keys "1" and "2" correspond to channel values )
input_dirmust be specified for the first step in a pipeline, typically usingorchestrator.workspace_path.output_diris optional and will be automatically determined if not specified.well_filteris optional and will inherit from the pipeline’s context if not specified.
Best Practices
For comprehensive best practices on using steps effectively, see Step Configuration and Usage Best Practices in the Best Practices guide.
For information on when to use specialized steps, see Step Configuration and Usage Best Practices in the Best Practices guide.
For channel-specific processing with different functions per channel, using a raw Step with a dictionary
of functions and group_by='channel' is the appropriate approach.