<div dir="ltr">Hi Stefan,<div><br></div><div>Very sorry for the long delay in reply. I should be faster in subsequent replies, if you have further questions.<br><div class="gmail_extra"><br></div><div class="gmail_extra"><div class="gmail_extra">

> What are the precoditions assumed when running a (headless) command</div><div class="gmail_extra"><br></div><div class="gmail_extra">What happens is highly dependent on *how* you invoke the command...</div><div class="gmail_extra">

<br></div><div class="gmail_extra">> may the command assume that its initializer, if any, has been executed<br></div><div class="gmail_extra">> prior to executing its run-Method?</div><div class="gmail_extra"><br></div>

<div class="gmail_extra"><div class="gmail_extra">I assume you are familiar with this tutorial:</div><div class="gmail_extra"><a href="https://github.com/imagej/imagej-tutorials/blob/master/execute-commands/src/main/java/ExecuteCommands.java">https://github.com/imagej/imagej-tutorials/blob/master/execute-commands/src/main/java/ExecuteCommands.java</a><br>

</div><div class="gmail_extra"><br></div><div class="gmail_extra">Note that when executing an ImageJ module using the ModuleService, the run methods (for the past couple of releases) have a "boolean process" flag. When process=true, the pre- and post-processing steps are run. This notably includes running the module initializer preprocessing step.</div>

</div><div class="gmail_extra"><br></div><div class="gmail_extra">> may the initializer-Method assume some of the parameter of the command</div><div class="gmail_extra">> already set (as e.g. a single ImageDisplay), and of course, which</div>

<div class="gmail_extra">> parameters?</div><div class="gmail_extra"><br></div><div class="gmail_extra">The InitPreprocessor calls module#initialize(), whose behavior can be overridden, but the default implementation of which is here:</div>

<div class="gmail_extra"><br></div><div class="gmail_extra"><a href="https://github.com/imagej/imagej/blob/imagej-2.0.0-beta-7.8/core/core/src/main/java/imagej/module/AbstractModule.java#L75">https://github.com/imagej/imagej/blob/imagej-2.0.0-beta-7.8/core/core/src/main/java/imagej/module/AbstractModule.java#L75</a><br>

</div><div class="gmail_extra"><br></div><div class="gmail_extra">In short: the module initializer is called first, followed by the individual initializers of each parameter, if any.</div><div class="gmail_extra"><br></div>

<div class="gmail_extra">As for *when* this occurs: the InitPreprocessor has "HIGH" priority:</div><div class="gmail_extra"><a href="https://github.com/imagej/imagej/blob/imagej-2.0.0-beta-7.8/core/core/src/main/java/imagej/module/process/InitPreprocessor.java#L50">https://github.com/imagej/imagej/blob/imagej-2.0.0-beta-7.8/core/core/src/main/java/imagej/module/process/InitPreprocessor.java#L50</a><br>

</div><div class="gmail_extra"><br></div><div class="gmail_extra">So it happens before many other preprocessors:</div><div class="gmail_extra"><br></div></div></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">

<div><div class="gmail_extra"><div class="gmail_extra"><span style="font-family:'courier new',monospace;font-size:x-small">$ grep 'priority = ' $(git ls-files | grep Preprocessor)</span></div></div></div>
<div>
<div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">core/core/src/main/java/imagej/display/ActiveDisplayPreprocessor.java:<span class="" style="white-space:pre">       </span>priority = Priority.VERY_HIGH_PRIORITY)</font></div>

</div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">core/core/src/main/java/imagej/module/process/CheckInputsPreprocessor.java:<span class="" style="white-space:pre">   </span>priority = InputHarvester.PRIORITY - 1)</font></div>

</div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">core/core/src/main/java/imagej/module/process/DebugPreprocessor.java:@Plugin(type = PreprocessorPlugin.class, priority = Priority.FIRST_PRIORITY)</font></div>

</div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">core/core/src/main/java/imagej/module/process/GatewayPreprocessor.java:<span class="" style="white-space:pre">       </span>priority = Priority.VERY_HIGH_PRIORITY)</font></div>

</div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">core/core/src/main/java/imagej/module/process/InitPreprocessor.java:@Plugin(type = PreprocessorPlugin.class, priority = Priority.HIGH_PRIORITY)</font></div>

</div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">core/core/src/main/java/imagej/module/process/LoadInputsPreprocessor.java:<span class="" style="white-space:pre">    </span>priority = Priority.VERY_LOW_PRIORITY + 1)</font></div>

</div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">core/core/src/main/java/imagej/module/process/SaveInputsPreprocessor.java:<span class="" style="white-space:pre">    </span>priority = Priority.VERY_LOW_PRIORITY - 1)</font></div>

</div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">core/core/src/main/java/imagej/module/process/ServicePreprocessor.java:<span class="" style="white-space:pre">       </span>priority = Priority.VERY_HIGH_PRIORITY)</font></div>

</div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">core/core/src/main/java/imagej/module/process/ValidityPreprocessor.java:<span class="" style="white-space:pre">      </span>priority = Priority.VERY_HIGH_PRIORITY + 1)</font></div>

</div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">core/data/src/main/java/imagej/data/display/ActiveImagePreprocessor.java:<span class="" style="white-space:pre">     </span>priority = Priority.VERY_HIGH_PRIORITY)</font></div>

</div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">core/ui/src/main/java/imagej/ui/FilePreprocessor.java:<span class="" style="white-space:pre">        </span>priority = Priority.VERY_LOW_PRIORITY + 1)</font></div>

</div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">core/ui/src/main/java/imagej/ui/UIPreprocessor.java:@Plugin(type = PreprocessorPlugin.class, priority = Priority.VERY_HIGH_PRIORITY)</font></div>

</div></div></div></blockquote><div><div class="gmail_extra"><div class="gmail_extra"><br></div><div class="gmail_extra">So the ones that happen before InitPreprocessor are:</div><div class="gmail_extra">1) DebugPreprocessor<br>

</div><div class="gmail_extra">2) ValidityPreprocessor<br></div><div class="gmail_extra"><div class="gmail_extra">3) ActiveDisplayPreprocessor</div><div class="gmail_extra">4) ActiveImagePreprocessor</div><div class="gmail_extra">

5) GatewayPreprocessor</div><div class="gmail_extra">6) ServicePreprocessor<br></div><div class="gmail_extra">7) UIPreprocessor</div><div><br></div><div>The DebugPreprocessor just logs some debugging output. The ValidityPreprocessor makes sure that the module is fundamentally well-formed (e.g., no "final" @Parameter variables, since those cannot be set via reflection). The other five (2-7) all set various types of variables based on the state of the ImageJ application context -- for example, all Service parameters are filled in. So that's why you never see the ImageJ UI prompt for them.</div>

<div><br></div><div>It should be case that Alida can reuse the default pre- and post-processing plugin stack -- in other words, you should be able to pass "process=true" to the ModuleService#run and everything will "just work". Let us know if not, and we can troubleshoot. As long as no UI has been shown, you will be in headless mode and no dialogs should ever be shown. (If one does pop up, it is probably a bug.)</div>

<div><br></div></div><div class="gmail_extra">> as an example, the DuplicateImage command adds input parameters to</div><div class="gmail_extra">> itself in its initializer-method depending on the inputDisplay. Thus</div>

<div class="gmail_extra">> is seems that DuplicateImage requires, that inputDisplay is set prior</div><div class="gmail_extra">> to calling its initializer and that the user is asked for further</div><div class="gmail_extra">

> parameters lateron.</div><div class="gmail_extra"><br></div><div class="gmail_extra">Yes, it works in that case because the ActiveDisplayPreprocessor runs before the InitPreprocessor, so inputDisplay is indeed already set.</div>

<div class="gmail_extra"><br></div><div class="gmail_extra">> more generally, are there parameters of commands set by the standard</div><div class="gmail_extra">> ij2 preprocessos besides a single unresolved Dataset? And is there an</div>

<div class="gmail_extra">> easy way to figure out what preprocessors are run in which order in</div><div class="gmail_extra">> the standard ij2 context?</div><div class="gmail_extra"><br></div><div class="gmail_extra">

