opentrons 8.1.0a0__py2.py3-none-any.whl → 8.2.0a0__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/cli/analyze.py +71 -7
- opentrons/config/__init__.py +9 -0
- opentrons/config/advanced_settings.py +22 -0
- opentrons/config/defaults_ot3.py +14 -36
- opentrons/config/feature_flags.py +4 -0
- opentrons/config/types.py +6 -17
- opentrons/drivers/absorbance_reader/abstract.py +27 -3
- opentrons/drivers/absorbance_reader/async_byonoy.py +207 -154
- opentrons/drivers/absorbance_reader/driver.py +24 -15
- opentrons/drivers/absorbance_reader/hid_protocol.py +79 -50
- opentrons/drivers/absorbance_reader/simulator.py +32 -6
- opentrons/drivers/types.py +23 -1
- opentrons/execute.py +2 -2
- opentrons/hardware_control/api.py +18 -10
- opentrons/hardware_control/backends/controller.py +3 -2
- opentrons/hardware_control/backends/flex_protocol.py +11 -5
- opentrons/hardware_control/backends/ot3controller.py +18 -50
- opentrons/hardware_control/backends/ot3simulator.py +7 -6
- opentrons/hardware_control/instruments/ot2/pipette_handler.py +22 -82
- opentrons/hardware_control/instruments/ot3/pipette_handler.py +10 -2
- opentrons/hardware_control/module_control.py +43 -2
- opentrons/hardware_control/modules/__init__.py +7 -1
- opentrons/hardware_control/modules/absorbance_reader.py +230 -83
- opentrons/hardware_control/modules/errors.py +7 -0
- opentrons/hardware_control/modules/heater_shaker.py +8 -3
- opentrons/hardware_control/modules/magdeck.py +12 -3
- opentrons/hardware_control/modules/mod_abc.py +27 -2
- opentrons/hardware_control/modules/tempdeck.py +15 -7
- opentrons/hardware_control/modules/thermocycler.py +69 -3
- opentrons/hardware_control/modules/types.py +11 -5
- opentrons/hardware_control/modules/update.py +11 -5
- opentrons/hardware_control/modules/utils.py +3 -1
- opentrons/hardware_control/ot3_calibration.py +6 -6
- opentrons/hardware_control/ot3api.py +126 -89
- opentrons/hardware_control/poller.py +15 -11
- opentrons/hardware_control/protocols/__init__.py +1 -7
- opentrons/hardware_control/protocols/instrument_configurer.py +14 -2
- opentrons/hardware_control/protocols/liquid_handler.py +5 -0
- opentrons/motion_planning/__init__.py +2 -0
- opentrons/motion_planning/waypoints.py +32 -0
- opentrons/protocol_api/__init__.py +2 -1
- opentrons/protocol_api/_liquid.py +87 -1
- opentrons/protocol_api/_parameter_context.py +10 -1
- opentrons/protocol_api/core/engine/deck_conflict.py +0 -297
- opentrons/protocol_api/core/engine/instrument.py +29 -25
- opentrons/protocol_api/core/engine/labware.py +10 -2
- opentrons/protocol_api/core/engine/module_core.py +129 -17
- opentrons/protocol_api/core/engine/pipette_movement_conflict.py +355 -0
- opentrons/protocol_api/core/engine/protocol.py +55 -2
- opentrons/protocol_api/core/instrument.py +2 -0
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +2 -0
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +5 -2
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +2 -0
- opentrons/protocol_api/core/module.py +22 -4
- opentrons/protocol_api/core/protocol.py +5 -2
- opentrons/protocol_api/instrument_context.py +52 -20
- opentrons/protocol_api/labware.py +13 -1
- opentrons/protocol_api/module_contexts.py +68 -13
- opentrons/protocol_api/protocol_context.py +38 -4
- opentrons/protocol_api/validation.py +5 -3
- opentrons/protocol_engine/__init__.py +10 -9
- opentrons/protocol_engine/actions/__init__.py +5 -0
- opentrons/protocol_engine/actions/actions.py +42 -25
- opentrons/protocol_engine/actions/get_state_update.py +38 -0
- opentrons/protocol_engine/clients/sync_client.py +7 -1
- opentrons/protocol_engine/clients/transports.py +1 -1
- opentrons/protocol_engine/commands/__init__.py +0 -4
- opentrons/protocol_engine/commands/absorbance_reader/__init__.py +41 -11
- opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +161 -0
- opentrons/protocol_engine/commands/absorbance_reader/initialize.py +53 -9
- opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +160 -0
- opentrons/protocol_engine/commands/absorbance_reader/read.py +196 -0
- opentrons/protocol_engine/commands/aspirate.py +29 -16
- opentrons/protocol_engine/commands/aspirate_in_place.py +32 -15
- opentrons/protocol_engine/commands/blow_out.py +63 -14
- opentrons/protocol_engine/commands/blow_out_in_place.py +55 -13
- opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +2 -5
- opentrons/protocol_engine/commands/calibration/calibrate_module.py +3 -4
- opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +2 -5
- opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +6 -4
- opentrons/protocol_engine/commands/command.py +28 -17
- opentrons/protocol_engine/commands/command_unions.py +37 -24
- opentrons/protocol_engine/commands/comment.py +5 -3
- opentrons/protocol_engine/commands/configure_for_volume.py +11 -14
- opentrons/protocol_engine/commands/configure_nozzle_layout.py +9 -15
- opentrons/protocol_engine/commands/custom.py +5 -3
- opentrons/protocol_engine/commands/dispense.py +42 -20
- opentrons/protocol_engine/commands/dispense_in_place.py +32 -14
- opentrons/protocol_engine/commands/drop_tip.py +68 -15
- opentrons/protocol_engine/commands/drop_tip_in_place.py +52 -11
- opentrons/protocol_engine/commands/get_tip_presence.py +5 -3
- opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +6 -6
- opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +6 -6
- opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +6 -6
- opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +8 -6
- opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +8 -4
- opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +6 -4
- opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +6 -6
- opentrons/protocol_engine/commands/home.py +11 -5
- opentrons/protocol_engine/commands/liquid_probe.py +146 -88
- opentrons/protocol_engine/commands/load_labware.py +19 -5
- opentrons/protocol_engine/commands/load_liquid.py +18 -7
- opentrons/protocol_engine/commands/load_module.py +43 -6
- opentrons/protocol_engine/commands/load_pipette.py +18 -17
- opentrons/protocol_engine/commands/magnetic_module/disengage.py +6 -6
- opentrons/protocol_engine/commands/magnetic_module/engage.py +6 -4
- opentrons/protocol_engine/commands/move_labware.py +106 -19
- opentrons/protocol_engine/commands/move_relative.py +15 -3
- opentrons/protocol_engine/commands/move_to_addressable_area.py +29 -4
- opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +13 -4
- opentrons/protocol_engine/commands/move_to_coordinates.py +11 -5
- opentrons/protocol_engine/commands/move_to_well.py +37 -10
- opentrons/protocol_engine/commands/pick_up_tip.py +50 -29
- opentrons/protocol_engine/commands/pipetting_common.py +39 -15
- opentrons/protocol_engine/commands/prepare_to_aspirate.py +62 -15
- opentrons/protocol_engine/commands/reload_labware.py +13 -4
- opentrons/protocol_engine/commands/retract_axis.py +6 -3
- opentrons/protocol_engine/commands/save_position.py +2 -3
- opentrons/protocol_engine/commands/set_rail_lights.py +5 -3
- opentrons/protocol_engine/commands/set_status_bar.py +5 -3
- opentrons/protocol_engine/commands/temperature_module/deactivate.py +6 -4
- opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +3 -4
- opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +6 -6
- opentrons/protocol_engine/commands/thermocycler/__init__.py +19 -0
- opentrons/protocol_engine/commands/thermocycler/close_lid.py +8 -8
- opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +6 -4
- opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +6 -4
- opentrons/protocol_engine/commands/thermocycler/open_lid.py +8 -4
- opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +165 -0
- opentrons/protocol_engine/commands/thermocycler/run_profile.py +6 -6
- opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +3 -4
- opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +3 -4
- opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +6 -4
- opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +6 -4
- opentrons/protocol_engine/commands/touch_tip.py +19 -7
- opentrons/protocol_engine/commands/unsafe/__init__.py +30 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +6 -4
- opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +12 -4
- opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +5 -3
- opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +194 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +75 -0
- opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +5 -3
- opentrons/protocol_engine/commands/verify_tip_presence.py +5 -5
- opentrons/protocol_engine/commands/wait_for_duration.py +5 -3
- opentrons/protocol_engine/commands/wait_for_resume.py +5 -3
- opentrons/protocol_engine/create_protocol_engine.py +41 -8
- opentrons/protocol_engine/engine_support.py +2 -1
- opentrons/protocol_engine/error_recovery_policy.py +14 -3
- opentrons/protocol_engine/errors/__init__.py +18 -0
- opentrons/protocol_engine/errors/exceptions.py +114 -2
- opentrons/protocol_engine/execution/__init__.py +2 -0
- opentrons/protocol_engine/execution/command_executor.py +22 -13
- opentrons/protocol_engine/execution/create_queue_worker.py +5 -1
- opentrons/protocol_engine/execution/door_watcher.py +1 -1
- opentrons/protocol_engine/execution/equipment.py +2 -1
- opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
- opentrons/protocol_engine/execution/gantry_mover.py +4 -2
- opentrons/protocol_engine/execution/hardware_stopper.py +3 -3
- opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +1 -4
- opentrons/protocol_engine/execution/labware_movement.py +6 -3
- opentrons/protocol_engine/execution/movement.py +8 -3
- opentrons/protocol_engine/execution/pipetting.py +7 -4
- opentrons/protocol_engine/execution/queue_worker.py +6 -2
- opentrons/protocol_engine/execution/run_control.py +1 -1
- opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +1 -1
- opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +2 -1
- opentrons/protocol_engine/execution/tip_handler.py +77 -43
- opentrons/protocol_engine/notes/__init__.py +14 -2
- opentrons/protocol_engine/notes/notes.py +18 -1
- opentrons/protocol_engine/plugins.py +1 -1
- opentrons/protocol_engine/protocol_engine.py +54 -31
- opentrons/protocol_engine/resources/__init__.py +2 -0
- opentrons/protocol_engine/resources/deck_data_provider.py +58 -5
- opentrons/protocol_engine/resources/file_provider.py +157 -0
- opentrons/protocol_engine/resources/fixture_validation.py +5 -0
- opentrons/protocol_engine/resources/labware_validation.py +10 -0
- opentrons/protocol_engine/state/__init__.py +0 -70
- opentrons/protocol_engine/state/addressable_areas.py +1 -1
- opentrons/protocol_engine/state/command_history.py +21 -2
- opentrons/protocol_engine/state/commands.py +110 -31
- opentrons/protocol_engine/state/files.py +59 -0
- opentrons/protocol_engine/state/frustum_helpers.py +440 -0
- opentrons/protocol_engine/state/geometry.py +359 -15
- opentrons/protocol_engine/state/labware.py +166 -63
- opentrons/protocol_engine/state/liquids.py +1 -1
- opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +19 -3
- opentrons/protocol_engine/state/modules.py +167 -85
- opentrons/protocol_engine/state/motion.py +16 -9
- opentrons/protocol_engine/state/pipettes.py +157 -317
- opentrons/protocol_engine/state/state.py +30 -1
- opentrons/protocol_engine/state/state_summary.py +3 -0
- opentrons/protocol_engine/state/tips.py +69 -114
- opentrons/protocol_engine/state/update_types.py +408 -0
- opentrons/protocol_engine/state/wells.py +236 -0
- opentrons/protocol_engine/types.py +90 -0
- opentrons/protocol_reader/file_format_validator.py +83 -15
- opentrons/protocol_runner/json_translator.py +21 -5
- opentrons/protocol_runner/legacy_command_mapper.py +27 -6
- opentrons/protocol_runner/legacy_context_plugin.py +27 -71
- opentrons/protocol_runner/protocol_runner.py +6 -3
- opentrons/protocol_runner/run_orchestrator.py +26 -6
- opentrons/protocols/advanced_control/mix.py +3 -5
- opentrons/protocols/advanced_control/transfers.py +125 -56
- opentrons/protocols/api_support/constants.py +1 -1
- opentrons/protocols/api_support/definitions.py +1 -1
- opentrons/protocols/api_support/labware_like.py +4 -4
- opentrons/protocols/api_support/tip_tracker.py +2 -2
- opentrons/protocols/api_support/types.py +15 -2
- opentrons/protocols/api_support/util.py +30 -42
- opentrons/protocols/duration/errors.py +1 -1
- opentrons/protocols/duration/estimator.py +50 -29
- opentrons/protocols/execution/dev_types.py +2 -2
- opentrons/protocols/execution/execute_json_v4.py +15 -10
- opentrons/protocols/execution/execute_python.py +8 -3
- opentrons/protocols/geometry/planning.py +12 -12
- opentrons/protocols/labware.py +17 -33
- opentrons/simulate.py +3 -3
- opentrons/types.py +30 -3
- opentrons/util/logging_config.py +34 -0
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/METADATA +5 -4
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/RECORD +227 -215
- opentrons/protocol_engine/commands/absorbance_reader/measure.py +0 -94
- opentrons/protocol_engine/commands/configuring_common.py +0 -26
- opentrons/protocol_runner/thread_async_queue.py +0 -174
- /opentrons/protocol_engine/state/{abstract_store.py → _abstract_store.py} +0 -0
- /opentrons/protocol_engine/state/{move_types.py → _move_types.py} +0 -0
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/LICENSE +0 -0
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/WHEEL +0 -0
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/entry_points.txt +0 -0
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/top_level.txt +0 -0
|
@@ -9,7 +9,7 @@ from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, Succe
|
|
|
9
9
|
from ...errors.error_occurrence import ErrorOccurrence
|
|
10
10
|
|
|
11
11
|
if TYPE_CHECKING:
|
|
12
|
-
from opentrons.protocol_engine.state import StateView
|
|
12
|
+
from opentrons.protocol_engine.state.state import StateView
|
|
13
13
|
from opentrons.protocol_engine.execution import EquipmentHandler
|
|
14
14
|
|
|
15
15
|
|
|
@@ -27,9 +27,7 @@ class DeactivateHeaterResult(BaseModel):
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
class DeactivateHeaterImpl(
|
|
30
|
-
AbstractCommandImpl[
|
|
31
|
-
DeactivateHeaterParams, SuccessData[DeactivateHeaterResult, None]
|
|
32
|
-
]
|
|
30
|
+
AbstractCommandImpl[DeactivateHeaterParams, SuccessData[DeactivateHeaterResult]]
|
|
33
31
|
):
|
|
34
32
|
"""Execution implementation of a Heater-Shaker's deactivate heater command."""
|
|
35
33
|
|
|
@@ -44,7 +42,7 @@ class DeactivateHeaterImpl(
|
|
|
44
42
|
|
|
45
43
|
async def execute(
|
|
46
44
|
self, params: DeactivateHeaterParams
|
|
47
|
-
) -> SuccessData[DeactivateHeaterResult
|
|
45
|
+
) -> SuccessData[DeactivateHeaterResult]:
|
|
48
46
|
"""Unset a Heater-Shaker's target temperature."""
|
|
49
47
|
hs_module_substate = self._state_view.modules.get_heater_shaker_module_substate(
|
|
50
48
|
module_id=params.moduleId
|
|
@@ -58,7 +56,9 @@ class DeactivateHeaterImpl(
|
|
|
58
56
|
if hs_hardware_module is not None:
|
|
59
57
|
await hs_hardware_module.deactivate_heater()
|
|
60
58
|
|
|
61
|
-
return SuccessData(
|
|
59
|
+
return SuccessData(
|
|
60
|
+
public=DeactivateHeaterResult(),
|
|
61
|
+
)
|
|
62
62
|
|
|
63
63
|
|
|
64
64
|
class DeactivateHeater(
|
|
@@ -9,7 +9,7 @@ from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, Succe
|
|
|
9
9
|
from ...errors.error_occurrence import ErrorOccurrence
|
|
10
10
|
|
|
11
11
|
if TYPE_CHECKING:
|
|
12
|
-
from opentrons.protocol_engine.state import StateView
|
|
12
|
+
from opentrons.protocol_engine.state.state import StateView
|
|
13
13
|
from opentrons.protocol_engine.execution import EquipmentHandler
|
|
14
14
|
|
|
15
15
|
DeactivateShakerCommandType = Literal["heaterShaker/deactivateShaker"]
|
|
@@ -26,9 +26,7 @@ class DeactivateShakerResult(BaseModel):
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
class DeactivateShakerImpl(
|
|
29
|
-
AbstractCommandImpl[
|
|
30
|
-
DeactivateShakerParams, SuccessData[DeactivateShakerResult, None]
|
|
31
|
-
]
|
|
29
|
+
AbstractCommandImpl[DeactivateShakerParams, SuccessData[DeactivateShakerResult]]
|
|
32
30
|
):
|
|
33
31
|
"""Execution implementation of a Heater-Shaker's deactivate shaker command."""
|
|
34
32
|
|
|
@@ -43,7 +41,7 @@ class DeactivateShakerImpl(
|
|
|
43
41
|
|
|
44
42
|
async def execute(
|
|
45
43
|
self, params: DeactivateShakerParams
|
|
46
|
-
) -> SuccessData[DeactivateShakerResult
|
|
44
|
+
) -> SuccessData[DeactivateShakerResult]:
|
|
47
45
|
"""Deactivate shaker for a Heater-Shaker."""
|
|
48
46
|
# Allow propagation of ModuleNotLoadedError and WrongModuleTypeError.
|
|
49
47
|
hs_module_substate = self._state_view.modules.get_heater_shaker_module_substate(
|
|
@@ -60,7 +58,9 @@ class DeactivateShakerImpl(
|
|
|
60
58
|
if hs_hardware_module is not None:
|
|
61
59
|
await hs_hardware_module.deactivate_shaker()
|
|
62
60
|
|
|
63
|
-
return SuccessData(
|
|
61
|
+
return SuccessData(
|
|
62
|
+
public=DeactivateShakerResult(),
|
|
63
|
+
)
|
|
64
64
|
|
|
65
65
|
|
|
66
66
|
class DeactivateShaker(
|
|
@@ -6,9 +6,10 @@ from pydantic import BaseModel, Field
|
|
|
6
6
|
|
|
7
7
|
from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
|
|
8
8
|
from ...errors.error_occurrence import ErrorOccurrence
|
|
9
|
+
from ...state import update_types
|
|
9
10
|
|
|
10
11
|
if TYPE_CHECKING:
|
|
11
|
-
from opentrons.protocol_engine.state import StateView
|
|
12
|
+
from opentrons.protocol_engine.state.state import StateView
|
|
12
13
|
from opentrons.protocol_engine.execution import EquipmentHandler, MovementHandler
|
|
13
14
|
|
|
14
15
|
OpenLabwareLatchCommandType = Literal["heaterShaker/openLabwareLatch"]
|
|
@@ -33,9 +34,7 @@ class OpenLabwareLatchResult(BaseModel):
|
|
|
33
34
|
|
|
34
35
|
|
|
35
36
|
class OpenLabwareLatchImpl(
|
|
36
|
-
AbstractCommandImpl[
|
|
37
|
-
OpenLabwareLatchParams, SuccessData[OpenLabwareLatchResult, None]
|
|
38
|
-
]
|
|
37
|
+
AbstractCommandImpl[OpenLabwareLatchParams, SuccessData[OpenLabwareLatchResult]]
|
|
39
38
|
):
|
|
40
39
|
"""Execution implementation of a Heater-Shaker's open latch labware command."""
|
|
41
40
|
|
|
@@ -52,8 +51,10 @@ class OpenLabwareLatchImpl(
|
|
|
52
51
|
|
|
53
52
|
async def execute(
|
|
54
53
|
self, params: OpenLabwareLatchParams
|
|
55
|
-
) -> SuccessData[OpenLabwareLatchResult
|
|
54
|
+
) -> SuccessData[OpenLabwareLatchResult]:
|
|
56
55
|
"""Open a Heater-Shaker's labware latch."""
|
|
56
|
+
state_update = update_types.StateUpdate()
|
|
57
|
+
|
|
57
58
|
# Allow propagation of ModuleNotLoadedError and WrongModuleTypeError.
|
|
58
59
|
hs_module_substate = self._state_view.modules.get_heater_shaker_module_substate(
|
|
59
60
|
module_id=params.moduleId
|
|
@@ -72,6 +73,7 @@ class OpenLabwareLatchImpl(
|
|
|
72
73
|
await self._movement.home(
|
|
73
74
|
axes=self._state_view.motion.get_robot_mount_axes()
|
|
74
75
|
)
|
|
76
|
+
state_update.clear_all_pipette_locations()
|
|
75
77
|
|
|
76
78
|
# Allow propagation of ModuleNotAttachedError.
|
|
77
79
|
hs_hardware_module = self._equipment.get_module_hardware_api(
|
|
@@ -83,7 +85,7 @@ class OpenLabwareLatchImpl(
|
|
|
83
85
|
|
|
84
86
|
return SuccessData(
|
|
85
87
|
public=OpenLabwareLatchResult(pipetteRetracted=pipette_should_retract),
|
|
86
|
-
|
|
88
|
+
state_update=state_update,
|
|
87
89
|
)
|
|
88
90
|
|
|
89
91
|
|
|
@@ -6,9 +6,10 @@ from pydantic import BaseModel, Field
|
|
|
6
6
|
|
|
7
7
|
from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
|
|
8
8
|
from ...errors.error_occurrence import ErrorOccurrence
|
|
9
|
+
from ...state import update_types
|
|
9
10
|
|
|
10
11
|
if TYPE_CHECKING:
|
|
11
|
-
from opentrons.protocol_engine.state import StateView
|
|
12
|
+
from opentrons.protocol_engine.state.state import StateView
|
|
12
13
|
from opentrons.protocol_engine.execution import EquipmentHandler, MovementHandler
|
|
13
14
|
|
|
14
15
|
SetAndWaitForShakeSpeedCommandType = Literal["heaterShaker/setAndWaitForShakeSpeed"]
|
|
@@ -35,7 +36,7 @@ class SetAndWaitForShakeSpeedResult(BaseModel):
|
|
|
35
36
|
|
|
36
37
|
class SetAndWaitForShakeSpeedImpl(
|
|
37
38
|
AbstractCommandImpl[
|
|
38
|
-
SetAndWaitForShakeSpeedParams, SuccessData[SetAndWaitForShakeSpeedResult
|
|
39
|
+
SetAndWaitForShakeSpeedParams, SuccessData[SetAndWaitForShakeSpeedResult]
|
|
39
40
|
]
|
|
40
41
|
):
|
|
41
42
|
"""Execution implementation of Heater-Shaker's set and wait shake speed command."""
|
|
@@ -54,8 +55,10 @@ class SetAndWaitForShakeSpeedImpl(
|
|
|
54
55
|
async def execute(
|
|
55
56
|
self,
|
|
56
57
|
params: SetAndWaitForShakeSpeedParams,
|
|
57
|
-
) -> SuccessData[SetAndWaitForShakeSpeedResult
|
|
58
|
+
) -> SuccessData[SetAndWaitForShakeSpeedResult]:
|
|
58
59
|
"""Set and wait for a Heater-Shaker's target shake speed."""
|
|
60
|
+
state_update = update_types.StateUpdate()
|
|
61
|
+
|
|
59
62
|
# Allow propagation of ModuleNotLoadedError and WrongModuleTypeError.
|
|
60
63
|
hs_module_substate = self._state_view.modules.get_heater_shaker_module_substate(
|
|
61
64
|
module_id=params.moduleId
|
|
@@ -77,6 +80,7 @@ class SetAndWaitForShakeSpeedImpl(
|
|
|
77
80
|
await self._movement.home(
|
|
78
81
|
axes=self._state_view.motion.get_robot_mount_axes()
|
|
79
82
|
)
|
|
83
|
+
state_update.clear_all_pipette_locations()
|
|
80
84
|
|
|
81
85
|
# Allow propagation of ModuleNotAttachedError.
|
|
82
86
|
hs_hardware_module = self._equipment.get_module_hardware_api(
|
|
@@ -90,7 +94,7 @@ class SetAndWaitForShakeSpeedImpl(
|
|
|
90
94
|
public=SetAndWaitForShakeSpeedResult(
|
|
91
95
|
pipetteRetracted=pipette_should_retract
|
|
92
96
|
),
|
|
93
|
-
|
|
97
|
+
state_update=state_update,
|
|
94
98
|
)
|
|
95
99
|
|
|
96
100
|
|
|
@@ -9,7 +9,7 @@ from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, Succe
|
|
|
9
9
|
from ...errors.error_occurrence import ErrorOccurrence
|
|
10
10
|
|
|
11
11
|
if TYPE_CHECKING:
|
|
12
|
-
from opentrons.protocol_engine.state import StateView
|
|
12
|
+
from opentrons.protocol_engine.state.state import StateView
|
|
13
13
|
from opentrons.protocol_engine.execution import EquipmentHandler
|
|
14
14
|
|
|
15
15
|
|
|
@@ -29,7 +29,7 @@ class SetTargetTemperatureResult(BaseModel):
|
|
|
29
29
|
|
|
30
30
|
class SetTargetTemperatureImpl(
|
|
31
31
|
AbstractCommandImpl[
|
|
32
|
-
SetTargetTemperatureParams, SuccessData[SetTargetTemperatureResult
|
|
32
|
+
SetTargetTemperatureParams, SuccessData[SetTargetTemperatureResult]
|
|
33
33
|
]
|
|
34
34
|
):
|
|
35
35
|
"""Execution implementation of a Heater-Shaker's set temperature command."""
|
|
@@ -46,7 +46,7 @@ class SetTargetTemperatureImpl(
|
|
|
46
46
|
async def execute(
|
|
47
47
|
self,
|
|
48
48
|
params: SetTargetTemperatureParams,
|
|
49
|
-
) -> SuccessData[SetTargetTemperatureResult
|
|
49
|
+
) -> SuccessData[SetTargetTemperatureResult]:
|
|
50
50
|
"""Set a Heater-Shaker's target temperature."""
|
|
51
51
|
# Allow propagation of ModuleNotLoadedError and WrongModuleTypeError.
|
|
52
52
|
hs_module_substate = self._state_view.modules.get_heater_shaker_module_substate(
|
|
@@ -64,7 +64,9 @@ class SetTargetTemperatureImpl(
|
|
|
64
64
|
if hs_hardware_module is not None:
|
|
65
65
|
await hs_hardware_module.start_set_temperature(validated_temp)
|
|
66
66
|
|
|
67
|
-
return SuccessData(
|
|
67
|
+
return SuccessData(
|
|
68
|
+
public=SetTargetTemperatureResult(),
|
|
69
|
+
)
|
|
68
70
|
|
|
69
71
|
|
|
70
72
|
class SetTargetTemperature(
|
|
@@ -9,7 +9,7 @@ from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, Succe
|
|
|
9
9
|
from ...errors.error_occurrence import ErrorOccurrence
|
|
10
10
|
|
|
11
11
|
if TYPE_CHECKING:
|
|
12
|
-
from opentrons.protocol_engine.state import StateView
|
|
12
|
+
from opentrons.protocol_engine.state.state import StateView
|
|
13
13
|
from opentrons.protocol_engine.execution import EquipmentHandler
|
|
14
14
|
|
|
15
15
|
|
|
@@ -36,9 +36,7 @@ class WaitForTemperatureResult(BaseModel):
|
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
class WaitForTemperatureImpl(
|
|
39
|
-
AbstractCommandImpl[
|
|
40
|
-
WaitForTemperatureParams, SuccessData[WaitForTemperatureResult, None]
|
|
41
|
-
]
|
|
39
|
+
AbstractCommandImpl[WaitForTemperatureParams, SuccessData[WaitForTemperatureResult]]
|
|
42
40
|
):
|
|
43
41
|
"""Execution implementation of a Heater-Shaker's wait for temperature command."""
|
|
44
42
|
|
|
@@ -53,7 +51,7 @@ class WaitForTemperatureImpl(
|
|
|
53
51
|
|
|
54
52
|
async def execute(
|
|
55
53
|
self, params: WaitForTemperatureParams
|
|
56
|
-
) -> SuccessData[WaitForTemperatureResult
|
|
54
|
+
) -> SuccessData[WaitForTemperatureResult]:
|
|
57
55
|
"""Wait for a Heater-Shaker's target temperature to be reached."""
|
|
58
56
|
hs_module_substate = self._state_view.modules.get_heater_shaker_module_substate(
|
|
59
57
|
module_id=params.moduleId
|
|
@@ -72,7 +70,9 @@ class WaitForTemperatureImpl(
|
|
|
72
70
|
if hs_hardware_module is not None:
|
|
73
71
|
await hs_hardware_module.await_temperature(awaiting_temperature=target_temp)
|
|
74
72
|
|
|
75
|
-
return SuccessData(
|
|
73
|
+
return SuccessData(
|
|
74
|
+
public=WaitForTemperatureResult(),
|
|
75
|
+
)
|
|
76
76
|
|
|
77
77
|
|
|
78
78
|
class WaitForTemperature(
|
|
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING, Optional, List, Type
|
|
|
5
5
|
from typing_extensions import Literal
|
|
6
6
|
|
|
7
7
|
from opentrons.types import MountType
|
|
8
|
+
from ..state import update_types
|
|
8
9
|
from ..types import MotorAxis
|
|
9
10
|
from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
|
|
10
11
|
from ..errors.error_occurrence import ErrorOccurrence
|
|
@@ -41,16 +42,16 @@ class HomeResult(BaseModel):
|
|
|
41
42
|
"""Result data from the execution of a Home command."""
|
|
42
43
|
|
|
43
44
|
|
|
44
|
-
class HomeImplementation(
|
|
45
|
-
AbstractCommandImpl[HomeParams, SuccessData[HomeResult, None]]
|
|
46
|
-
):
|
|
45
|
+
class HomeImplementation(AbstractCommandImpl[HomeParams, SuccessData[HomeResult]]):
|
|
47
46
|
"""Home command implementation."""
|
|
48
47
|
|
|
49
48
|
def __init__(self, movement: MovementHandler, **kwargs: object) -> None:
|
|
50
49
|
self._movement = movement
|
|
51
50
|
|
|
52
|
-
async def execute(self, params: HomeParams) -> SuccessData[HomeResult
|
|
51
|
+
async def execute(self, params: HomeParams) -> SuccessData[HomeResult]:
|
|
53
52
|
"""Home some or all motors to establish positional accuracy."""
|
|
53
|
+
state_update = update_types.StateUpdate()
|
|
54
|
+
|
|
54
55
|
if (
|
|
55
56
|
params.skipIfMountPositionOk is None
|
|
56
57
|
or not await self._movement.check_for_valid_position(
|
|
@@ -58,7 +59,12 @@ class HomeImplementation(
|
|
|
58
59
|
)
|
|
59
60
|
):
|
|
60
61
|
await self._movement.home(axes=params.axes)
|
|
61
|
-
|
|
62
|
+
|
|
63
|
+
# todo(mm, 2024-09-17): Clearing all pipette locations *unconditionally* is to
|
|
64
|
+
# preserve prior behavior, but we might only want to do this if we actually home.
|
|
65
|
+
state_update.clear_all_pipette_locations()
|
|
66
|
+
|
|
67
|
+
return SuccessData(public=HomeResult(), state_update=state_update)
|
|
62
68
|
|
|
63
69
|
|
|
64
70
|
class Home(BaseCommand[HomeParams, HomeResult, ErrorOccurrence]):
|
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
"""The liquidProbe and tryLiquidProbe commands."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
|
-
from typing import TYPE_CHECKING, Optional, Type, Union
|
|
4
|
+
from typing import TYPE_CHECKING, NamedTuple, Optional, Type, Union
|
|
5
|
+
from typing_extensions import Literal
|
|
6
|
+
|
|
7
|
+
from pydantic import Field
|
|
8
|
+
|
|
9
|
+
from opentrons.protocol_engine.state import update_types
|
|
5
10
|
from opentrons.protocol_engine.errors.exceptions import (
|
|
6
11
|
MustHomeError,
|
|
7
12
|
PipetteNotReadyToAspirateError,
|
|
8
13
|
TipNotEmptyError,
|
|
14
|
+
IncompleteLabwareDefinitionError,
|
|
9
15
|
)
|
|
10
16
|
from opentrons.types import MountType
|
|
11
17
|
from opentrons_shared_data.errors.exceptions import (
|
|
12
18
|
PipetteLiquidNotFoundError,
|
|
13
19
|
)
|
|
14
|
-
from typing_extensions import Literal
|
|
15
|
-
|
|
16
|
-
from pydantic import Field
|
|
17
20
|
|
|
18
21
|
from ..types import DeckPoint
|
|
19
22
|
from .pipetting_common import (
|
|
20
23
|
LiquidNotFoundError,
|
|
21
|
-
LiquidNotFoundErrorInternalData,
|
|
22
24
|
PipetteIdMixin,
|
|
23
25
|
WellLocationMixin,
|
|
24
26
|
DestinationPositionResult,
|
|
@@ -36,7 +38,7 @@ from ..errors.error_occurrence import ErrorOccurrence
|
|
|
36
38
|
if TYPE_CHECKING:
|
|
37
39
|
from ..execution import MovementHandler, PipettingHandler
|
|
38
40
|
from ..resources import ModelUtils
|
|
39
|
-
from ..state import StateView
|
|
41
|
+
from ..state.state import StateView
|
|
40
42
|
|
|
41
43
|
|
|
42
44
|
LiquidProbeCommandType = Literal["liquidProbe"]
|
|
@@ -84,10 +86,86 @@ class TryLiquidProbeResult(DestinationPositionResult):
|
|
|
84
86
|
|
|
85
87
|
|
|
86
88
|
_LiquidProbeExecuteReturn = Union[
|
|
87
|
-
SuccessData[LiquidProbeResult
|
|
88
|
-
DefinedErrorData[LiquidNotFoundError
|
|
89
|
+
SuccessData[LiquidProbeResult],
|
|
90
|
+
DefinedErrorData[LiquidNotFoundError],
|
|
89
91
|
]
|
|
90
|
-
_TryLiquidProbeExecuteReturn = SuccessData[TryLiquidProbeResult
|
|
92
|
+
_TryLiquidProbeExecuteReturn = SuccessData[TryLiquidProbeResult]
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class _ExecuteCommonResult(NamedTuple):
|
|
96
|
+
# If the probe succeeded, the z_pos that it returned.
|
|
97
|
+
# Or, if the probe found no liquid, the error representing that,
|
|
98
|
+
# so calling code can propagate those details up.
|
|
99
|
+
z_pos_or_error: float | PipetteLiquidNotFoundError
|
|
100
|
+
|
|
101
|
+
state_update: update_types.StateUpdate
|
|
102
|
+
deck_point: DeckPoint
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
async def _execute_common(
|
|
106
|
+
state_view: StateView,
|
|
107
|
+
movement: MovementHandler,
|
|
108
|
+
pipetting: PipettingHandler,
|
|
109
|
+
params: _CommonParams,
|
|
110
|
+
) -> _ExecuteCommonResult:
|
|
111
|
+
pipette_id = params.pipetteId
|
|
112
|
+
labware_id = params.labwareId
|
|
113
|
+
well_name = params.wellName
|
|
114
|
+
|
|
115
|
+
state_update = update_types.StateUpdate()
|
|
116
|
+
|
|
117
|
+
# May raise TipNotAttachedError.
|
|
118
|
+
aspirated_volume = state_view.pipettes.get_aspirated_volume(pipette_id)
|
|
119
|
+
|
|
120
|
+
if aspirated_volume is None:
|
|
121
|
+
# Theoretically, we could avoid raising an error by automatically preparing
|
|
122
|
+
# to aspirate above the well like AspirateImplementation does. However, the
|
|
123
|
+
# only way for this to happen is if someone tries to do a liquid probe with
|
|
124
|
+
# a tip that's previously held liquid, which they should avoid anyway.
|
|
125
|
+
raise PipetteNotReadyToAspirateError(
|
|
126
|
+
"The pipette cannot probe liquid because of a previous blow out."
|
|
127
|
+
" The plunger must be reset while the tip is somewhere away from liquid."
|
|
128
|
+
)
|
|
129
|
+
elif aspirated_volume != 0:
|
|
130
|
+
raise TipNotEmptyError(
|
|
131
|
+
message="The pipette cannot probe for liquid when the tip has liquid in it."
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
if await movement.check_for_valid_position(mount=MountType.LEFT) is False:
|
|
135
|
+
raise MustHomeError(
|
|
136
|
+
message="Current position of pipette is invalid. Please home."
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
# liquid_probe process start position
|
|
140
|
+
position = await movement.move_to_well(
|
|
141
|
+
pipette_id=pipette_id,
|
|
142
|
+
labware_id=labware_id,
|
|
143
|
+
well_name=well_name,
|
|
144
|
+
well_location=params.wellLocation,
|
|
145
|
+
)
|
|
146
|
+
deck_point = DeckPoint.construct(x=position.x, y=position.y, z=position.z)
|
|
147
|
+
state_update.set_pipette_location(
|
|
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
|
+
|
|
154
|
+
try:
|
|
155
|
+
z_pos = await pipetting.liquid_probe_in_place(
|
|
156
|
+
pipette_id=pipette_id,
|
|
157
|
+
labware_id=labware_id,
|
|
158
|
+
well_name=well_name,
|
|
159
|
+
well_location=params.wellLocation,
|
|
160
|
+
)
|
|
161
|
+
except PipetteLiquidNotFoundError as exception:
|
|
162
|
+
return _ExecuteCommonResult(
|
|
163
|
+
z_pos_or_error=exception, state_update=state_update, deck_point=deck_point
|
|
164
|
+
)
|
|
165
|
+
else:
|
|
166
|
+
return _ExecuteCommonResult(
|
|
167
|
+
z_pos_or_error=z_pos, state_update=state_update, deck_point=deck_point
|
|
168
|
+
)
|
|
91
169
|
|
|
92
170
|
|
|
93
171
|
class LiquidProbeImplementation(
|
|
@@ -124,48 +202,17 @@ class LiquidProbeImplementation(
|
|
|
124
202
|
MustHomeError: as an undefined error, if the plunger is not in a valid
|
|
125
203
|
position.
|
|
126
204
|
"""
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
well_name = params.wellName
|
|
130
|
-
|
|
131
|
-
# May raise TipNotAttachedError.
|
|
132
|
-
aspirated_volume = self._state_view.pipettes.get_aspirated_volume(pipette_id)
|
|
133
|
-
|
|
134
|
-
if aspirated_volume is None:
|
|
135
|
-
# Theoretically, we could avoid raising an error by automatically preparing
|
|
136
|
-
# to aspirate above the well like AspirateImplementation does. However, the
|
|
137
|
-
# only way for this to happen is if someone tries to do a liquid probe with
|
|
138
|
-
# a tip that's previously held liquid, which they should avoid anyway.
|
|
139
|
-
raise PipetteNotReadyToAspirateError(
|
|
140
|
-
"The pipette cannot probe liquid because of a previous blow out."
|
|
141
|
-
" The plunger must be reset while the tip is somewhere away from liquid."
|
|
142
|
-
)
|
|
143
|
-
elif aspirated_volume != 0:
|
|
144
|
-
raise TipNotEmptyError(
|
|
145
|
-
message="The pipette cannot probe for liquid when the tip has liquid in it."
|
|
146
|
-
)
|
|
147
|
-
|
|
148
|
-
if await self._movement.check_for_valid_position(mount=MountType.LEFT) is False:
|
|
149
|
-
raise MustHomeError(
|
|
150
|
-
message="Current position of pipette is invalid. Please home."
|
|
151
|
-
)
|
|
152
|
-
|
|
153
|
-
# liquid_probe process start position
|
|
154
|
-
position = await self._movement.move_to_well(
|
|
155
|
-
pipette_id=pipette_id,
|
|
156
|
-
labware_id=labware_id,
|
|
157
|
-
well_name=well_name,
|
|
158
|
-
well_location=params.wellLocation,
|
|
205
|
+
z_pos_or_error, state_update, deck_point = await _execute_common(
|
|
206
|
+
self._state_view, self._movement, self._pipetting, params
|
|
159
207
|
)
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
208
|
+
if isinstance(z_pos_or_error, PipetteLiquidNotFoundError):
|
|
209
|
+
state_update.set_liquid_probed(
|
|
210
|
+
labware_id=params.labwareId,
|
|
211
|
+
well_name=params.wellName,
|
|
212
|
+
height=update_types.CLEAR,
|
|
213
|
+
volume=update_types.CLEAR,
|
|
214
|
+
last_probed=self._model_utils.get_timestamp(),
|
|
167
215
|
)
|
|
168
|
-
except PipetteLiquidNotFoundError as e:
|
|
169
216
|
return DefinedErrorData(
|
|
170
217
|
public=LiquidNotFoundError(
|
|
171
218
|
id=self._model_utils.generate_id(),
|
|
@@ -174,21 +221,35 @@ class LiquidProbeImplementation(
|
|
|
174
221
|
ErrorOccurrence.from_failed(
|
|
175
222
|
id=self._model_utils.generate_id(),
|
|
176
223
|
createdAt=self._model_utils.get_timestamp(),
|
|
177
|
-
error=
|
|
224
|
+
error=z_pos_or_error,
|
|
178
225
|
)
|
|
179
226
|
],
|
|
180
227
|
),
|
|
181
|
-
|
|
182
|
-
position=DeckPoint(x=position.x, y=position.y, z=position.z)
|
|
183
|
-
),
|
|
228
|
+
state_update=state_update,
|
|
184
229
|
)
|
|
185
230
|
else:
|
|
231
|
+
try:
|
|
232
|
+
well_volume: float | update_types.ClearType = (
|
|
233
|
+
self._state_view.geometry.get_well_volume_at_height(
|
|
234
|
+
labware_id=params.labwareId,
|
|
235
|
+
well_name=params.wellName,
|
|
236
|
+
height=z_pos_or_error,
|
|
237
|
+
)
|
|
238
|
+
)
|
|
239
|
+
except IncompleteLabwareDefinitionError:
|
|
240
|
+
well_volume = update_types.CLEAR
|
|
241
|
+
state_update.set_liquid_probed(
|
|
242
|
+
labware_id=params.labwareId,
|
|
243
|
+
well_name=params.wellName,
|
|
244
|
+
height=z_pos_or_error,
|
|
245
|
+
volume=well_volume,
|
|
246
|
+
last_probed=self._model_utils.get_timestamp(),
|
|
247
|
+
)
|
|
186
248
|
return SuccessData(
|
|
187
249
|
public=LiquidProbeResult(
|
|
188
|
-
z_position=
|
|
189
|
-
position=DeckPoint(x=position.x, y=position.y, z=position.z),
|
|
250
|
+
z_position=z_pos_or_error, position=deck_point
|
|
190
251
|
),
|
|
191
|
-
|
|
252
|
+
state_update=state_update,
|
|
192
253
|
)
|
|
193
254
|
|
|
194
255
|
|
|
@@ -217,40 +278,37 @@ class TryLiquidProbeImplementation(
|
|
|
217
278
|
found, `tryLiquidProbe` returns a success result with `z_position=null` instead
|
|
218
279
|
of a defined error.
|
|
219
280
|
"""
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
# Otherwise, we return the result or propagate the exception unchanged.
|
|
223
|
-
|
|
224
|
-
original_impl = LiquidProbeImplementation(
|
|
225
|
-
state_view=self._state_view,
|
|
226
|
-
movement=self._movement,
|
|
227
|
-
pipetting=self._pipetting,
|
|
228
|
-
model_utils=self._model_utils,
|
|
281
|
+
z_pos_or_error, state_update, deck_point = await _execute_common(
|
|
282
|
+
self._state_view, self._movement, self._pipetting, params
|
|
229
283
|
)
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
z_position=None,
|
|
240
|
-
position=original_private.position,
|
|
241
|
-
),
|
|
242
|
-
private=None,
|
|
243
|
-
)
|
|
244
|
-
case SuccessData(
|
|
245
|
-
public=LiquidProbeResult() as original_public, private=None
|
|
246
|
-
):
|
|
247
|
-
return SuccessData(
|
|
248
|
-
public=TryLiquidProbeResult(
|
|
249
|
-
position=original_public.position,
|
|
250
|
-
z_position=original_public.z_position,
|
|
251
|
-
),
|
|
252
|
-
private=None,
|
|
284
|
+
|
|
285
|
+
if isinstance(z_pos_or_error, PipetteLiquidNotFoundError):
|
|
286
|
+
z_pos = None
|
|
287
|
+
well_volume: float | update_types.ClearType = update_types.CLEAR
|
|
288
|
+
else:
|
|
289
|
+
z_pos = z_pos_or_error
|
|
290
|
+
try:
|
|
291
|
+
well_volume = self._state_view.geometry.get_well_volume_at_height(
|
|
292
|
+
labware_id=params.labwareId, well_name=params.wellName, height=z_pos
|
|
253
293
|
)
|
|
294
|
+
except IncompleteLabwareDefinitionError:
|
|
295
|
+
well_volume = update_types.CLEAR
|
|
296
|
+
|
|
297
|
+
state_update.set_liquid_probed(
|
|
298
|
+
labware_id=params.labwareId,
|
|
299
|
+
well_name=params.wellName,
|
|
300
|
+
height=z_pos if z_pos is not None else update_types.CLEAR,
|
|
301
|
+
volume=well_volume,
|
|
302
|
+
last_probed=self._model_utils.get_timestamp(),
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
return SuccessData(
|
|
306
|
+
public=TryLiquidProbeResult(
|
|
307
|
+
z_position=z_pos,
|
|
308
|
+
position=deck_point,
|
|
309
|
+
),
|
|
310
|
+
state_update=state_update,
|
|
311
|
+
)
|
|
254
312
|
|
|
255
313
|
|
|
256
314
|
class LiquidProbe(
|
|
@@ -17,9 +17,10 @@ from ..types import (
|
|
|
17
17
|
|
|
18
18
|
from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
|
|
19
19
|
from ..errors.error_occurrence import ErrorOccurrence
|
|
20
|
+
from ..state.update_types import StateUpdate
|
|
20
21
|
|
|
21
22
|
if TYPE_CHECKING:
|
|
22
|
-
from ..state import StateView
|
|
23
|
+
from ..state.state import StateView
|
|
23
24
|
from ..execution import EquipmentHandler
|
|
24
25
|
|
|
25
26
|
|
|
@@ -87,7 +88,7 @@ class LoadLabwareResult(BaseModel):
|
|
|
87
88
|
|
|
88
89
|
|
|
89
90
|
class LoadLabwareImplementation(
|
|
90
|
-
AbstractCommandImpl[LoadLabwareParams, SuccessData[LoadLabwareResult
|
|
91
|
+
AbstractCommandImpl[LoadLabwareParams, SuccessData[LoadLabwareResult]]
|
|
91
92
|
):
|
|
92
93
|
"""Load labware command implementation."""
|
|
93
94
|
|
|
@@ -99,7 +100,7 @@ class LoadLabwareImplementation(
|
|
|
99
100
|
|
|
100
101
|
async def execute(
|
|
101
102
|
self, params: LoadLabwareParams
|
|
102
|
-
) -> SuccessData[LoadLabwareResult
|
|
103
|
+
) -> SuccessData[LoadLabwareResult]:
|
|
103
104
|
"""Load definition and calibration data necessary for a labware."""
|
|
104
105
|
# TODO (tz, 8-15-2023): extend column validation to column 1 when working
|
|
105
106
|
# on https://opentrons.atlassian.net/browse/RSS-258 and completing
|
|
@@ -115,7 +116,10 @@ class LoadLabwareImplementation(
|
|
|
115
116
|
|
|
116
117
|
if isinstance(params.location, AddressableAreaLocation):
|
|
117
118
|
area_name = params.location.addressableAreaName
|
|
118
|
-
if not
|
|
119
|
+
if not (
|
|
120
|
+
fixture_validation.is_deck_slot(params.location.addressableAreaName)
|
|
121
|
+
or fixture_validation.is_abs_reader(params.location.addressableAreaName)
|
|
122
|
+
):
|
|
119
123
|
raise LabwareIsNotAllowedInLocationError(
|
|
120
124
|
f"Cannot load {params.loadName} onto addressable area {area_name}"
|
|
121
125
|
)
|
|
@@ -138,6 +142,16 @@ class LoadLabwareImplementation(
|
|
|
138
142
|
labware_id=params.labwareId,
|
|
139
143
|
)
|
|
140
144
|
|
|
145
|
+
state_update = StateUpdate()
|
|
146
|
+
|
|
147
|
+
state_update.set_loaded_labware(
|
|
148
|
+
labware_id=loaded_labware.labware_id,
|
|
149
|
+
offset_id=loaded_labware.offsetId,
|
|
150
|
+
definition=loaded_labware.definition,
|
|
151
|
+
location=verified_location,
|
|
152
|
+
display_name=params.displayName,
|
|
153
|
+
)
|
|
154
|
+
|
|
141
155
|
# TODO(jbl 2023-06-23) these validation checks happen after the labware is loaded, because they rely on
|
|
142
156
|
# on the definition. In practice this will not cause any issues since they will raise protocol ending
|
|
143
157
|
# exception, but for correctness should be refactored to do this check beforehand.
|
|
@@ -153,7 +167,7 @@ class LoadLabwareImplementation(
|
|
|
153
167
|
definition=loaded_labware.definition,
|
|
154
168
|
offsetId=loaded_labware.offsetId,
|
|
155
169
|
),
|
|
156
|
-
|
|
170
|
+
state_update=state_update,
|
|
157
171
|
)
|
|
158
172
|
|
|
159
173
|
|