我正在尝试在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数据,并在blit之前绘制它们(“#Update fill data too”&“#Draw fill too”)。我尝试了fill_lines.set_verts()但没有成功,找不到示例...
谢谢!
答案 0 :(得分:5)
好的,正如有人指出的那样,我们正在处理一个集合,所以我们必须删除并重绘。因此,update_data
函数中的某个位置,删除与其关联的所有集合:
axes_dummy.collections.clear()
并绘制新的“fill_between”PolyCollection:
axes_dummy.fill_between(x, y-sigma, y+sigma, facecolor='yellow', alpha=0.5)
在填充的上面填充未填充的等高线图需要类似的技巧,因为未填充的等高线图也是一个集合(我猜想的是线条)。
答案 1 :(得分:3)
这不是我的答案,但我发现它最有用:
http://matplotlib.1069221.n5.nabble.com/animation-of-a-fill-between-region-td42814.html
嗨Mauricio, 补丁对象比线对象更难处理,因为与对象不同的是从用户提供的输入数据中删除的步骤。有一个类似于你想要做的例子: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,看看它们是如何布局的。 希望有所帮助, 杰克
答案 2 :(得分:2)
如果您不想使用anitmation,或者从图中移除所有内容以仅更新填充,您可以使用我的方式:
致电fill_lines.remove()
,然后再次致电axes_dummy.fill_between()
以吸引新的from core.sequencer import Sequencer
from gui.threadGui import ThreadGui
t1 = ThreadGui()
t2 = Sequencer()
t1.start()
t2.start()
t1.join()
t2.join()
。为我工作。
答案 3 :(得分:0)
初始化pyplot交互模式
import matplotlib.pyplot as plt
plt.ion()
在绘制填充时使用可选的label参数:
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:
答案 4 :(得分:0)
另一种行之有效的方法是保留绘制对象的列表。这种方法似乎适用于任何类型的绘图对象。
# 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)