Yes, the preprocessors are (by default) those mentioned above. You can get the list of them programmatically:</div><div class="gmail_extra"><br></div></div></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px">

<div><div class="gmail_extra"><font size="1" face="courier new, monospace">pre = pluginService.createInstancesOfType(PreprocessorPlugin.class)</font></div></div></blockquote><div><div class="gmail_extra"><br></div><div class="gmail_extra">

This gives you one instance each of each preprocessor, in priority order. Alternately, if you don't want to instantiate them but only inspect the plugin metadata:</div><div class="gmail_extra"><br></div><div class="gmail_extra">

<blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div class="gmail_extra"><font size="1" face="courier new, monospace">infos = pluginService.getPluginsOfType(PreprocessorPlugin.class)</font></div></blockquote>

<div></div></div><div class="gmail_extra"><br></div><div class="gmail_extra"><div class="gmail_extra">> What is your concept to run a headless command from command line (or</div><div class="gmail_extra">> shell script), which adds input parameters dependent on the value of</div>

<div class="gmail_extra">> other input parameters?</div><div class="gmail_extra"><br></div><div class="gmail_extra">On the CLI, we'll harvest values from the user at the same point in time that we currently do it via the UI. So most of the other preprocessing will be done; there will be a "CLIInputHarvesterPlugin" that prompts the user to type in these values using System.in or similar. We have not yet created this preprocessor plugin, but it would be very straightforward. If you need this, let me know -- it would be a fun side project. :-)</div>

<div class="gmail_extra"><br></div><div class="gmail_extra">> Do you encourcage to dynamically add input parameters to commands?</div><div class="gmail_extra"><br></div><div class="gmail_extra">Encourage? Definitely not. Unfortunately, there are certain commands that basically require this functionality. Use your IDE to check the subtype hierarchy of DynamicCommand to find them. But as a rule of thumb: headless modules should not be dynamic. Dynamic commands are *much* more challenging to support across many different environments (CellProfiler, KNIME, OMERO, Alida, etc.) *much* more challenging.</div>

<div class="gmail_extra"><br></div><div class="gmail_extra">> Is there (still) a static method to get hold of the context, as a</div><div class="gmail_extra">> while ago was possible via ImageJ.getContext() in order not to (very)</div>

<div class="gmail_extra">> often create a new context (or it the context impemented as a</div><div class="gmail_extra">> singelton)? And how does this work out if running command "truely"</div><div class="gmail_extra">

> headless that is from command line without ij2 GUI?</div><div class="gmail_extra"><br></div><div class="gmail_extra">The SciJava context is definitely not a singleton. But you can use it that way if you want: just create one a static variable in your own codebase somewhere; e.g.:</div>

<div class="gmail_extra"><div class="gmail_extra"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div class="gmail_extra"><font size="1" face="courier new, monospace"><br class="">public static final imagej.ImageJ IJ = new imagej.ImageJ();</font></div>

</blockquote><div></div></div></div><div class="gmail_extra"><br></div><div class="gmail_extra">Then you'll always have your ImageJ gateway, easily accessible from all your code. But I would caution you that if your design relies on statics like that, it will be fundamentally less flexible then if you always inject a Context in places where one is needed. We have taken great pains to make all of ImageJ2 work in that way...</div>

<div class="gmail_extra"><br></div><div class="gmail_extra">> is it remnants, that some ContextCommands have services as parameters</div><div class="gmail_extra">> as they - if I understand correctly - could retrievee the services</div>

<div class="gmail_extra">> from their contex?</div><div class="gmail_extra"><br></div><div class="gmail_extra">We feel that writing the services as @Parameters is cleaner, because those services are, in some sense, "inputs" to the module's operation. There are many ways to express a module's inputs, but our goal is for modules to declare their inputs in the most specific way possible. (We fall short of that goal in many places, but are very open to refactoring to improve things on a case by case basis.)</div>

<div class="gmail_extra"><br></div><div class="gmail_extra">For example, you could write:</div><div class="gmail_extra"><div class="gmail_extra"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div class="gmail_extra">

