opentrons 8.3.1a1__py2.py3-none-any.whl → 8.4.0a0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- opentrons/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 +7 -2
- 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 +19 -3
- opentrons/legacy_commands/helpers.py +15 -0
- opentrons/legacy_commands/types.py +3 -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 +1233 -65
- 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/protocol.py +253 -11
- opentrons/protocol_api/core/engine/stringify.py +19 -8
- opentrons/protocol_api/core/engine/transfer_components_executor.py +853 -0
- opentrons/protocol_api/core/engine/well.py +60 -5
- opentrons/protocol_api/core/instrument.py +65 -19
- 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 +69 -21
- 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 +25 -1
- 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 +67 -21
- opentrons/protocol_api/core/module.py +43 -0
- opentrons/protocol_api/core/protocol.py +33 -0
- opentrons/protocol_api/core/well.py +21 -1
- opentrons/protocol_api/instrument_context.py +245 -123
- opentrons/protocol_api/labware.py +75 -11
- opentrons/protocol_api/module_contexts.py +140 -0
- opentrons/protocol_api/protocol_context.py +156 -16
- 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 +30 -0
- 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 +237 -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 +69 -0
- 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 +240 -0
- opentrons/protocol_engine/commands/drop_tip.py +23 -1
- opentrons/protocol_engine/commands/evotip_dispense.py +6 -7
- opentrons/protocol_engine/commands/evotip_seal_pipette.py +2 -9
- opentrons/protocol_engine/commands/evotip_unseal_pipette.py +1 -7
- 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 +288 -0
- opentrons/protocol_engine/commands/generate_command_schema.py +31 -2
- opentrons/protocol_engine/commands/labware_handling_common.py +24 -0
- opentrons/protocol_engine/commands/liquid_probe.py +21 -12
- 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/pick_up_tip.py +5 -2
- opentrons/protocol_engine/commands/pipetting_common.py +154 -7
- opentrons/protocol_engine/commands/prepare_to_aspirate.py +3 -1
- opentrons/protocol_engine/commands/reload_labware.py +6 -19
- opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +3 -1
- opentrons/protocol_engine/errors/__init__.py +8 -0
- opentrons/protocol_engine/errors/exceptions.py +50 -0
- opentrons/protocol_engine/execution/equipment.py +123 -106
- opentrons/protocol_engine/execution/labware_movement.py +8 -6
- opentrons/protocol_engine/execution/pipetting.py +233 -26
- opentrons/protocol_engine/execution/tip_handler.py +14 -5
- opentrons/protocol_engine/labware_offset_standardization.py +173 -0
- opentrons/protocol_engine/protocol_engine.py +22 -13
- opentrons/protocol_engine/resources/deck_configuration_provider.py +94 -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 +26 -10
- opentrons/protocol_engine/state/geometry.py +683 -100
- 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 +178 -52
- 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 +54 -8
- opentrons/protocol_engine/types/__init__.py +292 -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 +110 -0
- opentrons/protocol_engine/types/labware_movement.py +22 -0
- opentrons/protocol_engine/types/labware_offset_location.py +108 -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 +137 -0
- opentrons/protocol_engine/types/location.py +193 -0
- opentrons/protocol_engine/types/module.py +269 -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 +107 -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 +5 -6
- opentrons/protocols/models/__init__.py +0 -21
- opentrons/simulate.py +4 -2
- opentrons/types.py +15 -6
- {opentrons-8.3.1a1.dist-info → opentrons-8.4.0a0.dist-info}/METADATA +4 -4
- {opentrons-8.3.1a1.dist-info → opentrons-8.4.0a0.dist-info}/RECORD +187 -147
- 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.1a1.dist-info → opentrons-8.4.0a0.dist-info}/LICENSE +0 -0
- {opentrons-8.3.1a1.dist-info → opentrons-8.4.0a0.dist-info}/WHEEL +0 -0
- {opentrons-8.3.1a1.dist-info → opentrons-8.4.0a0.dist-info}/entry_points.txt +0 -0
- {opentrons-8.3.1a1.dist-info → opentrons-8.4.0a0.dist-info}/top_level.txt +0 -0
|
@@ -8,7 +8,6 @@ from opentrons_shared_data.errors.exceptions import (
|
|
|
8
8
|
UnexpectedTipRemovalError,
|
|
9
9
|
UnsupportedHardwareCommand,
|
|
10
10
|
)
|
|
11
|
-
from opentrons_shared_data.robot.types import RobotTypeEnum
|
|
12
11
|
|
|
13
12
|
from opentrons.legacy_broker import LegacyBroker
|
|
14
13
|
from opentrons.hardware_control.dev_types import PipetteDict
|
|
@@ -37,12 +36,13 @@ from .config import Clearances
|
|
|
37
36
|
from .disposal_locations import TrashBin, WasteChute
|
|
38
37
|
from ._nozzle_layout import NozzleLayout
|
|
39
38
|
from ._liquid import LiquidClass
|
|
39
|
+
from ._transfer_liquid_validation import verify_and_normalize_transfer_args
|
|
40
40
|
from . import labware, validation
|
|
41
|
-
from ..config import feature_flags
|
|
42
41
|
from ..protocols.advanced_control.transfers.common import (
|
|
43
42
|
TransferTipPolicyV2,
|
|
44
43
|
TransferTipPolicyV2Type,
|
|
45
44
|
)
|
|
45
|
+
from ..protocol_engine.types.liquid_level_detection import LiquidTrackingType
|
|
46
46
|
|
|
47
47
|
_DEFAULT_ASPIRATE_CLEARANCE = 1.0
|
|
48
48
|
_DEFAULT_DISPENSE_CLEARANCE = 1.0
|
|
@@ -66,6 +66,7 @@ _PARTIAL_NOZZLE_CONFIGURATION_SINGLE_ROW_PARTIAL_COLUMN_ADDED_IN = APIVersion(2,
|
|
|
66
66
|
_AIR_GAP_TRACKING_ADDED_IN = APIVersion(2, 22)
|
|
67
67
|
"""The version after which air gaps should be implemented with a separate call instead of an aspirate for better liquid volume tracking."""
|
|
68
68
|
|
|
69
|
+
|
|
69
70
|
AdvancedLiquidHandling = v1_transfer.AdvancedLiquidHandling
|
|
70
71
|
|
|
71
72
|
|
|
@@ -166,6 +167,11 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
166
167
|
def default_speed(self, speed: float) -> None:
|
|
167
168
|
self._core.set_default_speed(speed)
|
|
168
169
|
|
|
170
|
+
@requires_version(2, 21)
|
|
171
|
+
def get_minimum_liquid_sense_height(self) -> float:
|
|
172
|
+
"""Get the minimum allowed height for liquid-level detection."""
|
|
173
|
+
return self._core.get_minimum_liquid_sense_height()
|
|
174
|
+
|
|
169
175
|
@requires_version(2, 0)
|
|
170
176
|
def aspirate(
|
|
171
177
|
self,
|
|
@@ -226,7 +232,6 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
226
232
|
|
|
227
233
|
move_to_location: types.Location
|
|
228
234
|
well: Optional[labware.Well] = None
|
|
229
|
-
is_meniscus: Optional[bool] = None
|
|
230
235
|
last_location = self._get_last_location_by_api_version()
|
|
231
236
|
try:
|
|
232
237
|
target = validation.validate_location(
|
|
@@ -244,7 +249,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
244
249
|
raise ValueError(
|
|
245
250
|
"Trash Bin and Waste Chute are not acceptable location parameters for Aspirate commands."
|
|
246
251
|
)
|
|
247
|
-
move_to_location, well,
|
|
252
|
+
move_to_location, well, meniscus_tracking = self._handle_aspirate_target(
|
|
248
253
|
target=target
|
|
249
254
|
)
|
|
250
255
|
if self.api_version >= APIVersion(2, 11):
|
|
@@ -266,6 +271,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
266
271
|
and self.liquid_presence_detection
|
|
267
272
|
and self._core.nozzle_configuration_valid_for_lld()
|
|
268
273
|
and self._core.get_current_volume() == 0
|
|
274
|
+
and self._core.get_has_clean_tip()
|
|
269
275
|
):
|
|
270
276
|
self._raise_if_pressure_not_supported_by_pipette()
|
|
271
277
|
self.require_liquid_presence(well=well)
|
|
@@ -287,13 +293,13 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
287
293
|
rate=rate,
|
|
288
294
|
flow_rate=flow_rate,
|
|
289
295
|
in_place=target.in_place,
|
|
290
|
-
|
|
296
|
+
meniscus_tracking=meniscus_tracking,
|
|
291
297
|
)
|
|
292
298
|
|
|
293
299
|
return self
|
|
294
300
|
|
|
295
301
|
@requires_version(2, 0)
|
|
296
|
-
def dispense(
|
|
302
|
+
def dispense(
|
|
297
303
|
self,
|
|
298
304
|
volume: Optional[float] = None,
|
|
299
305
|
location: Optional[
|
|
@@ -360,7 +366,10 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
360
366
|
:param push_out: Continue past the plunger bottom to help ensure all liquid
|
|
361
367
|
leaves the tip. Measured in µL. The default value is ``None``.
|
|
362
368
|
|
|
363
|
-
|
|
369
|
+
When not specified or set to ``None``, the plunger moves by a non-zero default amount.
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
For a table of default values, see :ref:`push-out-dispense`.
|
|
364
373
|
:type push_out: float
|
|
365
374
|
|
|
366
375
|
:returns: This instance.
|
|
@@ -389,8 +398,6 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
389
398
|
volume, location if location else "current position", rate
|
|
390
399
|
)
|
|
391
400
|
)
|
|
392
|
-
well: Optional[labware.Well] = None
|
|
393
|
-
is_meniscus: Optional[bool] = None
|
|
394
401
|
last_location = self._get_last_location_by_api_version()
|
|
395
402
|
|
|
396
403
|
try:
|
|
@@ -405,29 +412,6 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
405
412
|
"knows where it is."
|
|
406
413
|
) from e
|
|
407
414
|
|
|
408
|
-
if isinstance(target, validation.WellTarget):
|
|
409
|
-
well = target.well
|
|
410
|
-
if target.location:
|
|
411
|
-
move_to_location = target.location
|
|
412
|
-
is_meniscus = target.location.is_meniscus
|
|
413
|
-
elif well.parent._core.is_fixed_trash():
|
|
414
|
-
move_to_location = target.well.top()
|
|
415
|
-
else:
|
|
416
|
-
move_to_location = target.well.bottom(
|
|
417
|
-
z=self._well_bottom_clearances.dispense
|
|
418
|
-
)
|
|
419
|
-
if isinstance(target, validation.PointTarget):
|
|
420
|
-
move_to_location = target.location
|
|
421
|
-
|
|
422
|
-
if self.api_version >= APIVersion(2, 11) and not isinstance(
|
|
423
|
-
target, (TrashBin, WasteChute)
|
|
424
|
-
):
|
|
425
|
-
instrument.validate_takes_liquid(
|
|
426
|
-
location=move_to_location,
|
|
427
|
-
reject_module=self.api_version >= APIVersion(2, 13),
|
|
428
|
-
reject_adapter=self.api_version >= APIVersion(2, 15),
|
|
429
|
-
)
|
|
430
|
-
|
|
431
415
|
if self.api_version >= APIVersion(2, 16):
|
|
432
416
|
c_vol = self._core.get_current_volume() if volume is None else volume
|
|
433
417
|
else:
|
|
@@ -454,9 +438,21 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
454
438
|
flow_rate=flow_rate,
|
|
455
439
|
in_place=False,
|
|
456
440
|
push_out=push_out,
|
|
441
|
+
meniscus_tracking=None,
|
|
457
442
|
)
|
|
458
443
|
return self
|
|
459
444
|
|
|
445
|
+
move_to_location, well, meniscus_tracking = self._handle_dispense_target(
|
|
446
|
+
target=target
|
|
447
|
+
)
|
|
448
|
+
|
|
449
|
+
if self.api_version >= APIVersion(2, 11):
|
|
450
|
+
instrument.validate_takes_liquid(
|
|
451
|
+
location=move_to_location,
|
|
452
|
+
reject_module=self.api_version >= APIVersion(2, 13),
|
|
453
|
+
reject_adapter=self.api_version >= APIVersion(2, 15),
|
|
454
|
+
)
|
|
455
|
+
|
|
460
456
|
with publisher.publish_context(
|
|
461
457
|
broker=self.broker,
|
|
462
458
|
command=cmds.dispense(
|
|
@@ -475,7 +471,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
475
471
|
flow_rate=flow_rate,
|
|
476
472
|
in_place=target.in_place,
|
|
477
473
|
push_out=push_out,
|
|
478
|
-
|
|
474
|
+
meniscus_tracking=meniscus_tracking,
|
|
479
475
|
)
|
|
480
476
|
|
|
481
477
|
return self
|
|
@@ -756,18 +752,20 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
756
752
|
|
|
757
753
|
:returns: This instance.
|
|
758
754
|
|
|
759
|
-
|
|
755
|
+
Both ``volume`` and ``height`` are optional, but if you want to specify only
|
|
756
|
+
``height`` you must do it as a keyword argument:
|
|
757
|
+
``pipette.air_gap(height=2)``. If you call ``air_gap`` with a single,
|
|
758
|
+
unnamed argument, it will always be interpreted as a volume.
|
|
760
759
|
|
|
761
|
-
|
|
762
|
-
``height`` you must do it as a keyword argument:
|
|
763
|
-
``pipette.air_gap(height=2)``. If you call ``air_gap`` with a single,
|
|
764
|
-
unnamed argument, it will always be interpreted as a volume.
|
|
760
|
+
.. note::
|
|
765
761
|
|
|
766
|
-
|
|
767
|
-
Before API version 2.22, this function was implemented as an aspirate, and
|
|
762
|
+
In API version 2.21 and earlier, this function was implemented as an aspirate, and
|
|
768
763
|
dispensing into a well would add the air gap volume to the liquid tracked in
|
|
769
|
-
the well.
|
|
764
|
+
the well. In API version 2.22 and later, air gap volume is not tracked as liquid
|
|
770
765
|
when dispensing into a well.
|
|
766
|
+
|
|
767
|
+
.. versionchanged:: 2.22
|
|
768
|
+
No longer implemented as an aspirate.
|
|
771
769
|
"""
|
|
772
770
|
if not self._core.has_tip():
|
|
773
771
|
raise UnexpectedTipRemovalError("air_gap", self.name, self.mount)
|
|
@@ -1509,6 +1507,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1509
1507
|
for cmd in plan:
|
|
1510
1508
|
getattr(self, cmd["method"])(*cmd["args"], **cmd["kwargs"])
|
|
1511
1509
|
|
|
1510
|
+
@requires_version(2, 23)
|
|
1512
1511
|
def transfer_liquid(
|
|
1513
1512
|
self,
|
|
1514
1513
|
liquid_class: LiquidClass,
|
|
@@ -1520,96 +1519,195 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1520
1519
|
labware.Well, Sequence[labware.Well], Sequence[Sequence[labware.Well]]
|
|
1521
1520
|
],
|
|
1522
1521
|
new_tip: TransferTipPolicyV2Type = "once",
|
|
1523
|
-
|
|
1522
|
+
trash_location: Optional[
|
|
1524
1523
|
Union[types.Location, labware.Well, TrashBin, WasteChute]
|
|
1525
|
-
] = None,
|
|
1524
|
+
] = None,
|
|
1525
|
+
return_tip: bool = False,
|
|
1526
|
+
visit_every_well: bool = False,
|
|
1526
1527
|
) -> InstrumentContext:
|
|
1527
1528
|
"""Transfer liquid from source to dest using the specified liquid class properties.
|
|
1528
1529
|
|
|
1529
1530
|
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
1531
|
|
|
1538
|
-
|
|
1539
|
-
|
|
1532
|
+
:meta private:
|
|
1533
|
+
"""
|
|
1534
|
+
transfer_args = verify_and_normalize_transfer_args(
|
|
1535
|
+
source=source,
|
|
1536
|
+
dest=dest,
|
|
1537
|
+
tip_policy=new_tip,
|
|
1538
|
+
last_tip_picked_up_from=self._last_tip_picked_up_from,
|
|
1539
|
+
tip_racks=self._tip_racks,
|
|
1540
|
+
nozzle_map=self._core.get_nozzle_map(),
|
|
1541
|
+
target_all_wells=visit_every_well,
|
|
1542
|
+
current_volume=self.current_volume,
|
|
1543
|
+
trash_location=(
|
|
1544
|
+
trash_location if trash_location is not None else self.trash_container
|
|
1545
|
+
),
|
|
1540
1546
|
)
|
|
1541
|
-
|
|
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):
|
|
1547
|
+
if len(transfer_args.sources_list) != len(transfer_args.destinations_list):
|
|
1549
1548
|
raise ValueError(
|
|
1550
1549
|
"Sources and destinations should be of the same length in order to perform a transfer."
|
|
1551
1550
|
" To transfer liquid from one source to many destinations, use 'distribute_liquid',"
|
|
1552
1551
|
" to transfer liquid onto one destinations from many sources, use 'consolidate_liquid'."
|
|
1553
1552
|
)
|
|
1554
1553
|
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1554
|
+
self._core.transfer_liquid(
|
|
1555
|
+
liquid_class=liquid_class,
|
|
1556
|
+
volume=volume,
|
|
1557
|
+
source=[
|
|
1558
|
+
(types.Location(types.Point(), labware=well), well._core)
|
|
1559
|
+
for well in transfer_args.sources_list
|
|
1560
|
+
],
|
|
1561
|
+
dest=[
|
|
1562
|
+
(types.Location(types.Point(), labware=well), well._core)
|
|
1563
|
+
for well in transfer_args.destinations_list
|
|
1564
|
+
],
|
|
1565
|
+
new_tip=transfer_args.tip_policy,
|
|
1566
|
+
tip_racks=[
|
|
1567
|
+
(types.Location(types.Point(), labware=rack), rack._core)
|
|
1568
|
+
for rack in transfer_args.tip_racks
|
|
1569
|
+
],
|
|
1570
|
+
trash_location=transfer_args.trash_location,
|
|
1571
|
+
return_tip=return_tip,
|
|
1572
|
+
)
|
|
1573
|
+
return self
|
|
1574
|
+
|
|
1575
|
+
@requires_version(2, 23)
|
|
1576
|
+
def distribute_liquid(
|
|
1577
|
+
self,
|
|
1578
|
+
liquid_class: LiquidClass,
|
|
1579
|
+
volume: float,
|
|
1580
|
+
source: Union[labware.Well, Sequence[labware.Well]],
|
|
1581
|
+
dest: Union[
|
|
1582
|
+
labware.Well, Sequence[labware.Well], Sequence[Sequence[labware.Well]]
|
|
1583
|
+
],
|
|
1584
|
+
new_tip: TransferTipPolicyV2Type = "once",
|
|
1585
|
+
trash_location: Optional[
|
|
1586
|
+
Union[types.Location, labware.Well, TrashBin, WasteChute]
|
|
1587
|
+
] = None,
|
|
1588
|
+
return_tip: bool = False,
|
|
1589
|
+
visit_every_well: bool = False,
|
|
1590
|
+
) -> InstrumentContext:
|
|
1591
|
+
"""
|
|
1592
|
+
Distribute liquid from a single source to multiple destinations
|
|
1593
|
+
using the specified liquid class properties.
|
|
1594
|
+
|
|
1595
|
+
TODO: Add args description.
|
|
1596
|
+
|
|
1597
|
+
:meta private:
|
|
1598
|
+
"""
|
|
1599
|
+
transfer_args = verify_and_normalize_transfer_args(
|
|
1600
|
+
source=source,
|
|
1601
|
+
dest=dest,
|
|
1602
|
+
tip_policy=new_tip,
|
|
1603
|
+
last_tip_picked_up_from=self._last_tip_picked_up_from,
|
|
1604
|
+
tip_racks=self._tip_racks,
|
|
1605
|
+
nozzle_map=self._core.get_nozzle_map(),
|
|
1606
|
+
target_all_wells=visit_every_well,
|
|
1607
|
+
current_volume=self.current_volume,
|
|
1608
|
+
trash_location=(
|
|
1609
|
+
trash_location if trash_location is not None else self.trash_container
|
|
1610
|
+
),
|
|
1611
|
+
)
|
|
1612
|
+
if len(transfer_args.sources_list) != 1:
|
|
1613
|
+
raise ValueError(
|
|
1614
|
+
f"Source should be a single well (or resolve to a single transfer for multi-channel) "
|
|
1615
|
+
f"but received {transfer_args.sources_list}."
|
|
1571
1616
|
)
|
|
1572
|
-
if
|
|
1617
|
+
if transfer_args.tip_policy == TransferTipPolicyV2.PER_SOURCE:
|
|
1573
1618
|
raise RuntimeError(
|
|
1574
|
-
|
|
1575
|
-
" Ensure that all previously aspirated liquid is dispensed before starting"
|
|
1576
|
-
" a new transfer."
|
|
1619
|
+
'Tip transfer policy "per source" incompatible with distribute.'
|
|
1577
1620
|
)
|
|
1578
1621
|
|
|
1579
|
-
|
|
1580
|
-
|
|
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(
|
|
1622
|
+
verified_source = transfer_args.sources_list[0]
|
|
1623
|
+
self._core.distribute_liquid(
|
|
1595
1624
|
liquid_class=liquid_class,
|
|
1596
|
-
|
|
1597
|
-
|
|
1625
|
+
volume=volume,
|
|
1626
|
+
source=(
|
|
1627
|
+
types.Location(types.Point(), labware=verified_source),
|
|
1628
|
+
verified_source._core,
|
|
1629
|
+
),
|
|
1630
|
+
dest=[
|
|
1631
|
+
(types.Location(types.Point(), labware=well), well._core)
|
|
1632
|
+
for well in transfer_args.destinations_list
|
|
1633
|
+
],
|
|
1634
|
+
new_tip=transfer_args.tip_policy,
|
|
1635
|
+
tip_racks=[
|
|
1636
|
+
(types.Location(types.Point(), labware=rack), rack._core)
|
|
1637
|
+
for rack in transfer_args.tip_racks
|
|
1638
|
+
],
|
|
1639
|
+
trash_location=transfer_args.trash_location,
|
|
1640
|
+
return_tip=return_tip,
|
|
1598
1641
|
)
|
|
1642
|
+
return self
|
|
1599
1643
|
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1644
|
+
@requires_version(2, 23)
|
|
1645
|
+
def consolidate_liquid(
|
|
1646
|
+
self,
|
|
1647
|
+
liquid_class: LiquidClass,
|
|
1648
|
+
volume: float,
|
|
1649
|
+
source: Union[
|
|
1650
|
+
labware.Well, Sequence[labware.Well], Sequence[Sequence[labware.Well]]
|
|
1651
|
+
],
|
|
1652
|
+
dest: Union[labware.Well, Sequence[labware.Well]],
|
|
1653
|
+
new_tip: TransferTipPolicyV2Type = "once",
|
|
1654
|
+
trash_location: Optional[
|
|
1655
|
+
Union[types.Location, labware.Well, TrashBin, WasteChute]
|
|
1656
|
+
] = None,
|
|
1657
|
+
return_tip: bool = False,
|
|
1658
|
+
visit_every_well: bool = False,
|
|
1659
|
+
) -> InstrumentContext:
|
|
1660
|
+
"""
|
|
1661
|
+
Consolidate liquid from multiple sources to a single destination
|
|
1662
|
+
using the specified liquid class properties.
|
|
1663
|
+
|
|
1664
|
+
TODO: Add args description.
|
|
1665
|
+
|
|
1666
|
+
:meta private:
|
|
1667
|
+
"""
|
|
1668
|
+
transfer_args = verify_and_normalize_transfer_args(
|
|
1669
|
+
source=source,
|
|
1670
|
+
dest=dest,
|
|
1671
|
+
tip_policy=new_tip,
|
|
1672
|
+
last_tip_picked_up_from=self._last_tip_picked_up_from,
|
|
1673
|
+
tip_racks=self._tip_racks,
|
|
1674
|
+
nozzle_map=self._core.get_nozzle_map(),
|
|
1675
|
+
target_all_wells=visit_every_well,
|
|
1676
|
+
current_volume=self.current_volume,
|
|
1606
1677
|
trash_location=(
|
|
1607
|
-
|
|
1608
|
-
if isinstance(checked_trash_location, labware.Well)
|
|
1609
|
-
else checked_trash_location
|
|
1678
|
+
trash_location if trash_location is not None else self.trash_container
|
|
1610
1679
|
),
|
|
1611
1680
|
)
|
|
1681
|
+
if len(transfer_args.destinations_list) != 1:
|
|
1682
|
+
raise ValueError(
|
|
1683
|
+
f"Destination should be a single well (or resolve to a single transfer for multi-channel) "
|
|
1684
|
+
f"but received {transfer_args.destinations_list}."
|
|
1685
|
+
)
|
|
1686
|
+
if transfer_args.tip_policy == TransferTipPolicyV2.PER_SOURCE:
|
|
1687
|
+
raise RuntimeError(
|
|
1688
|
+
'Tip transfer policy "per source" incompatible with consolidate.'
|
|
1689
|
+
)
|
|
1612
1690
|
|
|
1691
|
+
verified_dest = transfer_args.destinations_list[0]
|
|
1692
|
+
self._core.consolidate_liquid(
|
|
1693
|
+
liquid_class=liquid_class,
|
|
1694
|
+
volume=volume,
|
|
1695
|
+
source=[
|
|
1696
|
+
(types.Location(types.Point(), labware=well), well._core)
|
|
1697
|
+
for well in transfer_args.sources_list
|
|
1698
|
+
],
|
|
1699
|
+
dest=(
|
|
1700
|
+
types.Location(types.Point(), labware=verified_dest),
|
|
1701
|
+
verified_dest._core,
|
|
1702
|
+
),
|
|
1703
|
+
new_tip=transfer_args.tip_policy,
|
|
1704
|
+
tip_racks=[
|
|
1705
|
+
(types.Location(types.Point(), labware=rack), rack._core)
|
|
1706
|
+
for rack in transfer_args.tip_racks
|
|
1707
|
+
],
|
|
1708
|
+
trash_location=transfer_args.trash_location,
|
|
1709
|
+
return_tip=return_tip,
|
|
1710
|
+
)
|
|
1613
1711
|
return self
|
|
1614
1712
|
|
|
1615
1713
|
@requires_version(2, 0)
|
|
@@ -1998,7 +2096,15 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1998
2096
|
@requires_version(2, 0)
|
|
1999
2097
|
def name(self) -> str:
|
|
2000
2098
|
"""
|
|
2001
|
-
The name string for the pipette
|
|
2099
|
+
The name string for the pipette.
|
|
2100
|
+
|
|
2101
|
+
From API version 2.15 to 2.22, this property returned an internal name for Flex
|
|
2102
|
+
pipettes. (e.g., ``"p1000_single_flex"``).
|
|
2103
|
+
|
|
2104
|
+
.. TODO uncomment when 2.23 is ready
|
|
2105
|
+
In API version 2.23 and later, this property returns the Python Protocol API
|
|
2106
|
+
:ref:`load name <new-pipette-models>` of Flex pipettes (e.g.,
|
|
2107
|
+
``"flex_1channel_1000"``).
|
|
2002
2108
|
"""
|
|
2003
2109
|
return self._core.get_pipette_name()
|
|
2004
2110
|
|
|
@@ -2411,7 +2517,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2411
2517
|
self._core.liquid_probe_with_recovery(well._core, loc)
|
|
2412
2518
|
|
|
2413
2519
|
@requires_version(2, 20)
|
|
2414
|
-
def measure_liquid_height(self, well: labware.Well) ->
|
|
2520
|
+
def measure_liquid_height(self, well: labware.Well) -> LiquidTrackingType:
|
|
2415
2521
|
"""Check the height of the liquid within a well.
|
|
2416
2522
|
|
|
2417
2523
|
:returns: The height, in mm, of the liquid from the deck.
|
|
@@ -2422,8 +2528,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2422
2528
|
"""
|
|
2423
2529
|
self._raise_if_pressure_not_supported_by_pipette()
|
|
2424
2530
|
loc = well.top()
|
|
2425
|
-
|
|
2426
|
-
return height
|
|
2531
|
+
return self._core.liquid_probe_without_recovery(well._core, loc)
|
|
2427
2532
|
|
|
2428
2533
|
def _raise_if_configuration_not_supported_by_pipette(
|
|
2429
2534
|
self, style: NozzleLayout
|
|
@@ -2448,24 +2553,41 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2448
2553
|
)
|
|
2449
2554
|
|
|
2450
2555
|
def _handle_aspirate_target(
|
|
2451
|
-
self, target: validation.
|
|
2452
|
-
) -> tuple[
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
is_meniscus: Optional[bool] = None
|
|
2556
|
+
self, target: Union[validation.WellTarget, validation.PointTarget]
|
|
2557
|
+
) -> tuple[
|
|
2558
|
+
types.Location, Optional[labware.Well], Optional[types.MeniscusTrackingTarget]
|
|
2559
|
+
]:
|
|
2456
2560
|
if isinstance(target, validation.WellTarget):
|
|
2457
|
-
well = target.well
|
|
2458
2561
|
if target.location:
|
|
2459
|
-
|
|
2460
|
-
is_meniscus = target.location.is_meniscus
|
|
2562
|
+
return target.location, target.well, target.location.meniscus_tracking
|
|
2461
2563
|
|
|
2462
2564
|
else:
|
|
2463
|
-
|
|
2464
|
-
z=self._well_bottom_clearances.aspirate
|
|
2565
|
+
return (
|
|
2566
|
+
target.well.bottom(z=self._well_bottom_clearances.aspirate),
|
|
2567
|
+
target.well,
|
|
2568
|
+
None,
|
|
2465
2569
|
)
|
|
2466
2570
|
if isinstance(target, validation.PointTarget):
|
|
2467
|
-
|
|
2468
|
-
|
|
2571
|
+
return target.location, None, None
|
|
2572
|
+
|
|
2573
|
+
def _handle_dispense_target(
|
|
2574
|
+
self, target: Union[validation.WellTarget, validation.PointTarget]
|
|
2575
|
+
) -> tuple[
|
|
2576
|
+
types.Location, Optional[labware.Well], Optional[types.MeniscusTrackingTarget]
|
|
2577
|
+
]:
|
|
2578
|
+
if isinstance(target, validation.WellTarget):
|
|
2579
|
+
if target.location:
|
|
2580
|
+
return target.location, target.well, target.location.meniscus_tracking
|
|
2581
|
+
elif target.well.parent._core.is_fixed_trash():
|
|
2582
|
+
return target.well.top(), target.well, None
|
|
2583
|
+
else:
|
|
2584
|
+
return (
|
|
2585
|
+
target.well.bottom(z=self._well_bottom_clearances.dispense),
|
|
2586
|
+
target.well,
|
|
2587
|
+
None,
|
|
2588
|
+
)
|
|
2589
|
+
if isinstance(target, validation.PointTarget):
|
|
2590
|
+
return target.location, None, None
|
|
2469
2591
|
|
|
2470
2592
|
|
|
2471
2593
|
class AutoProbeDisable:
|