使用matplotlib.animation和matplotlib.widgets(滑块和按钮),我想创建一个分布的动画模拟(从一个样本开始,以一个大的结尾),它从用户那里获取参数使用小部件的分发。这是我的代码:
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()
创建滑块但动画永远不会启动。 请给我一些线索吗?
答案 0 :(得分:0)
操作顺序稍微偏离,因为写入了一些变量是不可访问的。例如,永远不会定义n
。我继续将其设置为5000以绘制相当合理的分布。更改滑块时,您也不需要明确地执行任何操作,而是在update
中引用滑块的值。这样的事情应该有效。
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()
点击Run Simulation
按钮后,根据mu和sigma的设定值创建x1
。对于每次迭代,它都会绘制一个大小为iteration_num * 100 + 100
的样本,并绘制更新的分布。该过程在100次迭代后停止并且不重复。这是最后一帧的图像。