Plugin concept

2 views
Skip to first unread message

wil...@ieee.org

unread,
Mar 24, 2009, 2:30:15 PM3/24/09
to ImageJX
Hello IJX-list,

the plugin mechanism seems to be a central issue and it may be a good
initial focus to get structured somehow. Here are some points I find
important:

* First it should be clear what the role of a plugin is. A short
programs (script) with user interaction? To be invoked by scripts and
macros? To be be run from other plugins, possibly without (or
suppressed) user interaction? To provide some specific library (API)
to be used by others?
Currently they serve multiple roles and this creates an uncontrolled
mixture.

* Arguments to plugins (PlugInFilter): As said, the duality of
ImagPlus and ImageProcessor is quite distracting, I never understood
(and neither do my students) why setup() is passed a different
argument than run().

* Checking for capabilities/compatibility: The old-fashioned bit-
vector flags returned by setup() are error prone. There is no
guarantee that the plugin is not invoked on illegal arguments. There
are better ways to check for capabilities without even invoking a
method (interfaces, annotations, etc.).

* I wish plugins would be able to handle other arguments but images -
for example graph structures, trees, etc. Also on multiple images (not
necessarily stacks).

* I always found referencing "the current" image (as common in a
regular Plugin) rather brutal. I am not sure this is safe at all,
considering that the user may click on another image in the meantime.

* Return values: I often produce results in a plugin that might be
passed on to another plugin. Currently there is no mechanism to return
anything - statistics are a typical example. I usually store results
in some repository (hash table) or attach to the image, which is
unsatisfactory.

* Clean resource locking for multi-threading.

* Help support (as mentioned).

As I noted in an earlier post, I think plugins are only part of the
answer. What is needed in addition is an API that is modular and can
be extended dynamically. This is not the role of plugins but something
beyond is needed (llike "bundles" (OSGi-terminology), "modules" or
"extensions").

Btw., I just received my copy of "Practical API Design" by J. Tulach
(founder of NetBeans) - interesting stuff and very applicable for this
task.

--Wilhelm

Dimiter

unread,
Mar 24, 2009, 3:51:48 PM3/24/09
to ImageJX


On Mar 24, 7:30 pm, "wil...@ieee.org" <wil...@ieee.org> wrote:
> Hello IJX-list,
>
> the plugin mechanism seems to be a central issue and it may be a good
> initial focus to get structured somehow. Here are some points I find
> important:
>
> * First it should be clear what the role of a plugin is. A short
> programs (script) with user interaction? To be invoked by scripts and
> macros? To be be run from other plugins, possibly without (or
> suppressed) user interaction?

To provide some specific library (API)
> to be used by others?
This is rather interesting thought. But you can provide a library in
the package format.
I almost always implement a library providing the generic
functionality and use the Plug in/filter only to interact with the
user.
I also encapsulate the input/output information into objects that can
be read from other plugins, to answer your further comment.

> Currently they serve multiple roles and this creates an uncontrolled
> mixture.
I agree on this. But you can not prevent people from doing this.
>
> * Arguments to plugins (PlugInFilter): As said, the duality of
> ImagePlus and ImageProcessor is quite distracting, I never understood
> (and neither do my students) why setup() is passed a different
> argument than run().

I think it's rather logical. ImageProcessor implements image
processing functionality, while ImagePlus serves to display an image
and bundle it with a Calibration and Roi's and eventually Statistics
objects.
I agree than setup and run should have the same argument. But we can
also ask Wayne about this.

>
> * Checking for capabilities/compatibility: The old-fashioned bit-
> vector flags returned by setup() are error prone. There is no
> guarantee that the plugin is not invoked on illegal arguments. There
> are better ways to check for capabilities without even invoking a
> method (interfaces, annotations, etc.).

I don't like the clear distinction between Short, Byte and Float
images/processors. This is a rather time consuming hassle. Either I
have to use a generic type , e.g. Float or write separate versions of
the algorithms for all mentioned types. The 24bit RGB is a separate
concept both in visualization and in processing, so there I think it
is worth keeping the separation.

>
> * I wish plugins would be able to handle other arguments but images -
> for example graph structures, trees, etc. Also on multiple images (not
> necessarily stacks).

So now you are talking about something different than an image-
processing plugin. This is a rather major but easily introduced step.

>
> * I always found referencing "the current" image (as common in a
> regular Plugin) rather brutal. I am not sure this is safe at all,
> considering that the user may click on another image in the meantime.
The only time the current image is set is during the execution of the
setup method. So no worries. This is not a macro.

>
> * Return values: I often produce results in a plugin that might be
> passed on to another plugin. Currently there is no mechanism to return
> anything - statistics are a typical example. I usually store results
> in some repository (hash table) or attach to the image, which is
> unsatisfactory.
I agree on this issue.

>
> * Clean resource locking for multi-threading.
what do you propose? I think Albert can share some experience in multi-

Adrian...@gmx.de

unread,
Mar 24, 2009, 8:42:54 PM3/24/09
to ima...@googlegroups.com
Hello IJX-list,

I like Wilhelm's suggestion to use the discussion around the plugin
mechanism as a way of starting brainstorming. While it is not entirely clear to me whether 'core plugins' and 'user plugins' (in the sense of the 'core' vs 'plugins' discussion earlier in this thread) can/should be submitted to the same structures and interfaces, discussing the plugin mechanism is a good way of laying down ideas on how we want the different parts of IJX to interact.

> * First it should be clear what the role of a plugin is. [..]


> Currently they serve multiple roles and this creates an uncontrolled
> mixture.

Good point, but it would be nice if plugins could 'naturally' be able of
other usage that the primary intended one. If we distinguish different
roles too early, and one has to e.g. revisit the source to make an
interactive plugin work non-interactively, we might loose some flexibility.

> * I wish plugins would be able to handle other arguments but images -
> for example graph structures, trees, etc. Also on multiple images (not
> necessarily stacks).
>

> * I always found referencing "the current" image (as common in a
> regular Plugin) rather brutal. I am not sure this is safe at all,
> considering that the user may click on another image in the meantime.
>

> * Return values: I often produce results in a plugin that might be
> passed on to another plugin. Currently there is no mechanism to return
> anything - statistics are a typical example. I usually store results
> in some repository (hash table) or attach to the image, which is
> unsatisfactory.

These points seem important, and mean that a simple
ImageProvider/ImageConsumer type interface is not sufficient. It would
indeed be nice if a plugin could expose the results in a flexible
manner, and likewise take input of various types. Is there any nice way
to do this ? (I am not a professional programmer in any way, and
unfamiliar with many modern programming concepts, but I suspect some ideas might already be out there)

Just to jot down a quick concrete example (apologize in advance if this is perceived as too detailed at this time, but I feel sketching things tentatively might help expose bad ideas), what about using something like essentially a hashtable with appropriate access methods as a container to tansmit input and output data ? E.g. declare the central run() method of Plugins as

run(DataContainer input, DataContainer output)

The DataContainer would be an interface allowing to get objects e.g. by a key or so:

interface DataContainer() {
/** Register a reference to the image under the given key. The image
object itself is not copied. If a reference to an object already
exists for this key it is overwritten.*/
putImage(String key, ImageData image);
/** Return Image by key. Returns null if container has no image object
or key is unknown. */
ImageData getImageByKey(String key);

... // similar methods for other basic object types,
// plus possibly generic getObjectByKey(...)

deleteRef(String key);// call this to explicitly free reference so that object may become eligible for garbage collection
deleteAll();
}

One could specify from the start a number of base objects (images,
tables, trees, hash-tables) that can be handed down this way, but not
restricting to these. The global contract would require that plugins document the keys and returned objects in the API. In the case of simple plugins (PlugInFilter) a keyword could be reserved for the image/stack to be processed (say "active", to please Wilhelm ;-)), so that these plugins can function almost as before with:

run(DataContainer input, DataContainer output) {
imp = input.getImageByKey("active");

// do the stuff to imp as before

output.putImage("active", imp); // assumes image was processed
in-place, otherwise register newimp
}

This kind of plugin could then be re-used and chained easily:

plugin1.setup(blabla)
tmpdata = new DataContainerImplementation();
plugin1.run(input, tmpdata);

plugin2.setup(blablo)
plugin2.run(tmpdata, output);

Then again, I am neither a professional, nor particularly experienced programmer, so this is maybe a poor design choice.


I agree to all other points made by Wilhelm, and in particular also vote
that the ImagePlus/ImageProcessor distinction is very confusing. Some
clean-up needed here.

> * Help support (as mentioned).

I just read that it is possible since Java 1.6 to launch the system
default browser on an arbitrary URL in a portable way (via
java.awt.Desktop.browse()). This could maybe be used to point to the
javadoc-generated API documentation, which would greatly encourage
documentation of plugins in the canonical way, and require little infrastructure in IJX.

Not sure my contributions so far are up to level with the others', but
would really like to see this project evolve.

--
Adrian

--
Psssst! Schon vom neuen GMX MultiMessenger gehört? Der kann`s mit allen: http://www.gmx.net/de/go/multimessenger01

Reply all
Reply to author
Forward
0 new messages