简体   繁体   English

分岔流图 Matplotlib Animation

[英]Matplotlib Animation of Streamplot of Bifurcation

I am currently trying to animate the dynamics of a typical saddle node bifurcation ode: dx/dt = r + x^2.我目前正在尝试为典型的鞍节点分叉颂歌的动态设置动画:dx/dt = r + x^2。 Snapshots at specific values of r are realised with the streamplot function from r = -1 to 1. Unfortunately the init function and the animate function are not working properly because.set_array does not work for streamplots.特定值 r 的快照是通过流图 function 从 r = -1 到 1 实现的。不幸的是,初始化 function 和动画 function 无法正常工作,因为 .set_array 不适用于流图。 I am also not sure how to update the streams at each iteration in the animate function. My question is how I should modify the animate and init function so that the funcanimation function gives a proper animated plot of the flows.我也不确定如何在动画 function 中的每次迭代中更新流。我的问题是我应该如何修改动画和初始化 function,以便 funcanimation function 提供适当的动画流 plot。

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


nx, ny = .02, .02
x = np.arange(-15, 15, nx)
y = np.arange(-10, 10, ny)
X, Y = np.meshgrid(x, y)
dy = -1 + Y**2
dx = np.ones(dy.shape)

dyu = dy / np.sqrt(dy**2 + dx**2)
dxu = dx / np.sqrt(dy**2 + dx**2)


color = dyu
fig, ax = plt.subplots()
stream = ax.streamplot(X,Y,dxu, dyu, color=color, density=2, cmap='jet',arrowsize=1)
ax.set_xlabel('t')
ax.set_ylabel('x')

def init():
stream.set_array([])
return stream

def animate(iter):
    dy = -1 + iter * 0.01 + Y**2
    dx = np.ones(dy.shape)
    dyu = dy / np.sqrt(dy**2 + dx**2)
    dxu = dx / np.sqrt(dy**2 + dx**2)
    stream.set_array(dyu.ravel())

    return stream

anim =   animation.FuncAnimation(fig, animate, frames=100, interval=50, blit=False, repeat=False)
plt.show()

I worked around this by clearing the lines and arrows in every iteration:我通过在每次迭代中清除线条和箭头来解决这个问题:

ax.collections = [] # clear lines streamplot
ax.patches = [] # clear arrowheads streamplot

So, I modified your code like this:所以,我像这样修改了你的代码:

#!/usr/bin/env python3
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation


nx, ny = .02, .02
x = np.arange(-15, 15, nx)
y = np.arange(-10, 10, ny)
X, Y = np.meshgrid(x, y)
dy = -1 + Y**2
dx = np.ones(dy.shape)

dyu = dy / np.sqrt(dy**2 + dx**2)
dxu = dx / np.sqrt(dy**2 + dx**2)

color = dyu
fig, ax = plt.subplots()
stream = ax.streamplot(X,Y,dxu, dyu, color=color, density=2, cmap='jet',arrowsize=1)
ax.set_xlabel('t')
ax.set_ylabel('x')

def animate(iter):
    ax.collections = [] # clear lines streamplot
    ax.patches = [] # clear arrowheads streamplot
    dy = -1 + iter * 0.01 + Y**2
    dx = np.ones(dy.shape)
    dyu = dy / np.sqrt(dy**2 + dx**2)
    dxu = dx / np.sqrt(dy**2 + dx**2)
    stream = ax.streamplot(X,Y,dxu, dyu, color=color, density=2, cmap='jet',arrowsize=1)
    print(iter)
    return stream

anim =   animation.FuncAnimation(fig, animate, frames=100, interval=50, blit=False, repeat=False)
anim.save('./animation.gif', writer='imagemagick', fps=60)
# plt.show()

动画片

CAUTION: @SebastianBeyer's previously working answer no longer works in 2022. For unknown (and presumably indefensible) reasons, Matplotlib now prohibits attempts to manually replace the axes.patches list by raising a non-human-readable exception resembling:注意: @SebastianBeyer之前的工作答案在 2022 年不再有效。出于未知(并且可能是站不住脚的)原因,Matplotlib 现在禁止尝试通过引发类似于以下内容的非人类可读异常来手动替换axes.patches列表:

AttributeError: can't set attribute 'patches'

Thankfully, yet another working workaround exists.值得庆幸的是,还有另一种解决方法存在。 Inspired by @Sheldore's working answer here , you must now iteratively search for and remove all matplotlib.patches.FancyArrowPatch child artists from the streamplot's axes: eg,受@Sheldore在这里的工作答案的启发,您现在必须从流图的轴上迭代搜索并删除所有matplotlib.patches.FancyArrowPatch儿童艺术家:例如,

# Rather than this...
ax.patches = [] # clear arrowheads streamplot

# ...you must now do this.
from matplotlib.patches import FancyArrowPatch
for artist in ax.get_children():
    if isinstance(artist, FancyArrowPatch):
        artist.remove()

In full, the post-2020 working solution is now:总的来说,2020 年后的工作解决方案现在是:

#!/usr/bin/env python3
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation
from matplotlib.patches import FancyArrowPatch


nx, ny = .02, .02
x = np.arange(-15, 15, nx)
y = np.arange(-10, 10, ny)
X, Y = np.meshgrid(x, y)
dy = -1 + Y**2
dx = np.ones(dy.shape)

dyu = dy / np.sqrt(dy**2 + dx**2)
dxu = dx / np.sqrt(dy**2 + dx**2)

color = dyu
fig, ax = plt.subplots()
stream = ax.streamplot(X,Y,dxu, dyu, color=color, density=2, cmap='jet',arrowsize=1)
ax.set_xlabel('t')
ax.set_ylabel('x')

def animate(iter):
    ax.collections = [] # clear lines streamplot

    # Clear arrowheads streamplot.
    for artist in ax.get_children():
        if isinstance(artist, FancyArrowPatch):
            artist.remove()

    dy = -1 + iter * 0.01 + Y**2
    dx = np.ones(dy.shape)
    dyu = dy / np.sqrt(dy**2 + dx**2)
    dxu = dx / np.sqrt(dy**2 + dx**2)
    stream = ax.streamplot(X,Y,dxu, dyu, color=color, density=2, cmap='jet',arrowsize=1)
    print(iter)
    return stream

anim =   animation.FuncAnimation(fig, animate, frames=100, interval=50, blit=False, repeat=False)
anim.save('./animation.gif', writer='imagemagick', fps=60)
# plt.show()

Thanks alot, post-2020 matplotlib. </facepalm>非常感谢,2020 年后 matplotlib。 </facepalm>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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