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
|
@@ -2,12 +2,14 @@ from __future__ import annotations
|
|
|
2
2
|
import logging
|
|
3
3
|
from contextlib import ExitStack
|
|
4
4
|
from typing import Any, List, Optional, Sequence, Union, cast, Dict
|
|
5
|
-
from opentrons.protocol_engine.errors.exceptions import TipNotAttachedError
|
|
6
5
|
from opentrons_shared_data.errors.exceptions import (
|
|
7
6
|
CommandPreconditionViolated,
|
|
8
7
|
CommandParameterLimitViolated,
|
|
9
8
|
UnexpectedTipRemovalError,
|
|
9
|
+
UnsupportedHardwareCommand,
|
|
10
10
|
)
|
|
11
|
+
from opentrons_shared_data.robot.types import RobotTypeEnum
|
|
12
|
+
|
|
11
13
|
from opentrons.legacy_broker import LegacyBroker
|
|
12
14
|
from opentrons.hardware_control.dev_types import PipetteDict
|
|
13
15
|
from opentrons import types
|
|
@@ -15,8 +17,7 @@ from opentrons.legacy_commands import commands as cmds
|
|
|
15
17
|
|
|
16
18
|
from opentrons.legacy_commands import publisher
|
|
17
19
|
from opentrons.protocols.advanced_control.mix import mix_from_kwargs
|
|
18
|
-
from opentrons.protocols.advanced_control import
|
|
19
|
-
|
|
20
|
+
from opentrons.protocols.advanced_control.transfers import transfer as v1_transfer
|
|
20
21
|
from opentrons.protocols.api_support.deck_type import NoTrashDefinedError
|
|
21
22
|
from opentrons.protocols.api_support.types import APIVersion
|
|
22
23
|
from opentrons.protocols.api_support import instrument
|
|
@@ -28,7 +29,6 @@ from opentrons.protocols.api_support.util import (
|
|
|
28
29
|
APIVersionError,
|
|
29
30
|
UnsupportedAPIError,
|
|
30
31
|
)
|
|
31
|
-
from opentrons.hardware_control.nozzle_manager import NozzleConfigurationType
|
|
32
32
|
|
|
33
33
|
from .core.common import InstrumentCore, ProtocolCore
|
|
34
34
|
from .core.engine import ENGINE_CORE_API_VERSION
|
|
@@ -36,10 +36,13 @@ from .core.legacy.legacy_instrument_core import LegacyInstrumentCore
|
|
|
36
36
|
from .config import Clearances
|
|
37
37
|
from .disposal_locations import TrashBin, WasteChute
|
|
38
38
|
from ._nozzle_layout import NozzleLayout
|
|
39
|
+
from ._liquid import LiquidClass
|
|
39
40
|
from . import labware, validation
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
from ..config import feature_flags
|
|
42
|
+
from ..protocols.advanced_control.transfers.common import (
|
|
43
|
+
TransferTipPolicyV2,
|
|
44
|
+
TransferTipPolicyV2Type,
|
|
45
|
+
)
|
|
43
46
|
|
|
44
47
|
_DEFAULT_ASPIRATE_CLEARANCE = 1.0
|
|
45
48
|
_DEFAULT_DISPENSE_CLEARANCE = 1.0
|
|
@@ -60,6 +63,10 @@ _DISPOSAL_LOCATION_OFFSET_ADDED_IN = APIVersion(2, 18)
|
|
|
60
63
|
"""The version after which offsets for deck configured trash containers and changes to alternating tip drop behavior were introduced."""
|
|
61
64
|
_PARTIAL_NOZZLE_CONFIGURATION_SINGLE_ROW_PARTIAL_COLUMN_ADDED_IN = APIVersion(2, 20)
|
|
62
65
|
"""The version after which partial nozzle configurations of single, row, and partial column layouts became available."""
|
|
66
|
+
_AIR_GAP_TRACKING_ADDED_IN = APIVersion(2, 22)
|
|
67
|
+
"""The version after which air gaps should be implemented with a separate call instead of an aspirate for better liquid volume tracking."""
|
|
68
|
+
|
|
69
|
+
AdvancedLiquidHandling = v1_transfer.AdvancedLiquidHandling
|
|
63
70
|
|
|
64
71
|
|
|
65
72
|
class InstrumentContext(publisher.CommandPublisher):
|
|
@@ -257,9 +264,10 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
257
264
|
self.api_version >= APIVersion(2, 20)
|
|
258
265
|
and well is not None
|
|
259
266
|
and self.liquid_presence_detection
|
|
260
|
-
and self.
|
|
267
|
+
and self._core.nozzle_configuration_valid_for_lld()
|
|
261
268
|
and self._core.get_current_volume() == 0
|
|
262
269
|
):
|
|
270
|
+
self._raise_if_pressure_not_supported_by_pipette()
|
|
263
271
|
self.require_liquid_presence(well=well)
|
|
264
272
|
|
|
265
273
|
with publisher.publish_context(
|
|
@@ -513,6 +521,8 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
513
521
|
``pipette.mix(1, location=wellplate['A1'])`` is a valid call, but
|
|
514
522
|
``pipette.mix(1, wellplate['A1'])`` is not.
|
|
515
523
|
|
|
524
|
+
.. versionchanged:: 2.21
|
|
525
|
+
Does not repeatedly check for liquid presence.
|
|
516
526
|
"""
|
|
517
527
|
_log.debug(
|
|
518
528
|
"mixing {}uL with {} repetitions in {} at rate={}".format(
|
|
@@ -753,7 +763,11 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
753
763
|
``pipette.air_gap(height=2)``. If you call ``air_gap`` with a single,
|
|
754
764
|
unnamed argument, it will always be interpreted as a volume.
|
|
755
765
|
|
|
756
|
-
|
|
766
|
+
.. TODO: restore this as a note block for 2.22 docs
|
|
767
|
+
Before API version 2.22, this function was implemented as an aspirate, and
|
|
768
|
+
dispensing into a well would add the air gap volume to the liquid tracked in
|
|
769
|
+
the well. At or above API version 2.22, air gap volume is not counted as liquid
|
|
770
|
+
when dispensing into a well.
|
|
757
771
|
"""
|
|
758
772
|
if not self._core.has_tip():
|
|
759
773
|
raise UnexpectedTipRemovalError("air_gap", self.name, self.mount)
|
|
@@ -765,7 +779,12 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
765
779
|
raise RuntimeError("No previous Well cached to perform air gap")
|
|
766
780
|
target = loc.labware.as_well().top(height)
|
|
767
781
|
self.move_to(target, publish=False)
|
|
768
|
-
self.
|
|
782
|
+
if self.api_version >= _AIR_GAP_TRACKING_ADDED_IN:
|
|
783
|
+
c_vol = self._core.get_available_volume() if volume is None else volume
|
|
784
|
+
flow_rate = self._core.get_aspirate_flow_rate()
|
|
785
|
+
self._core.air_gap_in_place(c_vol, flow_rate)
|
|
786
|
+
else:
|
|
787
|
+
self.aspirate(volume)
|
|
769
788
|
return self
|
|
770
789
|
|
|
771
790
|
@publisher.publish(command=cmds.return_tip)
|
|
@@ -934,7 +953,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
934
953
|
if location is None:
|
|
935
954
|
if (
|
|
936
955
|
nozzle_map is not None
|
|
937
|
-
and nozzle_map.configuration != NozzleConfigurationType.FULL
|
|
956
|
+
and nozzle_map.configuration != types.NozzleConfigurationType.FULL
|
|
938
957
|
and self.starting_tip is not None
|
|
939
958
|
):
|
|
940
959
|
# Disallowing this avoids concerning the system with the direction
|
|
@@ -1206,7 +1225,6 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1206
1225
|
self._core.home_plunger()
|
|
1207
1226
|
return self
|
|
1208
1227
|
|
|
1209
|
-
# TODO (spp, 2024-03-08): verify if ok to & change source & dest types to AdvancedLiquidHandling
|
|
1210
1228
|
@publisher.publish(command=cmds.distribute)
|
|
1211
1229
|
@requires_version(2, 0)
|
|
1212
1230
|
def distribute(
|
|
@@ -1246,7 +1264,6 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1246
1264
|
|
|
1247
1265
|
return self.transfer(volume, source, dest, **kwargs)
|
|
1248
1266
|
|
|
1249
|
-
# TODO (spp, 2024-03-08): verify if ok to & change source & dest types to AdvancedLiquidHandling
|
|
1250
1267
|
@publisher.publish(command=cmds.consolidate)
|
|
1251
1268
|
@requires_version(2, 0)
|
|
1252
1269
|
def consolidate(
|
|
@@ -1396,9 +1413,9 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1396
1413
|
mix_strategy, mix_opts = mix_from_kwargs(kwargs)
|
|
1397
1414
|
|
|
1398
1415
|
if trash:
|
|
1399
|
-
drop_tip =
|
|
1416
|
+
drop_tip = v1_transfer.DropTipStrategy.TRASH
|
|
1400
1417
|
else:
|
|
1401
|
-
drop_tip =
|
|
1418
|
+
drop_tip = v1_transfer.DropTipStrategy.RETURN
|
|
1402
1419
|
|
|
1403
1420
|
new_tip = kwargs.get("new_tip")
|
|
1404
1421
|
if isinstance(new_tip, str):
|
|
@@ -1420,19 +1437,19 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1420
1437
|
|
|
1421
1438
|
if blow_out and not blowout_location:
|
|
1422
1439
|
if self.current_volume:
|
|
1423
|
-
blow_out_strategy =
|
|
1440
|
+
blow_out_strategy = v1_transfer.BlowOutStrategy.SOURCE
|
|
1424
1441
|
else:
|
|
1425
|
-
blow_out_strategy =
|
|
1442
|
+
blow_out_strategy = v1_transfer.BlowOutStrategy.TRASH
|
|
1426
1443
|
elif blow_out and blowout_location:
|
|
1427
1444
|
if blowout_location == "source well":
|
|
1428
|
-
blow_out_strategy =
|
|
1445
|
+
blow_out_strategy = v1_transfer.BlowOutStrategy.SOURCE
|
|
1429
1446
|
elif blowout_location == "destination well":
|
|
1430
|
-
blow_out_strategy =
|
|
1447
|
+
blow_out_strategy = v1_transfer.BlowOutStrategy.DEST
|
|
1431
1448
|
elif blowout_location == "trash":
|
|
1432
|
-
blow_out_strategy =
|
|
1449
|
+
blow_out_strategy = v1_transfer.BlowOutStrategy.TRASH
|
|
1433
1450
|
|
|
1434
1451
|
if new_tip != types.TransferTipPolicy.NEVER:
|
|
1435
|
-
|
|
1452
|
+
_, next_tip = labware.next_available_tip(
|
|
1436
1453
|
self.starting_tip,
|
|
1437
1454
|
self.tip_racks,
|
|
1438
1455
|
active_channels,
|
|
@@ -1444,9 +1461,9 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1444
1461
|
|
|
1445
1462
|
touch_tip = None
|
|
1446
1463
|
if kwargs.get("touch_tip"):
|
|
1447
|
-
touch_tip =
|
|
1464
|
+
touch_tip = v1_transfer.TouchTipStrategy.ALWAYS
|
|
1448
1465
|
|
|
1449
|
-
default_args =
|
|
1466
|
+
default_args = v1_transfer.Transfer()
|
|
1450
1467
|
|
|
1451
1468
|
disposal = kwargs.get("disposal_volume")
|
|
1452
1469
|
if disposal is None:
|
|
@@ -1459,7 +1476,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1459
1476
|
f"working volume, {max_volume}uL"
|
|
1460
1477
|
)
|
|
1461
1478
|
|
|
1462
|
-
transfer_args =
|
|
1479
|
+
transfer_args = v1_transfer.Transfer(
|
|
1463
1480
|
new_tip=new_tip or default_args.new_tip,
|
|
1464
1481
|
air_gap=air_gap,
|
|
1465
1482
|
carryover=kwargs.get("carryover") or default_args.carryover,
|
|
@@ -1472,10 +1489,10 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1472
1489
|
blow_out_strategy=blow_out_strategy or default_args.blow_out_strategy,
|
|
1473
1490
|
touch_tip_strategy=(touch_tip or default_args.touch_tip_strategy),
|
|
1474
1491
|
)
|
|
1475
|
-
transfer_options =
|
|
1492
|
+
transfer_options = v1_transfer.TransferOptions(
|
|
1476
1493
|
transfer=transfer_args, mix=mix_opts
|
|
1477
1494
|
)
|
|
1478
|
-
plan =
|
|
1495
|
+
plan = v1_transfer.TransferPlan(
|
|
1479
1496
|
volume,
|
|
1480
1497
|
source,
|
|
1481
1498
|
dest,
|
|
@@ -1488,10 +1505,113 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1488
1505
|
self._execute_transfer(plan)
|
|
1489
1506
|
return self
|
|
1490
1507
|
|
|
1491
|
-
def _execute_transfer(self, plan:
|
|
1508
|
+
def _execute_transfer(self, plan: v1_transfer.TransferPlan) -> None:
|
|
1492
1509
|
for cmd in plan:
|
|
1493
1510
|
getattr(self, cmd["method"])(*cmd["args"], **cmd["kwargs"])
|
|
1494
1511
|
|
|
1512
|
+
def transfer_liquid(
|
|
1513
|
+
self,
|
|
1514
|
+
liquid_class: LiquidClass,
|
|
1515
|
+
volume: float,
|
|
1516
|
+
source: Union[
|
|
1517
|
+
labware.Well, Sequence[labware.Well], Sequence[Sequence[labware.Well]]
|
|
1518
|
+
],
|
|
1519
|
+
dest: Union[
|
|
1520
|
+
labware.Well, Sequence[labware.Well], Sequence[Sequence[labware.Well]]
|
|
1521
|
+
],
|
|
1522
|
+
new_tip: TransferTipPolicyV2Type = "once",
|
|
1523
|
+
tip_drop_location: Optional[
|
|
1524
|
+
Union[types.Location, labware.Well, TrashBin, WasteChute]
|
|
1525
|
+
] = None, # Maybe call this 'tip_drop_location' which is similar to PD
|
|
1526
|
+
) -> InstrumentContext:
|
|
1527
|
+
"""Transfer liquid from source to dest using the specified liquid class properties.
|
|
1528
|
+
|
|
1529
|
+
TODO: Add args description.
|
|
1530
|
+
"""
|
|
1531
|
+
if not feature_flags.allow_liquid_classes(
|
|
1532
|
+
robot_type=RobotTypeEnum.robot_literal_to_enum(
|
|
1533
|
+
self._protocol_core.robot_type
|
|
1534
|
+
)
|
|
1535
|
+
):
|
|
1536
|
+
raise NotImplementedError("This method is not implemented.")
|
|
1537
|
+
|
|
1538
|
+
flat_sources_list = validation.ensure_valid_flat_wells_list_for_transfer_v2(
|
|
1539
|
+
source
|
|
1540
|
+
)
|
|
1541
|
+
flat_dests_list = validation.ensure_valid_flat_wells_list_for_transfer_v2(dest)
|
|
1542
|
+
for well in flat_sources_list + flat_dests_list:
|
|
1543
|
+
instrument.validate_takes_liquid(
|
|
1544
|
+
location=well.top(),
|
|
1545
|
+
reject_module=True,
|
|
1546
|
+
reject_adapter=True,
|
|
1547
|
+
)
|
|
1548
|
+
if len(flat_sources_list) != len(flat_dests_list):
|
|
1549
|
+
raise ValueError(
|
|
1550
|
+
"Sources and destinations should be of the same length in order to perform a transfer."
|
|
1551
|
+
" To transfer liquid from one source to many destinations, use 'distribute_liquid',"
|
|
1552
|
+
" to transfer liquid onto one destinations from many sources, use 'consolidate_liquid'."
|
|
1553
|
+
)
|
|
1554
|
+
|
|
1555
|
+
valid_new_tip = validation.ensure_new_tip_policy(new_tip)
|
|
1556
|
+
if valid_new_tip == TransferTipPolicyV2.NEVER:
|
|
1557
|
+
if self._last_tip_picked_up_from is None:
|
|
1558
|
+
raise RuntimeError(
|
|
1559
|
+
"Pipette has no tip attached to perform transfer."
|
|
1560
|
+
" Either do a pick_up_tip beforehand or specify a new_tip parameter"
|
|
1561
|
+
" of 'once' or 'always'."
|
|
1562
|
+
)
|
|
1563
|
+
else:
|
|
1564
|
+
tiprack = self._last_tip_picked_up_from.parent
|
|
1565
|
+
else:
|
|
1566
|
+
tiprack, well = labware.next_available_tip(
|
|
1567
|
+
starting_tip=self.starting_tip,
|
|
1568
|
+
tip_racks=self.tip_racks,
|
|
1569
|
+
channels=self.active_channels,
|
|
1570
|
+
nozzle_map=self._core.get_nozzle_map(),
|
|
1571
|
+
)
|
|
1572
|
+
if self.current_volume != 0:
|
|
1573
|
+
raise RuntimeError(
|
|
1574
|
+
"A transfer on a liquid class cannot start with liquid already in the tip."
|
|
1575
|
+
" Ensure that all previously aspirated liquid is dispensed before starting"
|
|
1576
|
+
" a new transfer."
|
|
1577
|
+
)
|
|
1578
|
+
|
|
1579
|
+
_trash_location: Union[types.Location, labware.Well, TrashBin, WasteChute]
|
|
1580
|
+
if tip_drop_location is None:
|
|
1581
|
+
saved_trash = self.trash_container
|
|
1582
|
+
if isinstance(saved_trash, labware.Labware):
|
|
1583
|
+
_trash_location = saved_trash.wells()[0]
|
|
1584
|
+
else:
|
|
1585
|
+
_trash_location = saved_trash
|
|
1586
|
+
else:
|
|
1587
|
+
_trash_location = tip_drop_location
|
|
1588
|
+
|
|
1589
|
+
checked_trash_location = (
|
|
1590
|
+
validation.ensure_valid_tip_drop_location_for_transfer_v2(
|
|
1591
|
+
tip_drop_location=_trash_location
|
|
1592
|
+
)
|
|
1593
|
+
)
|
|
1594
|
+
liquid_class_id = self._core.load_liquid_class(
|
|
1595
|
+
liquid_class=liquid_class,
|
|
1596
|
+
pipette_load_name=self.name,
|
|
1597
|
+
tiprack_uri=tiprack.uri,
|
|
1598
|
+
)
|
|
1599
|
+
|
|
1600
|
+
self._core.transfer_liquid(
|
|
1601
|
+
liquid_class_id=liquid_class_id,
|
|
1602
|
+
volume=volume,
|
|
1603
|
+
source=[well._core for well in flat_sources_list],
|
|
1604
|
+
dest=[well._core for well in flat_dests_list],
|
|
1605
|
+
new_tip=valid_new_tip,
|
|
1606
|
+
trash_location=(
|
|
1607
|
+
checked_trash_location._core
|
|
1608
|
+
if isinstance(checked_trash_location, labware.Well)
|
|
1609
|
+
else checked_trash_location
|
|
1610
|
+
),
|
|
1611
|
+
)
|
|
1612
|
+
|
|
1613
|
+
return self
|
|
1614
|
+
|
|
1495
1615
|
@requires_version(2, 0)
|
|
1496
1616
|
def delay(self, *args: Any, **kwargs: Any) -> None:
|
|
1497
1617
|
"""
|
|
@@ -1694,6 +1814,8 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1694
1814
|
@liquid_presence_detection.setter
|
|
1695
1815
|
@requires_version(2, 20)
|
|
1696
1816
|
def liquid_presence_detection(self, enable: bool) -> None:
|
|
1817
|
+
if enable:
|
|
1818
|
+
self._raise_if_pressure_not_supported_by_pipette()
|
|
1697
1819
|
self._core.set_liquid_presence_detection(enable)
|
|
1698
1820
|
|
|
1699
1821
|
@property
|
|
@@ -1870,19 +1992,6 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1870
1992
|
else:
|
|
1871
1993
|
return self._protocol_core.get_last_location()
|
|
1872
1994
|
|
|
1873
|
-
def _96_tip_config_valid(self) -> bool:
|
|
1874
|
-
n_map = self._core.get_nozzle_map()
|
|
1875
|
-
channels = self._core.get_active_channels()
|
|
1876
|
-
if channels == 96:
|
|
1877
|
-
if (
|
|
1878
|
-
n_map.back_left != n_map.full_instrument_back_left
|
|
1879
|
-
and n_map.front_right != n_map.full_instrument_front_right
|
|
1880
|
-
):
|
|
1881
|
-
raise TipNotAttachedError(
|
|
1882
|
-
"Either the front right or the back left nozzle must have a tip attached to do LLD."
|
|
1883
|
-
)
|
|
1884
|
-
return True
|
|
1885
|
-
|
|
1886
1995
|
def __repr__(self) -> str:
|
|
1887
1996
|
return "<{}: {} in {}>".format(
|
|
1888
1997
|
self.__class__.__name__,
|
|
@@ -2143,8 +2252,8 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2143
2252
|
.. note::
|
|
2144
2253
|
The pressure sensors for the Flex 8-channel pipette are on channels 1 and 8 (positions A1 and H1). For the Flex 96-channel pipette, the pressure sensors are on channels 1 and 96 (positions A1 and H12). Other channels on multi-channel pipettes do not have sensors and cannot detect liquid.
|
|
2145
2254
|
"""
|
|
2255
|
+
self._raise_if_pressure_not_supported_by_pipette()
|
|
2146
2256
|
loc = well.top()
|
|
2147
|
-
self._96_tip_config_valid()
|
|
2148
2257
|
return self._core.detect_liquid_presence(well._core, loc)
|
|
2149
2258
|
|
|
2150
2259
|
@requires_version(2, 20)
|
|
@@ -2156,8 +2265,8 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2156
2265
|
.. note::
|
|
2157
2266
|
The pressure sensors for the Flex 8-channel pipette are on channels 1 and 8 (positions A1 and H1). For the Flex 96-channel pipette, the pressure sensors are on channels 1 and 96 (positions A1 and H12). Other channels on multi-channel pipettes do not have sensors and cannot detect liquid.
|
|
2158
2267
|
"""
|
|
2268
|
+
self._raise_if_pressure_not_supported_by_pipette()
|
|
2159
2269
|
loc = well.top()
|
|
2160
|
-
self._96_tip_config_valid()
|
|
2161
2270
|
self._core.liquid_probe_with_recovery(well._core, loc)
|
|
2162
2271
|
|
|
2163
2272
|
@requires_version(2, 20)
|
|
@@ -2170,9 +2279,8 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2170
2279
|
|
|
2171
2280
|
This is intended for Opentrons internal use only and is not a guaranteed API.
|
|
2172
2281
|
"""
|
|
2173
|
-
|
|
2282
|
+
self._raise_if_pressure_not_supported_by_pipette()
|
|
2174
2283
|
loc = well.top()
|
|
2175
|
-
self._96_tip_config_valid()
|
|
2176
2284
|
height = self._core.liquid_probe_without_recovery(well._core, loc)
|
|
2177
2285
|
return height
|
|
2178
2286
|
|
|
@@ -2192,6 +2300,12 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2192
2300
|
)
|
|
2193
2301
|
# SINGLE, QUADRANT and ALL are supported by all pipettes
|
|
2194
2302
|
|
|
2303
|
+
def _raise_if_pressure_not_supported_by_pipette(self) -> None:
|
|
2304
|
+
if not self._core._pressure_supported_by_pipette():
|
|
2305
|
+
raise UnsupportedHardwareCommand(
|
|
2306
|
+
"Pressure sensor not available for this pipette"
|
|
2307
|
+
)
|
|
2308
|
+
|
|
2195
2309
|
def _handle_aspirate_target(
|
|
2196
2310
|
self, target: validation.ValidTarget
|
|
2197
2311
|
) -> tuple[types.Location, Optional[labware.Well], Optional[bool]]:
|