ImageJ2 scripting

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

ImageJ2 scripting

Jan Eglinger
Dear all,

*** TL;DR:
How do I proceed to get multiple input Datasets as ImageJ2 parameters
from open images in Fiji?
***

I was recently exploring ImageJ2 scripting in Fiji and found the
OpsThresholdIJ1Analyze template [1] in the script editor very helpful.

When trying to get more than one @net.imagej.Dataset input parameter
however, I noticed some inconsistencies.
Let me try to illustrate with the two following scripts:

     # @DisplayService display
     # @OpService ops
     # @net.imagej.Dataset inputData1

     from net.imglib2.meta import ImgPlus

     display.createDisplay("my1", ImgPlus(inputData1))


The above script re-displays the current image as expected (I tried with
the Blobs sample image open, which will be re-displayed with a
non-inverted LUT.)

When I ask for two input datasets (right after a fresh start of Fiji
with only the Blobs sample image open):

     # @DisplayService display
     # @OpService ops
     # @net.imagej.Dataset inputData1
     # @net.imagej.Dataset inputData2

     from net.imglib2.meta import ImgPlus

     display.createDisplay("my1", ImgPlus(inputData1))
     display.createDisplay("my2", ImgPlus(inputData2))

an error message is displayed: "A Dataset is required but none exist."
The same error message is displayed when I open a second image in Fiji
before running the script.

Now, when I run script #2 after script #1 was run at least once, I get a
dialog with two choices "InputData1" and "InputData2", both choice
fields containing "blobs.gif" and a number of "Untitled" entries (where
can this title be set, by the way?).

I guess that a choice is only displayed if there are ImageJ2 datasets
(i.e. wrapped ImagePlus) already available. The single input case seems
to be special-cased as it auto-wraps the currently open image.

So how do I proceed to get more than one input in ImageJ2 scripting from
open (ImageJ1-)images?

Thanks for your advice,
Regards,
Jan


[1]:
https://github.com/imagej/imagej-legacy/blob/master/src/main/resources/script_templates/Python/OpsThresholdIJ1Analyze.py

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: ImageJ2 scripting

Mark Hiner
Hi Jan,

>an error message is displayed: "A Dataset is required but none exist."

This was due to limitations with the input preprocessor presenting the list of datasets. Since ImagePluses aren't explicitly tracked by the IJ2 framework, having an ImagePlus recognized as a Dataset requires some extra layers. We had covered the single input case (which is why your first script worked) but not the general multi-input case. There is an issue tracking the multi-input case, which I resolved today. So this should work as intended in our next release - and thank you for the motivation to wrap this up!

You can also manually enable ImagePlus <> Dataset synchronization to ensure ImagePluses always have a corresponding Dataset: http://imagej.net/Compatibility#Translation_of_data_structures

>(where can this title be set, by the way?)

For the multiple choice input selection, the labels are based on the name of the input type. Since the input type is Dataset, the Dataset name is used (which delegates to the wrapped ImgPlus). In your code you are applying labels to the Display, but not the underlying dataset - if you name the ImgPlus, or explicitly create a Dataset and set its name, that name will propagate up to the input chooser (and the Display). As a side note, you should use the net.imagej.ImgPlus instead of the net.imglib2.meta.

An updated script would be:


   # @DisplayService display
   # @OpService ops
   # @net.imagej.Dataset inputData1
   # @net.imagej.Dataset inputData2

   from net.imagej import ImgPlus

   display.createDisplay(ImgPlus(inputData1, "my1"))
   display.createDisplay(ImgPlus(inputData2, "my2"))

Hope that helps. Let me know if you have any other questions.

Best,
Mark

On Mon, Apr 27, 2015 at 8:58 AM, Jan Eglinger <[hidden email]> wrote:
Dear all,

*** TL;DR:
How do I proceed to get multiple input Datasets as ImageJ2 parameters from open images in Fiji?
***

I was recently exploring ImageJ2 scripting in Fiji and found the OpsThresholdIJ1Analyze template [1] in the script editor very helpful.

When trying to get more than one @net.imagej.Dataset input parameter however, I noticed some inconsistencies.
Let me try to illustrate with the two following scripts:

    # @DisplayService display
    # @OpService ops
    # @net.imagej.Dataset inputData1

    from net.imglib2.meta import ImgPlus

    display.createDisplay("my1", ImgPlus(inputData1))


The above script re-displays the current image as expected (I tried with the Blobs sample image open, which will be re-displayed with a non-inverted LUT.)

When I ask for two input datasets (right after a fresh start of Fiji with only the Blobs sample image open):

    # @DisplayService display
    # @OpService ops
    # @net.imagej.Dataset inputData1
    # @net.imagej.Dataset inputData2

    from net.imglib2.meta import ImgPlus

    display.createDisplay("my1", ImgPlus(inputData1))
    display.createDisplay("my2", ImgPlus(inputData2))

an error message is displayed: "A Dataset is required but none exist."
The same error message is displayed when I open a second image in Fiji before running the script.

Now, when I run script #2 after script #1 was run at least once, I get a dialog with two choices "InputData1" and "InputData2", both choice fields containing "blobs.gif" and a number of "Untitled" entries (where can this title be set, by the way?).

I guess that a choice is only displayed if there are ImageJ2 datasets (i.e. wrapped ImagePlus) already available. The single input case seems to be special-cased as it auto-wraps the currently open image.

So how do I proceed to get more than one input in ImageJ2 scripting from open (ImageJ1-)images?

Thanks for your advice,
Regards,
Jan


[1]: https://github.com/imagej/imagej-legacy/blob/master/src/main/resources/script_templates/Python/OpsThresholdIJ1Analyze.py

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel


_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: ImageJ2 scripting

Curtis Rueden
Hi Jan,

Here is another version of the script, which avoids wrapping each Dataset in another ImgPlus (which the framework would then wrap into yet another Dataset....):

   # @DisplayService display
   # @OpService ops
   # @net.imagej.Dataset inputData1
   # @net.imagej.Dataset inputData2

   inputData1.setName("my1")
   inputData2.setName("my2")
   display.createDisplay(inputData1)
   display.createDisplay(inputData2)

But note that you also don't need to explicitly call createDisplay. Any output parameters of your script will automatically have displays created for them. E.g.:

   # @OUTPUT net.imagej.Dataset outputData

Will be shown at the conclusion of the script.

Apologies for the appalling lack of documentation -- it would be great to flesh out the wiki docs about all this.

HTH,
Curtis

On Mon, Apr 27, 2015 at 1:23 PM, Mark Hiner <[hidden email]> wrote:
Hi Jan,

>an error message is displayed: "A Dataset is required but none exist."

This was due to limitations with the input preprocessor presenting the list of datasets. Since ImagePluses aren't explicitly tracked by the IJ2 framework, having an ImagePlus recognized as a Dataset requires some extra layers. We had covered the single input case (which is why your first script worked) but not the general multi-input case. There is an issue tracking the multi-input case, which I resolved today. So this should work as intended in our next release - and thank you for the motivation to wrap this up!

You can also manually enable ImagePlus <> Dataset synchronization to ensure ImagePluses always have a corresponding Dataset: http://imagej.net/Compatibility#Translation_of_data_structures

>(where can this title be set, by the way?)

For the multiple choice input selection, the labels are based on the name of the input type. Since the input type is Dataset, the Dataset name is used (which delegates to the wrapped ImgPlus). In your code you are applying labels to the Display, but not the underlying dataset - if you name the ImgPlus, or explicitly create a Dataset and set its name, that name will propagate up to the input chooser (and the Display). As a side note, you should use the net.imagej.ImgPlus instead of the net.imglib2.meta.

An updated script would be:


   # @DisplayService display
   # @OpService ops
   # @net.imagej.Dataset inputData1
   # @net.imagej.Dataset inputData2

   from net.imagej import ImgPlus

   display.createDisplay(ImgPlus(inputData1, "my1"))
   display.createDisplay(ImgPlus(inputData2, "my2"))

Hope that helps. Let me know if you have any other questions.

Best,
Mark

On Mon, Apr 27, 2015 at 8:58 AM, Jan Eglinger <[hidden email]> wrote:
Dear all,

*** TL;DR:
How do I proceed to get multiple input Datasets as ImageJ2 parameters from open images in Fiji?
***

I was recently exploring ImageJ2 scripting in Fiji and found the OpsThresholdIJ1Analyze template [1] in the script editor very helpful.

When trying to get more than one @net.imagej.Dataset input parameter however, I noticed some inconsistencies.
Let me try to illustrate with the two following scripts:

    # @DisplayService display
    # @OpService ops
    # @net.imagej.Dataset inputData1

    from net.imglib2.meta import ImgPlus

    display.createDisplay("my1", ImgPlus(inputData1))


The above script re-displays the current image as expected (I tried with the Blobs sample image open, which will be re-displayed with a non-inverted LUT.)

