(headless) command execution

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

(headless) command execution

Stefan Posch
Hi Curtis, hi Johannes,

we have a few questions regarding commands and command execution
to wrap them for our graphical editor and also command line execution
of operators resp. commands.

What are the precoditions assumed when running a (headless) command

  o may the command assume that its initializer, if any, has been executed prior to executing its run-Method?

  o may the initializer-Method assume some of the parameter of the command already set
    (as e.g. a single ImageDisplay), and of course, which parameters?

    as an example, the DuplicateImage command adds input parameters to itself
    in its initializer-method depending on the inputDisplay.
    Thus is seems that DuplicateImage requires, that inputDisplay is set prior to
    calling its initializer and that the user is asked for further parameters lateron.

  o more generally, are there parameters of commands set by the standard ij2 preprocessos
    besides a single unresolved Dataset?
    And is there an easy way to figure out
    what preprocessors are run in which order in the standard ij2 context?

- What is your concept to run a headless command from command line (or shell script), which
  adds input parameters dependent on the value of other input parameters?

  Do you encourcage to dynamically add input parameters to commands?

- Is there (still) a static method to get hold of the context, as a while ago was
  possible via ImageJ.getContext() in order not to (very) often create a new
  context (or it the context impemented as a singelton)?
  And how does this work out if running command "truely" headless that is
  from command line without ij2 GUI?

- is it remnants, that some ContextCommands have services as parameters
  as they - if I understand correctly - could retrievee the services from their contex?

- has ij2 already support to execute a headless command from the command line or shell script

Thanks a lot and cheers

Stefan
--
Prof. Dr.-Ing. Stefan Posch,
        Institut fuer Informatik, Martin-Luther-Universitaet Halle-Wittenberg
        Von-Seckendorff-Platz 1, 06099 Halle (Saale)
phone:  ++49 345 55-24728
fax: ++49 345 55-27039
e-mail: [hidden email]
www:    www.informatik.uni-halle.de/~posch/

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: (headless) command execution

Curtis Rueden
Hi Stefan,

Apologies for the delay in reply. Just wanted to let you know that we are not ignoring you -- the timing was just rough because we recently returned from an intense hackathon (see https://github.com/imagej/imagej-ops if interested) and are still catching up on the backlog. I will make an effort to reply to your questions within the next few days.

Regards,
Curtis


On Thu, Mar 13, 2014 at 4:39 AM, Stefan Posch <[hidden email]> wrote:
Hi Curtis, hi Johannes,

we have a few questions regarding commands and command execution
to wrap them for our graphical editor and also command line execution
of operators resp. commands.

What are the precoditions assumed when running a (headless) command

  o may the command assume that its initializer, if any, has been executed prior to executing its run-Method?

  o may the initializer-Method assume some of the parameter of the command already set
    (as e.g. a single ImageDisplay), and of course, which parameters?

    as an example, the DuplicateImage command adds input parameters to itself
    in its initializer-method depending on the inputDisplay.
    Thus is seems that DuplicateImage requires, that inputDisplay is set prior to
    calling its initializer and that the user is asked for further parameters lateron.

  o more generally, are there parameters of commands set by the standard ij2 preprocessos
    besides a single unresolved Dataset?
    And is there an easy way to figure out
    what preprocessors are run in which order in the standard ij2 context?

- What is your concept to run a headless command from command line (or shell script), which
  adds input parameters dependent on the value of other input parameters?

  Do you encourcage to dynamically add input parameters to commands?

- Is there (still) a static method to get hold of the context, as a while ago was
  possible via ImageJ.getContext() in order not to (very) often create a new
  context (or it the context impemented as a singelton)?
  And how does this work out if running command "truely" headless that is
  from command line without ij2 GUI?

- is it remnants, that some ContextCommands have services as parameters
  as they - if I understand correctly - could retrievee the services from their contex?

- has ij2 already support to execute a headless command from the command line or shell script

Thanks a lot and cheers

Stefan
--
Prof. Dr.-Ing. Stefan Posch,
        Institut fuer Informatik, Martin-Luther-Universitaet Halle-Wittenberg
        Von-Seckendorff-Platz 1, 06099 Halle (Saale)
phone:  <a href="tel:%2B%2B49%20345%2055-24728" value="+493455524728" target="_blank">++49 345 55-24728
fax:    <a href="tel:%2B%2B49%20345%2055-27039" value="+493455527039" target="_blank">++49 345 55-27039
e-mail: [hidden email]
www:    www.informatik.uni-halle.de/~posch/

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel


_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: (headless) command execution

Curtis Rueden
In reply to this post by Stefan Posch
Hi Stefan,

Very sorry for the long delay in reply. I should be faster in subsequent replies, if you have further questions.

> What are the precoditions assumed when running a (headless) command

What happens is highly dependent on *how* you invoke the command...

> may the command assume that its initializer, if any, has been executed
> prior to executing its run-Method?

I assume you are familiar with this tutorial:

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.

> may the initializer-Method assume some of the parameter of the command
> already set (as e.g. a single ImageDisplay), and of course, which
> parameters?

The InitPreprocessor calls module#initialize(), whose behavior can be overridden, but the default implementation of which is here:


In short: the module initializer is called first, followed by the individual initializers of each parameter, if any.

As for *when* this occurs: the InitPreprocessor has "HIGH" priority:

So it happens before many other preprocessors:

$ grep 'priority = ' $(git ls-files | grep Preprocessor)
core/core/src/main/java/imagej/display/ActiveDisplayPreprocessor.java: priority = Priority.VERY_HIGH_PRIORITY)
core/core/src/main/java/imagej/module/process/CheckInputsPreprocessor.java: priority = InputHarvester.PRIORITY - 1)
core/core/src/main/java/imagej/module/process/DebugPreprocessor.java:@Plugin(type = PreprocessorPlugin.class, priority = Priority.FIRST_PRIORITY)
core/core/src/main/java/imagej/module/process/GatewayPreprocessor.java: priority = Priority.VERY_HIGH_PRIORITY)
core/core/src/main/java/imagej/module/process/InitPreprocessor.java:@Plugin(type = PreprocessorPlugin.class, priority = Priority.HIGH_PRIORITY)
core/core/src/main/java/imagej/module/process/LoadInputsPreprocessor.java: priority = Priority.VERY_LOW_PRIORITY + 1)
core/core/src/main/java/imagej/module/process/SaveInputsPreprocessor.java: priority = Priority.VERY_LOW_PRIORITY - 1)
core/core/src/main/java/imagej/module/process/ServicePreprocessor.java: priority = Priority.VERY_HIGH_PRIORITY)
core/core/src/main/java/imagej/module/process/ValidityPreprocessor.java: priority = Priority.VERY_HIGH_PRIORITY + 1)
core/data/src/main/java/imagej/data/display/ActiveImagePreprocessor.java: priority = Priority.VERY_HIGH_PRIORITY)
core/ui/src/main/java/imagej/ui/FilePreprocessor.java: priority = Priority.VERY_LOW_PRIORITY + 1)
core/ui/src/main/java/imagej/ui/UIPreprocessor.java:@Plugin(type = PreprocessorPlugin.class, priority = Priority.VERY_HIGH_PRIORITY)

So the ones that happen before InitPreprocessor are:
1) DebugPreprocessor
2) ValidityPreprocessor
3) ActiveDisplayPreprocessor
4) ActiveImagePreprocessor
5) GatewayPreprocessor
6) ServicePreprocessor
7) UIPreprocessor

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.

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

> as an example, the DuplicateImage command adds input parameters to
> itself in its initializer-method depending on the inputDisplay. Thus
> is seems that DuplicateImage requires, that inputDisplay is set prior
> to calling its initializer and that the user is asked for further
> parameters lateron.

Yes, it works in that case because the ActiveDisplayPreprocessor runs before the InitPreprocessor, so inputDisplay is indeed already set.

> more generally, are there parameters of commands set by the standard
> ij2 preprocessos besides a single unresolved Dataset? And is there an
> easy way to figure out what preprocessors are run in which order in
> the standard ij2 context?

Yes, the preprocessors are (by default) those mentioned above. You can get the list of them programmatically:

pre = pluginService.createInstancesOfType(PreprocessorPlugin.class)

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:

infos = pluginService.getPluginsOfType(PreprocessorPlugin.class)

> What is your concept to run a headless command from command line (or
> shell script), which adds input parameters dependent on the value of
> other input parameters?

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

> Do you encourcage to dynamically add input parameters to commands?

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.

> Is there (still) a static method to get hold of the context, as a
> while ago was possible via ImageJ.getContext() in order not to (very)
> often create a new context (or it the context impemented as a
> singelton)? And how does this work out if running command "truely"
> headless that is from command line without ij2 GUI?

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();

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

> is it remnants, that some ContextCommands have services as parameters
> as they - if I understand correctly - could retrievee the services
> from their contex?

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

For example, you could write:

@Parameter
private Context context;

And then call "context.service(ModuleService.class).run(...)" but that is less specific than:

@Parameter
private ModuleService moduleService;

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.

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.

> has ij2 already support to execute a headless command from the command
> line or shell script

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.


Example of usage:

... code is downloaded ...
$ cd imagej-scripting-cli
$ mvn
... code compiles ...
$ mvn exec:exec
... Maven spits out some stuff ...
ImageJ script interpreter: javascript
> dataset = ij.dataset().open("/Users/curtis/data/toucan.png");
toucan.png
> w = dataset.max(0);
160
> h = dataset.max(1);
148
> future = ij.command().run("imagej.plugins.commands.app.AboutImageJ", true, []);
java.util.concurrent.FutureTask@2698dd08
> module = future.get();
imagej.plugins.commands.app.AboutImageJ
> module.getOutput("display").getClass();
class imagej.data.display.DefaultImageDisplay

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.

Regards,
Curtis

On Thu, Mar 13, 2014 at 4:39 AM, Stefan Posch <[hidden email]> wrote:
Hi Curtis, hi Johannes,

we have a few questions regarding commands and command execution
to wrap them for our graphical editor and also command line execution
of operators resp. commands.

What are the precoditions assumed when running a (headless) command

  o may the command assume that its initializer, if any, has been executed prior to executing its run-Method?

  o may the initializer-Method assume some of the parameter of the command already set
    (as e.g. a single ImageDisplay), and of course, which parameters?

    as an example, the DuplicateImage command adds input parameters to itself
    in its initializer-method depending on the inputDisplay.
    Thus is seems that DuplicateImage requires, that inputDisplay is set prior to
    calling its initializer and that the user is asked for further parameters lateron.

  o more generally, are there parameters of commands set by the standard ij2 preprocessos
    besides a single unresolved Dataset?
    And is there an easy way to figure out
    what preprocessors are run in which order in the standard ij2 context?

- What is your concept to run a headless command from command line (or shell script), which
  adds input parameters dependent on the value of other input parameters?

  Do you encourcage to dynamically add input parameters to commands?

- Is there (still) a static method to get hold of the context, as a while ago was
  possible via ImageJ.getContext() in order not to (very) often create a new
  context (or it the context impemented as a singelton)?
  And how does this work out if running command "truely" headless that is
  from command line without ij2 GUI?

- is it remnants, that some ContextCommands have services as parameters
  as they - if I understand correctly - could retrievee the services from their contex?

- has ij2 already support to execute a headless command from the command line or shell script

Thanks a lot and cheers

Stefan
--
Prof. Dr.-Ing. Stefan Posch,
        Institut fuer Informatik, Martin-Luther-Universitaet Halle-Wittenberg
        Von-Seckendorff-Platz 1, 06099 Halle (Saale)
phone:  <a href="tel:%2B%2B49%20345%2055-24728" value="+493455524728">++49 345 55-24728
fax:    <a href="tel:%2B%2B49%20345%2055-27039" value="+493455527039">++49 345 55-27039
e-mail: [hidden email]
www:    www.informatik.uni-halle.de/~posch/

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel


_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: (headless) command execution

Stefan Posch
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

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: (headless) command execution - missing project files

Stefan Posch
sorry. I forgot to attach the project ... here it comes.

Stefan

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel

ij2-test.zip (8K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: (headless) command execution

Curtis Rueden
In reply to this post by Stefan Posch
Hi Stefan,

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

No worries, you were clear. The term "preconditions" is a technical software engineering term, so I know what you meant. I just dodged the question a bit there, figuring my detailed answers later would clarify everything. But I guess it still was not clear, sorry...

* The run() method of a module can assume that all required input parameters have been filled (i.e., are non-null). And the corresponding post-condition of run() is that all required output parameters are now filled.

* The initialize() method of a module cannot necessarily assume anything about the state of its parameters. As you pointed out, ImageJ2 has various commands right now that *do* assume certain parameters have been filled via preprocessing. This works in practice (at least from the ImageJ application), but is not particularly rigorous.

* Similarly, ImageJ2 has several commands which assume their initializer has been called, but it is not stated as a formal precondition. Most probably it makes sense to state that in the javadoc, would you agree? In other words: if you aren't going to include the InitPreprocessor in the preprocessing chain, you are still somehow responsible for calling module.initialize() before calling module.run(). Is that fair?

So the main sticky point is what to do about initialize() requiring certain parameters to be already filled. This is useful for dynamic modules, but also just for computing defaults -- e.g., setting default brightness/contrast min & max values to the current display min max of the input image. So it seems there are two "layers" of input parameters: those needed before initialize() and those not needed for it.

Maybe we need a way to formally flag these "required before initialize" parameters in the annotation? What do you think? Would that help you?

In any case, now is the perfect time to get the module framework fully solidified, since we are on the cusp of migrating it into the (non-image-specific) SciJava layer. After the June 1 release, we will not be able to introduce any more breaking changes.

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

One thing that may interest you is the recent ImageJ OPS announcement:

An Op is just an ImageJ command intended to be fully functional -- i.e., all inputs and outputs declared explicitly as parameters, with no side effects. They are essentially "lower level" commands intended for image processing, and they might be another good integration point for Alida. Really, your current implementation should gain access to them "for free" since they are just a subtype of Commands, but perhaps it makes sense to special case them somehow since they are in many ways friendlier for headless & non-dynamic situations?

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

Actually, there is a fair chance you could. It's just that the ActiveFooPreprocessor style things may either: A) always return null for you; or B) be populated via some alternate means that you can specify by extending the DefaultDisplayService, DefaultImageDisplayService, etc., with overridden method implementations that draw the "active" objects from somewhere else.

Alternately, it is just fine if they are always null, as long as you pass them in via the moduleService#run method "Object..." or "Map<String, Object>" arguments.

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

It seems the mailing list stripped your attachment. Can you please post on GitHub?

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

That error indicates that the CommandModule did not have a context injected properly. From your description, it sounds like your code is more low-level than it needs to be. But I'd have to see the code to be certain.

For customizing which pre- and post-processors get run, it is enough to do:

pre = pluginService.createInstancesOfType(PreprocessorPlugin.class);
post = pluginService.createInstancesOfType(PostprocessorPlugin.class);
// then loop over pre and post, removing blacklisted entries
// alternately, loop over pre and post, populating whitelists with desired entries
moduleService.run(moduleInfo, pre, post, inputName1, inputValue1, inputName2, inputValue2, ...etc...)

Is that how you were doing it?

// or if you really want to avoid creating instances which you then throw away...
// you can write:
//   infos = pluginService.getPluginsOfType(PreprocessorPlugin.class)
// and/or:
//   info = pluginService.getPlugin(InitPreprocessor.class)
// get the infos you want onto a list and then call:
//   pre = pluginService.createInstances(info);
// or even this way:
//   pre.add(pluginService.createInstance(InitPreprocessor.class);
// the advantage being that all context is injected automatically for you.

> And the ImageDisplayService is also still null.

Regardless of which preprocessors you use, such service parameters should not be null, as long as the context has that service associated with it; see below. Again, I'm guessing you didn't inject the context...

> 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?

Yes. :-) You have found a wrinkle that I didn't expect anyone to notice yet.

In the case of Modules generally (not just Commands), there can certainly be Service and Context parameters. The prime example there is scripts: we want to annotate scripts written various languages such as Jython with a header comment that declares all the typed input and output parameters, including services. The ServicePreprocessor will take care of filling them, and the ModuleInfo API will include them when iterating the inputs.

However, in the case of Commands specifically, the Service and Context fields annotated with @Parameter will actually *not* be reported as parameters by the ModuleInfo API. It was changed 8 months ago:


Unfortunately, I did not bother to elaborate in my commit message on *why* "we do then need to have a special exclusion for such parameters in the CommandInfo wrapper" and I've forgotten what problems it caused not to have that special exclusion.

So this is certainly inconsistent and confusing. Do you think that Commands should also include service and context inputs when iterating them? If so, we can try removing that exclusion and see what explodes... ;-)

> 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?

Regardless of how you do things, you should be able to keep reusing the same context. You can either create one static one as I described, or you can create one non-static one and then pass it around everywhere to things that need it (either via constructors, setters, or by injecting it as a @Parameter -- whatever pattern suits your fancy).

That said, we have put a fair amount of effort into optimizing context creation. What it comes down to is which services are part of the context. Creating a full-blown ImageJ context (all available services, huge classpath) on my system takes about 2000ms right now; creating one with only core SciJava services takes 450ms. This is actually much slower than last I checked, probably due to the Eclipse Helper making absolutely sure the annotation metadata is up to date. We will certainly be optimizing this more in the future -- e.g., if you run outside of the Eclipse development environment, the Eclipse Helper should not bog things down.

Also, as of https://github.com/scijava/scijava-common/commit/0fd0e2916d39505e792f1bbd8e56e3de0f1f8904, the log spam when creating a context has been eliminated by default. (It got to the point where those log messages were really annoying me. ;-) The next release will of course include this change.

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

Indeed, trying to create two contexts each with a DefaultLegacyService fails right now. The reasons are complex, but in short, it is a bug. And unfortunately one we will not be able to address before the June release. The problem can be avoided by either: A) calling context.dispose() on the first context before creating the second one; or B) creating additional contexts beyond the first without a LegacyService (admittedly awkward to code since you can no longer use the default Context() constructor).

If you urgently need support for multiple simultaneous ImageJ contexts created with the default constructor while ij-legacy is on the classpath, and you want to try fixing the bug yourself, we would be happy to elaborate further so that you can give it a shot.

> The Command EquationDataValues.java ist annotated as headless and has
> a @Parameter of type Button. Is this as intended?

Yes, the "Button" is just a marker interface indicating that the input harvester UI should render a button with that label which when pressed calls that callback method. In the case of no input harvester UI, there will be no button, and the callback will hence never occur. But that should not interfere with headless operation. Such Button parameters can be safely ignored on your end.

Note that we recently made the Button interface extend the Optional interface to clarify the fact that Button "values" are always allowed to be null, even if the @Parameter of the Button does not declare "required = false". See: https://github.com/imagej/imagej/commit/09ed9f9b6178312d86083094732b2a1201f82e16

Let's hope our next exchange does not need to be quite so long winded...

Regards,
Curtis


On Thu, Apr 10, 2014 at 9:01 AM, Stefan Posch <[hidden email]> wrote:
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

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel


_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: (headless) command execution - missing project files

Curtis Rueden
In reply to this post by Stefan Posch
Hi Stefan,

Thanks. Rather than doing this:

  CommandInfo testopInfo = new CommandInfo(IJTestOp.class.getName());
  testopModule = (CommandModule) testopInfo.createModule();

I suggest instead:

  CommandInfo testopInfo = commandService.getCommand(IJTestOp.class);
  testopModule = (CommandModule) moduleService.createModule(testopInfo);

Otherwise, you will have lots of problems because the created module will not know its context. If you use the service methods, all the injections are taken care of for you; see:


Also, rather than:

  testopModule.setInput("ivalIn", 321);
  testopModule.getCommand().run();

I would use the service method:

  moduleService.run(testopModule, false, "ivalIn", 321);

Regards,
Curtis


On Thu, Apr 10, 2014 at 3:13 PM, Stefan Posch <[hidden email]> wrote:
sorry. I forgot to attach the project ... here it comes.

Stefan

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel



_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: (headless) command execution

Stefan Posch
In reply to this post by Curtis Rueden
Hi Curtis,

thanks for your reply, we are getting ahead, but still questions for running commands

>    * The run() method of a module can assume that all required input
>    parameters have been filled (i.e., are non-null). And the corresponding
>    post-condition of run() is that all required output parameters are now
>    filled.
perfect, the same with us

>    * The initialize() method of a module cannot necessarily assume
>    anything about the state of its parameters. As you pointed out, ImageJ2
>    has various commands right now that *do* assume certain parameters have
>    been filled via preprocessing. This works in practice (at least from
>    the ImageJ application), but is not particularly rigorous.
>    * Similarly, ImageJ2 has several commands which assume their
>    initializer has been called, but it is not stated as a formal
>    precondition. Most probably it makes sense to state that in the
>    javadoc, would you agree? In other words: if you aren't going to
>    include the InitPreprocessor in the preprocessing chain, you are still
>    somehow responsible for calling module.initialize() before calling
>    module.run(). Is that fair?
again: perfect

>    So the main sticky point is what to do about initialize() requiring
>    certain parameters to be already filled. This is useful for dynamic
>    modules, but also just for computing defaults -- e.g., setting default
>    brightness/contrast min & max values to the current display min max of
>    the input image. So it seems there are two "layers" of input
>    parameters: those needed before initialize() and those not needed for
>    it.
>    Maybe we need a way to formally flag these "required before initialize"
>    parameters in the annotation? What do you think? Would that help you?
This would be different from autoFill() ?

Yes and no.

In a way it makes responsibilities clear, in so far I feel comfortable with it.

However, it seems to me that there are (potentially very heavy) restrictions
on the parameters which may be filled in advance (automaticcal and not by the user)
in a sensible way. As far as I understand ij2 fills in parameters with what I think
you called AutoFooPreprocessors, so active image and active display?
I cannot come up with further ones. How would we fill in an int parameter
without knowledge of its meaning/sematics?
And even for images is only possible for commands with exactly one image or display.
Obviously we could introduce a further flag for an image parameter to notify,
that I what to be assigned the active image with. But this seems pretty specific.
And probably not generic to be introduce to scijava but rather deferred to the
"application", e.g. imagej.
And there might be aplications which call for more the two layers?

Summing up, I am afraid that I do not have a cute idea.
Of course I appreciate the functionality the set initial values or make the type
of parameters depending on image features (like dimensionality, range of values).
Still adding parameters seems awkward to be. Could we come by with "only" changing
types of parameters. E.g. for DuplicateImage not add one parameter for each axes rather
have one array parameter with its length determined by the dimensionality?
And may be indicate via annotations, depending on which other parameter(s) the
type of this parameter will change?

Rather more question:
Thinking of module and parameter intitalizers it seems to be that I get more unsure.
Is it exactly to do processing between the two layers of parameters.
And it is to add further parameters and set initial values to parameters?
Are initial parameter values execulsively meant to serve as defaults for the
user or is it required that some initial values are set (in order to properly
run the command)?

If so: would this mean that for running a command head less in a non interactive way
makes the distiction of two layers is obsolete?

>    One thing that may interest you is the recent ImageJ OPS announcement:
>       [1]http://developer.imagej.net/2014/04/04/announcing-imagej-ops
>    An Op is just an ImageJ command intended to be fully functional --
That sounds great ...

>   Hi Stefan,
>   Thanks. Rather than doing this:
>     CommandInfo testopInfo = new CommandInfo(IJTestOp.class.getName());
>     testopModule = (CommandModule) testopInfo.createModule();
>   I suggest instead:
>     CommandInfo testopInfo = commandService.getCommand(IJTestOp.class);
>     testopModule = (CommandModule)
>   moduleService.createModule(testopInfo);

the advise you gave works fine, however only for running a module for a given Command once.
  (see attached source of RunTestOp.java, the zip is a tiny maven project ready to import to eclipse.
   hopefully I do not forget the attachment again :-)

  in short we have
        CommandInfo testopInfo = commandService.getCommand(IJTestOp.class.getName());
        CommandModule testopModule =  (CommandModule)moduleService.createModule( testopInfo);

   set some parameters

   run the service and init preprocessor on the module, then

        testopModule.run();
    or as an alternative
        moduleService.run(testopModule, false);

   running the init preprocessor gives
-----
Exception in thread "main" java.lang.IllegalStateException: Context already injected: org.scijava.AbstractContextual#context
        at org.scijava.Context.inject(Context.java:293)
        at imagej.command.CommandModule.initialize(CommandModule.java:144)
        at imagej.module.process.InitPreprocessor.process(InitPreprocessor.java:61)
        at mainroutine.RunTestOp.main(RunTestOp.java:62)
------

  Creating a new module for the same CommandInfo fixes the problem (line 60)

  Is this intended, i.e. that the init preprocessor for a module may be run only once?
  This would pose a serious problem to us:

  What we want to do is essentially the following:
  The user selects a Command via the GUI and we create a Window displaying the input parameters.
  The user may change/supply these parameters and run the Command.
  Upon return a window displaying the results pops up.
  However, the first window displaying the input parameters is still available, the user may
  change one/some parameters an rerun the command.
  This eases testing various parameter values or the same set of parameters on different
  images without the need to repeatatly select an operator/command.

  Have you further advise how we can accomplish this, i.e. reusing a command module?

  BTW: I prefer to not set the parameters via the moduleService.run method, as the parameters
       are set elsewhere (either by the user via a GUI configuring the operator/command e.g. from grappa,
       or by parsing command line argument in case of the command line oprunner.
       Additionaly I rather invoke the moduls run-method directly, as it seems to me that
       via moduleservie a new thread is started, and at this point we like to have this under control.

  it seems, that the init preprocessor assigns the service parameters of a Command,
  not the Service preprocessor as I expected. Is the correct?
  (Probably related to "shadowing" the Service and Context parameters of a Command)

  BTW: what is the sematics of injecting a context (into a module?)

>    So this is certainly inconsistent and confusing. Do you think that
>    Commands should also include service and context inputs when iterating
>    them? If so, we can try removing that exclusion and see what
>    explodes... ;-)
We would not need them rather hide the from the user.

>    If you urgently need support for multiple simultaneous ImageJ contexts
>    created with the default constructor while ij-legacy is on the
>    classpath, and you want to try fixing the bug yourself, we would be
>    happy to elaborate further so that you can give it a shot.
no, we are hapy with one, just have to get hold of it (and use it in a static way)

Again, thanks again

best regards   Stefan

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel

