Animation 如何设置散点图凸面外壳的动画

Animation 如何设置散点图凸面外壳的动画,animation,matplotlib,convex-hull,Animation,Matplotlib,Convex Hull,我正在尝试为散点图的凸面外壳设置动画。下面的代码实现了这一点,但不会删除以前时间点的外壳,导致每个帧显示外壳而不是最新的外壳 如何获得输出以显示每个时间点的凸包?所以每一帧都是一个新的凸包 import csv import matplotlib.pyplot as plt from scipy.spatial import ConvexHull import numpy as np import matplotlib.animation as animation visuals = [[],

我正在尝试为散点图的凸面外壳设置动画。下面的代码实现了这一点,但不会删除以前时间点的外壳,导致每个帧显示外壳而不是最新的外壳

如何获得输出以显示每个时间点的凸包?所以每一帧都是一个新的凸包

import csv
import matplotlib.pyplot as plt
from scipy.spatial import ConvexHull
import numpy as np
import matplotlib.animation as animation

visuals = [[],[],[]]

with open('Wide_Single_Timestamp.csv') as csvfile :
readCSV = csv.reader(csvfile, delimiter=',')
n=0
for row in readCSV :
    if n == 0 :
        n+=1
        continue
    visuals[0].append([float(row[3]),float(row[5]),float(row[7]),float(row[9]),float(row[11]),float(row[13]),float(row[15]),float(row[17]),float(row[19]),float(row[21]),float(row[23]),float(row[25]),float(row[27]),float(row[29]),float(row[31]),float(row[33]),float(row[35]),float(row[37]),float(row[39]),float(row[41]),float(row[43])])
    visuals[1].append([float(row[2]),float(row[4]),float(row[6]),float(row[8]),float(row[10]),float(row[12]),float(row[14]),float(row[16]),float(row[18]),float(row[20]),float(row[22]),float(row[24]),float(row[26]),float(row[28]),float(row[30]),float(row[32]),float(row[34]),float(row[36]),float(row[38]),float(row[40]),float(row[42])])
    visuals[2].append([1,2])

fig, ax = plt.subplots(figsize = (8,6))

X = np.array(visuals[0][0]) #X-Coordinates
Y = np.array(visuals[1][0]) #Y-Coordinates


scatterN = ax.scatter(X, Y, zorder = 2)   #Scatter Plot

def encircle(x,y, **kw):   #Convex Hull 
    ax
    p = np.c_[x,y]
    hull = ConvexHull(p)
    poly = plt.Polygon(p[hull.vertices,:])
    ax.add_patch(poly)


def animate(i) :
    scatterN.set_offsets([[[[[[[[[[[[[[[[[[[[[visuals[0][0+i][0], visuals[1][0+i][0]], [visuals[0][0+i][1], visuals[1][0+i][1]], [visuals[0][0+i][2], visuals[1][0+i][2]], [visuals[0][0+i][3], visuals[1][0+i][3]], [visuals[0][0+i][4], visuals[1][0+i][4]],[visuals[0][0+i][5], visuals[1][0+i][5]], [visuals[0][0+i][6], visuals[1][0+i][6]], [visuals[0][0+i][7], visuals[1][0+i][7]], [visuals[0][0+i][8], visuals[1][0+i][8]], [visuals[0][0+i][9], visuals[1][0+i][9]], [visuals[0][0+i][10], visuals[1][0+i][10]], [visuals[0][0+i][11], visuals[1][0+i][11]], [visuals[0][0+i][12], visuals[1][0+i][12]], [visuals[0][0+i][13], visuals[1][0+i][13]], [visuals[0][0+i][14], visuals[1][0+i][14]], [visuals[0][0+i][15], visuals[1][0+i][15]], [visuals[0][0+i][16], visuals[1][0+i][16]], [visuals[0][0+i][17], visuals[1][0+i][17]], [visuals[0][0+i][18], visuals[1][0+i][18]], [visuals[0][0+i][19], visuals[1][0+i][19]], [visuals[0][0+i][20], visuals[1][0+i][20]]]]]]]]]]]]]]]]]]]]]] )
    X = visuals[0][0+i]
    Y = visuals[1][0+i] 
    encircle(X, Y, ec="black", fc="gray", alpha=0.1)  #Convex Hull 


ani = animation.FuncAnimation(fig, animate, np.arange(0,61100),
                          interval = 50, blit = False)

'''AFL Ground (Etihad Dimensions)'''


plt.style.use('ggplot')

#fig, ax = plt.subplots()
ax.grid(False)
#ax.set_aspect('equal')

CC_xy = 0,70
GS1_xy = 75.3,67.5
GS2_xy = -84.2,67.5
F50_1_xy = -67.5, 70
F50_2_xy = 67.5, 70
angle = math.degrees(math.acos(5.5/9.15))
CS_xy = -25,45
E_xy = 0,67.5
E_xy_Freo = 0, 70

Halfway = mpl.lines.Line2D((0,0), (65,75), color = 'white', lw = 1.5, alpha = 0.2, zorder = 0.1)
Centre_Circle = mpl.patches.Circle(CC_xy, radius = 1.5, color = 'white', lw = 1.5, fill = False)
Centre_Circle_2 = mpl.patches.Circle(CC_xy, radius = 5, color = 'white', lw = 1.5, fill = False)
GS1 = mpl.patches.Rectangle(GS1_xy, 9, 6.4, color = 'white', lw = 1.5, fill = False)
GS2 = mpl.patches.Rectangle(GS2_xy, 9, 6.4, color = 'white', lw = 1.5, fill = False)
F50_1 = mpl.patches.Arc(F50_1_xy, 65, 135, angle = 0, theta2 = angle, theta1 = 360-angle, color = 'white', lw = 2)
F50_2 = mpl.patches.Arc(F50_2_xy, 65, 135, angle = 0, theta2 = 180+angle, theta1 = 180-angle, color = 'white', lw = 2)
Centre_Square = mpl.patches.Rectangle(CS_xy, 50, 50, lw = 2, color = 'white', fill = False)


Etihad_Freo = mpl.patches.Ellipse(E_xy_Freo, 168.47, 130.47, lw = 3, color = 'green', alpha = 0.1, zorder = 5)

ax.add_line(Halfway)
ax.add_patch(Centre_Circle)
ax.add_patch(Centre_Circle_2)
ax.add_patch(GS1)
ax.add_patch(GS2)
ax.add_patch(F50_1)
ax.add_patch(F50_2)
ax.add_patch(Centre_Square)
ax.add_patch(Etihad_Freo)


#ax.annotate('D50', xy = (35.5, 80), color = 'white', rotation = -75, alpha = 0.5)
#ax.annotate('D50', xy = (37, -80), color = 'white', rotation = -110, alpha = 0.5)
#ax.annotate('F50', xy = (28.5, -40), color = 'white', rotation = 110, alpha = 0.5)
#ax.annotate('F50', xy = (28, 40), color = 'white', rotation = 72, alpha = 0.5)


ax.autoscale()

plt.draw()


#plt.savefig('fill_between scatter.png', dpi = 300)

您必须从
ax
中删除旧修补程序。如果用此函数替换
环绕
函数,则一切正常:

def encircle(x,y, **kw):   #Convex Hull 
    ##remove old patch:
    try:
        last_patch = ax.patches[-1]
        last_patch.remove()
    except IndexError:
        pass

    ##do the other stuff
    p = np.c_[x,y]
    hull = ConvexHull(p)
    poly = plt.Polygon(p[hull.vertices,:])
    ax.add_patch(poly)
由于在第一次调用Encrocle时,
ax.patches
仍然为空,因此需要使用
try except
块。当然,您可以用
if
子句替换它,以测试
ax.patches
是否为空。请注意,此代码假定
轴中没有其他面片。如果是这样的话,你必须自己跟踪你的多边形。
poly.remove()
功能仍然有效。希望这有帮助

编辑

这里是一个基于OP问题的完整示例,但将
csv
数据替换为
numpy.random

import csv
import matplotlib.pyplot as plt
from scipy.spatial import ConvexHull
import numpy as np
import matplotlib.animation as animation
import matplotlib as mpl

N=20

fig, ax = plt.subplots(figsize = (8,6))


X = np.random.normal(1,1,N)
Y = np.random.normal(1,1,N)
scatterN = ax.scatter(X, Y, zorder = 2)   #Scatter Plot

to_be_deleted = []
def encircle(x,y, **kw):   #Convex Hull 
    ##removing old patches:
    for patch in to_be_deleted:
        patch.remove()
    del to_be_deleted[:]

    p = np.c_[x,y]
    hull = ConvexHull(p)
    poly = plt.Polygon(p[hull.vertices,:])
    ##saving new reference
    to_be_deleted.append(poly)


    ax.add_patch(poly)


def animate(i) :
    X = np.random.normal(0,50,N)
    Y = np.random.normal(70,30,N)
    scatterN.set_offsets(np.array([X,Y]).T)
    encircle(X, Y, ec="black", fc="gray", alpha=0.1, zorder = 100)  #Convex Hull 


ani = animation.FuncAnimation(fig, animate, np.arange(0,61100),
                          interval = 50, blit = False)

'''AFL Ground (Etihad Dimensions)'''


plt.style.use('ggplot')

#fig, ax = plt.subplots()
ax.grid(False)
#ax.set_aspect('equal')

CC_xy = 0,70
GS1_xy = 75.3,67.5
GS2_xy = -84.2,67.5
F50_1_xy = -67.5, 70
F50_2_xy = 67.5, 70
#angle = math.degrees(math.acos(5.5/9.15))
angle = np.degrees(np.arccos(5.5/9.15))
CS_xy = -25,45
E_xy = 0,67.5
E_xy_Freo = 0, 70

Halfway = mpl.lines.Line2D((0,0), (65,75), color = 'white', lw = 1.5, alpha = 0.2, zorder = 0.1)
Centre_Circle = mpl.patches.Circle(CC_xy, radius = 1.5, color = 'white', lw = 1.5, fill = False)
Centre_Circle_2 = mpl.patches.Circle(CC_xy, radius = 5, color = 'white', lw = 1.5, fill = False)
GS1 = mpl.patches.Rectangle(GS1_xy, 9, 6.4, color = 'white', lw = 1.5, fill = False)
GS2 = mpl.patches.Rectangle(GS2_xy, 9, 6.4, color = 'white', lw = 1.5, fill = False)
F50_1 = mpl.patches.Arc(F50_1_xy, 65, 135, angle = 0, theta2 = angle, theta1 = 360-angle, color = 'white', lw = 2)
F50_2 = mpl.patches.Arc(F50_2_xy, 65, 135, angle = 0, theta2 = 180+angle, theta1 = 180-angle, color = 'white', lw = 2)
Centre_Square = mpl.patches.Rectangle(CS_xy, 50, 50, lw = 2, color = 'white', fill = False)


Etihad_Freo = mpl.patches.Ellipse(E_xy_Freo, 168.47, 130.47, lw = 3, color = 'green', alpha = 0.1, zorder = 5)

ax.add_line(Halfway)
ax.add_patch(Centre_Circle)
ax.add_patch(Centre_Circle_2)
ax.add_patch(GS1)
ax.add_patch(GS2)
ax.add_patch(F50_1)
ax.add_patch(F50_2)
ax.add_patch(Centre_Square)
ax.add_patch(Etihad_Freo)


#ax.annotate('D50', xy = (35.5, 80), color = 'white', rotation = -75, alpha = 0.5)
#ax.annotate('D50', xy = (37, -80), color = 'white', rotation = -110, alpha = 0.5)
#ax.annotate('F50', xy = (28.5, -40), color = 'white', rotation = 110, alpha = 0.5)
#ax.annotate('F50', xy = (28, 40), color = 'white', rotation = 72, alpha = 0.5)


ax.autoscale()

plt.show()

由于csv文件不可用,因此无法按此方式运行代码。最好将代码发布为。例如,可以通过使用
numpy.random
或类似的方法生成随机数据来实现。谢谢Thomas。下次我会记住的。这很好。我有更多的
ax.patches
来绘制特定的轴限制。
poly.remove()
函数在这种情况下如何工作?@JeremyYalexander每次创建一个
补丁
poly
以后要删除的时候,都要保留对它的引用(可能在名为
的列表中,以便删除
或类似的列表中)。然后,当需要删除修补程序时,遍历该列表,对所有对象调用
remove()
,并清空该列表(
to\u be\u remove=[]
)。要得到更具体的答案,我需要更具体的代码:)谢谢你的帮助。我已经添加了包含附加补丁的代码。