简体   繁体   English

将线更改为插入轴

[英]Changing lines to inset axes

I'm using matplotlib v. 3.0.3.我正在使用 matplotlib v. 3.0.3。 I wanted to use inset axes to zoom in on a location in an imshow plot and then plot the zoomed in sections outside the main image.我想使用插入轴放大 imshow plot 中的位置,然后 plot 放大主图像之外的部分。 I was playing around with the inset axes using the following code我正在使用以下代码玩插入轴

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

fig, ax = plt.subplots(figsize=(6,6))
Z2 = np.random.rand(512, 512)

ax.imshow(Z2, interpolation='gaussian', cmap = 'RdBu', origin='lower')
ax.tick_params(axis='both', bottom=False, top=False, right=False, left=False, labelbottom=False, labelleft=False, labeltop=False, labelright=False)

# inset axes...
axins_1 = ax.inset_axes([0, -1, 1, 1]) # bottom left, outside main plot
axins_1.imshow(Z2, interpolation="gaussian", cmap = 'RdBu', origin='lower')
axins_1.tick_params(axis='both', bottom=False, top=False, right=False, left=False, labelbottom=False, labelleft=False, labeltop=False, labelright=False)
# sub region of the original image
axins_1.set_xlim(100, 150)
axins_1.set_ylim(85, 135)

ax.indicate_inset_zoom(axins_1, edgecolor='0')
#mark_inset(ax, axins_1, loc1=2, loc2=3, fc="none", lw=1, ec='k')

# inset axes...
axins_2 = ax.inset_axes([1, -1, 1, 1]) # bottom right, outside main plot
axins_2.imshow(Z2, interpolation="gaussian", cmap = 'RdBu', origin='lower')
axins_2.tick_params(axis='both', bottom=False, top=False, right=False, left=False, labelbottom=False, labelleft=False, labeltop=False, labelright=False)
# sub region of the original image
axins_2.set_xlim(400, 450)
axins_2.set_ylim(200, 250)

ax.indicate_inset_zoom(axins_2, edgecolor='0')
#mark_inset(ax, axins_2, loc1=2, loc2=3, fc="none", lw=1, ec='k')

# inset axes...
axins_3 = ax.inset_axes([1, 0, 1, 1]) # top right, outside main plot
axins_3.imshow(Z2, interpolation="gaussian", cmap = 'RdBu', origin='lower')
axins_3.tick_params(axis='both', bottom=False, top=False, right=False, left=False, labelbottom=False, labelleft=False, labeltop=False, labelright=False)
# sub region of the original image
axins_3.set_xlim(400, 450)
axins_3.set_ylim(400, 450)

ax.indicate_inset_zoom(axins_3, edgecolor='0')
#mark_inset(ax, axins_3, loc1=2, loc2=3, fc="none", lw=1, ec='k')

plt.show()

Here, the main plot is the top left while the top right and both bottom pictures are the zoomed quantities.在这里,主要的 plot 是左上角,而右上角和两个底部图片是放大的数量。 This generates almost exactly the plot I am after inside the Jupyter notebook .这几乎完全生成了我在 Jupyter notebook 中所追求的 plot However, I have two issues that I'm looking to fix.但是,我有两个问题要解决。

My first issue is that when I save the plot it comes out as follows我的第一个问题是,当我保存 plot 时,结果如下

在此处输入图像描述

which clearly cuts off the zoomed images.这清楚地切断了缩放的图像。 I was wondering how to fix this?我想知道如何解决这个问题?

The second issue is that the lines running from the subsections of the main plot to the zoomed images cross over in multiple places.第二个问题是从主要 plot 的子部分到缩放图像的线条在多个地方交叉。 What I would like is to keep the boxes around the subsections but change the lines.我想要的是保留小节周围的框,但改变线条。 However, from the documentation it seems you can't remove the lines only, as changing edgecolor does the colouring for both the box and lines.但是,从文档看来,您不能只删除线条,因为更改 edgecolor 会同时为框和线条着色。

What I would like is to have an arrow leading from the section pointing to the correct zoomed image or some other way of labelling the sections and their corresponding zoomed images.我想要的是有一个从该部分指向正确的缩放图像的箭头,或者以其他方式标记这些部分及其相应的缩放图像。 However, I haven't been able to find a way to do this.但是,我还没有找到一种方法来做到这一点。 Is this possible?这可能吗? And if so, how do we do it?如果是这样,我们该怎么做?

