opentrons 8.7.0a9__py3-none-any.whl → 8.8.0a8__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/_version.py +2 -2
- opentrons/cli/analyze.py +4 -1
- opentrons/config/__init__.py +7 -0
- opentrons/drivers/asyncio/communication/serial_connection.py +126 -49
- opentrons/drivers/heater_shaker/abstract.py +5 -0
- opentrons/drivers/heater_shaker/driver.py +10 -0
- opentrons/drivers/heater_shaker/simulator.py +4 -0
- opentrons/drivers/thermocycler/abstract.py +6 -0
- opentrons/drivers/thermocycler/driver.py +61 -10
- opentrons/drivers/thermocycler/simulator.py +6 -0
- opentrons/drivers/vacuum_module/__init__.py +5 -0
- opentrons/drivers/vacuum_module/abstract.py +93 -0
- opentrons/drivers/vacuum_module/driver.py +208 -0
- opentrons/drivers/vacuum_module/errors.py +39 -0
- opentrons/drivers/vacuum_module/simulator.py +85 -0
- opentrons/drivers/vacuum_module/types.py +79 -0
- opentrons/execute.py +3 -0
- opentrons/hardware_control/api.py +24 -5
- opentrons/hardware_control/backends/controller.py +8 -2
- opentrons/hardware_control/backends/flex_protocol.py +1 -0
- opentrons/hardware_control/backends/ot3controller.py +35 -2
- opentrons/hardware_control/backends/ot3simulator.py +3 -1
- opentrons/hardware_control/backends/ot3utils.py +37 -0
- opentrons/hardware_control/backends/simulator.py +2 -1
- opentrons/hardware_control/backends/subsystem_manager.py +5 -2
- opentrons/hardware_control/emulation/abstract_emulator.py +6 -4
- opentrons/hardware_control/emulation/connection_handler.py +8 -5
- opentrons/hardware_control/emulation/heater_shaker.py +12 -3
- opentrons/hardware_control/emulation/settings.py +1 -1
- opentrons/hardware_control/emulation/thermocycler.py +67 -15
- opentrons/hardware_control/module_control.py +105 -10
- opentrons/hardware_control/modules/__init__.py +3 -0
- opentrons/hardware_control/modules/absorbance_reader.py +11 -4
- opentrons/hardware_control/modules/flex_stacker.py +38 -9
- opentrons/hardware_control/modules/heater_shaker.py +42 -5
- opentrons/hardware_control/modules/magdeck.py +8 -4
- opentrons/hardware_control/modules/mod_abc.py +14 -6
- opentrons/hardware_control/modules/tempdeck.py +25 -5
- opentrons/hardware_control/modules/thermocycler.py +68 -11
- opentrons/hardware_control/modules/types.py +20 -1
- opentrons/hardware_control/modules/utils.py +11 -4
- opentrons/hardware_control/motion_utilities.py +6 -6
- opentrons/hardware_control/nozzle_manager.py +3 -0
- opentrons/hardware_control/ot3api.py +92 -17
- opentrons/hardware_control/poller.py +22 -8
- opentrons/hardware_control/protocols/liquid_handler.py +12 -4
- opentrons/hardware_control/scripts/update_module_fw.py +5 -0
- opentrons/hardware_control/types.py +43 -2
- opentrons/legacy_commands/commands.py +58 -5
- opentrons/legacy_commands/module_commands.py +52 -0
- opentrons/legacy_commands/protocol_commands.py +53 -1
- opentrons/legacy_commands/types.py +155 -1
- opentrons/motion_planning/deck_conflict.py +17 -12
- opentrons/motion_planning/waypoints.py +15 -29
- opentrons/protocol_api/__init__.py +5 -1
- opentrons/protocol_api/_transfer_liquid_validation.py +17 -2
- opentrons/protocol_api/_types.py +8 -1
- opentrons/protocol_api/core/common.py +3 -1
- opentrons/protocol_api/core/engine/_default_labware_versions.py +33 -11
- opentrons/protocol_api/core/engine/deck_conflict.py +3 -1
- opentrons/protocol_api/core/engine/instrument.py +109 -26
- opentrons/protocol_api/core/engine/labware.py +8 -1
- opentrons/protocol_api/core/engine/module_core.py +95 -4
- opentrons/protocol_api/core/engine/pipette_movement_conflict.py +4 -18
- opentrons/protocol_api/core/engine/protocol.py +51 -2
- opentrons/protocol_api/core/engine/stringify.py +2 -0
- opentrons/protocol_api/core/engine/tasks.py +48 -0
- opentrons/protocol_api/core/engine/well.py +8 -0
- opentrons/protocol_api/core/instrument.py +19 -2
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +19 -2
- opentrons/protocol_api/core/legacy/legacy_module_core.py +33 -2
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +23 -1
- opentrons/protocol_api/core/legacy/legacy_well_core.py +4 -0
- opentrons/protocol_api/core/legacy/tasks.py +19 -0
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +19 -2
- opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py +14 -2
- opentrons/protocol_api/core/legacy_simulator/tasks.py +19 -0
- opentrons/protocol_api/core/module.py +58 -2
- opentrons/protocol_api/core/protocol.py +23 -2
- opentrons/protocol_api/core/tasks.py +31 -0
- opentrons/protocol_api/core/well.py +4 -0
- opentrons/protocol_api/instrument_context.py +388 -2
- opentrons/protocol_api/labware.py +10 -2
- opentrons/protocol_api/module_contexts.py +170 -6
- opentrons/protocol_api/protocol_context.py +87 -21
- opentrons/protocol_api/robot_context.py +41 -25
- opentrons/protocol_api/tasks.py +48 -0
- opentrons/protocol_api/validation.py +49 -3
- opentrons/protocol_engine/__init__.py +4 -0
- opentrons/protocol_engine/actions/__init__.py +6 -2
- opentrons/protocol_engine/actions/actions.py +31 -9
- opentrons/protocol_engine/clients/sync_client.py +42 -7
- opentrons/protocol_engine/commands/__init__.py +56 -0
- opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +2 -15
- opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +2 -15
- opentrons/protocol_engine/commands/absorbance_reader/read.py +22 -23
- opentrons/protocol_engine/commands/aspirate.py +1 -0
- opentrons/protocol_engine/commands/aspirate_while_tracking.py +52 -19
- opentrons/protocol_engine/commands/capture_image.py +302 -0
- opentrons/protocol_engine/commands/command.py +2 -0
- opentrons/protocol_engine/commands/command_unions.py +62 -0
- opentrons/protocol_engine/commands/create_timer.py +83 -0
- opentrons/protocol_engine/commands/dispense.py +1 -0
- opentrons/protocol_engine/commands/dispense_while_tracking.py +56 -19
- opentrons/protocol_engine/commands/drop_tip.py +32 -8
- opentrons/protocol_engine/commands/flex_stacker/common.py +35 -0
- opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +7 -0
- opentrons/protocol_engine/commands/heater_shaker/__init__.py +14 -0
- opentrons/protocol_engine/commands/heater_shaker/common.py +20 -0
- opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +5 -4
- opentrons/protocol_engine/commands/heater_shaker/set_shake_speed.py +136 -0
- opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +31 -5
- opentrons/protocol_engine/commands/move_labware.py +3 -4
- opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +1 -1
- opentrons/protocol_engine/commands/movement_common.py +31 -2
- opentrons/protocol_engine/commands/pick_up_tip.py +21 -11
- opentrons/protocol_engine/commands/pipetting_common.py +48 -3
- opentrons/protocol_engine/commands/set_tip_state.py +97 -0
- opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +38 -7
- opentrons/protocol_engine/commands/thermocycler/__init__.py +16 -0
- opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +6 -0
- opentrons/protocol_engine/commands/thermocycler/run_profile.py +8 -0
- opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +44 -7
- opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +43 -14
- opentrons/protocol_engine/commands/thermocycler/start_run_extended_profile.py +191 -0
- opentrons/protocol_engine/commands/touch_tip.py +1 -1
- opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +6 -22
- opentrons/protocol_engine/commands/wait_for_tasks.py +98 -0
- opentrons/protocol_engine/create_protocol_engine.py +12 -0
- opentrons/protocol_engine/engine_support.py +3 -0
- opentrons/protocol_engine/errors/__init__.py +12 -0
- opentrons/protocol_engine/errors/exceptions.py +119 -0
- opentrons/protocol_engine/execution/__init__.py +4 -0
- opentrons/protocol_engine/execution/command_executor.py +62 -1
- opentrons/protocol_engine/execution/create_queue_worker.py +9 -2
- opentrons/protocol_engine/execution/labware_movement.py +13 -15
- opentrons/protocol_engine/execution/movement.py +2 -0
- opentrons/protocol_engine/execution/pipetting.py +26 -25
- opentrons/protocol_engine/execution/queue_worker.py +4 -0
- opentrons/protocol_engine/execution/run_control.py +8 -0
- opentrons/protocol_engine/execution/task_handler.py +157 -0
- opentrons/protocol_engine/protocol_engine.py +137 -36
- opentrons/protocol_engine/resources/__init__.py +4 -0
- opentrons/protocol_engine/resources/camera_provider.py +110 -0
- opentrons/protocol_engine/resources/concurrency_provider.py +27 -0
- opentrons/protocol_engine/resources/deck_configuration_provider.py +7 -0
- opentrons/protocol_engine/resources/file_provider.py +133 -58
- opentrons/protocol_engine/resources/labware_validation.py +10 -6
- opentrons/protocol_engine/slot_standardization.py +2 -0
- opentrons/protocol_engine/state/_well_math.py +60 -18
- opentrons/protocol_engine/state/addressable_areas.py +2 -0
- opentrons/protocol_engine/state/camera.py +54 -0
- opentrons/protocol_engine/state/commands.py +37 -14
- opentrons/protocol_engine/state/geometry.py +276 -379
- opentrons/protocol_engine/state/labware.py +62 -108
- opentrons/protocol_engine/state/labware_origin_math/errors.py +94 -0
- opentrons/protocol_engine/state/labware_origin_math/stackup_origin_to_labware_origin.py +1336 -0
- opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +37 -0
- opentrons/protocol_engine/state/modules.py +30 -8
- opentrons/protocol_engine/state/motion.py +60 -18
- opentrons/protocol_engine/state/preconditions.py +59 -0
- opentrons/protocol_engine/state/state.py +44 -0
- opentrons/protocol_engine/state/state_summary.py +4 -0
- opentrons/protocol_engine/state/tasks.py +139 -0
- opentrons/protocol_engine/state/tips.py +177 -258
- opentrons/protocol_engine/state/update_types.py +26 -9
- opentrons/protocol_engine/types/__init__.py +23 -4
- opentrons/protocol_engine/types/command_preconditions.py +18 -0
- opentrons/protocol_engine/types/deck_configuration.py +5 -1
- opentrons/protocol_engine/types/instrument.py +8 -1
- opentrons/protocol_engine/types/labware.py +1 -13
- opentrons/protocol_engine/types/location.py +26 -2
- opentrons/protocol_engine/types/module.py +11 -1
- opentrons/protocol_engine/types/tasks.py +38 -0
- opentrons/protocol_engine/types/tip.py +9 -0
- opentrons/protocol_runner/create_simulating_orchestrator.py +29 -2
- opentrons/protocol_runner/protocol_runner.py +14 -1
- opentrons/protocol_runner/run_orchestrator.py +49 -2
- opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +2 -2
- opentrons/protocols/api_support/definitions.py +1 -1
- opentrons/protocols/api_support/types.py +2 -1
- opentrons/simulate.py +51 -15
- opentrons/system/camera.py +334 -4
- opentrons/system/ffmpeg.py +110 -0
- {opentrons-8.7.0a9.dist-info → opentrons-8.8.0a8.dist-info}/METADATA +4 -4
- {opentrons-8.7.0a9.dist-info → opentrons-8.8.0a8.dist-info}/RECORD +189 -161
- opentrons/protocol_engine/state/_labware_origin_math.py +0 -636
- {opentrons-8.7.0a9.dist-info → opentrons-8.8.0a8.dist-info}/WHEEL +0 -0
- {opentrons-8.7.0a9.dist-info → opentrons-8.8.0a8.dist-info}/entry_points.txt +0 -0
- {opentrons-8.7.0a9.dist-info → opentrons-8.8.0a8.dist-info}/licenses/LICENSE +0 -0
|
@@ -74,6 +74,8 @@ _AIR_GAP_TRACKING_ADDED_IN = APIVersion(2, 22)
|
|
|
74
74
|
"""The version after which air gaps should be implemented with a separate call instead of an aspirate for better liquid volume tracking."""
|
|
75
75
|
_LIQUID_CLASS_TRANSFER_TIP_RACKS_ARG_ADDED_IN = APIVersion(2, 25)
|
|
76
76
|
"""The version after which the user can supply liquid class transfers with non-assigned tip racks."""
|
|
77
|
+
_LIQUID_CLASS_TRANSFER_TIPS_ARG_ADDED_IN = APIVersion(2, 27)
|
|
78
|
+
"""The version after which the user can supply liquid class transfers with selected tips."""
|
|
77
79
|
|
|
78
80
|
|
|
79
81
|
AdvancedLiquidHandling = v1_transfer.AdvancedLiquidHandling
|
|
@@ -199,6 +201,8 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
199
201
|
location: Optional[Union[types.Location, labware.Well]] = None,
|
|
200
202
|
rate: float = 1.0,
|
|
201
203
|
flow_rate: Optional[float] = None,
|
|
204
|
+
end_location: Optional[types.Location] = None,
|
|
205
|
+
movement_delay: Optional[float] = None,
|
|
202
206
|
) -> InstrumentContext:
|
|
203
207
|
"""
|
|
204
208
|
Draw liquid into a pipette tip.
|
|
@@ -238,6 +242,16 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
238
242
|
:param flow_rate: The absolute flow rate in µL/s. If ``flow_rate`` is specified,
|
|
239
243
|
``rate`` must not be set.
|
|
240
244
|
:type flow_rate: float
|
|
245
|
+
:param end_location: Tells the robot to move between location and end_location
|
|
246
|
+
while aspirating liquid. When this argument is used the location and
|
|
247
|
+
end_location must both be :py:class:`.Location`.
|
|
248
|
+
:type end_location: :py:class:`.Location`
|
|
249
|
+
:param movement_delay: Delay the x/y/z movement during a dynamic aspirate.
|
|
250
|
+
This option is only valid when using end_location. When this argument
|
|
251
|
+
is used, the x/y/z movement will wait movement_delay seconds after the pipette
|
|
252
|
+
starts to aspirate before moving. This may help when dispensing very viscous liquids
|
|
253
|
+
that need to build up some pressure before liquid starts to flow.
|
|
254
|
+
:type movement_delay: float
|
|
241
255
|
:returns: This instance.
|
|
242
256
|
|
|
243
257
|
.. note::
|
|
@@ -291,6 +305,50 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
291
305
|
move_to_location, well, meniscus_tracking = self._handle_aspirate_target(
|
|
292
306
|
target=target
|
|
293
307
|
)
|
|
308
|
+
if (
|
|
309
|
+
meniscus_tracking is not None
|
|
310
|
+
and meniscus_tracking == types.MeniscusTrackingTarget.DYNAMIC
|
|
311
|
+
):
|
|
312
|
+
# we're using the old dynamic pipetting
|
|
313
|
+
if end_location is not None:
|
|
314
|
+
raise ValueError(
|
|
315
|
+
"Dynamic target is depreciated and you cannot use a dynamic target and and end location."
|
|
316
|
+
)
|
|
317
|
+
# re-work the dynamic location as a start and end location
|
|
318
|
+
new_start_location = types.Location(
|
|
319
|
+
point=move_to_location.point,
|
|
320
|
+
labware=move_to_location.labware,
|
|
321
|
+
_meniscus_tracking=types.MeniscusTrackingTarget.START,
|
|
322
|
+
)
|
|
323
|
+
target = validation.validate_location(
|
|
324
|
+
location=new_start_location, last_location=last_location
|
|
325
|
+
)
|
|
326
|
+
# Target already checked for this above, this is just for lint
|
|
327
|
+
assert not isinstance(target, validation.DisposalTarget)
|
|
328
|
+
move_to_location, well, meniscus_tracking = self._handle_aspirate_target(
|
|
329
|
+
target=target
|
|
330
|
+
)
|
|
331
|
+
end_location = types.Location(
|
|
332
|
+
point=move_to_location.point,
|
|
333
|
+
labware=move_to_location.labware,
|
|
334
|
+
_meniscus_tracking=types.MeniscusTrackingTarget.END,
|
|
335
|
+
)
|
|
336
|
+
end_move_to_location: Optional[types.Location] = None
|
|
337
|
+
end_meniscus_tracking: Optional[types.MeniscusTrackingTarget] = None
|
|
338
|
+
if end_location is not None:
|
|
339
|
+
validation.validate_dynamic_locations(location, end_location)
|
|
340
|
+
end_target = validation.validate_location(
|
|
341
|
+
location=end_location, last_location=None
|
|
342
|
+
)
|
|
343
|
+
if isinstance(end_target, validation.DisposalTarget):
|
|
344
|
+
raise ValueError(
|
|
345
|
+
"Trash Bin and Waste Chute are not acceptable location parameters for Aspirate commands."
|
|
346
|
+
)
|
|
347
|
+
(
|
|
348
|
+
end_move_to_location,
|
|
349
|
+
end_well,
|
|
350
|
+
end_meniscus_tracking,
|
|
351
|
+
) = self._handle_aspirate_target(target=end_target)
|
|
294
352
|
if self.api_version >= APIVersion(2, 11):
|
|
295
353
|
instrument.validate_takes_liquid(
|
|
296
354
|
location=move_to_location,
|
|
@@ -322,6 +380,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
322
380
|
location=move_to_location,
|
|
323
381
|
flow_rate=flow_rate,
|
|
324
382
|
rate=rate,
|
|
383
|
+
end_location=end_move_to_location,
|
|
325
384
|
),
|
|
326
385
|
):
|
|
327
386
|
self._core.aspirate(
|
|
@@ -330,8 +389,11 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
330
389
|
volume=c_vol,
|
|
331
390
|
rate=rate,
|
|
332
391
|
flow_rate=flow_rate,
|
|
333
|
-
in_place=target.in_place,
|
|
392
|
+
in_place=target.in_place and end_move_to_location is None,
|
|
334
393
|
meniscus_tracking=meniscus_tracking,
|
|
394
|
+
end_location=end_move_to_location,
|
|
395
|
+
end_meniscus_tracking=end_meniscus_tracking,
|
|
396
|
+
movement_delay=movement_delay,
|
|
335
397
|
)
|
|
336
398
|
|
|
337
399
|
return self
|
|
@@ -346,6 +408,8 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
346
408
|
rate: float = 1.0,
|
|
347
409
|
push_out: Optional[float] = None,
|
|
348
410
|
flow_rate: Optional[float] = None,
|
|
411
|
+
end_location: Optional[types.Location] = None,
|
|
412
|
+
movement_delay: Optional[float] = None,
|
|
349
413
|
) -> InstrumentContext:
|
|
350
414
|
"""
|
|
351
415
|
Dispense liquid from a pipette tip.
|
|
@@ -415,6 +479,16 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
415
479
|
``rate`` must not be set.
|
|
416
480
|
:type flow_rate: float
|
|
417
481
|
|
|
482
|
+
:param end_location: Tells the robot to move between location and end_location
|
|
483
|
+
while dispensing liquid held in the pipette. When this argument is used
|
|
484
|
+
the location and end_location must both be a :py:class:`.Location`.
|
|
485
|
+
:type end_location: :py:class:`.Location`
|
|
486
|
+
:param movement_delay: Delay the x/y/z movement during a dynamic dispense.
|
|
487
|
+
This option is only valid when using end_location. When this argument
|
|
488
|
+
is used, the x/y/z movement will wait movement_delay seconds after the pipette
|
|
489
|
+
starts to dispense before moving. This may help when dispensing very viscous liquids
|
|
490
|
+
that need to build up some pressure before liquid starts to flow.
|
|
491
|
+
:type movement_delay: float
|
|
418
492
|
:returns: This instance.
|
|
419
493
|
|
|
420
494
|
.. note::
|
|
@@ -501,12 +575,59 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
501
575
|
in_place=target.in_place,
|
|
502
576
|
push_out=push_out,
|
|
503
577
|
meniscus_tracking=None,
|
|
578
|
+
end_location=None,
|
|
579
|
+
end_meniscus_tracking=None,
|
|
580
|
+
movement_delay=None,
|
|
504
581
|
)
|
|
505
582
|
return self
|
|
506
583
|
|
|
507
584
|
move_to_location, well, meniscus_tracking = self._handle_dispense_target(
|
|
508
585
|
target=target
|
|
509
586
|
)
|
|
587
|
+
if (
|
|
588
|
+
meniscus_tracking is not None
|
|
589
|
+
and meniscus_tracking == types.MeniscusTrackingTarget.DYNAMIC
|
|
590
|
+
):
|
|
591
|
+
# we're using the old dynamic pipetting
|
|
592
|
+
if end_location is not None:
|
|
593
|
+
raise ValueError(
|
|
594
|
+
"Dynamic target is depreciated and you cannot use a dynamic target and and end location."
|
|
595
|
+
)
|
|
596
|
+
# re-work the dynamic location as a start and end location
|
|
597
|
+
new_start_location = types.Location(
|
|
598
|
+
point=move_to_location.point,
|
|
599
|
+
labware=move_to_location.labware,
|
|
600
|
+
_meniscus_tracking=types.MeniscusTrackingTarget.START,
|
|
601
|
+
)
|
|
602
|
+
target = validation.validate_location(
|
|
603
|
+
location=new_start_location, last_location=last_location
|
|
604
|
+
)
|
|
605
|
+
# Target already checked for this above, this is just for lint
|
|
606
|
+
assert not isinstance(target, validation.DisposalTarget)
|
|
607
|
+
move_to_location, well, meniscus_tracking = self._handle_dispense_target(
|
|
608
|
+
target=target
|
|
609
|
+
)
|
|
610
|
+
end_location = types.Location(
|
|
611
|
+
point=move_to_location.point,
|
|
612
|
+
labware=move_to_location.labware,
|
|
613
|
+
_meniscus_tracking=types.MeniscusTrackingTarget.END,
|
|
614
|
+
)
|
|
615
|
+
end_move_to_location: Optional[types.Location] = None
|
|
616
|
+
end_meniscus_tracking: Optional[types.MeniscusTrackingTarget] = None
|
|
617
|
+
if end_location is not None:
|
|
618
|
+
validation.validate_dynamic_locations(location, end_location)
|
|
619
|
+
end_target = validation.validate_location(
|
|
620
|
+
location=end_location, last_location=None
|
|
621
|
+
)
|
|
622
|
+
if isinstance(end_target, validation.DisposalTarget):
|
|
623
|
+
raise ValueError(
|
|
624
|
+
"Trash Bin and Waste Chute are not acceptable location parameters for dynamic pipetting commands."
|
|
625
|
+
)
|
|
626
|
+
(
|
|
627
|
+
end_move_to_location,
|
|
628
|
+
end_well,
|
|
629
|
+
end_meniscus_tracking,
|
|
630
|
+
) = self._handle_dispense_target(target=end_target)
|
|
510
631
|
|
|
511
632
|
if self.api_version >= APIVersion(2, 11):
|
|
512
633
|
instrument.validate_takes_liquid(
|
|
@@ -523,6 +644,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
523
644
|
location=move_to_location,
|
|
524
645
|
rate=rate,
|
|
525
646
|
flow_rate=flow_rate,
|
|
647
|
+
end_location=end_move_to_location,
|
|
526
648
|
),
|
|
527
649
|
):
|
|
528
650
|
self._core.dispense(
|
|
@@ -531,9 +653,12 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
531
653
|
location=move_to_location,
|
|
532
654
|
well_core=well._core if well is not None else None,
|
|
533
655
|
flow_rate=flow_rate,
|
|
534
|
-
in_place=target.in_place,
|
|
656
|
+
in_place=target.in_place and end_move_to_location is None,
|
|
535
657
|
push_out=push_out,
|
|
536
658
|
meniscus_tracking=meniscus_tracking,
|
|
659
|
+
end_location=end_move_to_location,
|
|
660
|
+
end_meniscus_tracking=end_meniscus_tracking,
|
|
661
|
+
movement_delay=movement_delay,
|
|
537
662
|
)
|
|
538
663
|
|
|
539
664
|
return self
|
|
@@ -704,6 +829,204 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
704
829
|
dispense_with_delay(push_out=None)
|
|
705
830
|
return self
|
|
706
831
|
|
|
832
|
+
@requires_version(2, 27)
|
|
833
|
+
def dynamic_mix( # noqa: C901
|
|
834
|
+
self,
|
|
835
|
+
aspirate_start_location: types.Location,
|
|
836
|
+
dispense_start_location: types.Location,
|
|
837
|
+
repetitions: int = 1,
|
|
838
|
+
volume: Optional[float] = None,
|
|
839
|
+
aspirate_end_location: Optional[types.Location] = None,
|
|
840
|
+
dispense_end_location: Optional[types.Location] = None,
|
|
841
|
+
rate: float = 1.0,
|
|
842
|
+
aspirate_flow_rate: Optional[float] = None,
|
|
843
|
+
dispense_flow_rate: Optional[float] = None,
|
|
844
|
+
aspirate_delay: Optional[float] = None,
|
|
845
|
+
dispense_delay: Optional[float] = None,
|
|
846
|
+
final_push_out: Optional[float] = None,
|
|
847
|
+
movement_delay: Optional[float] = None,
|
|
848
|
+
) -> InstrumentContext:
|
|
849
|
+
"""
|
|
850
|
+
Mix a volume of liquid by repeatedly aspirating and dispensing it in a multiple locations.
|
|
851
|
+
|
|
852
|
+
See :ref:`dynamic_mix` for examples.
|
|
853
|
+
|
|
854
|
+
:param repetitions: Number of times to mix (default is 1).
|
|
855
|
+
:param volume: The volume to mix, measured in µL. If unspecified, defaults
|
|
856
|
+
to the maximum volume for the pipette and its attached tip.
|
|
857
|
+
|
|
858
|
+
If ``mix`` is called with a volume of precisely 0, its behavior
|
|
859
|
+
depends on the API level of the protocol. On API levels below 2.16,
|
|
860
|
+
it will behave the same as a volume of ``None``/unspecified: mix
|
|
861
|
+
the full working volume of the pipette. On API levels at or above 2.16,
|
|
862
|
+
no liquid will be mixed.
|
|
863
|
+
:param aspirate_start_location: The :py:class:`~.types.Location` where the pipette will aspirate from.
|
|
864
|
+
:param aspirate_end_location: The :py:class:`~.types.Location` If this argument is supplied
|
|
865
|
+
the pipette will move between aspirate_start_location and aspirate_end_location
|
|
866
|
+
while performing the aspirate.
|
|
867
|
+
:param dispense_start_location: The :py:class:`~.types.Location` where the pipette will dispense to.
|
|
868
|
+
:param dispense_end_location: The :py:class:`~.types.Location` If this argument is supplied
|
|
869
|
+
the pipette will move between dispense_start_location and dispense_end_location
|
|
870
|
+
while performing the dispense.
|
|
871
|
+
:param rate: How quickly the pipette aspirates and dispenses liquid while
|
|
872
|
+
mixing. The aspiration flow rate is calculated as ``rate``
|
|
873
|
+
multiplied by :py:attr:`flow_rate.aspirate <flow_rate>`. The
|
|
874
|
+
dispensing flow rate is calculated as ``rate`` multiplied by
|
|
875
|
+
:py:attr:`flow_rate.dispense <flow_rate>`. See
|
|
876
|
+
:ref:`new-plunger-flow-rates`.
|
|
877
|
+
:param aspirate_flow_rate: The absolute flow rate for each aspirate in the mix, in µL/s.
|
|
878
|
+
If this is specified, ``rate`` must not be set.
|
|
879
|
+
:param dispense_flow_rate: The absolute flow rate for each dispense in the mix, in µL/s.
|
|
880
|
+
If this is specified, ``rate`` must not be set.
|
|
881
|
+
:param aspirate_delay: How long to wait after each aspirate in the mix, in seconds.
|
|
882
|
+
:param dispense_delay: How long to wait after each dispense in the mix, in seconds.
|
|
883
|
+
:param final_push_out: How much volume to push out after the final mix repetition. The
|
|
884
|
+
pipette will not push out after earlier repetitions. If
|
|
885
|
+
not specified or ``None``, the pipette will push out the
|
|
886
|
+
default non-zero amount. See :ref:`push-out-dispense`.
|
|
887
|
+
:param movement_delay: Delay the x/y/z movement during a dynamic mix.
|
|
888
|
+
This option is only valid when using aspirate_end_location or dispense_end_location.
|
|
889
|
+
When this argument is used, the x/y/z movement will wait movement_delay seconds
|
|
890
|
+
after the pipette starts to aspirate/dispense before moving. This may help when mixing
|
|
891
|
+
very viscous liquids that need to build up some pressure before liquid starts to flow.
|
|
892
|
+
:type movement_delay: float
|
|
893
|
+
:raises: ``UnexpectedTipRemovalError`` -- If no tip is attached to the pipette.
|
|
894
|
+
:returns: This instance.
|
|
895
|
+
|
|
896
|
+
.. note::
|
|
897
|
+
|
|
898
|
+
All the arguments of ``mix`` are optional. However, if you omit one of them,
|
|
899
|
+
all subsequent arguments must be passed as keyword arguments. For instance,
|
|
900
|
+
``pipette.mix(1, location=wellplate['A1'])`` is a valid call, but
|
|
901
|
+
``pipette.mix(1, wellplate['A1'])`` is not.
|
|
902
|
+
|
|
903
|
+
"""
|
|
904
|
+
_log.debug(
|
|
905
|
+
"mixing {}uL with {} repetitions in {} and {} at rate={}".format(
|
|
906
|
+
volume,
|
|
907
|
+
repetitions,
|
|
908
|
+
aspirate_start_location,
|
|
909
|
+
dispense_start_location,
|
|
910
|
+
rate,
|
|
911
|
+
)
|
|
912
|
+
)
|
|
913
|
+
# Verify all locations are within the same well
|
|
914
|
+
if not aspirate_start_location.labware.is_well:
|
|
915
|
+
raise ValueError(
|
|
916
|
+
"Dynamic mix aspirate start location must be within a well"
|
|
917
|
+
)
|
|
918
|
+
if not dispense_start_location.labware.is_well:
|
|
919
|
+
raise ValueError(
|
|
920
|
+
"Dynamic mix dispense start location must be within a well"
|
|
921
|
+
)
|
|
922
|
+
|
|
923
|
+
if (
|
|
924
|
+
aspirate_end_location is not None
|
|
925
|
+
and not aspirate_end_location.labware.is_well
|
|
926
|
+
):
|
|
927
|
+
raise ValueError("Dynamic mix aspirate end location must be within a well")
|
|
928
|
+
if (
|
|
929
|
+
dispense_end_location is not None
|
|
930
|
+
and not dispense_end_location.labware.is_well
|
|
931
|
+
):
|
|
932
|
+
raise ValueError("Dynamic mix dispense end location must be within a well")
|
|
933
|
+
|
|
934
|
+
(
|
|
935
|
+
_,
|
|
936
|
+
asp_start_well,
|
|
937
|
+
) = aspirate_start_location.labware.get_parent_labware_and_well()
|
|
938
|
+
(
|
|
939
|
+
_,
|
|
940
|
+
disp_start_well,
|
|
941
|
+
) = dispense_start_location.labware.get_parent_labware_and_well()
|
|
942
|
+
|
|
943
|
+
if asp_start_well != disp_start_well:
|
|
944
|
+
raise ValueError(
|
|
945
|
+
"Aspirate and Dispense locations must be within the same well"
|
|
946
|
+
)
|
|
947
|
+
|
|
948
|
+
if not self._core.has_tip():
|
|
949
|
+
raise UnexpectedTipRemovalError("mix", self.name, self.mount)
|
|
950
|
+
|
|
951
|
+
c_vol = self._core.get_available_volume() if volume is None else volume
|
|
952
|
+
|
|
953
|
+
if aspirate_flow_rate:
|
|
954
|
+
if rate != 1.0:
|
|
955
|
+
raise ValueError(
|
|
956
|
+
"rate must not be set if aspirate_flow_rate is specified"
|
|
957
|
+
)
|
|
958
|
+
if dispense_flow_rate:
|
|
959
|
+
if rate != 1.0:
|
|
960
|
+
raise ValueError(
|
|
961
|
+
"rate must not be set if dispense_flow_rate is specified"
|
|
962
|
+
)
|
|
963
|
+
|
|
964
|
+
def delay_with_publish(seconds: float) -> None:
|
|
965
|
+
# We don't have access to ProtocolContext.delay() which would automatically
|
|
966
|
+
# publish a message to the broker, so we have to do it manually:
|
|
967
|
+
with publisher.publish_context(
|
|
968
|
+
broker=self.broker,
|
|
969
|
+
command=protocol_cmds.delay(seconds=seconds, minutes=0, msg=None),
|
|
970
|
+
):
|
|
971
|
+
self._protocol_core.delay(seconds=seconds, msg=None)
|
|
972
|
+
|
|
973
|
+
def aspirate_with_delay() -> None:
|
|
974
|
+
self.aspirate(
|
|
975
|
+
volume,
|
|
976
|
+
aspirate_start_location,
|
|
977
|
+
rate,
|
|
978
|
+
flow_rate=aspirate_flow_rate,
|
|
979
|
+
end_location=aspirate_end_location,
|
|
980
|
+
movement_delay=movement_delay,
|
|
981
|
+
)
|
|
982
|
+
if aspirate_delay:
|
|
983
|
+
delay_with_publish(aspirate_delay)
|
|
984
|
+
|
|
985
|
+
def dispense_with_delay(push_out: Optional[float]) -> None:
|
|
986
|
+
self.dispense(
|
|
987
|
+
volume=volume,
|
|
988
|
+
location=dispense_start_location,
|
|
989
|
+
rate=rate,
|
|
990
|
+
flow_rate=dispense_flow_rate,
|
|
991
|
+
push_out=push_out,
|
|
992
|
+
end_location=dispense_end_location,
|
|
993
|
+
movement_delay=movement_delay,
|
|
994
|
+
)
|
|
995
|
+
if dispense_delay:
|
|
996
|
+
delay_with_publish(dispense_delay)
|
|
997
|
+
|
|
998
|
+
with publisher.publish_context(
|
|
999
|
+
broker=self.broker,
|
|
1000
|
+
command=cmds.dynamic_mix(
|
|
1001
|
+
instrument=self,
|
|
1002
|
+
repetitions=repetitions,
|
|
1003
|
+
volume=c_vol,
|
|
1004
|
+
aspirate_start_location=aspirate_start_location,
|
|
1005
|
+
aspirate_end_location=aspirate_end_location,
|
|
1006
|
+
dispense_start_location=dispense_start_location,
|
|
1007
|
+
dispense_end_location=dispense_end_location,
|
|
1008
|
+
movement_delay=movement_delay or 0.0,
|
|
1009
|
+
),
|
|
1010
|
+
):
|
|
1011
|
+
aspirate_with_delay()
|
|
1012
|
+
with AutoProbeDisable(self):
|
|
1013
|
+
while repetitions - 1 > 0:
|
|
1014
|
+
# starting in 2.16, we disable push_out on all but the last
|
|
1015
|
+
# dispense() to prevent the tip from jumping out of the liquid
|
|
1016
|
+
# during the mix (PR #14004):
|
|
1017
|
+
self.move_to(dispense_start_location, force_direct=True)
|
|
1018
|
+
dispense_with_delay(push_out=0.0)
|
|
1019
|
+
self.move_to(aspirate_start_location, force_direct=True)
|
|
1020
|
+
aspirate_with_delay()
|
|
1021
|
+
repetitions -= 1
|
|
1022
|
+
|
|
1023
|
+
self.move_to(dispense_start_location, force_direct=True)
|
|
1024
|
+
if final_push_out is not None:
|
|
1025
|
+
dispense_with_delay(push_out=final_push_out)
|
|
1026
|
+
else:
|
|
1027
|
+
dispense_with_delay(push_out=None)
|
|
1028
|
+
return self
|
|
1029
|
+
|
|
707
1030
|
@requires_version(2, 0)
|
|
708
1031
|
def blow_out(
|
|
709
1032
|
self,
|
|
@@ -1799,6 +2122,9 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1799
2122
|
group_wells: bool = True,
|
|
1800
2123
|
keep_last_tip: Optional[bool] = None,
|
|
1801
2124
|
tip_racks: Optional[List[labware.Labware]] = None,
|
|
2125
|
+
tips: Optional[
|
|
2126
|
+
Union[Sequence[labware.Well], Sequence[Sequence[labware.Well]]]
|
|
2127
|
+
] = None,
|
|
1802
2128
|
) -> InstrumentContext:
|
|
1803
2129
|
"""Move a particular type of liquid from one well or group of wells to another.
|
|
1804
2130
|
|
|
@@ -1838,9 +2164,14 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1838
2164
|
:param tip_racks: A list of tip racks to pick up from for this command. If not provided, the pipette will pick
|
|
1839
2165
|
up from its associated :py:obj:`.InstrumentContext.tip_racks`. Providing this argument does not change the
|
|
1840
2166
|
value of ``InstrumentContext.tip_racks``.
|
|
2167
|
+
:param tips: An ordered list of tips to use for the transfer. If the list contains fewer tips than needed to
|
|
2168
|
+
complete the transfer, the API will raise an error. The pipette will use only these tips even if
|
|
2169
|
+
``InstrumentContext.tip_racks`` or the ``tip_racks`` parameter of this method is set.
|
|
1841
2170
|
|
|
1842
2171
|
.. versionchanged:: 2.25
|
|
1843
2172
|
Added the ``tip_racks`` parameter.
|
|
2173
|
+
.. versionchanged:: 2.27
|
|
2174
|
+
Added the ``tips`` parameter.
|
|
1844
2175
|
|
|
1845
2176
|
"""
|
|
1846
2177
|
if volume == 0.0:
|
|
@@ -1859,6 +2190,15 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1859
2190
|
until_version=f"{_LIQUID_CLASS_TRANSFER_TIP_RACKS_ARG_ADDED_IN}",
|
|
1860
2191
|
current_version=f"{self.api_version}",
|
|
1861
2192
|
)
|
|
2193
|
+
if (
|
|
2194
|
+
tips is not None
|
|
2195
|
+
and self.api_version < _LIQUID_CLASS_TRANSFER_TIPS_ARG_ADDED_IN
|
|
2196
|
+
):
|
|
2197
|
+
raise APIVersionError(
|
|
2198
|
+
api_element="tips",
|
|
2199
|
+
until_version=f"{_LIQUID_CLASS_TRANSFER_TIPS_ARG_ADDED_IN}",
|
|
2200
|
+
current_version=f"{self.api_version}",
|
|
2201
|
+
)
|
|
1862
2202
|
|
|
1863
2203
|
transfer_args = verify_and_normalize_transfer_args(
|
|
1864
2204
|
source=source,
|
|
@@ -1872,6 +2212,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1872
2212
|
trash_location=(
|
|
1873
2213
|
trash_location if trash_location is not None else self.trash_container
|
|
1874
2214
|
),
|
|
2215
|
+
tips=tips,
|
|
1875
2216
|
)
|
|
1876
2217
|
verified_keep_last_tip = resolve_keep_last_tip(
|
|
1877
2218
|
keep_last_tip, transfer_args.tip_policy
|
|
@@ -1926,6 +2267,9 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1926
2267
|
trash_location=transfer_args.trash_location,
|
|
1927
2268
|
return_tip=return_tip,
|
|
1928
2269
|
keep_last_tip=verified_keep_last_tip,
|
|
2270
|
+
tips=[tip._core for tip in transfer_args.tips]
|
|
2271
|
+
if transfer_args.tips is not None
|
|
2272
|
+
else None,
|
|
1929
2273
|
)
|
|
1930
2274
|
|
|
1931
2275
|
return self
|
|
@@ -1947,6 +2291,9 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1947
2291
|
group_wells: bool = True,
|
|
1948
2292
|
keep_last_tip: Optional[bool] = None,
|
|
1949
2293
|
tip_racks: Optional[List[labware.Labware]] = None,
|
|
2294
|
+
tips: Optional[
|
|
2295
|
+
Union[Sequence[labware.Well], Sequence[Sequence[labware.Well]]]
|
|
2296
|
+
] = None,
|
|
1950
2297
|
) -> InstrumentContext:
|
|
1951
2298
|
"""
|
|
1952
2299
|
Distribute a particular type of liquid from one well to a group of wells.
|
|
@@ -1983,9 +2330,14 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
1983
2330
|
:param tip_racks: A list of tip racks to pick up from for this command. If not provided, the pipette will pick
|
|
1984
2331
|
up from its associated :py:obj:`.InstrumentContext.tip_racks`. Providing this argument does not change the
|
|
1985
2332
|
value of ``InstrumentContext.tip_racks``.
|
|
2333
|
+
:param tips: An ordered list of tips to use for the transfer. If the list contains fewer tips than needed to
|
|
2334
|
+
complete the transfer, the API will raise an error. The pipette will use only these tips even if
|
|
2335
|
+
``InstrumentContext.tip_racks`` or the ``tip_racks`` parameter of this method is set.
|
|
1986
2336
|
|
|
1987
2337
|
.. versionchanged:: 2.25
|
|
1988
2338
|
Added the ``tip_racks`` parameter.
|
|
2339
|
+
.. versionchanged:: 2.27
|
|
2340
|
+
Added the ``tips`` parameter.
|
|
1989
2341
|
|
|
1990
2342
|
"""
|
|
1991
2343
|
if volume == 0.0:
|
|
@@ -2004,6 +2356,15 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2004
2356
|
until_version=f"{_LIQUID_CLASS_TRANSFER_TIP_RACKS_ARG_ADDED_IN}",
|
|
2005
2357
|
current_version=f"{self.api_version}",
|
|
2006
2358
|
)
|
|
2359
|
+
if (
|
|
2360
|
+
tips is not None
|
|
2361
|
+
and self.api_version < _LIQUID_CLASS_TRANSFER_TIPS_ARG_ADDED_IN
|
|
2362
|
+
):
|
|
2363
|
+
raise APIVersionError(
|
|
2364
|
+
api_element="tips",
|
|
2365
|
+
until_version=f"{_LIQUID_CLASS_TRANSFER_TIPS_ARG_ADDED_IN}",
|
|
2366
|
+
current_version=f"{self.api_version}",
|
|
2367
|
+
)
|
|
2007
2368
|
|
|
2008
2369
|
transfer_args = verify_and_normalize_transfer_args(
|
|
2009
2370
|
source=source,
|
|
@@ -2017,6 +2378,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2017
2378
|
trash_location=(
|
|
2018
2379
|
trash_location if trash_location is not None else self.trash_container
|
|
2019
2380
|
),
|
|
2381
|
+
tips=tips,
|
|
2020
2382
|
)
|
|
2021
2383
|
verified_keep_last_tip = resolve_keep_last_tip(
|
|
2022
2384
|
keep_last_tip, transfer_args.tip_policy
|
|
@@ -2079,6 +2441,9 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2079
2441
|
trash_location=transfer_args.trash_location,
|
|
2080
2442
|
return_tip=return_tip,
|
|
2081
2443
|
keep_last_tip=verified_keep_last_tip,
|
|
2444
|
+
tips=[tip._core for tip in transfer_args.tips]
|
|
2445
|
+
if transfer_args.tips is not None
|
|
2446
|
+
else None,
|
|
2082
2447
|
)
|
|
2083
2448
|
|
|
2084
2449
|
return self
|
|
@@ -2100,6 +2465,9 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2100
2465
|
group_wells: bool = True,
|
|
2101
2466
|
keep_last_tip: Optional[bool] = None,
|
|
2102
2467
|
tip_racks: Optional[List[labware.Labware]] = None,
|
|
2468
|
+
tips: Optional[
|
|
2469
|
+
Union[Sequence[labware.Well], Sequence[Sequence[labware.Well]]]
|
|
2470
|
+
] = None,
|
|
2103
2471
|
) -> InstrumentContext:
|
|
2104
2472
|
"""
|
|
2105
2473
|
Consolidate a particular type of liquid from a group of wells to one well.
|
|
@@ -2137,9 +2505,14 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2137
2505
|
:param tip_racks: A list of tip racks to pick up from for this command. If not provided, the pipette will pick
|
|
2138
2506
|
up from its associated :py:obj:`.InstrumentContext.tip_racks`. Providing this argument does not change the
|
|
2139
2507
|
value of ``InstrumentContext.tip_racks``.
|
|
2508
|
+
:param tips: An ordered list of tips to use for the transfer. If the list contains fewer tips than needed to
|
|
2509
|
+
complete the transfer, the API will raise an error. The pipette will use only these tips even if
|
|
2510
|
+
``InstrumentContext.tip_racks`` or the ``tip_racks`` parameter of this method is set.
|
|
2140
2511
|
|
|
2141
2512
|
.. versionchanged:: 2.25
|
|
2142
2513
|
Added the ``tip_racks`` parameter.
|
|
2514
|
+
.. versionchanged:: 2.27
|
|
2515
|
+
Added the ``tips`` parameter.
|
|
2143
2516
|
|
|
2144
2517
|
"""
|
|
2145
2518
|
if volume == 0.0:
|
|
@@ -2158,6 +2531,15 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2158
2531
|
until_version=f"{_LIQUID_CLASS_TRANSFER_TIP_RACKS_ARG_ADDED_IN}",
|
|
2159
2532
|
current_version=f"{self.api_version}",
|
|
2160
2533
|
)
|
|
2534
|
+
if (
|
|
2535
|
+
tips is not None
|
|
2536
|
+
and self.api_version < _LIQUID_CLASS_TRANSFER_TIPS_ARG_ADDED_IN
|
|
2537
|
+
):
|
|
2538
|
+
raise APIVersionError(
|
|
2539
|
+
api_element="tips",
|
|
2540
|
+
until_version=f"{_LIQUID_CLASS_TRANSFER_TIPS_ARG_ADDED_IN}",
|
|
2541
|
+
current_version=f"{self.api_version}",
|
|
2542
|
+
)
|
|
2161
2543
|
|
|
2162
2544
|
transfer_args = verify_and_normalize_transfer_args(
|
|
2163
2545
|
source=source,
|
|
@@ -2171,6 +2553,7 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2171
2553
|
trash_location=(
|
|
2172
2554
|
trash_location if trash_location is not None else self.trash_container
|
|
2173
2555
|
),
|
|
2556
|
+
tips=tips,
|
|
2174
2557
|
)
|
|
2175
2558
|
verified_keep_last_tip = resolve_keep_last_tip(
|
|
2176
2559
|
keep_last_tip, transfer_args.tip_policy
|
|
@@ -2232,6 +2615,9 @@ class InstrumentContext(publisher.CommandPublisher):
|
|
|
2232
2615
|
trash_location=transfer_args.trash_location,
|
|
2233
2616
|
return_tip=return_tip,
|
|
2234
2617
|
keep_last_tip=verified_keep_last_tip,
|
|
2618
|
+
tips=[tip._core for tip in transfer_args.tips]
|
|
2619
|
+
if transfer_args.tips is not None
|
|
2620
|
+
else None,
|
|
2235
2621
|
)
|
|
2236
2622
|
|
|
2237
2623
|
return self
|
|
@@ -347,6 +347,11 @@ class Well:
|
|
|
347
347
|
"""Get the current liquid volume in a well."""
|
|
348
348
|
return self._core.get_liquid_volume()
|
|
349
349
|
|
|
350
|
+
@requires_version(2, 27)
|
|
351
|
+
def has_tracked_liquid(self) -> bool:
|
|
352
|
+
"""Get the current liquid volume in a well."""
|
|
353
|
+
return self._core.has_tracked_liquid()
|
|
354
|
+
|
|
350
355
|
@requires_version(2, 24)
|
|
351
356
|
def volume_from_height(self, height: LiquidTrackingType) -> LiquidTrackingType:
|
|
352
357
|
"""Return the volume contained in a well at any height."""
|
|
@@ -817,8 +822,8 @@ class Labware:
|
|
|
817
822
|
def set_offset(self, x: float, y: float, z: float) -> None:
|
|
818
823
|
"""Set the labware's position offset.
|
|
819
824
|
|
|
820
|
-
|
|
821
|
-
|
|
825
|
+
An offset of `(x=0, y=0, z=0)` means the labware's uncalibrated position before
|
|
826
|
+
any offset from Labware Position Check is applied.
|
|
822
827
|
|
|
823
828
|
How the motion system applies the offset depends on the API level of the protocol.
|
|
824
829
|
|
|
@@ -877,6 +882,9 @@ class Labware:
|
|
|
877
882
|
def calibrated_offset(self) -> Point:
|
|
878
883
|
"""The front-left-bottom corner of the labware, including its labware offset.
|
|
879
884
|
|
|
885
|
+
The offset is an x, y, z vector in deck coordinates
|
|
886
|
+
(see :ref:`protocol-api-deck-coords`).
|
|
887
|
+
|
|
880
888
|
When running a protocol in the Opentrons App or on the touchscreen, Labware
|
|
881
889
|
Position Check sets the labware offset.
|
|
882
890
|
"""
|