将底图转换为Cartopy,是否存在底图的shiftgrid()等等效函数?

时间:2019-10-24 12:44:37

标签: python matplotlib-basemap cartopy

我正在将使用matplotlib工具包Basemap的应用程序转换为使用Cartopy,以准备从Python 2过渡到Python 3。 我在Cartopy中为底图的'addcyclic()'和'maskoceans()'找到了类似的功能, 但是,对于底图的shiftgrid()函数,我在numpy或Cartopy中都找不到类似的东西。

这是使用底图的代码: '''

    import matplotlib.pyplot as plt
    from mpl_toolkits.basemap import Basemap
    import cartopy
    import cartopy.crs as ccrs
    import cartopy.feature as cfeature
    import numpy as np
    from mpl_toolkits.basemap import shiftgrid

    bmap = Basemap(projection='ortho', lat_0=0, lon_0=0)
    lons = np.arange(30, 410, 30)
    lons[1] = 70
    lats = np.arange(0, 100, 10)

    data = np.indices((lats.shape[0], lons.shape[0]))
    data = data[0] + data[1]

    data, lons = shiftgrid(180., data, lons, start=False)

    llons, llats = np.meshgrid(lons, lats)
    x, y = bmap(llons, llats)
    bmap.contourf(x, y, data)
    bmap.drawcoastlines()

'''

初始数据: 数据 '''

    [[ 0  1  2  3  4  5  6  7  8  9 10 11 12]
     [ 1  2  3  4  5  6  7  8  9 10 11 12 13]
     [ 2  3  4  5  6  7  8  9 10 11 12 13 14]
     [ 3  4  5  6  7  8  9 10 11 12 13 14 15]
     [ 4  5  6  7  8  9 10 11 12 13 14 15 16]
     [ 5  6  7  8  9 10 11 12 13 14 15 16 17]
     [ 6  7  8  9 10 11 12 13 14 15 16 17 18]
     [ 7  8  9 10 11 12 13 14 15 16 17 18 19]
     [ 8  9 10 11 12 13 14 15 16 17 18 19 20]
     [ 9 10 11 12 13 14 15 16 17 18 19 20 21]]

     lons

     [ 30  70  90 120 150 180 210 240 270 300 330 360 390]

     After the 'data, lons = shiftgrid(180., data, lons, start=False)':
     data

     [[ 5  6  7  8  9 10 11 12  1  2  3  4  5]
      [ 6  7  8  9 10 11 12 13  2  3  4  5  6]
      [ 7  8  9 10 11 12 13 14  3  4  5  6  7]
      [ 8  9 10 11 12 13 14 15  4  5  6  7  8]
      [ 9 10 11 12 13 14 15 16  5  6  7  8  9]
      [10 11 12 13 14 15 16 17  6  7  8  9 10]
      [11 12 13 14 15 16 17 18  7  8  9 10 11]
      [12 13 14 15 16 17 18 19  8  9 10 11 12]
      [13 14 15 16 17 18 19 20  9 10 11 12 13]
      [14 15 16 17 18 19 20 21 10 11 12 13 14]]

      lons

      [-180 -150 -120  -90  -60  -30    0   30   70   90  120  150  180]

''' 我尝试了以下cartopy代码来重新创建底图shiftgrid所做的事情。 这是Cartopy代码,在我一次尝试时,某些内容已被注释掉: '''

    DATA_CRS = ccrs.PlateCarree()
    lons = np.arange(30, 410, 30)
    lons[1] = 70
    lats = np.arange(0, 100, 10)

    data = np.indices((lats.shape[0], lons.shape[0]))
    data = data[0] + data[1]
    # data2 = np.roll(data, -5)
    # lons2 = np.mod(lons2 - 180.0, 360.0) - 180.0
    cm_lon = 0
    #llons, llats = np.meshgrid(lons2, lats)
    llons, llats = np.meshgrid(lons, lats)
    PROJECTION = ccrs.Orthographic(central_longitude=cm_lon)
    fig1 = plt.figure(num=1, figsize=(11, 8.5), dpi=150)
    ax = plt.axes(projection=PROJECTION)
    ax.add_feature(cfeature.COASTLINE, linewidths=0.7)
    ax.add_feature(cfeature.BORDERS, edgecolor='black', linewidths=0.7)
    ax.contourf(llons, llats, data, transform=ccrs.PlateCarree())

'''

数据和经度与原始数据一样,我只是在投影中使用了“ central_longitude”。 底图图像显示了整个地球,而Cartopy图像仅从赤道向上显示。 数据的颜色看起来非常相似,除了最右侧之外,因此我担心Cartopy中的数据映射与底图中的映射不同。

所以,问题是...是否有与底图的shiftgrid()等效的东西,或者我需要找出类似于底图的shiftgrid()的东西还是仅在投影中使用“ central_longitude”? 我似乎无法粘贴.png文件。 任何帮助都非常感谢。 我在网上搜索了等效的功能,但没有找到用于shiftgrid()的功能。 谢谢。

3 个答案:

答案 0 :(得分:1)