The alternative way to do this would be to make subplots and simply plot the zoomed regions in the subplots.另一种方法是制作子图,并简单地 plot 子图中的缩放区域。 However, in this approach I am at a loss as to how to identify each subsection with the corresponding zoomed plot.但是,在这种方法中,我不知道如何用相应的缩放 plot 来识别每个小节。

You can always roll your own simplified inset function.您可以随时滚动您自己的简化inset function。

Here I'm using subplots to control my layout to help ensure I don't draw outside of the bounds of my Figure (which is why your Figure clips your Axes when saving to file).在这里,我使用subplots来控制我的布局,以帮助确保我不会在我的Figure边界之外绘制(这就是为什么你的Figure在保存到文件时会剪辑你的Axes )。

Additionally, I set up my own rectangle and ConnectionPatch so that I'm only drawing a single ConnectionPatch per desired inset with the arguments I need.此外,我设置了我自己的矩形和ConnectionPatch ,这样我只需使用我需要的 arguments 为每个所需的插图绘制一个ConnectionPatch This enables me to have explicit control over where the arrow starts and ends.这使我能够明确控制箭头的开始和结束位置。

In the function I provided在我提供的 function

  • arrow_start is an xy coordinate in proportional units on the Rectangle (eg (0, 0) is the lower left hand corner of the rectanble, (0, .5) is the center left, (0, 1) is the upper left, (1, 1) is the upper right, etc. arrow_start是矩形上比例单位的 xy 坐标(例如 (0, 0) 是矩形的左下角, (0, .5) 是左中角, (0, 1) 是左上角, ( 1, 1) 是右上角,等等。
  • arrow_end is an xy coordinate in proportional units on the inset Axes (eg (0, 0) is the lower left hand corner of the inset Axes, so on so forth. arrow_end是插入轴上比例单位的 xy 坐标(例如 (0, 0) 是插入轴的左下角,依此类推。

You can use these two parameters to explicitly place your arrows where you think they go best on your figure to not overlap with other Axes您可以使用这两个参数明确地将箭头放置在您认为它们 go 最好的位置,以免与其他Axes重叠

I also moved some of your style setting code to the top as default settings to be used.我还将您的一些样式设置代码移到顶部作为要使用的默认设置。

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle, ConnectionPatch
import numpy as np

plt.rc('xtick', bottom=False, top=False, labelbottom=False)
plt.rc('ytick', left=False, right=False, labelleft=False)
plt.rc('figure', facecolor='white')

def indicate_inset(axin, axout, arrow_start=(0, 0), arrow_end=(0, 0)):
    (x0, x1), (y0, y1) = axin.get_xlim(), axin.get_ylim()
    width = x1 - x0
    height = y1 - y0
    
    rect = Rectangle(
        [x0, y0], width=width, height=height, 
        transform=axout.transData, fc='none', ec='black'
    )
    axout.add_patch(rect)
    
    conn = ConnectionPatch(
        xyA=arrow_start, coordsA=rect.get_transform(),
        xyB=arrow_end, coordsB=axin.transAxes,
        arrowstyle='->'
    )
    fig.add_artist(conn)
    return rect, conn


fig, axes = plt.subplots(
    2, 2, figsize=(6, 6), 
    gridspec_kw={'wspace': 0.05, 'hspace': 0.05, 'left':.1, 'right': .9}
)
Z2 = np.random.rand(512, 512)

imshow_kws = dict(interpolation='gaussian', cmap='RdBu', origin='lower')
raw_ax = axes[0, 0]
raw_ax.imshow(Z2, **imshow_kws)

# inset axes...
axes[1, 0].imshow(Z2, **imshow_kws)
axes[1, 0].set(xlim=(100, 150), ylim=(85, 135))
indicate_inset(axes[1, 0], raw_ax, arrow_start=(.5, 0), arrow_end=(.5, 1))

# # inset axes...
axes[1, 1].imshow(Z2, **imshow_kws)
axes[1, 1].set(xlim=(400, 450), ylim=(200, 250))
indicate_inset(axes[1, 1], raw_ax, arrow_start=(.5, 0), arrow_end=(0, 1))

# # # inset axes...
axes[0, 1].imshow(Z2, **imshow_kws)
axes[0, 1].set(xlim=(400, 450), ylim=(400, 450))
indicate_inset(axes[0, 1], raw_ax, arrow_start=(1, 0), arrow_end=(0, .5))

fig.savefig('test.png') # This is the image uploaded to this answer

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM