Skip to content

Commit c9fa53c

Browse files
committed
fix volume tracking on dispense96
1 parent b7a6ff0 commit c9fa53c

File tree

2 files changed

+29
-17
lines changed

2 files changed

+29
-17
lines changed

pylabrobot/liquid_handling/liquid_handler.py

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1742,18 +1742,13 @@ async def dispense96(
17421742
raise ValueError("Container too small to accommodate 96 head")
17431743

17441744
for channel in self.head96.values():
1745-
# superfluous to have append in two places but the type checker is very angry and does not
1746-
# understand that Optional[Liquid] (remove_liquid) is the same as None from the first case
1747-
reversed_liquids: List[Tuple[Optional[Liquid], float]]
1748-
if container.tracker.is_disabled or not does_volume_tracking():
1749-
reversed_liquids = [(None, volume)]
1750-
all_liquids.append(reversed_liquids)
1751-
else:
1752-
reversed_liquids = container.tracker.remove_liquid(volume=volume) # type: ignore
1753-
all_liquids.append(reversed_liquids)
1745+
liquids = channel.get_tip().tracker.remove_liquid(volume=volume)
1746+
reversed_liquids = list(reversed(liquids))
1747+
all_liquids.append(reversed_liquids)
17541748

1755-
for liquid, vol in reversed(reversed_liquids):
1756-
channel.get_tip().tracker.add_liquid(liquid=liquid, volume=vol)
1749+
if not container.tracker.is_disabled and does_volume_tracking():
1750+
for liquid, vol in reversed(reversed_liquids):
1751+
container.tracker.add_liquid(liquid=liquid, volume=vol)
17571752

17581753
dispense = MultiHeadDispenseContainer(
17591754
container=container,
@@ -1765,8 +1760,6 @@ async def dispense96(
17651760
blow_out_air_volume=blow_out_air_volume,
17661761
liquids=cast(List[List[Tuple[Optional[Liquid], float]]], all_liquids), # stupid
17671762
)
1768-
1769-
containers = [resource]
17701763
else:
17711764
# ensure that wells are all in the same plate
17721765
plate = containers[0].parent
@@ -1803,13 +1796,13 @@ async def dispense96(
18031796
await self.backend.dispense96(dispense=dispense, **backend_kwargs)
18041797
except Exception as error:
18051798
for channel, container in zip(self.head96.values(), containers):
1806-
if does_volume_tracking() and not well.tracker.is_disabled:
1799+
if does_volume_tracking() and not container.tracker.is_disabled:
18071800
container.tracker.rollback()
18081801
channel.get_tip().tracker.rollback()
18091802
raise error
18101803
else:
18111804
for channel, container in zip(self.head96.values(), containers):
1812-
if does_volume_tracking() and not well.tracker.is_disabled:
1805+
if does_volume_tracking() and not container.tracker.is_disabled:
18131806
container.tracker.commit()
18141807
channel.get_tip().tracker.commit()
18151808

pylabrobot/liquid_handling/liquid_handler_tests.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
ResourceNotFoundError,
2626
ResourceStack,
2727
TipRack,
28+
nest_1_troughplate_195000uL_Vb,
2829
no_tip_tracking,
2930
set_tip_tracking,
3031
)
@@ -1038,9 +1039,11 @@ async def asyncSetUp(self):
10381039
self.deck = STARLetDeck()
10391040
self.lh = LiquidHandler(backend=self.backend, deck=self.deck)
10401041
self.tip_rack = STF(name="tip_rack")
1041-
self.plate = Cor_96_wellplate_360ul_Fb(name="plate")
10421042
self.deck.assign_child_resource(self.tip_rack, location=Coordinate(0, 0, 0))
1043+
self.plate = Cor_96_wellplate_360ul_Fb(name="plate")
10431044
self.deck.assign_child_resource(self.plate, location=Coordinate(100, 100, 0))
1045+
self.single_well_plate = nest_1_troughplate_195000uL_Vb(name="single_well_plate")
1046+
self.deck.assign_child_resource(self.single_well_plate, location=Coordinate(300, 100, 0))
10441047
await self.lh.setup()
10451048
set_volume_tracking(enabled=True)
10461049

@@ -1091,7 +1094,7 @@ async def error_func(*args, **kwargs):
10911094
# test volume doens't change on failed dispense
10921095
assert self.lh.head[0].get_tip().tracker.get_used_volume() == 200
10931096

1094-
async def test_96_head_volume_tracking(self):
1097+
async def test_96_head_volume_tracking_multi_container(self):
10951098
for item in self.plate.get_all_items():
10961099
item.tracker.set_liquids([(Liquid.WATER, 10)])
10971100
await self.lh.pick_up_tips96(self.tip_rack)
@@ -1103,6 +1106,22 @@ async def test_96_head_volume_tracking(self):
11031106
for i in range(96):
11041107
self.assertEqual(self.lh.head96[i].get_tip().tracker.get_used_volume(), 0)
11051108
self.plate.get_item(i).tracker.get_used_volume() == 10
1109+
await self.lh.return_tips96()
1110+
1111+
async def test_96_head_volume_tracking_single_container(self):
1112+
well = self.single_well_plate.get_item(0)
1113+
well.tracker.set_liquids([(Liquid.WATER, 10 * 96)])
1114+
await self.lh.pick_up_tips96(self.tip_rack)
1115+
1116+
await self.lh.aspirate96(self.single_well_plate, volume=10)
1117+
assert all(self.lh.head96[i].get_tip().tracker.get_used_volume() == 10 for i in range(96))
1118+
assert well.tracker.get_used_volume() == 0
1119+
1120+
await self.lh.dispense96(self.single_well_plate, volume=10)
1121+
assert all(self.lh.head96[i].get_tip().tracker.get_used_volume() == 0 for i in range(96))
1122+
assert well.tracker.get_used_volume() == 10 * 96
1123+
1124+
await self.lh.return_tips96()
11061125

11071126

11081127
class TestLiquidHandlerCrossContaminationTracking(unittest.IsolatedAsyncioTestCase):

0 commit comments

Comments
 (0)