Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

matplotlib.animation.FuncAnimation lagging when resizing the plot window (more than 5 seconds)

The code below generates random data, and displays it in realtime with Matplotlib. The sliders allow the user to change the y-axis range. All of this works.

Problem: when resizing the window size or moving the window, there is a performance problem: the plot is lagging during 5 seconds (and sometimes it comes back, and then lags again), sometimes even closer to 10 seconds (in an average i5 computer).

How to troubleshoot this in matplotlib.animation?

enter image description here

import numpy as np, threading, time
import matplotlib.animation as animation, matplotlib.pyplot as plt, matplotlib.widgets as widgets
class Test():
    def generate(self):  # generate random data
        while True:
            self.realtime_y = {i: np.random.rand(100) for i in range(4)}
            self.realtime_m = {i: np.random.rand(100) for i in range(4)}
            time.sleep(0.030)
    def start_gen(self):
        threading.Thread(target=self.generate).start()
    def realtime_visualization(self):
        fig = plt.figure("Test", figsize=(10, 6))
        ax1, ax2, ax3, ax4 = fig.subplots(4)
        ax1.set_ylim(Y_AXIS_RANGE)        
        ax2.set_ylim(Y_AXIS_RANGE)
        sliders = [widgets.Slider(ax3, f"Ymin", Y_AXIS_RANGE[0], Y_AXIS_RANGE[1], valinit=Y_AXIS_RANGE[0]),
                    widgets.Slider(ax4, f"Ymax", Y_AXIS_RANGE[0], Y_AXIS_RANGE[1], valinit=Y_AXIS_RANGE[1])]        
        sliders[0].on_changed(lambda v: [ax1.set_ylim(bottom=v), ax2.set_ylim(bottom=v)])
        sliders[1].on_changed(lambda v: [ax1.set_ylim(top=v), ax2.set_ylim(top=v)])
        l1 = {}
        l2 = {}
        for i, c in enumerate(["k", "r", "g", "b"]):
            l1[i], *_ = ax1.plot(self.realtime_y[i], color=c)
            l2[i], *_ = ax2.plot(self.realtime_m[i], color=c)        
        def func(n):
            for i in range(4):
                l1[i].set_ydata(self.realtime_y[i])
                l2[i].set_ydata(self.realtime_m[i])
        self.realtime_animation = animation.FuncAnimation(fig, func, frames=None, interval=30, blit=False, cache_frame_data=False)
        plt.show()
Y_AXIS_RANGE = [-3, 3]
t = Test()            
t.start_gen()
t.realtime_visualization()

Obviously with interval=500 the problem is less visible, but the animation has less fps, which is not always possible (e.g. if we have fast-moving data).

like image 869
Basj Avatar asked Jul 25 '26 02:07

Basj


1 Answers

As advised by @furas, this solves the problem indeed:

import matplotlib
matplotlib.use('wxAgg')

instead of TkAgg. Note that this requires pip install wxPython.

PS: It also works with QtAgg. So the problem comes from TkAgg.

like image 181
Basj Avatar answered Jul 27 '26 17:07

Basj