在matplotlib中放大了inset,但没有回复d

2024-06-17 15:19:15 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在绘制一些matplotlib绘图,需要放大的插图。这可以通过axes_grid1工具箱中的zoomed_inset_axes实现。请参见示例here

import matplotlib.pyplot as plt

from mpl_toolkits.axes_grid1.inset_locator import zoomed_inset_axes
from mpl_toolkits.axes_grid1.inset_locator import mark_inset

import numpy as np

def get_demo_image():
    from matplotlib.cbook import get_sample_data
    import numpy as np
    f = get_sample_data("axes_grid/bivariate_normal.npy", asfileobj=False)
    z = np.load(f)
    # z is a numpy array of 15x15
    return z, (-3,4,-4,3)

fig, ax = plt.subplots(figsize=[5,4])

# prepare the demo image
Z, extent = get_demo_image()
Z2 = np.zeros([150, 150], dtype="d")
ny, nx = Z.shape
Z2[30:30+ny, 30:30+nx] = Z

# extent = [-3, 4, -4, 3]
ax.imshow(Z2, extent=extent, interpolation="nearest",
          origin="lower")

axins = zoomed_inset_axes(ax, 6, loc=1) # zoom = 6
axins.imshow(Z2, extent=extent, interpolation="nearest",
             origin="lower")

# sub region of the original image
x1, x2, y1, y2 = -1.5, -0.9, -2.5, -1.9
axins.set_xlim(x1, x2)
axins.set_ylim(y1, y2)

plt.xticks(visible=False)
plt.yticks(visible=False)

# draw a bbox of the region of the inset axes in the parent axes and
# connecting lines between the bbox and the inset axes area
mark_inset(ax, axins, loc1=2, loc2=4, fc="none", ec="0.5")

plt.draw()
plt.show()

这将产生期望的结果:

Resulthttp://matplotlib.org/1.3.1/_images/inset_locator_demo21.png

但是正如您在代码中看到的那样,数据必须绘制两次-一次用于主轴(ax.imshow...),一次用于插入轴(axins.imshow...)。在

我的问题是:

有没有办法在主绘图完成后添加缩放的插图,而不需要在新轴上重新绘制所有内容?在

请注意:我不是在寻找一种解决方案,它用一个函数包装plot调用,并让函数绘图ax和{}(见下面的示例),而是(如果存在的话)使用ax中现有数据的本机解决方案。有人知道这样的解决方案是否存在?在

这是包装解决方案:

^{pr2}$

它可以工作,但感觉有点像黑客攻击,因为如果我只想放大现有绘图区域,为什么还要重新绘制所有数据呢。在


在ed smith的回答之后,还做了一些补充说明:

上面的例子当然只是最小的例子。图中可能有许多不同的数据集(对于数据集我指的是通过imshowplot等绘制的东西)。例如,想象一个有10个点阵列的散点图,所有这些点都是绘制的,而不是普通的x

正如我在上面所写的,最直接的方法就是使用一个包装器来绘制所有实例中的数据。但是我要寻找的是一种方法(如果它存在的话)从最后的ax对象开始(而不是单独的绘图命令),然后以某种方式创建缩放的inset。在


Tags: the数据import绘图getmatplotlibnp绘制
1条回答
网友
1楼 · 发布于 2024-06-17 15:19:15

我想下面的内容可以满足您的需要。注意,您将返回的句柄用于第一个imshow,并将其添加到插入的轴上。你需要复印一份,这样每个数字都有一个单独的把手

import matplotlib.pyplot as plt

from mpl_toolkits.axes_grid1.inset_locator import zoomed_inset_axes
from mpl_toolkits.axes_grid1.inset_locator import mark_inset

import numpy as np
import copy

def get_demo_image():
    from matplotlib.cbook import get_sample_data
    import numpy as np
    f = get_sample_data("axes_grid/bivariate_normal.npy", asfileobj=False)
    z = np.load(f)
    # z is a numpy array of 15x15
    return z, (-3,4,-4,3)

fig, ax = plt.subplots(figsize=[5,4])

# prepare the demo image
Z, extent = get_demo_image()
Z2 = np.zeros([150, 150], dtype="d")
ny, nx = Z.shape
Z2[30:30+ny, 30:30+nx] = Z

# extent = [-3, 4, -4, 3]
im = ax.imshow(Z2, extent=extent, interpolation="nearest",
          origin="lower")

#Without copy, image is shown in insert only
imcopy = copy.copy(im)
axins = zoomed_inset_axes(ax, 6, loc=1) # zoom = 6
axins.add_artist(imcopy)

# sub region of the original image
x1, x2, y1, y2 = -1.5, -0.9, -2.5, -1.9
axins.set_xlim(x1, x2)
axins.set_ylim(y1, y2)

plt.xticks(visible=False)
plt.yticks(visible=False)

# draw a bbox of the region of the inset axes in the parent axes and
# connecting lines between the bbox and the inset axes area
mark_inset(ax, axins, loc1=2, loc2=4, fc="none", ec="0.5")

plt.draw()
plt.show()

对于你的包装函数,这应该是这样的

^{pr2}$

但是,由于imshow只是将存储在数组Z中的数据显示为一个图像,我认为这个解决方案实际上比两个单独调用imshow慢。对于耗时较长的绘图,例如contour绘图或pcolormesh,这种方法可能是明智的。。。在

编辑:

超过一个imshow,以及不同类型的多个绘图。绘图函数都返回不同的句柄(例如,plot返回一个行列表,imshow返回一个matplotlib.image.AxesImage等等)。您可以在绘图时不断地将这些句柄添加到列表(或dict)中(如果它们足够相似,可以使用collection)。然后您可以编写一个通用函数,使用add_artist或add_patch方法从缩放的轴将它们添加到一个轴上,可能使用if类型检查来处理绘图中使用的各种类型。一个更简单的方法是循环ax.get_children()并重用任何不是轴本身元素的内容。在

另一个选择可能是研究bliting技术,rasterization或其他用于加速动画的技术,例如使用fig.canvas.copy_from_bbox或{}将整个图形复制为图像(请参见why is plotting with Matplotlib so slow?}低)。您还可以绘制图形,将其保存到非矢量图形(使用savefig或StringIObuffer),读回并绘制放大版本。在

相关问题 更多 >