136

シリアルポートからデータを収集し、収集されたデータのグラフを到着時間に対してプロットする Python でアプリケーションを作成しています。データの到着時間は不明です。データを受信したときにプロットを更新したい。これを行う方法を検索したところ、2つの方法が見つかりました。

  1. プロットをクリアし、すべての点でプロットを再描画します。
  2. 特定の間隔の後にプロットを変更して、プロットをアニメーション化します。

プログラムが長時間 (たとえば 1 日) 実行されてデータが収集されるため、最初のものは好みません。プロットの再描画はかなり遅くなります。データの到着時間が不確実であり、データが受信されたときにのみプロットを更新したいので、2番目のものも好ましくありません。

データを受信したときにのみポイントを追加するだけでプロットを更新できる方法はありますか?

4

4 に答える 4

153

ポイントを追加するだけでプロットを更新できる方法はありますか...

お持ちのバージョンに応じて、matplotlibでデータをアニメーション化する方法はいくつかあります。matplotlibクックブックの例を見たことがありますか?また、 matplotlibのドキュメントにある最新のアニメーションの例も確認してください。最後に、アニメーションAPIは、関数を時間内にアニメーション化する関数FuncAnimationを定義します。この関数は、データを取得するために使用する関数である可能性があります。

各メソッドは基本的dataに描画されるオブジェクトのプロパティを設定するため、画面や図をクリアする必要はありません。プロパティはdata単純に拡張できるため、前のポイントを保持し、線(または画像や描画しているもの)に追加し続けることができます。

データの到着時間が不確かであるとあなたが言うことを考えると、あなたの最善の策はおそらく次のようなことをすることです:

import matplotlib.pyplot as plt
import numpy

hl, = plt.plot([], [])

def update_line(hl, new_data):
    hl.set_xdata(numpy.append(hl.get_xdata(), new_data))
    hl.set_ydata(numpy.append(hl.get_ydata(), new_data))
    plt.draw()

次に、シリアルポートからデータを受信したら、を呼び出しますupdate_line

于 2012-06-08T07:49:21.193 に答える
5

この質問への回答が遅れていることは承知していますが、あなたの問題については、「ジョイスティック」パッケージを調べることができます。シリアル ポートからのデータ ストリームをプロットするように設計しましたが、どのストリームでも機能します。また、(グラフのプロットに加えて) 対話型のテキスト ロギングまたはイメージのプロットも可能です。別のスレッドで独自のループを実行する必要はありません。パッケージが処理します。必要な更新頻度を指定するだけです。さらに、ターミナルは、プロット中にコマンドを監視するために引き続き使用できます。http://www.github.com/ceyzeriat/joystick/またはhttps://pypi.python.org/pypi/joystickを参照してください(インストールには pip install ジョイスティックを使用します)

以下のコードで、np.random.random() をシリアル ポートから読み取った実際のデータ ポイントに置き換えるだけです。

import joystick as jk
import numpy as np
import time

class test(jk.Joystick):
    # initialize the infinite loop decorator
    _infinite_loop = jk.deco_infinite_loop()

    def _init(self, *args, **kwargs):
        """
        Function called at initialization, see the doc
        """
        self._t0 = time.time()  # initialize time
        self.xdata = np.array([self._t0])  # time x-axis
        self.ydata = np.array([0.0])  # fake data y-axis
        # create a graph frame
        self.mygraph = self.add_frame(jk.Graph(name="test", size=(500, 500), pos=(50, 50), fmt="go-", xnpts=10000, xnptsmax=10000, xylim=(None, None, 0, 1)))

    @_infinite_loop(wait_time=0.2)
    def _generate_data(self):  # function looped every 0.2 second to read or produce data
        """
        Loop starting with the simulation start, getting data and
    pushing it to the graph every 0.2 seconds
        """
        # concatenate data on the time x-axis
        self.xdata = jk.core.add_datapoint(self.xdata, time.time(), xnptsmax=self.mygraph.xnptsmax)
        # concatenate data on the fake data y-axis
        self.ydata = jk.core.add_datapoint(self.ydata, np.random.random(), xnptsmax=self.mygraph.xnptsmax)
        self.mygraph.set_xydata(t, self.ydata)

t = test()
t.start()
t.stop()
于 2016-09-28T22:41:00.077 に答える