language/environment: autoset scale for common units. Closes #448

This commit is contained in:
Sebastien Bourdeauducq 2016-05-28 13:37:18 -05:00
parent 8b556ef6d5
commit 0faa2d56b4
4 changed files with 51 additions and 15 deletions

View File

@ -40,6 +40,8 @@ unreleased [2.x]
has been replaced. Pass the parent as first argument instead. has been replaced. Pass the parent as first argument instead.
* In the dashboard's experiment windows, partial or full argument recomputation * In the dashboard's experiment windows, partial or full argument recomputation
takes into account the repository revision field. takes into account the repository revision field.
* By default, ``NumberValue`` and ``Scannable`` infer the scale from the unit
for common units.
1.1 (unreleased) 1.1 (unreleased)

View File

@ -7,7 +7,7 @@ class SubComponent1(HasEnvironment):
def build(self): def build(self):
self.setattr_argument("sc1_scan", self.setattr_argument("sc1_scan",
Scannable(default=[NoScan(3250), RandomScan(10, 20, 6)], Scannable(default=[NoScan(3250), RandomScan(10, 20, 6)],
scale=1e3, unit="kHz"), unit="kHz"),
"Flux capacitor") "Flux capacitor")
self.setattr_argument("sc1_enum", EnumerationValue(["1", "2", "3"]), self.setattr_argument("sc1_enum", EnumerationValue(["1", "2", "3"]),
"Flux capacitor") "Flux capacitor")
@ -43,7 +43,7 @@ class ArgumentsDemo(EnvExperiment):
self.setattr_argument("pyon_value", self.setattr_argument("pyon_value",
PYONValue(self.get_dataset("foo", default=42))) PYONValue(self.get_dataset("foo", default=42)))
self.setattr_argument("number", NumberValue(42e-6, self.setattr_argument("number", NumberValue(42e-6,
unit="us", scale=1e-6, unit="us",
ndecimals=4)) ndecimals=4))
self.setattr_argument("integer", NumberValue(42, self.setattr_argument("integer", NumberValue(42,
step=1, ndecimals=0)) step=1, ndecimals=0))

View File

