Time and Sequence

Overview

This section covers the ordering and timing of tasks within a workflow. It explains methods for controlling the sequence and constraining task execution to control exactly when tasks are completed.

Time Constraints

Time constraints define how two tasks are related in terms of their start and end times. They control task sequencing and timing to maintain order in workflows. These constraints are used by the planner when planning occurs. See planning and validation.

Available Constraint Types

  • START_TO_END: The first task starts before the second finishes.

  • START_TO_START: The second task starts after the first starts.

  • END_TO_END: The second task finishes after the first.

  • END_TO_START: The second task starts after the first finishes.

  • CONSISTENCY: Ensures timing consistency between two tasks.

plate_incubation = ActionTask(...)
dispense_reagent = ActionTask(...)

# Defining the time constraint for incubation
plate_incubation = TimeConstraint(
    id="incubate-to-dispense-constraint",
    constraint_type=TimeConstraintType(value="end_to_start"),
    start_task=plate_incubation,
    end_task=dispense_reagent,
    min_duration=600,
    max_duration=900
)

Time Constraints are added to a Workflow object. See Workflow.

In the event a time constraint is broken (for example due to an error or a large difference between estimated and real time) an error will be raised with mitigation options. See Error Handling.

class linq.workflow.TimeConstraint(*, id: str, constraint_type: TimeConstraintType, start_task: ActionTask, end_task: ActionTask, min_duration: int | None, max_duration: int | None)

A time constraint for a sequence of tasks.

id: str

Unique ID for this time constraint.

constraint_type: TimeConstraintType

Time constraint type.

start_task: ActionTask

First task in the sequence that the constraint applies to.

end_task: ActionTask

Last task in the sequence that the constraint applies to.

min_duration: int | None

Minimum duration allowed for the sequence.

max_duration: int | None

Maximum duration allowed for the sequence.

Max Idle Time

Max idle time sets the maximum duration a labware type can be left unattended during a workflow. This is important for labware containing sensitive materials like cells or samples that require timely handling to maintain their integrity.

To define max idle time, use the max_idle_time parameter in your labware type definition:

assay_plate = LabwareType(
    id="nest_flat_bottom_96_well_plate",
    max_idle_time=30  # Max idle time in seconds
)

Instrument Blocks

Instrument blocks prevent any task from executing on a specific instrument from a specified task until another specified task. This is useful when an instrument’s state is temporarily modified (e.g. holding a cap) meaning it is not strictly being used for a task, but is otherwise occupied.

A typical use case is an uncapping task which requires an instrument to hold a cap until the next task is completed. The specific uncapper can be blocked from use until a task completes.

Instrument blocks are added to a Workflow object. See Workflow.

class linq.workflow.InstrumentBlock(*, start_task: ActionTask, end_task: ActionTask)

An instrument block instruction, keeping the instrument from being used between two tasks.

Dependencies

Task dependencies ensure that certain tasks are completed before others can begin, maintaining proper task order. The first task of a chain of tasks will not have any dependencies. Any kind of task can have a dependency or be the target of a dependency.

Labware input and output creates labware dependencies automatically. In other words, if a given task has specified a previous task as containing labware that it needs as input, a dependency does not need to be specified. See Labware Flow.

Additional dependencies can be manually configured as follows:

dispense_reagent = ActionTask(...)

load_plate = ActionTask(
    id="load_plate",
    # ...
    dependencies=[dispense_reagent],
)

You can have multiple dependencies for the same task. Note that any type of task, e.g. a CodeTask or an ActionTask, can be specified in the dependency array or made dependent on any other task.

dependencies=[dispense_reagent, move_data],

Time estimates

Time estimates approximate how long each task will take, used by the planner to optimise task scheduling and predict workflow duration.

If the actual time is different from the estimated time for a task when executing on hardware, a replan may be triggered. See Planning and Validation.

dispense_reagent = ActionTask(...)

load_plate = ActionTask(
    id="load_plate",
    # ...
    time_estimate=20,
)

Transport Matrix and Robots

In workflows, transport actions are implicit, meaning they happen automatically between tasks (see Tasks and Transport. The transport matrix allows you to configure estimated timings for movements between workbenches and robots. These timings are used during planning to calculate transport tasks when the workflow is executed.

The default_transport_time serves as the fallback time for any unspecified transport paths. However, you can customize the timing between specific robots by defining transport paths. This lets you control how long it takes to move between robots while accounting for transport layer movements, ensuring more accurate planning.

workcell = Workcell(

    # ...

    transport_matrix=TransportMatrix(
            default_transport_time=20,
            paths=[
                TransportPath(source="robot_1", destination="robot_1", time=55),
                TransportPath(source="robot_2", destination="robot_2", time=20),
                TransportPath(source="robot_1", destination="robot_2", time=90),
                TransportPath(source="robot_2", destination="robot_1", time=100),
            ],
        ),
    )
class linq.workcell.TransportMatrix(*, default_transport_time: int, paths: list[TransportPath])

The transport matrix contains all estimates for transport times between benches.

default_transport_time: int

Default transport time if no specific estimate for a path is given.

paths: list[TransportPath]

List of paths describing the time to transport labware from one bench to another.