0

I am currently building software to receive data from device and plotting on my GUI real-time. This set of data is coming as a list from the device. I have looked up many methods and seems like "timer" is useful. However, when I tried to use it to plot, it does not work and crash. Following is my thread of receiving data from device. freq and sweep_max is defined from device API file.

class Worker(QThread):
    signal_x = pyqtSignal(object, object)


    def __init__(self):
        super().__init__()


    def run(self):
        while True:

            self.data_x = freqs
            self.data_y = sweep_max
            self.signal_x.emit(self.data_x, self.data_y)
            time.sleep(0.1)

And following is my Main python file with GUI.

import sys
from PyQt5.QtCore import *
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtWidgets import *
import LLAGUI1
from SignalThread import MyWidget, Worker

from sadevice.sa_api import *


from PyQt5 import QtCore, QtWidgets
import pyqtgraph as pg



class MainClass(QDialog,LLAGUI1.Ui_Dialog):

    def __init__(self):
        super().__init__()
        self.setupUi(self)

        ############Part of real time plotting but getting error because of plotCurve has no input
        self.timer = QtCore.QTimer(self)
        self.timer.setInterval(100) # in milliseconds
        self.timer.start()
        self.timer.timeout.connect(self.plotCurve)
        #############################################################################
        
        self.mywid = pg.GraphicsWindow()
        self.plotItem = self.mywid.addPlot(title="Linewidth Measurement")
        self.plotDataItem = self.plotItem.plot([], symbolSize=1, symbolPen=None)
        self.graphWidget.addItem(self.plotDataItem)
        self.make_connection()


    def make_connection(self):
        self.w = Worker()
        self.w.start()
        self.w.signal_x.connect(self.plotCurve)


    def plotCurve(self, x, y):
        self.plotDataItem.setData(x,y)
        print(x)
        print(y)


if __name__=='__main__':
    app=QApplication(sys.argv)


    lla=MainClass()
    lla.show()
    app.exec_()

I am getting error with following part of my code because there is no input of plotCurve. Without following 4lines, curve is not real time and it just plot and stop even tho it is keep receiving the data. I tried to put make_connection there but it also gives me error.

self.timer = QtCore.QTimer(self)
        self.timer.setInterval(100) # in milliseconds
        self.timer.start()
        self.timer.timeout.connect(self.plotCurve)

Please save me from this threading error, I really appreciate any idea! Thank you!

GUIsoft
  • 33
  • 6
  • You're accessing an attribute that is not defined. Where do you set the attribute `MainClass.plotCurve`? – bnaecker Dec 07 '20 at 23:14
  • @bnaecker I am not sure whether I am understanding your question correctly. Did you mean I did not defined `plotCurve` ? If so, it is defined within the `MainClass` if you scroll down. If you meant the inputs of `plotCurve`, it is not set and I do not know where to set it cuz that supposed to be real time inputs. `make_connection` is receiving thread data and passing to `plotCurve`. – GUIsoft Dec 07 '20 at 23:37
  • Ahh, I missed that, ignore me :) – bnaecker Dec 08 '20 at 00:38

1 Answers1

0

Okay, After searching and searching, post of this helped a lot!

For those who may struggle with similar issue, followings are my revised code. I was not understanding fully about the pyqtSlot correctly.

class MainClass(QDialog,LLAGUI1.Ui_Dialog):

    def __init__(self):
        super().__init__()
        self.setupUi(self)

        self.worker = Worker()
        self.make_connection(self.worker)
        self.worker.start()
        self.graph = pg.PlotWidget()
        self.graph.setYRange(-120,10)
        self.plot = self.graph.plot()
        self.gridLayout_graph.addWidget(self.graph, 0, 0)
        self.show()

        self.pushButton_amp_set.clicked.connect(self.setAmp)


    def make_connection(self, data_object):
        data_object.signal.connect(self.grab_data)

    @pyqtSlot(object, object)
    def grab_data(self, data, data1):
        print(data)
        print(data1)
        self.plot.setData(data, data1)

    #
    # def onStart(self):
    #     self.curve = MyWidget()
    #     # self.verticalLayout_3.
    #     self.verticalLayout_3.addWidget(self.curve)

    def setAmp(self):
        Min = float(self.lineEdit_amp_min.text())
        Max = float(self.lineEdit_amp_max.text())
        self.graph.setYRange(Min, Max)

    def CenterSpan(self):
        center = int(self.lineEdit_freq_center.text())
        span = int(self.lineEdit_freq_span.text())

        sa_config_center_span(handle, center, span)
        # self.w = MyWidget()






if __name__=='__main__':
    app=QApplication(sys.argv)

    lla=MainClass()
    lla.show()

    app.exec_()

And worker Thread is like following:

class Worker(QThread):
    signal = pyqtSignal(object, object)

    def __init__(self):
        super().__init__()

    def run(self):
        while True:
            freqs = [start_freq + i * bin_size for i in range(sweep_length)]
            sweep_max = list(sa_get_sweep_32f(handle)["max"])
            self.data_x = freqs
            self.data_y = sweep_max
            self.signal.emit(self.data_x, self.data_y)
            time.sleep(0.01)
GUIsoft
  • 33
  • 6