<font size="1" face="courier new, monospace"><br class="">@Parameter</font></div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div class="gmail_extra"><font size="1" face="courier new, monospace">private Context context;</font></div>

</blockquote><div></div></div></div><div class="gmail_extra"><br></div><div class="gmail_extra">And then call "context.service(ModuleService.class).run(...)" but that is less specific than:</div><div class="gmail_extra">

<br></div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div class="gmail_extra"><font size="1" face="courier new, monospace">@Parameter</font></div>

</blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div class="gmail_extra"><font size="1" face="courier new, monospace">private ModuleService moduleService;</font></div></blockquote></div></div>

</div><div class="gmail_extra"><br></div><div class="gmail_extra">And then calling "moduleService.run(...)". This latter form more clearly expresses the fact that it is actually the ModuleService, and not the Context as a whole, that is required for operation.</div>

<div class="gmail_extra"><br></div><div class="gmail_extra">As another example, you could declare an ImageDisplayService parameter and then use it to extract the active image display, then extract the active dataset from that, and finally process it. But it is much cleaner to declare the parameter as a Dataset in the first place, so that the module *could* be used with inputs besides just the active image display's active dataset. For other environments (CellProfiler/KNIME/OMERO/Alida/etc.), the notion of an "active image display" might not make sense, so using a Dataset inputs is better.</div>

<div class="gmail_extra"><br></div><div class="gmail_extra">> has ij2 already support to execute a headless command from the command</div><div class="gmail_extra">> line or shell script</div><div class="gmail_extra">

<br></div><div class="gmail_extra">I actually added something like that last week: a rudimentary interactive script interpreter. It is mainly for testing the ImageJ OPS project right now, but it supports whatever scripting language you want to use, with whatever ImageJ code you want to throw at it.</div>

<div class="gmail_extra"><br></div><div class="gmail_extra"><a href="https://github.com/imagej/imagej-scripting-cli">https://github.com/imagej/imagej-scripting-cli</a><br></div><div class="gmail_extra"><br></div><div class="gmail_extra">

Example of usage:</div><div class="gmail_extra"><br></div></div></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">$ git clone git://<a href="http://github.com/imagej/imagej-scripting-cli">github.com/imagej/imagej-scripting-cli</a></font></div>

</div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">... code is downloaded ...</font></div></div></div></div><div><div class="gmail_extra">

<div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">$ cd imagej-scripting-cli</font></div></div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra">

<font face="courier new, monospace" size="1">$ mvn</font></div></div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">... code compiles ...</font></div>

</div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">$ mvn exec:exec</font></div></div></div></div><div><div class="gmail_extra"><div class="gmail_extra">

<div class="gmail_extra"><font face="courier new, monospace" size="1">... Maven spits out some stuff ...</font></div></div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">ImageJ script interpreter: javascript</font></div>

</div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">> dataset = ij.dataset().open("/Users/curtis/data/toucan.png");</font></div>

</div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">toucan.png</font></div></div></div></div><div><div class="gmail_extra"><div class="gmail_extra">

<div class="gmail_extra"><font face="courier new, monospace" size="1">> w = dataset.max(0);</font></div></div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">160</font></div>

</div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">> h = dataset.max(1);</font></div></div></div></div><div><div class="gmail_extra">

<div class="gmail_extra"><div class="gmail_extra"><font face="courier new, monospace" size="1">148</font></div></div></div></div></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div class="gmail_extra">

<div class="gmail_extra"><div><div><font face="courier new, monospace" size="1">> future = ij.command().run("imagej.plugins.commands.app.AboutImageJ", true, []);</font></div></div></div></div></div><div><div class="gmail_extra">

<div class="gmail_extra"><div><font face="courier new, monospace" size="1">java.util.concurrent.FutureTask@2698dd08</font></div></div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div><font face="courier new, monospace" size="1">> module = future.get();</font></div>

</div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div><font face="courier new, monospace" size="1">imagej.plugins.commands.app.AboutImageJ</font></div></div></div></div><div><div class="gmail_extra">

