diff --git a/pyrelacs/app.py b/pyrelacs/app.py index 9c7dad5..6ab1200 100644 --- a/pyrelacs/app.py +++ b/pyrelacs/app.py @@ -1,8 +1,9 @@ from PyQt6.QtGui import QAction import sys import pathlib +import ctypes -from PyQt6.QtCore import QSize, Qt +from PyQt6.QtCore import QSize, QThreadPool, Qt from PyQt6.QtWidgets import ( QApplication, QGridLayout, @@ -17,6 +18,7 @@ from IPython import embed import numpy as np from pyrelacs.util.logging import config_logging +from pyrelacs.daq_thread import Worker log = config_logging() @@ -25,6 +27,7 @@ class PyRelacs(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("PyRelacs") + self.threadpool = QThreadPool() self.daq_connect_button = QPushButton("Connect Daq") self.daq_connect_button.setCheckable(True) @@ -92,22 +95,35 @@ class PyRelacs(QMainWindow): self.toolbar.addAction(individual_repro_button) def run_repro(self): + daq_thread = Worker(self.read_daq) + self.threadpool.start(daq_thread) + + def on_scan_finished(self): + log.debug("Scan finished") + + def read_daq(self, progress_callback): log.debug("running repro") - time = np.arange( - 0, self.config["Sinus"]["duration"], 1 / self.config["Sinus"]["fs"] - ) - data = self.config["Sinus"]["amplitude"] * np.sin( - 2 * np.pi * self.config["Sinus"]["freq"] * time - ) + time = np.arange(0, 10, 1 / 30_000.0) + data = 2 * np.sin(2 * np.pi * 10 * time) + + buffer = ctypes.c_double * len(time) + data_c = buffer(*data) + log.debug(f"Created C_double data {data_c}") ao_device = self.daq_device.get_ao_device() - ao_info = ao_device.get_info() - try: - err = ao_device.a_out_list( - 0, 0, [uldaq.Range.BIP2VOLTS], uldaq.AOutListFlag.DEFAULT, data - ) - except uldaq.ULException as e: - print(e) + + err = ao_device.a_out_scan( + 0, + 0, + uldaq.Range.BIP10VOLTS, + int(len(data)), + 30_000.0, + uldaq.ScanOption.DEFAULTIO, + uldaq.AOutScanFlag.DEFAULT, + data_c, + ) + while ao_device.get_scan_status()[0] == 1: + log.debug("Still running") if __name__ == "__main__": diff --git a/pyrelacs/daq_thread.py b/pyrelacs/daq_thread.py new file mode 100644 index 0000000..0823fbb --- /dev/null +++ b/pyrelacs/daq_thread.py @@ -0,0 +1,84 @@ +import pathlib + +import tomli +from PyQt6.QtCore import QRunnable, QThread, pyqtSignal, pyqtSlot, QObject +import ctypes +import uldaq +import numpy as np +from IPython import embed +import traceback, sys + +from pyrelacs.util.logging import config_logging + +log = config_logging() + + +class WorkerSignals(QObject): + """ + Defines the signals available from a running worker thread. + + Supported signals are: + + finished + No data + + error + tuple (exctype, value, traceback.format_exc() ) + + result + object data returned from processing, anything + + progress + int indicating % progress + + """ + + finished = pyqtSignal() + error = pyqtSignal(tuple) + result = pyqtSignal(object) + progress = pyqtSignal(int) + + +class Worker(QRunnable): + """ + Worker thread + + Inherits from QRunnable to handler worker thread setup, signals and wrap-up. + + :param callback: The function callback to run on this worker thread. Supplied args and + kwargs will be passed through to the runner. + :type callback: function + :param args: Arguments to pass to the callback function + :param kwargs: Keywords to pass to the callback function + + """ + + def __init__(self, fn, *args, **kwargs): + super(Worker, self).__init__() + + # Store constructor arguments (re-used for processing) + self.fn = fn + self.args = args + self.kwargs = kwargs + self.signals = WorkerSignals() + + # Add the callback to our kwargs + self.kwargs["progress_callback"] = self.signals.progress + + @pyqtSlot() + def run(self): + """ + Initialise the runner function with passed args, kwargs. + """ + + # Retrieve args/kwargs here; and fire processing using them + try: + result = self.fn(*self.args, **self.kwargs) + except: + traceback.print_exc() + exctype, value = sys.exc_info()[:2] + self.signals.error.emit((exctype, value, traceback.format_exc())) + else: + self.signals.result.emit(result) # Return the result of the processing + finally: + self.signals.finished.emit() # Done