PLR `lh.mix()` method?

Hi everyone,

A recurring question raised to the PLR devs is where a “simple” mixing method is?

I’m happy to create one at the liquid handling level if interest of active PLR users exists here.

I would implement it at the user-facing frontend LiquidHandler level and write a backend method that creates the expected behaviour based on the liquid handlers unique quirks:

e.g. the STAR(let) system does not actually have a standalone “mix” firmware command (to my knowledge), and on top of that the mixing parameters don’t seem to work in the dispense firmware command, leaving a standalone “mix” command with a volume=0 aspiration command only :slight_smile:

Please let me know whether you think this would be useful and whether you would have a different implementation strategy.

when is mix not a part of dispense or aspirate

they work on my star

I have seen the same as in this old post:

Does this mean you think a separate “mix” command is not necessary?

that’s odd, but the bug is a separate discussion from the point in this thread

unless we find a scenario to mix without dispensing / aspiration, it does not make sense to have a mix function in LiquidHandler

tangental: I do think mixing should be part of LH on the aspirate/dispense commands, not backend kwargs as it currently is. we should also make the api nicer

Mixing a sedimenting agent in a liquid during incubation:

e.g. beads binding a biomolecule

1 Like

so that’s an action that’s done not just before/after an aspiration/dispense?

no, it is performed during the incubation step to increase mixing (-> binding)

1 Like

ok in that case we should have lh.mix

2 Likes

I also wanted to ask:
for machine agnosticity reasons, aren’t there at least a few liquid handlers that do not have mixing arguments as part of the aspirate, dispense commands?
(I believe the OT-2 is an example?)

this is regarding making mix part of aspirate/dispense (as I said we should do here: PLR `lh.mix()` method? - #7 by rickwierenga), on the liquid handler level we can be agnostic to that because those backends can just call aspirate+mix when mixing params are passed to aspirate (or dispense)

agnosticity problems occur the other way around: when machine commands are less atomic than the PLR standard

todo plan:

  • make lh.mix, make it part of the backend, introduce Mix dataclass in standard.py
  • use Mix class in aspirate/dispense, or at least have those same parameters there, and in any case add Aspiration.mix: Mix and Dispense.mix: Mix to those standard.py dataclasses

So you’re saying that in PyLabRobot all liquid handlers should have aspirate and dispense commands that accept mixing as part of the LiquidHandler aspirate/dispense?

Does that not break the “atomic-ness” of these commands, e.g. because then aspirate actually contains [aspirate+dispense]*no_mix_cycles ?

on the front end, no. front end changes never break atomic-ness

on the backend it’s arguable, but I would say no since aspiration+mix means they are done in one motion whereas for aspiration then mix it’s technically possible to move the pipette out of the liquid then back in

In the special case of the STAR(let): isn’t the settling_time argument still generating a temporal separation between the aspiration/dispensation action and the mixing action?

yes temporal but it’s still part of the same motion whereas moving the tip in and out of the liquid is fundamentally different. do we agree that it is different or no?

if we do agree, then the problem is how do we clarify what we want if mix is not part of asp/disp

I don’t think I agree:
If an object moves in orientation A, then stops and then moves in orientation B I wouldn’t count the second movement the same as the first one since (1) a new motor signal has to be sent and (2) the direction of the movement has changed.

(A is e.g. channel plunger UP, B channel plunger DOWN for a dispense+mix command)

I am talking about the tip not the plunger