<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Python 如何實時繪制數(shù)據(jù)

          共 6178字,需瀏覽 13分鐘

           ·

          2020-08-04 12:55

          提到 GUI 繪圖,大家可能第一反應(yīng)是 OpenGL 和 Matplotlib,但其實基于 Qt 平臺還有個功能強(qiáng)大的 pyqtgraph 繪圖庫,不僅支持豐富的圖形種類,還能實時更新繪圖數(shù)據(jù)并進(jìn)行交互式操作。

          不同于網(wǎng)上其他文章或代碼講解,今天我們集中只關(guān)注實時繪制數(shù)據(jù)功能的實現(xiàn)。為了更精準(zhǔn)學(xué)習(xí)該 pyqtgraph 模塊功能,我們將參考官方給出的實例來邊學(xué)邊練。

          1. pyqtgraph 簡介

          1.1 pyqtgraph 特點

          關(guān)于 pyqtgraph 與 Matplotlib 的對比,大致要點如下:

          1. pyqtgraph 在畫圖方面不如 Matplotlib 功能完整和成熟,但運行更快
          2. Matplotlib 旨在繪制高質(zhì)量圖像,pyqtgraph 則主要面向數(shù)據(jù)抓取和數(shù)據(jù)分析的應(yīng)用
          3. 相比 Matplotlib,pyqtgraph 對 python 和 qt 編程更親和
          4. pyqtgraph 具備更好的圖像交互、3D展示等

          1.2 pyqtgraph 安裝

          一般配合 PyQt5 使用,這些都要預(yù)先安裝好,我們這里只提 pyqtgraph 相關(guān):

          pip?install?pyqtgraph

          1.3 pyqtgraph 實例全集

          官方專門給出了一個實例集合,包含了展示與源碼,非常方便學(xué)習(xí),通過以下代碼來運行:

          import?pyqtgraph.examples
          pyqtgraph.examples.run()

          運行后,會出現(xiàn)如下 GUI 界面今天我們主要關(guān)注實時繪制數(shù)據(jù),找到左側(cè)目錄中的 "Scrolling plots",單擊右側(cè)可以看到源碼

          雙擊或者點擊下方的 "Run Example" 便可展示運行效果:

          特定截圖:

          2. 實時繪制學(xué)習(xí)

          結(jié)合著實例代碼和演示效果,我們可以看到有如下不同實時展示模式:

          • 模式1: 從 0 開始固定 x 軸數(shù)值范圍,數(shù)據(jù)在該范圍內(nèi)向左移動展示
          • 模式2: 數(shù)據(jù)帶著 x 軸坐標(biāo)一起向左移動展示
          • 模式3: 固定 x 軸數(shù)值右側(cè)范圍到 0,數(shù)據(jù)左移展示
          • 模式4: 左側(cè)固定從 0 開始,數(shù)據(jù)累積展示
          • 模式5: 數(shù)據(jù)范圍右側(cè)截止到 0,但仍可查看大于 0 范圍

          2.1 ?模式1: 固定 x 范圍,左移展示數(shù)據(jù)

          2.1.1 模式1效果

          模式1 效果

          2.1.2 實例1代碼

          我們可以在實例匯總的代碼中將該部分代碼抽離出來,大致如下:

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

          win?=?pg.GraphicsLayoutWidget(show=True)
          win.setWindowTitle('Scrolling?Plots?Mode?1')

          p1?=?win.addPlot()
          data1?=?np.random.normal(size=300)

          curve1?=?p1.plot(data1)


          def?update1():
          ????global?data1,?ptr1
          ????data1[:-1]?=?data1[1:]??#?shift?data?in?the?array?one?sample?left
          ????#?(see?also:?np.roll)
          ????data1[-1]?=?np.random.normal()
          ????curve1.setData(data1)


          timer?=?pg.QtCore.QTimer()
          timer.timeout.connect(update1)
          timer.start(50)


          ##?Start?Qt?event?loop?unless?running?in?interactive?mode?or?using?pyside.
          if?__name__?==?'__main__':
          ????import?sys

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

          注意,模式 1 中實時繪制效果的實現(xiàn),是通過將數(shù)據(jù)列表中的數(shù)據(jù)整體左移實現(xiàn)的,關(guān)鍵語句就是 data1[:-1] = data1[1:],再通過計時器來綁定該左移數(shù)據(jù)的函數(shù),最終達(dá)到了展示中的數(shù)據(jù)動態(tài)展示效果。

          2.1.3 寫成 PlotWidget 形式

          總結(jié)下模式 1 的原理:x 坐標(biāo)數(shù)據(jù)不變化,對應(yīng)的 y 數(shù)據(jù)設(shè)置個左移變換的函數(shù),計時器信號綁定該左移數(shù)據(jù)的函數(shù),把 y 數(shù)據(jù)能實時設(shè)置到圖中即可。

          實例 1 中繪制圖的寫法比較少見,通常應(yīng)用是通過 pyqtgraph.PlotWidget.plot() 來實現(xiàn)在控件中作圖再添加到 GUI 控件中,所以我們將采用 PlotWidget 的寫法來實現(xiàn)模式1的繪制,代碼如下:

          __author__?=?'Ted'

          from?PyQt5.Qt?import?*
          from?pyqtgraph?import?PlotWidget
          from?PyQt5?import?QtCore
          import?numpy?as?np
          import?pyqtgraph?as?pq


          class?Window(QWidget):
          ????def?__init__(self):
          ????????super().__init__()
          ????????#?設(shè)置下尺寸
          ????????self.resize(600,600)
          ????????#?添加?PlotWidget?控件
          ????????self.plotWidget_ted?=?PlotWidget(self)
          ????????#?設(shè)置該控件尺寸和相對位置
          ????????self.plotWidget_ted.setGeometry(QtCore.QRect(25,25,550,550))

          ????????#?仿寫?mode1?代碼中的數(shù)據(jù)
          ????????#?生成?300?個正態(tài)分布的隨機(jī)數(shù)
          ????????self.data1?=?np.random.normal(size=300)

          ????????self.curve1?=?self.plotWidget_ted.plot(self.data1,?name="mode1")

          ????????#?設(shè)定定時器
          ????????self.timer?=?pq.QtCore.QTimer()
          ????????#?定時器信號綁定?update_data?函數(shù)
          ????????self.timer.timeout.connect(self.update_data)
          ????????#?定時器間隔50ms,可以理解為?50ms?刷新一次數(shù)據(jù)
          ????????self.timer.start(50)

          ????#?數(shù)據(jù)左移
          ????def?update_data(self):
          ????????self.data1[:-1]?=?self.data1[1:]
          ????????self.data1[-1]?=?np.random.normal()
          ????????#?數(shù)據(jù)填充到繪制曲線中
          ????????self.curve1.setData(self.data1)


          if?__name__?==?'__main__':
          ????import?sys
          ????#?PyQt5?程序固定寫法
          ????app?=?QApplication(sys.argv)

          ????#?將綁定了繪圖控件的窗口實例化并展示
          ????window?=?Window()
          ????window.show()

          ????#?PyQt5?程序固定寫法
          ????sys.exit(app.exec())

          我們在自己寫的代碼中重新設(shè)置了下窗口尺寸位置,數(shù)據(jù)還是按照實例中的寫法來完成的。

          2.1.4 自寫模式1效果

          自寫模式1效果

          2.2 ?數(shù)據(jù)隨 x 軸一起左移

          2.2.1 模式2效果

          模式 2 動態(tài)效果

          2.2.2 實例2代碼

          該模式代碼抽離出來大致如下:

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

          win?=?pg.GraphicsLayoutWidget(show=True)
          win.setWindowTitle('pyqtgraph?example:?Scrolling?Plots')


          p2?=?win.addPlot()
          data1?=?np.random.normal(size=300)

          curve2?=?p2.plot(data1)
          ptr1?=?0


          def?update1():
          ????global?data1,?ptr1
          ????data1[:-1]?=?data1[1:]??#?shift?data?in?the?array?one?sample?left

          ????data1[-1]?=?np.random.normal()

          ????ptr1?+=?1
          ????curve2.setData(data1)
          ????curve2.setPos(ptr1,?0)


          timer?=?pg.QtCore.QTimer()
          timer.timeout.connect(update1)
          timer.start(50)


          if?__name__?==?'__main__':
          ????import?sys

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

          對比模式1代碼,此部分多了個 curve2.setPos(ptr1, 0),通過 Qt 官網(wǎng)中搜索查閱,setPos(x,y) 是將原點設(shè)置到 (x,y):

          ?

          Sets the position of the item to pos, which is in parent coordinates. For items with no parent, pos is in scene coordinates. The position of the item describes its origin (local coordinate (0, 0)) in parent coordinates.

          ?

          這樣我們可以大致理解為,通過設(shè)置坐標(biāo)系相對原點位置來產(chǎn)生 x 軸移動的效果。

          2.2.3 寫成 PlotWidget 形式

          總結(jié)下模式 2 的原理:y 數(shù)據(jù)與模式1相同,設(shè)置左移變換的函數(shù),計時器信號綁定該左移數(shù)據(jù)的函數(shù),把 y 數(shù)據(jù)能實時設(shè)置到圖中;x 數(shù)據(jù)則通過 setPos() 函數(shù)隨著 y 的變化同步進(jìn)行設(shè)置,產(chǎn)生 x 軸同步移動的效果。

          我們繼續(xù)采用 PlotWidget 的寫法來實現(xiàn)模式2的繪制,在模式1基礎(chǔ)上添加幾行代碼即可,為作區(qū)分我們把曲線定義為 curve2:

          __author__?=?'Ted'

          from?PyQt5.Qt?import?*
          from?pyqtgraph?import?PlotWidget
          from?PyQt5?import?QtCore
          import?numpy?as?np
          import?pyqtgraph?as?pq


          class?Window(QWidget):
          ????def?__init__(self):
          ????????super().__init__()
          ????????#?設(shè)置下尺寸
          ????????self.resize(600,600)
          ????????#?添加?PlotWidget?控件
          ????????self.plotWidget_ted?=?PlotWidget(self)
          ????????#?設(shè)置該控件尺寸和相對位置
          ????????self.plotWidget_ted.setGeometry(QtCore.QRect(25,25,550,550))

          ????????#?仿寫?mode1?代碼中的數(shù)據(jù)
          ????????#?生成?300?個正態(tài)分布的隨機(jī)數(shù)
          ????????self.data1?=?np.random.normal(size=300)

          ????????self.curve2?=?self.plotWidget_ted.plot(self.data1,?name="mode2")
          ????????self.ptr1?=?0

          ????????#?設(shè)定定時器
          ????????self.timer?=?pq.QtCore.QTimer()
          ????????#?定時器信號綁定?update_data?函數(shù)
          ????????self.timer.timeout.connect(self.update_data)
          ????????#?定時器間隔50ms,可以理解為?50ms?刷新一次數(shù)據(jù)
          ????????self.timer.start(50)

          ????#?數(shù)據(jù)左移
          ????def?update_data(self):
          ????????self.data1[:-1]?=?self.data1[1:]
          ????????self.data1[-1]?=?np.random.normal()
          ????????#?數(shù)據(jù)填充到繪制曲線中
          ????????self.curve2.setData(self.data1)
          ????????#?x?軸記錄點
          ????????self.ptr1?+=?1
          ????????#?重新設(shè)定?x?相關(guān)的坐標(biāo)原點
          ????????self.curve2.setPos(self.ptr1,0)


          if?__name__?==?'__main__':
          ????import?sys
          ????#?PyQt5?程序固定寫法
          ????app?=?QApplication(sys.argv)

          ????#?將綁定了繪圖控件的窗口實例化并展示
          ????window?=?Window()
          ????window.show()

          ????#?PyQt5?程序固定寫法
          ????sys.exit(app.exec())

          我們在自己寫的代碼中重新設(shè)置了下窗口尺寸位置,數(shù)據(jù)還是按照實例中的寫法來完成的。

          2.2.4 自寫模式1效果

          自寫模式2

          3. 小結(jié)

          今天先只簡單整理這兩個較簡單的實時繪制模式,給定的代碼中數(shù)據(jù)是用的隨機(jī)正態(tài)分布數(shù)據(jù),我們結(jié)合著模式 1 和 2 的實例代碼來分析其原理算法來仿寫了常用版本的代碼。

          掌握模式 1 和模式 2 的用法后,我們便可以對更多的數(shù)據(jù)來進(jìn)行動態(tài)展示,比如 CPU 占用率、股票實時價格等,配合著 PyQt5 的 GUI 圖形界面,那么完全可以用 Python 來寫出看著高大上的數(shù)據(jù)可視化界面了,這個后續(xù)我們再繼續(xù)研究。


          瀏覽 94
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  蜜桃传媒AV| 日批网站wwww | 欧美视频网站中文字幕 | 大香蕉伊人影院网站 | 国产熟女性爱视频 |