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

WIP: ENH: Added type hints for wrapped Python classes and methods. #4

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

Conversation

kian-weimer
Copy link

@kian-weimer kian-weimer commented Sep 17, 2021

Logic was added to the igenerator.py file to produce type hints for wrapped ITK classes in Python.

Over half of the available ITK classes are currently supported by this feature, with more being worked on.

Two files are created, init.pyi and methods.pyi which contain the hint information needed for an IDE like Pycharm. Once built there should be no extra setup needed to get the hinting functionality.

The hints use have Template and Proxy names appended to them to differentiate them from the actual ITK classes. The hints are not perfect, they are merely suggestions for potentially correct input options. For example methods may only accept a double or character depending on the object type, but the hints will suggest both leaving it up to the user to determine which type is valid.

PR Checklist

  • No API changes were made (or the changes have been approved)
  • No major design changes were made (or the changes have been approved)
  • Added test (or behavior not changed)
  • Updated API documentation (or API not changed)
  • Added license to new files (if any)
  • Added Python wrapping to new files (if any) as described in ITK Software Guide Section 9.5
  • Added ITK examples for all new major features (if any)

Refer to the ITK Software Guide for
further development details if necessary.

Wrapped Python classes and methods, have introspection
enabled typehints to allow auto-completion in IDE's.

Logic was added to the igenerator.py file to produce stubs for
wrapped ITK classes in Python.

A large number of available ITK classes are currently supported by this
feature, with more being worked on.

The itk-stubs directory is created with a __init__.pyi file
that provides all the interface stubs to tools that
can utilize stub files. The included interface files provide
information needed for IDE's like Pycharm. Once built there should be no
extra setup needed to get the hinting functionality.

The hints for type selection factories use Template and Proxy names
appended to them to differentiate them from the actual ITK classes. The
interfaces may provide hints for types that are not valid in some cases.
The interfaces suggest potentially correct input options.  For example
methods may only accept a double or character depending on the object
type, but the hints will suggest both leaving it up to the user to
determine which type is valid.

NOTE: Stub files must use relative imports for .pyi files in order to
expose the imported symbols.

Co-authored-by: Kian Weimer <[email protected]>
hjmjohnson pushed a commit that referenced this pull request Nov 11, 2024
Found with thread sanitizer (TSan) running the `itkANTSNeighborhoodCorrelationImageToImageRegistrationTest` unit test.

