我有可以轻松自动地处理颜色和绘制多个图的代码(对我来说)。我想使注释更容易:
目标: 如果注释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
我可以对注解执行类似的操作(更改if语句和第二个循环的主体),但是1)我不喜欢这段代码2)我希望存在更优雅的方法。
谢谢
这是我想避免的解决方案。我在问题评论中链接的旧问题中看到有人提到这是一个np完全问题,但我想指出的是这并不重要。我测试了多达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
任何改进的建议 都会受到热烈欢迎。非常感谢!