ij2-test.zip (8K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: (headless) command execution

Stefan Posch
Hi Curtis,

regarding the concept of initializers I had a discussion with Birgit yesterday
and we came up with the following ideas.

We think we could do without command and parameter initializers but work only with
the parameter's callback function which - as currently - are to be invoked
upon setting/changing the corresponding parameters value.

As currently, depending on parameter values, e.g. the image assigned to a Dataset,
the command may add (or remove) parameters. This would be accomplished
by the callback functions of the parameter whose value is the cause for these new parameters.
E.g. the callback function of the inputDisplay of DuplicateImage would add the parameters
(which is currently done by the command initializer).
If some parameters should get (initial) values depending on the value of other
parameters (e.g. your example of setting default brightness/contrast min,max values
to current min,max of the input image) would we again the responsibility of
the callback function of the cause, i.e. the input image.

This would eleviate us of the need to fill in parameters required for the command initializer.
If a parameter's value is set (either by a pre processor or programmatically)
its callback function takes care of taking the apropriate actions.

If the pre processor is run, it just needs to set the parameter values it decides to,
and the callback functions would be could automatically.

What remains is of course:
(i) assume a parameter's value is changed, and its callback method
  called accordingly. What if this callback reqires/assumes one or several other parameters
  to aready have be set? It seems to be, that this necessarily is the responsibility
  of the callback function (resp. its programmer) to handle this. I.e. to check
  the validity of other parameters it requires. Otherwise the Command or its Parameters
  have to declare a predefine order in which parameters have to be set.
  (Which we have considered to introduce to alida/mitobo few years ago but abandoned this
  idea as it seems to messy/error prone.)
(ii) in case of command execution via GUI (in contrast to programmatically):
    what if not all parameters which add further parameters are
    filled before the GUI is created and presented to the user and are set by the user?
    What we are considering is that the GUI to figure out such events have happened
    and then to adapt the GUI accordingly.

    How to figure out that set set of parameter (or the type of an already existing parameter)
    was change by a callback function?
    We see two possibilities:
    (a) a parameter may announce via its annotation that it (occasionally)
        _may_ change paramter definitions and the GUI always assumes that this had happend,
        is such a parameter's value has changed (which the GUI knows at it controls this processes).
    (b) the callback function is to fire events in case it changes parameter definitions.

    (a) might be similar or be used in analogy to your idea of a parameter to announce "required before initialize",
       as the pre processor framework would know that setting of such a parameter probably/potentially
       may add parameters and should better be set before creating the GUI to ask the user for
       further parameters (and if it accomplishes to set all of those parameters and either excludes them from
       the GUI - as currently done by IJ2 for input images - or prohibits changing these parameters,
       we get rid of problem (i) stated above).


To make things conceptionally easier (for me) I favour the following guideline:
A parameter, e.g. inputDisplay, may add (or remove) parameters to the command
exclusively depending of its own value. Furthermore the parameter (names) potentially
added by this parameter are disjoint from those parameters added by other parameters of
the command. However, it is probably not possible to check or enforce this restriction.
As stated above in (ii) in my view it would be the task of the programmer of the Comand anyway
to cope with more complicated situations and does not affect to supporting "runtime system",
e.g. the functionality to run pre processors and creating GUIs to harvest input vlaues from the user.


Best regards

Stefan

PS.:
A different issue I came across have a second look at the Parameter annotation, sepcifically
its choices: The few examples of usage I had a look at are parameters of type String which
announce valid values. It might me worth considering to drop this feature and use Enums instead
of Strings which easily allows to generate an approprate selection by the GUI.
--
Prof. Dr.-Ing. Stefan Posch,
        Institut fuer Informatik, Martin-Luther-Universitaet Halle-Wittenberg
        Von-Seckendorff-Platz 1, 06099 Halle (Saale)
phone:  ++49 345 55-24728
fax: ++49 345 55-27039
e-mail: [hidden email]
www:    www.informatik.uni-halle.de/~posch/

_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel
Reply | Threaded
Open this post in threaded view
|

Re: (headless) command execution

Curtis Rueden
Hi Stefan and Birgit,

More than one year later! Better late than never, hopefully.

> > Maybe we need a way to formally flag these "required before
> > initialize" parameters in the annotation? What do you think?
> > Would that help you?
>
> This would be different from autoFill() ?

Yes. The autoFill attribute is a way of saying to preprocessors: "If you do some sort of automatic value setting, do not do it to me." E.g., it lets you have a single image or display input without the ActiveImagePreprocessor or Active*DisplayPreprocessor populating it. In the case of the ImageJ UI, the InputHarvester preprocessor will then include it in the dialog box (since the parameter is still not marked resolved), so the user can explicitly select the desired object.

> Yes and no.
> In a way it makes responsibilities clear, in so far I feel comfortable
> with it.

Agreed, I like the declaration of intent there. But I'm not sure it would help anything programmatically.

> However, it seems to me that there are (potentially very heavy)
> restrictions on the parameters which may be filled in advance
> (automaticcal and not by the user) in a sensible way. As far as I
> understand ij2 fills in parameters with what I think you called
> AutoFooPreprocessors, so active image and active display?

Indeed. Preprocessor plugins are contextual, meaning they have access to the entire state of the context. And since the context is extensible, I really have no idea what sorts of parameters are "sensible" to fill or not. It really depends on the use cases of the application(s) involved.

> I cannot come up with further ones. How would we fill in an int
> parameter without knowledge of its meaning/sematics?

Right. Of course, the meaning/semantics would need to be known somehow. But that is outside the scope of the SciJava library design. As I said above, I can imagine (abstractly) that someone designs an application with various preprocessors that populate various parameters, including int[], in some predefined way for its use cases.

> And even for images is only possible for commands with exactly one
> image or display. Obviously we could introduce a further flag for an
> image parameter to notify, that I what to be assigned the active image
> with. But this seems pretty specific. And probably not generic to be
> introduce to scijava but rather deferred to the "application", e.g.
> imagej.

I agree; that flag would be too specific. That's what the preprocessor design is for: to avoid overspecifying how parameters might get populated, and instead leave it to the extensions (preprocessors) available to the context. The ImageJ paradigm is to have an "active image" which we can then use for populating image parameters, but this is far from the only valid paradigm.

> And there might be aplications which call for more the two layers?

In a way, the preprocessor design accommodates N layers, because the preprocessors are run in priority order. But in practice there are two layers when it comes to the initializers: preprocessors that come before InitPreprocessor, and preprocessors that come after it. I think this is OK and there is no need to subdivide initialization farther than that, but if you have a use case that illustrates otherwise, we can figure it out.

> Summing up, I am afraid that I do not have a cute idea.

Well, your cute idea was in the follow-up mail. We'll get to that below...

> Of course I appreciate the functionality the set initial values or
> make the type of parameters depending on image features (like
> dimensionality, range of values). Still adding parameters seems
> awkward to be. Could we come by with "only" changing types of
> parameters. E.g. for DuplicateImage not add one parameter for each
> axes rather have one array parameter with its length determined by the
> dimensionality? And may be indicate via annotations, depending on
> which other parameter(s) the type of this parameter will change?

Yes, this is very related to a recent reply I sent to imagej-devel in another thread [1]. I will recapitulate it here:

There are five different classes of modules:

1) Totally fixed, with inputs and outputs known in advance.
2) Updates parameter attributes (such as choices—but not # or type of inputs/outputs) once during initialization.
3) Updates parameter number and type (i.e., adding/removing inputs/outputs) once during initialization.
4) Updates parameter attributes repeatedly e.g. during callbacks.
5) Updates parameter number and type repeatedly e.g. during callbacks.

