astropy/astropy — pull request #1255 by adonath (2013-07-12 22:30:50+00:00)
Title: NDData convolve kernel class

Here is the prototype for a new kernel class for convolutions. It includes also the changes from #1251, because it requires a few newly created models. The new files are "core.py", "utils.py" and "kernels.py" in NDData/convolution.

The idea for the kernel class was as following:
Instead of coding every formula again, every kernel type holds a ParametricModel which defines the kernels response function. To create the filter mask the model is than evaluated on a grid. I think this way it is much more easier to work with WCS transforms in future (e.g. you may want to smooth images with a 0.1° Gaussian etc.).

The kernel class istself doesn't have much functionality, but has some, in my opinion, important attributes to describe the kernel and speed up performance:

One attribute is "separable". There are a few kernels (especially Gaussian and Box) which are seperable. This means that you can write higher dimensional filter masks as outer product of one dimensional masks.
E.g. if you have a 2D image it can be first convolved with [1, 1, 1, 1, 1] and afterwards with
transposed([1, 1, 1, 1, 1]). the result wil be the same as taking a 5x5 filter mask. But using the seperated filter mask is much more faster, because you have much less arithmetic operations.

For the same reason there is a "weighted" attribute, which indicates if the filter mask is weighted. If not
the multiplication in the convolution operation could be omitted. Which should also be significantly faster.

Working with "separable" and "weighted" kernels is not yet supported by the convolve function. So far you can just pass the kernel.mask to the convolve function and it works as usual.

The size of the kernel is always odd. Is there any reason why one should work with a kernel of even size?
(The result would be on an intemediate grid.)

As convolution is linear I plan to implement some simple arithmethics for kernels, that you can add and subtract
two kernels (e.g. if you want a difference of Gaussian filter) or convolve two kernels with eachother (Instead of
filtering an image first with a Box and afterwards with a Gaussian, you would rather convolve the Gaussian and the Box and than convolve the result with the image).

I'd be happy for any kind of feedback and further ideas! Thanks