opentrons 8.2.0a4__py2.py3-none-any.whl → 8.3.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.
Potentially problematic release.
This version of opentrons might be problematic. Click here for more details.
- opentrons/calibration_storage/deck_configuration.py +3 -3
- opentrons/calibration_storage/file_operators.py +3 -3
- opentrons/calibration_storage/helpers.py +3 -1
- opentrons/calibration_storage/ot2/models/v1.py +16 -29
- opentrons/calibration_storage/ot2/tip_length.py +7 -4
- opentrons/calibration_storage/ot3/models/v1.py +14 -23
- opentrons/cli/analyze.py +18 -6
- opentrons/config/defaults_ot3.py +1 -0
- opentrons/drivers/asyncio/communication/__init__.py +2 -0
- opentrons/drivers/asyncio/communication/errors.py +16 -3
- opentrons/drivers/asyncio/communication/serial_connection.py +24 -9
- opentrons/drivers/command_builder.py +2 -2
- opentrons/drivers/flex_stacker/__init__.py +9 -0
- opentrons/drivers/flex_stacker/abstract.py +89 -0
- opentrons/drivers/flex_stacker/driver.py +260 -0
- opentrons/drivers/flex_stacker/simulator.py +109 -0
- opentrons/drivers/flex_stacker/types.py +138 -0
- opentrons/drivers/heater_shaker/driver.py +18 -3
- opentrons/drivers/temp_deck/driver.py +13 -3
- opentrons/drivers/thermocycler/driver.py +17 -3
- opentrons/execute.py +3 -1
- opentrons/hardware_control/__init__.py +1 -2
- opentrons/hardware_control/api.py +33 -21
- opentrons/hardware_control/backends/flex_protocol.py +17 -7
- opentrons/hardware_control/backends/ot3controller.py +213 -63
- opentrons/hardware_control/backends/ot3simulator.py +18 -9
- opentrons/hardware_control/backends/ot3utils.py +43 -15
- opentrons/hardware_control/dev_types.py +4 -0
- opentrons/hardware_control/emulation/heater_shaker.py +4 -0
- opentrons/hardware_control/emulation/module_server/client.py +1 -1
- opentrons/hardware_control/emulation/module_server/server.py +5 -3
- opentrons/hardware_control/emulation/settings.py +3 -4
- opentrons/hardware_control/instruments/ot2/instrument_calibration.py +2 -1
- opentrons/hardware_control/instruments/ot2/pipette.py +15 -22
- opentrons/hardware_control/instruments/ot2/pipette_handler.py +8 -1
- opentrons/hardware_control/instruments/ot3/gripper.py +2 -2
- opentrons/hardware_control/instruments/ot3/pipette.py +23 -22
- opentrons/hardware_control/instruments/ot3/pipette_handler.py +10 -1
- opentrons/hardware_control/modules/mod_abc.py +2 -2
- opentrons/hardware_control/motion_utilities.py +68 -0
- opentrons/hardware_control/nozzle_manager.py +39 -41
- opentrons/hardware_control/ot3_calibration.py +1 -1
- opentrons/hardware_control/ot3api.py +78 -31
- opentrons/hardware_control/protocols/gripper_controller.py +3 -0
- opentrons/hardware_control/protocols/hardware_manager.py +5 -1
- opentrons/hardware_control/protocols/liquid_handler.py +22 -1
- opentrons/hardware_control/protocols/motion_controller.py +7 -0
- opentrons/hardware_control/robot_calibration.py +1 -1
- opentrons/hardware_control/types.py +61 -0
- opentrons/legacy_commands/commands.py +37 -0
- opentrons/legacy_commands/types.py +39 -0
- opentrons/protocol_api/__init__.py +20 -1
- opentrons/protocol_api/_liquid.py +24 -49
- opentrons/protocol_api/_liquid_properties.py +754 -0
- opentrons/protocol_api/_types.py +24 -0
- opentrons/protocol_api/core/common.py +2 -0
- opentrons/protocol_api/core/engine/instrument.py +191 -10
- opentrons/protocol_api/core/engine/labware.py +29 -7
- opentrons/protocol_api/core/engine/protocol.py +130 -5
- opentrons/protocol_api/core/engine/robot.py +139 -0
- opentrons/protocol_api/core/engine/well.py +4 -1
- opentrons/protocol_api/core/instrument.py +73 -4
- opentrons/protocol_api/core/labware.py +13 -4
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +87 -3
- opentrons/protocol_api/core/legacy/legacy_labware_core.py +13 -4
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +32 -1
- opentrons/protocol_api/core/legacy/legacy_robot_core.py +0 -0
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +61 -3
- opentrons/protocol_api/core/protocol.py +34 -1
- opentrons/protocol_api/core/robot.py +51 -0
- opentrons/protocol_api/instrument_context.py +299 -44
- opentrons/protocol_api/labware.py +248 -9
- opentrons/protocol_api/module_contexts.py +21 -17
- opentrons/protocol_api/protocol_context.py +125 -4
- opentrons/protocol_api/robot_context.py +204 -32
- opentrons/protocol_api/validation.py +262 -3
- opentrons/protocol_engine/__init__.py +4 -0
- opentrons/protocol_engine/actions/actions.py +2 -3
- opentrons/protocol_engine/clients/sync_client.py +18 -0
- opentrons/protocol_engine/commands/__init__.py +121 -0
- opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +1 -3
- opentrons/protocol_engine/commands/absorbance_reader/initialize.py +20 -6
- opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +1 -2
- opentrons/protocol_engine/commands/absorbance_reader/read.py +36 -10
- opentrons/protocol_engine/commands/air_gap_in_place.py +160 -0
- opentrons/protocol_engine/commands/aspirate.py +103 -53
- opentrons/protocol_engine/commands/aspirate_in_place.py +55 -51
- opentrons/protocol_engine/commands/blow_out.py +44 -39
- opentrons/protocol_engine/commands/blow_out_in_place.py +21 -32
- opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +13 -6
- opentrons/protocol_engine/commands/calibration/calibrate_module.py +1 -1
- opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +3 -3
- opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +1 -1
- opentrons/protocol_engine/commands/command.py +73 -66
- opentrons/protocol_engine/commands/command_unions.py +140 -1
- opentrons/protocol_engine/commands/comment.py +1 -1
- opentrons/protocol_engine/commands/configure_for_volume.py +10 -3
- opentrons/protocol_engine/commands/configure_nozzle_layout.py +6 -4
- opentrons/protocol_engine/commands/custom.py +6 -12
- opentrons/protocol_engine/commands/dispense.py +82 -48
- opentrons/protocol_engine/commands/dispense_in_place.py +71 -51
- opentrons/protocol_engine/commands/drop_tip.py +52 -31
- opentrons/protocol_engine/commands/drop_tip_in_place.py +79 -8
- opentrons/protocol_engine/commands/evotip_dispense.py +156 -0
- opentrons/protocol_engine/commands/evotip_seal_pipette.py +331 -0
- opentrons/protocol_engine/commands/evotip_unseal_pipette.py +160 -0
- opentrons/protocol_engine/commands/generate_command_schema.py +4 -11
- opentrons/protocol_engine/commands/get_next_tip.py +134 -0
- opentrons/protocol_engine/commands/get_tip_presence.py +1 -1
- opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +1 -1
- opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +1 -1
- opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +1 -1
- opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +1 -1
- opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +1 -1
- opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +1 -1
- opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +10 -4
- opentrons/protocol_engine/commands/home.py +13 -4
- opentrons/protocol_engine/commands/liquid_probe.py +125 -31
- opentrons/protocol_engine/commands/load_labware.py +33 -6
- opentrons/protocol_engine/commands/load_lid.py +146 -0
- opentrons/protocol_engine/commands/load_lid_stack.py +189 -0
- opentrons/protocol_engine/commands/load_liquid.py +12 -4
- opentrons/protocol_engine/commands/load_liquid_class.py +144 -0
- opentrons/protocol_engine/commands/load_module.py +31 -10
- opentrons/protocol_engine/commands/load_pipette.py +19 -8
- opentrons/protocol_engine/commands/magnetic_module/disengage.py +1 -1
- opentrons/protocol_engine/commands/magnetic_module/engage.py +1 -1
- opentrons/protocol_engine/commands/move_labware.py +28 -6
- opentrons/protocol_engine/commands/move_relative.py +35 -25
- opentrons/protocol_engine/commands/move_to_addressable_area.py +40 -27
- opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +53 -32
- opentrons/protocol_engine/commands/move_to_coordinates.py +36 -22
- opentrons/protocol_engine/commands/move_to_well.py +40 -24
- opentrons/protocol_engine/commands/movement_common.py +338 -0
- opentrons/protocol_engine/commands/pick_up_tip.py +49 -27
- opentrons/protocol_engine/commands/pipetting_common.py +169 -87
- opentrons/protocol_engine/commands/prepare_to_aspirate.py +24 -33
- opentrons/protocol_engine/commands/reload_labware.py +1 -1
- opentrons/protocol_engine/commands/retract_axis.py +1 -1
- opentrons/protocol_engine/commands/robot/__init__.py +69 -0
- opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +86 -0
- opentrons/protocol_engine/commands/robot/common.py +18 -0
- opentrons/protocol_engine/commands/robot/move_axes_relative.py +101 -0
- opentrons/protocol_engine/commands/robot/move_axes_to.py +100 -0
- opentrons/protocol_engine/commands/robot/move_to.py +94 -0
- opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +77 -0
- opentrons/protocol_engine/commands/save_position.py +14 -5
- opentrons/protocol_engine/commands/set_rail_lights.py +1 -1
- opentrons/protocol_engine/commands/set_status_bar.py +1 -1
- opentrons/protocol_engine/commands/temperature_module/deactivate.py +1 -1
- opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +1 -1
- opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +10 -4
- opentrons/protocol_engine/commands/thermocycler/close_lid.py +1 -1
- opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +1 -1
- opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +1 -1
- opentrons/protocol_engine/commands/thermocycler/open_lid.py +1 -1
- opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +9 -3
- opentrons/protocol_engine/commands/thermocycler/run_profile.py +9 -3
- opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +11 -4
- opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +1 -1
- opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +1 -1
- opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +1 -1
- opentrons/protocol_engine/commands/touch_tip.py +65 -16
- opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +5 -2
- opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +13 -4
- opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +2 -5
- opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +1 -1
- opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +1 -1
- opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +2 -5
- opentrons/protocol_engine/commands/verify_tip_presence.py +11 -4
- opentrons/protocol_engine/commands/wait_for_duration.py +10 -3
- opentrons/protocol_engine/commands/wait_for_resume.py +10 -3
- opentrons/protocol_engine/errors/__init__.py +12 -0
- opentrons/protocol_engine/errors/error_occurrence.py +19 -20
- opentrons/protocol_engine/errors/exceptions.py +76 -0
- opentrons/protocol_engine/execution/command_executor.py +1 -1
- opentrons/protocol_engine/execution/equipment.py +73 -5
- opentrons/protocol_engine/execution/gantry_mover.py +369 -8
- opentrons/protocol_engine/execution/hardware_stopper.py +7 -7
- opentrons/protocol_engine/execution/movement.py +27 -0
- opentrons/protocol_engine/execution/pipetting.py +5 -1
- opentrons/protocol_engine/execution/tip_handler.py +34 -15
- opentrons/protocol_engine/notes/notes.py +1 -1
- opentrons/protocol_engine/protocol_engine.py +7 -6
- opentrons/protocol_engine/resources/labware_data_provider.py +1 -1
- opentrons/protocol_engine/resources/labware_validation.py +18 -0
- opentrons/protocol_engine/resources/module_data_provider.py +1 -1
- opentrons/protocol_engine/resources/pipette_data_provider.py +26 -0
- opentrons/protocol_engine/slot_standardization.py +9 -9
- opentrons/protocol_engine/state/_move_types.py +9 -5
- opentrons/protocol_engine/state/_well_math.py +193 -0
- opentrons/protocol_engine/state/addressable_areas.py +25 -61
- opentrons/protocol_engine/state/command_history.py +12 -0
- opentrons/protocol_engine/state/commands.py +22 -14
- opentrons/protocol_engine/state/files.py +10 -12
- opentrons/protocol_engine/state/fluid_stack.py +138 -0
- opentrons/protocol_engine/state/frustum_helpers.py +63 -69
- opentrons/protocol_engine/state/geometry.py +47 -1
- opentrons/protocol_engine/state/labware.py +92 -26
- opentrons/protocol_engine/state/liquid_classes.py +82 -0
- opentrons/protocol_engine/state/liquids.py +16 -4
- opentrons/protocol_engine/state/modules.py +52 -70
- opentrons/protocol_engine/state/motion.py +6 -1
- opentrons/protocol_engine/state/pipettes.py +149 -58
- opentrons/protocol_engine/state/state.py +21 -2
- opentrons/protocol_engine/state/state_summary.py +4 -2
- opentrons/protocol_engine/state/tips.py +11 -44
- opentrons/protocol_engine/state/update_types.py +343 -48
- opentrons/protocol_engine/state/wells.py +19 -11
- opentrons/protocol_engine/types.py +176 -28
- opentrons/protocol_reader/extract_labware_definitions.py +5 -2
- opentrons/protocol_reader/file_format_validator.py +5 -5
- opentrons/protocol_runner/json_file_reader.py +9 -3
- opentrons/protocol_runner/json_translator.py +51 -25
- opentrons/protocol_runner/legacy_command_mapper.py +66 -64
- opentrons/protocol_runner/protocol_runner.py +35 -4
- opentrons/protocol_runner/python_protocol_wrappers.py +1 -1
- opentrons/protocol_runner/run_orchestrator.py +13 -3
- opentrons/protocols/advanced_control/common.py +38 -0
- opentrons/protocols/advanced_control/mix.py +1 -1
- opentrons/protocols/advanced_control/transfers/__init__.py +0 -0
- opentrons/protocols/advanced_control/transfers/common.py +56 -0
- opentrons/protocols/advanced_control/{transfers.py → transfers/transfer.py} +10 -85
- opentrons/protocols/api_support/definitions.py +1 -1
- opentrons/protocols/api_support/instrument.py +1 -1
- opentrons/protocols/api_support/util.py +10 -0
- opentrons/protocols/labware.py +70 -8
- opentrons/protocols/models/json_protocol.py +5 -9
- opentrons/simulate.py +3 -1
- opentrons/types.py +162 -2
- opentrons/util/entrypoint_util.py +2 -5
- opentrons/util/logging_config.py +1 -1
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0.dist-info}/METADATA +16 -15
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0.dist-info}/RECORD +238 -208
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0.dist-info}/WHEEL +1 -1
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0.dist-info}/LICENSE +0 -0
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0.dist-info}/entry_points.txt +0 -0
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0.dist-info}/top_level.txt +0 -0
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
"""Drop tip command request, result, and implementation models."""
|
|
2
|
+
|
|
2
3
|
from __future__ import annotations
|
|
4
|
+
from typing import TYPE_CHECKING, Optional, Type, Any
|
|
3
5
|
|
|
4
6
|
from pydantic import Field
|
|
5
|
-
from
|
|
7
|
+
from pydantic.json_schema import SkipJsonSchema
|
|
8
|
+
|
|
6
9
|
from typing_extensions import Literal
|
|
7
10
|
|
|
8
11
|
from opentrons.protocol_engine.errors.exceptions import TipAttachedError
|
|
9
12
|
from opentrons.protocol_engine.resources.model_utils import ModelUtils
|
|
10
13
|
|
|
11
|
-
from ..state import
|
|
12
|
-
from ..types import DropTipWellLocation
|
|
14
|
+
from ..state.update_types import StateUpdate
|
|
15
|
+
from ..types import DropTipWellLocation
|
|
13
16
|
from .pipetting_common import (
|
|
14
17
|
PipetteIdMixin,
|
|
15
|
-
DestinationPositionResult,
|
|
16
18
|
TipPhysicallyAttachedError,
|
|
17
19
|
)
|
|
20
|
+
from .movement_common import (
|
|
21
|
+
DestinationPositionResult,
|
|
22
|
+
move_to_well,
|
|
23
|
+
StallOrCollisionError,
|
|
24
|
+
)
|
|
18
25
|
from .command import (
|
|
19
26
|
AbstractCommandImpl,
|
|
20
27
|
BaseCommand,
|
|
@@ -32,6 +39,10 @@ if TYPE_CHECKING:
|
|
|
32
39
|
DropTipCommandType = Literal["dropTip"]
|
|
33
40
|
|
|
34
41
|
|
|
42
|
+
def _remove_default(s: dict[str, Any]) -> None:
|
|
43
|
+
s.pop("default", None)
|
|
44
|
+
|
|
45
|
+
|
|
35
46
|
class DropTipParams(PipetteIdMixin):
|
|
36
47
|
"""Payload required to drop a tip in a specific well."""
|
|
37
48
|
|
|
@@ -41,15 +52,16 @@ class DropTipParams(PipetteIdMixin):
|
|
|
41
52
|
default_factory=DropTipWellLocation,
|
|
42
53
|
description="Relative well location at which to drop the tip.",
|
|
43
54
|
)
|
|
44
|
-
homeAfter:
|
|
55
|
+
homeAfter: bool | SkipJsonSchema[None] = Field(
|
|
45
56
|
None,
|
|
46
57
|
description=(
|
|
47
58
|
"Whether to home this pipette's plunger after dropping the tip."
|
|
48
59
|
" You should normally leave this unspecified to let the robot choose"
|
|
49
60
|
" a safe default depending on its hardware."
|
|
50
61
|
),
|
|
62
|
+
json_schema_extra=_remove_default,
|
|
51
63
|
)
|
|
52
|
-
alternateDropLocation:
|
|
64
|
+
alternateDropLocation: bool | SkipJsonSchema[None] = Field(
|
|
53
65
|
False,
|
|
54
66
|
description=(
|
|
55
67
|
"Whether to alternate location where tip is dropped within the labware."
|
|
@@ -58,6 +70,7 @@ class DropTipParams(PipetteIdMixin):
|
|
|
58
70
|
" labware well."
|
|
59
71
|
" If False, the tip will be dropped at the top center of the well."
|
|
60
72
|
),
|
|
73
|
+
json_schema_extra=_remove_default,
|
|
61
74
|
)
|
|
62
75
|
|
|
63
76
|
|
|
@@ -68,7 +81,9 @@ class DropTipResult(DestinationPositionResult):
|
|
|
68
81
|
|
|
69
82
|
|
|
70
83
|
_ExecuteReturn = (
|
|
71
|
-
SuccessData[DropTipResult]
|
|
84
|
+
SuccessData[DropTipResult]
|
|
85
|
+
| DefinedErrorData[TipPhysicallyAttachedError]
|
|
86
|
+
| DefinedErrorData[StallOrCollisionError]
|
|
72
87
|
)
|
|
73
88
|
|
|
74
89
|
|
|
@@ -95,8 +110,6 @@ class DropTipImplementation(AbstractCommandImpl[DropTipParams, _ExecuteReturn]):
|
|
|
95
110
|
well_name = params.wellName
|
|
96
111
|
home_after = params.homeAfter
|
|
97
112
|
|
|
98
|
-
state_update = update_types.StateUpdate()
|
|
99
|
-
|
|
100
113
|
if params.alternateDropLocation:
|
|
101
114
|
well_location = self._state_view.geometry.get_next_tip_drop_location(
|
|
102
115
|
labware_id=labware_id,
|
|
@@ -116,19 +129,16 @@ class DropTipImplementation(AbstractCommandImpl[DropTipParams, _ExecuteReturn]):
|
|
|
116
129
|
partially_configured=is_partially_configured,
|
|
117
130
|
)
|
|
118
131
|
|
|
119
|
-
|
|
132
|
+
move_result = await move_to_well(
|
|
133
|
+
movement=self._movement_handler,
|
|
134
|
+
model_utils=self._model_utils,
|
|
120
135
|
pipette_id=pipette_id,
|
|
121
136
|
labware_id=labware_id,
|
|
122
137
|
well_name=well_name,
|
|
123
138
|
well_location=tip_drop_location,
|
|
124
139
|
)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
pipette_id=pipette_id,
|
|
128
|
-
new_labware_id=labware_id,
|
|
129
|
-
new_well_name=well_name,
|
|
130
|
-
new_deck_point=deck_point,
|
|
131
|
-
)
|
|
140
|
+
if isinstance(move_result, DefinedErrorData):
|
|
141
|
+
return move_result
|
|
132
142
|
|
|
133
143
|
try:
|
|
134
144
|
await self._tip_handler.drop_tip(
|
|
@@ -145,33 +155,44 @@ class DropTipImplementation(AbstractCommandImpl[DropTipParams, _ExecuteReturn]):
|
|
|
145
155
|
error=exception,
|
|
146
156
|
)
|
|
147
157
|
],
|
|
148
|
-
errorInfo={
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
158
|
+
errorInfo={
|
|
159
|
+
"retryLocation": (
|
|
160
|
+
move_result.public.position.x,
|
|
161
|
+
move_result.public.position.y,
|
|
162
|
+
move_result.public.position.z,
|
|
163
|
+
)
|
|
164
|
+
},
|
|
153
165
|
)
|
|
154
166
|
return DefinedErrorData(
|
|
155
167
|
public=error,
|
|
156
|
-
state_update=
|
|
157
|
-
|
|
168
|
+
state_update=StateUpdate.reduce(
|
|
169
|
+
StateUpdate(), move_result.state_update
|
|
170
|
+
).set_fluid_unknown(pipette_id=pipette_id),
|
|
171
|
+
state_update_if_false_positive=move_result.state_update.update_pipette_tip_state(
|
|
172
|
+
pipette_id=params.pipetteId, tip_geometry=None
|
|
173
|
+
),
|
|
158
174
|
)
|
|
159
175
|
else:
|
|
160
|
-
state_update.update_pipette_tip_state(
|
|
161
|
-
pipette_id=params.pipetteId, tip_geometry=None
|
|
162
|
-
)
|
|
163
176
|
return SuccessData(
|
|
164
|
-
public=DropTipResult(position=
|
|
165
|
-
state_update=state_update
|
|
177
|
+
public=DropTipResult(position=move_result.public.position),
|
|
178
|
+
state_update=move_result.state_update.set_fluid_unknown(
|
|
179
|
+
pipette_id=pipette_id
|
|
180
|
+
).update_pipette_tip_state(
|
|
181
|
+
pipette_id=params.pipetteId, tip_geometry=None
|
|
182
|
+
),
|
|
166
183
|
)
|
|
167
184
|
|
|
168
185
|
|
|
169
|
-
class DropTip(
|
|
186
|
+
class DropTip(
|
|
187
|
+
BaseCommand[
|
|
188
|
+
DropTipParams, DropTipResult, TipPhysicallyAttachedError | StallOrCollisionError
|
|
189
|
+
]
|
|
190
|
+
):
|
|
170
191
|
"""Drop tip command model."""
|
|
171
192
|
|
|
172
193
|
commandType: DropTipCommandType = "dropTip"
|
|
173
194
|
params: DropTipParams
|
|
174
|
-
result: Optional[DropTipResult]
|
|
195
|
+
result: Optional[DropTipResult] = None
|
|
175
196
|
|
|
176
197
|
_ImplementationCls: Type[DropTipImplementation] = DropTipImplementation
|
|
177
198
|
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
"""Drop tip in place command request, result, and implementation models."""
|
|
2
2
|
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import TYPE_CHECKING, Optional, Type, Any, Union
|
|
5
|
+
|
|
3
6
|
from pydantic import Field, BaseModel
|
|
4
|
-
from
|
|
7
|
+
from pydantic.json_schema import SkipJsonSchema
|
|
5
8
|
from typing_extensions import Literal
|
|
6
9
|
|
|
10
|
+
from opentrons_shared_data.errors.exceptions import (
|
|
11
|
+
PipetteOverpressureError,
|
|
12
|
+
StallOrCollisionDetectedError,
|
|
13
|
+
)
|
|
14
|
+
|
|
7
15
|
from .command import (
|
|
8
16
|
AbstractCommandImpl,
|
|
9
17
|
BaseCommand,
|
|
@@ -11,7 +19,12 @@ from .command import (
|
|
|
11
19
|
DefinedErrorData,
|
|
12
20
|
SuccessData,
|
|
13
21
|
)
|
|
14
|
-
from .
|
|
22
|
+
from .movement_common import StallOrCollisionError
|
|
23
|
+
from .pipetting_common import (
|
|
24
|
+
PipetteIdMixin,
|
|
25
|
+
TipPhysicallyAttachedError,
|
|
26
|
+
OverpressureError,
|
|
27
|
+
)
|
|
15
28
|
from ..errors.exceptions import TipAttachedError
|
|
16
29
|
from ..errors.error_occurrence import ErrorOccurrence
|
|
17
30
|
from ..resources.model_utils import ModelUtils
|
|
@@ -24,16 +37,21 @@ if TYPE_CHECKING:
|
|
|
24
37
|
DropTipInPlaceCommandType = Literal["dropTipInPlace"]
|
|
25
38
|
|
|
26
39
|
|
|
40
|
+
def _remove_default(s: dict[str, Any]) -> None:
|
|
41
|
+
s.pop("default", None)
|
|
42
|
+
|
|
43
|
+
|
|
27
44
|
class DropTipInPlaceParams(PipetteIdMixin):
|
|
28
45
|
"""Payload required to drop a tip in place."""
|
|
29
46
|
|
|
30
|
-
homeAfter:
|
|
47
|
+
homeAfter: bool | SkipJsonSchema[None] = Field(
|
|
31
48
|
None,
|
|
32
49
|
description=(
|
|
33
50
|
"Whether to home this pipette's plunger after dropping the tip."
|
|
34
51
|
" You should normally leave this unspecified to let the robot choose"
|
|
35
52
|
" a safe default depending on its hardware."
|
|
36
53
|
),
|
|
54
|
+
json_schema_extra=_remove_default,
|
|
37
55
|
)
|
|
38
56
|
|
|
39
57
|
|
|
@@ -43,9 +61,12 @@ class DropTipInPlaceResult(BaseModel):
|
|
|
43
61
|
pass
|
|
44
62
|
|
|
45
63
|
|
|
46
|
-
_ExecuteReturn =
|
|
47
|
-
SuccessData[DropTipInPlaceResult]
|
|
48
|
-
|
|
64
|
+
_ExecuteReturn = Union[
|
|
65
|
+
SuccessData[DropTipInPlaceResult]
|
|
66
|
+
| DefinedErrorData[TipPhysicallyAttachedError]
|
|
67
|
+
| DefinedErrorData[OverpressureError]
|
|
68
|
+
| DefinedErrorData[StallOrCollisionError]
|
|
69
|
+
]
|
|
49
70
|
|
|
50
71
|
|
|
51
72
|
class DropTipInPlaceImplementation(
|
|
@@ -79,6 +100,7 @@ class DropTipInPlaceImplementation(
|
|
|
79
100
|
state_update_if_false_positive.update_pipette_tip_state(
|
|
80
101
|
pipette_id=params.pipetteId, tip_geometry=None
|
|
81
102
|
)
|
|
103
|
+
state_update.set_fluid_unknown(pipette_id=params.pipetteId)
|
|
82
104
|
error = TipPhysicallyAttachedError(
|
|
83
105
|
id=self._model_utils.generate_id(),
|
|
84
106
|
createdAt=self._model_utils.get_timestamp(),
|
|
@@ -96,7 +118,52 @@ class DropTipInPlaceImplementation(
|
|
|
96
118
|
state_update=state_update,
|
|
97
119
|
state_update_if_false_positive=state_update_if_false_positive,
|
|
98
120
|
)
|
|
121
|
+
except PipetteOverpressureError as exception:
|
|
122
|
+
state_update_if_false_positive = update_types.StateUpdate()
|
|
123
|
+
state_update_if_false_positive.update_pipette_tip_state(
|
|
124
|
+
pipette_id=params.pipetteId, tip_geometry=None
|
|
125
|
+
)
|
|
126
|
+
state_update.set_fluid_unknown(pipette_id=params.pipetteId)
|
|
127
|
+
return DefinedErrorData(
|
|
128
|
+
public=OverpressureError(
|
|
129
|
+
id=self._model_utils.generate_id(),
|
|
130
|
+
createdAt=self._model_utils.get_timestamp(),
|
|
131
|
+
wrappedErrors=[
|
|
132
|
+
ErrorOccurrence.from_failed(
|
|
133
|
+
id=self._model_utils.generate_id(),
|
|
134
|
+
createdAt=self._model_utils.get_timestamp(),
|
|
135
|
+
error=exception,
|
|
136
|
+
)
|
|
137
|
+
],
|
|
138
|
+
errorInfo={"retryLocation": retry_location},
|
|
139
|
+
),
|
|
140
|
+
state_update=state_update,
|
|
141
|
+
state_update_if_false_positive=state_update_if_false_positive,
|
|
142
|
+
)
|
|
143
|
+
except StallOrCollisionDetectedError as exception:
|
|
144
|
+
state_update_if_false_positive = update_types.StateUpdate()
|
|
145
|
+
state_update_if_false_positive.update_pipette_tip_state(
|
|
146
|
+
pipette_id=params.pipetteId, tip_geometry=None
|
|
147
|
+
)
|
|
148
|
+
state_update.set_fluid_unknown(pipette_id=params.pipetteId)
|
|
149
|
+
return DefinedErrorData(
|
|
150
|
+
public=StallOrCollisionError(
|
|
151
|
+
id=self._model_utils.generate_id(),
|
|
152
|
+
createdAt=self._model_utils.get_timestamp(),
|
|
153
|
+
wrappedErrors=[
|
|
154
|
+
ErrorOccurrence.from_failed(
|
|
155
|
+
id=self._model_utils.generate_id(),
|
|
156
|
+
createdAt=self._model_utils.get_timestamp(),
|
|
157
|
+
error=exception,
|
|
158
|
+
)
|
|
159
|
+
],
|
|
160
|
+
errorInfo={"retryLocation": retry_location},
|
|
161
|
+
),
|
|
162
|
+
state_update=state_update,
|
|
163
|
+
state_update_if_false_positive=state_update_if_false_positive,
|
|
164
|
+
)
|
|
99
165
|
else:
|
|
166
|
+
state_update.set_fluid_unknown(pipette_id=params.pipetteId)
|
|
100
167
|
state_update.update_pipette_tip_state(
|
|
101
168
|
pipette_id=params.pipetteId, tip_geometry=None
|
|
102
169
|
)
|
|
@@ -104,13 +171,17 @@ class DropTipInPlaceImplementation(
|
|
|
104
171
|
|
|
105
172
|
|
|
106
173
|
class DropTipInPlace(
|
|
107
|
-
BaseCommand[
|
|
174
|
+
BaseCommand[
|
|
175
|
+
DropTipInPlaceParams,
|
|
176
|
+
DropTipInPlaceResult,
|
|
177
|
+
TipPhysicallyAttachedError | OverpressureError | StallOrCollisionError,
|
|
178
|
+
]
|
|
108
179
|
):
|
|
109
180
|
"""Drop tip in place command model."""
|
|
110
181
|
|
|
111
182
|
commandType: DropTipInPlaceCommandType = "dropTipInPlace"
|
|
112
183
|
params: DropTipInPlaceParams
|
|
113
|
-
result: Optional[DropTipInPlaceResult]
|
|
184
|
+
result: Optional[DropTipInPlaceResult] = None
|
|
114
185
|
|
|
115
186
|
_ImplementationCls: Type[
|
|
116
187
|
DropTipInPlaceImplementation
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"""Evotip Dispense-in-place command request, result, and implementation models."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
from typing import TYPE_CHECKING, Optional, Type, Union
|
|
5
|
+
from typing_extensions import Literal
|
|
6
|
+
|
|
7
|
+
from opentrons.protocol_engine.errors import UnsupportedLabwareForActionError
|
|
8
|
+
from .pipetting_common import (
|
|
9
|
+
PipetteIdMixin,
|
|
10
|
+
FlowRateMixin,
|
|
11
|
+
DispenseVolumeMixin,
|
|
12
|
+
BaseLiquidHandlingResult,
|
|
13
|
+
dispense_in_place,
|
|
14
|
+
)
|
|
15
|
+
from .movement_common import (
|
|
16
|
+
LiquidHandlingWellLocationMixin,
|
|
17
|
+
StallOrCollisionError,
|
|
18
|
+
move_to_well,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
from .command import (
|
|
22
|
+
AbstractCommandImpl,
|
|
23
|
+
BaseCommand,
|
|
24
|
+
BaseCommandCreate,
|
|
25
|
+
SuccessData,
|
|
26
|
+
DefinedErrorData,
|
|
27
|
+
)
|
|
28
|
+
from ..state.update_types import StateUpdate
|
|
29
|
+
from ..resources import labware_validation
|
|
30
|
+
from ..errors import ProtocolEngineError
|
|
31
|
+
|
|
32
|
+
if TYPE_CHECKING:
|
|
33
|
+
from ..execution import PipettingHandler, GantryMover, MovementHandler
|
|
34
|
+
from ..resources import ModelUtils
|
|
35
|
+
from ..state.state import StateView
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
EvotipDispenseCommandType = Literal["evotipDispense"]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class EvotipDispenseParams(
|
|
42
|
+
PipetteIdMixin, DispenseVolumeMixin, FlowRateMixin, LiquidHandlingWellLocationMixin
|
|
43
|
+
):
|
|
44
|
+
"""Payload required to dispense in place."""
|
|
45
|
+
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class EvotipDispenseResult(BaseLiquidHandlingResult):
|
|
50
|
+
"""Result data from the execution of a DispenseInPlace command."""
|
|
51
|
+
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
_ExecuteReturn = Union[
|
|
56
|
+
SuccessData[EvotipDispenseResult],
|
|
57
|
+
DefinedErrorData[StallOrCollisionError],
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class EvotipDispenseImplementation(
|
|
62
|
+
AbstractCommandImpl[EvotipDispenseParams, _ExecuteReturn]
|
|
63
|
+
):
|
|
64
|
+
"""DispenseInPlace command implementation."""
|
|
65
|
+
|
|
66
|
+
def __init__(
|
|
67
|
+
self,
|
|
68
|
+
pipetting: PipettingHandler,
|
|
69
|
+
state_view: StateView,
|
|
70
|
+
gantry_mover: GantryMover,
|
|
71
|
+
model_utils: ModelUtils,
|
|
72
|
+
movement: MovementHandler,
|
|
73
|
+
**kwargs: object,
|
|
74
|
+
) -> None:
|
|
75
|
+
self._pipetting = pipetting
|
|
76
|
+
self._state_view = state_view
|
|
77
|
+
self._gantry_mover = gantry_mover
|
|
78
|
+
self._model_utils = model_utils
|
|
79
|
+
self._movement = movement
|
|
80
|
+
|
|
81
|
+
async def execute(self, params: EvotipDispenseParams) -> _ExecuteReturn:
|
|
82
|
+
"""Move to and dispense to the requested well."""
|
|
83
|
+
well_location = params.wellLocation
|
|
84
|
+
labware_id = params.labwareId
|
|
85
|
+
well_name = params.wellName
|
|
86
|
+
|
|
87
|
+
labware_definition = self._state_view.labware.get_definition(params.labwareId)
|
|
88
|
+
if not labware_validation.is_evotips(labware_definition.parameters.loadName):
|
|
89
|
+
raise UnsupportedLabwareForActionError(
|
|
90
|
+
f"Cannot use command: `EvotipDispense` with labware: {labware_definition.parameters.loadName}"
|
|
91
|
+
)
|
|
92
|
+
move_result = await move_to_well(
|
|
93
|
+
movement=self._movement,
|
|
94
|
+
model_utils=self._model_utils,
|
|
95
|
+
pipette_id=params.pipetteId,
|
|
96
|
+
labware_id=labware_id,
|
|
97
|
+
well_name=well_name,
|
|
98
|
+
well_location=well_location,
|
|
99
|
+
)
|
|
100
|
+
if isinstance(move_result, DefinedErrorData):
|
|
101
|
+
return move_result
|
|
102
|
+
|
|
103
|
+
current_position = await self._gantry_mover.get_position(params.pipetteId)
|
|
104
|
+
result = await dispense_in_place(
|
|
105
|
+
pipette_id=params.pipetteId,
|
|
106
|
+
volume=params.volume,
|
|
107
|
+
flow_rate=params.flowRate,
|
|
108
|
+
push_out=None,
|
|
109
|
+
location_if_error={
|
|
110
|
+
"retryLocation": (
|
|
111
|
+
current_position.x,
|
|
112
|
+
current_position.y,
|
|
113
|
+
current_position.z,
|
|
114
|
+
)
|
|
115
|
+
},
|
|
116
|
+
pipetting=self._pipetting,
|
|
117
|
+
model_utils=self._model_utils,
|
|
118
|
+
)
|
|
119
|
+
if isinstance(result, DefinedErrorData):
|
|
120
|
+
# TODO (chb, 2025-01-29): Remove this and the OverpressureError returns once disabled for this function
|
|
121
|
+
raise ProtocolEngineError(
|
|
122
|
+
message="Overpressure Error during Resin Tip Dispense Command."
|
|
123
|
+
)
|
|
124
|
+
return SuccessData(
|
|
125
|
+
public=EvotipDispenseResult(volume=result.public.volume),
|
|
126
|
+
state_update=StateUpdate.reduce(
|
|
127
|
+
move_result.state_update, result.state_update
|
|
128
|
+
),
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
class EvotipDispense(
|
|
133
|
+
BaseCommand[
|
|
134
|
+
EvotipDispenseParams,
|
|
135
|
+
EvotipDispenseResult,
|
|
136
|
+
StallOrCollisionError,
|
|
137
|
+
]
|
|
138
|
+
):
|
|
139
|
+
"""DispenseInPlace command model."""
|
|
140
|
+
|
|
141
|
+
commandType: EvotipDispenseCommandType = "evotipDispense"
|
|
142
|
+
params: EvotipDispenseParams
|
|
143
|
+
result: Optional[EvotipDispenseResult] = None
|
|
144
|
+
|
|
145
|
+
_ImplementationCls: Type[
|
|
146
|
+
EvotipDispenseImplementation
|
|
147
|
+
] = EvotipDispenseImplementation
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class EvotipDispenseCreate(BaseCommandCreate[EvotipDispenseParams]):
|
|
151
|
+
"""DispenseInPlace command request model."""
|
|
152
|
+
|
|
153
|
+
commandType: EvotipDispenseCommandType = "evotipDispense"
|
|
154
|
+
params: EvotipDispenseParams
|
|
155
|
+
|
|
156
|
+
_CommandCls: Type[EvotipDispense] = EvotipDispense
|