opentrons 8.3.2__py2.py3-none-any.whl → 8.4.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of opentrons might be problematic. Click here for more details.
- opentrons/calibration_storage/ot2/mark_bad_calibration.py +2 -0
- opentrons/calibration_storage/ot2/tip_length.py +6 -6
- opentrons/config/advanced_settings.py +9 -11
- opentrons/config/feature_flags.py +0 -4
- opentrons/config/reset.py +7 -2
- opentrons/drivers/asyncio/communication/__init__.py +2 -0
- opentrons/drivers/asyncio/communication/async_serial.py +4 -0
- opentrons/drivers/asyncio/communication/errors.py +41 -8
- opentrons/drivers/asyncio/communication/serial_connection.py +36 -10
- opentrons/drivers/flex_stacker/__init__.py +9 -3
- opentrons/drivers/flex_stacker/abstract.py +140 -15
- opentrons/drivers/flex_stacker/driver.py +593 -47
- opentrons/drivers/flex_stacker/errors.py +64 -0
- opentrons/drivers/flex_stacker/simulator.py +222 -24
- opentrons/drivers/flex_stacker/types.py +211 -15
- opentrons/drivers/flex_stacker/utils.py +19 -0
- opentrons/execute.py +4 -2
- opentrons/hardware_control/api.py +5 -0
- opentrons/hardware_control/backends/flex_protocol.py +4 -0
- opentrons/hardware_control/backends/ot3controller.py +12 -1
- opentrons/hardware_control/backends/ot3simulator.py +3 -0
- opentrons/hardware_control/backends/subsystem_manager.py +8 -4
- opentrons/hardware_control/instruments/ot2/instrument_calibration.py +10 -6
- opentrons/hardware_control/instruments/ot3/pipette_handler.py +59 -6
- opentrons/hardware_control/modules/__init__.py +12 -1
- opentrons/hardware_control/modules/absorbance_reader.py +11 -9
- opentrons/hardware_control/modules/flex_stacker.py +498 -0
- opentrons/hardware_control/modules/heater_shaker.py +12 -10
- opentrons/hardware_control/modules/magdeck.py +5 -1
- opentrons/hardware_control/modules/tempdeck.py +5 -1
- opentrons/hardware_control/modules/thermocycler.py +15 -14
- opentrons/hardware_control/modules/types.py +191 -1
- opentrons/hardware_control/modules/utils.py +3 -0
- opentrons/hardware_control/motion_utilities.py +20 -0
- opentrons/hardware_control/ot3api.py +145 -15
- opentrons/hardware_control/protocols/liquid_handler.py +47 -1
- opentrons/hardware_control/types.py +6 -0
- opentrons/legacy_commands/commands.py +102 -5
- opentrons/legacy_commands/helpers.py +74 -1
- opentrons/legacy_commands/types.py +33 -2
- opentrons/protocol_api/__init__.py +2 -0
- opentrons/protocol_api/_liquid.py +39 -8
- opentrons/protocol_api/_liquid_properties.py +20 -19
- opentrons/protocol_api/_transfer_liquid_validation.py +91 -0
- opentrons/protocol_api/core/common.py +3 -1
- opentrons/protocol_api/core/engine/deck_conflict.py +11 -1
- opentrons/protocol_api/core/engine/instrument.py +1356 -107
- opentrons/protocol_api/core/engine/labware.py +8 -4
- opentrons/protocol_api/core/engine/load_labware_params.py +68 -10
- opentrons/protocol_api/core/engine/module_core.py +118 -2
- opentrons/protocol_api/core/engine/pipette_movement_conflict.py +6 -14
- opentrons/protocol_api/core/engine/protocol.py +253 -11
- opentrons/protocol_api/core/engine/stringify.py +19 -8
- opentrons/protocol_api/core/engine/transfer_components_executor.py +858 -0
- opentrons/protocol_api/core/engine/well.py +73 -5
- opentrons/protocol_api/core/instrument.py +71 -21
- opentrons/protocol_api/core/labware.py +6 -2
- opentrons/protocol_api/core/legacy/labware_offset_provider.py +7 -3
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +76 -49
- opentrons/protocol_api/core/legacy/legacy_labware_core.py +8 -4
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +36 -0
- opentrons/protocol_api/core/legacy/legacy_well_core.py +27 -2
- opentrons/protocol_api/core/legacy/load_info.py +4 -12
- opentrons/protocol_api/core/legacy/module_geometry.py +6 -1
- opentrons/protocol_api/core/legacy/well_geometry.py +3 -3
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +73 -23
- opentrons/protocol_api/core/module.py +43 -0
- opentrons/protocol_api/core/protocol.py +33 -0
- opentrons/protocol_api/core/well.py +23 -2
- opentrons/protocol_api/instrument_context.py +454 -150
- opentrons/protocol_api/labware.py +98 -50
- opentrons/protocol_api/module_contexts.py +140 -0
- opentrons/protocol_api/protocol_context.py +163 -19
- opentrons/protocol_api/validation.py +51 -41
- opentrons/protocol_engine/__init__.py +21 -2
- opentrons/protocol_engine/actions/actions.py +5 -5
- opentrons/protocol_engine/clients/sync_client.py +6 -0
- opentrons/protocol_engine/commands/__init__.py +66 -36
- opentrons/protocol_engine/commands/absorbance_reader/__init__.py +0 -1
- opentrons/protocol_engine/commands/air_gap_in_place.py +3 -2
- opentrons/protocol_engine/commands/aspirate.py +6 -2
- opentrons/protocol_engine/commands/aspirate_in_place.py +3 -1
- opentrons/protocol_engine/commands/aspirate_while_tracking.py +210 -0
- opentrons/protocol_engine/commands/blow_out.py +2 -0
- opentrons/protocol_engine/commands/blow_out_in_place.py +4 -1
- opentrons/protocol_engine/commands/command_unions.py +102 -33
- opentrons/protocol_engine/commands/configure_for_volume.py +3 -0
- opentrons/protocol_engine/commands/dispense.py +3 -1
- opentrons/protocol_engine/commands/dispense_in_place.py +3 -0
- opentrons/protocol_engine/commands/dispense_while_tracking.py +204 -0
- opentrons/protocol_engine/commands/drop_tip.py +23 -1
- opentrons/protocol_engine/commands/flex_stacker/__init__.py +106 -0
- opentrons/protocol_engine/commands/flex_stacker/close_latch.py +72 -0
- opentrons/protocol_engine/commands/flex_stacker/common.py +15 -0
- opentrons/protocol_engine/commands/flex_stacker/empty.py +161 -0
- opentrons/protocol_engine/commands/flex_stacker/fill.py +164 -0
- opentrons/protocol_engine/commands/flex_stacker/open_latch.py +70 -0
- opentrons/protocol_engine/commands/flex_stacker/prepare_shuttle.py +112 -0
- opentrons/protocol_engine/commands/flex_stacker/retrieve.py +394 -0
- opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +190 -0
- opentrons/protocol_engine/commands/flex_stacker/store.py +291 -0
- opentrons/protocol_engine/commands/generate_command_schema.py +31 -2
- opentrons/protocol_engine/commands/labware_handling_common.py +29 -0
- opentrons/protocol_engine/commands/liquid_probe.py +27 -13
- opentrons/protocol_engine/commands/load_labware.py +42 -39
- opentrons/protocol_engine/commands/load_lid.py +21 -13
- opentrons/protocol_engine/commands/load_lid_stack.py +130 -47
- opentrons/protocol_engine/commands/load_module.py +18 -17
- opentrons/protocol_engine/commands/load_pipette.py +3 -0
- opentrons/protocol_engine/commands/move_labware.py +139 -20
- opentrons/protocol_engine/commands/move_to_well.py +5 -11
- opentrons/protocol_engine/commands/pick_up_tip.py +5 -2
- opentrons/protocol_engine/commands/pipetting_common.py +159 -8
- opentrons/protocol_engine/commands/prepare_to_aspirate.py +15 -5
- opentrons/protocol_engine/commands/{evotip_dispense.py → pressure_dispense.py} +33 -34
- opentrons/protocol_engine/commands/reload_labware.py +6 -19
- opentrons/protocol_engine/commands/{evotip_seal_pipette.py → seal_pipette_to_tip.py} +97 -76
- opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +3 -1
- opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +6 -1
- opentrons/protocol_engine/commands/{evotip_unseal_pipette.py → unseal_pipette_from_tip.py} +31 -40
- opentrons/protocol_engine/errors/__init__.py +10 -0
- opentrons/protocol_engine/errors/exceptions.py +62 -0
- opentrons/protocol_engine/execution/equipment.py +123 -106
- opentrons/protocol_engine/execution/labware_movement.py +8 -6
- opentrons/protocol_engine/execution/pipetting.py +235 -25
- opentrons/protocol_engine/execution/tip_handler.py +82 -32
- opentrons/protocol_engine/labware_offset_standardization.py +194 -0
- opentrons/protocol_engine/protocol_engine.py +22 -13
- opentrons/protocol_engine/resources/deck_configuration_provider.py +98 -2
- opentrons/protocol_engine/resources/deck_data_provider.py +1 -1
- opentrons/protocol_engine/resources/labware_data_provider.py +32 -12
- opentrons/protocol_engine/resources/labware_validation.py +7 -5
- opentrons/protocol_engine/slot_standardization.py +11 -23
- opentrons/protocol_engine/state/addressable_areas.py +84 -46
- opentrons/protocol_engine/state/frustum_helpers.py +36 -14
- opentrons/protocol_engine/state/geometry.py +892 -227
- opentrons/protocol_engine/state/labware.py +252 -55
- opentrons/protocol_engine/state/module_substates/__init__.py +4 -0
- opentrons/protocol_engine/state/module_substates/flex_stacker_substate.py +68 -0
- opentrons/protocol_engine/state/module_substates/heater_shaker_module_substate.py +22 -0
- opentrons/protocol_engine/state/module_substates/temperature_module_substate.py +13 -0
- opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +20 -0
- opentrons/protocol_engine/state/modules.py +210 -67
- opentrons/protocol_engine/state/pipettes.py +54 -0
- opentrons/protocol_engine/state/state.py +1 -1
- opentrons/protocol_engine/state/tips.py +14 -0
- opentrons/protocol_engine/state/update_types.py +180 -25
- opentrons/protocol_engine/state/wells.py +55 -9
- opentrons/protocol_engine/types/__init__.py +300 -0
- opentrons/protocol_engine/types/automatic_tip_selection.py +39 -0
- opentrons/protocol_engine/types/command_annotations.py +53 -0
- opentrons/protocol_engine/types/deck_configuration.py +72 -0
- opentrons/protocol_engine/types/execution.py +96 -0
- opentrons/protocol_engine/types/hardware_passthrough.py +25 -0
- opentrons/protocol_engine/types/instrument.py +47 -0
- opentrons/protocol_engine/types/instrument_sensors.py +47 -0
- opentrons/protocol_engine/types/labware.py +111 -0
- opentrons/protocol_engine/types/labware_movement.py +22 -0
- opentrons/protocol_engine/types/labware_offset_location.py +111 -0
- opentrons/protocol_engine/types/labware_offset_vector.py +33 -0
- opentrons/protocol_engine/types/liquid.py +40 -0
- opentrons/protocol_engine/types/liquid_class.py +59 -0
- opentrons/protocol_engine/types/liquid_handling.py +13 -0
- opentrons/protocol_engine/types/liquid_level_detection.py +131 -0
- opentrons/protocol_engine/types/location.py +194 -0
- opentrons/protocol_engine/types/module.py +301 -0
- opentrons/protocol_engine/types/partial_tip_configuration.py +76 -0
- opentrons/protocol_engine/types/run_time_parameters.py +133 -0
- opentrons/protocol_engine/types/tip.py +18 -0
- opentrons/protocol_engine/types/util.py +21 -0
- opentrons/protocol_engine/types/well_position.py +124 -0
- opentrons/protocol_reader/extract_labware_definitions.py +7 -3
- opentrons/protocol_reader/file_format_validator.py +5 -3
- opentrons/protocol_runner/json_translator.py +4 -2
- opentrons/protocol_runner/legacy_command_mapper.py +6 -2
- opentrons/protocol_runner/run_orchestrator.py +4 -1
- opentrons/protocols/advanced_control/transfers/common.py +48 -1
- opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +204 -0
- opentrons/protocols/api_support/definitions.py +1 -1
- opentrons/protocols/api_support/instrument.py +16 -3
- opentrons/protocols/labware.py +27 -23
- opentrons/protocols/models/__init__.py +0 -21
- opentrons/simulate.py +4 -2
- opentrons/types.py +20 -7
- opentrons/util/logging_config.py +94 -25
- opentrons/util/logging_queue_handler.py +61 -0
- {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/METADATA +4 -4
- {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/RECORD +192 -151
- opentrons/calibration_storage/ot2/models/defaults.py +0 -0
- opentrons/calibration_storage/ot3/models/defaults.py +0 -0
- opentrons/protocol_api/core/legacy/legacy_robot_core.py +0 -0
- opentrons/protocol_engine/types.py +0 -1311
- {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/LICENSE +0 -0
- {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/WHEEL +0 -0
- {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/entry_points.txt +0 -0
- {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/top_level.txt +0 -0
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Pressure Dispense-in-place command request, result, and implementation models."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
from typing import TYPE_CHECKING, Optional, Type, Union
|
|
5
5
|
from typing_extensions import Literal
|
|
6
6
|
|
|
7
|
-
from opentrons.protocol_engine.errors import UnsupportedLabwareForActionError
|
|
8
7
|
from .pipetting_common import (
|
|
9
8
|
PipetteIdMixin,
|
|
10
9
|
FlowRateMixin,
|
|
11
10
|
DispenseVolumeMixin,
|
|
12
11
|
BaseLiquidHandlingResult,
|
|
13
12
|
dispense_in_place,
|
|
13
|
+
increase_evo_disp_count,
|
|
14
|
+
DEFAULT_CORRECTION_VOLUME,
|
|
14
15
|
)
|
|
15
16
|
from .movement_common import (
|
|
16
17
|
LiquidHandlingWellLocationMixin,
|
|
@@ -26,7 +27,6 @@ from .command import (
|
|
|
26
27
|
DefinedErrorData,
|
|
27
28
|
)
|
|
28
29
|
from ..state.update_types import StateUpdate
|
|
29
|
-
from ..resources import labware_validation
|
|
30
30
|
from ..errors import ProtocolEngineError
|
|
31
31
|
|
|
32
32
|
if TYPE_CHECKING:
|
|
@@ -35,33 +35,33 @@ if TYPE_CHECKING:
|
|
|
35
35
|
from ..state.state import StateView
|
|
36
36
|
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
PressureDispenseCommandType = Literal["pressureDispense"]
|
|
39
39
|
|
|
40
40
|
|
|
41
|
-
class
|
|
41
|
+
class PressureDispenseParams(
|
|
42
42
|
PipetteIdMixin, DispenseVolumeMixin, FlowRateMixin, LiquidHandlingWellLocationMixin
|
|
43
43
|
):
|
|
44
|
-
"""Payload required to dispense in place."""
|
|
44
|
+
"""Payload required to pressure dispense in place."""
|
|
45
45
|
|
|
46
46
|
pass
|
|
47
47
|
|
|
48
48
|
|
|
49
|
-
class
|
|
50
|
-
"""Result data from the execution of a
|
|
49
|
+
class PressureDispenseResult(BaseLiquidHandlingResult):
|
|
50
|
+
"""Result data from the execution of a PressureDispense command."""
|
|
51
51
|
|
|
52
52
|
pass
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
_ExecuteReturn = Union[
|
|
56
|
-
SuccessData[
|
|
56
|
+
SuccessData[PressureDispenseResult],
|
|
57
57
|
DefinedErrorData[StallOrCollisionError],
|
|
58
58
|
]
|
|
59
59
|
|
|
60
60
|
|
|
61
|
-
class
|
|
62
|
-
AbstractCommandImpl[
|
|
61
|
+
class PressureDispenseImplementation(
|
|
62
|
+
AbstractCommandImpl[PressureDispenseParams, _ExecuteReturn]
|
|
63
63
|
):
|
|
64
|
-
"""
|
|
64
|
+
"""Pressure dispense command implementation."""
|
|
65
65
|
|
|
66
66
|
def __init__(
|
|
67
67
|
self,
|
|
@@ -78,17 +78,12 @@ class EvotipDispenseImplementation(
|
|
|
78
78
|
self._model_utils = model_utils
|
|
79
79
|
self._movement = movement
|
|
80
80
|
|
|
81
|
-
async def execute(self, params:
|
|
82
|
-
"""Move to and dispense to the requested well."""
|
|
81
|
+
async def execute(self, params: PressureDispenseParams) -> _ExecuteReturn:
|
|
82
|
+
"""Move to and pressure dispense to the requested well."""
|
|
83
83
|
well_location = params.wellLocation
|
|
84
84
|
labware_id = params.labwareId
|
|
85
85
|
well_name = params.wellName
|
|
86
86
|
|
|
87
|
-
labware_definition = self._state_view.labware.get_definition(params.labwareId)
|
|
88
|
-
if not labware_validation.is_evotips(labware_definition.parameters.loadName):
|
|
89
|
-
raise UnsupportedLabwareForActionError(
|
|
90
|
-
f"Cannot use command: `EvotipDispense` with labware: {labware_definition.parameters.loadName}"
|
|
91
|
-
)
|
|
92
87
|
move_result = await move_to_well(
|
|
93
88
|
movement=self._movement,
|
|
94
89
|
model_utils=self._model_utils,
|
|
@@ -101,6 +96,9 @@ class EvotipDispenseImplementation(
|
|
|
101
96
|
return move_result
|
|
102
97
|
|
|
103
98
|
current_position = await self._gantry_mover.get_position(params.pipetteId)
|
|
99
|
+
await increase_evo_disp_count(
|
|
100
|
+
pipette_id=params.pipetteId, pipetting=self._pipetting
|
|
101
|
+
)
|
|
104
102
|
result = await dispense_in_place(
|
|
105
103
|
pipette_id=params.pipetteId,
|
|
106
104
|
volume=params.volume,
|
|
@@ -115,6 +113,7 @@ class EvotipDispenseImplementation(
|
|
|
115
113
|
},
|
|
116
114
|
pipetting=self._pipetting,
|
|
117
115
|
model_utils=self._model_utils,
|
|
116
|
+
correction_volume=params.correctionVolume or DEFAULT_CORRECTION_VOLUME,
|
|
118
117
|
)
|
|
119
118
|
if isinstance(result, DefinedErrorData):
|
|
120
119
|
# TODO (chb, 2025-01-29): Remove this and the OverpressureError returns once disabled for this function
|
|
@@ -122,35 +121,35 @@ class EvotipDispenseImplementation(
|
|
|
122
121
|
message="Overpressure Error during Resin Tip Dispense Command."
|
|
123
122
|
)
|
|
124
123
|
return SuccessData(
|
|
125
|
-
public=
|
|
124
|
+
public=PressureDispenseResult(volume=result.public.volume),
|
|
126
125
|
state_update=StateUpdate.reduce(
|
|
127
126
|
move_result.state_update, result.state_update
|
|
128
127
|
),
|
|
129
128
|
)
|
|
130
129
|
|
|
131
130
|
|
|
132
|
-
class
|
|
131
|
+
class PressureDispense(
|
|
133
132
|
BaseCommand[
|
|
134
|
-
|
|
135
|
-
|
|
133
|
+
PressureDispenseParams,
|
|
134
|
+
PressureDispenseResult,
|
|
136
135
|
StallOrCollisionError,
|
|
137
136
|
]
|
|
138
137
|
):
|
|
139
|
-
"""
|
|
138
|
+
"""PressureDispense command model."""
|
|
140
139
|
|
|
141
|
-
commandType:
|
|
142
|
-
params:
|
|
143
|
-
result: Optional[
|
|
140
|
+
commandType: PressureDispenseCommandType = "pressureDispense"
|
|
141
|
+
params: PressureDispenseParams
|
|
142
|
+
result: Optional[PressureDispenseResult] = None
|
|
144
143
|
|
|
145
144
|
_ImplementationCls: Type[
|
|
146
|
-
|
|
147
|
-
] =
|
|
145
|
+
PressureDispenseImplementation
|
|
146
|
+
] = PressureDispenseImplementation
|
|
148
147
|
|
|
149
148
|
|
|
150
|
-
class
|
|
151
|
-
"""
|
|
149
|
+
class PressureDispenseCreate(BaseCommandCreate[PressureDispenseParams]):
|
|
150
|
+
"""PressureDispense command request model."""
|
|
152
151
|
|
|
153
|
-
commandType:
|
|
154
|
-
params:
|
|
152
|
+
commandType: PressureDispenseCommandType = "pressureDispense"
|
|
153
|
+
params: PressureDispenseParams
|
|
155
154
|
|
|
156
|
-
_CommandCls: Type[
|
|
155
|
+
_CommandCls: Type[PressureDispense] = PressureDispense
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"""Reload labware command request, result, and implementation models."""
|
|
2
|
+
|
|
2
3
|
from __future__ import annotations
|
|
3
4
|
from pydantic import BaseModel, Field
|
|
4
5
|
from typing import TYPE_CHECKING, Optional, Type
|
|
5
6
|
from typing_extensions import Literal
|
|
6
7
|
|
|
8
|
+
from .labware_handling_common import LabwarePositionResultMixin
|
|
7
9
|
from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
|
|
8
10
|
from ..errors.error_occurrence import ErrorOccurrence
|
|
9
11
|
from ..state.update_types import StateUpdate
|
|
@@ -24,27 +26,9 @@ class ReloadLabwareParams(BaseModel):
|
|
|
24
26
|
)
|
|
25
27
|
|
|
26
28
|
|
|
27
|
-
class ReloadLabwareResult(
|
|
29
|
+
class ReloadLabwareResult(LabwarePositionResultMixin):
|
|
28
30
|
"""Result data from the execution of a LoadLabware command."""
|
|
29
31
|
|
|
30
|
-
labwareId: str = Field(
|
|
31
|
-
...,
|
|
32
|
-
description="An ID to reference this labware in subsequent commands. Same as the one in the parameters.",
|
|
33
|
-
)
|
|
34
|
-
offsetId: Optional[str] = Field(
|
|
35
|
-
# Default `None` instead of `...` so this field shows up as non-required in
|
|
36
|
-
# OpenAPI. The server is allowed to omit it or make it null.
|
|
37
|
-
None,
|
|
38
|
-
description=(
|
|
39
|
-
"An ID referencing the labware offset that will apply"
|
|
40
|
-
" to the reloaded labware."
|
|
41
|
-
" This offset will be in effect until the labware is moved"
|
|
42
|
-
" with a `moveLabware` command."
|
|
43
|
-
" Null or undefined means no offset applies,"
|
|
44
|
-
" so the default of (0, 0, 0) will be used."
|
|
45
|
-
),
|
|
46
|
-
)
|
|
47
|
-
|
|
48
32
|
|
|
49
33
|
class ReloadLabwareImplementation(
|
|
50
34
|
AbstractCommandImpl[ReloadLabwareParams, SuccessData[ReloadLabwareResult]]
|
|
@@ -77,6 +61,9 @@ class ReloadLabwareImplementation(
|
|
|
77
61
|
public=ReloadLabwareResult(
|
|
78
62
|
labwareId=params.labwareId,
|
|
79
63
|
offsetId=reloaded_labware.offsetId,
|
|
64
|
+
locationSequence=self._state_view.geometry.get_predicted_location_sequence(
|
|
65
|
+
reloaded_labware.location
|
|
66
|
+
),
|
|
80
67
|
),
|
|
81
68
|
state_update=state_update,
|
|
82
69
|
)
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
"""Seal
|
|
1
|
+
"""Seal tips to pipette command request, result, and implementation models."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
|
-
from pydantic import Field, BaseModel
|
|
5
4
|
from typing import TYPE_CHECKING, Optional, Type, Union
|
|
6
|
-
|
|
7
|
-
from opentrons.protocol_engine.types import MotorAxis
|
|
5
|
+
|
|
8
6
|
from typing_extensions import Literal
|
|
7
|
+
from pydantic import Field, BaseModel
|
|
9
8
|
|
|
10
|
-
from
|
|
11
|
-
|
|
9
|
+
from opentrons_shared_data.errors.exceptions import PositionUnknownError
|
|
10
|
+
|
|
11
|
+
from opentrons.types import MountType
|
|
12
|
+
from opentrons.protocol_engine.types import MotorAxis
|
|
13
|
+
from ..resources import ModelUtils, ensure_ot3_hardware
|
|
12
14
|
from ..types import PickUpTipWellLocation, FluidKind, AspiratedFluid
|
|
13
15
|
from .pipetting_common import (
|
|
14
16
|
PipetteIdMixin,
|
|
@@ -28,7 +30,6 @@ from .command import (
|
|
|
28
30
|
|
|
29
31
|
from opentrons.hardware_control import HardwareControlAPI
|
|
30
32
|
from opentrons.hardware_control.types import Axis
|
|
31
|
-
from ..state.update_types import StateUpdate
|
|
32
33
|
|
|
33
34
|
if TYPE_CHECKING:
|
|
34
35
|
from ..state.state import StateView
|
|
@@ -40,11 +41,14 @@ if TYPE_CHECKING:
|
|
|
40
41
|
)
|
|
41
42
|
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
SealPipetteToTipCommandType = Literal["sealPipetteToTip"]
|
|
45
|
+
_CAM_PREP_DISTANCE_DEFAULT = 8.25
|
|
46
|
+
_CAM_PRESS_DISTANCE_DEFAULT = 3.5
|
|
47
|
+
_CAM_EJECTOR_PUSH_MM_DEFAULT = 7.0
|
|
48
|
+
_PRESS_FIT_PREP_DISTANCE_DEFAULT = 0
|
|
49
|
+
_PRESS_FIT_PRESS_DISTANCE_DEFAULT = -11.0
|
|
50
|
+
_PRESS_FIT_EJECTOR_PUSH_MM_DEFAULT = 0
|
|
51
|
+
_SAFE_TOP_VOLUME = 1000
|
|
48
52
|
|
|
49
53
|
|
|
50
54
|
class TipPickUpParams(BaseModel):
|
|
@@ -62,7 +66,7 @@ class TipPickUpParams(BaseModel):
|
|
|
62
66
|
)
|
|
63
67
|
|
|
64
68
|
|
|
65
|
-
class
|
|
69
|
+
class SealPipetteToTipParams(PipetteIdMixin):
|
|
66
70
|
"""Payload needed to seal resin tips to a pipette."""
|
|
67
71
|
|
|
68
72
|
labwareId: str = Field(..., description="Identifier of labware to use.")
|
|
@@ -76,8 +80,8 @@ class EvotipSealPipetteParams(PipetteIdMixin):
|
|
|
76
80
|
)
|
|
77
81
|
|
|
78
82
|
|
|
79
|
-
class
|
|
80
|
-
"""Result data from the execution of a
|
|
83
|
+
class SealPipetteToTipResult(DestinationPositionResult):
|
|
84
|
+
"""Result data from the execution of a SealPipetteToTip."""
|
|
81
85
|
|
|
82
86
|
tipVolume: float = Field(
|
|
83
87
|
0,
|
|
@@ -99,15 +103,15 @@ class EvotipSealPipetteResult(DestinationPositionResult):
|
|
|
99
103
|
|
|
100
104
|
|
|
101
105
|
_ExecuteReturn = Union[
|
|
102
|
-
SuccessData[
|
|
106
|
+
SuccessData[SealPipetteToTipResult],
|
|
103
107
|
DefinedErrorData[StallOrCollisionError],
|
|
104
108
|
]
|
|
105
109
|
|
|
106
110
|
|
|
107
|
-
class
|
|
108
|
-
AbstractCommandImpl[
|
|
111
|
+
class SealPipetteToTipImplementation(
|
|
112
|
+
AbstractCommandImpl[SealPipetteToTipParams, _ExecuteReturn]
|
|
109
113
|
):
|
|
110
|
-
"""
|
|
114
|
+
"""Seal pipette command implementation."""
|
|
111
115
|
|
|
112
116
|
def __init__(
|
|
113
117
|
self,
|
|
@@ -136,25 +140,52 @@ class EvotipSealPipetteImplementation(
|
|
|
136
140
|
"""A relative press-fit pick up command using gantry moves."""
|
|
137
141
|
prep_distance = tip_pick_up_params.prepDistance
|
|
138
142
|
press_distance = tip_pick_up_params.pressDistance
|
|
139
|
-
retract_distance = -1 * (
|
|
143
|
+
retract_distance = -1 * (press_distance) / 2
|
|
140
144
|
|
|
141
145
|
mount_axis = MotorAxis.LEFT_Z if mount == MountType.LEFT else MotorAxis.RIGHT_Z
|
|
142
|
-
|
|
146
|
+
ot3_hardware_api = ensure_ot3_hardware(self._hardware_api)
|
|
143
147
|
# TODO chb, 2025-01-29): Factor out the movement constants and relocate this logic into the hardware controller
|
|
144
|
-
|
|
145
|
-
|
|
148
|
+
try:
|
|
149
|
+
await self._gantry_mover.move_axes(
|
|
150
|
+
axis_map={mount_axis: prep_distance},
|
|
151
|
+
speed=10,
|
|
152
|
+
relative_move=True,
|
|
153
|
+
expect_stalls=True,
|
|
154
|
+
)
|
|
155
|
+
except PositionUnknownError:
|
|
156
|
+
# if this happens it's from the get position after the move and we can ignore it
|
|
157
|
+
pass
|
|
158
|
+
|
|
159
|
+
await ot3_hardware_api.update_axis_position_estimations(
|
|
160
|
+
self._gantry_mover.motor_axes_to_present_hardware_axes([mount_axis])
|
|
146
161
|
)
|
|
147
162
|
|
|
148
163
|
# Drive mount down for press-fit
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
164
|
+
try:
|
|
165
|
+
await self._gantry_mover.move_axes(
|
|
166
|
+
axis_map={mount_axis: press_distance},
|
|
167
|
+
speed=10.0,
|
|
168
|
+
relative_move=True,
|
|
169
|
+
expect_stalls=True,
|
|
170
|
+
)
|
|
171
|
+
except PositionUnknownError:
|
|
172
|
+
# if this happens it's from the get position after the move and we can ignore it
|
|
173
|
+
pass
|
|
174
|
+
|
|
175
|
+
await ot3_hardware_api.update_axis_position_estimations(
|
|
176
|
+
self._gantry_mover.motor_axes_to_present_hardware_axes([mount_axis])
|
|
154
177
|
)
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
178
|
+
|
|
179
|
+
try:
|
|
180
|
+
await self._gantry_mover.move_axes(
|
|
181
|
+
axis_map={mount_axis: retract_distance}, speed=5.5, relative_move=True
|
|
182
|
+
)
|
|
183
|
+
except PositionUnknownError:
|
|
184
|
+
# if this happens it's from the get position after the move and we can ignore it
|
|
185
|
+
pass
|
|
186
|
+
|
|
187
|
+
await ot3_hardware_api.update_axis_position_estimations(
|
|
188
|
+
self._gantry_mover.motor_axes_to_present_hardware_axes([mount_axis])
|
|
158
189
|
)
|
|
159
190
|
|
|
160
191
|
async def cam_action_relative_pickup_tip(
|
|
@@ -210,19 +241,13 @@ class EvotipSealPipetteImplementation(
|
|
|
210
241
|
)
|
|
211
242
|
|
|
212
243
|
async def execute(
|
|
213
|
-
self, params:
|
|
214
|
-
) -> Union[SuccessData[
|
|
244
|
+
self, params: SealPipetteToTipParams
|
|
245
|
+
) -> Union[SuccessData[SealPipetteToTipResult], _ExecuteReturn]:
|
|
215
246
|
"""Move to and pick up a tip using the requested pipette."""
|
|
216
247
|
pipette_id = params.pipetteId
|
|
217
248
|
labware_id = params.labwareId
|
|
218
249
|
well_name = params.wellName
|
|
219
250
|
|
|
220
|
-
labware_definition = self._state_view.labware.get_definition(params.labwareId)
|
|
221
|
-
if not labware_validation.is_evotips(labware_definition.parameters.loadName):
|
|
222
|
-
raise UnsupportedLabwareForActionError(
|
|
223
|
-
f"Cannot use command: `EvotipSealPipette` with labware: {labware_definition.parameters.loadName}"
|
|
224
|
-
)
|
|
225
|
-
|
|
226
251
|
well_location = self._state_view.geometry.convert_pick_up_tip_well_location(
|
|
227
252
|
well_location=params.wellLocation
|
|
228
253
|
)
|
|
@@ -251,29 +276,28 @@ class EvotipSealPipetteImplementation(
|
|
|
251
276
|
channels = self._state_view.tips.get_pipette_active_channels(pipette_id)
|
|
252
277
|
mount = self._state_view.pipettes.get_mount(pipette_id)
|
|
253
278
|
tip_pick_up_params = params.tipPickUpParams
|
|
254
|
-
if tip_pick_up_params is None:
|
|
255
|
-
tip_pick_up_params = TipPickUpParams(
|
|
256
|
-
prepDistance=_PREP_DISTANCE_DEFAULT,
|
|
257
|
-
pressDistance=_PRESS_DISTANCE_DEFAULT,
|
|
258
|
-
ejectorPushMm=_EJECTOR_PUSH_MM_DEFAULT,
|
|
259
|
-
)
|
|
260
279
|
|
|
261
|
-
if channels
|
|
262
|
-
|
|
263
|
-
tip_pick_up_params=
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
280
|
+
if channels == 96:
|
|
281
|
+
if tip_pick_up_params is None:
|
|
282
|
+
tip_pick_up_params = TipPickUpParams(
|
|
283
|
+
prepDistance=_CAM_PREP_DISTANCE_DEFAULT,
|
|
284
|
+
pressDistance=_CAM_PRESS_DISTANCE_DEFAULT,
|
|
285
|
+
ejectorPushMm=_CAM_EJECTOR_PUSH_MM_DEFAULT,
|
|
286
|
+
)
|
|
267
287
|
await self.cam_action_relative_pickup_tip(
|
|
268
288
|
tip_pick_up_params=tip_pick_up_params,
|
|
269
289
|
mount=mount,
|
|
270
290
|
)
|
|
271
291
|
else:
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
292
|
+
if tip_pick_up_params is None:
|
|
293
|
+
tip_pick_up_params = TipPickUpParams(
|
|
294
|
+
prepDistance=_PRESS_FIT_PREP_DISTANCE_DEFAULT,
|
|
295
|
+
pressDistance=_PRESS_FIT_PRESS_DISTANCE_DEFAULT,
|
|
296
|
+
ejectorPushMm=_PRESS_FIT_EJECTOR_PUSH_MM_DEFAULT,
|
|
297
|
+
)
|
|
298
|
+
await self.relative_pickup_tip(
|
|
299
|
+
tip_pick_up_params=tip_pick_up_params,
|
|
300
|
+
mount=mount,
|
|
277
301
|
)
|
|
278
302
|
|
|
279
303
|
# cache_tip
|
|
@@ -283,18 +307,15 @@ class EvotipSealPipetteImplementation(
|
|
|
283
307
|
if hw_instr is not None:
|
|
284
308
|
hw_instr.set_current_volume(_SAFE_TOP_VOLUME)
|
|
285
309
|
|
|
286
|
-
state_update =
|
|
287
|
-
state_update.update_pipette_tip_state(
|
|
310
|
+
state_update = move_result.state_update.update_pipette_tip_state(
|
|
288
311
|
pipette_id=pipette_id,
|
|
289
312
|
tip_geometry=tip_geometry,
|
|
290
|
-
)
|
|
291
|
-
|
|
292
|
-
state_update.set_fluid_aspirated(
|
|
313
|
+
).set_fluid_aspirated(
|
|
293
314
|
pipette_id=pipette_id,
|
|
294
315
|
fluid=AspiratedFluid(kind=FluidKind.LIQUID, volume=_SAFE_TOP_VOLUME),
|
|
295
316
|
)
|
|
296
317
|
return SuccessData(
|
|
297
|
-
public=
|
|
318
|
+
public=SealPipetteToTipResult(
|
|
298
319
|
tipVolume=tip_geometry.volume,
|
|
299
320
|
tipLength=tip_geometry.length,
|
|
300
321
|
tipDiameter=tip_geometry.diameter,
|
|
@@ -304,28 +325,28 @@ class EvotipSealPipetteImplementation(
|
|
|
304
325
|
)
|
|
305
326
|
|
|
306
327
|
|
|
307
|
-
class
|
|
328
|
+
class SealPipetteToTip(
|
|
308
329
|
BaseCommand[
|
|
309
|
-
|
|
310
|
-
|
|
330
|
+
SealPipetteToTipParams,
|
|
331
|
+
SealPipetteToTipResult,
|
|
311
332
|
StallOrCollisionError,
|
|
312
333
|
]
|
|
313
334
|
):
|
|
314
|
-
"""Seal
|
|
335
|
+
"""Seal tip command model."""
|
|
315
336
|
|
|
316
|
-
commandType:
|
|
317
|
-
params:
|
|
318
|
-
result: Optional[
|
|
337
|
+
commandType: SealPipetteToTipCommandType = "sealPipetteToTip"
|
|
338
|
+
params: SealPipetteToTipParams
|
|
339
|
+
result: Optional[SealPipetteToTipResult] = None
|
|
319
340
|
|
|
320
341
|
_ImplementationCls: Type[
|
|
321
|
-
|
|
322
|
-
] =
|
|
342
|
+
SealPipetteToTipImplementation
|
|
343
|
+
] = SealPipetteToTipImplementation
|
|
323
344
|
|
|
324
345
|
|
|
325
|
-
class
|
|
326
|
-
"""Seal
|
|
346
|
+
class SealPipetteToTipCreate(BaseCommandCreate[SealPipetteToTipParams]):
|
|
347
|
+
"""Seal tip command creation request model."""
|
|
327
348
|
|
|
328
|
-
commandType:
|
|
329
|
-
params:
|
|
349
|
+
commandType: SealPipetteToTipCommandType = "sealPipetteToTip"
|
|
350
|
+
params: SealPipetteToTipParams
|
|
330
351
|
|
|
331
|
-
_CommandCls: Type[
|
|
352
|
+
_CommandCls: Type[SealPipetteToTip] = SealPipetteToTip
|
|
@@ -69,7 +69,9 @@ class UnsafeBlowOutInPlaceImplementation(
|
|
|
69
69
|
)
|
|
70
70
|
state_update = update_types.StateUpdate()
|
|
71
71
|
state_update.set_fluid_empty(pipette_id=params.pipetteId)
|
|
72
|
-
|
|
72
|
+
state_update.set_pipette_ready_to_aspirate(
|
|
73
|
+
pipette_id=params.pipetteId, ready_to_aspirate=False
|
|
74
|
+
)
|
|
73
75
|
return SuccessData(
|
|
74
76
|
public=UnsafeBlowOutInPlaceResult(), state_update=state_update
|
|
75
77
|
)
|
|
@@ -78,7 +78,12 @@ class UnsafeDropTipInPlaceImplementation(
|
|
|
78
78
|
[Axis.of_main_tool_actuator(pipette_location.mount.to_hw_mount())]
|
|
79
79
|
)
|
|
80
80
|
await self._tip_handler.drop_tip(
|
|
81
|
-
pipette_id=params.pipetteId,
|
|
81
|
+
pipette_id=params.pipetteId,
|
|
82
|
+
home_after=params.homeAfter,
|
|
83
|
+
ignore_plunger=(
|
|
84
|
+
self._state_view.tips.get_pipette_active_channels(params.pipetteId)
|
|
85
|
+
== 96
|
|
86
|
+
),
|
|
82
87
|
)
|
|
83
88
|
|
|
84
89
|
state_update = StateUpdate()
|