opentrons 8.5.0a4__py2.py3-none-any.whl → 8.5.0a7__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/protocol_api/_transfer_liquid_validation.py +31 -6
- opentrons/protocol_api/core/engine/instrument.py +191 -148
- opentrons/protocol_api/core/engine/transfer_components_executor.py +114 -40
- opentrons/protocol_api/core/instrument.py +9 -3
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +9 -3
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +9 -3
- opentrons/protocol_api/instrument_context.py +84 -16
- opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +37 -27
- {opentrons-8.5.0a4.dist-info → opentrons-8.5.0a7.dist-info}/METADATA +4 -4
- {opentrons-8.5.0a4.dist-info → opentrons-8.5.0a7.dist-info}/RECORD +14 -14
- {opentrons-8.5.0a4.dist-info → opentrons-8.5.0a7.dist-info}/LICENSE +0 -0
- {opentrons-8.5.0a4.dist-info → opentrons-8.5.0a7.dist-info}/WHEEL +0 -0
- {opentrons-8.5.0a4.dist-info → opentrons-8.5.0a7.dist-info}/entry_points.txt +0 -0
- {opentrons-8.5.0a4.dist-info → opentrons-8.5.0a7.dist-info}/top_level.txt +0 -0
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"""ProtocolEngine-based InstrumentContext core implementation."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
|
-
from contextlib import contextmanager
|
|
5
4
|
from itertools import dropwhile
|
|
6
5
|
from copy import deepcopy
|
|
7
6
|
from typing import (
|
|
@@ -13,7 +12,6 @@ from typing import (
|
|
|
13
12
|
Sequence,
|
|
14
13
|
Tuple,
|
|
15
14
|
NamedTuple,
|
|
16
|
-
Generator,
|
|
17
15
|
Literal,
|
|
18
16
|
)
|
|
19
17
|
from opentrons.types import (
|
|
@@ -1205,7 +1203,9 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1205
1203
|
starting_tip: Optional[WellCore],
|
|
1206
1204
|
trash_location: Union[Location, TrashBin, WasteChute],
|
|
1207
1205
|
return_tip: bool,
|
|
1208
|
-
|
|
1206
|
+
keep_last_tip: bool,
|
|
1207
|
+
last_tip_location: Optional[Tuple[Location, WellCore]],
|
|
1208
|
+
) -> Optional[Tuple[Location, WellCore]]:
|
|
1209
1209
|
"""Execute transfer using liquid class properties.
|
|
1210
1210
|
|
|
1211
1211
|
Args:
|
|
@@ -1219,8 +1219,18 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1219
1219
|
types.Location is only necessary for saving the last accessed location.
|
|
1220
1220
|
new_tip: Whether the transfer should use a new tip 'once', 'never', 'always',
|
|
1221
1221
|
or 'per source'.
|
|
1222
|
-
|
|
1223
|
-
|
|
1222
|
+
tip_racks: List of tipracks that the transfer will pick up tips from, represented
|
|
1223
|
+
as tuples of types.Location and WellCore.
|
|
1224
|
+
starting_tip: The user-chosen starting tip to use when deciding what tip to pick
|
|
1225
|
+
up, if the user has set it.
|
|
1226
|
+
trash_location: The chosen trash container to drop tips in and dispose liquid in.
|
|
1227
|
+
return_tip: If `True`, return tips to the tip rack location they were picked up from,
|
|
1228
|
+
otherwise drop in `trash_location`
|
|
1229
|
+
keep_last_tip: When set to `True`, do not drop the final tip used in the transfer.
|
|
1230
|
+
last_tip_location: If a tip is already attached, this will be the tiprack and well it was
|
|
1231
|
+
picked up from, represented as a tuple of types.Location and WellCore.
|
|
1232
|
+
Used so a tip can be returned if it was picked up outside this function
|
|
1233
|
+
as could be the case for a new_tip of `never`.
|
|
1224
1234
|
"""
|
|
1225
1235
|
if not tip_racks:
|
|
1226
1236
|
raise RuntimeError(
|
|
@@ -1272,14 +1282,15 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1272
1282
|
)
|
|
1273
1283
|
)
|
|
1274
1284
|
|
|
1275
|
-
|
|
1285
|
+
last_tip = last_tip_location
|
|
1276
1286
|
|
|
1277
1287
|
def _drop_tip() -> None:
|
|
1278
1288
|
if return_tip:
|
|
1279
|
-
assert
|
|
1289
|
+
assert last_tip is not None
|
|
1290
|
+
_, tip_well = last_tip
|
|
1280
1291
|
self.drop_tip(
|
|
1281
1292
|
location=None,
|
|
1282
|
-
well_core=
|
|
1293
|
+
well_core=tip_well,
|
|
1283
1294
|
home_after=False,
|
|
1284
1295
|
alternate_drop_location=False,
|
|
1285
1296
|
)
|
|
@@ -1297,7 +1308,7 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1297
1308
|
alternate_drop_location=True,
|
|
1298
1309
|
)
|
|
1299
1310
|
|
|
1300
|
-
def _pick_up_tip() -> WellCore:
|
|
1311
|
+
def _pick_up_tip() -> Tuple[Location, WellCore]:
|
|
1301
1312
|
next_tip = self.get_next_tip(
|
|
1302
1313
|
tip_racks=[core for loc, core in tip_racks],
|
|
1303
1314
|
starting_well=starting_tip,
|
|
@@ -1323,10 +1334,10 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1323
1334
|
presses=None,
|
|
1324
1335
|
increment=None,
|
|
1325
1336
|
)
|
|
1326
|
-
return tip_well
|
|
1337
|
+
return tiprack_loc, tip_well
|
|
1327
1338
|
|
|
1328
1339
|
if new_tip == TransferTipPolicyV2.ONCE:
|
|
1329
|
-
|
|
1340
|
+
last_tip = _pick_up_tip()
|
|
1330
1341
|
|
|
1331
1342
|
prev_src: Optional[Tuple[Location, WellCore]] = None
|
|
1332
1343
|
prev_dest: Optional[
|
|
@@ -1364,70 +1375,59 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1364
1375
|
):
|
|
1365
1376
|
if prev_src is not None and prev_dest is not None:
|
|
1366
1377
|
_drop_tip()
|
|
1367
|
-
|
|
1378
|
+
last_tip = _pick_up_tip()
|
|
1368
1379
|
post_disp_tip_contents = [
|
|
1369
1380
|
tx_comps_executor.LiquidAndAirGapPair(
|
|
1370
1381
|
liquid=0,
|
|
1371
1382
|
air_gap=0,
|
|
1372
1383
|
)
|
|
1373
1384
|
]
|
|
1374
|
-
# Enable LPD only if all of these apply:
|
|
1375
|
-
# - LPD is globally enabled for this pipette
|
|
1376
|
-
# - it is the first time visiting this well
|
|
1377
|
-
# - pipette tip is unused
|
|
1378
|
-
enable_lpd = (
|
|
1379
|
-
self.get_liquid_presence_detection() and step_source != prev_src
|
|
1380
|
-
)
|
|
1381
|
-
elif new_tip == TransferTipPolicyV2.ONCE:
|
|
1382
|
-
# Enable LPD only if:
|
|
1383
|
-
# - LPD is globally enabled for this pipette
|
|
1384
|
-
# - this is the first source well of the entire transfer, which means
|
|
1385
|
-
# that the current tip is unused
|
|
1386
|
-
enable_lpd = self.get_liquid_presence_detection() and prev_src is None
|
|
1387
|
-
else:
|
|
1388
|
-
enable_lpd = False
|
|
1389
1385
|
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
if is_last_step and new_tip == TransferTipPolicyV2.NEVER
|
|
1409
|
-
else True
|
|
1410
|
-
),
|
|
1411
|
-
trash_location=trash_location,
|
|
1412
|
-
)
|
|
1386
|
+
post_asp_tip_contents = self.aspirate_liquid_class(
|
|
1387
|
+
volume=step_volume,
|
|
1388
|
+
source=step_source,
|
|
1389
|
+
transfer_properties=transfer_props,
|
|
1390
|
+
transfer_type=tx_comps_executor.TransferType.ONE_TO_ONE,
|
|
1391
|
+
tip_contents=post_disp_tip_contents,
|
|
1392
|
+
volume_for_pipette_mode_configuration=step_volume,
|
|
1393
|
+
)
|
|
1394
|
+
post_disp_tip_contents = self.dispense_liquid_class(
|
|
1395
|
+
volume=step_volume,
|
|
1396
|
+
dest=step_destination,
|
|
1397
|
+
source=step_source,
|
|
1398
|
+
transfer_properties=transfer_props,
|
|
1399
|
+
transfer_type=tx_comps_executor.TransferType.ONE_TO_ONE,
|
|
1400
|
+
tip_contents=post_asp_tip_contents,
|
|
1401
|
+
add_final_air_gap=(False if is_last_step and keep_last_tip else True),
|
|
1402
|
+
trash_location=trash_location,
|
|
1403
|
+
)
|
|
1413
1404
|
prev_src = step_source
|
|
1414
1405
|
prev_dest = step_destination
|
|
1415
|
-
|
|
1406
|
+
|
|
1407
|
+
if not keep_last_tip:
|
|
1416
1408
|
_drop_tip()
|
|
1409
|
+
last_tip = None
|
|
1410
|
+
|
|
1411
|
+
return last_tip
|
|
1417
1412
|
|
|
1418
|
-
# TODO(spp, 2025-02-25): wire up return tip
|
|
1419
1413
|
def distribute_with_liquid_class( # noqa: C901
|
|
1420
1414
|
self,
|
|
1421
1415
|
liquid_class: LiquidClass,
|
|
1422
1416
|
volume: float,
|
|
1423
1417
|
source: Tuple[Location, WellCore],
|
|
1424
1418
|
dest: List[Tuple[Location, WellCore]],
|
|
1425
|
-
new_tip: Literal[
|
|
1419
|
+
new_tip: Literal[
|
|
1420
|
+
TransferTipPolicyV2.NEVER,
|
|
1421
|
+
TransferTipPolicyV2.ONCE,
|
|
1422
|
+
TransferTipPolicyV2.ALWAYS,
|
|
1423
|
+
],
|
|
1426
1424
|
tip_racks: List[Tuple[Location, LabwareCore]],
|
|
1427
1425
|
starting_tip: Optional[WellCore],
|
|
1428
1426
|
trash_location: Union[Location, TrashBin, WasteChute],
|
|
1429
1427
|
return_tip: bool,
|
|
1430
|
-
|
|
1428
|
+
keep_last_tip: bool,
|
|
1429
|
+
last_tip_location: Optional[Tuple[Location, WellCore]],
|
|
1430
|
+
) -> Optional[Tuple[Location, WellCore]]:
|
|
1431
1431
|
"""Execute a distribution using liquid class properties.
|
|
1432
1432
|
|
|
1433
1433
|
Args:
|
|
@@ -1438,9 +1438,22 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1438
1438
|
dest: List of destination wells, with each well represented as a tuple of
|
|
1439
1439
|
types.Location and WellCore.
|
|
1440
1440
|
types.Location is only necessary for saving the last accessed location.
|
|
1441
|
-
new_tip: Whether the transfer should use a new tip 'once' or 'never'.
|
|
1442
|
-
|
|
1443
|
-
|
|
1441
|
+
new_tip: Whether the transfer should use a new tip 'once', 'always' or 'never'.
|
|
1442
|
+
'never': the transfer will never pick up a new tip
|
|
1443
|
+
'once': the transfer will pick up a new tip once at the start of transfer
|
|
1444
|
+
'always': the transfer will pick up a new tip before every aspirate
|
|
1445
|
+
tip_racks: List of tipracks that the transfer will pick up tips from, represented
|
|
1446
|
+
as tuples of types.Location and WellCore.
|
|
1447
|
+
starting_tip: The user-chosen starting tip to use when deciding what tip to pick
|
|
1448
|
+
up, if the user has set it.
|
|
1449
|
+
trash_location: The chosen trash container to drop tips in and dispose liquid in.
|
|
1450
|
+
return_tip: If `True`, return tips to the tip rack location they were picked up from,
|
|
1451
|
+
otherwise drop in `trash_location`
|
|
1452
|
+
keep_last_tip: When set to `True`, do not drop the final tip used in the distribute.
|
|
1453
|
+
last_tip_location: If a tip is already attached, this will be the tiprack and well it was
|
|
1454
|
+
picked up from, represented as a tuple of types.Location and WellCore.
|
|
1455
|
+
Used so a tip can be returned if it was picked up outside this function
|
|
1456
|
+
as could be the case for a new_tip of `never`
|
|
1444
1457
|
|
|
1445
1458
|
This method distributes the liquid in the source well into multiple destinations.
|
|
1446
1459
|
It can accomplish this by either doing a multi-dispense (aspirate once and then
|
|
@@ -1448,13 +1461,17 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1448
1461
|
(going back to aspirate after each dispense). Whether it does a multi-dispense or
|
|
1449
1462
|
multiple single dispenses is determined by whether multi-dispense properties
|
|
1450
1463
|
are available in the liquid class and whether the tip in use can hold multiple
|
|
1451
|
-
volumes to be dispensed
|
|
1464
|
+
volumes to be dispensed without having to refill.
|
|
1452
1465
|
"""
|
|
1453
1466
|
if not tip_racks:
|
|
1454
1467
|
raise RuntimeError(
|
|
1455
1468
|
"No tipracks found for pipette in order to perform transfer"
|
|
1456
1469
|
)
|
|
1457
|
-
assert new_tip in [
|
|
1470
|
+
assert new_tip in [
|
|
1471
|
+
TransferTipPolicyV2.NEVER,
|
|
1472
|
+
TransferTipPolicyV2.ONCE,
|
|
1473
|
+
TransferTipPolicyV2.ALWAYS,
|
|
1474
|
+
]
|
|
1458
1475
|
|
|
1459
1476
|
tiprack_uri_for_transfer_props = tip_racks[0][1].get_uri()
|
|
1460
1477
|
working_volume = min(
|
|
@@ -1500,7 +1517,7 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1500
1517
|
tip_working_volume=working_volume,
|
|
1501
1518
|
)
|
|
1502
1519
|
):
|
|
1503
|
-
self.transfer_with_liquid_class(
|
|
1520
|
+
return self.transfer_with_liquid_class(
|
|
1504
1521
|
liquid_class=liquid_class,
|
|
1505
1522
|
volume=volume,
|
|
1506
1523
|
source=[source for _ in range(len(dest))],
|
|
@@ -1510,8 +1527,9 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1510
1527
|
starting_tip=starting_tip,
|
|
1511
1528
|
trash_location=trash_location,
|
|
1512
1529
|
return_tip=return_tip,
|
|
1530
|
+
keep_last_tip=keep_last_tip,
|
|
1531
|
+
last_tip_location=last_tip_location,
|
|
1513
1532
|
)
|
|
1514
|
-
return
|
|
1515
1533
|
|
|
1516
1534
|
# TODO: use the ID returned by load_liquid_class in command annotations
|
|
1517
1535
|
self.load_liquid_class(
|
|
@@ -1538,14 +1556,15 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1538
1556
|
)
|
|
1539
1557
|
)
|
|
1540
1558
|
|
|
1541
|
-
|
|
1559
|
+
last_tip = last_tip_location
|
|
1542
1560
|
|
|
1543
1561
|
def _drop_tip() -> None:
|
|
1544
1562
|
if return_tip:
|
|
1545
|
-
assert
|
|
1563
|
+
assert last_tip is not None
|
|
1564
|
+
_, tip_well = last_tip
|
|
1546
1565
|
self.drop_tip(
|
|
1547
1566
|
location=None,
|
|
1548
|
-
well_core=
|
|
1567
|
+
well_core=tip_well,
|
|
1549
1568
|
home_after=False,
|
|
1550
1569
|
alternate_drop_location=False,
|
|
1551
1570
|
)
|
|
@@ -1563,7 +1582,7 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1563
1582
|
alternate_drop_location=True,
|
|
1564
1583
|
)
|
|
1565
1584
|
|
|
1566
|
-
def _pick_up_tip() -> WellCore:
|
|
1585
|
+
def _pick_up_tip() -> Tuple[Location, WellCore]:
|
|
1567
1586
|
next_tip = self.get_next_tip(
|
|
1568
1587
|
tip_racks=[core for loc, core in tip_racks],
|
|
1569
1588
|
starting_well=starting_tip,
|
|
@@ -1589,10 +1608,10 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1589
1608
|
presses=None,
|
|
1590
1609
|
increment=None,
|
|
1591
1610
|
)
|
|
1592
|
-
return tip_well
|
|
1611
|
+
return tiprack_loc, tip_well
|
|
1593
1612
|
|
|
1594
1613
|
if new_tip != TransferTipPolicyV2.NEVER:
|
|
1595
|
-
|
|
1614
|
+
last_tip = _pick_up_tip()
|
|
1596
1615
|
|
|
1597
1616
|
tip_contents = [
|
|
1598
1617
|
tx_comps_executor.LiquidAndAirGapPair(
|
|
@@ -1656,28 +1675,28 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1656
1675
|
" Specify a blowout location and enable blowout when using a disposal volume."
|
|
1657
1676
|
)
|
|
1658
1677
|
|
|
1659
|
-
if
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1678
|
+
if not is_first_step and new_tip == TransferTipPolicyV2.ALWAYS:
|
|
1679
|
+
_drop_tip()
|
|
1680
|
+
last_tip = _pick_up_tip()
|
|
1681
|
+
tip_contents = [
|
|
1682
|
+
tx_comps_executor.LiquidAndAirGapPair(
|
|
1683
|
+
liquid=0,
|
|
1684
|
+
air_gap=0,
|
|
1685
|
+
)
|
|
1686
|
+
]
|
|
1687
|
+
# Aspirate the total volume determined by the loop above
|
|
1688
|
+
tip_contents = self.aspirate_liquid_class(
|
|
1689
|
+
volume=total_aspirate_volume + conditioning_vol + disposal_vol,
|
|
1690
|
+
source=source,
|
|
1691
|
+
transfer_properties=transfer_props,
|
|
1692
|
+
transfer_type=tx_comps_executor.TransferType.ONE_TO_MANY,
|
|
1693
|
+
tip_contents=tip_contents,
|
|
1694
|
+
# We configure the mode based on the last dispense volume and disposal volume
|
|
1695
|
+
# since the mode is only used to determine the dispense push out volume
|
|
1696
|
+
# and we can do a push out only at the last dispense, that too if there is no disposal volume.
|
|
1697
|
+
volume_for_pipette_mode_configuration=vol_dest_combo[-1][0],
|
|
1698
|
+
conditioning_volume=conditioning_vol,
|
|
1699
|
+
)
|
|
1681
1700
|
|
|
1682
1701
|
# If the tip has volumes correspoinding to multiple destinations, then
|
|
1683
1702
|
# multi-dispense in those destinations.
|
|
@@ -1693,9 +1712,7 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1693
1712
|
transfer_type=tx_comps_executor.TransferType.ONE_TO_MANY,
|
|
1694
1713
|
tip_contents=tip_contents,
|
|
1695
1714
|
add_final_air_gap=(
|
|
1696
|
-
False
|
|
1697
|
-
if is_last_step and new_tip == TransferTipPolicyV2.NEVER
|
|
1698
|
-
else True
|
|
1715
|
+
False if is_last_step and keep_last_tip else True
|
|
1699
1716
|
),
|
|
1700
1717
|
trash_location=trash_location,
|
|
1701
1718
|
)
|
|
@@ -1708,9 +1725,7 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1708
1725
|
transfer_type=tx_comps_executor.TransferType.ONE_TO_MANY,
|
|
1709
1726
|
tip_contents=tip_contents,
|
|
1710
1727
|
add_final_air_gap=(
|
|
1711
|
-
False
|
|
1712
|
-
if is_last_step and new_tip == TransferTipPolicyV2.NEVER
|
|
1713
|
-
else True
|
|
1728
|
+
False if is_last_step and keep_last_tip else True
|
|
1714
1729
|
),
|
|
1715
1730
|
trash_location=trash_location,
|
|
1716
1731
|
conditioning_volume=conditioning_vol,
|
|
@@ -1718,8 +1733,11 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1718
1733
|
)
|
|
1719
1734
|
is_first_step = False
|
|
1720
1735
|
|
|
1721
|
-
if
|
|
1736
|
+
if not keep_last_tip:
|
|
1722
1737
|
_drop_tip()
|
|
1738
|
+
last_tip = None
|
|
1739
|
+
|
|
1740
|
+
return last_tip
|
|
1723
1741
|
|
|
1724
1742
|
def _tip_can_hold_volume_for_multi_dispensing(
|
|
1725
1743
|
self,
|
|
@@ -1748,17 +1766,57 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1748
1766
|
volume: float,
|
|
1749
1767
|
source: List[Tuple[Location, WellCore]],
|
|
1750
1768
|
dest: Union[Tuple[Location, WellCore], TrashBin, WasteChute],
|
|
1751
|
-
new_tip: Literal[
|
|
1769
|
+
new_tip: Literal[
|
|
1770
|
+
TransferTipPolicyV2.NEVER,
|
|
1771
|
+
TransferTipPolicyV2.ONCE,
|
|
1772
|
+
TransferTipPolicyV2.ALWAYS,
|
|
1773
|
+
],
|
|
1752
1774
|
tip_racks: List[Tuple[Location, LabwareCore]],
|
|
1753
1775
|
starting_tip: Optional[WellCore],
|
|
1754
1776
|
trash_location: Union[Location, TrashBin, WasteChute],
|
|
1755
1777
|
return_tip: bool,
|
|
1756
|
-
|
|
1778
|
+
keep_last_tip: bool,
|
|
1779
|
+
last_tip_location: Optional[Tuple[Location, WellCore]],
|
|
1780
|
+
) -> Optional[Tuple[Location, WellCore]]:
|
|
1781
|
+
"""Execute consolidate using liquid class properties.
|
|
1782
|
+
|
|
1783
|
+
Args:
|
|
1784
|
+
liquid_class: The liquid class to use for transfer properties.
|
|
1785
|
+
volume: Volume to transfer per well.
|
|
1786
|
+
source: List of source wells, with each well represented as a tuple of
|
|
1787
|
+
types.Location and WellCore.
|
|
1788
|
+
types.Location is only necessary for saving the last accessed location.
|
|
1789
|
+
dest: List of destination wells, with each well represented as a tuple of
|
|
1790
|
+
types.Location and WellCore.
|
|
1791
|
+
types.Location is only necessary for saving the last accessed location.
|
|
1792
|
+
new_tip: Whether the transfer should use a new tip 'once', 'always' or 'never'.
|
|
1793
|
+
'never': the transfer will never pick up a new tip
|
|
1794
|
+
'once': the transfer will pick up a new tip once at the start of transfer
|
|
1795
|
+
'always': the transfer will pick up a new tip after every dispense
|
|
1796
|
+
tip_racks: List of tipracks that the transfer will pick up tips from, represented
|
|
1797
|
+
as tuples of types.Location and WellCore.
|
|
1798
|
+
starting_tip: The user-chosen starting tip to use when deciding what tip to pick
|
|
1799
|
+
up, if the user has set it.
|
|
1800
|
+
trash_location: The chosen trash container to drop tips in and dispose liquid in.
|
|
1801
|
+
return_tip: If `True`, return tips to the tip rack location they were picked up from,
|
|
1802
|
+
otherwise drop in `trash_location`
|
|
1803
|
+
keep_last_tip: When set to `True`, do not drop the final tip used in the consolidate.
|
|
1804
|
+
last_tip_location: If a tip is already attached, this will be the tiprack and well it was
|
|
1805
|
+
picked up from, represented as a tuple of types.Location and WellCore.
|
|
1806
|
+
Used so a tip can be returned if it was picked up outside this function
|
|
1807
|
+
as could be the case for a new_tip of `never`.
|
|
1808
|
+
"""
|
|
1757
1809
|
if not tip_racks:
|
|
1758
1810
|
raise RuntimeError(
|
|
1759
1811
|
"No tipracks found for pipette in order to perform transfer"
|
|
1760
1812
|
)
|
|
1761
|
-
|
|
1813
|
+
# NOTE: Tip option of "always" in consolidate is equivalent to "after every dispense",
|
|
1814
|
+
# or more specifically, "before the next chunk of aspirates".
|
|
1815
|
+
assert new_tip in [
|
|
1816
|
+
TransferTipPolicyV2.NEVER,
|
|
1817
|
+
TransferTipPolicyV2.ONCE,
|
|
1818
|
+
TransferTipPolicyV2.ALWAYS,
|
|
1819
|
+
]
|
|
1762
1820
|
tiprack_uri_for_transfer_props = tip_racks[0][1].get_uri()
|
|
1763
1821
|
try:
|
|
1764
1822
|
transfer_props = liquid_class.get_for(
|
|
@@ -1807,14 +1865,15 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1807
1865
|
)
|
|
1808
1866
|
)
|
|
1809
1867
|
|
|
1810
|
-
|
|
1868
|
+
last_tip = last_tip_location
|
|
1811
1869
|
|
|
1812
1870
|
def _drop_tip() -> None:
|
|
1813
1871
|
if return_tip:
|
|
1814
|
-
assert
|
|
1872
|
+
assert last_tip is not None
|
|
1873
|
+
_, tip_well = last_tip
|
|
1815
1874
|
self.drop_tip(
|
|
1816
1875
|
location=None,
|
|
1817
|
-
well_core=
|
|
1876
|
+
well_core=tip_well,
|
|
1818
1877
|
home_after=False,
|
|
1819
1878
|
alternate_drop_location=False,
|
|
1820
1879
|
)
|
|
@@ -1832,7 +1891,7 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1832
1891
|
alternate_drop_location=True,
|
|
1833
1892
|
)
|
|
1834
1893
|
|
|
1835
|
-
def _pick_up_tip() -> WellCore:
|
|
1894
|
+
def _pick_up_tip() -> Tuple[Location, WellCore]:
|
|
1836
1895
|
next_tip = self.get_next_tip(
|
|
1837
1896
|
tip_racks=[core for loc, core in tip_racks],
|
|
1838
1897
|
starting_well=starting_tip,
|
|
@@ -1858,10 +1917,10 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1858
1917
|
presses=None,
|
|
1859
1918
|
increment=None,
|
|
1860
1919
|
)
|
|
1861
|
-
return tip_well
|
|
1920
|
+
return tiprack_loc, tip_well
|
|
1862
1921
|
|
|
1863
|
-
if new_tip
|
|
1864
|
-
|
|
1922
|
+
if new_tip in [TransferTipPolicyV2.ONCE, TransferTipPolicyV2.ALWAYS]:
|
|
1923
|
+
last_tip = _pick_up_tip()
|
|
1865
1924
|
|
|
1866
1925
|
tip_contents = [
|
|
1867
1926
|
tx_comps_executor.LiquidAndAirGapPair(
|
|
@@ -1889,32 +1948,31 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1889
1948
|
is_last_step = True
|
|
1890
1949
|
break
|
|
1891
1950
|
|
|
1892
|
-
if
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1951
|
+
if not is_first_step and new_tip == TransferTipPolicyV2.ALWAYS:
|
|
1952
|
+
_drop_tip()
|
|
1953
|
+
last_tip = _pick_up_tip()
|
|
1954
|
+
tip_contents = [
|
|
1955
|
+
tx_comps_executor.LiquidAndAirGapPair(
|
|
1956
|
+
liquid=0,
|
|
1957
|
+
air_gap=0,
|
|
1958
|
+
)
|
|
1959
|
+
]
|
|
1900
1960
|
|
|
1901
1961
|
total_aspirated_volume = 0.0
|
|
1902
1962
|
for step_num, (step_volume, step_source) in enumerate(vol_aspirate_combo):
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
)
|
|
1963
|
+
tip_contents = self.aspirate_liquid_class(
|
|
1964
|
+
volume=step_volume,
|
|
1965
|
+
source=step_source,
|
|
1966
|
+
transfer_properties=transfer_props,
|
|
1967
|
+
transfer_type=tx_comps_executor.TransferType.MANY_TO_ONE,
|
|
1968
|
+
tip_contents=tip_contents,
|
|
1969
|
+
volume_for_pipette_mode_configuration=(
|
|
1970
|
+
total_dispense_volume if step_num == 0 else None
|
|
1971
|
+
),
|
|
1972
|
+
current_volume=total_aspirated_volume,
|
|
1973
|
+
)
|
|
1915
1974
|
total_aspirated_volume += step_volume
|
|
1916
1975
|
is_first_step = False
|
|
1917
|
-
enable_lpd = False
|
|
1918
1976
|
tip_contents = self.dispense_liquid_class(
|
|
1919
1977
|
volume=total_dispense_volume,
|
|
1920
1978
|
dest=dest,
|
|
@@ -1922,15 +1980,15 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
1922
1980
|
transfer_properties=transfer_props,
|
|
1923
1981
|
transfer_type=tx_comps_executor.TransferType.MANY_TO_ONE,
|
|
1924
1982
|
tip_contents=tip_contents,
|
|
1925
|
-
add_final_air_gap=(
|
|
1926
|
-
False
|
|
1927
|
-
if is_last_step and new_tip == TransferTipPolicyV2.NEVER
|
|
1928
|
-
else True
|
|
1929
|
-
),
|
|
1983
|
+
add_final_air_gap=(False if is_last_step and keep_last_tip else True),
|
|
1930
1984
|
trash_location=trash_location,
|
|
1931
1985
|
)
|
|
1932
|
-
|
|
1986
|
+
|
|
1987
|
+
if not keep_last_tip:
|
|
1933
1988
|
_drop_tip()
|
|
1989
|
+
last_tip = None
|
|
1990
|
+
|
|
1991
|
+
return last_tip
|
|
1934
1992
|
|
|
1935
1993
|
def _get_location_and_well_core_from_next_tip_info(
|
|
1936
1994
|
self,
|
|
@@ -2011,13 +2069,6 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
2011
2069
|
location=prep_location,
|
|
2012
2070
|
)
|
|
2013
2071
|
last_liquid_and_airgap_in_tip.air_gap = 0
|
|
2014
|
-
if (
|
|
2015
|
-
transfer_type != tx_comps_executor.TransferType.MANY_TO_ONE
|
|
2016
|
-
and self.get_liquid_presence_detection()
|
|
2017
|
-
):
|
|
2018
|
-
self.liquid_probe_with_recovery(
|
|
2019
|
-
well_core=source_well, loc=prep_location
|
|
2020
|
-
)
|
|
2021
2072
|
# TODO: do volume configuration + prepare for aspirate only if the mode needs to be changed
|
|
2022
2073
|
self.configure_for_volume(volume_for_pipette_mode_configuration)
|
|
2023
2074
|
self.prepare_to_aspirate()
|
|
@@ -2436,14 +2487,6 @@ class InstrumentCore(AbstractInstrument[WellCore, LabwareCore]):
|
|
|
2436
2487
|
"""Call a protocol delay."""
|
|
2437
2488
|
self._protocol_core.delay(seconds=seconds, msg=None)
|
|
2438
2489
|
|
|
2439
|
-
@contextmanager
|
|
2440
|
-
def lpd_for_transfer(self, enable: bool) -> Generator[None, None, None]:
|
|
2441
|
-
"""Context manager for the instrument's LPD state during a transfer."""
|
|
2442
|
-
global_lpd_enabled = self.get_liquid_presence_detection()
|
|
2443
|
-
self.set_liquid_presence_detection(enable=enable)
|
|
2444
|
-
yield
|
|
2445
|
-
self.set_liquid_presence_detection(enable=global_lpd_enabled)
|
|
2446
|
-
|
|
2447
2490
|
|
|
2448
2491
|
class _TipInfo(NamedTuple):
|
|
2449
2492
|
tiprack_location: Location
|