Add conversion for BitType and BoolType imgs
Using PyImageJ, functionality that returns boolean type images, like thresholds and morphology Ops, returns those images as images of BitType and/or BoolType. PyImageJ normally converts these to DataArrays of float64, which seems suboptimal.
This change, utilizing imagej/imagej-ops#651, allows those BitType and/or BoolType images to become boolean arrays instead. Of course, we will need to wait for that PR to make its way into release before we can merge this PR.
@elevans is there a better place to put the tests I wrote?
@gselzer This looks great to me, very clean and simple. I think it makes sense to put your tests in tests/test_image_conversion.py. Just as a heads up, since JPype 1.0.0 you can create Java arrays like this:
from jpype import JLong
jarray = JLong[:] @ [15, 20, 30]
Instead of calling the JArray constructor!
@gselzer It looks like I can't convert BitType to NativeBoolType. What am I doing wrong?
Operating in headless mode - the original ImageJ will have limited functionality.
Traceback (most recent call last):
File "Thread.java", line 829, in java.lang.Thread.run
java.lang.java.lang.ClassCastException: java.lang.ClassCastException: class net.imglib2.type.logic.BitType cannot be cast to class net.imglib2.type.logic.NativeBoolType (net.imglib2.type.logic.BitType and net.imglib2.type.logic.NativeBoolType are in unnamed module of loader 'app')
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "OpEnvironment.java", line 136, in net.imagej.ops.OpEnvironment.run
java.util.concurrent.java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: java.lang.ClassCastException: class net.imglib2.type.logic.BitType cannot be cast to class net.imglib2.type.logic.NativeBoolType (net.imglib2.type.logic.BitType and net.imglib2.type.logic.NativeBoolType are in unnamed module of loader 'app')
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "OpEnvironment.java", line 136, in net.imagej.ops.OpEnvironment.run
Exception: Java Exception
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/edward/Documents/repos/loci/pyimagej/src/imagej/__init__.py", line 193, in from_java
return sj.to_python(data)
^^^^^^^^^^^^^^^^^^
File "/home/edward/Documents/repos/loci/scyjava/src/scyjava/_convert.py", line 553, in to_python
return _convert(data, py_converters)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/edward/Documents/repos/loci/scyjava/src/scyjava/_convert.py", line 104, in _convert
return converter.convert(obj, **hints)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/edward/Documents/repos/loci/scyjava/src/scyjava/_convert.py", line 74, in convert
else self.converter(obj)
^^^^^^^^^^^^^^^^^^^
File "/home/edward/Documents/repos/loci/pyimagej/src/imagej/__init__.py", line 663, in <lambda>
converter=lambda obj: convert.java_to_ndarray(self._ij, obj),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/edward/Documents/repos/loci/pyimagej/src/imagej/convert.py", line 203, in java_to_ndarray
images.copy_rai_into_ndarray(ij, rai, narr)
File "/home/edward/Documents/repos/loci/pyimagej/src/imagej/images.py", line 166, in copy_rai_into_ndarray
ij.op().run("copy.rai", sj.to_java(narr), rai)
java.lang.java.lang.RuntimeException: java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.ClassCastException: class net.imglib2.type.logic.BitType cannot be cast to class net.imglib2.type.logic.NativeBoolType (net.imglib2.type.logic.BitType and net.imglib2.type.logic.NativeBoolType are in unnamed module of loader 'app')
Hmm, fails on my machine too @elevans. Looks like the object sj.to_java(narr) is a DefaultDataset with NativeBoolType elements, while rai is an ArrayImg<BitType>. Naturally, the matching copy Op doesn't handle that, because the Ops there require elements be of the same type.
Options:
- Write a better Op that can copy between
BooleanTypes. Would take a little while to get dependable releases but probably the most correct option. - Find some more explicit way to copy the images, where you can make use of the fact that the element types may be different. Unfortunately,
ImgUtil.copycan't handle differentbooleanTypeimplementations either...
I'd prefer (1).
This branch passes test successfully with imagej-ops version 2.1.0 which contains the necessary patch for the BitType and BoolType to be converted directly to boolean arrays. A new release of pom-scijava is needed to bumps the imagej ops version requirements.