使用basemap制作地图的对齐方法

6

有没有一种方法可以像下面这张图片一样对齐Python basemaps呢?enter image description here

以下是一些示例basemap代码,用于生成地图:

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt

fig = plt.figure(figsize=(8, 4.5))
plt.subplots_adjust(left=0.02, right=0.98, top=0.98, bottom=0.00)
m = Basemap(projection='robin',lon_0=0,resolution='c')
m.fillcontinents(color='gray',lake_color='white')
m.drawcoastlines()
plt.savefig('world.png',dpi=75)

1
你能具体说明一下吗?如果你只是想在一个图中使用几个“Basemaps”,请使用subplots。如果这不是你所需要的,请告诉我们更多关于你实际问题的信息。 - Thomas Kühn
感谢@ThomasKühn,我想在一个图中使用几个底图,但更重要的是,我想将它们以某个角度对齐(与问题中的图类似)。 - user308827
1个回答

7

我不是Matplotlib的专家,但是我发现可以通过使用“basemap”源文件夹中包含的数据文件来获得类似的结果。可以将它们组合成一个“meshgrid”来绘制一些数据,在下面的示例中,我们绘制每个点的高度。

我使用的一个技巧是将“matplotlib”设置为正交投影,以便地图的垂直间距没有扭曲。

我将参数放在代码开头,因为您可能会发现调整很有用。

有一件事情让我感到困惑,那就是地图下面的阴影。

from mpl_toolkits.mplot3d import proj3d
from mpl_toolkits.basemap import Basemap
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
import numpy as np
import matplotlib.pyplot as plt

# Parameters
n_maps = 5 # Number of maps
z_spacing = 4. # Spacing of maps along z
z_reduction = 1E-8 # Reduction factor for Z data, makes the map look flat
view_angles = (14., -100.) # Set view port angles
colbar_bottom = 0.2 # Space at the bottom of colorbar column
colbar_spacing = .132 # Space between colorbars
colbar_height = 0.1 # Height of colorbars

# Set orthogonal projection
def orthogonal_proj(zfront, zback):
    a = (zfront+zback)/(zfront-zback)
    b = -2*(zfront*zback)/(zfront-zback)
    return np.array([[1,0,0,0],
                     [0,1,0,0],
                     [0,0,a,b],
                     [0,0,-0.0001,zback]])

proj3d.persp_transformation = orthogonal_proj

fig = plt.figure(figsize=[30, 10*n_maps])
ax = fig.gca(projection='3d')

etopo = np.loadtxt('etopo20data.gz')
lons  = np.loadtxt('etopo20lons.gz')
lats  = np.loadtxt('etopo20lats.gz')
# Create Basemap instance for Robinson projection.
m = Basemap(projection='robin', lon_0=0.5*(lons[0]+lons[-1]))
# Compute map projection coordinates for lat/lon grid.
X, Y = m(*np.meshgrid(lons,lats))

# Exclude the oceans
Z = etopo.clip(-1)

# Set the colormap
cmap = plt.cm.get_cmap("terrain")
cmap.set_under("grey")

for i in range(n_maps):
    c = ax.contourf(X, Y, z_spacing*i + z_reduction*Z, 30, cmap=cmap, vmin=z_spacing*i, extend='neither')
    cax = inset_axes(ax,
               width="5%",
               height="100%",
               loc=3,
               bbox_to_anchor=(.85, colbar_spacing*i+colbar_bottom, .2, colbar_height),
               bbox_transform=ax.transAxes,
               borderpad=0
               )
    cb = fig.colorbar(c, cax=cax)
    cb.set_label("Altitude")
    # Reset the ticks of the color bar to match initial data
    cb.set_ticks([z_spacing * i + j/10. * z_reduction * Z.max() for j in range(11)])
    cb.set_ticklabels([str(int(j/10. * Z.max())) for j in range(11)])

ax.set_axis_off()
ax.view_init(*view_angles)
ax.set_xlim3d(X.min(), X.max())
ax.set_ylim3d(Y.min(), Y.max())
ax.set_zlim3d(-1E-2, (n_maps-1)*z_spacing)

plt.savefig('world.png',dpi=75)

结果

编辑:

如果你想要阴影效果并且不介意额外的计算时间,可以将 for 循环的开头改为以下内容:

shadow_Z = np.empty(Z.shape)
for i in range(n_maps):
    c = ax.contourf(X, Y, z_spacing*i + z_reduction*Z, 30, cmap=cmaps[i], vmin=z_spacing*i, extend='neither')
    for j in range(10):
        shadow_Z.fill(z_spacing*i - 1E-2 * j)
        s = ax.contourf((X - X.mean()) * (1 + 8E-3 * j) + X.mean() + 2E5, 
                        (Y - Y.mean()) * (1 + 8E-3 * j) + Y.mean() - 2E5, 
                        shadow_Z, colors='black', alpha=0.1 - j * 1E-2)

@user308827 我成功地在地图下方添加了一些阴影,尽管速度有点慢。 - Jacques Gaudin
1
感谢@jacques!这个解决方案超出了我的预期。 - user308827
你能否将.gz文件上传到某个地方? - user308827
1
您可以在源代码的示例文件夹中获取.gz文件:https://sourceforge.net/projects/matplotlib/files/matplotlib-toolkits/basemap-1.0.7/basemap-1.0.7.tar.gz/download - Jacques Gaudin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接