imagej/imagej-ops — pull request #76 by bnorthan (2014-10-19 18:49:34+00:00)
Title: Fftmethods wrapper

This is coming along so I am opening a pull request for review. This pull request adds the following features

1. A new version of FFTMethods that wraps JTransform.

https://github.com/imagej/imagej-ops/blob/fftmethods_wrapper/src/main/java/net/imagej/ops/fft/methods/FFTMethodsJTransform.java

2. Interface for fft, ifft.

3. Interface for fftsize op. This returns the optimal fft size for either speed (fast) or memory (small). Optimal and/or supported sizes can differ between implementations.

4. Fft and Ifft ops that wrap FFTMethods

5. SmoothNumber utility that is used to get the fastest size for JTransform fft (Thanks to @dscho).

6. Several tests and benchmarks.

https://github.com/imagej/imagej-ops/blob/fftmethods_wrapper/src/test/java/net/imagej/ops/fft/testFFT.java

Below is example fft code from one of the tests

```java
// define the original dimensions
long[] originalDimensions = new long[] { i, 129, 129 };

long[] smallDimensions = new long[3];
long[] fastDimensions = new long[3];
long[] fftDimensions = new long[3];

// compute smallest dimensions possible given the original
// dimensions
// (since jtransform supports all sizes smallDimensions should be = to original size.
ops.run(FftSizeJTransform.class, originalDimensions, smallDimensions,
fftDimensions, true, false);

// compute the dimensions that will result in the fastest fft time
ops.run(FftSizeJTransform.class, originalDimensions, fastDimensions,
fftDimensions, true, true);

// create an input with a small sphere at the center
Img inSmall =
(Img) ops.run(CreateImgDefault.class,
new ArrayImgFactory(), new FloatType(), smallDimensions);
placeSphereInCenter(inSmall);

// create the same input using the fast size
Img inFast =
(Img) ops.run(CreateImgDefault.class,
new ArrayImgFactory(), new FloatType(), fastDimensions);
placeSphereInCenter(inFast);

// call fft passing true for "fast" (in order to pass the optional
// parameter we have to pass null for the
// output parameter). The fft op will pad the input to the fast
// size.
Img fft1 =
(Img) ops.run("fft", null, inSmall, true);

// call fft using the img that was created with the fast size (no
// need to pass the optional parameter so the call is simplified)
Img fft2 =
(Img) ops.run("fft", inFast);

// assert that the two ffts are equal
assertComplexImagesEqual(fft1, fft1, 0f);

// create an inverse image using the small size
Img inverseSmall =
(Img) ops
.run(CreateImgDefault.class, new ArrayImgFactory(),
new FloatType(), originalDimensions);

// create an inverse image using the fast size
Img inverseFast =
(Img) ops.run(CreateImgDefault.class,
new ArrayImgFactory(), new FloatType(), fastDimensions);

// Perform inverse using fast dimensions. The output needs to be an
// image with dimensions = to the real fast size. We do not not need
// to pass in the padded
// dimensions in this case because no padding was done with the
// forward fft
ops.run("ifft", inverseFast, fft2);

// Perform the inverse using the small dimensions. The output needs
// to be an image with dimensions = to the original (small) size.
// We also need to pass in the padded
// dimensions so that inverse fft can be unpacked properly.
ops.run("ifft", inverseSmall, fft1, fastDimensions);

// assert that the inverse images are equal to the original
assertImagesEqual(inverseSmall, inSmall, .001f);
assertImagesEqual(inverseFast, inFast, 0.001f);
```