MacroExtension Interface returning arrays?

Hi,

I was wondering if the MacroExtension Interface could support also arrays in addition to strings and numbers as a return type back to the macro language. See here for the documentation:

https://imagej.nih.gov/ij/macros/MacroExtensions.txt

I started to used the MacroExtension Interface to write some functions in Java, that would make life easier for me for in the world of ImageJ macro language. I am new to Java, but with a little help I was able to make a plugin (.jar) that was doing what is should, however my main goal would be to pass arrays to Java and get back assays in macro language.

Does anyone know if that could be implemented?

Many thanks!

Martin

1 Like

Hi @stoeter,

Do you have an example script of what you want to achieve ?

I have some experience on MacroExtension, but I’ve never used it with arrays. According to your link, I guess that you cannot output an array like this:

myArray = Ext.myFunc();

However this may work:

myArray = newArray(20);
Ext.myFunc(myArray);

You can modify myArray in the java code that handles myFunc. The modification will then be visible in the macro.

Be aware that MacroExtension is a way to increase the language possibilities of ImageJ1 scripting. But now you can overcome limitations of this language by scripting in other languages such as Jython and Groovy in Fiji.

I like groovy the most because it is pretty much the same as java (and has a syntax similar to ImageJ1 macros). Using Groovy, you don’t need MacroExtension anymore: you just need to import your package at the beginning of the script:
import myDomain.myPackage

And then you can use any objects and methods that are specific to your package.

Best

PS: Looking quickly, I cannot find a good resource to show Groovy examples in ImageJ. Maybe someone can help ?

1 Like

You can find some more information in chapter 12 of the macro language reference guide :

Here are also some linked examples:

https://imagej.nih.gov/ij/developer/macro/macros.html#ext

1 Like

Hi Nico,
many thanks for your reply.

myArray = newArray(20);
Ext.myFunc(myArray);

I have tried this already, but unfortunaltely this doesnt work, because the it seems that the Extensions can only give back numbers or strings, but not arrays. I was able to give arrays to the Java side like:

myArray = newArray(20);
myString = “test”;
Ext.myFunc(myString, myArray);

…however, the argument that receives back a variable from Java side needs to be numeric or string as mentioned in the description:

Only string and numeric output variables are supported, and are passed as arrays:
  d. string 'output' variables are passed as a 1-element String[] array
  e. numeric 'output' variables are passed as a 1-element Double[] array

On Java side the definition can be this:

ExtensionDescriptor.newDescriptor(“myCoolFunction”, this, ARG_OUTPUT + ARG_STRING, ARG_ARRAY)

However, definition as an array like this is not supported:

ExtensionDescriptor.newDescriptor(“myCoolFunction”, this, ARG_OUTPUT + ARG_ARRAY, ARG_ARRAY)

I will have a look into other scripting languages as you suggest and will try JPython or JavaScript…

Best,

Martin

Thanks Bio7,
I went through the referece guide already and there it is also mentioned that only numbers and strings are supported.
Best,
Martin

Hi,

Did you try ARG_ARRAY, without +ARG_OUTPUT, but nonetheless trying to modify the array ? Looking at this, https://github.com/imagej/imagej1/blob/master/ij/macro/ExtensionDescriptor.java, I would have thought it would work.

I’ll try it as well and let you know.

Best,

Nico

Ok, it doesn’t work. It looks like there are some piece of code to handle it:

But they are never reached in my tests because an exception is triggered in the interpreter before (it says '[' expected when setting ARG_OUTPUT+ARG_ARRAY)

No luck!

1 Like

Hi,

I read your other subject, so since you are still interested in this, I continued to search a bit more.

Finally, the fix to make output arrays looks surprisingly simple :

One just need to replace this part (https://github.com/imagej/imagej1/blob/b5a864369cbf1d37b71261974616b5fee5c8fe3b/ij/macro/ExtensionDescriptor.java#L158-L160) of code in the ExtensionDescriptor class:

if (output) {
    	v = func.getVariable();
}

By this one:

if (output) {
    	if (getRawType(argTypes[i])==MacroExtension.ARG_ARRAY) {
            v = func.getArrayVariable();
    	} else {
    	    v = func.getVariable();
    	}
}

The reason it is so simple is because, as I wrote before, there are some piece of code already there to handle output arrays.

It all looks like the non-implementation was a deliberate choice done afterwards… So I’m worried the reason why it is not implemented is because of some side-effects that I am not aware of (I tested only a very simple macro).

Best,
Nico

3 Likes

Maybe @Wayne could comment on this?

I am not an expert on the MacroExtension interface. It was contributed to the ImageJ project about 10 years ago by Shannon Stewman. As an alternative, consider using JavaScript, which is almost as fast as Java. Check out the Help>Examples>JavaScript>Plasma Cloud example.

2 Likes

Hi Nico,
thank you very much!
Unfortunately, this is a change of a core part of imageJ and goes beyond my level of programming. Maybe at some point it will be tested again and will find its way to an update later.
Meanwhile I think a workaround of sending arrays to Java and sending them back to IJ-macro language as a concatenated string followed by a splitting into an array will be the best solution for me. The split(); command doesnt cost any time, even for arrays 10k length.

I tried sending arrays forth and back using JavaScript, but I could not get this working either as I described in this other post.
Best,
Martin

2 Likes

Hi everyone,
I just came across this thread with a similar need, I want to provide an ImageJ macro equivalent of a java function returning a String array.
So the fix proposed by @NicoKiaru would need more testing but could potentially be merged into later ImageJ releases ?

I think I would go for the string concatenation and splitting as suggested by @stoeter for the moment.
But I am happy to hear if there is any change since