These five types of modules challenge us in different ways:

#1 is easy -- I think everything can support it easily.

#2 and #4 do not update the fundamental aspects of the module: the name and types of the parameters are known. So such modules can be classified as fundamentally "well behaved".

#3 and #5 are more difficult because they are fully dynamic: the names and types of parameters are not known a priori.

I agree with you that it would be nice if #2 and #4 type commands did not need to extend DynamicCommand, but instead some other abstract class that indicates they are well behaved from a typing perspective.

I filed an issue for it:

While at it, I also filed an issue for commands which are iteratively dynamic (i.e., alter their parameters during callbacks):

Though the distinction of "iteratively dynamic" may go away after implementing your idea to totally eliminate initializers in favor of callbacks.

And for what it's worth, I agree that better support for List and array parameters will often times avoid the need to use dynamic modules at all. This is something we have wanted for a long time:

> Thinking of module and parameter intitalizers it seems to be that I
> get more unsure. Is it exactly to do processing between the two layers
> of parameters.

Yes, that is one of the purposes, as discussed above. But not the sole purpose.

> And it is to add further parameters

In the case of dynamic modules, yes. And I would classify that as a "processing between two layers" use case.

> and set initial values to parameters?

Yes, that was the primary intended use case: when you want to set the initial value of a parameter and it cannot be expressed as a simple assignment. That is: if you want the default sigma to be 2.5, you simply write:

  @Parameter
  private double sigma = 2.5;

But if you want to define it by writing code -- presumably to somehow derive its initial value from the application state -- you need an initializer. It is not enough to write:

  @Parameter
  private double sigma = initialSigma();

  private double initialSigma() {
    ...
  }

Because in that case, the initialSigma method is called when the object is first instantiated, but before any context is injected. The initializer, conversely, is typically called at a very specific point in the preprocessing chain.

> Are initial parameter values execulsively meant to serve as defaults
> for the user or is it required that some initial values are set (in
> order to properly run the command)?

There is no hard assumption that initializers leave parameters "open" for further user alteration. Actually, a dynamic command could set any number of parameters to resolved during initializer routines, and then those parameters would not be shown to the user in the input harvester.

As discussed earlier in this thread, the precondition of run is that all required parameters be non-null when run() is called. This can be achieved by the preprocessing chain, or because some/all parameter values were passed to the moduleService.run method and prepopulated that way.

> If so: would this mean that for running a command head less in a non interactive way makes the distiction of two layers is obsolete?

The typically non-interactive use case is to pass all parameter values explicitly, which would make all the initializer stuff moot, yes. But it is not a hard requirement -- it really depends on your definition of "non-interactive"; if the preprocessing chain fulfills missing parameters in some other way, that is also acceptable from the standpoint of fulfilling the preconditions of run().

> running the init preprocessor gives
> -----
> Exception in thread "main" java.lang.IllegalStateException: Context
> already injected: org.scijava.AbstractContextual#context

Given the long time frame since you sent this: did you resolve this issue in an acceptable way? Or is it still a problem for you? If it is still a problem, I will be happy to look in more detail and give some advice -- in a much more timely fashion this time.

> Is this intended, i.e. that the init preprocessor for a module may be
> run only once?

Yes, module.initialize() is intended to be called only once. To execute a module again, create a new instance each time. The current code does still have this requirement, because CommandModule#initialize() injects the context, which is only allowed once.

> What we want to do is essentially the following:
> * The user selects a Command via the GUI and we create a Window
> displaying the input parameters.
> * The user may change/supply these parameters and run the Command.
> * Upon return a window displaying the results pops up.
> * However, the first window displaying the input parameters is still
> available, the user may change one/some parameters an rerun the
> command.
> * This eases testing various parameter values or the same set of
> parameters on different images without the need to repeatatly select
> an operator/command.
>
> Have you further advise how we can accomplish this, i.e. reusing a
> command module?

I think you can accomplish all of the above without reusing the same module instance, but instead creating a new one every time. Is that how you are currently doing it these days?

Alternately, if you don't call initialize() beyond the first time, that would probably do the trick as well, although reusing module instances is not a use case we have considered much.

> BTW: I prefer to not set the parameters via the moduleService.run
> method, as the parameters are set elsewhere (either by the user via a
> GUI configuring the operator/command e.g. from grappa, or by parsing
> command line argument in case of the command line oprunner.
> Additionaly I rather invoke the moduls run-method directly, as it
> seems to me that via moduleservie a new thread is started, and at this
> point we like to have this under control.

All makes sense. You can populate the parameters prior to run() in whatever way you see fit. If you want to do it after initialization, you could create your own preprocessor that does it. Or just set them directly right away. Whatever works.

> it seems, that the init preprocessor assigns the service parameters of
> a Command, not the Service preprocessor as I expected. Is the correct?
> (Probably related to "shadowing" the Service and Context parameters of
> a Command)

Yes, because the InitPreprocessor calls initialize() and for CommandModules that injects the context. And InitPreprocessor happens before ServicePreprocessor. I discussed this wrinkle in my previous reply. 

> BTW: what is the sematics of injecting a context (into a module?)

Does this answer your question:
?

Note that "injecting a Context" is something done to Java objects, not modules per se. Initializing a CommandModule instance injects its context into its associated Command instance [2]. But for other sorts of modules such as ScriptModule, there is no associated Java object.

> > Do you think that Commands should also include service and context
> > inputs when iterating them? If so, we can try removing that
> > exclusion and see what explodes... ;-)
>
> We would not need them rather hide the from the user.

OK, then I will not worry about changing this behavior any time soon -- I think it is tolerable for the time being. But unfortunately, to fully support all modules (not just commands), you still need the logic to hide service and context inputs, since other modules types like scripts will often have them.

> no, we are hapy with one, just have to get hold of it (and use it in a
> static way)

Since you only need a single Context, you presumably either: A) have a standalone application, in which case you should just spin up a Context and keep a reference to it; or: B) have an ImageJ plugin, in which case you should implement Command and write "@Parameter private Context context" in your command and you'll magically get the context injected. Actually, it is most direct in that case to declare @Parameters for all your needed services, rather than the context itself, since typically what you will want to do is make various service calls.

> We think we could do without command and parameter initializers but
> work only with the parameter's callback function

Great idea. This would elegant, and often superior in case of later changes to the relevant parameter(s). We can try to simplify this for SJC3, which is slated for release within the next few months [3]. I filed an issue for it [4]. There are some minor obstacles in certain cases, which I describe on the issue if you are interested, but they all seem surmountable.

