opentrons 8.1.0a0__py2.py3-none-any.whl → 8.2.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/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 +208 -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/backends/ot3utils.py +1 -0
- 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 +232 -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 +131 -94
- 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/hardware_control/protocols/position_estimator.py +3 -1
- opentrons/hardware_control/types.py +2 -0
- opentrons/legacy_commands/helpers.py +8 -2
- 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 +20 -4
- opentrons/protocol_api/core/engine/module_core.py +166 -17
- opentrons/protocol_api/core/engine/pipette_movement_conflict.py +362 -0
- opentrons/protocol_api/core/engine/protocol.py +30 -2
- opentrons/protocol_api/core/instrument.py +2 -0
- opentrons/protocol_api/core/labware.py +4 -0
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +2 -0
- opentrons/protocol_api/core/legacy/legacy_labware_core.py +5 -0
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +6 -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 +6 -2
- opentrons/protocol_api/instrument_context.py +52 -20
- opentrons/protocol_api/labware.py +13 -1
- opentrons/protocol_api/module_contexts.py +115 -17
- opentrons/protocol_api/protocol_context.py +49 -5
- opentrons/protocol_api/validation.py +5 -3
- opentrons/protocol_engine/__init__.py +10 -9
- opentrons/protocol_engine/actions/__init__.py +3 -0
- opentrons/protocol_engine/actions/actions.py +30 -25
- opentrons/protocol_engine/actions/get_state_update.py +38 -0
- opentrons/protocol_engine/clients/sync_client.py +1 -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 +148 -0
- opentrons/protocol_engine/commands/absorbance_reader/initialize.py +65 -9
- opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +148 -0
- opentrons/protocol_engine/commands/absorbance_reader/read.py +200 -0
- opentrons/protocol_engine/commands/aspirate.py +29 -16
- opentrons/protocol_engine/commands/aspirate_in_place.py +33 -16
- 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 +31 -18
- 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 +70 -16
- opentrons/protocol_engine/commands/drop_tip_in_place.py +59 -13
- 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 +28 -5
- opentrons/protocol_engine/commands/load_liquid.py +18 -7
- opentrons/protocol_engine/commands/load_module.py +4 -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 +155 -23
- 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 +51 -30
- opentrons/protocol_engine/commands/pipetting_common.py +47 -16
- 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 +208 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +77 -0
- opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +10 -4
- 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 +60 -10
- opentrons/protocol_engine/engine_support.py +2 -1
- opentrons/protocol_engine/error_recovery_policy.py +14 -3
- opentrons/protocol_engine/errors/__init__.py +20 -0
- opentrons/protocol_engine/errors/error_occurrence.py +8 -3
- opentrons/protocol_engine/errors/exceptions.py +127 -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 +73 -22
- opentrons/protocol_engine/execution/movement.py +17 -7
- 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 +47 -31
- opentrons/protocol_engine/resources/__init__.py +2 -0
- opentrons/protocol_engine/resources/deck_data_provider.py +19 -5
- opentrons/protocol_engine/resources/file_provider.py +161 -0
- opentrons/protocol_engine/resources/fixture_validation.py +11 -1
- 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 +445 -59
- opentrons/protocol_engine/state/labware.py +264 -84
- opentrons/protocol_engine/state/liquids.py +1 -1
- opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +21 -3
- opentrons/protocol_engine/state/modules.py +145 -90
- opentrons/protocol_engine/state/motion.py +33 -14
- 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 +424 -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 +41 -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/protocols/parameters/csv_parameter_interface.py +3 -1
- 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.0.dist-info}/METADATA +5 -4
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0.dist-info}/RECORD +235 -223
- 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.0.dist-info}/LICENSE +0 -0
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0.dist-info}/WHEEL +0 -0
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0.dist-info}/entry_points.txt +0 -0
- {opentrons-8.1.0a0.dist-info → opentrons-8.2.0.dist-info}/top_level.txt +0 -0
|
@@ -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(
|
|
@@ -10,6 +10,8 @@ from ..errors import LabwareIsNotAllowedInLocationError
|
|
|
10
10
|
from ..resources import labware_validation, fixture_validation
|
|
11
11
|
from ..types import (
|
|
12
12
|
LabwareLocation,
|
|
13
|
+
ModuleLocation,
|
|
14
|
+
ModuleModel,
|
|
13
15
|
OnLabwareLocation,
|
|
14
16
|
DeckSlotLocation,
|
|
15
17
|
AddressableAreaLocation,
|
|
@@ -17,9 +19,10 @@ from ..types import (
|
|
|
17
19
|
|
|
18
20
|
from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
|
|
19
21
|
from ..errors.error_occurrence import ErrorOccurrence
|
|
22
|
+
from ..state.update_types import StateUpdate
|
|
20
23
|
|
|
21
24
|
if TYPE_CHECKING:
|
|
22
|
-
from ..state import StateView
|
|
25
|
+
from ..state.state import StateView
|
|
23
26
|
from ..execution import EquipmentHandler
|
|
24
27
|
|
|
25
28
|
|
|
@@ -87,7 +90,7 @@ class LoadLabwareResult(BaseModel):
|
|
|
87
90
|
|
|
88
91
|
|
|
89
92
|
class LoadLabwareImplementation(
|
|
90
|
-
AbstractCommandImpl[LoadLabwareParams, SuccessData[LoadLabwareResult
|
|
93
|
+
AbstractCommandImpl[LoadLabwareParams, SuccessData[LoadLabwareResult]]
|
|
91
94
|
):
|
|
92
95
|
"""Load labware command implementation."""
|
|
93
96
|
|
|
@@ -99,7 +102,7 @@ class LoadLabwareImplementation(
|
|
|
99
102
|
|
|
100
103
|
async def execute(
|
|
101
104
|
self, params: LoadLabwareParams
|
|
102
|
-
) -> SuccessData[LoadLabwareResult
|
|
105
|
+
) -> SuccessData[LoadLabwareResult]:
|
|
103
106
|
"""Load definition and calibration data necessary for a labware."""
|
|
104
107
|
# TODO (tz, 8-15-2023): extend column validation to column 1 when working
|
|
105
108
|
# on https://opentrons.atlassian.net/browse/RSS-258 and completing
|
|
@@ -115,7 +118,10 @@ class LoadLabwareImplementation(
|
|
|
115
118
|
|
|
116
119
|
if isinstance(params.location, AddressableAreaLocation):
|
|
117
120
|
area_name = params.location.addressableAreaName
|
|
118
|
-
if not
|
|
121
|
+
if not (
|
|
122
|
+
fixture_validation.is_deck_slot(params.location.addressableAreaName)
|
|
123
|
+
or fixture_validation.is_abs_reader(params.location.addressableAreaName)
|
|
124
|
+
):
|
|
119
125
|
raise LabwareIsNotAllowedInLocationError(
|
|
120
126
|
f"Cannot load {params.loadName} onto addressable area {area_name}"
|
|
121
127
|
)
|
|
@@ -138,6 +144,16 @@ class LoadLabwareImplementation(
|
|
|
138
144
|
labware_id=params.labwareId,
|
|
139
145
|
)
|
|
140
146
|
|
|
147
|
+
state_update = StateUpdate()
|
|
148
|
+
|
|
149
|
+
state_update.set_loaded_labware(
|
|
150
|
+
labware_id=loaded_labware.labware_id,
|
|
151
|
+
offset_id=loaded_labware.offsetId,
|
|
152
|
+
definition=loaded_labware.definition,
|
|
153
|
+
location=verified_location,
|
|
154
|
+
display_name=params.displayName,
|
|
155
|
+
)
|
|
156
|
+
|
|
141
157
|
# TODO(jbl 2023-06-23) these validation checks happen after the labware is loaded, because they rely on
|
|
142
158
|
# on the definition. In practice this will not cause any issues since they will raise protocol ending
|
|
143
159
|
# exception, but for correctness should be refactored to do this check beforehand.
|
|
@@ -146,6 +162,13 @@ class LoadLabwareImplementation(
|
|
|
146
162
|
top_labware_definition=loaded_labware.definition,
|
|
147
163
|
bottom_labware_id=verified_location.labwareId,
|
|
148
164
|
)
|
|
165
|
+
# Validate labware for the absorbance reader
|
|
166
|
+
elif isinstance(params.location, ModuleLocation):
|
|
167
|
+
module = self._state_view.modules.get(params.location.moduleId)
|
|
168
|
+
if module is not None and module.model == ModuleModel.ABSORBANCE_READER_V1:
|
|
169
|
+
self._state_view.labware.raise_if_labware_incompatible_with_plate_reader(
|
|
170
|
+
loaded_labware.definition
|
|
171
|
+
)
|
|
149
172
|
|
|
150
173
|
return SuccessData(
|
|
151
174
|
public=LoadLabwareResult(
|
|
@@ -153,7 +176,7 @@ class LoadLabwareImplementation(
|
|
|
153
176
|
definition=loaded_labware.definition,
|
|
154
177
|
offsetId=loaded_labware.offsetId,
|
|
155
178
|
),
|
|
156
|
-
|
|
179
|
+
state_update=state_update,
|
|
157
180
|
)
|
|
158
181
|
|
|
159
182
|
|
|
@@ -4,11 +4,14 @@ from pydantic import BaseModel, Field
|
|
|
4
4
|
from typing import Optional, Type, Dict, TYPE_CHECKING
|
|
5
5
|
from typing_extensions import Literal
|
|
6
6
|
|
|
7
|
+
from opentrons.protocol_engine.state.update_types import StateUpdate
|
|
8
|
+
|
|
7
9
|
from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
|
|
8
10
|
from ..errors.error_occurrence import ErrorOccurrence
|
|
9
11
|
|
|
10
12
|
if TYPE_CHECKING:
|
|
11
|
-
from ..state import StateView
|
|
13
|
+
from ..state.state import StateView
|
|
14
|
+
from ..resources import ModelUtils
|
|
12
15
|
|
|
13
16
|
LoadLiquidCommandType = Literal["loadLiquid"]
|
|
14
17
|
|
|
@@ -37,16 +40,17 @@ class LoadLiquidResult(BaseModel):
|
|
|
37
40
|
|
|
38
41
|
|
|
39
42
|
class LoadLiquidImplementation(
|
|
40
|
-
AbstractCommandImpl[LoadLiquidParams, SuccessData[LoadLiquidResult
|
|
43
|
+
AbstractCommandImpl[LoadLiquidParams, SuccessData[LoadLiquidResult]]
|
|
41
44
|
):
|
|
42
45
|
"""Load liquid command implementation."""
|
|
43
46
|
|
|
44
|
-
def __init__(
|
|
47
|
+
def __init__(
|
|
48
|
+
self, state_view: StateView, model_utils: ModelUtils, **kwargs: object
|
|
49
|
+
) -> None:
|
|
45
50
|
self._state_view = state_view
|
|
51
|
+
self._model_utils = model_utils
|
|
46
52
|
|
|
47
|
-
async def execute(
|
|
48
|
-
self, params: LoadLiquidParams
|
|
49
|
-
) -> SuccessData[LoadLiquidResult, None]:
|
|
53
|
+
async def execute(self, params: LoadLiquidParams) -> SuccessData[LoadLiquidResult]:
|
|
50
54
|
"""Load data necessary for a liquid."""
|
|
51
55
|
self._state_view.liquid.validate_liquid_id(params.liquidId)
|
|
52
56
|
|
|
@@ -54,7 +58,14 @@ class LoadLiquidImplementation(
|
|
|
54
58
|
labware_id=params.labwareId, wells=params.volumeByWell
|
|
55
59
|
)
|
|
56
60
|
|
|
57
|
-
|
|
61
|
+
state_update = StateUpdate()
|
|
62
|
+
state_update.set_liquid_loaded(
|
|
63
|
+
labware_id=params.labwareId,
|
|
64
|
+
volumes=params.volumeByWell,
|
|
65
|
+
last_loaded=self._model_utils.get_timestamp(),
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
return SuccessData(public=LoadLiquidResult(), state_update=state_update)
|
|
58
69
|
|
|
59
70
|
|
|
60
71
|
class LoadLiquid(BaseCommand[LoadLiquidParams, LoadLiquidResult, ErrorOccurrence]):
|
|
@@ -16,8 +16,9 @@ from opentrons.types import DeckSlotName
|
|
|
16
16
|
|
|
17
17
|
from opentrons.protocol_engine.resources import deck_configuration_provider
|
|
18
18
|
|
|
19
|
+
|
|
19
20
|
if TYPE_CHECKING:
|
|
20
|
-
from ..state import StateView
|
|
21
|
+
from ..state.state import StateView
|
|
21
22
|
from ..execution import EquipmentHandler
|
|
22
23
|
|
|
23
24
|
|
|
@@ -103,7 +104,7 @@ class LoadModuleResult(BaseModel):
|
|
|
103
104
|
|
|
104
105
|
|
|
105
106
|
class LoadModuleImplementation(
|
|
106
|
-
AbstractCommandImpl[LoadModuleParams, SuccessData[LoadModuleResult
|
|
107
|
+
AbstractCommandImpl[LoadModuleParams, SuccessData[LoadModuleResult]]
|
|
107
108
|
):
|
|
108
109
|
"""The implementation of the load module command."""
|
|
109
110
|
|
|
@@ -113,9 +114,7 @@ class LoadModuleImplementation(
|
|
|
113
114
|
self._equipment = equipment
|
|
114
115
|
self._state_view = state_view
|
|
115
116
|
|
|
116
|
-
async def execute(
|
|
117
|
-
self, params: LoadModuleParams
|
|
118
|
-
) -> SuccessData[LoadModuleResult, None]:
|
|
117
|
+
async def execute(self, params: LoadModuleParams) -> SuccessData[LoadModuleResult]:
|
|
119
118
|
"""Check that the requested module is attached and assign its identifier."""
|
|
120
119
|
module_type = params.model.as_type()
|
|
121
120
|
self._ensure_module_location(params.location.slotName, module_type)
|
|
@@ -158,7 +157,6 @@ class LoadModuleImplementation(
|
|
|
158
157
|
model=loaded_module.definition.model,
|
|
159
158
|
definition=loaded_module.definition,
|
|
160
159
|
),
|
|
161
|
-
private=None,
|
|
162
160
|
)
|
|
163
161
|
|
|
164
162
|
def _ensure_module_location(
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Load pipette command request, result, and implementation models."""
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
|
+
from opentrons.protocol_engine.state.update_types import StateUpdate
|
|
4
5
|
from opentrons_shared_data.pipette.pipette_load_name_conversions import (
|
|
5
6
|
convert_to_pipette_name_type,
|
|
6
7
|
)
|
|
@@ -16,23 +17,16 @@ from opentrons.types import MountType
|
|
|
16
17
|
|
|
17
18
|
from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
|
|
18
19
|
from ..errors.error_occurrence import ErrorOccurrence
|
|
19
|
-
from .configuring_common import PipetteConfigUpdateResultMixin
|
|
20
20
|
from ..errors import InvalidSpecificationForRobotTypeError, InvalidLoadPipetteSpecsError
|
|
21
21
|
|
|
22
22
|
if TYPE_CHECKING:
|
|
23
23
|
from ..execution import EquipmentHandler
|
|
24
|
-
from ..state import StateView
|
|
24
|
+
from ..state.state import StateView
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
LoadPipetteCommandType = Literal["loadPipette"]
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
class LoadPipettePrivateResult(PipetteConfigUpdateResultMixin):
|
|
31
|
-
"""The not-to-be-exposed results of a load pipette call."""
|
|
32
|
-
|
|
33
|
-
...
|
|
34
|
-
|
|
35
|
-
|
|
36
30
|
class LoadPipetteParams(BaseModel):
|
|
37
31
|
"""Payload needed to load a pipette on to a mount."""
|
|
38
32
|
|
|
@@ -72,9 +66,7 @@ class LoadPipetteResult(BaseModel):
|
|
|
72
66
|
|
|
73
67
|
|
|
74
68
|
class LoadPipetteImplementation(
|
|
75
|
-
AbstractCommandImpl[
|
|
76
|
-
LoadPipetteParams, SuccessData[LoadPipetteResult, LoadPipettePrivateResult]
|
|
77
|
-
]
|
|
69
|
+
AbstractCommandImpl[LoadPipetteParams, SuccessData[LoadPipetteResult]]
|
|
78
70
|
):
|
|
79
71
|
"""Load pipette command implementation."""
|
|
80
72
|
|
|
@@ -86,7 +78,7 @@ class LoadPipetteImplementation(
|
|
|
86
78
|
|
|
87
79
|
async def execute(
|
|
88
80
|
self, params: LoadPipetteParams
|
|
89
|
-
) -> SuccessData[LoadPipetteResult
|
|
81
|
+
) -> SuccessData[LoadPipetteResult]:
|
|
90
82
|
"""Check that requested pipette is attached and assign its identifier."""
|
|
91
83
|
pipette_generation = convert_to_pipette_name_type(
|
|
92
84
|
params.pipetteName.value
|
|
@@ -123,13 +115,22 @@ class LoadPipetteImplementation(
|
|
|
123
115
|
tip_overlap_version=params.tipOverlapNotAfterVersion,
|
|
124
116
|
)
|
|
125
117
|
|
|
118
|
+
state_update = StateUpdate()
|
|
119
|
+
state_update.set_load_pipette(
|
|
120
|
+
pipette_id=loaded_pipette.pipette_id,
|
|
121
|
+
pipette_name=params.pipetteName,
|
|
122
|
+
mount=params.mount,
|
|
123
|
+
liquid_presence_detection=params.liquidPresenceDetection,
|
|
124
|
+
)
|
|
125
|
+
state_update.update_pipette_config(
|
|
126
|
+
pipette_id=loaded_pipette.pipette_id,
|
|
127
|
+
serial_number=loaded_pipette.serial_number,
|
|
128
|
+
config=loaded_pipette.static_config,
|
|
129
|
+
)
|
|
130
|
+
|
|
126
131
|
return SuccessData(
|
|
127
132
|
public=LoadPipetteResult(pipetteId=loaded_pipette.pipette_id),
|
|
128
|
-
|
|
129
|
-
pipette_id=loaded_pipette.pipette_id,
|
|
130
|
-
serial_number=loaded_pipette.serial_number,
|
|
131
|
-
config=loaded_pipette.static_config,
|
|
132
|
-
),
|
|
133
|
+
state_update=state_update,
|
|
133
134
|
)
|
|
134
135
|
|
|
135
136
|
|
|
@@ -13,7 +13,7 @@ from ...errors.error_occurrence import ErrorOccurrence
|
|
|
13
13
|
|
|
14
14
|
if TYPE_CHECKING:
|
|
15
15
|
from opentrons.protocol_engine.execution import EquipmentHandler
|
|
16
|
-
from opentrons.protocol_engine.state import StateView
|
|
16
|
+
from opentrons.protocol_engine.state.state import StateView
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
DisengageCommandType = Literal["magneticModule/disengage"]
|
|
@@ -38,7 +38,7 @@ class DisengageResult(BaseModel):
|
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
class DisengageImplementation(
|
|
41
|
-
AbstractCommandImpl[DisengageParams, SuccessData[DisengageResult
|
|
41
|
+
AbstractCommandImpl[DisengageParams, SuccessData[DisengageResult]]
|
|
42
42
|
):
|
|
43
43
|
"""The implementation of a Magnetic Module disengage command."""
|
|
44
44
|
|
|
@@ -51,9 +51,7 @@ class DisengageImplementation(
|
|
|
51
51
|
self._state_view = state_view
|
|
52
52
|
self._equipment = equipment
|
|
53
53
|
|
|
54
|
-
async def execute(
|
|
55
|
-
self, params: DisengageParams
|
|
56
|
-
) -> SuccessData[DisengageResult, None]:
|
|
54
|
+
async def execute(self, params: DisengageParams) -> SuccessData[DisengageResult]:
|
|
57
55
|
"""Execute a Magnetic Module disengage command.
|
|
58
56
|
|
|
59
57
|
Raises:
|
|
@@ -75,7 +73,9 @@ class DisengageImplementation(
|
|
|
75
73
|
if hardware_module is not None: # Not virtualizing modules.
|
|
76
74
|
await hardware_module.deactivate()
|
|
77
75
|
|
|
78
|
-
return SuccessData(
|
|
76
|
+
return SuccessData(
|
|
77
|
+
public=DisengageResult(),
|
|
78
|
+
)
|
|
79
79
|
|
|
80
80
|
|
|
81
81
|
class Disengage(BaseCommand[DisengageParams, DisengageResult, ErrorOccurrence]):
|
|
@@ -10,7 +10,7 @@ from ...errors.error_occurrence import ErrorOccurrence
|
|
|
10
10
|
|
|
11
11
|
if TYPE_CHECKING:
|
|
12
12
|
from opentrons.protocol_engine.execution import EquipmentHandler
|
|
13
|
-
from opentrons.protocol_engine.state import StateView
|
|
13
|
+
from opentrons.protocol_engine.state.state import StateView
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
EngageCommandType = Literal["magneticModule/engage"]
|
|
@@ -54,7 +54,7 @@ class EngageResult(BaseModel):
|
|
|
54
54
|
|
|
55
55
|
|
|
56
56
|
class EngageImplementation(
|
|
57
|
-
AbstractCommandImpl[EngageParams, SuccessData[EngageResult
|
|
57
|
+
AbstractCommandImpl[EngageParams, SuccessData[EngageResult]]
|
|
58
58
|
):
|
|
59
59
|
"""The implementation of a Magnetic Module engage command."""
|
|
60
60
|
|
|
@@ -67,7 +67,7 @@ class EngageImplementation(
|
|
|
67
67
|
self._state_view = state_view
|
|
68
68
|
self._equipment = equipment
|
|
69
69
|
|
|
70
|
-
async def execute(self, params: EngageParams) -> SuccessData[EngageResult
|
|
70
|
+
async def execute(self, params: EngageParams) -> SuccessData[EngageResult]:
|
|
71
71
|
"""Execute a Magnetic Module engage command.
|
|
72
72
|
|
|
73
73
|
Raises:
|
|
@@ -95,7 +95,9 @@ class EngageImplementation(
|
|
|
95
95
|
if hardware_module is not None: # Not virtualizing modules.
|
|
96
96
|
await hardware_module.engage(height=hardware_height)
|
|
97
97
|
|
|
98
|
-
return SuccessData(
|
|
98
|
+
return SuccessData(
|
|
99
|
+
public=EngageResult(),
|
|
100
|
+
)
|
|
99
101
|
|
|
100
102
|
|
|
101
103
|
class Engage(BaseCommand[EngageParams, EngageResult, ErrorOccurrence]):
|