简体   繁体   中英

How to combine a slider with an animation?

Using matplotlib.animation and matplotlib.widgets (sliders and buttons), I wanted to create an animated simulation of a distribution (starting from a sample and ending in a big one), which takes as input from the user the parameters of the distribution using widgets. This is my code:

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

#create fig
fig,((ax1,ax2))=plt.subplots(2,1,sharex=True)
fig.suptitle("Sampling of Distributions\n\n(Parametrize and then run)", fontsize="x-large")

#animation function
def update(curr):
    # check if animation is at the last frame, and if so, stop the animation 
    if curr*100+100 == n: 
        a.event_source.stop()

    plt.subplot(2, 1, 1)
    plt.cla()
    plt.axis([np.round(np.percentile(x1,.05)),np.round(np.percentile(x1,99.5)),0,1])   #plot 99% cuantile
    plt.hist(x1[:curr*100+100], normed=True, bins=20, alpha=0.5)
    plt.gca().set_title('\n\nNormal n={}'.format(curr*100+100))


#sliders axis
ax2=plt.subplot(2, 1, 2)             
ax2.axis('off')
ax2.set_title('\nParametrize Normal Distribution')
axis_color = 'lightgoldenrodyellow'
E0_slider_ax = fig.add_axes([0.13, .22, 0.3, 0.02], axisbg=axis_color)
E1_slider_ax = fig.add_axes([0.13, .17, 0.3, .02], axisbg = axis_color)
E0_slider = Slider(E0_slider_ax, r'Normal $\mu$', valmin = -5, valmax = 5, valinit = -2.5)
E0_slider.label.set_size(15)
E1_slider = Slider(E1_slider_ax, r'Normal $\sigma$', 0, 5, valinit = 1)
E1_slider.label.set_size(15)

#generate random numbers with slider values
def slider_on_change(val):   #generate the random numbers 
    x1 = np.random.normal(E0_slider.val, E1_slider.val, n)
E0_slider.on_changed(slider_on_change)
E1_slider.on_changed(slider_on_change)

#create animation start button
def animate_button(self):
    a = animation.FuncAnimation(fig, update, frames=100,interval=100)
    plt.Figure.canvas.show()

#animation button
axnext = fig.add_axes([0.785, 0.02,0.1, 0.075], axisbg = axis_color)
bnext = Button(axnext, 'Run Simulations!')
bnext.on_clicked(animate_button)


plt.show()

The slider is created but the animation never starts. Could please provide me some clues?

在此处输入图片说明

The order of operations is a little off and some variables are not accessible as this is written. For example n is never defined. I went ahead and set it to 5000 to draw a pretty reasonably sized distribution. You also don't explicitly need to do anything when the slider is changed, but rather reference the value of the sliders within update . Something like this should work.

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

#create fig
fig,((ax1,ax2))=plt.subplots(2,1,sharex=True)
fig.suptitle("Sampling of Distributions\n\n(Parametrize and then run)", fontsize="x-large")

#sliders axis
ax2=plt.subplot(2, 1, 2)             
ax2.axis('off')
ax2.set_title('\nParametrize Normal Distribution')
axis_color = 'lightgoldenrodyellow'
E0_slider_ax = fig.add_axes([0.13, .22, 0.3, 0.02], axisbg=axis_color)
E1_slider_ax = fig.add_axes([0.13, .17, 0.3, .02], axisbg = axis_color)
E0_slider = Slider(E0_slider_ax, r'Normal $\mu$', valmin = -5, valmax = 5, valinit = -2.5)
E0_slider.label.set_size(15)
E1_slider = Slider(E1_slider_ax, r'Normal $\sigma$', 0, 5, valinit = 1)
E1_slider.label.set_size(15)

#animation function
def update(curr, x1):
    plt.subplot(2, 1, 1)
    plt.cla()


    plt.axis([np.round(np.percentile(x1,.05)),np.round(np.percentile(x1,99.5)),0,1])   #plot 99% cuantile
    plt.hist(x1[:curr*100+100], normed=True, bins=20, alpha=0.5)
    plt.gca().set_title('\n\nNormal n={}'.format(curr*100+100))

#create animation start button
def animate_button(self):
    x1 = np.random.normal(E0_slider.val, E1_slider.val, 5000)
    a = animation.FuncAnimation(fig, update, , fargs=(x1, ), frames=100,interval=500, repeat=False)
    fig.canvas.draw()

#animation button
axnext = fig.add_axes([0.785, 0.02,0.1, 0.075], axisbg = axis_color)
bnext = Button(axnext, 'Run Simulations!')
bnext.on_clicked(animate_button)

plt.show()

Upon clicking the Run Simulation button it creates x1 based on the set values of mu and sigma. For each iteration it draws a sample of size iteration_num * 100 + 100 and plots the updated distribution. The process stops and does not repeat after 100 iterations. This is an image of the last frame.

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM