Slow and smooth drawing lines python matplotlib

独自空忆成欢 提交于 2019-12-13 08:47:24

问题


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 and y outside of the animation but inside for the plot to develop (in your case you had the complete x and y set up so that the animation would only plot the entire graph)
  • You need to pass an interable to animate (the i); this is the third input to FuncAnimation - 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!