mirror of https://github.com/m-labs/artiq.git
gui: support X axis, fit, error bars in XY plot
This commit is contained in:
parent
7180552d24
commit
263ff86e66
|
@ -1,4 +1,5 @@
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
from quamash import QtGui
|
from quamash import QtGui
|
||||||
import pyqtgraph as pg
|
import pyqtgraph as pg
|
||||||
|
@ -47,24 +48,30 @@ class _SimpleSettings(_BaseSettings):
|
||||||
_BaseSettings.__init__(self, parent, self._window_title,
|
_BaseSettings.__init__(self, parent, self._window_title,
|
||||||
prev_name, create_cb)
|
prev_name, create_cb)
|
||||||
|
|
||||||
self.grid.addWidget(QtGui.QLabel("Result:"))
|
self.result_widgets = dict()
|
||||||
self.result = QtGui.QComboBox()
|
for row, (has_none, key) in enumerate(self._result_keys):
|
||||||
self.grid.addWidget(self.result, 1, 1)
|
self.grid.addWidget(QtGui.QLabel(key.capitalize() + ":"))
|
||||||
self.result.addItems(result_list)
|
w = QtGui.QComboBox()
|
||||||
self.result.setEditable(True)
|
self.grid.addWidget(w, row + 1, 1)
|
||||||
if "result" in prev_settings:
|
if has_none:
|
||||||
self.result.setEditText(prev_settings["result"])
|
w.addItem("<None>")
|
||||||
|
w.addItems(result_list)
|
||||||
|
w.setEditable(True)
|
||||||
|
if key in prev_settings:
|
||||||
|
w.setEditText(prev_settings[key])
|
||||||
|
self.result_widgets[key] = w
|
||||||
self.add_buttons()
|
self.add_buttons()
|
||||||
|
|
||||||
def validate_input(self):
|
def validate_input(self):
|
||||||
return bool(self.result.currentText())
|
return all(w.currentText() for w in self.result_widgets.values())
|
||||||
|
|
||||||
def get_input(self):
|
def get_input(self):
|
||||||
return {"result": self.result.currentText()}
|
return {k: v.currentText() for k, v in self.result_widgets.items()}
|
||||||
|
|
||||||
|
|
||||||
class NumberDisplaySettings(_SimpleSettings):
|
class NumberDisplaySettings(_SimpleSettings):
|
||||||
_window_title = "Number display"
|
_window_title = "Number display"
|
||||||
|
_result_keys = [(False, "result")]
|
||||||
|
|
||||||
|
|
||||||
class NumberDisplay(dockarea.Dock):
|
class NumberDisplay(dockarea.Dock):
|
||||||
|
@ -90,6 +97,7 @@ class NumberDisplay(dockarea.Dock):
|
||||||
|
|
||||||
class XYDisplaySettings(_SimpleSettings):
|
class XYDisplaySettings(_SimpleSettings):
|
||||||
_window_title = "XY plot"
|
_window_title = "XY plot"
|
||||||
|
_result_keys = [(False, "y"), (True, "x"), (True, "error"), (True, "fit")]
|
||||||
|
|
||||||
|
|
||||||
class XYDisplay(dockarea.Dock):
|
class XYDisplay(dockarea.Dock):
|
||||||
|
@ -101,44 +109,56 @@ class XYDisplay(dockarea.Dock):
|
||||||
self.addWidget(self.plot)
|
self.addWidget(self.plot)
|
||||||
|
|
||||||
def data_sources(self):
|
def data_sources(self):
|
||||||
return {self.settings["result"]}
|
s = {self.settings["y"]}
|
||||||
|
for k in "x", "error", "fit":
|
||||||
|
if self.settings[k] != "<None>":
|
||||||
|
s.add(self.settings[k])
|
||||||
|
return s
|
||||||
|
|
||||||
def update_data(self, data):
|
def update_data(self, data):
|
||||||
result = self.settings["result"]
|
result_y = self.settings["y"]
|
||||||
|
result_x = self.settings["x"]
|
||||||
|
result_error = self.settings["error"]
|
||||||
|
result_fit = self.settings["fit"]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
y = data[result]
|
y = data[result_y]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return
|
return
|
||||||
self.plot.clear()
|
x = data.get(result_x, None)
|
||||||
if not y:
|
if x is None:
|
||||||
|
x = list(range(len(y)))
|
||||||
|
error = data.get(result_error, None)
|
||||||
|
fit = data.get(result_fit, None)
|
||||||
|
|
||||||
|
if not y or len(y) != len(x):
|
||||||
return
|
return
|
||||||
self.plot.plot(y)
|
if error is not None and hasattr(error, "__len__"):
|
||||||
|
if not len(error):
|
||||||
|
error = None
|
||||||
|
elif len(error) != len(y):
|
||||||
|
return
|
||||||
|
if fit is not None:
|
||||||
|
if not len(fit):
|
||||||
|
fit = None
|
||||||
|
elif len(fit) != len(y):
|
||||||
|
return
|
||||||
|
|
||||||
|
self.plot.clear()
|
||||||
|
self.plot.plot(x, y, pen=None, symbol="x")
|
||||||
|
if error is not None:
|
||||||
|
# See https://github.com/pyqtgraph/pyqtgraph/issues/211
|
||||||
|
if hasattr(error, "__len__") and not isinstance(error, np.ndarray):
|
||||||
|
error = np.array(error)
|
||||||
|
errbars = pg.ErrorBarItem(x=np.array(x), y=np.array(y), height=error)
|
||||||
|
self.plot.addItem(errbars)
|
||||||
|
if fit is not None:
|
||||||
|
self.plot.plot(x, fit)
|
||||||
|
|
||||||
|
|
||||||
class HistogramDisplaySettings(_BaseSettings):
|
class HistogramDisplaySettings(_SimpleSettings):
|
||||||
def __init__(self, parent, prev_name, prev_settings,
|
_window_title = "Histogram"
|
||||||
result_list, create_cb):
|
_result_keys = [(False, "y"), (True, "x")]
|
||||||
_BaseSettings.__init__(self, parent, "Histogram",
|
|
||||||
prev_name, create_cb)
|
|
||||||
|
|
||||||
for row, axis in enumerate("yx"):
|
|
||||||
self.grid.addWidget(QtGui.QLabel(axis.upper() + ":"))
|
|
||||||
w = QtGui.QComboBox()
|
|
||||||
self.grid.addWidget(w, row + 1, 1)
|
|
||||||
if axis == "x":
|
|
||||||
w.addItem("<None>")
|
|
||||||
w.addItems(result_list)
|
|
||||||
w.setEditable(True)
|
|
||||||
if axis in prev_settings:
|
|
||||||
w.setEditText(prev_settings["y"])
|
|
||||||
setattr(self, axis, w)
|
|
||||||
self.add_buttons()
|
|
||||||
|
|
||||||
def validate_input(self):
|
|
||||||
return bool(self.y.currentText()) and bool(self.x.currentText())
|
|
||||||
|
|
||||||
def get_input(self):
|
|
||||||
return {"y": self.y.currentText(), "x": self.x.currentText()}
|
|
||||||
|
|
||||||
|
|
||||||
class HistogramDisplay(dockarea.Dock):
|
class HistogramDisplay(dockarea.Dock):
|
||||||
|
|
Loading…
Reference in New Issue