简体   繁体   中英

Plotting with pyqtgraph using external data

I'm trying to plot data of diferentes sensors en realtime,so I decided to plot the data using PyQtGraph in PyQt, in order to make it work with several sensor's data from differnte sources. Searching example on the internet, i found one and i tried to adapt it , Because of QtGui.QApplication.instance().exec_(), which carries the inconvenient side effect of blocking the execution of the rest of the code after it. I tried to manage to used threads using Multiproccessing. I could make the rest of the code works, but how coud I update the plot using external data (Plo2D.update2),I tried to used multiprocessing.Queue , but I didn't work, instead appears massage of the window must be closed.

from pyqtgraph.Qt import QtGui, QtCore
import numpy as np
from numpy import arange
import pyqtgraph as pg
import sys
import multiprocessing

class Plot2D():
    def __init__(self,):
        self.traces = dict()
        self.app = QtGui.QApplication([])
        self.win = pg.GraphicsWindow(title="Dibujar")
        self.win.resize(1000, 600)
        self.win.setWindowTitle('Ejemplo')
        pg.setConfigOptions(antialias=True)
        #self.canvas = self.win.addPlot(title="Pytelemetry")
        self.waveform1 = self.win.addPlot(title='WAVEFORM1', row=1, col=1)
        self.waveform2 = self.win.addPlot(title='WAVEFORM2', row=2, col=1)

    def start(self):
        if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
            QtGui.QApplication.instance().exec_()

    def set_plotdata(self, name, datax, datay):
        if name in self.traces:
            self.traces[name].setData(datax, datay)
        else:
            if name == '910D':
                self.traces[name] = self.waveform1.plot(pen='c', width=3)
            if name == 'MPU':
                self.traces[name] = self.waveform2.plot(pen='c', width=3)

    def update2(self):
        # Trying to get external data
        ptm1 = globals()['DatExt1']
        ptm2 = globals()['DatExt2']
        while ptm1.empty() is False:
            self.data1 = ptm1.get()
            self.set_plotdata('MPU', self.data1[0], self.data1[1])
            # csvWriterG910D.writerows(Informa)
            # file1.flush()
        while ptm2.empty() is False:
            self.data2 = ptm2.get()
            self.set_plotdata('910D', self.data1[0], self.data1[1])

    def animation(self):
        timer = QtCore.QTimer()
        timer.timeout.connect(self.update2)
        timer.start(60)
        self.start()

# It is thread started from main.py
def ShowData(Data1, Data2): # Data1,Data2 : multiprocessing.Queue
    DatExt1 = Data1
    DatExt2 = Data2
    p = Plot2D()
    p.animation()

the main.py:

    if __name__ == '__main__':

    Data1 = multiprocessing.Queue()
    Data2 = multiprocessing.Queue()

    Plottingdata = Process(target=PlotData.ShowData, args=(Data1, Data2, ))
    Plottingdata.start()

    t = np.arange(-3.0, 2.0, 0.01)
    i = 0.0
    while True:
        s = np.sin(2 * 2 * 3.1416 * t) / (2 * 3.1416 * t + i)
        time.sleep(1)
        Data1.put([t, s])
        i = i + 0.1

thanks ind advanced for help

Instead of using MultiProcessing you should use MultiThreading, that is, create threads that are responsible for collecting data (in your example emulate data) and then send the data to the GUI by signals.

PlotData.py

from pyqtgraph.Qt import QtGui, QtCore
import numpy as np
import pyqtgraph as pg
import sys

class Plot2D(pg.GraphicsWindow):
    def __init__(self):
        pg.GraphicsWindow.__init__(self, title="Dibujar")
        self.traces = dict()
        self.resize(1000, 600)
        pg.setConfigOptions(antialias=True)
        #self.canvas = self.win.addPlot(title="Pytelemetry")
        self.waveform1 = self.addPlot(title='WAVEFORM1', row=1, col=1)
        self.waveform2 = self.addPlot(title='WAVEFORM2', row=2, col=1)

    def set_plotdata(self, name, x, y):
        if name in self.traces:
            self.traces[name].setData(x, y)
        else:
            if name == "910D":
                self.traces[name] = self.waveform1.plot(x, y, pen='y', width=3)
            elif name == "MPU":
                self.traces[name] = self.waveform2.plot(x, y, pen='y', width=3)

    @QtCore.pyqtSlot(str, tuple)
    def updateData(self, name, ptm):
        x, y = ptm
        self.set_plotdata(name, x, y)

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    plot = Plot2D()
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QtGui.QApplication.instance().exec_()

main.py

import sys

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

from PlotData import Plot2D

class Helper(QtCore.QObject):
    changedSignal = QtCore.pyqtSignal(str, tuple)

def create_data1(helper, name):
    t = np.arange(-3.0, 2.0, 0.01)
    i = 0.0
    while True:
        s = np.sin(2 * 2 * 3.1416 * t) / (2 * 3.1416 * t + i)
        time.sleep(.1)
        helper.changedSignal.emit(name, (t, s))
        i = i + 0.1

def create_data2(helper, name):
    t = np.arange(-3.0, 2.0, 0.01)
    i = 0.0
    while True:
        s = np.cos(2 * 2 * 3.1416 * t) / (2 * 3.1416 * t - i)
        time.sleep(.1)
        helper.changedSignal.emit(name, (t, s))
        i = i + 0.1

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    helper = Helper()
    plot = Plot2D()
    helper.changedSignal.connect(plot.updateData, QtCore.Qt.QueuedConnection)
    threading.Thread(target=create_data1, args=(helper, "910D"), daemon=True).start()
    threading.Thread(target=create_data2, args=(helper, "MPU"), daemon=True).start()
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QtGui.QApplication.instance().exec_()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM