opentrons 8.2.0a4__py2.py3-none-any.whl → 8.3.0a1__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 +28 -20
- 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 +60 -23
- 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 +18 -0
- opentrons/hardware_control/protocols/motion_controller.py +6 -0
- opentrons/hardware_control/robot_calibration.py +1 -1
- opentrons/hardware_control/types.py +61 -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 +82 -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 +46 -4
- opentrons/protocol_api/core/labware.py +13 -4
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +37 -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 +37 -3
- opentrons/protocol_api/core/protocol.py +34 -1
- opentrons/protocol_api/core/robot.py +51 -0
- opentrons/protocol_api/instrument_context.py +158 -44
- opentrons/protocol_api/labware.py +231 -7
- 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 +81 -0
- opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +0 -2
- opentrons/protocol_engine/commands/absorbance_reader/initialize.py +19 -5
- opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +0 -1
- opentrons/protocol_engine/commands/absorbance_reader/read.py +32 -9
- 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 +101 -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 +13 -3
- 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 +67 -24
- opentrons/protocol_engine/commands/load_labware.py +29 -7
- 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 +19 -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 +8 -2
- 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 +4 -1
- opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +12 -3
- opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +1 -4
- opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +1 -4
- 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 +8 -0
- opentrons/protocol_engine/errors/error_occurrence.py +19 -20
- opentrons/protocol_engine/errors/exceptions.py +50 -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 +364 -8
- opentrons/protocol_engine/execution/movement.py +27 -0
- opentrons/protocol_engine/execution/pipetting.py +5 -1
- opentrons/protocol_engine/execution/tip_handler.py +4 -6
- 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 +5 -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 +17 -13
- opentrons/protocol_engine/state/files.py +10 -12
- opentrons/protocol_engine/state/fluid_stack.py +138 -0
- opentrons/protocol_engine/state/frustum_helpers.py +57 -32
- opentrons/protocol_engine/state/geometry.py +47 -1
- opentrons/protocol_engine/state/labware.py +79 -25
- opentrons/protocol_engine/state/liquid_classes.py +82 -0
- opentrons/protocol_engine/state/liquids.py +16 -4
- opentrons/protocol_engine/state/modules.py +52 -70
- opentrons/protocol_engine/state/motion.py +6 -1
- opentrons/protocol_engine/state/pipettes.py +144 -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 +39 -6
- opentrons/protocols/models/json_protocol.py +5 -9
- opentrons/simulate.py +3 -1
- opentrons/types.py +162 -2
- opentrons/util/logging_config.py +1 -1
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0a1.dist-info}/METADATA +16 -15
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0a1.dist-info}/RECORD +229 -202
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0a1.dist-info}/WHEEL +1 -1
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0a1.dist-info}/LICENSE +0 -0
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0a1.dist-info}/entry_points.txt +0 -0
- {opentrons-8.2.0a4.dist-info → opentrons-8.3.0a1.dist-info}/top_level.txt +0 -0
|
@@ -10,7 +10,7 @@ data still adheres to the shapes that ProtocolEngine expects.
|
|
|
10
10
|
If you are implementing a custom command, you should probably
|
|
11
11
|
put your own disambiguation identifier in the payload.
|
|
12
12
|
"""
|
|
13
|
-
from pydantic import BaseModel,
|
|
13
|
+
from pydantic import ConfigDict, BaseModel, SerializeAsAny
|
|
14
14
|
from typing import Optional, Type
|
|
15
15
|
from typing_extensions import Literal
|
|
16
16
|
|
|
@@ -24,19 +24,13 @@ CustomCommandType = Literal["custom"]
|
|
|
24
24
|
class CustomParams(BaseModel):
|
|
25
25
|
"""Payload used by a custom command."""
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
"""Allow arbitrary fields."""
|
|
29
|
-
|
|
30
|
-
extra = Extra.allow
|
|
27
|
+
model_config = ConfigDict(extra="allow")
|
|
31
28
|
|
|
32
29
|
|
|
33
30
|
class CustomResult(BaseModel):
|
|
34
31
|
"""Result data from a custom command."""
|
|
35
32
|
|
|
36
|
-
|
|
37
|
-
"""Allow arbitrary fields."""
|
|
38
|
-
|
|
39
|
-
extra = Extra.allow
|
|
33
|
+
model_config = ConfigDict(extra="allow")
|
|
40
34
|
|
|
41
35
|
|
|
42
36
|
class CustomImplementation(
|
|
@@ -50,7 +44,7 @@ class CustomImplementation(
|
|
|
50
44
|
async def execute(self, params: CustomParams) -> SuccessData[CustomResult]:
|
|
51
45
|
"""A custom command does nothing when executed directly."""
|
|
52
46
|
return SuccessData(
|
|
53
|
-
public=CustomResult.
|
|
47
|
+
public=CustomResult.model_construct(),
|
|
54
48
|
)
|
|
55
49
|
|
|
56
50
|
|
|
@@ -58,8 +52,8 @@ class Custom(BaseCommand[CustomParams, CustomResult, ErrorOccurrence]):
|
|
|
58
52
|
"""Custom command model."""
|
|
59
53
|
|
|
60
54
|
commandType: CustomCommandType = "custom"
|
|
61
|
-
params: CustomParams
|
|
62
|
-
result: Optional[CustomResult]
|
|
55
|
+
params: SerializeAsAny[CustomParams]
|
|
56
|
+
result: Optional[CustomResult] = None
|
|
63
57
|
|
|
64
58
|
_ImplementationCls: Type[CustomImplementation] = CustomImplementation
|
|
65
59
|
|
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
"""Dispense command request, result, and implementation models."""
|
|
2
|
+
|
|
2
3
|
from __future__ import annotations
|
|
3
|
-
from typing import TYPE_CHECKING, Optional, Type, Union
|
|
4
|
+
from typing import TYPE_CHECKING, Optional, Type, Union, Any
|
|
4
5
|
from typing_extensions import Literal
|
|
5
6
|
|
|
6
|
-
from opentrons_shared_data.errors.exceptions import PipetteOverpressureError
|
|
7
7
|
|
|
8
8
|
from pydantic import Field
|
|
9
|
+
from pydantic.json_schema import SkipJsonSchema
|
|
9
10
|
|
|
10
|
-
from ..types import DeckPoint
|
|
11
11
|
from ..state.update_types import StateUpdate, CLEAR
|
|
12
12
|
from .pipetting_common import (
|
|
13
13
|
PipetteIdMixin,
|
|
14
14
|
DispenseVolumeMixin,
|
|
15
15
|
FlowRateMixin,
|
|
16
|
-
LiquidHandlingWellLocationMixin,
|
|
17
16
|
BaseLiquidHandlingResult,
|
|
18
|
-
DestinationPositionResult,
|
|
19
17
|
OverpressureError,
|
|
18
|
+
dispense_in_place,
|
|
19
|
+
)
|
|
20
|
+
from .movement_common import (
|
|
21
|
+
LiquidHandlingWellLocationMixin,
|
|
22
|
+
DestinationPositionResult,
|
|
23
|
+
StallOrCollisionError,
|
|
24
|
+
move_to_well,
|
|
20
25
|
)
|
|
21
26
|
from .command import (
|
|
22
27
|
AbstractCommandImpl,
|
|
@@ -25,7 +30,6 @@ from .command import (
|
|
|
25
30
|
DefinedErrorData,
|
|
26
31
|
SuccessData,
|
|
27
32
|
)
|
|
28
|
-
from ..errors.error_occurrence import ErrorOccurrence
|
|
29
33
|
|
|
30
34
|
if TYPE_CHECKING:
|
|
31
35
|
from ..execution import MovementHandler, PipettingHandler
|
|
@@ -36,14 +40,19 @@ if TYPE_CHECKING:
|
|
|
36
40
|
DispenseCommandType = Literal["dispense"]
|
|
37
41
|
|
|
38
42
|
|
|
43
|
+
def _remove_default(s: dict[str, Any]) -> None:
|
|
44
|
+
s.pop("default", None)
|
|
45
|
+
|
|
46
|
+
|
|
39
47
|
class DispenseParams(
|
|
40
48
|
PipetteIdMixin, DispenseVolumeMixin, FlowRateMixin, LiquidHandlingWellLocationMixin
|
|
41
49
|
):
|
|
42
50
|
"""Payload required to dispense to a specific well."""
|
|
43
51
|
|
|
44
|
-
pushOut:
|
|
52
|
+
pushOut: float | SkipJsonSchema[None] = Field(
|
|
45
53
|
None,
|
|
46
54
|
description="push the plunger a small amount farther than necessary for accurate low-volume dispensing",
|
|
55
|
+
json_schema_extra=_remove_default,
|
|
47
56
|
)
|
|
48
57
|
|
|
49
58
|
|
|
@@ -55,7 +64,7 @@ class DispenseResult(BaseLiquidHandlingResult, DestinationPositionResult):
|
|
|
55
64
|
|
|
56
65
|
_ExecuteReturn = Union[
|
|
57
66
|
SuccessData[DispenseResult],
|
|
58
|
-
DefinedErrorData[OverpressureError],
|
|
67
|
+
DefinedErrorData[OverpressureError] | DefinedErrorData[StallOrCollisionError],
|
|
59
68
|
]
|
|
60
69
|
|
|
61
70
|
|
|
@@ -77,7 +86,6 @@ class DispenseImplementation(AbstractCommandImpl[DispenseParams, _ExecuteReturn]
|
|
|
77
86
|
|
|
78
87
|
async def execute(self, params: DispenseParams) -> _ExecuteReturn:
|
|
79
88
|
"""Move to and dispense to the requested well."""
|
|
80
|
-
state_update = StateUpdate()
|
|
81
89
|
well_location = params.wellLocation
|
|
82
90
|
labware_id = params.labwareId
|
|
83
91
|
well_name = params.wellName
|
|
@@ -85,66 +93,92 @@ class DispenseImplementation(AbstractCommandImpl[DispenseParams, _ExecuteReturn]
|
|
|
85
93
|
|
|
86
94
|
# TODO(pbm, 10-15-24): call self._state_view.geometry.validate_dispense_volume_into_well()
|
|
87
95
|
|
|
88
|
-
|
|
96
|
+
move_result = await move_to_well(
|
|
97
|
+
movement=self._movement,
|
|
98
|
+
model_utils=self._model_utils,
|
|
89
99
|
pipette_id=params.pipetteId,
|
|
90
100
|
labware_id=labware_id,
|
|
91
101
|
well_name=well_name,
|
|
92
102
|
well_location=well_location,
|
|
93
103
|
)
|
|
94
|
-
|
|
95
|
-
|
|
104
|
+
if isinstance(move_result, DefinedErrorData):
|
|
105
|
+
return move_result
|
|
106
|
+
dispense_result = await dispense_in_place(
|
|
96
107
|
pipette_id=params.pipetteId,
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
108
|
+
volume=volume,
|
|
109
|
+
flow_rate=params.flowRate,
|
|
110
|
+
push_out=params.pushOut,
|
|
111
|
+
location_if_error={
|
|
112
|
+
"retryLocation": (
|
|
113
|
+
move_result.public.position.x,
|
|
114
|
+
move_result.public.position.y,
|
|
115
|
+
move_result.public.position.z,
|
|
116
|
+
)
|
|
117
|
+
},
|
|
118
|
+
pipetting=self._pipetting,
|
|
119
|
+
model_utils=self._model_utils,
|
|
100
120
|
)
|
|
101
121
|
|
|
102
|
-
|
|
103
|
-
volume = await self._pipetting.dispense_in_place(
|
|
104
|
-
pipette_id=params.pipetteId,
|
|
105
|
-
volume=volume,
|
|
106
|
-
flow_rate=params.flowRate,
|
|
107
|
-
push_out=params.pushOut,
|
|
108
|
-
)
|
|
109
|
-
except PipetteOverpressureError as e:
|
|
110
|
-
state_update.set_liquid_operated(
|
|
111
|
-
labware_id=labware_id,
|
|
112
|
-
well_name=well_name,
|
|
113
|
-
volume_added=CLEAR,
|
|
114
|
-
)
|
|
122
|
+
if isinstance(dispense_result, DefinedErrorData):
|
|
115
123
|
return DefinedErrorData(
|
|
116
|
-
public=
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
|
|
124
|
+
public=dispense_result.public,
|
|
125
|
+
state_update=(
|
|
126
|
+
StateUpdate.reduce(
|
|
127
|
+
move_result.state_update, dispense_result.state_update
|
|
128
|
+
).set_liquid_operated(
|
|
129
|
+
labware_id=labware_id,
|
|
130
|
+
well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well(
|
|
131
|
+
labware_id, well_name, params.pipetteId
|
|
132
|
+
),
|
|
133
|
+
volume_added=CLEAR,
|
|
134
|
+
)
|
|
135
|
+
),
|
|
136
|
+
state_update_if_false_positive=StateUpdate.reduce(
|
|
137
|
+
move_result.state_update,
|
|
138
|
+
dispense_result.state_update_if_false_positive,
|
|
127
139
|
),
|
|
128
|
-
state_update=state_update,
|
|
129
140
|
)
|
|
130
141
|
else:
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
142
|
+
volume_added = (
|
|
143
|
+
self._state_view.pipettes.get_liquid_dispensed_by_ejecting_volume(
|
|
144
|
+
pipette_id=params.pipetteId, volume=dispense_result.public.volume
|
|
145
|
+
)
|
|
135
146
|
)
|
|
147
|
+
if volume_added is not None:
|
|
148
|
+
volume_added *= self._state_view.geometry.get_nozzles_per_well(
|
|
149
|
+
labware_id, well_name, params.pipetteId
|
|
150
|
+
)
|
|
136
151
|
return SuccessData(
|
|
137
|
-
public=DispenseResult(
|
|
138
|
-
|
|
152
|
+
public=DispenseResult(
|
|
153
|
+
volume=dispense_result.public.volume,
|
|
154
|
+
position=move_result.public.position,
|
|
155
|
+
),
|
|
156
|
+
state_update=(
|
|
157
|
+
StateUpdate.reduce(
|
|
158
|
+
move_result.state_update, dispense_result.state_update
|
|
159
|
+
).set_liquid_operated(
|
|
160
|
+
labware_id=labware_id,
|
|
161
|
+
well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well(
|
|
162
|
+
labware_id, well_name, params.pipetteId
|
|
163
|
+
),
|
|
164
|
+
volume_added=volume_added
|
|
165
|
+
if volume_added is not None
|
|
166
|
+
else CLEAR,
|
|
167
|
+
)
|
|
168
|
+
),
|
|
139
169
|
)
|
|
140
170
|
|
|
141
171
|
|
|
142
|
-
class Dispense(
|
|
172
|
+
class Dispense(
|
|
173
|
+
BaseCommand[
|
|
174
|
+
DispenseParams, DispenseResult, OverpressureError | StallOrCollisionError
|
|
175
|
+
]
|
|
176
|
+
):
|
|
143
177
|
"""Dispense command model."""
|
|
144
178
|
|
|
145
179
|
commandType: DispenseCommandType = "dispense"
|
|
146
180
|
params: DispenseParams
|
|
147
|
-
result: Optional[DispenseResult]
|
|
181
|
+
result: Optional[DispenseResult] = None
|
|
148
182
|
|
|
149
183
|
_ImplementationCls: Type[DispenseImplementation] = DispenseImplementation
|
|
150
184
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"""Dispense-in-place command request, result, and implementation models."""
|
|
2
|
+
|
|
2
3
|
from __future__ import annotations
|
|
3
|
-
from typing import TYPE_CHECKING, Optional, Type, Union
|
|
4
|
+
from typing import TYPE_CHECKING, Optional, Type, Union, Any
|
|
4
5
|
from typing_extensions import Literal
|
|
5
6
|
from pydantic import Field
|
|
6
|
-
|
|
7
|
-
from opentrons_shared_data.errors.exceptions import PipetteOverpressureError
|
|
7
|
+
from pydantic.json_schema import SkipJsonSchema
|
|
8
8
|
|
|
9
9
|
from .pipetting_common import (
|
|
10
10
|
PipetteIdMixin,
|
|
@@ -12,6 +12,7 @@ from .pipetting_common import (
|
|
|
12
12
|
FlowRateMixin,
|
|
13
13
|
BaseLiquidHandlingResult,
|
|
14
14
|
OverpressureError,
|
|
15
|
+
dispense_in_place,
|
|
15
16
|
)
|
|
16
17
|
from .command import (
|
|
17
18
|
AbstractCommandImpl,
|
|
@@ -20,8 +21,7 @@ from .command import (
|
|
|
20
21
|
SuccessData,
|
|
21
22
|
DefinedErrorData,
|
|
22
23
|
)
|
|
23
|
-
from ..
|
|
24
|
-
from ..state.update_types import StateUpdate, CLEAR
|
|
24
|
+
from ..state.update_types import CLEAR
|
|
25
25
|
from ..types import CurrentWell
|
|
26
26
|
|
|
27
27
|
if TYPE_CHECKING:
|
|
@@ -33,12 +33,17 @@ if TYPE_CHECKING:
|
|
|
33
33
|
DispenseInPlaceCommandType = Literal["dispenseInPlace"]
|
|
34
34
|
|
|
35
35
|
|
|
36
|
+
def _remove_default(s: dict[str, Any]) -> None:
|
|
37
|
+
s.pop("default", None)
|
|
38
|
+
|
|
39
|
+
|
|
36
40
|
class DispenseInPlaceParams(PipetteIdMixin, DispenseVolumeMixin, FlowRateMixin):
|
|
37
41
|
"""Payload required to dispense in place."""
|
|
38
42
|
|
|
39
|
-
pushOut:
|
|
43
|
+
pushOut: float | SkipJsonSchema[None] = Field(
|
|
40
44
|
None,
|
|
41
45
|
description="push the plunger a small amount farther than necessary for accurate low-volume dispensing",
|
|
46
|
+
json_schema_extra=_remove_default,
|
|
42
47
|
)
|
|
43
48
|
|
|
44
49
|
|
|
@@ -74,63 +79,78 @@ class DispenseInPlaceImplementation(
|
|
|
74
79
|
|
|
75
80
|
async def execute(self, params: DispenseInPlaceParams) -> _ExecuteReturn:
|
|
76
81
|
"""Dispense without moving the pipette."""
|
|
77
|
-
state_update = StateUpdate()
|
|
78
82
|
current_location = self._state_view.pipettes.get_current_location()
|
|
79
83
|
current_position = await self._gantry_mover.get_position(params.pipetteId)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
84
|
+
result = await dispense_in_place(
|
|
85
|
+
pipette_id=params.pipetteId,
|
|
86
|
+
volume=params.volume,
|
|
87
|
+
flow_rate=params.flowRate,
|
|
88
|
+
push_out=params.pushOut,
|
|
89
|
+
location_if_error={
|
|
90
|
+
"retryLocation": (
|
|
91
|
+
current_position.x,
|
|
92
|
+
current_position.y,
|
|
93
|
+
current_position.z,
|
|
94
|
+
)
|
|
95
|
+
},
|
|
96
|
+
pipetting=self._pipetting,
|
|
97
|
+
model_utils=self._model_utils,
|
|
98
|
+
)
|
|
99
|
+
if isinstance(result, DefinedErrorData):
|
|
88
100
|
if (
|
|
89
101
|
isinstance(current_location, CurrentWell)
|
|
90
102
|
and current_location.pipette_id == params.pipetteId
|
|
91
103
|
):
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
ErrorOccurrence.from_failed(
|
|
103
|
-
id=self._model_utils.generate_id(),
|
|
104
|
-
createdAt=self._model_utils.get_timestamp(),
|
|
105
|
-
error=e,
|
|
106
|
-
)
|
|
107
|
-
],
|
|
108
|
-
errorInfo=(
|
|
109
|
-
{
|
|
110
|
-
"retryLocation": (
|
|
111
|
-
current_position.x,
|
|
112
|
-
current_position.y,
|
|
113
|
-
current_position.z,
|
|
114
|
-
)
|
|
115
|
-
}
|
|
104
|
+
return DefinedErrorData(
|
|
105
|
+
public=result.public,
|
|
106
|
+
state_update=result.state_update.set_liquid_operated(
|
|
107
|
+
labware_id=current_location.labware_id,
|
|
108
|
+
well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well(
|
|
109
|
+
current_location.labware_id,
|
|
110
|
+
current_location.well_name,
|
|
111
|
+
params.pipetteId,
|
|
112
|
+
),
|
|
113
|
+
volume_added=CLEAR,
|
|
116
114
|
),
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
115
|
+
state_update_if_false_positive=result.state_update_if_false_positive,
|
|
116
|
+
)
|
|
117
|
+
else:
|
|
118
|
+
return result
|
|
120
119
|
else:
|
|
121
120
|
if (
|
|
122
121
|
isinstance(current_location, CurrentWell)
|
|
123
122
|
and current_location.pipette_id == params.pipetteId
|
|
124
123
|
):
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
124
|
+
volume_added = (
|
|
125
|
+
self._state_view.pipettes.get_liquid_dispensed_by_ejecting_volume(
|
|
126
|
+
pipette_id=params.pipetteId, volume=result.public.volume
|
|
127
|
+
)
|
|
128
|
+
)
|
|
129
|
+
if volume_added is not None:
|
|
130
|
+
volume_added *= self._state_view.geometry.get_nozzles_per_well(
|
|
131
|
+
current_location.labware_id,
|
|
132
|
+
current_location.well_name,
|
|
133
|
+
params.pipetteId,
|
|
134
|
+
)
|
|
135
|
+
return SuccessData(
|
|
136
|
+
public=DispenseInPlaceResult(volume=result.public.volume),
|
|
137
|
+
state_update=result.state_update.set_liquid_operated(
|
|
138
|
+
labware_id=current_location.labware_id,
|
|
139
|
+
well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well(
|
|
140
|
+
current_location.labware_id,
|
|
141
|
+
current_location.well_name,
|
|
142
|
+
params.pipetteId,
|
|
143
|
+
),
|
|
144
|
+
volume_added=volume_added
|
|
145
|
+
if volume_added is not None
|
|
146
|
+
else CLEAR,
|
|
147
|
+
),
|
|
148
|
+
)
|
|
149
|
+
else:
|
|
150
|
+
return SuccessData(
|
|
151
|
+
public=DispenseInPlaceResult(volume=result.public.volume),
|
|
152
|
+
state_update=result.state_update,
|
|
129
153
|
)
|
|
130
|
-
return SuccessData(
|
|
131
|
-
public=DispenseInPlaceResult(volume=volume),
|
|
132
|
-
state_update=state_update,
|
|
133
|
-
)
|
|
134
154
|
|
|
135
155
|
|
|
136
156
|
class DispenseInPlace(
|
|
@@ -140,7 +160,7 @@ class DispenseInPlace(
|
|
|
140
160
|
|
|
141
161
|
commandType: DispenseInPlaceCommandType = "dispenseInPlace"
|
|
142
162
|
params: DispenseInPlaceParams
|
|
143
|
-
result: Optional[DispenseInPlaceResult]
|
|
163
|
+
result: Optional[DispenseInPlaceResult] = None
|
|
144
164
|
|
|
145
165
|
_ImplementationCls: Type[
|
|
146
166
|
DispenseInPlaceImplementation
|
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
"""Drop tip command request, result, and implementation models."""
|
|
2
|
+
|
|
2
3
|
from __future__ import annotations
|
|
4
|
+
from typing import TYPE_CHECKING, Optional, Type, Any
|
|
3
5
|
|
|
4
6
|
from pydantic import Field
|
|
5
|
-
from
|
|
7
|
+
from pydantic.json_schema import SkipJsonSchema
|
|
8
|
+
|
|
6
9
|
from typing_extensions import Literal
|
|
7
10
|
|
|
8
11
|
from opentrons.protocol_engine.errors.exceptions import TipAttachedError
|
|
9
12
|
from opentrons.protocol_engine.resources.model_utils import ModelUtils
|
|
10
13
|
|
|
11
|
-
from ..state import
|
|
12
|
-
from ..types import DropTipWellLocation
|
|
14
|
+
from ..state.update_types import StateUpdate
|
|
15
|
+
from ..types import DropTipWellLocation
|
|
13
16
|
from .pipetting_common import (
|
|
14
17
|
PipetteIdMixin,
|
|
15
|
-
DestinationPositionResult,
|
|
16
18
|
TipPhysicallyAttachedError,
|
|
17
19
|
)
|
|
20
|
+
from .movement_common import (
|
|
21
|
+
DestinationPositionResult,
|
|
22
|
+
move_to_well,
|
|
23
|
+
StallOrCollisionError,
|
|
24
|
+
)
|
|
18
25
|
from .command import (
|
|
19
26
|
AbstractCommandImpl,
|
|
20
27
|
BaseCommand,
|
|
@@ -32,6 +39,10 @@ if TYPE_CHECKING:
|
|
|
32
39
|
DropTipCommandType = Literal["dropTip"]
|
|
33
40
|
|
|
34
41
|
|
|
42
|
+
def _remove_default(s: dict[str, Any]) -> None:
|
|
43
|
+
s.pop("default", None)
|
|
44
|
+
|
|
45
|
+
|
|
35
46
|
class DropTipParams(PipetteIdMixin):
|
|
36
47
|
"""Payload required to drop a tip in a specific well."""
|
|
37
48
|
|
|
@@ -41,15 +52,16 @@ class DropTipParams(PipetteIdMixin):
|
|
|
41
52
|
default_factory=DropTipWellLocation,
|
|
42
53
|
description="Relative well location at which to drop the tip.",
|
|
43
54
|
)
|
|
44
|
-
homeAfter:
|
|
55
|
+
homeAfter: bool | SkipJsonSchema[None] = Field(
|
|
45
56
|
None,
|
|
46
57
|
description=(
|
|
47
58
|
"Whether to home this pipette's plunger after dropping the tip."
|
|
48
59
|
" You should normally leave this unspecified to let the robot choose"
|
|
49
60
|
" a safe default depending on its hardware."
|
|
50
61
|
),
|
|
62
|
+
json_schema_extra=_remove_default,
|
|
51
63
|
)
|
|
52
|
-
alternateDropLocation:
|
|
64
|
+
alternateDropLocation: bool | SkipJsonSchema[None] = Field(
|
|
53
65
|
False,
|
|
54
66
|
description=(
|
|
55
67
|
"Whether to alternate location where tip is dropped within the labware."
|
|
@@ -58,6 +70,7 @@ class DropTipParams(PipetteIdMixin):
|
|
|
58
70
|
" labware well."
|
|
59
71
|
" If False, the tip will be dropped at the top center of the well."
|
|
60
72
|
),
|
|
73
|
+
json_schema_extra=_remove_default,
|
|
61
74
|
)
|
|
62
75
|
|
|
63
76
|
|
|
@@ -68,7 +81,9 @@ class DropTipResult(DestinationPositionResult):
|
|
|
68
81
|
|
|
69
82
|
|
|
70
83
|
_ExecuteReturn = (
|
|
71
|
-
SuccessData[DropTipResult]
|
|
84
|
+
SuccessData[DropTipResult]
|
|
85
|
+
| DefinedErrorData[TipPhysicallyAttachedError]
|
|
86
|
+
| DefinedErrorData[StallOrCollisionError]
|
|
72
87
|
)
|
|
73
88
|
|
|
74
89
|
|
|
@@ -95,8 +110,6 @@ class DropTipImplementation(AbstractCommandImpl[DropTipParams, _ExecuteReturn]):
|
|
|
95
110
|
well_name = params.wellName
|
|
96
111
|
home_after = params.homeAfter
|
|
97
112
|
|
|
98
|
-
state_update = update_types.StateUpdate()
|
|
99
|
-
|
|
100
113
|
if params.alternateDropLocation:
|
|
101
114
|
well_location = self._state_view.geometry.get_next_tip_drop_location(
|
|
102
115
|
labware_id=labware_id,
|
|
@@ -116,19 +129,16 @@ class DropTipImplementation(AbstractCommandImpl[DropTipParams, _ExecuteReturn]):
|
|
|
116
129
|
partially_configured=is_partially_configured,
|
|
117
130
|
)
|
|
118
131
|
|
|
119
|
-
|
|
132
|
+
move_result = await move_to_well(
|
|
133
|
+
movement=self._movement_handler,
|
|
134
|
+
model_utils=self._model_utils,
|
|
120
135
|
pipette_id=pipette_id,
|
|
121
136
|
labware_id=labware_id,
|
|
122
137
|
well_name=well_name,
|
|
123
138
|
well_location=tip_drop_location,
|
|
124
139
|
)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
pipette_id=pipette_id,
|
|
128
|
-
new_labware_id=labware_id,
|
|
129
|
-
new_well_name=well_name,
|
|
130
|
-
new_deck_point=deck_point,
|
|
131
|
-
)
|
|
140
|
+
if isinstance(move_result, DefinedErrorData):
|
|
141
|
+
return move_result
|
|
132
142
|
|
|
133
143
|
try:
|
|
134
144
|
await self._tip_handler.drop_tip(
|
|
@@ -145,33 +155,44 @@ class DropTipImplementation(AbstractCommandImpl[DropTipParams, _ExecuteReturn]):
|
|
|
145
155
|
error=exception,
|
|
146
156
|
)
|
|
147
157
|
],
|
|
148
|
-
errorInfo={
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
158
|
+
errorInfo={
|
|
159
|
+
"retryLocation": (
|
|
160
|
+
move_result.public.position.x,
|
|
161
|
+
move_result.public.position.y,
|
|
162
|
+
move_result.public.position.z,
|
|
163
|
+
)
|
|
164
|
+
},
|
|
153
165
|
)
|
|
154
166
|
return DefinedErrorData(
|
|
155
167
|
public=error,
|
|
156
|
-
state_update=
|
|
157
|
-
|
|
168
|
+
state_update=StateUpdate.reduce(
|
|
169
|
+
StateUpdate(), move_result.state_update
|
|
170
|
+
).set_fluid_unknown(pipette_id=pipette_id),
|
|
171
|
+
state_update_if_false_positive=move_result.state_update.update_pipette_tip_state(
|
|
172
|
+
pipette_id=params.pipetteId, tip_geometry=None
|
|
173
|
+
),
|
|
158
174
|
)
|
|
159
175
|
else:
|
|
160
|
-
state_update.update_pipette_tip_state(
|
|
161
|
-
pipette_id=params.pipetteId, tip_geometry=None
|
|
162
|
-
)
|
|
163
176
|
return SuccessData(
|
|
164
|
-
public=DropTipResult(position=
|
|
165
|
-
state_update=state_update
|
|
177
|
+
public=DropTipResult(position=move_result.public.position),
|
|
178
|
+
state_update=move_result.state_update.set_fluid_unknown(
|
|
179
|
+
pipette_id=pipette_id
|
|
180
|
+
).update_pipette_tip_state(
|
|
181
|
+
pipette_id=params.pipetteId, tip_geometry=None
|
|
182
|
+
),
|
|
166
183
|
)
|
|
167
184
|
|
|
168
185
|
|
|
169
|
-
class DropTip(
|
|
186
|
+
class DropTip(
|
|
187
|
+
BaseCommand[
|
|
188
|
+
DropTipParams, DropTipResult, TipPhysicallyAttachedError | StallOrCollisionError
|
|
189
|
+
]
|
|
190
|
+
):
|
|
170
191
|
"""Drop tip command model."""
|
|
171
192
|
|
|
172
193
|
commandType: DropTipCommandType = "dropTip"
|
|
173
194
|
params: DropTipParams
|
|
174
|
-
result: Optional[DropTipResult]
|
|
195
|
+
result: Optional[DropTipResult] = None
|
|
175
196
|
|
|
176
197
|
_ImplementationCls: Type[DropTipImplementation] = DropTipImplementation
|
|
177
198
|
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"""Drop tip in place command request, result, and implementation models."""
|
|
2
2
|
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import TYPE_CHECKING, Optional, Type, Any
|
|
5
|
+
|
|
3
6
|
from pydantic import Field, BaseModel
|
|
4
|
-
from
|
|
7
|
+
from pydantic.json_schema import SkipJsonSchema
|
|
5
8
|
from typing_extensions import Literal
|
|
6
9
|
|
|
7
10
|
from .command import (
|
|
@@ -24,16 +27,21 @@ if TYPE_CHECKING:
|
|
|
24
27
|
DropTipInPlaceCommandType = Literal["dropTipInPlace"]
|
|
25
28
|
|
|
26
29
|
|
|
30
|
+
def _remove_default(s: dict[str, Any]) -> None:
|
|
31
|
+
s.pop("default", None)
|
|
32
|
+
|
|
33
|
+
|
|
27
34
|
class DropTipInPlaceParams(PipetteIdMixin):
|
|
28
35
|
"""Payload required to drop a tip in place."""
|
|
29
36
|
|
|
30
|
-
homeAfter:
|
|
37
|
+
homeAfter: bool | SkipJsonSchema[None] = Field(
|
|
31
38
|
None,
|
|
32
39
|
description=(
|
|
33
40
|
"Whether to home this pipette's plunger after dropping the tip."
|
|
34
41
|
" You should normally leave this unspecified to let the robot choose"
|
|
35
42
|
" a safe default depending on its hardware."
|
|
36
43
|
),
|
|
44
|
+
json_schema_extra=_remove_default,
|
|
37
45
|
)
|
|
38
46
|
|
|
39
47
|
|
|
@@ -79,6 +87,7 @@ class DropTipInPlaceImplementation(
|
|
|
79
87
|
state_update_if_false_positive.update_pipette_tip_state(
|
|
80
88
|
pipette_id=params.pipetteId, tip_geometry=None
|
|
81
89
|
)
|
|
90
|
+
state_update.set_fluid_unknown(pipette_id=params.pipetteId)
|
|
82
91
|
error = TipPhysicallyAttachedError(
|
|
83
92
|
id=self._model_utils.generate_id(),
|
|
84
93
|
createdAt=self._model_utils.get_timestamp(),
|
|
@@ -97,6 +106,7 @@ class DropTipInPlaceImplementation(
|
|
|
97
106
|
state_update_if_false_positive=state_update_if_false_positive,
|
|
98
107
|
)
|
|
99
108
|
else:
|
|
109
|
+
state_update.set_fluid_unknown(pipette_id=params.pipetteId)
|
|
100
110
|
state_update.update_pipette_tip_state(
|
|
101
111
|
pipette_id=params.pipetteId, tip_geometry=None
|
|
102
112
|
)
|
|
@@ -110,7 +120,7 @@ class DropTipInPlace(
|
|
|
110
120
|
|
|
111
121
|
commandType: DropTipInPlaceCommandType = "dropTipInPlace"
|
|
112
122
|
params: DropTipInPlaceParams
|
|
113
|
-
result: Optional[DropTipInPlaceResult]
|
|
123
|
+
result: Optional[DropTipInPlaceResult] = None
|
|
114
124
|
|
|
115
125
|
_ImplementationCls: Type[
|
|
116
126
|
DropTipInPlaceImplementation
|