> What if this callback reqires/assumes one or several other parameters
> to aready have be set? It seems to be, that this necessarily is the
> responsibility of the callback function (resp. its programmer) to
> handle this.

Agreed. This is a secondary parameter which depends on multiple primary parameters. So they all need callbacks which recompute the secondary parameter -- presumably by calling the same helper method, which does nothing if any of the needed primary parameters are still null.

> Otherwise the Command or its Parameters have to declare a predefine
> order in which parameters have to be set. (Which we have considered to
> introduce to alida/mitobo few years ago but abandoned this idea as it
> seems to messy/error prone.)

Again agreed: best not to mandate anything with respect to order.

> in case of command execution via GUI (in contrast to
> programmatically): what if not all parameters which add further
> parameters are filled before the GUI is created and presented to the
> user and are set by the user? What we are considering is that the GUI
> to figure out such events have happened and then to adapt the GUI
> accordingly.

Yes, ideally we should support that in the ImageJ UI. I believe that CellProfiler handles it by rebuilding the UI every time anything changes structurally. We could do the same thing, and it would be efficient enough -- the ImageJ API requires specific method calls to mutate parameter attributes, which would tell us when a UI rebuild of the input harvester is necessary.

> How to figure out that set set of parameter (or the type of an already
> existing parameter) was change by a callback function?

When a parameter _value_ is changed in a callback, it is typically a direct assignment to a field. So that would not trigger any additional callbacks. This makes infinite loops impossible, but also means it becomes the programmers responsibility to keep track of "transitive parameter dependencies" and update all downstream parameters accordingly.

When a parameter attribute is changed in a callback (which only DynamicCommands can do), we can easily make the framework publish some event -- individual programmers would not need to deal with this, and everything would "just work."

> I favour the following guideline: A parameter, e.g. inputDisplay, may
> add (or remove) parameters to the command exclusively depending of its
> own value. Furthermore the parameter (names) potentially added by this
> parameter are disjoint from those parameters added by other parameters
> of the command. However, it is probably not possible to check or
> enforce this restriction.

While that would certainly provide some guarantees, I agree that it is not possible to enforce it. So I would favor not stating any restrictions of that sort.

> A different issue I came across have a second look at the Parameter
> annotation, sepcifically its choices: The few examples of usage I had
> a look at are parameters of type String which announce valid values.
> It might me worth considering to drop this feature and use Enums
> instead of Strings which easily allows to generate an approprate
> selection by the GUI.

The problem with enums is they are not extensible. So if you want to dynamically generate the choices via callbacks, an enum will not work. IIRC, the module framework does already support enums as dropdown list boxes. But I think there is still a place for the choices attribute, too. Let me know if you see a way around it.

Regards,
Curtis




On Wed, Apr 16, 2014 at 9:47 AM, Stefan Posch <[hidden email]> wrote:
Hi Curtis,

regarding the concept of initializers I had a discussion with Birgit yesterday
and we came up with the following ideas.

We think we could do without command and parameter initializers but work only with
the parameter's callback function which - as currently - are to be invoked
upon setting/changing the corresponding parameters value.

As currently, depending on parameter values, e.g. the image assigned to a Dataset,
the command may add (or remove) parameters. This would be accomplished
by the callback functions of the parameter whose value is the cause for these new parameters.
E.g. the callback function of the inputDisplay of DuplicateImage would add the parameters
(which is currently done by the command initializer).
If some parameters should get (initial) values depending on the value of other
parameters (e.g. your example of setting default brightness/contrast min,max values
to current min,max of the input image) would we again the responsibility of
the callback function of the cause, i.e. the input image.

This would eleviate us of the need to fill in parameters required for the command initializer.
If a parameter's value is set (either by a pre processor or programmatically)
its callback function takes care of taking the apropriate actions.

If the pre processor is run, it just needs to set the parameter values it decides to,
and the callback functions would be could automatically.

What remains is of course:
(i) assume a parameter's value is changed, and its callback method
  called accordingly. What if this callback reqires/assumes one or several other parameters
  to aready have be set? It seems to be, that this necessarily is the responsibility
  of the callback function (resp. its programmer) to handle this. I.e. to check
  the validity of other parameters it requires. Otherwise the Command or its Parameters
  have to declare a predefine order in which parameters have to be set.
  (Which we have considered to introduce to alida/mitobo few years ago but abandoned this
  idea as it seems to messy/error prone.)
(ii) in case of command execution via GUI (in contrast to programmatically):
    what if not all parameters which add further parameters are
    filled before the GUI is created and presented to the user and are set by the user?
    What we are considering is that the GUI to figure out such events have happened
    and then to adapt the GUI accordingly.

    How to figure out that set set of parameter (or the type of an already existing parameter)
    was change by a callback function?
    We see two possibilities:
    (a) a parameter may announce via its annotation that it (occasionally)
        _may_ change paramter definitions and the GUI always assumes that this had happend,
        is such a parameter's value has changed (which the GUI knows at it controls this processes).
    (b) the callback function is to fire events in case it changes parameter definitions.

    (a) might be similar or be used in analogy to your idea of a parameter to announce "required before initialize",
       as the pre processor framework would know that setting of such a parameter probably/potentially
       may add parameters and should better be set before creating the GUI to ask the user for
       further parameters (and if it accomplishes to set all of those parameters and either excludes them from
       the GUI - as currently done by IJ2 for input images - or prohibits changing these parameters,
       we get rid of problem (i) stated above).


To make things conceptionally easier (for me) I favour the following guideline:
A parameter, e.g. inputDisplay, may add (or remove) parameters to the command
exclusively depending of its own value. Furthermore the parameter (names) potentially
added by this parameter are disjoint from those parameters added by other parameters of
the command. However, it is probably not possible to check or enforce this restriction.
As stated above in (ii) in my view it would be the task of the programmer of the Comand anyway
to cope with more complicated situations and does not affect to supporting "runtime system",
e.g. the functionality to run pre processors and creating GUIs to harvest input vlaues from the user.


Best regards

Stefan

PS.:
A different issue I came across have a second look at the Parameter annotation, sepcifically
its choices: The few examples of usage I had a look at are parameters of type String which
announce valid values. It might me worth considering to drop this feature and use Enums instead
of Strings which easily allows to generate an approprate selection by the GUI.
--
Prof. Dr.-Ing. Stefan Posch,
        Institut fuer Informatik, Martin-Luther-Universitaet Halle-Wittenberg
        Von-Seckendorff-Platz 1, 06099 Halle (Saale)
phone:  <a href="tel:%2B%2B49%20345%2055-24728" value="+493455524728" target="_blank">++49 345 55-24728
fax:    <a href="tel:%2B%2B49%20345%2055-27039" value="+493455527039" target="_blank">++49 345 55-27039
e-mail: [hidden email]
www:    www.informatik.uni-halle.de/~posch/



