从中心坐标重新采样网格到外部(即角落)坐标

5

有没有一种现成的方法可以从网格中心位置(红色点)推断网格角落位置(蓝色点)?

我正在处理的网格不是矩形的,因此常规的双线性插值似乎不是最好的方法;但是,这只是为了使用pyplot.pcolormesh()绘制我的数据,所以那可能并不那么重要。

enter image description here

示例网格数据

import numpy as np

lons = np.array([[ 109.93299681,  109.08091365,  108.18301276,  107.23602539],
                 [ 108.47911382,  107.60397996,  106.68325946,  105.71386119],
                 [ 107.06790187,  106.17259769,  105.23214707,  104.2436463 ],
                 [ 105.69908292,  104.78633156,  103.82905363,  102.82453812]])

lats = np.array([[ 83.6484245 ,  83.81088466,  83.97177823,  84.13098916],
                 [ 83.55459198,  83.71460466,  83.87294803,  84.02950188],
                 [ 83.4569054 ,  83.61444708,  83.77022192,  83.92410637],
                 [ 83.35554612,  83.51060313,  83.6638013 ,  83.81501464]])
2个回答

4
我不知道有什么强大的matplotlib技术可以完成您的需求,但我可能有一个不同的解决方案。我经常需要填充/外推到缺少信息的网格区域。为此,我使用一个Fortran程序,使用F2PY(随numpy一起发布)进行编译,它会将其创建为python模块。假设您拥有Intel Fortran编译器,则可以使用以下命令进行编译:f2py --verbose --fcompiler=intelem -c -m extrapolate fill.f90。您可以使用以下命令从Python中调用该程序(请参见这里以获取完整示例):
    import extrapolate as ex
    undef=2.0e+35
    tx=0.9*undef
    critx=0.01
    cor=1.6
    mxs=100

    field = Zg
    field=np.where(abs(field) > 50 ,undef,field)

    field=ex.extrapolate.fill(int(1),int(grdROMS.xi_rho),
                            int(1),int(grdROMS.eta_rho),
                            float(tx), float(critx), float(cor), float(mxs),
                            np.asarray(field, order='Fortran'),
                            int(grdROMS.xi_rho),
                            int(grdROMS.eta_rho))

该程序使用迭代方法解决了在矩形坐标系中有Neumann边界条件(dA / dn = 0)的Laplace方程,以填充包含"undef"值的网格点的合理值。这个程序非常好用,也许您会发现它很有用。该程序可在我的Github账户这里找到。

我之前不知道F2PY。这个工具在其他方面也可能很有用。我正在绘制NORWECOM.e2e模型的模块输出。我会等待其他输入,看看是否还有其他可用的东西。谢谢! - ryanjdillon
1
F2PY非常棒,如果你想加速代码的部分,比如嵌套循环。我自己实际上一直在处理norwecom.e2e,我知道这可能是具有挑战性的。 - Trond Kristiansen

2

这是我采用的不太优雅的方法,使用pyproj首先计算点之间的距离和方位角(使用pyproj.Geod.inv),然后通过必要的距离插值/外推该角度(使用pyproj.Geod.fwd)到psi位置。

代码:

