cellprofiler-library-nightly 5.0.0.dev634__tar.gz → 5.0.0.dev642__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 (116) hide show
  1. {cellprofiler_library_nightly-5.0.0.dev634/cellprofiler_library_nightly.egg-info → cellprofiler_library_nightly-5.0.0.dev642}/PKG-INFO +1 -1
  2. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/_version.py +3 -3
  3. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/functions/image_processing.py +251 -1
  4. cellprofiler_library_nightly-5.0.0.dev642/cellprofiler_library/modules/_identifydeadworms.py +92 -0
  5. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_measuregranularity.py +1 -1
  6. cellprofiler_library_nightly-5.0.0.dev642/cellprofiler_library/opts/identifydeadworms.py +20 -0
  7. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642/cellprofiler_library_nightly.egg-info}/PKG-INFO +1 -1
  8. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library_nightly.egg-info/SOURCES.txt +2 -0
  9. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/LICENSE +0 -0
  10. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/README.md +0 -0
  11. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/__init__.py +0 -0
  12. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/functions/__init__.py +0 -0
  13. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/functions/file_processing.py +0 -0
  14. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/functions/measurement.py +0 -0
  15. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/functions/object_processing.py +0 -0
  16. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/functions/segmentation.py +0 -0
  17. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/measurement_model.py +0 -0
  18. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/__init__.py +0 -0
  19. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_closing.py +0 -0
  20. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_colortogray.py +0 -0
  21. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_combineobjects.py +0 -0
  22. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_convertimagetoobjects.py +0 -0
  23. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_convertobjectstoimage.py +0 -0
  24. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_correctilluminationapply.py +0 -0
  25. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_crop.py +0 -0
  26. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_dilateimage.py +0 -0
  27. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_dilateobjects.py +0 -0
  28. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_enhanceedges.py +0 -0
  29. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_enhanceorsuppressfeatures.py +0 -0
  30. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_erodeimage.py +0 -0
  31. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_erodeobjects.py +0 -0
  32. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_expandorshrinkobjects.py +0 -0
  33. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_fillobjects.py +0 -0
  34. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_flipandrotate.py +0 -0
  35. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_gaussianfilter.py +0 -0
  36. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_graytocolor.py +0 -0
  37. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_identifyprimaryobjects.py +0 -0
  38. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_identifysecondaryobjects.py +0 -0
  39. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_identifytertiaryobjects.py +0 -0
  40. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_imagemath.py +0 -0
  41. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_measurecolocalization.py +0 -0
  42. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_measureimageareaoccupied.py +0 -0
  43. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_measureimageintensity.py +0 -0
  44. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_measureimageoverlap.py +0 -0
  45. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_measureimagequality.py +0 -0
  46. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_measureimageskeleton.py +0 -0
  47. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_measureobjectintensity.py +0 -0
  48. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_measureobjectintensitydistribution.py +0 -0
  49. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_measureobjectneighbors.py +0 -0
  50. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_measureobjectoverlap.py +0 -0
  51. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_measureobjectsizeshape.py +0 -0
  52. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_measureobjectskeleton.py +0 -0
  53. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_measuretexture.py +0 -0
  54. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_medialaxis.py +0 -0
  55. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_medianfilter.py +0 -0
  56. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_morph.py +0 -0
  57. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_morphologicalskeleton.py +0 -0
  58. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_opening.py +0 -0
  59. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_overlayobjects.py +0 -0
  60. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_overlayoutlines.py +0 -0
  61. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_reducenoise.py +0 -0
  62. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_removeholes.py +0 -0
  63. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_resize.py +0 -0
  64. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_savecroppedobjects.py +0 -0
  65. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_shrinktoobjectcenters.py +0 -0
  66. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_smooth.py +0 -0
  67. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_threshold.py +0 -0
  68. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/modules/_watershed.py +0 -0
  69. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/__init__.py +0 -0
  70. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/colortogray.py +0 -0
  71. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/convertimagetoobjects.py +0 -0
  72. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/convertobjectstoimage.py +0 -0
  73. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/correctilluminationapply.py +0 -0
  74. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/crop.py +0 -0
  75. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/dilateimage.py +0 -0
  76. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/dilateobjects.py +0 -0
  77. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/enhanceedges.py +0 -0
  78. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/enhanceorsuppressfeatures.py +0 -0
  79. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/erodeimage.py +0 -0
  80. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/erodeobjects.py +0 -0
  81. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/flipandrotate.py +0 -0
  82. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/graytocolor.py +0 -0
  83. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/identifyprimaryobjects.py +0 -0
  84. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/identifysecondaryobjects.py +0 -0
  85. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/identifytertiaryobjects.py +0 -0
  86. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/imagemath.py +0 -0
  87. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/measurecolocalization.py +0 -0
  88. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/measuregranularity.py +0 -0
  89. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/measureimageareaoccupied.py +0 -0
  90. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/measureimageintensity.py +0 -0
  91. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/measureimageoverlap.py +0 -0
  92. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/measureimagequality.py +0 -0
  93. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/measureimageskeleton.py +0 -0
  94. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/measureobjectintensity.py +0 -0
  95. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/measureobjectintensitydistribution.py +0 -0
  96. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/measureobjectneighbors.py +0 -0
  97. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/measureobjectoverlap.py +0 -0
  98. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/measureobjectskeleton.py +0 -0
  99. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/measuretexture.py +0 -0
  100. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/morph.py +0 -0
  101. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/objectsizeshapefeatures.py +0 -0
  102. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/overlayoutlines.py +0 -0
  103. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/removeholes.py +0 -0
  104. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/resize.py +0 -0
  105. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/shrinktoobjectcenters.py +0 -0
  106. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/smooth.py +0 -0
  107. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/structuring_elements.py +0 -0
  108. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/opts/threshold.py +0 -0
  109. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/py.typed +0 -0
  110. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library/types.py +0 -0
  111. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library_nightly.egg-info/dependency_links.txt +0 -0
  112. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library_nightly.egg-info/requires.txt +0 -0
  113. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/cellprofiler_library_nightly.egg-info/top_level.txt +0 -0
  114. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/environment.yml +0 -0
  115. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/pyproject.toml +0 -0
  116. {cellprofiler_library_nightly-5.0.0.dev634 → cellprofiler_library_nightly-5.0.0.dev642}/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.dev634
