matplotlib Basemap Fundamental Lune

matplotlib Basemap Fundamental Lune

我正在尝试使用 matplotlib 重新创建此投影 Fundamental Lune Plot. The reference material associated with this specific projection is here, Carl Tape Moment Tensors

绘图背后的地球物理学并不重要,但本质上它是经度 -30 到 30 度和纬度 -90 到 90 之间的投影。我认为底图可能是创建投影的好方法, 但我似乎无法弄清楚如何只显示这个基本的 lune 部分。这是我一直在玩的东西,但它仍然显示整个地球:

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

m = Basemap(
        resolution='l',     # coastline resolution, can be 'l' (low), 'h'
        projection='hammer', # Hammer projection
        lat_ts=0,          # latitude of true scale
        lon_0=0,          # longitude of the plotting domain center
        lat_0=0)           # latitude of the plotting domain center

# draw parallels and meridians.
m.drawparallels(np.arange(-90.,90.,10.))
m.drawmeridians(np.arange(-30.,31.,10.))
ax = plt.gca()
plt.show()

有人可以提供一些指导或建议吗?

在 Basemap 中,我认为 Hammer 投影是 "global",这意味着它不需要输入范围,因此始终显示整个地球是有意义的。

我不确定如何使用底图制作您正在寻找的那种图,但我认为我可以使用 Cartopy 来完成。以下代码生成下方和左侧的图像,以及一些演示数据:

import matplotlib.pyplot as plt
import numpy as np
import cartopy.crs as ccrs
import matplotlib.path as mpath

# Mollweide projection
fig = plt.figure()
ax = fig.add_subplot(111, projection=ccrs.Mollweide())

# Here I define a matplotlib Path object to use as the boundary
outlinex = np.concatenate([[-30],np.tile(-30,180), np.tile(30,180),[-30]])
outliney = np.concatenate([[-90],np.arange(-90,90),np.arange(89,-91,-1),[-90]])
outlinecodes = np.array([mpath.Path.MOVETO]+[mpath.Path.LINETO]*360+[mpath.Path.MOVETO])
outlinepath = mpath.Path(np.column_stack([outlinex[::-1], outliney[::-1]]), outlinecodes[::-1])

# For good measure, plot some data
ax.plot(np.arange(-10,25), np.linspace(80,45,35), transform=ccrs.Geodetic())
ax.plot(np.tile(25,91),np.arange(45,-46,-1), transform=ccrs.Geodetic())

# Plot gridlines and set the boundary
ax.gridlines(xlocs=np.arange(-30,31,10), ylocs=np.arange(-90,91,45))
ax.set_boundary(outlinepath, transform=ccrs.Geodetic(), use_as_clip_path=False)

# The plotting will have automatically set the extents, so set them to what we want
ax.set_extent((-30,30,-90,90))

plt.show()

请注意,如果您省略 set_boundary 元素而只使用 set_extent,您将获得右侧的图像,而不是左侧的图像。