def calc_psi_coords(lons, lats):
    ''' Calcuate psi points from centered grid points'''

    import numpy as np
    import pyproj

    # Create Geod object with WGS84 ellipsoid
    g = pyproj.Geod(ellps='WGS84')

    # Get grid field dimensions
    ydim, xdim = lons.shape

    # Create empty coord arrays
    lons_psi = np.zeros((ydim+1, xdim+1))
    lats_psi = np.zeros((ydim+1, xdim+1))

    # Calculate internal points
    #--------------------------
    for j in range(ydim-1):
        for i in range(xdim-1):
            lon1 = lons[j,i]     # top left point
            lat1 = lats[j,i]
            lon2 = lons[j+1,i+1] # bottom right point
            lat2 = lats[j+1,i+1]
            # Calc distance between points, find position at half of dist
            fwd_az, bck_az, dist = g.inv(lon1,lat1,lon2,lat2)
            lon_psi, lat_psi, bck_az = g.fwd(lon1,lat1,fwd_az,dist*0.5)
            # Assign to psi interior positions
            lons_psi[j+1,i+1] = lon_psi
            lats_psi[j+1,i+1] = lat_psi

    # Caclulate external points (not corners)
    #----------------------------------------
    for j in range(ydim):
        # Left external points
        #~~~~~~~~~~~~~~~~~~~~~
        lon1 = lons_psi[j+1,2] # left inside point
        lat1 = lats_psi[j+1,2]
        lon2 = lons_psi[j+1,1] # left outside point
        lat2 = lats_psi[j+1,1]
        # Calc dist between points, find position at dist*2 from pos1
        fwd_az, bck_az, dist = g.inv(lon1,lat1,lon2,lat2)
        lon_psi, lat_psi, bck_az = g.fwd(lon1,lat1,fwd_az,dist*2.)
        lons_psi[j+1,0] = lon_psi
        lats_psi[j+1,0] = lat_psi

        # Right External points
        #~~~~~~~~~~~~~~~~~~~~~~
        lon1 = lons_psi[j+1,-3] # right inside point
        lat1 = lats_psi[j+1,-3]
        lon2 = lons_psi[j+1,-2] # right outside point
        lat2 = lats_psi[j+1,-2]
        # Calc dist between points, find position at dist*2 from pos1
        fwd_az, bck_az, dist = g.inv(lon1,lat1,lon2,lat2)
        lon_psi, lat_psi, bck_az = g.fwd(lon1,lat1,fwd_az,dist*2.)
        lons_psi[j+1,-1] = lon_psi
        lats_psi[j+1,-1] = lat_psi

    for i in range(xdim):
        # Top external points
        #~~~~~~~~~~~~~~~~~~~~
        lon1 = lons_psi[2,i+1] # top inside point
        lat1 = lats_psi[2,i+1]
        lon2 = lons_psi[1,i+1] # top outside point
        lat2 = lats_psi[1,i+1]
        # Calc dist between points, find position at dist*2 from pos1
        fwd_az, bck_az, dist = g.inv(lon1,lat1,lon2,lat2)
        lon_psi, lat_psi, bck_az = g.fwd(lon1,lat1,fwd_az,dist*2.)
        lons_psi[0,i+1] = lon_psi
        lats_psi[0,i+1] = lat_psi

        # Bottom external points
        #~~~~~~~~~~~~~~~~~~~~~~~
        lon1 = lons_psi[-3,i+1] # bottom inside point
        lat1 = lats_psi[-3,i+1]
        lon2 = lons_psi[-2,i+1] # bottom outside point
        lat2 = lats_psi[-2,i+1]
        # Calc dist between points, find position at dist*2 from pos1
        fwd_az, bck_az, dist = g.inv(lon1,lat1,lon2,lat2)
        lon_psi, lat_psi, bck_az = g.fwd(lon1,lat1,fwd_az,dist*2.)
        lons_psi[-1,i+1] = lon_psi
        lats_psi[-1,i+1] = lat_psi

    # Calculate corners:
    #-------------------
    # top left corner
    #~~~~~~~~~~~~~~~~
    lon1 = lons_psi[2,2] # bottom right point
    lat1 = lats_psi[2,2]
    lon2 = lons_psi[1,1] # top left point
    lat2 = lats_psi[1,1]
    # Calc dist between points, find position at dist*2 from pos1
    fwd_az, bck_az, dist = g.inv(lon1,lat1,lon2,lat2)
    lon_psi, lat_psi, bck_az = g.fwd(lon1,lat1,fwd_az,dist*2.)
    lons_psi[0,0] = lon_psi
    lats_psi[0,0] = lat_psi
    # top right corner
    #~~~~~~~~~~~~~~~~~
    lon1 = lons_psi[2,-3] # bottom left point
    lat1 = lats_psi[2,-3]
    lon2 = lons_psi[1,-2] # top right point
    lat2 = lats_psi[1,-2]
    # Calc dist between points, find position at dist*2 from pos1
    fwd_az, bck_az, dist = g.inv(lon1,lat1,lon2,lat2)
    lon_psi, lat_psi, bck_az = g.fwd(lon1,lat1,fwd_az,dist*2.)
    lons_psi[0,-1] = lon_psi
    lats_psi[0,-1] = lat_psi
    # bottom left corner
    #~~~~~~~~~~~~~~~~~~~
    lon1 = lons_psi[-3,2] # top right point
    lat1 = lats_psi[-3,2]
    lon2 = lons_psi[-2,1] # bottom left point
    lat2 = lats_psi[-2,1]
    # Calc dist between points, find position at dist*2 from pos1
    fwd_az, bck_az, dist = g.inv(lon1,lat1,lon2,lat2)
    lon_psi, lat_psi, bck_az = g.fwd(lon1,lat1,fwd_az,dist*2.)
    lons_psi[-1,0] = lon_psi
    lats_psi[-1,0] = lat_psi
    # bottom right corner
    #~~~~~~~~~~~~~~~~~~~~
    lon1 = lons_psi[-3,-3] # top left point
    lat1 = lats_psi[-3,-3]
    lon2 = lons_psi[-2,-2] # bottom right point
    lat2 = lats_psi[-2,-2]
    # Calc dist between points, find position at dist*2 from pos1
    fwd_az, bck_az, dist = g.inv(lon1,lat1,lon2,lat2)
    lon_psi, lat_psi, bck_az = g.fwd(lon1,lat1,fwd_az,dist*2.)
    lons_psi[-1,-1] = lon_psi
    lats_psi[-1,-1] = lat_psi

    return lons_psi, lats_psi

示例图片(位于丹麦/瑞典南部附近)

输入图像描述


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接