0

I'm trying to plot data that is generated in runtime. In order to do so I'm using matplotlib.animation.FuncAnimation.

While the data is displayed correctly, the axis values are not updating accordingly to the values that are being displayed:

graph animation

The x axis displays values from 0 to 10 eventhough I update them in every iteration in the update_line function (see code below).

DataSource contains the data vector and appends values at runtime, and also returns the indexes of the values being returned:

import numpy as np

class DataSource:
    data = []
    display = 10

    # Append one random number and return last 10 values
    def getData(self):
        self.data.append(np.random.rand(1)[0])
        if(len(self.data) <= self.display):
            return self.data
        else:
            return self.data[-self.display:]

    # Return the index of the last 10 values
    def getIndexVector(self):
        if(len(self.data) <= self.display):
            return list(range(len(self.data)))

        else:
            return list(range(len(self.data)))[-self.display:]

I've obtained the plot_animation function from the matplotlib docs.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from datasource import DataSource


def update_line(num, source, line):
    data = source.getData()
    indexs = source.getIndexVector()
    if indexs[0] != 0:
        plt.xlim(indexs[0], indexs[-1])
        dim=np.arange(indexs[0],indexs[-1],1)
        plt.xticks(dim)
    line.set_data(indexs,data)
    return line,

def plot_animation():
    fig1 = plt.figure()
    source = DataSource()

    l, = plt.plot([], [], 'r-')

    plt.xlim(0, 10)
    plt.ylim(0, 1)
    plt.xlabel('x')
    plt.title('test')
    line_ani = animation.FuncAnimation(fig1, update_line, fargs=(source, l),
                                    interval=150, blit=True)

    # To save the animation, use the command: line_ani.save('lines.mp4')


    plt.show()

if __name__ == "__main__":
    plot_animation()

How can I update the x axis values in every iteration of the animation?

(I appreciate suggestions to improve the code if you see any mistakes, eventhough they might not be related to the question).

  • Is it correct that the data set for the graph in the animation function is out of the IF function, I thought so because I set `plt.xlim(indexes,data)` in the IF function. – r-beginners Sep 16 '21 at 12:35
  • The graph displays 10 values. The IF statement ensures (or at least i want it to ensure) that the axis is only updated once there are more than 10 values in the set, so it has to "move" to the right. – Ferran Capallera Guirado Sep 16 '21 at 12:40
  • I actually got the code to work. Since the data we are drawing is less than 1.0, I think we can handle it by adding the following after the dataset for the graph. `line.set_data(indexs,data);plt.xlim(indexs[0], indexs[-1])` – r-beginners Sep 16 '21 at 13:30
  • We would be setting the xlim to (1,1) at the first iteration, since there would be only one element in the dataset. That answer is not correct. – Ferran Capallera Guirado Sep 16 '21 at 13:58

2 Answers2

1

Here is a simple case of how you can achieve this.

import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
%matplotlib notebook

#data generator
data = np.random.random((100,))

#setup figure
fig = plt.figure(figsize=(5,4))
ax = fig.add_subplot(1,1,1)

#rolling window size
repeat_length = 25

ax.set_xlim([0,repeat_length])
ax.set_ylim([-2,2])


#set figure to be modified
im, = ax.plot([], [])

def func(n):
    im.set_xdata(np.arange(n))
    im.set_ydata(data[0:n])
    if n>repeat_length:
        lim = ax.set_xlim(n-repeat_length, n)
    else:
        lim = ax.set_xlim(0,repeat_length)
    return im

ani = animation.FuncAnimation(fig, func, frames=data.shape[0], interval=30, blit=False)

plt.show()

#ani.save('animation.gif',writer='pillow', fps=30)

enter image description here

Akshay Sehgal
  • 18,741
  • 3
  • 21
  • 51
1

Solution

My problem was in the following line:

line_ani = animation.FuncAnimation(fig1, update_line, fargs=(source, l),
                                    interval=150, blit=True)

What I had to do is change the blit parameter to False and the x axis started to move as desired.