Build `lh.consolidate_tip_inventory()`
Hi everyone,
It is time to free PyLabRobot users - no matter what liquid handling machine they are using - from the torture of manual tip re-racking.
In this PR I am adding a new LiquidHandler() method:
async def consolidate_tip_inventory(
self,
ignore_tiprack_list: List[str] = ["teaching_tip_rack"]
):
"""
Consolidate partial tip racks on the deck by redistributing tips.
This function identifies partially-filled tip racks (excluding any in
`ignore_tiprack_list`) in the 'tip_inventory`, the subset of the deck tree
that is of type TipRack, and consolidates their tips into as few tip racks
as possible, grouped by tip model.
Tips are moved efficiently to minimize pipetting steps, avoiding redundant
visits to the same drop columns.
Args:
lh: The liquid handler instance providing access to deck resources and
pick/drop operations.
ignore_tiprack_list: List of tip rack names to exclude from consolidation.
Returns:
None. The function performs in-place tip redistribution via async pick/drop.
"""
This is step 4 of a multi-feature generation process:
- Build
lh.probe_tip_presence_via_pickup() - Build
measured_tip_inventory = lh.probe_tip_inventory(probing_mode=lh.probe_tip_presence_via_pickup) - Build
lh.update_tip_inventory(measured_tip_inventory) - Build
lh.consolidate_tip_inventory()
lh.consolidate_tip_inventory(), step 4, is independent of the previous steps.
It assumes that the liquid handler's tip_tracking information is correct, and consolidates tip_racks based on PLR's tip_tracking system (you therefore have to set_tip_tracking(True) at the beginning of your script!).
This has the opportunity to save operators enormous amounts of time: most automation runs don't use up all tips. Particularly if one uses multiple tipracks of the same model (e.g. 1000ul tips) across an automation run, leaving each partially-filled, operators can spend multiple minutes per run on manual reracking, amounting to hours of operator time lost per month. (and let's not forget the mental fatigue...)
Note: "tip inventory" is defined as the subset of all resources in the deck/resource tree that is of type Tip and whether it's parent resource, the TipSpot has or does not have a tip.
Examples
I have generated some showcases and added the notebook with which I generated the showcases into the docs.
Showcase 1: STARlet
- randomize 1000ul & 50 ul tips
- execute
lh.consolidate_tip_inventory()(no method argument given)
tested on the machine:
| start of automated protocol | after randomization of specified tips | after tip inventory consolidation |
Note: the automated protocol here is a stress-test of various aspects of this new method while not wasting tips :)
(This is why I'm making the .consolidate_tip_inventory() method solve random tip usage. In more realistic runs random tip usage would be considered madness.)
Modification with specification on what tip_racks to ignore
- randomize 1000ul & 50 ul tips
- execute
lh.consolidate_tip_inventory(ignore_tiprack_list = ["teaching_tip_rack", "tip_rack_1000ul_3"])(exclude specific tip_racks from consolidation process)
Machine Agnosticity
PyLabRobot focuses on the commonalities between different lab machines, including liquid handlers.
Therefore a method that is implemented at LiquidHandler level applies to all PLR-integrated liquid handlers.
Since all liquid handlers can - by definition - perform tip_pickups and tip_drops (they are 2 of a liquid handler's atomic command), all PLR-integrated liquid handlers can execute lh.consolidate_tip_inventory()!
In silico example of the same process on an OT-2 (note: I don't have access to an OT-2 to test on the machine):