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.
Files changed (112) hide show
  1. {cellprofiler_library_nightly-5.0.0.dev611/cellprofiler_library_nightly.egg-info → cellprofiler_library_nightly-5.0.0.dev627}/PKG-INFO +1 -1
  2. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/_version.py +3 -3
  3. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/functions/measurement.py +463 -1
  4. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/functions/object_processing.py +33 -0
  5. cellprofiler_library_nightly-5.0.0.dev627/cellprofiler_library/modules/_measureobjectintensitydistribution.py +423 -0
  6. cellprofiler_library_nightly-5.0.0.dev627/cellprofiler_library/opts/measureobjectintensitydistribution.py +94 -0
  7. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/types.py +1 -0
  8. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627/cellprofiler_library_nightly.egg-info}/PKG-INFO +1 -1
  9. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library_nightly.egg-info/SOURCES.txt +2 -0
  10. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/LICENSE +0 -0
  11. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/README.md +0 -0
  12. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/__init__.py +0 -0
  13. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/functions/__init__.py +0 -0
  14. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/functions/file_processing.py +0 -0
  15. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/functions/image_processing.py +0 -0
  16. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/functions/segmentation.py +0 -0
  17. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/measurement_model.py +0 -0
  18. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/__init__.py +0 -0
  19. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_closing.py +0 -0
  20. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_colortogray.py +0 -0
  21. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_combineobjects.py +0 -0
  22. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_convertimagetoobjects.py +0 -0
  23. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_convertobjectstoimage.py +0 -0
  24. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_correctilluminationapply.py +0 -0
  25. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_crop.py +0 -0
  26. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_dilateimage.py +0 -0
  27. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_dilateobjects.py +0 -0
  28. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_enhanceedges.py +0 -0
  29. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_enhanceorsuppressfeatures.py +0 -0
  30. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_erodeimage.py +0 -0
  31. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_erodeobjects.py +0 -0
  32. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_expandorshrinkobjects.py +0 -0
  33. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_fillobjects.py +0 -0
  34. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_flipandrotate.py +0 -0
  35. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_gaussianfilter.py +0 -0
  36. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_graytocolor.py +0 -0
  37. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_identifyprimaryobjects.py +0 -0
  38. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_identifysecondaryobjects.py +0 -0
  39. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_identifytertiaryobjects.py +0 -0
  40. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_imagemath.py +0 -0
  41. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measurecolocalization.py +0 -0
  42. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measuregranularity.py +0 -0
  43. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measureimageareaoccupied.py +0 -0
  44. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measureimageintensity.py +0 -0
  45. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measureimageoverlap.py +0 -0
  46. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measureimagequality.py +0 -0
  47. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measureimageskeleton.py +0 -0
  48. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measureobjectintensity.py +0 -0
  49. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measureobjectneighbors.py +0 -0
  50. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measureobjectoverlap.py +0 -0
  51. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measureobjectsizeshape.py +0 -0
  52. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_measureobjectskeleton.py +0 -0
  53. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_medialaxis.py +0 -0
  54. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_medianfilter.py +0 -0
  55. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_morph.py +0 -0
  56. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_morphologicalskeleton.py +0 -0
  57. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_opening.py +0 -0
  58. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_overlayobjects.py +0 -0
  59. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_overlayoutlines.py +0 -0
  60. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_reducenoise.py +0 -0
  61. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_removeholes.py +0 -0
  62. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_resize.py +0 -0
  63. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_savecroppedobjects.py +0 -0
  64. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_shrinktoobjectcenters.py +0 -0
  65. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_smooth.py +0 -0
  66. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_threshold.py +0 -0
  67. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/modules/_watershed.py +0 -0
  68. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/__init__.py +0 -0
  69. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/colortogray.py +0 -0
  70. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/convertimagetoobjects.py +0 -0
  71. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/convertobjectstoimage.py +0 -0
  72. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/correctilluminationapply.py +0 -0
  73. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/crop.py +0 -0
  74. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/dilateimage.py +0 -0
  75. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/dilateobjects.py +0 -0
  76. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/enhanceedges.py +0 -0
  77. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/enhanceorsuppressfeatures.py +0 -0
  78. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/erodeimage.py +0 -0
  79. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/erodeobjects.py +0 -0
  80. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/flipandrotate.py +0 -0
  81. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/graytocolor.py +0 -0
  82. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/identifyprimaryobjects.py +0 -0
  83. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/identifysecondaryobjects.py +0 -0
  84. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/identifytertiaryobjects.py +0 -0
  85. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/imagemath.py +0 -0
  86. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/measurecolocalization.py +0 -0
  87. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/measuregranularity.py +0 -0
  88. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/measureimageareaoccupied.py +0 -0
  89. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/measureimageintensity.py +0 -0
  90. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/measureimageoverlap.py +0 -0
  91. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/measureimagequality.py +0 -0
  92. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/measureimageskeleton.py +0 -0
  93. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/measureobjectintensity.py +0 -0
  94. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/measureobjectneighbors.py +0 -0
  95. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/measureobjectoverlap.py +0 -0
  96. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/measureobjectskeleton.py +0 -0
  97. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/morph.py +0 -0
  98. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/objectsizeshapefeatures.py +0 -0
  99. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/overlayoutlines.py +0 -0
  100. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/removeholes.py +0 -0
  101. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/resize.py +0 -0
  102. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/shrinktoobjectcenters.py +0 -0
  103. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/smooth.py +0 -0
  104. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/structuring_elements.py +0 -0
  105. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/opts/threshold.py +0 -0
  106. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library/py.typed +0 -0
  107. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library_nightly.egg-info/dependency_links.txt +0 -0
  108. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library_nightly.egg-info/requires.txt +0 -0
  109. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/cellprofiler_library_nightly.egg-info/top_level.txt +0 -0
  110. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/environment.yml +0 -0
  111. {cellprofiler_library_nightly-5.0.0.dev611 → cellprofiler_library_nightly-5.0.0.dev627}/pyproject.toml +0 -0
  112. {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.dev611
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.dev611'
32
- __version_tuple__ = version_tuple = (5, 0, 0, 'dev611')
31
+ __version__ = version = '5.0.0.dev627'
32
+ __version_tuple__ = version_tuple = (5, 0, 0, 'dev627')
33
33
 
34
- __commit_id__ = commit_id = 'g8f9474e82'
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],