-
-
Notifications
You must be signed in to change notification settings - Fork 664
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
base: master
Are you sure you want to change the base?
ENH: Add "itkPointSetTest.py" unittest, testing SetPointsByCoordinates
#4860
Conversation
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)`
/azp.run ITK.macOS.Arm64 |
/azp run ITK.macOS.Arm64 |
/azp run ITK.macOS.Python |
/azp run ITK.macOS |
@dzenanz FYI "ITK.macOS.Arm64"does not listen to I just pressed "Re-run jobs" for this GitHub Action, at https://github.com/InsightSoftwareConsortium/ITK/actions/runs/11019940074/job/30603577840?pr=4860 |
Just checked, the test has actually run, and passed successfully: https://open.cdash.org/tests/1733705147
Command Line:
👍 My very first ITK Python unittest 😇 |
Instead of Unsigned Char, can we instead use float ? |
We should also replace all the older tests using SetPoints with the new method to ensure everything else is working. |
# The pixel type is irrelevant for this test, just use unsigned char. | ||
PixelType = itk.UC |
There was a problem hiding this comment.
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.)
There was a problem hiding this comment.
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
@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.) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this 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.
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]) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 😃
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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. 🤷
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
|
Specifically tested
SetPointsByCoordinates
with a NumPy array as input argument, as was suggested by @PranjalSahu.SetPointsByCoordinates
to PointSet, add warning toSetPoints(PointsVectorContainer *)
#4850 commit f43b1b8ENH: Add
PointSet::SetPointsByCoordinates(coordinates)