Read images with ImageJ; display them with napari

Simple first cut at reading images with SCIFIO+Bio-Formats via pyimagej into NumPy arrays, and displaying them with napari.

python read_images_with_imagej.py /Users/curtis/data/dub/dub*.pic

(Dub dataset can be found here.)

Source code
"""
Read images with ImageJ; display them with Napari.
"""

import napari, sys

if len(sys.argv) <= 1:
    print('Please specify one or more images as arguments.')
    exit(1)

try:
    import imagej
except ImportError:
    raise ImportError("""This example uses ImageJ but pyimagej is not
    installed. To install try 'conda install pyimagej'.""")

with napari.gui_qt():

    print('--> Initializing imagej')
    ij = imagej.init('sc.fiji:fiji') # Fiji includes Bio-Formats.

    for i in range(1, len(sys.argv)):
        path = sys.argv[i]
        print('--> Reading {}'.format(path))

        dataset = ij.io().open(path)
        image = ij.py.from_java(dataset)

        if i == 1:
            viewer = napari.view_image(image)
        else:
            viewer.add_image(image)

    ij.getContext().dispose()

    viewer.grid_view()

More work still to be done on image metadata (name, axes, etc.), as well as time and memory efficiency.

22 Likes

Why can the “love” button only be clicked once? Can you change this in the discourse config, @ctrueden? :joy:

I love the use of grid mode here. :grinning:

3 Likes

Cool.
Can you used dask.delayed on ij.py.from_java(dataset) or will it break things?
I guess I should try…

2 Likes

So cool @ctrueden and let us know what you find @VolkerH!!

1 Like

I just tried putting the two calls required to get a numpy array through imagej into a function and creating a lazy reader using dask.delayed, following Talley’s blog post. I did not encounter any issues. Seems to work just fine, even with the whole pyimagej machinery in the background. (code snippet).

5 Likes

Any way to remove layers via the console? I didn’t see API for it. I wanted to visualize the whole dub time series in 3D after loading the stacks as layers, as follows:

import numpy
time_series = numpy.concatenate([layer.data for layer in viewer.layers]).reshape([len(viewer.layers)] + list(viewer.layers[0].data.shape))
viewer.layers.clear()
viewer.add_image(time_series)
viewer.layers[0].scale = [10, 1, 1, 1]

But unsurprisingly, viewer.layers.clear() directly hoses the state. :crying_cat_face:

one option is to pop the layer index as follows:

viewer.layers.pop(0)

Thanks @talley, that worked! Although I had to toggle grid view to reset the projection—switching to 3D mode alone wasn’t enough.

In other news: the memory footprint of this dataset has dropped from 8GB to 1GB, as of this commit:

Because previously when copying an ImgLib2 image back to Python, float64 was always used—now it uses a matching dtype for the ImgLib2 image instead.

3 Likes