opentrons 8.2.0a3__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.
- 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 +40 -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 +4 -2
- 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 +56 -71
- 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.0a3.dist-info → opentrons-8.3.0.dist-info}/METADATA +16 -15
- {opentrons-8.2.0a3.dist-info → opentrons-8.3.0.dist-info}/RECORD +238 -208
- {opentrons-8.2.0a3.dist-info → opentrons-8.3.0.dist-info}/WHEEL +1 -1
- {opentrons-8.2.0a3.dist-info → opentrons-8.3.0.dist-info}/LICENSE +0 -0
- {opentrons-8.2.0a3.dist-info → opentrons-8.3.0.dist-info}/entry_points.txt +0 -0
- {opentrons-8.2.0a3.dist-info → opentrons-8.3.0.dist-info}/top_level.txt +0 -0
|
@@ -96,7 +96,7 @@ class OpenLabwareLatch(
|
|
|
96
96
|
|
|
97
97
|
commandType: OpenLabwareLatchCommandType = "heaterShaker/openLabwareLatch"
|
|
98
98
|
params: OpenLabwareLatchParams
|
|
99
|
-
result: Optional[OpenLabwareLatchResult]
|
|
99
|
+
result: Optional[OpenLabwareLatchResult] = None
|
|
100
100
|
|
|
101
101
|
_ImplementationCls: Type[OpenLabwareLatchImpl] = OpenLabwareLatchImpl
|
|
102
102
|
|
|
@@ -109,7 +109,7 @@ class SetAndWaitForShakeSpeed(
|
|
|
109
109
|
"heaterShaker/setAndWaitForShakeSpeed"
|
|
110
110
|
)
|
|
111
111
|
params: SetAndWaitForShakeSpeedParams
|
|
112
|
-
result: Optional[SetAndWaitForShakeSpeedResult]
|
|
112
|
+
result: Optional[SetAndWaitForShakeSpeedResult] = None
|
|
113
113
|
|
|
114
114
|
_ImplementationCls: Type[SetAndWaitForShakeSpeedImpl] = SetAndWaitForShakeSpeedImpl
|
|
115
115
|
|
|
@@ -76,7 +76,7 @@ class SetTargetTemperature(
|
|
|
76
76
|
|
|
77
77
|
commandType: SetTargetTemperatureCommandType = "heaterShaker/setTargetTemperature"
|
|
78
78
|
params: SetTargetTemperatureParams
|
|
79
|
-
result: Optional[SetTargetTemperatureResult]
|
|
79
|
+
result: Optional[SetTargetTemperatureResult] = None
|
|
80
80
|
|
|
81
81
|
_ImplementationCls: Type[SetTargetTemperatureImpl] = SetTargetTemperatureImpl
|
|
82
82
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"""Command models to wait for a Heater-Shaker Module's target temperature."""
|
|
2
2
|
from __future__ import annotations
|
|
3
|
-
from typing import Optional, TYPE_CHECKING
|
|
4
|
-
from typing_extensions import Literal, Type
|
|
3
|
+
from typing import Optional, TYPE_CHECKING, Any
|
|
5
4
|
|
|
5
|
+
from typing_extensions import Literal, Type
|
|
6
6
|
from pydantic import BaseModel, Field
|
|
7
|
+
from pydantic.json_schema import SkipJsonSchema
|
|
7
8
|
|
|
8
9
|
from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
|
|
9
10
|
from ...errors.error_occurrence import ErrorOccurrence
|
|
@@ -16,11 +17,15 @@ if TYPE_CHECKING:
|
|
|
16
17
|
WaitForTemperatureCommandType = Literal["heaterShaker/waitForTemperature"]
|
|
17
18
|
|
|
18
19
|
|
|
20
|
+
def _remove_default(s: dict[str, Any]) -> None:
|
|
21
|
+
s.pop("default", None)
|
|
22
|
+
|
|
23
|
+
|
|
19
24
|
class WaitForTemperatureParams(BaseModel):
|
|
20
25
|
"""Input parameters to wait for a Heater-Shaker's target temperature."""
|
|
21
26
|
|
|
22
27
|
moduleId: str = Field(..., description="Unique ID of the Heater-Shaker Module.")
|
|
23
|
-
celsius:
|
|
28
|
+
celsius: float | SkipJsonSchema[None] = Field(
|
|
24
29
|
None,
|
|
25
30
|
description="Target temperature in °C. If not specified, will "
|
|
26
31
|
"default to the module's target temperature. "
|
|
@@ -28,6 +33,7 @@ class WaitForTemperatureParams(BaseModel):
|
|
|
28
33
|
"could lead to unpredictable behavior and hence is not "
|
|
29
34
|
"recommended for use. This parameter can be removed in a "
|
|
30
35
|
"future version without prior notice.",
|
|
36
|
+
json_schema_extra=_remove_default,
|
|
31
37
|
)
|
|
32
38
|
|
|
33
39
|
|
|
@@ -82,7 +88,7 @@ class WaitForTemperature(
|
|
|
82
88
|
|
|
83
89
|
commandType: WaitForTemperatureCommandType = "heaterShaker/waitForTemperature"
|
|
84
90
|
params: WaitForTemperatureParams
|
|
85
|
-
result: Optional[WaitForTemperatureResult]
|
|
91
|
+
result: Optional[WaitForTemperatureResult] = None
|
|
86
92
|
|
|
87
93
|
_ImplementationCls: Type[WaitForTemperatureImpl] = WaitForTemperatureImpl
|
|
88
94
|
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"""Home command payload, result, and implementation models."""
|
|
2
2
|
from __future__ import annotations
|
|
3
|
+
from typing import TYPE_CHECKING, Optional, List, Type, Any
|
|
4
|
+
|
|
3
5
|
from pydantic import BaseModel, Field
|
|
4
|
-
from
|
|
6
|
+
from pydantic.json_schema import SkipJsonSchema
|
|
7
|
+
|
|
5
8
|
from typing_extensions import Literal
|
|
6
9
|
|
|
7
10
|
from opentrons.types import MountType
|
|
@@ -17,24 +20,30 @@ if TYPE_CHECKING:
|
|
|
17
20
|
HomeCommandType = Literal["home"]
|
|
18
21
|
|
|
19
22
|
|
|
23
|
+
def _remove_default(s: dict[str, Any]) -> None:
|
|
24
|
+
s.pop("default", None)
|
|
25
|
+
|
|
26
|
+
|
|
20
27
|
class HomeParams(BaseModel):
|
|
21
28
|
"""Payload required for a Home command."""
|
|
22
29
|
|
|
23
|
-
axes:
|
|
30
|
+
axes: List[MotorAxis] | SkipJsonSchema[None] = Field(
|
|
24
31
|
None,
|
|
25
32
|
description=(
|
|
26
33
|
"Axes to return to their home positions. If omitted,"
|
|
27
34
|
" will home all motors. Extra axes may be implicitly homed"
|
|
28
35
|
" to ensure accurate homing of the explicitly specified axes."
|
|
29
36
|
),
|
|
37
|
+
json_schema_extra=_remove_default,
|
|
30
38
|
)
|
|
31
|
-
skipIfMountPositionOk:
|
|
39
|
+
skipIfMountPositionOk: MountType | SkipJsonSchema[None] = Field(
|
|
32
40
|
None,
|
|
33
41
|
description=(
|
|
34
42
|
"If this parameter is provided, the gantry will only be homed if the"
|
|
35
43
|
" specified mount has an invalid position. If omitted, the homing action"
|
|
36
44
|
" will be executed unconditionally."
|
|
37
45
|
),
|
|
46
|
+
json_schema_extra=_remove_default,
|
|
38
47
|
)
|
|
39
48
|
|
|
40
49
|
|
|
@@ -77,7 +86,7 @@ class Home(BaseCommand[HomeParams, HomeResult, ErrorOccurrence]):
|
|
|
77
86
|
|
|
78
87
|
commandType: HomeCommandType = "home"
|
|
79
88
|
params: HomeParams
|
|
80
|
-
result: Optional[HomeResult]
|
|
89
|
+
result: Optional[HomeResult] = None
|
|
81
90
|
|
|
82
91
|
_ImplementationCls: Type[HomeImplementation] = HomeImplementation
|
|
83
92
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"""The liquidProbe and tryLiquidProbe commands."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
|
-
from typing import TYPE_CHECKING, NamedTuple, Optional, Type, Union
|
|
5
|
-
from typing_extensions import Literal
|
|
4
|
+
from typing import TYPE_CHECKING, NamedTuple, Optional, Type, Union, Any
|
|
6
5
|
|
|
6
|
+
from typing_extensions import Literal
|
|
7
7
|
from pydantic import Field
|
|
8
|
+
from pydantic.json_schema import SkipJsonSchema
|
|
8
9
|
|
|
9
10
|
from opentrons.protocol_engine.state import update_types
|
|
10
11
|
from opentrons.protocol_engine.errors.exceptions import (
|
|
@@ -12,18 +13,26 @@ from opentrons.protocol_engine.errors.exceptions import (
|
|
|
12
13
|
PipetteNotReadyToAspirateError,
|
|
13
14
|
TipNotEmptyError,
|
|
14
15
|
IncompleteLabwareDefinitionError,
|
|
16
|
+
TipNotAttachedError,
|
|
15
17
|
)
|
|
16
18
|
from opentrons.types import MountType
|
|
17
19
|
from opentrons_shared_data.errors.exceptions import (
|
|
18
20
|
PipetteLiquidNotFoundError,
|
|
21
|
+
UnsupportedHardwareCommand,
|
|
22
|
+
PipetteOverpressureError,
|
|
19
23
|
)
|
|
20
24
|
|
|
21
25
|
from ..types import DeckPoint
|
|
22
26
|
from .pipetting_common import (
|
|
23
27
|
LiquidNotFoundError,
|
|
24
28
|
PipetteIdMixin,
|
|
29
|
+
OverpressureError,
|
|
30
|
+
)
|
|
31
|
+
from .movement_common import (
|
|
25
32
|
WellLocationMixin,
|
|
26
33
|
DestinationPositionResult,
|
|
34
|
+
StallOrCollisionError,
|
|
35
|
+
move_to_well,
|
|
27
36
|
)
|
|
28
37
|
from .command import (
|
|
29
38
|
AbstractCommandImpl,
|
|
@@ -36,11 +45,15 @@ from .command import (
|
|
|
36
45
|
from ..errors.error_occurrence import ErrorOccurrence
|
|
37
46
|
|
|
38
47
|
if TYPE_CHECKING:
|
|
39
|
-
from ..execution import MovementHandler, PipettingHandler
|
|
48
|
+
from ..execution import MovementHandler, PipettingHandler, GantryMover
|
|
40
49
|
from ..resources import ModelUtils
|
|
41
50
|
from ..state.state import StateView
|
|
42
51
|
|
|
43
52
|
|
|
53
|
+
def _remove_default(s: dict[str, Any]) -> None:
|
|
54
|
+
s.pop("default", None)
|
|
55
|
+
|
|
56
|
+
|
|
44
57
|
LiquidProbeCommandType = Literal["liquidProbe"]
|
|
45
58
|
TryLiquidProbeCommandType = Literal["tryLiquidProbe"]
|
|
46
59
|
|
|
@@ -76,43 +89,64 @@ class LiquidProbeResult(DestinationPositionResult):
|
|
|
76
89
|
class TryLiquidProbeResult(DestinationPositionResult):
|
|
77
90
|
"""Result data from the execution of a `tryLiquidProbe` command."""
|
|
78
91
|
|
|
79
|
-
z_position:
|
|
92
|
+
z_position: float | SkipJsonSchema[None] = Field(
|
|
80
93
|
...,
|
|
81
94
|
description=(
|
|
82
95
|
"The Z coordinate, in mm, of the found liquid in deck space."
|
|
83
96
|
" If no liquid was found, `null` or omitted."
|
|
84
97
|
),
|
|
98
|
+
json_schema_extra=_remove_default,
|
|
85
99
|
)
|
|
86
100
|
|
|
87
101
|
|
|
88
102
|
_LiquidProbeExecuteReturn = Union[
|
|
89
103
|
SuccessData[LiquidProbeResult],
|
|
90
|
-
DefinedErrorData[LiquidNotFoundError]
|
|
104
|
+
DefinedErrorData[LiquidNotFoundError]
|
|
105
|
+
| DefinedErrorData[StallOrCollisionError]
|
|
106
|
+
| DefinedErrorData[OverpressureError],
|
|
91
107
|
]
|
|
92
|
-
_TryLiquidProbeExecuteReturn =
|
|
108
|
+
_TryLiquidProbeExecuteReturn = (
|
|
109
|
+
SuccessData[TryLiquidProbeResult]
|
|
110
|
+
| DefinedErrorData[StallOrCollisionError]
|
|
111
|
+
| DefinedErrorData[OverpressureError]
|
|
112
|
+
)
|
|
93
113
|
|
|
94
114
|
|
|
95
115
|
class _ExecuteCommonResult(NamedTuple):
|
|
96
116
|
# If the probe succeeded, the z_pos that it returned.
|
|
97
117
|
# Or, if the probe found no liquid, the error representing that,
|
|
98
118
|
# so calling code can propagate those details up.
|
|
99
|
-
z_pos_or_error: float | PipetteLiquidNotFoundError
|
|
119
|
+
z_pos_or_error: float | PipetteLiquidNotFoundError | PipetteOverpressureError
|
|
100
120
|
|
|
101
121
|
state_update: update_types.StateUpdate
|
|
102
122
|
deck_point: DeckPoint
|
|
103
123
|
|
|
104
124
|
|
|
105
|
-
async def _execute_common(
|
|
125
|
+
async def _execute_common( # noqa: C901
|
|
106
126
|
state_view: StateView,
|
|
107
127
|
movement: MovementHandler,
|
|
128
|
+
gantry_mover: GantryMover,
|
|
108
129
|
pipetting: PipettingHandler,
|
|
130
|
+
model_utils: ModelUtils,
|
|
109
131
|
params: _CommonParams,
|
|
110
|
-
) -> _ExecuteCommonResult
|
|
132
|
+
) -> _ExecuteCommonResult | DefinedErrorData[StallOrCollisionError] | DefinedErrorData[
|
|
133
|
+
OverpressureError
|
|
134
|
+
]:
|
|
111
135
|
pipette_id = params.pipetteId
|
|
112
136
|
labware_id = params.labwareId
|
|
113
137
|
well_name = params.wellName
|
|
138
|
+
if (
|
|
139
|
+
"pressure"
|
|
140
|
+
not in state_view.pipettes.get_config(pipette_id).available_sensors.sensors
|
|
141
|
+
):
|
|
142
|
+
raise UnsupportedHardwareCommand(
|
|
143
|
+
"Pressure sensor not available for this pipette"
|
|
144
|
+
)
|
|
114
145
|
|
|
115
|
-
|
|
146
|
+
if not state_view.pipettes.get_nozzle_configuration_supports_lld(pipette_id):
|
|
147
|
+
raise TipNotAttachedError(
|
|
148
|
+
"Either the front right or back left nozzle must have a tip attached to probe liquid height."
|
|
149
|
+
)
|
|
116
150
|
|
|
117
151
|
# May raise TipNotAttachedError.
|
|
118
152
|
aspirated_volume = state_view.pipettes.get_aspirated_volume(pipette_id)
|
|
@@ -137,21 +171,18 @@ async def _execute_common(
|
|
|
137
171
|
)
|
|
138
172
|
|
|
139
173
|
# liquid_probe process start position
|
|
140
|
-
|
|
174
|
+
move_result = await move_to_well(
|
|
175
|
+
movement=movement,
|
|
176
|
+
model_utils=model_utils,
|
|
141
177
|
pipette_id=pipette_id,
|
|
142
178
|
labware_id=labware_id,
|
|
143
179
|
well_name=well_name,
|
|
144
180
|
well_location=params.wellLocation,
|
|
145
181
|
)
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
pipette_id=pipette_id,
|
|
149
|
-
new_labware_id=labware_id,
|
|
150
|
-
new_well_name=well_name,
|
|
151
|
-
new_deck_point=deck_point,
|
|
152
|
-
)
|
|
153
|
-
|
|
182
|
+
if isinstance(move_result, DefinedErrorData):
|
|
183
|
+
return move_result
|
|
154
184
|
try:
|
|
185
|
+
current_position = await gantry_mover.get_position(params.pipetteId)
|
|
155
186
|
z_pos = await pipetting.liquid_probe_in_place(
|
|
156
187
|
pipette_id=pipette_id,
|
|
157
188
|
labware_id=labware_id,
|
|
@@ -160,11 +191,42 @@ async def _execute_common(
|
|
|
160
191
|
)
|
|
161
192
|
except PipetteLiquidNotFoundError as exception:
|
|
162
193
|
return _ExecuteCommonResult(
|
|
163
|
-
z_pos_or_error=exception,
|
|
194
|
+
z_pos_or_error=exception,
|
|
195
|
+
state_update=move_result.state_update,
|
|
196
|
+
deck_point=move_result.public.position,
|
|
197
|
+
)
|
|
198
|
+
except PipetteOverpressureError as e:
|
|
199
|
+
return DefinedErrorData(
|
|
200
|
+
public=OverpressureError(
|
|
201
|
+
id=model_utils.generate_id(),
|
|
202
|
+
createdAt=model_utils.get_timestamp(),
|
|
203
|
+
wrappedErrors=[
|
|
204
|
+
ErrorOccurrence.from_failed(
|
|
205
|
+
id=model_utils.generate_id(),
|
|
206
|
+
createdAt=model_utils.get_timestamp(),
|
|
207
|
+
error=e,
|
|
208
|
+
)
|
|
209
|
+
],
|
|
210
|
+
errorInfo=(
|
|
211
|
+
{
|
|
212
|
+
# This is here bc its not optional in the type but we are not using the retry location for this case
|
|
213
|
+
"retryLocation": (
|
|
214
|
+
current_position.x,
|
|
215
|
+
current_position.y,
|
|
216
|
+
current_position.z,
|
|
217
|
+
)
|
|
218
|
+
}
|
|
219
|
+
),
|
|
220
|
+
),
|
|
221
|
+
state_update=move_result.state_update.set_fluid_unknown(
|
|
222
|
+
pipette_id=pipette_id
|
|
223
|
+
),
|
|
164
224
|
)
|
|
165
225
|
else:
|
|
166
226
|
return _ExecuteCommonResult(
|
|
167
|
-
z_pos_or_error=z_pos,
|
|
227
|
+
z_pos_or_error=z_pos,
|
|
228
|
+
state_update=move_result.state_update,
|
|
229
|
+
deck_point=move_result.public.position,
|
|
168
230
|
)
|
|
169
231
|
|
|
170
232
|
|
|
@@ -177,12 +239,14 @@ class LiquidProbeImplementation(
|
|
|
177
239
|
self,
|
|
178
240
|
state_view: StateView,
|
|
179
241
|
movement: MovementHandler,
|
|
242
|
+
gantry_mover: GantryMover,
|
|
180
243
|
pipetting: PipettingHandler,
|
|
181
244
|
model_utils: ModelUtils,
|
|
182
245
|
**kwargs: object,
|
|
183
246
|
) -> None:
|
|
184
247
|
self._state_view = state_view
|
|
185
248
|
self._movement = movement
|
|
249
|
+
self._gantry_mover = gantry_mover
|
|
186
250
|
self._pipetting = pipetting
|
|
187
251
|
self._model_utils = model_utils
|
|
188
252
|
|
|
@@ -202,10 +266,20 @@ class LiquidProbeImplementation(
|
|
|
202
266
|
MustHomeError: as an undefined error, if the plunger is not in a valid
|
|
203
267
|
position.
|
|
204
268
|
"""
|
|
205
|
-
|
|
206
|
-
self._state_view,
|
|
269
|
+
result = await _execute_common(
|
|
270
|
+
state_view=self._state_view,
|
|
271
|
+
movement=self._movement,
|
|
272
|
+
gantry_mover=self._gantry_mover,
|
|
273
|
+
pipetting=self._pipetting,
|
|
274
|
+
model_utils=self._model_utils,
|
|
275
|
+
params=params,
|
|
207
276
|
)
|
|
208
|
-
if isinstance(
|
|
277
|
+
if isinstance(result, DefinedErrorData):
|
|
278
|
+
return result
|
|
279
|
+
z_pos_or_error, state_update, deck_point = result
|
|
280
|
+
if isinstance(
|
|
281
|
+
z_pos_or_error, (PipetteLiquidNotFoundError, PipetteOverpressureError)
|
|
282
|
+
):
|
|
209
283
|
state_update.set_liquid_probed(
|
|
210
284
|
labware_id=params.labwareId,
|
|
211
285
|
well_name=params.wellName,
|
|
@@ -262,12 +336,14 @@ class TryLiquidProbeImplementation(
|
|
|
262
336
|
self,
|
|
263
337
|
state_view: StateView,
|
|
264
338
|
movement: MovementHandler,
|
|
339
|
+
gantry_mover: GantryMover,
|
|
265
340
|
pipetting: PipettingHandler,
|
|
266
341
|
model_utils: ModelUtils,
|
|
267
342
|
**kwargs: object,
|
|
268
343
|
) -> None:
|
|
269
344
|
self._state_view = state_view
|
|
270
345
|
self._movement = movement
|
|
346
|
+
self._gantry_mover = gantry_mover
|
|
271
347
|
self._pipetting = pipetting
|
|
272
348
|
self._model_utils = model_utils
|
|
273
349
|
|
|
@@ -278,11 +354,21 @@ class TryLiquidProbeImplementation(
|
|
|
278
354
|
found, `tryLiquidProbe` returns a success result with `z_position=null` instead
|
|
279
355
|
of a defined error.
|
|
280
356
|
"""
|
|
281
|
-
|
|
282
|
-
self._state_view,
|
|
357
|
+
result = await _execute_common(
|
|
358
|
+
state_view=self._state_view,
|
|
359
|
+
movement=self._movement,
|
|
360
|
+
gantry_mover=self._gantry_mover,
|
|
361
|
+
pipetting=self._pipetting,
|
|
362
|
+
model_utils=self._model_utils,
|
|
363
|
+
params=params,
|
|
283
364
|
)
|
|
365
|
+
if isinstance(result, DefinedErrorData):
|
|
366
|
+
return result
|
|
367
|
+
z_pos_or_error, state_update, deck_point = result
|
|
284
368
|
|
|
285
|
-
if isinstance(
|
|
369
|
+
if isinstance(
|
|
370
|
+
z_pos_or_error, (PipetteLiquidNotFoundError, PipetteOverpressureError)
|
|
371
|
+
):
|
|
286
372
|
z_pos = None
|
|
287
373
|
well_volume: float | update_types.ClearType = update_types.CLEAR
|
|
288
374
|
else:
|
|
@@ -312,25 +398,33 @@ class TryLiquidProbeImplementation(
|
|
|
312
398
|
|
|
313
399
|
|
|
314
400
|
class LiquidProbe(
|
|
315
|
-
BaseCommand[
|
|
401
|
+
BaseCommand[
|
|
402
|
+
LiquidProbeParams,
|
|
403
|
+
LiquidProbeResult,
|
|
404
|
+
LiquidNotFoundError | StallOrCollisionError | OverpressureError,
|
|
405
|
+
]
|
|
316
406
|
):
|
|
317
407
|
"""The model for a full `liquidProbe` command."""
|
|
318
408
|
|
|
319
409
|
commandType: LiquidProbeCommandType = "liquidProbe"
|
|
320
410
|
params: LiquidProbeParams
|
|
321
|
-
result: Optional[LiquidProbeResult]
|
|
411
|
+
result: Optional[LiquidProbeResult] = None
|
|
322
412
|
|
|
323
413
|
_ImplementationCls: Type[LiquidProbeImplementation] = LiquidProbeImplementation
|
|
324
414
|
|
|
325
415
|
|
|
326
416
|
class TryLiquidProbe(
|
|
327
|
-
BaseCommand[
|
|
417
|
+
BaseCommand[
|
|
418
|
+
TryLiquidProbeParams,
|
|
419
|
+
TryLiquidProbeResult,
|
|
420
|
+
StallOrCollisionError | OverpressureError,
|
|
421
|
+
]
|
|
328
422
|
):
|
|
329
423
|
"""The model for a full `tryLiquidProbe` command."""
|
|
330
424
|
|
|
331
425
|
commandType: TryLiquidProbeCommandType = "tryLiquidProbe"
|
|
332
426
|
params: TryLiquidProbeParams
|
|
333
|
-
result: Optional[TryLiquidProbeResult]
|
|
427
|
+
result: Optional[TryLiquidProbeResult] = None
|
|
334
428
|
|
|
335
429
|
_ImplementationCls: Type[
|
|
336
430
|
TryLiquidProbeImplementation
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"""Load labware command request, result, and implementation models."""
|
|
2
2
|
from __future__ import annotations
|
|
3
|
+
from typing import TYPE_CHECKING, Optional, Type, Any
|
|
4
|
+
|
|
3
5
|
from pydantic import BaseModel, Field
|
|
4
|
-
from
|
|
6
|
+
from pydantic.json_schema import SkipJsonSchema
|
|
5
7
|
from typing_extensions import Literal
|
|
6
8
|
|
|
7
9
|
from opentrons_shared_data.labware.labware_definition import LabwareDefinition
|
|
@@ -29,6 +31,10 @@ if TYPE_CHECKING:
|
|
|
29
31
|
LoadLabwareCommandType = Literal["loadLabware"]
|
|
30
32
|
|
|
31
33
|
|
|
34
|
+
def _remove_default(s: dict[str, Any]) -> None:
|
|
35
|
+
s.pop("default", None)
|
|
36
|
+
|
|
37
|
+
|
|
32
38
|
class LoadLabwareParams(BaseModel):
|
|
33
39
|
"""Payload required to load a labware into a slot."""
|
|
34
40
|
|
|
@@ -48,18 +54,20 @@ class LoadLabwareParams(BaseModel):
|
|
|
48
54
|
...,
|
|
49
55
|
description="The labware definition version.",
|
|
50
56
|
)
|
|
51
|
-
labwareId:
|
|
57
|
+
labwareId: str | SkipJsonSchema[None] = Field(
|
|
52
58
|
None,
|
|
53
59
|
description="An optional ID to assign to this labware. If None, an ID "
|
|
54
60
|
"will be generated.",
|
|
61
|
+
json_schema_extra=_remove_default,
|
|
55
62
|
)
|
|
56
|
-
displayName:
|
|
63
|
+
displayName: str | SkipJsonSchema[None] = Field(
|
|
57
64
|
None,
|
|
58
65
|
description="An optional user-specified display name "
|
|
59
66
|
"or label for this labware.",
|
|
60
67
|
# NOTE: v4/5 JSON protocols will always have a displayName which will be the
|
|
61
68
|
# user-specified label OR the displayName property of the labware's definition.
|
|
62
69
|
# TODO: Make sure v6 JSON protocols don't do that.
|
|
70
|
+
json_schema_extra=_remove_default,
|
|
63
71
|
)
|
|
64
72
|
|
|
65
73
|
|
|
@@ -104,6 +112,8 @@ class LoadLabwareImplementation(
|
|
|
104
112
|
self, params: LoadLabwareParams
|
|
105
113
|
) -> SuccessData[LoadLabwareResult]:
|
|
106
114
|
"""Load definition and calibration data necessary for a labware."""
|
|
115
|
+
state_update = StateUpdate()
|
|
116
|
+
|
|
107
117
|
# TODO (tz, 8-15-2023): extend column validation to column 1 when working
|
|
108
118
|
# on https://opentrons.atlassian.net/browse/RSS-258 and completing
|
|
109
119
|
# https://opentrons.atlassian.net/browse/RSS-255
|
|
@@ -128,10 +138,12 @@ class LoadLabwareImplementation(
|
|
|
128
138
|
self._state_view.addressable_areas.raise_if_area_not_in_deck_configuration(
|
|
129
139
|
area_name
|
|
130
140
|
)
|
|
141
|
+
state_update.set_addressable_area_used(area_name)
|
|
131
142
|
elif isinstance(params.location, DeckSlotLocation):
|
|
132
143
|
self._state_view.addressable_areas.raise_if_area_not_in_deck_configuration(
|
|
133
144
|
params.location.slotName.id
|
|
134
145
|
)
|
|
146
|
+
state_update.set_addressable_area_used(params.location.slotName.id)
|
|
135
147
|
|
|
136
148
|
verified_location = self._state_view.geometry.ensure_location_not_occupied(
|
|
137
149
|
params.location
|
|
@@ -144,8 +156,6 @@ class LoadLabwareImplementation(
|
|
|
144
156
|
labware_id=params.labwareId,
|
|
145
157
|
)
|
|
146
158
|
|
|
147
|
-
state_update = StateUpdate()
|
|
148
|
-
|
|
149
159
|
state_update.set_loaded_labware(
|
|
150
160
|
labware_id=loaded_labware.labware_id,
|
|
151
161
|
offset_id=loaded_labware.offsetId,
|
|
@@ -162,6 +172,19 @@ class LoadLabwareImplementation(
|
|
|
162
172
|
top_labware_definition=loaded_labware.definition,
|
|
163
173
|
bottom_labware_id=verified_location.labwareId,
|
|
164
174
|
)
|
|
175
|
+
# Validate load location is valid for lids
|
|
176
|
+
if (
|
|
177
|
+
labware_validation.validate_definition_is_lid(
|
|
178
|
+
definition=loaded_labware.definition
|
|
179
|
+
)
|
|
180
|
+
and loaded_labware.definition.compatibleParentLabware is not None
|
|
181
|
+
and self._state_view.labware.get_load_name(verified_location.labwareId)
|
|
182
|
+
not in loaded_labware.definition.compatibleParentLabware
|
|
183
|
+
):
|
|
184
|
+
raise ValueError(
|
|
185
|
+
f"Labware Lid {params.loadName} may not be loaded on parent labware {self._state_view.labware.get_display_name(verified_location.labwareId)}."
|
|
186
|
+
)
|
|
187
|
+
|
|
165
188
|
# Validate labware for the absorbance reader
|
|
166
189
|
elif isinstance(params.location, ModuleLocation):
|
|
167
190
|
module = self._state_view.modules.get(params.location.moduleId)
|
|
@@ -170,6 +193,10 @@ class LoadLabwareImplementation(
|
|
|
170
193
|
loaded_labware.definition
|
|
171
194
|
)
|
|
172
195
|
|
|
196
|
+
self._state_view.labware.raise_if_labware_cannot_be_ondeck(
|
|
197
|
+
location=params.location, labware_definition=loaded_labware.definition
|
|
198
|
+
)
|
|
199
|
+
|
|
173
200
|
return SuccessData(
|
|
174
201
|
public=LoadLabwareResult(
|
|
175
202
|
labwareId=loaded_labware.labware_id,
|
|
@@ -185,7 +212,7 @@ class LoadLabware(BaseCommand[LoadLabwareParams, LoadLabwareResult, ErrorOccurre
|
|
|
185
212
|
|
|
186
213
|
commandType: LoadLabwareCommandType = "loadLabware"
|
|
187
214
|
params: LoadLabwareParams
|
|
188
|
-
result: Optional[LoadLabwareResult]
|
|
215
|
+
result: Optional[LoadLabwareResult] = None
|
|
189
216
|
|
|
190
217
|
_ImplementationCls: Type[LoadLabwareImplementation] = LoadLabwareImplementation
|
|
191
218
|
|