我正在尝试为散点图的凸包设置动画。下面的代码实现了这一点,但不删除前一时间点的船体,导致每个框架显示船体而不是最新的船体。
如何获得输出以显示每个时间点的凸包?所以每个框架都是一个新的凸包。
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)
答案 0 :(得分:1)
您必须从ax
删除旧补丁。如果用这个替换encircle
函数,一切都应该正常工作:
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)
需要try-except
块,因为在第一次调用环绕期间,ax.patches
仍为空。您当然可以用if
子句替换它来测试ax.patches
是否为空。请注意,此代码假定您的Axes
实例中没有其他补丁。如果是这种情况,您必须自己跟踪多边形。 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()