opentrons 8.4.1a1__py2.py3-none-any.whl → 8.5.0__py2.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/config/defaults_ot3.py +1 -1
- opentrons/hardware_control/backends/flex_protocol.py +25 -0
- opentrons/hardware_control/backends/ot3controller.py +76 -1
- opentrons/hardware_control/backends/ot3simulator.py +27 -0
- opentrons/hardware_control/instruments/ot3/pipette_handler.py +1 -0
- opentrons/hardware_control/ot3api.py +32 -0
- opentrons/legacy_commands/commands.py +16 -4
- opentrons/legacy_commands/robot_commands.py +51 -0
- opentrons/legacy_commands/types.py +91 -2
- opentrons/protocol_api/_liquid.py +60 -15
- opentrons/protocol_api/_liquid_properties.py +149 -90
- opentrons/protocol_api/_transfer_liquid_validation.py +43 -14
- opentrons/protocol_api/core/engine/instrument.py +367 -221
- opentrons/protocol_api/core/engine/protocol.py +14 -15
- opentrons/protocol_api/core/engine/robot.py +2 -2
- opentrons/protocol_api/core/engine/transfer_components_executor.py +275 -163
- opentrons/protocol_api/core/engine/well.py +16 -0
- opentrons/protocol_api/core/instrument.py +11 -5
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +11 -5
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +2 -2
- opentrons/protocol_api/core/legacy/legacy_well_core.py +8 -0
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +11 -5
- opentrons/protocol_api/core/protocol.py +3 -3
- opentrons/protocol_api/core/well.py +8 -0
- opentrons/protocol_api/instrument_context.py +478 -111
- opentrons/protocol_api/labware.py +10 -0
- opentrons/protocol_api/module_contexts.py +5 -2
- opentrons/protocol_api/protocol_context.py +76 -11
- opentrons/protocol_api/robot_context.py +48 -6
- opentrons/protocol_api/validation.py +15 -8
- opentrons/protocol_engine/commands/command_unions.py +10 -10
- opentrons/protocol_engine/commands/generate_command_schema.py +1 -1
- opentrons/protocol_engine/commands/get_next_tip.py +2 -2
- opentrons/protocol_engine/commands/load_labware.py +0 -19
- opentrons/protocol_engine/commands/pick_up_tip.py +9 -3
- opentrons/protocol_engine/commands/robot/__init__.py +20 -20
- opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +34 -24
- opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +29 -20
- opentrons/protocol_engine/commands/seal_pipette_to_tip.py +1 -1
- opentrons/protocol_engine/commands/unsafe/__init__.py +17 -1
- opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +1 -2
- opentrons/protocol_engine/execution/labware_movement.py +9 -2
- opentrons/protocol_engine/execution/movement.py +12 -9
- opentrons/protocol_engine/execution/queue_worker.py +8 -1
- opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +52 -19
- opentrons/protocol_engine/resources/labware_validation.py +7 -1
- opentrons/protocol_engine/state/_well_math.py +2 -2
- opentrons/protocol_engine/state/commands.py +14 -28
- opentrons/protocol_engine/state/frustum_helpers.py +11 -7
- opentrons/protocol_engine/state/labware.py +12 -0
- opentrons/protocol_engine/state/modules.py +1 -1
- opentrons/protocol_engine/state/pipettes.py +8 -0
- opentrons/protocol_engine/state/tips.py +46 -83
- opentrons/protocol_engine/state/update_types.py +8 -23
- opentrons/protocol_engine/types/liquid_level_detection.py +68 -8
- opentrons/protocol_runner/legacy_command_mapper.py +12 -6
- opentrons/protocol_runner/run_orchestrator.py +1 -1
- opentrons/protocols/advanced_control/transfers/common.py +54 -11
- opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +55 -28
- opentrons/protocols/api_support/definitions.py +1 -1
- opentrons/types.py +6 -6
- {opentrons-8.4.1a1.dist-info → opentrons-8.5.0.dist-info}/METADATA +4 -4
- {opentrons-8.4.1a1.dist-info → opentrons-8.5.0.dist-info}/RECORD +67 -66
- {opentrons-8.4.1a1.dist-info → opentrons-8.5.0.dist-info}/LICENSE +0 -0
- {opentrons-8.4.1a1.dist-info → opentrons-8.5.0.dist-info}/WHEEL +0 -0
- {opentrons-8.4.1a1.dist-info → opentrons-8.5.0.dist-info}/entry_points.txt +0 -0
- {opentrons-8.4.1a1.dist-info → opentrons-8.5.0.dist-info}/top_level.txt +0 -0
|
@@ -346,6 +346,16 @@ class Well:
|
|
|
346
346
|
"""Get the current liquid volume in a well."""
|
|
347
347
|
return self._core.get_liquid_volume()
|
|
348
348
|
|
|
349
|
+
@requires_version(2, 24)
|
|
350
|
+
def volume_from_height(self, height: LiquidTrackingType) -> LiquidTrackingType:
|
|
351
|
+
"""Return the volume contained in a well at any height."""
|
|
352
|
+
return self._core.volume_from_height(height)
|
|
353
|
+
|
|
354
|
+
@requires_version(2, 24)
|
|
355
|
+
def height_from_volume(self, volume: LiquidTrackingType) -> LiquidTrackingType:
|
|
356
|
+
"""Return the height in a well corresponding to a given volume."""
|
|
357
|
+
return self._core.height_from_volume(volume)
|
|
358
|
+
|
|
349
359
|
@requires_version(2, 21)
|
|
350
360
|
def estimate_liquid_height_after_pipetting(
|
|
351
361
|
self,
|
|
@@ -177,7 +177,7 @@ class ModuleContext(CommandPublisher):
|
|
|
177
177
|
|
|
178
178
|
labware_core = self._protocol_core.load_labware(
|
|
179
179
|
load_name=name,
|
|
180
|
-
label=label,
|
|
180
|
+
label=label if label is None else str(label),
|
|
181
181
|
namespace=namespace,
|
|
182
182
|
version=version,
|
|
183
183
|
location=load_location,
|
|
@@ -246,7 +246,10 @@ class ModuleContext(CommandPublisher):
|
|
|
246
246
|
"""
|
|
247
247
|
_log.warning("load_labware_by_name is deprecated. Use load_labware instead.")
|
|
248
248
|
return self.load_labware(
|
|
249
|
-
name=name,
|
|
249
|
+
name=name,
|
|
250
|
+
label=label,
|
|
251
|
+
namespace=namespace,
|
|
252
|
+
version=version,
|
|
250
253
|
)
|
|
251
254
|
|
|
252
255
|
@requires_version(2, 15)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
+
from copy import deepcopy
|
|
4
5
|
from typing import (
|
|
5
6
|
Callable,
|
|
6
7
|
Dict,
|
|
@@ -13,6 +14,11 @@ from typing import (
|
|
|
13
14
|
)
|
|
14
15
|
|
|
15
16
|
from opentrons_shared_data.labware.types import LabwareDefinition
|
|
17
|
+
from opentrons_shared_data.liquid_classes.liquid_class_definition import (
|
|
18
|
+
TransferProperties as SharedTransferProperties,
|
|
19
|
+
)
|
|
20
|
+
from opentrons_shared_data.liquid_classes import DEFAULT_LC_VERSION, definition_exists
|
|
21
|
+
from opentrons_shared_data.liquid_classes.types import TransferPropertiesDict
|
|
16
22
|
from opentrons_shared_data.pipette.types import PipetteNameType
|
|
17
23
|
|
|
18
24
|
from opentrons.types import Mount, Location, DeckLocation, DeckSlotName, StagingSlotName
|
|
@@ -48,6 +54,7 @@ from opentrons.protocols.api_support.util import (
|
|
|
48
54
|
)
|
|
49
55
|
from opentrons_shared_data.errors.exceptions import CommandPreconditionViolated
|
|
50
56
|
from opentrons.protocol_engine.errors import LabwareMovementNotAllowedError
|
|
57
|
+
from ._liquid_properties import build_transfer_properties
|
|
51
58
|
|
|
52
59
|
from ._types import OffDeckType
|
|
53
60
|
from .core.common import ModuleCore, LabwareCore, ProtocolCore
|
|
@@ -196,6 +203,7 @@ class ProtocolContext(CommandPublisher):
|
|
|
196
203
|
core=self._core.load_robot(),
|
|
197
204
|
protocol_core=self._core,
|
|
198
205
|
api_version=self._api_version,
|
|
206
|
+
broker=broker,
|
|
199
207
|
)
|
|
200
208
|
except APIVersionError:
|
|
201
209
|
self._robot = None
|
|
@@ -491,7 +499,7 @@ class ProtocolContext(CommandPublisher):
|
|
|
491
499
|
labware_core = self._core.load_labware(
|
|
492
500
|
load_name=load_name,
|
|
493
501
|
location=load_location,
|
|
494
|
-
label=label,
|
|
502
|
+
label=label if label is None else str(label),
|
|
495
503
|
namespace=namespace,
|
|
496
504
|
version=version,
|
|
497
505
|
)
|
|
@@ -1189,9 +1197,16 @@ class ProtocolContext(CommandPublisher):
|
|
|
1189
1197
|
self._core.home()
|
|
1190
1198
|
|
|
1191
1199
|
@property
|
|
1192
|
-
def location_cache(self) -> Optional[Location]:
|
|
1193
|
-
"""The cache used by the robot to determine where it last was.
|
|
1194
|
-
|
|
1200
|
+
def location_cache(self) -> Optional[Union[Location, TrashBin, WasteChute]]:
|
|
1201
|
+
"""The cache used by the robot to determine where it last was.
|
|
1202
|
+
|
|
1203
|
+
.. versionchanged:: 2.24
|
|
1204
|
+
Can return a ``TrashBin`` or ``WasteChute`` object.
|
|
1205
|
+
"""
|
|
1206
|
+
last_loc = self._core.get_last_location()
|
|
1207
|
+
if isinstance(last_loc, Location) or self._api_version >= APIVersion(2, 24):
|
|
1208
|
+
return last_loc
|
|
1209
|
+
return None
|
|
1195
1210
|
|
|
1196
1211
|
@location_cache.setter
|
|
1197
1212
|
def location_cache(self, loc: Optional[Location]) -> None:
|
|
@@ -1356,19 +1371,69 @@ class ProtocolContext(CommandPublisher):
|
|
|
1356
1371
|
display_color=display_color,
|
|
1357
1372
|
)
|
|
1358
1373
|
|
|
1359
|
-
@requires_version(2,
|
|
1360
|
-
def
|
|
1374
|
+
@requires_version(2, 24)
|
|
1375
|
+
def get_liquid_class(
|
|
1361
1376
|
self,
|
|
1362
1377
|
name: str,
|
|
1363
1378
|
) -> LiquidClass:
|
|
1364
1379
|
"""
|
|
1365
|
-
|
|
1366
|
-
..
|
|
1367
|
-
This is intended for Opentrons internal use only and is not a guaranteed API.
|
|
1380
|
+
Get an instance of an Opentrons-verified liquid class for use in a Flex protocol.
|
|
1368
1381
|
|
|
1369
|
-
:
|
|
1382
|
+
:param name: Name of an Opentrons-verified liquid class. Must be one of:
|
|
1383
|
+
|
|
1384
|
+
- ``"water"``: an Opentrons-verified liquid class based on deionized water.
|
|
1385
|
+
- ``"glycerol_50"``: an Opentrons-verified liquid class for viscous liquid. Based on 50% glycerol.
|
|
1386
|
+
- ``"ethanol_80"``: an Opentrons-verified liquid class for volatile liquid. Based on 80% ethanol.
|
|
1387
|
+
|
|
1388
|
+
:raises: ``LiquidClassDefinitionDoesNotExist``: if the specified liquid class does not exist.
|
|
1370
1389
|
"""
|
|
1371
|
-
return self._core.
|
|
1390
|
+
return self._core.get_liquid_class(name=name, version=DEFAULT_LC_VERSION)
|
|
1391
|
+
|
|
1392
|
+
@requires_version(2, 24)
|
|
1393
|
+
def define_liquid_class(
|
|
1394
|
+
self,
|
|
1395
|
+
name: str,
|
|
1396
|
+
properties: Dict[str, Dict[str, TransferPropertiesDict]],
|
|
1397
|
+
base_liquid_class: Optional[LiquidClass] = None,
|
|
1398
|
+
display_name: Optional[str] = None,
|
|
1399
|
+
) -> LiquidClass:
|
|
1400
|
+
"""Define a custom liquid class, either based on an existing, Opentrons-verified liquid class, or to create a completely new one.
|
|
1401
|
+
|
|
1402
|
+
:param name: The name to give to the new liquid class. Cannot use the name of an Opentrons-verified liquid class.
|
|
1403
|
+
:param properties: A dict of transfer properties for the Flex pipette and tips to use for liquid class transfers. The nested dictionary must have top-level keys corresponding to pipette load names and second-level keys corresponding to compatible tip rack load names. Further nested key–value pairs should be in the format returned by :py:meth:`.LiquidClass.get_for`. See also the `liquid class JSON schema <https://github.com/Opentrons/opentrons/tree/edge/shared-data/liquid-class/schemas>`_.
|
|
1404
|
+
|
|
1405
|
+
:param base_liquid_class: An Opentrons-verified liquid class to base the newly defined liquid class on. The specified ``transfer_properties`` will override any existing properties for the Flex pipette and tips. All other properties will remain the same as those in the base class.
|
|
1406
|
+
|
|
1407
|
+
:param display_name: An optional name for the liquid class. Defaults to the title-case ``name`` if a display name isn't provided.
|
|
1408
|
+
|
|
1409
|
+
"""
|
|
1410
|
+
if definition_exists(name, DEFAULT_LC_VERSION):
|
|
1411
|
+
raise ValueError(
|
|
1412
|
+
f"Liquid class named {name} already exists. Please specify a different name."
|
|
1413
|
+
)
|
|
1414
|
+
new_liquid_class: LiquidClass
|
|
1415
|
+
if base_liquid_class:
|
|
1416
|
+
# If base liquid is provided, copy to new class
|
|
1417
|
+
# and replace the entries mentioned in transfer props arg
|
|
1418
|
+
new_liquid_class = deepcopy(base_liquid_class)
|
|
1419
|
+
else:
|
|
1420
|
+
new_liquid_class = LiquidClass.create_from(
|
|
1421
|
+
name=name,
|
|
1422
|
+
display_name=display_name or name.title(),
|
|
1423
|
+
by_pipette_setting={},
|
|
1424
|
+
)
|
|
1425
|
+
for pipette, by_tiprack_props in properties.items():
|
|
1426
|
+
for tiprack, transfer_props in by_tiprack_props.items():
|
|
1427
|
+
new_liquid_class.update_for(
|
|
1428
|
+
pipette=pipette,
|
|
1429
|
+
tip_rack=tiprack,
|
|
1430
|
+
transfer_properties=build_transfer_properties(
|
|
1431
|
+
transfer_properties=SharedTransferProperties.model_validate(
|
|
1432
|
+
transfer_props
|
|
1433
|
+
)
|
|
1434
|
+
),
|
|
1435
|
+
)
|
|
1436
|
+
return new_liquid_class
|
|
1372
1437
|
|
|
1373
1438
|
@property
|
|
1374
1439
|
@requires_version(2, 5)
|
|
@@ -9,6 +9,8 @@ from opentrons.types import (
|
|
|
9
9
|
AxisType,
|
|
10
10
|
StringAxisMap,
|
|
11
11
|
)
|
|
12
|
+
from opentrons.legacy_broker import LegacyBroker
|
|
13
|
+
from opentrons.legacy_commands import robot_commands as cmds
|
|
12
14
|
from opentrons.legacy_commands import publisher
|
|
13
15
|
from opentrons.hardware_control import SyncHardwareAPI
|
|
14
16
|
from opentrons.protocols.api_support.util import requires_version
|
|
@@ -49,8 +51,13 @@ class RobotContext(publisher.CommandPublisher):
|
|
|
49
51
|
"""
|
|
50
52
|
|
|
51
53
|
def __init__(
|
|
52
|
-
self,
|
|
54
|
+
self,
|
|
55
|
+
core: RobotCore,
|
|
56
|
+
protocol_core: ProtocolCore,
|
|
57
|
+
api_version: APIVersion,
|
|
58
|
+
broker: Optional[LegacyBroker] = None,
|
|
53
59
|
) -> None:
|
|
60
|
+
super().__init__(broker)
|
|
54
61
|
self._hardware = HardwareManager(hardware=protocol_core.get_hardware())
|
|
55
62
|
self._core = core
|
|
56
63
|
self._protocol_core = protocol_core
|
|
@@ -87,7 +94,16 @@ class RobotContext(publisher.CommandPublisher):
|
|
|
87
94
|
:param speed:
|
|
88
95
|
"""
|
|
89
96
|
mount = validation.ensure_instrument_mount(mount)
|
|
90
|
-
|
|
97
|
+
with publisher.publish_context(
|
|
98
|
+
broker=self.broker,
|
|
99
|
+
command=cmds.move_to(
|
|
100
|
+
# This needs to be called from protocol context and not the command for import loop reasons
|
|
101
|
+
mount=mount,
|
|
102
|
+
location=destination,
|
|
103
|
+
speed=speed,
|
|
104
|
+
),
|
|
105
|
+
):
|
|
106
|
+
self._core.move_to(mount, destination.point, speed)
|
|
91
107
|
|
|
92
108
|
@requires_version(2, 22)
|
|
93
109
|
def move_axes_to(
|
|
@@ -119,7 +135,15 @@ class RobotContext(publisher.CommandPublisher):
|
|
|
119
135
|
)
|
|
120
136
|
else:
|
|
121
137
|
critical_point = None
|
|
122
|
-
|
|
138
|
+
with publisher.publish_context(
|
|
139
|
+
broker=self.broker,
|
|
140
|
+
command=cmds.move_axis_to(
|
|
141
|
+
# This needs to be called from protocol context and not the command for import loop reasons
|
|
142
|
+
axis_map=axis_map,
|
|
143
|
+
speed=speed,
|
|
144
|
+
),
|
|
145
|
+
):
|
|
146
|
+
self._core.move_axes_to(axis_map, critical_point, speed)
|
|
123
147
|
|
|
124
148
|
@requires_version(2, 22)
|
|
125
149
|
def move_axes_relative(
|
|
@@ -142,15 +166,33 @@ class RobotContext(publisher.CommandPublisher):
|
|
|
142
166
|
axis_map = validation.ensure_axis_map_type(
|
|
143
167
|
axis_map, self._protocol_core.robot_type, is_96_channel
|
|
144
168
|
)
|
|
145
|
-
|
|
169
|
+
with publisher.publish_context(
|
|
170
|
+
broker=self.broker,
|
|
171
|
+
command=cmds.move_axis_relative(
|
|
172
|
+
# This needs to be called from protocol context and not the command for import loop reasons
|
|
173
|
+
axis_map=axis_map,
|
|
174
|
+
speed=speed,
|
|
175
|
+
),
|
|
176
|
+
):
|
|
177
|
+
self._core.move_axes_relative(axis_map, speed)
|
|
146
178
|
|
|
147
179
|
def close_gripper_jaw(self, force: Optional[float] = None) -> None:
|
|
148
180
|
"""Command the gripper closed with some force."""
|
|
149
|
-
|
|
181
|
+
with publisher.publish_context(
|
|
182
|
+
broker=self.broker,
|
|
183
|
+
command=cmds.close_gripper(
|
|
184
|
+
force=force,
|
|
185
|
+
),
|
|
186
|
+
):
|
|
187
|
+
self._core.close_gripper(force)
|
|
150
188
|
|
|
151
189
|
def open_gripper_jaw(self) -> None:
|
|
152
190
|
"""Command the gripper open."""
|
|
153
|
-
|
|
191
|
+
with publisher.publish_context(
|
|
192
|
+
broker=self.broker,
|
|
193
|
+
command=cmds.open_gripper(),
|
|
194
|
+
):
|
|
195
|
+
self._core.release_grip()
|
|
154
196
|
|
|
155
197
|
def axis_coordinates_for(
|
|
156
198
|
self,
|
|
@@ -545,6 +545,11 @@ class PointTarget(NamedTuple):
|
|
|
545
545
|
in_place: bool
|
|
546
546
|
|
|
547
547
|
|
|
548
|
+
class DisposalTarget(NamedTuple):
|
|
549
|
+
location: Union[TrashBin, WasteChute]
|
|
550
|
+
in_place: bool
|
|
551
|
+
|
|
552
|
+
|
|
548
553
|
class NoLocationError(ValueError):
|
|
549
554
|
"""Error representing that no location was supplied."""
|
|
550
555
|
|
|
@@ -553,12 +558,12 @@ class LocationTypeError(TypeError):
|
|
|
553
558
|
"""Error representing that the location supplied is of different expected type."""
|
|
554
559
|
|
|
555
560
|
|
|
556
|
-
ValidTarget = Union[WellTarget, PointTarget,
|
|
561
|
+
ValidTarget = Union[WellTarget, PointTarget, DisposalTarget]
|
|
557
562
|
|
|
558
563
|
|
|
559
564
|
def validate_location(
|
|
560
|
-
location: Union[Location, Well, TrashBin, WasteChute
|
|
561
|
-
last_location: Optional[Location],
|
|
565
|
+
location: Optional[Union[Location, Well, TrashBin, WasteChute]],
|
|
566
|
+
last_location: Optional[Union[Location, TrashBin, WasteChute]],
|
|
562
567
|
) -> ValidTarget:
|
|
563
568
|
"""Validate a given location for a liquid handling command.
|
|
564
569
|
|
|
@@ -569,9 +574,11 @@ def validate_location(
|
|
|
569
574
|
Returns:
|
|
570
575
|
A `WellTarget` if the input location represents a well.
|
|
571
576
|
A `PointTarget` if the input location is an x, y, z coordinate.
|
|
577
|
+
A `TrashBin` if the input location is a trash bin
|
|
578
|
+
A `WasteChute` if the input location is a waste chute
|
|
572
579
|
|
|
573
580
|
Raises:
|
|
574
|
-
NoLocationError:
|
|
581
|
+
NoLocationError: There is no input location and no cached location.
|
|
575
582
|
LocationTypeError: The location supplied is of unexpected type.
|
|
576
583
|
"""
|
|
577
584
|
from .labware import Well
|
|
@@ -586,11 +593,11 @@ def validate_location(
|
|
|
586
593
|
f"location should be a Well, Location, TrashBin or WasteChute, but it is {location}"
|
|
587
594
|
)
|
|
588
595
|
|
|
589
|
-
if isinstance(target_location, (TrashBin, WasteChute)):
|
|
590
|
-
return target_location
|
|
591
|
-
|
|
592
596
|
in_place = target_location == last_location
|
|
593
597
|
|
|
598
|
+
if isinstance(target_location, (TrashBin, WasteChute)):
|
|
599
|
+
return DisposalTarget(location=target_location, in_place=in_place)
|
|
600
|
+
|
|
594
601
|
if isinstance(target_location, Well):
|
|
595
602
|
return WellTarget(well=target_location, location=None, in_place=in_place)
|
|
596
603
|
|
|
@@ -662,7 +669,7 @@ def ensure_new_tip_policy(value: str) -> TransferTipPolicyV2:
|
|
|
662
669
|
except ValueError:
|
|
663
670
|
raise ValueError(
|
|
664
671
|
f"'{value}' is invalid value for 'new_tip'."
|
|
665
|
-
f" Acceptable value is either 'never', 'once', 'always' or 'per
|
|
672
|
+
f" Acceptable value is either 'never', 'once', 'always', 'per source' or 'per destination'."
|
|
666
673
|
)
|
|
667
674
|
|
|
668
675
|
|
|
@@ -498,8 +498,8 @@ Command = Annotated[
|
|
|
498
498
|
robot.MoveTo,
|
|
499
499
|
robot.MoveAxesRelative,
|
|
500
500
|
robot.MoveAxesTo,
|
|
501
|
-
robot.
|
|
502
|
-
robot.
|
|
501
|
+
robot.OpenGripperJaw,
|
|
502
|
+
robot.CloseGripperJaw,
|
|
503
503
|
],
|
|
504
504
|
Field(discriminator="commandType"),
|
|
505
505
|
]
|
|
@@ -599,8 +599,8 @@ CommandParams = Union[
|
|
|
599
599
|
robot.MoveAxesRelativeParams,
|
|
600
600
|
robot.MoveAxesToParams,
|
|
601
601
|
robot.MoveToParams,
|
|
602
|
-
robot.
|
|
603
|
-
robot.
|
|
602
|
+
robot.OpenGripperJawParams,
|
|
603
|
+
robot.CloseGripperJawParams,
|
|
604
604
|
]
|
|
605
605
|
|
|
606
606
|
CommandType = Union[
|
|
@@ -698,8 +698,8 @@ CommandType = Union[
|
|
|
698
698
|
robot.MoveAxesRelativeCommandType,
|
|
699
699
|
robot.MoveAxesToCommandType,
|
|
700
700
|
robot.MoveToCommandType,
|
|
701
|
-
robot.
|
|
702
|
-
robot.
|
|
701
|
+
robot.OpenGripperJawCommandType,
|
|
702
|
+
robot.CloseGripperJawCommandType,
|
|
703
703
|
]
|
|
704
704
|
|
|
705
705
|
CommandCreate = Annotated[
|
|
@@ -798,8 +798,8 @@ CommandCreate = Annotated[
|
|
|
798
798
|
robot.MoveAxesRelativeCreate,
|
|
799
799
|
robot.MoveAxesToCreate,
|
|
800
800
|
robot.MoveToCreate,
|
|
801
|
-
robot.
|
|
802
|
-
robot.
|
|
801
|
+
robot.OpenGripperJawCreate,
|
|
802
|
+
robot.CloseGripperJawCreate,
|
|
803
803
|
],
|
|
804
804
|
Field(discriminator="commandType"),
|
|
805
805
|
]
|
|
@@ -906,8 +906,8 @@ CommandResult = Union[
|
|
|
906
906
|
robot.MoveAxesRelativeResult,
|
|
907
907
|
robot.MoveAxesToResult,
|
|
908
908
|
robot.MoveToResult,
|
|
909
|
-
robot.
|
|
910
|
-
robot.
|
|
909
|
+
robot.OpenGripperJawResult,
|
|
910
|
+
robot.CloseGripperJawResult,
|
|
911
911
|
]
|
|
912
912
|
|
|
913
913
|
|
|
@@ -11,7 +11,7 @@ from opentrons_shared_data.load import get_shared_data_root
|
|
|
11
11
|
|
|
12
12
|
def generate_command_schema(version: str) -> str:
|
|
13
13
|
"""Generate a JSON Schema that all valid create commands can validate against."""
|
|
14
|
-
schema_as_dict = CommandCreateAdapter.json_schema(mode="validation")
|
|
14
|
+
schema_as_dict = CommandCreateAdapter.json_schema(mode="validation", by_alias=False)
|
|
15
15
|
schema_as_dict["$id"] = f"opentronsCommandSchemaV{version}"
|
|
16
16
|
schema_as_dict["$schema"] = "http://json-schema.org/draft-07/schema#"
|
|
17
17
|
return json.dumps(schema_as_dict, indent=2, sort_keys=True)
|
|
@@ -73,8 +73,8 @@ class GetNextTipImplementation(
|
|
|
73
73
|
pipette_id = params.pipetteId
|
|
74
74
|
starting_tip_name = params.startingTipWell
|
|
75
75
|
|
|
76
|
-
num_tips = self._state_view.
|
|
77
|
-
nozzle_map = self._state_view.
|
|
76
|
+
num_tips = self._state_view.pipettes.get_active_channels(pipette_id)
|
|
77
|
+
nozzle_map = self._state_view.pipettes.get_nozzle_configuration(pipette_id)
|
|
78
78
|
|
|
79
79
|
if (
|
|
80
80
|
starting_tip_name is not None
|
|
@@ -165,25 +165,6 @@ class LoadLabwareImplementation(
|
|
|
165
165
|
top_labware_definition=loaded_labware.definition,
|
|
166
166
|
bottom_labware_id=verified_location.labwareId,
|
|
167
167
|
)
|
|
168
|
-
# Validate load location is valid for lids
|
|
169
|
-
if labware_validation.validate_definition_is_lid(
|
|
170
|
-
definition=loaded_labware.definition
|
|
171
|
-
):
|
|
172
|
-
# This parent is assumed to be compatible, unless the lid enumerates
|
|
173
|
-
# all its compatible parents and this parent is missing from the list.
|
|
174
|
-
parent_is_incompatible = (
|
|
175
|
-
loaded_labware.definition.compatibleParentLabware is not None
|
|
176
|
-
and self._state_view.labware.get_load_name(
|
|
177
|
-
verified_location.labwareId
|
|
178
|
-
)
|
|
179
|
-
not in loaded_labware.definition.compatibleParentLabware
|
|
180
|
-
)
|
|
181
|
-
|
|
182
|
-
if parent_is_incompatible:
|
|
183
|
-
raise ValueError(
|
|
184
|
-
f"Labware Lid {params.loadName} may not be loaded on parent labware"
|
|
185
|
-
f" {self._state_view.labware.get_display_name(verified_location.labwareId)}."
|
|
186
|
-
)
|
|
187
168
|
|
|
188
169
|
# Validate labware for the absorbance reader
|
|
189
170
|
if self._is_loading_to_module(
|
|
@@ -121,6 +121,12 @@ class PickUpTipImplementation(AbstractCommandImpl[PickUpTipParams, _ExecuteRetur
|
|
|
121
121
|
labware_id = params.labwareId
|
|
122
122
|
well_name = params.wellName
|
|
123
123
|
|
|
124
|
+
tips_to_mark_as_used = self._state_view.tips.compute_tips_to_mark_as_used(
|
|
125
|
+
labware_id=labware_id,
|
|
126
|
+
well_name=well_name,
|
|
127
|
+
nozzle_map=self._state_view.pipettes.get_nozzle_configuration(pipette_id),
|
|
128
|
+
)
|
|
129
|
+
|
|
124
130
|
well_location = self._state_view.geometry.convert_pick_up_tip_well_location(
|
|
125
131
|
well_location=params.wellLocation
|
|
126
132
|
)
|
|
@@ -152,7 +158,7 @@ class PickUpTipImplementation(AbstractCommandImpl[PickUpTipParams, _ExecuteRetur
|
|
|
152
158
|
)
|
|
153
159
|
.set_fluid_empty(pipette_id=pipette_id, clean_tip=True)
|
|
154
160
|
.mark_tips_as_used(
|
|
155
|
-
|
|
161
|
+
labware_id=labware_id, well_names=tips_to_mark_as_used
|
|
156
162
|
)
|
|
157
163
|
)
|
|
158
164
|
state_update = (
|
|
@@ -160,7 +166,7 @@ class PickUpTipImplementation(AbstractCommandImpl[PickUpTipParams, _ExecuteRetur
|
|
|
160
166
|
update_types.StateUpdate(), move_result.state_update
|
|
161
167
|
)
|
|
162
168
|
.mark_tips_as_used(
|
|
163
|
-
|
|
169
|
+
labware_id=labware_id, well_names=tips_to_mark_as_used
|
|
164
170
|
)
|
|
165
171
|
.set_fluid_unknown(pipette_id=pipette_id)
|
|
166
172
|
)
|
|
@@ -186,7 +192,7 @@ class PickUpTipImplementation(AbstractCommandImpl[PickUpTipParams, _ExecuteRetur
|
|
|
186
192
|
tip_geometry=tip_geometry,
|
|
187
193
|
)
|
|
188
194
|
.mark_tips_as_used(
|
|
189
|
-
|
|
195
|
+
labware_id=labware_id, well_names=tips_to_mark_as_used
|
|
190
196
|
)
|
|
191
197
|
.set_fluid_empty(pipette_id=pipette_id, clean_tip=True)
|
|
192
198
|
.set_pipette_ready_to_aspirate(
|
|
@@ -22,18 +22,18 @@ from .move_axes_relative import (
|
|
|
22
22
|
MoveAxesRelativeCommandType,
|
|
23
23
|
)
|
|
24
24
|
from .open_gripper_jaw import (
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
OpenGripperJaw,
|
|
26
|
+
OpenGripperJawCreate,
|
|
27
|
+
OpenGripperJawParams,
|
|
28
|
+
OpenGripperJawResult,
|
|
29
|
+
OpenGripperJawCommandType,
|
|
30
30
|
)
|
|
31
31
|
from .close_gripper_jaw import (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
CloseGripperJaw,
|
|
33
|
+
CloseGripperJawCreate,
|
|
34
|
+
CloseGripperJawParams,
|
|
35
|
+
CloseGripperJawResult,
|
|
36
|
+
CloseGripperJawCommandType,
|
|
37
37
|
)
|
|
38
38
|
|
|
39
39
|
__all__ = [
|
|
@@ -56,15 +56,15 @@ __all__ = [
|
|
|
56
56
|
"MoveAxesRelativeResult",
|
|
57
57
|
"MoveAxesRelativeCommandType",
|
|
58
58
|
# robot/openGripperJaw
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
59
|
+
"OpenGripperJaw",
|
|
60
|
+
"OpenGripperJawCreate",
|
|
61
|
+
"OpenGripperJawParams",
|
|
62
|
+
"OpenGripperJawResult",
|
|
63
|
+
"OpenGripperJawCommandType",
|
|
64
64
|
# robot/closeGripperJaw
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
65
|
+
"CloseGripperJaw",
|
|
66
|
+
"CloseGripperJawCreate",
|
|
67
|
+
"CloseGripperJawParams",
|
|
68
|
+
"CloseGripperJawResult",
|
|
69
|
+
"CloseGripperJawCommandType",
|
|
70
70
|
]
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Command models for opening a gripper jaw."""
|
|
2
|
+
|
|
2
3
|
from __future__ import annotations
|
|
3
|
-
from typing import Literal, Type, Optional, Any
|
|
4
|
+
from typing import Literal, Type, Optional, Any, TYPE_CHECKING
|
|
4
5
|
|
|
5
6
|
from pydantic import BaseModel, Field
|
|
6
7
|
from pydantic.json_schema import SkipJsonSchema
|
|
@@ -16,15 +17,18 @@ from ..command import (
|
|
|
16
17
|
)
|
|
17
18
|
from opentrons.protocol_engine.errors.error_occurrence import ErrorOccurrence
|
|
18
19
|
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from ...state.state import StateView
|
|
22
|
+
|
|
19
23
|
|
|
20
|
-
|
|
24
|
+
CloseGripperJawCommandType = Literal["robot/closeGripperJaw"]
|
|
21
25
|
|
|
22
26
|
|
|
23
27
|
def _remove_default(s: dict[str, Any]) -> None:
|
|
24
28
|
s.pop("default", None)
|
|
25
29
|
|
|
26
30
|
|
|
27
|
-
class
|
|
31
|
+
class CloseGripperJawParams(BaseModel):
|
|
28
32
|
"""Payload required to close a gripper."""
|
|
29
33
|
|
|
30
34
|
force: float | SkipJsonSchema[None] = Field(
|
|
@@ -34,53 +38,59 @@ class closeGripperJawParams(BaseModel):
|
|
|
34
38
|
)
|
|
35
39
|
|
|
36
40
|
|
|
37
|
-
class
|
|
38
|
-
"""Result data from the execution of a
|
|
41
|
+
class CloseGripperJawResult(BaseModel):
|
|
42
|
+
"""Result data from the execution of a CloseGripperJaw command."""
|
|
39
43
|
|
|
40
44
|
pass
|
|
41
45
|
|
|
42
46
|
|
|
43
|
-
class
|
|
44
|
-
AbstractCommandImpl[
|
|
47
|
+
class CloseGripperJawImplementation(
|
|
48
|
+
AbstractCommandImpl[CloseGripperJawParams, SuccessData[CloseGripperJawResult]]
|
|
45
49
|
):
|
|
46
|
-
"""
|
|
50
|
+
"""CloseGripperJaw command implementation."""
|
|
47
51
|
|
|
48
52
|
def __init__(
|
|
49
53
|
self,
|
|
50
54
|
hardware_api: HardwareControlAPI,
|
|
55
|
+
state_view: StateView,
|
|
51
56
|
**kwargs: object,
|
|
52
57
|
) -> None:
|
|
53
58
|
self._hardware_api = hardware_api
|
|
59
|
+
self._state_view = state_view
|
|
54
60
|
|
|
55
61
|
async def execute(
|
|
56
|
-
self, params:
|
|
57
|
-
) -> SuccessData[
|
|
62
|
+
self, params: CloseGripperJawParams
|
|
63
|
+
) -> SuccessData[CloseGripperJawResult]:
|
|
58
64
|
"""Release the gripper."""
|
|
65
|
+
if self._state_view.config.use_virtual_gripper:
|
|
66
|
+
return SuccessData(
|
|
67
|
+
public=CloseGripperJawResult(),
|
|
68
|
+
)
|
|
59
69
|
ot3_hardware_api = ensure_ot3_hardware(self._hardware_api)
|
|
60
70
|
await ot3_hardware_api.grip(force_newtons=params.force)
|
|
61
71
|
return SuccessData(
|
|
62
|
-
public=
|
|
72
|
+
public=CloseGripperJawResult(),
|
|
63
73
|
)
|
|
64
74
|
|
|
65
75
|
|
|
66
|
-
class
|
|
67
|
-
BaseCommand[
|
|
76
|
+
class CloseGripperJaw(
|
|
77
|
+
BaseCommand[CloseGripperJawParams, CloseGripperJawResult, ErrorOccurrence]
|
|
68
78
|
):
|
|
69
|
-
"""
|
|
79
|
+
"""CloseGripperJaw command model."""
|
|
70
80
|
|
|
71
|
-
commandType:
|
|
72
|
-
params:
|
|
73
|
-
result: Optional[
|
|
81
|
+
commandType: CloseGripperJawCommandType = "robot/closeGripperJaw"
|
|
82
|
+
params: CloseGripperJawParams
|
|
83
|
+
result: Optional[CloseGripperJawResult] = None
|
|
74
84
|
|
|
75
85
|
_ImplementationCls: Type[
|
|
76
|
-
|
|
77
|
-
] =
|
|
86
|
+
CloseGripperJawImplementation
|
|
87
|
+
] = CloseGripperJawImplementation
|
|
78
88
|
|
|
79
89
|
|
|
80
|
-
class
|
|
81
|
-
"""
|
|
90
|
+
class CloseGripperJawCreate(BaseCommandCreate[CloseGripperJawParams]):
|
|
91
|
+
"""CloseGripperJaw command request model."""
|
|
82
92
|
|
|
83
|
-
commandType:
|
|
84
|
-
params:
|
|
93
|
+
commandType: CloseGripperJawCommandType = "robot/closeGripperJaw"
|
|
94
|
+
params: CloseGripperJawParams
|
|
85
95
|
|
|
86
|
-
_CommandCls: Type[
|
|
96
|
+
_CommandCls: Type[CloseGripperJaw] = CloseGripperJaw
|