Getting BigDataViewer instance in an ImageJ Command

Hello,

Is it possible to retrieve an instance of an opened bigdataviewer in an ImageJ2 command ?

Something like this:

    @Parameter
    BigDataViewer bdv;

I’m afraid it’s not currently possible (see BigDataViewer/BigDataServer: get an ImagePlus Image of the current slice and BigDataViewer I/O). Don’t you think it could be useful ? One way to do it could be to modify the ‘standard’ BigDataViewer commands, like in this one:

What do you think ?

Nico

2 Likes

Hi Nico,

I think it would be very useful!
If you want to have a go at it, that would be very welcome.

best regards,
Tobias

1 Like

Maybe I would make on of the bigdataviewer-vistools interfaces


or

the annotated @Parameter.

This would give an easier way to add content and manipulate the BDV instance

2 Likes

Hi and thanks for your answers!

I tried two things.

This works. The BigDataViewer object can be retrieved using the parameter annotation with a BigDataViewer field in other commands:

@Parameter
BigDataViewer bdv;

But it’s not ideal in my opinion because you need to provide an ObjectService to run the initial command. If one has to run the command completely indenpendently of Fiji it’s great to be able to use commands without having to provide services. (I had to do that)

This would be ideal because no service is needed (and it looks cleaner). However, currently this parameter is ignored (by scijava ?). The console window displays:
[WARNING] Ignoring unsupported output: bdv [bdv.BigDataViewer]

Can this behaviour be modified ? How ?

Thanks!

The UI ignores the output because it doesn’t know what to do with a BigDataViewer object.

I’m unsure what would be the best way to do it:

  • you could modify DisplayPostprocessor that currently does the post-processing of modules and displays all the displayable outputs (but that would create an undesirable dependency from scijava-common to bigdataviewer – so, no…), or

  • you might want to implement your own PostprocessorPlugin that takes care of displaying the object in the current UI (if there is a UI present; you could also be in a headless environment, for example). This plugin would likely need to sit in bigdataviewer-vistools and create a dependency to scijava-common, which is probably fine.

Maybe @ctrueden can comment on the recommended way to implement this.


See here for an implementation example of a PostprocessorPlugin:


BTW, I agree with @tpietzsch that it would make more sense to use Bdv or BdvHandle instead of BigDataViewer as the parameter here.

2 Likes

Ok, I need to dig into this. I never used Bdv or BdvHandle so it’s a bit obscure to me. It’s not clear to me how Bdv and BdvHandle can help to achieve these sort of things for instance: (BigDataViewer/BigDataServer: get an ImagePlus Image of the current slice)

I looked a bit and indeed, I saw that somehow FIJI (or Scijava) needs to be able to display the output object to handle it, (otherwise it’s discarded ?).

But why is that ? IMO it could be useful to output an object from a command even if it’s not displayable. Maybe I want to output a weird object (a transform for instance), just because I want to work on it with other commands.

So, one suggestion. Wouldn’t it be possible to do this ?

  • If an object can be displayed, fine, it’s processed as expected, with a proper “displayer”.
  • If an object can’t be displayed, it’s saved into an ObjectService by default. It could also be send to a Standard Display, which would just print object.toString() in a console window.

What’s your thoughts about this ?

I happened to use a lot ObjectService because I need to work with “non standard” object within Fiji. Being able to annotate (type=ItemIO.OUPUT) on any kind of object would be very useful I think.

I may miss some bigger picture here, so happy to get your opinion.

Nico

@imagejan I think your approach would be good, and modeling it after the ResultsPostprocessor makes sense. Happy to respond in more detail if any aspect of it is unclear. I think it would be great if the bigdataviewer-vistools included plugins to make the BDV play more nicely with the SciJava Common framework.

2 Likes

Any parameter annotated as OUTPUT is indeed output by the Command/Module. The warning you see in the console just means that there is an output, but ImageJ/SciJava currently don’t know how to handle it.

But you can always access the output(s) of any {Command}Module by using module.getOutputs() or module.getOutput(String name) after running it.

For an example implementation, see the batch-processor project, where we process a given module n times (e.g. for n input files) and collect its outputs for each iteration:

Is this the information you were missing, or did I misunderstand your use case?


Note: In these cases – i.e. when you take care of handling the output yourself – it might be desirable to avoid output post-processing altogether, e.g. to not display an image output that you want to handle yourself. Unfortunately, you currently cannot do so without also switching off input pre-processing. Here’s an issue relating to this:

1 Like

I’ll do a quick minimal example, first to be sure of what I’m writing, second to clarify my point (hopefully).

(and thanks for all your answers btw!)

1 Like

Here’s my minimal example:

It’s not a real use case, but I think it’s ok to get the idea.

Suppose I have a class ImageDisplaySettings, which encapsulates some settings I’d like to apply on any image:

String lookupTable="Grays";
int minValue=0;
int maxValue=255;

Now I’d like to have:

  • a Command which creates the ImageDisplaySettings object. Let’s call it CreateDisplaySettingsPutAsItemOutput. The important part is that I annotate ImageDisplaySettings ids as an ItemIO.OUTPUTobject in it.
@Parameter(type= ItemIO.OUTPUT)
ImageDisplaySettings ids;
  • and a Command which applies these settings to an Image, called ApplyDisplaySettings. It takes an ImagePlus as an input as well as a ImageDisplaySettings object.
@Parameter
ImageDisplaySettings ids;

@Parameter
ImagePlus imp;

This pair of Command do not work together when using Fiji (at least with the FIJI user interface). See this screencast:

The first command CreateDisplaySettingsPutAsItemOutput can be launched but the output is ignored, and a warning message is shown. Thus, when I start the ApplyDisplaySettings Command no argument is found for the input parameter ids.

If I replace the first Command by another Command CreateDisplaySettingsPutInObjectService, which puts the newly created object into an ObjectService:

@Parameter
ObjectService os;

and

ImageDisplaySettings ids = new ImageDisplaySettings();
ids.minValue=minValue;
ids.maxValue=maxValue;
ids.lookupTable=lookupTable;
os.addObject(ids);

Then both Commands can work together (see end of screencast): I can execute the first one, and thanks to the object service, the ImageDisplaySettings is passed to the ApplyDisplaySettings Command via the Parameter annotation.


However I feel that using the ObjectService in the second command is a bit painful. The first command using ItemIO.OUTPUT looks nicer. But how to avoid ignoring the output Object ?

What’s the (proper) solution ?

  • Implementing a DisplayPostprocessor for these new classes ? (I need to look at it)
  • Couldn’t all ignored output objects be send to a default ObjectService ?

Thanks for reading all this!


Link to the full repo:

1 Like

I think you’re slightly misunderstanding how SciJava outputs are supposed to work (or at least how they currently work): after running a Module, you can ask for its outputs, but there is no default mechanism to make output objects persist in memory so that you can query them. If this was done for every module output by default, you’d possibly run into memory issues rather quickly.

For images, the reason why you can get them into an input is that they’re registered with the ObjectService, and in addition there’s a SingleInputPreprocessor to cover the case of a single image input, and fill it with the currently active image.

So, if you want your ImageDisplaySettings to persist in memory, your approach using the ObjectService is the way to go, I think. If there’s a more general requirement for persisted objects like this, maybe we can discuss here how to best implement it in the SciJava framework so that it works for everybody.

1 Like

Ok, thanks fo clarifying this. Your answer helps a lot!

I get it. Just a suggestion for the memory issues. Maybe this could be solved by adding a method in the Parameter annotation, which explicitely asks to keep it in memory (keepInObjectService=true)? Or just do it by default in case the object is annotated with (ItemIO.OUTPUT)

[Still, there could be some memory issues, because, as there is no display, the user can not delete these objects, or is not aware that they exist]

What I don’t like with the use of an ObjectService, is that I cannot use the command if there’s no ObjectService given (if I want to use the Comamnd in an ImageJ1 context for instance). [Ok it’s doable, but I need to check for the OjectService nullity everywhere in the Command.]


So back to the original post objective:

  • How to query BigDataViewer (or BdvHandle) instances in commands ?

-> from your answers, the solution for is:

  • to declare the output object with (type=ItemIO.Output) (BigDataViewer or BdvHandle objects)
  • to write a PostProcessorPlugin, which handles these objects, right ?
1 Like

I like that idea. Maybe we could reuse the persist=true flag for this, as it currently make sense for inputs only, right? (However, what would we do with (type=ItemIO.BOTH, persist=true) then?)

I’d be curious to know what @ctrueden thinks about this.

Agreed. Ideally you’d have some kind of object manager then (similar to the idea of ROI Manager, Overlay Manager, Window Manager, etc.)

Sorry, I don’t understand.

In a pure IJ1 context, you won’t be able to run your SciJava Command anyways. If you work with IJ2 and a legacy context, you should still have access to an ObjectService.


I don’t know what the best way would be.

  • modify bigdataviewer-vistools or bigdataviewer_fiji to register BDV instances with some service by default (similar to the IJ1 WindowManager); or
  • specifically only handle outputs with your custom postprocessor as you suggest.

What do others think?

1 Like

Is your objection purely aesthetic? Because from your description, it sounds like the ObjectService is serving its intended purpose here, and working exactly as you need. Personally, I do not find it ugly.

I’m sorry, I don’t understand. Can you explain in more detail, and/or post a code snippet illustrating what you would like to do that the ObjectService approach does not solve?

@ctrueden, @imagejan, @tpietzsch, I created a pull request with the modifications that would facilitate BigDataViewer use in FIJI command. Details are written in the PR :

Let me know what you think.

2 Likes