diff --git a/doc/images/box_vs_column_seeding.png b/doc/images/box_vs_column_seeding.png new file mode 100644 index 00000000..d6216377 Binary files /dev/null and b/doc/images/box_vs_column_seeding.png differ diff --git a/doc/segmentation_parameters.rst b/doc/segmentation_parameters.rst index dbffafec..786bfb36 100644 --- a/doc/segmentation_parameters.rst +++ b/doc/segmentation_parameters.rst @@ -8,35 +8,62 @@ A full list of parameters and descriptions can be found in the API Reference: :p ========================= Basic Operating Procedure ========================= -The *tobac* watershedding segmentation algorithm selects regions of the data :code:`field` with values greater than :code:`threshold` and associates those regions with the features :code:`features` detected by feature detection (see :doc:`feature_detection_overview`). This algorithm uses a *watershedding* approach, which sets the individual features as initial seed points, and then has identified regions grow from those original seed points. For further information on watershedding segmentation, see `the scikit-image documentation `. +The *tobac* watershedding segmentation algorithm selects regions of the data :code:`field` with values greater than :code:`threshold` and associates those regions with the features :code:`features` detected by feature detection (see :doc:`feature_detection_overview`). This algorithm uses a *watershedding* approach, which sets the individual features as initial seed points, and then has identified regions grow from those original seed points. For further information on watershedding segmentation, see `the scikit-image documentation `_. Note that you can run the watershedding segmentation algorithm on any variable that shares a grid with the variable detected in the feature detection step. It is not required that the variable used in feature detection be the same as the one in segmentation (e.g., you can detect updraft features and then run segmentation on total condensate). -Segmentation can be run on 2D or 3D input data, but segmentation on 3D data using a 2D feature detection field requires careful consideration of where the vertical seeding will occur (see `Level`_). +Segmentation can be run on 2D or 3D input data and with 2D or 3D feature detection output, but segmentation on 3D data using a 2D feature detection field requires careful consideration of where the vertical seeding will occur (see `Level`_). .. _Target: ====== Target ====== -The :code:`target` parameter works similarly to how it works in feature detection (see :doc:`threshold_detection_parameters`). To segment areas that are greater than :code:`threshold`, use :code:`target='maximum'`. To segment areas that are less than :code:`threshold`, use :code:`target='minimum'`. +The :code:`target` parameter works similarly to how it works in feature detection (see :doc:`threshold_detection_parameters`). To segment areas that are greater than :code:`threshold`, use :code:`target='maximum'`. To segment areas that are less than :code:`threshold`, use :code:`target='minimum'`. .. _Threshold: ========= Threshold ========= -Unlike in multiple threshold detection in Feature Detection, Watershedding Segmentation only accepts one threshold. This value will set either the minimum (for :code:`target='maximum'`) or maximum (for :code:`target='minimum'`) value to be segmented. Note that the segmentation is not inclusive of the threshold value, meaning that only values greater than (for :code:`target='maximum'`) or smaller than (for :code:`target='minimum'`) the threshold are included in the segmented region. +Unlike in multiple threshold detection in Feature Detection, Watershedding Segmentation only accepts one threshold. This value will set either the minimum (for :code:`target='maximum'`) or maximum (for :code:`target='minimum'`) value to be segmented. Note that the segmentation is not inclusive of the threshold value, meaning that only values greater than (for :code:`target='maximum'`) or smaller than (for :code:`target='minimum'`) the threshold are included in the segmented region. .. _Level: -====================================================== -Where the 3D seeds are placed for 2D feature detection -====================================================== +=================================================== +Projecting 2D Spatial Features into 3D Segmentation +=================================================== When running feature detection on a 2D dataset and then using these detected features to segment data in 3D, there is clearly no information on where to put the seeds in the vertical. This is currently controlled by the :code:`level` parameter. By default, this parameter is :code:`None`, which seeds the full column at every 2D detected feature point. As *tobac* does not run a continuity check, this can result in undesired behavior, such as clouds in multiple layers being detected as one large object. -:code:`level` can also be set to a `slice `, which determines where in the vertical dimension (see `Vertical Coordinate`_) the features are seeded from. Note that :code:`level` operates in *array* coordinates rather than physical coordinates. +:code:`level` can also be set to a `slice `_, which determines where in the vertical dimension (see `Vertical Coordinate`_) the features are seeded from. Note that :code:`level` operates in *array* coordinates rather than physical coordinates. + + +.. _seg_2d_feature_3d: + +=================================================== +Projecting 3D Spatial Features into 2D Segmentation +=================================================== +When running feature detection on a 3D dataset and then using these detected features to segment data in 2D, the vertical coordinate is ignored. In case of vertically overlapping features, the larger :code:`Feature` value is currently seeded. + + +.. _seg_3d_feature_3d: + +=================================================== +Projecting 3D Spatial Features into 3D Segmentation +=================================================== +When running feature detection on a 3D dataset and then using these detected features to segment data in 3D, there are currently two options for determining how to seed the watershedding algorithm: *column* seeding (set by :code:`seed_3D_flag='column'`) and *box* seeding (set by :code:`seed_3D_flag='box'`). We generally recommend *box* seeding when running feature detection and segmentation in 3D. + +**Column** seeding (:code:`seed_3D_flag='column'`) works by setting seed markers throughout some or all of the vertical column at all detected feature centroids (i.e., one column per feature detected). While the default behavior is to seed throughout the full vertical column, the vertical extent of the seeds can be set by passing a `slice `_ into the :code:`level` parameter. Note that :code:`level` operates in *array* coordinates rather than physical coordinates. + +**Box** seeding (:code:`seed_3D_flag='box'`) sets a cube or rectangular seed markers around the detected feature in 3D space. The marker size is user defined (in array coordinates) by :code:`seed_3D_size` as either an integer (for a cube) or a tuple of :code:`(int, int, int)`, ordered :code:`(vertical, hdim_1, hdim_2)`. Note that :code:`seed_3D_size` must be an odd number to avoid the box becoming biased to one side. If two seed boxes overlap, the seeded area is marked with the closest feature centroid. + +.. figure:: images/box_vs_column_seeding.png + :scale: 50 % + :alt: an example 3D plot showing column seeding linking features that should not be linked + + An example plot from a numerical model simulation showing the real-world difference between column and box seeding with a tilted feature. As this image demonstrates, box seeding is typically recommended for 3D data. + .. _Max Distance: diff --git a/tobac/segmentation.py b/tobac/segmentation.py index b59d7975..dc971420 100644 --- a/tobac/segmentation.py +++ b/tobac/segmentation.py @@ -67,7 +67,7 @@ def add_markers( Array to add the markers to. Assumes a (z, y, x) configuration. seed_3D_flag: str('column', 'box') Seed 3D field at feature positions with either the full column - or a box of user-set size + or a box of user-set size seed_3D_size: int or tuple (dimensions equal to dimensions of `field`) This sets the size of the seed box when `seed_3D_flag` is 'box'. If it's an integer (units of number of pixels), the seed box is identical in all dimensions. @@ -395,7 +395,7 @@ def segmentation_timestep( 'both' means that we are periodic along both horizontal dimensions seed_3D_flag: str('column', 'box') Seed 3D field at feature positions with either the full column (default) - or a box of user-set size + or a box of user-set size seed_3D_size: int or tuple (dimensions equal to dimensions of `field`) This sets the size of the seed box when `seed_3D_flag` is 'box'. If it's an integer (units of number of pixels), the seed box is identical in all dimensions. @@ -1185,7 +1185,7 @@ def segmentation( seed_3D_flag: str('column', 'box') Seed 3D field at feature positions with either the full column (default) - or a box of user-set size + or a box of user-set size seed_3D_size: int or tuple (dimensions equal to dimensions of `field`) This sets the size of the seed box when `seed_3D_flag` is 'box'. If it's an