I am a newbie to python and the various libraries. In my attempts to get up to speed I am have been attempting to learn to create, manage and visualize data sets. Part of this process has been attempting to set up a 2 x 2 animated plot of 4 distributions, and then using slider control to manipulate the various parameters of these distributions. Unfortunately I am now stuck....I have been able to get the animation to work with no sliders and also to draw the sliders. But am yet to get the sliders to work with the animation. So I have three questions if anyone is able to help.
- Any advice on where I am going wrong with my code and why the animation is not working?
- Once the animation has commenced, is there anyway to change the distribution parameters and therefore get the plots to change?
- Any advice on my coding would be much appreciated.
Code as follows (thanks in advance!):
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()