I stumbled across the cfunc Numba decorator this morning, with much excitement. But I'm having trouble using it with ndimage.generic_filter:
=============================================
In [3]: def mean(arr):
...: i = 0.
...: tot = 0.
...: for val in arr:
...: tot += val
...: i += 1.
...: return tot / i
...:
In [4]: cmean = cfunc("float64(float64[:])")(mean)
In [5]: from skimage import data
In [6]: coins = data.coins() / 255
In [8]: from scipy import ndimage as ndi
In [9]: fp = ndi.generate_binary_structure(2, 2)
In [14]: coins_mean = ndi.generic_filter(coins, cmean.ctypes, footprint=fp)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-14-ccdc82fc8ce6> in <module>()
----> 1 coins_mean = ndi.generic_filter(coins, cmean.ctypes, footprint=fp)
/Users/nuneziglesiasj/anaconda/envs/ana3/lib/python3.5/site-packages/numba/utils.py in __get__(self, instance, type)
276 if instance is None:
277 return self
--> 278 res = instance.__dict__[self.name] = self.func(instance) 279 return res
280
/Users/nuneziglesiasj/anaconda/envs/ana3/lib/python3.5/site-packages/numba/ccallback.py in ctypes(self)
156 A ctypes function object representing the C callback.
157 """
--> 158 ctypes_args = [to_ctypes(ty) for ty in self._sig.args]
159 ctypes_restype = to_ctypes(self._sig.return_type)
160 functype = ctypes.CFUNCTYPE(ctypes_restype, *ctypes_args)
/Users/nuneziglesiasj/anaconda/envs/ana3/lib/python3.5/site-packages/numba/ccallback.py in <listcomp>(.0)
156 A ctypes function object representing the C callback.
157 """
--> 158 ctypes_args = [to_ctypes(ty) for ty in self._sig.args]
159 ctypes_restype = to_ctypes(self._sig.return_type)
160 functype = ctypes.CFUNCTYPE(ctypes_restype, *ctypes_args)
/Users/nuneziglesiasj/anaconda/envs/ana3/lib/python3.5/site-packages/numba/typing/ctypes_utils.py in to_ctypes(ty)
80 if ctypeobj is None:
81 raise TypeError("Cannot convert Numba type '%s' to ctypes type"
---> 82 % (ty,))
83 return ctypeobj
84
TypeError: Cannot convert Numba type 'array(float64, 1d, A)' to ctypes type
=============================================
I also tried an alternate formulation, naively hoping that Numba would gladly convert between array buffers and (double*, size) pairs, with no luck:
=============================================
In [21]: signature = types.float64(types.CPointer(types.float64), types.intc)
In [23]: def mean(arr, size):
...: i = 0.
...: tot = 0.
...: arr = carray(arr, size)
...: for idx in range(size):
...: tot += arr[idx]
...: i += 1.
...: return tot / i
...:
...:
In [24]: cmean = cfunc(signature)(mean)
In [25]: coins_mean = ndi.generic_filter(coins, cmean.ctypes, footprint=fp)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-25-ccdc82fc8ce6> in <module>()
----> 1 coins_mean = ndi.generic_filter(coins, cmean.ctypes, footprint=fp)
/Users/nuneziglesiasj/anaconda/envs/ana3/lib/python3.5/site-packages/scipy/ndimage/filters.py in generic_filter(input, function, size, footprint, output, mode, cval, origin, extra_arguments, extra_keywords)
1243 mode = _ni_support._extend_mode_to_code(mode)
1244 _nd_image.generic_filter(input, function, footprint, output, mode,
-> 1245 cval, origins, extra_arguments, extra_keywords)
1246 return return_value
TypeError: this function takes at least 2 arguments (1 given)
In [26]: coins_mean = ndi.generic_filter(coins, cmean.ctypes, footprint=fp, extra_arguments=(np.sum(fp),))
---------------------------------------------------------------------------
ArgumentError Traceback (most recent call last)
<ipython-input-26-f40d45b26623> in <module>()
----> 1 coins_mean = ndi.generic_filter(coins, cmean.ctypes, footprint=fp, extra_arguments=(np.sum(fp),))
/Users/nuneziglesiasj/anaconda/envs/ana3/lib/python3.5/site-packages/scipy/ndimage/filters.py in generic_filter(input, function, size, footprint, output, mode, cval, origin, extra_arguments, extra_keywords)
1243 mode = _ni_support._extend_mode_to_code(mode)
1244 _nd_image.generic_filter(input, function, footprint, output, mode,
-> 1245 cval, origins, extra_arguments, extra_keywords)
1246 return return_value
ArgumentError: argument 1: <class 'TypeError'>: expected LP_c_double instance instead of numpy.ndarray
=============================================
The relevant doc pages are Numba's cfunc page:
And SciPy's C callable instructions for ndimage:
Unfortunately the above is how far my interpretation of those pages have taken me. Can anyone on this list help me with this? I'll be happy to contribute the solution back to the docs if it's considered useful!
Thanks,
Juan.