opentrons 8.3.2__py2.py3-none-any.whl → 8.4.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of opentrons might be problematic. Click here for more details.
- opentrons/calibration_storage/ot2/mark_bad_calibration.py +2 -0
- opentrons/calibration_storage/ot2/tip_length.py +6 -6
- opentrons/config/advanced_settings.py +9 -11
- opentrons/config/feature_flags.py +0 -4
- opentrons/config/reset.py +7 -2
- opentrons/drivers/asyncio/communication/__init__.py +2 -0
- opentrons/drivers/asyncio/communication/async_serial.py +4 -0
- opentrons/drivers/asyncio/communication/errors.py +41 -8
- opentrons/drivers/asyncio/communication/serial_connection.py +36 -10
- opentrons/drivers/flex_stacker/__init__.py +9 -3
- opentrons/drivers/flex_stacker/abstract.py +140 -15
- opentrons/drivers/flex_stacker/driver.py +593 -47
- opentrons/drivers/flex_stacker/errors.py +64 -0
- opentrons/drivers/flex_stacker/simulator.py +222 -24
- opentrons/drivers/flex_stacker/types.py +211 -15
- opentrons/drivers/flex_stacker/utils.py +19 -0
- opentrons/execute.py +4 -2
- opentrons/hardware_control/api.py +5 -0
- opentrons/hardware_control/backends/flex_protocol.py +4 -0
- opentrons/hardware_control/backends/ot3controller.py +12 -1
- opentrons/hardware_control/backends/ot3simulator.py +3 -0
- opentrons/hardware_control/backends/subsystem_manager.py +8 -4
- opentrons/hardware_control/instruments/ot2/instrument_calibration.py +10 -6
- opentrons/hardware_control/instruments/ot3/pipette_handler.py +59 -6
- opentrons/hardware_control/modules/__init__.py +12 -1
- opentrons/hardware_control/modules/absorbance_reader.py +11 -9
- opentrons/hardware_control/modules/flex_stacker.py +498 -0
- opentrons/hardware_control/modules/heater_shaker.py +12 -10
- opentrons/hardware_control/modules/magdeck.py +5 -1
- opentrons/hardware_control/modules/tempdeck.py +5 -1
- opentrons/hardware_control/modules/thermocycler.py +15 -14
- opentrons/hardware_control/modules/types.py +191 -1
- opentrons/hardware_control/modules/utils.py +3 -0
- opentrons/hardware_control/motion_utilities.py +20 -0
- opentrons/hardware_control/ot3api.py +145 -15
- opentrons/hardware_control/protocols/liquid_handler.py +47 -1
- opentrons/hardware_control/types.py +6 -0
- opentrons/legacy_commands/commands.py +102 -5
- opentrons/legacy_commands/helpers.py +74 -1
- opentrons/legacy_commands/types.py +33 -2
- opentrons/protocol_api/__init__.py +2 -0
- opentrons/protocol_api/_liquid.py +39 -8
- opentrons/protocol_api/_liquid_properties.py +20 -19
- opentrons/protocol_api/_transfer_liquid_validation.py +91 -0
- opentrons/protocol_api/core/common.py +3 -1
- opentrons/protocol_api/core/engine/deck_conflict.py +11 -1
- opentrons/protocol_api/core/engine/instrument.py +1356 -107
- opentrons/protocol_api/core/engine/labware.py +8 -4
- opentrons/protocol_api/core/engine/load_labware_params.py +68 -10
- opentrons/protocol_api/core/engine/module_core.py +118 -2
- opentrons/protocol_api/core/engine/pipette_movement_conflict.py +6 -14
- opentrons/protocol_api/core/engine/protocol.py +253 -11
- opentrons/protocol_api/core/engine/stringify.py +19 -8
- opentrons/protocol_api/core/engine/transfer_components_executor.py +858 -0
- opentrons/protocol_api/core/engine/well.py +73 -5
- opentrons/protocol_api/core/instrument.py +71 -21
- opentrons/protocol_api/core/labware.py +6 -2
- opentrons/protocol_api/core/legacy/labware_offset_provider.py +7 -3
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +76 -49
- opentrons/protocol_api/core/legacy/legacy_labware_core.py +8 -4
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +36 -0
- opentrons/protocol_api/core/legacy/legacy_well_core.py +27 -2
- opentrons/protocol_api/core/legacy/load_info.py +4 -12
- opentrons/protocol_api/core/legacy/module_geometry.py +6 -1
- opentrons/protocol_api/core/legacy/well_geometry.py +3 -3
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +73 -23
- opentrons/protocol_api/core/module.py +43 -0
- opentrons/protocol_api/core/protocol.py +33 -0
- opentrons/protocol_api/core/well.py +23 -2
- opentrons/protocol_api/instrument_context.py +454 -150
- opentrons/protocol_api/labware.py +98 -50
- opentrons/protocol_api/module_contexts.py +140 -0
- opentrons/protocol_api/protocol_context.py +163 -19
- opentrons/protocol_api/validation.py +51 -41
- opentrons/protocol_engine/__init__.py +21 -2
- opentrons/protocol_engine/actions/actions.py +5 -5
- opentrons/protocol_engine/clients/sync_client.py +6 -0
- opentrons/protocol_engine/commands/__init__.py +66 -36
- opentrons/protocol_engine/commands/absorbance_reader/__init__.py +0 -1
- opentrons/protocol_engine/commands/air_gap_in_place.py +3 -2
- opentrons/protocol_engine/commands/aspirate.py +6 -2
- opentrons/protocol_engine/commands/aspirate_in_place.py +3 -1
- opentrons/protocol_engine/commands/aspirate_while_tracking.py +210 -0
- opentrons/protocol_engine/commands/blow_out.py +2 -0
- opentrons/protocol_engine/commands/blow_out_in_place.py +4 -1
- opentrons/protocol_engine/commands/command_unions.py +102 -33
- opentrons/protocol_engine/commands/configure_for_volume.py +3 -0
- opentrons/protocol_engine/commands/dispense.py +3 -1
- opentrons/protocol_engine/commands/dispense_in_place.py +3 -0
- opentrons/protocol_engine/commands/dispense_while_tracking.py +204 -0
- opentrons/protocol_engine/commands/drop_tip.py +23 -1
- opentrons/protocol_engine/commands/flex_stacker/__init__.py +106 -0
- opentrons/protocol_engine/commands/flex_stacker/close_latch.py +72 -0
- opentrons/protocol_engine/commands/flex_stacker/common.py +15 -0
- opentrons/protocol_engine/commands/flex_stacker/empty.py +161 -0
- opentrons/protocol_engine/commands/flex_stacker/fill.py +164 -0
- opentrons/protocol_engine/commands/flex_stacker/open_latch.py +70 -0
- opentrons/protocol_engine/commands/flex_stacker/prepare_shuttle.py +112 -0
- opentrons/protocol_engine/commands/flex_stacker/retrieve.py +394 -0
- opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +190 -0
- opentrons/protocol_engine/commands/flex_stacker/store.py +291 -0
- opentrons/protocol_engine/commands/generate_command_schema.py +31 -2
- opentrons/protocol_engine/commands/labware_handling_common.py +29 -0
- opentrons/protocol_engine/commands/liquid_probe.py +27 -13
- opentrons/protocol_engine/commands/load_labware.py +42 -39
- opentrons/protocol_engine/commands/load_lid.py +21 -13
- opentrons/protocol_engine/commands/load_lid_stack.py +130 -47
- opentrons/protocol_engine/commands/load_module.py +18 -17
- opentrons/protocol_engine/commands/load_pipette.py +3 -0
- opentrons/protocol_engine/commands/move_labware.py +139 -20
- opentrons/protocol_engine/commands/move_to_well.py +5 -11
- opentrons/protocol_engine/commands/pick_up_tip.py +5 -2
- opentrons/protocol_engine/commands/pipetting_common.py +159 -8
- opentrons/protocol_engine/commands/prepare_to_aspirate.py +15 -5
- opentrons/protocol_engine/commands/{evotip_dispense.py → pressure_dispense.py} +33 -34
- opentrons/protocol_engine/commands/reload_labware.py +6 -19
- opentrons/protocol_engine/commands/{evotip_seal_pipette.py → seal_pipette_to_tip.py} +97 -76
- opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +3 -1
- opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +6 -1
- opentrons/protocol_engine/commands/{evotip_unseal_pipette.py → unseal_pipette_from_tip.py} +31 -40
- opentrons/protocol_engine/errors/__init__.py +10 -0
- opentrons/protocol_engine/errors/exceptions.py +62 -0
- opentrons/protocol_engine/execution/equipment.py +123 -106
- opentrons/protocol_engine/execution/labware_movement.py +8 -6
- opentrons/protocol_engine/execution/pipetting.py +235 -25
- opentrons/protocol_engine/execution/tip_handler.py +82 -32
- opentrons/protocol_engine/labware_offset_standardization.py +194 -0
- opentrons/protocol_engine/protocol_engine.py +22 -13
- opentrons/protocol_engine/resources/deck_configuration_provider.py +98 -2
- opentrons/protocol_engine/resources/deck_data_provider.py +1 -1
- opentrons/protocol_engine/resources/labware_data_provider.py +32 -12
- opentrons/protocol_engine/resources/labware_validation.py +7 -5
- opentrons/protocol_engine/slot_standardization.py +11 -23
- opentrons/protocol_engine/state/addressable_areas.py +84 -46
- opentrons/protocol_engine/state/frustum_helpers.py +36 -14
- opentrons/protocol_engine/state/geometry.py +892 -227
- opentrons/protocol_engine/state/labware.py +252 -55
- opentrons/protocol_engine/state/module_substates/__init__.py +4 -0
- opentrons/protocol_engine/state/module_substates/flex_stacker_substate.py +68 -0
- opentrons/protocol_engine/state/module_substates/heater_shaker_module_substate.py +22 -0
- opentrons/protocol_engine/state/module_substates/temperature_module_substate.py +13 -0
- opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +20 -0
- opentrons/protocol_engine/state/modules.py +210 -67
- opentrons/protocol_engine/state/pipettes.py +54 -0
- opentrons/protocol_engine/state/state.py +1 -1
- opentrons/protocol_engine/state/tips.py +14 -0
- opentrons/protocol_engine/state/update_types.py +180 -25
- opentrons/protocol_engine/state/wells.py +55 -9
- opentrons/protocol_engine/types/__init__.py +300 -0
- opentrons/protocol_engine/types/automatic_tip_selection.py +39 -0
- opentrons/protocol_engine/types/command_annotations.py +53 -0
- opentrons/protocol_engine/types/deck_configuration.py +72 -0
- opentrons/protocol_engine/types/execution.py +96 -0
- opentrons/protocol_engine/types/hardware_passthrough.py +25 -0
- opentrons/protocol_engine/types/instrument.py +47 -0
- opentrons/protocol_engine/types/instrument_sensors.py +47 -0
- opentrons/protocol_engine/types/labware.py +111 -0
- opentrons/protocol_engine/types/labware_movement.py +22 -0
- opentrons/protocol_engine/types/labware_offset_location.py +111 -0
- opentrons/protocol_engine/types/labware_offset_vector.py +33 -0
- opentrons/protocol_engine/types/liquid.py +40 -0
- opentrons/protocol_engine/types/liquid_class.py +59 -0
- opentrons/protocol_engine/types/liquid_handling.py +13 -0
- opentrons/protocol_engine/types/liquid_level_detection.py +131 -0
- opentrons/protocol_engine/types/location.py +194 -0
- opentrons/protocol_engine/types/module.py +301 -0
- opentrons/protocol_engine/types/partial_tip_configuration.py +76 -0
- opentrons/protocol_engine/types/run_time_parameters.py +133 -0
- opentrons/protocol_engine/types/tip.py +18 -0
- opentrons/protocol_engine/types/util.py +21 -0
- opentrons/protocol_engine/types/well_position.py +124 -0
- opentrons/protocol_reader/extract_labware_definitions.py +7 -3
- opentrons/protocol_reader/file_format_validator.py +5 -3
- opentrons/protocol_runner/json_translator.py +4 -2
- opentrons/protocol_runner/legacy_command_mapper.py +6 -2
- opentrons/protocol_runner/run_orchestrator.py +4 -1
- opentrons/protocols/advanced_control/transfers/common.py +48 -1
- opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +204 -0
- opentrons/protocols/api_support/definitions.py +1 -1
- opentrons/protocols/api_support/instrument.py +16 -3
- opentrons/protocols/labware.py +27 -23
- opentrons/protocols/models/__init__.py +0 -21
- opentrons/simulate.py +4 -2
- opentrons/types.py +20 -7
- opentrons/util/logging_config.py +94 -25
- opentrons/util/logging_queue_handler.py +61 -0
- {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/METADATA +4 -4
- {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/RECORD +192 -151
- opentrons/calibration_storage/ot2/models/defaults.py +0 -0
- opentrons/calibration_storage/ot3/models/defaults.py +0 -0
- opentrons/protocol_api/core/legacy/legacy_robot_core.py +0 -0
- opentrons/protocol_engine/types.py +0 -1311
- {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/LICENSE +0 -0
- {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/WHEEL +0 -0
- {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/entry_points.txt +0 -0
- {opentrons-8.3.2.dist-info → opentrons-8.4.0.dist-info}/top_level.txt +0 -0
|
@@ -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 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
|
|
@@ -610,7 +606,20 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
610
606
|
"Blow_out being performed on a tiprack. "
|
|
611
607
|
"Please re-check your code"
|
|
612
608
|
)
|
|
613
|
-
|
|
609
|
+
if target.location:
|
|
610
|
+
# because the lower levels of blowout don't handle LiquidHandlingWellLocation and
|
|
611
|
+
# there is no "operation_volume" for blowout we need to convert the relative location
|
|
612
|
+
# given with a .meniscus to an absolute point. To maintain the meniscus behavior
|
|
613
|
+
# we can just add the offset to the current liquid height.
|
|
614
|
+
if target.location.meniscus_tracking:
|
|
615
|
+
move_to_location = target.well.bottom(
|
|
616
|
+
target.well.current_liquid_height() # type: ignore [arg-type]
|
|
617
|
+
+ target.location.point.z
|
|
618
|
+
)
|
|
619
|
+
else:
|
|
620
|
+
move_to_location = target.location
|
|
621
|
+
else:
|
|
622
|
+
move_to_location = target.well.top()
|
|
614
623
|
well = target.well
|
|
615
624
|
elif isinstance(target, validation.PointTarget):
|
|
616
625
|
move_to_location = target.location
|
|
@@ -756,18 +765,20 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
756
765
|
|
|
757
766
|
:returns: This instance.
|
|
758
767
|
|
|
759
|
-
|
|
768
|
+
Both ``volume`` and ``height`` are optional, but if you want to specify only
|
|
769
|
+
``height`` you must do it as a keyword argument:
|
|
770
|
+
``pipette.air_gap(height=2)``. If you call ``air_gap`` with a single,
|
|
771
|
+
unnamed argument, it will always be interpreted as a volume.
|
|
760
772
|
|
|
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.
|
|
773
|
+
.. note::
|
|
765
774
|
|
|
766
|
-
|
|
767
|
-
Before API version 2.22, this function was implemented as an aspirate, and
|
|
775
|
+
In API version 2.21 and earlier, this function was implemented as an aspirate, and
|
|
768
776
|
dispensing into a well would add the air gap volume to the liquid tracked in
|
|
769
|
-
the well.
|
|
777
|
+
the well. In API version 2.22 and later, air gap volume is not tracked as liquid
|
|
770
778
|
when dispensing into a well.
|
|
779
|
+
|
|
780
|
+
.. versionchanged:: 2.22
|
|
781
|
+
No longer implemented as an aspirate.
|
|
771
782
|
"""
|
|
772
783
|
if not self._core.has_tip():
|
|
773
784
|
raise UnexpectedTipRemovalError("air_gap", self.name, self.mount)
|
|
@@ -780,6 +791,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
780
791
|
target = loc.labware.as_well().top(height)
|
|
781
792
|
self.move_to(target, publish=False)
|
|
782
793
|
if self.api_version >= _AIR_GAP_TRACKING_ADDED_IN:
|
|
794
|
+
self._core.prepare_to_aspirate()
|
|
783
795
|
c_vol = self._core.get_available_volume() if volume is None else volume
|
|
784
796
|
flow_rate = self._core.get_aspirate_flow_rate()
|
|
785
797
|
self._core.air_gap_in_place(c_vol, flow_rate)
|
|
@@ -1509,7 +1521,8 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1509
1521
|
for cmd in plan:
|
|
1510
1522
|
getattr(self, cmd["method"])(*cmd["args"], **cmd["kwargs"])
|
|
1511
1523
|
|
|
1512
|
-
|
|
1524
|
+
@requires_version(2, 23)
|
|
1525
|
+
def transfer_with_liquid_class(
|
|
1513
1526
|
self,
|
|
1514
1527
|
liquid_class: LiquidClass,
|
|
1515
1528
|
volume: float,
|
|
@@ -1520,96 +1533,335 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1520
1533
|
labware.Well, Sequence[labware.Well], Sequence[Sequence[labware.Well]]
|
|
1521
1534
|
],
|
|
1522
1535
|
new_tip: TransferTipPolicyV2Type = "once",
|
|
1523
|
-
|
|
1536
|
+
trash_location: Optional[
|
|
1524
1537
|
Union[types.Location, labware.Well, TrashBin, WasteChute]
|
|
1525
|
-
] = None,
|
|
1538
|
+
] = None,
|
|
1539
|
+
return_tip: bool = False,
|
|
1540
|
+
visit_every_well: bool = False,
|
|
1526
1541
|
) -> InstrumentContext:
|
|
1527
|
-
"""
|
|
1542
|
+
"""Move a particular type of liquid from one well or group of wells to another.
|
|
1543
|
+
|
|
1544
|
+
..
|
|
1545
|
+
This is intended for Opentrons internal use only and is not a guaranteed API.
|
|
1546
|
+
|
|
1547
|
+
:param liquid_class: The type of liquid to move. You must specify the liquid class,
|
|
1548
|
+
even if you have used :py:meth:`.Labware.load_liquid` to indicate what liquid the
|
|
1549
|
+
source contains.
|
|
1550
|
+
:type liquid_class: :py:class:`.LiquidClass`
|
|
1528
1551
|
|
|
1529
|
-
|
|
1552
|
+
:param volume: The amount, in µL, to aspirate from each source and dispense to
|
|
1553
|
+
each destination.
|
|
1554
|
+
:param source: A single well or a list of wells to aspirate liquid from.
|
|
1555
|
+
:param dest: A single well or a list of wells to dispense liquid into.
|
|
1556
|
+
:param new_tip: When to pick up and drop tips during the command.
|
|
1557
|
+
Defaults to ``"once"``.
|
|
1558
|
+
|
|
1559
|
+
- ``"once"``: Use one tip for the entire command.
|
|
1560
|
+
- ``"always"``: Use a new tip for each set of aspirate and dispense steps.
|
|
1561
|
+
- ``"per source"``: Use one tip for each source well, even if
|
|
1562
|
+
:ref:`tip refilling <complex-tip-refilling>` is required.
|
|
1563
|
+
- ``"never"``: Do not pick up or drop tips at all.
|
|
1564
|
+
|
|
1565
|
+
See :ref:`param-tip-handling` for details.
|
|
1566
|
+
|
|
1567
|
+
:param trash_location: A trash container, well, or other location to dispose of
|
|
1568
|
+
tips. Depending on the liquid class, the pipette may also blow out liquid here.
|
|
1569
|
+
:param return_tip: Whether to drop used tips in their original locations
|
|
1570
|
+
in the tip rack, instead of the trash.
|
|
1571
|
+
|
|
1572
|
+
:meta private:
|
|
1530
1573
|
"""
|
|
1531
|
-
if
|
|
1532
|
-
|
|
1533
|
-
|
|
1574
|
+
if volume == 0.0:
|
|
1575
|
+
_log.info(
|
|
1576
|
+
f"Transfer of {liquid_class.name} specified with a volume of 0uL."
|
|
1577
|
+
f" Skipping."
|
|
1534
1578
|
)
|
|
1535
|
-
|
|
1536
|
-
raise NotImplementedError("This method is not implemented.")
|
|
1579
|
+
return self
|
|
1537
1580
|
|
|
1538
|
-
|
|
1539
|
-
source
|
|
1581
|
+
transfer_args = verify_and_normalize_transfer_args(
|
|
1582
|
+
source=source,
|
|
1583
|
+
dest=dest,
|
|
1584
|
+
tip_policy=new_tip,
|
|
1585
|
+
last_tip_picked_up_from=self._last_tip_picked_up_from,
|
|
1586
|
+
tip_racks=self._tip_racks,
|
|
1587
|
+
nozzle_map=self._core.get_nozzle_map(),
|
|
1588
|
+
target_all_wells=visit_every_well,
|
|
1589
|
+
current_volume=self.current_volume,
|
|
1590
|
+
trash_location=(
|
|
1591
|
+
trash_location if trash_location is not None else self.trash_container
|
|
1592
|
+
),
|
|
1540
1593
|
)
|
|
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):
|
|
1594
|
+
if len(transfer_args.sources_list) != len(transfer_args.destinations_list):
|
|
1549
1595
|
raise ValueError(
|
|
1550
1596
|
"Sources and destinations should be of the same length in order to perform a transfer."
|
|
1551
1597
|
" To transfer liquid from one source to many destinations, use 'distribute_liquid',"
|
|
1552
1598
|
" to transfer liquid onto one destinations from many sources, use 'consolidate_liquid'."
|
|
1553
1599
|
)
|
|
1554
1600
|
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1601
|
+
with publisher.publish_context(
|
|
1602
|
+
broker=self.broker,
|
|
1603
|
+
command=cmds.transfer_with_liquid_class(
|
|
1604
|
+
instrument=self,
|
|
1605
|
+
liquid_class=liquid_class,
|
|
1606
|
+
volume=volume,
|
|
1607
|
+
source=source,
|
|
1608
|
+
destination=dest,
|
|
1609
|
+
),
|
|
1610
|
+
):
|
|
1611
|
+
self._core.transfer_with_liquid_class(
|
|
1612
|
+
liquid_class=liquid_class,
|
|
1613
|
+
volume=volume,
|
|
1614
|
+
source=[
|
|
1615
|
+
(types.Location(types.Point(), labware=well), well._core)
|
|
1616
|
+
for well in transfer_args.sources_list
|
|
1617
|
+
],
|
|
1618
|
+
dest=[
|
|
1619
|
+
(types.Location(types.Point(), labware=well), well._core)
|
|
1620
|
+
for well in transfer_args.destinations_list
|
|
1621
|
+
],
|
|
1622
|
+
new_tip=transfer_args.tip_policy,
|
|
1623
|
+
tip_racks=[
|
|
1624
|
+
(types.Location(types.Point(), labware=rack), rack._core)
|
|
1625
|
+
for rack in transfer_args.tip_racks
|
|
1626
|
+
],
|
|
1627
|
+
starting_tip=(
|
|
1628
|
+
self.starting_tip._core if self.starting_tip is not None else None
|
|
1629
|
+
),
|
|
1630
|
+
trash_location=transfer_args.trash_location,
|
|
1631
|
+
return_tip=return_tip,
|
|
1577
1632
|
)
|
|
1633
|
+
return self
|
|
1578
1634
|
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1635
|
+
@requires_version(2, 23)
|
|
1636
|
+
def distribute_with_liquid_class(
|
|
1637
|
+
self,
|
|
1638
|
+
liquid_class: LiquidClass,
|
|
1639
|
+
volume: float,
|
|
1640
|
+
source: Union[labware.Well, Sequence[labware.Well]],
|
|
1641
|
+
dest: Union[
|
|
1642
|
+
labware.Well, Sequence[labware.Well], Sequence[Sequence[labware.Well]]
|
|
1643
|
+
],
|
|
1644
|
+
new_tip: TransferTipPolicyV2Type = "once",
|
|
1645
|
+
trash_location: Optional[
|
|
1646
|
+
Union[types.Location, labware.Well, TrashBin, WasteChute]
|
|
1647
|
+
] = None,
|
|
1648
|
+
return_tip: bool = False,
|
|
1649
|
+
visit_every_well: bool = False,
|
|
1650
|
+
) -> InstrumentContext:
|
|
1651
|
+
"""
|
|
1652
|
+
Distribute a particular type of liquid from one well to a group of wells.
|
|
1653
|
+
|
|
1654
|
+
..
|
|
1655
|
+
This is intended for Opentrons internal use only and is not a guaranteed API.
|
|
1656
|
+
|
|
1657
|
+
:param liquid_class: The type of liquid to move. You must specify the liquid class,
|
|
1658
|
+
even if you have used :py:meth:`.Labware.load_liquid` to indicate what liquid the
|
|
1659
|
+
source contains.
|
|
1660
|
+
:type liquid_class: :py:class:`.LiquidClass`
|
|
1661
|
+
|
|
1662
|
+
:param volume: The amount, in µL, to aspirate from the source and dispense to
|
|
1663
|
+
each destination.
|
|
1664
|
+
:param source: A single well to aspirate liquid from.
|
|
1665
|
+
:param dest: A list of wells to dispense liquid into.
|
|
1666
|
+
:param new_tip: When to pick up and drop tips during the command.
|
|
1667
|
+
Defaults to ``"once"``.
|
|
1668
|
+
|
|
1669
|
+
- ``"once"``: Use one tip for the entire command.
|
|
1670
|
+
- ``"never"``: Do not pick up or drop tips at all.
|
|
1588
1671
|
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1672
|
+
See :ref:`param-tip-handling` for details.
|
|
1673
|
+
|
|
1674
|
+
:param trash_location: A trash container, well, or other location to dispose of
|
|
1675
|
+
tips. Depending on the liquid class, the pipette may also blow out liquid here.
|
|
1676
|
+
:param return_tip: Whether to drop used tips in their original locations
|
|
1677
|
+
in the tip rack, instead of the trash.
|
|
1678
|
+
|
|
1679
|
+
:meta private:
|
|
1680
|
+
"""
|
|
1681
|
+
if volume == 0.0:
|
|
1682
|
+
_log.info(
|
|
1683
|
+
f"Distribution of {liquid_class.name} specified with a volume of 0uL."
|
|
1684
|
+
f" Skipping."
|
|
1592
1685
|
)
|
|
1686
|
+
return self
|
|
1687
|
+
|
|
1688
|
+
transfer_args = verify_and_normalize_transfer_args(
|
|
1689
|
+
source=source,
|
|
1690
|
+
dest=dest,
|
|
1691
|
+
tip_policy=new_tip,
|
|
1692
|
+
last_tip_picked_up_from=self._last_tip_picked_up_from,
|
|
1693
|
+
tip_racks=self._tip_racks,
|
|
1694
|
+
nozzle_map=self._core.get_nozzle_map(),
|
|
1695
|
+
target_all_wells=visit_every_well,
|
|
1696
|
+
current_volume=self.current_volume,
|
|
1697
|
+
trash_location=(
|
|
1698
|
+
trash_location if trash_location is not None else self.trash_container
|
|
1699
|
+
),
|
|
1593
1700
|
)
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1701
|
+
if len(transfer_args.sources_list) != 1:
|
|
1702
|
+
raise ValueError(
|
|
1703
|
+
f"Source should be a single well (or resolve to a single transfer for multi-channel) "
|
|
1704
|
+
f"but received {transfer_args.sources_list}."
|
|
1705
|
+
)
|
|
1706
|
+
if transfer_args.tip_policy not in [
|
|
1707
|
+
TransferTipPolicyV2.ONCE,
|
|
1708
|
+
TransferTipPolicyV2.NEVER,
|
|
1709
|
+
]:
|
|
1710
|
+
raise ValueError(
|
|
1711
|
+
f"Incompatible `new_tip` value of {new_tip}."
|
|
1712
|
+
f" `distribute_with_liquid_class()` only supports `new_tip` values of"
|
|
1713
|
+
f" 'once' and 'never'."
|
|
1714
|
+
)
|
|
1715
|
+
|
|
1716
|
+
verified_source = transfer_args.sources_list[0]
|
|
1717
|
+
with publisher.publish_context(
|
|
1718
|
+
broker=self.broker,
|
|
1719
|
+
command=cmds.distribute_with_liquid_class(
|
|
1720
|
+
instrument=self,
|
|
1721
|
+
liquid_class=liquid_class,
|
|
1722
|
+
volume=volume,
|
|
1723
|
+
source=source,
|
|
1724
|
+
destination=dest,
|
|
1725
|
+
),
|
|
1726
|
+
):
|
|
1727
|
+
self._core.distribute_with_liquid_class(
|
|
1728
|
+
liquid_class=liquid_class,
|
|
1729
|
+
volume=volume,
|
|
1730
|
+
source=(
|
|
1731
|
+
types.Location(types.Point(), labware=verified_source),
|
|
1732
|
+
verified_source._core,
|
|
1733
|
+
),
|
|
1734
|
+
dest=[
|
|
1735
|
+
(types.Location(types.Point(), labware=well), well._core)
|
|
1736
|
+
for well in transfer_args.destinations_list
|
|
1737
|
+
],
|
|
1738
|
+
new_tip=transfer_args.tip_policy, # type: ignore[arg-type]
|
|
1739
|
+
tip_racks=[
|
|
1740
|
+
(types.Location(types.Point(), labware=rack), rack._core)
|
|
1741
|
+
for rack in transfer_args.tip_racks
|
|
1742
|
+
],
|
|
1743
|
+
starting_tip=(
|
|
1744
|
+
self.starting_tip._core if self.starting_tip is not None else None
|
|
1745
|
+
),
|
|
1746
|
+
trash_location=transfer_args.trash_location,
|
|
1747
|
+
return_tip=return_tip,
|
|
1748
|
+
)
|
|
1749
|
+
return self
|
|
1750
|
+
|
|
1751
|
+
@requires_version(2, 23)
|
|
1752
|
+
def consolidate_with_liquid_class(
|
|
1753
|
+
self,
|
|
1754
|
+
liquid_class: LiquidClass,
|
|
1755
|
+
volume: float,
|
|
1756
|
+
source: Union[
|
|
1757
|
+
labware.Well, Sequence[labware.Well], Sequence[Sequence[labware.Well]]
|
|
1758
|
+
],
|
|
1759
|
+
dest: Union[labware.Well, Sequence[labware.Well]],
|
|
1760
|
+
new_tip: TransferTipPolicyV2Type = "once",
|
|
1761
|
+
trash_location: Optional[
|
|
1762
|
+
Union[types.Location, labware.Well, TrashBin, WasteChute]
|
|
1763
|
+
] = None,
|
|
1764
|
+
return_tip: bool = False,
|
|
1765
|
+
visit_every_well: bool = False,
|
|
1766
|
+
) -> InstrumentContext:
|
|
1767
|
+
"""
|
|
1768
|
+
Consolidate a particular type of liquid from a group of wells to one well.
|
|
1769
|
+
|
|
1770
|
+
..
|
|
1771
|
+
This is intended for Opentrons internal use only and is not a guaranteed API.
|
|
1772
|
+
|
|
1773
|
+
:param liquid_class: The type of liquid to move. You must specify the liquid class,
|
|
1774
|
+
even if you have used :py:meth:`.Labware.load_liquid` to indicate what liquid the
|
|
1775
|
+
source contains.
|
|
1776
|
+
:type liquid_class: :py:class:`.LiquidClass`
|
|
1777
|
+
|
|
1778
|
+
:param volume: The amount, in µL, to aspirate from the source and dispense to
|
|
1779
|
+
each destination.
|
|
1780
|
+
:param source: A list of wells to aspirate liquid from.
|
|
1781
|
+
:param dest: A single well to dispense liquid into.
|
|
1782
|
+
:param new_tip: When to pick up and drop tips during the command.
|
|
1783
|
+
Defaults to ``"once"``.
|
|
1784
|
+
|
|
1785
|
+
- ``"once"``: Use one tip for the entire command.
|
|
1786
|
+
- ``"never"``: Do not pick up or drop tips at all.
|
|
1787
|
+
|
|
1788
|
+
See :ref:`param-tip-handling` for details.
|
|
1789
|
+
|
|
1790
|
+
:param trash_location: A trash container, well, or other location to dispose of
|
|
1791
|
+
tips. Depending on the liquid class, the pipette may also blow out liquid here.
|
|
1792
|
+
:param return_tip: Whether to drop used tips in their original locations
|
|
1793
|
+
in the tip rack, instead of the trash.
|
|
1794
|
+
|
|
1795
|
+
:meta private:
|
|
1796
|
+
"""
|
|
1797
|
+
if volume == 0.0:
|
|
1798
|
+
_log.info(
|
|
1799
|
+
f"Consolidation of {liquid_class.name} specified with a volume of 0uL."
|
|
1800
|
+
f" Skipping."
|
|
1801
|
+
)
|
|
1802
|
+
return self
|
|
1599
1803
|
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1804
|
+
transfer_args = verify_and_normalize_transfer_args(
|
|
1805
|
+
source=source,
|
|
1806
|
+
dest=dest,
|
|
1807
|
+
tip_policy=new_tip,
|
|
1808
|
+
last_tip_picked_up_from=self._last_tip_picked_up_from,
|
|
1809
|
+
tip_racks=self._tip_racks,
|
|
1810
|
+
nozzle_map=self._core.get_nozzle_map(),
|
|
1811
|
+
target_all_wells=visit_every_well,
|
|
1812
|
+
current_volume=self.current_volume,
|
|
1606
1813
|
trash_location=(
|
|
1607
|
-
|
|
1608
|
-
if isinstance(checked_trash_location, labware.Well)
|
|
1609
|
-
else checked_trash_location
|
|
1814
|
+
trash_location if trash_location is not None else self.trash_container
|
|
1610
1815
|
),
|
|
1611
1816
|
)
|
|
1817
|
+
if len(transfer_args.destinations_list) != 1:
|
|
1818
|
+
raise ValueError(
|
|
1819
|
+
f"Destination should be a single well (or resolve to a single transfer for multi-channel) "
|
|
1820
|
+
f"but received {transfer_args.destinations_list}."
|
|
1821
|
+
)
|
|
1822
|
+
if transfer_args.tip_policy not in [
|
|
1823
|
+
TransferTipPolicyV2.ONCE,
|
|
1824
|
+
TransferTipPolicyV2.NEVER,
|
|
1825
|
+
]:
|
|
1826
|
+
raise ValueError(
|
|
1827
|
+
f"Incompatible `new_tip` value of {new_tip}."
|
|
1828
|
+
f" `consolidate_with_liquid_class()` only supports `new_tip` values of"
|
|
1829
|
+
f" 'once' and 'never'."
|
|
1830
|
+
)
|
|
1612
1831
|
|
|
1832
|
+
verified_dest = transfer_args.destinations_list[0]
|
|
1833
|
+
with publisher.publish_context(
|
|
1834
|
+
broker=self.broker,
|
|
1835
|
+
command=cmds.consolidate_with_liquid_class(
|
|
1836
|
+
instrument=self,
|
|
1837
|
+
liquid_class=liquid_class,
|
|
1838
|
+
volume=volume,
|
|
1839
|
+
source=source,
|
|
1840
|
+
destination=dest,
|
|
1841
|
+
),
|
|
1842
|
+
):
|
|
1843
|
+
self._core.consolidate_with_liquid_class(
|
|
1844
|
+
liquid_class=liquid_class,
|
|
1845
|
+
volume=volume,
|
|
1846
|
+
source=[
|
|
1847
|
+
(types.Location(types.Point(), labware=well), well._core)
|
|
1848
|
+
for well in transfer_args.sources_list
|
|
1849
|
+
],
|
|
1850
|
+
dest=(
|
|
1851
|
+
types.Location(types.Point(), labware=verified_dest),
|
|
1852
|
+
verified_dest._core,
|
|
1853
|
+
),
|
|
1854
|
+
new_tip=transfer_args.tip_policy, # type: ignore[arg-type]
|
|
1855
|
+
tip_racks=[
|
|
1856
|
+
(types.Location(types.Point(), labware=rack), rack._core)
|
|
1857
|
+
for rack in transfer_args.tip_racks
|
|
1858
|
+
],
|
|
1859
|
+
starting_tip=(
|
|
1860
|
+
self.starting_tip._core if self.starting_tip is not None else None
|
|
1861
|
+
),
|
|
1862
|
+
trash_location=transfer_args.trash_location,
|
|
1863
|
+
return_tip=return_tip,
|
|
1864
|
+
)
|
|
1613
1865
|
return self
|
|
1614
1866
|
|
|
1615
1867
|
@requires_version(2, 0)
|
|
@@ -1690,6 +1942,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1690
1942
|
force_direct=force_direct,
|
|
1691
1943
|
minimum_z_height=minimum_z_height,
|
|
1692
1944
|
speed=speed,
|
|
1945
|
+
check_for_movement_conflicts=False,
|
|
1693
1946
|
)
|
|
1694
1947
|
else:
|
|
1695
1948
|
if publish:
|
|
@@ -1708,23 +1961,24 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1708
1961
|
force_direct=force_direct,
|
|
1709
1962
|
minimum_z_height=minimum_z_height,
|
|
1710
1963
|
speed=speed,
|
|
1964
|
+
check_for_movement_conflicts=False,
|
|
1711
1965
|
)
|
|
1712
1966
|
|
|
1713
1967
|
return self
|
|
1714
1968
|
|
|
1715
|
-
@requires_version(2,
|
|
1969
|
+
@requires_version(2, 23)
|
|
1716
1970
|
def resin_tip_seal(
|
|
1717
1971
|
self,
|
|
1718
1972
|
location: Union[labware.Well, labware.Labware],
|
|
1719
1973
|
) -> InstrumentContext:
|
|
1720
1974
|
"""Seal resin tips onto the pipette.
|
|
1721
1975
|
|
|
1722
|
-
The location provided should contain resin tips.
|
|
1723
|
-
|
|
1724
|
-
|
|
1976
|
+
The location provided should contain resin tips. The pipette will attach itself
|
|
1977
|
+
to the resin tips but does not check any tip presence sensors. Before the pipette
|
|
1978
|
+
seals to the tips, the plunger will rise to the top of its working range so that
|
|
1979
|
+
it can perform a :py:func:`resin_tip_dispense` immediately.
|
|
1725
1980
|
|
|
1726
1981
|
:param location: A location containing resin tips, must be a Labware or a Well.
|
|
1727
|
-
|
|
1728
1982
|
:type location: :py:class:`~.types.Location`
|
|
1729
1983
|
"""
|
|
1730
1984
|
if isinstance(location, labware.Labware):
|
|
@@ -1744,7 +1998,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1744
1998
|
)
|
|
1745
1999
|
return self
|
|
1746
2000
|
|
|
1747
|
-
@requires_version(2,
|
|
2001
|
+
@requires_version(2, 23)
|
|
1748
2002
|
def resin_tip_unseal(
|
|
1749
2003
|
self,
|
|
1750
2004
|
location: Union[labware.Well, labware.Labware],
|
|
@@ -1778,35 +2032,64 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1778
2032
|
location=well,
|
|
1779
2033
|
),
|
|
1780
2034
|
):
|
|
1781
|
-
self._core.resin_tip_unseal(location=
|
|
2035
|
+
self._core.resin_tip_unseal(location=None, well_core=well._core)
|
|
1782
2036
|
|
|
1783
2037
|
return self
|
|
1784
2038
|
|
|
1785
|
-
@requires_version(2,
|
|
2039
|
+
@requires_version(2, 23)
|
|
1786
2040
|
def resin_tip_dispense(
|
|
1787
2041
|
self,
|
|
1788
2042
|
location: types.Location,
|
|
1789
2043
|
volume: Optional[float] = None,
|
|
1790
2044
|
rate: Optional[float] = None,
|
|
1791
2045
|
) -> InstrumentContext:
|
|
1792
|
-
"""
|
|
2046
|
+
"""Push liquid out of resin tips that are currently sealed to a pipette.
|
|
2047
|
+
|
|
2048
|
+
The volume and rate parameters for this function control the motion of the plunger
|
|
2049
|
+
to create a desired pressure profile inside the pipette chamber. Unlike a regular
|
|
2050
|
+
dispense action, the volume and rate do not correspond to liquid volume or flow rate
|
|
2051
|
+
dispensed from the resin tips. Select your values for volume and flow rate based on
|
|
2052
|
+
experimentation with the resin tips to create a pressure profile.
|
|
2053
|
+
|
|
2054
|
+
The common way to use this function is as follows:
|
|
2055
|
+
|
|
2056
|
+
#. Seal resin tips to the pipette using :py:meth:`InstrumentContext.resin_tip_seal`.
|
|
2057
|
+
|
|
2058
|
+
#. Use :py:meth:`InstrumentContext.resin_tip_dispense` to displace an experimentally
|
|
2059
|
+
derived volume at an experimentally derived rate to create an experimentally derived
|
|
2060
|
+
target pressure inside the pipette.
|
|
2061
|
+
|
|
2062
|
+
#. Use :py:meth:`ProtocolContext.delay` to wait an experimentally derived amount of
|
|
2063
|
+
time for the pressure inside the pipette to push liquid into and through the resin tip
|
|
2064
|
+
and out the other side.
|
|
2065
|
+
|
|
2066
|
+
#. As liquid passes through the resin tip, the pressure inside the pipette will
|
|
2067
|
+
fall. If not all liquid has been dispensed from the resin tip, repeat steps 2
|
|
2068
|
+
and 3.
|
|
1793
2069
|
|
|
1794
|
-
|
|
1795
|
-
receptical for dispensed liquid. Dispensing from tip will perform a
|
|
1796
|
-
`dispense` action of the specified volume at a desired flow rate.
|
|
2070
|
+
#. Unseal resin tips from the pipette using :py:meth:`InstrumentContext.resin_tip_unseal`.
|
|
1797
2071
|
|
|
1798
|
-
|
|
2072
|
+
Flex pipette pressure sensors will raise an overpressure when a differential pressure
|
|
2073
|
+
inside the pipette chamber above sensor limits is detected. You may need to disable the
|
|
2074
|
+
pressure sensor to create the required pressure profile.
|
|
2075
|
+
|
|
2076
|
+
.. warning::
|
|
2077
|
+
Building excessive pressure inside the pipette chamber (significantly above the sensor
|
|
2078
|
+
limit) with the pressure sensors disabled can damage the pipette.
|
|
2079
|
+
|
|
2080
|
+
|
|
2081
|
+
:param location: Tells the robot where to dispense.
|
|
1799
2082
|
:type location: :py:class:`~.types.Location`
|
|
1800
2083
|
|
|
1801
|
-
:param volume:
|
|
1802
|
-
|
|
2084
|
+
:param volume: The volume that the plunger should displace, in µL. Does not directly relate
|
|
2085
|
+
to the volume of liquid that will be dispensed.
|
|
1803
2086
|
:type volume: float
|
|
1804
2087
|
|
|
1805
|
-
:param rate:
|
|
1806
|
-
|
|
1807
|
-
``rate`` multiplied by :py:attr:`flow_rate.dispense<flow_rate>`.
|
|
1808
|
-
:type rate: float
|
|
2088
|
+
:param rate: How quickly the plunger moves to displace the commanded volume, in µL/s. This rate does not directly relate to
|
|
2089
|
+
the flow rate of liquid out of the resin tip.
|
|
1809
2090
|
|
|
2091
|
+
Defaults to ``10.0`` µL/s.
|
|
2092
|
+
:type rate: float
|
|
1810
2093
|
"""
|
|
1811
2094
|
well: Optional[labware.Well] = None
|
|
1812
2095
|
last_location = self._get_last_location_by_api_version()
|
|
@@ -1998,7 +2281,15 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1998
2281
|
@requires_version(2, 0)
|
|
1999
2282
|
def name(self) -> str:
|
|
2000
2283
|
"""
|
|
2001
|
-
The name string for the pipette
|
|
2284
|
+
The name string for the pipette.
|
|
2285
|
+
|
|
2286
|
+
From API version 2.15 to 2.22, this property returned an internal name for Flex
|
|
2287
|
+
pipettes. (e.g., ``"p1000_single_flex"``).
|
|
2288
|
+
|
|
2289
|
+
.. TODO uncomment when 2.23 is ready
|
|
2290
|
+
In API version 2.23 and later, this property returns the Python Protocol API
|
|
2291
|
+
:ref:`load name <new-pipette-models>` of Flex pipettes (e.g.,
|
|
2292
|
+
``"flex_1channel_1000"``).
|
|
2002
2293
|
"""
|
|
2003
2294
|
return self._core.get_pipette_name()
|
|
2004
2295
|
|
|
@@ -2411,19 +2702,15 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2411
2702
|
self._core.liquid_probe_with_recovery(well._core, loc)
|
|
2412
2703
|
|
|
2413
2704
|
@requires_version(2, 20)
|
|
2414
|
-
def measure_liquid_height(self, well: labware.Well) ->
|
|
2705
|
+
def measure_liquid_height(self, well: labware.Well) -> LiquidTrackingType:
|
|
2415
2706
|
"""Check the height of the liquid within a well.
|
|
2416
2707
|
|
|
2417
|
-
:returns: The height, in mm, of the liquid from the
|
|
2418
|
-
|
|
2419
|
-
:meta private:
|
|
2420
|
-
|
|
2421
|
-
This is intended for Opentrons internal use only and is not a guaranteed API.
|
|
2708
|
+
:returns: The height, in mm, of the liquid from the bottom of the well.
|
|
2422
2709
|
"""
|
|
2423
2710
|
self._raise_if_pressure_not_supported_by_pipette()
|
|
2424
2711
|
loc = well.top()
|
|
2425
|
-
|
|
2426
|
-
return
|
|
2712
|
+
self._core.liquid_probe_with_recovery(well._core, loc)
|
|
2713
|
+
return well.current_liquid_height()
|
|
2427
2714
|
|
|
2428
2715
|
def _raise_if_configuration_not_supported_by_pipette(
|
|
2429
2716
|
self, style: NozzleLayout
|
|
@@ -2448,24 +2735,41 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2448
2735
|
)
|
|
2449
2736
|
|
|
2450
2737
|
def _handle_aspirate_target(
|
|
2451
|
-
self, target: validation.
|
|
2452
|
-
) -> tuple[
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
is_meniscus: Optional[bool] = None
|
|
2738
|
+
self, target: Union[validation.WellTarget, validation.PointTarget]
|
|
2739
|
+
) -> tuple[
|
|
2740
|
+
types.Location, Optional[labware.Well], Optional[types.MeniscusTrackingTarget]
|
|
2741
|
+
]:
|
|
2456
2742
|
if isinstance(target, validation.WellTarget):
|
|
2457
|
-
well = target.well
|
|
2458
2743
|
if target.location:
|
|
2459
|
-
|
|
2460
|
-
is_meniscus = target.location.is_meniscus
|
|
2744
|
+
return target.location, target.well, target.location.meniscus_tracking
|
|
2461
2745
|
|
|
2462
2746
|
else:
|
|
2463
|
-
|
|
2464
|
-
z=self._well_bottom_clearances.aspirate
|
|
2747
|
+
return (
|
|
2748
|
+
target.well.bottom(z=self._well_bottom_clearances.aspirate),
|
|
2749
|
+
target.well,
|
|
2750
|
+
None,
|
|
2465
2751
|
)
|
|
2466
2752
|
if isinstance(target, validation.PointTarget):
|
|
2467
|
-
|
|
2468
|
-
|
|
2753
|
+
return target.location, None, None
|
|
2754
|
+
|
|
2755
|
+
def _handle_dispense_target(
|
|
2756
|
+
self, target: Union[validation.WellTarget, validation.PointTarget]
|
|
2757
|
+
) -> tuple[
|
|
2758
|
+
types.Location, Optional[labware.Well], Optional[types.MeniscusTrackingTarget]
|
|
2759
|
+
]:
|
|
2760
|
+
if isinstance(target, validation.WellTarget):
|
|
2761
|
+
if target.location:
|
|
2762
|
+
return target.location, target.well, target.location.meniscus_tracking
|
|
2763
|
+
elif target.well.parent._core.is_fixed_trash():
|
|
2764
|
+
return target.well.top(), target.well, None
|
|
2765
|
+
else:
|
|
2766
|
+
return (
|
|
2767
|
+
target.well.bottom(z=self._well_bottom_clearances.dispense),
|
|
2768
|
+
target.well,
|
|
2769
|
+
None,
|
|
2770
|
+
)
|
|
2771
|
+
if isinstance(target, validation.PointTarget):
|
|
2772
|
+
return target.location, None, None
|
|
2469
2773
|
|
|
2470
2774
|
|
|
2471
2775
|
class AutoProbeDisable:
|