language,gui: combine LinearScan and RandomScan into RangeScan. Closes #679

This commit is contained in:
Chris Ballance 2017-03-30 23:04:17 +01:00 committed by Sébastien Bourdeauducq
parent 28211e0b32
commit 07c71bf020
3 changed files with 39 additions and 54 deletions

View File

@ -29,7 +29,7 @@ Release notes
* The "collision" and "busy" RTIO errors are reported through the log instead of * The "collision" and "busy" RTIO errors are reported through the log instead of
raising exceptions. raising exceptions.
* Results are still saved when ``analyze`` raises an exception. * Results are still saved when ``analyze`` raises an exception.
* LinearScan and RandomScan have been consolidated into RangeScan
2.2 2.2
--- ---

View File

@ -229,6 +229,9 @@ class _RangeScan(LayoutWidget):
disable_scroll_wheel(stop) disable_scroll_wheel(stop)
self.addWidget(stop, 2, 1) self.addWidget(stop, 2, 1)
randomize = QtWidgets.QCheckBox("Randomize")
self.addWidget(randomize, 3, 1)
apply_properties(start) apply_properties(start)
start.setPrecision() start.setPrecision()
start.setRelativeStep() start.setRelativeStep()
@ -255,15 +258,22 @@ class _RangeScan(LayoutWidget):
if npoints.value() != value: if npoints.value() != value:
npoints.setValue(value) npoints.setValue(value)
def update_randomize(value):
state["randomize"] = value
if randomize.isChecked() != value:
randomize.setChecked(value)
scanner.startChanged.connect(update_start) scanner.startChanged.connect(update_start)
scanner.numChanged.connect(update_npoints) scanner.numChanged.connect(update_npoints)
scanner.stopChanged.connect(update_stop) scanner.stopChanged.connect(update_stop)
start.valueChanged.connect(update_start) start.valueChanged.connect(update_start)
npoints.valueChanged.connect(update_npoints) npoints.valueChanged.connect(update_npoints)
stop.valueChanged.connect(update_stop) stop.valueChanged.connect(update_stop)
randomize.stateChanged.connect(update_randomize)
scanner.setStart(state["start"]/scale) scanner.setStart(state["start"]/scale)
scanner.setNum(state["npoints"]) scanner.setNum(state["npoints"])
scanner.setStop(state["stop"]/scale) scanner.setStop(state["stop"]/scale)
randomize.setChecked(state["randomize"])
class _ExplicitScan(LayoutWidget): class _ExplicitScan(LayoutWidget):
@ -297,16 +307,14 @@ class ScanEntry(LayoutWidget):
state = argument["state"] state = argument["state"]
self.widgets = OrderedDict() self.widgets = OrderedDict()
self.widgets["NoScan"] = _NoScan(procdesc, state["NoScan"]) self.widgets["NoScan"] = _NoScan(procdesc, state["NoScan"])
self.widgets["LinearScan"] = _RangeScan(procdesc, state["LinearScan"]) self.widgets["RangeScan"] = _RangeScan(procdesc, state["RangeScan"])
self.widgets["RandomScan"] = _RangeScan(procdesc, state["RandomScan"])
self.widgets["ExplicitScan"] = _ExplicitScan(state["ExplicitScan"]) self.widgets["ExplicitScan"] = _ExplicitScan(state["ExplicitScan"])
for widget in self.widgets.values(): for widget in self.widgets.values():
self.stack.addWidget(widget) self.stack.addWidget(widget)
self.radiobuttons = OrderedDict() self.radiobuttons = OrderedDict()
self.radiobuttons["NoScan"] = QtWidgets.QRadioButton("No scan") self.radiobuttons["NoScan"] = QtWidgets.QRadioButton("No scan")
self.radiobuttons["LinearScan"] = QtWidgets.QRadioButton("Linear") self.radiobuttons["RangeScan"] = QtWidgets.QRadioButton("Range")
self.radiobuttons["RandomScan"] = QtWidgets.QRadioButton("Random")
self.radiobuttons["ExplicitScan"] = QtWidgets.QRadioButton("Explicit") self.radiobuttons["ExplicitScan"] = QtWidgets.QRadioButton("Explicit")
scan_type = QtWidgets.QButtonGroup() scan_type = QtWidgets.QButtonGroup()
for n, b in enumerate(self.radiobuttons.values()): for n, b in enumerate(self.radiobuttons.values()):
@ -334,8 +342,8 @@ class ScanEntry(LayoutWidget):
state = { state = {
"selected": "NoScan", "selected": "NoScan",
"NoScan": {"value": 0.0, "repetitions": 1}, "NoScan": {"value": 0.0, "repetitions": 1},
"LinearScan": {"start": 0.0, "stop": 100.0*scale, "npoints": 10}, "RangeScan": {"start": 0.0, "stop": 100.0*scale, "npoints": 10,
"RandomScan": {"start": 0.0, "stop": 100.0*scale, "npoints": 10}, "randomize": False},
"ExplicitScan": {"sequence": []} "ExplicitScan": {"sequence": []}
} }
if "default" in procdesc: if "default" in procdesc:
@ -348,10 +356,11 @@ class ScanEntry(LayoutWidget):
if ty == "NoScan": if ty == "NoScan":
state[ty]["value"] = default["value"] state[ty]["value"] = default["value"]
state[ty]["repetitions"] = default["repetitions"] state[ty]["repetitions"] = default["repetitions"]
elif ty == "LinearScan" or ty == "RandomScan": elif ty == "RangeScan":
state[ty]["start"] = default["start"] state[ty]["start"] = default["start"]
state[ty]["stop"] = default["stop"] state[ty]["stop"] = default["stop"]
state[ty]["npoints"] = default["npoints"] state[ty]["npoints"] = default["npoints"]
state[ty]["randomize"] = default["randomize"]
elif ty == "ExplicitScan": elif ty == "ExplicitScan":
state[ty]["sequence"] = default["sequence"] state[ty]["sequence"] = default["sequence"]
else: else:

