Xarray Roll和Cartopy add_cyclic_point函数冲突

时间:2018-01-15 15:12:08

标签: python-xarray cartopy

最近,我试图从180W-20E一起制作太平洋和大西洋的简单情节。为了越过0度线我使用滚动方法如下:

db=Test3

使用roll方法:

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

from cartopy.mpl.ticker    import LongitudeFormatter, LatitudeFormatter
from cartopy.util          import add_cyclic_point


dset  =  xr.open_dataset('sst.mnmean.nc')
var   =  dset['sst'][:,:,:]
lat   =  dset['lat'][:]
lon   =  dset['lon'][:]

这将给我以下经度数组:

lonr = lon.roll(lon=300)

然后我继续用'sel'方法提取我想要的区域:

[ 120.  122.  124.  126.  128.  130.  132.  134.  136.  138.  140.  142.
  144.  146.  148.  150.  152.  154.  156.  158.  160.  162.  164.  166.
  168.  170.  172.  174.  176.  178.  180.  182.  184.  186.  188.  190.
  192.  194.  196.  198.  200.  202.  204.  206.  208.  210.  212.  214.
  216.  218.  220.  222.  224.  226.  228.  230.  232.  234.  236.  238.
  240.  242.  244.  246.  248.  250.  252.  254.  256.  258.  260.  262.
  264.  266.  268.  270.  272.  274.  276.  278.  280.  282.  284.  286.
  288.  290.  292.  294.  296.  298.  300.  302.  304.  306.  308.  310.
  312.  314.  316.  318.  320.  322.  324.  326.  328.  330.  332.  334.
  336.  338.  340.  342.  344.  346.  348.  350.  352.  354.  356.  358.
    0.    2.    4.    6.    8.   10.   12.   14.   16.   18.   20.   22.
   24.   26.   28.   30.   32.   34.   36.   38.   40.   42.   44.   46.
   48.   50.   52.   54.   56.   58.   60.   62.   64.   66.   68.   70.
   72.   74.   76.   78.   80.   82.   84.   86.   88.   90.   92.   94.
   96.   98.  100.  102.  104.  106.  108.  110.  112.  114.  116.  118.]

应用这最后一行是为了避免情节上的奇怪水平线,如here所述。也就是说我的切片经度阵列现在看起来像这样:

lonr = lonr.sel(lon=slice(180,12))
lonr = lonr.roll(lon=104)

现在的问题是:这解决了区域选择问题,但它在绘制时给出了0经度值周围的奇怪白线,你可以看到here。要解决它,我们会考虑使用“add_cyclic_point”方法,但这会产生以下错误:

[   0.    2.    4.    6.    8.   10.   12.  180.  182.  184.  186.  188.
  190.  192.  194.  196.  198.  200.  202.  204.  206.  208.  210.  212.
  214.  216.  218.  220.  222.  224.  226.  228.  230.  232.  234.  236.
  238.  240.  242.  244.  246.  248.  250.  252.  254.  256.  258.  260.
  262.  264.  266.  268.  270.  272.  274.  276.  278.  280.  282.  284.
  286.  288.  290.  292.  294.  296.  298.  300.  302.  304.  306.  308.
  310.  312.  314.  316.  318.  320.  322.  324.  326.  328.  330.  332.
  334.  336.  338.  340.  342.  344.  346.  348.  350.  352.  354.  356.
  358.]

正如它所说的那样,我无法将该点添加到数组中,因为它不是等间距的。从方法手册中可以看出为什么我不能使用它,但当然我不想在我的情节(an example of what I did can be seen here)中使用那条奇怪的白线。

对于相当冗长的问题感到抱歉,但是有谁知道如何解决这个问题?任何帮助,将不胜感激。

1 个答案:

答案 0 :(得分:2)

鉴于我们无法访问您的代码来重现问题,我将发明一些数据来说明滚动问题:

In [1]: import numpy as np

In [2]: lons = np.arange(0, 360, 10)

In [3]: lons
Out[3]: 
array([  0,  10,  20,  30,  40,  50,  60,  70,  80,  90, 100, 110, 120,
       130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 250,
       260, 270, 280, 290, 300, 310, 320, 330, 340, 350])

现在,如果我们像你一样滚动它:

In [4]: lons = np.roll(lons, -list(lons).index(100))

In [5]: lons
Out[5]: 
array([100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220,
       230, 240, 250, 260, 270, 280, 290, 300, 310, 320, 330, 340, 350,
         0,  10,  20,  30,  40,  50,  60,  70,  80,  90])

这些数字的问题在于它们很好,如果你认为它们是球形的(其中350与0相差10度),但是如果认为它们是笛卡尔坐标,那么有两点之间的距离数据点是350度。在绘制数据时,如果您告诉Cartopy您的数据在PlateCarree投影坐标系中,这正是正在发生的事情。

在这种情况下,有很多方法可以修复您的号码,这样您就可以在某些点之间保持这样的距离。一种方式:

In [6]: np.diff(lons) < -180
Out[6]: 
array([False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False,  True, False,
       False, False, False, False, False, False, False, False], dtype=bool)

In [7]: np.cumsum(np.diff(lons) < -180)
Out[7]: 
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])

In [8]: new_lons = lons.copy()

In [8]: new_lons[1:] += np.cumsum(np.diff(lons) < -180) * 360

In [9]: new_lons
Out[9]: 
array([100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220,
       230, 240, 250, 260, 270, 280, 290, 300, 310, 320, 330, 340, 350,
       360, 370, 380, 390, 400, 410, 420, 430, 440, 450])

你现在回到了预计空间中等距坐标的领域,并且应该比add_cyclic_point更有运气。