我不知道有任何等效的shiftgrid。可能值得在CartoPy issue tracker上提出一个要求这种功能的问题。提及可靠的用例以帮助驱动该功能将对此有所帮助。

答案 1 :(得分:0)

我发现了底图的shiftgrid功能 here 您可以将其与Cartopy一起作为单独的函数来调用。

import numpy as np
import numpy.ma as ma
def shiftgrid(lon0,datain,lonsin,start=True,cyclic=360.0):
    """
    Shift global lat/lon grid east or west.
    .. tabularcolumns:: |l|L|
    ==============   ====================================================
    Arguments        Description
    ==============   ====================================================
    lon0             starting longitude for shifted grid
                     (ending longitude if start=False). lon0 must be on
                     input grid (within the range of lonsin).
    datain           original data with longitude the right-most
                     dimension.
    lonsin           original longitudes.
    ==============   ====================================================
    .. tabularcolumns:: |l|L|
    ==============   ====================================================
    Keywords         Description
    ==============   ====================================================
    start            if True, lon0 represents the starting longitude
                     of the new grid. if False, lon0 is the ending
                     longitude. Default True.
    cyclic           width of periodic domain (default 360)
    ==============   ====================================================
    returns ``dataout,lonsout`` (data and longitudes on shifted grid).
    """
    if np.fabs(lonsin[-1]-lonsin[0]-cyclic) > 1.e-4:
        # Use all data instead of raise ValueError, 'cyclic point not included'
        start_idx = 0
    else:
        # If cyclic, remove the duplicate point
        start_idx = 1
    if lon0 < lonsin[0] or lon0 > lonsin[-1]:
        raise ValueError('lon0 outside of range of lonsin')
    i0 = np.argmin(np.fabs(lonsin-lon0))
    i0_shift = len(lonsin)-i0
    if ma.isMA(datain):
        dataout  = ma.zeros(datain.shape,datain.dtype)
    else:
        dataout  = np.zeros(datain.shape,datain.dtype)
    if ma.isMA(lonsin):
        lonsout = ma.zeros(lonsin.shape,lonsin.dtype)
    else:
        lonsout = np.zeros(lonsin.shape,lonsin.dtype)
    if start:
        lonsout[0:i0_shift] = lonsin[i0:]
    else:
        lonsout[0:i0_shift] = lonsin[i0:]-cyclic
    dataout[...,0:i0_shift] = datain[...,i0:]
    if start:
        lonsout[i0_shift:] = lonsin[start_idx:i0+start_idx]+cyclic
    else:
        lonsout[i0_shift:] = lonsin[start_idx:i0+start_idx]
    dataout[...,i0_shift:] = datain[...,start_idx:i0+start_idx]
    return dataout,lonsout

答案 2 :(得分:0)

这肯定是最优雅的解决方案,但是我对Carmapy中尚未使用的Basemap的几个有用功能所做的只是从Basemap的源代码复制功能定义。它工作正常。例如,shiftgrid:

def shiftgrid(lon0,datain,lonsin,start=True,cyclic=360.0):
"""
Shift global lat/lon grid east or west.
.. tabularcolumns:: |l|L|
==============   ====================================================
Arguments        Description
==============   ====================================================
lon0             starting longitude for shifted grid
                 (ending longitude if start=False). lon0 must be on
                 input grid (within the range of lonsin).
datain           original data with longitude the right-most
                 dimension.
lonsin           original longitudes.
==============   ====================================================
.. tabularcolumns:: |l|L|
==============   ====================================================
Keywords         Description
==============   ====================================================
start            if True, lon0 represents the starting longitude
                 of the new grid. if False, lon0 is the ending
                 longitude. Default True.
cyclic           width of periodic domain (default 360)
==============   ====================================================
returns ``dataout,lonsout`` (data and longitudes on shifted grid).
"""
if np.fabs(lonsin[-1]-lonsin[0]-cyclic) > 1.e-4:
    # Use all data instead of raise ValueError, 'cyclic point not included'
    start_idx = 0
else:
    # If cyclic, remove the duplicate point
    start_idx = 1
if lon0 < lonsin[0] or lon0 > lonsin[-1]:
    raise ValueError('lon0 outside of range of lonsin')
i0 = np.argmin(np.fabs(lonsin-lon0))
i0_shift = len(lonsin)-i0
if ma.isMA(datain):
    dataout  = ma.zeros(datain.shape,datain.dtype)
else:
    dataout  = np.zeros(datain.shape,datain.dtype)
if ma.isMA(lonsin):
    lonsout = ma.zeros(lonsin.shape,lonsin.dtype)
else:
    lonsout = np.zeros(lonsin.shape,lonsin.dtype)
if start:
    lonsout[0:i0_shift] = lonsin[i0:]
else:
    lonsout[0:i0_shift] = lonsin[i0:]-cyclic
dataout[...,0:i0_shift] = datain[...,i0:]
if start:
    lonsout[i0_shift:] = lonsin[start_idx:i0+start_idx]+cyclic
else:
    lonsout[i0_shift:] = lonsin[start_idx:i0+start_idx]
dataout[...,i0_shift:] = datain[...,start_idx:i0+start_idx]
return dataout,lonsout