opentrons 8.6.0a12__py3-none-any.whl → 8.7.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- opentrons/_version.py +2 -2
- opentrons/drivers/asyncio/communication/serial_connection.py +8 -5
- opentrons/drivers/flex_stacker/driver.py +6 -1
- opentrons/hardware_control/backends/flex_protocol.py +1 -0
- opentrons/hardware_control/backends/ot3controller.py +25 -13
- opentrons/hardware_control/backends/ot3simulator.py +2 -1
- opentrons/hardware_control/dev_types.py +3 -1
- opentrons/hardware_control/instruments/ot2/pipette_handler.py +1 -0
- opentrons/hardware_control/instruments/ot3/pipette_handler.py +1 -0
- opentrons/hardware_control/ot3api.py +3 -1
- opentrons/hardware_control/protocols/gripper_controller.py +1 -0
- opentrons/protocol_api/core/engine/_default_liquid_class_versions.py +56 -0
- opentrons/protocol_api/core/engine/instrument.py +143 -18
- opentrons/protocol_api/core/engine/pipette_movement_conflict.py +77 -17
- opentrons/protocol_api/core/engine/protocol.py +53 -7
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +1 -1
- opentrons/protocol_api/core/protocol.py +1 -1
- opentrons/protocol_api/labware.py +36 -2
- opentrons/protocol_api/module_contexts.py +146 -14
- opentrons/protocol_api/protocol_context.py +162 -12
- opentrons/protocol_api/validation.py +4 -0
- opentrons/protocol_engine/commands/command_unions.py +2 -0
- opentrons/protocol_engine/commands/flex_stacker/common.py +13 -0
- opentrons/protocol_engine/commands/flex_stacker/store.py +20 -2
- opentrons/protocol_engine/execution/labware_movement.py +14 -12
- opentrons/protocol_engine/resources/pipette_data_provider.py +3 -0
- opentrons/protocol_engine/state/geometry.py +33 -5
- opentrons/protocol_engine/state/labware.py +66 -0
- opentrons/protocol_engine/state/modules.py +6 -0
- opentrons/protocol_engine/state/pipettes.py +12 -3
- opentrons/protocol_engine/types/__init__.py +2 -0
- opentrons/protocol_engine/types/labware.py +9 -0
- opentrons/protocols/api_support/definitions.py +1 -1
- {opentrons-8.6.0a12.dist-info → opentrons-8.7.0.dist-info}/METADATA +4 -4
- {opentrons-8.6.0a12.dist-info → opentrons-8.7.0.dist-info}/RECORD +38 -37
- {opentrons-8.6.0a12.dist-info → opentrons-8.7.0.dist-info}/WHEEL +0 -0
- {opentrons-8.6.0a12.dist-info → opentrons-8.7.0.dist-info}/entry_points.txt +0 -0
- {opentrons-8.6.0a12.dist-info → opentrons-8.7.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -21,7 +21,11 @@ from opentrons.protocol_engine import (
|
|
|
21
21
|
OnLabwareLocation,
|
|
22
22
|
DropTipWellLocation,
|
|
23
23
|
)
|
|
24
|
-
from opentrons.protocol_engine.types import
|
|
24
|
+
from opentrons.protocol_engine.types import (
|
|
25
|
+
StagingSlotLocation,
|
|
26
|
+
WellLocationType,
|
|
27
|
+
LoadedModule,
|
|
28
|
+
)
|
|
25
29
|
from opentrons.types import DeckSlotName, StagingSlotName, Point
|
|
26
30
|
from . import point_calculations
|
|
27
31
|
|
|
@@ -136,22 +140,47 @@ def check_safe_for_pipette_movement( # noqa: C901
|
|
|
136
140
|
f" will result in collision with thermocycler lid in deck slot A1."
|
|
137
141
|
)
|
|
138
142
|
|
|
143
|
+
def _check_for_column_4_module_collision(slot: DeckSlotName) -> None:
|
|
144
|
+
slot_module = engine_state.modules.get_by_slot(slot)
|
|
145
|
+
if (
|
|
146
|
+
slot_module
|
|
147
|
+
and engine_state.modules.is_column_4_module(slot_module.model)
|
|
148
|
+
and _slot_has_potential_colliding_object(
|
|
149
|
+
engine_state=engine_state,
|
|
150
|
+
pipette_bounds=pipette_bounds_at_well_location,
|
|
151
|
+
surrounding_location=slot_module,
|
|
152
|
+
)
|
|
153
|
+
):
|
|
154
|
+
raise PartialTipMovementNotAllowedError(
|
|
155
|
+
f"Moving to {engine_state.labware.get_display_name(labware_id)} in slot"
|
|
156
|
+
f" {slot} with {primary_nozzle} nozzle partial configuration will"
|
|
157
|
+
f" result in collision with items on {slot_module.model} mounted in {slot}."
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
# We check the labware slot for a module that is mounted in the same cutout
|
|
161
|
+
# as the labwares slot but does not occupy the same heirarchy (like the stacker).
|
|
162
|
+
_check_for_column_4_module_collision(labware_slot)
|
|
163
|
+
|
|
139
164
|
for regular_slot in surrounding_slots.regular_slots:
|
|
140
165
|
if _slot_has_potential_colliding_object(
|
|
141
166
|
engine_state=engine_state,
|
|
142
167
|
pipette_bounds=pipette_bounds_at_well_location,
|
|
143
|
-
|
|
168
|
+
surrounding_location=regular_slot,
|
|
144
169
|
):
|
|
145
170
|
raise PartialTipMovementNotAllowedError(
|
|
146
171
|
f"Moving to {engine_state.labware.get_display_name(labware_id)} in slot"
|
|
147
172
|
f" {labware_slot} with {primary_nozzle} nozzle partial configuration"
|
|
148
173
|
f" will result in collision with items in deck slot {regular_slot}."
|
|
149
174
|
)
|
|
175
|
+
|
|
176
|
+
# Check for Column 4 Modules that may be descendants of a given surrounding slot
|
|
177
|
+
_check_for_column_4_module_collision(regular_slot)
|
|
178
|
+
|
|
150
179
|
for staging_slot in surrounding_slots.staging_slots:
|
|
151
180
|
if _slot_has_potential_colliding_object(
|
|
152
181
|
engine_state=engine_state,
|
|
153
182
|
pipette_bounds=pipette_bounds_at_well_location,
|
|
154
|
-
|
|
183
|
+
surrounding_location=staging_slot,
|
|
155
184
|
):
|
|
156
185
|
raise PartialTipMovementNotAllowedError(
|
|
157
186
|
f"Moving to {engine_state.labware.get_display_name(labware_id)} in slot"
|
|
@@ -178,18 +207,45 @@ def _get_critical_point_to_use(
|
|
|
178
207
|
def _slot_has_potential_colliding_object(
|
|
179
208
|
engine_state: StateView,
|
|
180
209
|
pipette_bounds: Tuple[Point, Point, Point, Point],
|
|
181
|
-
|
|
210
|
+
surrounding_location: Union[DeckSlotName, StagingSlotName, LoadedModule],
|
|
182
211
|
) -> bool:
|
|
183
|
-
"""Return the slot, if any, that has an item that the pipette might collide into.
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
212
|
+
"""Return the slot, if any, that has an item that the pipette might collide into.
|
|
213
|
+
Can be provided a Deck Slot, Staging Slot, or Column 4 Module.
|
|
214
|
+
"""
|
|
215
|
+
if isinstance(surrounding_location, LoadedModule):
|
|
216
|
+
if (
|
|
217
|
+
engine_state.modules.is_column_4_module(surrounding_location.model)
|
|
218
|
+
and surrounding_location.location is not None
|
|
219
|
+
):
|
|
220
|
+
module_area = (
|
|
221
|
+
engine_state.modules.ensure_and_convert_module_fixture_location(
|
|
222
|
+
surrounding_location.location.slotName, surrounding_location.model
|
|
223
|
+
)
|
|
224
|
+
)
|
|
225
|
+
slot_pos = engine_state.addressable_areas.get_addressable_area_position(
|
|
226
|
+
addressable_area_name=module_area,
|
|
227
|
+
do_compatibility_check=False,
|
|
228
|
+
)
|
|
229
|
+
slot_bounds = (
|
|
230
|
+
engine_state.addressable_areas.get_addressable_area_bounding_box(
|
|
231
|
+
addressable_area_name=module_area,
|
|
232
|
+
do_compatibility_check=False,
|
|
233
|
+
)
|
|
234
|
+
)
|
|
235
|
+
else:
|
|
236
|
+
raise ValueError(
|
|
237
|
+
f"Error during collision validation, Module {surrounding_location.model} must be in Column 4."
|
|
238
|
+
)
|
|
239
|
+
else:
|
|
240
|
+
# Check if slot overlaps with pipette position
|
|
241
|
+
slot_pos = engine_state.addressable_areas.get_addressable_area_position(
|
|
242
|
+
addressable_area_name=surrounding_location.id,
|
|
243
|
+
do_compatibility_check=False,
|
|
244
|
+
)
|
|
245
|
+
slot_bounds = engine_state.addressable_areas.get_addressable_area_bounding_box(
|
|
246
|
+
addressable_area_name=surrounding_location.id,
|
|
247
|
+
do_compatibility_check=False,
|
|
248
|
+
)
|
|
193
249
|
slot_back_left_coords = Point(slot_pos.x, slot_pos.y + slot_bounds.y, slot_pos.z)
|
|
194
250
|
slot_front_right_coords = Point(slot_pos.x + slot_bounds.x, slot_pos.y, slot_pos.z)
|
|
195
251
|
|
|
@@ -199,13 +255,17 @@ def _slot_has_potential_colliding_object(
|
|
|
199
255
|
rectangle2=(slot_back_left_coords, slot_front_right_coords),
|
|
200
256
|
):
|
|
201
257
|
# Check z-height of items in overlapping slot
|
|
202
|
-
if isinstance(
|
|
258
|
+
if isinstance(surrounding_location, DeckSlotName):
|
|
203
259
|
slot_highest_z = engine_state.geometry.get_highest_z_in_slot(
|
|
204
|
-
DeckSlotLocation(slotName=
|
|
260
|
+
DeckSlotLocation(slotName=surrounding_location)
|
|
261
|
+
)
|
|
262
|
+
elif isinstance(surrounding_location, LoadedModule):
|
|
263
|
+
slot_highest_z = engine_state.geometry.get_highest_z_of_column_4_module(
|
|
264
|
+
surrounding_location
|
|
205
265
|
)
|
|
206
266
|
else:
|
|
207
267
|
slot_highest_z = engine_state.geometry.get_highest_z_in_slot(
|
|
208
|
-
StagingSlotLocation(slotName=
|
|
268
|
+
StagingSlotLocation(slotName=surrounding_location)
|
|
209
269
|
)
|
|
210
270
|
return slot_highest_z >= pipette_bounds[0].z
|
|
211
271
|
return False
|
|
@@ -78,7 +78,12 @@ from .module_core import (
|
|
|
78
78
|
FlexStackerCore,
|
|
79
79
|
)
|
|
80
80
|
from .exceptions import InvalidModuleLocationError
|
|
81
|
-
from . import
|
|
81
|
+
from . import (
|
|
82
|
+
load_labware_params,
|
|
83
|
+
deck_conflict,
|
|
84
|
+
overlap_versions,
|
|
85
|
+
_default_liquid_class_versions,
|
|
86
|
+
)
|
|
82
87
|
from opentrons.protocol_engine.resources import labware_validation
|
|
83
88
|
|
|
84
89
|
if TYPE_CHECKING:
|
|
@@ -492,13 +497,28 @@ class ProtocolCore(
|
|
|
492
497
|
)
|
|
493
498
|
# if this is a labware with a lid, we just need to find its lid_id
|
|
494
499
|
else:
|
|
495
|
-
|
|
496
|
-
|
|
500
|
+
# we need to check to see if this labware is hosting a lid stack
|
|
501
|
+
potential_lid_stack = (
|
|
502
|
+
self._engine_client.state.labware.get_next_child_labware(
|
|
503
|
+
labware.labware_id
|
|
504
|
+
)
|
|
497
505
|
)
|
|
498
|
-
if
|
|
499
|
-
|
|
506
|
+
if potential_lid_stack and labware_validation.is_lid_stack(
|
|
507
|
+
self._engine_client.state.labware.get_load_name(potential_lid_stack)
|
|
508
|
+
):
|
|
509
|
+
lid_id = self._engine_client.state.labware.get_highest_child_labware(
|
|
510
|
+
labware.labware_id
|
|
511
|
+
)
|
|
500
512
|
else:
|
|
501
|
-
|
|
513
|
+
lid = self._engine_client.state.labware.get_lid_by_labware_id(
|
|
514
|
+
labware.labware_id
|
|
515
|
+
)
|
|
516
|
+
if lid is not None:
|
|
517
|
+
lid_id = lid.id
|
|
518
|
+
else:
|
|
519
|
+
raise ValueError(
|
|
520
|
+
f"Cannot move a lid off of {labware.get_display_name()} because it has no lid."
|
|
521
|
+
)
|
|
502
522
|
|
|
503
523
|
_pick_up_offset = (
|
|
504
524
|
LabwareOffsetVector(
|
|
@@ -602,6 +622,9 @@ class ProtocolCore(
|
|
|
602
622
|
)
|
|
603
623
|
|
|
604
624
|
# Handle leftover empty lid stack if there is one
|
|
625
|
+
potential_lid_stack = self._engine_client.state.labware.get_next_child_labware(
|
|
626
|
+
labware.labware_id
|
|
627
|
+
)
|
|
605
628
|
if (
|
|
606
629
|
labware_validation.is_lid_stack(labware.load_name)
|
|
607
630
|
and self._engine_client.state.labware.get_highest_child_labware(
|
|
@@ -619,6 +642,25 @@ class ProtocolCore(
|
|
|
619
642
|
dropOffset=None,
|
|
620
643
|
)
|
|
621
644
|
)
|
|
645
|
+
elif (
|
|
646
|
+
potential_lid_stack
|
|
647
|
+
and labware_validation.is_lid_stack(
|
|
648
|
+
self._engine_client.state.labware.get_load_name(potential_lid_stack)
|
|
649
|
+
)
|
|
650
|
+
and self._engine_client.state.labware.get_highest_child_labware(
|
|
651
|
+
potential_lid_stack
|
|
652
|
+
)
|
|
653
|
+
== potential_lid_stack
|
|
654
|
+
):
|
|
655
|
+
self._engine_client.execute_command(
|
|
656
|
+
cmd.MoveLabwareParams(
|
|
657
|
+
labwareId=potential_lid_stack,
|
|
658
|
+
newLocation=SYSTEM_LOCATION,
|
|
659
|
+
strategy=LabwareMovementStrategy.MANUAL_MOVE_WITHOUT_PAUSE,
|
|
660
|
+
pickUpOffset=None,
|
|
661
|
+
dropOffset=None,
|
|
662
|
+
)
|
|
663
|
+
)
|
|
622
664
|
|
|
623
665
|
if strategy == LabwareMovementStrategy.USING_GRIPPER:
|
|
624
666
|
# Clear out last location since it is not relevant to pipetting
|
|
@@ -1068,8 +1110,12 @@ class ProtocolCore(
|
|
|
1068
1110
|
display_color=(liquid.displayColor.root if liquid.displayColor else None),
|
|
1069
1111
|
)
|
|
1070
1112
|
|
|
1071
|
-
def get_liquid_class(self, name: str, version: int) -> LiquidClass:
|
|
1113
|
+
def get_liquid_class(self, name: str, version: Optional[int]) -> LiquidClass:
|
|
1072
1114
|
"""Get an instance of a built-in liquid class."""
|
|
1115
|
+
if version is None:
|
|
1116
|
+
version = _default_liquid_class_versions.get_liquid_class_version(
|
|
1117
|
+
self._api_version, name
|
|
1118
|
+
)
|
|
1073
1119
|
try:
|
|
1074
1120
|
# Check if we have already loaded this liquid class' definition
|
|
1075
1121
|
liquid_class_def = self._liquid_class_def_cache[(name, version)]
|
|
@@ -599,7 +599,7 @@ class LegacyProtocolCore(
|
|
|
599
599
|
"""Define a liquid to load into a well."""
|
|
600
600
|
assert False, "define_liquid only supported on engine core"
|
|
601
601
|
|
|
602
|
-
def get_liquid_class(self, name: str, version: int) -> LiquidClass:
|
|
602
|
+
def get_liquid_class(self, name: str, version: Optional[int]) -> LiquidClass:
|
|
603
603
|
"""Get an instance of a built-in liquid class."""
|
|
604
604
|
assert False, "define_liquid_class is only supported on engine core"
|
|
605
605
|
|
|
@@ -297,7 +297,7 @@ class AbstractProtocol(
|
|
|
297
297
|
"""Define a liquid to load into a well."""
|
|
298
298
|
|
|
299
299
|
@abstractmethod
|
|
300
|
-
def get_liquid_class(self, name: str, version: int) -> LiquidClass:
|
|
300
|
+
def get_liquid_class(self, name: str, version: Optional[int]) -> LiquidClass:
|
|
301
301
|
"""Get an instance of a built-in liquid class."""
|
|
302
302
|
|
|
303
303
|
@abstractmethod
|
|
@@ -640,6 +640,9 @@ class Labware:
|
|
|
640
640
|
lid: Optional[str] = None,
|
|
641
641
|
namespace: Optional[str] = None,
|
|
642
642
|
version: Optional[int] = None,
|
|
643
|
+
*,
|
|
644
|
+
lid_namespace: Optional[str] = None,
|
|
645
|
+
lid_version: Optional[int] = None,
|
|
643
646
|
) -> Labware:
|
|
644
647
|
"""Load a compatible labware onto the labware using its load parameters.
|
|
645
648
|
|
|
@@ -650,6 +653,24 @@ class Labware:
|
|
|
650
653
|
|
|
651
654
|
:returns: The initialized and loaded labware object.
|
|
652
655
|
"""
|
|
656
|
+
if self._api_version < validation.NAMESPACE_VERSION_ADAPTER_LID_VERSION_GATE:
|
|
657
|
+
if lid_namespace is not None:
|
|
658
|
+
raise APIVersionError(
|
|
659
|
+
api_element="The `lid_namespace` parameter",
|
|
660
|
+
until_version=str(
|
|
661
|
+
validation.NAMESPACE_VERSION_ADAPTER_LID_VERSION_GATE
|
|
662
|
+
),
|
|
663
|
+
current_version=str(self._api_version),
|
|
664
|
+
)
|
|
665
|
+
if lid_version is not None:
|
|
666
|
+
raise APIVersionError(
|
|
667
|
+
api_element="The `lid_version` parameter",
|
|
668
|
+
until_version=str(
|
|
669
|
+
validation.NAMESPACE_VERSION_ADAPTER_LID_VERSION_GATE
|
|
670
|
+
),
|
|
671
|
+
current_version=str(self._api_version),
|
|
672
|
+
)
|
|
673
|
+
|
|
653
674
|
labware_core = self._protocol_core.load_labware(
|
|
654
675
|
load_name=name,
|
|
655
676
|
label=label,
|
|
@@ -674,11 +695,24 @@ class Labware:
|
|
|
674
695
|
until_version="2.23",
|
|
675
696
|
current_version=f"{self._api_version}",
|
|
676
697
|
)
|
|
698
|
+
if (
|
|
699
|
+
self._api_version
|
|
700
|
+
< validation.NAMESPACE_VERSION_ADAPTER_LID_VERSION_GATE
|
|
701
|
+
):
|
|
702
|
+
checked_lid_namespace = namespace
|
|
703
|
+
checked_lid_version = version
|
|
704
|
+
else:
|
|
705
|
+
# This is currently impossible to reach because of the
|
|
706
|
+
# `if self._api_version < validation.validation.LID_STACK_VERSION_GATE`
|
|
707
|
+
# check above. This is here for now in case that check is removed in
|
|
708
|
+
# the future, and for symmetry with the other labware load methods.
|
|
709
|
+
checked_lid_namespace = lid_namespace
|
|
710
|
+
checked_lid_version = lid_version
|
|
677
711
|
self._protocol_core.load_lid(
|
|
678
712
|
load_name=lid,
|
|
679
713
|
location=labware_core,
|
|
680
|
-
namespace=
|
|
681
|
-
version=
|
|
714
|
+
namespace=checked_lid_namespace,
|
|
715
|
+
version=checked_lid_version,
|
|
682
716
|
)
|
|
683
717
|
|
|
684
718
|
return labware
|
|
@@ -123,7 +123,7 @@ class ModuleContext(CommandPublisher):
|
|
|
123
123
|
|
|
124
124
|
return core.geometry.add_labware(labware)
|
|
125
125
|
|
|
126
|
-
def load_labware(
|
|
126
|
+
def load_labware( # noqa: C901
|
|
127
127
|
self,
|
|
128
128
|
name: str,
|
|
129
129
|
label: Optional[str] = None,
|
|
@@ -131,6 +131,11 @@ class ModuleContext(CommandPublisher):
|
|
|
131
131
|
version: Optional[int] = None,
|
|
132
132
|
adapter: Optional[str] = None,
|
|
133
133
|
lid: Optional[str] = None,
|
|
134
|
+
*,
|
|
135
|
+
adapter_namespace: Optional[str] = None,
|
|
136
|
+
adapter_version: Optional[int] = None,
|
|
137
|
+
lid_namespace: Optional[str] = None,
|
|
138
|
+
lid_version: Optional[int] = None,
|
|
134
139
|
) -> Labware:
|
|
135
140
|
"""Load a labware onto the module using its load parameters.
|
|
136
141
|
|
|
@@ -142,7 +147,11 @@ class ModuleContext(CommandPublisher):
|
|
|
142
147
|
:returns: The initialized and loaded labware object.
|
|
143
148
|
|
|
144
149
|
.. versionadded:: 2.1
|
|
145
|
-
The
|
|
150
|
+
The ``label``, ``namespace``, and ``version`` parameters.
|
|
151
|
+
|
|
152
|
+
.. versionadded:: 2.26
|
|
153
|
+
The ``adapter_namespace``, ``adapter_version``,
|
|
154
|
+
``lid_namespace``, and ``lid_version`` parameters.
|
|
146
155
|
"""
|
|
147
156
|
if self._api_version < APIVersion(2, 1) and (
|
|
148
157
|
label is not None or namespace is not None or version != 1
|
|
@@ -152,6 +161,40 @@ class ModuleContext(CommandPublisher):
|
|
|
152
161
|
"are trying to utilize new load_labware parameters in 2.1"
|
|
153
162
|
)
|
|
154
163
|
|
|
164
|
+
if self._api_version < validation.NAMESPACE_VERSION_ADAPTER_LID_VERSION_GATE:
|
|
165
|
+
if adapter_namespace is not None:
|
|
166
|
+
raise APIVersionError(
|
|
167
|
+
api_element="The `adapter_namespace` parameter",
|
|
168
|
+
until_version=str(
|
|
169
|
+
validation.NAMESPACE_VERSION_ADAPTER_LID_VERSION_GATE
|
|
170
|
+
),
|
|
171
|
+
current_version=str(self._api_version),
|
|
172
|
+
)
|
|
173
|
+
if adapter_version is not None:
|
|
174
|
+
raise APIVersionError(
|
|
175
|
+
api_element="The `adapter_version` parameter",
|
|
176
|
+
until_version=str(
|
|
177
|
+
validation.NAMESPACE_VERSION_ADAPTER_LID_VERSION_GATE
|
|
178
|
+
),
|
|
179
|
+
current_version=str(self._api_version),
|
|
180
|
+
)
|
|
181
|
+
if lid_namespace is not None:
|
|
182
|
+
raise APIVersionError(
|
|
183
|
+
api_element="The `lid_namespace` parameter",
|
|
184
|
+
until_version=str(
|
|
185
|
+
validation.NAMESPACE_VERSION_ADAPTER_LID_VERSION_GATE
|
|
186
|
+
),
|
|
187
|
+
current_version=str(self._api_version),
|
|
188
|
+
)
|
|
189
|
+
if lid_version is not None:
|
|
190
|
+
raise APIVersionError(
|
|
191
|
+
api_element="The `lid_version` parameter",
|
|
192
|
+
until_version=str(
|
|
193
|
+
validation.NAMESPACE_VERSION_ADAPTER_LID_VERSION_GATE
|
|
194
|
+
),
|
|
195
|
+
current_version=str(self._api_version),
|
|
196
|
+
)
|
|
197
|
+
|
|
155
198
|
load_location: Union[ModuleCore, LabwareCore]
|
|
156
199
|
if adapter is not None:
|
|
157
200
|
if self._api_version < APIVersion(2, 15):
|
|
@@ -160,9 +203,21 @@ class ModuleContext(CommandPublisher):
|
|
|
160
203
|
until_version="2.15",
|
|
161
204
|
current_version=f"{self._api_version}",
|
|
162
205
|
)
|
|
206
|
+
|
|
207
|
+
if (
|
|
208
|
+
self._api_version
|
|
209
|
+
< validation.NAMESPACE_VERSION_ADAPTER_LID_VERSION_GATE
|
|
210
|
+
):
|
|
211
|
+
checked_adapter_namespace = namespace
|
|
212
|
+
checked_adapter_version = None
|
|
213
|
+
else:
|
|
214
|
+
checked_adapter_namespace = adapter_namespace
|
|
215
|
+
checked_adapter_version = adapter_version
|
|
216
|
+
|
|
163
217
|
loaded_adapter = self.load_adapter(
|
|
164
218
|
name=adapter,
|
|
165
|
-
namespace=
|
|
219
|
+
namespace=checked_adapter_namespace,
|
|
220
|
+
version=checked_adapter_version,
|
|
166
221
|
)
|
|
167
222
|
load_location = loaded_adapter._core
|
|
168
223
|
else:
|
|
@@ -193,11 +248,22 @@ class ModuleContext(CommandPublisher):
|
|
|
193
248
|
until_version="2.23",
|
|
194
249
|
current_version=f"{self._api_version}",
|
|
195
250
|
)
|
|
251
|
+
|
|
252
|
+
if (
|
|
253
|
+
self._api_version
|
|
254
|
+
< validation.NAMESPACE_VERSION_ADAPTER_LID_VERSION_GATE
|
|
255
|
+
):
|
|
256
|
+
checked_lid_namespace = namespace
|
|
257
|
+
checked_lid_version = None
|
|
258
|
+
else:
|
|
259
|
+
checked_lid_namespace = lid_namespace
|
|
260
|
+
checked_lid_version = lid_version
|
|
261
|
+
|
|
196
262
|
self._protocol_core.load_lid(
|
|
197
263
|
load_name=lid,
|
|
198
264
|
location=labware_core,
|
|
199
|
-
namespace=
|
|
200
|
-
version=
|
|
265
|
+
namespace=checked_lid_namespace,
|
|
266
|
+
version=checked_lid_version,
|
|
201
267
|
)
|
|
202
268
|
|
|
203
269
|
if isinstance(self._core, LegacyModuleCore):
|
|
@@ -1272,7 +1338,7 @@ class FlexStackerContext(ModuleContext):
|
|
|
1272
1338
|
def set_stored_labware_items(
|
|
1273
1339
|
self,
|
|
1274
1340
|
labware: list[Labware],
|
|
1275
|
-
stacking_offset_z: float | None,
|
|
1341
|
+
stacking_offset_z: float | None = None,
|
|
1276
1342
|
) -> None:
|
|
1277
1343
|
"""Configure the labware the Flex Stacker will store during a protocol by providing an initial list of stored labware objects. The start of the list represents the bottom of the Stacker,
|
|
1278
1344
|
and the end of the list represents the top of the Stacker.
|
|
@@ -1330,6 +1396,11 @@ class FlexStackerContext(ModuleContext):
|
|
|
1330
1396
|
lid: str | None = None,
|
|
1331
1397
|
count: int | None = None,
|
|
1332
1398
|
stacking_offset_z: float | None = None,
|
|
1399
|
+
*,
|
|
1400
|
+
adapter_namespace: str | None = None,
|
|
1401
|
+
adapter_version: int | None = None,
|
|
1402
|
+
lid_namespace: str | None = None,
|
|
1403
|
+
lid_version: int | None = None,
|
|
1333
1404
|
) -> None:
|
|
1334
1405
|
"""Configure the type and starting quantity of labware the Flex Stacker will store during a protocol. This is the only type of labware you'll be able to store in the Stacker until it's reconfigured.
|
|
1335
1406
|
|
|
@@ -1338,6 +1409,7 @@ class FlexStackerContext(ModuleContext):
|
|
|
1338
1409
|
:param str load_name: A string to use for looking up a labware definition.
|
|
1339
1410
|
You can find the ``load_name`` for any Opentrons-verified labware on the
|
|
1340
1411
|
`Labware Library <https://labware.opentrons.com>`__.
|
|
1412
|
+
|
|
1341
1413
|
:param str namespace: The namespace that the labware definition belongs to.
|
|
1342
1414
|
If unspecified, the API will automatically search two namespaces:
|
|
1343
1415
|
|
|
@@ -1348,19 +1420,34 @@ class FlexStackerContext(ModuleContext):
|
|
|
1348
1420
|
You might need to specify an explicit ``namespace`` if you have a custom
|
|
1349
1421
|
definition whose ``load_name`` is the same as an Opentrons-verified
|
|
1350
1422
|
definition, and you want to explicitly choose one or the other.
|
|
1423
|
+
|
|
1351
1424
|
:param version: The version of the labware definition. You should normally
|
|
1352
1425
|
leave this unspecified to let the method choose a version
|
|
1353
1426
|
automatically.
|
|
1427
|
+
|
|
1354
1428
|
:param adapter: An adapter to load the labware on top of. Accepts the same
|
|
1355
|
-
values as the ``load_name`` parameter of :py:meth:`.load_adapter`.
|
|
1356
|
-
|
|
1357
|
-
|
|
1429
|
+
values as the ``load_name`` parameter of :py:meth:`.load_adapter`.
|
|
1430
|
+
|
|
1431
|
+
:param adapter_namespace: Applies to ``adapter`` the same way that ``namespace``
|
|
1432
|
+
applies to ``load_name``.
|
|
1433
|
+
|
|
1434
|
+
:param adapter_version: Applies to ``adapter`` the same way that ``version``
|
|
1435
|
+
applies to ``load_name``.
|
|
1436
|
+
|
|
1358
1437
|
:param lid: A lid to load the on top of the main labware. Accepts the same
|
|
1359
1438
|
values as the ``load_name`` parameter of :py:meth:`~.ProtocolContext.load_lid_stack`. The
|
|
1360
1439
|
lid will use the same namespace as the labware, and the API will
|
|
1361
1440
|
choose the lid's version automatically.
|
|
1441
|
+
|
|
1442
|
+
:param lid_namespace: Applies to ``lid`` the same way that ``namespace``
|
|
1443
|
+
applies to ``load_name``.
|
|
1444
|
+
|
|
1445
|
+
:param lid_version: Applies to ``lid`` the same way that ``version``
|
|
1446
|
+
applies to ``load_name``.
|
|
1447
|
+
|
|
1362
1448
|
:param count: The number of labware that the Flex Stacker should store. If not specified, this will be the maximum amount of this kind of
|
|
1363
1449
|
labware that the Flex Stacker is capable of storing.
|
|
1450
|
+
|
|
1364
1451
|
:param stacking_offset_z: Stacking ``z`` offset in mm of stored labware. If specified, this overrides the
|
|
1365
1452
|
calculated value in the labware definition.
|
|
1366
1453
|
|
|
@@ -1378,18 +1465,63 @@ class FlexStackerContext(ModuleContext):
|
|
|
1378
1465
|
- Labware on adapter: the adapter (bottom side) of the upper labware unit overlaps with the top side of the labware below.
|
|
1379
1466
|
- Labware with lid: the labware (bottom side) of the upper labware unit overlaps with the lid (top side) of the unit below.
|
|
1380
1467
|
- Labware with lid and adapter: the adapter (bottom side) of the upper labware unit overlaps with the lid (top side) of the unit below.
|
|
1381
|
-
|
|
1382
1468
|
"""
|
|
1469
|
+
|
|
1470
|
+
if self._api_version < validation.NAMESPACE_VERSION_ADAPTER_LID_VERSION_GATE:
|
|
1471
|
+
if adapter_namespace is not None:
|
|
1472
|
+
raise APIVersionError(
|
|
1473
|
+
api_element="The `adapter_namespace` parameter",
|
|
1474
|
+
until_version=str(
|
|
1475
|
+
validation.NAMESPACE_VERSION_ADAPTER_LID_VERSION_GATE
|
|
1476
|
+
),
|
|
1477
|
+
current_version=str(self._api_version),
|
|
1478
|
+
)
|
|
1479
|
+
if adapter_version is not None:
|
|
1480
|
+
raise APIVersionError(
|
|
1481
|
+
api_element="The `adapter_version` parameter",
|
|
1482
|
+
until_version=str(
|
|
1483
|
+
validation.NAMESPACE_VERSION_ADAPTER_LID_VERSION_GATE
|
|
1484
|
+
),
|
|
1485
|
+
current_version=str(self._api_version),
|
|
1486
|
+
)
|
|
1487
|
+
if lid_namespace is not None:
|
|
1488
|
+
raise APIVersionError(
|
|
1489
|
+
api_element="The `lid_namespace` parameter",
|
|
1490
|
+
until_version=str(
|
|
1491
|
+
validation.NAMESPACE_VERSION_ADAPTER_LID_VERSION_GATE
|
|
1492
|
+
),
|
|
1493
|
+
current_version=str(self._api_version),
|
|
1494
|
+
)
|
|
1495
|
+
if lid_version is not None:
|
|
1496
|
+
raise APIVersionError(
|
|
1497
|
+
api_element="The `lid_version` parameter",
|
|
1498
|
+
until_version=str(
|
|
1499
|
+
validation.NAMESPACE_VERSION_ADAPTER_LID_VERSION_GATE
|
|
1500
|
+
),
|
|
1501
|
+
current_version=str(self._api_version),
|
|
1502
|
+
)
|
|
1503
|
+
|
|
1504
|
+
if self._api_version < validation.NAMESPACE_VERSION_ADAPTER_LID_VERSION_GATE:
|
|
1505
|
+
checked_adapter_namespace = namespace
|
|
1506
|
+
checked_adapter_version = version
|
|
1507
|
+
checked_lid_namespace = namespace
|
|
1508
|
+
checked_lid_version = version
|
|
1509
|
+
else:
|
|
1510
|
+
checked_adapter_namespace = adapter_namespace
|
|
1511
|
+
checked_adapter_version = adapter_version
|
|
1512
|
+
checked_lid_namespace = lid_namespace
|
|
1513
|
+
checked_lid_version = lid_version
|
|
1514
|
+
|
|
1383
1515
|
self._core.set_stored_labware(
|
|
1384
1516
|
main_load_name=load_name,
|
|
1385
1517
|
main_namespace=namespace,
|
|
1386
1518
|
main_version=version,
|
|
1387
1519
|
lid_load_name=lid,
|
|
1388
|
-
lid_namespace=
|
|
1389
|
-
lid_version=
|
|
1520
|
+
lid_namespace=checked_lid_namespace,
|
|
1521
|
+
lid_version=checked_lid_version,
|
|
1390
1522
|
adapter_load_name=adapter,
|
|
1391
|
-
adapter_namespace=
|
|
1392
|
-
adapter_version=
|
|
1523
|
+
adapter_namespace=checked_adapter_namespace,
|
|
1524
|
+
adapter_version=checked_adapter_version,
|
|
1393
1525
|
count=count,
|
|
1394
1526
|
stacking_offset_z=stacking_offset_z,
|
|
1395
1527
|
)
|