diff --git a/napari_skimage_regionprops/__init__.py b/napari_skimage_regionprops/__init__.py index e57481a..82e7957 100644 --- a/napari_skimage_regionprops/__init__.py +++ b/napari_skimage_regionprops/__init__.py @@ -8,7 +8,7 @@ try: from ._version import version as __version__ except ImportError: - __version__ = "0.6.2" + __version__ = "0.7.0" @napari_hook_implementation diff --git a/napari_skimage_regionprops/_regionprops.py b/napari_skimage_regionprops/_regionprops.py index a267ccf..18d4072 100644 --- a/napari_skimage_regionprops/_regionprops.py +++ b/napari_skimage_regionprops/_regionprops.py @@ -51,8 +51,13 @@ def regionprops_table(image : napari.types.ImageData, labels: napari.types.Label extra_properties = [] if size: - properties = properties + ['area', 'bbox_area', 'convex_area', 'equivalent_diameter'] - + properties = properties + ['area', 'bbox_area', 'equivalent_diameter'] + # Workaround to avoid existing scikit-image bug + # See https://github.com/scikit-image/scikit-image/issues/6432 + if (len(labels.shape) == 3) and (_check_2D_labels_in_3D_images(labels)): + warnings.warn("2D labels are present in 3D label image, 'convex_area' not calculated") + else: + properties = properties + ['convex_area'] if intensity: properties = properties + ['max_intensity', 'mean_intensity', 'min_intensity'] @@ -69,7 +74,13 @@ def standard_deviation_intensity(region, intensities): warnings.warn("Perimeter measurements are not supported in 3D") if shape: - properties = properties + ['solidity', 'extent', 'feret_diameter_max', 'local_centroid'] + properties = properties + ['extent', 'local_centroid'] + # Workaround to avoid existing scikit-image bug + # See https://github.com/scikit-image/scikit-image/issues/6432 + if (len(labels.shape) == 3) and (_check_2D_labels_in_3D_images(labels)): + warnings.warn("2D labels are present in 3D label image, 'feret_diameter_max' and 'solidity' not calculated") + else: + properties = properties + ['solidity', 'feret_diameter_max'] if len(labels.shape) == 2: properties = properties + ['major_axis_length', 'minor_axis_length', 'orientation', 'eccentricity'] # we need these two to compute some shape descriptors @@ -97,7 +108,7 @@ def standard_deviation_intensity(region, intensities): # weighted_moments_central # weighted_moments_hu # weighted_moments_normalized - + print('PROPERTIES = ', properties) # quantitative analysis using scikit-image's regionprops from skimage.measure import regionprops_table as sk_regionprops_table table = sk_regionprops_table(np.asarray(labels).astype(int), intensity_image=np.asarray(image), @@ -185,7 +196,18 @@ def ellipsoid_axis_lengths(table): regionprops_table_all_frames = analyze_all_frames(regionprops_table) register_function(regionprops_table_all_frames, menu="Measurement tables > Regionprops of all frames (nsr)") - +def _check_2D_labels_in_3D_images(label_image): + ''' + Checks if there are 2D labels in a 3D label image + ''' + from skimage.measure import regionprops as sk_regionprops + + measurements = sk_regionprops(label_image) + for props in measurements: + label_shape = np.array(props.bbox[3:]) - np.array(props.bbox[:3]) + if np.any(label_shape == 1): + return True + return False try: # morphometrics API diff --git a/napari_skimage_regionprops/_tests/test_function.py b/napari_skimage_regionprops/_tests/test_function.py index 384a88a..fa70c54 100644 --- a/napari_skimage_regionprops/_tests/test_function.py +++ b/napari_skimage_regionprops/_tests/test_function.py @@ -397,3 +397,21 @@ def test_measure_points(): points = np.random.random((100, 2)) * 99 nsr.measure_points(points, image) + +def test_2d_labels_in_3d_image(): + import numpy as np + labels = np.zeros((6,6,6), dtype=np.uint8) + labels[1:4, 1:4, 1:4] = 1 # 3D label + labels[4, 1:4, 1:4] = 2 # 2D label + + from napari_skimage_regionprops import regionprops_table + table = regionprops_table(labels, labels, size=True, intensity=True, perimeter=True, shape=True, position=True, + moments=True) + + # check one measurement + assert np.array_equal(table['area'], [27, 9]) + + # check that measurements that depend on convex_area are absent in this case + assert "convex_area" not in table.keys() + assert "feret_max_diameter" not in table.keys() + assert "solidity" not in table.keys() diff --git a/setup.py b/setup.py index da76ef7..811d112 100644 --- a/setup.py +++ b/setup.py @@ -36,7 +36,7 @@ def read(fname): packages=find_packages(), python_requires='>=3.8', install_requires=requirements, - version='0.6.2', + version='0.7.0', #use_scm_version=use_scm, setup_requires=['setuptools_scm'], classifiers=[