簡體   English   中英

Matplotlib 動畫 fill_between 形狀

[英]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_dataline2_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 的verticescodes屬性。假設您已經通過以下方式創建了一個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)

現在您想用新數據xnewy0newy1new更新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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM