Search in sources :

Example 26 with PathObject

use of qupath.lib.objects.PathObject in project qupath by qupath.

the class PathObjectTileCache method removeFromCache.

/**
 * This doesn't acquire the lock! The locking is done first.
 *
 * @param pathObject
 * @param removeChildren
 */
private void removeFromCache(PathObject pathObject, boolean removeChildren) {
    // If the cache isn't active, then nothing to remove
    if (!isActive())
        return;
    SpatialIndex mapObjects = map.get(pathObject.getClass());
    // We can remove objects from a Quadtree
    if (mapObjects instanceof Quadtree) {
        Envelope envelope = lastEnvelopeMap.get(pathObject);
        envelope = MAX_ENVELOPE;
        if (envelope != null) {
            if (mapObjects.remove(envelope, pathObject)) {
                logger.debug("Removed {} from cache", pathObject);
            } else
                logger.debug("Unable to remove {} from cache", pathObject);
        } else {
            logger.debug("No envelope found for {}", pathObject);
        }
        // Remove the children
        if (removeChildren) {
            for (PathObject child : pathObject.getChildObjectsAsArray()) removeFromCache(child, removeChildren);
        }
    } else if (mapObjects instanceof SpatialIndex && !removeChildren) {
        // We can't remove objects from a STRtree, but since we're just removing one object we can rebuild only the cache for this class
        constructCache(pathObject.getClass());
    } else {
        // If we need to remove multiple objects, better to just rebuild the entire cache
        constructCache(null);
    }
}
Also used : Quadtree(org.locationtech.jts.index.quadtree.Quadtree) PathObject(qupath.lib.objects.PathObject) SpatialIndex(org.locationtech.jts.index.SpatialIndex) Envelope(org.locationtech.jts.geom.Envelope)

Example 27 with PathObject

use of qupath.lib.objects.PathObject in project qupath by qupath.

the class PathObjectHierarchy method addPathObjects.

/**
 * Add multiple objects to the hierarchy.
 * @param pathObjects
 * @return
 */
public synchronized boolean addPathObjects(Collection<? extends PathObject> pathObjects) {
    boolean changes = false;
    int n = pathObjects.size();
    int counter = 0;
    for (PathObject pathObject : pathObjects) {
        if (n > 10000) {
            if (counter % 1000 == 0)
                logger.debug("Adding {} of {}", counter, n);
        } else if (n > 1000 && counter % 100 == 0)
            logger.debug("Adding {} of {}", counter, n);
        changes = addPathObjectToList(getRootObject(), pathObject, false) || changes;
        counter++;
    }
    if (changes)
        fireHierarchyChangedEvent(getRootObject());
    // fireChangeEvent(getRootObject());
    return changes;
}
Also used : PathObject(qupath.lib.objects.PathObject)

Example 28 with PathObject

use of qupath.lib.objects.PathObject in project qupath by qupath.

the class PathObjectHierarchy method insertPathObject.

/**
 * Insert a path object at the appropriate place in the hierarchy, without making other changes.
 * @param pathObjectParent the first potential parent; this can be used to help filter out 'impossible' parents to aid performance
 * @param pathObject the object to insert
 * @param fireChangeEvents if true, fire hierarchy change events after inserting the object
 * @param resetCache if true, reset the tile cache after adding the object; this is only used if fireChangeEvents is false
 * @return
 */
