forked from M-Labs/artiq
experiment/gui: support reverse scan (closes #246)
This commit is contained in:
parent
2859382e11
commit
33da27a749
|
@ -10,9 +10,13 @@ Release notes
|
|||
* Core device flash storage has moved due to increased runtime size.
|
||||
This requires reflashing the runtime and the flash storage filesystem image
|
||||
or erase and rewrite its entries.
|
||||
* RTIOCollisionError has been renamed to RTIOCollision
|
||||
* the new API for DDS batches is:
|
||||
* ``RTIOCollisionError`` has been renamed to ``RTIOCollision``
|
||||
* the new API for DDS batches is::
|
||||
with self.core_dds.batch:
|
||||
...
|
||||
with core_dds a device of type artiq.coredevice.dds.CoreDDS.
|
||||
|
||||
with ``core_dds`` a device of type ``artiq.coredevice.dds.CoreDDS``.
|
||||
The dds_bus device should not be used anymore.
|
||||
* LinearScan now supports scanning from high to low. Accordingly,
|
||||
it's arguments ``min/max`` have been renamed to ``start/stop`` respectively.
|
||||
Same for RandomScan (even though there direction matters little).
|
||||
|
|
|
@ -154,52 +154,52 @@ class _RangeScan(LayoutWidget):
|
|||
if procdesc["unit"]:
|
||||
spinbox.setSuffix(" " + procdesc["unit"])
|
||||
|
||||
self.scanner = scanner = ScanWidget()
|
||||
scanner = ScanWidget()
|
||||
disable_scroll_wheel(scanner)
|
||||
self.addWidget(scanner, 0, 0, -1, 1)
|
||||
|
||||
self.min = ScientificSpinBox()
|
||||
self.min.setStyleSheet("QDoubleSpinBox {color:blue}")
|
||||
self.min.setMinimumSize(110, 0)
|
||||
self.min.setSizePolicy(QtWidgets.QSizePolicy(
|
||||
start = ScientificSpinBox()
|
||||
start.setStyleSheet("QDoubleSpinBox {color:blue}")
|
||||
start.setMinimumSize(110, 0)
|
||||
start.setSizePolicy(QtWidgets.QSizePolicy(
|
||||
QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed))
|
||||
disable_scroll_wheel(self.min)
|
||||
self.addWidget(self.min, 0, 1)
|
||||
disable_scroll_wheel(start)
|
||||
self.addWidget(start, 0, 1)
|
||||
|
||||
self.npoints = QtWidgets.QSpinBox()
|
||||
self.npoints.setMinimum(1)
|
||||
disable_scroll_wheel(self.npoints)
|
||||
self.addWidget(self.npoints, 1, 1)
|
||||
npoints = QtWidgets.QSpinBox()
|
||||
npoints.setMinimum(1)
|
||||
disable_scroll_wheel(npoints)
|
||||
self.addWidget(npoints, 1, 1)
|
||||
|
||||
self.max = ScientificSpinBox()
|
||||
self.max.setStyleSheet("QDoubleSpinBox {color:red}")
|
||||
self.max.setMinimumSize(110, 0)
|
||||
disable_scroll_wheel(self.max)
|
||||
self.addWidget(self.max, 2, 1)
|
||||
stop = ScientificSpinBox()
|
||||
stop.setStyleSheet("QDoubleSpinBox {color:red}")
|
||||
stop.setMinimumSize(110, 0)
|
||||
disable_scroll_wheel(stop)
|
||||
self.addWidget(stop, 2, 1)
|
||||
|
||||
def update_min(value):
|
||||
state["min"] = value*scale
|
||||
def update_start(value):
|
||||
state["start"] = value*scale
|
||||
scanner.setStart(value)
|
||||
|
||||
def update_max(value):
|
||||
state["max"] = value*scale
|
||||
def update_stop(value):
|
||||
state["stop"] = value*scale
|
||||
scanner.setStop(value)
|
||||
|
||||
def update_npoints(value):
|
||||
state["npoints"] = value
|
||||
scanner.setNum(value)
|
||||
|
||||
scanner.startChanged.connect(self.min.setValue)
|
||||
scanner.numChanged.connect(self.npoints.setValue)
|
||||
scanner.stopChanged.connect(self.max.setValue)
|
||||
self.min.valueChanged.connect(update_min)
|
||||
self.npoints.valueChanged.connect(update_npoints)
|
||||
self.max.valueChanged.connect(update_max)
|
||||
scanner.setStart(state["min"]/scale)
|
||||
scanner.startChanged.connect(start.setValue)
|
||||
scanner.numChanged.connect(npoints.setValue)
|
||||
scanner.stopChanged.connect(stop.setValue)
|
||||
start.valueChanged.connect(update_start)
|
||||
npoints.valueChanged.connect(update_npoints)
|
||||
stop.valueChanged.connect(update_stop)
|
||||
scanner.setStart(state["start"]/scale)
|
||||
scanner.setNum(state["npoints"])
|
||||
scanner.setStop(state["max"]/scale)
|
||||
apply_properties(self.min)
|
||||
apply_properties(self.max)
|
||||
scanner.setStop(state["stop"]/scale)
|
||||
apply_properties(start)
|
||||
apply_properties(stop)
|
||||
|
||||
|
||||
class _ExplicitScan(LayoutWidget):
|
||||
|
@ -266,8 +266,8 @@ class _ScanEntry(LayoutWidget):
|
|||
state = {
|
||||
"selected": "NoScan",
|
||||
"NoScan": {"value": 0.0},
|
||||
"LinearScan": {"min": 0.0, "max": 100.0*scale, "npoints": 10},
|
||||
"RandomScan": {"min": 0.0, "max": 100.0*scale, "npoints": 10},
|
||||
"LinearScan": {"start": 0.0, "stop": 100.0*scale, "npoints": 10},
|
||||
"RandomScan": {"start": 0.0, "stop": 100.0*scale, "npoints": 10},
|
||||
"ExplicitScan": {"sequence": []}
|
||||
}
|
||||
if "default" in procdesc:
|
||||
|
@ -278,8 +278,8 @@ class _ScanEntry(LayoutWidget):
|
|||
state["NoScan"]["value"] = default["value"]
|
||||
elif ty == "LinearScan" or ty == "RandomScan":
|
||||
for d in state["LinearScan"], state["RandomScan"]:
|
||||
d["min"] = default["min"]
|
||||
d["max"] = default["max"]
|
||||
d["start"] = default["start"]
|
||||
d["stop"] = default["stop"]
|
||||
d["npoints"] = default["npoints"]
|
||||
elif ty == "ExplicitScan":
|
||||
state["ExplicitScan"]["sequence"] = default["sequence"]
|
||||
|
|
|
@ -11,7 +11,7 @@ Iterate on a scan object to scan it, e.g. ::
|
|||
do_something(variable)
|
||||
|
||||
Iterating multiple times on the same scan object is possible, with the scan
|
||||
restarting at the minimum value each time. Iterating concurrently on the
|
||||
yielding the same values each time. Iterating concurrently on the
|
||||
same scan object (e.g. via nested loops) is also supported, and the
|
||||
iterators are independent from each other.
|
||||
|
||||
|
@ -55,21 +55,23 @@ class NoScan(ScanObject):
|
|||
|
||||
|
||||
class LinearScan(ScanObject):
|
||||
"""A scan object that yields a fixed number of increasing evenly
|
||||
"""A scan object that yields a fixed number of evenly
|
||||
spaced values in a range."""
|
||||
def __init__(self, min, max, npoints):
|
||||
if min > max:
|
||||
raise ValueError("Scan minimum must be less than maximum")
|
||||
self.min = min
|
||||
self.max = max
|
||||
def __init__(self, start, stop, npoints):
|
||||
self.start = start
|
||||
self.stop = stop
|
||||
self.npoints = npoints
|
||||
|
||||
@portable
|
||||
def _gen(self):
|
||||
r = self.max - self.min
|
||||
d = self.npoints - 1
|
||||
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 r*i/d + self.min
|
||||
yield i*dx + self.start
|
||||
|
||||
@portable
|
||||
def __iter__(self):
|
||||
|
@ -80,19 +82,18 @@ class LinearScan(ScanObject):
|
|||
|
||||
def describe(self):
|
||||
return {"ty": "LinearScan",
|
||||
"min": self.min, "max": self.max, "npoints": self.npoints}
|
||||
"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, min, max, npoints, seed=0):
|
||||
if min > max:
|
||||
raise ValueError("Scan minimum must be less than maximum")
|
||||
self.min = min
|
||||
self.max = max
|
||||
def __init__(self, start, stop, npoints, seed=0):
|
||||
self.start = start
|
||||
self.stop = stop
|
||||
self.npoints = npoints
|
||||
self.sequence = list(LinearScan(min, max, npoints))
|
||||
self.sequence = list(LinearScan(start, stop, npoints))
|
||||
shuffle(self.sequence, Random(seed).random)
|
||||
|
||||
@portable
|
||||
|
@ -104,7 +105,8 @@ class RandomScan(ScanObject):
|
|||
|
||||
def describe(self):
|
||||
return {"ty": "RandomScan",
|
||||
"min": self.min, "max": self.max, "npoints": self.npoints}
|
||||
"start": self.start, "stop": self.stop,
|
||||
"npoints": self.npoints}
|
||||
|
||||
|
||||
class ExplicitScan(ScanObject):
|
||||
|
@ -142,8 +144,8 @@ 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 user
|
||||
interface (UI) purposes.
|
||||
:param unit: A string representing the unit of the scanned variable, for
|
||||
user interface (UI) purposes.
|
||||
:param scale: The scale of value for UI purposes. The displayed value is
|
||||
divided by the scale.
|
||||
:param ndecimals: The number of decimals a UI should use.
|
||||
|
|
Loading…
Reference in New Issue