opentrons 8.3.1a1__py2.py3-none-any.whl → 8.4.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/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 +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 +246 -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 +24 -29
- 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 +17 -2
- 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/commands/unsafe/unsafe_drop_tip_in_place.py +6 -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.0a1.dist-info}/METADATA +4 -4
- {opentrons-8.3.1a1.dist-info → opentrons-8.4.0a1.dist-info}/RECORD +188 -148
- 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.0a1.dist-info}/LICENSE +0 -0
- {opentrons-8.3.1a1.dist-info → opentrons-8.4.0a1.dist-info}/WHEEL +0 -0
- {opentrons-8.3.1a1.dist-info → opentrons-8.4.0a1.dist-info}/entry_points.txt +0 -0
- {opentrons-8.3.1a1.dist-info → opentrons-8.4.0a1.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)
|
|
@@ -780,6 +778,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
780
778
|
target = loc.labware.as_well().top(height)
|
|
781
779
|
self.move_to(target, publish=False)
|
|
782
780
|
if self.api_version >= _AIR_GAP_TRACKING_ADDED_IN:
|
|
781
|
+
self._core.prepare_to_aspirate()
|
|
783
782
|
c_vol = self._core.get_available_volume() if volume is None else volume
|
|
784
783
|
flow_rate = self._core.get_aspirate_flow_rate()
|
|
785
784
|
self._core.air_gap_in_place(c_vol, flow_rate)
|
|
@@ -1509,6 +1508,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1509
1508
|
for cmd in plan:
|
|
1510
1509
|
getattr(self, cmd["method"])(*cmd["args"], **cmd["kwargs"])
|
|
1511
1510
|
|
|
1511
|
+
@requires_version(2, 23)
|
|
1512
1512
|
def transfer_liquid(
|
|
1513
1513
|
self,
|
|
1514
1514
|
liquid_class: LiquidClass,
|
|
@@ -1520,96 +1520,195 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1520
1520
|
labware.Well, Sequence[labware.Well], Sequence[Sequence[labware.Well]]
|
|
1521
1521
|
],
|
|
1522
1522
|
new_tip: TransferTipPolicyV2Type = "once",
|
|
1523
|
-
|
|
1523
|
+
trash_location: Optional[
|
|
1524
1524
|
Union[types.Location, labware.Well, TrashBin, WasteChute]
|
|
1525
|
-
] = None,
|
|
1525
|
+
] = None,
|
|
1526
|
+
return_tip: bool = False,
|
|
1527
|
+
visit_every_well: bool = False,
|
|
1526
1528
|
) -> InstrumentContext:
|
|
1527
1529
|
"""Transfer liquid from source to dest using the specified liquid class properties.
|
|
1528
1530
|
|
|
1529
1531
|
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
1532
|
|
|
1538
|
-
|
|
1539
|
-
|
|
1533
|
+
:meta private:
|
|
1534
|
+
"""
|
|
1535
|
+
transfer_args = verify_and_normalize_transfer_args(
|
|
1536
|
+
source=source,
|
|
1537
|
+
dest=dest,
|
|
1538
|
+
tip_policy=new_tip,
|
|
1539
|
+
last_tip_picked_up_from=self._last_tip_picked_up_from,
|
|
1540
|
+
tip_racks=self._tip_racks,
|
|
1541
|
+
nozzle_map=self._core.get_nozzle_map(),
|
|
1542
|
+
target_all_wells=visit_every_well,
|
|
1543
|
+
current_volume=self.current_volume,
|
|
1544
|
+
trash_location=(
|
|
1545
|
+
trash_location if trash_location is not None else self.trash_container
|
|
1546
|
+
),
|
|
1540
1547
|
)
|
|
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):
|
|
1548
|
+
if len(transfer_args.sources_list) != len(transfer_args.destinations_list):
|
|
1549
1549
|
raise ValueError(
|
|
1550
1550
|
"Sources and destinations should be of the same length in order to perform a transfer."
|
|
1551
1551
|
" To transfer liquid from one source to many destinations, use 'distribute_liquid',"
|
|
1552
1552
|
" to transfer liquid onto one destinations from many sources, use 'consolidate_liquid'."
|
|
1553
1553
|
)
|
|
1554
1554
|
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1555
|
+
self._core.transfer_liquid(
|
|
1556
|
+
liquid_class=liquid_class,
|
|
1557
|
+
volume=volume,
|
|
1558
|
+
source=[
|
|
1559
|
+
(types.Location(types.Point(), labware=well), well._core)
|
|
1560
|
+
for well in transfer_args.sources_list
|
|
1561
|
+
],
|
|
1562
|
+
dest=[
|
|
1563
|
+
(types.Location(types.Point(), labware=well), well._core)
|
|
1564
|
+
for well in transfer_args.destinations_list
|
|
1565
|
+
],
|
|
1566
|
+
new_tip=transfer_args.tip_policy,
|
|
1567
|
+
tip_racks=[
|
|
1568
|
+
(types.Location(types.Point(), labware=rack), rack._core)
|
|
1569
|
+
for rack in transfer_args.tip_racks
|
|
1570
|
+
],
|
|
1571
|
+
trash_location=transfer_args.trash_location,
|
|
1572
|
+
return_tip=return_tip,
|
|
1573
|
+
)
|
|
1574
|
+
return self
|
|
1575
|
+
|
|
1576
|
+
@requires_version(2, 23)
|
|
1577
|
+
def distribute_liquid(
|
|
1578
|
+
self,
|
|
1579
|
+
liquid_class: LiquidClass,
|
|
1580
|
+
volume: float,
|
|
1581
|
+
source: Union[labware.Well, Sequence[labware.Well]],
|
|
1582
|
+
dest: Union[
|
|
1583
|
+
labware.Well, Sequence[labware.Well], Sequence[Sequence[labware.Well]]
|
|
1584
|
+
],
|
|
1585
|
+
new_tip: TransferTipPolicyV2Type = "once",
|
|
1586
|
+
trash_location: Optional[
|
|
1587
|
+
Union[types.Location, labware.Well, TrashBin, WasteChute]
|
|
1588
|
+
] = None,
|
|
1589
|
+
return_tip: bool = False,
|
|
1590
|
+
visit_every_well: bool = False,
|
|
1591
|
+
) -> InstrumentContext:
|
|
1592
|
+
"""
|
|
1593
|
+
Distribute liquid from a single source to multiple destinations
|
|
1594
|
+
using the specified liquid class properties.
|
|
1595
|
+
|
|
1596
|
+
TODO: Add args description.
|
|
1597
|
+
|
|
1598
|
+
:meta private:
|
|
1599
|
+
"""
|
|
1600
|
+
transfer_args = verify_and_normalize_transfer_args(
|
|
1601
|
+
source=source,
|
|
1602
|
+
dest=dest,
|
|
1603
|
+
tip_policy=new_tip,
|
|
1604
|
+
last_tip_picked_up_from=self._last_tip_picked_up_from,
|
|
1605
|
+
tip_racks=self._tip_racks,
|
|
1606
|
+
nozzle_map=self._core.get_nozzle_map(),
|
|
1607
|
+
target_all_wells=visit_every_well,
|
|
1608
|
+
current_volume=self.current_volume,
|
|
1609
|
+
trash_location=(
|
|
1610
|
+
trash_location if trash_location is not None else self.trash_container
|
|
1611
|
+
),
|
|
1612
|
+
)
|
|
1613
|
+
if len(transfer_args.sources_list) != 1:
|
|
1614
|
+
raise ValueError(
|
|
1615
|
+
f"Source should be a single well (or resolve to a single transfer for multi-channel) "
|
|
1616
|
+
f"but received {transfer_args.sources_list}."
|
|
1571
1617
|
)
|
|
1572
|
-
if
|
|
1618
|
+
if transfer_args.tip_policy == TransferTipPolicyV2.PER_SOURCE:
|
|
1573
1619
|
raise RuntimeError(
|
|
1574
|
-
|
|
1575
|
-
" Ensure that all previously aspirated liquid is dispensed before starting"
|
|
1576
|
-
" a new transfer."
|
|
1620
|
+
'Tip transfer policy "per source" incompatible with distribute.'
|
|
1577
1621
|
)
|
|
1578
1622
|
|
|
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(
|
|
1623
|
+
verified_source = transfer_args.sources_list[0]
|
|
1624
|
+
self._core.distribute_liquid(
|
|
1595
1625
|
liquid_class=liquid_class,
|
|
1596
|
-
|
|
1597
|
-
|
|
1626
|
+
volume=volume,
|
|
1627
|
+
source=(
|
|
1628
|
+
types.Location(types.Point(), labware=verified_source),
|
|
1629
|
+
verified_source._core,
|
|
1630
|
+
),
|
|
1631
|
+
dest=[
|
|
1632
|
+
(types.Location(types.Point(), labware=well), well._core)
|
|
1633
|
+
for well in transfer_args.destinations_list
|
|
1634
|
+
],
|
|
1635
|
+
new_tip=transfer_args.tip_policy,
|
|
1636
|
+
tip_racks=[
|
|
1637
|
+
(types.Location(types.Point(), labware=rack), rack._core)
|
|
1638
|
+
for rack in transfer_args.tip_racks
|
|
1639
|
+
],
|
|
1640
|
+
trash_location=transfer_args.trash_location,
|
|
1641
|
+
return_tip=return_tip,
|
|
1598
1642
|
)
|
|
1643
|
+
return self
|
|
1599
1644
|
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1645
|
+
@requires_version(2, 23)
|
|
1646
|
+
def consolidate_liquid(
|
|
1647
|
+
self,
|
|
1648
|
+
liquid_class: LiquidClass,
|
|
1649
|
+
volume: float,
|
|
1650
|
+
source: Union[
|
|
1651
|
+
labware.Well, Sequence[labware.Well], Sequence[Sequence[labware.Well]]
|
|
1652
|
+
],
|
|
1653
|
+
dest: Union[labware.Well, Sequence[labware.Well]],
|
|
1654
|
+
new_tip: TransferTipPolicyV2Type = "once",
|
|
1655
|
+
trash_location: Optional[
|
|
1656
|
+
Union[types.Location, labware.Well, TrashBin, WasteChute]
|
|
1657
|
+
] = None,
|
|
1658
|
+
return_tip: bool = False,
|
|
1659
|
+
visit_every_well: bool = False,
|
|
1660
|
+
) -> InstrumentContext:
|
|
1661
|
+
"""
|
|
1662
|
+
Consolidate liquid from multiple sources to a single destination
|
|
1663
|
+
using the specified liquid class properties.
|
|
1664
|
+
|
|
1665
|
+
TODO: Add args description.
|
|
1666
|
+
|
|
1667
|
+
:meta private:
|
|
1668
|
+
"""
|
|
1669
|
+
transfer_args = verify_and_normalize_transfer_args(
|
|
1670
|
+
source=source,
|
|
1671
|
+
dest=dest,
|
|
1672
|
+
tip_policy=new_tip,
|
|
1673
|
+
last_tip_picked_up_from=self._last_tip_picked_up_from,
|
|
1674
|
+
tip_racks=self._tip_racks,
|
|
1675
|
+
nozzle_map=self._core.get_nozzle_map(),
|
|
1676
|
+
target_all_wells=visit_every_well,
|
|
1677
|
+
current_volume=self.current_volume,
|
|
1606
1678
|
trash_location=(
|
|
1607
|
-
|
|
1608
|
-
if isinstance(checked_trash_location, labware.Well)
|
|
1609
|
-
else checked_trash_location
|
|
1679
|
+
trash_location if trash_location is not None else self.trash_container
|
|
1610
1680
|
),
|
|
1611
1681
|
)
|
|
1682
|
+
if len(transfer_args.destinations_list) != 1:
|
|
1683
|
+
raise ValueError(
|
|
1684
|
+
f"Destination should be a single well (or resolve to a single transfer for multi-channel) "
|
|
1685
|
+
f"but received {transfer_args.destinations_list}."
|
|
1686
|
+
)
|
|
1687
|
+
if transfer_args.tip_policy == TransferTipPolicyV2.PER_SOURCE:
|
|
1688
|
+
raise RuntimeError(
|
|
1689
|
+
'Tip transfer policy "per source" incompatible with consolidate.'
|
|
1690
|
+
)
|
|
1612
1691
|
|
|
1692
|
+
verified_dest = transfer_args.destinations_list[0]
|
|
1693
|
+
self._core.consolidate_liquid(
|
|
1694
|
+
liquid_class=liquid_class,
|
|
1695
|
+
volume=volume,
|
|
1696
|
+
source=[
|
|
1697
|
+
(types.Location(types.Point(), labware=well), well._core)
|
|
1698
|
+
for well in transfer_args.sources_list
|
|
1699
|
+
],
|
|
1700
|
+
dest=(
|
|
1701
|
+
types.Location(types.Point(), labware=verified_dest),
|
|
1702
|
+
verified_dest._core,
|
|
1703
|
+
),
|
|
1704
|
+
new_tip=transfer_args.tip_policy,
|
|
1705
|
+
tip_racks=[
|
|
1706
|
+
(types.Location(types.Point(), labware=rack), rack._core)
|
|
1707
|
+
for rack in transfer_args.tip_racks
|
|
1708
|
+
],
|
|
1709
|
+
trash_location=transfer_args.trash_location,
|
|
1710
|
+
return_tip=return_tip,
|
|
1711
|
+
)
|
|
1613
1712
|
return self
|
|
1614
1713
|
|
|
1615
1714
|
@requires_version(2, 0)
|
|
@@ -1998,7 +2097,15 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1998
2097
|
@requires_version(2, 0)
|
|
1999
2098
|
def name(self) -> str:
|
|
2000
2099
|
"""
|
|
2001
|
-
The name string for the pipette
|
|
2100
|
+
The name string for the pipette.
|
|
2101
|
+
|
|
2102
|
+
From API version 2.15 to 2.22, this property returned an internal name for Flex
|
|
2103
|
+
pipettes. (e.g., ``"p1000_single_flex"``).
|
|
2104
|
+
|
|
2105
|
+
.. TODO uncomment when 2.23 is ready
|
|
2106
|
+
In API version 2.23 and later, this property returns the Python Protocol API
|
|
2107
|
+
:ref:`load name <new-pipette-models>` of Flex pipettes (e.g.,
|
|
2108
|
+
``"flex_1channel_1000"``).
|
|
2002
2109
|
"""
|
|
2003
2110
|
return self._core.get_pipette_name()
|
|
2004
2111
|
|
|
@@ -2411,7 +2518,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2411
2518
|
self._core.liquid_probe_with_recovery(well._core, loc)
|
|
2412
2519
|
|
|
2413
2520
|
@requires_version(2, 20)
|
|
2414
|
-
def measure_liquid_height(self, well: labware.Well) ->
|
|
2521
|
+
def measure_liquid_height(self, well: labware.Well) -> LiquidTrackingType:
|
|
2415
2522
|
"""Check the height of the liquid within a well.
|
|
2416
2523
|
|
|
2417
2524
|
:returns: The height, in mm, of the liquid from the deck.
|
|
@@ -2422,8 +2529,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2422
2529
|
"""
|
|
2423
2530
|
self._raise_if_pressure_not_supported_by_pipette()
|
|
2424
2531
|
loc = well.top()
|
|
2425
|
-
|
|
2426
|
-
return height
|
|
2532
|
+
return self._core.liquid_probe_without_recovery(well._core, loc)
|
|
2427
2533
|
|
|
2428
2534
|
def _raise_if_configuration_not_supported_by_pipette(
|
|
2429
2535
|
self, style: NozzleLayout
|
|
@@ -2448,24 +2554,41 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2448
2554
|
)
|
|
2449
2555
|
|
|
2450
2556
|
def _handle_aspirate_target(
|
|
2451
|
-
self, target: validation.
|
|
2452
|
-
) -> tuple[
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
is_meniscus: Optional[bool] = None
|
|
2557
|
+
self, target: Union[validation.WellTarget, validation.PointTarget]
|
|
2558
|
+
) -> tuple[
|
|
2559
|
+
types.Location, Optional[labware.Well], Optional[types.MeniscusTrackingTarget]
|
|
2560
|
+
]:
|
|
2456
2561
|
if isinstance(target, validation.WellTarget):
|
|
2457
|
-
well = target.well
|
|
2458
2562
|
if target.location:
|
|
2459
|
-
|
|
2460
|
-
is_meniscus = target.location.is_meniscus
|
|
2563
|
+
return target.location, target.well, target.location.meniscus_tracking
|
|
2461
2564
|
|
|
2462
2565
|
else:
|
|
2463
|
-
|
|
2464
|
-
z=self._well_bottom_clearances.aspirate
|
|
2566
|
+
return (
|
|
2567
|
+
target.well.bottom(z=self._well_bottom_clearances.aspirate),
|
|
2568
|
+
target.well,
|
|
2569
|
+
None,
|
|
2465
2570
|
)
|
|
2466
2571
|
if isinstance(target, validation.PointTarget):
|
|
2467
|
-
|
|
2468
|
-
|
|
2572
|
+
return target.location, None, None
|
|
2573
|
+
|
|
2574
|
+
def _handle_dispense_target(
|
|
2575
|
+
self, target: Union[validation.WellTarget, validation.PointTarget]
|
|
2576
|
+
) -> tuple[
|
|
2577
|
+
types.Location, Optional[labware.Well], Optional[types.MeniscusTrackingTarget]
|
|
2578
|
+
]:
|
|
2579
|
+
if isinstance(target, validation.WellTarget):
|
|
2580
|
+
if target.location:
|
|
2581
|
+
return target.location, target.well, target.location.meniscus_tracking
|
|
2582
|
+
elif target.well.parent._core.is_fixed_trash():
|
|
2583
|
+
return target.well.top(), target.well, None
|
|
2584
|
+
else:
|
|
2585
|
+
return (
|
|
2586
|
+
target.well.bottom(z=self._well_bottom_clearances.dispense),
|
|
2587
|
+
target.well,
|
|
2588
|
+
None,
|
|
2589
|
+
)
|
|
2590
|
+
if isinstance(target, validation.PointTarget):
|
|
2591
|
+
return target.location, None, None
|
|
2469
2592
|
|
|
2470
2593
|
|
|
2471
2594
|
class AutoProbeDisable:
|