问题描述
我想将子图画布嵌入到cartopy投影地图中。我编写了这段代码,以使用矩形显示预期的结果:
#%%
import numpy as np
import cartopy as cr
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from cartopy.io import shapereader
import geopandas
resolution = '10m'
category = 'cultural'
name = 'admin_0_countries'
shpfilename = shapereader.natural_earth(resolution,category,name)
# read the shapefile using geopandas
df = geopandas.read_file(shpfilename)
# read the country borders
usa = df.loc[df['ADMIN'] == 'United States of America']['geometry'].values[0]
can = df.loc[df['ADMIN'] == 'Canada']['geometry'].values[0]
central_lon,central_lat = -80,60
extent = [-85,-55,40,62]
# ax = plt.axes(projection=ccrs.Orthographic(central_lon,central_lat))
#Golden ratio
phi = 1.618033987
h = 7
w = phi*h
fig = plt.figure(figsize=(w,h))
ax = fig.add_subplot(1,1,projection=ccrs.PlateCarree())
#Set map extent
ax.set_extent(extent)
ax.set_xticks(np.linspace(extent[0],extent[1],11))
ax.set_yticks(np.linspace(extent[2],extent[3],6))
ax.add_geometries(usa,crs=ccrs.PlateCarree(),facecolor='none',edgecolor='k')
# ax.gridlines()
ax.coastlines(resolution='50m')
nx,ny = 7,6
#Begin firts rectangle
xi = extent[0] + 0.5
yi = extent[2] + 0.5
x,y = xi,yi
#Loop for create the plots grid
for i in range(nx):
for j in range(ny):
#Inner rect height
in_h = 2.8
#Draw the rect
rect = ax.add_patch(mpatches.Rectangle(xy=[x,y],width=phi*in_h,height=in_h,facecolor='blue',alpha=0.2,transform=ccrs.PlateCarree()))
#Get vertex of the drawn rectangle
verts = rect.get_path().vertices
trans = rect.get_patch_transform()
points = trans.transform(verts)
#Refresh rectangle coordinates
x += (points[1,0]-points[0,0]) + 0.2
if j == ny-1:
x = xi
y += (points[2,1]-points[1,1]) + 0.2
# print(points)
fig.tight_layout()
fig.savefig('figure.pdf',format='pdf',dpi=90)
plt.show()
我正在寻找一种嵌入与图中每个矩形匹配的图的方法。我尝试使用fig.add_axes
,但无法使迷你画布与实际矩形匹配。
解决方法
由于建议您使用inset_axes
将轴嵌入父轴中,请参阅文档here。
我编写了简单的代码来演示其工作原理。显然,您需要对inset_axes的位置和大小进行一些调整,以实现所需的输出,但是我认为我的琐碎实现确实不错。
所有创建的轴实例都存储在列表中,以便以后可以访问。
import matplotlib.pyplot as plt
import numpy as np
fig,ax = plt.subplots()
axis = []
x = np.linspace(-85,-55)
y = np.linspace(40,62)
ax.plot(x,y)
offset_l = 0.05
offset_h = 0.12
num_x = 6
num_y = 7
xs = np.linspace(offset_l,1-offset_h,num_x)
ys = np.linspace(offset_l,num_y)
for k in range(num_x):
for j in range(num_y):
ax_ins = ax.inset_axes([xs[k],ys[j],0.1,0.1])
ax_ins.axhspan(0,1,color='tab:blue',alpha=0.2)
axis.append(ax_ins)
或者,您也可以使用数据坐标指定inset_axes位置,为此,您必须将方法中的kwarg transform
设置为transform=ax.transData
,另请参见下面的代码。
import matplotlib.pyplot as plt
import numpy as np
#Golden ratio
phi = 1.618033987
h = 7
w = phi*h
fig,ax = plt.subplots(figsize=(w,h))
axis = []
x = np.linspace(-85,y)
offset_l = 0.05
offset_h = 0.12
num_x = 6
num_y = 7
fig.tight_layout()
extent = [-85,-55,40,62]
xi = extent[0] + 0.5
yi = extent[2] + 0.5
in_h = 2.8
in_w = phi * 2.8
spacing = 0.4
for k in range(num_x):
for j in range(num_y):
ax_ins = ax.inset_axes([xi+k*(in_w + phi*spacing),yi+j*(in_h + spacing),in_w,in_h],transform=ax.transData)
ax_ins.axhspan(0,alpha=0.2)
axis.append(ax_ins)