web-dev-qa-db-ja.com

Pythonリアルタイムプロット

2つの配列でいくつかのデータを取得します。1つは時間用、もう1つは値用です。 1000ポイントに達すると、信号をトリガーしてこれらのポイントをプロットします(x =時間、y =値)。

前のプロットと同じ数値を維持する必要がありますが、プロセスの速度低下を避けるために妥当な数だけです。たとえば、グラフ上に10,000ポイントを保持したいとします。 matplotlibインタラクティブプロットは正常に機能しますが、最初のポイントを消去する方法がわからず、コンピューターの速度が非常に速くなります。 matplotlib.animationを調べましたが、同じプロットを繰り返しているようで、実際には実現していません。

速度が低下しないように、私は本当に軽い解決策を探しています。

非常に長い時間を取得するため、ループごとに入力データを消去します(1001番目のポイントは1行目に格納されます)。

これが私が今持っているものですが、それはグラフ上のすべてのポイントを保持します:

import matplotlib.pyplot as plt

def init_plot():
  plt.ion()
  plt.figure()
  plt.title("Test d\'acqusition", fontsize=20)
  plt.xlabel("Temps(s)", fontsize=20)
  plt.ylabel("Tension (V)", fontsize=20)
  plt.grid(True)

def continuous_plot(x, fx, x2, fx2):
  plt.plot(x, fx, 'bo', markersize=1)
  plt.plot(x2, fx2, 'ro', markersize=1)
  plt.draw()

Init関数を1回呼び出すと、continous_plotが処理中であり、配列に1000ポイントがあるたびに呼び出されます。

5
CoMartel

あなたが持っているかもしれない最も軽い解決策は、既存のプロットのX値とY値を置き換えることです。 (または、Xデータが変更されない場合はY値のみ。簡単な例:

import matplotlib.pyplot as plt
import numpy as np
import time

fig = plt.figure()
ax = fig.add_subplot(111)

# some X and Y data
x = np.arange(10000)
y = np.random.randn(10000)

li, = ax.plot(x, y)

# draw and show it
ax.relim() 
ax.autoscale_view(True,True,True)
fig.canvas.draw()
plt.show(block=False)

# loop to update the data
while True:
    try:
        y[:-10] = y[10:]
        y[-10:] = np.random.randn(10)

        # set the new data
        li.set_ydata(y)

        fig.canvas.draw()

        time.sleep(0.01)
    except KeyboardInterrupt:
        break

このソリューションも非常に高速です。上記のコードの最大速度は毎秒100回の再描画です(time.sleepによって制限されます)。70〜80程度になります。つまり、1回の再描画には約4ミリ秒かかります。ただし、YMMVはバックエンドなどによって異なります。

7
DrV

固定サイズの配列を使用し、matplotを使用してそれをプロットします。

 import collections
 array = collections.deque([None] * 1000, maxlen=1000)

配列に追加するたびに、最初の要素が削除されます。

5
f.rodrigues

私はこの質問に答えるのが遅れていることを知っています。あなたの問題については、「ジョイスティック」パッケージを調べることができます。これは、line.set_data()メソッドとcanvas.draw()メソッドに基づいており、オプションで軸の再スケーリングが行われます。また、(グラフプロットに加えて)インタラクティブなテキストロギングまたは画像プロットも可能です。別のスレッドで独自のループを実行する必要はありません。パッケージがそれを処理します。必要な更新頻度を指定するだけです。さらに、コンソールは引き続き追加の監視コマンドに使用できます。 http://www.github.com/ceyzeriat/joystick/ または https://pypi.python.org/pypi/joystick (pip installjoystickを使用してインストール)

試してください:

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()
0
Guillaume S

完全にインタラクティブにするために、これにBokehを使用できます。具体的には、Xミリ秒ごとに呼び出される更新関数を使用して、新しいデータをストリーミングできます。

ここに私が使用するフラグメントがあります:

def update():
     candle_data.stream(new_data, 300)   

plot = figure(x_axis_type='datetime',x_range=(start_day, final_day), width=1500, height=900, title='Live Chart', sizing_mode='scale_both')
plot.segment(x0='time', y0='highest', x1='time', y1='lowest', color='black', source=candle_data)
plot.vbar(x='time', width = 0.5*60*60*50 ,bottom='open', top='close',fill_color='color', line_color='black', source = candle_data) 
doc.add_root(column([plot]))
doc.add_periodic_callback(update, 20000)
doc.title = "Candle Data Live Rates"
0
Javier Guzman