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
|
||||
raising exceptions.
|
||||
* Results are still saved when ``analyze`` raises an exception.
|
||||
|
||||
* LinearScan and RandomScan have been consolidated into RangeScan
|
||||
|
||||
2.2
|
||||
---
|
||||
|
@ -229,6 +229,9 @@ class _RangeScan(LayoutWidget):
|
||||
disable_scroll_wheel(stop)
|
||||
self.addWidget(stop, 2, 1)
|
||||
|
||||
randomize = QtWidgets.QCheckBox("Randomize")
|
||||
self.addWidget(randomize, 3, 1)
|
||||
|
||||
apply_properties(start)
|
||||
start.setPrecision()
|
||||
start.setRelativeStep()
|
||||
@ -255,15 +258,22 @@ class _RangeScan(LayoutWidget):
|
||||
if npoints.value() != value:
|
||||
npoints.setValue(value)
|
||||
|
||||
def update_randomize(value):
|
||||
state["randomize"] = value
|
||||
if randomize.isChecked() != value:
|
||||
randomize.setChecked(value)
|
||||
|
||||
scanner.startChanged.connect(update_start)
|
||||
scanner.numChanged.connect(update_npoints)
|
||||
scanner.stopChanged.connect(update_stop)
|
||||
start.valueChanged.connect(update_start)
|
||||
npoints.valueChanged.connect(update_npoints)
|
||||
stop.valueChanged.connect(update_stop)
|
||||
randomize.stateChanged.connect(update_randomize)
|
||||
scanner.setStart(state["start"]/scale)
|
||||
scanner.setNum(state["npoints"])
|
||||
scanner.setStop(state["stop"]/scale)
|
||||
randomize.setChecked(state["randomize"])
|
||||
|
||||
|
||||
class _ExplicitScan(LayoutWidget):
|
||||
@ -297,16 +307,14 @@ class ScanEntry(LayoutWidget):
|
||||
state = argument["state"]
|
||||
self.widgets = OrderedDict()
|
||||
self.widgets["NoScan"] = _NoScan(procdesc, state["NoScan"])
|
||||
self.widgets["LinearScan"] = _RangeScan(procdesc, state["LinearScan"])
|
||||
self.widgets["RandomScan"] = _RangeScan(procdesc, state["RandomScan"])
|
||||
self.widgets["RangeScan"] = _RangeScan(procdesc, state["RangeScan"])
|
||||
self.widgets["ExplicitScan"] = _ExplicitScan(state["ExplicitScan"])
|
||||
for widget in self.widgets.values():
|
||||
self.stack.addWidget(widget)
|
||||
|
||||
self.radiobuttons = OrderedDict()
|
||||
self.radiobuttons["NoScan"] = QtWidgets.QRadioButton("No scan")
|
||||
self.radiobuttons["LinearScan"] = QtWidgets.QRadioButton("Linear")
|
||||
self.radiobuttons["RandomScan"] = QtWidgets.QRadioButton("Random")
|
||||
self.radiobuttons["RangeScan"] = QtWidgets.QRadioButton("Range")
|
||||
self.radiobuttons["ExplicitScan"] = QtWidgets.QRadioButton("Explicit")
|
||||
scan_type = QtWidgets.QButtonGroup()
|
||||
for n, b in enumerate(self.radiobuttons.values()):
|
||||
@ -334,8 +342,8 @@ class ScanEntry(LayoutWidget):
|
||||
state = {
|
||||
"selected": "NoScan",
|
||||
"NoScan": {"value": 0.0, "repetitions": 1},
|
||||
"LinearScan": {"start": 0.0, "stop": 100.0*scale, "npoints": 10},
|
||||
"RandomScan": {"start": 0.0, "stop": 100.0*scale, "npoints": 10},
|
||||
"RangeScan": {"start": 0.0, "stop": 100.0*scale, "npoints": 10,
|
||||
"randomize": False},
|
||||
"ExplicitScan": {"sequence": []}
|
||||
}
|
||||
if "default" in procdesc:
|
||||
@ -348,10 +356,11 @@ class ScanEntry(LayoutWidget):
|
||||
if ty == "NoScan":
|
||||
state[ty]["value"] = default["value"]
|
||||
state[ty]["repetitions"] = default["repetitions"]
|
||||
elif ty == "LinearScan" or ty == "RandomScan":
|
||||
elif ty == "RangeScan":
|
||||
state[ty]["start"] = default["start"]
|
||||
state[ty]["stop"] = default["stop"]
|
||||
state[ty]["npoints"] = default["npoints"]
|
||||
state[ty]["randomize"] = default["randomize"]
|
||||
elif ty == "ExplicitScan":
|
||||
state[ty]["sequence"] = default["sequence"]
|
||||
else:
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
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
|
||||
constructed by combining several scan objects, for example using
|
||||
:class:`artiq.language.scan.MultiScanManager`.
|
||||
@ -27,7 +27,7 @@ from artiq.language import units
|
||||
|
||||
|
||||
__all__ = ["ScanObject",
|
||||
"NoScan", "LinearScan", "RandomScan", "ExplicitScan",
|
||||
"NoScan", "RangeScan", "ExplicitScan",
|
||||
"Scannable", "MultiScanManager"]
|
||||
|
||||
|
||||
@ -59,52 +59,28 @@ class NoScan(ScanObject):
|
||||
"repetitions": self.repetitions}
|
||||
|
||||
|
||||
class LinearScan(ScanObject):
|
||||
"""A scan object that yields a fixed number of evenly
|
||||
spaced values in a range."""
|
||||
def __init__(self, start, stop, npoints):
|
||||
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):
|
||||
class RangeScan(ScanObject):
|
||||
"""A scan object that yields a fixed number of evenly spaced values in a
|
||||
range. If ``randomize`` is True the points are randomly ordered."""
|
||||
def __init__(self, start, stop, npoints, randomize=False, seed=None):
|
||||
self.start = start
|
||||
self.stop = stop
|
||||
self.npoints = npoints
|
||||
self.randomize = randomize
|
||||
self.seed = seed
|
||||
self.sequence = list(LinearScan(start, stop, npoints))
|
||||
if seed is None:
|
||||
rf = random.random
|
||||
|
||||
if npoints == 0:
|
||||
self.sequence = []
|
||||
if npoints == 1:
|
||||
self.sequence = [self.start]
|
||||
else:
|
||||
rf = Random(seed).random
|
||||
random.shuffle(self.sequence, rf)
|
||||
dx = (stop - start)/(npoints - 1)
|
||||
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
|
||||
def __iter__(self):
|
||||
@ -114,9 +90,10 @@ class RandomScan(ScanObject):
|
||||
return self.npoints
|
||||
|
||||
def describe(self):
|
||||
return {"ty": "RandomScan",
|
||||
return {"ty": "RangeScan",
|
||||
"start": self.start, "stop": self.stop,
|
||||
"npoints": self.npoints,
|
||||
"randomize": self.randomize,
|
||||
"seed": self.seed}
|
||||
|
||||
|
||||
@ -138,8 +115,7 @@ class ExplicitScan(ScanObject):
|
||||
|
||||
_ty_to_scan = {
|
||||
"NoScan": NoScan,
|
||||
"LinearScan": LinearScan,
|
||||
"RandomScan": RandomScan,
|
||||
"RangeScan": RangeScan,
|
||||
"ExplicitScan": ExplicitScan
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user