@ -2,6 +2,7 @@ from collections import OrderedDict
from inspect import isclass from inspect import isclass
from artiq.protocols import pyon from artiq.protocols import pyon
from artiq.language import units
__all__ = ["NoDefault", __all__ = ["NoDefault",
@ -79,7 +80,6 @@ class EnumerationValue(_SimpleArgProcessor):
d["choices"] = self.choices d["choices"] = self.choices
return d return d
class NumberValue(_SimpleArgProcessor): class NumberValue(_SimpleArgProcessor):
"""An argument that can take a numerical value. """An argument that can take a numerical value.
@ -88,14 +88,20 @@ class NumberValue(_SimpleArgProcessor):
The simplest way to represent an integer argument is The simplest way to represent an integer argument is
``NumberValue(step=1, ndecimals=0)``. ``NumberValue(step=1, ndecimals=0)``.
For arguments with units, use both the unit parameter (a string for When ``scale`` is not specified, and the unit is a common one (i.e.
display) and the scale parameter (a numerical scale for experiments). defined in ``artiq.language.units``), then the scale is obtained from
For example, ``NumberValue(1, unit="ms", scale=1*ms)`` will display as the unit using a simple string match. For example, milliseconds (``"ms"``)
1 ms in the GUI window because of the unit setting, and appear as the units set the scale to 0.001. No unit (default) corresponds to a scale of
1.0.
For arguments with uncommon or complex units, use both the unit parameter
(a string for display) and the scale parameter (a numerical scale for
experiments).
For example, ``NumberValue(1, unit="xyz", scale=0.001)`` will display as
1 xyz in the GUI window because of the unit setting, and appear as the
numerical value 0.001 in the code because of the scale setting. numerical value 0.001 in the code because of the scale setting.
:param unit: A string representing the unit of the value, for display :param unit: A string representing the unit of the value.
purposes only.
:param scale: A numerical scaling factor by which the displayed value is :param scale: A numerical scaling factor by which the displayed value is
multiplied when referenced in the experiment. multiplied when referenced in the experiment.
:param step: The step with which the value should be modified by up/down :param step: The step with which the value should be modified by up/down
@ -104,8 +110,17 @@ class NumberValue(_SimpleArgProcessor):
:param max: The maximum value of the argument. :param max: The maximum value of the argument.
:param ndecimals: The number of decimals a UI should use. :param ndecimals: The number of decimals a UI should use.
""" """
def __init__(self, default=NoDefault, unit="", scale=1.0, def __init__(self, default=NoDefault, unit="", scale=None,
step=None, min=None, max=None, ndecimals=2): step=None, min=None, max=None, ndecimals=2):
if scale is None:
if unit == "":
scale = 1.0
else:
try:
scale = getattr(units, unit)
except AttributeError:
raise KeyError("Unit {} is unknown, you must specify "
"the scale manually".format(unit))
if step is None: if step is None:
step = scale/10.0 step = scale/10.0
if default is not NoDefault: if default is not NoDefault:

View File

@ -23,6 +23,7 @@ import inspect
from artiq.language.core import * from artiq.language.core import *
from artiq.language.environment import NoDefault, DefaultMissing from artiq.language.environment import NoDefault, DefaultMissing
from artiq.language import units
__all__ = ["ScanObject", __all__ = ["ScanObject",
@ -143,8 +144,18 @@ class Scannable:
"""An argument (as defined in :class:`artiq.language.environment`) that """An argument (as defined in :class:`artiq.language.environment`) that
takes a scan object. takes a scan object.
For arguments with units, use both the unit parameter (a string for When ``scale`` is not specified, and the unit is a common one (i.e.
display) and the scale parameter (a numerical scale for experiments). defined in ``artiq.language.units``), then the scale is obtained from
the unit using a simple string match. For example, milliseconds (``"ms"``)
units set the scale to 0.001. No unit (default) corresponds to a scale of
1.0.
For arguments with uncommon or complex units, use both the unit parameter
(a string for display) and the scale parameter (a numerical scale for
experiments).
For example, a scan shown between 1 xyz and 10 xyz in the GUI with
``scale=0.001`` and ``unit="xyz"`` results in values between 0.001 and
0.01 being scanned.
:param default: The default scan object. This parameter can be a list of :param default: The default scan object. This parameter can be a list of
scan objects, in which case the first one is used as default and the scan objects, in which case the first one is used as default and the
@ -157,15 +168,23 @@ class Scannable:
:param global_step: The step with which the value should be modified by :param global_step: The step with which the value should be modified by
up/down buttons in a user interface. The default is the scale divided up/down buttons in a user interface. The default is the scale divided
by 10. by 10.
:param unit: A string representing the unit of the scanned variable, for :param unit: A string representing the unit of the scanned variable.
display purposes only.
:param scale: A numerical scaling factor by which the displayed values :param scale: A numerical scaling factor by which the displayed values
are multiplied when referenced in the experiment. are multiplied when referenced in the experiment.
:param ndecimals: The number of decimals a UI should use. :param ndecimals: The number of decimals a UI should use.
""" """
def __init__(self, default=NoDefault, unit="", scale=1.0, def __init__(self, default=NoDefault, unit="", scale=None,
global_step=None, global_min=None, global_max=None, global_step=None, global_min=None, global_max=None,
ndecimals=2): ndecimals=2):
if scale is None:
if unit == "":
scale = 1.0
else:
try:
scale = getattr(units, unit)
except AttributeError:
raise KeyError("Unit {} is unknown, you must specify "
"the scale manually".format(unit))
if global_step is None: if global_step is None:
global_step = scale/10.0 global_step = scale/10.0
if default is not NoDefault: if default is not NoDefault: