Python 3.9, matplotlib 3.4, Mac OS 11.6.1
I have a slider on a tkinter Toplevel containing a figure convas showing two sets of axes. As the slider advances, the axes illustrate the heatplots over time for two sequences of 4-by-300 matrices. Each increment of the slider value increases the number of depicted columns for each matrix by 10. The problem I encounter is that the slider becomes unresponsive after a couple frames.
import numpy as np
import matplotlib.pyplot as plt
import random
from matplotlib.widgets import Slider
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from tkinter import Tk,TOP,BOTH,Toplevel
import matplotlib
matplotlib.use('TkAgg',force=True)
def scrolling_matrix_viewer(M,channels,win_size):
plot_window = Toplevel(bg="lightgray")
plot_window.geometry('1000x900')
plot_window.attributes('-topmost', 'true')
fig, ax = plt.subplots(2,sharex=True)
canvas = FigureCanvasTkAgg(fig, master=plot_window)
canvas.draw()
canvas.get_tk_widget().pack(side=TOP,fill=BOTH,expand=1)
ax[0].invert_yaxis
fig.subplots_adjust(left=.09, bottom=.2, right=None, top=.9, wspace=.2,
hspace=.2)
ax_time=fig.add_axes([0.15, 0.1, 0.65, 0.03]) # axis for slider
spos = Slider(ax_time, '',valinit=0,valmin=0,valmax=M.shape[1]-
win_size,valstep=win_size)
def update_graph(val):
start=spos.val #starting column index of M used for this frame
stop=spos.val+win_size #ending column index of M used for this frame
if stop<=M.shape[1]:
ax[0].cla
ax[1].cla
heatmap0=ax[0].imshow(M[:,start:stop],vmin=0, vmax=1, cmap='coolwarm',
aspect='auto',extent=[0,win_size,M.shape[0],0])
heatmap1=ax[1].imshow(N[:,start:stop],vmin=0, vmax=1, cmap='coolwarm',
aspect='auto',extent=[0,win_size,N.shape[0],0])
ax_time.set_xlabel('time (sec)',fontsize=12)
ax[0].set_ylabel('channel',fontsize=12)
ticks=ax[0].get_xticks()
x_labels=[str(start+ticks[i]) for i in range(len(ticks))]
ax[0].set_yticks(range(len(channels)))
ax[0].set_yticklabels(channels,fontsize=12)
ax[1].set_ylabel('channel',fontsize=12)
ax[1].set_yticks(range(len(channels)))
ax[1].set_yticklabels(channels,fontsize=12)
spos.on_changed(update_graph)
spos.set_val(0)
# Example
root=Tk()
M=np.random.rand(4,300)
N=np.random.rand(4,300)
channels=['A','B','C','D']
win_size=10 # the number of columns of M we advance by from frame to frame
scrolling_matrix_viewer(M,channels,win_size)
root.mainloop()
The image below shows the result. The slider becomes unresponsive when spos.val
is 20
I have noticed that when only one matrix is used, hence only one set of axes, then everything works fine. Also, the animation for both matrices works fine when I'm simply creating the animation using matplotlib and not placing the result on a figure canvas.
ALSO: The fact that all the animation takes place inside a function could be the source of the problem. Specifically, when the matrices M and N are entered at the start of the file and all commands are executed outside a function, with the exception of the update, everything works fine.