imagej / imagej-common

ImageJ core data model
https://imagej.net/libs/imagej-common
BSD 2-Clause "Simplified" License
9 stars 18 forks source link

Support postprocessing of ImgLib2 types #80

Closed imagejan closed 2 years ago

imagejan commented 5 years ago

Currently, when a module has outputs of ComplexType (and therefore RealType and IntegerType), a warning is logged such as:

[WARNING] Ignoring unsupported output: value [net.imglib2.type.numeric.integer.UnsignedByteType]

It would be nice to support the most common types by using their getRealDouble() or more specific methods to populate a results table. For "simple" types, this is already done in org.scijava.table.process.ResultsPostprocessor.

I'm not sure how this is best achieved, as we cannot add an ImgLib2 dependency to scijava-table. But implementing a new PostprocessorPlugin in imagej-common would not allow to fill the same results table instance as the existing scijava-table plugin, so we'd need to re-implement the processing of simple types in a plugin of higher priority, or make the existing table somehow accessible to extend the behavior.

@ctrueden any suggestions, hints?

ctrueden commented 5 years ago

We could use the ConvertService. Rather than checking if an output is a simple type, we could check if the output can be converted to a simple type. And if so, include it in the table. Then we just need converters from ImgLib2 Type classes to primitives (and ideally also the other way).

Unfortunately, stock Fiji does not have those converters yet:

#@ ConvertService cs

// List converters that convert to or from ImgLib2 Type classes.
println("-- Type converters --")
converters = cs.getInstances()
for (converter in converters) {
    s = converter.getClass().getSimpleName() +
        ": " + converter.getInputType().getName() +
        " -> " + converter.getOutputType().getName()
    if (s.contains("Type")) println(s)
}

// Can we convert FloatType -> Float ?
println("-- Can we convert FloatType -> Float ? --")
t = new net.imglib2.type.numeric.real.FloatType(4.5f)
f = cs.convert(t, Float.class)
println(t.toString() + " [" + t.getClass().getName() + "] -> " + f + " [" + f.getClass().getName() + "]")

Prints:

-- Type converters --
-- Can we convert FloatType -> Float ? --
4.5 [net.imglib2.type.numeric.real.FloatType] -> null [org.codehaus.groovy.runtime.NullObject]

There are some ImgLib2 Type-related converters in the imagej-server project:

-- Type converters --
DoubleToDoubleTypeConverter: java.lang.Double -> net.imglib2.type.numeric.real.DoubleType
FloatToFloatTypeConverter: java.lang.Float -> net.imglib2.type.numeric.real.FloatType
IntegerToIntTypeConverter: java.lang.Integer -> net.imglib2.type.numeric.integer.IntType
LongToLongTypeConverter: java.lang.Long -> net.imglib2.type.numeric.integer.LongType
-- Can we convert FloatType -> Float ? --
4.5 [net.imglib2.type.numeric.real.FloatType] -> null [org.codehaus.groovy.runtime.NullObject]

But as you can see, these are the "wrong" direction for this use case. We should probably:

  1. Move those converters from imagej-server into imagej-common; and
  2. Implement converters in the other direction.

What do you think?

imagejan commented 4 years ago

Move those converters from imagej-server into imagej-common

As mentioned in https://github.com/imagej/imagej-common/pull/82#issuecomment-616624045, these converters are actually unnecessary, as this direction of the conversion is covered by org.scijava.convert.DefaultConverter already.

Implement converters in the other direction.

See #82.