Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH: Add "itkPointSetTest.py" unittest, testing SetPointsByCoordinates #4860

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

N-Dekker
Copy link
Contributor

Specifically tested SetPointsByCoordinates with a NumPy array as input argument, as was suggested by @PranjalSahu.

Specifically tested `SetPointsByCoordinates` with a NumPy array as input
argument, as was suggested by Pranjal Sahu.

- Follow-up to pull request InsightSoftwareConsortium#4850
commit f43b1b8
ENH: Add `PointSet::SetPointsByCoordinates(coordinates)`
@github-actions github-actions bot added type:Infrastructure Infrastructure/ecosystem related changes, such as CMake or buildbots type:Enhancement Improvement of existing methods or implementation area:Python wrapping Python bindings for a class type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct area:Core Issues affecting the Core module labels Sep 24, 2024
@dzenanz
Copy link
Member

dzenanz commented Sep 24, 2024

/azp.run ITK.macOS.Arm64

@dzenanz
Copy link
Member

dzenanz commented Sep 24, 2024

/azp run ITK.macOS.Arm64

@dzenanz
Copy link
Member

dzenanz commented Sep 24, 2024

/azp run ITK.macOS.Python

@dzenanz
Copy link
Member

dzenanz commented Sep 24, 2024

/azp run ITK.macOS

@N-Dekker
Copy link
Contributor Author

N-Dekker commented Sep 25, 2024

/azp run ITK.macOS.Arm64

@dzenanz FYI "ITK.macOS.Arm64"does not listen to /azp run, because it's not using Azure Pipelines!

I just pressed "Re-run jobs" for this GitHub Action, at https://github.com/InsightSoftwareConsortium/ITK/actions/runs/11019940074/job/30603577840?pr=4860

@N-Dekker N-Dekker marked this pull request as ready for review September 25, 2024 12:15
@N-Dekker
Copy link
Contributor Author

N-Dekker commented Sep 25, 2024

Just checked, the test has actually run, and passed successfully: https://open.cdash.org/tests/1733705147

Test: itkPointSetTest (Passed)

Command Line:

/home/vsts/work/1/s-build/Wrapping/Generators/Python/itk/itkTestDriver "--add-before-env" "PYTHONPATH" "/home/vsts/work/1/s-build/Wrapping/Generators/Python" "--add-before-env" "PYTHONPATH" "/home/vsts/work/1/s-build/Wrapping/Generators/Python/itk" "--add-before-libpath" "/home/vsts/work/1/s-build/Wrapping/Generators/Python/itk" "/opt/hostedtoolcache/Python/3.9.20/x64/bin/python3" "/home/vsts/work/1/s/Modules/Core/Common/wrapping/test/itkPointSetTest.py"

👍

My very first ITK Python unittest 😇

@PranjalSahu
Copy link
Contributor

PranjalSahu commented Sep 25, 2024

Instead of Unsigned Char, can we instead use float ?
Because that will be the most used datatype.

@PranjalSahu
Copy link
Contributor

We should also replace all the older tests using SetPoints with the new method to ensure everything else is working.

Comment on lines +29 to +30
# The pixel type is irrelevant for this test, just use unsigned char.
PixelType = itk.UC
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of Unsigned Char, can we instead use float ? Because that will be the most used datatype.

@PranjalSahu Thanks for the suggestion, but isn't UC a common pixel type as well? We could extend the test to try any possible pixel type, but it's irrelevant to the functionality of SetPointsByCoordinates anyway. SetPointsByCoordinates is just about the points of a PointSet. It's not about the pixels.

Note that this is not about the coordinate type. The coordinate type is defined by the "MeshTraits" of a PointSet type. (By default, it is 32-bit float, independent of the pixel type.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the record, by default, itk.PointSet supports double, float, short, unsigned char, unsigned int, itk::Array, itk::Matrix, itk::Point, and itk::Vector as pixel type, according to itk.PointSet.GetTypes():

>>> print(itk.PointSet.GetTypes())
<itkTemplate itk::PointSet>
Options:
  [<itkCType double>, 2]
  [<itkCType double>, 3]
  [<itkCType float>, 2]
  [<itkCType float>, 3]
  [<itkCType signed short>, 2]
  [<itkCType signed short>, 3]
  [<itkCType unsigned char>, 2]
  [<itkCType unsigned char>, 3]
  [<itkCType unsigned int>, 2, <class 'itk.itkDefaultStaticMeshTraitsPython.itkDefaultStaticMeshTraitsUI22FFUI'>]
  [<itkCType unsigned int>, 3, <class 'itk.itkDefaultStaticMeshTraitsPython.itkDefaultStaticMeshTraitsUI33FFUI'>]
  [<class 'itk.itkArrayPython.itkArrayD'>, 2]
  [<class 'itk.itkArrayPython.itkArrayD'>, 3]
  [<class 'itk.itkMatrixPython.itkMatrixD22'>, 2]
  [<class 'itk.itkMatrixPython.itkMatrixD33'>, 3]
  [<class 'itk.itkPointPython.itkPointD2'>, 2, <class 'itk.itkDefaultStaticMeshTraitsPython.itkDefaultStaticMeshTraitsD22DDD'>]
  [<class 'itk.itkPointPython.itkPointD3'>, 3, <class 'itk.itkDefaultStaticMeshTraitsPython.itkDefaultStaticMeshTraitsD33DDD'>]
  [<class 'itk.itkVectorPython.itkVectorF3'>, 3]
None

@N-Dekker
Copy link
Contributor Author

We should also replace all the older tests using SetPoints with the new method to ensure everything else is working.

@PranjalSahu Please feel free to make another pull request to do so. (Otherwise I can also give it a try, once this pull request is merged.)

Copy link
Contributor

@PranjalSahu PranjalSahu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Member

@thewtex thewtex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@N-Dekker thanks!

Request inline.

Comment on lines +45 to +48
for i in range(number_of_points):
point = points.GetElement(i)
for j in range(dimension):
self.assertAlmostEqual(point[j], np_array[i * dimension + j])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is better to use numpy assert_allclose, which is must faster and has a shape check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion @thewtex Can you possibly type out exactly how you want it to be?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@thewtex Also, do you think the test should be faster than it is right now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@thewtex Can you please show us exactly how you want to adjust this test, by using numpy assert_allclose? Otherwise can you please reconsider your change request? I would very much like this PR to be merged 😃

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe np.assert_allclose(points, np_array.T)? Does that compile and work?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @thewtex, but sorry, that does not work for me either. See below. Did you locally try this particular unit test with your suggested adjustment?

No

Would it be acceptable to you to just merge the pull request as it is right now, and then afterwards possibly make a new PR to further optimize the test, for example by using numpy.testing.assert_allclose?

No, this is an important performance and usage fix, and it is also important to verify that the proposed change is correct in terms of shape.

I will investigate locally.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is also important to verify that the proposed change is correct in terms of shape.

@thewtex Regarding the shape, please note that it is important that the argument of SetPointsByCoordinates is a "flat" (1-D) array of coordinate values, when doing

point_set.SetPointsByCoordinates(np_array)

The SetPointsByCoordinates member function is meant to be an alternative to the existing unsafe SetPoints overload (issue #4848), which also expects a "flat" array of coordinate values as argument.

So the PointSet and the array of coordinates (np_array) have different shapes, but that is intentionally. So I'm sorry, I don't think numpy.testing.assert_allclose can be used for this unit test. 🤷

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might, with reshaping. Reshaping in numpy is easy.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry, but this is just a single unit test. It is not meant to be a tutorial on how to reshape a numpy array.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SetPointsByCoordinates member function is meant to be an alternative to the existing unsafe SetPoints overload (issue #4848), which also expects a "flat" array of coordinate values as argument.

So the PointSet and the array of coordinates (np_array) have different shapes, but that is intentionally.

The intension and/or the related support functions may need improvements :-). NumPy arrays representing points should not be flat -- they should have a dimension that corresponds to the spatial dimension.

@N-Dekker
Copy link
Contributor Author

N-Dekker commented Nov 5, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:Core Issues affecting the Core module area:Python wrapping Python bindings for a class type:Enhancement Improvement of existing methods or implementation type:Infrastructure Infrastructure/ecosystem related changes, such as CMake or buildbots type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants