Volume tracker on mix cycles

I’m trying to run this:


    for i in range(0,8):
        reagent_source.set_liquid(liquid=Liquid.SERUM, volume=55, well=i)

    await lh.pick_up_tips(tip_rack_200s[0,1,2,3,4,5,6,7], use_channels=[0,1,2,3,4,5,6,7])
    for _ in range(10):
        await lh.aspirate(reagent_source[0,1,2,3,4,5,6,7], vols=45)
        await lh.dispense(reagent_source[0,1,2,3,4,5,6,7], vols=45)

However, on the 2nd aspirate cycle, it pylabrobot.resources.errors.TooLittleLiquidError: Tracker only has 10.0uL

When I step through the sequence of actions - it looks like the tip’s volume tracker isn’t committed during the aspirate step. So the dispense isn’t getting a liquid type and volume set, which means no volume is added to the well’s tracker.

I’m still a bit new to PLR’s code base, so not sure if this is me or a bug. Anyone else tried this?

1 Like

looking into it

1 Like

Where is reagent_source.set_liquid defined? I can only find set_liquids in the latest version, or set_well_liquids for Plate. My hope is you’re running a slightly outdated version so you can just update.

Added a small test to make sure this works:

for i in range(8):
  self.plate.get_item(i).set_liquids([(Liquid.SERUM, 55)])

await self.lh.pick_up_tips(self.tip_rack[0:8])
initial_liquids = [self.plate.get_item(i).tracker.liquids for i in range(8)]
for _ in range(10):
  await self.lh.aspirate(self.plate[0:8], vols=45)
  await self.lh.dispense(self.plate[0:8], vols=45)
liquids_now = [self.plate.get_item(i).tracker.liquids for i in range(8)]
self.assertEqual(liquids_now, initial_liquids)

(self.plate = reagent_source, using an existing part of the unit test.)

Sorry, should have mentioned that. I added a small method to the Plate class:

  def set_liquid(
      self,
      liquid: Liquid,
      volume: float,
      well: int
  ) -> None:
    _well = self.get_well(well)
    _well.tracker.set_liquids([(liquid, volume)])

That was another thing I meant to ask about - I wasn’t able to set different liquids into different wells of a plate. I’ll start a separate thread on that…

I also added this to the aspirate/dispense methods:

    # commit or rollback the state trackers
    for channel, op, success in zip(use_channels, dispenses, successes):
      if does_volume_tracking():
        if not op.resource.tracker.is_disabled:
          (op.resource.tracker.commit if success else op.resource.tracker.rollback)()
          (op.tip.tracker.commit if success else op.tip.tracker.rollback)() #added by RK
        (self.head[channel].commit if success else self.head[channel].rollback)()

That seems to result in the well and tip trackers volumes to be correct after each step (as read out by:

   for op in dispenses:
      print(op.resource.name)
      print(op.resource.tracker.serialize())
      print(op.tip.tracker.serialize())

could you please confirm you’re running the latest version?

Please!

this is supposed to be self.head[channel].get_tip().tracker (a VolumeTracker) instead of self.head[channel].commit. Fixed recently-ish with fix LH.dispense volume tracker issue · PyLabRobot/pylabrobot@c655ceb · GitHub.

I’m a bit confused because your code above seems to run fine in the unit tests. I can’t reproduce this issue on plr:main.