在嵌入的绘图中使用不同数据的matplotlib mark_inset

3
这个有点棘手,我来解释一下。基本上,我想制作一个嵌入式图表,然后利用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个回答

4
如果我理解正确,您需要在给定位置上具有任意比例的轴,看起来像缩放的插图,但与插图标记的位置没有关联。
按照您的方法,您可以简单地向图表中添加另一个轴,并将其定位到真正插图的相同位置,使用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


我也考虑过类似的东西……我的hack会影响蓝色框的位置,而你的hack会影响插图中的数据。拥有多个选项总是好的,而你的选项不需要修改mpl源代码。 - Brian Hayden

2

值得一提的是,我想到了一个可行的方法。

在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

这显然是一种取巧的方法,目前我不确定它是否比手动绘制线条更加简洁,但我认为对于许多插图来说,这将使概念上更加清晰。
其他想法仍然受欢迎。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接