I am currently trying to use ImageFunction::IsInsideBuffer from within a Python script. My environment runs Python 3.12.0 and ITK 5.4.3 installed directly from Pypi.
As can be seen from the documentation, ImageFunction::IsInsideBuffer can accept three kinds of input: a continuous index, an index or a point. However, only the “point version” seems to be callable from Python in my case.
My problems boils down to the following script:
import itk
import numpy as np
image = itk.GetImageFromArray(np.full((200, 200, 200), 1.))
interp = itk.LinearInterpolateImageFunction.New(image) # concrete subclass of ImageFunction
# From the doc, the three versions of IsInsideBuffer appear
print(interp.IsInsideBuffer.__doc__)
# The following line calls the "point version" of IsInsideBuffer and works correctly
print(interp.IsInsideBuffer([1, 2, 3]))
# The line below fails, as IsInsideBuffer excepts ints or longs
print(interp.IsInsideBuffer([1.5, 2.5, 3.5]))
# To force the function to be called with a continuous index instead, I manually create one
cindex = itk.ContinuousIndex[itk.D, 3]()
cindex[0] = 1.5
cindex[1] = 2.5
cindex[2] = 3.5
# …but IsInsideBuffer still fails
print(interp.IsInsideBuffer(cindex)) # error
# The same happens with points instead of continuous index
point = itk.Point[itk.D, 3]()
point[0] = 1.5
point[1] = 2.5
point[2] = 3.5
print(interp.IsInsideBuffer(point)) # error
The error is the following:
ValueError: Expecting a sequence of int (or long)
Is there a trick to call the proper version of IsInsideBuffer from Python? Or is it a bug in the way this function is wrapped? Sorry if this is a silly question, but I could not find a way to call the function as I need.
I was able to reproduce this with a recent master version:
C:\Users\Dzenan>"C:\Program Files\Python311\python.exe"
Python 3.11.0 (main, Oct 24 2022, 18:26:48) [MSC v.1933 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import itk
>>> import itk
>>> import numpy as np
>>>
>>> image = itk.GetImageFromArray(np.full((200, 200, 200), 1.))
>>> interp = itk.LinearInterpolateImageFunction.New(image) # concrete subclass of ImageFunction
>>>
>>> # From the doc, the three versions of IsInsideBuffer appear
>>> print(interp.IsInsideBuffer.__doc__)
IsInsideBuffer(self, index) -> bool
Parameters
----------
index: itkIndex3 const &
IsInsideBuffer(self, index) -> bool
Parameters
----------
index: itkContinuousIndexD3 const &
IsInsideBuffer(self, point) -> bool
Parameters
----------
point: itkPointD3 const &
>>>
>>> # The following line calls the "point version" of IsInsideBuffer and works correctly
>>> print(interp.IsInsideBuffer([1, 2, 3]))
True
>>>
>>> # The line below fails, as IsInsideBuffer excepts ints or longs
>>> print(interp.IsInsideBuffer([1.5, 2.5, 3.5]))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Dev\ITK-py11\Wrapping\Generators\Python\itk\itkImageFunctionBasePython.py", line 1259, in IsInsideBuffer
return _itkImageFunctionBasePython.itkImageFunctionID3DD_IsInsideBuffer(self, *args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: Expecting a sequence of int (or long)
>>>
>>> # To force the function to be called with a continuous index instead, I manually create one
>>> cindex = itk.ContinuousIndex[itk.D, 3]()
>>> cindex[0] = 1.5
>>> cindex[1] = 2.5
>>> cindex[2] = 3.5
>>> # …but IsInsideBuffer still fails
>>> print(interp.IsInsideBuffer(cindex)) # error
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Dev\ITK-py11\Wrapping\Generators\Python\itk\itkImageFunctionBasePython.py", line 1259, in IsInsideBuffer
return _itkImageFunctionBasePython.itkImageFunctionID3DD_IsInsideBuffer(self, *args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: Expecting a sequence of int (or long)
>>>
>>> # The same happens with points instead of continuous index
>>> point = itk.Point[itk.D, 3]()
>>> point[0] = 1.5
>>> point[1] = 2.5
>>> point[2] = 3.5
>>> print(interp.IsInsideBuffer(point)) # error
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Dev\ITK-py11\Wrapping\Generators\Python\itk\itkImageFunctionBasePython.py", line 1259, in IsInsideBuffer
return _itkImageFunctionBasePython.itkImageFunctionID3DD_IsInsideBuffer(self, *args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: Expecting a sequence of int (or long)
>>> itk.__version__
'6.0.0'
>>> itk.__file__
'C:\\Dev\\ITK-py11\\Wrapping\\Generators\\Python\\itk\\__init__.py'
>>>
I turned your code into a unit test via this (currently draft) PR: