我有代码可以自动处理着色和绘制多个绘图(对我来说)。我想让注释更容易:
目标:如果注释xy与前一个注释发生冲突,请移位 - 说 - 直到与其他注释没有冲突。
如果有一个能够实现梦想的功能,我就找不到了。
否则 - 列出注释并在坐标系中获取边界框的最佳方法是什么?
我有一个自动着色的代码,如下所示:
if chain:
children = []
for child in Iplot.axes.get_children():
if (type(child) is not matplotlib.collections.PathCollection and
type(child) is not matplotlib.lines.Line2D):
continue
children.append(child)
col_step = 1.0/(len(children)+len(args))
for child in children:
child.set_color([Iplot.col,0,1-Iplot.col])
Iplot.col += col_step
我可以为注释做一些类似的事情(改变第二个循环的语句和主体),但是1)我不喜欢这段代码2)我希望存在更优雅的东西。
由于
答案 0 :(得分:2)
这是我的解决方案,我试图避免。我在问题评论中链接的旧问题中看到有人提到这是一个完整的问题,但我想指出这并不重要。我测试了多达26个注释,需要几秒钟但不会更多。任何实用的情节都不会有1000个注释。
注意事项:
背景:
Iplot
是一个助手类,我必须处理多色图,处理着色,大小调整和现在注释。plt
是matplotlib.pyplot
Iplot.axes
拥有我的斧头。修改强> 我删除了我的类代码,使其更易于复制。轴应该被赋予函数,并且kwargs接受现有的box关键字以考虑先前的注释,这些注释是在适当的位置编辑的。注意我使用一个类来封装它。该函数必须返回框以供使用,以防这是第一次调用。
编辑2
过了一会儿加速了 - 不需要画那么多,最好循环两次然后更新渲染器。
代码:
def annotate(axes,boxes,labels,data,**kwargs):
#slide should be relevant edge of bbox - e.g. (0,0) for left, (0,1) for bottom ...
try: slide = kwargs.pop("slide")
except KeyError: slide = None
try:
xytexts = kwargs.pop("xytexts")
xytext = xytexts
except KeyError:
xytext = (0,2)
xytexts = None
try: boxes = kwargs.pop("boxes")
except KeyError: boxes = list()
pixel_diff = 1
newlabs = []
for i in range(len(labels)):
try:
len(xytexts[i])
xytext = xytexts[i]
except TypeError: pass
a = axes.annotate(labels[i],xy=data[i],textcoords='offset pixels',
xytext=xytext,**kwargs)
newlabs.append(a)
plt.draw()
for i in range(len(labels)):
cbox = a.get_window_extent()
if slide is not None:
direct = int((slide[0] - 0.5)*2)
current = -direct*float("inf")
arrow = False
while True:
overlaps = False
count = 0
for box in boxes:
if cbox.overlaps(box):
if direct*box.get_points()[slide] > direct*current:
overlaps = True
current = box.get_points()[slide]
shift = direct*(current - cbox.get_points()[1-slide[0],slide[1]])
if not overlaps: break
arrow = True
position = array(a.get_position())
position[slide[1]] += shift * direct * pixel_diff
a.set_position(position)
plt.draw()
cbox = a.get_window_extent()
x,y = axes.transData.inverted().transform(cbox)[0]
if arrow:
axes.arrow(x,y,data[i][0]-x,data[i][1]-y,head_length=0,head_width=0)
boxes.append(cbox)
plt.draw()
return boxes
欢迎任何改进建议。非常感谢!