Architecture
This page explains how Orca organizes and executes laboratory automation.
Component Hierarchy
Orca uses a hierarchical structure:
System
├── Devices (shaker, sealer, centrifuge, liquid handler)
├── Transporters (robotic arms)
└── Workflows
└── Threads (a single piece of labware's path through the system)
└── Methods (grouped actions)
└── Actions (Shake, Seal, Spin, RunProtocol, and more)
Workflows
A WorkflowTemplate orchestrates multiple threads. It defines:
- Which threads exist
- Which threads start when the workflow starts (marked with
is_start=True) - Spawn points where new threads are created
- Join points where threads synchronize
Threads
A ThreadTemplate represents a single piece of labware's path through the system:
- Which labware template it processes
- Start and end locations
- Sequence of methods to execute
Threads run in parallel. Multiple plates can be processing simultaneously.
Methods
A MethodTemplate groups related actions:
- Actions execute sequentially within a method
- The transporter moves labware to the method's device before execution
- Methods can be shared between threads using
SharedMethodTemplate
Actions
Actions are individual device operations:
Shake- Shake on a shakerSpin- CentrifugeSeal- Heat sealRead- Read on plate readerDelid- Remove lidRunProtocol- Run external protocol filePythonMethod- Execute custom Python code
Execution Flow
For each thread:
- Start - Thread begins at its start location
- For each method:
- Transporter picks plate from current location
- Transporter places plate at method's device
- All actions in the method execute sequentially
- End - Transporter moves plate to end location
Example Flow
Thread: sample_plate
├── Start: input_stack
├── Method 1: dispense_method (at liquid_handler)
│ └── Action: PythonMethod (custom dispense logic)
├── Method 2: seal_method (at sealer)
│ └── Action: Seal (165°C, 5 seconds)
└── End: output_stack
Physical execution:
- Pick plate from input_stack
- Place at liquid_handler → Execute PythonMethod
- Pick from liquid_handler
- Place at sealer → Execute Seal
- Pick from sealer
- Place at output_stack
Parallel Execution
Threads execute concurrently:
Thread A: ─────[Method1]─────[Method2]─────[Method3]────→
Thread B: ───────────[Method1]─────[Method2]───────────→
Thread C: ─────────────────[Method1]─────[Method2]─────→
The scheduler coordinates resource access. If two threads need the same device, one waits.
Multi-Plate Operations
Some operations need multiple plates simultaneously (e.g., liquid transfer). Use SharedMethodTemplate:
from orca.sdk.workflow import SharedMethodTemplate
transfer_method = MethodTemplate(
name="transfer",
actions=[
RunProtocol(
resource=liquid_handler,
protocol_filepath="transfer.hsl",
inputs=[source_plate, dest_plate],
outputs=[source_plate, dest_plate]
)
]
)
# Source thread has the full method
source_thread = ThreadTemplate(
source_plate, start, end,
methods=[transfer_method]
)
# Dest thread uses SharedMethodTemplate as placeholder
dest_thread = ThreadTemplate(
dest_plate, start, end,
methods=[SharedMethodTemplate()]
)
# Configure spawn point with join
workflow.set_spawn_point(
spawn_thread=dest_thread,
from_thread=source_thread,
at=transfer_method,
join=True # Both plates must arrive before method executes
)
System Building
Before execution, you build a System from templates:
builder = SdkToSystemBuilder(
name="My System",
description="Description",
labwares=[plate1, plate2],
resources=registry,
system_map=system_map,
methods=[method1, method2],
workflows=[workflow],
event_bus=event_bus
)
system = builder.get_system()
The builder:
- Validates all references
- Creates executable versions of templates
- Connects devices and locations