Skip to content

Commit

Permalink
Added hierarchy and measurements docs
Browse files Browse the repository at this point in the history
  • Loading branch information
petebankhead committed May 4, 2020
1 parent eb17a80 commit 444ce18
Show file tree
Hide file tree
Showing 10 changed files with 267 additions and 30 deletions.
Binary file added docs/concepts/images/hierarchy_complex.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/concepts/images/hierarchy_view.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/concepts/images/measurement_types.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/concepts/images/qupath_approach.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
84 changes: 83 additions & 1 deletion docs/concepts/measurements.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,86 @@
Measurements
************

Not yet written for v0.2.0... see `Object measurements <https://github.com/qupath/qupath/wiki/Object-measurements>`_ on the old wiki.
In :doc:`object` it was stated that all objects have their own measurement lists.
While true, this is not the whole store.

==============================
Different kinds of measurement
==============================

There are actually three main sources of measurements for individual objects within QuPath:

1. **Measurement lists** (static)
2. **Shape statistics** (dynamic)
3. **Summary statistics** (dynamic)

The main difference between them is whether they are static (i.e. unchanging) or dynamic (i.e. updating automatically).

Measurement lists
=================

**Measurement lists** are, as the name suggests, basically just lists of measurement names and their numeric values.
These values are usually fixed when the objects is created, or added or updated by running a specific command (e.g. feature smoothing, or to add intensity features).

They are mainly important with **detections**, and provide the features used when training a classifier (see :doc:`../tutorials/cell_classification`).

Shape statistics
================

**Shape statistics** are calculated for each ROI.
They are mainly used with **annotations** and important when manually measuring structures.

QuPath can show the shape statistics for each annotation, adapted for the ROI type (e.g. length for lines, areas for areas, counts for numbers of points).
They are not stored statically in measurement lists because it is possible that the ROI for an annotation changes (e.g. if it is being drawn or moved).

Summary statistics
==================

**Summary statistics** are calculated for each **annotation** or **TMA core object** based upon whatever is known about it.

This could be the number of child or descendant objects of a particular class, or the percentage of positive cells falling within it.
These are important as the final output for biomaker scores, e.g. to provide Allred or H-scores.


====================
Viewing measurements
====================

When viewing a results table, the actual measurements can be pulled from any or all of these sources.
The user generally doesn't have to care where the measurements came from, but the distinction is crucial when scripting or trying to decipher the details of what is going on.

Of particular importance, measurement lists need to be explicitly updated and so should be used for 'permanent' measurements.
The other measurements need to be calculated dynamically.

In this regard, it is strongly preferable that summary statistics are dynamic because it's usually the case that the numbers and classifications of descendant objects could change at any moment... and it's essential to ensure that when a parent object is asked for summary measurements, they are always up-to-date.


.. figure:: images/measurement_types.jpg
:width: 60%
:align: center

Illustration of the different measurement types within QuPath. |br|
The measurement list on the left relates to the individual selected cell shown in yellow (a **detection** object).
The measurement table contains both summary and shape statistics for the polygonal **annotation** object.

The summary statistics are based upon the detection objects descended from the annotation.
More information is given in :doc:`object_hierarchy`.


==================================
A warning about summary statistics
==================================

It is important to be aware that **not all summary measurements are necessarily dynamic**.
The most common ones for pathology that are built-in to QuPath (e.g. H-score, Positive %) are dynamic, but others that are added elsewhere may not be.
It really depends upon how the person who wrote the code to make the measurement designed it.

For example, if you run a particular script to calculate a new measurement somewhere, it is possible that it creates a static measurement and adds it to a measurement list - in fact, this is actually quite likely, because it is easiest for the developer of the script to do it this way.
This means that, if you want this measurement to be updated later whenever you make further changes, you probably need to run the script again.