When I ask for two input datasets (right after a fresh start of Fiji with only the Blobs sample image open):

    # @DisplayService display
    # @OpService ops
    # @net.imagej.Dataset inputData1
    # @net.imagej.Dataset inputData2

    from net.imglib2.meta import ImgPlus

    display.createDisplay("my1", ImgPlus(inputData1))
    display.createDisplay("my2", ImgPlus(inputData2))

an error message is displayed: "A Dataset is required but none exist."
The same error message is displayed when I open a second image in Fiji before running the script.

Now, when I run script #2 after script #1 was run at least once, I get a dialog with two choices "InputData1" and "InputData2", both choice fields containing "blobs.gif" and a number of "Untitled" entries (where can this title be set, by the way?).

I guess that a choice is only displayed if there are ImageJ2 datasets (i.e. wrapped ImagePlus) already available. The single input case seems to be special-cased as it auto-wraps the currently open image.

So how do I proceed to get more than one input in ImageJ2 scripting from open (ImageJ1-)images?

Thanks for your advice,
Regards,
Jan


[1]: https://github.com/imagej/imagej-legacy/blob/master/src/main/resources/script_templates/Python/OpsThresholdIJ1Analyze.py

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel


_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel



_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: ImageJ2 scripting

Jan Eglinger
Dear Mark and Curtis,

thank you very much for the quick replies and helpful pointers!

Jan


On 27.04.2015 20:42, Curtis Rueden wrote:

> Hi Jan,
>
> Here is another version of the script, which avoids wrapping each
> Dataset in another ImgPlus (which the framework would then wrap into yet
> another Dataset....):
>
>     # @DisplayService display
>     # @OpService ops
>     # @net.imagej.Dataset inputData1
>     # @net.imagej.Dataset inputData2
>
>     inputData1.setName("my1")
>     inputData2.setName("my2")
>     display.createDisplay(inputData1)
>     display.createDisplay(inputData2)
>
> But note that you also don't need to explicitly call createDisplay. Any
> output parameters of your script will automatically have displays
> created for them. E.g.:
>
>     # @OUTPUT net.imagej.Dataset outputData
>
> Will be shown at the conclusion of the script.
>
> Apologies for the appalling lack of documentation -- it would be great
> to flesh out the wiki docs about all this.
>
> HTH,
> Curtis
>
> On Mon, Apr 27, 2015 at 1:23 PM, Mark Hiner <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>     Hi Jan,
>
>     >an error message is displayed: "A Dataset is required but none exist."
>
>     This was due to limitations with the input preprocessor presenting
>     the list of datasets. Since ImagePluses aren't explicitly tracked by
>     the IJ2 framework, having an ImagePlus recognized as a Dataset
>     requires some extra layers. We had covered the single input case
>     (which is why your first script worked) but not the general
>     multi-input case. There is an issue tracking the multi-input
>     <https://github.com/imagej/imagej-legacy/issues/106> case, which I
>     resolved today. So this should work as intended in our next release
>     - and thank you for the motivation to wrap this up!
>
>     You can also manually enable ImagePlus <> Dataset synchronization to
>     ensure ImagePluses always have a corresponding Dataset:
>     http://imagej.net/Compatibility#Translation_of_data_structures
>
>     >(where can this title be set, by the way?)
>
>     For the multiple choice input selection, the labels are based on the
>     name of the input type. Since the input type is Dataset, the Dataset
>     name is used (which delegates to the wrapped ImgPlus). In your code
>     you are applying labels to the Display, but not the underlying
>     dataset - if you name the ImgPlus, or explicitly create a Dataset
>     and set its name, that name will propagate up to the input chooser
>     (and the Display). As a side note, you should use the
>     net.imagej.ImgPlus instead of the net.imglib2.meta.
>
>     An updated script would be:
>
>
>         # @DisplayService display
>         # @OpService ops
>         # @net.imagej.Dataset inputData1
>         # @net.imagej.Dataset inputData2
>
>         from net.imagej import ImgPlus
>
>         display.createDisplay(ImgPlus(inputData1, "my1"))
>         display.createDisplay(ImgPlus(inputData2, "my2"))
>
>     Hope that helps. Let me know if you have any other questions.
>
>     Best,
>     Mark
>
>     On Mon, Apr 27, 2015 at 8:58 AM, Jan Eglinger
>     <[hidden email] <mailto:[hidden email]>> wrote:
>
>         Dear all,
>
>         *** TL;DR:
>         How do I proceed to get multiple input Datasets as ImageJ2
>         parameters from open images in Fiji?
>         ***
>
>         I was recently exploring ImageJ2 scripting in Fiji and found the
>         OpsThresholdIJ1Analyze template [1] in the script editor very
>         helpful.
>
>         When trying to get more than one @net.imagej.Dataset input
>         parameter however, I noticed some inconsistencies.
>         Let me try to illustrate with the two following scripts:
>
>              # @DisplayService display
>              # @OpService ops
>              # @net.imagej.Dataset inputData1
>
>              from net.imglib2.meta import ImgPlus
>
>              display.createDisplay("my1", ImgPlus(inputData1))
>
>
>         The above script re-displays the current image as expected (I
>         tried with the Blobs sample image open, which will be
>         re-displayed with a non-inverted LUT.)
>
>         When I ask for two input datasets (right after a fresh start of
>         Fiji with only the Blobs sample image open):
>
>              # @DisplayService display
>              # @OpService ops
>              # @net.imagej.Dataset inputData1
>              # @net.imagej.Dataset inputData2
>
>              from net.imglib2.meta import ImgPlus
>
>              display.createDisplay("my1", ImgPlus(inputData1))
>              display.createDisplay("my2", ImgPlus(inputData2))
>
>         an error message is displayed: "A Dataset is required but none
>         exist."
>         The same error message is displayed when I open a second image
>         in Fiji before running the script.
>
>         Now, when I run script #2 after script #1 was run at least once,
>         I get a dialog with two choices "InputData1" and "InputData2",
>         both choice fields containing "blobs.gif" and a number of
>         "Untitled" entries (where can this title be set, by the way?).
>
>         I guess that a choice is only displayed if there are ImageJ2
>         datasets (i.e. wrapped ImagePlus) already available. The single
>         input case seems to be special-cased as it auto-wraps the
>         currently open image.
>
>         So how do I proceed to get more than one input in ImageJ2
>         scripting from open (ImageJ1-)images?
>
>         Thanks for your advice,
>         Regards,
>         Jan
>
>
>         [1]:
>         https://github.com/imagej/imagej-legacy/blob/master/src/main/resources/script_templates/Python/OpsThresholdIJ1Analyze.py
>

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: ImageJ2 scripting

