简体   繁体   English

在 cartopy 中绘制旋转极点投影

[英]Plotting rotated pole projection in cartopy

I have a rotated pole projection (taken from the Rapid Refresh model parameters) that I am able to plot correctly in matplotlib-basemap, but can't figure out how to reproduce with cartopy.我有一个旋转的极点投影(取自 Rapid Refresh 模型参数),我能够在 matplotlib-basemap 中正确绘制,但无法弄清楚如何使用 cartopy 进行再现。 Here is the Python code using basemap:这是使用底图的 Python 代码:

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

bm = Basemap(projection = "rotpole",
                  o_lat_p = 36.0,
                  o_lon_p = 180.0,
                  llcrnrlat = -10.590603,
                  urcrnrlat = 46.591976,
                  llcrnrlon = -139.08585,
                  urcrnrlon = 22.661009,
                  lon_0 = -106.0,
                  rsphere = 6370000,
                  resolution = 'l')

fig = plt.figure(figsize=(8,8))
ax = fig.add_axes([0.1,0.1,0.8,0.8])

bm.drawcoastlines(linewidth=.5)

print bm.proj4string

plt.savefig("basemap_map.png")
plt.close(fig)

The proj4 string that prints is:打印的 proj4 字符串是:

+o_proj=longlat +lon_0=-106.0 +o_lat_p=36.0 +R=6370000.0 +proj=ob_tran +units=m +o_lon_p=180.0

If I use the RotatedPole projection in cartopy and supply the projection parameters from above, I get an image in the south pole.如果我在 cartopy 中使用 RotatedPole 投影并从上面提供投影参数,我会在南极得到一个图像。 Here is a snippet (manually typed in from a real example, be warned):这是一个片段(从真实示例中手动输入,请注意):

from cartopy import crs
import matplotlib.pyplot as plt

cart = crs.RotatedPole(pole_longitude=180.0, 
                       pole_latitude=36.0,
                       central_rotated_longitude=-106.0, 
                       globe = crs.Globe(semimajor_axis=6370000,
                                semiminor_axis=6370000))

fig = plt.figure(figsize=(8,8))
ax = plt.axes([0.1,0.1,0.8,0.8], projection=cart)
ax.set_extent([-139.08585, 22.661009, -10.590603, 46.591976], crs.Geodetic())
plt.savefig("cartopy_map.png")
plt.close(fig)

I've also tried modifying arguments to the RotatedPole class to produce the proj4 parameters from above, and even tried making my own subclass of _CylindricalProjection and setting the proj4 parameters directly in the constructor, but still no luck.我还尝试修改 RotatedPole 类的参数以从上面生成 proj4 参数,甚至尝试创建我自己的 _CylindricalProjection 子类并直接在构造函数中设置 proj4 参数,但仍然没有运气。

What is the right way in cartopy to produce the same result as basemap?在 cartopy 中产生与底图相同的结果的正确方法是什么?

Here is the basemap image:这是底图图像:

底图图像

Here is what cartopy produces for the above example:以下是 cartopy 为上述示例生成的内容:

图像

Thanks for your help!谢谢你的帮助!

Bill账单

There is an attribute available on a cartopy CRS which gives you the proj4 parameters. cartopy CRS 上有一个可用的属性,它为您提供 proj4 参数。

from cartopy import crs


rp = crs.RotatedPole(pole_longitude=180.0,     
                     pole_latitude=36.0,
                     central_rotated_longitude=-106.0,
                     globe=crs.Globe(semimajor_axis=6370000,
                                     semiminor_axis=6370000))

print(rp.proj4_params)

Gives:给出:

{'a': 6370000, 'o_proj': 'latlon',
 'b': 6370000, 'to_meter': 0.017453292519943295,
 'ellps': 'WGS84', 'lon_0': 360.0,
 'proj': 'ob_tran', 'o_lat_p': 36.0,
 'o_lon_p': -106.0}

So it looks like you only need to set the pole longitude and latitude in order to match your desired projection.所以看起来你只需要设置极点经度和纬度就可以匹配你想要的投影。 The important point being that pole longitude is the position of the dateline of the new projection, not its central longitude - from memory, I seem to remember that this is consistent with bodies such as the WMO, but inconsistent with proj.4:重要的一点是极经度是新投影的日期变更线的位置,而不是其中心经度 - 从记忆中,我似乎记得这与 WMO 等机构一致,但与 proj.4 不一致:

>>> rp = ccrs.RotatedPole(pole_longitude=-106.0 - 180,
                         pole_latitude=36,
                         globe=ccrs.Globe(semimajor_axis=6370000,
                                          semiminor_axis=6370000))
>>> print(rp.proj4_params)
{'a': 6370000, 'o_proj': 'latlon', 'b': 6370000, 'to_meter': 0.017453292519943295,
 'ellps': 'WGS84', 'lon_0': -106.0, 'proj': 'ob_tran',
 'o_lat_p': 36, 'o_lon_p': 0.0}

With all of that in place, the final code might look something like:有了所有这些,最终的代码可能看起来像:

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

rp = ccrs.RotatedPole(pole_longitude=-106.0 - 180,
                      pole_latitude=36,
                      globe=ccrs.Globe(semimajor_axis=6370000,
                                       semiminor_axis=6370000))
pc = ccrs.PlateCarree()

ax = plt.axes(projection=rp)
ax.coastlines('50m', linewidth=0.8)
ax.add_feature(cartopy.feature.LAKES,
               edgecolor='black', facecolor='none',
               linewidth=0.8)

# In order to reproduce the extent, we can't use cartopy's smarter
# "set_extent" method, as the bounding box is computed based on a transformed
# rectangle of given size. Instead, we want to emulate the "lower left corner"
# and "upper right corner" behaviour of basemap.
xs, ys, zs = rp.transform_points(pc,
                                 np.array([-139.08, 22.66]),
                                 np.array([-10.59, 46.59])).T
ax.set_xlim(xs)
ax.set_ylim(ys)

plt.show()

结果图

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM