[ImageJ-devel] (headless) command execution

Stefan Posch posch at informatik.uni-halle.de
Thu Apr 10 09:01:27 CDT 2014

Hi Curtis,

thank you very much for the details answers (and I did not mean to press you with
regard to "delays" - this goes, of course, also for the future).

Though very helpful a few issues are still open:

>> What are the precoditions assumed when running a (headless) command
> What happens is highly dependent on *how* you invoke the command...

   Maybe I was unclear on this issue. May question is, what does a method 
   of a Command (e.g. its initializer, the run method) or rather the implementor
   may assumed to have "happend".

   Or other way round: in case the run-method of OpenFile command used in the tutorial 
   requires the initializer to have been executed:
   Is the run-method responsible to check, if it has already been executed (e.g. if called
   via the invokeWithArgs or invokeWihtMap methods of the tutorial) or not
   (if e.g. called via invokeFrmoJava).
   Or is it the callers responsibility to ensure the the initializer has been already been
   executed before actually running the OpenFile command (if it indeed requires the initializer to
   have been invoked beforehand).

   The same questions goes for the initializer method: may it assume that a single Dataset
   parameter has already been set? And if so, may it asume other prerequisites as well?
   E.g. it seems to me that the initializer of DuplicateImage would probably crash if
   the inputDisplay is null.
   Or is it the other way round: That whoever (indirectly) invokes the initializer is
   responsible for certain parameters to be set in advance.

   Besides interesting for a programmer of a Command we are interested in this issue
   to be able to wrap IJ2 commands in order to run them from our GUI (originaly design
   for alida operators), our command line runner,
   and to support them in our graphical editor for alida/mitobo operators and hopefully
   ij2 commands (at least head less and non DynamicCommands)

> 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.)

  I am not sure whether we can recycle all IJ2s preprocessors as there might be differences
  in the concept of parameter handling.

  But trying to reused (some of) them "by hand", not by using the Modules run method,
  I somehow got stuck, as obviously I do not understand the concepts
  properly. Maybe you are willing to help with this.

  In the attached zip of a tiny maven project using ij2 (2.0.0-beta-7.8)
  there is a command RunTestOp which tries to invoke a IJTestOp command "by hand".
  I first create a CommandInfo for IJTestOp, then a CommandModule for this info,
  collects all preprocessors and (try to) invoke them for the CommandModule created.
  I disabled invoking of the InitPreprocessor, as it crashes with a null pointer exception:
    Exception in thread "main" java.lang.NullPointerException
	at imagej.command.CommandModule.initialize(CommandModule.java:144)
	at imagej.module.process.InitPreprocessor.process(InitPreprocessor.java:61)
	at mainroutine.RunTestOp.main(RunTestOp.java:49)

  Additionally it seems to be that creating the CommandInfo already invokes preprocessors,
  however the initializer of IJTestOp is not invoked.
  And the ImageDisplayService is also still null.
  BTW: when diving a little bit into the code I realized that 
   Service and Context @Parameters of Commands are nor reflected in the CommandInfo.
   Somehow I was confused when I saw, that the ServicePreprocessor's process method
   looks for Service and Context parameters in the moduls CommandInfo.inputs().
   Could there ever by any?

> 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.
 Is it easily possible to state what makes a Command a DynamicCommand,
 and what is the difference to interactive() commands?

> 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. :-)
   We have one "command line oprunner" for alida 
   (which does not work interactively, thus can be used also from shell-scripts,
   e.g. for parameter tuning). And as noted above would like to support also 
   ij2 commands.

> 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.:
> public static final imagej.ImageJ IJ = new imagej.ImageJ();

   I was aware of the option to create a context but was/am reluctant to use
   it (in excess) due to overhead considerations. Just looking at the logging output
   it seems pretty time consuming. Is this impression wrong?

   In addition I am able to create only on instance of imagej.ImageJ, the second
   constructor crashes. See the file createContext.log in the zip which results from
   running RunTestOp. 
   (It seems to me the creating a second instance of DefaultLegacyService fails,
   and I faintly remeber to have read somewhere that only one instance of the 
   DefaultLegacyService may exist ??)

A new (and for the moment last) question:
  The Command EquationDataValues.java ist annotated as headless and has a @Parameter
  of type Button. Is this as intended?

Again thanks a lot

Best regards    Stefan

More information about the ImageJ-devel mailing list