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.da...@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 <ctrue...@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.da...@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@imagej.net >>> http://imagej.net/mailman/listinfo/imagej-devel >>> >>> > -- > http://www.msc.univ-paris-diderot.fr/~daerr/ >
_______________________________________________ ImageJ-devel mailing list ImageJ-devel@imagej.net http://imagej.net/mailman/listinfo/imagej-devel