简体   繁体   中英

python animation reading data from file

I'm trying to plot the time evolution of a function f(x,t) . The data is stored in a file which has the following format:

1st row:f(0,0) f(0,1) f(0,2) ....f(0,N)

2nd row:f(1,0) f(1,1) f(1,2) ....f(1,N)

Mth row:f(M,0) f(M,1) f(M,2) ....f(M,N)

where N is the no: of points of the simulation box and M is the number of timesteps. I used basic_animation by Jake Vanderplas ( https://jakevdp.github.io/blog/2012/08/18/matplotlib-animation-tutorial/ ) to start with, the original example works fine as long as i put blit=False.

Then i tried to replace x by :

x= np.arange(0,192)

and y by the contents of the file mentioned above.

If i do just plt.plot(x,y) , it does plot f(x,t) at a given time t, but I want the animation of f(x,t) in time.

set_data should accept 2 1Darrays and I've checked that len(x)=len(y) .

But I get the following error message: ' RuntimeError: xdata and ydata must be the same length'

This is the code (in the future i would like to plot multiple functions):

"""
Modified Matplotlib Animation Example
original example:
email: vanderplas@astro.washington.edu
website: http://jakevdp.github.com
license: BSD
Feel free to use and modify this, but keep the above information.   
"""

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
from itertools import islice


filename = 'DensityByPropagation__a_0_VHxcS_kick'

# First set up the figure, the axis, and the plot element we want to    animate
fig = plt.figure()
ax = plt.axes(xlim=(0, 192), ylim=(-2, 2))
lineS, = ax.plot([], [], lw=2)

# initialization function: plot the background of each frame
def init():
       lineS.set_data([], [])
       return lineS,

# animation function.  This is called sequentially
def animate(i):
   w = np.linspace(0, 2, 1000)
   z = np.sin(2 * np.pi * (w - 0.01 * i))

   x= np.arange(0,192)
   with open(filename) as fobj:
       ketchup = islice(fobj, 0, None, 10)
       for line in ketchup:
            x,y = x,zip(*([float(y) for y in line.split("\t")] for line in fobj))

            #plt.plot(x,y)
            #plt.show()
#print len(x)
#print len(y)
            #lineS.set_data(w,z)
            lineS.set_data(x,y)
    return lineS,

# call the animator.  blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,
                           frames=200, interval=20, blit=False)

# save the animation as an mp4.  This requires ffmpeg or mencoder to be
# installed.  The extra_args ensure that the x264 codec is used, so that
# the video can be embedded in html5.  You may need to adjust this for
# your system: for more information, see
# http://matplotlib.sourceforge.net/api/animation_api.html

anim.save('movieJoh.mp4', fps=30, extra_args=['-vcodec', 'libx264'])

plt.show()

I'm not sure what exactly is causing your error, but let me point something out, then I'll make a toy example that should help clarify what's happening.

These lines seem unnecessarily complicated.

with open(filename) as fobj:
    ketchup = islice(fobj, 0, None, 10)
    for line in ketchup:
        x,y = x,zip(*([float(y) for y in line.split("\t")] for line in fobj))

If your data is in fact in the simple format you stated, ie, values separated by spaces, np.loadtxt() would load all the values into an easy to manage array.

Example

Lets assume this is your data file (10 time steps, 2 points on plot at each step):

0 0 0 0 0 0 0 0 0 0
9 8 7 6 5 4 3 2 1 0

Now some code:

filename = 'data.txt'

# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(0, 1), ylim=(0, 9))
lineS, = ax.plot([], [], lw=2)

x = range(2) # the domain

Now we load the data in with np.loadtxt() , this creates a 2-d matrix with t in the columns and x in the rows. We then transpose it to make indexing each time step possible in animate() .

# load the data from file
data = np.loadtxt(filename)
# transpose so we could easily index in the animate() function
data = np.transpose(data)

Now for animation functions. This part is really quite simple. animate(i) takes one argument - the frame number. Using the frame number, we extract the values of f(x,t=frameNumber) and set that as the data on the plot.

# initialization function: plot the background of each frame
def init():
    lineS.set_data([], [])
    return lineS,

# animation function.  This is called sequentially
def animate(i):
    lineS.set_data(x, data[i])
    return lineS,

# call the animator.  blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,
                           frames=10, interval=100, blit=True)

plt.show()

This is the working code:

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

# Input
filename = 'PeriodicDensity'    # Filename

x = np.linspace(-7.5,7.5,192)   # Domain
xLimits=[-7.5,7.5]          # x limits
yLimits=[0,1]           # y limits
framesToUse = range(1,9000,150)# The time-steps to plot

# load the data from file
data = np.loadtxt(filename)

# Set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=xLimits,ylim=yLimits)
lineS, = ax.plot([], [], lw=2)

# Initialisation function
def init():
   lineS.set_data([],[])
   return lineS,

# Animation function (called sequentially)
def animate(i):
    lineS.set_data(x,data[i])
    return lineS,

# call the animator.  blit=True means only re-draw the parts that have      changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,interval=1000, frames=framesToUse, blit=True)

# save the animation as an mp4.  This requires ffmpeg or mencoder to be
# installed.  The extra_args ensure that the x264 codec is used, so that
# the video can be embedded in html5.  You may need to adjust this for
# your system: for more information, see
# http://matplotlib.sourceforge.net/api/animation_api.html

anim.save('movieDensity.mp4', fps=1, extra_args=['-vcodec', 'libx264'])

plt.show()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM