imagej / imagej-legacy

ImageJ+ImageJ2 compatibility layer
https://imagej.net/libs/imagej-legacy
BSD 2-Clause "Simplified" License
16 stars 25 forks source link

`ImgPlus` images with a new `ROITree` that contains a `RealPointCollection` can't be displayed #299

Open elevans opened 1 year ago

elevans commented 1 year ago

I’m in the process of creating better Python ↔ ImageJ/ImgLib2 ROI support for PyImageJ. While working on this, I discovered that net.imagej.ImgPlus images that have a new net.imagej.roi.DefaultROITree that contains a net.imglib2.roi.geom.real.DefaultWritableRealPointCollection of net.imglib2.RealPoint points can’t be displayed. Here is a minimal example that replicates this bug:

import net.imagej.ImageJ;
import net.imagej.ImgPlus;
import net.imglib2.RealLocalizable;
import net.imglib2.RealPoint;
import net.imglib2.roi.geom.real.DefaultWritableRealPointCollection;
import net.imglib2.roi.geom.real.RealPointCollection;
import net.imglib2.img.Img;
import net.imagej.roi.DefaultROITree;

import java.io.IOException;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class RealPointCollectionTest {
    private static void run() throws IOException {
        ImageJ ij = new ImageJ();

        // open blobs
        Img img = (Img) ij.io().open(Object.class.getResource("/blobs.png").getPath());
        ImgPlus imgPlus = new ImgPlus(img);

        // create points
        List<RealLocalizable> points =  new ArrayList<>(5);
        points.add(new RealPoint(new double[] {50, 200}));
        points.add(new RealPoint(new double[] {180, 90}));
        points.add(new RealPoint(new double[] {62, 76}));
        points.add(new RealPoint(new double[] {90, 110}));
        points.add(new RealPoint(new double[] {12, 80}));
        RealPointCollection< ? > rpc = new DefaultWritableRealPointCollection<>(points);

        // create ROITree and add points
        final DefaultROITree tree = new DefaultROITree();
        tree.addROIs(Arrays.asList(rpc));

        // create metadata map
        Map<String, DefaultROITree> metadata = new HashMap<>();
        metadata.put("rois", tree);

        // attach metadata to the imgplus
        imgPlus.getProperties().putAll(metadata);

        // show blobs
        ij.ui().show(imgPlus);
    }

    public static void main(String...args) throws IOException {
        run();
    }
}

And here's the stack trace:

[ERROR] java.lang.reflect.InvocationTargetException
        at java.awt.EventQueue.invokeAndWait(EventQueue.java:1349)
        at java.awt.EventQueue.invokeAndWait(EventQueue.java:1324)
        at org.scijava.thread.DefaultThreadService.invoke(DefaultThreadService.java:115)
        at net.imagej.legacy.ui.LegacyUI.show(LegacyUI.java:191)
        at org.scijava.ui.AbstractUserInterface.show(AbstractUserInterface.java:103)
        at org.scijava.ui.UserInterface.show(UserInterface.java:75)
        at org.scijava.ui.DefaultUIService.show(DefaultUIService.java:247)
        at howto.images.RealPointCollectionTest.run(RealPointCollectionTest.java:48)
        at howto.images.RealPointCollectionTest.main(RealPointCollectionTest.java:52)
Caused by: java.lang.ClassCastException: net.imglib2.RealPoint cannot be cast to net.imglib2.roi.util.RealLocalizableRealPositionable
        at net.imagej.legacy.convert.roi.point.RealPointCollectionWrapper.getCoors(RealPointCollectionWrapper.java:111)
        at net.imagej.legacy.convert.roi.point.RealPointCollectionWrapper.<init>(RealPointCollectionWrapper.java:60)
        at net.imagej.legacy.convert.roi.point.WritableRealPointCollectionToPointRoiConverter.convert(WritableRealPointCollectionToPointRoiConverter.java:70)
        at net.imagej.legacy.convert.roi.point.WritableRealPointCollectionToPointRoiConverter.convert(WritableRealPointCollectionToPointRoiConverter.java:48)
        at net.imagej.legacy.convert.roi.AbstractMaskPredicateToRoiConverter.convert(AbstractMaskPredicateToRoiConverter.java:71)
        at org.scijava.convert.ConvertService.convert(ConvertService.java:68)
        at net.imagej.legacy.convert.ROITreeToOverlayConverter.addROIs(ROITreeToOverlayConverter.java:83)
        at net.imagej.legacy.convert.ROITreeToOverlayConverter.addROIs(ROITreeToOverlayConverter.java:89)
        at net.imagej.legacy.convert.ROITreeToOverlayConverter.convert(ROITreeToOverlayConverter.java:77)
        at org.scijava.convert.ConvertService.convert(ConvertService.java:68)
        at net.imagej.legacy.LegacyImageMap.synchronizeAttachmentsToImagePlus(LegacyImageMap.java:536)
        at net.imagej.legacy.LegacyImageMap.synchronizeAttachmentsToImagePlus(LegacyImageMap.java:512)
        at net.imagej.legacy.LegacyImageMap.registerDisplay(LegacyImageMap.java:268)
        at net.imagej.legacy.LegacyImageMap.registerDisplay(LegacyImageMap.java:252)
        at net.imagej.legacy.display.LegacyImageDisplayViewer.view(LegacyImageDisplayViewer.java:138)
        at net.imagej.legacy.display.LegacyImageDisplayViewer.view(LegacyImageDisplayViewer.java:107)
        at net.imagej.legacy.ui.LegacyUI$1.run(LegacyUI.java:195)
        at org.scijava.thread.DefaultThreadService.lambda$wrap$1(DefaultThreadService.java:211)
        at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:301)
        at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
        at java.awt.EventQueue.access$500(EventQueue.java:97)
        at java.awt.EventQueue$3.run(EventQueue.java:709)
        at java.awt.EventQueue$3.run(EventQueue.java:703)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
ctrueden commented 1 year ago

Confirmed that I can reproduce this bug, using the recipe above.