3
+ Version: 5.0.0.dev642
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.dev634'
32
- __version_tuple__ = version_tuple = (5, 0, 0, 'dev634')
31
+ __version__ = version = '5.0.0.dev642'
32
+ __version_tuple__ = version_tuple = (5, 0, 0, 'dev642')
33
33
 
34
- __commit_id__ = commit_id = 'g738dcd5a2'
34
+ __commit_id__ = commit_id = 'gd1a2f7635'
@@ -19,6 +19,9 @@ from numpy.typing import NDArray
19
19
  from centrosome.cpmorphology import fixup_scipy_ndimage_result as fix
20
20
  from typing import Any, Optional, Tuple, Callable, Union, List, cast, Dict, TypeVar
21
21
  from skimage.restoration import denoise_bilateral
22
+ from centrosome.cpmorphology import get_line_pts, all_connected_components
23
+ from scipy.ndimage import binary_erosion, binary_fill_holes
24
+ from scipy.ndimage import mean as mean_of_labels
22
25
  from cellprofiler_library.types import (
23
26
  ImageGrayscale, ImageGrayscaleMask,
24
27
  Image2DColor,
@@ -27,6 +30,7 @@ from cellprofiler_library.types import (
27
30
  ObjectSegmentation,
28
31
  Image2D, Image2DMask,
29
32
  StructuringElement, ObjectLabelSet, ImageColor, ImageBinaryMask,
33
+ Image2DBinary, ObjectLabel
30
34
  )
31
35
  from cellprofiler_library.opts import threshold as Threshold
32
36
  from cellprofiler_library.opts.enhanceorsuppressfeatures import SpeckleAccuracy, NeuriteMethod
@@ -2312,4 +2316,250 @@ def get_morphology_footprint(radius, dimensions):
2312
2316
  else:
2313
2317
  footprint = skimage.morphology.ball(radius, dtype=bool)
2314
2318
  return footprint
2315
-
2319
+
2320
+ ###############################################################################
2321
+ # IdentifyDeadWorms
2322
+ ###############################################################################
2323
+
2324
+
2325
+ def get_3d_adjacent_after_erosion(
2326
+ mask: Image2DBinary,
2327
+ angle_count: int = 32,
2328
+ worm_width: int = 100,
2329
+ worm_length: int = 10,
2330
+ ) -> Tuple[
2331
+ NDArray[numpy.int_],
2332
+ NDArray[numpy.int_],
2333
+ NDArray[numpy.int_],
2334
+ ]:
2335
+ #
2336
+ # We collect the i,j and angle of pairs of points that
2337
+ # are 3-d adjacent after erosion.
2338
+ #
2339
+ # i - the i coordinate of each point found after erosion
2340
+ # j - the j coordinate of each point found after erosion
2341
+ # a - the angle of the structuring element for each point found
2342
+ #
2343
+ i = numpy.zeros(0, int)
2344
+ j = numpy.zeros(0, int)
2345
+ a = numpy.zeros(0, int)
2346
+
2347
+ ig, jg = numpy.mgrid[0 : mask.shape[0], 0 : mask.shape[1]]
2348
+ for angle_number in range(angle_count):
2349
+ angle = float(angle_number) * numpy.pi / float(angle_count)
2350
+ strel = get_diamond(angle, worm_width, worm_length)
2351
+ erosion = binary_erosion(mask, strel)
2352
+ #
2353
+ # Accumulate the count, i, j and angle for all foreground points
2354
+ # in the erosion
2355
+ #
2356
+ this_count = numpy.sum(erosion)
2357
+ i = numpy.hstack((i, ig[erosion]))
2358
+ j = numpy.hstack((j, jg[erosion]))
2359
+ a = numpy.hstack((a, numpy.ones(this_count, float) * angle))
2360
+
2361
+ return i, j, a
2362
+
2363
+ def process_all_connected_components(
2364
+ first: NDArray[numpy.int_],
2365
+ second: NDArray[numpy.int_],
2366
+ i_center: NDArray[numpy.int_],
2367
+ j_center: NDArray[numpy.int_],
2368
+ angular_orientation: NDArray[numpy.int_],
2369
+ mask: NDArray[numpy.bool_]
2370
+ ) -> Tuple[
2371
+ NDArray[numpy.int_],
2372
+ NDArray[numpy.int_],
2373
+ NDArray[numpy.float_],
2374
+ int,
2375
+ NDArray[numpy.int_],
2376
+ NDArray[ObjectLabel],
2377
+ ]:
2378
+ #
2379
+ # Do all connected components.
2380
+ #
2381
+ if len(first) > 0:
2382
+ ij_labels = all_connected_components(first, second) + 1
2383
+ nlabels = numpy.max(ij_labels)
2384
+ label_indexes = numpy.arange(1, nlabels + 1)
2385
+ #
2386
+ # Compute the measurements
2387
+ #
2388
+ center_x = fix(mean_of_labels(j_center, ij_labels, label_indexes))
2389
+ center_y = fix(mean_of_labels(i_center, ij_labels, label_indexes))
2390
+ #
2391
+ # The angles are wierdly complicated because of the wrap-around.
2392
+ # You can imagine some horrible cases, like a circular patch of
2393
+ # "worm" in which all angles are represented or a gentle "U"
2394
+ # curve.
2395
+ #
2396
+ # For now, I'm going to use the following heuristic:
2397
+ #
2398
+ # Compute two different "angles". The angles of one go
2399
+ # from 0 to 180 and the angles of the other go from -90 to 90.
2400
+ # Take the variance of these from the mean and
2401
+ # choose the representation with the lowest variance.
2402
+ #
2403
+ # An alternative would be to compute the variance at each possible
2404
+ # dividing point. Another alternative would be to actually trace through
2405
+ # the connected components - both overkill for such an inconsequential
2406
+ # measurement I hope.
2407
+ #
2408
+ angles = fix(mean_of_labels(angular_orientation, ij_labels, label_indexes))
2409
+ angular_orientation_variance = (angular_orientation - angles[ij_labels - 1]) ** 2
2410
+
2411
+ vangles = fix(mean_of_labels(angular_orientation_variance, ij_labels, label_indexes))
2412
+
2413
+ aa = angular_orientation.copy()
2414
+ aa[angular_orientation > numpy.pi / 2] -= numpy.pi
2415
+
2416
+ aangles = fix(mean_of_labels(aa, ij_labels, label_indexes))
2417
+ aangular_orientation_variance = (aa - aangles[ij_labels - 1]) ** 2
2418
+
2419
+ vaangles = fix(mean_of_labels(aangular_orientation_variance, ij_labels, label_indexes))
2420
+
2421
+ aangles[aangles < 0] += numpy.pi
2422
+ angles[vaangles < vangles] = aangles[vaangles < vangles]
2423
+ #
2424
+ # Squish the labels to 2-d. The labels for overlaps are arbitrary.
2425
+ #
2426
+ labels = numpy.zeros(mask.shape, int)
2427
+ labels[i_center, j_center] = ij_labels
2428
+ else:
2429
+ center_x = numpy.zeros(0, int)
2430
+ center_y = numpy.zeros(0, int)
2431
+ angles = numpy.zeros(0)
2432
+ nlabels = 0
2433
+ label_indexes = numpy.zeros(0, int)
2434
+ labels = numpy.zeros(mask.shape, int)
2435
+
2436
+ return center_x, center_y, angles, nlabels, label_indexes, labels
2437
+
2438
+
2439
+ def get_diamond(
2440
+ angle: float,
2441
+ worm_width: int,
2442
+ worm_length: int
2443
+ ) -> StructuringElement:
2444
+ """Get a diamond-shaped structuring element
2445
+
2446
+ angle - angle at which to tilt the diamond
2447
+
2448
+ returns a binary array that can be used as a footprint for
2449
+ the erosion
2450
+ """
2451
+ #
2452
+ # The shape:
2453
+ #
2454
+ # + x1,y1
2455
+ #
2456
+ # x0,y0 + + x2, y2
2457
+ #
2458
+ # + x3,y3
2459
+ #
2460
+ x0 = int(numpy.sin(angle) * worm_length / 2)
2461
+ x1 = int(numpy.cos(angle) * worm_width / 2)
2462
+ x2 = -x0
2463
+ x3 = -x1
2464
+ y2 = int(numpy.cos(angle) * worm_length / 2)
2465
+ y1 = int(numpy.sin(angle) * worm_width / 2)
2466
+ y0 = -y2
2467
+ y3 = -y1
2468
+ xmax = numpy.max(numpy.abs([x0, x1, x2, x3]))
2469
+ ymax = numpy.max(numpy.abs([y0, y1, y2, y3]))
2470
+ strel = numpy.zeros((ymax * 2 + 1, xmax * 2 + 1), bool)
2471
+ index, count, i, j = get_line_pts(
2472
+ numpy.array([y0, y1, y2, y3]) + ymax,
2473
+ numpy.array([x0, x1, x2, x3]) + xmax,
2474
+ numpy.array([y1, y2, y3, y0]) + ymax,
2475
+ numpy.array([x1, x2, x3, x0]) + xmax,
2476
+ )
2477
+ strel[i, j] = True
2478
+ strel = binary_fill_holes(strel)
2479
+ return strel
2480
+
2481
+
2482
+ def find_adjacent_by_distance(
2483
+ i_center: NDArray[numpy.int_],
2484
+ j_center: NDArray[numpy.int_],
2485
+ angular_orientation: NDArray[numpy.int_],
2486
+ wants_automatic_distance: bool = True,
2487
+ worm_width: Optional[int] = 100,
2488
+ worm_length: Optional[int] = 10,
2489
+ angle_count: Optional[int] = 32,
2490
+ space_distance: Optional[float] = 5,
2491
+ angular_distance: Optional[float] = 30,
2492
+ ) -> Tuple[
2493
+ NDArray[numpy.int_],
2494
+ NDArray[numpy.int_],
2495
+ ]:
2496
+ """Return pairs of worm centers that are deemed adjacent by distance
2497
+
2498
+ i - i-centers of worms
2499
+ j - j-centers of worms
2500
+ a - angular orientation of worms
2501
+
2502
+ Returns two vectors giving the indices of the first and second
2503
+ centers that are connected.
2504
+ """
2505
+ if len(i_center) < 2:
2506
+ return numpy.zeros(len(i_center), int), numpy.zeros(len(i_center), int)
2507
+ if wants_automatic_distance:
2508
+ assert worm_width is not None and worm_length is not None, "worm_width and worm_length must be provided if wants_automatic_distance is True"
2509
+ space_distance = worm_width
2510
+ angle_distance = numpy.arctan2(
2511
+ worm_width, worm_length
2512
+ )
2513
+ angle_distance += numpy.pi / angle_count
2514
+ else:
2515
+ assert space_distance is not None and angular_distance is not None, "space_distance and angular_distance must be provided if wants_automatic_distance is False"
2516
+ space_distance = space_distance
2517
+ angle_distance = angular_distance * numpy.pi / 180
2518
+ #
2519
+ # Sort by i and break the sorted vector into chunks where
2520
+ # consecutive locations are separated by more than space_distance
2521
+ #
2522
+ order = numpy.lexsort((angular_orientation, j_center, i_center))
2523
+ i_center = i_center[order]
2524
+ j_center = j_center[order]
2525
+ angular_orientation = angular_orientation[order]
2526
+ breakpoint = numpy.hstack(([False], i_center[1:] - i_center[:-1] > space_distance))
2527
+ if numpy.all(~breakpoint):
2528
+ # No easy win - cross all with all
2529
+ first, second = numpy.mgrid[0 : len(i_center), 0 : len(i_center)]
2530
+ else:
2531
+ # The segment that each belongs to
2532
+ segment_number = numpy.cumsum(breakpoint)
2533
+ # The number of elements in each segment
2534
+ member_count = numpy.bincount(segment_number)
2535
+ # The index of the first element in the segment
2536
+ member_idx = numpy.hstack(([0], numpy.cumsum(member_count[:-1])))
2537
+ # The index of the first element, for every element in the segment
2538
+ segment_start = member_idx[segment_number]
2539
+ #
2540
+ # Develop the cross-products for each segment. Each segment has
2541
+ # member_count * member_count crosses.
2542
+ #
2543
+ # # of (first,second) pairs in each segment
2544
+ cross_size = member_count ** 2
2545
+ # Index in final array of first element of each segment
2546
+ segment_idx = numpy.cumsum(cross_size)
2547
+ # relative location of first "first"
2548
+ first_start_idx = numpy.cumsum(member_count[segment_number[:-1]])
2549
+ first = numpy.zeros(segment_idx[-1], int)
2550
+ first[first_start_idx] = 1
2551
+ # The "firsts" array
2552
+ first = numpy.cumsum(first)
2553
+ first_start_idx = numpy.hstack(([0], first_start_idx))
2554
+ second = (
2555
+ numpy.arange(len(first)) - first_start_idx[first] + segment_start[first]
2556
+ )
2557
+ mask = (
2558
+ numpy.abs((i_center[first] - i_center[second]) ** 2 + (j_center[first] - j_center[second]) ** 2)
2559
+ <= space_distance ** 2
2560
+ ) & (
2561
+ (numpy.abs(angular_orientation[first] - angular_orientation[second]) <= angle_distance)
2562
+ | (angular_orientation[first] + numpy.pi - angular_orientation[second] <= angle_distance)
2563
+ | (angular_orientation[second] + numpy.pi - angular_orientation[first] <= angle_distance)
2564
+ )
2565
+ return order[first[mask]], order[second[mask]]
@@ -0,0 +1,92 @@
1
+ import numpy
2
+
3
+ from numpy.typing import NDArray
4
+ from typing import Optional, Annotated, Union, Tuple
5
+ from pydantic import Field, validate_call, ConfigDict, BaseModel
6
+
7
+ from cellprofiler_library.types import Image2DBinary, Image2DBinaryMask, ObjectLabel
8
+ from cellprofiler_library.functions.image_processing import get_3d_adjacent_after_erosion, process_all_connected_components, find_adjacent_by_distance
9
+ from cellprofiler_library.measurement_model import LibraryMeasurements
10
+
11
+ from cellprofiler_library.opts.identifydeadworms import M_LOCATION_CENTER_X, M_LOCATION_CENTER_Y, M_ANGLE, M_NUMBER_OBJECT_NUMBER, TemplateMeasurementFormat
12
+
13
+
14
+ class IdentifyDeadWormsDisplayData(BaseModel):
15
+ model_config = ConfigDict(
16
+ arbitrary_types_allowed=True,
17
+ populate_by_name=True
18
+ )
19
+
20
+ center_x: NDArray[numpy.int_]
21
+ center_y: NDArray[numpy.int_]
22
+ angles: NDArray[numpy.float_]
23
+ mask: Image2DBinaryMask
24
+ nlabels: int
25
+
26
+
27
+ @validate_call(config=ConfigDict(arbitrary_types_allowed=True))
28
+ def identify_dead_worms(
29
+ pixel_data: Annotated[Image2DBinary, Field(description="Input binary image")],
30
+ image_mask: Annotated[Optional[Image2DBinaryMask], Field(description="Input binary image mask")],
31
+ automatic_distance: Annotated[bool, Field(default=True, description="Whether to calculate distance parameters automatically")],
32
+ worm_width: Annotated[int, Field(default=100, ge=1, description="This is the width (the short axis), measured in pixels, of the diamond used as a template when matching against the worm. It should be less than the width of a worm.")],
33
+ worm_length: Annotated[int, Field(default=10, ge=1, description="This is the length (the long axis), measured in pixels, of the diamond used as a template when matching against the worm. It should be less than the length of a worm")],
34
+ angle_count: Annotated[int, Field(description="Number of different angles at which the template will betried", ge=1)] = 32,
35
+ space_distance: Annotated[Optional[float], Field(default=5, ge=1, description="Used only if not automatically calculating distance parameters Enter the distance for calculating the worm centers, in units of pixels. The worm centers must be at least many pixels apart for the centers to be considered two separate worms.")]=5,
36
+ angular_distance: Annotated[Optional[float], Field(default=30, ge=1, description="Used only if automatically calculating distance parameters IdentifyDeadWorms calculates the worm centers at different angles. Two worm centers are considered to represent different worms if their angular distance is larger than this number. The number is measured in degrees.")]=30,
37
+ object_name: Annotated[str, Field(description="Name for the dead worm object")]="dead worm",
38
+ return_visualization_data: Annotated[bool, Field(description="Return data for display")] = False,
39
+ ) -> Union[
40
+ Tuple[NDArray[ObjectLabel], LibraryMeasurements],
41
+ Tuple[NDArray[ObjectLabel], LibraryMeasurements, IdentifyDeadWormsDisplayData]
42
+ ]:
43
+
44
+ mask = pixel_data
45
+ if image_mask is not None:
46
+ mask = mask & image_mask
47
+ #
48
+ # We collect the i,j and angle of pairs of points that
49
+ # are 3-d adjacent after erosion.
50
+ #
51
+ i_center, j_center, angular_orientation = get_3d_adjacent_after_erosion(mask, angle_count, worm_width, worm_length)
52
+
53
+ #
54
+ # Find connections based on distances, not adjacency
55
+ #
56
+ first, second = find_adjacent_by_distance(
57
+ i_center,
58
+ j_center,
59
+ angular_orientation,
60
+ automatic_distance,
61
+ worm_width,
62
+ worm_length,
63
+ angle_count,
64
+ space_distance,
65
+ angular_distance
66
+ )
67
+
68
+ #
69
+ # Do all connected components.
70
+ #
71
+ center_x, center_y, angles, nlabels, label_indexes, labels = process_all_connected_components(first, second, i_center, j_center, angular_orientation, mask)
72
+
73
+ #
74
+ # Make measurements
75
+ #
76
+ measurements = LibraryMeasurements()
77
+
78
+ measurements.add_measurement(object_name, M_LOCATION_CENTER_X, center_x)
79
+ measurements.add_measurement(object_name, M_LOCATION_CENTER_Y, center_y)
80
+ measurements.add_measurement(object_name, M_ANGLE, angles * 180 / numpy.pi)
81
+ measurements.add_measurement(object_name, M_NUMBER_OBJECT_NUMBER, label_indexes)
82
+ measurements.add_image_measurement(TemplateMeasurementFormat.FF_COUNT % object_name, nlabels)
83
+
84
+ if return_visualization_data:
85
+ return labels, measurements, IdentifyDeadWormsDisplayData(
86
+ mask=mask,
87
+ center_x=center_x,
88
+ center_y=center_y,
89
+ angles=angles,
90
+ nlabels=nlabels,
91
+ )
92
+ return labels, measurements
@@ -33,7 +33,7 @@ def measure_granularity(
33
33
  granular_spectrum_length: Annotated[int, Field(description="Range of the granular spectrum")],
34
34
  dimensions: Annotated[int, Field(description="Dimensionality of the image")] = 2,
35
35
  return_visualization_data: Annotated[bool, Field(description="Return data for display")] = False,
36
- ) -> Union[LibraryMeasurements, Tuple[LibraryMeasurements, GranularityDisplayData]]:
36
+ ) -> Union[LibraryMeasurements, Tuple[LibraryMeasurements, GranularityDisplayData]]:
37
37
  #
