0

I've been obsessing over a minor detail in an animation function I'm designing. The animation as a whole has the following properties:

  1. The animation will be placed on a tkinter figure canvas.
  2. 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 in M_list and bar_list is the same, and each individual list in bar_list has length equal to the dimension of each matrix in M_list.
  3. 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 in bar_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!!!

fishbacp
  • 865
  • 8
  • 20

0 Answers0