2
0
mirror of https://github.com/m-labs/artiq.git synced 2025-01-13 12:28:54 +08:00
artiq/artiq/applets/plot_xy.py
David Nadlinger 9fbd6de30c Qt{5 -> 6}
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.
2024-07-27 21:37:19 +08:00

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()