0

So what I'm currently trying to do is to create a class I can use for real time plotting of any kind. In principle I just want to call the class variable and use a command like set_data(x,y). The problem I encountered is that I need to use python threading to update the displayed graphs. But when I use threading like in the code below the pyqtgraph window doesn't respond anymore when executing the while True part at the end of my code where I want to update the plotted graph data. Is there an alternative way to update the graphs instead of my not working thread method? I read about the QtCore timer but this method also crashes like the normal threading I'm using here.

import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
import numpy as np
import random
import threading
import time

from pyqtgraph.dockarea import *


class liveplot(threading.Thread):
    def __init__(self, updating_time__s=0.01):
        """
        Contructor of the liveplot class

        """
        self.app = pg.mkQApp("DockArea Example")
        self.win = QtGui.QMainWindow()
        self.area = DockArea()
        self.win.setCentralWidget(self.area)
        self.win.resize(1000, 500)
        self.win.setWindowTitle('pyqtgraph example: dockarea')

        threading.Thread.__init__(self)     # Init thread class
        self._lock = threading.Lock()       # Needed to prevent data races in threads.

        self._stop_thread = False

        self.widgetlist = []
        self.docklist = []
        self.x_data = []
        self.y_data = []
        self.plotlist = []
        self.updateing_time__s = updating_time__s
        
        self._last_measurement_time__s = time.time()
    
        self.start()        
                         

    def plot(self, widgetnumber, axis, x_data, y_data):
        self.plotlist.append(self.widgetlist[widgetnumber].plot(x_data, y_data))
        self.x_data = x_data
        self.y_data = y_data
        

    def add_widget(self, docktitle="Test", docksize=(500,200), widgettitle="Test"):
        d = Dock(docktitle, size=docksize)
        w = pg.PlotWidget(title=widgettitle)
        d.addWidget(w)
        self.docklist.append(d)
        self.widgetlist.append(w)
        self.area.addDock(d)


    def set_data(self, x_data, y_data):
        self.x_data = x_data
        self.y_data = y_data
        self.new_data_available = True

    def update_plot_data(self):
         # In the end I want it to be as general as possible but in the moment I just want it to work properly
         # for the first part so I only have one element in the plotlist.
        self.plotlist[0].setData(self.x_data.tolist(), self.y_data.tolist()) 


    def show(self):
        self.win.show()


    def run(self):
        """
        Main

        """
        # Run thread until stop() is called
        while True:
            if self._stop_thread:
                break

            current_time__s = time.time()
            time_since_last_measurement__s = current_time__s - self._last_measurement_time__s

            if time_since_last_measurement__s >= self.updateing_time__s:
                self._last_measurement_time__s = current_time__s

                if len(self.plotlist) > 0:
                    self.update_plot_data()


    def stop(self):
        with self._lock:
            self._stop_thread = True


x = liveplot()
x.add_widget()
x_dat = np.linspace(0, 10, 100)
y_dat = np.sin(x_dat)
x.add_widget()
x.plot(widgetnumber=0, axis=0, x_data=x_dat, y_data=y_dat)
x.show()

while True:
    time.sleep(1)
    x_dat = np.roll(x_dat, 1)  
    x_dat[-1] = x_dat[-2] + 1  # Add a new value 1 higher than the last.

    y_dat = np.roll(y_dat, 1)  
    y_dat[-1] = random.randint(0,100)  # Add a new random value.
    x.set_data(x_dat, y_dat)

Benji
  • 1
  • There are many problems with your code: 1. the QApplication (which is GUI based) should *always* be in the main thread; 2. there should be one and only one QApplication instance, so you should not try to create a class that could span multiple applications; 3. no blocking functions and while loops should ever be used in the thread of a QApplication. If you need to do updates at regular intervals, use a QTimer. – musicamante Sep 07 '21 at 14:39

0 Answers0