2

時間の経過とともにヒストグラムをアニメーション化しようとしていますが、これまでのところ、コードは次のとおりです。

import matplotlib.pyplot as plt
import numpy as np
import time
plt.ion()
fig = plt.figure()
ax = fig.add_subplot(111)

alphab = ['A', 'B', 'C', 'D', 'E', 'F']
frequencies = [1, 44, 12, 11, 2, 10]

pos = np.arange(len(alphab))
width = 1.0     # gives histogram aspect to the bar diagram
ax.set_xticks(pos + (width / 2))
ax.set_xticklabels(alphab)
for bin_idx in np.linspace(0,1000000,100000000):
     t = time.time()
     #Here we just change the first bin, so it increases through the animation.
     frequencies[0] = bin_idx
     line1 =plt.bar(pos, frequencies, width, color='r')
     plt.draw()
     elapsed = time.time() - t
     print elapsed

コードは機能しますが、出力は、いくつかの反復の後、最初よりも遅くなる方法を示しています。スピードアップする方法はありますか。これをリアルタイムで更新したいと考えており、実行プロセスは非常に高速です。

また、後処理アニメーションは必要ないことに注意してください。リアルタイムの更新が必要なため、ヒストグラム アニメーションの例はこの特定のプロセスでは機能しませんでした。

ありがとう

4

2 に答える 2

3

新しいバージョンの Matplotlib を使用している場合は、定型コードの一部を削減するのに役立つanimations.FuncAnimationクラスがあります。(例については、このページを参照してください。) かなり高速です (~ 52 フレーム/秒):

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import timeit

clock = timeit.default_timer

fig, ax = plt.subplots()

alphab = ['A', 'B', 'C', 'D', 'E', 'F']
frequencies = [1, 44, 12, 11, 2, 10]

pos = np.arange(len(alphab))
width = 1.0     # gives histogram aspect to the bar diagram
ax.set_xticks(pos + (width / 2))
ax.set_xticklabels(alphab)

rects = plt.bar(pos, frequencies, width, color='r')
start = clock()

def animate(arg, rects):
    frameno, frequencies = arg
    for rect, f in zip(rects, frequencies):
        rect.set_height(f)
    print("FPS: {:.2f}".format(frameno / (clock() - start))) 

def step():
    for frame, bin_idx in enumerate(np.linspace(0,1000000,100000000), 1):
        #Here we just change the first bin, so it increases through the animation.
        frequencies[0] = bin_idx
        yield frame, frequencies


ani = animation.FuncAnimation(fig, animate, step, interval=10,
                              repeat=False, blit=False, fargs=(rects,))
plt.show()

新しいバージョンの Matplotlib を持っていない場合は、古い方法でこれを行うことができます。少し遅いです (~ 45 フレーム/秒):

plt.barループの繰り返しごとに呼び出さないでください。rects代わりに、一度だけ呼び出し、戻り値を保存してから、ループの後続の繰り返しでset_heightそれらの高さを変更するために呼び出します。rectsこのトリック (およびその他) は、Matplotlib アニメーション クックブックで説明されています。

import sys
import matplotlib as mpl
mpl.use('TkAgg')  # do this before importing pyplot
import matplotlib.pyplot as plt
import numpy as np
import timeit

clock = timeit.default_timer

fig, ax = plt.subplots()

alphab = ['A', 'B', 'C', 'D', 'E', 'F']
frequencies = [1, 44, 12, 11, 2, 10]

pos = np.arange(len(alphab))
width = 1.0     # gives histogram aspect to the bar diagram
ax.set_xticks(pos + (width / 2))
ax.set_xticklabels(alphab)

def animate():
    start = clock()
    rects = plt.bar(pos, frequencies, width, color='r')
    for frameno, bin_idx in enumerate(np.linspace(0,1000000,100000000), 2):
        #Here we just change the first bin, so it increases through the animation.
        frequencies[0] = bin_idx
        # rects = plt.bar(pos, frequencies, width, color='r')
        for rect, f in zip(rects, frequencies):
            rect.set_height(f)
        fig.canvas.draw()
        print("FPS: {:.2f}".format(frameno / (clock() - start)))         

win = fig.canvas.manager.window
win.after(1, animate)
plt.show()

比較のためplt.clfに、元のコードに追加すると、私のマシンでは毎秒約 12 フレームに達します。


タイミングに関するいくつかのコメント:

ループを通過するたびに非常にわずかな時間差を計算しても、正確な測定値は得られません。の時間分解能はtime.time()、少なくとも私のコンピュータでは十分ではありません。1 つの開始時間を測定し、開始時間と現在の時間の間の大きな時間差を計算してから、フレーム数で割ると、より正確な測定値が得られます。

にも変更time.timeしましたtimeit.default_timer。この 2 つは Unix コンピュータでは同じですが、Windows マシンでtimeit.default_timerは に設定されています。time.clockしたがってtimeit.default_timer、プラットフォームごとにより正確なタイマーを選択します。

于 2013-08-19T18:46:55.927 に答える