Login  Register

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

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options Options
Embed post
Permalink
Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

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

Emmanuel Levy
36 posts
Hello,

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.

Many thanks for your help,

All the best,

Emmanuel

~~~~~~~~~~~~~
Run function of the (very simple) plugin:

   In the end, the float array myT contains the pixel values of the
currently selected ROI --> how to make myT available in a macro?

        public float[] myT;

        public void run(ImageProcessor ip) {

       
                Rectangle r = ip.getRoi();
                ImageProcessor mask = ip.getMask();
                if (mask==null) {
                mask = new ByteProcessor(r.width, r.height);
                mask.invert();
            }
           
                int total = 0;
                for (int x= 0; x < r.width; x++) {
                        for (int y=0; y < r.height; y++) {
                                if(mask.getf(x,y) >  0){
                                        total++;
                                }
                        }
                }

                myT = new float[total];
                total=0;
                for (int x= 0; x < r.width; x++) {
                        for (int y=0; y < r.height; y++) {
                                if(mask.getf(x,y) >  0){
                                        myT[total++]=ip.getf(x, y);
                                }
                                //IJ.log("Pixel: Y="+y+" ; X="+x+" ; value=" + ip.getf(x, y) +
"Mask = "+ mask.getf(x,y) );
                        }
                }
        }

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

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

dscho
1631 posts
Hi Emmanuel,

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.

I fear that you are trying to do something with the macro language that it
was not designed for. Remember, the macro language is meant to be very
simple so it is easy to learn, it is not meant to be fast (and it is
indeed not fast) nor a fully-fledged scripting language. Javascript is.

Sure, you may get Wayne to extend the macro language, but everytime the
syntax gets extended, the macro interpreter becomes more brittle since the
original design was not intended to be extended in that way.

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));

Ciao,
Johannes

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

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

Emmanuel Levy
36 posts
Hi Johannes,

Thanks, I understand that this does sound a bit strange but the reason is that i started working on a macro a long time ago and it would require a significant amount of work to port the whole thing to Javascript.

I was thinking that there should already be a way to do this as the getSttatistics function gives access to an array of values (hist) that (i suppose) is calculated from java code.

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. E.g., just like one has access to the value of "hist" after calling getStatistics, id like to have access to myT.

I hope im clearer!

Thank you,

Emmanuel


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

> Hi Emmanuel,
>
> 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.
>
> I fear that you are trying to do something with the macro language that it
> was not designed for. Remember, the macro language is meant to be very
> simple so it is easy to learn, it is not meant to be fast (and it is
> indeed not fast) nor a fully-fledged scripting language. Javascript is.
>
> Sure, you may get Wayne to extend the macro language, but everytime the
> syntax gets extended, the macro interpreter becomes more brittle since the
> original design was not intended to be extended in that way.
>
> 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));
>
> Ciao,
> Johannes

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

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

Gabriel Landini
1783 posts
On Monday 01 Apr 2013 19:04:11 Emmanuel Levy wrote:
> Thanks, I understand that this does sound a bit strange but the reason is
> that i started working on a macro a long time ago and it would require a
> significant amount of work to port the whole thing to Javascript.

Currently you can't pass an array the way you want.

You could, write the array to a file, and read it from the macro.
Or make an image of n columns and 1 row and set the pixel values from the
array and read it from the macro.
Or set and get values to the so called "image properties" with the ImpProps
class.

Cheers

Gabriel

 

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

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

dscho
1631 posts
In reply to this post by Emmanuel Levy
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
Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

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

Emmanuel Levy
36 posts
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