numpy 更新直线的方程matplotlib动画

wwwo4jvm  于 2023-08-05  发布在  其他
关注(0)|答案(1)|浏览(87)

我正在尝试将泰勒级数从1项到50项动画化。我目前拥有的代码允许我指定一些术语并将其绘制到一个图上(与另一个图进行比较):

import math
import numpy as np

import matplotlib.pyplot as plt

def func_cos(x, n):
    cos_approx = 0
    for i in range(n):
        coef = (-1)**i
        num = x**(2*i)
        denom = math.factorial(2*i)
        cos_approx += ( coef ) * ( (num)/(denom) )
    
    return cos_approx

def func_sin(x, n):
    sin_approx = 0
    for i in range(n):
        coef = (-1)**i
        num = x**(2*i+1)
        denom = math.factorial(2*i+1)
        sin_approx += ( coef ) * ( (num)/(denom) )
    
    return sin_approx

i = 1j
e = math.e

x = np.linspace(0, 10, 1000)

fx = e**(i*x)

taylor = lambda j: np.array([func_cos(x_val,j) + i*func_sin(x_val,j) for x_val in x])

plt.plot(fx.real, fx.imag)
plt.plot(taylor(50).real, taylor(50).imag)

plt.show()

字符串
有没有一种方法来动画的图形,使线改变方程的每一帧的泰勒级数的数目?

f2uvfpb9

f2uvfpb91#

动画模块

一种是animation模块。在这种情况下,这可能是最好的方法,因为您对第i帧应该是什么样子有了明确的定义。
下面是您的代码,更新了一些注解行。

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

# You need this module 
import matplotlib.animation as anim

def func_cos(x, n):
    cos_approx = 0
    for i in range(n):
        coef = (-1)**i
        num = x**(2*i)
        denom = math.factorial(2*i)
        cos_approx += ( coef ) * ( (num)/(denom) )
    
    return cos_approx

def func_sin(x, n):
    sin_approx = 0
    for i in range(n):
        coef = (-1)**i
        num = x**(2*i+1)
        denom = math.factorial(2*i+1)
        sin_approx += ( coef ) * ( (num)/(denom) )
    
    return sin_approx

i = 1j
e = math.e

x = np.linspace(0, 10, 1000)

fx = e**(i*x)

taylor = lambda j: np.array([func_cos(x_val,j) + i*func_sin(x_val,j) for x_val in x])

plt.plot(fx.real, fx.imag)

# You need to keep the "artist", that is the plotted line, to be able to update its data later
# Note the `,`: plt.plot returns 2 things, the first being the one we want (pltdata)
pltdata,=plt.plot(taylor(0).real, taylor(0).imag)

# The animate function is in charge of updating the data
# i is the frame number
def animate(i):
    pltdata.set_data(taylor(i).real, taylor(i).imag)
    # Animate returns the list of the "artists" it has changed. So here, just [pltdata]
    return [pltdata]

# Note the dummy "myanim" variable. Even if we don't use it afterward, it is necessary 
# so that the garbage collector doesn't destry the animation
# plt.gcf() is just the figure. So, if you have a fig=plt.figure() somewhere, that should be replaced by `fig`
# I reduced the 50 values, because, well, 20 is more than enough (at this point, you even start adding
# more numerical noise that accuracy. But well, that has nothing to do with animation)
myanim = anim.FuncAnimation(plt.gcf(), animate, frames=20, interval=200, blit=True)
plt.show()
# or myanim.save('out.mp4') to create a animation in a file

字符串
另外(见最后一行注解),animation允许轻松创建很酷的动画gif(或mp4,但需要gif来放入[so]消息),如

离子

另一种方法是使情节互动,并更新它(甚至每次从头开始重绘一切,这取决于你),使用你自己的时间策略。

plt.ion()

for k in range(20):
    plt.gcf().clear()
    plt.xlim(-1.5, 1.5)
    plt.ylim(-1.5, 1.5)
    plt.plot(fx.real, fx.imag)
    plt.plot(taylor(k).real, taylor(k).imag)
    plt.draw()
    plt.pause(0.2)


或者两者的混合

plt.ion()

plt.plot(fx.real, fx.imag)
plt.xlim(-1.5, 1.5)
plt.ylim(-1.5, 1.5)
pltdata,=plt.plot(taylor(0).real, taylor(0).imag)

for k in range(20):
    pltdata.set_data(taylor(k).real, taylor(k).imag)
    plt.draw()
    plt.pause(0.2)


请注意,我想在这里只关注动画部分。所以没有针对您的情况进行优化。例如,通过每次计算taylor(k)taylor(k)本身计算所有项,我基本上计算了30倍的常数系数,29倍的x系数,28倍的x²系数,...
显然,这是可以优化的。
比如像这样

plt.ion()

plt.plot(fx.real, fx.imag)
plt.xlim(-1.5, 1.5)
plt.ylim(-1.5, 1.5)
pltdata,=plt.plot(xx, yy)

fac=1.0
for k in range(20):
    xx += (-1)**k * x**(2*k) / fac
    fac *= (2*k+1)
    yy += (-1)**k * x**(2*k+1) / fac
    fac *= (2*k+2)
    pltdata.set_data(xx,yy)
    plt.draw()
    plt.pause(0.2)

相关问题