private synchronized boolean insertPathObject(PathObject pathObjectParent, PathObject pathObject, boolean fireChangeEvents, boolean resetCache) {
    if (pathObject.isTMACore()) {
        logger.warn("TMA core objects cannot be inserted - use resolveHierarchy() instead");
        return false;
    }
    // Get all the annotations that might be a parent of this object
    var region = ImageRegion.createInstance(pathObject.getROI());
    Collection<PathObject> tempSet = new HashSet<>();
    tempSet.add(getRootObject());
    tileCache.getObjectsForRegion(PathAnnotationObject.class, region, tempSet, true);
    if (tmaGrid != null)
        tileCache.getObjectsForRegion(TMACoreObject.class, region, tempSet, true);
    if (pathObjectParent != null) {
        tempSet.removeIf(p -> p != pathObjectParent && !PathObjectTools.isAncestor(p, pathObjectParent));
    }
    var possibleParentObjects = new ArrayList<PathObject>(tempSet);
    Collections.sort(possibleParentObjects, HIERARCHY_COMPARATOR);
    for (PathObject possibleParent : possibleParentObjects) {
        if (possibleParent == pathObject || possibleParent.isDetection())
            continue;
        boolean addObject;
        if (possibleParent.isRootObject()) {
            // If we've reached the root, definitely add
            addObject = true;
        } else {
            // If we're adding a detection, check centroid; otherwise check covers
            if (pathObject.isDetection())
                addObject = tileCache.containsCentroid(possibleParent, pathObject);
            else
                addObject = pathObjectParent != null && possibleParent == pathObjectParent || tileCache.covers(possibleParent, pathObject);
        }
        if (addObject) {
            // Don't add if we're already where we should be
            if (pathObject.getParent() == possibleParent)
                return false;
            // Reassign child objects if we need to
            Collection<PathObject> previousChildren = pathObject.isDetection() ? new ArrayList<>() : new ArrayList<>(possibleParent.getChildObjects());
            // Can't reassign TMA core objects (these must be directly below the root object)
            previousChildren.removeIf(p -> p.isTMACore());
            // Beware that we could have 'orphaned' detections
            if (possibleParent.isTMACore())
                possibleParent.getParent().getChildObjects().stream().filter(p -> p.isDetection()).forEach(previousChildren::add);
            possibleParent.addPathObject(pathObject);
            if (!previousChildren.isEmpty()) {
                pathObject.addPathObjects(filterObjectsForROI(pathObject.getROI(), previousChildren));
            }
            // Notify listeners of changes, if required
            if (fireChangeEvents)
                fireObjectAddedEvent(this, pathObject);
            else if (resetCache)
                tileCache.resetCache();
            return true;
        }
    }
    return true;
}
Also used : PathObject(qupath.lib.objects.PathObject) TMACoreObject(qupath.lib.objects.TMACoreObject) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 29 with PathObject

use of qupath.lib.objects.PathObject in project qupath by qupath.

the class PathObjectSelectionModel method setSelectedObject.

/**
 * Set the specified object to be selected, deselecting all others.
 * @param pathObject
 */
public void setSelectedObject(PathObject pathObject) {
    // Here we fire even when the object is the same... this is because sometimes the object is selected but not
    // in the hierarchy - and some listeners respond differently depending upon which is the case
    // if (this.pathObjectSelected == pathObject)
    // return;
    PathObject previousObject = pathObjectSelected;
    pathObjectSelected = pathObject;
    selectedSet.clear();
    if (pathObjectSelected != null)
        selectedSet.add(pathObjectSelected);
    firePathObjectSelectionChangedEvent(pathObjectSelected, previousObject);
}
Also used : PathObject(qupath.lib.objects.PathObject)

Example 30 with PathObject

use of qupath.lib.objects.PathObject in project qupath by qupath.

the class PathObjectSelectionModel method deselectObject.

/**
 * Ensure that the specified object is removed from the selection.
 * @param pathObject
 */
public void deselectObject(PathObject pathObject) {
    PathObject previousSelected = pathObjectSelected;
    boolean changes = selectedSet.remove(pathObject);
    if (pathObjectSelected == previousSelected) {
        pathObjectSelected = null;
        updateToLastSelectedObject();
        changes = true;
    }
    if (changes)
        firePathObjectSelectionChangedEvent(pathObjectSelected, previousSelected);
}
Also used : PathObject(qupath.lib.objects.PathObject)

Aggregations

PathObject (qupath.lib.objects.PathObject)182 ArrayList (java.util.ArrayList)84 ROI (qupath.lib.roi.interfaces.ROI)74 PathObjectHierarchy (qupath.lib.objects.hierarchy.PathObjectHierarchy)61 List (java.util.List)48 BufferedImage (java.awt.image.BufferedImage)37 IOException (java.io.IOException)37 PathClass (qupath.lib.objects.classes.PathClass)37 Collectors (java.util.stream.Collectors)35 PathAnnotationObject (qupath.lib.objects.PathAnnotationObject)34 Map (java.util.Map)33 Logger (org.slf4j.Logger)33 LoggerFactory (org.slf4j.LoggerFactory)33 ImageData (qupath.lib.images.ImageData)31 TMACoreObject (qupath.lib.objects.TMACoreObject)31 Collection (java.util.Collection)29 Collections (java.util.Collections)29 HashMap (java.util.HashMap)28 PathObjectTools (qupath.lib.objects.PathObjectTools)26 Arrays (java.util.Arrays)25