Therefore be careful with measurements, and try to always check that you have definitely measured what you think you have, e.g. by moving or deleting an object that you predict should have an effect on the measurement to see if the measurement in question updates (i.e. it is dynamic) or not.

.. note::

Because this can be confusing, in the future QuPath may make it clearer when measurements are dynamic and when they are not.
It is also planned to make it easier for developers to write their own dynamic measurements.
151 changes: 150 additions & 1 deletion docs/concepts/object_hierarchy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,153 @@
Object hierarchy
****************

Not yet written for v0.2.0... see `Object hierarchies <https://github.com/qupath/qupath/wiki/Object-hierarchies>`_ on the old wiki.
:doc:`Objects <objects>` in QuPath need to be stored somewhere - and that place is the *object hierarchy*.

.. important::

The hierarchy behavior has changed in v0.2.0! |br|
If you are familiar with the old behavior, be sure to read :ref:`Differences from QuPath v0.1.2`.

The name comes from the fact that the objects are all stored in a hierarchical, tree-like structure.
This is achieved by each object having having a reference to:

* One **parent object**
* Zero or more **'child' objects**

You can think of a bit like a family tree, except for the fact that an object only ever has one parent.
'Child objects of child objects' can be considered descendants.

Representing parent/child relationships makes it possible to use simple objects as the building blocks for more complex representations of image content within QuPath.

For example, an entire tissue section could be considered as one (large) object, and inside it there might be tens of smaller child objects representing different structures (e.g. vessels, tumor and stromal regions), and inside each of these there may be hundreds of further child objects that are smaller still - the individual cells.
There might even be additional, subcellular structures.

Once we can identify the objects in an image and their key relationships, generating image analysis results typically involves simply summarizing this information.

.. figure:: images/hierarchy_complex.png
:width: 60%
:align: center

Schematic illustration of an object hierarchy in QuPath.
Annotations are shown in red, detections in green.


.. admonition:: How important is the object hierarchy?

Not every analysis application needs this hierarchy information, and it can be computationally expensive to maintain all the relationships unnecessarily.
Sometimes it is better to treat objects in QuPath as simply existing in a single flat list.

In QuPath v0.2.0, you can choose to what extent you rely on maintaining hierarchical relationships between objects.
But regardless of how much you use it, it's important to know the concept exists.


=================================
The root object & its descendants
=================================

At the base of the object hierarchy is the **root object**.

The root differs from the :doc:`annotation and detection objects <objects>` we met previously in two main ways:

* the root object doesn't have a parent
* the root object doesn't have a region of interest (ROI); rather, it relates to the entire image

Each image in QuPath has only one root object associated with it.
Every other object is either one of the direct children of the root, or a more distant descendant.

=========================
Visualizing the hierarchy
=========================

The tree structure of the object hierarchy can be visualized under the :guilabel:`Hierarchy` tab.
The root object is omitted, but all other objects can be displayed.

.. figure:: images/hierarchy_view.jpg
:width: 80%
:align: center

Viewing the object hierarchy in QuPath.


.. tip::

In QuPath, it is common to have hundreds of thousands - or even millions - of objects in a single hierarchy.
Usually, most of these are detection objects.

Showing such large numbers of objects under the 'Hierarchy' tab can slow down the application.
Therefore if you right-click on the hierarchy view, you can choose not to show detections.
This can make QuPath much faster in cases where many detections are present.


===========================
Understanding relationships
===========================

Where an object falls in the hierarchy (i.e. who is its parent, who are its children) depends upon two things:

1. how the object was created
2. whether the default relationships have been overridden

The first happens automatically.
The second allows the user (or programmer) to adjust the automatic behavior where needed to support more complex scenarios.

1. How the object was created
=============================

Most detection commands in QuPath involve selecting a specific parent object (usually an annotation) first.
This defines the region of interest used for detection.

In this case, everything detected within the region of interest defined by the parent object will be assigned as a child of that parent object.

This helps preserve knowledge about how the detections were generated, and means that if the parent object is later deleted its children can (optionally) be removed as well.

.. note::

The parent is usually :doc:`locked <../starting/annotating>` when used to define a ROI for detection, so that the relationship cannot be lost by accidentally moving it.


2. Setting the hierarchy location
=================================

In many cases, the automatic assignment to a hierarchy location is fine.

But sometimes you might want to override this, perhaps because annotation objects have been added by other means (not via detection commands) and the hierarchical relationships between these should be somehow represented.

QuPath provides one built-in way to do this through :menuselection:`Objects --> Annotations... --> Resolve hierarchy`.

This applies the following rules to set object relationships:

* An *annotation* object becomes a child of another *annotation* object if its *entire ROI* is contained within the potential parent annotation
* A *detection* object becomes a child of another *annotation* object if *its ROI centroid* is contained within the potential parent annotation

Two consequences of these rules are:

* A detection is never the parent of an annotation
* Surprises can happen with detections that are very large/have weird shapes, so that their centroid falls outside the bounds of the ROI

.. tip::

If you want to apply these rules to only on few objects (not the whole hierarchy), you can select the relevant objects and choose :menuselection:`Objects --> Annotations... --> Insert into hierarchy`.


.. admonition:: Note for scripters

You can also access objects programmatically and set parent/child relationships however you like, but this should be done cautiously - since it could give some strange or counter-intuitive results.

Programmatically overriding the normal behavior is best restricted to cases where the built-in rules are excessively strict (e.g. one annotation is *almost* completely contained with another, but perhaps a few pixels fall outside).

Any time you do some weird hierarchy manipulations by scripting, be sure to call ``fireHierarchyUpdate()`` so that QuPath is notified that something has changed.
This is crucial because the ``PathObjectHierarchy`` class uses spatial caching and other tricks to keep track of where everything is.


==============================
Differences from QuPath v0.1.2
==============================

In QuPath v0.1.2, the hierarchy was resolved automatically (without asking) and this was *essential* to make sense of the measurements.

The behavior of the object hierarchy has changed in QuPath v0.2.0, with the aim of making the software faster, more powerful, and more intuitive.
In v0.2.0 the details of the hierarchy can very often be ignored, and exists only to support sophisticated workflows where it might be needed.

`This blog post <https://petebankhead.github.io/qupath/2019/11/17/changing-the-hierarchy.html>`_ describes the reasons why it changed.
To read about the earlier behavior see `Object hierarchies <https://github.com/qupath/qupath/wiki/Object-hierarchies>`_ on the old wiki.
43 changes: 16 additions & 27 deletions docs/concepts/objects.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@ The object encapsulates not only the shape of the thing, but also some propertie
The reason for extracting objects from images is that objects are easier to summarize, quantify and interpret than :doc:`billions of raw pixel values <images>`.

Objects themselves are simple, but the idea is powerful as it enables us to generate and query a complex but intuitive representation of the image as lists or hierarchies of objects.
This is the QuPath approach to :doc:`image analysis <processing_and_analysis>`.
This is the QuPath approach to image analysis :doc:`introduced in the previous section <processing_and_analysis>`.

.. figure:: images/qupath_approach.png
:width: 90%
:align: center

General workflow for analyzing images in QuPath.

===============
Types of object
Expand Down Expand Up @@ -120,6 +125,11 @@ It is frequently left empty.

To set the name of an annotation, select it in the viewer and press the :guilabel:`Enter`.


.. tip::

To toggle the visualization of annotation names, use the shortcut key :kbd:`N`.


ROI
===
Expand Down Expand Up @@ -156,7 +166,9 @@ Knowing the classification makes it possible to do more interesting things, e.g.
Measurement list
================

The **measurement list** can be interesting in itself, but it can also be useful in terms of automatically figuring out what the classification of the object should be :doc:`by training a machine learning classifier <../tutorials/cell_classification>`.
The **measurement list** encapsulates some (numeric) measurements of an object.

