I’m having issues with a complete failure of DiscreteGaussianImageFilter as implemented in SmoothImage in ANTs as well as its internal use in the antsRegistration pipeline.
For some combinations of large resolution/large sigma, the filter produces no output (including no warnings, as what happens if the gaussian approximation is truncated to a limited with). In SmoothImage this is reasonably easy to catch, as you get an empty file, but in the case of inside antsRegistration, it completely derails the registration.
The error message noted in the bug report may identify the issue:
GaussianOperator (0x7ffc6d0f4a00): Kernel size has exceeded the specified maximum width of 32 and has been truncated to 33 elements. You can raise the maximum width using the SetMaximumKernelWidth method.
i.e. SmoothImage may need to call SetMaximumKernelWidth.
But, for smoothing with large Gaussian, consider using these filters instead for efficiency:
The next step to improve itk::DiscreteGaussianImageFilter are to create a minimal pipeline that reproduces the behavior in a single .cxx with a file reader itk::DiscreteGaussianImageFilter, and a file writer, the corresponding CMakeLists.txt, and the data that causes the issue.
However, again, for the purpose of smoothing large images with large sigma, use itk::SmoothingRecursiveYvvGaussianImageFilter.
Success (warning is expected, since I have truncated the gaussian too small)
./DiscreteGaussianImageFilter mni_icbm152_nlin_sym_09b/mni_
icbm152_t1_tal_nlin_sym_09b_hires.nii smooth.nii.gz 177 32
WARNING: In /storage/software/ANTs-build/ITKv5/Modules/Core/Common/include/itkGaussianOperator.hxx, line 61
GaussianOperator (0x7ffeb651b990): Kernel size has exceeded the specified maximum width of 32 and has been truncated to 33 elements. You can raise the maximum width using the SetMaximumKernelWidth method.
WARNING: In /storage/software/ANTs-build/ITKv5/Modules/Core/Common/include/itkGaussianOperator.hxx, line 61
GaussianOperator (0x7ffeb651b990): Kernel size has exceeded the specified maximum width of 32 and has been truncated to 33 elements. You can raise the maximum width using the SetMaximumKernelWidth method.
WARNING: In /storage/software/ANTs-build/ITKv5/Modules/Core/Common/include/itkGaussianOperator.hxx, line 61
GaussianOperator (0x7ffeb651b990): Kernel size has exceeded the specified maximum width of 32 and has been truncated to 33 elements. You can raise the maximum width using the SetMaximumKernelWidth method.
WARNING: In /storage/software/ANTs-build/ITKv5/Modules/Core/Common/include/itkGaussianOperator.hxx, line 61
GaussianOperator (0x561256913710): Kernel size has exceeded the specified maximum width of 32 and has been truncated to 33 elements. You can raise the maximum width using the SetMaximumKernelWidth method.
WARNING: In /storage/software/ANTs-build/ITKv5/Modules/Core/Common/include/itkGaussianOperator.hxx, line 61
GaussianOperator (0x561256913678): Kernel size has exceeded the specified maximum width of 32 and has been truncated to 33 elements. You can raise the maximum width using the SetMaximumKernelWidth method.
WARNING: In /storage/software/ANTs-build/ITKv5/Modules/Core/Common/include/itkGaussianOperator.hxx, line 61
GaussianOperator (0x5612569135e0): Kernel size has exceeded the specified maximum width of 32 and has been truncated to 33 elements. You can raise the maximum width using the SetMaximumKernelWidth method.
The ModifiedBesselI0 etc functions produce very large values for large variance. After their return they’re multiplied by exp(-m_variance) which then scales the values right now. Unfortunately, there’s a tipping point where we get an overflow.
It looks like given the current implementation of the bessel function, we could roll the exp(-m_variance) into the accumulator line and cancel out the overflow. Of course, the function proper wouldn’t be a modified bessel, but rather the “coeffcient generator”
Nice research, I would suggest submitting a patch with the implementation you find more reasonable (boost looks good?), and check that the tests are passing. The ModifiedBessell functions are local to that class, so it shouldn’t interfere with any other existing code. And if it does, is probably for good.
We have duplicate implementations in the GaussianOperator and the GaussianDerivativeOperator. This is a method I would expect to come from a numeric library. The VNL library we currently use seems to not have the required bessel methods.
I would suggest declaring the method in the itk::Math namespace and header.
itk::SmoothingRecursiveYvvGaussianImageFilter is broken with the new threading updates:
terminate called after throwing an instance of 'itk::ExceptionObject'
what(): /storage/software/ANTs-build/ITKv5/Modules/Core/Common/include/itkImageSource.hxx:280:
itk::ERROR: RecursiveLineYvvGaussianImageFilter(0x5622a8b96620): Subclass should override this method!!! If old behavior is desired invoke this->DynamicMultiThreadingOff(); before Update() is called. The best place is in class constructor.
Aborted (core dumped)
Not all remote modules have been updated to new threading model. We planned to the transition to be incremental, as the need arises. As you now ask I will take a look at that module.