gpt4 book ai didi

python - `matplotlib` : `self._chachedRenderer` fails `assert self._cachedRenderer is not None` , 在补丁上调用 `draw_artist` 时?

转载 作者:太空宇宙 更新时间:2023-11-04 03:33:26 28 4
gpt4 key购买 nike

基于 John Hunter 的 answer to a question regarding using patches in animations here ,我的印象是:

  1. 我可以用 its animated stated being True 创建一个 patch 对象.
  2. 使用 add_patch 将其添加到现有的 axis(假设 axis 对象称为 ax)方法。
  3. 然后当我想绘制补丁时,我会这样做:ax.draw_artist(patch)

这样做,我遇到了以下错误:

  File "environment.py", line 254, in animation_function
ax.draw_artist(patches[index])
File "A:\Anaconda\lib\site-packages\matplotlib\axes\_base.py", line 2121, in draw_artist
assert self._cachedRenderer is not None
AssertionError

顶层代码组织如下:

  • 函数根据数据创建补丁,然后将它们添加到 axis 对象——基本上,我得到一个补丁对象列表,patches,每个补丁都已添加到 ax我认为问题可能出在这里,因为 patches 中的补丁对象不是真正连接到 ax...,它们是添加到其中,但通过复制传递,而不是引用?

  • 动画函数使用从 FuncAnimation 接收到的数字(比如 n)来引用相关的补丁对象,然后调用 ax.draw_artist(补丁[n])

起初我在做以下事情:

patches = []
...
patch = mpatches.PathPatch(...)
patch.set_animated(True)
ax.add_patch(patch)
patches.append(patch)
...
ax.draw_artist(patches[n])

然后,在 reading the documentation 之后,这表明返回了一个补丁对象(可能现在连接到一个轴对象?),我尝试了以下操作:

patches = []
...
patch = mpatches.PathPatch(...)
patch.set_animated(True)
ax_patch = ax.add_patch(patch)
patches.append(ax_patch)
...
ax.draw_artist(patches[n])

但是,问题还是一样。

您能否评论一下您认为可能是什么问题,或者我可能需要在哪些方面提供额外信息才能找出问题?

编辑: 产生错误的顶级函数。

def create_animation_from_data(self, vertex_marker_radius=0.25, labels = ['a', 'a', 'b', 'b'], unit_line=0.5, colours=['red', 'blue', 'green', 'orange']):

fig = plt.figure()

ax = fig.add_subplot(111, aspect='equal', autoscale_on=False, xlim=(-2, 100), ylim=(-2, 100))
ax.grid()

print "Initializing patches..."

patches, patch_indices_per_timestep, num_polys, num_timesteps = self.make_patches_from_environment(ax, vertex_marker_radius, labels, unit_line, colours)

def animation_function(n):
relevant_patch_indices = patch_indices_per_timestep[n]

for polygon_based_index_group in relevant_patch_indices:
for index in polygon_based_index_group:
patches[index].draw(fig.canvas.get_renderer())

return patches,

print "Beginning animation..."
ani = animation.FuncAnimation(fig, animation_function, blit=True)

plt.show()

最佳答案

您正确理解了所有内容,但缺少几个较低级别的步骤。 renderer 尚未初始化,您会收到反射(reflect)该情况的错误。

简而言之,在第一次绘制绘图之前,您不能使用 draw_artist。您需要至少调用一次 fig.canvas.draw()(在某些情况下您可以只调用 fig.canvas.get_renderer())可以使用draw_artist


如果您遇到这个问题,通常是因为您试图“违背常理”并做一些最好不要直接处理的事情。

你到底想做什么?可能有一种更简单的方法来处理这个问题(例如,如果您要获取背景,请将这部分代码放在绘制事件的回调中)。


让我备份并解释发生了什么。 Matplotlib Artist 使用 Renderer 实例在 FigureCanvas(例如 fig.canvas)上绘制(例如 fig.canvas.renderer). renderer 是后端特定的和低级别的。您通常不会直接触摸它。

ax.draw_artist 是一个比 fig.canvas.draw 更底层的函数。更具体地说,它是 artist.draw(renderer) 的简写。

renderer 的初始化相对较慢,因此它会被缓存并重复使用,除非图形的大小或 dpi 发生变化。这就是您遇到的错误:canvas 还没有渲染器。


您有几种不同的选择。您可以手动初始化渲染器(最简单的方法是调用 fig.canvas.get_renderer())。然而,有时您想要获得一些在绘制之后才定义的东西(例如文本对象的大小)。在这些情况下,您需要一个“完整的”fig.canvas.draw()

不过,通常情况下,遇到这样的事情表明有更简单的方法可以做到这一点。通常最好将需要绘制的代码放入绘制事件的回调中。 (特别是如果它取决于图形的确切大小——例如 blitting 的背景)。


基于代码示例更新

如果您使用的是 matplotlib.animation 框架,那么您不需要在更新函数中绘制艺术家。动画框架将为您处理该步骤。

听起来您似乎只想显示您在每个时间步绘制的艺术家的子集?

如果是这样,您可能会考虑切换它们的可见性。举个简单的例子:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation


def main():
fig, ax = plt.subplots()
p = Plotter(ax)

# Note: We need to save a referce to the animation object, otherwise it
# will be garbage collected and never properly animate.
anim = matplotlib.animation.FuncAnimation(fig, p.update,
init_func=p.anim_init)
plt.show()

class Plotter(object):
def __init__(self, ax):
self.ax = ax

def anim_init(self):
self.triangles = [self.random_triangle() for _ in range(10)]

# Initially, show a blank plot...
for tri in self.triangles:
tri.set_visible(False)

return self.triangles

def update(self, i):
"""Animation step."""
# Hide all triangles
for tri in self.triangles:
tri.set(visible=False)

# pick 2 at random to show (e.g. your patch_indices_per_timestep)
for tri in np.random.choice(self.triangles, size=2):
tri.set(visible=True)

return self.triangles

def random_triangle(self):
x, y = np.random.random((2,3))
x += 10 * np.random.random(1)
y += 10 * np.random.random(1)
return self.ax.fill(x, y)[0]

main()

关于python - `matplotlib` : `self._chachedRenderer` fails `assert self._cachedRenderer is not None` , 在补丁上调用 `draw_artist` 时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30154473/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com