Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
07aa22d
Refactor hovernet post-processing
bhashemian Nov 30, 2022
9ebd464
Make type_prediction optional
bhashemian Nov 30, 2022
bd9f36b
Restructure
bhashemian Dec 1, 2022
3764ad1
Update unittests
bhashemian Dec 1, 2022
43ce643
Update dictionary wrapper
bhashemian Dec 1, 2022
d015dc8
Update docs
bhashemian Dec 1, 2022
220dfe2
Update unittests
bhashemian Dec 1, 2022
b918839
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 1, 2022
ffdd4b5
Expand if statement to avoid type error
bhashemian Dec 1, 2022
6306913
Merge branch 'hovernet-post' of github.com:drbeh/MONAI into hovernet-…
bhashemian Dec 1, 2022
9115d7e
Update names and fix typos
bhashemian Dec 1, 2022
be9bad7
Refactor GenerateWatershedMask and HoVerNetPostProcessing
bhashemian Dec 1, 2022
4144996
Refactor GenerateInstanceBorder
bhashemian Dec 1, 2022
a2a17f8
Update GenerateDistanceMap
bhashemian Dec 1, 2022
f1e7047
Update dict wrappers
bhashemian Dec 1, 2022
e36e0a7
Update GenerateWatershedMarkersd
bhashemian Dec 1, 2022
8263514
docs and formatting
bhashemian Dec 1, 2022
1998d7f
docs and formatting
bhashemian Dec 1, 2022
eb1a6f5
add unittests
bhashemian Dec 1, 2022
6fb1e5e
Add HoVerNetTypeMapPostProcessingd and unittests
bhashemian Dec 1, 2022
18ea67b
Refactor HoVerNetTypeMapPostProcessing and HoVerNetTypeMapPostProcess…
bhashemian Dec 1, 2022
027cb11
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 1, 2022
912f9e1
formatting
bhashemian Dec 1, 2022
9ded9d4
Merge branch 'hovernet-post' of github.com:drbeh/MONAI into hovernet-…
bhashemian Dec 1, 2022
bb7da35
Merge branch 'dev' into hovernet-post
bhashemian Dec 1, 2022
e2f181b
fix typo
bhashemian Dec 1, 2022
831fdac
update type
bhashemian Dec 1, 2022
3aa08bf
Update watershedd test
bhashemian Dec 2, 2022
6890f70
address commnets
bhashemian Dec 2, 2022
57384c1
Merge branch 'dev' into hovernet-post
bhashemian Dec 2, 2022
cd9e3f2
Allow 2D masks
bhashemian Dec 2, 2022
d0dd448
Merge branch 'hovernet-post' of github.com:drbeh/MONAI into hovernet-…
bhashemian Dec 2, 2022
300341f
Allow more 2D masks
bhashemian Dec 2, 2022
878676c
Merge branch 'dev' into hovernet-post
bhashemian Dec 2, 2022
57d54bc
Merge branch 'dev' into hovernet-post
bhashemian Dec 2, 2022
de2ff96
correct file names
bhashemian Dec 5, 2022
b538d40
Merge branch 'hovernet-post' of github.com:drbeh/MONAI into hovernet-…
bhashemian Dec 5, 2022
06e69b7
Merge branch 'dev' into hovernet-post
bhashemian Dec 5, 2022
a9145a1
Merge branch 'dev' into hovernet-post
bhashemian Dec 5, 2022
b58d61b
Merge branch 'dev' into hovernet-post
wyli Dec 5, 2022
08562e5
Merge branch 'dev' into hovernet-post
wyli Dec 5, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/source/apps.rst
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ Applications
:members:
.. autoclass:: HoVerNetNuclearTypePostProcessing
:members:
.. autoclass:: HoVerNetInstanceMapPostProcessing
:members:

.. automodule:: monai.apps.pathology.transforms.post.dictionary
.. autoclass:: GenerateSuccinctContourd
Expand All @@ -175,6 +177,8 @@ Applications
:members:
.. autoclass:: GenerateWatershedMarkersd
:members:
.. autoclass:: HoVerNetInstanceMapPostProcessingd
:members:
.. autoclass:: HoVerNetNuclearTypePostProcessingd
:members:

Expand Down
4 changes: 4 additions & 0 deletions monai/apps/pathology/transforms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
GenerateSuccinctContour,
GenerateWatershedMarkers,
GenerateWatershedMask,
HoVerNetInstanceMapPostProcessing,
HoVerNetNuclearTypePostProcessing,
Watershed,
)
Expand Down Expand Up @@ -46,6 +47,9 @@
GenerateWatershedMaskD,
GenerateWatershedMaskd,
GenerateWatershedMaskDict,
HoVerNetInstanceMapPostProcessingD,
HoVerNetInstanceMapPostProcessingd,
HoVerNetInstanceMapPostProcessingDict,
HoVerNetNuclearTypePostProcessingD,
HoVerNetNuclearTypePostProcessingd,
HoVerNetNuclearTypePostProcessingDict,
Expand Down
4 changes: 4 additions & 0 deletions monai/apps/pathology/transforms/post/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
GenerateSuccinctContour,
GenerateWatershedMarkers,
GenerateWatershedMask,
HoVerNetInstanceMapPostProcessing,
HoVerNetNuclearTypePostProcessing,
Watershed,
)
Expand Down Expand Up @@ -46,6 +47,9 @@
GenerateWatershedMaskD,
GenerateWatershedMaskd,
GenerateWatershedMaskDict,
HoVerNetInstanceMapPostProcessingD,
HoVerNetInstanceMapPostProcessingd,
HoVerNetInstanceMapPostProcessingDict,
HoVerNetNuclearTypePostProcessingD,
HoVerNetNuclearTypePostProcessingd,
HoVerNetNuclearTypePostProcessingDict,
Expand Down
472 changes: 298 additions & 174 deletions monai/apps/pathology/transforms/post/array.py

Large diffs are not rendered by default.

301 changes: 169 additions & 132 deletions monai/apps/pathology/transforms/post/dictionary.py

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion monai/transforms/post/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ class RemoveSmallObjects(Transform):
Data should be one-hotted.

Args:
min_size: objects smaller than this size are removed.
min_size: objects smaller than this size (in pixel) are removed.
connectivity: Maximum number of orthogonal hops to consider a pixel/voxel as a neighbor.
Accepted values are ranging from 1 to input.ndim. If ``None``, a full
connectivity of ``input.ndim`` is used. For more details refer to linked scikit-image
Expand Down
2 changes: 0 additions & 2 deletions tests/test_generate_distance_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,8 @@

for p in TEST_NDARRAYS:
EXCEPTION_TESTS.append([{}, p(np.random.rand(2, 5, 5)), p(np.random.rand(1, 5, 5)), ValueError])

EXCEPTION_TESTS.append([{}, p(np.random.rand(1, 5, 5)), p(np.random.rand(2, 5, 5)), ValueError])

for p in TEST_NDARRAYS:
TESTS.append([{}, p(np.random.rand(1, 5, 5)), p(np.random.rand(1, 5, 5)), (1, 5, 5)])
TESTS.append(
[{"smooth_fn": GaussianSmooth(sigma=0.4)}, p(np.random.rand(1, 5, 5)), p(np.random.rand(1, 5, 5)), (1, 5, 5)]
Expand Down
24 changes: 15 additions & 9 deletions tests/test_generate_distance_mapd.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,26 @@

for p in TEST_NDARRAYS:
EXCEPTION_TESTS.append(
[{"keys": "mask", "border_key": "border"}, p(np.random.rand(2, 5, 5)), p(np.random.rand(1, 5, 5)), ValueError]
[
{"mask_key": "mask", "border_key": "border"},
p(np.random.rand(2, 5, 5)),
p(np.random.rand(1, 5, 5)),
ValueError,
]
)

EXCEPTION_TESTS.append(
[{"keys": "mask", "border_key": "border"}, p(np.random.rand(1, 5, 5)), p(np.random.rand(2, 5, 5)), ValueError]
[
{"mask_key": "mask", "border_key": "border"},
p(np.random.rand(1, 5, 5)),
p(np.random.rand(2, 5, 5)),
ValueError,
]
)

for p in TEST_NDARRAYS:
TESTS.append(
[{"keys": "mask", "border_key": "border"}, p(np.random.rand(1, 5, 5)), p(np.random.rand(1, 5, 5)), (1, 5, 5)]
)
TESTS.append([{}, p(np.random.rand(1, 5, 5)), p(np.random.rand(1, 5, 5)), (1, 5, 5)])
TESTS.append(
[
{"keys": "mask", "border_key": "border", "smooth_fn": GaussianSmooth(sigma=0.4)},
{"mask_key": "mask", "border_key": "border", "smooth_fn": GaussianSmooth(sigma=0.4)},
p(np.random.rand(1, 5, 5)),
p(np.random.rand(1, 5, 5)),
(1, 5, 5),
Expand All @@ -55,7 +61,7 @@ def test_value(self, argments, mask, border_map, exception_type):
@parameterized.expand(TESTS)
def test_value2(self, argments, mask, border_map, expected_shape):
result = GenerateDistanceMapd(**argments)({"mask": mask, "border": border_map})
self.assertEqual(result["dist"].shape, expected_shape)
self.assertEqual(result["dist_map"].shape, expected_shape)


if __name__ == "__main__":
Expand Down
56 changes: 9 additions & 47 deletions tests/test_generate_instance_border.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,61 +23,23 @@
np.random.RandomState(123)

for p in TEST_NDARRAYS:
EXCEPTION_TESTS.append(
[
{"kernel_size": 3, "remove_small_objects": False},
p(np.random.rand(1, 5, 5, 5)),
p(np.random.rand(2, 5, 5)),
ValueError,
]
)
EXCEPTION_TESTS.append([{"kernel_size": 3}, p(np.random.rand(1, 5, 5, 5)), p(np.random.rand(2, 5, 5)), ValueError])
EXCEPTION_TESTS.append([{"kernel_size": 3}, p(np.random.rand(1, 5, 5)), p(np.random.rand(1, 5, 5)), ValueError])
EXCEPTION_TESTS.append([{"kernel_size": 3}, p(np.random.rand(2, 5, 5)), p(np.random.rand(2, 5, 5)), ValueError])

EXCEPTION_TESTS.append(
[
{"kernel_size": 3, "remove_small_objects": False},
p(np.random.rand(1, 5, 5)),
p(np.random.rand(1, 5, 5)),
ValueError,
]
)

EXCEPTION_TESTS.append(
[
{"kernel_size": 3, "remove_small_objects": False},
p(np.random.rand(2, 5, 5)),
p(np.random.rand(2, 5, 5)),
ValueError,
]
)

for p in TEST_NDARRAYS:
TESTS.append(
[
{"kernel_size": 3, "remove_small_objects": False},
p(np.random.rand(1, 5, 5)),
p(np.random.rand(2, 5, 5)),
(1, 5, 5),
]
)
TESTS.append(
[
{"kernel_size": 3, "remove_small_objects": False},
p(np.random.rand(1, 5, 5)),
p(np.random.rand(2, 5, 5)),
(1, 5, 5),
]
)
TESTS.append([{"kernel_size": 3}, p(np.random.rand(1, 5, 5)), p(np.random.rand(2, 5, 5)), (1, 5, 5)])
TESTS.append([{"kernel_size": 3}, p(np.random.rand(1, 5, 5)), p(np.random.rand(2, 5, 5)), (1, 5, 5)])


class TestGenerateInstanceBorder(unittest.TestCase):
@parameterized.expand(EXCEPTION_TESTS)
def test_value(self, argments, mask, hover_map, exception_type):
def test_value(self, arguments, mask, hover_map, exception_type):
with self.assertRaises(exception_type):
GenerateInstanceBorder(**argments)(mask, hover_map)
GenerateInstanceBorder(**arguments)(mask, hover_map)

@parameterized.expand(TESTS)
def test_value2(self, argments, mask, hover_map, expected_shape):
result = GenerateInstanceBorder(**argments)(mask, hover_map)
def test_value2(self, arguments, mask, hover_map, expected_shape):
result = GenerateInstanceBorder(**arguments)(mask, hover_map)
self.assertEqual(result.shape, expected_shape)


Expand Down
38 changes: 5 additions & 33 deletions tests/test_generate_instance_borderd.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,48 +24,20 @@

for p in TEST_NDARRAYS:
EXCEPTION_TESTS.append(
[
{"keys": "mask", "kernel_size": 3, "remove_small_objects": True, "min_size": 10},
p(np.random.rand(1, 5, 5, 5)),
p(np.random.rand(2, 5, 5)),
ValueError,
]
[{"mask_key": "mask", "kernel_size": 3}, p(np.random.rand(1, 5, 5, 5)), p(np.random.rand(2, 5, 5)), ValueError]
)

EXCEPTION_TESTS.append(
[
{"keys": "mask", "kernel_size": 3, "remove_small_objects": True, "min_size": 10},
p(np.random.rand(1, 5, 5)),
p(np.random.rand(1, 5, 5)),
ValueError,
]
[{"mask_key": "mask", "kernel_size": 3}, p(np.random.rand(1, 5, 5)), p(np.random.rand(1, 5, 5)), ValueError]
)

EXCEPTION_TESTS.append(
[
{"keys": "mask", "kernel_size": 3, "remove_small_objects": True, "min_size": 10},
p(np.random.rand(2, 5, 5)),
p(np.random.rand(2, 5, 5)),
ValueError,
]
[{"mask_key": "mask", "kernel_size": 3}, p(np.random.rand(2, 5, 5)), p(np.random.rand(2, 5, 5)), ValueError]
)

for p in TEST_NDARRAYS:
TESTS.append(
[
{"keys": "mask", "kernel_size": 3, "remove_small_objects": False, "min_size": 10},
p(np.random.rand(1, 5, 5)),
p(np.random.rand(2, 5, 5)),
(1, 5, 5),
]
[{"mask_key": "mask", "kernel_size": 3}, p(np.random.rand(1, 5, 5)), p(np.random.rand(2, 5, 5)), (1, 5, 5)]
)
TESTS.append(
[
{"keys": "mask", "kernel_size": 3, "remove_small_objects": True, "min_size": 10},
p(np.random.rand(1, 5, 5)),
p(np.random.rand(2, 5, 5)),
(1, 5, 5),
]
[{"mask_key": "mask", "kernel_size": 3}, p(np.random.rand(1, 5, 5)), p(np.random.rand(2, 5, 5)), (1, 5, 5)]
)


Expand Down
10 changes: 4 additions & 6 deletions tests/test_generate_watershed_markers.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,22 @@

for p in TEST_NDARRAYS:
EXCEPTION_TESTS.append([{}, p(np.random.rand(2, 5, 5)), p(np.random.rand(1, 5, 5)), ValueError])

EXCEPTION_TESTS.append([{}, p(np.random.rand(1, 5, 5)), p(np.random.rand(2, 5, 5)), ValueError])

for p in TEST_NDARRAYS:
TESTS.append([{}, p(np.random.rand(1, 5, 5)), p(np.random.rand(1, 5, 5)), (1, 5, 5)])


@unittest.skipUnless(has_skimage, "Requires scikit-image library.")
@unittest.skipUnless(has_scipy, "Requires scipy library.")
class TestGenerateWatershedMarkers(unittest.TestCase):
@parameterized.expand(EXCEPTION_TESTS)
def test_value(self, argments, mask, probmap, exception_type):
def test_value(self, arguments, mask, probmap, exception_type):
with self.assertRaises(exception_type):
GenerateWatershedMarkers(**argments)(mask, probmap)
GenerateWatershedMarkers(**arguments)(mask, probmap)

@parameterized.expand(TESTS)
def test_value2(self, argments, mask, probmap, expected_shape):
result = GenerateWatershedMarkers(**argments)(mask, probmap)
def test_value2(self, arguments, mask, probmap, expected_shape):
result = GenerateWatershedMarkers(**arguments)(mask, probmap)
self.assertEqual(result.shape, expected_shape)


Expand Down
35 changes: 24 additions & 11 deletions tests/test_generate_watershed_markersd.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,39 +28,52 @@

for p in TEST_NDARRAYS:
EXCEPTION_TESTS.append(
[{"keys": "mask", "border_key": "border"}, p(np.random.rand(2, 5, 5)), p(np.random.rand(1, 5, 5)), ValueError]
[
{"mask_key": "mask", "border_key": "border"},
p(np.random.rand(2, 5, 5)),
p(np.random.rand(1, 5, 5)),
ValueError,
]
)

EXCEPTION_TESTS.append(
[{"keys": "mask", "border_key": "border"}, p(np.random.rand(1, 5, 5)), p(np.random.rand(2, 5, 5)), ValueError]
[
{"mask_key": "mask", "border_key": "border"},
p(np.random.rand(1, 5, 5)),
p(np.random.rand(2, 5, 5)),
ValueError,
]
)

EXCEPTION_TESTS.append(
[
{"keys": "mask", "border_key": "border", "markers_key": "old_markers"},
{"mask_key": "mask", "border_key": "border", "markers_key": "old_markers"},
p(np.random.rand(1, 5, 5)),
p(np.random.rand(1, 5, 5)),
KeyError,
]
)

for p in TEST_NDARRAYS:
TESTS.append([{}, p(np.random.rand(1, 5, 5)), p(np.random.rand(1, 5, 5)), (1, 5, 5)])
TESTS.append(
[{"keys": "mask", "border_key": "border"}, p(np.random.rand(1, 5, 5)), p(np.random.rand(1, 5, 5)), (1, 5, 5)]
[
{"threshold": 0.4, "radius": 1, "min_object_size": 0},
p(np.random.rand(1, 5, 5)),
p(np.random.rand(1, 5, 5)),
(1, 5, 5),
]
)


@unittest.skipUnless(has_skimage, "Requires scikit-image library.")
@unittest.skipUnless(has_scipy, "Requires scipy library.")
class TestGenerateWatershedMarkersd(unittest.TestCase):
@parameterized.expand(EXCEPTION_TESTS)
def test_value(self, argments, mask, border_map, exception_type):
def test_value(self, arguments, mask, border_map, exception_type):
with self.assertRaises(exception_type):
GenerateWatershedMarkersd(**argments)({"mask": mask, "border": border_map, "old_markers": 1})
GenerateWatershedMarkersd(**arguments)({"mask": mask, "border": border_map, "old_markers": 1})

@parameterized.expand(TESTS)
def test_value2(self, argments, mask, border_map, expected_shape):
result = GenerateWatershedMarkersd(**argments)({"mask": mask, "border": border_map})
def test_value2(self, arguments, mask, border_map, expected_shape):
result = GenerateWatershedMarkersd(**arguments)({"mask": mask, "border": border_map})
self.assertEqual(result["markers"].shape, expected_shape)


Expand Down
22 changes: 8 additions & 14 deletions tests/test_generate_watershed_mask.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,12 @@
np.random.RandomState(123)

for p in TEST_NDARRAYS:
EXCEPTION_TESTS.append(
[
{"softmax": False, "sigmoid": True, "remove_small_objects": True, "min_size": 10},
p(np.random.rand(1, 5, 5)),
ValueError,
]
)
EXCEPTION_TESTS.append([{"activation": "incorrect"}, ValueError])
EXCEPTION_TESTS.append([{"activation": 1}, ValueError])

for p in TEST_NDARRAYS:
TESTS.append(
[
{"softmax": True, "sigmoid": False, "threshold": None, "remove_small_objects": False, "min_size": 10},
{"activation": "softmax", "min_object_size": 0},
p(
[
[[0.5022, 0.3403, 0.9997], [0.8793, 0.5514, 0.2697], [0.6134, 0.6389, 0.0680]],
Expand All @@ -52,7 +46,7 @@

TESTS.append(
[
{"softmax": False, "sigmoid": True, "threshold": 0.5, "remove_small_objects": False, "min_size": 10},
{"activation": "sigmoid", "threshold": 0.5, "min_object_size": 0},
p([[[0.5022, 0.3403, 0.9997], [0.8793, 0.5514, 0.2697], [-0.1134, -0.0389, -0.0680]]]),
(1, 3, 3),
[0, 1],
Expand All @@ -63,13 +57,13 @@
@unittest.skipUnless(has_scipy, "Requires scipy library.")
class TestGenerateWatershedMask(unittest.TestCase):
@parameterized.expand(EXCEPTION_TESTS)
def test_value(self, argments, image, exception_type):
def test_value(self, arguments, exception_type):
with self.assertRaises(exception_type):
GenerateWatershedMask(**argments)(image)
GenerateWatershedMask(**arguments)

@parameterized.expand(TESTS)
def test_value2(self, argments, image, expected_shape, expected_value):
result = GenerateWatershedMask(**argments)(image)
def test_value2(self, arguments, image, expected_shape, expected_value):
result = GenerateWatershedMask(**arguments)(image)
self.assertEqual(result.shape, expected_shape)

if isinstance(result, torch.Tensor):
Expand Down
Loading