Skip to content

Commit

Permalink
Fix localmaxpeakfinder spot_props filter (#1839)
Browse files Browse the repository at this point in the history
* modified local_max_peak_finder to be able to remove labeled regions from masked_image when masked_image is 2D

* fixed to allow 2D data with is_volume=True

* added note LocalMaxPeakFinder on 3D data with is_volume=True is slow

* removed unnecessary code

* Update local_max_peak_finder.py

* Delete expression
  • Loading branch information
mattcai authored Jul 23, 2020
1 parent e0eb180 commit e42e071
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 12 deletions.
22 changes: 13 additions & 9 deletions examples/how_to/local_max_peak_finder.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,20 @@
:py:class:`.LocalMaxPeakFinder` finds spots by finding the optimal threshold to binarize image
into foreground (spots) and background and then using :py:func:`skimage.feature.peak_local_max` to
find local maxima or peaks in the foreground. Each peak is counted as a spot with radius equal to
one pixel. Using :py:class:`.LocalMaxPeakFinder` requires knowledge of expected spot sizes since it
uses ``min_obj_area`` and ``max_obj_area`` to filter foreground connected components before finding
peaks. ``min_distance`` is also used to to filter out noise by limiting the distance between peaks
find local maxima or peaks in the foreground. If spots are being detected in the dark areas,
increase the ``stringency`` value to increase the threshold. Using :py:class:`.LocalMaxPeakFinder`
requires knowledge of expected foreground sizes since it uses ``min_obj_area`` and
``max_obj_area`` to filter connected foreground components before finding peaks. On the low end,
``min_obj_area`` should be set to the area of one spot so that smaller foreground objects are
removed. On the high end, ``max_obj_area`` can be set to ``np.inf`` and decreased if necessary.
``min_distance`` is another threshold to filter out noise by limiting the distance between peaks
that can be detected. The recommended way to set parameters is to take a representative image and
:ref:`visually assess <howto_spotfindingresults>` results.
:ref:`visually assess <howto_spotfindingresults>` results. Each peak is counted as a spot with
radius equal to one pixel.
.. warning::
:py:class:`.LocalMaxPeakFinder` does not support finding spots on independent 2D slices of a
volume (i.e., ``is_volume = False``).
.. note::
Running :py:class:`.LocalMaxPeakFinder` on 3-Dimensional images with ``is_volume=True`` can
be extremely slow.
.. warning::
:py:class:`.LocalMaxPeakFinder` is not compatible with cropped data sets.
Expand Down Expand Up @@ -53,6 +57,6 @@
stringency=0,
min_obj_area=6,
max_obj_area=600,
is_volume=True
is_volume=False
)
spots = lmp.run(max_imgs)
13 changes: 10 additions & 3 deletions starfish/core/spots/FindSpots/local_max_peak_finder.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,14 +236,21 @@ def image_to_spots(
data_image_np = np.asarray(data_image)

# identify each spot's size by binarizing and calculating regionprops
masked_image = data_image_np[:, :] > optimal_threshold
masked_image = data_image_np > optimal_threshold
labels = label(masked_image)[0]
spot_props = regionprops(np.squeeze(labels))
if self.is_volume:
spot_props = regionprops(labels)
else:
spot_props = regionprops(np.squeeze(labels))

# mask spots whose areas are too small or too large
for spot_prop in spot_props:
if spot_prop.area < self.min_obj_area or spot_prop.area > self.max_obj_area:
masked_image[0, spot_prop.coords[:, 0], spot_prop.coords[:, 1]] = 0
if self.is_volume:
masked_image[spot_prop.coords[:, 0], spot_prop.coords[:, 1],
spot_prop.coords[:, 2]] = 0
else:
masked_image[spot_prop.coords[:, 0], spot_prop.coords[:, 1]] = 0

# store re-calculated regionprops and labels based on the area-masked image
labels = label(masked_image)[0]
Expand Down

0 comments on commit e42e071

Please sign in to comment.