From: Nils W. <nw...@ia...> - 2011-12-20 14:21:10
|
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 |
From: Benjamin R. <ben...@ou...> - 2011-12-20 15:58:04
|
On Tue, Dec 20, 2011 at 8:00 AM, Nils Wagner <nw...@ia...>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 > > 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 |
From: Ryan M. <rm...@gm...> - 2011-12-20 16:49:13
|
On Tue, Dec 20, 2011 at 8:00 AM, Nils Wagner <nw...@ia...> 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 |
From: Nils W. <nw...@ia...> - 2011-12-21 08:53:41
|
On Tue, 20 Dec 2011 10:48:42 -0600 Ryan May <rm...@gm...> wrote: > On Tue, Dec 20, 2011 at 8:00 AM, Nils Wagner > <nw...@ia...> 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 Hi Ryan, is it possible to autoscale the axes whenever it is needed by a new chunk of data ? Nils |