Matplotlib - 带数据生成器的动画轮廓图

时间:2014-05-09 15:04:41

标签: python animation matplotlib

我正在编写一个简单的代码来演示点源的振荡行为。我想用matplotlib.animation制作一个动画。

我有一个工作代码(见下文),但它依赖于预先计算所有帧的值并将它们保存在内存中。我一直在尝试使用生成器重新编写它,以便在需要时可以计算每个帧,如下例所示:

http://matplotlib.org/examples/animation/animate_decay.html

我已经设法使用此处给出的指导解决了一些问题:

http://matplotlib.1069221.n5.nabble.com/Matplotlib-1-1-0-animation-vs-contour-plots-td18703.html

但是现在我在更新我无能为力的动画时会得到KeyErrors:

Traceback (most recent call last):
File "/usr/lib/pymodules/python2.7/matplotlib/backend_bases.py", line 1092, in _on_timer
ret = func(*args, **kwargs)
File "/usr/lib/pymodules/python2.7/matplotlib/animation.py", line 315, in _step
still_going = Animation._step(self, *args)
File "/usr/lib/pymodules/python2.7/matplotlib/animation.py", line 177, in _step
self._draw_next_frame(framedata, self._blit)
File "/usr/lib/pymodules/python2.7/matplotlib/animation.py", line 195, in _draw_next_frame
self._pre_draw(framedata, blit)
File "/usr/lib/pymodules/python2.7/matplotlib/animation.py", line 208, in _pre_draw
self._blit_clear(self._drawn_artists, self._blit_cache)
File "/usr/lib/pymodules/python2.7/matplotlib/animation.py", line 248, in _blit_clear
a.figure.canvas.restore_region(bg_cache[a])
KeyError: <matplotlib.axes.PolarAxesSubplot object at 0x37e2290>

代码:

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

class monopole(object):

    def __init__(self):
        """
        Construct by initialising the itnernal fields
        """
        self.omega = 2000.0 # frequency
        self.Q = 1.0 # strength
        self.c = 1500. # speed of sound
        self.rho = 1000. # density
        self.k = self.omega/self.c # wavenumber

    def getSources(self,thetaGrid,Rgrid,t):
        """
        Calculates the monopole source values for the given time on the specified mesh
        NOTE: the time-dependency here is exemplary, not a proper monopole formula
        """
        return self.Q*self.rho*self.c*self.k/(4.*np.pi*Rgrid) * np.sin(self.omega*max(1e-20,t))

def getData():
    """
    Creates a constructor for a list filled with time and data values
    """
    t = getData.T0
    cnt = 0
    while cnt < getData.nT:
        cnt+=1
        t += getData.T1/getData.nT
        yield t, getData.source.getSources(getData.thetaGrid,getData.Rgrid,t)

def updatePreCalc(i,ax,thetaGrid,Rgrid,data):
    """
    Clears and updates the current plot to show the new frame
    """
    ax.cla()
    im = plt.contour(thetaGrid, Rgrid, data[i], 100)
    return im,

def update(data,ax,thetaGrid,Rgrid):
    """
    Clears and updates the current plot to show the new frame
    """
    ax.cla()
    t,z = data
    im = plt.contour(thetaGrid, Rgrid, z, 100)
    def setvisible(self,vis):
        for c in self.collections: c.set_visible(vis)
    im.set_visible = types.MethodType(setvisible,im,None)
    im.axes = ax
    return im,

# GRID
theta = np.linspace(0.,2.*np.pi,360)
R = np.linspace(0.1,1.0,50)
thetaGrid, Rgrid = np.meshgrid(theta, R)

# CONSTANTS

# initialise a monopole object
mon1 = monopole()

# initialise the timing function
getData.T0 = 0. # start time
getData.T1 = 10. # max time
getData.nT = 1000 # no.  time intervals

# associate the timing function with the grid and monopole
getData.thetaGrid = thetaGrid
getData.Rgrid = Rgrid
getData.source = mon1

# create data for each frame
time,data = [0.]*getData.nT, [0.]*getData.nT
i = 0
for frame in getData():
    time[i] = frame[0]
    data[i] = frame[1]
    i += 1

# PLOTTING

# set the window
fig = plt.figure(figsize=(12,10))
plt.subplot(1,1,1,polar=True)

# initial state
im = plt.contour(thetaGrid,Rgrid, mon1.getSources(thetaGrid,Rgrid,0.), 100)
plt.colorbar(im)
ax = fig.gca()

# aimate
# This works:
#ani = animation.FuncAnimation(fig, updatePreCalc, frames=xrange(getData.nT), fargs=(ax,thetaGrid,Rgrid,data), interval=1)
# This doesn't work
ani = animation.FuncAnimation(fig, update, getData, blit=True,fargs=(ax,thetaGrid,Rgrid), interval=1, repeat=False)

plt.show()

0 个答案:

没有答案