From 9e29a4650ac073c4214465a9f8f5b3ca70cfa094 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sat, 18 Jul 2015 16:25:08 +0200 Subject: [PATCH] environment,gui: more argument types --- artiq/gui/explorer.py | 61 ++++++++++++++++- artiq/language/environment.py | 69 +++++++++++++++++++- examples/master/repository/arguments_demo.py | 18 +++++ 3 files changed, 144 insertions(+), 4 deletions(-) create mode 100644 examples/master/repository/arguments_demo.py diff --git a/artiq/gui/explorer.py b/artiq/gui/explorer.py index e4d594969..ccf1bea46 100644 --- a/artiq/gui/explorer.py +++ b/artiq/gui/explorer.py @@ -33,8 +33,67 @@ class _FreeValueEntry(QtGui.QLineEdit): return pyon.decode(self.text()) +class _BooleanEntry(QtGui.QCheckBox): + def __init__(self, procdesc): + QtGui.QCheckBox.__init__(self) + if "default" in procdesc: + self.setChecked(procdesc["default"]) + + def get_argument_value(self): + return self.isChecked() + + +class _EnumerationEntry(QtGui.QComboBox): + def __init__(self, procdesc): + QtGui.QComboBox.__init__(self) + self.choices = procdesc["choices"] + self.addItems(self.choices) + if "default" in procdesc: + try: + idx = self.choices.index(procdesc["default"]) + except: + pass + else: + self.setCurrentIndex(idx) + + def get_argument_value(self): + return self.choices[self.currentIndex()] + + +class _NumberEntry(QtGui.QDoubleSpinBox): + def __init__(self, procdesc): + QtGui.QDoubleSpinBox.__init__(self) + if procdesc["step"] is not None: + self.setSingleStep(procdesc["step"]) + if procdesc["min"] is not None: + self.setMinimum(procdesc["min"]) + if procdesc["max"] is not None: + self.setMinimum(procdesc["max"]) + if procdesc["unit"]: + self.setSuffix(" " + procdesc["unit"]) + if "default" in procdesc: + self.setValue(procdesc["default"]) + + def get_argument_value(self): + return self.value() + + +class _StringEntry(QtGui.QLineEdit): + def __init__(self, procdesc): + QtGui.QLineEdit.__init__(self) + if "default" in procdesc: + self.insert(procdesc["default"]) + + def get_argument_value(self): + return self.text() + + _procty_to_entry = { - "FreeValue": _FreeValueEntry + "FreeValue": _FreeValueEntry, + "BooleanValue": _BooleanEntry, + "EnumerationValue": _EnumerationEntry, + "NumberValue": _NumberEntry, + "StringValue": _StringEntry } diff --git a/artiq/language/environment.py b/artiq/language/environment.py index 613a42f3c..f6da67803 100644 --- a/artiq/language/environment.py +++ b/artiq/language/environment.py @@ -2,7 +2,10 @@ from collections import OrderedDict from inspect import isclass -__all__ = ["NoDefault", "FreeValue", "HasEnvironment", +__all__ = ["NoDefault", + "FreeValue", "BooleanValue", "EnumerationValue", + "NumberValue", "StringValue", + "HasEnvironment", "Experiment", "EnvExperiment", "is_experiment"] @@ -17,7 +20,7 @@ class DefaultMissing(Exception): pass -class FreeValue: +class _SimpleArgProcessor: def __init__(self, default=NoDefault): if default is not NoDefault: self.default_value = default @@ -31,12 +34,72 @@ class FreeValue: return x def describe(self): - d = {"ty": "FreeValue"} + d = {"ty": self.__class__.__name__} if hasattr(self, "default_value"): d["default"] = self.default_value return d +class FreeValue(_SimpleArgProcessor): + """An argument that can be an arbitrary Python value.""" + pass + + +class BooleanValue(_SimpleArgProcessor): + """A boolean argument.""" + pass + + +class EnumerationValue(_SimpleArgProcessor): + """An argument that can take a string value among a predefined set of + values. + + :param choices: A list of string representing the possible values of the + argument. + """ + def __init__(self, choices, default=NoDefault): + _SimpleArgProcessor.__init__(self, default) + assert default is NoDefault or default in choices + self.choices = choices + + def describe(self): + d = _SimpleArgProcessor.describe(self) + d["choices"] = self.choices + return d + + +class NumberValue(_SimpleArgProcessor): + """An argument that can take a numerical value (typically floating point). + + :param unit: A string representing the unit of the value, for user + interface (UI) purposes. + :param step: The step with with the value should be modified by up/down + buttons in a UI. + :param min: The minimum value of the argument. + :param max: The maximum value of the argument. + """ + def __init__(self, default=NoDefault, unit="", step=None, + min=None, max=None): + _SimpleArgProcessor.__init__(self, default) + self.unit = unit + self.step = step + self.min = min + self.max = max + + def describe(self): + d = _SimpleArgProcessor.describe(self) + d["unit"] = self.unit + d["step"] = self.step + d["min"] = self.min + d["max"] = self.max + return d + + +class StringValue(_SimpleArgProcessor): + """A string argument.""" + pass + + class HasEnvironment: """Provides methods to manage the environment of an experiment (devices, parameters, results, arguments).""" diff --git a/examples/master/repository/arguments_demo.py b/examples/master/repository/arguments_demo.py new file mode 100644 index 000000000..78b8521b3 --- /dev/null +++ b/examples/master/repository/arguments_demo.py @@ -0,0 +1,18 @@ +from artiq import * + + +class ArgumentsDemo(EnvExperiment): + def build(self): + self.attr_argument("free_value", FreeValue(None)) + self.attr_argument("boolean", BooleanValue(True)) + self.attr_argument("enum", EnumerationValue( + ["foo", "bar", "quux"], "foo")) + self.attr_argument("number", NumberValue(42, unit="s", step=0.1)) + self.attr_argument("string", StringValue("Hello World")) + + def run(self): + print(self.free_value) + print(self.boolean) + print(self.enum) + print(self.number) + print(self.string)