如何从列表列表中有效地动画多个修补程序

时间:2018-02-13 05:23:20

标签: python animation matplotlib patch

我正在尝试从列表中读取数据时尽可能高效地动画多个补丁?

下面的代码显示散点图的动画,但不显示补丁。散点图中的每个点都包含各种大小的圆。此示例需要6个不同的圆圈,每个时间点在2个主题上进行动画处理。但是,如果有20个主题,每个主题周围有3个圆圈。

为每个帧动画所有60个圆圈的最有效方法是什么?

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

x_data = np.random.randint(80, size=(400, 4))
y_data = np.random.randint(80, size=(400, 4))

fig, ax = plt.subplots(figsize = (8,6))
ax.set_xlim(0,80)
ax.set_ylim(0,80)

scatter = ax.scatter(x_data[0], y_data[0], zorder = 5) #Scatter plot

Player_1 = x_data[0][0], y_data[0][0]
Player_2 = x_data[0][1], y_data[0][1]

Player_1_IR = mpl.patches.Circle(Player_1, radius = 2, color = 'black', lw = 1, alpha = 0.8, zorder = 4)
Player_1_MR = mpl.patches.Circle(Player_1, radius = 4, color = 'gray', lw = 1, alpha = 0.8, zorder = 3)
Player_1_OR = mpl.patches.Circle(Player_1, radius = 6, color = 'lightgrey', lw = 1, alpha = 0.8, zorder = 2)

Player_2_IR = mpl.patches.Circle(Player_2, radius = 2, color = 'black', lw = 1, alpha = 0.8, zorder = 4)
Player_2_MR = mpl.patches.Circle(Player_2, radius = 4, color = 'gray', lw = 1, alpha = 0.8, zorder = 3)
Player_2_OR = mpl.patches.Circle(Player_2, radius = 6, color = 'lightgrey', lw = 1, alpha = 0.8, zorder = 2)

ax.add_patch(Player_1_IR)
ax.add_patch(Player_1_MR)
ax.add_patch(Player_1_OR)

ax.add_patch(Player_2_IR)
ax.add_patch(Player_2_MR)
ax.add_patch(Player_2_OR)

def animate(i) : 
    scatter.set_offsets(np.c_[x_data[i,:], y_data[i,:]])

ani = animation.FuncAnimation(fig, animate, frames=len(x_data), 
                              interval = 700, blit = False)

plt.show()

1 个答案:

答案 0 :(得分:1)

您可以将要更新的所有修补程序存储在列表中,然后通过该列表迭代每个迭代步骤。请注意,Circle色块的大小是以数据单位/坐标为单位,而散点图以点为单位(一个点= 1/72英寸),这意味着散点和圆之间的相对大小取决于图形尺寸和轴限制,并在重新缩放图形时发生变化。

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

x_data = np.random.randint(80, size=(400, 20))
y_data = np.random.randint(80, size=(400, 20))

fig, ax = plt.subplots(figsize = (8,6))
ax.set_xlim(0,80)
ax.set_ylim(0,80)

scatter = ax.scatter(x_data[0], y_data[0], zorder = 5) #Scatter plot

##creating list of patches
players = []
for n in range(10):
    ##as there are always 3 circles, append all three patches as a list at once
    players.append([
        mpl.patches.Circle((x_data[0,n],y_data[0,n]), radius = 2, color = 'black', lw = 1, alpha = 0.8, zorder = 4),
        mpl.patches.Circle((x_data[0,n],y_data[0,n]), radius = 4, color = 'gray', lw = 1, alpha = 0.8, zorder = 3),
        mpl.patches.Circle((x_data[0,n],y_data[0,n]), radius = 6, color = 'lightgrey', lw = 1, alpha = 0.8, zorder = 2)
    ])

##adding patches to axes
for player in players:
    for circle in player:
        ax.add_patch(circle)


def animate(i):
    scatter.set_offsets(np.c_[x_data[i,:], y_data[i,:]])
    ##updating players:
    for n,player in enumerate(players):
        for circle in player:
            circle.center = (x_data[i,n],y_data[i,n])

ani = animation.FuncAnimation(fig, animate, frames=len(x_data), 
                              interval = 700, blit = False)

plt.show()

旧答案(视觉效果略有不同,但可以调整为相同):

如果您真的只想在散点图周围使用圆圈,那么您实际上可以忘记Circle个补丁,只需覆盖几个不同标记尺寸的散点图。

在下面的例子中,我只是通过切片随机数组来用圆圈标记部分散点。还要记住,在散点图中,标记大小以点的平方值给出,因此如果要将圆半径从5增加到6,则给定的标记大小应从25更改为36。

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

x_data = np.random.randint(80, size=(400, 20))
y_data = np.random.randint(80, size=(400, 20))

fig, ax = plt.subplots(figsize = (8,6))
ax.set_xlim(0,80)
ax.set_ylim(0,80)

scatter = ax.scatter(x_data[0], y_data[0], zorder = 5) #Scatter plot
scatter_IR = ax.scatter(
    x_data[0,:10], y_data[0,:10], zorder = 4,
    facecolor='black', edgecolor = 'black',
    alpha = 0.8, s = 100
)
scatter_MR = ax.scatter(
    x_data[0,:10], y_data[0,:10], zorder = 3,
    facecolor='grey', edgecolor = 'grey',
    alpha = 0.8, s = 225
)
scatter_OR = ax.scatter(
    x_data[0,:10], y_data[0,:10], zorder = 2,
    facecolor='lightgrey', edgecolor = 'lightgrey',
    alpha = 0.8, s = 400
)

def animate(i) : 
    scatter.set_offsets(np.c_[x_data[i,:], y_data[i,:]])
    scatter_IR.set_offsets(np.c_[x_data[i,:10], y_data[i,:10]])
    scatter_MR.set_offsets(np.c_[x_data[i,:10], y_data[i,:10]])
    scatter_OR.set_offsets(np.c_[x_data[i,:10], y_data[i,:10]])


ani = animation.FuncAnimation(fig, animate, frames=len(x_data), 
                              interval = 700, blit = False)

plt.show()
相关问题