These measurements may be interesting in themselves, but they can also be useful to :doc:`train a machine learning classifier <../tutorials/cell_classification>` to assign classifications automatically.

.. figure:: images/objects_hierarchy.jpg
:class: shadow-image
Expand All @@ -165,31 +177,6 @@ The **measurement list** can be interesting in itself, but it can also be useful

Measurement list (bottom left) for a selected detection object.

=============================
Relationships between objects
=============================

In addition to the above, each object has two other important properties:

* A **parent object**
* A **collection of 'child' objects**

These store the relationships between different objects, in a **hierarchical** (or 'family-tree-like') way.
This is illustrated under the *Hierarchy* tab (see also the figure above).

Representing parent/child relationships makes it possible to use simple objects as the building blocks for more complex structures within QuPath.
For example, an entire tissue section could be considered as one (large) object, and inside it there might be tens of smaller child objects representing different structures (e.g. vessels, tumor and stromal regions), and inside each of these there may be hundreds of further child objects that are smaller still - the individual cells.
There might even be additional, subcellular structures.

All this is described in more detail in :doc:`object_hierarchy`.

.. tip::
Not every analysis application needs this hierarchy information, and it can be computationally expensive to maintain all the relationships unnecessarily.
Sometimes it is better to treat objects in QuPath as simply existing in a single flat list.

In QuPath v0.2.0, you can choose to what extent you rely on maintaining hierarchical relationships between objects.
But regardless of how much you use it, it's important to know the concept exists.


=======
Summary
Expand All @@ -200,3 +187,5 @@ A conceptual overview of how many images can be analyzed in QuPath is:
1. Extract objects from the image (e.g. with tissue or cell detection)
2. Classify the objects, and establish relationships between them if necessary
3. Explore and interrogate the classified objects and their relationships

Now you know the basics about objects, :doc:`the next will examines how relationships between objects are represented <object_hierarchy>`.
6 changes: 6 additions & 0 deletions docs/concepts/processing_and_analysis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ Where QuPath fits in
Although it *uses* image processing, this is generally wrapped up inside specific commands, e.g. for *Cell detection* or *TMA dearraying*.
These commands can be used to generate objects, which can then be queried and summarized as described :doc:`in the next section <objects>`.

.. figure:: images/qupath_approach.png
:width: 90%
:align: center

General workflow for analyzing images in QuPath.

This means that, for the most part, it is not necessary to have detailed knowledge of image processing to use the software (but it can help!).
Rather, users of the software are often specialists in other areas, who, after learning the basics of how QuPath works, can focus on how they apply it and how to interpret the results.

Expand Down
11 changes: 11 additions & 0 deletions docs/reference/faqs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,17 @@ How can I set the display range (brightness/contrast) exactly?
Double-clicking on the *Min/Max display* labels should work, as discussed `here <https://github.com/qupath/qupath/issues/26>`__.


Why are some commands marked as 'Deprecated'?
=============================================

The 'deprecated' flag acts as a warning that the days of that command are numbered... it is likely to be removed in a later version.

The reason for this is usually that it a) isn't considered terribly useful, or b) has been replaced by a better alternative, c) *will* be replaced by a better alternative soon.
Removing old commands helps make QuPath more maintainable, and creates space for new features to be added without the menus becoming excessively clogged up.

If you find a command you particularly need has been marked as deprecated, feel free to ask on the forum why and discuss its future.


Why can I not rotate my image more than 90 degrees?
===================================================

Expand Down
2 changes: 1 addition & 1 deletion index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Welcome to QuPath!
******************

This page hosts the new, still-developing docs for the new, still-developing QuPath v0.2.0.
This page hosts the documentation for QuPath |version|.

.. sidebar:: Using QuPath v0.1.2?

Expand Down

0 comments on commit 444ce18

Please sign in to comment.