matplotlibでリアルタイム描画
この記事は最終更新日から3年以上が経過しています。
モチベーション
センサーとかの値を確認したり,機械学習の学習状況とかそんなんをリアルタイムにグラフにプロットしながら見たいときがある.
pythonには
pythonには
matplotlib
っていう便利なグラフ作成ライブラリがあるのでこれを使いたい.既知の問題とか
普通
matplotlib
でグラフを作るときはimport matplotlib.pyplot as plt
"""
plotしたいデータを計算する処理
...
"""
plt.plot(data)
plt.show()
とかやる.
だけど,
調べてみると
(たしかMacとかのUnix環境だったら使えたような気がする.)
だけど,
show()
を呼ぶとプログラムがそこでブロックされてリアルタイムな描画ができない.調べてみると
show()
ではなくてdraw()
を使おう!みたいな記事とか,Tkinter(tkinter)
とかQt
とかのGUIライブラリと組み合わせた方法とかがでてくるんだけど,Windows環境だとグラフに一度でも触るとGUIが固まったりしてとてもじゃないけど使えなかったりした.(たしかMacとかのUnix環境だったら使えたような気がする.)
pause()を使おう!!!
例の如くstackoverflowにそれ関係のやりとりがあった.
参考: real-time plotting in while loop with matplotlib
参考: real-time plotting in while loop with matplotlib
結論は
下に簡単なsin関数を永遠にplotする例を載っける.
plt.show()
の代わりにplt.pause(interval)
を使うということ.下に簡単なsin関数を永遠にplotする例を載っける.
注意点などはコメントに書いたので,読んでください.
matplotlib_realtime_plot_example.py
# -*- coding: utf-8 -*-
"""
matplotlibでリアルタイムプロットする例
無限にsin関数をplotし続ける
"""
from __future__ import unicode_literals, print_function
import numpy as np
import matplotlib.pyplot as plt
def pause_plot():
fig, ax = plt.subplots(1, 1)
x = np.arange(-np.pi, np.pi, 0.1)
y = np.sin(x)
# 初期化的に一度plotしなければならない
# そのときplotしたオブジェクトを受け取る受け取る必要がある.
# listが返ってくるので,注意
lines, = ax.plot(x, y)
# ここから無限にplotする
while True:
# plotデータの更新
x += 0.1
y = np.sin(x)
# 描画データを更新するときにplot関数を使うと
# lineオブジェクトが都度増えてしまうので,注意.
#
# 一番楽なのは上記で受け取ったlinesに対して
# set_data()メソッドで描画データを更新する方法.
lines.set_data(x, y)
# set_data()を使うと軸とかは自動設定されないっぽいので,
# 今回の例だとあっという間にsinカーブが描画範囲からいなくなる.
# そのためx軸の範囲は適宜修正してやる必要がある.
ax.set_xlim((x.min(), x.max()))
# 一番のポイント
# - plt.show() ブロッキングされてリアルタイムに描写できない
# - plt.ion() + plt.draw() グラフウインドウが固まってプログラムが止まるから使えない
# ----> plt.pause(interval) これを使う!!! 引数はsleep時間
plt.pause(.01)
if __name__ == "__main__":
pause_plot()
これで色々捗る!!!
おまけ
上で載っけたstackoverflowに
drawnow
というパッケージを使った方法も載っているので紹介する.drawnow
はpip
で入るので$ pip install drawnow
でOK.
使い方
matplotlib_drawnow_realtime_plot_example.py
# -*- coding: utf-8 -*-
"""
matplotlibでリアルタイムプロットする例
無限にsin関数をplotし続ける
"""
from __future__ import unicode_literals, print_function
import numpy as np
import matplotlib.pyplot as plt
from drawnow import drawnow, figure
def drawnow_plot():
# drawnowパッケージに含まれているfigure関数を使って
# figureオブジェクトを作る
fig = figure()
x = np.arange(-np.pi, np.pi, .1)
y = np.sin(x)
def draw():
"""
drawnow関数に渡すplotに必要な処理を記述
plotに必要な変数はこの関数がアクセスできるスコープの変数にしておく
"""
plt.plot(x, y)
while True:
x += .1
y = np.sin(x)
drawnow(draw)
...書いてからソースコード見てみたが,
drawnow
は結局中でdraw()
を呼んでるみたいで,Windowsでやると上手く行かなかった(GUIが固まる現象)...結論
リアルタイムにプロットしたいときは
plt.pause()
を使おう!!!
0 件のコメント:
コメントを投稿