[ImageJ-devel] @parameter choice update in component callback

Curtis Rueden ctrueden at wisc.edu
Thu Aug 27 16:33:03 CDT 2015


Hi Adrian,

> https://gitlab.com/pendant-drop/pendant-drop.git
> (checkout branch overlay_issue (commit 2887f8ec))
>
> This is a MVCE that has parameters

Thanks, I was able to replicate the problems using your code.

I tried to reproduce using a script with various parameter combinations
mirroring yours, but was initially unsuccessful. It seems the problem is a
little subtle.

It is likely related to the syncing of IJ1 and IJ2 data structures. So I'm
not going to worry about further for the time being—that logic will be
revised in the future anyway.

> More than a tutorial I missed some explanations on the technical
> design of, and the interplay between, the different parts that now
> make up ImageJ2.

The best I have to offer right now is:
* http://imagej.net/Architecture
* http://imagej.net/Development

> I just opened a sheet in an editor on which I will jot down notes as I
> go ahead with my plugin, about problems, discoveries and things I
> suddenly understand. Maybe this can be a starting point or
> contribution for a transition guide.

That would be fantastic! It is physically impossible for Mark and me to
write the entire wiki...

Regards,
Curtis

On Thu, Aug 27, 2015 at 2:18 PM, Adrian Daerr <
adrian.daerr at univ-paris-diderot.fr> wrote:

> Hello Curtis,
>
> @Parameter(persist = false) private RectangleOverlay roi;
>>>
>>> which appears to be populated only after the initializer is called
>>> (its value is null in the initializer and valid in the run() method).
>>>
>>
>> Hmm, that should not be the case. [..]
>> The issue might be typing-related: try using Overlay instead of
>> RectangleOverlay and see if that makes a difference.
>>
>> Alternately: can you post an MVCE [3, 4] illustrating the issue?
>>
>
> https://gitlab.com/pendant-drop/pendant-drop.git
> (checkout branch overlay_issue (commit 2887f8ec))
>
> This is a MVCE that has parameters
>
>     @Parameter
>     private ImagePlus imp;
>
>     @Parameter(persist = false)
>     private RectangleOverlay region;
>
>     @Parameter(persist = false)
>     private Overlay overlay;
>
> It compiles and executes with
>
> mvn -o package && fiji --class-path \
> target/pendant_drop-2.0.0-SNAPSHOT.jar Goutte_pendante.class
>
> and logs the following to the console:
>
> [INFO] imp parameter in initializer(): non-null
> [INFO] region parameter in initializer(): null
> [INFO] overlay parameter in initializer(): null
> [INFO] imp parameter in preview(): non-null
> [INFO] region parameter in preview(): non-null
> [INFO] overlay parameter in preview(): non-null
> [INFO] imp parameter in run(): non-null
> [INFO] region parameter in run(): non-null
> [INFO] overlay parameter in run(): non-null
> [ERROR] Module threw exception
> java.lang.NullPointerException
>         at ij.plugin.frame.Recorder.addQuotes(Recorder.java:612)
> ...
>
> Note 1) Since I switched to the OverlayService.getSelectionBounds()
> solution you suggested in another thread, do not bother looking into
> this for me. I just submit this MVCE in case the issue is more
> important than I suspect.
>
> Note 2) It appears (RectangleOverlay).toString() returns null in any
> case.
>
> Note 3) Overlay and RectangleOverlay have the same issue with respect
> to initialization, but the reason I used RectangleOverlay is that I
> did not see how to get the bounds of an Overlay.
>
> I am sorry—the tutorials need to be improved. What sort of tutorial do you
>> think would aid your understanding here?
>>
>
> More than a tutorial I missed some explanations on the technical
> design of, and the interplay between, the different parts that now
> make up ImageJ2. Instead of one single place to find the API and
> Source of ij.*, things are split up into packages (org.scijava.*,
> net.imagej.*, imglib) and it takes a bit to figure out how things are
> organized and why this division of labour makes sense. So deciding
> e.g. where to look for ROI/Overlay related stuff was not easy
> (net.imagej? imglib? both seem to have bits). For someone used to the
> often static, in any case ultra specific ImageJ1 API, understanding
> what a context is, what Services are good for, how menus, views, even
> whole GUIs are flexibly handled, how roughly plugins are recognized,
> how and when annotations are parsed (what's an annotation anyway from
> a Java perspective ?) and how they are instantiated and executed, well
> all this is quite a lot of new stuff. Not to speak about understanding
> how the new Dataset/ImageDisplay/Views classes replacing ImageJ1's
> ImagePlus/ImageWindow/.. work together, and why some of them are
> already deprecated ;-)
>
> Now this very design still seems to be changing, so I understand
> writing up something might be a bit early. Besides, it's a good thing
> not to pin it down to early, and producing documentation wikis that
> may soon prove outdated can be not only a waste of time, but even
> prove quite perturbing later when they contradict reality. Even if I'd
> like to see some gently (but technically oriented) introduction to the
> class zoo and ecosystem of ImageJ2, and also a guide to plugin
> programming specifically for the ImageJ1 veteran (with, for now, your
> recommendation to just take advantage of the parameter harvesting
> features but to stick to IJ1 data structures), I think this is
> probably too early to do. But I just opened a sheet in an editor on
> which I will jot down notes as I go ahead with my plugin, about
> problems, discoveries and things I suddenly understand. Maybe this can
> be a starting point or contribution for a transition guide.
>
> If I do have ideas about specific programming examples for the
> imagej-tutorials, I'll voice them of course.
>
> In any case your reactivity on this list is simply invaluable, thanks
> a lot for adding communication efforts to your programming mission.
>
> best regards,
> Adrian
>
>
>
>
> On Mon, 24 Aug 2015 10:25:59 -0500
>  Curtis Rueden <ctrueden at wisc.edu> wrote:
>
>> Hi Adrian,
>>
>> Thanks for the suggestion, which almost does the job, except that the
>>> initialization also depends on a parameter
>>>
>>> @Parameter(persist = false) private RectangleOverlay roi;
>>>
>>> which appears to be populated only after the initializer is called
>>> (its value is null in the initializer and valid in the run() method).
>>>
>>
>> Hmm, that should not be the case. Commands that include a single overlay
>> parameter should automatically draw from the active image's active
>> overlay,
>> when possible [1]. This happens _before_ the initializers are called [2]
>> (because Priority.VERY_HIGH_PRIORITY > Priority.HIGH_PRIORITY).
>>
>> The issue might be typing-related: try using Overlay instead of
>> RectangleOverlay and see if that makes a difference. If so, it is probably
>> a limitation of the ActiveOverlayPreprocessor [1]; patches welcome.
>>
>> Alternately: can you post an MVCE [3, 4] illustrating the issue?
>>
>> do I have to write a Preprocessor of some sorts
>>>
>>
>> This is certainly possible to do, but I would hope not necessary.
>>
>> can the initializer 'manually' call the code which normally harvest
>>> the RectangleOverlay parameter later on ?
>>>
>>
>> Sure, you can always code in whatever logic you want to the plugin
>> initializer method. But again, hopefully not necessary in this case.
>>
>> even after some reading of the tutorials and the scijava source code
>>> around org.scijava.command.CommandInfo my understanding of how the
>>> plugin initialisation works is still poor.
>>>
>>
>> I am sorry—the tutorials need to be improved. What sort of tutorial do you
>> think would aid your understanding here? The "execute-commands" and
>> "custom-preprocessor-plugin" tutorials are probably touch on these topics
>> most closely, although neither provides a real overview of the
>> pre-/post-processing chain in conjunction with module execution.
>>
>> Would it make sense to distinguish (by an annotation ?) parameters
>>> that are to be initialized from the context (i.e. services, active
>>> image, roi etc), and whose lack should be immediately fatal to the
>>> plugin (no UI harvesting, and in exchange can be assumed final for the
>>> rest of the command execution), from parameters that, if they cannot
>>> be populated from already available data, should be harvested through
>>> a dialog (and may change several times) ?
>>>
>>
>> Potentially, yes. Feel free to comment on the issue on GitHub!
>>
>> Regards,
>> Curtis
>>
>> [1]
>>
>> https://github.com/imagej/imagej-common/blob/imagej-common-0.15.1/src/main/java/net/imagej/display/process/ActiveOverlayPreprocessor.java#L57
>>
>> [2]
>>
>> https://github.com/scijava/scijava-common/blob/scijava-common-2.44.2/src/main/java/org/scijava/module/process/InitPreprocessor.java#L49
>>
>> [3] http://imagej.net/Bug_reporting_best_practices
>>
>> [4] http://stackoverflow.com/help/mcve
>>
>>
>> On Mon, Aug 24, 2015 at 9:07 AM, Adrian Daerr <
>> adrian.daerr at univ-paris-diderot.fr> wrote:
>>
>> Hi Curtis,
>>>
>>> I have parameters a, b, c whose initialisation depend on a common
>>>
>>>> calculation (depending on the image gotten through a previous
>>>>> @Parameter ImagePlus imp): can I do this calculation in the
>>>>> initialiser for the first parameter a, and then in the initialisers of
>>>>> b
>>>>> and c rely on the fact that the calculation was already done ?
>>>>>
>>>>>
>>>> Perhaps simplest at the moment would be to give your command a global
>>>> initializer -- i.e., set the initializer method in the
>>>> @Plugin annotation itself, rather than on specific parameters.
>>>> The ImagePlus will be populated by a preprocessor _before_ the
>>>> initialize method is called, so when your global initializer gets
>>>> called you will already have access to the ImagePlus.
>>>>
>>>>
>>> Thanks for the suggestion, which almost does the job, except that the
>>> initialization also depends on a parameter
>>>
>>> @Parameter(persist = false) private RectangleOverlay roi;
>>>
>>> which appears to be populated only after the initializer is called (its
>>> value is null in the initializer and valid in the run() method).
>>>
>>> I am not sure how to solve this: do I have to write a Preprocessor of
>>> some
>>> sorts, or can the initializer 'manually' call the code which normally
>>> harvest the RectangleOverlay parameter later on ? Somehow the fact that
>>> ImagePlus is populated by a Preprocessor but RectangleOverlay isn't,
>>> seems
>>> linked to issues that I mentionned in another post[1], but even after
>>> some
>>> reading of the tutorials and the scijava source code around
>>> org.scijava.command.CommandInfo my understanding of how the plugin
>>> initialisation works is still poor.
>>>
>>> [1]
>>> (e.g. that the Overlay appears in the harvesting dialog, or that an
>>> Exception is thrown because of the overlay after command execution)
>>>
>>>
>>> http://imagej-devel.54429.x6.nabble.com/Masking-Parameter-from-GUI-harvesting-td1098.html
>>>
>>> But again, scijava/scijava-common#181 is very relevant here.
>>>
>>>>
>>>>
>>> Would it make sense to distinguish (by an annotation ?) parameters that
>>> are to be initialized from the context (i.e. services, active image, roi
>>> etc), and whose lack should be immediately fatal to the plugin (no UI
>>> harvesting, and in exchange can be assumed final for the rest of the
>>> command execution), from parameters that, if they cannot be populated
>>> from
>>> already available data, should be harvested through a dialog (and may
>>> change several times) ?
>>>
>>> cheers,
>>> Adrian
>>>
>>>
> --
> http://www.msc.univ-paris-diderot.fr/~daerr/
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://imagej.net/pipermail/imagej-devel/attachments/20150827/850e279c/attachment-0001.html>


More information about the ImageJ-devel mailing list