38
38
  # Downsample the image and mask
39
39
  #
@@ -0,0 +1,20 @@
1
+ C_LOCATION = "Location"
2
+
3
+ FTR_CENTER_X = "Center_X"
4
+ M_LOCATION_CENTER_X = f"{C_LOCATION}_{FTR_CENTER_X}"
5
+
6
+ FTR_CENTER_Y = "Center_Y"
7
+ M_LOCATION_CENTER_Y = f"{C_LOCATION}_{FTR_CENTER_Y}"
8
+
9
+ C_WORMS = "Worm"
10
+ F_ANGLE = "Angle"
11
+ M_ANGLE = f"{C_WORMS}_{F_ANGLE}"
12
+
13
+ C_NUMBER = "Number"
14
+ FTR_OBJECT_NUMBER = "Object_Number"
15
+ M_NUMBER_OBJECT_NUMBER = f"{C_NUMBER}_{FTR_OBJECT_NUMBER}"
16
+
17
+ C_COUNT = "Count"
18
+
19
+ class TemplateMeasurementFormat(str):
20
+ FF_COUNT = f"{C_COUNT}_%s"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cellprofiler-library-nightly
3
- Version: 5.0.0.dev634
3
+ Version: 5.0.0.dev642
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>
@@ -32,6 +32,7 @@ cellprofiler_library/modules/_fillobjects.py
32
32
  cellprofiler_library/modules/_flipandrotate.py
33
33
  cellprofiler_library/modules/_gaussianfilter.py
34
34
  cellprofiler_library/modules/_graytocolor.py
35
+ cellprofiler_library/modules/_identifydeadworms.py
35
36
  cellprofiler_library/modules/_identifyprimaryobjects.py
36
37
  cellprofiler_library/modules/_identifysecondaryobjects.py
37
38
  cellprofiler_library/modules/_identifytertiaryobjects.py
@@ -79,6 +80,7 @@ cellprofiler_library/opts/erodeimage.py
79
80
  cellprofiler_library/opts/erodeobjects.py
80
81
  cellprofiler_library/opts/flipandrotate.py
81
82
  cellprofiler_library/opts/graytocolor.py
83
+ cellprofiler_library/opts/identifydeadworms.py
82
84
  cellprofiler_library/opts/identifyprimaryobjects.py
83
85
  cellprofiler_library/opts/identifysecondaryobjects.py
84
86
  cellprofiler_library/opts/identifytertiaryobjects.py