Skip to main content

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 shaker
  • Spin - Centrifuge
  • Seal - Heat seal
  • Read - Read on plate reader
  • Delid - Remove lid
  • RunProtocol - Run external protocol file
  • PythonMethod - Execute custom Python code

Execution Flow

For each thread:

  1. Start - Thread begins at its start location
  2. For each method:
    • Transporter picks plate from current location
    • Transporter places plate at method's device
    • All actions in the method execute sequentially
  3. 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:

  1. Pick plate from input_stack
  2. Place at liquid_handler → Execute PythonMethod
  3. Pick from liquid_handler
  4. Place at sealer → Execute Seal
  5. Pick from sealer
  6. 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

Next Steps