0
votes

I am building a PyQT4 gui which plots a scatter plot of points from a certain file. Now, these points are paired as X,Y in the .txt file. Basically, the X data is a time in milliseconds and Y is a certain event happening at the particular time. I want to create an animated matplotlib scatter plot which pans the time axis from 0 to time t, lets say 1000 ms while the time(X) axis pans in 100 ms frames or sections. So that the plot appears moving from 0 to time t while plotting these points.

The data sample is as shown below:

105.40000000000001  330.0
105.40000000000001  344.0
105.5   259.0
105.5   262.0
.........
.....

And so on..

I am trying to use the FuncAnimation of matplotlib which takes an update method where I try to add more data to the scatter plot. But how do I pan the time axis in 100 ms steps.

I tried using the data generator which yields the next data point every time the update method is called, but the time axis kind of slows down while there are more points.

Here is what I have tried so far.

ani = animation.FuncAnimation(self.figure,self._upd_plot,self.data_gen,blit=False, interval=10, repeat=False)
def data_gen(self):
    for d in self.data:
        yield d

def init_ani(self):
    self.g = self.data_gen()

def _upd_plot(self,d):
    d = next(g)
    self.time.append(d[0])
    self.neu.append(d[1])
    self.scat.set_xdata(self.time)
    self.scat.set_ydata(self.neu)
    self.canvas.draw()

Where is the problem? Any help would be greatly appreciated. Pardon my bad english

1
You do not need the self.canvas.draw(), that gets taken care of in the animation code. I assume there is more class code around this that got dropped? What is self.scat? See matplotlib.org/examples/animation/animate_decay.htmltacaswell
Yes, there is definitely more class code around this which I am still working on. self.scat is a reference to the scatter plot initialisation which is done in init, which is done with empty x and y data.frisco_1989
So do you mean, if just set the data of the plot object, the plot is updated with new points? without redrawing the canvas?frisco_1989
FuncAnimation has the re-drawing logic built into ittacaswell

1 Answers

2
votes

It might be a good idea to only work on those points which are plotted, instead of appending them to a list, if the latter slows things down.

Here is an example of how I would imagine such a panning animation plot and it seems to work fine.

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

class some():
    def __init__(self):
        self.fig = plt.figure()
        self.ax = self.fig.add_subplot(111)
        self.line,  = self.ax.plot([],[], color="red", linestyle="-")
        self.scat, = self.ax.plot([],[], color="orange", marker="s", linestyle="")

        self.data = np.random.rand(1000)
        self.times = np.arange(1000)

        self.stepsize = 10
        self.showntimes = np.arange(self.stepsize)
        self.ax.set_ylim([0,1])
        self.ax.set_xlim([self.showntimes[0],self.showntimes[-1]])

        self.ani = animation.FuncAnimation(self.fig, self._upd_plot, blit=False, interval=60, repeat=False)
        plt.show()

    def _upd_plot(self,i):
        print i
        if i < len(self.data)-self.stepsize:
            self.scat.set_data(self.showntimes, self.data[i:i+self.stepsize])
            self.line.set_data(self.showntimes, self.data[i:i+self.stepsize].mean()*np.ones(len(self.showntimes)) )
            self.ax.set_xticklabels(self.times[i:i+self.stepsize])
        else:
            self.ani.event_source.stop()

if __name__ == '__main__':
    s = some()