Jan Eglinger
Hi all,

some follow-up questions regarding imagej-ops:

I tried to use some basic ops in python. From the 2014 wiki announcement
[1] and the python template [2], I assumed something like this would
work in python:

     # @OpService ops
     # @DisplayService display

     blank = ops.create([100, 50])

     display.createDisplay(blank)

But a choice of candidate functions is listed in output:

**********************************************
Request:
- createimg(
                Integer,
                Integer)

Candidates:
1. (Img output) =
        net.imagej.ops.create.DefaultCreateImg(
==> Type outType?,
                ImgFactory fac?,
                long[] dims)
        Inconvertible type: java.lang.Integer => net.imglib2.type.Type<capture
of ?>
2. (ImgPlus output) =
        net.imagej.ops.create.CreateEmptyImgCopy(
                ImgPlus input)
        Too many arguments: 2 > 1
3. (Img output) =
        net.imagej.ops.create.CreateImgNativeType(
                ImgFactory fac,
                NativeType outType,
                Dimensions dims)
        Not enough arguments: 2 < 3
4. (Img output) =
        net.imagej.ops.create.CreateImgDifferentNativeType(
==> Img input,
                NativeType type)
        Inconvertible type: java.lang.Integer => net.imglib2.img.Img<capture of ?>
5. (ImgPlus output) =
        net.imagej.ops.create.CreateEmptyImgPlusCopy(
                ImgPlus input)
        Too many arguments: 2 > 1
**********************************************

and I am unsure if I have to provide image type and factory here.


Similarly, for the subtract op:

     # @OpService ops
     # @StatisticsService stats
     # @net.imagej.Dataset inData
     # @OUTPUT net.imagej.Dataset outData

     outData = inData.duplicate()

     mean = stats.alphaTrimmedMean(inData, 0)
     print mean

     ops.subtract(outData, inData, mean)

I am getting the following list of candidates:

**********************************************
Request:
- math.subtract(
                DefaultDataset,
                DefaultDataset,
                Double)

Candidates:
1. (Object result) =
        net.imagej.ops.onthefly.ArithmeticOp$SubtractOp(
                Object result,
                Object a,
                Object b)
        Inputs do not conform to op rules
                result = blobs.gif
                a = blobs.gif
                b = 103.26857775590551
2. (int result) =
        net.imagej.ops.math.PrimitiveMath$IntegerSubtract(
                int a,
                int b)
        Too many arguments: 3 > 2
3. (long result) =
        net.imagej.ops.math.PrimitiveMath$LongSubtract(
                long a,
                long b)
        Too many arguments: 3 > 2
4. (float result) =
        net.imagej.ops.math.PrimitiveMath$FloatSubtract(
                float a,
                float b)
        Too many arguments: 3 > 2
5. (double result) =
        net.imagej.ops.math.PrimitiveMath$DoubleSubtract(
                double a,
                double b)
        Too many arguments: 3 > 2
6. (RealType out) =
        net.imagej.ops.arithmetic.real.RealSubtract(
==> RealType out,
                RealType in,
                double constant)
        Inconvertible type: net.imagej.DefaultDataset => capture of ?
**********************************************

is there a way with the type-unsafe scripting languages to get ops to
use the correct function? Or am I misunderstanding the concept of
imagej-ops here?

Thanks again for any hints.

Jan


[1] http://fiji.sc/2014-04-04_-_Announcing_ImageJ_OPS
[2]
https://github.com/imagej/imagej-legacy/blob/master/src/main/resources/script_templates/Python/OpsThresholdIJ1Analyze.py


On 28.04.2015 09:03, Jan Eglinger wrote:

> Dear Mark and Curtis,
>
> thank you very much for the quick replies and helpful pointers!
>
> Jan
>
>
> On 27.04.2015 20:42, Curtis Rueden wrote:
>> Hi Jan,
>>
>> Here is another version of the script, which avoids wrapping each
>> Dataset in another ImgPlus (which the framework would then wrap into yet
>> another Dataset....):
>>
>>     # @DisplayService display
>>     # @OpService ops
>>     # @net.imagej.Dataset inputData1
>>     # @net.imagej.Dataset inputData2
>>
>>     inputData1.setName("my1")
>>     inputData2.setName("my2")
>>     display.createDisplay(inputData1)
>>     display.createDisplay(inputData2)
>>
>> But note that you also don't need to explicitly call createDisplay. Any
>> output parameters of your script will automatically have displays
>> created for them. E.g.:
>>
>>     # @OUTPUT net.imagej.Dataset outputData
>>
>> Will be shown at the conclusion of the script.
>>
>> Apologies for the appalling lack of documentation -- it would be great
>> to flesh out the wiki docs about all this.
>>
>> HTH,
>> Curtis
>>
>> On Mon, Apr 27, 2015 at 1:23 PM, Mark Hiner <[hidden email]
>> <mailto:[hidden email]>> wrote:
>>
>>     Hi Jan,
>>
>>     >an error message is displayed: "A Dataset is required but none
>> exist."
>>
>>     This was due to limitations with the input preprocessor presenting
>>     the list of datasets. Since ImagePluses aren't explicitly tracked by
>>     the IJ2 framework, having an ImagePlus recognized as a Dataset
>>     requires some extra layers. We had covered the single input case
>>     (which is why your first script worked) but not the general
>>     multi-input case. There is an issue tracking the multi-input
>>     <https://github.com/imagej/imagej-legacy/issues/106> case, which I
>>     resolved today. So this should work as intended in our next release
>>     - and thank you for the motivation to wrap this up!
>>
>>     You can also manually enable ImagePlus <> Dataset synchronization to
>>     ensure ImagePluses always have a corresponding Dataset:
>>     http://imagej.net/Compatibility#Translation_of_data_structures
>>
>>     >(where can this title be set, by the way?)
>>
>>     For the multiple choice input selection, the labels are based on the
>>     name of the input type. Since the input type is Dataset, the Dataset
>>     name is used (which delegates to the wrapped ImgPlus). In your code
>>     you are applying labels to the Display, but not the underlying
>>     dataset - if you name the ImgPlus, or explicitly create a Dataset
>>     and set its name, that name will propagate up to the input chooser
>>     (and the Display). As a side note, you should use the
>>     net.imagej.ImgPlus instead of the net.imglib2.meta.
>>
>>     An updated script would be:
>>
>>
>>         # @DisplayService display
>>         # @OpService ops
>>         # @net.imagej.Dataset inputData1
>>         # @net.imagej.Dataset inputData2
>>
>>         from net.imagej import ImgPlus
>>
>>         display.createDisplay(ImgPlus(inputData1, "my1"))
>>         display.createDisplay(ImgPlus(inputData2, "my2"))
>>
>>     Hope that helps. Let me know if you have any other questions.
>>
>>     Best,
>>     Mark
>>
>>     On Mon, Apr 27, 2015 at 8:58 AM, Jan Eglinger
>>     <[hidden email] <mailto:[hidden email]>> wrote:
>>
>>         Dear all,
>>
>>         *** TL;DR:
>>         How do I proceed to get multiple input Datasets as ImageJ2
>>         parameters from open images in Fiji?
>>         ***
>>
>>         I was recently exploring ImageJ2 scripting in Fiji and found the
>>         OpsThresholdIJ1Analyze template [1] in the script editor very
>>         helpful.
>>
>>         When trying to get more than one @net.imagej.Dataset input
>>         parameter however, I noticed some inconsistencies.
>>         Let me try to illustrate with the two following scripts:
>>
>>              # @DisplayService display
>>              # @OpService ops
>>              # @net.imagej.Dataset inputData1
>>
>>              from net.imglib2.meta import ImgPlus
>>
>>              display.createDisplay("my1", ImgPlus(inputData1))
>>
>>
>>         The above script re-displays the current image as expected (I
>>         tried with the Blobs sample image open, which will be
>>         re-displayed with a non-inverted LUT.)
>>
>>         When I ask for two input datasets (right after a fresh start of
>>         Fiji with only the Blobs sample image open):
>>
>>              # @DisplayService display
>>              # @OpService ops
>>              # @net.imagej.Dataset inputData1
>>              # @net.imagej.Dataset inputData2
>>
>>              from net.imglib2.meta import ImgPlus
>>
>>              display.createDisplay("my1", ImgPlus(inputData1))
>>              display.createDisplay("my2", ImgPlus(inputData2))
>>
>>         an error message is displayed: "A Dataset is required but none
>>         exist."
>>         The same error message is displayed when I open a second image
>>         in Fiji before running the script.
>>
>>         Now, when I run script #2 after script #1 was run at least once,
>>         I get a dialog with two choices "InputData1" and "InputData2",
>>         both choice fields containing "blobs.gif" and a number of
>>         "Untitled" entries (where can this title be set, by the way?).
>>
>>         I guess that a choice is only displayed if there are ImageJ2
>>         datasets (i.e. wrapped ImagePlus) already available. The single
>>         input case seems to be special-cased as it auto-wraps the
>>         currently open image.
>>
>>         So how do I proceed to get more than one input in ImageJ2
>>         scripting from open (ImageJ1-)images?
>>
>>         Thanks for your advice,
>>         Regards,
>>         Jan
>>
>>
>>         [1]:
>>
>> https://github.com/imagej/imagej-legacy/blob/master/src/main/resources/script_templates/Python/OpsThresholdIJ1Analyze.py
>>
>>

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: ImageJ2 scripting

