ParameterSet pondering

in work to remove hamilton liquid classes from pylabrobot (background in issue remove Hamilton liquid classes · Issue #225 · PyLabRobot/pylabrobot · GitHub), i was adding a new class ParameterSet (add ParameterSet by rickwierenga · Pull Request #248 · PyLabRobot/pylabrobot · GitHub), because liquid classes are essentially just parameters. ParameterSet is an abstract base class that generates parameters for an aspiration or a dispense. These parameters can then be passed to LiquidHandler.aspirate and dispense. Robot-specific arguments will be passed through backend_kwargs.

For each robot, the parameters sets (“liquid classes”) are different, and so each robot may define a subclass of ParameterSet. Users may also only want to customize some parameters, so also users should be free to define ParameterSet subclasses so that they can just include attributes for parameters they want. For STAR, I created STARParameterSet, with similar attributes to a hamilton liquid class.

Each channel may liquid handling operation with different parameters (such as flow rate). Given this, it makes sense to store the parameters on STARParameterSet in lists.

It got interesting when I was just implementing this for {aspirate,dispense}96 commands. At least on hamilton, they take a single parameter that applies to all channels. This means STARParameterSet will not work naturally, I would have to check that there is only a single value in each list. It’s possible to introduce a second class STARCore96ParameterSet.

Thinking about this, I don’t think it really makes sense to have this class. It provides nothing not even a defined set of attributes and data types (all is user defined). Is there any reason to not only use dictionaries? The user can store

asp_kwargs = {
  "flow_rates": [21, 42],
  ...
}

and simply lh.aspirate(..., **asp_kwargs). I don’t really see why we would need ParameterSet.

1 Like

In general, I like passing around dataclasses, but given that you are orienting this towards ease of scripting, I think a nice compromise could be just making from_hamilton_liquid_class a standalone function that returned a typed dict.

2 Likes

would be a nice method of HamiltonLiquidClass (while it lasts), because the first parameter is gonna be liquid_class anyway, so might as well call that self.

1 Like

a data class provides guidance to new users about protocol structure by organizing all valid commands to send to a liquid handler into in one place + facilitates autocomplete when scripting

it is not immediately obvious the full optionality you have in a single pipetting step, especially when you are using a new tool. combining both liquid class characteristics and unit pipetting operations into one unit for each tool: core, core96, the lynx individually variable 96ch head, etc will help users understand how to use the tool

2 Likes

good point, discoverability of parameters is extremely important and we’re underperforming there

I don’t think ParameterSet would have been a solution, since the set of parameters is still user-configurable (as a result of required hardware agnosticity) and for user preference. It was essentially an empty wrapper around dictionaries.

I’m learning towards keeping liquid classes in their new form (dictionary exporters) for fast reasonably-good values, and not adding bad new code for “ParameterSet”

this would be nice to clearly define for users for each LH tool that has been tested & is working

that should just be the method header on the backend imo (some work to do, but getting there)