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

pull/605/head
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.
* In the dashboard's experiment windows, partial or full argument recomputation
takes into account the repository revision field.
* By default, ``NumberValue`` and ``Scannable`` infer the scale from the unit
for common units.
1.1 (unreleased)

View File

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

View File

@ -2,6 +2,7 @@ from collections import OrderedDict
from inspect import isclass
from artiq.protocols import pyon
from artiq.language import units
__all__ = ["NoDefault",
@ -79,7 +80,6 @@ class EnumerationValue(_SimpleArgProcessor):
d["choices"] = self.choices
return d
class NumberValue(_SimpleArgProcessor):
"""An argument that can take a numerical value.
@ -88,14 +88,20 @@ class NumberValue(_SimpleArgProcessor):
The simplest way to represent an integer argument is
``NumberValue(step=1, ndecimals=0)``.
For arguments with units, use both the unit parameter (a string for
display) and the scale parameter (a numerical scale for experiments).
For example, ``NumberValue(1, unit="ms", scale=1*ms)`` will display as
1 ms in the GUI window because of the unit setting, and appear as the
When ``scale`` is not specified, and the unit is a common one (i.e.
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, ``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.
:param unit: A string representing the unit of the value, for display
purposes only.
:param unit: A string representing the unit of the value.
:param scale: A numerical scaling factor by which the displayed value is
multiplied when referenced in the experiment.
: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 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):
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:
step = scale/10.0
if default is not NoDefault:

View File

@ -23,6 +23,7 @@ import inspect
from artiq.language.core import *
from artiq.language.environment import NoDefault, DefaultMissing
from artiq.language import units
__all__ = ["ScanObject",
@ -143,8 +144,18 @@ class Scannable:
"""An argument (as defined in :class:`artiq.language.environment`) that
takes a scan object.
For arguments with units, use both the unit parameter (a string for
display) and the scale parameter (a numerical scale for experiments).
When ``scale`` is not specified, and the unit is a common one (i.e.
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
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
up/down buttons in a user interface. The default is the scale divided
by 10.
:param unit: A string representing the unit of the scanned variable, for
display purposes only.
:param unit: A string representing the unit of the scanned variable.
:param scale: A numerical scaling factor by which the displayed values
are multiplied when referenced in the experiment.
: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,
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:
global_step = scale/10.0
if default is not NoDefault: