[英]Matplotlib animate fill_between shape
我正在嘗試為 matplotlib 內的fill_between
形狀制作動畫,但我不知道如何更新PolyCollection
的數據。 舉個簡單的例子:我有兩條線,我總是在它們之間填充。 當然,線條會改變並且是動畫的。
這是一個虛擬示例:
import matplotlib.pyplot as plt
# Init plot:
f_dummy = plt.figure(num=None, figsize=(6, 6));
axes_dummy = f_dummy.add_subplot(111);
# Plotting:
line1, = axes_dummy.plot(X, line1_data, color = 'k', linestyle = '--', linewidth=2.0, animated=True);
line2, = axes_dummy.plot(X, line2_data, color = 'Grey', linestyle = '--', linewidth=2.0, animated=True);
fill_lines = axes_dummy.fill_between(X, line1_data, line2_data, color = '0.2', alpha = 0.5, animated=True);
f_dummy.show();
f_dummy.canvas.draw();
dummy_background = f_dummy.canvas.copy_from_bbox(axes_dummy.bbox);
# [...]
# Update plot data:
def update_data():
line1_data = # Do something with data
line2_data = # Do something with data
f_dummy.canvas.restore_region( dummy_background );
line1.set_ydata(line1_data);
line2.set_ydata(line2_data);
# Update fill data too
axes_dummy.draw_artist(line1);
axes_dummy.draw_artist(line2);
# Draw fill too
f_dummy.canvas.blit( axes_dummy.bbox );
問題是每次調用update_data()
時如何根據line1_data
和line2_data
更新fill_between
Poly
數據,並在blit
之前繪制它們(“# Update fill data too” & “# Draw fill too”)。 我試過fill_lines.set_verts()
但沒有成功,找不到示例。
好的,正如有人指出的,我們在這里處理一個集合,所以我們將不得不刪除和重繪。 所以在update_data
函數的某個地方,刪除所有與之關聯的集合:
axes_dummy.collections.clear()
並繪制新的“fill_between”PolyCollection:
axes_dummy.fill_between(x, y-sigma, y+sigma, facecolor='yellow', alpha=0.5)
需要一個類似的技巧來將未填充的等高線圖疊加在已填充的等高線圖的頂部,因為未填充的等高線圖也是一個集合(我認為是線條?)。
這不是我的答案,但我發現它最有用:
http://matplotlib.1069221.n5.nabble.com/animation-of-a-fill-between-region-td42814.html
嗨 Mauricio, Patch 對象比線對象更難使用,因為與線對象不同的是從用戶提供的輸入數據中刪除了一個步驟。 有一個類似於你想在這里做的例子: http : //matplotlib.org/examples/animation/histogram.html
基本上,您需要在每一幀修改路徑的頂點。 它可能看起來像這樣:
from matplotlib import animation
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.set_xlim([0,10000])
x = np.linspace(6000.,7000., 5)
y = np.ones_like(x)
collection = plt.fill_between(x, y)
def animate(i):
path = collection.get_paths()[0]
path.vertices[:, 1] *= 0.9
animation.FuncAnimation(fig, animate,
frames=25, interval=30)
查看 path.vertices 以了解它們的布局。 希望有所幫助,傑克
如果您不想使用動畫,或從圖形中刪除所有內容以僅更新填充,則可以使用這種方式:
調用fill_lines.remove()
然后再次調用axes_dummy.fill_between()
繪制新的。 它在我的情況下有效。
初始化pyplot交互模式
import matplotlib.pyplot as plt
plt.ion()
繪制填充時使用可選的標簽參數:
plt.fill_between(
x,
y1,
y2,
color="yellow",
label="cone"
)
plt.pause(0.001) # refresh the animation
稍后在我們的腳本中,我們可以按標簽選擇刪除特定填充或填充列表,從而逐個對象地制作動畫。
axis = plt.gca()
fills = ["cone", "sideways", "market"]
for collection in axis.collections:
if str(collection.get_label()) in fills:
collection.remove()
del collection
plt.pause(0.001)
您可以對要刪除的對象組使用相同的標簽; 或以其他方式根據需要使用標簽對標簽進行編碼以滿足需求
例如,如果我們有填充標簽:
“cone1”“cone2”“sideways1”
if "cone" in str(collection.get_label()):
將排序刪除以“cone”為前綴的那些。
您還可以以相同的方式為線條設置動畫
for line in axis.lines:
另一個可以工作的習語是保留您繪制的對象的列表; 這種方法似乎適用於任何類型的繪制對象。
# plot interactive mode on
plt.ion()
# create a dict to store "fills"
# perhaps some other subclass of plots
# "yellow lines" etc.
plots = {"fills":[]}
# begin the animation
while 1:
# cycle through previously plotted objects
# attempt to kill them; else remember they exist
fills = []
for fill in plots["fills"]:
try:
# remove and destroy reference
fill.remove()
del fill
except:
# and if not try again next time
fills.append(fill)
pass
plots["fills"] = fills
# transformation of data for next frame
x, y1, y2 = your_function(x, y1, y2)
# fill between plot is appended to stored fills list
plots["fills"].append(
plt.fill_between(
x,
y1,
y2,
color="red",
)
)
# frame rate
plt.pause(1)
與這里所說的大多數答案相反,每次要更新其數據時,不必刪除和重新繪制PolyCollection
返回的fill_between
。 相反,您可以修改底層Path
object 的vertices
和codes
屬性。假設您已經通過以下方式創建了一個PolyCollection
import numpy as np
import matplotlib.pyplot as plt
#dummy data
x = np.arange(10)
y0 = x-1
y1 = x+1
fig = plt.figure()
ax = fig.add_subplot()
p = ax.fill_between(x,y0,y1)
現在您想用新數據xnew
、 y0new
和y1new
更新p
。 那么你可以做的是
v_x = np.hstack([xnew[0],xnew,xnew[-1],xnew[::-1],xnew[0]])
v_y = np.hstack([y1new[0],y0new,y0new[-1],y1new[::-1],y1new[0]])
vertices = np.vstack([v_x,v_y]).T
codes = np.array([1]+(2*len(xnew)+1)*[2]+[79]).astype('uint8')
path = p.get_paths()[0]
path.vertices = vertices
path.codes = codes
說明: path.vertices
包含由fill_between
繪制的補丁的頂點,包括額外的開始和結束位置, path.codes
包含有關如何使用它們的說明(1=MOVE POINTER TO,2=DRAW LINE TO,79=CLOSE POLY)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.