Подтвердить что ты не робот

Интерполяция по нерегулярной сетке

Итак, у меня есть три массива numpy, которые хранят широту, долготу и некоторое значение свойства в сетке - то есть у меня есть LAT (y, x), LON (y, x) и, скажем, температура T ( y, x), для некоторых пределов x и y. Сетка не обязательно регулярна - на самом деле она триполярная.

Затем я хочу интерполировать эти значения свойств (температуры) на кучу разных точек lat/lon (сохраненных как lat1 (t), lon1 (t), около 10000 т...), которые не попадают на фактические точки сетки. Я пробовал matplotlib.mlab.griddata, но это занимает слишком много времени (в конце концов, это не совсем то, что я делаю). Я также пробовал scipy.interpolate.interp2d, но я получаю MemoryError (мои решетки около 400x400).

Есть ли какой-нибудь пятно, желательно быстрый способ сделать это? Я не могу не думать, что ответ - это нечто очевидное... Спасибо!

4b9b3361

Ответ 1

Попробуйте комбинацию взвешивания с обратным расстоянием и scipy.spatial.KDTree описанный в SO inverse-distance-weighted-idw-interpolation-with-python. Kd-деревья работать красиво в 2d 3d..., взвешивание с обратным расстоянием является гладким и локальным, и k = число ближайших соседей может быть изменено до скорости/точности компромисса.

Ответ 2

отличный пример обратного расстояния Роджером Вечаной и Ровирой вместе с некоторым кодом, использующим GDAL для записи в geotiff, если вы в это.

Это грубая регулярная сетка, но при условии, что вы сначала проецируете данные в сетку пикселей с помощью pyproj или что-то в этом роде, при этом тщательно проверяя, какая проекция используется для ваших данных.

Копия его алгоритма с тестом:

from math import pow  
from math import sqrt  
import numpy as np  
import matplotlib.pyplot as plt  

def pointValue(x,y,power,smoothing,xv,yv,values):  
    nominator=0  
    denominator=0  
    for i in range(0,len(values)):  
        dist = sqrt((x-xv[i])*(x-xv[i])+(y-yv[i])*(y-yv[i])+smoothing*smoothing);  
        #If the point is really close to one of the data points, return the data point value to avoid singularities  
        if(dist<0.0000000001):  
            return values[i]  
        nominator=nominator+(values[i]/pow(dist,power))  
        denominator=denominator+(1/pow(dist,power))  
    #Return NODATA if the denominator is zero  
    if denominator > 0:  
        value = nominator/denominator  
    else:  
        value = -9999  
    return value  

def invDist(xv,yv,values,xsize=100,ysize=100,power=2,smoothing=0):  
    valuesGrid = np.zeros((ysize,xsize))  
    for x in range(0,xsize):  
        for y in range(0,ysize):  
            valuesGrid[y][x] = pointValue(x,y,power,smoothing,xv,yv,values)  
    return valuesGrid  


if __name__ == "__main__":  
    power=1  
    smoothing=20  

    #Creating some data, with each coodinate and the values stored in separated lists  
    xv = [10,60,40,70,10,50,20,70,30,60]  
    yv = [10,20,30,30,40,50,60,70,80,90]  
    values = [1,2,2,3,4,6,7,7,8,10]  

    #Creating the output grid (100x100, in the example)  
    ti = np.linspace(0, 100, 100)  
    XI, YI = np.meshgrid(ti, ti)  

    #Creating the interpolation function and populating the output matrix value  
    ZI = invDist(xv,yv,values,100,100,power,smoothing)  


    # Plotting the result  
    n = plt.normalize(0.0, 100.0)  
    plt.subplot(1, 1, 1)  
    plt.pcolor(XI, YI, ZI)  
    plt.scatter(xv, yv, 100, values)  
    plt.title('Inv dist interpolation - power: ' + str(power) + ' smoothing: ' + str(smoothing))  
    plt.xlim(0, 100)  
    plt.ylim(0, 100)  
    plt.colorbar()  

    plt.show() 

Ответ 3

Здесь есть несколько вариантов, которые лучше всего будут зависеть от ваших данных... Однако я не знаю, какое из готовых решений для вас

Вы говорите, что ваши входные данные взяты из трехполярных данных. Существует три основных случая, по которым эти данные могут быть структурированы.

  • Отбирается из трехмерной сетки в трехполюсном пространстве, проецируется обратно на 2d LAT, данные LON.
  • Отбирается из 2d-сетки в трехполюсном пространстве, проецируется в 2d LAT-данные LON.
  • Неструктурированные данные в трехполюсном пространстве, проецируемые в 2d данные LAT LON

Самый простой из них - 2. Вместо интерполирования в пространстве LAT LON "просто" преобразует вашу точку обратно в исходное пространство и интерполирует там.

Другим вариантом, который работает для 1 и 2, является поиск ячеек, которые отображаются из трехполярного пространства, чтобы покрыть ваш образец. (Вы можете использовать структуру BSP или тип сетки, чтобы ускорить этот поиск). Выберите одну из ячеек и выполните интерполяцию внутри нее.

Наконец, есть куча вариантов неструктурированной интерполяции.. но они, как правило, медленные. Мой личный фаворит заключается в использовании линейной интерполяции ближайших N точек, нахождение тех N точек снова может быть выполнено с помощью грида или BSP. Другим хорошим вариантом является то, что Делоне триангулирует неструктурированные точки и интерполирует на полученную треугольную сетку.

Лично, если мой сет был случай 1, я бы использовал неструктурированную стратегию, так как я был бы обеспокоен необходимостью обрабатывать поиск через ячейки с перекрывающимися проекциями. Выбор "правильной" ячейки будет затруднен.

Ответ 4

Я предлагаю вам взглянуть на функции интерполяции GRASS (с открытым исходным кодом GIS) (http://grass.ibiblio.org/gdp/html_grass62/v.surf.bspline.html). Это не в python, но вы можете переопределить его или интерфейс с C-кодом.

Ответ 5

Я правильно понимаю, что ваши сетки данных выглядят примерно так (красный - это старые данные, синий - это новые интерполированные данные)?

alt text http://www.geekops.co.uk/photos/0000-00-02%20%28Forum%20images%29/DataSeparation.png

Это может быть немного грубый-силовой подход, но как насчет рендеринга ваших существующих данных в виде растрового изображения (opengl будет делать простую интерполяцию цветов для вас с нужными параметрами, и вы можете отображать данные как треугольники, которые должны быть довольно быстрым). Затем вы можете пробовать пиксели в местах расположения новых точек.

В качестве альтернативы вы можете сортировать свой первый набор точек пространственно, а затем находить самые близкие старые точки, окружающие вашу новую точку, и интерполировать на основе расстояний до этих точек.

Ответ 6

Существует библиотека FORTRAN, называемая BIVAR, что очень подходит для этой проблемы. С помощью нескольких модификаций вы можете использовать его в python с помощью f2py.

Из описания:

BIVAR - библиотека FORTRAN90, которая интерполирует разбросанные двумерные данные Хироши Акимой.

BIVAR принимает набор (X, Y) точек данных, разбросанных по 2D, с соответствующими значениями данных Z и способен построить гладкую интерполяционную функцию Z (X, Y), которая согласуется с данными, и может оцениваться в других точках плоскости.