cellprofiler-library-nightly 5.0.0.dev611__tar.gz → 5.0.0.dev627__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cellprofiler_library_nightly-5.0.0.dev611/cellprofiler_library_nightly.egg-info → cellprofiler_library_nightly-5.0.0.dev627}/PKG-INFO +1 -1
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/_version.py +3 -3
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/functions/measurement.py +463 -1
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/functions/object_processing.py +33 -0
- cellprofiler_library_nightly-5.0.0.dev627/cellprofiler_library/modules/_measureobjectintensitydistribution.py +423 -0
- cellprofiler_library_nightly-5.0.0.dev627/cellprofiler_library/opts/measureobjectintensitydistribution.py +94 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/types.py +1 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627/cellprofiler_library_nightly.egg-info}/PKG-INFO +1 -1
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library_nightly.egg-info/SOURCES.txt +2 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/LICENSE +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/README.md +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/__init__.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/functions/__init__.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/functions/file_processing.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/functions/image_processing.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/functions/segmentation.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/measurement_model.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/__init__.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_closing.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_colortogray.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_combineobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_convertimagetoobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_convertobjectstoimage.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_correctilluminationapply.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_crop.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_dilateimage.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_dilateobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_enhanceedges.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_enhanceorsuppressfeatures.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_erodeimage.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_erodeobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_expandorshrinkobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_fillobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_flipandrotate.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_gaussianfilter.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_graytocolor.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_identifyprimaryobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_identifysecondaryobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_identifytertiaryobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_imagemath.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measurecolocalization.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measuregranularity.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measureimageareaoccupied.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measureimageintensity.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measureimageoverlap.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measureimagequality.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measureimageskeleton.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measureobjectintensity.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measureobjectneighbors.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measureobjectoverlap.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measureobjectsizeshape.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measureobjectskeleton.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_medialaxis.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_medianfilter.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_morph.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_morphologicalskeleton.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_opening.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_overlayobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_overlayoutlines.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_reducenoise.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_removeholes.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_resize.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_savecroppedobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_shrinktoobjectcenters.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_smooth.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_threshold.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_watershed.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/__init__.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/colortogray.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/convertimagetoobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/convertobjectstoimage.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/correctilluminationapply.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/crop.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/dilateimage.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/dilateobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/enhanceedges.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/enhanceorsuppressfeatures.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/erodeimage.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/erodeobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/flipandrotate.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/graytocolor.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/identifyprimaryobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/identifysecondaryobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/identifytertiaryobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/imagemath.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/measurecolocalization.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/measuregranularity.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/measureimageareaoccupied.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/measureimageintensity.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/measureimageoverlap.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/measureimagequality.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/measureimageskeleton.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/measureobjectintensity.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/measureobjectneighbors.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/measureobjectoverlap.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/measureobjectskeleton.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/morph.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/objectsizeshapefeatures.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/overlayoutlines.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/removeholes.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/resize.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/shrinktoobjectcenters.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/smooth.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/structuring_elements.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/threshold.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/py.typed +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library_nightly.egg-info/dependency_links.txt +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library_nightly.egg-info/requires.txt +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library_nightly.egg-info/top_level.txt +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/environment.yml +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/pyproject.toml +0 -0
- {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cellprofiler-library-nightly
|
|
3
|
-
Version: 5.0.0.
|
|
3
|
+
Version: 5.0.0.dev627
|
|
4
4
|
Summary: cellprofiler-library implements CellProfiler's image processing and mathematical code, and is usable as a standalone library
|
|
5
5
|
Author: Anne Carpenter, Thouis (Ray) Jones, Lee Kamentsky, Vebjorn Ljosa, David Logan, Mark Bray, Madison Swain-Bowden, Allen Goodman, Claire McQuinn, Alice Lucas, Callum Tromans-Coia
|
|
6
6
|
Author-email: Beth Cimini <bcimini@broadinstitute.org>, David Stirling <dstirling@glencoesoftware.com>, Nodar Gogoberidze <ngogober@broadinstitute.org>
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '5.0.0.
|
|
32
|
-
__version_tuple__ = version_tuple = (5, 0, 0, '
|
|
31
|
+
__version__ = version = '5.0.0.dev627'
|
|
32
|
+
__version_tuple__ = version_tuple = (5, 0, 0, 'dev627')
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'gab80ce3b5'
|
|
@@ -13,6 +13,7 @@ import centrosome.cpmorphology
|
|
|
13
13
|
import centrosome.threshold
|
|
14
14
|
import centrosome.haralick
|
|
15
15
|
import centrosome.radial_power_spectrum
|
|
16
|
+
import centrosome.zernike
|
|
16
17
|
from centrosome.outline import outline
|
|
17
18
|
from functools import reduce
|
|
18
19
|
from sklearn.cluster import KMeans
|
|
@@ -27,9 +28,10 @@ from cellprofiler_library.functions.segmentation import areas_from_ijv
|
|
|
27
28
|
from cellprofiler_library.functions.segmentation import cast_labels_to_label_set
|
|
28
29
|
from cellprofiler_library.functions.segmentation import convert_label_set_to_ijv
|
|
29
30
|
from cellprofiler_library.functions.image_processing import masked_erode, restore_scale, get_morphology_footprint
|
|
31
|
+
from cellprofiler_library.functions.object_processing import size_similarly
|
|
30
32
|
from cellprofiler_library.functions.segmentation import relate_labels
|
|
31
33
|
|
|
32
|
-
from cellprofiler_library.types import Pixel, ObjectLabel, ImageGrayscale, ImageGrayscaleMask, ImageAny, ImageBinary, ImageBinaryMask, ObjectSegmentation, ObjectLabelsDense, ObjectLabelSet, ObjectSegmentationIJV, Image2DBinary, Image2DColor, Image2DGrayscale
|
|
34
|
+
from cellprofiler_library.types import Pixel, ObjectLabel, ImageGrayscale, ImageGrayscaleMask, ImageAny, ImageBinary, ImageBinaryMask, ObjectSegmentation, ObjectLabelsDense, ObjectLabelSet, ObjectSegmentationIJV, Image2DBinary, Image2DColor, Image2DGrayscale, ObjectLabelMask
|
|
33
35
|
from cellprofiler_library.opts.objectsizeshapefeatures import get_zernike_indexes
|
|
34
36
|
from cellprofiler_library.opts.measurecolocalization import CostesMethod
|
|
35
37
|
from cellprofiler_library.opts.measureobjectoverlap import DecimationMethod as ObjectDecimationMethod
|
|
@@ -3437,3 +3439,463 @@ def measure_object_neighbors(
|
|
|
3437
3439
|
second_objects,
|
|
3438
3440
|
expanded_labels,
|
|
3439
3441
|
)
|
|
3442
|
+
|
|
3443
|
+
|
|
3444
|
+
###############################################################################
|
|
3445
|
+
# MeasureObjectIntensityDistribution
|
|
3446
|
+
###############################################################################
|
|
3447
|
+
|
|
3448
|
+
|
|
3449
|
+
def compute_center_distances(
|
|
3450
|
+
labels: ObjectSegmentation,
|
|
3451
|
+
objects_indices: NDArray[numpy.int_],
|
|
3452
|
+
center_objects_segmented: Optional[ObjectSegmentation],
|
|
3453
|
+
use_centers_of_other: bool,
|
|
3454
|
+
use_edges_of_other: bool,
|
|
3455
|
+
wants_scaled: bool,
|
|
3456
|
+
maximum_radius: int,
|
|
3457
|
+
) -> Tuple[
|
|
3458
|
+
NDArray[numpy.float_],
|
|
3459
|
+
NDArray[numpy.float_],
|
|
3460
|
+
NDArray[numpy.float_],
|
|
3461
|
+
NDArray[numpy.bool_]
|
|
3462
|
+
]:
|
|
3463
|
+
"""Compute per-pixel normalized distances from each object's center.
|
|
3464
|
+
|
|
3465
|
+
When ``center_objects_segmented`` is None, the center of each object is
|
|
3466
|
+
the point farthest from its edge. Otherwise, the supplied label matrix
|
|
3467
|
+
provides centering objects:
|
|
3468
|
+
- ``use_centers_of_other=True`` collapses each centering object to its
|
|
3469
|
+
centroid before propagating distances.
|
|
3470
|
+
- ``use_edges_of_other=True`` keeps the centering objects extended and
|
|
3471
|
+
excludes their pixels from the result.
|
|
3472
|
+
|
|
3473
|
+
Returns ``(normalized_distance, i_center, j_center, good_mask)``.
|
|
3474
|
+
"""
|
|
3475
|
+
# Distance from every labeled pixel to the nearest object edge. Combined
|
|
3476
|
+
# with the distance-from-center below, this defines the normalized radius.
|
|
3477
|
+
distance_to_edge = centrosome.cpmorphology.distance_to_edge(labels)
|
|
3478
|
+
|
|
3479
|
+
if center_objects_segmented is not None:
|
|
3480
|
+
#
|
|
3481
|
+
# Use the center of the centering objects to assign a center
|
|
3482
|
+
# to each labeled pixel using propagation.
|
|
3483
|
+
#
|
|
3484
|
+
# Resize the centering-object labels to match the object label matrix
|
|
3485
|
+
# so the two can be indexed together.
|
|
3486
|
+
center_labels, center_resized_mask = size_similarly(
|
|
3487
|
+
labels, center_objects_segmented
|
|
3488
|
+
)
|
|
3489
|
+
|
|
3490
|
+
# Count the pixels belonging to each centering object so we can ignore
|
|
3491
|
+
# any centering object that ended up empty after resizing.
|
|
3492
|
+
center_pixel_counts = centrosome.cpmorphology.fixup_scipy_ndimage_result(
|
|
3493
|
+
scipy.ndimage.sum(
|
|
3494
|
+
numpy.ones(center_labels.shape),
|
|
3495
|
+
center_labels,
|
|
3496
|
+
numpy.arange(
|
|
3497
|
+
1, numpy.max(center_labels) + 1, dtype=numpy.int32
|
|
3498
|
+
),
|
|
3499
|
+
)
|
|
3500
|
+
)
|
|
3501
|
+
|
|
3502
|
+
centers_with_pixels = center_pixel_counts > 0
|
|
3503
|
+
|
|
3504
|
+
# Integer (row, col) centroid of each centering object. The +0.5 rounds
|
|
3505
|
+
# to the nearest pixel before truncation to int.
|
|
3506
|
+
center_i, center_j = (
|
|
3507
|
+
centrosome.cpmorphology.centers_of_labels(center_labels) + 0.5
|
|
3508
|
+
).astype(int)
|
|
3509
|
+
|
|
3510
|
+
# Keep only the centroids (and labels) of the non-empty centering objects.
|
|
3511
|
+
good_center_i = center_i[centers_with_pixels]
|
|
3512
|
+
|
|
3513
|
+
good_center_j = center_j[centers_with_pixels]
|
|
3514
|
+
|
|
3515
|
+
good_center_labels = numpy.arange(1, len(center_i) + 1)[centers_with_pixels]
|
|
3516
|
+
|
|
3517
|
+
if use_centers_of_other:
|
|
3518
|
+
#
|
|
3519
|
+
# Reduce the propagation seeds to the single-pixel centroids of
|
|
3520
|
+
# the centering objects (rather than their full extent).
|
|
3521
|
+
#
|
|
3522
|
+
center_labels = numpy.zeros(center_labels.shape, int)
|
|
3523
|
+
|
|
3524
|
+
center_labels[good_center_i, good_center_j] = good_center_labels
|
|
3525
|
+
|
|
3526
|
+
# Propagate the centering-object labels outward across the objects,
|
|
3527
|
+
# recording per pixel the assigned center label and the geodesic
|
|
3528
|
+
# distance from that center.
|
|
3529
|
+
assigned_center_label, distance_from_center = centrosome.propagate.propagate(
|
|
3530
|
+
numpy.zeros(center_labels.shape), center_labels, labels != 0, 1
|
|
3531
|
+
)
|
|
3532
|
+
|
|
3533
|
+
# Erase the centers that fall outside of labels.
|
|
3534
|
+
assigned_center_label[labels == 0] = 0
|
|
3535
|
+
|
|
3536
|
+
#
|
|
3537
|
+
# If objects are hollow or crescent-shaped, there may be objects
|
|
3538
|
+
# without center labels. As a backup, assign each such object the
|
|
3539
|
+
# centering object whose centroid is closest to its center of mass.
|
|
3540
|
+
#
|
|
3541
|
+
missing_center_mask = (labels != 0) & (assigned_center_label == 0)
|
|
3542
|
+
|
|
3543
|
+
missing_labels = numpy.unique(labels[missing_center_mask])
|
|
3544
|
+
|
|
3545
|
+
if len(missing_labels):
|
|
3546
|
+
all_centers = centrosome.cpmorphology.centers_of_labels(labels)
|
|
3547
|
+
|
|
3548
|
+
missing_i_centers, missing_j_centers = all_centers[
|
|
3549
|
+
:, missing_labels - 1
|
|
3550
|
+
]
|
|
3551
|
+
|
|
3552
|
+
# Squared distance from each missing object's centroid to every
|
|
3553
|
+
# candidate centering-object centroid; argsort picks the nearest.
|
|
3554
|
+
delta_i = missing_i_centers[:, numpy.newaxis] - good_center_i[numpy.newaxis, :]
|
|
3555
|
+
|
|
3556
|
+
delta_j = missing_j_centers[:, numpy.newaxis] - good_center_j[numpy.newaxis, :]
|
|
3557
|
+
|
|
3558
|
+
nearest_center_label = good_center_labels[
|
|
3559
|
+
numpy.argsort(delta_i * delta_i + delta_j * delta_j)[:, 0]
|
|
3560
|
+
]
|
|
3561
|
+
|
|
3562
|
+
# Map every object label to its chosen center, then stamp the
|
|
3563
|
+
# assigned center onto the missing pixels.
|
|
3564
|
+
nearest_center_by_label = numpy.zeros(numpy.max(labels) + 1, int)
|
|
3565
|
+
|
|
3566
|
+
nearest_center_by_label[missing_labels] = nearest_center_label
|
|
3567
|
+
|
|
3568
|
+
assigned_center_label[missing_center_mask] = nearest_center_by_label[
|
|
3569
|
+
labels[missing_center_mask]
|
|
3570
|
+
]
|
|
3571
|
+
|
|
3572
|
+
#
|
|
3573
|
+
# Now compute the crow-flies (Euclidean) distance to the centers
|
|
3574
|
+
# of these pixels from whatever center was assigned to the object.
|
|
3575
|
+
#
|
|
3576
|
+
pixel_grid_i, pixel_grid_j = numpy.mgrid[
|
|
3577
|
+
0 : labels.shape[0], 0 : labels.shape[1]
|
|
3578
|
+
]
|
|
3579
|
+
|
|
3580
|
+
delta_i = (
|
|
3581
|
+
pixel_grid_i[missing_center_mask]
|
|
3582
|
+
- center_i[assigned_center_label[missing_center_mask] - 1]
|
|
3583
|
+
)
|
|
3584
|
+
|
|
3585
|
+
delta_j = (
|
|
3586
|
+
pixel_grid_j[missing_center_mask]
|
|
3587
|
+
- center_j[assigned_center_label[missing_center_mask] - 1]
|
|
3588
|
+
)
|
|
3589
|
+
|
|
3590
|
+
distance_from_center[missing_center_mask] = numpy.sqrt(
|
|
3591
|
+
delta_i * delta_i + delta_j * delta_j
|
|
3592
|
+
)
|
|
3593
|
+
else:
|
|
3594
|
+
#
|
|
3595
|
+
# Find the point in each object farthest away from the edge.
|
|
3596
|
+
# This does better than the centroid:
|
|
3597
|
+
# * The center is within the object
|
|
3598
|
+
# * The center tends to be an interesting point, like the center of
|
|
3599
|
+
# the nucleus or the center of one or the other of two touching cells.
|
|
3600
|
+
#
|
|
3601
|
+
center_i, center_j = centrosome.cpmorphology.maximum_position_of_labels(
|
|
3602
|
+
distance_to_edge, labels, objects_indices
|
|
3603
|
+
)
|
|
3604
|
+
|
|
3605
|
+
center_labels = numpy.zeros(labels.shape, int)
|
|
3606
|
+
|
|
3607
|
+
center_labels[center_i, center_j] = labels[center_i, center_j]
|
|
3608
|
+
|
|
3609
|
+
#
|
|
3610
|
+
# Use the coloring trick here to process touching objects in separate
|
|
3611
|
+
# operations: objects sharing a color never touch, so propagation
|
|
3612
|
+
# within one color cannot bleed across object boundaries.
|
|
3613
|
+
#
|
|
3614
|
+
colors = centrosome.cpmorphology.color_labels(labels)
|
|
3615
|
+
|
|
3616
|
+
n_colors = numpy.max(colors)
|
|
3617
|
+
|
|
3618
|
+
distance_from_center = numpy.zeros(labels.shape)
|
|
3619
|
+
|
|
3620
|
+
assigned_center_label = numpy.zeros(labels.shape, int)
|
|
3621
|
+
|
|
3622
|
+
for color in range(1, n_colors + 1):
|
|
3623
|
+
color_mask = colors == color
|
|
3624
|
+
|
|
3625
|
+
propagated_labels, propagated_distance = centrosome.propagate.propagate(
|
|
3626
|
+
numpy.zeros(center_labels.shape), center_labels, color_mask, 1
|
|
3627
|
+
)
|
|
3628
|
+
|
|
3629
|
+
distance_from_center[color_mask] = propagated_distance[color_mask]
|
|
3630
|
+
|
|
3631
|
+
assigned_center_label[color_mask] = propagated_labels[color_mask]
|
|
3632
|
+
|
|
3633
|
+
# A pixel is "good" if it was assigned to some center.
|
|
3634
|
+
good_mask = assigned_center_label > 0
|
|
3635
|
+
|
|
3636
|
+
if use_edges_of_other:
|
|
3637
|
+
# Exclude pixels within the centering objects when measuring distance
|
|
3638
|
+
# from their edges.
|
|
3639
|
+
good_mask = good_mask & (center_labels == 0)
|
|
3640
|
+
|
|
3641
|
+
# Per-pixel center coordinates, looked up by the assigned center label
|
|
3642
|
+
# (labels are 1-based, hence the -1).
|
|
3643
|
+
i_center = numpy.zeros(assigned_center_label.shape)
|
|
3644
|
+
|
|
3645
|
+
i_center[good_mask] = center_i[assigned_center_label[good_mask] - 1]
|
|
3646
|
+
|
|
3647
|
+
j_center = numpy.zeros(assigned_center_label.shape)
|
|
3648
|
+
|
|
3649
|
+
j_center[good_mask] = center_j[assigned_center_label[good_mask] - 1]
|
|
3650
|
+
|
|
3651
|
+
normalized_distance = numpy.zeros(labels.shape)
|
|
3652
|
+
|
|
3653
|
+
if wants_scaled:
|
|
3654
|
+
# Normalize so the object center is ~0 and the edge is ~1. The 0.001
|
|
3655
|
+
# guards against division by zero when a pixel is both center and edge.
|
|
3656
|
+
total_distance = distance_from_center + distance_to_edge
|
|
3657
|
+
|
|
3658
|
+
normalized_distance[good_mask] = distance_from_center[good_mask] / (
|
|
3659
|
+
total_distance[good_mask] + 0.001
|
|
3660
|
+
)
|
|
3661
|
+
else:
|
|
3662
|
+
# Fixed-scale binning: express distance as a fraction of the user's
|
|
3663
|
+
# maximum radius rather than the per-object radius.
|
|
3664
|
+
normalized_distance[good_mask] = (
|
|
3665
|
+
distance_from_center[good_mask] / maximum_radius
|
|
3666
|
+
)
|
|
3667
|
+
|
|
3668
|
+
return normalized_distance, i_center, j_center, good_mask
|
|
3669
|
+
|
|
3670
|
+
|
|
3671
|
+
def compute_per_bin_distributions(
|
|
3672
|
+
labels: ObjectSegmentation,
|
|
3673
|
+
pixel_data: ImageGrayscale,
|
|
3674
|
+
good_mask: ObjectLabelMask,
|
|
3675
|
+
normalized_distance: NDArray[numpy.float_],
|
|
3676
|
+
bin_count: int,
|
|
3677
|
+
nobjects: int,
|
|
3678
|
+
) -> Tuple[
|
|
3679
|
+
NDArray[numpy.int_],
|
|
3680
|
+
NDArray[Union[numpy.float32, numpy.float64]],
|
|
3681
|
+
NDArray[Union[numpy.float32, numpy.float64]],
|
|
3682
|
+
NDArray[Union[numpy.float32, numpy.float64]],
|
|
3683
|
+
NDArray[Union[numpy.float32, numpy.float64]],
|
|
3684
|
+
]:
|
|
3685
|
+
"""Compute per-(object, bin) intensity-fraction matrices.
|
|
3686
|
+
|
|
3687
|
+
Returns ``(bin_indexes, fraction_at_distance, mean_pixel_fraction,
|
|
3688
|
+
masked_fraction_at_distance, masked_mean_pixel_fraction)``.
|
|
3689
|
+
"""
|
|
3690
|
+
ngood_pixels: numpy.int_ = numpy.sum(good_mask)
|
|
3691
|
+
|
|
3692
|
+
good_labels = labels[good_mask]
|
|
3693
|
+
|
|
3694
|
+
bin_indexes: NDArray[numpy.int_] = (normalized_distance * bin_count).astype(int)
|
|
3695
|
+
|
|
3696
|
+
bin_indexes[bin_indexes > bin_count] = bin_count
|
|
3697
|
+
|
|
3698
|
+
labels_and_bins = (good_labels - 1, bin_indexes[good_mask])
|
|
3699
|
+
|
|
3700
|
+
histogram: NDArray[Union[numpy.float32, numpy.float64]] = scipy.sparse.coo_matrix(
|
|
3701
|
+
(pixel_data[good_mask], labels_and_bins), (nobjects, bin_count + 1)
|
|
3702
|
+
).toarray()
|
|
3703
|
+
|
|
3704
|
+
sum_by_object: NDArray[Union[numpy.float32, numpy.float64]] = numpy.sum(histogram, 1)
|
|
3705
|
+
|
|
3706
|
+
sum_by_object_per_bin: NDArray[Union[numpy.float32, numpy.float64]] = numpy.dstack([sum_by_object] * (bin_count + 1))[0]
|
|
3707
|
+
|
|
3708
|
+
fraction_at_distance: NDArray[Union[numpy.float32, numpy.float64]] = histogram / sum_by_object_per_bin
|
|
3709
|
+
|
|
3710
|
+
number_at_distance: NDArray[Union[numpy.float32, numpy.float64]] = scipy.sparse.coo_matrix(
|
|
3711
|
+
(numpy.ones(ngood_pixels), labels_and_bins), (nobjects, bin_count + 1)
|
|
3712
|
+
).toarray()
|
|
3713
|
+
|
|
3714
|
+
object_mask: NDArray[Union[numpy.float32, numpy.float64]] = number_at_distance > 0
|
|
3715
|
+
|
|
3716
|
+
sum_by_object = numpy.sum(number_at_distance, 1)
|
|
3717
|
+
|
|
3718
|
+
sum_by_object_per_bin = numpy.dstack([sum_by_object] * (bin_count + 1))[0]
|
|
3719
|
+
|
|
3720
|
+
fraction_at_bin = number_at_distance / sum_by_object_per_bin
|
|
3721
|
+
|
|
3722
|
+
mean_pixel_fraction = fraction_at_distance / (
|
|
3723
|
+
fraction_at_bin + numpy.finfo(float).eps
|
|
3724
|
+
)
|
|
3725
|
+
|
|
3726
|
+
masked_fraction_at_distance = numpy.ma.masked_array(
|
|
3727
|
+
fraction_at_distance, ~object_mask
|
|
3728
|
+
)
|
|
3729
|
+
|
|
3730
|
+
masked_mean_pixel_fraction = numpy.ma.masked_array(
|
|
3731
|
+
mean_pixel_fraction, ~object_mask
|
|
3732
|
+
)
|
|
3733
|
+
|
|
3734
|
+
return (
|
|
3735
|
+
bin_indexes,
|
|
3736
|
+
fraction_at_distance,
|
|
3737
|
+
mean_pixel_fraction,
|
|
3738
|
+
masked_fraction_at_distance,
|
|
3739
|
+
masked_mean_pixel_fraction,
|
|
3740
|
+
)
|
|
3741
|
+
|
|
3742
|
+
|
|
3743
|
+
def compute_radial_indexes(
|
|
3744
|
+
labels: ObjectSegmentation,
|
|
3745
|
+
i_center: NDArray[numpy.float_],
|
|
3746
|
+
j_center: NDArray[numpy.float_],
|
|
3747
|
+
good_mask: ObjectLabelMask,
|
|
3748
|
+
) -> NDArray[numpy.int_]:
|
|
3749
|
+
"""Assign each good-mask pixel to one of 8 angular wedges around its center.
|
|
3750
|
+
|
|
3751
|
+
Used by the radial CV computation.
|
|
3752
|
+
"""
|
|
3753
|
+
i, j = numpy.mgrid[0 : labels.shape[0], 0 : labels.shape[1]]
|
|
3754
|
+
|
|
3755
|
+
imask = i[good_mask] > i_center[good_mask]
|
|
3756
|
+
|
|
3757
|
+
jmask = j[good_mask] > j_center[good_mask]
|
|
3758
|
+
|
|
3759
|
+
absmask = abs(i[good_mask] - i_center[good_mask]) > abs(
|
|
3760
|
+
j[good_mask] - j_center[good_mask]
|
|
3761
|
+
)
|
|
3762
|
+
|
|
3763
|
+
radial_index = (
|
|
3764
|
+
imask.astype(int) + jmask.astype(int) * 2 + absmask.astype(int) * 4
|
|
3765
|
+
)
|
|
3766
|
+
|
|
3767
|
+
return radial_index
|
|
3768
|
+
|
|
3769
|
+
|
|
3770
|
+
def compute_minimum_enclosing_circles(
|
|
3771
|
+
label_indexes_pairs: ObjectLabelSet,
|
|
3772
|
+
n_objects: int,
|
|
3773
|
+
) -> Tuple[
|
|
3774
|
+
NDArray[numpy.float64],
|
|
3775
|
+
NDArray[numpy.float64],
|
|
3776
|
+
]:
|
|
3777
|
+
"""For each object, compute (i, j) center and radius of the minimum enclosing circle.
|
|
3778
|
+
|
|
3779
|
+
``label_indexes_pairs`` is a list of ``(labels_array, indexes_array)``
|
|
3780
|
+
tuples (matching the iteration shape of ``Objects.get_labels()``).
|
|
3781
|
+
Returns ``(ij, r)`` arrays sized ``n_objects + 1`` (slot 0 is unused
|
|
3782
|
+
so callers can index by 1-based label).
|
|
3783
|
+
"""
|
|
3784
|
+
ij = numpy.zeros((n_objects + 1, 2))
|
|
3785
|
+
|
|
3786
|
+
r = numpy.zeros(n_objects + 1)
|
|
3787
|
+
|
|
3788
|
+
for labels, indexes in label_indexes_pairs:
|
|
3789
|
+
ij_, r_ = centrosome.cpmorphology.minimum_enclosing_circle(
|
|
3790
|
+
labels, indexes
|
|
3791
|
+
)
|
|
3792
|
+
|
|
3793
|
+
ij[indexes] = ij_
|
|
3794
|
+
|
|
3795
|
+
r[indexes] = r_
|
|
3796
|
+
|
|
3797
|
+
return ij, r
|
|
3798
|
+
|
|
3799
|
+
|
|
3800
|
+
def prepare_object_zernike_polynomials(
|
|
3801
|
+
label_indexes_pairs: ObjectLabelSet,
|
|
3802
|
+
n_objects: int,
|
|
3803
|
+
ijv: ObjectSegmentationIJV,
|
|
3804
|
+
zernike_degree: int,
|
|
3805
|
+
) -> Tuple[
|
|
3806
|
+
NDArray[ObjectLabel],
|
|
3807
|
+
NDArray[numpy.complex128],
|
|
3808
|
+
NDArray[numpy.int32],
|
|
3809
|
+
]:
|
|
3810
|
+
"""Build per-pixel Zernike polynomial values for one object set.
|
|
3811
|
+
|
|
3812
|
+
For each labeled pixel in ``ijv``, computes its normalized position
|
|
3813
|
+
inside its object's minimum enclosing circle, then evaluates all
|
|
3814
|
+
Zernike polynomials up to ``zernike_degree`` at that position.
|
|
3815
|
+
|
|
3816
|
+
Returns ``(l, z, zernike_indexes)`` where ``l`` is the per-pixel
|
|
3817
|
+
label vector (= ``ijv[:, 2]``), ``z`` is the
|
|
3818
|
+
``(n_pixels, n_zernikes)`` complex matrix of polynomial values, and
|
|
3819
|
+
``zernike_indexes`` is the list of ``(n, m)`` pairs identifying each
|
|
3820
|
+
column of ``z``.
|
|
3821
|
+
"""
|
|
3822
|
+
ij, r = compute_minimum_enclosing_circles(label_indexes_pairs, n_objects)
|
|
3823
|
+
|
|
3824
|
+
label_vec = ijv[:, 2]
|
|
3825
|
+
|
|
3826
|
+
yx = (ijv[:, :2] - ij[label_vec, :]) / r[label_vec, numpy.newaxis]
|
|
3827
|
+
|
|
3828
|
+
zernike_indexes = centrosome.zernike.get_zernike_indexes(zernike_degree + 1)
|
|
3829
|
+
|
|
3830
|
+
zernike_polynomials = centrosome.zernike.construct_zernike_polynomials(
|
|
3831
|
+
yx[:, 1], yx[:, 0], zernike_indexes
|
|
3832
|
+
)
|
|
3833
|
+
|
|
3834
|
+
return label_vec, zernike_polynomials, zernike_indexes
|
|
3835
|
+
|
|
3836
|
+
|
|
3837
|
+
def compute_radial_cv_for_bin(
|
|
3838
|
+
nbin: int,
|
|
3839
|
+
labels: ObjectSegmentation,
|
|
3840
|
+
pixel_data: ImageGrayscale,
|
|
3841
|
+
good_mask: ObjectLabelMask,
|
|
3842
|
+
bin_indexes: NDArray[numpy.int_],
|
|
3843
|
+
radial_index: NDArray[numpy.int_],
|
|
3844
|
+
nobjects: int,
|
|
3845
|
+
) -> Tuple[
|
|
3846
|
+
NDArray[numpy.bool_],
|
|
3847
|
+
NDArray[numpy.int_],
|
|
3848
|
+
NDArray[Union[numpy.float32, numpy.float64]],
|
|
3849
|
+
NDArray[numpy.bool_],
|
|
3850
|
+
]:
|
|
3851
|
+
"""Compute the per-object radial coefficient of variation for one bin.
|
|
3852
|
+
|
|
3853
|
+
Anisotropy: split each cell into 8 angular wedges, compute the mean
|
|
3854
|
+
intensity per wedge, then the CV across wedges within this radial bin.
|
|
3855
|
+
|
|
3856
|
+
Returns ``(bin_mask, bin_labels, radial_cv, empty_object_mask)``:
|
|
3857
|
+
- ``bin_mask``: pixels in ``good_mask`` that fall in this radial bin.
|
|
3858
|
+
- ``bin_labels``: object label at each pixel in ``bin_mask``.
|
|
3859
|
+
- ``radial_cv``: length-``nobjects`` array of per-object CV values
|
|
3860
|
+
(0 for objects with no pixels in this bin).
|
|
3861
|
+
- ``empty_object_mask``: length-``nobjects`` boolean, True for objects
|
|
3862
|
+
that contributed no wedge to this bin. The caller can apply this
|
|
3863
|
+
as a numpy.ma mask when aggregating ``radial_cv``.
|
|
3864
|
+
"""
|
|
3865
|
+
# Pixels of `good_mask` that fall in this radial bin.
|
|
3866
|
+
bin_mask = good_mask & (bin_indexes == nbin)
|
|
3867
|
+
|
|
3868
|
+
bin_pixels = numpy.sum(bin_mask)
|
|
3869
|
+
|
|
3870
|
+
bin_labels = labels[bin_mask]
|
|
3871
|
+
|
|
3872
|
+
# Slice the per-pixel wedge index to just this bin's pixels. radial_index
|
|
3873
|
+
# is dense over good_mask, so filter via the same predicate.
|
|
3874
|
+
bin_radial_index = radial_index[bin_indexes[good_mask] == nbin]
|
|
3875
|
+
|
|
3876
|
+
labels_and_radii = (bin_labels - 1, bin_radial_index)
|
|
3877
|
+
|
|
3878
|
+
# Sum of pixel intensities and pixel counts per (object, wedge), as
|
|
3879
|
+
# dense (nobjects, 8) matrices via sparse construction.
|
|
3880
|
+
radial_values = scipy.sparse.coo_matrix(
|
|
3881
|
+
(pixel_data[bin_mask], labels_and_radii), (nobjects, 8)
|
|
3882
|
+
).toarray()
|
|
3883
|
+
|
|
3884
|
+
pixel_count = scipy.sparse.coo_matrix(
|
|
3885
|
+
(numpy.ones(bin_pixels), labels_and_radii), (nobjects, 8)
|
|
3886
|
+
).toarray()
|
|
3887
|
+
|
|
3888
|
+
# A wedge is "empty" if it has zero pixels in this bin. Mask those
|
|
3889
|
+
# cells so the per-object mean/std isn't biased by NaNs.
|
|
3890
|
+
wedge_empty = pixel_count == 0
|
|
3891
|
+
|
|
3892
|
+
radial_means = numpy.ma.masked_array(radial_values / pixel_count, wedge_empty)
|
|
3893
|
+
|
|
3894
|
+
radial_cv = numpy.std(radial_means, 1) / numpy.mean(radial_means, 1)
|
|
3895
|
+
|
|
3896
|
+
# Objects with no contributing wedge get CV = 0.
|
|
3897
|
+
empty_object_mask = numpy.sum(~wedge_empty, 1) == 0
|
|
3898
|
+
|
|
3899
|
+
radial_cv[empty_object_mask] = 0
|
|
3900
|
+
|
|
3901
|
+
return bin_mask, bin_labels, radial_cv, empty_object_mask
|
|
@@ -875,6 +875,39 @@ def filter_labels(
|
|
|
875
875
|
return segmented_labels_out
|
|
876
876
|
|
|
877
877
|
|
|
878
|
+
def crop_labels_and_image(
|
|
879
|
+
labels: ObjectSegmentation,
|
|
880
|
+
image: ImageAny,
|
|
881
|
+
):
|
|
882
|
+
"""Crop a labels matrix and an image to the lowest common size
|
|
883
|
+
|
|
884
|
+
labels - a n x m labels matrix
|
|
885
|
+
image - a 2-d or 3-d image
|
|
886
|
+
|
|
887
|
+
Assumes that points outside of the common boundary should be masked.
|
|
888
|
+
"""
|
|
889
|
+
min_dim1 = min(labels.shape[0], image.shape[0])
|
|
890
|
+
min_dim2 = min(labels.shape[1], image.shape[1])
|
|
891
|
+
|
|
892
|
+
if labels.ndim == 3: # volume
|
|
893
|
+
min_dim3 = min(labels.shape[2], image.shape[2])
|
|
894
|
+
|
|
895
|
+
if image.ndim == 4: # multichannel volume
|
|
896
|
+
return (
|
|
897
|
+
labels[:min_dim1, :min_dim2, :min_dim3],
|
|
898
|
+
image[:min_dim1, :min_dim2, :min_dim3, :],
|
|
899
|
+
)
|
|
900
|
+
|
|
901
|
+
return (
|
|
902
|
+
labels[:min_dim1, :min_dim2, :min_dim3],
|
|
903
|
+
image[:min_dim1, :min_dim2, :min_dim3],
|
|
904
|
+
)
|
|
905
|
+
|
|
906
|
+
if image.ndim == 3: # multichannel image
|
|
907
|
+
return labels[:min_dim1, :min_dim2], image[:min_dim1, :min_dim2, :]
|
|
908
|
+
|
|
909
|
+
return labels[:min_dim1, :min_dim2], image[:min_dim1, :min_dim2]
|
|
910
|
+
|
|
878
911
|
def size_similarly(
|
|
879
912
|
labels: ObjectSegmentation,
|
|
880
913
|
secondary: Union[ObjectSegmentation, ImageAny],
|