From 410f0e0d9ce47e2b34894d2bcc6b7a8de5671be3 Mon Sep 17 00:00:00 2001 From: Wenqi Li Date: Sun, 25 Apr 2021 13:11:06 +0100 Subject: [PATCH 01/12] enhance persistent temp Signed-off-by: Wenqi Li --- monai/data/dataset.py | 12 ++++++--- tests/test_persistentdataset.py | 44 +++++++++++++++++++++++++++------ 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/monai/data/dataset.py b/monai/data/dataset.py index a09050e5bc..2ee410c4d5 100644 --- a/monai/data/dataset.py +++ b/monai/data/dataset.py @@ -14,6 +14,7 @@ import math import pickle import sys +import tempfile import threading import time import warnings @@ -240,12 +241,15 @@ def _cachecheck(self, item_transformed): _item_transformed = self._pre_transform(deepcopy(item_transformed)) # keep the original hashed if hashfile is not None: - # NOTE: Writing to ".temp_write_cache" and then using a nearly atomic rename operation + # NOTE: Writing to a temporary directory and then using a nearly atomic rename operation # to make the cache more robust to manual killing of parent process # which may leave partially written cache files in an incomplete state - temp_hash_file = hashfile.with_suffix(".temp_write_cache") - torch.save(_item_transformed, temp_hash_file) - temp_hash_file.rename(hashfile) + with tempfile.TemporaryDirectory(dir=self.cache_dir) as tmpdirname: + temp_hash_file = Path(tmpdirname) / hashfile.name + torch.save(_item_transformed, temp_hash_file) + if temp_hash_file.is_file() and not hashfile.is_file(): + # On Unix, if target exists and is a file, it will be replaced silently if the user has permission. + temp_hash_file.rename(hashfile) return _item_transformed def _transform(self, index: int): diff --git a/tests/test_persistentdataset.py b/tests/test_persistentdataset.py index 5d94064cf4..3bd52d0caa 100644 --- a/tests/test_persistentdataset.py +++ b/tests/test_persistentdataset.py @@ -10,15 +10,18 @@ # limitations under the License. import os +import shutil import tempfile import unittest import nibabel as nib import numpy as np +import torch.distributed as dist from parameterized import parameterized from monai.data import PersistentDataset, json_hashing from monai.transforms import Compose, LoadImaged, SimulateDelayd, Transform +from tests.utils import DistCall, DistTestCase TEST_CASE_1 = [ Compose( @@ -41,19 +44,20 @@ TEST_CASE_3 = [None, (128, 128, 128)] +class _InplaceXform(Transform): + def __call__(self, data): + if data: + data[0] = data[0] + np.pi + else: + data.append(1) + return data + + class TestDataset(unittest.TestCase): def test_cache(self): """testing no inplace change to the hashed item""" items = [[list(range(i))] for i in range(5)] - class _InplaceXform(Transform): - def __call__(self, data): - if data: - data[0] = data[0] + np.pi - else: - data.append(1) - return data - with tempfile.TemporaryDirectory() as tempdir: ds = PersistentDataset(items, transform=_InplaceXform(), cache_dir=tempdir) self.assertEqual(items, [[[]], [[0]], [[0, 1]], [[0, 1, 2]], [[0, 1, 2, 3]]]) @@ -123,5 +127,29 @@ def test_shape(self, transform, expected_shape): self.assertTupleEqual(d["image"].shape, expected_shape) +class TestDistDataset(DistTestCase): + def setUp(self): + self.tempdir = tempfile.mkdtemp() + + def tearDown(self): + shutil.rmtree(self.tempdir) + + @DistCall(nnodes=1, nproc_per_node=2) + def test_mp_dataset(self): + print("persistent", dist.get_rank()) + items = [[list(range(i))] for i in range(5)] + ds = PersistentDataset(items, transform=_InplaceXform(), cache_dir=self.tempdir) + self.assertEqual(items, [[[]], [[0]], [[0, 1]], [[0, 1, 2]], [[0, 1, 2, 3]]]) + ds1 = PersistentDataset(items, transform=_InplaceXform(), cache_dir=self.tempdir) + self.assertEqual(list(ds1), list(ds)) + self.assertEqual(items, [[[]], [[0]], [[0, 1]], [[0, 1, 2]], [[0, 1, 2, 3]]]) + + ds = PersistentDataset(items, transform=_InplaceXform(), cache_dir=self.tempdir, hash_func=json_hashing) + self.assertEqual(items, [[[]], [[0]], [[0, 1]], [[0, 1, 2]], [[0, 1, 2, 3]]]) + ds1 = PersistentDataset(items, transform=_InplaceXform(), cache_dir=self.tempdir, hash_func=json_hashing) + self.assertEqual(list(ds1), list(ds)) + self.assertEqual(items, [[[]], [[0]], [[0, 1]], [[0, 1, 2]], [[0, 1, 2, 3]]]) + + if __name__ == "__main__": unittest.main() From d5ecf97dd1ba921949106df95e8020cd9c5fadfa Mon Sep 17 00:00:00 2001 From: Wenqi Li Date: Sun, 25 Apr 2021 14:42:02 +0100 Subject: [PATCH 02/12] fixes windows file rename issue Signed-off-by: Wenqi Li --- monai/data/dataset.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/monai/data/dataset.py b/monai/data/dataset.py index 2ee410c4d5..85fda46cb8 100644 --- a/monai/data/dataset.py +++ b/monai/data/dataset.py @@ -244,12 +244,15 @@ def _cachecheck(self, item_transformed): # NOTE: Writing to a temporary directory and then using a nearly atomic rename operation # to make the cache more robust to manual killing of parent process # which may leave partially written cache files in an incomplete state - with tempfile.TemporaryDirectory(dir=self.cache_dir) as tmpdirname: + with tempfile.TemporaryDirectory() as tmpdirname: temp_hash_file = Path(tmpdirname) / hashfile.name torch.save(_item_transformed, temp_hash_file) if temp_hash_file.is_file() and not hashfile.is_file(): # On Unix, if target exists and is a file, it will be replaced silently if the user has permission. - temp_hash_file.rename(hashfile) + try: + temp_hash_file.rename(hashfile) + except FileExistsError: + pass return _item_transformed def _transform(self, index: int): From 176bed0f721756a54dbd2e9955815f1da81c47df Mon Sep 17 00:00:00 2001 From: Wenqi Li Date: Sun, 25 Apr 2021 16:34:29 +0100 Subject: [PATCH 03/12] enhance multiprocess LMDB Signed-off-by: Wenqi Li --- monai/data/dataset.py | 4 +++ tests/test_lmdbdataset.py | 59 +++++++++++++++++++++++++++++++++------ 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/monai/data/dataset.py b/monai/data/dataset.py index 85fda46cb8..bfb3d8b86d 100644 --- a/monai/data/dataset.py +++ b/monai/data/dataset.py @@ -415,6 +415,10 @@ def _fill_cache_start_reader(self): new_size = size * 2 warnings.warn(f"Resizing the cache database from {int(size) >> 20}MB to {int(new_size) >> 20}MB.") env.set_mapsize(new_size) + except lmdb.MapResizedError: + # the mapsize is increased by another process + # set_mapsize with a size of 0 to adopt the new size, + env.set_mapsize(0) if not done: # still has the map full error size = env.info()["map_size"] env.close() diff --git a/tests/test_lmdbdataset.py b/tests/test_lmdbdataset.py index 90a4b4a0b4..96a23327fb 100644 --- a/tests/test_lmdbdataset.py +++ b/tests/test_lmdbdataset.py @@ -10,6 +10,7 @@ # limitations under the License. import os +import shutil import tempfile import unittest @@ -19,7 +20,7 @@ from monai.data import LMDBDataset, json_hashing from monai.transforms import Compose, LoadImaged, SimulateDelayd, Transform -from tests.utils import skip_if_windows +from tests.utils import DistCall, DistTestCase, skip_if_windows TEST_CASE_1 = [ Compose( @@ -78,20 +79,21 @@ ] +class _InplaceXform(Transform): + def __call__(self, data): + if data: + data[0] = data[0] + np.pi + else: + data.append(1) + return data + + @skip_if_windows class TestLMDBDataset(unittest.TestCase): def test_cache(self): """testing no inplace change to the hashed item""" items = [[list(range(i))] for i in range(5)] - class _InplaceXform(Transform): - def __call__(self, data): - if data: - data[0] = data[0] + np.pi - else: - data.append(1) - return data - with tempfile.TemporaryDirectory() as tempdir: ds = LMDBDataset(items, transform=_InplaceXform(), cache_dir=tempdir, lmdb_kwargs={"map_size": 10 * 1024}) self.assertEqual(items, [[[]], [[0]], [[0, 1]], [[0, 1, 2]], [[0, 1, 2, 3]]]) @@ -177,5 +179,44 @@ def test_shape(self, transform, expected_shape, kwargs=None): self.assertTupleEqual(data2_postcached["extra"].shape, expected_shape) +@skip_if_windows +class TestMPLMDBDataset(DistTestCase): + def setUp(self): + self.tempdir = tempfile.mkdtemp() + + def tearDown(self): + shutil.rmtree(self.tempdir) + + @DistCall(nnodes=1, nproc_per_node=2) + def test_mp_cache(self): + items = [[list(range(i))] for i in range(5)] + + ds = LMDBDataset(items, transform=_InplaceXform(), cache_dir=self.tempdir, lmdb_kwargs={"map_size": 10 * 1024}) + self.assertEqual(items, [[[]], [[0]], [[0, 1]], [[0, 1, 2]], [[0, 1, 2, 3]]]) + ds1 = LMDBDataset(items, transform=_InplaceXform(), cache_dir=self.tempdir, lmdb_kwargs={"map_size": 10 * 1024}) + self.assertEqual(list(ds1), list(ds)) + self.assertEqual(items, [[[]], [[0]], [[0, 1]], [[0, 1, 2]], [[0, 1, 2, 3]]]) + + ds = LMDBDataset( + items, + transform=_InplaceXform(), + cache_dir=self.tempdir, + lmdb_kwargs={"map_size": 10 * 1024}, + hash_func=json_hashing, + ) + self.assertEqual(items, [[[]], [[0]], [[0, 1]], [[0, 1, 2]], [[0, 1, 2, 3]]]) + ds1 = LMDBDataset( + items, + transform=_InplaceXform(), + cache_dir=self.tempdir, + lmdb_kwargs={"map_size": 10 * 1024}, + hash_func=json_hashing, + ) + self.assertEqual(list(ds1), list(ds)) + self.assertEqual(items, [[[]], [[0]], [[0, 1]], [[0, 1, 2]], [[0, 1, 2, 3]]]) + + self.assertTrue(isinstance(ds1.info(), dict)) + + if __name__ == "__main__": unittest.main() From 26ab6c373652ba96229f724458894c42d4d8738a Mon Sep 17 00:00:00 2001 From: Wenqi Li Date: Sun, 25 Apr 2021 17:09:03 +0100 Subject: [PATCH 04/12] remove usued vars Signed-off-by: Wenqi Li --- monai/apps/datasets.py | 2 -- monai/networks/nets/efficientnet.py | 2 -- monai/utils/jupyter_utils.py | 2 +- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/monai/apps/datasets.py b/monai/apps/datasets.py index a193b7391e..b5bc6e839b 100644 --- a/monai/apps/datasets.py +++ b/monai/apps/datasets.py @@ -128,10 +128,8 @@ def _generate_data_list(self, dataset_dir: str) -> List[Dict]: image_files_list.extend(image_files[i]) image_class.extend([i] * num_each[i]) class_name.extend([class_names[i]] * num_each[i]) - num_total = len(image_class) data = [] - length = len(image_files_list) indices = np.arange(length) self.randomize(indices) diff --git a/monai/networks/nets/efficientnet.py b/monai/networks/nets/efficientnet.py index 65054c870f..1104b577ed 100644 --- a/monai/networks/nets/efficientnet.py +++ b/monai/networks/nets/efficientnet.py @@ -763,8 +763,6 @@ def _calculate_output_image_size(input_image_size: List[int], stride: Union[int, Returns: output_image_size: output image/feature spatial size. """ - # get number of spatial dimensions, corresponds to image spatial size length - num_dims = len(input_image_size) # checks to extract integer stride in case tuple was received if isinstance(stride, tuple): diff --git a/monai/utils/jupyter_utils.py b/monai/utils/jupyter_utils.py index a867d22ca1..1781d743aa 100644 --- a/monai/utils/jupyter_utils.py +++ b/monai/utils/jupyter_utils.py @@ -342,5 +342,5 @@ def plot_status(self, logger, plot_func: Callable = plot_engine_status): which holds the internal lock during the plot generation. """ with self.lock: - self.fig, axes = plot_func(title=self.status(), engine=self.engine, logger=logger, fig=self.fig) + self.fig, _ = plot_func(title=self.status(), engine=self.engine, logger=logger, fig=self.fig) return self.fig From 2c5022886ab1516f0da6dc7a867b5373a022c8c1 Mon Sep 17 00:00:00 2001 From: Wenqi Li Date: Sun, 25 Apr 2021 17:28:37 +0100 Subject: [PATCH 05/12] fixes LGTM errors Signed-off-by: Wenqi Li --- monai/config/deviceconfig.py | 6 ------ tests/test_focal_loss.py | 2 -- 2 files changed, 8 deletions(-) diff --git a/monai/config/deviceconfig.py b/monai/config/deviceconfig.py index 213be56b5c..e1a82b52f1 100644 --- a/monai/config/deviceconfig.py +++ b/monai/config/deviceconfig.py @@ -218,12 +218,6 @@ def get_gpu_info() -> OrderedDict: _dict_append(output, f"GPU {gpu} Is multi GPU board", lambda: bool(gpu_info.is_multi_gpu_board)) _dict_append(output, f"GPU {gpu} Multi processor count", lambda: gpu_info.multi_processor_count) _dict_append(output, f"GPU {gpu} Total memory (GB)", lambda: round(gpu_info.total_memory / 1024 ** 3, 1)) - _dict_append( - output, f"GPU {gpu} Cached memory (GB)", lambda: round(torch.cuda.memory_reserved(gpu) / 1024 ** 3, 1) - ) - _dict_append( - output, f"GPU {gpu} Allocated memory (GB)", lambda: round(torch.cuda.memory_allocated(gpu) / 1024 ** 3, 1) - ) _dict_append(output, f"GPU {gpu} CUDA capability (maj.min)", lambda: f"{gpu_info.major}.{gpu_info.minor}") return output diff --git a/tests/test_focal_loss.py b/tests/test_focal_loss.py index 66665774ef..0c247702cb 100644 --- a/tests/test_focal_loss.py +++ b/tests/test_focal_loss.py @@ -178,8 +178,6 @@ def test_ill_opts(self): chn_target = torch.ones((1, 2, 3)) with self.assertRaisesRegex(ValueError, ""): FocalLoss(reduction="unknown")(chn_input, chn_target) - with self.assertRaisesRegex(TypeError, ""): - FocalLoss(other_act="tanh")(chn_input, chn_target) def test_ill_shape(self): chn_input = torch.ones((1, 2, 3)) From 72f36f8966d4bfe6fb55f6aba372b37f5fd441e6 Mon Sep 17 00:00:00 2001 From: Wenqi Li Date: Sun, 25 Apr 2021 17:35:31 +0100 Subject: [PATCH 06/12] remove comparison-with-callable (W0143) Signed-off-by: Wenqi Li --- monai/data/inverse_batch_transform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monai/data/inverse_batch_transform.py b/monai/data/inverse_batch_transform.py index 3035a1910d..cee1b3bcb2 100644 --- a/monai/data/inverse_batch_transform.py +++ b/monai/data/inverse_batch_transform.py @@ -77,7 +77,7 @@ def __init__( self.batch_size = loader.batch_size self.num_workers = loader.num_workers if num_workers is None else num_workers self.collate_fn = collate_fn - self.pad_collation_used = loader.collate_fn == pad_list_data_collate + self.pad_collation_used = loader.collate_fn.__doc__ == pad_list_data_collate.__doc__ def __call__(self, data: Dict[str, Any]) -> Any: From 9439679cc6881d4f1d03276422a0598c143e9ea1 Mon Sep 17 00:00:00 2001 From: Wenqi Li Date: Sun, 25 Apr 2021 17:38:08 +0100 Subject: [PATCH 07/12] fixes pylint W0231 Signed-off-by: Wenqi Li --- tests/test_handler_prob_map_producer.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tests/test_handler_prob_map_producer.py b/tests/test_handler_prob_map_producer.py index 4f719fccc0..b21cf03171 100644 --- a/tests/test_handler_prob_map_producer.py +++ b/tests/test_handler_prob_map_producer.py @@ -30,14 +30,16 @@ class TestDataset(Dataset): def __init__(self, name, size): - self.data = [ - { - "name": name, - "mask_shape": (size, size), - "mask_locations": [[i, i] for i in range(size)], - "level": 0, - } - ] + super().__init__( + data=[ + { + "name": name, + "mask_shape": (size, size), + "mask_locations": [[i, i] for i in range(size)], + "level": 0, + } + ] + ) self.len = size def __len__(self): From 3135ce86fa5187cf916f34490165fe8829d4a1c8 Mon Sep 17 00:00:00 2001 From: Wenqi Li Date: Sun, 25 Apr 2021 17:39:12 +0100 Subject: [PATCH 08/12] fixes PYL-R1705 Signed-off-by: Wenqi Li --- monai/networks/nets/efficientnet.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/monai/networks/nets/efficientnet.py b/monai/networks/nets/efficientnet.py index 1104b577ed..2afe9481b9 100644 --- a/monai/networks/nets/efficientnet.py +++ b/monai/networks/nets/efficientnet.py @@ -702,8 +702,7 @@ def _make_same_padder(conv_op: Union[nn.Conv1d, nn.Conv2d, nn.Conv3d], image_siz padder = Pad["constantpad", len(padding) // 2] if sum(padding) > 0: return padder(padding=padding, value=0.0) - else: - return nn.Identity() + return nn.Identity() def _round_filters(filters: int, width_coefficient: Optional[float], depth_divisor: float) -> int: From 5e0b1c722ce5422e928ba5503c68efe7570b7373 Mon Sep 17 00:00:00 2001 From: Wenqi Li Date: Sun, 25 Apr 2021 17:40:10 +0100 Subject: [PATCH 09/12] fixes PYL-R1720 Signed-off-by: Wenqi Li --- monai/apps/pathology/datasets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monai/apps/pathology/datasets.py b/monai/apps/pathology/datasets.py index 3e59607c62..3694ca4144 100644 --- a/monai/apps/pathology/datasets.py +++ b/monai/apps/pathology/datasets.py @@ -274,7 +274,7 @@ def _calculate_mask_level(self, image: np.ndarray, mask: np.ndarray) -> Tuple[in f"ratio 0: {ratios[0]} ({image_shape[0]} / {mask_shape[0]})," f"ratio 1: {ratios[1]} ({image_shape[1]} / {mask_shape[1]})," ) - elif not level.is_integer(): + if not level.is_integer(): raise ValueError(f"Mask is not at a regular level (ratio not power of 2), image / mask ratio: {ratios[0]}") return int(level), ratios[0] From e8315fa49311625bddc5db97245821fd7172fd9d Mon Sep 17 00:00:00 2001 From: Wenqi Li Date: Sun, 25 Apr 2021 17:56:57 +0100 Subject: [PATCH 10/12] fixes PTC-W0060 Signed-off-by: Wenqi Li --- monai/apps/deepgrow/transforms.py | 8 ++++---- monai/losses/dice.py | 4 ++-- monai/networks/nets/dynunet.py | 4 ++-- monai/transforms/croppad/array.py | 6 +++--- monai/transforms/croppad/batch.py | 6 +++--- monai/transforms/utils.py | 6 ++++-- monai/visualize/occlusion_sensitivity.py | 9 ++++----- tests/test_affine_transform.py | 2 +- tests/test_autoencoder.py | 2 +- tests/test_dice_focal_loss.py | 2 +- tests/test_npzdictitemdataset.py | 4 ++-- tests/test_rand_rotate90d.py | 2 +- 12 files changed, 28 insertions(+), 27 deletions(-) diff --git a/monai/apps/deepgrow/transforms.py b/monai/apps/deepgrow/transforms.py index 1a56357db6..20d9458882 100644 --- a/monai/apps/deepgrow/transforms.py +++ b/monai/apps/deepgrow/transforms.py @@ -185,8 +185,8 @@ def _get_signal(self, image, guidance): signal = np.zeros((len(guidance), image.shape[-2], image.shape[-1]), dtype=np.float32) sshape = signal.shape - for i in range(len(guidance)): - for point in guidance[i]: + for i, g_i in enumerate(guidance): + for point in g_i: if np.any(np.asarray(point) < 0): continue @@ -924,8 +924,8 @@ def __init__( def _apply(self, image, guidance): slice_idx = guidance[2] # (pos, neg, slice_idx) idx = [] - for i in range(len(image.shape)): - idx.append(slice_idx) if i == self.axis else idx.append(slice(0, image.shape[i])) + for i, size_i in enumerate(image.shape): + idx.append(slice_idx) if i == self.axis else idx.append(slice(0, size_i)) idx = tuple(idx) return image[idx], idx diff --git a/monai/losses/dice.py b/monai/losses/dice.py index 47af8ea171..52757aeb66 100644 --- a/monai/losses/dice.py +++ b/monai/losses/dice.py @@ -590,8 +590,8 @@ def _compute_alpha_generalized_true_positives(self, flat_target: torch.Tensor) - if self.alpha_mode == "GDL": # GDL style # Define alpha like in the generalized dice loss # i.e. the inverse of the volume of each class. - one_hot = F.one_hot(flat_target, num_classes=self.num_classes).permute(0, 2, 1).float() - volumes = torch.sum(one_hot, dim=2) + one_hot_f = F.one_hot(flat_target, num_classes=self.num_classes).permute(0, 2, 1).float() + volumes = torch.sum(one_hot_f, dim=2) alpha = 1.0 / (volumes + 1.0) else: # default, i.e. like in the original paper # alpha weights are 0 for the background and 1 the other classes diff --git a/monai/networks/nets/dynunet.py b/monai/networks/nets/dynunet.py index c22f99db4e..596a623c1d 100644 --- a/monai/networks/nets/dynunet.py +++ b/monai/networks/nets/dynunet.py @@ -181,8 +181,8 @@ def check_kernel_stride(self): if not (len(kernels) == len(strides) and len(kernels) >= 3): raise AssertionError(error_msg) - for idx in range(len(kernels)): - kernel, stride = kernels[idx], strides[idx] + for idx, k_i in enumerate(kernels): + kernel, stride = k_i, strides[idx] if not isinstance(kernel, int): error_msg = "length of kernel_size in block {} should be the same as spatial_dims.".format(idx) if len(kernel) != self.spatial_dims: diff --git a/monai/transforms/croppad/array.py b/monai/transforms/croppad/array.py index 637f96d4b0..dd6b5e3193 100644 --- a/monai/transforms/croppad/array.py +++ b/monai/transforms/croppad/array.py @@ -78,11 +78,11 @@ def _determine_data_pad_width(self, data_shape: Sequence[int]) -> List[Tuple[int self.spatial_size = fall_back_tuple(self.spatial_size, data_shape) if self.method == Method.SYMMETRIC: pad_width = [] - for i in range(len(self.spatial_size)): - width = max(self.spatial_size[i] - data_shape[i], 0) + for i, sp_i in enumerate(self.spatial_size): + width = max(sp_i - data_shape[i], 0) pad_width.append((width // 2, width - (width // 2))) return pad_width - return [(0, max(self.spatial_size[i] - data_shape[i], 0)) for i in range(len(self.spatial_size))] + return [(0, max(sp_i - data_shape[i], 0)) for i, sp_i in enumerate(self.spatial_size)] def __call__(self, img: np.ndarray, mode: Optional[Union[NumpyPadMode, str]] = None) -> np.ndarray: """ diff --git a/monai/transforms/croppad/batch.py b/monai/transforms/croppad/batch.py index 37ff8618fa..b7352ce384 100644 --- a/monai/transforms/croppad/batch.py +++ b/monai/transforms/croppad/batch.py @@ -99,10 +99,10 @@ def __call__(self, batch: Any): padder = SpatialPad(max_shape, self.method, self.mode) # type: ignore transform = padder if not output_to_tensor else Compose([padder, ToTensor()]) - for idx in range(len(batch)): - im = batch[idx][key_or_idx] + for idx, batch_i in enumerate(batch): + im = batch_i[key_or_idx] orig_size = im.shape[1:] - padded = transform(batch[idx][key_or_idx]) + padded = transform(batch_i[key_or_idx]) batch = replace_element(padded, batch, idx, key_or_idx) # If we have a dictionary of data, append to list diff --git a/monai/transforms/utils.py b/monai/transforms/utils.py index b371a65d1a..87fc4365e4 100644 --- a/monai/transforms/utils.py +++ b/monai/transforms/utils.py @@ -339,8 +339,10 @@ def generate_pos_neg_label_crop_centers( valid_end = np.subtract(label_spatial_shape + np.array(1), spatial_size / np.array(2)).astype(np.uint16) # int generation to have full range on upper side, but subtract unfloored size/2 to prevent rounded range # from being too high - for i in range(len(valid_start)): # need this because np.random.randint does not work with same start and end - if valid_start[i] == valid_end[i]: + for i, valid_s in enumerate( + valid_start + ): # need this because np.random.randint does not work with same start and end + if valid_s == valid_end[i]: valid_end[i] += 1 def _correct_centers( diff --git a/monai/visualize/occlusion_sensitivity.py b/monai/visualize/occlusion_sensitivity.py index ec010e32b4..61b84bb406 100644 --- a/monai/visualize/occlusion_sensitivity.py +++ b/monai/visualize/occlusion_sensitivity.py @@ -299,15 +299,14 @@ def __call__( # type: ignore sensitivity_ims_list, output_im_shape = self._compute_occlusion_sensitivity(x, b_box) # Loop over image for each classification - for i in range(len(sensitivity_ims_list)): - + for i, sens_i in enumerate(sensitivity_ims_list): # upsample if self.upsampler is not None: - if len(sensitivity_ims_list[i].shape) != len(x.shape): + if len(sens_i.shape) != len(x.shape): raise AssertionError - if np.any(sensitivity_ims_list[i].shape != x.shape): + if np.any(sens_i.shape != x.shape): img_spatial = tuple(output_im_shape[1:]) - sensitivity_ims_list[i] = self.upsampler(img_spatial)(sensitivity_ims_list[i]) + sensitivity_ims_list[i] = self.upsampler(img_spatial)(sens_i) # Convert list of tensors to tensor sensitivity_ims = torch.stack(sensitivity_ims_list, dim=-1) diff --git a/tests/test_affine_transform.py b/tests/test_affine_transform.py index c3dc9cc6ef..42af58be73 100644 --- a/tests/test_affine_transform.py +++ b/tests/test_affine_transform.py @@ -311,7 +311,7 @@ def test_ill_affine_transform(self): with self.assertRaises(RuntimeError): # dtype doesn't match affine = torch.as_tensor([[2.0, 0.0, 0.0], [0.0, 2.0, 0.0]], dtype=torch.float64) image = torch.arange(1.0, 13.0).view(1, 1, 3, 4).to(device=torch.device("cpu:0")) - out = AffineTransform((1, 2))(image, affine) + AffineTransform((1, 2))(image, affine) def test_forward_2d(self): x = torch.rand(2, 1, 4, 4) diff --git a/tests/test_autoencoder.py b/tests/test_autoencoder.py index 36c04bb94f..54d6832c8d 100644 --- a/tests/test_autoencoder.py +++ b/tests/test_autoencoder.py @@ -98,7 +98,7 @@ def test_script(self): def test_channel_stride_difference(self): with self.assertRaises(ValueError): - net = AutoEncoder(**TEST_CASE_FAIL) + AutoEncoder(**TEST_CASE_FAIL) if __name__ == "__main__": diff --git a/tests/test_dice_focal_loss.py b/tests/test_dice_focal_loss.py index 4bab68131c..920994f8de 100644 --- a/tests/test_dice_focal_loss.py +++ b/tests/test_dice_focal_loss.py @@ -67,7 +67,7 @@ def test_ill_shape(self): def test_ill_lambda(self): with self.assertRaisesRegex(ValueError, ""): - loss = DiceFocalLoss(lambda_dice=-1.0) + DiceFocalLoss(lambda_dice=-1.0) @SkipIfBeforePyTorchVersion((1, 7, 0)) def test_script(self): diff --git a/tests/test_npzdictitemdataset.py b/tests/test_npzdictitemdataset.py index 5ec52f45a2..2e86ef29d0 100644 --- a/tests/test_npzdictitemdataset.py +++ b/tests/test_npzdictitemdataset.py @@ -24,7 +24,7 @@ def test_load_stream(self): dat1 = np.random.rand(10, 1, 4, 4) npzfile = BytesIO() - npz = np.savez_compressed(npzfile, dat0=dat0, dat1=dat1) + np.savez_compressed(npzfile, dat0=dat0, dat1=dat1) npzfile.seek(0) npzds = NPZDictItemDataset(npzfile, {"dat0": "images", "dat1": "seg"}) @@ -41,7 +41,7 @@ def test_load_file(self): with tempfile.TemporaryDirectory() as tempdir: npzfile = f"{tempdir}/test.npz" - npz = np.savez_compressed(npzfile, dat0=dat0, dat1=dat1) + np.savez_compressed(npzfile, dat0=dat0, dat1=dat1) npzds = NPZDictItemDataset(npzfile, {"dat0": "images", "dat1": "seg"}) diff --git a/tests/test_rand_rotate90d.py b/tests/test_rand_rotate90d.py index 48b3ef3586..a487b695f5 100644 --- a/tests/test_rand_rotate90d.py +++ b/tests/test_rand_rotate90d.py @@ -66,7 +66,7 @@ def test_no_key(self): key = "unknown" rotate = RandRotate90d(keys=key, prob=1.0, max_k=2, spatial_axes=(0, 1)) with self.assertRaisesRegex(KeyError, ""): - rotated = rotate({"test": self.imt[0]}) + rotate({"test": self.imt[0]}) if __name__ == "__main__": From 61ddb58b685a6da77bdefaea433607e27b105d00 Mon Sep 17 00:00:00 2001 From: Wenqi Li Date: Sun, 25 Apr 2021 18:00:53 +0100 Subject: [PATCH 11/12] fixes PYL-W0105 Signed-off-by: Wenqi Li --- monai/networks/nets/ahnet.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/monai/networks/nets/ahnet.py b/monai/networks/nets/ahnet.py index 71eb249a55..410c1f3b3a 100644 --- a/monai/networks/nets/ahnet.py +++ b/monai/networks/nets/ahnet.py @@ -390,10 +390,8 @@ def __init__( self.bn0 = norm_type(64) self.relu = relu_type(inplace=True) if upsample_mode in ["transpose", "nearest"]: - """ - To maintain the determinism, the value of kernel_size and stride should be the same. - (you can check this link for reference: https://github.com/Project-MONAI/MONAI/pull/815 ) - """ + # To maintain the determinism, the value of kernel_size and stride should be the same. + # (you can check this link for reference: https://github.com/Project-MONAI/MONAI/pull/815 ) self.maxpool = pool_type(kernel_size=(2, 2, 2)[-spatial_dims:], stride=2) else: self.maxpool = pool_type(kernel_size=(3, 3, 3)[-spatial_dims:], stride=2, padding=1) From 5ad6026c746b7bd1c29510101d77635a8354868a Mon Sep 17 00:00:00 2001 From: Wenqi Li Date: Sun, 25 Apr 2021 18:02:55 +0100 Subject: [PATCH 12/12] PTC-W0016 Signed-off-by: Wenqi Li --- 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 6232b15d02..f5c4461b99 100644 --- a/monai/transforms/utility/array.py +++ b/monai/transforms/utility/array.py @@ -777,7 +777,7 @@ def __init__(self, orig_labels: Sequence, target_labels: Sequence, dtype: DtypeL """ if len(orig_labels) != len(target_labels): raise ValueError("orig_labels and target_labels must have the same length.") - if all([o == z for o, z in zip(orig_labels, target_labels)]): + if all(o == z for o, z in zip(orig_labels, target_labels)): raise ValueError("orig_labels and target_labels are exactly the same, should be different to map.") self.orig_labels = orig_labels