简体   繁体   中英

Use mark_inset with different range plot

Say I want to inset a plot to a figure, but the inset plot has different axis range than the one I am marking the inset to. For example:

fig, ax = plt.subplots()
axins = inset_axes(ax, 1,1 , loc=2, bbox_to_anchor=(0.35,0.85),bbox_transform=ax.figure.transFigure)

x = np.linspace(0, 3, 100)
y = x**2
ax.plot(x, y)
axins.plot(x, x**3)

x1, x2, y1, y2 = 2.,3, 6, 8 # specify the limits
axins.set_xlim(x1, x2) # apply the x-limits
axins.set_ylim(y1, y2) # apply the y-limits

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

mark_inset(ax, axins, loc1=4, loc2=1)#, fc="none")#, ec="0.5")

The result is an empty inset plot:

在此处输入图片说明

But this is obvious, since I set the limits of x and y to ranges where x**3 does not pass. What I want to see is, for example, a plot of x**3 for 0 to 1 in the inset plot, while the mark_inset will still 'zoom' to the region boxed above, which is of different range.

How can I do this?

In that case you cannot use mark_inset directly, because that is exactly what this function does: synchronizing the marker with the axes limits of the inset.

Using a rectangle

Instead you may position some rectangle whereever you want it to be and use ConnectionPatch es to draw some lines in between the inset and the rectangle.

import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.axes_grid1.inset_locator as il
import matplotlib.patches as mpatches

fig, ax = plt.subplots()

axins = il.inset_axes(ax, 1,1 , loc=2, bbox_to_anchor=(0.35,0.85),bbox_transform=ax.figure.transFigure)

x = np.linspace(0, 3, 100)
y = x**2
ax.plot(x, y)
axins.plot(x, x**3)

x1, x2, y1, y2 = 2.,3, 6, 8 # specify the limits
rect = mpatches.Rectangle((x1,y1), width=x2-x1, height=y2-y1, facecolor="None", edgecolor="k", linewidth=0.8)
fig.canvas.draw()
p1 = mpatches.ConnectionPatch(xyA=(1,0), xyB=(x2,y1), coordsA="axes fraction", coordsB="data",  axesA=axins, axesB=ax)
p2 = mpatches.ConnectionPatch(xyA=(1,1), xyB=(x2,y2), coordsA="axes fraction", coordsB="data",  axesA=axins, axesB=ax)

ax.add_patch(rect)
ax.add_patch(p1)
ax.add_patch(p2)

plt.show()

Use dummy axes

You may also simply add an additional inset, just for the purpose of using mark_inset with it.

import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.axes_grid1.inset_locator as il

fig, ax = plt.subplots()
axins_dummy = il.inset_axes(ax, 1,1 , loc=2, bbox_to_anchor=(0.35,0.85),bbox_transform=ax.figure.transFigure)
axins = il.inset_axes(ax, 1,1 , loc=2, bbox_to_anchor=(0.35,0.85),bbox_transform=ax.figure.transFigure)

x = np.linspace(0, 3, 100)
y = x**2
ax.plot(x, y)
axins.plot(x, x**3)

x1, x2, y1, y2 = 2.,3, 6, 8 # specify the limits
axins_dummy .set_xlim(x1, x2) # apply the x-limits
axins_dummy .set_ylim(y1, y2) # apply the y-limits

axins_dummy.tick_params(left=False, bottom=False, labelleft=False, labelbottom=False )

il.mark_inset(ax,axins_dummy , loc1=4, loc2=1)#, fc="none")#, ec="0.5")

plt.show()

In both cases, the resulting plot would look like

在此处输入图片说明

Maybe it's worth noting that the resulting graph is of course incorrect. Any reader would assume that the inset shows part of the curve, which is not the case. Hence make sure not to use such graph in a publication or report.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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