[ImageJ-devel] ImageJ2 scripting

Jan Eglinger jan.eglinger at gmail.com
Tue Apr 28 10:53:21 CDT 2015


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 <hiner at wisc.edu
>> <mailto:hiner at wisc.edu>> 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
>>     <jan.eglinger at gmail.com <mailto:jan.eglinger at gmail.com>> 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
>>
>>



More information about the ImageJ-devel mailing list