scijava-common
scijava-common copied to clipboard
Mark non-required inputs as resolved if all required inputs are resolved
As reported by @cniedwor, see this discussion on the forum.
Consider the following Groovy script:
#@ ScriptService scripts
script = """
\n#@ String (required = true, persist = false) text1
\n#@ String (value = "not required", required = false, persist = false) text2
println text1
println text2
"""
scripts.run("Foo.groovy", script, true).get() // displays dialog, as expected
scripts.run("Foo.groovy", script, true, ["text1": "Bar"]).get() // should not display dialog
scripts.run("Foo.groovy", script, true, ["text1": "Bar", "text2": "Really?"]).get() // doesn't display, as expected
null
To be consistent with IJ1 macro behavior (where default parameters get automatically filled when not included in an option string of run("Some Plugin", "")), the second scripts.run call in the above script should not display a dialog.
We need some logic to mark all remaining (non-required) inputs as resolved as soon as all required inputs are resolved.
I am ambivalent. Imagine a case where all parameters are marked optional. With this proposal, no dialog would ever appear. We might need to introduce a new state flag like triggersDialogGenerationWhenNotResolved (but with a less horrible name, obviously).
Another possibility would be that, like IJ1, modules could run in one of two modes: programmatic or user. And in programmatic mode, no dialogs appear. But this is a half-baked idea—needs further consideration.
I see where you are going with this, however If all parameters of e.g. a plugin are optional, I personally would not expect a dialog to appear in a scripted run of the plugin. For me it would make more sense to specifically ask the user in the script that does the call for the relevant optional parameters and then pass them on.
Alternatively, would it be possible to control the dialog display from the script that does the call to the plugin? If it is possible to add parameters to the script that get passed on to the code injection mechanism rather than the plugin itself you could have a flag such as param.show_dialog = true that could let the calling script decide whether a dialog should be shown.
Regarding backwards compatibility with IJ1, I would expect a difference between these two macro calls:
run("ModuleWithParameters"); // will show a dialog
run("ModuleWithParameters", ""); // won't show a dialog
@cniedwor wrote:
would it be possible to control the dialog display from the script that does the call to the plugin?
If instead of using an IJ1 macro call, you call ModuleService.run (from any full-fledged script language) like in @stelfrich's example on the forum thread:
run(M module, boolean process, Object... inputs)
... you can use the boolean process flag to determine if the parameter harvesting (preprocessing) should kick in.
Hmmm, I doubt I will be successful in weaning off everyone from IJ1 macro, as much as I dislike that language.
@imagejan wrote:
... you can use the boolean process flag to determine if the parameter harvesting (preprocessing) should kick in.
If preprocessing is completely disabled will that cause non-user parameters like the LogService to remain null as well?
If preprocessing is completely disabled will that cause non-user parameters like the LogService to remain null as well?
As far as I know, that's the case. You can, however, mark the String inputs as resolved manually:
#@ ModuleService moduleService
moduleInfo = moduleService.getModuleById("script:Plugins/Script_.groovy");
module = moduleService.createModule(moduleInfo);
// Mark the input as resolved s.t. it is not harvested
module.resolveInput("text1");
See also some related discussion in https://github.com/scijava/scijava-common/issues/191.
We should still make it possible to run from macro without having to provide values for inputs that have visibility=MESSAGE.
Another use case where this is relevant: ilastik4ij, see https://github.com/ilastik/ilastik4ij/pull/65.
Let's say you have:
#@ Dataset inputImage
#@ Dataset (required = false) predictionMask
If you now have a macro call like:
run("ilastik Pixel Classification", "inputImage=[My Test Image]")
... you don't want any dialog to be shown for the "missing" predictionMask parameter.
/cc @Tomaz-Vieira @k-dominik
This issue has been mentioned on Image.sc Forum. There might be relevant details there:
https://forum.image.sc/t/run-plugin-headless-pendant-drop/43349/2
If you now have a macro call like:
run("ilastik Pixel Classification", "inputImage=[My Test Image]")... you don't want any dialog to be shown for the "missing"
predictionMaskparameter.
What about using:
run("ilastik Pixel Classification", "inputImage=[My Test Image] predictionMask=null")
to resolve the predictionMask parameter so it doesn't get harvested?
I still think we're going to cause problems if we never show a dialog when only optional parameters exist. The problem is that in some scenarios people are going to want a dialog, and in others, they aren't. One idea is to have a distinction between "non-required and leaning toward the default" versus "non-required but leaning toward asking the user for it". But this would provide context per SciJava module input, not per scenario.
If all parameters of e.g. a plugin are optional, I personally would not expect a dialog to appear in a scripted run of the plugin.
Yeah, I personally would not expect such s dialog to appear in a scripted run, period. I.e.: regardless of whether or not there are any required parameters left. If there are required parameters left when the input harvesting step is reached, but the plugin is being run programmatically, I think the execution should fail with "a Foo is required but none exists" style error.
would it be possible to control the dialog display from the script that does the call to the plugin?
Yes, that's probably the way to go. Then if someone really does want to script a programmatic plugin invocation, but which pops a dialog for needed inputs, they can do it. However, it won't fully solve the conundrum here, because your choices from script would then become: 1) fail the plugin execution if any required inputs are not populated; or 2) pop a dialog if any (required or not) inputs are not populated. I guess we want to have three modes: the previous two, plus: 3) pop a dialog only if required inputs are not populated...