Error of porting "Using ImageJ Ops" example to Beaker notebook [SOLVED]

I’m porting the “Using ImageJ Ops” example in imagej-tutorials to Beaker notebook using the Groovy language:

long[] dims = [150, 100]
IterableInterval<DoubleType> blank = ij.op().create().img(dims)

ij.log().info("-------- Fill in an image with a formula --------")
formula = "10 * (Math.cos(0.3*p[0]) + Math.sin(0.3*p[1]))"
IterableInterval<DoubleType> sinusoid = ij.op().image().equation(blank, formula)

ij.log().info("-------- Add a constant value to an image --------")
ij.op().math().add(sinusoid, 13.0)

ij.log().info("-------- Generate gradient image using a formula --------")
IterableInterval<DoubleType> gBlank = ij.op().create().img(dims)
IterableInterval<DoubleType> gradient = ij.op().image().equation(gBlank, "p[0]+p[1]")

ij.log().info("-------- Add two images --------")
composite = ij.op().math().add(sinusoid, gradient)

However, there is an error:

[INFO] -------- Add two images --------
+groovy.lang.GroovyRuntimeException: Ambiguous method overloading for method net.imagej.ops.math.MathNamespace#add.
Cannot resolve which method to invoke for [class net.imglib2.img.array.ArrayImg, class net.imglib2.img.array.ArrayImg] due to overlapping prototypes between:
[interface net.imglib2.IterableInterval, interface net.imglib2.IterableInterval]
[interface net.imglib2.IterableInterval, interface net.imglib2.RandomAccessibleInterval]

The create op creates image as Img, which can be converted to IterableInterval or RandomAccessibleInterval. So I think this is why the Groovy runtime can’t resolve which method should be invoked.

But I have explicitly converted the Img to the IterableInterval in the Groovy code above, so I’m a bit confused.

How can solve this issue?
Thanks!

2 Likes

I think this is something @ctrueden will be able to help you with. However, he is currently not available, but as soon as he’s back, I’m sure he can help you.

1 Like

I solved this problem by adding the “as” keyword:

composite = ij.op().math().add(sinusoid as IterableInterval, gradient as IterableInterval)

2 Likes

@dietzc I asked @panovr to post here because it seemed like a general programming issue which does not require my help specifically. I was hoping others could help him in my absence. And of course, even if I do end up being the person who answers, it is good to have the public record here.

@panovr I’m very glad to hear you figured it out.

Yes, that is exactly the problem. There are clashes of built-in type signatures. Python also has similar problems with overloaded methods. You have to specify the type explicitly so that the script interpreter knows which method you mean. I do not know any easy way around this, other than to reduce the number of type-safe methods. @dietzc This is a downside of the “lowest common interface” approach to typing we have chosen. If we typed everything on e.g. RichImage and then relied on converters to “enrich” lower-level types, we would not have this problem. But of course that has its own downsides.

1 Like