cellprofiler-library-nightly 5.0.0.dev592__tar.gz → 5.0.0.dev610__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.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/PKG-INFO +1 -1
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/_version.py +3 -3
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/functions/measurement.py +261 -0
- cellprofiler_library_nightly-5.0.0.dev610/cellprofiler_library/modules/_measureimagequality.py +302 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_threshold.py +2 -0
- cellprofiler_library_nightly-5.0.0.dev610/cellprofiler_library/opts/measureimagequality.py +89 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library_nightly.egg-info/PKG-INFO +1 -1
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library_nightly.egg-info/SOURCES.txt +2 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/LICENSE +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/README.md +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/__init__.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/functions/__init__.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/functions/file_processing.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/functions/image_processing.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/functions/object_processing.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/functions/segmentation.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/measurement_model.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/__init__.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_closing.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_colortogray.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_combineobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_convertimagetoobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_convertobjectstoimage.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_correctilluminationapply.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_crop.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_dilateimage.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_dilateobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_enhanceedges.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_enhanceorsuppressfeatures.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_erodeimage.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_erodeobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_expandorshrinkobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_fillobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_flipandrotate.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_gaussianfilter.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_graytocolor.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_identifyprimaryobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_identifysecondaryobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_identifytertiaryobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_imagemath.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_measurecolocalization.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_measuregranularity.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_measureimageareaoccupied.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_measureimageintensity.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_measureimageoverlap.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_measureimageskeleton.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_measureobjectintensity.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_measureobjectneighbors.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_measureobjectoverlap.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_measureobjectsizeshape.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_measureobjectskeleton.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_medialaxis.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_medianfilter.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_morph.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_morphologicalskeleton.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_opening.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_overlayobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_overlayoutlines.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_reducenoise.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_removeholes.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_resize.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_savecroppedobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_shrinktoobjectcenters.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_smooth.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/modules/_watershed.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/__init__.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/colortogray.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/convertimagetoobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/convertobjectstoimage.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/correctilluminationapply.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/crop.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/dilateimage.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/dilateobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/enhanceedges.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/enhanceorsuppressfeatures.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/erodeimage.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/erodeobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/flipandrotate.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/graytocolor.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/identifyprimaryobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/identifysecondaryobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/identifytertiaryobjects.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/imagemath.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/measurecolocalization.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/measuregranularity.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/measureimageareaoccupied.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/measureimageintensity.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/measureimageoverlap.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/measureimageskeleton.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/measureobjectintensity.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/measureobjectneighbors.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/measureobjectoverlap.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/measureobjectskeleton.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/morph.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/objectsizeshapefeatures.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/overlayoutlines.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/removeholes.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/resize.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/shrinktoobjectcenters.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/smooth.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/structuring_elements.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/opts/threshold.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/py.typed +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library/types.py +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library_nightly.egg-info/dependency_links.txt +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library_nightly.egg-info/requires.txt +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/cellprofiler_library_nightly.egg-info/top_level.txt +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/environment.yml +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/pyproject.toml +0 -0
- {cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/setup.cfg +0 -0
{cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/PKG-INFO
RENAMED
|
@@ -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.dev610
|
|
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.dev610'
|
|
32
|
+
__version_tuple__ = version_tuple = (5, 0, 0, 'dev610')
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'g53b2372ff'
|
|
@@ -10,6 +10,9 @@ import centrosome.propagate
|
|
|
10
10
|
import centrosome.fastemd
|
|
11
11
|
import centrosome.index
|
|
12
12
|
import centrosome.cpmorphology
|
|
13
|
+
import centrosome.threshold
|
|
14
|
+
import centrosome.haralick
|
|
15
|
+
import centrosome.radial_power_spectrum
|
|
13
16
|
from centrosome.outline import outline
|
|
14
17
|
from functools import reduce
|
|
15
18
|
from sklearn.cluster import KMeans
|
|
@@ -2173,6 +2176,264 @@ def compute_earth_movers_distance_objects(
|
|
|
2173
2176
|
return emd
|
|
2174
2177
|
|
|
2175
2178
|
|
|
2179
|
+
###############################################################################
|
|
2180
|
+
# MeasureImageQuality
|
|
2181
|
+
###############################################################################
|
|
2182
|
+
|
|
2183
|
+
def get_focus_score_for_scale_group(
|
|
2184
|
+
scale_groups: Sequence[int],
|
|
2185
|
+
pixel_data: ImageGrayscale,
|
|
2186
|
+
dimensions: int,
|
|
2187
|
+
image_mask: Optional[ImageGrayscaleMask]=None,
|
|
2188
|
+
) -> Tuple[
|
|
2189
|
+
NDArray[numpy.float_],
|
|
2190
|
+
int,
|
|
2191
|
+
Sequence[numpy.float_]
|
|
2192
|
+
]:
|
|
2193
|
+
if image_mask is not None:
|
|
2194
|
+
masked_pixel_data = pixel_data[image_mask]
|
|
2195
|
+
else:
|
|
2196
|
+
masked_pixel_data = pixel_data
|
|
2197
|
+
shape = pixel_data.shape
|
|
2198
|
+
local_focus_score = []
|
|
2199
|
+
focus_score = 0
|
|
2200
|
+
for scale in scale_groups:
|
|
2201
|
+
focus_score = 0
|
|
2202
|
+
if len(masked_pixel_data):
|
|
2203
|
+
mean_image_value = numpy.mean(masked_pixel_data)
|
|
2204
|
+
squared_normalized_image = (masked_pixel_data - mean_image_value) ** 2
|
|
2205
|
+
if mean_image_value > 0:
|
|
2206
|
+
focus_score = numpy.sum(squared_normalized_image) / (
|
|
2207
|
+
numpy.product(masked_pixel_data.shape) * mean_image_value
|
|
2208
|
+
)
|
|
2209
|
+
#
|
|
2210
|
+
# Create a labels matrix that grids the image to the dimensions
|
|
2211
|
+
# of the window size
|
|
2212
|
+
#
|
|
2213
|
+
if dimensions == 2:
|
|
2214
|
+
i, j = numpy.mgrid[0 : shape[0], 0 : shape[1]].astype(float)
|
|
2215
|
+
m, n = (numpy.array(shape) + scale - 1) // scale
|
|
2216
|
+
i = (i * float(m) / float(shape[0])).astype(int)
|
|
2217
|
+
j = (j * float(n) / float(shape[1])).astype(int)
|
|
2218
|
+
grid = i * n + j + 1
|
|
2219
|
+
grid_range = numpy.arange(0, m * n + 1, dtype=numpy.int32)
|
|
2220
|
+
elif dimensions == 3:
|
|
2221
|
+
k, i, j = numpy.mgrid[
|
|
2222
|
+
0 : shape[0], 0 : shape[1], 0 : shape[2]
|
|
2223
|
+
].astype(float)
|
|
2224
|
+
o, m, n = (numpy.array(shape) + scale - 1) // scale
|
|
2225
|
+
k = (k * float(o) / float(shape[0])).astype(int)
|
|
2226
|
+
i = (i * float(m) / float(shape[1])).astype(int)
|
|
2227
|
+
j = (j * float(n) / float(shape[2])).astype(int)
|
|
2228
|
+
grid = k * o + i * n + j + 1 # hmm
|
|
2229
|
+
grid_range = numpy.arange(0, m * n * o + 1, dtype=numpy.int32)
|
|
2230
|
+
else:
|
|
2231
|
+
raise ValueError("Image dimensions must be 2 or 3")
|
|
2232
|
+
if image_mask is not None:
|
|
2233
|
+
grid[numpy.logical_not(image_mask)] = 0
|
|
2234
|
+
|
|
2235
|
+
#
|
|
2236
|
+
# Do the math per label
|
|
2237
|
+
#
|
|
2238
|
+
local_means = centrosome.cpmorphology.fixup_scipy_ndimage_result(
|
|
2239
|
+
scipy.ndimage.mean(pixel_data, grid, grid_range)
|
|
2240
|
+
)
|
|
2241
|
+
local_squared_normalized_image = (
|
|
2242
|
+
pixel_data - local_means[grid]
|
|
2243
|
+
) ** 2
|
|
2244
|
+
#
|
|
2245
|
+
# Compute the sum of local_squared_normalized_image values for each
|
|
2246
|
+
# grid for means > 0. Exclude grid label = 0 because that's masked
|
|
2247
|
+
#
|
|
2248
|
+
grid_mask = (local_means != 0) & ~numpy.isnan(local_means)
|
|
2249
|
+
nz_grid_range = grid_range[grid_mask]
|
|
2250
|
+
if len(nz_grid_range) and nz_grid_range[0] == 0:
|
|
2251
|
+
nz_grid_range = nz_grid_range[1:]
|
|
2252
|
+
local_means = local_means[1:]
|
|
2253
|
+
grid_mask = grid_mask[1:]
|
|
2254
|
+
local_focus_score += [
|
|
2255
|
+
0
|
|
2256
|
+
] # assume the worst - that we can't calculate it
|
|
2257
|
+
if len(nz_grid_range):
|
|
2258
|
+
sums = centrosome.cpmorphology.fixup_scipy_ndimage_result(
|
|
2259
|
+
scipy.ndimage.sum(
|
|
2260
|
+
local_squared_normalized_image, grid, nz_grid_range
|
|
2261
|
+
)
|
|
2262
|
+
)
|
|
2263
|
+
pixel_counts = centrosome.cpmorphology.fixup_scipy_ndimage_result(
|
|
2264
|
+
scipy.ndimage.sum(numpy.ones(shape), grid, nz_grid_range)
|
|
2265
|
+
)
|
|
2266
|
+
local_norm_var = sums / (pixel_counts * local_means[grid_mask])
|
|
2267
|
+
local_norm_median = numpy.median(local_norm_var)
|
|
2268
|
+
if numpy.isfinite(local_norm_median) and local_norm_median > 0:
|
|
2269
|
+
local_focus_score[-1] = (
|
|
2270
|
+
numpy.var(local_norm_var) / local_norm_median
|
|
2271
|
+
)
|
|
2272
|
+
return focus_score, scale, local_focus_score
|
|
2273
|
+
|
|
2274
|
+
def get_correlation_for_scale_group(
|
|
2275
|
+
pixel_data: ImageGrayscale,
|
|
2276
|
+
scale_groups: Sequence[int],
|
|
2277
|
+
image_mask: Optional[ImageGrayscaleMask]=None
|
|
2278
|
+
) -> Dict[int, numpy.float_]:
|
|
2279
|
+
# Compute Haralick's correlation texture for the given scales
|
|
2280
|
+
image_labels = numpy.ones(pixel_data.shape, int)
|
|
2281
|
+
if image_mask is not None:
|
|
2282
|
+
image_labels[~image_mask] = 0
|
|
2283
|
+
scale_measurements = {}
|
|
2284
|
+
for scale in scale_groups:
|
|
2285
|
+
scale_measurements[scale] = get_correlation_for_scale(pixel_data, image_labels, scale)
|
|
2286
|
+
return scale_measurements
|
|
2287
|
+
|
|
2288
|
+
def get_correlation_for_scale(
|
|
2289
|
+
pixel_data: ImageGrayscale,
|
|
2290
|
+
image_labels: NDArray[numpy.int_],
|
|
2291
|
+
scale: int
|
|
2292
|
+
) -> float:
|
|
2293
|
+
# Compute Haralick's correlation texture for the given scale
|
|
2294
|
+
value = centrosome.haralick.Haralick(pixel_data, image_labels, 0, scale).H3()
|
|
2295
|
+
|
|
2296
|
+
if len(value) != 1 or not numpy.isfinite(value[0]):
|
|
2297
|
+
value = 0.0
|
|
2298
|
+
else:
|
|
2299
|
+
value = float(value)
|
|
2300
|
+
return value
|
|
2301
|
+
|
|
2302
|
+
|
|
2303
|
+
def get_saturation_value(
|
|
2304
|
+
pixel_data: ImageGrayscale,
|
|
2305
|
+
image_mask: Optional[ImageGrayscaleMask]=None
|
|
2306
|
+
) -> Tuple[
|
|
2307
|
+
float,
|
|
2308
|
+
float
|
|
2309
|
+
]:
|
|
2310
|
+
if image_mask is not None:
|
|
2311
|
+
pixel_data = pixel_data[image_mask]
|
|
2312
|
+
pixel_count = numpy.product(pixel_data.shape)
|
|
2313
|
+
if pixel_count == 0:
|
|
2314
|
+
percent_maximal = 0
|
|
2315
|
+
percent_minimal = 0
|
|
2316
|
+
else:
|
|
2317
|
+
number_pixels_maximal = numpy.sum(pixel_data == numpy.max(pixel_data))
|
|
2318
|
+
number_pixels_minimal = numpy.sum(pixel_data == numpy.min(pixel_data))
|
|
2319
|
+
percent_maximal = (
|
|
2320
|
+
100.0 * float(number_pixels_maximal) / float(pixel_count)
|
|
2321
|
+
)
|
|
2322
|
+
percent_minimal = (
|
|
2323
|
+
100.0 * float(number_pixels_minimal) / float(pixel_count)
|
|
2324
|
+
)
|
|
2325
|
+
return percent_minimal, percent_maximal
|
|
2326
|
+
|
|
2327
|
+
|
|
2328
|
+
def get_intensity_measurement_values(
|
|
2329
|
+
pixels: ImageGrayscale,
|
|
2330
|
+
image_mask: Optional[ImageGrayscaleMask]=None
|
|
2331
|
+
) -> Tuple[
|
|
2332
|
+
numpy.int_,
|
|
2333
|
+
numpy.float_,
|
|
2334
|
+
numpy.float_,
|
|
2335
|
+
numpy.float_,
|
|
2336
|
+
numpy.float_,
|
|
2337
|
+
numpy.float_,
|
|
2338
|
+
numpy.float_,
|
|
2339
|
+
numpy.float_
|
|
2340
|
+
]:
|
|
2341
|
+
if image_mask is not None:
|
|
2342
|
+
pixels = pixels[image_mask]
|
|
2343
|
+
|
|
2344
|
+
pixel_count = numpy.product(pixels.shape)
|
|
2345
|
+
if pixel_count == 0:
|
|
2346
|
+
pixel_sum = 0
|
|
2347
|
+
pixel_mean = 0
|
|
2348
|
+
pixel_std = 0
|
|
2349
|
+
pixel_mad = 0
|
|
2350
|
+
pixel_median = 0
|
|
2351
|
+
pixel_min = 0
|
|
2352
|
+
pixel_max = 0
|
|
2353
|
+
else:
|
|
2354
|
+
pixel_sum = numpy.sum(pixels)
|
|
2355
|
+
pixel_mean = pixel_sum / float(pixel_count)
|
|
2356
|
+
pixel_std = numpy.std(pixels)
|
|
2357
|
+
pixel_median = numpy.median(pixels)
|
|
2358
|
+
pixel_mad = numpy.median(numpy.abs(pixels - pixel_median))
|
|
2359
|
+
pixel_min = numpy.min(pixels)
|
|
2360
|
+
pixel_max = numpy.max(pixels)
|
|
2361
|
+
return pixel_count, pixel_sum, pixel_mean, pixel_std, pixel_mad, pixel_median, pixel_min, pixel_max
|
|
2362
|
+
|
|
2363
|
+
|
|
2364
|
+
def get_power_spectrum_measurement_values(
|
|
2365
|
+
pixel_data: ImageGrayscale,
|
|
2366
|
+
image_mask: Optional[ImageGrayscaleMask]=None,
|
|
2367
|
+
dimensions: int = 2
|
|
2368
|
+
) -> float:
|
|
2369
|
+
if dimensions == 3:
|
|
2370
|
+
# TODO: cannot calculate "radial power spectrum" for volumes: Not implemented.
|
|
2371
|
+
pass
|
|
2372
|
+
|
|
2373
|
+
if image_mask is not None:
|
|
2374
|
+
pixel_data = numpy.array(pixel_data) # make a copy
|
|
2375
|
+
masked_pixels = pixel_data[image_mask]
|
|
2376
|
+
pixel_count = numpy.product(masked_pixels.shape)
|
|
2377
|
+
if pixel_count > 0:
|
|
2378
|
+
pixel_data[~image_mask] = numpy.mean(masked_pixels)
|
|
2379
|
+
else:
|
|
2380
|
+
pixel_data[~image_mask] = 0
|
|
2381
|
+
|
|
2382
|
+
radii, magnitude, power = centrosome.radial_power_spectrum.rps(pixel_data)
|
|
2383
|
+
if sum(magnitude) > 0 and len(numpy.unique(pixel_data)) > 1:
|
|
2384
|
+
valid = magnitude > 0
|
|
2385
|
+
radii = radii[valid].reshape((-1, 1))
|
|
2386
|
+
power = power[valid].reshape((-1, 1))
|
|
2387
|
+
if radii.shape[0] > 1:
|
|
2388
|
+
idx = numpy.isfinite(numpy.log(power))
|
|
2389
|
+
powerslope = scipy.linalg.basic.lstsq(
|
|
2390
|
+
numpy.hstack(
|
|
2391
|
+
(
|
|
2392
|
+
numpy.log(radii)[idx][:, numpy.newaxis],
|
|
2393
|
+
numpy.ones(radii.shape)[idx][:, numpy.newaxis],
|
|
2394
|
+
)
|
|
2395
|
+
),
|
|
2396
|
+
numpy.log(power)[idx][:, numpy.newaxis],
|
|
2397
|
+
)[0][0]
|
|
2398
|
+
else:
|
|
2399
|
+
powerslope = 0.
|
|
2400
|
+
else:
|
|
2401
|
+
powerslope = 0.
|
|
2402
|
+
return powerslope
|
|
2403
|
+
|
|
2404
|
+
|
|
2405
|
+
def calculate_threshold_for_threshold_group(
|
|
2406
|
+
image_pixel_data: ImageGrayscale = numpy.ones((100, 100)),
|
|
2407
|
+
mask: Optional[ImageGrayscaleMask] = None,
|
|
2408
|
+
algorithm: str = centrosome.threshold.TM_OTSU,
|
|
2409
|
+
object_fraction: float = 0.1,
|
|
2410
|
+
two_class_otsu: bool = True,
|
|
2411
|
+
use_weighted_variance: bool = True,
|
|
2412
|
+
assign_middle_to_foreground: bool = True,
|
|
2413
|
+
) -> float:
|
|
2414
|
+
if mask is not None:
|
|
2415
|
+
_, global_threshold = centrosome.threshold.get_threshold(
|
|
2416
|
+
algorithm,
|
|
2417
|
+
centrosome.threshold.TM_GLOBAL,
|
|
2418
|
+
image_pixel_data,
|
|
2419
|
+
mask = mask,
|
|
2420
|
+
object_fraction=object_fraction,
|
|
2421
|
+
two_class_otsu=two_class_otsu,
|
|
2422
|
+
use_weighted_variance=use_weighted_variance,
|
|
2423
|
+
assign_middle_to_foreground=assign_middle_to_foreground,
|
|
2424
|
+
)
|
|
2425
|
+
else:
|
|
2426
|
+
_, global_threshold = centrosome.threshold.get_threshold(
|
|
2427
|
+
algorithm,
|
|
2428
|
+
centrosome.threshold.TM_GLOBAL,
|
|
2429
|
+
image_pixel_data,
|
|
2430
|
+
object_fraction=object_fraction,
|
|
2431
|
+
two_class_otsu=two_class_otsu,
|
|
2432
|
+
use_weighted_variance=use_weighted_variance,
|
|
2433
|
+
assign_middle_to_foreground=assign_middle_to_foreground,
|
|
2434
|
+
)
|
|
2435
|
+
return global_threshold
|
|
2436
|
+
|
|
2176
2437
|
###############################################################################
|
|
2177
2438
|
# Measure Image Skeleton
|
|
2178
2439
|
###############################################################################
|
cellprofiler_library_nightly-5.0.0.dev610/cellprofiler_library/modules/_measureimagequality.py
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import numpy
|
|
2
|
+
from numpy.typing import NDArray
|
|
3
|
+
from typing import Optional, List, Sequence, Annotated, Union, Tuple, Any
|
|
4
|
+
from pydantic import BaseModel, Field, validate_call, ConfigDict
|
|
5
|
+
from cellprofiler_library.types import ImageGrayscale, ImageGrayscaleMask
|
|
6
|
+
from cellprofiler_library.measurement_model import LibraryMeasurements
|
|
7
|
+
from cellprofiler_library.opts.measureimagequality import (
|
|
8
|
+
Feature, ScaledThresholdMethod, TemplateMeasurementFormat
|
|
9
|
+
)
|
|
10
|
+
from cellprofiler_library.functions.measurement import (
|
|
11
|
+
get_focus_score_for_scale_group,
|
|
12
|
+
get_correlation_for_scale_group,
|
|
13
|
+
get_saturation_value,
|
|
14
|
+
get_intensity_measurement_values,
|
|
15
|
+
get_power_spectrum_measurement_values,
|
|
16
|
+
calculate_threshold_for_threshold_group
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
ImageQualityMesVal = Union[
|
|
20
|
+
# image scaling, blur powerslope, saturation percent_minimal|percent_maximal, threshold global_threshold
|
|
21
|
+
float,
|
|
22
|
+
# blur focus_score
|
|
23
|
+
NDArray[numpy.float_],
|
|
24
|
+
# intensity pixel_count
|
|
25
|
+
numpy.int_,
|
|
26
|
+
# blur local_focus_score
|
|
27
|
+
# intensity
|
|
28
|
+
# pixel_sum|pixel_mean|pixel_std|pixel_mad|pixel_median|pixel_min|pixel_max
|
|
29
|
+
numpy.float_,
|
|
30
|
+
# converted stat vals
|
|
31
|
+
str
|
|
32
|
+
]
|
|
33
|
+
ImageQualityStatistics = List[Tuple[str, ImageQualityMesVal]]
|
|
34
|
+
|
|
35
|
+
class ImageQualityDisplayData(BaseModel):
|
|
36
|
+
model_config = ConfigDict(
|
|
37
|
+
arbitrary_types_allowed=True,
|
|
38
|
+
populate_by_name=True
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
statistics: ImageQualityStatistics
|
|
42
|
+
|
|
43
|
+
class ThresholdConfig(BaseModel):
|
|
44
|
+
algorithm: str
|
|
45
|
+
object_fraction: float = 0.1
|
|
46
|
+
two_class_otsu: bool = True
|
|
47
|
+
use_weighted_variance: bool = True
|
|
48
|
+
assign_middle_to_foreground: bool = True
|
|
49
|
+
|
|
50
|
+
def get_scale_string(self) -> Optional[str]:
|
|
51
|
+
if self.algorithm == ScaledThresholdMethod.OTSU.value:
|
|
52
|
+
scale = "2" if self.two_class_otsu else "3"
|
|
53
|
+
if not self.two_class_otsu:
|
|
54
|
+
scale += "F" if self.assign_middle_to_foreground else "B"
|
|
55
|
+
scale += "W" if self.use_weighted_variance else "S"
|
|
56
|
+
return scale
|
|
57
|
+
elif self.algorithm == ScaledThresholdMethod.MOG.value:
|
|
58
|
+
return str(int(self.object_fraction * 100))
|
|
59
|
+
return None
|
|
60
|
+
|
|
61
|
+
@validate_call(config=ConfigDict(arbitrary_types_allowed=True))
|
|
62
|
+
def measure_image_quality(
|
|
63
|
+
image: Annotated[ImageGrayscale, Field(description="The image to measure.")],
|
|
64
|
+
image_name: Annotated[str, Field(description="The name of the image.")],
|
|
65
|
+
image_mask: Annotated[Optional[ImageGrayscaleMask], Field(description="The mask for the image.")] = None,
|
|
66
|
+
volumetric: Annotated[bool, Field(description="Whether the image is volumetric (3D).")] = False,
|
|
67
|
+
include_image_scalings: Annotated[bool, Field(description="Whether to include image scalings in the measurements.")] = False,
|
|
68
|
+
image_scale_value: Annotated[float, Field(description="The scaling value of the image.")] = numpy.nan,
|
|
69
|
+
check_blur: Annotated[bool, Field(description="Whether to calculate blur metrics.")] = False,
|
|
70
|
+
blur_scales: Annotated[Optional[Sequence[int]], Field(description="List of scales (window sizes) for blur metrics.")] = None,
|
|
71
|
+
check_saturation: Annotated[bool, Field(description="Whether to calculate saturation metrics.")] = False,
|
|
72
|
+
check_intensity: Annotated[bool, Field(description="Whether to calculate intensity metrics.")] = False,
|
|
73
|
+
calculate_threshold: Annotated[bool, Field(description="Whether to calculate threshold metrics.")] = False,
|
|
74
|
+
threshold_groups: Annotated[Optional[List[ThresholdConfig]], Field(description="List of threshold configurations.")] = None,
|
|
75
|
+
return_visualization_data: Annotated[bool, Field(description="Return data for display")] = False,
|
|
76
|
+
) -> Union[LibraryMeasurements, Tuple[LibraryMeasurements, ImageQualityDisplayData]]:
|
|
77
|
+
"""
|
|
78
|
+
Measure image quality metrics.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
image: Input image.
|
|
82
|
+
image_name: Name of the image.
|
|
83
|
+
image_mask: Optional mask for the image.
|
|
84
|
+
volumetric: Whether the image is volumetric (3D).
|
|
85
|
+
include_image_scalings: Whether to record image scaling.
|
|
86
|
+
image_scale_value: The scaling value of the image.
|
|
87
|
+
check_blur: Whether to calculate blur metrics.
|
|
88
|
+
blur_scales: List of scales (window sizes) for blur metrics.
|
|
89
|
+
check_saturation: Whether to calculate saturation metrics.
|
|
90
|
+
check_intensity: Whether to calculate intensity metrics.
|
|
91
|
+
calculate_threshold: Whether to calculate threshold metrics.
|
|
92
|
+
threshold_groups: List of threshold configurations.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
LibraryMeasurements object containing the measurements.
|
|
96
|
+
"""
|
|
97
|
+
measurements = LibraryMeasurements()
|
|
98
|
+
statistics: ImageQualityStatistics = []
|
|
99
|
+
|
|
100
|
+
dimensions = image.ndim
|
|
101
|
+
|
|
102
|
+
feat_stat_name_map = {
|
|
103
|
+
TemplateMeasurementFormat.IQ_SCALING: f"{image_name} scaling",
|
|
104
|
+
TemplateMeasurementFormat.IQ_POWER_SPECTRUM_SLOPE: f"{image_name} {Feature.POWER_SPECTRUM_SLOPE.value}",
|
|
105
|
+
TemplateMeasurementFormat.IQ_PERCENT_MAXIMAL: f"{image_name} maximal",
|
|
106
|
+
TemplateMeasurementFormat.IQ_PERCENT_MINIMAL: f"{image_name} minimal",
|
|
107
|
+
TemplateMeasurementFormat.IQ_TOTAL_AREA: f"{image_name} Total Area",
|
|
108
|
+
TemplateMeasurementFormat.IQ_TOTAL_VOLUME: f"{image_name} Total Volume",
|
|
109
|
+
TemplateMeasurementFormat.IQ_TOTAL_INTENSITY: f"{image_name} Total intensity",
|
|
110
|
+
TemplateMeasurementFormat.IQ_MEAN_INTENSITY: f"{image_name} Mean intensity",
|
|
111
|
+
TemplateMeasurementFormat.IQ_MEDIAN_INTENSITY: f"{image_name} Median intensity",
|
|
112
|
+
TemplateMeasurementFormat.IQ_STD_INTENSITY: f"{image_name} Std intensity",
|
|
113
|
+
TemplateMeasurementFormat.IQ_MAD_INTENSITY: f"{image_name} MAD intensity",
|
|
114
|
+
TemplateMeasurementFormat.IQ_MIN_INTENSITY: f"{image_name} Min intensity",
|
|
115
|
+
TemplateMeasurementFormat.IQ_MAX_INTENSITY: f"{image_name} Max intensity",
|
|
116
|
+
# template stat names
|
|
117
|
+
TemplateMeasurementFormat.IQ_FOCUS_SCORE: f"{image_name} focus score @%d",
|
|
118
|
+
TemplateMeasurementFormat.IQ_LOCAL_FOCUS_SCORE: f"{image_name} local focus score @%d",
|
|
119
|
+
TemplateMeasurementFormat.IQ_CORR: f"{image_name} {Feature.CORRELATION.value} @%d",
|
|
120
|
+
TemplateMeasurementFormat.IQ_THRESHOLD: f"{image_name} %s",
|
|
121
|
+
}
|
|
122
|
+
def add_measurement(
|
|
123
|
+
feature_template: str,
|
|
124
|
+
template_val: str,
|
|
125
|
+
feat_val: ImageQualityMesVal,
|
|
126
|
+
stat_template_val: Optional[Any]=None,
|
|
127
|
+
feat_val_template: Optional[str]=None
|
|
128
|
+
):
|
|
129
|
+
feature = feature_template % template_val
|
|
130
|
+
measurements.add_image_measurement(feature, feat_val)
|
|
131
|
+
if return_visualization_data:
|
|
132
|
+
stat_name = feat_stat_name_map.get(feature_template, None)
|
|
133
|
+
if stat_name is None:
|
|
134
|
+
return # TODO: 5114 - handle this
|
|
135
|
+
if stat_template_val is not None:
|
|
136
|
+
stat_name = stat_name % stat_template_val
|
|
137
|
+
if feat_val_template is not None:
|
|
138
|
+
feat_val = feat_val_template % feat_val
|
|
139
|
+
statistics.append((stat_name, feat_val))
|
|
140
|
+
|
|
141
|
+
# Image Scalings
|
|
142
|
+
if include_image_scalings:
|
|
143
|
+
add_measurement(TemplateMeasurementFormat.IQ_SCALING, image_name, image_scale_value)
|
|
144
|
+
|
|
145
|
+
# Blur Measurements
|
|
146
|
+
if check_blur and blur_scales is not None:
|
|
147
|
+
# Focus Score
|
|
148
|
+
focus_score, scale, local_focus_score = get_focus_score_for_scale_group(
|
|
149
|
+
blur_scales,
|
|
150
|
+
image,
|
|
151
|
+
dimensions,
|
|
152
|
+
image_mask,
|
|
153
|
+
)
|
|
154
|
+
# Correlation
|
|
155
|
+
scale_measurements = get_correlation_for_scale_group(image, blur_scales, image_mask)
|
|
156
|
+
|
|
157
|
+
# Focus Score
|
|
158
|
+
add_measurement(
|
|
159
|
+
TemplateMeasurementFormat.IQ_FOCUS_SCORE,
|
|
160
|
+
image_name,
|
|
161
|
+
focus_score,
|
|
162
|
+
stat_template_val=blur_scales[-1]
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
for idx, scale in enumerate(blur_scales):
|
|
166
|
+
# Focus Score
|
|
167
|
+
add_measurement(
|
|
168
|
+
TemplateMeasurementFormat.IQ_LOCAL_FOCUS_SCORE,
|
|
169
|
+
f"{image_name}_{scale}",
|
|
170
|
+
local_focus_score[idx],
|
|
171
|
+
stat_template_val=scale,
|
|
172
|
+
)
|
|
173
|
+
# Correlation
|
|
174
|
+
add_measurement(
|
|
175
|
+
TemplateMeasurementFormat.IQ_CORR,
|
|
176
|
+
f"{image_name}_{scale}",
|
|
177
|
+
scale_measurements[scale],
|
|
178
|
+
stat_template_val=scale,
|
|
179
|
+
feat_val_template="%.2f",
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# Power Spectrum
|
|
183
|
+
if dimensions == 2:
|
|
184
|
+
powerslope = get_power_spectrum_measurement_values(image, image_mask, dimensions)
|
|
185
|
+
add_measurement(
|
|
186
|
+
TemplateMeasurementFormat.IQ_POWER_SPECTRUM_SLOPE,
|
|
187
|
+
image_name,
|
|
188
|
+
powerslope,
|
|
189
|
+
feat_val_template="%.1f",
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
# Saturation Measurements
|
|
193
|
+
if check_saturation:
|
|
194
|
+
percent_minimal, percent_maximal = get_saturation_value(image, image_mask)
|
|
195
|
+
|
|
196
|
+
add_measurement(
|
|
197
|
+
TemplateMeasurementFormat.IQ_PERCENT_MAXIMAL,
|
|
198
|
+
image_name,
|
|
199
|
+
percent_maximal,
|
|
200
|
+
feat_val_template="%.1f",
|
|
201
|
+
)
|
|
202
|
+
add_measurement(
|
|
203
|
+
TemplateMeasurementFormat.IQ_PERCENT_MINIMAL,
|
|
204
|
+
image_name,
|
|
205
|
+
percent_minimal,
|
|
206
|
+
feat_val_template="%.1f",
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
# Intensity Measurements
|
|
210
|
+
if check_intensity:
|
|
211
|
+
(
|
|
212
|
+
pixel_count,
|
|
213
|
+
pixel_sum,
|
|
214
|
+
pixel_mean,
|
|
215
|
+
pixel_std,
|
|
216
|
+
pixel_mad,
|
|
217
|
+
pixel_median,
|
|
218
|
+
pixel_min,
|
|
219
|
+
pixel_max,
|
|
220
|
+
) = get_intensity_measurement_values(image, image_mask)
|
|
221
|
+
|
|
222
|
+
add_measurement(
|
|
223
|
+
TemplateMeasurementFormat.IQ_TOTAL_VOLUME if volumetric else TemplateMeasurementFormat.IQ_TOTAL_AREA,
|
|
224
|
+
image_name,
|
|
225
|
+
pixel_count,
|
|
226
|
+
feat_val_template="%.2f",
|
|
227
|
+
)
|
|
228
|
+
add_measurement(
|
|
229
|
+
TemplateMeasurementFormat.IQ_TOTAL_INTENSITY,
|
|
230
|
+
image_name,
|
|
231
|
+
pixel_sum,
|
|
232
|
+
feat_val_template="%.2f",
|
|
233
|
+
)
|
|
234
|
+
add_measurement(
|
|
235
|
+
TemplateMeasurementFormat.IQ_MEAN_INTENSITY,
|
|
236
|
+
image_name,
|
|
237
|
+
pixel_mean,
|
|
238
|
+
feat_val_template="%.2f",
|
|
239
|
+
)
|
|
240
|
+
add_measurement(
|
|
241
|
+
TemplateMeasurementFormat.IQ_MEDIAN_INTENSITY,
|
|
242
|
+
image_name,
|
|
243
|
+
pixel_median,
|
|
244
|
+
feat_val_template="%.2f",
|
|
245
|
+
)
|
|
246
|
+
add_measurement(
|
|
247
|
+
TemplateMeasurementFormat.IQ_STD_INTENSITY,
|
|
248
|
+
image_name,
|
|
249
|
+
pixel_std,
|
|
250
|
+
feat_val_template="%.2f",
|
|
251
|
+
)
|
|
252
|
+
add_measurement(
|
|
253
|
+
TemplateMeasurementFormat.IQ_MAD_INTENSITY,
|
|
254
|
+
image_name,
|
|
255
|
+
pixel_mad,
|
|
256
|
+
feat_val_template="%.2f",
|
|
257
|
+
)
|
|
258
|
+
add_measurement(
|
|
259
|
+
TemplateMeasurementFormat.IQ_MAX_INTENSITY,
|
|
260
|
+
image_name,
|
|
261
|
+
pixel_max,
|
|
262
|
+
feat_val_template="%.2f",
|
|
263
|
+
)
|
|
264
|
+
add_measurement(
|
|
265
|
+
TemplateMeasurementFormat.IQ_MIN_INTENSITY,
|
|
266
|
+
image_name,
|
|
267
|
+
pixel_min,
|
|
268
|
+
feat_val_template="%.2f",
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
# Threshold Measurements
|
|
272
|
+
if calculate_threshold and threshold_groups is not None:
|
|
273
|
+
# We need to cast pixel data to float32 for threshold calculations as in original code
|
|
274
|
+
# "pixel_data = image.pixel_data.astype(numpy.float32)"
|
|
275
|
+
pixel_data_float = image.astype(numpy.float32)
|
|
276
|
+
|
|
277
|
+
for config in threshold_groups:
|
|
278
|
+
global_threshold = calculate_threshold_for_threshold_group(
|
|
279
|
+
image_pixel_data=pixel_data_float,
|
|
280
|
+
mask=image_mask,
|
|
281
|
+
algorithm=config.algorithm,
|
|
282
|
+
object_fraction=config.object_fraction,
|
|
283
|
+
two_class_otsu=config.two_class_otsu,
|
|
284
|
+
use_weighted_variance=config.use_weighted_variance,
|
|
285
|
+
assign_middle_to_foreground=config.assign_middle_to_foreground,
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
scale = config.get_scale_string()
|
|
289
|
+
algo = config.algorithm
|
|
290
|
+
|
|
291
|
+
add_measurement(
|
|
292
|
+
TemplateMeasurementFormat.IQ_THRESHOLD,
|
|
293
|
+
f"{algo}_{image_name}_{scale}" if scale else f"{algo}_{image_name}",
|
|
294
|
+
global_threshold,
|
|
295
|
+
stat_template_val=f"{algo}" + (f" {scale}" if scale else "")
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
if return_visualization_data:
|
|
299
|
+
return measurements, ImageQualityDisplayData(
|
|
300
|
+
statistics=statistics,
|
|
301
|
+
)
|
|
302
|
+
return measurements
|
|
@@ -15,6 +15,8 @@ from ..opts.threshold import (
|
|
|
15
15
|
)
|
|
16
16
|
from ..types import ImageGrayscale, ImageGrayscaleMask
|
|
17
17
|
|
|
18
|
+
# TODO: library cleanup - needs standardizing
|
|
19
|
+
# frontend still uses centrosome
|
|
18
20
|
@validate_call(config=ConfigDict(arbitrary_types_allowed=True))
|
|
19
21
|
def threshold(
|
|
20
22
|
image: Annotated[ImageGrayscale, Field(description="Image to threshold")],
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from centrosome.threshold import (
|
|
3
|
+
TM_OTSU,
|
|
4
|
+
TM_MOG,
|
|
5
|
+
TM_METHODS,
|
|
6
|
+
)
|
|
7
|
+
from .threshold import OtsuMethod as ThreshOtsuMethod
|
|
8
|
+
|
|
9
|
+
"""Root module measurement name"""
|
|
10
|
+
C_IMAGE_QUALITY = "ImageQuality"
|
|
11
|
+
|
|
12
|
+
C_SCALING = "Scaling"
|
|
13
|
+
|
|
14
|
+
class Feature(str, Enum):
|
|
15
|
+
FOCUS_SCORE = "FocusScore"
|
|
16
|
+
LOCAL_FOCUS_SCORE = "LocalFocusScore"
|
|
17
|
+
CORRELATION = "Correlation"
|
|
18
|
+
POWER_SPECTRUM_SLOPE = "PowerLogLogSlope"
|
|
19
|
+
TOTAL_AREA = "TotalArea"
|
|
20
|
+
TOTAL_VOLUME = "TotalVolume"
|
|
21
|
+
TOTAL_INTENSITY = "TotalIntensity"
|
|
22
|
+
MEAN_INTENSITY = "MeanIntensity"
|
|
23
|
+
MEDIAN_INTENSITY = "MedianIntensity"
|
|
24
|
+
STD_INTENSITY = "StdIntensity"
|
|
25
|
+
MAD_INTENSITY = "MADIntensity"
|
|
26
|
+
MAX_INTENSITY = "MaxIntensity"
|
|
27
|
+
MIN_INTENSITY = "MinIntensity"
|
|
28
|
+
PERCENT_MAXIMAL = "PercentMaximal"
|
|
29
|
+
PERCENT_MINIMAL = "PercentMinimal"
|
|
30
|
+
THRESHOLD = "Threshold"
|
|
31
|
+
|
|
32
|
+
class TemplateMeasurementFormat(str):
|
|
33
|
+
"""A string subclass for measurement formatting."""
|
|
34
|
+
# IQ = Image Quality
|
|
35
|
+
IQ_SCALING = f"{C_IMAGE_QUALITY}_{C_SCALING}_%s"
|
|
36
|
+
IQ_FOCUS_SCORE = f"{C_IMAGE_QUALITY}_{Feature.FOCUS_SCORE.value}_%s"
|
|
37
|
+
IQ_LOCAL_FOCUS_SCORE = f"{C_IMAGE_QUALITY}_{Feature.LOCAL_FOCUS_SCORE.value}_%s"
|
|
38
|
+
IQ_CORR = f"{C_IMAGE_QUALITY}_{Feature.CORRELATION.value}_%s"
|
|
39
|
+
IQ_POWER_SPECTRUM_SLOPE = f"{C_IMAGE_QUALITY}_{Feature.POWER_SPECTRUM_SLOPE.value}_%s"
|
|
40
|
+
IQ_PERCENT_MAXIMAL = f"{C_IMAGE_QUALITY}_{Feature.PERCENT_MAXIMAL.value}_%s"
|
|
41
|
+
IQ_PERCENT_MINIMAL = f"{C_IMAGE_QUALITY}_{Feature.PERCENT_MINIMAL.value}_%s"
|
|
42
|
+
IQ_TOTAL_AREA = f"{C_IMAGE_QUALITY}_{Feature.TOTAL_AREA.value}_%s"
|
|
43
|
+
IQ_TOTAL_VOLUME = f"{C_IMAGE_QUALITY}_{Feature.TOTAL_VOLUME.value}_%s"
|
|
44
|
+
IQ_TOTAL_INTENSITY = f"{C_IMAGE_QUALITY}_{Feature.TOTAL_INTENSITY.value}_%s"
|
|
45
|
+
IQ_MEAN_INTENSITY = f"{C_IMAGE_QUALITY}_{Feature.MEAN_INTENSITY.value}_%s"
|
|
46
|
+
IQ_MEDIAN_INTENSITY = f"{C_IMAGE_QUALITY}_{Feature.MEDIAN_INTENSITY.value}_%s"
|
|
47
|
+
IQ_STD_INTENSITY = f"{C_IMAGE_QUALITY}_{Feature.STD_INTENSITY.value}_%s"
|
|
48
|
+
IQ_MAD_INTENSITY = f"{C_IMAGE_QUALITY}_{Feature.MAD_INTENSITY.value}_%s"
|
|
49
|
+
IQ_MAX_INTENSITY = f"{C_IMAGE_QUALITY}_{Feature.MAX_INTENSITY.value}_%s"
|
|
50
|
+
IQ_MIN_INTENSITY = f"{C_IMAGE_QUALITY}_{Feature.MIN_INTENSITY.value}_%s"
|
|
51
|
+
IQ_THRESHOLD = f"{C_IMAGE_QUALITY}_{Feature.THRESHOLD.value}%s"
|
|
52
|
+
|
|
53
|
+
class Aggregate(str, Enum):
|
|
54
|
+
MEAN = "Mean"
|
|
55
|
+
MEDIAN = "Median"
|
|
56
|
+
STD = "Std"
|
|
57
|
+
INTENSITY_FEATURES = [
|
|
58
|
+
Feature.TOTAL_INTENSITY,
|
|
59
|
+
Feature.MEAN_INTENSITY,
|
|
60
|
+
Feature.MEDIAN_INTENSITY,
|
|
61
|
+
Feature.STD_INTENSITY,
|
|
62
|
+
Feature.MAD_INTENSITY,
|
|
63
|
+
Feature.MAX_INTENSITY,
|
|
64
|
+
Feature.MIN_INTENSITY,
|
|
65
|
+
]
|
|
66
|
+
INTENSITY_TEMPLATES = [
|
|
67
|
+
TemplateMeasurementFormat.IQ_TOTAL_INTENSITY,
|
|
68
|
+
TemplateMeasurementFormat.IQ_MEAN_INTENSITY,
|
|
69
|
+
TemplateMeasurementFormat.IQ_MEDIAN_INTENSITY,
|
|
70
|
+
TemplateMeasurementFormat.IQ_STD_INTENSITY,
|
|
71
|
+
TemplateMeasurementFormat.IQ_MAD_INTENSITY,
|
|
72
|
+
TemplateMeasurementFormat.IQ_MAX_INTENSITY,
|
|
73
|
+
TemplateMeasurementFormat.IQ_MIN_INTENSITY,
|
|
74
|
+
]
|
|
75
|
+
SATURATION_FEATURES = [Feature.PERCENT_MAXIMAL, Feature.PERCENT_MINIMAL]
|
|
76
|
+
SATURATION_TEMPLATES = [TemplateMeasurementFormat.IQ_PERCENT_MAXIMAL, TemplateMeasurementFormat.IQ_PERCENT_MINIMAL]
|
|
77
|
+
AGGREGATES = [Aggregate.MEAN.value, Aggregate.MEDIAN.value, Aggregate.STD.value]
|
|
78
|
+
MEAN_THRESH_ALL_IMAGES = "MeanThresh_AllImages"
|
|
79
|
+
MEDIAN_THRESH_ALL_IMAGES = "MedianThresh_AllImages"
|
|
80
|
+
STD_THRESH_ALL_IMAGES = "StdThresh_AllImages"
|
|
81
|
+
|
|
82
|
+
class ScaledThresholdMethod(str, Enum):
|
|
83
|
+
OTSU = TM_OTSU
|
|
84
|
+
MOG = TM_MOG
|
|
85
|
+
# could just do `from .threshold import OtsuMethod` at the top
|
|
86
|
+
# but we make it explicit here to silence static analysis warnings
|
|
87
|
+
OtsuMethod = ThreshOtsuMethod
|
|
88
|
+
# similar to above
|
|
89
|
+
THRESHOLD_METHODS = TM_METHODS
|
|
@@ -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.dev610
|
|
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>
|
|
@@ -41,6 +41,7 @@ cellprofiler_library/modules/_measuregranularity.py
|
|
|
41
41
|
cellprofiler_library/modules/_measureimageareaoccupied.py
|
|
42
42
|
cellprofiler_library/modules/_measureimageintensity.py
|
|
43
43
|
cellprofiler_library/modules/_measureimageoverlap.py
|
|
44
|
+
cellprofiler_library/modules/_measureimagequality.py
|
|
44
45
|
cellprofiler_library/modules/_measureimageskeleton.py
|
|
45
46
|
cellprofiler_library/modules/_measureobjectintensity.py
|
|
46
47
|
cellprofiler_library/modules/_measureobjectneighbors.py
|
|
@@ -85,6 +86,7 @@ cellprofiler_library/opts/measuregranularity.py
|
|
|
85
86
|
cellprofiler_library/opts/measureimageareaoccupied.py
|
|
86
87
|
cellprofiler_library/opts/measureimageintensity.py
|
|
87
88
|
cellprofiler_library/opts/measureimageoverlap.py
|
|
89
|
+
cellprofiler_library/opts/measureimagequality.py
|
|
88
90
|
cellprofiler_library/opts/measureimageskeleton.py
|
|
89
91
|
cellprofiler_library/opts/measureobjectintensity.py
|
|
90
92
|
cellprofiler_library/opts/measureobjectneighbors.py
|
{cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/LICENSE
RENAMED
|
File without changes
|
{cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/README.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cellprofiler_library_nightly-5.0.0.dev592 → cellprofiler_library_nightly-5.0.0.dev610}/setup.cfg
RENAMED
|
File without changes
|