[英]Matplotlib - mark_inset with different edges for axes
我想在一個子圖中繪制阻尼隨機游走的時間序列,然后在第二個子圖中放大它。 我知道 matplotlib 中的mark_inset
,它工作正常。 我到目前為止的代碼是:
from mpl_toolkits.axes_grid1.inset_locator import mark_inset
from astroML.time_series import generate_damped_RW
fig = plt.figure()
ax = fig.add_subplot(111)
ax0 = fig.add_subplot(211)
ax1 = fig.add_subplot(212)
ax.set_ylabel('Brightness[mag]')
ax.yaxis.labelpad=30
ax.spines['top'].set_color('none')
ax.spines['bottom'].set_color('none')
ax.spines['left'].set_color('none')
ax.spines['right'].set_color('none')
ax.tick_params(labelcolor='w', top='off', bottom='off', left='off',
right='off')
t = np.linspace(0, 5000, 100000)
data = generate_damped_RW(t, tau=100, xmean=20, z=0, SFinf=0.3,
random_state=1)
ax0.scatter(t, data, s=0.5)
ax0.text(1, 1, r'$E(m) = %.2f, \sigma(m) = %.2f$'%(np.mean(data),
np.std(data)),
verticalalignment='top', horizontalalignment='right',
transform=ax0.transAxes, fontsize=23)
mask = (t > 370) & (t < 470)
ax1.set_xlabel('Time[years]')
ax1.scatter(t[mask], data[mask], s=0.5)
mark_inset(ax0, ax1, loc1=2, loc=1, fc='none')
這幾乎是我想要的,除了連接 2 個子圖的線從第一個子圖的框的上邊緣開始。 是否有可能讓它們從兩個下邊緣開始,而它們仍然在第二個子圖中的上兩個邊緣結束? 我必須做什么才能實現這一目標?
mark_inset
有兩個參數loc1
和loc2
來設置兩個連接器的位置。 這些位置對於框和插入軸是相同的。
然而,我們可以向mark_inset
函數添加兩個新參數,以設置連接器開始和結束的不同位置。
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import TransformedBbox, BboxPatch, BboxConnector
import numpy as np
fig, (ax, axins) = plt.subplots(nrows=2)
x = np.linspace(0,6*np.pi)
y = np.sin(x)
ax.plot(x,y)
axins.plot(x,y)
axins.set_xlim((2*np.pi, 2.5*np.pi))
axins.set_ylim((0, 1))
# 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
# loc1, loc2 : {1, 2, 3, 4}
def mark_inset(parent_axes, inset_axes, loc1a=1, loc1b=1, loc2a=2, loc2b=2, **kwargs):
rect = TransformedBbox(inset_axes.viewLim, parent_axes.transData)
pp = BboxPatch(rect, fill=False, **kwargs)
parent_axes.add_patch(pp)
p1 = BboxConnector(inset_axes.bbox, rect, loc1=loc1a, loc2=loc1b, **kwargs)
inset_axes.add_patch(p1)
p1.set_clip_on(False)
p2 = BboxConnector(inset_axes.bbox, rect, loc1=loc2a, loc2=loc2b, **kwargs)
inset_axes.add_patch(p2)
p2.set_clip_on(False)
return pp, p1, p2
mark_inset(ax, axins, loc1a=1, loc1b=4, loc2a=2, loc2b=3, fc="none", ec="crimson")
plt.draw()
plt.show()
不幸的是, mark_inset
總是必須連接相同的角(即右下角總是必須連接到右下角等)。
不過,我們可以創建自己的模仿mark_inset
函數的函數,將兩個底角與插圖中的兩個頂角連接起來(下面代碼中的custom_mark_inset
)。
這使用Rectangle
patch 在主軸上繪制框,並使用ConnectionPatch
實例繪制軸之間的連接線。
from mpl_toolkits.axes_grid1.inset_locator import mark_inset
#from astroML.time_series import generate_damped_RW
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111)
ax0 = fig.add_subplot(211)
ax1 = fig.add_subplot(212)
ax.set_ylabel('Brightness[mag]')
ax.yaxis.labelpad=30
ax.spines['top'].set_color('none')
ax.spines['bottom'].set_color('none')
ax.spines['left'].set_color('none')
ax.spines['right'].set_color('none')
ax.tick_params(labelcolor='w', top='off', bottom='off', left='off',
right='off')
t = np.linspace(0, 5000, 10000)
#data = generate_damped_RW(t, tau=100, xmean=20, z=0, SFinf=0.3,
# random_state=1)
## Fake some data
data = np.sin(t/800.) + 20.
ax0.scatter(t, data, s=0.5)
ax0.text(1, 1, r'$E(m) = %.2f, \sigma(m) = %.2f$'%(np.mean(data),
np.std(data)),
verticalalignment='top', horizontalalignment='right',
transform=ax0.transAxes, fontsize=23)
mask = (t > 370) & (t < 470)
ax1.set_xlabel('Time[years]')
ax1.scatter(t[mask], data[mask], s=0.5)
def custom_mark_inset(axA, axB, fc='None', ec='k'):
xx = axB.get_xlim()
yy = axB.get_ylim()
xy = (xx[0], yy[0])
width = xx[1] - xx[0]
height = yy[1] - yy[0]
pp = axA.add_patch(patches.Rectangle(xy, width, height, fc=fc, ec=ec))
p1 = axA.add_patch(patches.ConnectionPatch(
xyA=(xx[0], yy[0]), xyB=(xx[0], yy[1]),
coordsA='data', coordsB='data',
axesA=axA, axesB=axB))
p2 = axA.add_patch(patches.ConnectionPatch(
xyA=(xx[1], yy[0]), xyB=(xx[1], yy[1]),
coordsA='data', coordsB='data',
axesA=axA, axesB=axB))
return pp, p1, p2
pp, p1, p2 = custom_mark_inset(ax0, ax1)
plt.show()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.