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
Please let me know whether you think this would be useful and whether you would have a different implementation strategy.
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
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
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)