我使用的是matplotlib v3.0.3.我想使用插入轴放大imshow绘图中的某个位置,然后将放大的部分绘制在主图像之外.我使用了以下代码来处理插入轴

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()

在这里,主要的情节是左上角,而右上角和两个底部的图片是zoom 量.这几乎就产生了我在inside the Jupyter notebook岁之后的情节.然而,我有两个问题需要解决.

我的第一个问题是,当我保存情节时,它如下所示

enter image description here

这清楚地切断了放大的图像.我在想怎么解决这个问题?

第二个问题是,从主地块的子部分到zoom 图像的直线在多个地方交叉.我想要的是保留小节周围的方框,但改变线条.然而,从the documentation开始,你似乎不能只删除线条,因为改变边框 colored颜色 会同时为盒子和线条上色.

我想要的是有一个箭头从部分指向正确的zoom 图像或一些其他方式的标签部分及其相应的zoom 图像.然而,我还没有找到一种方法来做到这一点.这个是可能的吗?如果是这样的话,我们该怎么做?

另一种方法是制作子图,然后简单地在子图中绘制zoom 区域.然而,在这种方法中,我不知所措,不知道如何将每个小节与相应的zoom 情节区分开来.

推荐答案

你可以随时滚动你自己的简化的inset功能.

在这里,我使用subplots来控制我的布局,以帮助确保我不会超出Figure的界限(这就是为什么Figure在保存到文件时会剪切Axes的原因).

此外,我还设置了自己的矩形和ConnectionPatch,这样我就可以用我需要的参数 for each 想要的插入值绘制一个ConnectionPatch.这使我能够明确控制箭头的起点和终点.

在我提供的函数中

  • arrow_start是以矩形上的比例单位表示的XY坐标 (例如,(0,0)是直方图的左下角,(0,0.5)是左中,(0,1)是左上,(1,1)是右上,依此类推.
  • arrow_end是插入轴上比例单位的XY坐标(例如,(0,0)是插入轴的左下角,依此类推.

您可以使用这两个参数来显式地将箭头放置在图形上您认为最合适的位置,以避免与其他Axes个箭头重叠

我还将您的一些样式设置代码移到了顶部,作为要使用的默认设置.

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

enter image description here

Python相关问答推荐

处理(潜在)不断增长的任务队列的并行/并行方法

如何记录脚本输出

OR—Tools中CP—SAT求解器的IntVar设置值

在Python中动态计算范围

关于Python异步编程的问题和使用await/await def关键字

有没有一种ONE—LINER的方法给一个框架的每一行一个由整数和字符串组成的唯一id?

如何在达到end_time时自动将状态字段从1更改为0

重置PD帧中的值

Python—为什么我的代码返回一个TypeError

一个telegram 机器人应该发送一个测验如何做?""

如何将泛型类类型与函数返回类型结合使用?

BeatuifulSoup从欧洲志愿者服务中获取数据和解析:一个从EU-Site收集机会的小铲子

如果服务器设置为不侦听创建,则QWebSocket客户端不连接到QWebSocketServer;如果服务器稍后开始侦听,则不连接

如何在python tkinter中绑定键盘上的另一个回车?

将标签与山脊线图对齐

为什么内置的sorted()对于一个包含降序数字的列表来说,如果每个数字连续出现两次,会变慢?

Python键盘模块不会立即检测到按键

从`end_date`回溯,如何计算以极为单位的滚动统计量?

如何计算二十面体每条三角形边的中点

有理由将基于Django职业的观点个人化吗?