Skip to content

Commit 8d9b210

Browse files
authored
Merge branch 'edge' into docs-flow-rates-update
2 parents 30ea07c + 5303a3b commit 8d9b210

File tree

91 files changed

+2609
-683
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+2609
-683
lines changed

api-client/src/maintenance_runs/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type {
66
} from '@opentrons/shared-data'
77
import type {
88
RunCommandSummary,
9-
LabwareOffsetCreateData,
9+
LegacyLabwareOffsetCreateData,
1010
RunStatus,
1111
RunAction,
1212
} from '../runs'
@@ -42,7 +42,7 @@ export interface MaintenanceRunError {
4242
}
4343

4444
export interface CreateMaintenanceRunData {
45-
labwareOffsets?: LabwareOffsetCreateData[]
45+
labwareOffsets?: LegacyLabwareOffsetCreateData[]
4646
}
4747

4848
export interface LabwareDefinitionSummary {

api-client/src/runs/createLabwareOffset.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ import { POST, request } from '../request'
22

33
import type { ResponsePromise } from '../request'
44
import type { HostConfig } from '../types'
5-
import type { LabwareOffsetCreateData, Run } from './types'
5+
import type { LegacyLabwareOffsetCreateData, Run } from './types'
66

77
export function createLabwareOffset(
88
config: HostConfig,
99
runId: string,
10-
data: LabwareOffsetCreateData
10+
data: LegacyLabwareOffsetCreateData
1111
): ResponsePromise<Run> {
12-
return request<Run, { data: LabwareOffsetCreateData }>(
12+
return request<Run, { data: LegacyLabwareOffsetCreateData }>(
1313
POST,
1414
`/runs/${runId}/labware_offsets`,
1515
{ data },

api-client/src/runs/createRun.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ import type { ResponsePromise } from '../request'
44
import type { HostConfig } from '../types'
55
import type {
66
Run,
7-
LabwareOffsetCreateData,
7+
LegacyLabwareOffsetCreateData,
88
RunTimeParameterValuesCreateData,
99
RunTimeParameterFilesCreateData,
1010
} from './types'
1111

1212
export interface CreateRunData {
1313
protocolId?: string
14-
labwareOffsets?: LabwareOffsetCreateData[]
14+
labwareOffsets?: LegacyLabwareOffsetCreateData[]
1515
runTimeParameterValues?: RunTimeParameterValuesCreateData
1616
runTimeParameterFiles?: RunTimeParameterFilesCreateData
1717
}

api-client/src/runs/types.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ export interface LabwareOffset {
8585
id: string
8686
createdAt: string
8787
definitionUri: string
88-
location: LabwareOffsetLocation
88+
location: LegacyLabwareOffsetLocation
89+
locationSequence?: LabwareOffsetLocationSequence
8990
vector: VectorOffset
9091
}
9192

@@ -156,14 +157,35 @@ export interface CreateRunActionData {
156157
actionType: RunActionType
157158
}
158159

159-
export interface LabwareOffsetLocation {
160+
export interface OnAddressableAreaLabwareOffsetLocationSequenceComponent {
161+
kind: 'onAddressableArea'
162+
labware: string
163+
}
164+
165+
export interface OnModuleOffsetLocationSequenceComponent {
166+
kind: 'onModule'
167+
moduleModel: ModuleModel
168+
}
169+
170+
export interface OnLabwareOffsetLocationSequenceComponent {
171+
kind: 'onLabware'
172+
labwareUri: string
173+
}
174+
175+
export type LabwareOffsetLocationSequenceComponent =
176+
| OnAddressableAreaLabwareOffsetLocationSequenceComponent
177+
| OnModuleOffsetLocationSequenceComponent
178+
| OnLabwareOffsetLocationSequenceComponent
179+
export type LabwareOffsetLocationSequence = LabwareOffsetLocationSequenceComponent[]
180+
181+
export interface LegacyLabwareOffsetLocation {
160182
slotName: string
161183
moduleModel?: ModuleModel
162184
definitionUri?: string
163185
}
164-
export interface LabwareOffsetCreateData {
186+
export interface LegacyLabwareOffsetCreateData {
165187
definitionUri: string
166-
location: LabwareOffsetLocation
188+
location: LegacyLabwareOffsetLocation
167189
vector: VectorOffset
168190
}
169191

api/src/opentrons/protocol_api/core/engine/labware.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ def set_calibration(self, delta: Point) -> None:
122122

123123
request = LabwareOffsetCreate.model_construct(
124124
definitionUri=self.get_uri(),
125-
location=offset_location,
125+
locationSequence=offset_location,
126126
vector=LabwareOffsetVector(x=delta.x, y=delta.y, z=delta.z),
127127
)
128128
self._engine_client.add_labware_offset(request)

api/src/opentrons/protocol_api/core/legacy/labware_offset_provider.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
from typing import Optional
44

55
from opentrons.hardware_control.modules import ModuleModel as HardwareModuleModel
6-
from opentrons.protocol_engine import ProtocolEngine, LabwareOffsetLocation, ModuleModel
6+
from opentrons.protocol_engine import (
7+
ProtocolEngine,
8+
LegacyLabwareOffsetLocation,
9+
ModuleModel,
10+
)
711
from opentrons.types import DeckSlotName, Point
812

913
from ..labware import LabwareLoadParams
@@ -81,9 +85,9 @@ def find(
8185
8286
See the parent class for param details.
8387
"""
84-
offset = self._labware_view.find_applicable_labware_offset(
88+
offset = self._labware_view.find_applicable_labware_offset_by_legacy_location(
8589
definition_uri=load_params.as_uri(),
86-
location=LabwareOffsetLocation(
90+
location=LegacyLabwareOffsetLocation(
8791
slotName=deck_slot,
8892
moduleModel=(
8993
None

api/src/opentrons/protocol_engine/__init__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@
2626

2727
from .types import (
2828
LabwareOffset,
29+
LegacyLabwareOffsetCreate,
2930
LabwareOffsetCreate,
3031
LabwareOffsetVector,
31-
LabwareOffsetLocation,
32+
LegacyLabwareOffsetLocation,
3233
LabwareMovementStrategy,
3334
AddressableOffsetVector,
3435
DeckPoint,
@@ -96,7 +97,8 @@
9697
"LabwareOffset",
9798
"LabwareOffsetCreate",
9899
"LabwareOffsetVector",
99-
"LabwareOffsetLocation",
100+
"LegacyLabwareOffsetCreate",
101+
"LegacyLabwareOffsetLocation",
100102
"LabwareMovementStrategy",
101103
"AddressableOffsetVector",
102104
"DeckSlotLocation",

api/src/opentrons/protocol_engine/actions/actions.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from ..notes.notes import CommandNote
2424
from ..state.update_types import StateUpdate
2525
from ..types import (
26-
LabwareOffsetCreate,
26+
LabwareOffsetCreateInternal,
2727
ModuleDefinition,
2828
Liquid,
2929
DeckConfigurationType,
@@ -206,7 +206,7 @@ class AddLabwareOffsetAction:
206206

207207
labware_offset_id: str
208208
created_at: datetime
209-
request: LabwareOffsetCreate
209+
request: LabwareOffsetCreateInternal
210210

211211

212212
@dataclasses.dataclass(frozen=True)

api/src/opentrons/protocol_engine/errors/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
InvalidLiquidError,
8383
LiquidClassDoesNotExistError,
8484
LiquidClassRedefinitionError,
85+
OffsetLocationInvalidError,
8586
)
8687

8788
from .error_occurrence import ErrorOccurrence, ProtocolCommandFailedError
@@ -160,6 +161,7 @@
160161
"LocationIsLidDockSlotError",
161162
"InvalidAxisForRobotType",
162163
"NotSupportedOnRobotType",
164+
"OffsetLocationInvalidError",
163165
# error occurrence models
164166
"ErrorOccurrence",
165167
"CommandNotAllowedError",

api/src/opentrons/protocol_engine/errors/exceptions.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,19 @@ def __init__(
433433
super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
434434

435435

436+
class OffsetLocationInvalidError(ProtocolEngineError):
437+
"""Raised when encountering an invalid labware offset location sequence."""
438+
439+
def __init__(
440+
self,
441+
message: Optional[str] = None,
442+
details: Optional[Dict[str, Any]] = None,
443+
wrapping: Optional[Sequence[EnumeratedError]] = None,
444+
) -> None:
445+
"""Build an OffsetLocationSequenceDoesNotTerminateAtAnAddressableAreaError."""
446+
super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
447+
448+
436449
class SlotDoesNotExistError(ProtocolEngineError):
437450
"""Raised when referencing a deck slot that does not exist."""
438451

api/src/opentrons/protocol_engine/execution/equipment.py

Lines changed: 3 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""Equipment command side-effect logic."""
2+
23
from dataclasses import dataclass
34
from typing import Optional, overload, Union, List
45

@@ -42,10 +43,7 @@
4243
from ..types import (
4344
LabwareLocation,
4445
DeckSlotLocation,
45-
ModuleLocation,
46-
OnLabwareLocation,
4746
LabwareOffset,
48-
LabwareOffsetLocation,
4947
ModuleModel,
5048
ModuleDefinition,
5149
AddressableAreaLocation,
@@ -633,8 +631,9 @@ def find_applicable_labware_offset_id(
633631
or None if no labware offset will apply.
634632
"""
635633
labware_offset_location = (
636-
self._get_labware_offset_location_from_labware_location(labware_location)
634+
self._state_store.geometry.get_projected_offset_location(labware_location)
637635
)
636+
638637
if labware_offset_location is None:
639638
# No offset for off-deck location.
640639
# Returning None instead of raising an exception allows loading a labware
@@ -647,72 +646,6 @@ def find_applicable_labware_offset_id(
647646
)
648647
return self._get_id_from_offset(offset)
649648

650-
def _get_labware_offset_location_from_labware_location(
651-
self, labware_location: LabwareLocation
652-
) -> Optional[LabwareOffsetLocation]:
653-
if isinstance(labware_location, DeckSlotLocation):
654-
return LabwareOffsetLocation(slotName=labware_location.slotName)
655-
elif isinstance(labware_location, ModuleLocation):
656-
module_id = labware_location.moduleId
657-
# Allow ModuleNotLoadedError to propagate.
658-
# Note also that we match based on the module's requested model, not its
659-
# actual model, to implement robot-server's documented HTTP API semantics.
660-
module_model = self._state_store.modules.get_requested_model(
661-
module_id=module_id
662-
)
663-
664-
# If `module_model is None`, it probably means that this module was added by
665-
# `ProtocolEngine.use_attached_modules()`, instead of an explicit
666-
# `loadModule` command.
667-
#
668-
# This assert should never raise in practice because:
669-
# 1. `ProtocolEngine.use_attached_modules()` is only used by
670-
# robot-server's "stateless command" endpoints, under `/commands`.
671-
# 2. Those endpoints don't support loading labware, so this code will
672-
# never run.
673-
#
674-
# Nevertheless, if it does happen somehow, we do NOT want to pass the
675-
# `None` value along to `LabwareView.find_applicable_labware_offset()`.
676-
# `None` means something different there, which will cause us to return
677-
# wrong results.
678-
assert module_model is not None, (
679-
"Can't find offsets for labware"
680-
" that are loaded on modules"
681-
" that were loaded with ProtocolEngine.use_attached_modules()."
682-
)
683-
684-
module_location = self._state_store.modules.get_location(
685-
module_id=module_id
686-
)
687-
slot_name = module_location.slotName
688-
return LabwareOffsetLocation(slotName=slot_name, moduleModel=module_model)
689-
elif isinstance(labware_location, OnLabwareLocation):
690-
parent_labware_id = labware_location.labwareId
691-
parent_labware_uri = self._state_store.labware.get_definition_uri(
692-
parent_labware_id
693-
)
694-
695-
base_location = self._state_store.labware.get_parent_location(
696-
parent_labware_id
697-
)
698-
base_labware_offset_location = (
699-
self._get_labware_offset_location_from_labware_location(base_location)
700-
)
701-
if base_labware_offset_location is None:
702-
# No offset for labware sitting on labware off-deck
703-
return None
704-
705-
# If labware is being stacked on itself, all labware in the stack will share a labware offset due to
706-
# them sharing the same definitionUri in `LabwareOffsetLocation`. This will not be true for the
707-
# bottom-most labware, which will have a `DeckSlotLocation` and have its definitionUri field empty.
708-
return LabwareOffsetLocation(
709-
slotName=base_labware_offset_location.slotName,
710-
moduleModel=base_labware_offset_location.moduleModel,
711-
definitionUri=parent_labware_uri,
712-
)
713-
else: # Off deck
714-
return None
715-
716649
@staticmethod
717650
def _get_id_from_offset(labware_offset: Optional[LabwareOffset]) -> Optional[str]:
718651
return None if labware_offset is None else labware_offset.id

0 commit comments

Comments
 (0)