From 7dfea38cb36c88024a9b834e90e1019d7186bffa Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Wed, 25 Aug 2021 11:42:22 +0800 Subject: [PATCH 01/11] [DLMED] support random fill Signed-off-by: Nic Ma --- monai/transforms/intensity/array.py | 12 +++++++++--- tests/test_rand_coarse_dropout.py | 13 +++++++------ tests/test_rand_coarse_dropoutd.py | 6 +----- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/monai/transforms/intensity/array.py b/monai/transforms/intensity/array.py index 8b2bf32145..4e8afa4b26 100644 --- a/monai/transforms/intensity/array.py +++ b/monai/transforms/intensity/array.py @@ -1637,7 +1637,8 @@ class RandCoarseDropout(RandomizableTransform): if some components of the `spatial_size` are non-positive values, the transform will use the corresponding components of input img size. For example, `spatial_size=(32, -1)` will be adapted to `(32, 64)` if the second spatial dimension size of img is `64`. - fill_value: target value to fill the dropout regions. + fill_value: target value to fill the dropout regions, if providing a tuple for the `min` and `max`, + will randomly select value for every pixel / voxel from the range `[min, max)`. max_holes: if not None, define the maximum number to randomly select the expected number of regions. max_spatial_size: if not None, define the maximum spatial size to randomly select size for every region. if some components of the `max_spatial_size` are non-positive values, the transform will use the @@ -1651,7 +1652,7 @@ def __init__( self, holes: int, spatial_size: Union[Sequence[int], int], - fill_value: Union[float, int] = 0, + fill_value: Union[Tuple[Union[float, int]], Union[float, int]] = 0, max_holes: Optional[int] = None, max_spatial_size: Optional[Union[Sequence[int], int]] = None, prob: float = 0.1, @@ -1682,7 +1683,12 @@ def __call__(self, img: np.ndarray): self.randomize(img.shape[1:]) if self._do_transform: for h in self.hole_coords: - img[h] = self.fill_value + if isinstance(self.fill_value, (tuple, list)): + if len(self.fill_value) != 2: + raise ValueError("fill_value should contain 2 numbers if providing the `min` and `max`.") + img[h] = self.R.uniform(self.fill_value[0], self.fill_value[1], size=img[h].shape) + else: + img[h] = self.fill_value return img diff --git a/tests/test_rand_coarse_dropout.py b/tests/test_rand_coarse_dropout.py index 235a391567..d8e454f460 100644 --- a/tests/test_rand_coarse_dropout.py +++ b/tests/test_rand_coarse_dropout.py @@ -20,31 +20,32 @@ TEST_CASE_0 = [ {"holes": 2, "spatial_size": [2, 2, 2], "fill_value": 5, "prob": 1.0}, np.random.randint(0, 2, size=[3, 3, 3, 4]), - (3, 3, 3, 4), ] TEST_CASE_1 = [ {"holes": 1, "spatial_size": [1, 2, 3], "fill_value": 5, "max_holes": 5, "prob": 1.0}, np.random.randint(0, 2, size=[3, 3, 3, 4]), - (3, 3, 3, 4), ] TEST_CASE_2 = [ {"holes": 2, "spatial_size": [2, 2, 2], "fill_value": 5, "max_spatial_size": [4, 4, 3], "prob": 1.0}, np.random.randint(0, 2, size=[3, 3, 3, 4]), - (3, 3, 3, 4), ] TEST_CASE_3 = [ {"holes": 2, "spatial_size": [2, -1, 2], "fill_value": 5, "max_spatial_size": [4, 4, -1], "prob": 1.0}, np.random.randint(0, 2, size=[3, 3, 3, 4]), - (3, 3, 3, 4), +] + +TEST_CASE_4 = [ + {"holes": 2, "spatial_size": [2, 2, 2], "fill_value": (3, 6), "prob": 1.0}, + np.random.randint(0, 2, size=[3, 3, 3, 4]), ] class TestRandCoarseDropout(unittest.TestCase): - @parameterized.expand([TEST_CASE_0, TEST_CASE_1, TEST_CASE_2, TEST_CASE_3]) - def test_value(self, input_param, input_data, expected_shape): + @parameterized.expand([TEST_CASE_0, TEST_CASE_1, TEST_CASE_2, TEST_CASE_3, TEST_CASE_4]) + def test_value(self, input_param, input_data): dropout = RandCoarseDropout(**input_param) result = dropout(input_data) holes = input_param.get("holes") diff --git a/tests/test_rand_coarse_dropoutd.py b/tests/test_rand_coarse_dropoutd.py index d189a80f56..fbbfc5b584 100644 --- a/tests/test_rand_coarse_dropoutd.py +++ b/tests/test_rand_coarse_dropoutd.py @@ -20,13 +20,11 @@ TEST_CASE_0 = [ {"keys": "img", "holes": 2, "spatial_size": [2, 2, 2], "fill_value": 5, "prob": 1.0}, {"img": np.random.randint(0, 2, size=[3, 3, 3, 4])}, - (3, 3, 3, 4), ] TEST_CASE_1 = [ {"keys": "img", "holes": 1, "spatial_size": [1, 2, 3], "fill_value": 5, "max_holes": 5, "prob": 1.0}, {"img": np.random.randint(0, 2, size=[3, 3, 3, 4])}, - (3, 3, 3, 4), ] TEST_CASE_2 = [ @@ -39,7 +37,6 @@ "prob": 1.0, }, {"img": np.random.randint(0, 2, size=[3, 3, 3, 4])}, - (3, 3, 3, 4), ] TEST_CASE_3 = [ @@ -52,13 +49,12 @@ "prob": 1.0, }, {"img": np.random.randint(0, 2, size=[3, 3, 3, 4])}, - (3, 3, 3, 4), ] class TestRandCoarseDropoutd(unittest.TestCase): @parameterized.expand([TEST_CASE_0, TEST_CASE_1, TEST_CASE_2, TEST_CASE_3]) - def test_value(self, input_param, input_data, expected_shape): + def test_value(self, input_param, input_data): dropout = RandCoarseDropoutd(**input_param) result = dropout(input_data)["img"] holes = input_param.get("holes") From 0583edee171f2b2a56407cff975eb559d45e7ff6 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Wed, 25 Aug 2021 11:57:23 +0800 Subject: [PATCH 02/11] [DLMED] update for test Signed-off-by: Nic Ma --- tests/test_rand_coarse_dropout.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/test_rand_coarse_dropout.py b/tests/test_rand_coarse_dropout.py index d8e454f460..2e16d45e73 100644 --- a/tests/test_rand_coarse_dropout.py +++ b/tests/test_rand_coarse_dropout.py @@ -61,7 +61,16 @@ def test_value(self, input_param, input_data): for h in dropout.hole_coords: data = result[h] - np.testing.assert_allclose(data, input_param.get("fill_value", 0)) + fill_value = input_param.get("fill_value", 0) + if isinstance(fill_value, (int, float)): + np.testing.assert_allclose(data, fill_value) + else: + print("hole data:", data) + min_value = min(data) + max_value = max(data) + self.assertGreaterEqual(max_value, min_value) + self.assertGreaterEqual(min_value, fill_value[0]) + self.assertLess(max_value, fill_value[1]) if max_spatial_size is None: self.assertTupleEqual(data.shape[1:], tuple(spatial_size)) else: From 0eb589581930405844d37ea25228eda7760a5173 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Wed, 25 Aug 2021 12:53:38 +0800 Subject: [PATCH 03/11] [DLMED] fix typo Signed-off-by: Nic Ma --- tests/test_rand_coarse_dropout.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_rand_coarse_dropout.py b/tests/test_rand_coarse_dropout.py index 2e16d45e73..920d449ddd 100644 --- a/tests/test_rand_coarse_dropout.py +++ b/tests/test_rand_coarse_dropout.py @@ -66,8 +66,8 @@ def test_value(self, input_param, input_data): np.testing.assert_allclose(data, fill_value) else: print("hole data:", data) - min_value = min(data) - max_value = max(data) + min_value = data.min() + max_value = data.max() self.assertGreaterEqual(max_value, min_value) self.assertGreaterEqual(min_value, fill_value[0]) self.assertLess(max_value, fill_value[1]) From ac97a0c642f58f8847ebb0e8ceff0cd722ad7b2e Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Wed, 25 Aug 2021 14:39:12 +0800 Subject: [PATCH 04/11] [DLMED] update dict transform Signed-off-by: Nic Ma --- monai/transforms/intensity/dictionary.py | 12 +++++++++--- tests/test_rand_coarse_dropout.py | 1 - tests/test_rand_coarse_dropoutd.py | 10 +++++++++- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/monai/transforms/intensity/dictionary.py b/monai/transforms/intensity/dictionary.py index bce45b57d3..3fe955cd2c 100644 --- a/monai/transforms/intensity/dictionary.py +++ b/monai/transforms/intensity/dictionary.py @@ -1431,7 +1431,8 @@ class RandCoarseDropoutd(RandomizableTransform, MapTransform): if some components of the `spatial_size` are non-positive values, the transform will use the corresponding components of input img size. For example, `spatial_size=(32, -1)` will be adapted to `(32, 64)` if the second spatial dimension size of img is `64`. - fill_value: target value to fill the dropout regions. + fill_value: target value to fill the dropout regions, if providing a tuple for the `min` and `max`, + will randomly select value for every pixel / voxel from the range `[min, max)`. max_holes: if not None, define the maximum number to randomly select the expected number of regions. max_spatial_size: if not None, define the maximum spatial size to randomly select size for every region. if some components of the `max_spatial_size` are non-positive values, the transform will use the @@ -1447,7 +1448,7 @@ def __init__( keys: KeysCollection, holes: int, spatial_size: Union[Sequence[int], int], - fill_value: Union[float, int] = 0, + fill_value: Union[Tuple[Union[float, int]], Union[float, int]] = 0, max_holes: Optional[int] = None, max_spatial_size: Optional[Union[Sequence[int], int]] = None, prob: float = 0.1, @@ -1483,7 +1484,12 @@ def __call__(self, data): if self._do_transform: for key in self.key_iterator(d): for h in self.hole_coords: - d[key][h] = self.fill_value + if isinstance(self.fill_value, (tuple, list)): + if len(self.fill_value) != 2: + raise ValueError("fill_value should contain 2 numbers if providing the `min` and `max`.") + d[key][h] = self.R.uniform(self.fill_value[0], self.fill_value[1], size=d[key][h].shape) + else: + d[key][h] = self.fill_value return d diff --git a/tests/test_rand_coarse_dropout.py b/tests/test_rand_coarse_dropout.py index 920d449ddd..d2c90af2bf 100644 --- a/tests/test_rand_coarse_dropout.py +++ b/tests/test_rand_coarse_dropout.py @@ -65,7 +65,6 @@ def test_value(self, input_param, input_data): if isinstance(fill_value, (int, float)): np.testing.assert_allclose(data, fill_value) else: - print("hole data:", data) min_value = data.min() max_value = data.max() self.assertGreaterEqual(max_value, min_value) diff --git a/tests/test_rand_coarse_dropoutd.py b/tests/test_rand_coarse_dropoutd.py index fbbfc5b584..de0a017aef 100644 --- a/tests/test_rand_coarse_dropoutd.py +++ b/tests/test_rand_coarse_dropoutd.py @@ -70,7 +70,15 @@ def test_value(self, input_param, input_data): for h in dropout.hole_coords: data = result[h] - np.testing.assert_allclose(data, input_param.get("fill_value", 0)) + fill_value = input_param.get("fill_value", 0) + if isinstance(fill_value, (int, float)): + np.testing.assert_allclose(data, fill_value) + else: + min_value = data.min() + max_value = data.max() + self.assertGreaterEqual(max_value, min_value) + self.assertGreaterEqual(min_value, fill_value[0]) + self.assertLess(max_value, fill_value[1]) if max_spatial_size is None: self.assertTupleEqual(data.shape[1:], tuple(spatial_size)) else: From ad79cdfd42a79671b69f9b03c1367d20e5e75a94 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Wed, 25 Aug 2021 15:05:42 +0800 Subject: [PATCH 05/11] [DLMED] fix mypy Signed-off-by: Nic Ma --- monai/transforms/intensity/array.py | 2 +- monai/transforms/intensity/dictionary.py | 2 +- tests/test_rand_coarse_dropoutd.py | 8 +++++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/monai/transforms/intensity/array.py b/monai/transforms/intensity/array.py index 4e8afa4b26..122ed947ca 100644 --- a/monai/transforms/intensity/array.py +++ b/monai/transforms/intensity/array.py @@ -1688,7 +1688,7 @@ def __call__(self, img: np.ndarray): raise ValueError("fill_value should contain 2 numbers if providing the `min` and `max`.") img[h] = self.R.uniform(self.fill_value[0], self.fill_value[1], size=img[h].shape) else: - img[h] = self.fill_value + img[h] = self.fill_value # type: ignore return img diff --git a/monai/transforms/intensity/dictionary.py b/monai/transforms/intensity/dictionary.py index 3fe955cd2c..865d391455 100644 --- a/monai/transforms/intensity/dictionary.py +++ b/monai/transforms/intensity/dictionary.py @@ -1489,7 +1489,7 @@ def __call__(self, data): raise ValueError("fill_value should contain 2 numbers if providing the `min` and `max`.") d[key][h] = self.R.uniform(self.fill_value[0], self.fill_value[1], size=d[key][h].shape) else: - d[key][h] = self.fill_value + d[key][h] = self.fill_value # type: ignore return d diff --git a/tests/test_rand_coarse_dropoutd.py b/tests/test_rand_coarse_dropoutd.py index de0a017aef..051218c2cb 100644 --- a/tests/test_rand_coarse_dropoutd.py +++ b/tests/test_rand_coarse_dropoutd.py @@ -51,9 +51,14 @@ {"img": np.random.randint(0, 2, size=[3, 3, 3, 4])}, ] +TEST_CASE_4 = [ + {"keys": "img", "holes": 2, "spatial_size": [2, 2, 2], "fill_value": (0.2, 0.6), "prob": 1.0}, + {"img": np.random.rand((3, 3, 3, 4))}, +] + class TestRandCoarseDropoutd(unittest.TestCase): - @parameterized.expand([TEST_CASE_0, TEST_CASE_1, TEST_CASE_2, TEST_CASE_3]) + @parameterized.expand([TEST_CASE_0, TEST_CASE_1, TEST_CASE_2, TEST_CASE_3, TEST_CASE_4]) def test_value(self, input_param, input_data): dropout = RandCoarseDropoutd(**input_param) result = dropout(input_data)["img"] @@ -74,6 +79,7 @@ def test_value(self, input_param, input_data): if isinstance(fill_value, (int, float)): np.testing.assert_allclose(data, fill_value) else: + print("hole data:", data) min_value = data.min() max_value = data.max() self.assertGreaterEqual(max_value, min_value) From 2778dc1683b502620e71d7ebb52491adc0619053 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Wed, 25 Aug 2021 15:11:57 +0800 Subject: [PATCH 06/11] [DLMED] fix typo Signed-off-by: Nic Ma --- tests/test_rand_coarse_dropoutd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_rand_coarse_dropoutd.py b/tests/test_rand_coarse_dropoutd.py index 051218c2cb..7685f72715 100644 --- a/tests/test_rand_coarse_dropoutd.py +++ b/tests/test_rand_coarse_dropoutd.py @@ -53,7 +53,7 @@ TEST_CASE_4 = [ {"keys": "img", "holes": 2, "spatial_size": [2, 2, 2], "fill_value": (0.2, 0.6), "prob": 1.0}, - {"img": np.random.rand((3, 3, 3, 4))}, + {"img": np.random.rand(3, 3, 3, 4)}, ] From c558dd914b7782677b16493ab68b793c74bb16e3 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Wed, 25 Aug 2021 15:31:06 +0800 Subject: [PATCH 07/11] [DLMED] fix typo Signed-off-by: Nic Ma --- monai/transforms/intensity/array.py | 4 ++-- monai/transforms/intensity/dictionary.py | 4 ++-- tests/test_rand_coarse_dropout.py | 3 ++- tests/test_rand_coarse_dropoutd.py | 1 - 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/monai/transforms/intensity/array.py b/monai/transforms/intensity/array.py index 1ce7529693..6b5f865bd4 100644 --- a/monai/transforms/intensity/array.py +++ b/monai/transforms/intensity/array.py @@ -1658,7 +1658,7 @@ def __init__( self, holes: int, spatial_size: Union[Sequence[int], int], - fill_value: Union[Tuple[Union[float, int]], Union[float, int]] = 0, + fill_value: Union[Tuple[float, float], float] = 0, max_holes: Optional[int] = None, max_spatial_size: Optional[Union[Sequence[int], int]] = None, prob: float = 0.1, @@ -1694,7 +1694,7 @@ def __call__(self, img: np.ndarray): raise ValueError("fill_value should contain 2 numbers if providing the `min` and `max`.") img[h] = self.R.uniform(self.fill_value[0], self.fill_value[1], size=img[h].shape) else: - img[h] = self.fill_value # type: ignore + img[h] = self.fill_value return img diff --git a/monai/transforms/intensity/dictionary.py b/monai/transforms/intensity/dictionary.py index 6e781e8ceb..04970319e7 100644 --- a/monai/transforms/intensity/dictionary.py +++ b/monai/transforms/intensity/dictionary.py @@ -1452,7 +1452,7 @@ def __init__( keys: KeysCollection, holes: int, spatial_size: Union[Sequence[int], int], - fill_value: Union[Tuple[Union[float, int]], Union[float, int]] = 0, + fill_value: Union[Tuple[float, float], float] = 0, max_holes: Optional[int] = None, max_spatial_size: Optional[Union[Sequence[int], int]] = None, prob: float = 0.1, @@ -1493,7 +1493,7 @@ def __call__(self, data): raise ValueError("fill_value should contain 2 numbers if providing the `min` and `max`.") d[key][h] = self.R.uniform(self.fill_value[0], self.fill_value[1], size=d[key][h].shape) else: - d[key][h] = self.fill_value # type: ignore + d[key][h] = self.fill_value return d diff --git a/tests/test_rand_coarse_dropout.py b/tests/test_rand_coarse_dropout.py index d2c90af2bf..4f016b0488 100644 --- a/tests/test_rand_coarse_dropout.py +++ b/tests/test_rand_coarse_dropout.py @@ -38,7 +38,7 @@ ] TEST_CASE_4 = [ - {"holes": 2, "spatial_size": [2, 2, 2], "fill_value": (3, 6), "prob": 1.0}, + {"holes": 2, "spatial_size": [2, 2, 2], "fill_value": (3.5, 6.0), "prob": 1.0}, np.random.randint(0, 2, size=[3, 3, 3, 4]), ] @@ -65,6 +65,7 @@ def test_value(self, input_param, input_data): if isinstance(fill_value, (int, float)): np.testing.assert_allclose(data, fill_value) else: + print("hole data:", data) min_value = data.min() max_value = data.max() self.assertGreaterEqual(max_value, min_value) diff --git a/tests/test_rand_coarse_dropoutd.py b/tests/test_rand_coarse_dropoutd.py index 7685f72715..4175624b3a 100644 --- a/tests/test_rand_coarse_dropoutd.py +++ b/tests/test_rand_coarse_dropoutd.py @@ -79,7 +79,6 @@ def test_value(self, input_param, input_data): if isinstance(fill_value, (int, float)): np.testing.assert_allclose(data, fill_value) else: - print("hole data:", data) min_value = data.min() max_value = data.max() self.assertGreaterEqual(max_value, min_value) From e47ea1502194161d20d2ca943fa3f99370a6afed Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Wed, 25 Aug 2021 15:38:57 +0800 Subject: [PATCH 08/11] [DLMED] fix typo Signed-off-by: Nic Ma --- tests/test_rand_coarse_dropout.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_rand_coarse_dropout.py b/tests/test_rand_coarse_dropout.py index 4f016b0488..a66e3e2fbf 100644 --- a/tests/test_rand_coarse_dropout.py +++ b/tests/test_rand_coarse_dropout.py @@ -38,7 +38,7 @@ ] TEST_CASE_4 = [ - {"holes": 2, "spatial_size": [2, 2, 2], "fill_value": (3.5, 6.0), "prob": 1.0}, + {"holes": 2, "spatial_size": [2, 2, 2], "fill_value": (3, 6), "prob": 1.0}, np.random.randint(0, 2, size=[3, 3, 3, 4]), ] @@ -65,6 +65,7 @@ def test_value(self, input_param, input_data): if isinstance(fill_value, (int, float)): np.testing.assert_allclose(data, fill_value) else: + print("hole data:", data) print("hole data:", data) min_value = data.min() max_value = data.max() From ab7d32a29fdda7e6c07b573e5b04df43db06e6d5 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Wed, 25 Aug 2021 15:54:07 +0800 Subject: [PATCH 09/11] [DLMED] fix typo Signed-off-by: Nic Ma --- tests/test_rand_coarse_dropout.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_rand_coarse_dropout.py b/tests/test_rand_coarse_dropout.py index a66e3e2fbf..d2c90af2bf 100644 --- a/tests/test_rand_coarse_dropout.py +++ b/tests/test_rand_coarse_dropout.py @@ -65,8 +65,6 @@ def test_value(self, input_param, input_data): if isinstance(fill_value, (int, float)): np.testing.assert_allclose(data, fill_value) else: - print("hole data:", data) - print("hole data:", data) min_value = data.min() max_value = data.max() self.assertGreaterEqual(max_value, min_value) From 886a84c4d81b3ba15e7c23f94033f6b47bb09dc7 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Wed, 25 Aug 2021 20:10:08 +0800 Subject: [PATCH 10/11] [DLMED] support auto computing min and max Signed-off-by: Nic Ma --- monai/transforms/intensity/array.py | 17 ++++++++++------- monai/transforms/intensity/dictionary.py | 17 ++++++++++------- tests/test_rand_coarse_dropout.py | 12 +++++++++--- tests/test_rand_coarse_dropoutd.py | 7 ++++++- 4 files changed, 35 insertions(+), 18 deletions(-) diff --git a/monai/transforms/intensity/array.py b/monai/transforms/intensity/array.py index 6b5f865bd4..25f2af98f9 100644 --- a/monai/transforms/intensity/array.py +++ b/monai/transforms/intensity/array.py @@ -1643,8 +1643,10 @@ class RandCoarseDropout(RandomizableTransform): if some components of the `spatial_size` are non-positive values, the transform will use the corresponding components of input img size. For example, `spatial_size=(32, -1)` will be adapted to `(32, 64)` if the second spatial dimension size of img is `64`. - fill_value: target value to fill the dropout regions, if providing a tuple for the `min` and `max`, - will randomly select value for every pixel / voxel from the range `[min, max)`. + fill_value: target value to fill the dropout regions, if providing a number, will use it as constant + value to fill all the regions. if providing a tuple for the `min` and `max`, will randomly select + value for every pixel / voxel from the range `[min, max)`. if None, will compute the `min` and `max` + value of input image then randomly select value to fill, default to None. max_holes: if not None, define the maximum number to randomly select the expected number of regions. max_spatial_size: if not None, define the maximum spatial size to randomly select size for every region. if some components of the `max_spatial_size` are non-positive values, the transform will use the @@ -1658,7 +1660,7 @@ def __init__( self, holes: int, spatial_size: Union[Sequence[int], int], - fill_value: Union[Tuple[float, float], float] = 0, + fill_value: Optional[Union[Tuple[float, float], float]] = None, max_holes: Optional[int] = None, max_spatial_size: Optional[Union[Sequence[int], int]] = None, prob: float = 0.1, @@ -1689,12 +1691,13 @@ def __call__(self, img: np.ndarray): self.randomize(img.shape[1:]) if self._do_transform: for h in self.hole_coords: - if isinstance(self.fill_value, (tuple, list)): - if len(self.fill_value) != 2: + fill_value = (img.min(), img.max()) if self.fill_value is None else self.fill_value + if isinstance(fill_value, (tuple, list)): + if len(fill_value) != 2: raise ValueError("fill_value should contain 2 numbers if providing the `min` and `max`.") - img[h] = self.R.uniform(self.fill_value[0], self.fill_value[1], size=img[h].shape) + img[h] = self.R.uniform(fill_value[0], fill_value[1], size=img[h].shape) else: - img[h] = self.fill_value + img[h] = fill_value return img diff --git a/monai/transforms/intensity/dictionary.py b/monai/transforms/intensity/dictionary.py index 04970319e7..beb210c645 100644 --- a/monai/transforms/intensity/dictionary.py +++ b/monai/transforms/intensity/dictionary.py @@ -1435,8 +1435,10 @@ class RandCoarseDropoutd(RandomizableTransform, MapTransform): if some components of the `spatial_size` are non-positive values, the transform will use the corresponding components of input img size. For example, `spatial_size=(32, -1)` will be adapted to `(32, 64)` if the second spatial dimension size of img is `64`. - fill_value: target value to fill the dropout regions, if providing a tuple for the `min` and `max`, - will randomly select value for every pixel / voxel from the range `[min, max)`. + fill_value: target value to fill the dropout regions, if providing a number, will use it as constant + value to fill all the regions. if providing a tuple for the `min` and `max`, will randomly select + value for every pixel / voxel from the range `[min, max)`. if None, will compute the `min` and `max` + value of input image then randomly select value to fill, default to None. max_holes: if not None, define the maximum number to randomly select the expected number of regions. max_spatial_size: if not None, define the maximum spatial size to randomly select size for every region. if some components of the `max_spatial_size` are non-positive values, the transform will use the @@ -1452,7 +1454,7 @@ def __init__( keys: KeysCollection, holes: int, spatial_size: Union[Sequence[int], int], - fill_value: Union[Tuple[float, float], float] = 0, + fill_value: Optional[Union[Tuple[float, float], float]] = None, max_holes: Optional[int] = None, max_spatial_size: Optional[Union[Sequence[int], int]] = None, prob: float = 0.1, @@ -1488,12 +1490,13 @@ def __call__(self, data): if self._do_transform: for key in self.key_iterator(d): for h in self.hole_coords: - if isinstance(self.fill_value, (tuple, list)): - if len(self.fill_value) != 2: + fill_value = (d[key].min(), d[key].max()) if self.fill_value is None else self.fill_value + if isinstance(fill_value, (tuple, list)): + if len(fill_value) != 2: raise ValueError("fill_value should contain 2 numbers if providing the `min` and `max`.") - d[key][h] = self.R.uniform(self.fill_value[0], self.fill_value[1], size=d[key][h].shape) + d[key][h] = self.R.uniform(fill_value[0], fill_value[1], size=d[key][h].shape) else: - d[key][h] = self.fill_value + d[key][h] = fill_value return d diff --git a/tests/test_rand_coarse_dropout.py b/tests/test_rand_coarse_dropout.py index d2c90af2bf..18d026e573 100644 --- a/tests/test_rand_coarse_dropout.py +++ b/tests/test_rand_coarse_dropout.py @@ -42,9 +42,14 @@ np.random.randint(0, 2, size=[3, 3, 3, 4]), ] +TEST_CASE_5 = [ + {"holes": 2, "spatial_size": [2, 2, 2], "fill_value": None, "prob": 1.0}, + np.random.randint(0, 2, size=[3, 3, 3, 4]), +] + class TestRandCoarseDropout(unittest.TestCase): - @parameterized.expand([TEST_CASE_0, TEST_CASE_1, TEST_CASE_2, TEST_CASE_3, TEST_CASE_4]) + @parameterized.expand([TEST_CASE_0, TEST_CASE_1, TEST_CASE_2, TEST_CASE_3, TEST_CASE_4, TEST_CASE_5]) def test_value(self, input_param, input_data): dropout = RandCoarseDropout(**input_param) result = dropout(input_data) @@ -61,15 +66,16 @@ def test_value(self, input_param, input_data): for h in dropout.hole_coords: data = result[h] - fill_value = input_param.get("fill_value", 0) + fill_value = input_param.get("fill_value", None) if isinstance(fill_value, (int, float)): np.testing.assert_allclose(data, fill_value) - else: + elif fill_value is not None: min_value = data.min() max_value = data.max() self.assertGreaterEqual(max_value, min_value) self.assertGreaterEqual(min_value, fill_value[0]) self.assertLess(max_value, fill_value[1]) + if max_spatial_size is None: self.assertTupleEqual(data.shape[1:], tuple(spatial_size)) else: diff --git a/tests/test_rand_coarse_dropoutd.py b/tests/test_rand_coarse_dropoutd.py index 4175624b3a..ed1348a999 100644 --- a/tests/test_rand_coarse_dropoutd.py +++ b/tests/test_rand_coarse_dropoutd.py @@ -56,6 +56,10 @@ {"img": np.random.rand(3, 3, 3, 4)}, ] +TEST_CASE_5 = [ + {"keys": "img", "holes": 2, "spatial_size": [2, 2, 2], "fill_value": None, "prob": 1.0}, + {"img": np.random.rand(3, 3, 3, 4)}, +] class TestRandCoarseDropoutd(unittest.TestCase): @parameterized.expand([TEST_CASE_0, TEST_CASE_1, TEST_CASE_2, TEST_CASE_3, TEST_CASE_4]) @@ -78,12 +82,13 @@ def test_value(self, input_param, input_data): fill_value = input_param.get("fill_value", 0) if isinstance(fill_value, (int, float)): np.testing.assert_allclose(data, fill_value) - else: + elif fill_value is not None: min_value = data.min() max_value = data.max() self.assertGreaterEqual(max_value, min_value) self.assertGreaterEqual(min_value, fill_value[0]) self.assertLess(max_value, fill_value[1]) + if max_spatial_size is None: self.assertTupleEqual(data.shape[1:], tuple(spatial_size)) else: From a34a4521e4766aa0767067dcaa878420c7888d8f Mon Sep 17 00:00:00 2001 From: monai-bot Date: Wed, 25 Aug 2021 12:17:52 +0000 Subject: [PATCH 11/11] [MONAI] python code formatting Signed-off-by: monai-bot --- tests/test_rand_coarse_dropoutd.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_rand_coarse_dropoutd.py b/tests/test_rand_coarse_dropoutd.py index ed1348a999..932e65c8cf 100644 --- a/tests/test_rand_coarse_dropoutd.py +++ b/tests/test_rand_coarse_dropoutd.py @@ -61,6 +61,7 @@ {"img": np.random.rand(3, 3, 3, 4)}, ] + class TestRandCoarseDropoutd(unittest.TestCase): @parameterized.expand([TEST_CASE_0, TEST_CASE_1, TEST_CASE_2, TEST_CASE_3, TEST_CASE_4]) def test_value(self, input_param, input_data):