<div class="gmail_extra"><div><font face="courier new, monospace" size="1">> module.getOutput("display").getClass();</font></div></div></div></div><div><div class="gmail_extra"><div class="gmail_extra"><div>
<font face="courier new, monospace" size="1">class imagej.data.display.DefaultImageDisplay</font></div>
</div></div></div></blockquote><div><div class="gmail_extra"><div class="gmail_extra"><div><br></div></div><div class="gmail_extra">Once we have the CLI input harvesting plugin, this will be a little slicker in that "ij.module().run(...)" and "ij.command().run(...)" will be usable for modules that take "real" inputs.</div>

</div><div class="gmail_extra"><br></div><div class="gmail_extra">Regards,</div><div class="gmail_extra">Curtis<br><br><div class="gmail_quote">On Thu, Mar 13, 2014 at 4:39 AM, Stefan Posch <span dir="ltr"><<a href="mailto:posch@informatik.uni-halle.de" target="_blank">posch@informatik.uni-halle.de</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Hi Curtis, hi Johannes,<br>
<br>
we have a few questions regarding commands and command execution<br>
to wrap them for our graphical editor and also command line execution<br>
of operators resp. commands.<br>
<br>
What are the precoditions assumed when running a (headless) command<br>
<br>
  o may the command assume that its initializer, if any, has been executed prior to executing its run-Method?<br>
<br>
  o may the initializer-Method assume some of the parameter of the command already set<br>
    (as e.g. a single ImageDisplay), and of course, which parameters?<br>
<br>
    as an example, the DuplicateImage command adds input parameters to itself<br>
    in its initializer-method depending on the inputDisplay.<br>
    Thus is seems that DuplicateImage requires, that inputDisplay is set prior to<br>
    calling its initializer and that the user is asked for further parameters lateron.<br>
<br>
  o more generally, are there parameters of commands set by the standard ij2 preprocessos<br>
    besides a single unresolved Dataset?<br>
    And is there an easy way to figure out<br>
    what preprocessors are run in which order in the standard ij2 context?<br>
<br>
- What is your concept to run a headless command from command line (or shell script), which<br>
  adds input parameters dependent on the value of other input parameters?<br>
<br>
  Do you encourcage to dynamically add input parameters to commands?<br>
<br>
- Is there (still) a static method to get hold of the context, as a while ago was<br>
  possible via ImageJ.getContext() in order not to (very) often create a new<br>
  context (or it the context impemented as a singelton)?<br>
  And how does this work out if running command "truely" headless that is<br>
  from command line without ij2 GUI?<br>
<br>
- is it remnants, that some ContextCommands have services as parameters<br>
  as they - if I understand correctly - could retrievee the services from their contex?<br>
<br>
- has ij2 already support to execute a headless command from the command line or shell script<br>
<br>
Thanks a lot and cheers<br>
<br>
Stefan<br>
--<br>
Prof. Dr.-Ing. Stefan Posch,<br>
        Institut fuer Informatik, Martin-Luther-Universitaet Halle-Wittenberg<br>
        Von-Seckendorff-Platz 1, 06099 Halle (Saale)<br>
phone:  <a href="tel:%2B%2B49%20345%2055-24728" value="+493455524728">++49 345 55-24728</a><br>
fax:    <a href="tel:%2B%2B49%20345%2055-27039" value="+493455527039">++49 345 55-27039</a><br>
e-mail: <a href="mailto:Stefan.Posch@informatik.uni-halle.de">Stefan.Posch@informatik.uni-halle.de</a><br>
www:    <a href="http://www.informatik.uni-halle.de/~posch/" target="_blank">www.informatik.uni-halle.de/~posch/</a><br>
<br>
_______________________________________________<br>
ImageJ-devel mailing list<br>
<a href="mailto:ImageJ-devel@imagej.net">ImageJ-devel@imagej.net</a><br>
<a href="http://imagej.net/mailman/listinfo/imagej-devel" target="_blank">http://imagej.net/mailman/listinfo/imagej-devel</a><br>
</blockquote></div><br></div></div></div>