在课堂上制作pyqtgraph动画

2024-10-01 15:36:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试编写一个程序,通过串行从arduino获取串行数据,并实时绘制。我用matplotlib编写了代码,但是我希望得到满意的结果,所以我试图让它在pyqtgraph上工作(学习如何使用它的资源少得多)。我的问题是代码显示了一个空的图形。似乎只有一次调用了\u update,但是当我把它放到一个循环中时,图形甚至都没有显示出来。在

我还编写了一些其他代码来实现我想要的,即实时绘制数据,在数据通过阈值后,它在数据上绘制新行,显示线性回归。我从这里得到了一个例子(https://github.com/JaFeKl/joystick_real_time_plot_with_pyqtgraph/blob/master/real_time_plot.py),因为我希望我的代码是可调用的(在一个函数中,但我不能让它工作)。到目前为止,我在python中生成数据以简化调试

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

import serial

# test
import math
import time


class Graph(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(Graph, self).__init__(parent)
        self.n = 3
        self.mainbox = QtGui.QWidget()
        self.setCentralWidget(self.mainbox)
        self.mainbox.setLayout(QtGui.QVBoxLayout())

        self.canvas = pg.GraphicsLayoutWidget()             # create GrpahicsLayoutWidget obejct  
        self.mainbox.layout().addWidget(self.canvas)

        #  Set up plot
        self.analogPlot = self.canvas.addPlot(title='Signal from serial port')
        self.analogPlot.setYRange(-1,1123)                # set axis range
        self.analogPlot.setXRange(-1,1123)
        self.analogPlot.showGrid(x=True, y=True, alpha=0.5) # show Grid
        x_axis = self.analogPlot.getAxis('bottom')
        y_axis = self.analogPlot.getAxis('left')
        font=QtGui.QFont()
        font.setPixelSize(20)
        x_axis.tickFont = font
        y_axis.tickFont = font
        x_axis.setLabel(text='Tensão [V]')              # set axis labels
        y_axis.setLabel(text='Corrente [mA]')

        self.plts = []
        self.intplts = []
        colors = ['r', 'b', 'w', 'y', 'g', 'm', 'c', 'k']
        for i in range(self.n):
            self.plts.append([])
            self.intplts.append([])


        for i in range(self.n):
            if len(self.plts) <= len(colors):
                self.plts[i]=(self.analogPlot.plot(pen= pg.mkPen(colors[i], width=6)))
        for i in range(self.n):
            if len(self.plts) <= len(colors)*2:
                self.intplts.append(self.analogPlot.plot(pen= pg.mkPen(colors[i+3], width=3)))

        #Data
        self.datay = []
        self.datax = []
        for i in range(self.n):
            self.datax.append([])
            self.datay.append([])

        # set up image exporter (necessary to be able to export images)
        QtGui.QApplication.processEvents()
        self.exporter=pg.exporters.ImageExporter(self.canvas.scene())
        self.image_counter = 1


        # start updating
        self.t=0

        self._update()


    def _update(self):
        time.sleep(0.01)
        if self.t<= 30:
            #line = raw.readline()
            #data.append(int(line))
            self.datay[0].append(math.sin(self.t+(math.pi/2)))
            self.datay[1].append(math.sin(self.t+(5*math.pi/4)))
            self.datay[2].append(math.sin(self.t))
            self.datax[0].append(self.t)
            self.datax[1].append(self.t)
            self.datax[2].append(self.t)
            self.t+=0.1
            self.plts[0].setData(self.datax[0], self.datay[0])
            self.plts[1].setData(self.datax[1], self.datay[1])
            self.plts[2].setData(self.datax[2], self.datay[2])

            app.processEvents()
        elif self.t>=30 and self.t<=30.1 :
            self.t+=1

if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)
    plot = Graph()
    plot.show()
    sys.exit(app.exec_())

我期望得到与此代码类似的结果(只不过没有线性回归)

^{pr2}$

Tags: 数据代码importselfplotmathpyqtgraphpg
1条回答
网友
1楼 · 发布于 2024-10-01 15:36:24

enter image description here

我没有一个Arduino连接起来从中获取数据,所以在这个例子中,我使用随机数据来绘制。绘制数据时,要避免使用time.sleep(),因为它会导致GUI冻结。相反,请使用连接到更新处理程序的QtGui.QTimer()来绘制数据。作为一种优化,您可以使用线程轮询数据,然后在单独的计时器中更新数据。在

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

"""Scrolling Plot Widget Example"""

# Scrolling plot widget with adjustable X-axis and dynamic Y-axis
class ScrollingPlot(QtGui.QWidget):
    def __init__(self, parent=None):
        super(ScrollingPlot, self).__init__(parent)

        # Desired Frequency (Hz) = 1 / self.FREQUENCY
        # USE FOR TIME.SLEEP (s)
        self.FREQUENCY = .004

        # Frequency to update plot (ms)
        # USE FOR TIMER.TIMER (ms)
        self.TIMER_FREQUENCY = self.FREQUENCY * 1000

        # Set X Axis range. If desired is [-10,0] then set LEFT_X = -10 and RIGHT_X = 0
        self.LEFT_X = -10
        self.RIGHT_X = 0
        self.X_Axis = np.arange(self.LEFT_X, self.RIGHT_X, self.FREQUENCY)
        self.buffer = int((abs(self.LEFT_X) + abs(self.RIGHT_X))/self.FREQUENCY)
        self.data = [] 

        # Create Plot Widget 
        self.scrolling_plot_widget = pg.PlotWidget()

        # Enable/disable plot squeeze (Fixed axis movement)
        self.scrolling_plot_widget.plotItem.setMouseEnabled(x=False, y=False)
        self.scrolling_plot_widget.setXRange(self.LEFT_X, self.RIGHT_X)
        self.scrolling_plot_widget.setTitle('Scrolling Plot Example')
        self.scrolling_plot_widget.setLabel('left', 'Value')
        self.scrolling_plot_widget.setLabel('bottom', 'Time (s)')

        self.scrolling_plot = self.scrolling_plot_widget.plot()
        self.scrolling_plot.setPen(197,235,255)

        self.layout = QtGui.QGridLayout()
        self.layout.addWidget(self.scrolling_plot_widget)

        self.read_position_thread()
        self.start()

    # Update plot
    def start(self):
        self.position_update_timer = QtCore.QTimer()
        self.position_update_timer.timeout.connect(self.plot_updater)
        self.position_update_timer.start(self.get_scrolling_plot_timer_frequency())

    # Read in data using a thread
    def read_position_thread(self):
        self.current_position_value = 0
        self.old_current_position_value = 0
        self.position_update_thread = Thread(target=self.read_position, args=())
        self.position_update_thread.daemon = True
        self.position_update_thread.start()

    def read_position(self):
        frequency = self.get_scrolling_plot_frequency()
        while True:
            try:
                # Add data
                self.current_position_value = random.randint(1,101) 
                self.old_current_position_value = self.current_position_value
                time.sleep(frequency)
            except:
                self.current_position_value = self.old_current_position_value

    def plot_updater(self):
        self.dataPoint = float(self.current_position_value)

        if len(self.data) >= self.buffer:
            del self.data[:1]
        self.data.append(self.dataPoint)
        self.scrolling_plot.setData(self.X_Axis[len(self.X_Axis) - len(self.data):], self.data)

    def clear_scrolling_plot(self):
        self.data[:] = []

    def get_scrolling_plot_frequency(self):
        return self.FREQUENCY

    def get_scrolling_plot_timer_frequency(self):
        return self.TIMER_FREQUENCY

    def get_scrolling_plot_layout(self):
        return self.layout

    def get_current_position_value(self):
        return self.current_position_value

    def get_scrolling_plot_widget(self):
        return self.scrolling_plot_widget

if __name__ == '__main__':
    # Create main application window
    app = QtGui.QApplication([])
    app.setStyle(QtGui.QStyleFactory.create("Cleanlooks"))
    mw = QtGui.QMainWindow()
    mw.setWindowTitle('Scrolling Plot Example')

    # Create scrolling plot
    scrolling_plot_widget = ScrollingPlot()

    # Create and set widget layout
    # Main widget container
    cw = QtGui.QWidget()
    ml = QtGui.QGridLayout()
    cw.setLayout(ml)
    mw.setCentralWidget(cw)

    # Can use either to add plot to main layout
    #ml.addWidget(scrolling_plot_widget.get_scrolling_plot_widget(),0,0)
    ml.addLayout(scrolling_plot_widget.get_scrolling_plot_layout(),0,0)
    mw.show()

    # Start Qt event loop unless running in interactive mode or using pyside
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QtGui.QApplication.instance().exec_()

相关问题 更多 >

    热门问题