Fast interpolation over 3D array

后端 未结 6 984
梦毁少年i
梦毁少年i 2020-12-13 22:03

I have a 3D array that I need to interpolate over one axis (the last dimension). Let\'s say y.shape = (nx, ny, nz), I want to interpolate in nz for

6条回答
  •  粉色の甜心
    2020-12-13 22:38

    As the numpy suggestion above was taking too long, I could wait so here's the cython version for future reference. From some loose benchmarks it is about 3000 times faster (granted, it is only linear interpolation and doesn't to as much as interp1d but it's ok for this purpose).

    import numpy as N
    cimport numpy as N
    cimport cython
    
    DTYPEf = N.float64
    ctypedef N.float64_t DTYPEf_t
    
    @cython.boundscheck(False) # turn of bounds-checking for entire function
    @cython.wraparound(False)  # turn of bounds-checking for entire function
    cpdef interp3d(N.ndarray[DTYPEf_t, ndim=1] x, N.ndarray[DTYPEf_t, ndim=3] y,
                   N.ndarray[DTYPEf_t, ndim=2] new_x):
        """
        interp3d(x, y, new_x)
    
        Performs linear interpolation over the last dimension of a 3D array,
        according to new values from a 2D array new_x. Thus, interpolate
        y[i, j, :] for new_x[i, j].
    
        Parameters
        ----------
        x : 1-D ndarray (double type)
            Array containg the x (abcissa) values. Must be monotonically
            increasing.
        y : 3-D ndarray (double type)
            Array containing the y values to interpolate.
        x_new: 2-D ndarray (double type)
            Array with new abcissas to interpolate.
    
        Returns
        -------
        new_y : 3-D ndarray
            Interpolated values.
        """
        cdef int nx = y.shape[0]
        cdef int ny = y.shape[1]
        cdef int nz = y.shape[2]
        cdef int i, j, k
        cdef N.ndarray[DTYPEf_t, ndim=2] new_y = N.zeros((nx, ny), dtype=DTYPEf)
    
        for i in range(nx):
            for j in range(ny):
                for k in range(1, nz):
                     if x[k] > new_x[i, j]:
                         new_y[i, j] = (y[i, j, k] - y[i, j, k - 1]) * \
                      (new_x[i, j] - x[k-1]) / (x[k] - x[k - 1]) + y[i, j, k - 1]
                         break
        return new_y
    

提交回复
热议问题