问题
I'm using matplotlib for drawing graphs such as smooth lines. it is not problem to draw for me, but I have problems with animations.
import numpy as np
import random as random
from matplotlib import pyplot as plt
from matplotlib import animation
So, i have array, such as:
a = [0,1,2,4,5,8,9,12,14,18,22,17,30,37,29,45]
And I need to draw it smooth point-to-point. Now I have this strings:
for i in range(len(a)-1):
desty = np.append(desty,np.linspace(a[i],a[i+1],n))
destx = np.append(destx,np.linspace(i,i+1,n))
that allows me to draw lines without problems (and animations :))
the full code:
# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(0, 50), ylim=(0, 50))
line, = ax.plot([], [], lw=2)
global x
global y
global n
global a
n=5
a = [0,1,2,4,5,8,9,12,14,18,22,17,30,37,29,45]
global desty,destx
desty = np.linspace(0,0,n)
destx = np.linspace(0,0,n)
for i in range(len(a)-1):
desty = np.append(desty,np.linspace(a[i],a[i+1],n))
destx = np.append(destx,np.linspace(i,i+1,n))
# initialization function: plot the background of each frame
def init():
line.set_data([], [])
return line,
# animation function. This is called sequentially
def animate(i):
global destx
global desty
x=destx
y=desty
line.set_data(x, y)
return line,
# 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=True)
plt.show()
Allows me to draw it only, but how can i draw it slow and smooth point to point?
I'm using python 2.7, centos 7.
回答1:
You can slim your plotting routine down to:
import numpy as np
import random as random
from matplotlib import pyplot as plt
from matplotlib import animation
# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(0, 50), ylim=(0, 50))
line, = ax.plot([], [], lw=2)
n=5
a = [0,1,2,4,5,8,9,12,14,18,22,17,30,37,29,45]
x = []
y = []
# initialization function: plot the background of each frame
def init():
line.set_data([], [])
return line,
# animation function. This is called sequentially
def animate(i):
x.append(np.linspace(i,i+1,n))
y.append(np.linspace(a[i],a[i+1],n))
line.set_data(x,y)
return line,
# call the animator. blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, np.arange(0,len(a)-1) ,init_func=init,
interval=200, blit=True, repeat=False)
plt.show()
Things to note:
- You don't require
global
variables for this to work - You don't want to set up
x
andy
outside of the animation but inside for the plot to develop (in your case you had the completex
andy
set up so that the animation would only plot the entire graph) - You need to pass an interable to
animate
(thei
); this is the third input toFuncAnimation
-np.arange(0,len(a)-1)
. - set
repeat=False
to stop after one run and to avoid 'closing' the curve - I increased
interval
to make the plot develop slower
回答2:
You need to use i
in your animate function, otherwise it just plots the same thing over and over, which is what you see.
import numpy as np
import random as random
from matplotlib import pyplot as plt
from matplotlib import animation
# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(0, 50), ylim=(0, 50))
line, = ax.plot([], [], lw=2)
global x
global y
global n
global a
n=5
a = [0,1,2,4,5,8,9,12,14,18,22,17,30,37,29,45]
global desty,destx
desty = np.linspace(0,0,n)
destx = np.linspace(0,0,n)
plot_me_x = []
plot_me_y = []
for i in range(len(a)-1):
desty = np.append(desty, np.linspace(a[i],a[i+1],n))
destx = np.append(destx, np.linspace(i,i+1,n))
plot_me_x.append(np.array(destx)) # keep a copy of the intermediaries to plot later
plot_me_y.append(np.array(desty))
# initialization function: plot the background of each frame
def init():
line.set_data([], [])
return line,
# animation function. This is called sequentially
def animate(i):
global destx
global desty
x=plot_me_x[i]
y=plot_me_y[i]
line.set_data(x, y)
return line,
# call the animator. blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=len(a)-1, interval=20, blit=True)
plt.show()
For the plot to look different at each animation, i
must index something that looks different at each iteration. Although desty
and destx
are appended to gradually in the iteration that builds them, the final result is not this gradual build but a single thing, so you need to save the intermediaries of this build. I did this with plot_me_x
and y
.
I wrote this answer with minimal changes to the OP's code to make it clear where the error was. Overall, the changes that @Schorsch made lead to an overall cleaner approach (eg, with no globals).
来源:https://stackoverflow.com/questions/27385619/slow-and-smooth-drawing-lines-python-matplotlib