ImageJ convolve Op runs as Function but not as Computer

Hey all,

I am wondering why the ImageJ convolve Op runs as a Function:

int[] size = new int[] { 128, 128, 128 };

Img<DoubleType> phantom = ops.create().img(size);

RandomAccessibleInterval<DoubleType> psf = ops.create().kernelGauss(
	new double[] { 5, 5, 5 }, new DoubleType());

Img<DoubleType> convolved = (Img<DoubleType>) ops.filter().convolve(phantom, psf);

… but not as a Computer:

ImageJ ij = new ImageJ();
int[] size = new int[] { 128, 128, 128 };
Img<DoubleType> phantom = ops.create().img(size);
Img<DoubleType> convolved = ops.create().img(size);
RandomAccessibleInterval<DoubleType> psf = ops.create().kernelGauss(
	new double[] { 5, 5, 5 }, new DoubleType());

ops.filter().convolve(convolved, phantom, psf);

This is the error message:

java.lang.IllegalArgumentException: No matching 'net.imagej.ops.math.IIToIIOutputII$Multiply/net.imagej.ops.special.hybrid.BinaryHybridCF' op

Request:
-	net.imagej.ops.math.IIToIIOutputII$Multiply/net.imagej.ops.special.hybrid.BinaryHybridCF(
		null,
		null,
		null)

Candidates:
1. 	(IterableInterval out?) =
	net.imagej.ops.math.IIToIIOutputII$Multiply(
		IterableInterval out?,
==>		IterableInterval in1,
		IterableInterval in2)
	Missing required argument


	at net.imagej.ops.DefaultOpMatchingService.singleMatch(DefaultOpMatchingService.java:432)
	at net.imagej.ops.DefaultOpMatchingService.findMatch(DefaultOpMatchingService.java:97)
	at net.imagej.ops.OpEnvironment.op(OpEnvironment.java:239)
	at net.imagej.ops.OpEnvironment.op(OpEnvironment.java:221)
	at net.imagej.ops.special.SpecialOp.op(SpecialOp.java:308)
	at net.imagej.ops.special.hybrid.Hybrids.binaryCF(Hybrids.java:425)
	at net.imagej.ops.filter.convolve.ConvolveFFTC.initialize(ConvolveFFTC.java:72)
	at net.imagej.ops.DefaultOpMatchingService.singleMatch(DefaultOpMatchingService.java:425)
	at net.imagej.ops.DefaultOpMatchingService.findMatch(DefaultOpMatchingService.java:97)
	at net.imagej.ops.DefaultOpMatchingService.findMatch(DefaultOpMatchingService.java:83)
	at net.imagej.ops.OpEnvironment.module(OpEnvironment.java:269)
	at net.imagej.ops.OpEnvironment.run(OpEnvironment.java:157)
	at net.imagej.ops.filter.FilterNamespace.convolve(FilterNamespace.java:301)
	at net.imagej.ops.filter.convolve.ConvolveTest.testCreateAndConvolvePoints(ConvolveTest.java:251)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)


Process finished with exit code 255

What am I doing wrong? Thanks for any hints,
Deborah

Hi @frauzufall

You are not doing anything wrong. This is a bug/design issue. The issue is occurring in ConvolveFFTC line 72 because it is trying to match an Op for FFT multiplication however the FFT memory isn’t defined yet.

That part is easy to fix. However once I fix that then I get an issue where the imglib2 FFT throws a message ‘Input dimensions not supported by FFT’. This is because imglib2 FFTs only support certain sizes.

All the logic to pad the image to a supported FFT size is in AbstractFFTFunctionF, and that is why the function version of convolve works.

One solution is to make AbstractFFTFunctionF a HybridCF instead of a function… then we have a Function/Computer with all the logic in it to pad to the right size, and unpad.

The only reason this isn’t trivial is because it seems to mangle the namespace a bit. For example say you wanted to convolve with optional parameters, boundarysize and boundaryfactory, right now it’s

convolve(in, kernel, boundarysize, boundaryfactory)

If I make AbstractFFTFunctionF a hybrid, it seems the above signature is no longer valid. And I need

convolve(null, in, kernel, boundarysize, boundaryfactory)

Basically the output becomes the first optional parameter, and you need it whenever using any optional parameters. So all the signatures change a bit.

So I’m still trying to figure out a way to easily make Computers versions of the Functions but keep the current signatures the same . I’m open to other suggestion you or others might have.

3 Likes