0

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

frisco_1989
  • 75
  • 1
  • 8
  • 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 http://matplotlib.org/examples/animation/animate_decay.html – tacaswell Nov 10 '16 at 22:05
  • 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 Nov 11 '16 at 18:16
  • 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 Nov 11 '16 at 22:07
  • `FuncAnimation` has the re-drawing logic built into it – tacaswell Nov 11 '16 at 22:08

1 Answers1

2

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()
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • Thank you very much for the reply. Well, its kind of important for the app that I am building to show all the data points and hence this requires me to append data to the scatter plot while panning the x axis. Please pardon this question of mine since I am new to PyQT4 and Python in general, what does a comma at the end of `self.scat,` and `self.line,` mean in the declaration? – frisco_1989 Nov 11 '16 at 18:15
  • Stating `x, = [1,2,3]` means that `x` is `1` instead of a list. Since plot returns a list of lines (in our case only one) and we only want to use this line afterwards, `line, = plt.plot(); line.set_data()` is a shortage of `lines = plt.plot(); lines[0].set_data()`. – ImportanceOfBeingErnest Nov 11 '16 at 20:48
  • In my example I'm panning the x axis. Do mean something else? Maybe by *panning* you mean scrolling the right axis limit, but not the left? – ImportanceOfBeingErnest Nov 11 '16 at 20:50
  • Alright, I got it now! Thanks for the very useful information. No, no by panning I mean exactly as portrayed by your example. Just that, The number of points in my data file is very large and at some particular time stamp say x = 600 ms, the y data is very large, I mean many number of points converge at that point and hence the panning of the axis is kind of slowing down. – frisco_1989 Nov 11 '16 at 21:56
  • Also, I wanted to know, because from the example I think, the plotting is hapening in a matplotlib window. But I am embedding this animation in a PyQT4 GUI window. Can I take the same code and put it in my GUI code? Would it pop up another matplotlib window or would it plot in my main gui window? – frisco_1989 Nov 11 '16 at 22:03
  • How many is "many"? Do you really need 10ms update time? Using a slower animation wouldn't make the slow-down effect so obvious. Concerning Matplotlib, you can do both, [embed a figure canvas into PyQt](http://stackoverflow.com/questions/12459811/how-to-embed-matplotib-in-pyqt-for-dummies) as well as simply call plt.show() (which will open a new window as usual) – ImportanceOfBeingErnest Nov 11 '16 at 22:30
  • Many in the sense there are about 100 points for just one particular time stamp. And I dont really need 10 ms update time, but the animation shd be moving and shd not stand still at a particular x point. For now I am working with `plt.show()` and I will concentrate later on bringing into my PyQT4 GUI – frisco_1989 Nov 13 '16 at 10:56