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