2
0
forked from awendt/pyrelacs

adding threading to fix segementation fault

This commit is contained in:
wendtalexander 2024-09-18 10:25:22 +02:00
parent 25cd1c0585
commit e975bcd7e1
2 changed files with 114 additions and 14 deletions

View File

@ -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__":

84
pyrelacs/daq_thread.py Normal file
View File

@ -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