View File

@ -1,7 +1,7 @@
""" """
Implementation and management of scan objects. Implementation and management of scan objects.
A scan object (e.g. :class:`artiq.language.scan.LinearScan`) represents a A scan object (e.g. :class:`artiq.language.scan.RangeScan`) represents a
one-dimensional sweep of a numerical range. Multi-dimensional scans are one-dimensional sweep of a numerical range. Multi-dimensional scans are
constructed by combining several scan objects, for example using constructed by combining several scan objects, for example using
:class:`artiq.language.scan.MultiScanManager`. :class:`artiq.language.scan.MultiScanManager`.
@ -27,7 +27,7 @@ from artiq.language import units
__all__ = ["ScanObject", __all__ = ["ScanObject",
"NoScan", "LinearScan", "RandomScan", "ExplicitScan", "NoScan", "RangeScan", "ExplicitScan",
"Scannable", "MultiScanManager"] "Scannable", "MultiScanManager"]
@ -59,52 +59,28 @@ class NoScan(ScanObject):
"repetitions": self.repetitions} "repetitions": self.repetitions}
class LinearScan(ScanObject): class RangeScan(ScanObject):
"""A scan object that yields a fixed number of evenly """A scan object that yields a fixed number of evenly spaced values in a
spaced values in a range.""" range. If ``randomize`` is True the points are randomly ordered."""
def __init__(self, start, stop, npoints): def __init__(self, start, stop, npoints, randomize=False, seed=None):
self.start = start
self.stop = stop
self.npoints = npoints
@portable
def _gen(self):
if self.npoints == 0:
return
if self.npoints == 1:
yield self.start
else:
dx = (self.stop - self.start)/(self.npoints - 1)
for i in range(self.npoints):
yield i*dx + self.start
@portable
def __iter__(self):
return self._gen()
def __len__(self):
return self.npoints
def describe(self):
return {"ty": "LinearScan",
"start": self.start, "stop": self.stop,
"npoints": self.npoints}
class RandomScan(ScanObject):
"""A scan object that yields a fixed number of randomly ordered evenly
spaced values in a range."""
def __init__(self, start, stop, npoints, seed=None):
self.start = start self.start = start
self.stop = stop self.stop = stop
self.npoints = npoints self.npoints = npoints
self.randomize = randomize
self.seed = seed self.seed = seed
self.sequence = list(LinearScan(start, stop, npoints))
if seed is None: if npoints == 0:
rf = random.random self.sequence = []
if npoints == 1:
self.sequence = [self.start]
else: else:
rf = Random(seed).random dx = (stop - start)/(npoints - 1)
random.shuffle(self.sequence, rf) self.sequence = [i*dx + start for i in range(npoints)]
if randomize:
if seed is not None:
random.seed(seed)
random.shuffle(self.sequence)
@portable @portable
def __iter__(self): def __iter__(self):
@ -114,9 +90,10 @@ class RandomScan(ScanObject):
return self.npoints return self.npoints
def describe(self): def describe(self):
return {"ty": "RandomScan", return {"ty": "RangeScan",
"start": self.start, "stop": self.stop, "start": self.start, "stop": self.stop,
"npoints": self.npoints, "npoints": self.npoints,
"randomize": self.randomize,
"seed": self.seed} "seed": self.seed}
@ -138,8 +115,7 @@ class ExplicitScan(ScanObject):
_ty_to_scan = { _ty_to_scan = {
"NoScan": NoScan, "NoScan": NoScan,
"LinearScan": LinearScan, "RangeScan": RangeScan,
"RandomScan": RandomScan,
"ExplicitScan": ExplicitScan "ExplicitScan": ExplicitScan
} }