使用 cartopy 在其他投影中绘制投影数据

Plotting projected data in other projectons using cartopy

这个问题是关于绘制我拥有的一些使用 Lambert Conformal (LCC) CRS 的数据。虽然这些问题具体涉及在多个投影中绘制 LCC 数据,但它也适用于一般的 cartopy 的使用,因为我想更好地理解 logic/process 使用 cartopy 进行绘图。

下面是我正在尝试做的一些代码示例。第一个示例只是绘制一些 LCC 数据。我使用的数据在linkhere.

import cartopy.crs as ccrs
import cartopy.feature as cf
import matplotlib.pyplot as plt
import numpy as np

proj = ccrs.LambertConformal(central_latitude = 25, 
                             central_longitude = 265, 
                             standard_parallels = (25, 25))

# Data and coordinates (from download link above)
with np.load('nam_218_20120414_1200_006.npz') as nam:
   dat = nam['dpc']
   lat = nam['lat']
   lon = nam['lon']

ax = plt.axes(projection = proj)
ax.pcolormesh(lon, lat, dat, transform = ccrs.PlateCarree())
ax.add_feature(cf.NaturalEarthFeature(
               category='cultural',
               name='admin_1_states_provinces_lines',
               scale='50m',
               facecolor='none'))
ax.coastlines('50m')
ax.add_feature(cf.BORDERS)
plt.show()

制作的剧情可以看这里:

LCC 地图上的美国露点

我在使用cartopy时的第一个困惑是为什么我在绘图时总是要转换为PlateCarree?我最初的想法是 pcolormesh 调用的 transform 关键字需要 LCC 投影信息而不是 PlateCarree

下一步,如果我想在另一个投影中绘制我的 LCC 数据,例如正字法,我会像下面那样做吗?

# First, transform from LCC to Orthographic
transform = proj.transform_points(ccrs.Orthographic(265,25), lon, lat)
x = transform[..., 0]
y = transform[..., 1]

ax = plt.axes(projection = ccrs.Orthographic(265,25))
ax.pcolormesh(x, y, dat, transform = ccrs.PlateCarree())
ax.add_feature(cf.NaturalEarthFeature(
               category='cultural',
               name='admin_1_states_provinces_lines',
               scale='50m',
               facecolor='none'))
ax.coastlines('50m')
ax.add_feature(cf.BORDERS)
ax.set_global()

制作的剧情可以看这里:

正射地图上的美国露点

我认为正交地图看起来不错,但我想确保我正确理解了使用 cartopy 重新投影的过程。

综上所述,我想了解以下内容:

  1. 画图的时候总是transformPlateCarree吗?为什么或为什么不?
  2. 重新投影只需要调用 transform_points 方法还是涉及其他步骤?

更新 1

根据 @swatchai 的回答,似乎我的问题 2 的答案是 transform_points 不是必需的。在许多 matplotlib 绘图方法中,可以简单地使用 transform 关键字参数。这就是我最初的想法。但是,跳过 transform_points 对我没有用。请参见下面的示例:

ax = plt.axes(projection = ccrs.Orthographic(265,25))
ax.pcolormesh(lon, lat, dat, transform = proj)
ax.add_feature(cf.NaturalEarthFeature(
               category='cultural',
               name='admin_1_states_provinces_lines',
               scale='50m',
               facecolor='none'))
ax.coastlines('50m')
ax.add_feature(cf.BORDERS)
ax.set_global()

产生这个情节:

没有 transform_points 步骤的正交图

问题似乎是纬度和经度输入未转换为网格坐标,因此它们仅绘制在绘图的极小区域中。因此,为了扩展问题 2,如果您应该跳过 transform_points 基于我上面的示例,cartopy 的绘图方法是否存在错误?还是我还漏了一步?

在Cartopy中,ccrs.PlateCarree()是最基本的地图投影,有时也称为un-projected投影,即一个以度为单位的地理位置(lat,long) -> 成为网格值y =纬度; x=long 在 PlateCarree 地图上。

这段代码:

import cartopy.crs as ccrs
axm = plt.axes( projection = ccrs.xxxx() ) 

创建轴 axm 用于在 xxxx 投影中绘制地图。当您在 axm 上绘制数据时,默认坐标是该投影的网格 (x,y)(通常以米为单位)。这就是为什么您需要 transform=ccrs.PlateCarree() 来声明您的输入 (x,y) 确实在 (long,lat) 度数中,或者换句话说,在 PlateCarree 网格坐标的 (x,y) 中。

如果您的目标投影是正交投影,而数据是 LambertConformal,

ax = plt.axes(projection = ccrs.Orthographic(265,25))
lccproj = ccrs.LambertConformal(central_latitude = 25, 
                         central_longitude = 265, 
                         standard_parallels = (25, 25))

您可以使用

绘制数据
ax.pcolormesh(x, y, dat, transform = lccproj)

绘图时根本不需要使用 transform_points()。但是当你想在某些情况下访问转换后的坐标时它很有用。

需要在地理坐标和投影(或网格)坐标之间做出重要区分。更详细的描述可以在 here 中找到。重要的是,有助于回答问题 1 的是纬度和经度是 geographic 坐标,而以米为单位的点是 projected 坐标.

来自示例数据的数值天气模型在其计算中使用兰伯特共形投影(更多 here)。但是,得到输出的坐标是纬度和经度。如果您对空间数据没有经验,您最终可能会认为 lat/lon 对是 LCC projected 坐标,而实际上它们是 geogrphic坐标; LCC 的东西在模型集成期间使用。

要回答问题 1,不,您不必总是使用 PlateCarree 作为源 CRS。但是,您确实总是使用 PlateCarree 作为纬度和经度数据(这里就是这种情况)。这样 cartopy 将正确地将您的 lat/lon 值转换为 projected 坐标(以米为单位),并且能够在绘图期间轻松地将您的数据 transform 转换为其他投影。这个问题最终是更新 1 中看似空白图的原因。通过说源数据在 transform 中有 LCC 投影坐标,cartopy 接受了 lat/lon 输入并将它们解释为具有米单位。确实绘制了数据,但范围太小,如果不将绘图范围更改为与数据相同,则无法看到它们。

关于问题 2,不,不要求使用 transform_points。 cartopy 以这样一种方式设置,可以轻松地以最少的中间步骤在多个投影中绘制。正如@swatchai 提到的,有时您可能想要使用实际的投影坐标,使用 transform_points 方法可以让您做到这一点。当 transform_points 用于生成原始 post 中的第二个图时,它本质上是手动执行如果在 transform 中使用 PlateCarree 正确处理输入坐标会自动完成的操作].

最后,@ajdawson 就绘图时如何使用 projectiontransform 做出了重要说明。一旦了解了源坐标的内容,此信息也很有用。评论转引如下:

In general, projection tells cartopy what the drawn map should look like, and transform tells cartopy what coordinate system your data is represented in. You can set projection to any projection you like, but transform needs to match whatever coordinate system your data uses.