Я пишу плагин для приложения, которое включает NumPy в двоичном дистрибутиве, но не SciPy. Мой плагин должен интерполировать данные из одной регулярной трехмерной сетки в другую обычную трехмерную сетку. Исходя из источника, это можно сделать очень эффективно с помощью scipy.ndimage
или, если у пользователя нет установленного SciPy, сгенерировано weave .pyd
. К сожалению, ни одна из этих опций недоступна, если пользователь запускает двоичный файл.
Я написал простую процедуру трилинейную интерполяцию в python, которая дает правильный результат, но для размеров массивов, которые я использую, принимает долгое время (~ 5 минут). Мне интересно, есть ли способ ускорить его, используя только функциональность в NumPy. Точно так же, как scipy.ndimage.map_coordinates
, он принимает трехмерный входной массив и массив с координатами x, y и z каждой интерполяции точки.
def trilinear_interp(input_array, indices):
"""Evaluate the input_array data at the indices given"""
output = np.empty(indices[0].shape)
x_indices = indices[0]
y_indices = indices[1]
z_indices = indices[2]
for i in np.ndindex(x_indices.shape):
x0 = np.floor(x_indices[i])
y0 = np.floor(y_indices[i])
z0 = np.floor(z_indices[i])
x1 = x0 + 1
y1 = y0 + 1
z1 = z0 + 1
#Check if xyz1 is beyond array boundary:
if x1 == input_array.shape[0]:
x1 = x0
if y1 == input_array.shape[1]:
y1 = y0
if z1 == input_array.shape[2]:
z1 = z0
x = x_indices[i] - x0
y = y_indices[i] - y0
z = z_indices[i] - z0
output[i] = (input_array[x0,y0,z0]*(1-x)*(1-y)*(1-z) +
input_array[x1,y0,z0]*x*(1-y)*(1-z) +
input_array[x0,y1,z0]*(1-x)*y*(1-z) +
input_array[x0,y0,z1]*(1-x)*(1-y)*z +
input_array[x1,y0,z1]*x*(1-y)*z +
input_array[x0,y1,z1]*(1-x)*y*z +
input_array[x1,y1,z0]*x*y*(1-z) +
input_array[x1,y1,z1]*x*y*z)
return output
Очевидно, причина, по которой функция настолько медленна, - это цикл for
для каждой точки в трехмерном пространстве. Есть ли способ выполнить какую-то магию для нарезки или векторизации, чтобы ускорить ее? Спасибо.