Skip to content

Commit 4bc69f3

Browse files
Digitally transfer only the aspiratable volumes in worklist methods
Closes #102
1 parent 95b04e2 commit 4bc69f3

File tree

6 files changed

+30
-9
lines changed

6 files changed

+30
-9
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "robotools"
7-
version = "1.13.0"
7+
version = "1.13.1"
88
description = "Pythonic in-silico liquid handling and creation of Tecan FreedomEVO worklists."
99
readme = "README.md"
1010
requires-python = ">=3.10"

robotools/evotools/test_worklist.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -598,11 +598,11 @@ def test_transfer_on_underflow(self):
598598
with EvoWorklist() as wl:
599599
wl.transfer(A, "A01", A, "A02", 600, on_underflow="debug")
600600
assert A.volumes[0, 0] == 100
601-
assert A.volumes[0, 1] == 1100
601+
assert A.volumes[0, 1] == 900 # only the aspiratable volume is transferred
602602
with pytest.warns(VolumeUnderflowWarning, match="500.0 - 600.0 < 100"):
603603
wl.transfer(A, "B01", A, "B02", 600, on_underflow="warn")
604604
assert A.volumes[1, 0] == 100
605-
assert A.volumes[1, 1] == 1100
605+
assert A.volumes[1, 1] == 900
606606
with pytest.raises(VolumeUnderflowError, match="500.0 - 600.0 < 100"):
607607
wl.transfer(A, "C01", A, "C02", 600, on_underflow="raise")
608608

robotools/evotools/worklist.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,13 +331,16 @@ def transfer(
331331
if len(vs) > p:
332332
v = vs[p]
333333
if v > 0:
334-
self.aspirate(source, s, v, label=None, on_underflow=on_underflow, **kwargs)
334+
vasp = self.aspirate(
335+
source, s, v, label=None, on_underflow=on_underflow, **kwargs
336+
)
335337
self.dispense(
336338
destination,
337339
d,
338340
v,
339341
label=None,
340342
compositions=[source.get_well_composition(s)],
343+
vtrack=vasp,
341344
**kwargs,
342345
)
343346
nsteps += 1

robotools/fluenttools/test_worklist.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@ def test_transfer_on_underflow(self):
5252
with FluentWorklist() as wl:
5353
wl.transfer(A, "A01", A, "A02", 600, on_underflow="debug")
5454
assert A.volumes[0, 0] == 100
55-
assert A.volumes[0, 1] == 1100
55+
assert A.volumes[0, 1] == 900 # only the aspiratable volume is transferred
5656
with pytest.warns(VolumeUnderflowWarning, match="500.0 - 600.0 < 100"):
5757
wl.transfer(A, "B01", A, "B02", 600, on_underflow="warn")
5858
assert A.volumes[1, 0] == 100
59-
assert A.volumes[1, 1] == 1100
59+
assert A.volumes[1, 1] == 900
6060
with pytest.raises(VolumeUnderflowError, match="500.0 - 600.0 < 100"):
6161
wl.transfer(A, "C01", A, "C02", 600, on_underflow="raise")

robotools/fluenttools/worklist.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,16 @@ def transfer(
136136
if len(vs) > p:
137137
v = vs[p]
138138
if v > 0:
139-
self.aspirate(source, s, v, label=None, on_underflow=on_underflow, **kwargs)
139+
vasp = self.aspirate(
140+
source, s, v, label=None, on_underflow=on_underflow, **kwargs
141+
)
140142
self.dispense(
141143
destination,
142144
d,
143145
v,
144146
label=None,
145147
compositions=[source.get_well_composition(s)],
148+
vtrack=vasp,
146149
**kwargs,
147150
)
148151
nsteps += 1

robotools/worklists/base.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,7 @@ def dispense(
501501
*,
502502
label: Optional[str] = None,
503503
compositions: Optional[List[Optional[Dict[str, float]]]] = None,
504+
vtrack: Union[float, Sequence[float], numpy.ndarray] | None = None,
504505
**kwargs,
505506
) -> None:
506507
"""Performs dispensing into the provided labware.
@@ -512,11 +513,16 @@ def dispense(
512513
wells : str or iterable
513514
List of well ids
514515
volumes : float or iterable
515-
Volume(s) to dispense
516+
Volume(s) to dispense in the command
516517
label : str
517518
Label of the operation to log into labware history
518519
compositions : list
519520
Iterable of liquid compositions
521+
vtrack
522+
Volume to add to the destination in digital volume tracking.
523+
Defaults to ``volume``.
524+
Used by ``transfer`` commands to account for ``on_underflow`` situations
525+
where more volume was aspirated than considered aspiratable based on volume tracking.
520526
kwargs
521527
Additional keyword arguments to pass to `dispense_well`.
522528
Most prominent example: `liquid_class`.
@@ -526,7 +532,16 @@ def dispense(
526532
volumes = numpy.array(volumes).flatten("F")
527533
if len(volumes) == 1:
528534
volumes = numpy.repeat(volumes, len(wells))
529-
labware.add(wells, volumes, label, compositions=compositions)
535+
536+
# Digital volume transfer overrides may be provided
537+
if vtrack is None:
538+
vtrack = volumes
539+
else:
540+
vtrack = numpy.array(vtrack).flatten("F")
541+
if len(vtrack) == 1:
542+
vtrack = numpy.repeat(vtrack, len(wells))
543+
544+
labware.add(wells, vtrack, label, compositions=compositions)
530545
self.comment(label)
531546
for well, volume in zip(wells, volumes):
532547
if volume > 0:

0 commit comments

Comments
 (0)