Brian Northan
Hi Jan

The following might work for the create op -- it takes a java array not a python list....

from jarray import array
blank=ops.createimg(array([100, 50], 'l'))

Brian



On Tue, Apr 28, 2015 at 11:53 AM, Jan Eglinger <[hidden email]> wrote:
Hi all,

some follow-up questions regarding imagej-ops:

I tried to use some basic ops in python. From the 2014 wiki announcement [1] and the python template [2], I assumed something like this would work in python:

    # @OpService ops
    # @DisplayService display

    blank = ops.create([100, 50])

    display.createDisplay(blank)

But a choice of candidate functions is listed in output:

**********************************************
Request:
-       createimg(
                Integer,
                Integer)

Candidates:
1.      (Img output) =
        net.imagej.ops.create.DefaultCreateImg(
==>             Type outType?,
                ImgFactory fac?,
                long[] dims)
        Inconvertible type: java.lang.Integer => net.imglib2.type.Type<capture of ?>
2.      (ImgPlus output) =
        net.imagej.ops.create.CreateEmptyImgCopy(
                ImgPlus input)
        Too many arguments: 2 > 1
3.      (Img output) =
        net.imagej.ops.create.CreateImgNativeType(
                ImgFactory fac,
                NativeType outType,
                Dimensions dims)
        Not enough arguments: 2 < 3
4.      (Img output) =
        net.imagej.ops.create.CreateImgDifferentNativeType(
==>             Img input,
                NativeType type)
        Inconvertible type: java.lang.Integer => net.imglib2.img.Img<capture of ?>
5.      (ImgPlus output) =
        net.imagej.ops.create.CreateEmptyImgPlusCopy(
                ImgPlus input)
        Too many arguments: 2 > 1
**********************************************

and I am unsure if I have to provide image type and factory here.


Similarly, for the subtract op:

    # @OpService ops
    # @StatisticsService stats
    # @net.imagej.Dataset inData
    # @OUTPUT net.imagej.Dataset outData

    outData = inData.duplicate()

    mean = stats.alphaTrimmedMean(inData, 0)
    print mean

    ops.subtract(outData, inData, mean)

I am getting the following list of candidates:

**********************************************
Request:
-       math.subtract(
                DefaultDataset,
                DefaultDataset,
                Double)

Candidates:
1.      (Object result) =
        net.imagej.ops.onthefly.ArithmeticOp$SubtractOp(
                Object result,
                Object a,
                Object b)
        Inputs do not conform to op rules
                result = blobs.gif
                a = blobs.gif
                b = 103.26857775590551
2.      (int result) =
        net.imagej.ops.math.PrimitiveMath$IntegerSubtract(
                int a,
                int b)
        Too many arguments: 3 > 2
3.      (long result) =
        net.imagej.ops.math.PrimitiveMath$LongSubtract(
                long a,
                long b)
        Too many arguments: 3 > 2
4.      (float result) =
        net.imagej.ops.math.PrimitiveMath$FloatSubtract(
                float a,
                float b)
        Too many arguments: 3 > 2
5.      (double result) =
        net.imagej.ops.math.PrimitiveMath$DoubleSubtract(
                double a,
                double b)
        Too many arguments: 3 > 2
6.      (RealType out) =
        net.imagej.ops.arithmetic.real.RealSubtract(
==>             RealType out,
                RealType in,
                double constant)
        Inconvertible type: net.imagej.DefaultDataset => capture of ?
**********************************************

is there a way with the type-unsafe scripting languages to get ops to use the correct function? Or am I misunderstanding the concept of imagej-ops here?

Thanks again for any hints.

Jan


[1] http://fiji.sc/2014-04-04_-_Announcing_ImageJ_OPS
[2] https://github.com/imagej/imagej-legacy/blob/master/src/main/resources/script_templates/Python/OpsThresholdIJ1Analyze.py



On 28.04.2015 09:03, Jan Eglinger wrote:
Dear Mark and Curtis,

thank you very much for the quick replies and helpful pointers!

Jan


On <a href="tel:27.04.2015%2020" value="+12704201520" target="_blank">27.04.2015 20:42, Curtis Rueden wrote:
Hi Jan,

Here is another version of the script, which avoids wrapping each
Dataset in another ImgPlus (which the framework would then wrap into yet
another Dataset....):

    # @DisplayService display
    # @OpService ops
    # @net.imagej.Dataset inputData1
    # @net.imagej.Dataset inputData2

    inputData1.setName("my1")
    inputData2.setName("my2")
    display.createDisplay(inputData1)
    display.createDisplay(inputData2)

But note that you also don't need to explicitly call createDisplay. Any
output parameters of your script will automatically have displays
created for them. E.g.:

    # @OUTPUT net.imagej.Dataset outputData

Will be shown at the conclusion of the script.

Apologies for the appalling lack of documentation -- it would be great
to flesh out the wiki docs about all this.

HTH,
Curtis

On Mon, Apr 27, 2015 at 1:23 PM, Mark Hiner <[hidden email]
<mailto:[hidden email]>> wrote:

    Hi Jan,

    >an error message is displayed: "A Dataset is required but none
