Skip to content

96 Head requires all 96 tips to be present in the tip rack #547

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Ferryistaken opened this issue Jun 4, 2025 · 5 comments
Closed

96 Head requires all 96 tips to be present in the tip rack #547

Ferryistaken opened this issue Jun 4, 2025 · 5 comments

Comments

@Ferryistaken
Copy link

Ferryistaken commented Jun 4, 2025

I've noticed that the pick_up_tips96 method checks that all 96 tips are present in the tip rack, and raises a ValueError otherwise.

see code

    ...
    if not tip_rack.num_items == 96:
      raise ValueError("Tip rack must have 96 tips")
    ...

Why is this? Sometimes it could be useful to remove tips from the rack used by the 96 head since the head by itself doesn't allow to aspirate different volumes, and removing certain tips with the 8-channel essentially adds the "feature" of being able to not aspirate from certain wells.

Maybe a flag like checkTips could be added to this method? Is there another way to remove this check? (ideally I could remove the check temporarily only when using the 96 head)

I know I can momentarily disable tip tracking, however it's less than ideal as doing that resets all tip racks to their initial state in the visualizer

@Ferryistaken
Copy link
Author

Update

Giving it a second look, I realized that the line I pointed out was not the issue, but rather the issues comes up during the "queue operation on all tip trackers" section in the same file, just a couple lines afterwards:

    # queue operation on all tip trackers
    for i, tip_spot in enumerate(tip_rack.get_all_items()):
      if not does_tip_tracking() and self.head96[i].has_tip:
        self.head96[i].remove_tip()
      self.head96[i].add_tip(tip_spot.get_tip(), origin=tip_spot, commit=False). # Right here
      if does_tip_tracking() and not tip_spot.tracker.is_disabled:
        tip_spot.tracker.remove_tip()

Specifically because get_tip throws an error if the tip isn't there. Is there a reason behind this behavior? Do some liquid handlers require all tips to be present?

@rickwierenga
Copy link
Member

to your first question: tip_rack.num_items actually refers to the number of "children" (child resources) of this tip rack. The children of tip racks are actually TipSpot, the holes that you see in the tip rack. It does not refer to the tips themselves. It is defined here:

def num_items(self) -> int:
.

This check ensures that you are not picking up tips from a tip rack that does not have at least 96 spots. Whether there are tips on these spots is not specifically checked here.


To your second question: as you point out, we should support situations where not all 96 tips are present when picking up with the 96 head. This current implementation (with tip tracking enabled) is actually wrong as you point out.

This feature of picking up !96 tips at a time (which we should definitely have), is not very well thought out. As you can see LH.pick_up_tips96 only supports TipRack right now. I think in the current TipRack case, it's obvious the 96 head should go to the same location as if all tips were there (i.e. not changing the position of the head wrt the tip rack). After that we can move on to picking up tips with an "offset", e.g. picking up 8 tips using the first column.

We previously assumed tip racks would be full, and we need to change that for this. One place is this in the STARBackend, where we use the A1 tip as the prototypical tip. We should replace this by a search through the tip rack for a tip. It is a simple change that I will make a PR for.

tip_spot_a1 = pickup.resource.get_item("A1")

@Ferryistaken
Copy link
Author

I see, that makes sense, thanks for the clarification

@rickwierenga
Copy link
Member

should be fixed with #548. if the issue still occurs please reopen

@Ferryistaken
Copy link
Author

Ferryistaken commented Jun 5, 2025

That was quick, Rick, thank you very much.

However I think there are still some missing parts that should be changed, for example here:

tips = [channel.get_tip() for channel in self.head96.values()]

This list comprehension calls get_tip() which raises NoTipError if there's no tip present.

It should probably be enough to do something like:

 tips = [channel.get_tip() for channel in self.head96.values() if channel.has_tip()] 

Or I'm not sure if you'd like to take a different approach of adding a flag to the trackers to make NoTipError be a warning if I set something like allow_partial_96head to True.

ps:

if the issue still occurs please reopen

I don't have the permissions to reopen issues, I think it's set to only contributors

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants