animation.FuncAnimation

Hi all,

How do I use animation.FuncAnimation to plot real-life data from parsing a text file ?

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

import sys
import time
import re

x = [] # x
y = [] # y

fig = plt.figure()
ax = fig.add_subplot(111)
curve,= ax.plot([],[],lw=2)
ax.set_xlim(0,5)
ax.grid()

def tail_f(file):
   interval = 1.0

   while True:
     where = file.tell() # current file position, an integer (may be a long integer).
     line = file.readline()
     if re.search('without errors',line): break
     if not line:
       time.sleep(interval)
       file.seek(where) # seek(offset[, whence]) -> None. Move to new file position.
     else:
       yield line

def run():
     for line in tail_f(open(sys.argv[1])):
         print line,
         if re.search('x=',line):
             liste = line.split('=')
             x.append(liste[1].strip())
         if re.search('y=',line):
             liste = line.split('=')
             y.append(liste[1].strip())

             curve.set_data(x,y)
             print x,y

···

#
run()
plt.show()

The text file looks like

x=0.0
y=0.0
blabla
x=1.0
y=1.0
blabla
x=2.0
y=4.0
blabla
...

Nils

Nils,

I think the key thing to keep in mind when using any of the animators is that the animator in question is driving the calls to update the plot from its own event source. In most cases, that source is a timer. For FuncAnimator, the function passed into the constructor must perform whatever actions are needed for a single update.

What I would do is Subclass FuncAnimator so that its constructor will create an empty Line2D object that has already been added to an axes object (or you can pass an empty one yourself as an argument to the function). In the function run(), you would obtain the next chunk of data and then update the Line2D object with that information.

I think you have it mostly done, just need a few extra pieces.

Cheers!
Ben Root

···

On Tue, Dec 20, 2011 at 8:00 AM, Nils Wagner <nwagner@…878…1052…> wrote:

Hi all,

How do I use animation.FuncAnimation to plot real-life

data from parsing a text file ?

import numpy as np

import matplotlib.pyplot as plt

import matplotlib.animation as animation

import sys

import time

import re

x = # x

y = # y

fig = plt.figure()

ax = fig.add_subplot(111)

curve,= ax.plot(,,lw=2)

ax.set_xlim(0,5)

ax.grid()

def tail_f(file):

interval = 1.0

while True:

 where = file.tell()      # current file position, an

integer (may be a long integer).

 line = file.readline()

 if re.search('without errors',line): break

 if not line:

   time.sleep(interval)

   file.seek(where)       # seek(offset[, whence]) ->

None. Move to new file position.

 else:

   yield line

def run():

 for line in tail_f(open(sys.argv[1])):

     print line,

     if re.search('x=',line):

         liste = line.split('=')

         x.append(liste[1].strip())

     if re.search('y=',line):

         liste = line.split('=')

         y.append(liste[1].strip())



         curve.set_data(x,y)

         print x,y

run()

plt.show()

The text file looks like

x=0.0

y=0.0

blabla

x=1.0

y=1.0

blabla

x=2.0

y=4.0

blabla

Nils

Here's a version that does what I think you want:

import matplotlib.pyplot as plt
import matplotlib.animation as animation
import sys
import time
import re

x_data = # x
y_data = # y

fig = plt.figure()
ax = fig.add_subplot(111)
curve,= ax.plot(,,lw=2)
ax.set_xlim(0,5)
ax.set_ylim(0,25)
ax.grid()

def tail_f(file):
  while True:
    where = file.tell() # current file position, an integer (may
be a long integer).
    line = file.readline()
    if re.search('without errors',line): break
    # Always yield the line so that we return back to the event loop. If we
    # need to go back and read again, we'll get a free delay from the
    # animation system.
    yield line
    if not line:
      file.seek(where) # seek(offset[, whence]) ->None. Move to
new file position.

def run(line, curve, x, y):
        if re.search('x=',line):
            liste = line.split('=')
            x.append(liste[1].strip())
        if re.search('y=',line):
            liste = line.split('=')
            y.append(liste[1].strip())

            curve.set_data(x,y)
            print x,y
        return curve

# The passed in frames can be a func that returns a generator. This
# generator keeps return "frame data"
def data_source(fname=sys.argv[1]):
        return tail_f(open(fname))

# This init function initializes for drawing returns any initialized
# artists.
def init():
        curve.set_data(,)
        return curve

line_ani = animation.FuncAnimation(fig, run, data_source, init_func=init,
        fargs=(curve,x_data,y_data), interval=100)

plt.show()

Ben was also right in that you could subclass FuncAnimation and
override/extend methods. This would have the benefit of giving more
control over the handling of seek(). (Something else for my todo
list...)

Ryan

···

On Tue, Dec 20, 2011 at 8:00 AM, Nils Wagner <nwagner@...1052...> wrote:

Hi all,

How do I use animation.FuncAnimation to plot real-life
data from parsing a text file ?

--
Ryan May
Graduate Research Assistant
School of Meteorology
University of Oklahoma

Hi Ryan,

is it possible to autoscale the axes whenever it is needed by a new chunk of data ?

Nils

···

On Tue, 20 Dec 2011 10:48:42 -0600 Ryan May <rmay31@...287...> wrote:

On Tue, Dec 20, 2011 at 8:00 AM, Nils Wagner > <nwagner@...1052...> wrote:

Hi all,

How do I use animation.FuncAnimation to plot real-life
data from parsing a text file ?

Here's a version that does what I think you want:

import matplotlib.pyplot as plt
import matplotlib.animation as animation
import sys
import time
import re

x_data = # x
y_data = # y

fig = plt.figure()
ax = fig.add_subplot(111)
curve,= ax.plot(,,lw=2)
ax.set_xlim(0,5)
ax.set_ylim(0,25)
ax.grid()

def tail_f(file):
while True:
   where = file.tell() # current file position, an integer (may
be a long integer).
   line = file.readline()
   if re.search('without errors',line): break
   # Always yield the line so that we return back to the event loop. If we
   # need to go back and read again, we'll get a free delay from the
   # animation system.
   yield line
   if not line:
     file.seek(where) # seek(offset[, whence]) ->None. Move to
new file position.

def run(line, curve, x, y):
       if re.search('x=',line):
           liste = line.split('=')
           x.append(liste[1].strip())
       if re.search('y=',line):
           liste = line.split('=')
           y.append(liste[1].strip())

           curve.set_data(x,y)
           print x,y
       return curve

# The passed in frames can be a func that returns a generator. This
# generator keeps return "frame data"
def data_source(fname=sys.argv[1]):
       return tail_f(open(fname))

# This init function initializes for drawing returns any initialized
# artists.
def init():
       curve.set_data(,)
       return curve

line_ani = animation.FuncAnimation(fig, run, data_source, init_func=init,
       fargs=(curve,x_data,y_data), interval=100)

plt.show()

Ben was also right in that you could subclass FuncAnimation and
override/extend methods. This would have the benefit of giving more
control over the handling of seek(). (Something else for my todo
list...)

Ryan

--
Ryan May
Graduate Research Assistant
School of Meteorology
University of Oklahoma