exist."

    This was due to limitations with the input preprocessor presenting
    the list of datasets. Since ImagePluses aren't explicitly tracked by
    the IJ2 framework, having an ImagePlus recognized as a Dataset
    requires some extra layers. We had covered the single input case
    (which is why your first script worked) but not the general
    multi-input case. There is an issue tracking the multi-input
    <https://github.com/imagej/imagej-legacy/issues/106> case, which I
    resolved today. So this should work as intended in our next release
    - and thank you for the motivation to wrap this up!

    You can also manually enable ImagePlus <> Dataset synchronization to
    ensure ImagePluses always have a corresponding Dataset:
    http://imagej.net/Compatibility#Translation_of_data_structures

    >(where can this title be set, by the way?)

    For the multiple choice input selection, the labels are based on the
    name of the input type. Since the input type is Dataset, the Dataset
    name is used (which delegates to the wrapped ImgPlus). In your code
    you are applying labels to the Display, but not the underlying
    dataset - if you name the ImgPlus, or explicitly create a Dataset
    and set its name, that name will propagate up to the input chooser
    (and the Display). As a side note, you should use the
    net.imagej.ImgPlus instead of the net.imglib2.meta.

    An updated script would be:


        # @DisplayService display
        # @OpService ops
        # @net.imagej.Dataset inputData1
        # @net.imagej.Dataset inputData2

        from net.imagej import ImgPlus

        display.createDisplay(ImgPlus(inputData1, "my1"))
        display.createDisplay(ImgPlus(inputData2, "my2"))

    Hope that helps. Let me know if you have any other questions.

    Best,
    Mark

    On Mon, Apr 27, 2015 at 8:58 AM, Jan Eglinger
    <[hidden email] <mailto:[hidden email]>> wrote:

        Dear all,

        *** TL;DR:
        How do I proceed to get multiple input Datasets as ImageJ2
        parameters from open images in Fiji?
        ***

        I was recently exploring ImageJ2 scripting in Fiji and found the
        OpsThresholdIJ1Analyze template [1] in the script editor very
        helpful.

        When trying to get more than one @net.imagej.Dataset input
        parameter however, I noticed some inconsistencies.
        Let me try to illustrate with the two following scripts:

             # @DisplayService display
             # @OpService ops
             # @net.imagej.Dataset inputData1

             from net.imglib2.meta import ImgPlus

             display.createDisplay("my1", ImgPlus(inputData1))


        The above script re-displays the current image as expected (I
        tried with the Blobs sample image open, which will be
        re-displayed with a non-inverted LUT.)

        When I ask for two input datasets (right after a fresh start of
        Fiji with only the Blobs sample image open):

             # @DisplayService display
             # @OpService ops
             # @net.imagej.Dataset inputData1
             # @net.imagej.Dataset inputData2

             from net.imglib2.meta import ImgPlus

             display.createDisplay("my1", ImgPlus(inputData1))
             display.createDisplay("my2", ImgPlus(inputData2))

        an error message is displayed: "A Dataset is required but none
        exist."
        The same error message is displayed when I open a second image
        in Fiji before running the script.

        Now, when I run script #2 after script #1 was run at least once,
        I get a dialog with two choices "InputData1" and "InputData2",
        both choice fields containing "blobs.gif" and a number of
        "Untitled" entries (where can this title be set, by the way?).

        I guess that a choice is only displayed if there are ImageJ2
        datasets (i.e. wrapped ImagePlus) already available. The single
        input case seems to be special-cased as it auto-wraps the
        currently open image.

        So how do I proceed to get more than one input in ImageJ2
        scripting from open (ImageJ1-)images?

        Thanks for your advice,
        Regards,
        Jan


        [1]:

https://github.com/imagej/imagej-legacy/blob/master/src/main/resources/script_templates/Python/OpsThresholdIJ1Analyze.py



_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel


_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: ImageJ2 scripting

Mark Hiner

from jarray import array
blank=ops.createimg(array([100, 50], 'l'))

Thanks for this Brian! It definitely worked for me.

I would like to make things friendlier by automatically converting python arrays to java, so I opened a new issue: https://github.com/scijava/scripting-jython/issues/2

Thanks for pointing this out Jan.

Best,
Mark

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: ImageJ2 scripting

Mark Hiner
Hi all,

>I would like to make things friendlier by automatically converting python arrays to java, so I opened a new issue: https://github.com/scijava/scripting-jython/issues/2

After further investigation, the problem wasn't type conversion but rather that the createimg (and create) ops have a varargs parameter. Even though an array was being passed, the individual values were being unwrapped (so the Ops framework saw two parameters, instead of a single array parameter with two elements).

The issue was not limited to jython scripting. I filed a PR to improve the matching logic[1] - once it's merged, the following will all work:

   blank = ops.create(100, 50)

   blank = ops.create([100, 50])

   from jarray import array
   blank=ops.createimg(array([100, 50], 'l'))

Thanks again for the help and feedback!

Best,

On Tue, Apr 28, 2015 at 1:54 PM, Mark Hiner <[hidden email]> wrote:

from jarray import array
blank=ops.createimg(array([100, 50], 'l'))

Thanks for this Brian! It definitely worked for me.

I would like to make things friendlier by automatically converting python arrays to java, so I opened a new issue: https://github.com/scijava/scripting-jython/issues/2

Thanks for pointing this out Jan.

Best,
Mark


_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel