ImageJ2 misbehaves with XYZC images

Hi there,

I have found that ImageJ2 dislikes XYZC images. It does, however, work fine with XYCZ.

XYCZ example (works):

# @DatasetService ds
# @DisplayService display
# @IOService io
# @OpService ops

from net.imglib2.type.numeric.real import FloatType
from net.imagej.axis import Axes
from net.imagej.display import ColorTables

sinusoid = ops.run("create.img", [512, 512, 2, 32], FloatType())
formula = "63 * (Math.cos(0.3*p[0]) + Math.sin(0.3*p[1])) + 127"
image = ds.create(ops.image().equation(sinusoid, formula))

image.axis(2).setType(Axes.CHANNEL)
image.axis(3).setType(Axes.Z)

image.initializeColorTables(2)
image.setChannelMinimum(0, 0)
image.setChannelMaximum(0, 512)
image.setColorTable(ColorTables.FIRE, 0)
image.setColorTable(ColorTables.SPECTRUM, 1)

imageDisplay = display.createDisplay('XYCZ', image)

XYZC example (does not work):

# @DatasetService ds
# @DisplayService display
# @IOService io
# @OpService ops

from net.imglib2.type.numeric.real import FloatType
from net.imagej.axis import Axes
from net.imagej.display import ColorTables

sinusoid = ops.run("create.img", [512, 512, 32, 2], FloatType())
formula = "63 * (Math.cos(0.3*p[0]) + Math.sin(0.3*p[1])) + 127"
image = ds.create(ops.image().equation(sinusoid, formula))

image.axis(2).setType(Axes.Z)
image.axis(3).setType(Axes.CHANNEL)

image.initializeColorTables(2)
image.setChannelMinimum(0, 0)
image.setChannelMaximum(0, 512)
image.setColorTable(ColorTables.FIRE, 0)
image.setColorTable(ColorTables.SPECTRUM, 1)

imageDisplay = display.createDisplay('XYZC', image)

Edit: fixed silly image = image = ds.create(...) assignment. @ctrueden thanks for syntax highlighting .

1 Like

Hi Radoslaw,

I’ve noticed this issue too. I think this is due some kind of tie in to the legacy code or legacy UI where the hyperstack convention is {X, Y, C, Z, T}. Unfortunately I know of no solution other than create a display like you do, or use Views.permute. Have you tested if the same error occurs without the legacy-ui?

Best regards,
Richard

@rimadoma Hi Richard,

Unfortunately, this exists both in legacy and IJ2 UI. I plan to test if this gets solved in IJ2 by setting display parameters (MinMax and LUTs) on ImageView instead of Dataset. That could be a clue on where the bug sits.

Best,

Radek

Maybe, I’ve noticed other issues displaying Datasets. For example, if you have an output @Parameter Dataset dataset it won’t get automatically displayed, where as a @Parameter ImgPlus imgPlus will.

Interestingly, it does work when setting up LUTs and MinMax values through view. Both in IJ1 and IJ2 modes! And regardless of the axis order! I think crucial steps are to call view.rebuild() and setting up axis properly before doing anything with display parameters.

# @DatasetService ds
# @ImageDisplayService ids
# @DisplayService display
# @IOService io
# @OpService ops

from net.imglib2.type.numeric.real import FloatType
from net.imagej.axis import Axes
from net.imagej.display import ColorTables

sinusoid = ops.run("create.img", [512, 512, 32, 2], FloatType())
formula = "63 * (Math.cos(0.3*p[0]) + Math.sin(0.3*p[1])) + 127"
image = ds.create(ops.image().equation(sinusoid, formula))

image.axis(2).setType(Axes.Z)
image.axis(3).setType(Axes.CHANNEL)

view = ids.createDataView(image)
view.rebuild() # Required to initialize view data structures
view.setChannelRange(0, 0, 512)
view.setColorTable(ColorTables.FIRE, 0)
view.setColorTable(ColorTables.SPECTRUM, 1)

imageDisplay = display.createDisplay('XYZC view', view)

This probably means it’s related to this issue:
https://github.com/imagej/imagej-legacy/issues/164

2 Likes

More research: setting view lookup tables, etc AFTER the view is displayed does NOT work, even when view.rebuild() is called:

# @DatasetService ds
# @ImageDisplayService ids
# @DisplayService display
# @IOService io
# @OpService ops

from net.imglib2.type.numeric.real import FloatType
from net.imagej.axis import Axes
from net.imagej.display import ColorTables

sinusoid = ops.run("create.img", [512, 512, 32, 2], FloatType())
formula = "63 * (Math.cos(0.3*p[0]) + Math.sin(0.3*p[1])) + 127"
image = image = ds.create(ops.image().equation(sinusoid, formula))

image.axis(2).setType(Axes.Z)
image.axis(3).setType(Axes.CHANNEL)

imageDisplay = display.createDisplay('XYZC view', image)
view = imageDisplay.getActiveView()
view.rebuild() # This has no use here
view.setChannelRange(0, 0, 512)
view.setColorTable(ColorTables.FIRE, 0)
view.setColorTable(ColorTables.SPECTRUM, 1)
1 Like

So here is a recap of my tests:

  • Setting display parameters BEFORE image is displayed works for IJ1 and IJ2 when using DefaultDataset methods, but only for XYCZ images and not for XYZC images
  • Setting display parameters BEFORE image is displayed works for IJ1 and IJ2 when using DefaultDatasetView methods, regardless of the axis order, but requires calling DefaultDatasetView.rebuild() before any methods are called
  • Setting display parameters AFTER the image is displayed works only in IJ2 using both methods
  • Setting display parameters AFTER the image is displayed does not work in IJ1

@ctrueden - Any ideas?

1 Like