Search in sources :

Example 1 with PointsROI

use of qupath.lib.roi.PointsROI in project qupath by qupath.

the class PointIO method writePoints.

/**
 * Write a list of point annotations to a stream.
 * @param stream
 * @param pathObjects
 * @throws IOException
 */
public static void writePoints(OutputStream stream, Collection<? extends PathObject> pathObjects) throws IOException {
    // Check that all PathObjects contain only point annotations
    int unfilteredSize = pathObjects.size();
    pathObjects = pathObjects.stream().filter(p -> p.getROI() instanceof PointsROI).collect(Collectors.toList());
    int filteredSize = pathObjects.size();
    if (unfilteredSize != filteredSize)
        logger.warn(unfilteredSize - filteredSize + " of the " + filteredSize + " elements in list is/are not point annotations. These will be skipped.");
    try (Writer writer = new BufferedWriter(new OutputStreamWriter(stream, StandardCharsets.UTF_8))) {
        List<String> cols = new ArrayList<>();
        cols.addAll(Arrays.asList("x", "y"));
        String sep = "\t";
        ImagePlane defaultPlane = ImagePlane.getDefaultPlane();
        boolean hasClass = pathObjects.stream().anyMatch(p -> p.getPathClass() != null);
        boolean hasName = pathObjects.stream().anyMatch(p -> p.getName() != null);
        boolean hasColor = pathObjects.stream().anyMatch(p -> p.getColorRGB() != null);
        boolean hasC = pathObjects.stream().anyMatch(p -> p.getROI().getC() > defaultPlane.getC());
        boolean hasZ = pathObjects.stream().anyMatch(p -> p.getROI().getZ() > defaultPlane.getZ());
        boolean hasT = pathObjects.stream().anyMatch(p -> p.getROI().getT() > defaultPlane.getT());
        if (hasC)
            cols.add("c");
        if (hasZ)
            cols.add("z");
        if (hasT)
            cols.add("t");
        if (hasClass)
            cols.add("class");
        if (hasName)
            cols.add("name");
        if (hasColor)
            cols.add("color");
        for (String col : cols) writer.write(col + sep);
        writer.write(System.lineSeparator());
        for (PathObject pathObject : pathObjects) {
            if (!PathObjectTools.hasPointROI(pathObject))
                continue;
            PointsROI points = (PointsROI) pathObject.getROI();
            for (Point2 point : points.getAllPoints()) {
                String[] row = new String[cols.size()];
                row[cols.indexOf("x")] = point.getX() + "";
                row[cols.indexOf("y")] = sep + point.getY();
                if (hasC)
                    row[cols.indexOf("c")] = sep + points.getC();
                if (hasZ)
                    row[cols.indexOf("z")] = sep + points.getZ();
                if (hasT)
                    row[cols.indexOf("t")] = sep + points.getT();
                if (hasClass)
                    row[cols.indexOf("class")] = pathObject.getPathClass() != null ? sep + pathObject.getPathClass() : sep;
                if (hasName)
                    row[cols.indexOf("name")] = pathObject.getName() != null ? sep + pathObject.getName() : sep;
                if (hasColor)
                    row[cols.indexOf("color")] = pathObject.getColorRGB() != null ? sep + pathObject.getColorRGB() : sep;
                for (String val : row) writer.write(val);
                writer.write(System.lineSeparator());
            }
        }
    }
}
Also used : ArrayList(java.util.ArrayList) PointsROI(qupath.lib.roi.PointsROI) BufferedWriter(java.io.BufferedWriter) PathObject(qupath.lib.objects.PathObject) Point2(qupath.lib.geom.Point2) OutputStreamWriter(java.io.OutputStreamWriter) ImagePlane(qupath.lib.regions.ImagePlane) OutputStreamWriter(java.io.OutputStreamWriter) BufferedWriter(java.io.BufferedWriter) Writer(java.io.Writer)

Example 2 with PointsROI

use of qupath.lib.roi.PointsROI in project qupath by qupath.

the class IJTools method convertToIJRoi.

/**
 * Convert a QuPath ROI to an ImageJ Roi.
 * @param <T>
 * @param pathROI
 * @param xOrigin x-origin indicating relationship of ImagePlus to the original image, as stored in ImageJ Calibration object
 * @param yOrigin y-origin indicating relationship of ImagePlus to the original image, as stored in ImageJ Calibration object
 * @param downsampleFactor downsample factor at which the ImagePlus was extracted from the full-resolution image
 * @return
 */
public static <T extends PathImage<ImagePlus>> Roi convertToIJRoi(ROI pathROI, double xOrigin, double yOrigin, double downsampleFactor) {
    if (pathROI instanceof PolygonROI)
        return ROIConverterIJ.convertToPolygonROI((PolygonROI) pathROI, xOrigin, yOrigin, downsampleFactor);
    if (pathROI instanceof RectangleROI)
        return ROIConverterIJ.getRectangleROI((RectangleROI) pathROI, xOrigin, yOrigin, downsampleFactor);
    if (pathROI instanceof EllipseROI)
        return ROIConverterIJ.convertToOvalROI((EllipseROI) pathROI, xOrigin, yOrigin, downsampleFactor);
    if (pathROI instanceof LineROI)
        return ROIConverterIJ.convertToLineROI((LineROI) pathROI, xOrigin, yOrigin, downsampleFactor);
    if (pathROI instanceof PolylineROI)
        return ROIConverterIJ.convertToPolygonROI((PolylineROI) pathROI, xOrigin, yOrigin, downsampleFactor);
    if (pathROI instanceof PointsROI)
        return ROIConverterIJ.convertToPointROI((PointsROI) pathROI, xOrigin, yOrigin, downsampleFactor);
    // If we have any other kind of shape, create a general shape roi
    if (pathROI != null && pathROI.isArea()) {
        // TODO: Deal with non-AWT area ROIs!
        Shape shape = RoiTools.getArea(pathROI);
        // "scaleX", "shearY", "shearX", "scaleY", "translateX", "translateY"
        shape = new AffineTransform(1.0 / downsampleFactor, 0, 0, 1.0 / downsampleFactor, xOrigin, yOrigin).createTransformedShape(shape);
        return ROIConverterIJ.setIJRoiProperties(new ShapeRoi(shape), pathROI);
    }
    // TODO: Integrate ROI not supported exception...?
    return null;
}
Also used : PolygonROI(qupath.lib.roi.PolygonROI) ShapeRoi(ij.gui.ShapeRoi) RectangleROI(qupath.lib.roi.RectangleROI) Shape(java.awt.Shape) EllipseROI(qupath.lib.roi.EllipseROI) PolylineROI(qupath.lib.roi.PolylineROI) PointsROI(qupath.lib.roi.PointsROI) AffineTransform(java.awt.geom.AffineTransform) LineROI(qupath.lib.roi.LineROI)

Example 3 with PointsROI

use of qupath.lib.roi.PointsROI in project qupath by qupath.

the class PointsTool method mouseReleased.

@Override
public void mouseReleased(MouseEvent e) {
    super.mouseReleased(e);
    if (e.getButton() != MouseButton.PRIMARY || e.isConsumed()) {
        return;
    }
    PointsROI points = getCurrentPoints();
    if (points == null)
        return;
    var viewer = getViewer();
    RoiEditor editor = viewer.getROIEditor();
    editor.resetActiveHandle();
    var currentObject = viewer.getSelectedObject();
    viewer.getHierarchy().updateObject(currentObject, false);
// viewer.getHierarchy().fireHierarchyChangedEvent(this, vcurrentObject);
// // Find out the coordinates in the image domain & update the adjustment
// Point2D p = viewer.componentPointToImagePoint(e.getX(), e.getY(), null, false);
// points.finishAdjusting(p.getX(), p.getY(), e.isShiftDown());
// points.resetMeasurements();
}
Also used : RoiEditor(qupath.lib.roi.RoiEditor) PointsROI(qupath.lib.roi.PointsROI)

Example 4 with PointsROI

use of qupath.lib.roi.PointsROI in project qupath by qupath.

the class PathClassificationLabellingHelper method getClassificationMap.

/**
 * Get a map of training data, based on the child objects of some classified annotations.
 *
 * @param hierarchy the hierarchy containing all the objects and annotations.
 * @param pointsOnly if true, only Point annotations will be used for training.
 *
 * @return
 */
public static Map<PathClass, List<PathObject>> getClassificationMap(final PathObjectHierarchy hierarchy, final boolean pointsOnly) {
    Map<PathClass, List<PathObject>> classifications = new TreeMap<>();
    // Get the annotations & filter out those that are useful
    List<PathObject> annotations = new ArrayList<>(getAnnotations(hierarchy));
    Iterator<PathObject> iter = annotations.iterator();
    while (iter.hasNext()) {
        PathObject pathObject = iter.next();
        // We need a PathClass, and may need to only include points
        if (pathObject.getPathClass() == null || pathObject.getPathClass() == PathClassFactory.getPathClass(StandardPathClasses.REGION) || (pointsOnly && !PathObjectTools.hasPointROI(pathObject)))
            iter.remove();
        else
            classifications.put(pathObject.getPathClass(), new ArrayList<>());
    }
    // from the hierarchy
    if (annotations.size() > 1) {
        annotations.sort(new Comparator<PathObject>() {

            @Override
            public int compare(PathObject o1, PathObject o2) {
                PathAnnotationObject p1 = (PathAnnotationObject) o1;
                PathAnnotationObject p2 = (PathAnnotationObject) o2;
                int comp = 0;
                if (p1.hasROI()) {
                    if (p2.hasROI()) {
                        comp = Double.compare(p1.getROI().getCentroidY(), p2.getROI().getCentroidY());
                        if (comp == 0)
                            comp = Double.compare(p1.getROI().getCentroidX(), p2.getROI().getCentroidX());
                        if (comp == 0)
                            comp = p1.getROI().toString().compareTo(p2.getROI().toString());
                    }
                }
                if (comp == 0)
                    return Integer.compare(o1.hashCode(), o2.hashCode());
                else
                    return comp;
            }
        });
    }
    // StringBuilder sb = new StringBuilder("DETECTIONS:\t");
    for (PathObject pathObject : annotations) {
        PathClass pathClass = pathObject.getPathClass();
        List<PathObject> list = classifications.get(pathClass);
        // sb.append(list.size() + ", ");
        if (PathObjectTools.hasPointROI(pathObject)) {
            for (Point2 p : ((PointsROI) pathObject.getROI()).getAllPoints()) {
                // TODO: Pay attention to z & t position!
                Collection<PathObject> pathObjectsTemp = PathObjectTools.getObjectsForLocation(hierarchy, p.getX(), p.getY(), 0, 0, -1);
                pathObjectsTemp = PathObjectTools.getObjectsOfClass(pathObjectsTemp, PathDetectionObject.class);
                // Clumsy way to avoid duplicates...
                list.removeAll(pathObjectsTemp);
                list.addAll(pathObjectsTemp);
            }
        } else
            list.addAll(hierarchy.getObjectsForROI(PathDetectionObject.class, pathObject.getROI()));
    }
    for (Entry<PathClass, List<PathObject>> entry : classifications.entrySet()) {
        logger.info(entry.getKey() + ": " + entry.getValue().size());
    }
    return classifications;
}
Also used : PathDetectionObject(qupath.lib.objects.PathDetectionObject) ArrayList(java.util.ArrayList) PointsROI(qupath.lib.roi.PointsROI) TreeMap(java.util.TreeMap) PathClass(qupath.lib.objects.classes.PathClass) PathAnnotationObject(qupath.lib.objects.PathAnnotationObject) PathObject(qupath.lib.objects.PathObject) Point2(qupath.lib.geom.Point2) ArrayList(java.util.ArrayList) List(java.util.List)

Example 5 with PointsROI

use of qupath.lib.roi.PointsROI in project qupath by qupath.

the class PathHierarchyPaintingHelper method paintPoints.

private static void paintPoints(ROI pathPoints, Graphics2D g2d, double radius, Color colorStroke, Stroke stroke, Color colorFill, double downsample) {
    PointsROI pathPointsROI = pathPoints instanceof PointsROI ? (PointsROI) pathPoints : null;
    if (pathPointsROI != null && PathPrefs.showPointHullsProperty().get()) {
        ROI convexHull = pathPointsROI.getConvexHull();
        if (convexHull != null) {
            Color colorHull = colorFill != null ? colorFill : colorStroke;
            colorHull = ColorToolsAwt.getColorWithOpacity(colorHull, 0.1);
            if (colorHull != null)
                paintShape(RoiTools.getShape(convexHull), g2d, null, null, colorHull);
        // getConvexHull().draw(g, null, colorHull);
        }
    }
    RectangularShape ellipse;
    // double radius = pathPointsROI == null ? PointsROI.defaultPointRadiusProperty().get() : pathPointsROI.getPointRadius();
    // Ensure that points are drawn with at least a radius of one, after any transforms have been applied
    double scale = Math.max(1, downsample);
    radius = (Math.max(1 / scale, radius));
    // Get clip bounds
    Rectangle2D bounds = g2d.getClipBounds();
    if (bounds != null) {
        bounds.setRect(bounds.getX() - radius, bounds.getY() - radius, bounds.getWidth() + radius * 2, bounds.getHeight() + radius * 2);
    }
    // Don't fill if we have a small radius, and use a rectangle instead of an ellipse (as this repaints much faster)
    Graphics2D g = g2d;
    if (radius / downsample < 0.5) {
        if (colorStroke == null)
            colorStroke = colorFill;
        colorFill = null;
        ellipse = new Rectangle2D.Double();
        // Use opacity to avoid obscuring points completely
        int rule = AlphaComposite.SRC_OVER;
        float alpha = (float) (radius / downsample);
        var composite = g.getComposite();
        if (composite instanceof AlphaComposite) {
            var temp = (AlphaComposite) composite;
            rule = temp.getRule();
            alpha = temp.getAlpha() * alpha;
        }
        // If we are close to completely transparent, do not paint
        if (alpha < 0.01f)
            return;
        composite = AlphaComposite.getInstance(rule, alpha);
        g = (Graphics2D) g2d.create();
        g.setComposite(composite);
    // ellipse = new Ellipse2D.Double();
    } else
        ellipse = new Ellipse2D.Double();
    g.setStroke(stroke);
    for (Point2 p : pathPoints.getAllPoints()) {
        if (bounds != null && !bounds.contains(p.getX(), p.getY()))
            continue;
        ellipse.setFrame(p.getX() - radius, p.getY() - radius, radius * 2, radius * 2);
        if (colorFill != null) {
            g.setColor(colorFill);
            g.fill(ellipse);
        }
        if (colorStroke != null) {
            g.setColor(colorStroke);
            g.draw(ellipse);
        }
    }
    if (g != g2d)
        g.dispose();
}
Also used : AlphaComposite(java.awt.AlphaComposite) Color(java.awt.Color) Rectangle2D(java.awt.geom.Rectangle2D) PointsROI(qupath.lib.roi.PointsROI) EllipseROI(qupath.lib.roi.EllipseROI) PointsROI(qupath.lib.roi.PointsROI) RectangleROI(qupath.lib.roi.RectangleROI) LineROI(qupath.lib.roi.LineROI) ROI(qupath.lib.roi.interfaces.ROI) Graphics2D(java.awt.Graphics2D) Point2(qupath.lib.geom.Point2) RectangularShape(java.awt.geom.RectangularShape)

Aggregations

PointsROI (qupath.lib.roi.PointsROI)10 PathObject (qupath.lib.objects.PathObject)5 Point2 (qupath.lib.geom.Point2)4 PathROIObject (qupath.lib.objects.PathROIObject)3 RoiEditor (qupath.lib.roi.RoiEditor)3 ROI (qupath.lib.roi.interfaces.ROI)3 Point2D (java.awt.geom.Point2D)2 ArrayList (java.util.ArrayList)2 ImagePlane (qupath.lib.regions.ImagePlane)2 EllipseROI (qupath.lib.roi.EllipseROI)2 LineROI (qupath.lib.roi.LineROI)2 RectangleROI (qupath.lib.roi.RectangleROI)2 ShapeRoi (ij.gui.ShapeRoi)1 AlphaComposite (java.awt.AlphaComposite)1 Color (java.awt.Color)1 Graphics2D (java.awt.Graphics2D)1 Shape (java.awt.Shape)1 Clipboard (java.awt.datatransfer.Clipboard)1 StringSelection (java.awt.datatransfer.StringSelection)1 AffineTransform (java.awt.geom.AffineTransform)1