Re: How to pass an array from a plugin to a macro?

Posted by Emmanuel Levy on
URL: http://imagej.273.s1.nabble.com/How-to-pass-an-array-from-a-plugin-to-a-macro-tp5002492p5002502.html

Hi Johannes and Gabriel,

I agree that adding a built-in function is not the logical way.

I guess time has come to start JS or Java then.

Thanks again,

Emmanuel

On 1 Apr 2013, at 22:18, Johannes Schindelin <[hidden email]> wrote:

> Hi Emmanue,
>
> On Mon, 1 Apr 2013, Emmanuel Levy wrote:
>
>> On 1 Apr 2013, at 20:13, Johannes Schindelin <[hidden email]> wrote:
>>
>>> On Mon, 1 Apr 2013, Emmanuel Levy wrote:
>>>
>>>> I wrote a simple plugin that puts all pixel values of a selected ROI
>>>> into a 1D table. What I can't figure out is how to pass the resulting 1D
>>>> array to a macro calling the plugin? i.e., similarly to getStatistics,
>>>> which makes a histogram array available in the macro calling the
>>>> function for example.
>>>
>>> [...]
>>>
>>> In your case, the easiest may be a work-around: you *can* set the ROI
>>> thusly:
>>>
>>>   dummy = new float[myT.length];
>>>   image.setRoi(new PointRoi(myT, dummy, dummy.length));
>>
>> [...]
>>
>> I'm not sure I explained my question clearly, all I want is to pass an
>> array of values back to the macro language to process it, not set or
>> modify a ROI.
>
> I understood your question. And I pointed out that you can use the ROI to
> transport an array to the macro: after setting the ROI as I illustrated,
> getSelectionCoordinates(myT, dummy) will put the array values into the
> *macro* array called myT.
>
>> E.g., just like one has access to the value of "hist" after calling
>> getStatistics, id like to have access to myT.
>
> getStatistics is not really a macro function, it is a *built-in* function.
> There are a couple of such functions which allow passing variables by
> reference (even uninitialized ones), e.g. getStatistics and
> getSelectionCoordinates.
>
> Such functions illustrate exactly my point about making the core of the
> macro language brittle: its design does not include by-reference passing,
> just by-value passing. Now we have a mix, and no way to define
> by-reference passing outside the few pre-defined functions in the macro
> core.
>
> Having said that, there is actually a way to extend the macro language: by
> calling Functions.registerExtensions(). It is a little clumsy to use, but
> in theory, something like this should work:
>
> -- snip --
> import ij.macro.ExtensionDescriptor;
> import ij.macro.Functions;
> import ij.macro.MacroExtension;
>
> import ij.plugin.PlugIn;
>
> public class Macro_Test_Extension implements PlugIn, MacroExtension {
>    private float[] array = { 1, 2, 3 };
>
>    @Override
>    public void run(String arg) {
>        Functions.registerExtensions(this);
>    }
>
>    private ExtensionDescriptor[] descriptors = {
>        ExtensionDescriptor.newDescriptor("getArray", this,
>            ARG_OUTPUT | ARG_ARRAY)
>    };
>
>    @Override
>    public ExtensionDescriptor[] getExtensionFunctions() {
>        return descriptors;
>    }
>
>    @Override
>    public String handleExtension(String name, Object[] args) {
>        if (name.equals("getArray")) {
>            Double[] copy = new Double[array.length];
>            for (int i = 0; i < copy.length; i++) {
>                copy[i] = new Double(array[i]);
>            }
>            ((Double[][])args[0])[0] = copy;
>        }
>        return "";
>    }
> }
> -- snap --
>
> Alas, it does not. The problem is -- as I mentioned earlier -- that the
> macro language was not designed to handle such things and the extension
> mechanism was only bolted onto it. Therefore, array output variables are
> not supported.
>
> And as I pointed out, you probably get Wayne to add support for that, but
> the macro language will become more and more brittle that way, and your
> macro will not get faster.
>
> At some stage you will have to convert it to Javascript anyway, and the
> later you do it, the more work it will be.
>
> Ciao,
> Johannes

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html