2024-06-10

動的に Matplotlib のチャートを利用する ~ PySide6

PySide (Qt for Python) は、Qt(キュート)の Python バインディングで、GUI などを構築するためのクロスプラットフォームなライブラリです。Linux/X11, macOS および Microsoft Windows をサポートしています。配布ライセンスは LGPL で公開されています。

Matplotlib のチャートを PySide6 に GUI に埋め込んで利用しています。リアルタイムに…、と言っても更新頻度は数秒に一回程度なのですが、データを取得して Matplotlib のチャートに反映させるときは、表示されているチャートを一旦消してから書き直しています。この程度の更新頻度であれば、チャートを書き直しても問題ありませんが、もっと更新頻度が高いときに、チャートを書き直さずにチャート上に新しいデータ点を追加する方法を確認しておきたくなりました。

下記の OS 環境で動作確認をしています。

RHEL 9.4 x86_64
Python 3.12.1
PySide6 6.7.1
matplotlib 3.9.0

次のサンプルは、タイマーで 50 ミリ秒毎にイベントを発生させて、タイムスタンプとその値で計算した正弦曲線 (Sin) を描画します(最大 1,000 点)。点と点を描画するだけでなく、点と点を直線で結びたかったので、前の点の座標を保持しておき、表示上は擬似的な正弦曲線に見えるようにしています。

qt_matplotlib_realtime.py
import datetime
import math
import sys
import pandas as pd
from PySide6.QtCore import Qt, QTimer
from PySide6.QtWidgets import (
QApplication,
QMainWindow,
)
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qtagg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
class RTChart(FigureCanvas):
def __init__(self):
self.fig = Figure()
super().__init__(self.fig)
self.ax = ax = self.fig.add_subplot(111)
ax.set(title='Sample')
ax.set_ylabel('Y')
ax.grid(True)
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('Real Time Sample')
self.resize(600, 400)
self.t0 = None
self.y0 = None
self.count = 0
self.canvas = canvas = RTChart()
self.setCentralWidget(canvas)
toolbar = NavigationToolbar(canvas, self)
self.addToolBar(Qt.ToolBarArea.BottomToolBarArea, toolbar)
self.timer = timer = QTimer(self)
timer.timeout.connect(self.update_data)
timer.start(50)
def update_data(self):
if self.count > 1000:
self.timer.stop()
print('completed!')
return
t1 = datetime.datetime.now()
y1 = math.sin(t1.timestamp())
if self.t0 is not None:
self.canvas.ax.plot(
[self.t0, t1], [self.y0, y1], color='C1',
linewidth=1, marker='o', markersize=2)
self.canvas.fig.canvas.draw()
self.t0 = t1
self.y0 = y1
self.count += 1
def main():
app = QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec())
if __name__ == '__main__':
main()

このサンプルを実行した例を示しました。x 軸の時刻表示については改善の余地があります。🙇🏻

qt_matplotlib_realtime.py の実行例
completed!

このサンプルでは、タイマーのイベントが発生する度にカウンタの値を増やし、1000 回になったところでタイマーを止めています。

参考サイト

  1. matplotlib.pyplot.plot — Matplotlib documentation
  2. Embedding in Qt — Matplotlib documentation
  3. QTimer - Qt for Python

 

ブログランキング・にほんブログ村へ bitWalk's - にほんブログ村 にほんブログ村 IT技術ブログ オープンソースへ
にほんブログ村

オープンソース - ブログ村ハッシュタグ
#オープンソース



0 件のコメント: