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

Adrian Daerr adrian.daerr at univ-paris-diderot.fr
Thu Aug 27 10:35:32 CDT 2015


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/



More information about the ImageJ-devel mailing list