Animation not working on matplotlib

2020-02-13 04:34发布

问题:

I am trying to make an animation of the shape an exponential distribution as the sample size increases (from 100 to 1000). There is also a slider to configure the lambda parameter of the distribution and a button to start the animation.

My problem is that even though the layout gets rendered, when I press the start button no animation occurs. Here's my attempt so far:

Editted to simplify things, I am running it in the Python notebook:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.widgets import Slider

n0 = 100
n1 = 1000

#Create figure object
fig, ax = plt.subplots(1,1)
plt.subplots_adjust(bottom=0.3)

#Create Sliders for parameters
axlam = plt.axes([0.20, 0.05, 0.20, 0.03], facecolor=axcolor)

slam = Slider(axlam, 'Exp lambda', 0, 5, valinit=1)

#Default distributions
dexp = np.random.exponential(1, n1)

#Updates distributions when sliders are changed
def updateDist(val):
    lam = slam.val
    dexp = np.random.exponential(lam, n1)

slam.on_changed(updateDist)

#updates plot on FuncAnimation call
def update(curr):
    if( curr == (n1-n0) ):
        a.event.source.stop()
    plt.cla()
    bins_exp = np.arange(0,4/slam.val,0.25)
    ax.hist(dexp[:(n0+curr)],bins=bins_exp)
    ax.set_title('Exp n={}'.format(n0+curr))

#Define Start button and function to start animation
goax = plt.axes([0.8, 0.025, 0.1, 0.04])
button = Button(goax, 'Start', color=axcolor, hovercolor='0.975')    

a = None
def start(event):
    a = animation.FuncAnimation(fig,update,interval=100)
button.on_clicked(start)

回答1:

You should mind the namespaces of functions.

Consider

a = 0
def f():
    a = 1
f()
print(a) # will print 0

So you need to work on the actual objects and not some local copy of them.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.widgets import Slider, Button

n0 = 100
n1 = 1000

#Create figure object
fig, ax = plt.subplots(1,1)
plt.subplots_adjust(bottom=0.3)

#Create Sliders for parameters
axcolor = "skyblue"
axlam = plt.axes([0.20, 0.05, 0.20, 0.03], facecolor=axcolor)

slam = Slider(axlam, 'Exp lambda', 0, 5, valinit=1)

#Default distributions
dexp = [np.random.exponential(1, n1)]

##Updates distributions when sliders are changed
def updateDist(val):
    lam = slam.val
    dexp[0] = np.random.exponential(lam, n1)

slam.on_changed(updateDist)

#updates plot on FuncAnimation call
def update(curr):
    if( curr == (n1-n0) ):
        a.event.source.stop()
    ax.clear()
    bins_exp = np.arange(0,4/slam.val,0.25)
    ax.hist(dexp[0][:(n0+curr)],bins=bins_exp)
    ax.set_title('Exp n={}'.format(n0+curr))
    fig.canvas.draw_idle()

#Define Start button and function to start animation
goax = plt.axes([0.8, 0.025, 0.1, 0.04])
button = Button(goax, 'Start', color=axcolor, hovercolor='0.975')    

a = [0]
def start(event):
    a[0] = animation.FuncAnimation(fig,update,interval=100)
button.on_clicked(start)

plt.show()