Search code examples
pythonmatplotlibanimationmathmatplotlib-animation

How do you smoothen matplotlib animations?


I'm relatively new to programming, and I've tried using matplotlib's animation library to, quite obviously, animate. However, the animation I produce is really slow and discontinuous. The following code is an example of this, it does, however, involve a relatively large number of computations. random_set is just a randomly generated set, temp_set serves to be a copy of random_set because I sort random_set later, and new_set just stores the values of the change in y and x that the animation will alter each point by. I've tried using transform on the ax.texts that might make it faster, but I learned that transform doesn't mean it in the traditional mathematics way; so I just resorted to constantly deleting and replotting these points. Is there any way to speed up the animation? I feel the entire piece of code is necessary to demonstrate the extent of the problem.

import matplotlib.pyplot as plt
import matplotlib.animation as animation
import random
import math

fig , ax = plt.subplots()

random_set = []
while len(random_set) != 99:
    choice = random.randint(-100,100)
    if choice in random_set:
        pass
    else:
        random_set.append(choice)
print(random_set)

lengths = [(i,int(len(random_set) / i)) for i in range(1,int(len(random_set) ** (1/2) + 1)) if len(random_set) % i == 0][-1]
print(lengths)
counter = 0

temp_set = []
for i in random_set:
    plt.text(*(counter % lengths[1],math.floor(counter / lengths[1])),i)
    temp_set.append((i,counter % lengths[1],math.floor(counter / lengths[1])))
    counter += 1
random_set.sort()

x_lims = (0,lengths[1])
y_lims = (0,lengths[0])
ax.set_xlim(*x_lims)
ax.set_ylim(*y_lims)
plt.axis("off")

new_set = []
for j in temp_set:
    new_x = random_set.index(j[0]) / lengths[0]
    random_set[random_set.index(j[0])] = None
    new_y = (lengths[0] - 1) / 2
    dy = (new_y - j[2]) / 250
    dx = (new_x - j[1]) / 250
    new_set.append((j[0],dx,dy))

def percentile(i):
    ax.texts.clear()
    for j in range(0,len(new_set)):
        plt.text(temp_set[j][1] + (i * new_set[j][1]),temp_set[j][2] + (i * new_set[j][2]),new_set[j][0])

animate = animation.FuncAnimation(fig, func = percentile, frames = [i for i in range(1,251)], interval = 1,repeat = False)
plt.show()

Solution

  • Check this code:

    import matplotlib.pyplot as plt
    import matplotlib.animation as animation
    import random
    import math
    
    fig , ax = plt.subplots()
    N = 25
    
    random_set = []
    while len(random_set) != 99:
        choice = random.randint(-100,100)
        if choice in random_set:
            pass
        else:
            random_set.append(choice)
    print(random_set)
    
    lengths = [(i,int(len(random_set) / i)) for i in range(1,int(len(random_set) ** (1/2) + 1)) if len(random_set) % i == 0][-1]
    print(lengths)
    counter = 0
    
    temp_set = []
    for i in random_set:
        plt.text(*(counter % lengths[1],math.floor(counter / lengths[1])),i)
        temp_set.append((i,counter % lengths[1],math.floor(counter / lengths[1])))
        counter += 1
    random_set.sort()
    
    x_lims = (0,lengths[1])
    y_lims = (0,lengths[0])
    ax.set_xlim(*x_lims)
    ax.set_ylim(*y_lims)
    plt.axis("off")
    
    new_set = []
    for j in temp_set:
        new_x = random_set.index(j[0]) / lengths[0]
        random_set[random_set.index(j[0])] = None
        new_y = (lengths[0] - 1) / 2
        dy = (new_y - j[2]) / N
        dx = (new_x - j[1]) / N
        new_set.append((j[0],dx,dy))
    
    def percentile(i):
        ax.texts.clear()
        for j in range(0,len(new_set)):
            plt.text(temp_set[j][1] + (i * new_set[j][1]),temp_set[j][2] + (i * new_set[j][2]),new_set[j][0])
    
    animate = animation.FuncAnimation(fig, func = percentile, frames = [i for i in range(1,N+1)], interval = 1, repeat = False)
    plt.show()
    

    I replaced your 250 with N (and 251 with N+1), then I set N = 25 in order to decrease the number of frames. This is the result:

    enter image description here