On Mon, Apr 14, 2014 at 10:16 AM, Stefan Posch <[hidden email]> wrote:
Hi Curtis,

thanks for your reply, we are getting ahead, but still questions for running commands

>    * The run() method of a module can assume that all required input
>    parameters have been filled (i.e., are non-null). And the corresponding
>    post-condition of run() is that all required output parameters are now
>    filled.
perfect, the same with us

>    * The initialize() method of a module cannot necessarily assume
>    anything about the state of its parameters. As you pointed out, ImageJ2
>    has various commands right now that *do* assume certain parameters have
>    been filled via preprocessing. This works in practice (at least from
>    the ImageJ application), but is not particularly rigorous.
>    * Similarly, ImageJ2 has several commands which assume their
>    initializer has been called, but it is not stated as a formal
>    precondition. Most probably it makes sense to state that in the
>    javadoc, would you agree? In other words: if you aren't going to
>    include the InitPreprocessor in the preprocessing chain, you are still
>    somehow responsible for calling module.initialize() before calling
>    module.run(). Is that fair?
again: perfect

>    So the main sticky point is what to do about initialize() requiring
>    certain parameters to be already filled. This is useful for dynamic
>    modules, but also just for computing defaults -- e.g., setting default
>    brightness/contrast min & max values to the current display min max of
>    the input image. So it seems there are two "layers" of input
>    parameters: those needed before initialize() and those not needed for
>    it.
>    Maybe we need a way to formally flag these "required before initialize"
>    parameters in the annotation? What do you think? Would that help you?
This would be different from autoFill() ?

Yes and no.

In a way it makes responsibilities clear, in so far I feel comfortable with it.

However, it seems to me that there are (potentially very heavy) restrictions
on the parameters which may be filled in advance (automaticcal and not by the user)
in a sensible way. As far as I understand ij2 fills in parameters with what I think
you called AutoFooPreprocessors, so active image and active display?
I cannot come up with further ones. How would we fill in an int parameter
without knowledge of its meaning/sematics?
And even for images is only possible for commands with exactly one image or display.
Obviously we could introduce a further flag for an image parameter to notify,
that I what to be assigned the active image with. But this seems pretty specific.
And probably not generic to be introduce to scijava but rather deferred to the
"application", e.g. imagej.
And there might be aplications which call for more the two layers?

Summing up, I am afraid that I do not have a cute idea.
Of course I appreciate the functionality the set initial values or make the type
of parameters depending on image features (like dimensionality, range of values).
Still adding parameters seems awkward to be. Could we come by with "only" changing
types of parameters. E.g. for DuplicateImage not add one parameter for each axes rather
have one array parameter with its length determined by the dimensionality?
And may be indicate via annotations, depending on which other parameter(s) the
type of this parameter will change?

Rather more question:
Thinking of module and parameter intitalizers it seems to be that I get more unsure.
Is it exactly to do processing between the two layers of parameters.
And it is to add further parameters and set initial values to parameters?
Are initial parameter values execulsively meant to serve as defaults for the
user or is it required that some initial values are set (in order to properly
run the command)?

If so: would this mean that for running a command head less in a non interactive way
makes the distiction of two layers is obsolete?

>    One thing that may interest you is the recent ImageJ OPS announcement:
>       [1]http://developer.imagej.net/2014/04/04/announcing-imagej-ops
>    An Op is just an ImageJ command intended to be fully functional --
That sounds great ...

>   Hi Stefan,
>   Thanks. Rather than doing this:
>     CommandInfo testopInfo = new CommandInfo(IJTestOp.class.getName());
>     testopModule = (CommandModule) testopInfo.createModule();
>   I suggest instead:
>     CommandInfo testopInfo = commandService.getCommand(IJTestOp.class);
>     testopModule = (CommandModule)
>   moduleService.createModule(testopInfo);

the advise you gave works fine, however only for running a module for a given Command once.
  (see attached source of RunTestOp.java, the zip is a tiny maven project ready to import to eclipse.
   hopefully I do not forget the attachment again :-)

  in short we have
        CommandInfo testopInfo = commandService.getCommand(IJTestOp.class.getName());
        CommandModule testopModule =  (CommandModule)moduleService.createModule( testopInfo);

   set some parameters

   run the service and init preprocessor on the module, then

        testopModule.run();
    or as an alternative
        moduleService.run(testopModule, false);

   running the init preprocessor gives
-----
Exception in thread "main" java.lang.IllegalStateException: Context already injected: org.scijava.AbstractContextual#context
        at org.scijava.Context.inject(Context.java:293)
        at imagej.command.CommandModule.initialize(CommandModule.java:144)
        at imagej.module.process.InitPreprocessor.process(InitPreprocessor.java:61)
        at mainroutine.RunTestOp.main(RunTestOp.java:62)
------

  Creating a new module for the same CommandInfo fixes the problem (line 60)

  Is this intended, i.e. that the init preprocessor for a module may be run only once?
  This would pose a serious problem to us:

  What we want to do is essentially the following:
  The user selects a Command via the GUI and we create a Window displaying the input parameters.
  The user may change/supply these parameters and run the Command.
  Upon return a window displaying the results pops up.
  However, the first window displaying the input parameters is still available, the user may
  change one/some parameters an rerun the command.
  This eases testing various parameter values or the same set of parameters on different
  images without the need to repeatatly select an operator/command.

  Have you further advise how we can accomplish this, i.e. reusing a command module?

  BTW: I prefer to not set the parameters via the moduleService.run method, as the parameters
       are set elsewhere (either by the user via a GUI configuring the operator/command e.g. from grappa,
       or by parsing command line argument in case of the command line oprunner.
       Additionaly I rather invoke the moduls run-method directly, as it seems to me that
       via moduleservie a new thread is started, and at this point we like to have this under control.

  it seems, that the init preprocessor assigns the service parameters of a Command,
  not the Service preprocessor as I expected. Is the correct?
  (Probably related to "shadowing" the Service and Context parameters of a Command)

  BTW: what is the sematics of injecting a context (into a module?)

>    So this is certainly inconsistent and confusing. Do you think that
>    Commands should also include service and context inputs when iterating
>    them? If so, we can try removing that exclusion and see what
>    explodes... ;-)
We would not need them rather hide the from the user.

>    If you urgently need support for multiple simultaneous ImageJ contexts
>    created with the default constructor while ij-legacy is on the
>    classpath, and you want to try fixing the bug yourself, we would be
>    happy to elaborate further so that you can give it a shot.
no, we are hapy with one, just have to get hold of it (and use it in a static way)

Again, thanks again

best regards   Stefan


_______________________________________________
ImageJ-devel mailing list
[hidden email]
http://imagej.net/mailman/listinfo/imagej-devel