There was already a `m_ANTSAssociateOnceFlag` flag for use with `std::call_once`, so I just used that in this place too (it's already used elsewhere).

Partial backtrace from TSan:

```
WARNING: ThreadSanitizer: data race (pid=79176)
  Write of size 8 at 0x000108f02240 by thread T2:
    #0 void itk::ANTSNeighborhoodCorrelationImageToImageMetricv4GetValueAndDerivativeThreader<itk::ThreadedIndexedContainerPartitioner, itk::ImageToImageMetricv4<itk::Image<double, 2u>, itk::Image<double, 2u>, itk::Image<double, 2u>, double, itk::DefaultImageToImageMetricTraitsv4<itk::Image<double, 2u>, itk::Image<double, 2u>, itk::Image<double, 2u>, double>>, itk::ANTSNeighborhoodCorrelationImageToImageMetricv4<itk::Image<double, 2u>, itk::Image<double, 2u>, itk::Image<double, 2u>, double, itk::DefaultImageToImageMetricTraitsv4<itk::Image<double, 2u>, itk::Image<double, 2u>, itk::Image<double, 2u>, double>>>::ThreadedExecution_impl<itk::ThreadedIndexedContainerPartitioner>(itk::IdentityHelper<itk::ThreadedIndexedContainerPartitioner>, itk::Index<2u> const&, unsigned int) itkANTSNeighborhoodCorrelationImageToImageMetricv4GetValueAndDerivativeThreader.hxx:118 (ITKMetricsv4TestDriver:arm64+0x1004bfe50)
    #1 itk::ANTSNeighborhoodCorrelationImageToImageMetricv4GetValueAndDerivativeThreader<itk::ThreadedIndexedContainerPartitioner, itk::ImageToImageMetricv4<itk::Image<double, 2u>, itk::Image<double, 2u>, itk::Image<double, 2u>, double, itk::DefaultImageToImageMetricTraitsv4<itk::Image<double, 2u>, itk::Image<double, 2u>, itk::Image<double, 2u>, double>>, itk::ANTSNeighborhoodCorrelationImageToImageMetricv4<itk::Image<double, 2u>, itk::Image<double, 2u>, itk::Image<double, 2u>, double, itk::DefaultImageToImageMetricTraitsv4<itk::Image<double, 2u>, itk::Image<double, 2u>, itk::Image<double, 2u>, double>>>::ThreadedExecution(itk::Index<2u> const&, unsigned int) itkANTSNeighborhoodCorrelationImageToImageMetricv4GetValueAndDerivativeThreader.h:235 (ITKMetricsv4TestDriver:arm64+0x1004bf9c0)
    #2 itk::DomainThreader<itk::ThreadedIndexedContainerPartitioner, itk::ImageToImageMetricv4<itk::Image<double, 2u>, itk::Image<double, 2u>, itk::Image<double, 2u>, double, itk::DefaultImageToImageMetricTraitsv4<itk::Image<double, 2u>, itk::Image<double, 2u>, itk::Image<double, 2u>, double>>>::ThreaderCallback(void*) itkDomainThreader.hxx:123 (ITKMetricsv4TestDriver:arm64+0x100259b6c)
    #3 std::__1::future<std::__1::invoke_result<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>::type> itk::ThreadPool::AddWork<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>(void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&)::'lambda'()::operator()() const itkThreadPool.h:92 (ITKMetricsv4TestDriver:arm64+0x1007d3228)
    #4 decltype(std::declval<void* (*&)(void*)>()(std::declval<itk::PoolMultiThreader::ThreadPoolInfoStruct*>())) std::__1::__invoke[abi:v160006]<std::__1::future<std::__1::invoke_result<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>::type> itk::ThreadPool::AddWork<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>(void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&)::'lambda'()&>(void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&) invoke.h:394 (ITKMetricsv4TestDriver:arm64+0x1007d31a4)

  Previous write of size 8 at 0x000108f02240 by thread T14:
    #0 void itk::ANTSNeighborhoodCorrelationImageToImageMetricv4GetValueAndDerivativeThreader<itk::ThreadedIndexedContainerPartitioner, itk::ImageToImageMetricv4<itk::Image<double, 2u>, itk::Image<double, 2u>, itk::Image<double, 2u>, double, itk::DefaultImageToImageMetricTraitsv4<itk::Image<double, 2u>, itk::Image<double, 2u>, itk::Image<double, 2u>, double>>, itk::ANTSNeighborhoodCorrelationImageToImageMetricv4<itk::Image<double, 2u>, itk::Image<double, 2u>, itk::Image<double, 2u>, double, itk::DefaultImageToImageMetricTraitsv4<itk::Image<double, 2u>, itk::Image<double, 2u>, itk::Image<double, 2u>, double>>>::ThreadedExecution_impl<itk::ThreadedIndexedContainerPartitioner>(itk::IdentityHelper<itk::ThreadedIndexedContainerPartitioner>, itk::Index<2u> const&, unsigned int) itkANTSNeighborhoodCorrelationImageToImageMetricv4GetValueAndDerivativeThreader.hxx:118 (ITKMetricsv4TestDriver:arm64+0x1004bfe50)
    #1 itk::ANTSNeighborhoodCorrelationImageToImageMetricv4GetValueAndDerivativeThreader<itk::ThreadedIndexedContainerPartitioner, itk::ImageToImageMetricv4<itk::Image<double, 2u>, itk::Image<double, 2u>, itk::Image<double, 2u>, double, itk::DefaultImageToImageMetricTraitsv4<itk::Image<double, 2u>, itk::Image<double, 2u>, itk::Image<double, 2u>, double>>, itk::ANTSNeighborhoodCorrelationImageToImageMetricv4<itk::Image<double, 2u>, itk::Image<double, 2u>, itk::Image<double, 2u>, double, itk::DefaultImageToImageMetricTraitsv4<itk::Image<double, 2u>, itk::Image<double, 2u>, itk::Image<double, 2u>, double>>>::ThreadedExecution(itk::Index<2u> const&, unsigned int) itkANTSNeighborhoodCorrelationImageToImageMetricv4GetValueAndDerivativeThreader.h:235 (ITKMetricsv4TestDriver:arm64+0x1004bf9c0)
    #2 itk::DomainThreader<itk::ThreadedIndexedContainerPartitioner, itk::ImageToImageMetricv4<itk::Image<double, 2u>, itk::Image<double, 2u>, itk::Image<double, 2u>, double, itk::DefaultImageToImageMetricTraitsv4<itk::Image<double, 2u>, itk::Image<double, 2u>, itk::Image<double, 2u>, double>>>::ThreaderCallback(void*) itkDomainThreader.hxx:123 (ITKMetricsv4TestDriver:arm64+0x100259b6c)
    #3 std::__1::future<std::__1::invoke_result<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>::type> itk::ThreadPool::AddWork<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>(void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&)::'lambda'()::operator()() const itkThreadPool.h:92 (ITKMetricsv4TestDriver:arm64+0x1007d3228)
    #4 decltype(std::declval<void* (*&)(void*)>()(std::declval<itk::PoolMultiThreader::ThreadPoolInfoStruct*>())) std::__1::__invoke[abi:v160006]<std::__1::future<std::__1::invoke_result<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>::type> itk::ThreadPool::AddWork<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>(void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&)::'lambda'()&>(void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&) invoke.h:394 (ITKMetricsv4TestDriver:arm64+0x1007d31a4)
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant