matplotlib mark_inset在插图中有不同的数据

时间:2016-12-13 21:37:37

标签: python matplotlib

这是一个有点棘手的解释。基本上,我想制作一个插图,然后利用mpl_toolkits.axes_grid1.inset_locator.mark_inset的便利性,但我希望插图中的数据完全独立于父轴中的数据。

具有我想要使用的功能的示例代码:

import numpy as np

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
from mpl_toolkits.axes_grid1.inset_locator import mark_inset
from mpl_toolkits.axes_grid1.inset_locator import InsetPosition

data = np.random.normal(size=(2000,2000))
plt.imshow(data, origin='lower')
parent_axes = plt.gca()

ax2 = inset_axes(parent_axes, 1, 1)
ax2.plot([900,1100],[900,1100])

# I need more control over the position of the inset axes than is given by the inset_axes function
ip = InsetPosition(parent_axes,[0.7,0.7,0.3,0.3])
ax2.set_axes_locator(ip)

# I want to be able to control where the mark is connected to, independently of the data in the ax2.plot call
mark_inset(parent_axes, ax2, 2,4)

# plt.savefig('./inset_example.png')
plt.show()

示例代码生成以下图像: enter image description here

总而言之:蓝框的位置完全由ax2.plot()的输入数据控制。我想手动放置蓝色框并输入我想要的任何东西到ax2。这可能吗?

快速编辑:要清楚,我理解为什么插图会将数据链接起来,因为这是最有可能的用法。因此,如果在matplotlib中实现这一目标的方式完全不同,请随时回复。但是,我试图避免手动将盒子和线条放置到我放置的所有轴上,因为我需要在大图像中插入一些插图。

2 个答案:

答案 0 :(得分:3)

如果我理解正确,您希望在给定位置处任意缩放的轴看起来像缩放的插图,但与插入标记的位置没有关联。

按照您的方法,您可以使用set_axes_locator(ip)函数简单地将另一个轴添加到绘图中并将其放置在真实插图的相同位置。由于此轴是在原始插图之后绘制的,因此它将位于其上方,您只需要隐藏原始绘图的刻度线以使其完全消失(set_visible(False)在此处不起作用,因为它会隐藏插图和标记位置之间的线条。)

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes, mark_inset, InsetPosition

data = np.random.normal(size=(200,200))
plt.imshow(data, origin='lower')
parent_axes = plt.gca()

ax2 = inset_axes(parent_axes, 1, 1)
ax2.plot([60,75],[90,110])
# hide the ticks of the linked axes
ax2.set_xticks([])
ax2.set_yticks([])

#add a new axes to the plot and plot whatever you like
ax3 = plt.gcf().add_axes([0,0,1,1])
ax3.plot([0,3,4], [2,3,1], marker=ur'$\u266B$' , markersize=30, linestyle="") 
ax3.set_xlim([-1,5])
ax3.set_ylim([-1,5])


ip = InsetPosition(parent_axes,[0.7,0.7,0.3,0.3])
ax2.set_axes_locator(ip)
# set the new axes (ax3) to the position of the linked axes
ax3.set_axes_locator(ip)
# I want to be able to control where the mark is connected to, independently of the data in the ax2.plot call
mark_inset(parent_axes, ax2, 2,4)

plt.show()

enter image description here

答案 1 :(得分:2)

FWIW,我想出了一个有效的黑客。

在inset_locator的源代码中,我添加了一个mark_inset版本,它带有另一组用于定义TransformedBbox的轴:

def mark_inset_hack(parent_axes, inset_axes, hack_axes, loc1, loc2, **kwargs):
    rect = TransformedBbox(hack_axes.viewLim, parent_axes.transData)

    pp = BboxPatch(rect, **kwargs)
    parent_axes.add_patch(pp)

    p1 = BboxConnector(inset_axes.bbox, rect, loc1=loc1, **kwargs)
    inset_axes.add_patch(p1)
    p1.set_clip_on(False)
    p2 = BboxConnector(inset_axes.bbox, rect, loc1=loc2, **kwargs)
    inset_axes.add_patch(p2)
    p2.set_clip_on(False)

    return pp, p1, p2

然后在我的原始邮政编码中,我创建了一个插入轴,我希望框在哪里,将其传递给我的黑客函数,并使其不可见:

# location of desired axes
axdesire = inset_axes(parent_axes,1,1)
axdesire.plot([100,200],[100,200])

mark_inset_hack(parent_axes, ax2, axdesire, 2,4)

axdesire.set_visible(False)

现在我在数据单元中的不同位置有一个标记框,而不是我标记的插图:

enter image description here

这肯定是一个彻头彻尾的黑客攻击,而且在这一点上我不确定它比简单地手动绘制线更清晰,但我认为对于很多插件来说这将使概念更加清晰。

其他想法仍然受到欢迎。