HPInc / HP-Digital-Microfluidics

HP Digital Microfluidics Software Platform and Libraries
MIT License
2 stars 0 forks source link

Add default units and means of specifying #167

Closed EvanKirshenbaum closed 5 months ago

EvanKirshenbaum commented 5 months ago

As it stands now, all exercisers are responsible for adding something like

    Time.default_units = ms
    Volume.default_units = uL
    Voltage.default_units = V
    Temperature.default_units = deg_C

when they forget, you get things like

   INFO|bilby|Near-zero voltage (1.5152856866068552e-44 m**2*g/A*ms**3) read from device.  Assuming zero.

This should be moved someplace more central (e.g., in Exerciser) and made overridable with a command-line parameter.

Migrated from internal repository. Originally created by @EvanKirshenbaum on Jun 10, 2022 at 3:29 PM PDT. Closed on Jun 15, 2022 at 12:06 PM PDT.
EvanKirshenbaum commented 5 months ago

This issue was referenced by the following commit before migration:

EvanKirshenbaum commented 5 months ago

That was reasonably straightforward. I started by adding an ArgUnits class that does most of the heavy lifting for handling arguments that involve quantities. So, e.g., time_arg is simply defined as

ArgUnits.register_units(Time,
                        {
                            ns: ("ns", "nsec"),
                            us: ("us", "usec"),
                            ms: ("ms", "msec"),
                            sec: ("s", "sec", "secs", "second", "seconds"),
                            minutes: ("min", "minute", "minutes"),
                            hr: ("hr", "hour", "hours"),
                            days: ("days", "day"),
                            }                        
                        )

def time_arg(arg: str) -> Time:
    return ArgUnits.parse_arg(Time, arg, default="30ms")

Then I added a units_arg that can parse a comma- or space-separated list of unit names and return a mapping from Dimensionality to sequence of Unit, declared a --units arg (that can be specified more than once), and added set_default_units(), called from parse_args_and_run(), which does the actual setting.

Note that I set default defaults at the beginning of parse_args_and_run(), before the call to parse_args():

        Time.default_units = ms
        Volume.default_units = uL
        Temperature.default_units = deg_C
        Voltage.default_units = volts

so that units will be reasonably chosen for help strings and error messages. Any explicitly-specified --units will replace these.

For explicitly-specified units, if more than one is specified for the same dimension (e.g., uL,mL), all are provided to the default_units assignment, which will result in choosing the larges one that is no bigger than the given value (or the smallest, if there is none).

Unfortunately, this doesn't give the user any way to say "Forget what you might have been told earlier about time units, use these instead." This may have to be revisited, but it is probably a general issue with arguments that can be provided multiple times.

Migrated from internal repository. Originally created by @EvanKirshenbaum on Jun 15, 2022 at 12:06 PM PDT.