When is DatasetService "updated"? and getting a list of 'Dataset'

Dear scijava gurus,

I’d like for an imagej2 script to know about all the currently open images, but ran into something confusing.

Summary is that the DatasetService seemed not to always be “up-to-date,” but rather needed me to click through things.

Secondary question: is the DatasetService approach even the right one for this task?

  1. Opened ImageJ
  2. Opened two images.
  3. Ran this script
// @DatasetService ds
// @LogService log

log.info( "datasets: " + ds.getDatasets() )
  1. and got this output ( didn’t get either image)
[INFO] datasets: []
  1. Ran this script:
// @DatasetService ds
// @LogService log
// @ImageDisplayService ids

log.info( ds.getDatasets( ids.getActiveImageDisplay()))
log.info( "datasets: " + ds.getDatasets() )

and got this output ( only the active image in both lines )

[INFO] [mri-stack.tif]
[INFO] datasets: [mri-stack.tif]
  1. Clicked the previously non-active image, ran that second script again, and got this output (what I expected all along):
[INFO] [mri-stack-1.tif]
[INFO] datasets: [mri-stack.tif, mri-stack-1.tif]
  1. Ran that first script one more time (DatasetService only), and got the output (also as expected)
[INFO] datasets: [mri-stack.tif, mri-stack-1.tif]

Any guidance would be much appreciated.


Yeah, this is weird. But if you open the image using IOService things work as expected:

#@IOService io
#@UIService ui
#@LogService log
#@DatasetService ds

for ( i in 0..2 ) {
	img = io.open("/home/tferr/Fiji.app/samples/mri-stack.zip")
	ui.show("mri-stack" + i, img)
log.info( "datasets: " + ds.getDatasets() )

So the problem seems to be with the LegacyService that does not seem to sync images opened by IJ1? I tried the suggestion here of setting
java System.setProperty("imagej.legacy.sync", "true");
but that did not seem to work for me.

However, if in your step 3) above you go through each of the images open in legacy mode and explicitly sync them, then things seem to work as expected:

#@LegacyService ls
for (imp in ls.getImageMap().getImagePlusInstances()) {
log.info( "datasets: " + ds.getDatasets() )

but I guess this is way too hacky? I’m really convinced none of this was needed while back. Maybe something change in the LegacyService?


The problem is that synchronisation between the IJ1 (Legacy) UI and the IJ2 data structures happens lazily, and, as you found, in some scenarios even incorrectly, as datasets are not synchronized when they should.

There’s been some related discussion here:

and here:

There are also a few open pull requests by @stelfrich and @bnorthan:

I think it would be great if you could take a look at them and see if they solve your issues, as this problem has been around for quite a while now…


Do you actually need to query the full lists of datasets/images for your script?

Or would it be sufficient if you have one or several @Dataset input parameters, and maybe some more flexible way to control (e.g. via style= annotation) how the choice widget is populated (e.g. allow only 3D images as input parameters, etc.). If that’s the case, I guess your scripts would more easily be callable headless from other scripts or from KNIME in the future, as they don’t have to rely on interactive user input…

Thanks @imagejan,
I will have a look at those

The fundamental thing I was working toward was having a script work with a list of images of unknown/arbitrary length. Having some fixed number of input @Dataset parameters isn’t workable. Getting everything open seemed a sensible way to get this, but I’m open to alternatives.

Having an input list of arbitrary size is a recurring use case.

For example:

  • ImageJ 1.x has this in the Concatenator plugin:

  • KNIME’s Segment nodes (and others) have expandable lists of rules:


  • For SciJava / ImageJ2, there’s no widget for this yet, but @tibuch has put some work on it, as mentioned in this long-standing issue:

Here’s the source code:

Would this widget work for you if it was included in SciJava? I’d have a bunch of use cases for this as well, but I think it might be good to wait for @ctrueden’s current work on SJC3 that will make list inputs aware of their generic types :tada: (see branch type-service). (See also this discussion on gitter for some background.)


Yes, this would be great. No urgency on my side, so happy to wait for @ctrueden’s continuing work.

I’m going to mark your post with PRs as the solution to this, as well as add something about lists of Datasets to the title so that this will be easier to find.

Thanks again @tferr & @imagejan


It is very tricky to do things right. For some types of images, as of this writing, synchronization entails copying all the pixel data. So if a call like DatasetService#getDatasets() triggers a resync of all legacy images, performance is wrecked. Users complained that Fiji was “grinding to a halt” so we now err on the side of undersynchronization. @maarzt is currently working on ensuring that all IJ1-IJ2 image synchronization is done with wrappers (and VirtualStack when necessary) and never by copying pixels. This will hopefully allow us to reinstate synchronization-on-demand behaviors in more situations.

Regarding the List widget, I do plan on implementing that as part of the SJC3 widget suite, using @tibuch’s code as a starting point. Thanks @imagejan for the thorough yet concise summary of the current situation.