Improper wrapping of ImageFunction::IsInsideBuffer?

Dear ITK community,

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.

Thank you very much!

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:

@matt.mccormick Can you figure out what is going on here?

@dzenanz go for it.

I meant, I took a look and nothing stood out to me. Can you take a look too?

Nothing stands out to me.