[ImageJ-devel] Masking @Parameter from GUI harvesting ?

Curtis Rueden ctrueden at wisc.edu
Thu Aug 27 13:54:22 CDT 2015


Hi Adrian,

> Some parameters do not affect the preview, but preview() is called
> nevertheless. Can we avoid calculating a new preview in this case ? Of
> course we can check inside the preview() body, before performing the
> actual calculation, whether any of the relevant parameters have
> changed.

Checking inside preview() is the approach I favor in general, because your
constraints on what triggers a preview recomputation could be based on
anything.

That said, perhaps it would make sense to make the really common case easy:
add a flag "boolean preview" to the @Parameter annotation (and
corresponding ModuleItem#isPreviewed() method). I filed an issue:

https://github.com/scijava/scijava-common/issues/184

> If I want a parameter to be strictly positive (so I can divide by it
> without checking for zero), it appears that I need to specify a small
> non-negative number explicitely in the min="" annotation:

More generally, it would be nice if you could annotate min and/or max as an
exclusive bound rather than an inclusive one. This would solve your
non-zero problem. Issue filed:

https://github.com/scijava/scijava-common/issues/183

Regards,
Curtis

On Thu, Aug 27, 2015 at 10:35 AM, Adrian Daerr <
adrian.daerr at univ-paris-diderot.fr> wrote:

> Hi Curtis,
>
> Thanks for the explanations on how parameters are resolved.
>
> We could add a way to mark parameters which are not desired to be
>> shown in the dialog box. What is your use case for a parameter you
>> want to have in the script, but never shown to the user in cases
>> where it is still null?
>>
>
> Upon reflection I don't see when this would be needed. I
> misinterpreted the behaviour of the UI harvester in the case of a
> net.imagej.overlay.RectangleOverlay, which was being properly
> populated but which caused a strangely useless selector to appear in
> the dialog (the selector seemed empty or possibly contained one empty
> String). Of course the selector is really only usefull if there were
> several RectangleOverlays to chose from, and they had meaningful
> labels. In the case only one selection is defined one could just drop
> the selector from the dialog. But I thought (should have checked) that
> the UI would try to ask for a RectangleOverlay if none were found.
> This is not the case: when there is no RectangleOverlay at all the
> plugin fails just as in the absence of an image, which is what I want
> (the user can then define a selection as usual and call the plugin
> again). No need for any new annotation here.
>
> 2) A net.imagej.overlay.RectangleOverlay parameter, although properly
>>> populated, provoques an Exception after the execution of the command.
>>> (more details and stacktraces below)
>>>
>>
>> As I mentioned in the other thread: try with Overlay instead? We
>> could certainly make it autofill parameters with specific Overlay
>> subclasses too—just need to confirm first that that is indeed your
>> problem.
>>
>
> No need, the OverlayService.getSelectionBounds() you mention in the
> other thread behaves just fine.
>
> 3) When a new preview is triggered, and that preview modifies numeric
>>> parameters, then the numeric values visible in the gui dialog are
>>> updated except for the NumericField on which input has triggered the
>>> call to preview().
>>>
>>
>> It is a programming error for the preview() function to modify
>> parameter values. Use callbacks instead, which occur before
>> preview() is called [1].
>>
>
> Ok, makes sense.
>
> 4) It would be nice if a parameter could have a label even if
>>> ItemVisibility is MESSAGE
>>>
>>
>> Fixed [2].
>>
>
> Great, thanks a lot!
>
> I have two new small comments (not sure they qualify as feature requests
> as I'm not sure they're necessarily good ideas):
>
> 5) Some parameters do not affect the preview, but preview() is called
> nevertheless. Can we avoid calculating a new preview in this case ? Of
> course we can check inside the preview() body, before performing the
> actual calculation, whether any of the relevant parameters have
> changed. A second possibility would be to introduce a new @Parameter
> annotation to disable the preview() callback. A third way would be
> to modify the framework to skip the preview() call on parameters which
> register their own callback. It would be this callback's
> responsibility to invoque preview() if desired. One could then easily
> register an empty callback function on parameters for which preview()
> should not be invoqued. The only drawback I see is that plugin authors
> may not expect the fact that registering an explicit callback by
> annotation unregisters/disables the preview callback. On the other
> hand widgets such as Buttons which rely on their callback seem already
> excluded from preview() invocation. One advantage is that the
> programmer decides at which point in the callback, if at all,
> preview() gets called, as opposed to the current situation where the
> order is fixed: the specific callback is invoqued before preview().
>
> 6) Really a minor detail: If I want a parameter to be strictly
> positive (so I can divide by it without checking for zero), it appears
> that I need to specify a small non-negative number explicitely in the
> min="" annotation:
>
> @Parameter(min = "1e-300") private double capillary_length;
>
> I cannot specify Double.MIN_VALUE because the 'min' attribute requires
> a String, nor Double.toString(Double.MIN_VALUE) as it is not a
> constant to the compiler. If the constraint of positivity is
> sufficiently common to warrant a small hack, one could allow e.g.
> "epsilon" or "positive" as special value for the annotation 'min' that
> would be translated to <T>.MIN_VALUE
>
> cheers,
> Adrian
>
>
>
> On Mon, 24 Aug 2015 15:31:07 -0500
>  Curtis Rueden <ctrueden at wisc.edu> wrote:
>
>> Hi Adrian,
>>
>> 1) How does one prevent a @Parameter from showing up in the harvesting
>>> GUI dialog, in the manner of a '@Parameter LogService log'? (more
>>> below)
>>>
>>
>> Parameters which are resolved before the input harvester dialog pops up
>> will not show up.
>>
>> They get resolved by the various preprocessors in the preprocessing chain,
>> which is applied before the module is actually run. The InputHarvester --
>> which is what pops the dialog box -- is (IIRC) the final preprocessing
>> step
>> before run happens.
>>
>> We could add a way to mark parameters which are not desired to be shown in
>> the dialog box. What is your use case for a parameter you want to have in
>> the script, but never shown to the user in cases where it is still null?
>>
>> 2) A net.imagej.overlay.RectangleOverlay parameter, although properly
>>> populated, provoques an Exception after the execution of the command.
>>> (more details and stacktraces below)
>>>
>>
>> As I mentioned in the other thread: try with Overlay instead? We could
>> certainly make it autofill parameters with specific Overlay subclasses
>> too—just need to confirm first that that is indeed your problem.
>>
>> 3) When a new preview is triggered, and that preview modifies numeric
>>> parameters, then the numeric values visible in the gui dialog are
>>> updated except for the NumericField on which input has triggered the
>>> call to preview().
>>>
>>
>> It is a programming error for the preview() function to modify parameter
>> values. Use callbacks instead, which occur before preview() is called [1].
>>
>> 4) It would be nice if a parameter could have a label even if
>>> ItemVisibility is MESSAGE
>>>
>>
>> Fixed [2].
>>
>> Regards,
>> Curtis
>>
>> [1]
>>
>> https://github.com/scijava/scijava-common/blob/scijava-common-2.44.2/src/main/java/org/scijava/widget/DefaultWidgetModel.java#L167-L169
>>
>> [2]
>>
>> https://github.com/scijava/scijava-ui-swing/commit/84c30c045bf3327a424f499f1f2fe867b0d9375e
>>
>>
>> On Sun, Aug 23, 2015 at 6:44 AM, Adrian Daerr <
>> adrian.daerr at univ-paris-diderot.fr> wrote:
>>
>> Dear ImageJ developers,
>>>
>>> As I slowly learn more about IJ2 @Plugins, I have one question and three
>>> minor comments that I would like to submit to you.
>>>
>>> 1) How does one prevent a @Parameter from showing up in the harvesting
>>> GUI dialog, in the manner of a '@Parameter LogService log'? (more below)
>>>
>>> 2) A net.imagej.overlay.RectangleOverlay parameter, although properly
>>> populated, provoques an Exception after the execution of the command.
>>> (more details and stacktraces below)
>>>
>>> 3) When a new preview is triggered, and that preview modifies numeric
>>> parameters, then the numeric values visible in the gui dialog are
>>> updated except for the NumericField on which input has triggered the
>>> call to preview().
>>>
>>> 4) It would be nice if a parameter could have a label even if
>>> ItemVisibility is MESSAGE:
>>>   @Parameter(persist = false,
>>>              visibility = org.scijava.ItemVisibility.MESSAGE,
>>>              label = "Current foo value")
>>>     private double foo = 0;
>>> (currently, at least on my box, the label is not shown in this case)
>>> Obviously a workaround is to build a String with label+foo instead.
>>>
>>> cheers,
>>> Adrian
>>>
>>>
>>>
>>> ad 1)
>>> How to prevent a @Parameter from showing up in the harvesting GUI
>>> dialog? Some seem to be masked by default (ImagePlus, LogService), but
>>> I did not find the appropriate annotation to make the parameter roi in
>>> the following not show up, although it is already properly populated
>>> by the rectangular selection of the active image ? There is no
>>> meaningful thing I can do with the associated selector in the dialog.
>>>
>>>     @Parameter private ImagePlus imp;
>>>     @Parameter private RectangleOverlay roi;
>>>     @Parameter private double a;
>>>
>>>
>>> ad 2)
>>> A net.imagej.overlay.RectangleOverlay parameter
>>>
>>>   @Parameter private RectangleOverlay roi;
>>>
>>> is properly populated when the Command is invoqued on an active image
>>> containing a rectangular selection. However it provoques an Exception
>>> after the execution of the command, when either the
>>> DefaultPrefService, or the Recorder if a persist=false attribute is
>>> added, apparently tries to record a 'null' value for an option. The
>>> two stacktraces are
>>>
>>>   [ERROR] Module threw exception
>>>   java.lang.NullPointerException
>>>         at
>>> java.util.prefs.AbstractPreferences.put(AbstractPreferences.java:224)
>>>         at
>>> org.scijava.prefs.DefaultPrefService.put(DefaultPrefService.java:183)
>>>         at
>>>
>>> org.scijava.module.DefaultModuleService.save(DefaultModuleService.java:278)
>>>         at
>>>
>>> org.scijava.module.process.SaveInputsPreprocessor.saveValue(SaveInputsPreprocessor.java:74)
>>>         at
>>>
>>> org.scijava.module.process.SaveInputsPreprocessor.process(SaveInputsPreprocessor.java:65)
>>>         at
>>> org.scijava.module.ModuleRunner.preProcess(ModuleRunner.java:104)
>>>         at org.scijava.module.ModuleRunner.run(ModuleRunner.java:156)
>>>         at org.scijava.module.ModuleRunner.call(ModuleRunner.java:126)
>>>         at org.scijava.module.ModuleRunner.call(ModuleRunner.java:65)
>>>         at
>>>
>>> org.scijava.thread.DefaultThreadService$2.call(DefaultThreadService.java:191)
>>>         at
>>> java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
>>>         at java.util.concurrent.FutureTask.run(FutureTask.java:138)
>>>         at
>>>
>>> java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
>>>         at
>>>
>>> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
>>>         at java.lang.Thread.run(Thread.java:662)
>>>
>>>   [ERROR] Module threw exception
>>>   java.lang.NullPointerException
>>>         at ij.plugin.frame.Recorder.addQuotes(Recorder.java:612)
>>>         at ij.plugin.frame.Recorder.recordOption(Recorder.java:362)
>>>         at net.imagej.legacy.IJ1Helper.recordOption(IJ1Helper.java:467)
>>>         at
>>>
>>> net.imagej.legacy.plugin.MacroRecorderPostprocessor.process(MacroRecorderPostprocessor.java:70)
>>>         at
>>> org.scijava.module.ModuleRunner.postProcess(ModuleRunner.java:116)
>>>         at org.scijava.module.ModuleRunner.run(ModuleRunner.java:176)
>>>         at org.scijava.module.ModuleRunner.call(ModuleRunner.java:126)
>>>         at org.scijava.module.ModuleRunner.call(ModuleRunner.java:65)
>>>         at
>>>
>>> org.scijava.thread.DefaultThreadService$2.call(DefaultThreadService.java:191)
>>>         at
>>> java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
>>>         at java.util.concurrent.FutureTask.run(FutureTask.java:138)
>>>         at
>>>
>>> java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
>>>         at
>>>
>>> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
>>>         at java.lang.Thread.run(Thread.java:662)
>>>
>>> _______________________________________________
>>> ImageJ-devel mailing list
>>> ImageJ-devel at imagej.net
>>> http://imagej.net/mailman/listinfo/imagej-devel
>>>
>>>
> --
> http://www.msc.univ-paris-diderot.fr/~daerr/
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://imagej.net/pipermail/imagej-devel/attachments/20150827/2437d645/attachment-0001.html>


More information about the ImageJ-devel mailing list