mirror of
https://github.com/m-labs/artiq.git
synced 2025-01-13 12:28:54 +08:00
9fbd6de30c
Some changes are due to deprecations in Qt6 which were outright removed in PyQt, for instance QRegExp or the x()/y() QMouseEvent properties. Most of the diff is due to enumeration values now no longer being available directly in the parent namespace. This commit is purposefully restricted to the mechanical changes, no reformatting/… is done to keep the diff easy to validate.
90 lines
2.9 KiB
Python
Executable File
90 lines
2.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import numpy as np
|
|
import PyQt6 # make sure pyqtgraph imports Qt6
|
|
from PyQt6.QtCore import QTimer
|
|
import pyqtgraph
|
|
|
|
from artiq.applets.simple import TitleApplet
|
|
|
|
|
|
class XYPlot(pyqtgraph.PlotWidget):
|
|
def __init__(self, args, req):
|
|
pyqtgraph.PlotWidget.__init__(self)
|
|
self.args = args
|
|
self.timer = QTimer()
|
|
self.timer.setSingleShot(True)
|
|
self.timer.timeout.connect(self.length_warning)
|
|
self.mismatch = {'X values': False,
|
|
'Error bars': False,
|
|
'Fit values': False}
|
|
|
|
def data_changed(self, value, metadata, persist, mods, title):
|
|
try:
|
|
y = value[self.args.y]
|
|
except KeyError:
|
|
return
|
|
x = value.get(self.args.x)
|
|
if x is None:
|
|
x = np.arange(len(y))
|
|
error = value.get(self.args.error)
|
|
fit = value.get(self.args.fit)
|
|
|
|
if not len(y) or len(y) != len(x):
|
|
self.mismatch['X values'] = True
|
|
else:
|
|
self.mismatch['X values'] = False
|
|
if error is not None and hasattr(error, "__len__"):
|
|
if not len(error):
|
|
error = None
|
|
elif len(error) != len(y):
|
|
self.mismatch['Error bars'] = True
|
|
else:
|
|
self.mismatch['Error bars'] = False
|
|
if fit is not None:
|
|
if not len(fit):
|
|
fit = None
|
|
elif len(fit) != len(y):
|
|
self.mismatch['Fit values'] = True
|
|
else:
|
|
self.mismatch['Fit values'] = False
|
|
if not any(self.mismatch.values()):
|
|
self.timer.stop()
|
|
else:
|
|
if not self.timer.isActive():
|
|
self.timer.start(1000)
|
|
return
|
|
|
|
self.clear()
|
|
self.plot(x, y, pen=None, symbol="x")
|
|
self.setTitle(title)
|
|
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 = pyqtgraph.ErrorBarItem(
|
|
x=np.array(x), y=np.array(y), height=error)
|
|
self.addItem(errbars)
|
|
if fit is not None:
|
|
xi = np.argsort(x)
|
|
self.plot(x[xi], fit[xi])
|
|
|
|
def length_warning(self):
|
|
self.clear()
|
|
text = "⚠️ dataset lengths mismatch:\n"
|
|
errors = ', '.join([k for k, v in self.mismatch.items() if v])
|
|
text = ' '.join([errors, "should have the same length as Y values"])
|
|
self.addItem(pyqtgraph.TextItem(text))
|
|
|
|
|
|
def main():
|
|
applet = TitleApplet(XYPlot)
|
|
applet.add_dataset("y", "Y values")
|
|
applet.add_dataset("x", "X values", required=False)
|
|
applet.add_dataset("error", "Error bars for each X value", required=False)
|
|
applet.add_dataset("fit", "Fit values for each X value", required=False)
|
|
applet.run()
|
|
|
|
if __name__ == "__main__":
|
|
main()
|