forked from M-Labs/artiq
language,gui: combine LinearScan and RandomScan into RangeScan. Closes #679
This commit is contained in:
parent
28211e0b32
commit
07c71bf020
|
@ -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
|
||||||
---
|
---
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue