Передискретизируйте сетку из центральных координат во внешние (т.е. угловые) координаты.

Существует ли доступный метод экстраполяции положений углов сетки (синие точки) из положений центра сетки (красные точки)?

Сетка, с которой я работаю, не прямоугольная, поэтому обычная билинейная интерполяция не кажется лучшим способом; хотя это просто так, что я использую свои данные для построения графика pyplot.pcolormesh(), так что, возможно, это не имеет большого значения.

введите здесь описание изображения

Пример данных сетки:

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]])

person ryanjdillon    schedule 26.03.2014    source источник


Ответы (2)


Я не знаю какой-либо надежной техники matplotlib для выполнения того, что вы просите, но у меня может быть другое решение. Мне часто приходится заполнять/экстраполировать области сетки, где мне не хватает информации. Для этого я использую программу на Фортране, которую компилирую с помощью 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))

Программа решает уравнение Лапласа с граничными условиями Неймана (dA/dn = 0) в ПРЯМОУГОЛЬНЫХ координатах итеративным методом для заполнения разумных значений в узлах сетки, содержащих такие значения, как «undef». Это отлично работает для меня, и, возможно, вы найдете это полезным. Программа доступна в моей учетной записи github здесь.

person Trond Kristiansen    schedule 26.03.2014
comment
Я не знал о F2PY. Это, безусловно, может быть полезно и для некоторых других вещей. Это вывод моего модуля для модели NORWECOM.e2e, которую я рисую. Я буду ждать других входных данных, чтобы посмотреть, что там может быть. Спасибо! - person ryanjdillon; 26.03.2014
comment
F2PY великолепен, если вы хотите ускорить некоторые части своего кода, такие как вложенные циклы. На самом деле я сам работал над norwecom.e2e и знаю, что это может быть непросто. - person Trond Kristiansen; 26.03.2014

Это не очень элегантный подход, который я использовал, используя pyproj, чтобы сначала вычислить расстояние и азимут между точками (с pyproj.Geod.inv, а затем интерполировать/экстраполировать этот угол на необходимое расстояние (с pyproj.Geod.fwd) до положения в пси.

код:

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

Пример изображения (вокруг Дании/южной Швеции):

введите здесь описание изображения

person ryanjdillon    schedule 31.03.2014