Class PathObjectHierarchy

java.lang.Object
qupath.lib.objects.hierarchy.PathObjectHierarchy
All Implemented Interfaces:
Serializable

public final class PathObjectHierarchy extends Object implements Serializable
A basic hierarchy in which to store PathObjects.

This essentially contains a single PathRootObject from which all other objects can be reached using the child object lists. However, by adding/removing objects via this hierarchy (rather than through the child lists directly), it is possible to maintain a more consistent structure (e.g. by automatically inserting objects as children of the objects whose ROI completely contains the object to be added), along with a spatial cache so that objects can be extracted if their ROIs overlap with a specified region.

Note: Be cautious when deserializing - it may not result in a hierarchy in a valid state. As a workaround, you can construct a new PathObjectHierarchy and call setHierarchy(deserializedHierarchy) to ensure that you have a properly-constructed hierarchy with the same data within it.

See Also:
  • Field Details

    • HIERARCHY_COMPARATOR

      public static final Comparator<PathObject> HIERARCHY_COMPARATOR
      Comparator to use when looking for a parent annotation in the hierarchy. The logic is:
      1. Sort by area (smallest first)
      2. Sort by hierarchy level (deepest first)
      3. Sort by DefaultPathObjectComparator
      In practice, one expects an object to be placed inside the smallest containing annotation - identical areas are likely to be rare, unless obtained by duplication.
  • Constructor Details

    • PathObjectHierarchy

      public PathObjectHierarchy()
      Default constructor, creates an empty hierarchy.
  • Method Details

    • isEmpty

      public boolean isEmpty()
      Check if the hierarchy is empty (i.e. no objects apart from the root object, no feature maps)
      Returns:
    • addListener

      public void addListener(PathObjectHierarchyListener listener)
      Add a hierarchy change listener.
      Parameters:
      listener -
      Since:
      v0.4.0; replaced addPathObjectListener(PathObjectHierarchyListener)
    • removeListener

      public void removeListener(PathObjectHierarchyListener listener)
      Remove a hierarchy change listener.
      Parameters:
      listener -
      Since:
      v0.4.0; replaced removePathObjectListener(PathObjectHierarchyListener)
    • getRootObject

      public PathObject getRootObject()
      Get the root object. All other objects in the hierarchy are descendants of the root.
      Returns:
    • getTMAGrid

      public TMAGrid getTMAGrid()
      Get the TMAGrid, or null if there is no TMA grid associated with this hierarchy.
      Returns:
    • getSelectionModel

      public PathObjectSelectionModel getSelectionModel()
      Get the selection model, which handles the selection status of objects.
      Returns:
    • setTMAGrid

      public void setTMAGrid(TMAGrid tmaGrid)
      Set the tma grid for this hierarchy. If identical to the current TMA grid, nothing will happen. Otherwise, if null then any existing TMA grid will be removed.
      Parameters:
      tmaGrid -
    • insertPathObject

      public boolean insertPathObject(PathObject pathObject, boolean fireChangeEvents)
      Insert an object into the hierarchy. This differs from addObject(PathObject, boolean) in that it will seek to place the object in an appropriate location relative to existing objects, using the logic of HIERARCHY_COMPARATOR.
      Parameters:
      pathObject - the object to add
      fireChangeEvents - if true, an event will be added after adding the object. Choose false if a single event should be added after making multiple changes.
      Returns:
      true if the hierarchy changed as a result of this call, false otherwise
    • insertPathObjects

      public boolean insertPathObjects(Collection<? extends PathObject> pathObjects)
      Insert a collection of objects into the hierarchy, firing a change event on completion. This differs from addObjects(Collection) in that it will seek to place the object in an appropriate location relative to existing objects, using the logic of HIERARCHY_COMPARATOR.
      Parameters:
      pathObjects - the objects to add
      Returns:
      true if the hierarchy changed as a result of this call, false otherwise
    • resolveHierarchy

      public void resolveHierarchy()
      Attempt to resolve the parent-child relationships between all objects within the hierarchy.
    • removeObject

      public boolean removeObject(PathObject pathObject, boolean keepChildren)
      Remove a single object from the hierarchy, firing a remove event.
      Parameters:
      pathObject - the object to remove
      keepChildren - if true, retain all children and descendants of the object being removed; if false, remove these also
      Returns:
    • removeObjectWithoutUpdate

      public boolean removeObjectWithoutUpdate(PathObject pathObject, boolean keepChildren)
      Remove a single object from the hierarchy, without firing a remove event.
      Parameters:
      pathObject - the object to remove
      keepChildren - if true, retain all children and descendants of the object being removed; if false, remove these also
      Returns:
    • removeObjects

      public void removeObjects(Collection<? extends PathObject> pathObjects, boolean keepChildren)
      Remove a collection of objects, firing a single 'hierarchy changed' event afterwards to notify listeners if anything happened (i.e. if any of the objects really were found within the hierarchy) & removed.
      Parameters:
      pathObjects - the objects to remove
      keepChildren - if true, retain children and descendants of the objects being removed
    • addObject

      public boolean addObject(PathObject pathObject)
      Add an object to the hierarchy, firing an event.
      Parameters:
      pathObject -
      Returns:
    • addObject

      public boolean addObject(PathObject pathObject, boolean fireUpdate)
      Add an object to the hierarchy, optionally firing an event.
      Parameters:
      pathObject -
      fireUpdate -
      Returns:
      Since:
      v0.4.0; replaces addPathObjectWithoutUpdate(PathObject)
    • addObjectBelowParent

      public boolean addObjectBelowParent(PathObject pathObjectParent, PathObject pathObject, boolean fireUpdate)
      Add path object as descendant of the requested parent.
      Parameters:
      pathObjectParent -
      pathObject -
      fireUpdate -
      Returns:
      Since:
      v0.4.0 (replaces addPathObjectBelowParent(PathObject, PathObject, boolean)
    • addObjects

      public boolean addObjects(Collection<? extends PathObject> pathObjects)
      Add multiple objects to the hierarchy.
      Parameters:
      pathObjects -
      Returns:
      Since:
      v0.4.0; replaces addPathObjects(Collection)
    • clearAll

      public void clearAll()
      Remove all objects from the hierarchy.
    • getPointObjects

      @Deprecated public Collection<PathObject> getPointObjects(Class<? extends PathObject> cls)
      Deprecated.
      v0.6.0; use getAllPointObjects() instead, and filter by object type if required.
      Get objects that contain Point ROIs.
      Parameters:
      cls -
      Returns:
    • getAllPointObjects

      public Collection<PathObject> getAllPointObjects()
      Get all objects in the hierarchy that have a point (or multi-point) ROI.
      Returns:
    • getAllPointAnnotations

      public Collection<PathObject> getAllPointAnnotations()
      Get all annotation objects in the hierarchy that have a point (or multi-point) ROI.
      Returns:
    • getCellObjects

      public Collection<PathObject> getCellObjects()
      Get all cell objects in the hierarchy.
      Returns:
    • getTileObjects

      public Collection<PathObject> getTileObjects()
      Get all tile objects in the hierarchy.
      Returns:
    • getDetectionObjects

      public Collection<PathObject> getDetectionObjects()
      Get all detection objects in the hierarchy (including sub-classes of detections).
      Returns:
    • getAnnotationObjects

      public Collection<PathObject> getAnnotationObjects()
      Get all annotation objects in the hierarchy.
      Returns:
    • getObjects

      public Collection<PathObject> getObjects(Collection<PathObject> pathObjects, Class<? extends PathObject> cls)
      Get all objects in the hierarchy, optionally filtering to return only objects that are instances of a specific class. Note that this method returns the root object, unless it has been filtered out.
      Parameters:
      pathObjects -
      cls -
      Returns:
    • updateObject

      public void updateObject(PathObject pathObject, boolean isChanging)
      Update an object that is already in the hierarchy (e.g. because its ROI has changed).
      Parameters:
      pathObject - the object to update
      isChanging - if true, indicate that the object is still being changed. Some listeners may delay processing in expectation of an update event where isChanging is false.
    • getFlattenedObjectList

      public List<PathObject> getFlattenedObjectList(List<PathObject> list)
      Get a flattened list containing all PathObjects in the hierarchy (including from the root object).

      To get a flattened list containing all PathObjects without the root object, one can run the following:
      getFlattenedObjectList(null).stream().filter(p -> !p.isRootObject()).toList()

      Or, since v0.4.0, just use getAllObjects(boolean) instead.

      Parameters:
      list -
      Returns:
      Since:
      getAllObjects(boolean)
    • getAllObjects

      public Collection<PathObject> getAllObjects(boolean includeRoot)
      Get all the objects in the hierarchy, optionally including the root object.
      Parameters:
      includeRoot -
      Returns:
      Since:
      v0.4.0
    • nObjects

      public int nObjects()
      Number of objects in the hierarchy, excluding the root.
      Returns:
    • setHierarchy

      public void setHierarchy(PathObjectHierarchy hierarchy)
      Set the contents of this hierarchy to be the same as that of another hierarchy. In practice, this means copying the root and TMA grid of the second hierarchy.
      Parameters:
      hierarchy -
    • getObjectsForROI

      public Collection<PathObject> getObjectsForROI(Class<? extends PathObject> cls, ROI roi)
      Get the objects within a specified ROI, as defined by the general rules for resolving the hierarchy. This relies on centroids for detections (including subclasses), and a 'covers' rule for others (annotations, TMA cores).

      Note: Since v0.6.0 use of this method is discouraged, and it may be deprecated and/or removed in a future release. Instead use getAllObjectsForROI(ROI) and filter the returned collection; or, alternatively, use getAnnotationsForROI(ROI), getCellsForROI(ROI), getAllDetectionsForROI(ROI) or getTilesForROI(ROI).

      Parameters:
      cls - class of PathObjects (e.g. PathDetectionObject), or null to accept all
      roi -
      Returns:
    • getAllObjectsForROI

      public Collection<PathObject> getAllObjectsForROI(ROI roi)
      Get all objects for a ROI. This uses the same rules as resolveHierarchy(): annotations must be completely covered by the ROI, while detections need only have their centroid within the ROI.
      Parameters:
      roi -
      Returns:
      Since:
      v0.6.0
      See Also:
    • getAnnotationsForROI

      public Collection<PathObject> getAnnotationsForROI(ROI roi)
      Get all the annotations covered by the specified ROI.
      Parameters:
      roi - the ROI to use for filtering
      Returns:
      a collection of annotation objects that are completely covered by the specified ROI
      Since:
      v0.6.0
      See Also:
      Implementation Requirements
      This does not return all annotations that intersect with the ROI, but rather only those that are covered by the ROI - consistent with the behavior of resolveHierarchy().
    • getTilesForROI

      public Collection<PathObject> getTilesForROI(ROI roi)
      Get all the tile objects with centroids falling within the specified ROI. Tile objects are a special subclass of detections.
      Parameters:
      roi - the ROI to use for filtering
      Returns:
      a collection of tile objects with centroids contained within the specified ROI
      Since:
      v0.6.0
      See Also:
      Implementation Requirements
      This does not return all tiles that intersect with the ROI, but rather only those whose centroid falls within the ROI - consistent with the behavior of resolveHierarchy().
    • getCellsForROI

      public Collection<PathObject> getCellsForROI(ROI roi)
      Get all the cell objects with centroids falling within the specified ROI. Cell objects are a special subclass of detections.
      Parameters:
      roi - the ROI to use for filtering
      Returns:
      a collection of cell objects with centroids contained within the specified ROI
      Since:
      v0.6.0
      See Also:
      Implementation Requirements
      This does not return all cells that intersect with the ROI, but rather only those whose centroid falls within the ROI - consistent with the behavior of resolveHierarchy().
    • getAllDetectionsForROI

      public Collection<PathObject> getAllDetectionsForROI(ROI roi)
      Get all the detection objects with centroids falling within the specified ROI - including subclasses of detections, such as cells and tiles.
      Parameters:
      roi - the ROI to use for filtering
      Returns:
      a collection of detection objects with centroids contained within the specified ROI
      Since:
      v0.6.0
      See Also:
      Implementation Requirements
      This does not return all cells that intersect with the ROI, but rather only those whose centroid falls within the ROI - consistent with the behavior of resolveHierarchy().
    • getObjectsForRegion

      @Deprecated public Collection<PathObject> getObjectsForRegion(Class<? extends PathObject> cls, ImageRegion region, Collection<PathObject> pathObjects)
      Deprecated.
      v0.6.0, use getAllObjectsForRegion(ImageRegion, Collection) or its related methods instead.
      Get the objects overlapping or close to a specified region. Note that this performs a quick check; the results typically should be filtered if a more strict test for overlapping is applied.
      Parameters:
      cls - class of object to return (subclasses are included)
      region - requested region overlapping the objects ROI
      pathObjects - optionally collection to which objects will be added
      Returns:
      collection containing identified objects (same as the input collection, if provided)
      See Also:
    • getAllObjectsForRegion

      public Collection<PathObject> getAllObjectsForRegion(ImageRegion region, Collection<PathObject> pathObjects)
      Get all the objects overlapping or close to a specified region, optionally adding to an existing collection. Note that this performs a quick check; the results typically should be filtered if a more strict test for overlapping is applied.
      Parameters:
      region - requested region overlapping the objects ROI
      pathObjects - optional collection to which objects will be added
      Returns:
      collection containing identified objects (same as the input collection, if provided)
      Since:
      v0.6.0
      See Also:
    • getAllObjectsForRegion

      public Collection<PathObject> getAllObjectsForRegion(ImageRegion region)
      Get all the objects overlapping or close to a specified region. Note that this performs a quick check; the results typically should be filtered if a more strict test for overlapping is applied.
      Parameters:
      region - requested region overlapping the objects ROI
      Returns:
      collection containing identified objects (same as the input collection, if provided)
      Since:
      v0.6.0
      See Also:
    • getAnnotationsForRegion

      public Collection<PathObject> getAnnotationsForRegion(ImageRegion region, Collection<PathObject> pathObjects)
      Get all the annotation objects overlapping or close to a specified region, optionally adding to an existing collection. Note that this performs a quick check; the results typically should be filtered if a more strict test for overlapping is applied.
      Parameters:
      region - requested region overlapping the objects ROI
      pathObjects - optional collection to which objects will be added
      Returns:
      collection containing identified objects (same as the input collection, if provided)
      Since:
      v0.6.0
      See Also:
    • getAnnotationsForRegion

      public Collection<PathObject> getAnnotationsForRegion(ImageRegion region)
      Get all the annotation objects overlapping or close to a specified region. Note that this performs a quick check; the results typically should be filtered if a more strict test for overlapping is applied.
      Parameters:
      region - requested region overlapping the objects ROI
      Returns:
      collection containing identified objects (same as the input collection, if provided)
      Since:
      v0.6.0
      See Also:
    • getAllDetectionsForRegion

      public Collection<PathObject> getAllDetectionsForRegion(ImageRegion region, Collection<PathObject> pathObjects)
      Get all the detection objects overlapping or close to a specified region, optionally adding to an existing collection. Note that this performs a quick check; the results typically should be filtered if a more strict test for overlapping is applied.
      Parameters:
      region - requested region overlapping the objects ROI
      pathObjects - optional collection to which objects will be added
      Returns:
      collection containing identified objects (same as the input collection, if provided)
      Since:
      v0.6.0
      See Also:
    • getAllDetectionsForRegion

      public Collection<PathObject> getAllDetectionsForRegion(ImageRegion region)
      Get all the detection objects overlapping or close to a specified region. Note that this performs a quick check; the results typically should be filtered if a more strict test for overlapping is applied.
      Parameters:
      region - requested region overlapping the objects ROI
      Returns:
      collection containing identified objects (same as the input collection, if provided)
      Since:
      v0.6.0
      See Also:
    • hasObjectsForRegion

      public boolean hasObjectsForRegion(Class<? extends PathObject> cls, ImageRegion region)
      Returns true if the hierarchy contains objects overlapping a specific region, optionally filtering to identify only objects of a specific class.
      Parameters:
      cls -
      region -
      Returns:
      Since:
      v0.6.0
    • hasObjectsForRegion

      public boolean hasObjectsForRegion(ImageRegion region)
      Returns true if the hierarchy contains any objects intersecting a specific region. This is similar to getAllObjectsForRegion(ImageRegion, Collection), but does not return the objects themselves.
      Parameters:
      region -
      Returns:
      true if objects are found, false otherwise.
      Since:
      v0.6.0
      See Also:
    • hasAnnotationsForRegion

      public boolean hasAnnotationsForRegion(ImageRegion region)
      Returns true if the hierarchy contains any annotation objects intersecting a specific region. This is similar to getAnnotationsForRegion(ImageRegion, Collection), but does not return the objects themselves.
      Parameters:
      region -
      Returns:
      true if annotations are found, false otherwise.
      Since:
      v0.6.0
      See Also:
    • hasDetectionsForRegion

      public boolean hasDetectionsForRegion(ImageRegion region)
      Returns true if the hierarchy contains any detection objects (including subclasses) intersecting a specific region. This is similar to getAllDetectionsForRegion(ImageRegion, Collection), but does not return the objects themselves.
      Parameters:
      region -
      Returns:
      true if detections are found, false otherwise.
      Since:
      v0.6.0
      See Also:
    • fireObjectMeasurementsChangedEvent

      public void fireObjectMeasurementsChangedEvent(Object source, Collection<? extends PathObject> pathObjects)
      Fire a hierarchy update indicating object measurements have changed.
      Parameters:
      source -
      pathObjects -
    • fireObjectMeasurementsChangedEvent

      public void fireObjectMeasurementsChangedEvent(Object source, Collection<? extends PathObject> pathObjects, boolean isChanging)
      Fire a hierarchy update indicating object measurements have changed.
      Parameters:
      source -
      pathObjects -
      isChanging -
    • fireObjectClassificationsChangedEvent

      public void fireObjectClassificationsChangedEvent(Object source, Collection<? extends PathObject> pathObjects)
      Fire a hierarchy update indicating object classifications have changed.
      Parameters:
      source -
      pathObjects -
    • fireObjectsChangedEvent

      public void fireObjectsChangedEvent(Object source, Collection<? extends PathObject> pathObjects)
      Fire a hierarchy update indicating objects have changed.
      Parameters:
      source -
      pathObjects -
    • fireObjectsChangedEvent

      public void fireObjectsChangedEvent(Object source, Collection<? extends PathObject> pathObjects, boolean isChanging)
      Fire a hierarchy update indicating objects have changed, and may still be changing.
      Parameters:
      source -
      pathObjects -
      isChanging - is true, listeners may choose not to respond until an event is fired with isChanging false
    • fireHierarchyChangedEvent

      public void fireHierarchyChangedEvent(Object source, PathObject pathObject)
      Fire a hierarchy update indicating the hierarchy structure has changed, impacting descendants of a specified object.
      Parameters:
      source -
      pathObject -
    • fireHierarchyChangedEvent

      public void fireHierarchyChangedEvent(Object source)
      Fire a hierarchy update indicating the hierarchy structure has changed. This is often a good choice of event if multiple changes may have occurred, of if one is unsure what exactly has changed.
      Parameters:
      source -
    • getEventCount

      public long getEventCount()
      Get the number of events that were fired.

      Important notes:

      • This is a transient property (not stored in the data file)
      • The value is incremented before> listeners have been notified (so that a listener may query it)
      The purpose of this method is to support lazy evaluation within functions that depend upon the hierarchy, but where adding and removing a listener would require too much overhead. Use of the event count makes it possible to cache the result of expensive computations, and return the cached values for as long as the count is unchanged.
      Returns:
      a timestamp
      Since:
      v0.6.0
    • findAllNeighbors

      public List<PathObject> findAllNeighbors(PathObject pathObject)
      Find all neighbors of a PathObject, having the same class as the object (e.g. detection, cell, annotation). This is based on centroids and Delaunay triangulation. It also assumes 'square' pixels, and searches for neighbors only on the same 2D plane (z and t).
      Parameters:
      pathObject -

      This is an experimental method added in v0.6.0, subject to change.

      Returns:
      Since:
      v0.6.0
    • findNearestNeighbor

      public PathObject findNearestNeighbor(PathObject pathObject)
      Find the nearest neighbor of a PathObject, having the same class as the object (e.g. detection, cell, annotation). This is based on centroids and Delaunay triangulation. It also assumes 'square' pixels, and searches for neighbors only on the same 2D plane (z and t).

      This is an experimental method added in v0.6.0, subject to change.

      Parameters:
      pathObject -
      Returns:
      Since:
      v0.6.0
    • getSubdivision

      public DelaunayTools.Subdivision getSubdivision(PathObject pathObject)
      Get the subdivision containing a specific PathObject. This is based on centroids and Delaunay triangulation in 2D. It supports #findAllNeighbors(PathObject) and #findNearestNeighbor(PathObject); obtaining the subdivision enables a wider range of spatial queries.

      This is an experimental method added in v0.6.0, subject to change.

      Parameters:
      pathObject -
      Returns:
      Since:
      v0.6.0
    • getDetectionSubdivision

      public DelaunayTools.Subdivision getDetectionSubdivision(ImagePlane plane)
      Get a subdivision containing detections. This does not include sub-classes such as 'cell' or 'tile'.

      This is an experimental method added in v0.6.0, subject to change.

      Parameters:
      plane -
      Returns:
      Since:
      v0.6.0
    • getCellSubdivision

      public DelaunayTools.Subdivision getCellSubdivision(ImagePlane plane)
      Get a subdivision containing cell objects.

      This is an experimental method added in v0.6.0, subject to change.

      Parameters:
      plane -
      Returns:
      Since:
      v0.6.0
    • getAnnotationSubdivision

      public DelaunayTools.Subdivision getAnnotationSubdivision(ImagePlane plane)
      Get a subdivision containing annotation objects.

      This is an experimental method added in v0.6.0, subject to change.

      Parameters:
      plane -
      Returns:
      Since:
      v0.6.0
    • toString

      public String toString()
      Overrides:
      toString in class Object