From 3933045b53c1ea7d83cb18d4651cc134074dd1da Mon Sep 17 00:00:00 2001 From: Leo Tam Date: Tue, 9 Feb 2021 00:17:47 +0000 Subject: [PATCH 01/12] DeleteChannel array, dictionary, tests Signed-off-by: Leo Tam --- monai/transforms/utility/array.py | 27 ++++++++++++++++++++++ monai/transforms/utility/dictionary.py | 25 ++++++++++++++++++++ tests/test_delete_channel.py | 31 +++++++++++++++++++++++++ tests/test_delete_channeld.py | 32 ++++++++++++++++++++++++++ 4 files changed, 115 insertions(+) create mode 100644 tests/test_delete_channel.py create mode 100644 tests/test_delete_channeld.py diff --git a/monai/transforms/utility/array.py b/monai/transforms/utility/array.py index c0ae40de59..961d8fb323 100644 --- a/monai/transforms/utility/array.py +++ b/monai/transforms/utility/array.py @@ -31,6 +31,7 @@ "AsChannelLast", "AddChannel", "RepeatChannel", + "DeleteChannel", "SplitChannel", "CastToType", "ToTensor", @@ -159,6 +160,32 @@ def __call__(self, img: np.ndarray) -> np.ndarray: Apply the transform to `img`, assuming `img` is a "channel-first" array. """ return np.repeat(img, self.repeats, 0) + + +class DeleteChannel(Transform): + """ + DeleteChannel data to undo RepeatChannel + The `repeats` count specifies the deletion of the origin data, for example: + ``DeleteChannel(repeats=2)([[1, 2], [1, 2], [3, 4], [3, 4]])`` generates: ``[[1, 2], [3, 4]]`` + + Args: + repeats: the number of repetitions to be deleted for each element. + """ + + def __init__(self, repeats: int) -> None: + if repeats <= 0: + raise AssertionError("repeats count must be greater than 0.") + + self.repeats = repeats + + def __call__(self, img: np.ndarray) -> np.ndarray: + """ + Apply the transform to `img`, assuming `img` is a "channel-first" array. + """ + if np.shape(img)[0]<2: + raise AssertionError("Image must have more than one channel") + + return img[::self.repeats,:] class SplitChannel(Transform): diff --git a/monai/transforms/utility/dictionary.py b/monai/transforms/utility/dictionary.py index f374b82d76..1efe87cc3e 100644 --- a/monai/transforms/utility/dictionary.py +++ b/monai/transforms/utility/dictionary.py @@ -36,6 +36,7 @@ LabelToMask, Lambda, RepeatChannel, + DeleteChannel, SimulateDelay, SplitChannel, SqueezeDim, @@ -52,6 +53,7 @@ "AsChannelLastd", "AddChanneld", "RepeatChanneld", + "DeleteChanneld", "SplitChanneld", "CastToTyped", "ToTensord", @@ -226,6 +228,28 @@ def __call__(self, data: Mapping[Hashable, np.ndarray]) -> Dict[Hashable, np.nda return d +class DeleteChanneld(MapTransform): + """ + Dictionary-based wrapper of :py:class:`monai.transforms.DeleteChannel`. + """ + + def __init__(self, keys: KeysCollection, repeats: int) -> None: + """ + Args: + keys: keys of the corresponding items to be transformed. + See also: :py:class:`monai.transforms.compose.MapTransform` + repeats: the number of repetitions for each element. + """ + super().__init__(keys) + self.repeater = DeleteChannel(repeats) + + def __call__(self, data: Mapping[Hashable, np.ndarray]) -> Dict[Hashable, np.ndarray]: + d = dict(data) + for key in self.keys: + d[key] = self.repeater(d[key]) + return d + + class SplitChanneld(MapTransform): """ Dictionary-based wrapper of :py:class:`monai.transforms.SplitChannel`. @@ -836,6 +860,7 @@ def __call__(self, data: Mapping[Hashable, torch.Tensor]) -> Dict[Hashable, torc AsChannelFirstD = AsChannelFirstDict = AsChannelFirstd AsChannelLastD = AsChannelLastDict = AsChannelLastd AddChannelD = AddChannelDict = AddChanneld +DeleteChannelD = DeleteChannelDict = DeleteChanneld RepeatChannelD = RepeatChannelDict = RepeatChanneld SplitChannelD = SplitChannelDict = SplitChanneld CastToTypeD = CastToTypeDict = CastToTyped diff --git a/tests/test_delete_channel.py b/tests/test_delete_channel.py new file mode 100644 index 0000000000..3777420886 --- /dev/null +++ b/tests/test_delete_channel.py @@ -0,0 +1,31 @@ +# Copyright 2020 - 2021 MONAI Consortium +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest + +import numpy as np +from parameterized import parameterized + +from monai.transforms import DeleteChannel + +# TEST_CASE_1 = [{"repeats": 3}, np.array([[[0, 1], [1, 2]]]), (3, 2, 2)] + +TEST_CASE_1 = [{"repeats": 2}, np.array([[1, 2], [1, 2], [3, 4], [3, 4]]), (2, 2)] + +class TestRepeatChannel(unittest.TestCase): + @parameterized.expand([TEST_CASE_1]) + def test_shape(self, input_param, input_data, expected_shape): + result = DeleteChannel(**input_param)(input_data) + self.assertEqual(result.shape, expected_shape) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_delete_channeld.py b/tests/test_delete_channeld.py new file mode 100644 index 0000000000..46da3ba87f --- /dev/null +++ b/tests/test_delete_channeld.py @@ -0,0 +1,32 @@ +# Copyright 2020 - 2021 MONAI Consortium +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest + +import numpy as np +from parameterized import parameterized + +from monai.transforms import DeleteChanneld + +TEST_CASE_1 = [ + {"keys": ["img"], "repeats": 2}, + {"img": np.array([[1, 2], [1, 2], [3, 4], [3, 4]]), "seg": np.array([[1, 2], [1, 2], [3, 4], [3, 4]])}, + (2, 2), +] + +class TestAddChanneld(unittest.TestCase): + @parameterized.expand([TEST_CASE_1]) + def test_shape(self, input_param, input_data, expected_shape): + result = DeleteChanneld(**input_param)(input_data) + self.assertEqual(result["img"].shape, expected_shape) + +if __name__ == "__main__": + unittest.main() From c661c9cbcb716f3684af81c2d4631fa401c8f6b6 Mon Sep 17 00:00:00 2001 From: Leo Tam Date: Tue, 9 Feb 2021 00:28:42 +0000 Subject: [PATCH 02/12] formatting Signed-off-by: Leo Tam --- monai/transforms/utility/array.py | 16 ++++++++-------- monai/transforms/utility/dictionary.py | 8 ++++---- tests/test_delete_channel.py | 1 + tests/test_delete_channeld.py | 2 ++ 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/monai/transforms/utility/array.py b/monai/transforms/utility/array.py index 961d8fb323..50643f0fea 100644 --- a/monai/transforms/utility/array.py +++ b/monai/transforms/utility/array.py @@ -31,7 +31,7 @@ "AsChannelLast", "AddChannel", "RepeatChannel", - "DeleteChannel", + "DeleteChannel", "SplitChannel", "CastToType", "ToTensor", @@ -160,14 +160,14 @@ def __call__(self, img: np.ndarray) -> np.ndarray: Apply the transform to `img`, assuming `img` is a "channel-first" array. """ return np.repeat(img, self.repeats, 0) - - + + class DeleteChannel(Transform): """ DeleteChannel data to undo RepeatChannel The `repeats` count specifies the deletion of the origin data, for example: ``DeleteChannel(repeats=2)([[1, 2], [1, 2], [3, 4], [3, 4]])`` generates: ``[[1, 2], [3, 4]]`` - + Args: repeats: the number of repetitions to be deleted for each element. """ @@ -175,17 +175,17 @@ class DeleteChannel(Transform): def __init__(self, repeats: int) -> None: if repeats <= 0: raise AssertionError("repeats count must be greater than 0.") - + self.repeats = repeats def __call__(self, img: np.ndarray) -> np.ndarray: """ Apply the transform to `img`, assuming `img` is a "channel-first" array. """ - if np.shape(img)[0]<2: + if np.shape(img)[0] < 2: raise AssertionError("Image must have more than one channel") - - return img[::self.repeats,:] + + return img[:: self.repeats, :] class SplitChannel(Transform): diff --git a/monai/transforms/utility/dictionary.py b/monai/transforms/utility/dictionary.py index 1efe87cc3e..fa4770b0fe 100644 --- a/monai/transforms/utility/dictionary.py +++ b/monai/transforms/utility/dictionary.py @@ -31,12 +31,12 @@ CastToType, ConvertToMultiChannelBasedOnBratsClasses, DataStats, + DeleteChannel, FgBgToIndices, Identity, LabelToMask, Lambda, RepeatChannel, - DeleteChannel, SimulateDelay, SplitChannel, SqueezeDim, @@ -53,7 +53,7 @@ "AsChannelLastd", "AddChanneld", "RepeatChanneld", - "DeleteChanneld", + "DeleteChanneld", "SplitChanneld", "CastToTyped", "ToTensord", @@ -249,7 +249,7 @@ def __call__(self, data: Mapping[Hashable, np.ndarray]) -> Dict[Hashable, np.nda d[key] = self.repeater(d[key]) return d - + class SplitChanneld(MapTransform): """ Dictionary-based wrapper of :py:class:`monai.transforms.SplitChannel`. @@ -860,7 +860,7 @@ def __call__(self, data: Mapping[Hashable, torch.Tensor]) -> Dict[Hashable, torc AsChannelFirstD = AsChannelFirstDict = AsChannelFirstd AsChannelLastD = AsChannelLastDict = AsChannelLastd AddChannelD = AddChannelDict = AddChanneld -DeleteChannelD = DeleteChannelDict = DeleteChanneld +DeleteChannelD = DeleteChannelDict = DeleteChanneld RepeatChannelD = RepeatChannelDict = RepeatChanneld SplitChannelD = SplitChannelDict = SplitChanneld CastToTypeD = CastToTypeDict = CastToTyped diff --git a/tests/test_delete_channel.py b/tests/test_delete_channel.py index 3777420886..c232ef74df 100644 --- a/tests/test_delete_channel.py +++ b/tests/test_delete_channel.py @@ -20,6 +20,7 @@ TEST_CASE_1 = [{"repeats": 2}, np.array([[1, 2], [1, 2], [3, 4], [3, 4]]), (2, 2)] + class TestRepeatChannel(unittest.TestCase): @parameterized.expand([TEST_CASE_1]) def test_shape(self, input_param, input_data, expected_shape): diff --git a/tests/test_delete_channeld.py b/tests/test_delete_channeld.py index 46da3ba87f..114cea038d 100644 --- a/tests/test_delete_channeld.py +++ b/tests/test_delete_channeld.py @@ -22,11 +22,13 @@ (2, 2), ] + class TestAddChanneld(unittest.TestCase): @parameterized.expand([TEST_CASE_1]) def test_shape(self, input_param, input_data, expected_shape): result = DeleteChanneld(**input_param)(input_data) self.assertEqual(result["img"].shape, expected_shape) + if __name__ == "__main__": unittest.main() From e1c1bd79f348bc88ddf7466da6f4e62bffb32778 Mon Sep 17 00:00:00 2001 From: Leo Tam Date: Tue, 9 Feb 2021 00:51:26 +0000 Subject: [PATCH 03/12] DeleteChannel array, dictionary, tests Signed-off-by: Leo Tam --- monai/transforms/utility/array.py | 27 ++++++++++++++++++++ monai/transforms/utility/dictionary.py | 25 +++++++++++++++++++ tests/test_delete_channel.py | 32 ++++++++++++++++++++++++ tests/test_delete_channeld.py | 34 ++++++++++++++++++++++++++ 4 files changed, 118 insertions(+) create mode 100644 tests/test_delete_channel.py create mode 100644 tests/test_delete_channeld.py diff --git a/monai/transforms/utility/array.py b/monai/transforms/utility/array.py index c0ae40de59..50643f0fea 100644 --- a/monai/transforms/utility/array.py +++ b/monai/transforms/utility/array.py @@ -31,6 +31,7 @@ "AsChannelLast", "AddChannel", "RepeatChannel", + "DeleteChannel", "SplitChannel", "CastToType", "ToTensor", @@ -161,6 +162,32 @@ def __call__(self, img: np.ndarray) -> np.ndarray: return np.repeat(img, self.repeats, 0) +class DeleteChannel(Transform): + """ + DeleteChannel data to undo RepeatChannel + The `repeats` count specifies the deletion of the origin data, for example: + ``DeleteChannel(repeats=2)([[1, 2], [1, 2], [3, 4], [3, 4]])`` generates: ``[[1, 2], [3, 4]]`` + + Args: + repeats: the number of repetitions to be deleted for each element. + """ + + def __init__(self, repeats: int) -> None: + if repeats <= 0: + raise AssertionError("repeats count must be greater than 0.") + + self.repeats = repeats + + def __call__(self, img: np.ndarray) -> np.ndarray: + """ + Apply the transform to `img`, assuming `img` is a "channel-first" array. + """ + if np.shape(img)[0] < 2: + raise AssertionError("Image must have more than one channel") + + return img[:: self.repeats, :] + + class SplitChannel(Transform): """ Split Numpy array or PyTorch Tensor data according to the channel dim. diff --git a/monai/transforms/utility/dictionary.py b/monai/transforms/utility/dictionary.py index f374b82d76..fa4770b0fe 100644 --- a/monai/transforms/utility/dictionary.py +++ b/monai/transforms/utility/dictionary.py @@ -31,6 +31,7 @@ CastToType, ConvertToMultiChannelBasedOnBratsClasses, DataStats, + DeleteChannel, FgBgToIndices, Identity, LabelToMask, @@ -52,6 +53,7 @@ "AsChannelLastd", "AddChanneld", "RepeatChanneld", + "DeleteChanneld", "SplitChanneld", "CastToTyped", "ToTensord", @@ -226,6 +228,28 @@ def __call__(self, data: Mapping[Hashable, np.ndarray]) -> Dict[Hashable, np.nda return d +class DeleteChanneld(MapTransform): + """ + Dictionary-based wrapper of :py:class:`monai.transforms.DeleteChannel`. + """ + + def __init__(self, keys: KeysCollection, repeats: int) -> None: + """ + Args: + keys: keys of the corresponding items to be transformed. + See also: :py:class:`monai.transforms.compose.MapTransform` + repeats: the number of repetitions for each element. + """ + super().__init__(keys) + self.repeater = DeleteChannel(repeats) + + def __call__(self, data: Mapping[Hashable, np.ndarray]) -> Dict[Hashable, np.ndarray]: + d = dict(data) + for key in self.keys: + d[key] = self.repeater(d[key]) + return d + + class SplitChanneld(MapTransform): """ Dictionary-based wrapper of :py:class:`monai.transforms.SplitChannel`. @@ -836,6 +860,7 @@ def __call__(self, data: Mapping[Hashable, torch.Tensor]) -> Dict[Hashable, torc AsChannelFirstD = AsChannelFirstDict = AsChannelFirstd AsChannelLastD = AsChannelLastDict = AsChannelLastd AddChannelD = AddChannelDict = AddChanneld +DeleteChannelD = DeleteChannelDict = DeleteChanneld RepeatChannelD = RepeatChannelDict = RepeatChanneld SplitChannelD = SplitChannelDict = SplitChanneld CastToTypeD = CastToTypeDict = CastToTyped diff --git a/tests/test_delete_channel.py b/tests/test_delete_channel.py new file mode 100644 index 0000000000..c232ef74df --- /dev/null +++ b/tests/test_delete_channel.py @@ -0,0 +1,32 @@ +# Copyright 2020 - 2021 MONAI Consortium +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest + +import numpy as np +from parameterized import parameterized + +from monai.transforms import DeleteChannel + +# TEST_CASE_1 = [{"repeats": 3}, np.array([[[0, 1], [1, 2]]]), (3, 2, 2)] + +TEST_CASE_1 = [{"repeats": 2}, np.array([[1, 2], [1, 2], [3, 4], [3, 4]]), (2, 2)] + + +class TestRepeatChannel(unittest.TestCase): + @parameterized.expand([TEST_CASE_1]) + def test_shape(self, input_param, input_data, expected_shape): + result = DeleteChannel(**input_param)(input_data) + self.assertEqual(result.shape, expected_shape) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_delete_channeld.py b/tests/test_delete_channeld.py new file mode 100644 index 0000000000..114cea038d --- /dev/null +++ b/tests/test_delete_channeld.py @@ -0,0 +1,34 @@ +# Copyright 2020 - 2021 MONAI Consortium +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest + +import numpy as np +from parameterized import parameterized + +from monai.transforms import DeleteChanneld + +TEST_CASE_1 = [ + {"keys": ["img"], "repeats": 2}, + {"img": np.array([[1, 2], [1, 2], [3, 4], [3, 4]]), "seg": np.array([[1, 2], [1, 2], [3, 4], [3, 4]])}, + (2, 2), +] + + +class TestAddChanneld(unittest.TestCase): + @parameterized.expand([TEST_CASE_1]) + def test_shape(self, input_param, input_data, expected_shape): + result = DeleteChanneld(**input_param)(input_data) + self.assertEqual(result["img"].shape, expected_shape) + + +if __name__ == "__main__": + unittest.main() From b28489438331eb532427f27bb3488afe7a9a0767 Mon Sep 17 00:00:00 2001 From: Leo Tam Date: Tue, 9 Feb 2021 17:23:46 +0000 Subject: [PATCH 04/12] Register in transform init Signed-off-by: Leo Tam --- monai/transforms/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/monai/transforms/__init__.py b/monai/transforms/__init__.py index ebd21a1c45..29bbcc6cb5 100644 --- a/monai/transforms/__init__.py +++ b/monai/transforms/__init__.py @@ -242,6 +242,7 @@ CastToType, ConvertToMultiChannelBasedOnBratsClasses, DataStats, + DeleteChannel, FgBgToIndices, Identity, LabelToMask, @@ -283,6 +284,8 @@ DataStatsd, DataStatsD, DataStatsDict, + DeleteChanneld, + DeleteChannelD, DeleteItemsd, DeleteItemsD, DeleteItemsDict, From 986752f734c2ecb9b5d6bd8ae6f20241984e339f Mon Sep 17 00:00:00 2001 From: Leo Tam Date: Tue, 9 Feb 2021 17:29:14 +0000 Subject: [PATCH 05/12] clean comment Signed-off-by: Leo Tam --- tests/test_delete_channel.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_delete_channel.py b/tests/test_delete_channel.py index c232ef74df..87eae6c992 100644 --- a/tests/test_delete_channel.py +++ b/tests/test_delete_channel.py @@ -16,8 +16,6 @@ from monai.transforms import DeleteChannel -# TEST_CASE_1 = [{"repeats": 3}, np.array([[[0, 1], [1, 2]]]), (3, 2, 2)] - TEST_CASE_1 = [{"repeats": 2}, np.array([[1, 2], [1, 2], [3, 4], [3, 4]]), (2, 2)] From 38fe64a13a6676547f6eb06802274dd9e0224afc Mon Sep 17 00:00:00 2001 From: Leo Tam Date: Tue, 9 Feb 2021 18:03:11 +0000 Subject: [PATCH 06/12] Dict init Signed-off-by: Leo Tam --- monai/transforms/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/monai/transforms/__init__.py b/monai/transforms/__init__.py index cd4287f62f..060dc664de 100644 --- a/monai/transforms/__init__.py +++ b/monai/transforms/__init__.py @@ -286,6 +286,7 @@ DataStatsDict, DeleteChanneld, DeleteChannelD, + DeleteChannelDict, DeleteItemsd, DeleteItemsD, DeleteItemsDict, From cfb2693807467a0f4400371f03862d5e055306ca Mon Sep 17 00:00:00 2001 From: Leo Tam Date: Wed, 10 Feb 2021 18:51:52 +0000 Subject: [PATCH 07/12] Register D and Dict Signed-off-by: Leo Tam --- monai/transforms/utility/dictionary.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/monai/transforms/utility/dictionary.py b/monai/transforms/utility/dictionary.py index fa4770b0fe..4742fa40b5 100644 --- a/monai/transforms/utility/dictionary.py +++ b/monai/transforms/utility/dictionary.py @@ -84,6 +84,8 @@ "RandLambdaDict", "RepeatChannelD", "RepeatChannelDict", + "DeleteChannelD", + "DeleteChannelDict", "SplitChannelD", "SplitChannelDict", "CastToTypeD", From 9a7793f874d052f8223fd208190bbd7670c2420a Mon Sep 17 00:00:00 2001 From: Leo Tam Date: Wed, 10 Feb 2021 23:10:20 +0000 Subject: [PATCH 08/12] Style fix Signed-off-by: Leo Tam --- monai/transforms/utility/dictionary.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monai/transforms/utility/dictionary.py b/monai/transforms/utility/dictionary.py index 4742fa40b5..be5a01b0f4 100644 --- a/monai/transforms/utility/dictionary.py +++ b/monai/transforms/utility/dictionary.py @@ -85,7 +85,7 @@ "RepeatChannelD", "RepeatChannelDict", "DeleteChannelD", - "DeleteChannelDict", + "DeleteChannelDict", "SplitChannelD", "SplitChannelDict", "CastToTypeD", From 15293043191b26b4fabf2b350fa0ed55d2adb1c1 Mon Sep 17 00:00:00 2001 From: Leo Tam Date: Sat, 13 Feb 2021 03:48:29 +0000 Subject: [PATCH 09/12] Safety cast Signed-off-by: Leo Tam --- monai/transforms/utility/array.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monai/transforms/utility/array.py b/monai/transforms/utility/array.py index 50643f0fea..1a4aac7d65 100644 --- a/monai/transforms/utility/array.py +++ b/monai/transforms/utility/array.py @@ -185,7 +185,7 @@ def __call__(self, img: np.ndarray) -> np.ndarray: if np.shape(img)[0] < 2: raise AssertionError("Image must have more than one channel") - return img[:: self.repeats, :] + return np.array(img[:: self.repeats, :]) class SplitChannel(Transform): From f2e994412335f2b1f0bbc23b311f261fd99e57f5 Mon Sep 17 00:00:00 2001 From: Leo Tam Date: Thu, 25 Feb 2021 18:52:42 +0000 Subject: [PATCH 10/12] Changinging names from DeleteChannel to RemoveRepeatedChannel Signed-off-by: Leo Tam --- monai/transforms/__init__.py | 8 ++++---- monai/transforms/utility/array.py | 8 ++++---- monai/transforms/utility/dictionary.py | 16 ++++++++-------- ...hannel.py => test_remove_repeated_channel.py} | 4 ++-- ...nneld.py => test_remove_repeated_channeld.py} | 4 ++-- 5 files changed, 20 insertions(+), 20 deletions(-) rename tests/{test_delete_channel.py => test_remove_repeated_channel.py} (89%) rename tests/{test_delete_channeld.py => test_remove_repeated_channeld.py} (90%) diff --git a/monai/transforms/__init__.py b/monai/transforms/__init__.py index df8a693b27..d9474df45e 100644 --- a/monai/transforms/__init__.py +++ b/monai/transforms/__init__.py @@ -246,7 +246,7 @@ CastToType, ConvertToMultiChannelBasedOnBratsClasses, DataStats, - DeleteChannel, + RemoveRepeatedChannel, FgBgToIndices, Identity, LabelToMask, @@ -288,9 +288,9 @@ DataStatsd, DataStatsD, DataStatsDict, - DeleteChanneld, - DeleteChannelD, - DeleteChannelDict, + RemoveRepeatedChanneld, + RemoveRepeatedChannelD, + RemoveRepeatedChannelDict, DeleteItemsd, DeleteItemsD, DeleteItemsDict, diff --git a/monai/transforms/utility/array.py b/monai/transforms/utility/array.py index 885abbba16..fb9ae3c089 100644 --- a/monai/transforms/utility/array.py +++ b/monai/transforms/utility/array.py @@ -31,7 +31,7 @@ "AsChannelLast", "AddChannel", "RepeatChannel", - "DeleteChannel", + "RemoveRepeatedChannel", "SplitChannel", "CastToType", "ToTensor", @@ -162,11 +162,11 @@ def __call__(self, img: np.ndarray) -> np.ndarray: return np.repeat(img, self.repeats, 0) -class DeleteChannel(Transform): +class RemoveRepeatedChannel(Transform): """ - DeleteChannel data to undo RepeatChannel + RemoveRepeatedChannel data to undo RepeatChannel The `repeats` count specifies the deletion of the origin data, for example: - ``DeleteChannel(repeats=2)([[1, 2], [1, 2], [3, 4], [3, 4]])`` generates: ``[[1, 2], [3, 4]]`` + ``RemoveRepeatedChannel(repeats=2)([[1, 2], [1, 2], [3, 4], [3, 4]])`` generates: ``[[1, 2], [3, 4]]`` Args: repeats: the number of repetitions to be deleted for each element. diff --git a/monai/transforms/utility/dictionary.py b/monai/transforms/utility/dictionary.py index 62edc7024b..b5050df504 100644 --- a/monai/transforms/utility/dictionary.py +++ b/monai/transforms/utility/dictionary.py @@ -31,7 +31,7 @@ CastToType, ConvertToMultiChannelBasedOnBratsClasses, DataStats, - DeleteChannel, + RemoveRepeatedChannel, FgBgToIndices, Identity, LabelToMask, @@ -53,7 +53,7 @@ "AsChannelLastd", "AddChanneld", "RepeatChanneld", - "DeleteChanneld", + "RemoveRepeatedChanneld", "SplitChanneld", "CastToTyped", "ToTensord", @@ -84,8 +84,8 @@ "RandLambdaDict", "RepeatChannelD", "RepeatChannelDict", - "DeleteChannelD", - "DeleteChannelDict", + "RemoveRepeatedChannelD", + "RemoveRepeatedChannelDict", "SplitChannelD", "SplitChannelDict", "CastToTypeD", @@ -230,9 +230,9 @@ def __call__(self, data: Mapping[Hashable, np.ndarray]) -> Dict[Hashable, np.nda return d -class DeleteChanneld(MapTransform): +class RemoveRepeatedChanneld(MapTransform): """ - Dictionary-based wrapper of :py:class:`monai.transforms.DeleteChannel`. + Dictionary-based wrapper of :py:class:`monai.transforms.RemoveRepeatedChannel`. """ def __init__(self, keys: KeysCollection, repeats: int) -> None: @@ -243,7 +243,7 @@ def __init__(self, keys: KeysCollection, repeats: int) -> None: repeats: the number of repetitions for each element. """ super().__init__(keys) - self.repeater = DeleteChannel(repeats) + self.repeater = RemoveRepeatedChannel(repeats) def __call__(self, data: Mapping[Hashable, np.ndarray]) -> Dict[Hashable, np.ndarray]: d = dict(data) @@ -862,7 +862,7 @@ def __call__(self, data: Mapping[Hashable, torch.Tensor]) -> Dict[Hashable, torc AsChannelFirstD = AsChannelFirstDict = AsChannelFirstd AsChannelLastD = AsChannelLastDict = AsChannelLastd AddChannelD = AddChannelDict = AddChanneld -DeleteChannelD = DeleteChannelDict = DeleteChanneld +RemoveRepeatedChannelD = RemoveRepeatedChannelDict = RemoveRepeatedChanneld RepeatChannelD = RepeatChannelDict = RepeatChanneld SplitChannelD = SplitChannelDict = SplitChanneld CastToTypeD = CastToTypeDict = CastToTyped diff --git a/tests/test_delete_channel.py b/tests/test_remove_repeated_channel.py similarity index 89% rename from tests/test_delete_channel.py rename to tests/test_remove_repeated_channel.py index 87eae6c992..a361dad9ef 100644 --- a/tests/test_delete_channel.py +++ b/tests/test_remove_repeated_channel.py @@ -19,10 +19,10 @@ TEST_CASE_1 = [{"repeats": 2}, np.array([[1, 2], [1, 2], [3, 4], [3, 4]]), (2, 2)] -class TestRepeatChannel(unittest.TestCase): +class TestRemoveRepeatedChannel(unittest.TestCase): @parameterized.expand([TEST_CASE_1]) def test_shape(self, input_param, input_data, expected_shape): - result = DeleteChannel(**input_param)(input_data) + result = RemoveRepeatedChannel(**input_param)(input_data) self.assertEqual(result.shape, expected_shape) diff --git a/tests/test_delete_channeld.py b/tests/test_remove_repeated_channeld.py similarity index 90% rename from tests/test_delete_channeld.py rename to tests/test_remove_repeated_channeld.py index 114cea038d..1183cf67cc 100644 --- a/tests/test_delete_channeld.py +++ b/tests/test_remove_repeated_channeld.py @@ -23,10 +23,10 @@ ] -class TestAddChanneld(unittest.TestCase): +class TestRemoveRepeatedChanneld(unittest.TestCase): @parameterized.expand([TEST_CASE_1]) def test_shape(self, input_param, input_data, expected_shape): - result = DeleteChanneld(**input_param)(input_data) + result = RemoveRepeatedChanneld(**input_param)(input_data) self.assertEqual(result["img"].shape, expected_shape) From e038cc0cf8bf6b121d94fc2cef2b0bc293c4d3a0 Mon Sep 17 00:00:00 2001 From: Leo Tam Date: Thu, 25 Feb 2021 19:00:21 +0000 Subject: [PATCH 11/12] Lint fixes Signed-off-by: Leo Tam --- monai/transforms/__init__.py | 8 ++++---- monai/transforms/utility/dictionary.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/monai/transforms/__init__.py b/monai/transforms/__init__.py index d9474df45e..3499afcf95 100644 --- a/monai/transforms/__init__.py +++ b/monai/transforms/__init__.py @@ -246,11 +246,11 @@ CastToType, ConvertToMultiChannelBasedOnBratsClasses, DataStats, - RemoveRepeatedChannel, FgBgToIndices, Identity, LabelToMask, Lambda, + RemoveRepeatedChannel, RepeatChannel, SimulateDelay, SplitChannel, @@ -288,9 +288,6 @@ DataStatsd, DataStatsD, DataStatsDict, - RemoveRepeatedChanneld, - RemoveRepeatedChannelD, - RemoveRepeatedChannelDict, DeleteItemsd, DeleteItemsD, DeleteItemsDict, @@ -309,6 +306,9 @@ RandLambdad, RandLambdaD, RandLambdaDict, + RemoveRepeatedChanneld, + RemoveRepeatedChannelD, + RemoveRepeatedChannelDict, RepeatChanneld, RepeatChannelD, RepeatChannelDict, diff --git a/monai/transforms/utility/dictionary.py b/monai/transforms/utility/dictionary.py index b5050df504..83426734eb 100644 --- a/monai/transforms/utility/dictionary.py +++ b/monai/transforms/utility/dictionary.py @@ -31,11 +31,11 @@ CastToType, ConvertToMultiChannelBasedOnBratsClasses, DataStats, - RemoveRepeatedChannel, FgBgToIndices, Identity, LabelToMask, Lambda, + RemoveRepeatedChannel, RepeatChannel, SimulateDelay, SplitChannel, From 6c8379cb857c6f8590d0c475dd3ad0d30f8518b3 Mon Sep 17 00:00:00 2001 From: Leo Tam Date: Thu, 25 Feb 2021 19:11:30 +0000 Subject: [PATCH 12/12] Test import fix, autofix again Signed-off-by: Leo Tam --- tests/test_remove_repeated_channel.py | 2 +- tests/test_remove_repeated_channeld.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_remove_repeated_channel.py b/tests/test_remove_repeated_channel.py index a361dad9ef..070e0e2b8d 100644 --- a/tests/test_remove_repeated_channel.py +++ b/tests/test_remove_repeated_channel.py @@ -14,7 +14,7 @@ import numpy as np from parameterized import parameterized -from monai.transforms import DeleteChannel +from monai.transforms import RemoveRepeatedChannel TEST_CASE_1 = [{"repeats": 2}, np.array([[1, 2], [1, 2], [3, 4], [3, 4]]), (2, 2)] diff --git a/tests/test_remove_repeated_channeld.py b/tests/test_remove_repeated_channeld.py index 1183cf67cc..46c68bbdc2 100644 --- a/tests/test_remove_repeated_channeld.py +++ b/tests/test_remove_repeated_channeld.py @@ -14,7 +14,7 @@ import numpy as np from parameterized import parameterized -from monai.transforms import DeleteChanneld +from monai.transforms import RemoveRepeatedChanneld TEST_CASE_1 = [ {"keys": ["img"], "repeats": 2},