ここで図の再描画に問題があります。ユーザーが時間スケール(x軸)で単位を指定できるようにし、この関数plots()
を再計算して呼び出します。図に別のプロットを追加するのではなく、プロットを更新するだけです。
def plots():
global vlgaBuffSorted
cntr()
result = collections.defaultdict(list)
for d in vlgaBuffSorted:
result[d['event']].append(d)
result_list = result.values()
f = Figure()
graph1 = f.add_subplot(211)
graph2 = f.add_subplot(212,sharex=graph1)
for item in result_list:
tL = []
vgsL = []
vdsL = []
isubL = []
for dict in item:
tL.append(dict['time'])
vgsL.append(dict['vgs'])
vdsL.append(dict['vds'])
isubL.append(dict['isub'])
graph1.plot(tL,vdsL,'bo',label='a')
graph1.plot(tL,vgsL,'rp',label='b')
graph2.plot(tL,isubL,'b-',label='c')
plotCanvas = FigureCanvasTkAgg(f, pltFrame)
toolbar = NavigationToolbar2TkAgg(plotCanvas, pltFrame)
toolbar.pack(side=BOTTOM)
plotCanvas.get_tk_widget().pack(side=TOP)
基本的に2つのオプションがあります。
現在実行していることを正確に実行しますが、データを再プロットする前にgraph1.clear()
およびgraph2.clear()
を呼び出します。これは最も低速ですが、最も単純で最も堅牢なオプションです。
再プロットの代わりに、プロットオブジェクトのデータを更新するだけです。コードにいくつかの変更を加える必要がありますが、これは毎回再プロットするよりもはるかに高速です。ただし、プロットするデータの形状は変更できません。データの範囲が変更されている場合は、x軸とy軸の制限を手動でリセットする必要があります。
2番目のオプションの例を示します。
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 6*np.pi, 100)
y = np.sin(x)
# You probably won't need this if you're embedding things in a tkinter plot...
plt.ion()
fig = plt.figure()
ax = fig.add_subplot(111)
line1, = ax.plot(x, y, 'r-') # Returns a Tuple of line objects, thus the comma
for phase in np.linspace(0, 10*np.pi, 500):
line1.set_ydata(np.sin(x + phase))
fig.canvas.draw()
fig.canvas.flush_events()
また、次のようにすることもできます。これにより、forループの50サイクルのプロットに10x1のランダムマトリックスデータが描画されます。
import matplotlib.pyplot as plt
import numpy as np
plt.ion()
for i in range(50):
y = np.random.random([10,1])
plt.plot(y)
plt.draw()
plt.pause(0.0001)
plt.clf()
これは私のために働いた。毎回グラフを更新する関数を繰り返し呼び出します。
import matplotlib.pyplot as plt
import matplotlib.animation as anim
def plot_cont(fun, xmax):
y = []
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
def update(i):
yi = fun()
y.append(yi)
x = range(len(y))
ax.clear()
ax.plot(x, y)
print i, ': ', yi
a = anim.FuncAnimation(fig, update, frames=xmax, repeat=False)
plt.show()
「fun」は整数を返す関数です。 FuncAnimationは繰り返し「更新」を呼び出し、「xmax」回実行します。
誰かが私が探していたものを探してこの記事を見つけた場合、私は例を見つけました
そして
http://mri.brechmos.org/2009/07/automatically-update-a-figure-in-a-loop(on web.archive.org)
次に、その場で輪郭を生成して使用する代わりに、フレームの入力スタックでimshowを使用するように変更しました。
frames
と呼ばれる形状(nBins、nBins、nBins)の画像の3D配列で始まります。
def animate_frames(frames):
nBins = frames.shape[0]
frame = frames[0]
tempCS1 = plt.imshow(frame, cmap=plt.cm.gray)
for k in range(nBins):
frame = frames[k]
tempCS1 = plt.imshow(frame, cmap=plt.cm.gray)
del tempCS1
fig.canvas.draw()
#time.sleep(1e-2) #unnecessary, but useful
fig.clf()
fig = plt.figure()
ax = fig.add_subplot(111)
win = fig.canvas.manager.window
fig.canvas.manager.window.after(100, animate_frames, frames)
また、堅牢ではありませんが、このプロセス全体を実行するはるかに簡単な方法を見つけました。
fig = plt.figure()
for k in range(nBins):
plt.clf()
plt.imshow(frames[k],cmap=plt.cm.gray)
fig.canvas.draw()
time.sleep(1e-6) #unnecessary, but useful
これらは両方ともipython --pylab=tk
、a.k.a .backend = TkAgg
でのみ動作するように見えることに注意してください
すべての助けてくれてありがとう。
Matlabのdrawnow
に似た、通常forループ内で呼び出されるFigureの更新を可能にする機能を提供する python-drawnow というパッケージをリリースしました。
使用例:
from pylab import figure, plot, ion, linspace, arange, sin, pi
def draw_fig():
# can be arbitrarily complex; just to draw a figure
#figure() # don't call!
plot(t, x)
#show() # don't call!
N = 1e3
figure() # call here instead!
ion() # enable interactivity
t = linspace(0, 2*pi, num=N)
for i in arange(100):
x = sin(2 * pi * i**2 * t / 100.0)
drawnow(draw_fig)
このパッケージは、任意のmatplotlib Figureで動作し、各Figureの更新またはデバッガーへのドロップ後に待機するオプションを提供します。
上記はすべて真実かもしれませんが、私にとっては、数字の「オンライン更新」は一部のバックエンド、特にwx
でのみ機能します。これに変更してみてください。 ipython --pylab=wx
でipython/pylabを起動して!がんばろう!