Bug in Hiearachy (0.13)

Playing around with scripts to export for DL I found a strange behavior in the hierarchy for (0.1.3 and 0.2m4, so I guess all versions). This is what happens:

Scenario 1 (the desired behavior)
-Make tissueannotation
-make tiles (not annotation tiles)
-select tissueannotation
-add annotation inside tile
-corresponding hierarchy = tissueannotation->tile->annotation

Scenario 2 (the undesired behavior)
-Make tissueannotation
-make tiles (not annotation tiles)
-select tile
-add annotation inside tile
-corresponding hierarchy = tissueannotation->annotation->tile

Not a big problem once you know about it, but could potentially create some problems

It’s not clear to me if this is a bug or just a limitation in how the hierarchy works: https://github.com/qupath/qupath/wiki/Object-hierarchies

Basically, detections (including tiles) are assigned based on their centroid. Annotations are assigned based on their full contour. The latter is much more computationally expensive, and would be infeasible for large numbers of detections. But if annotations used centroids then even weirder things could happen (e.g. for multi-part annotations, or annotations with holes).

It’s debatable if this is the ‘right’ behavior or not… and I’m not entirely satisfied with the hierarchy idea in the longer term, although it has some benefits.

From your description it seems to me that it is operating as intended… even if it remains debatable whether the intentions are right.

Or have I misunderstood?

Indeed you are right. Selection of the tile had nothing to do with it. The tile was assigned as the child of the annotation inside it because its centroid was inside the annotation.

Currently the situation is as follows in the case of annotations inside a single tile:
-An annotation inside a tile containing the centroid of the tile is considered the parent of the tile
-An annotation inside a tile not containing the centroid of the tile is considered the child of the tile
-If two or more annotations are inside a tile and one of them contain the centroid of the tile. Then the hierarchy will be annotation(containing centorid)->tile->other annotations within the tile

Or even worse

Notice that the highlighted circle is the child of the outer large square on the right.

I guess there is no way to address this without rewriting the hierarchy. But nice to know about

Yes, when overlaps are involved there are more ways to confound the hierarchy than I really appreciated (or needed to consider) at the time I first wrote it. Sometimes the order in which the annotations are created can matter, which doesn’t exactly feel right.

On the other hand, it is really helpful for the data model to be able to represent tissue in a hierarchical way… so dropping the concept entirely would potentially lose a lot of good stuff.

I’ve written a bit about the topic, e.g.

In the longer term I can think of a couple of ways to go:

  • Forbid annotation overlaps
  • Move to a more layer-based approach

I tend towards the second option, but it’s a rather drastic solution that can’t be done quickly.

In the meantime, I think it’s best to see the hierarchy as a useful way to represent your objects if you want to use it… but taking full control really means scripting to construct it in exactly the way that fits your needs, because leaving it up to the automatic resolution isn’t robust enough in many cases.

But also, for most applications the hierarchy is never really more than 2 levels deep and can often be ignored. The changes in v0.2.0 to be able to count objects based on spatial location rather than strictly where they hierarchy makes the whole concept much less important than it was in v0.1.2 in these cases.

Thanks for the answers. I guess the bottom line is: The hierarchy mostly works except for a rare few cases like me who abuses it badly. However, once you are aware of these shortcomings it is easy to overcome them.

I mostly run into issues when I script (abuse QuPath). This was the first I was able to make the hierarchy fail using ordinary commands. The problem is obviously that you are not supposed to make an annotation inside a detection.

So last night I tried something, and it has turned into a proposed change that may address this… curious what you think of it…

For now, it’s only documented on Twitter (or the commits on my fork)

1 Like

This is a big step in the right direction! I have some scripts that use opening-closing to create new annotations and filter “noise”. I guess these will work much smoother now. Previously I had to downsample ~256-512x in ordner to make these run smoothly.

For the future, perhaps a split situation will be optimal.
-the hierarchy working as it currently is with minor modifications as a basic mode suitable for most situations
-A fully custom, scriptable layered approach as an advanced mode

However, the code needs to be maintainable, so supporting too many weird wishes is perhaps not best afterall…:slight_smile:

1 Like