cythoncythonize

cython error unsupported operand type(s) for -: 'list' and 'int'


I have the following function in cython (run from Jupyter notebooks)

##
%%cython
cimport numpy as np
cimport cython
import numpy as np

@cython.boundscheck(False)  
@cython.wraparound(False)
def Variance_Filter_3D(float[:, :, :] image, kernel = 30):
    cdef double min_var = 10000
    cdef list min_var_coord = [0,0,0] 
    cdef Py_ssize_t[32] z,y,x = image.shape
    cdef np.ndarray[np.int32_t, ndim=3] window = np.zeros(shape=(kernel,kernel,kernel), dtype=np.int32)
    
    for i in np.arange(0,(x-kernel),1):
        for j in np.arange(0,(y-kernel),1):
            for k in np.arange(0,(z-kernel),1):
                window = image[k:k+kernel,j:j+kernel,i:i+kernel]
                var = np.var(window)
                if var < min_var:
                    min_var = var
                    min_var_coord = [k,j,i]
                print(min_var_coord)
    return min_var,min_var_coord

When I call the function, I get the following error:

Variance_Filter_3D(fet_arr)
>>
Input In [136], in <cell line: 1>()
----> 1 Variance_Filter_3D(fet_arr)

File _cython_magic_adb8c2575881fd3a5d05f7bfdf76a7fa.pyx:13, in _cython_magic_adb8c2575881fd3a5d05f7bfdf76a7fa.Variance_Filter_3D()

TypeError: unsupported operand type(s) for -: 'list' and 'int'

However, the only list I have is min_var_coord. The only operation I execute on it is reassigning it's values. I'm not sure how else to do this in cython?

Any help would be appreciated.


Solution

  • I think that

        cdef Py_ssize_t[32] z,y,x = image.shape
    

    might not be doing what you expect it to

    The following works for me:

    %%cython
    cimport numpy as np
    cimport cython
    import numpy as np
    
    @cython.boundscheck(False)  
    @cython.wraparound(False)
    def Variance_Filter_3D(double[:, :, :] image, kernel = 30):
        cdef double min_var = 10000
        cdef list min_var_coord = [0,0,0] 
        cdef Py_ssize_t z = image.shape[0]
        cdef Py_ssize_t y = image.shape[1]
        cdef Py_ssize_t x = image.shape[2]
        cdef np.ndarray[np.int32_t, ndim=3] window = np.zeros(shape=(kernel,kernel,kernel), dtype=np.int32)
        
        for i in np.arange(0,(x-kernel),1):
            for j in np.arange(0,(y-kernel),1):
                for k in np.arange(0,(z-kernel),1):
                    window[:] = image[k:k+kernel,j:j+kernel,i:i+kernel]
                    var = np.var(window)
                    if var < min_var:
                        min_var = var
                        min_var_coord = [k,j,i]
                    print(min_var_coord)
        return min_var,min_var_coord
    
    image = np.random.randn(100, 100, 100)
    Variance_Filter_3D(image)