具有动画和滑块的多个子图

时间:2019-03-19 04:13:02

标签: python matplotlib animation widget slider

我是python和各种库的新手。在尝试加快速度的过程中,我一直在尝试学习创建,管理和可视化数据集。此过程的一部分一直在尝试建立2 x 2的4个分布的动画图,然后使用滑块控件来操纵这些分布的各种参数。不幸的是,我现在被困住了...。我已经能够使动画在没有滑块的情况下工作,并且能够绘制滑块。但是还没有让滑块与动画配合使用。因此,如果有人可以提供帮助,我有三个问题。

  1. 关于我的代码哪里出错以及为什么动画不起作用的任何建议?
  2. 动画开始后,是否有必要更改分布参数并因此更改绘图?
  3. 任何有关我的编码的建议将不胜感激。

代码如下(谢谢!):

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.gridspec as gridspec
import matplotlib.animation as animation
import mpl_toolkits.axes_grid1
import matplotlib.widgets 

%matplotlib notebook

n = 1000

gspec = gridspec.GridSpec(7, 2)
fig = plt.figure()

top_left = plt.subplot(gspec[0:2, 0])
top_right = plt.subplot(gspec[0:2, 1])
lower_left = plt.subplot(gspec[3:5, 0])
lower_right = plt.subplot(gspec[3:5, 1])
ax = [top_right, top_left, lower_right, lower_left]
ax_right = [top_right, lower_right]

axis1 = [-5, 0, 0, 0.6]
axis2 = [0, 10, 0, 0.6]
axis3 = [7, 15, 0, 0.6]
axis4 = [14, 20, 0, 0.6]
axis = [axis1, axis2, axis3, axis4]

# generate 4 random variables from the random, gamma, exponential, and uniform distributions
x1 = np.random.normal(-2.5, 1, n)
x2 = np.random.gamma(2, 1.5, n)
x3 = np.random.exponential(2, n)+7
x4 = np.random.uniform(14,20, n)
x = [x1, x2, x3, x4]
bar_color = ['lightgrey', 'lightgrey', 'grey', 'grey']

for a in ax:
    a.spines['left'].set_visible(False)
    a.spines['right'].set_visible(False)
    a.spines['top'].set_visible(False)
    a.tick_params(top=False, bottom=True, left=True, right=False, labelleft=True, labelbottom=True)

for a in ax_right:
    a.spines['left'].set_visible(False)
    a.tick_params(top=False, bottom=True, left=False, right=False, labelleft=False, labelbottom=True)


norm_slidecolor = 'lightgrey'
sd_slidecolor = 'grey'
button_color = 'grey'

normsliderpos_sd = fig.add_axes([0.65, 0.2, 0.25, 0.03], facecolor=norm_slidecolor)
normslider_sd = Slider(normsliderpos_sd, r'Norm $\sigma$', 0, 5, valinit = 1, valstep = 0.5)
normslider_sd.label.set_size(10)

normsliderpos_mean = fig.add_axes([0.65, 0.25, 0.25, 0.03], facecolor=norm_slidecolor)
normslider_mean = Slider(normsliderpos_mean, r'Norm $\mu$', -10, 10, valinit = -2.5, valstep = 0.5)
normslider_mean.label.set_size(10)

expsliderpos_decay = fig.add_axes([0.65, 0.1, 0.25, 0.03], facecolor=sd_slidecolor)
expslider_decay = Slider(expsliderpos_decay, r'Exp Decay', 0, 5, valinit = 2, valstep = 0.5)
expslider_decay.label.set_size(10)

class Player(animation.FuncAnimation):

    def __init__(self, fig, func, frames=None, init_func=None, fargs=None,
                 save_count=None, mini=0, maxi=100, pos=(0.55, 0.02), **kwargs):

        self.i = 0
        self.min=mini
        self.max=maxi
        self.runs = True
        self.forwards = True
        self.fig = fig
        self.func = func
        self.setup(pos)
        animation.FuncAnimation.__init__(self,self.fig, self.func, frames=self.play(), 
                                           init_func=init_func, fargs=fargs,
                                           save_count=save_count, **kwargs )    

    def play(self):
        print(i)
        while self.runs:
            self.i = self.i+self.forwards-(not self.forwards)
            if self.i > self.min and self.i < self.max:
                yield self.i
            else:
                self.stop()
                yield self.i

    def start(self, event = None):
        self.runs=True
        self.event_source.start()

    def stop(self, event=None):
        self.runs = False
        self.event_source.stop()

    def forward(self, event=None):
        self.forwards = True
        self.start()

    def backward(self, event=None):
        self.forwards = False
        self.start()


    def setup(self, pos):
        playerax = self.fig.add_axes([pos[0],pos[1], 0.4, 0.04])
        divider = mpl_toolkits.axes_grid1.make_axes_locatable(playerax)
        sax = divider.append_axes("left", size="100%", pad=0.05)
        fax = divider.append_axes("left", size="100%", pad=0.05)
        stax = divider.append_axes("left", size="100%", pad=0.05)

        self.button_back = matplotlib.widgets.Button(playerax, label='Back')
        self.button_stop = matplotlib.widgets.Button(sax, label='Start')
        self.button_forward = matplotlib.widgets.Button(fax, label='Forward')
        self.button_start = matplotlib.widgets.Button(stax, label='Stop')

        self.button_back.on_clicked(self.backward)
        self.button_stop.on_clicked(self.stop)
        self.button_forward.on_clicked(self.forward)
        self.button_start.on_clicked(self.start)

def update(i):

    if curr >= n: 
        a.event_source.stop()

    for a in range(len(ax)):  
        ax[a].cla()
        ax[a].hist(x[a][:i], density = True, bins = 20, color = bar_color[a])
        ax[a].axis(axis[a])
    fig.suptitle('Normed Frequency. Sample Number: {}'.format(i))

ani = Player(fig, update)

plt.show()

0 个答案:

没有答案