Incomplete loading of nd2 file through Python script in ImageJ: positions missing

Hello,

I am new to the use of scripting in ImageJ, and I am facing an issue when trying to load a nd2 file (from Nikon Elements software) with a Python script in ImageJ.

The nd2 file contains a sequence of images for 256 different positions, with 15 time points at each positions, and 3 channels. Each frame is 124x124 pixels.

The file loads fine using the usual “File/Open” in ImageJ, with just an extra window “Bio Format Series Options” popping up to ask me which of the 256 positions I would like to open.

I tried to open the same file via a script the following way, following the Jython example from @ctrueden:

from loci.plugins import BF

file = "Z:/case_imagesc/test_1.nd2"
imps = BF.openImagePlus(file)

print(imps)
for imp in imps:
    imp.show()
    stack = imp.getImageStack()
    print 'Number of frames in stack = ', stack.size()

The output of this short script is:

array(ij.ImagePlus, [img[“Z:/case_imagesc/test_1.nd2 - test_1.nd2 (series 001)” (-48), 16-bit, 124x124x3x1x15]])
Number of frames in stack = 45

So it seems that only the first position (series 001) is loaded in the object “imps”. And indeed, the corresponding stack contains only 3x15 frames corresponding to a single position, and the shown images correspond to a single position.

However, I would like to open all the positions into one or separate objects, to be able to apply plugins to all of them (256 positions x 15 time points x 3 channels).

Is there a way to do so?

Thank you for your help!

@fpeaudec Unfortunately, IIRC, the BF.openImagePlus will behave based on your last-used Bio-Formats settings. So if you opened only a single position last time, I think it will open only a single position this time.

Here is a way to override the last-used settings:

from loci.plugins import BF
from loci.plugins.in import ImporterOptions
file = "Z:/case_imagesc/test_1.nd2"
options = ImporterOptions()
options.setId(file)
options.setOpenAllSeries(true)
imps = BF.openImagePlus(options)

(caveat emptor: I did not test this just now)

You may run into performance issues (both time and space) if you have a large number of positions. As an alternative, you could process them one position at a time:

from loci.plugins import BF
from loci.plugins.in import ImporterOptions
file = "Z:/case_imagesc/test_1.nd2"
options = ImporterOptions()
options.setId(file)
for s in range(0, seriesCount):
    options.setSeriesOn(s, True)
    imp = BF.openImagePlus(options)[0]
    # do something with the image
    options.setSeriesOn(s, False)

(again, not tested)

If you know seriesCount a priori this is OK; if not, you can open the dataset’s metadata only and extract the number of series, although this is a bit of a hassle. If you cannot figure out how to do this, just ask.

You could also try switching to the ImageJ2 API. If you are able to share a link to a multi-position test image, I can respond with some working code that uses SCIFIO.

2 Likes

Thanks a lot @ctrueden for the solutions!

I have tested both solutions, and they both work well, allowing me to recover all the positions.

Using your example of code, I’ve also modified your second solution in order to extract seriesCount from my nd2 file. I post the resulting code below in case it is useful for someone, it works well too:

from loci.plugins import BF
from loci.plugins.in import ImporterOptions
from loci.formats import MetadataTools
from loci.formats import ImageReader

file = "Z:/case_imagesc/test_1.nd2"

# parse metadata to get size of series
reader = ImageReader()
omeMeta = MetadataTools.createOMEXMLMetadata()
reader.setMetadataStore(omeMeta)
reader.setId(file)
seriesCount = reader.getSeriesCount()
reader.close()

# load position by position
options = ImporterOptions()
options.setId(file)

for s in range(0, seriesCount):
    options.setSeriesOn(s, True)
    imp = BF.openImagePlus(options)[0]
    # do something with the image
    options.setSeriesOn(s, False)