I've been obsessing over a minor detail in an animation function I'm designing. The animation as a whole has the following properties:
- The animation will be placed on a tkinter figure canvas.
- The function accepts as inputs the name of tkinter main window,
root, a list of axes labels,channels, a list of square matrices of equal dimension,M_list, and a list of lists,bar_list. The number of elements inM_listandbar_listis the same, and each individual list inbar_listhas length equal to the dimension of each matrix inM_list. - Each frame of the animation consists of a figure having two axes. The first axis is the heatmap of a matrix in
M_list, to which is appended a colorbar. The second axis appears below the first and consists of a barplot of the corresponding list inbar_list. The figure includes an animation player console as described at Managing dynamic plotting in matplotlib Animation module
Here's the function:
def heatplot_barplot_animation_combined(root,channels,M_list,bar_list):
num_times=len(M_list)-1
fig, ax = plt.subplots(2)
plot_window = Toplevel(root,bg="lightgray")
plot_window.geometry('700x700')
plot_window.wm_title(title)
canvas = FigureCanvasTkAgg(fig, master=plot_window)
canvas.draw()
canvas.get_tk_widget().pack(side=TOP,fill=BOTH,expand=1)
def update_graph(i):
ax[0].cla #clears both the heatmap and corresponding colorbar
ax[0].set_xticks(range(len(channels)))
ax[0].set_xticklabels(channels,fontsize=10)
ax[0].set_yticks(range(len(channels)))
ax[0].set_yticklabels(channels,fontsize=10,rotation=0)
heatmap=ax[0].imshow(M_list[i],vmin=0, vmax=1, cmap='coolwarm', aspect='auto')
ax0_divider = make_axes_locatable(ax[0])
cax0 = ax0_divider.append_axes('right', size='7%', pad='2%')
cb = fig.colorbar(heatmap, cax=cax0, orientation='vertical')
ax[1].cla()
ax[1].bar(channels,bar_list[i])
ax[1].set_ylim(0, 1)
fig.suptitle('Frame: '+str(i*conn_win_value)+ ' sec', fontsize=12)
ani = Player(fig, update_graph, maxi=num_times) #Player class as defined at above URL
Sample implementation, where relevant packages have already been loaded:
root=Tk()
root.title('Main Window')
root.geometry('1000x1000')
channels=['a','b','c','d','e','f','g','h']
Nc=len(channels)
Nt=50
M_list=[np.random.rand(Nc,Nc) for i in range(Nt)]
bar_list=[[random.uniform(0,1) for i in range(Nc)] for t in range(Nt)]
heatplot_centrality_animation_combined(root,channels,M_list,bar_list)
root.mainloop()
Works just the way I want, except the first frame has axes labelled numerically instead of using entries in channels. Ugh!!!