From eb5966631713b2a44d7f3fccb22ab8b55b22d543 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Thu, 3 Feb 2022 23:41:51 +0800 Subject: [PATCH 1/4] [DLMED] fix PadListCollate issue Signed-off-by: Nic Ma --- monai/data/test_time_augmentation.py | 7 ++++--- monai/data/utils.py | 8 ++++---- monai/transforms/croppad/batch.py | 5 +++-- monai/transforms/inverse_batch_transform.py | 2 +- tests/test_testtimeaugmentation.py | 2 +- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/monai/data/test_time_augmentation.py b/monai/data/test_time_augmentation.py index c75a61c56d..0b97c9febf 100644 --- a/monai/data/test_time_augmentation.py +++ b/monai/data/test_time_augmentation.py @@ -21,6 +21,7 @@ from monai.data.dataset import Dataset from monai.data.utils import decollate_batch, pad_list_data_collate from monai.transforms.compose import Compose +from monai.transforms.croppad.batch import PadListDataCollate from monai.transforms.inverse import InvertibleTransform from monai.transforms.post.dictionary import Invertd from monai.transforms.transform import Randomizable @@ -189,10 +190,10 @@ def __call__( outs: List = [] - for batch_data in tqdm(dl) if has_tqdm and self.progress else dl: + for b in tqdm(dl) if has_tqdm and self.progress else dl: # do model forward pass - batch_data[self._pred_key] = self.inferrer_fn(batch_data[self.image_key].to(self.device)) - outs.extend([self.inverter(i)[self._pred_key] for i in decollate_batch(batch_data)]) + b[self._pred_key] = self.inferrer_fn(b[self.image_key].to(self.device)) + outs.extend([self.inverter(PadListDataCollate.inverse(i))[self._pred_key] for i in decollate_batch(b)]) output: NdarrayOrTensor = stack(outs, 0) diff --git a/monai/data/utils.py b/monai/data/utils.py index ae784dc07f..d19a2b133d 100644 --- a/monai/data/utils.py +++ b/monai/data/utils.py @@ -492,10 +492,10 @@ def pad_list_data_collate( tensor in each dimension. This transform is useful if some of the applied transforms generate batch data of different sizes. - This can be used on both list and dictionary data. In the case of the dictionary data, this transform will be added - to the list of invertible transforms. - - The inverse can be called using the static method: `monai.transforms.croppad.batch.PadListDataCollate.inverse`. + This can be used on both list and dictionary data. + Note that in the case of the dictionary data, this decollate function may add the transform information of + `PadListDataCollate` to the list of invertible transforms if input batch have different spatial shape, so need to + call static method: `monai.transforms.croppad.batch.PadListDataCollate.inverse` before inverting other transforms. Args: batch: batch of data to pad-collate diff --git a/monai/transforms/croppad/batch.py b/monai/transforms/croppad/batch.py index 6edaf4622d..52d0c7be3b 100644 --- a/monai/transforms/croppad/batch.py +++ b/monai/transforms/croppad/batch.py @@ -45,8 +45,9 @@ class PadListDataCollate(InvertibleTransform): tensor in each dimension. This transform is useful if some of the applied transforms generate batch data of different sizes. - This can be used on both list and dictionary data. In the case of the dictionary data, this transform will be added - to the list of invertible transforms. + This can be used on both list and dictionary data. + Note that in the case of the dictionary data, it may add the transform information to the list of invertible transforms + if input batch have different spatial shape, so need to call static method: `inverse` before inverting other transforms. Note that normally, a user won't explicitly use the `__call__` method. Rather this would be passed to the `DataLoader`. This means that `__call__` handles data as it comes out of a `DataLoader`, containing batch dimension. However, the diff --git a/monai/transforms/inverse_batch_transform.py b/monai/transforms/inverse_batch_transform.py index ae0317cea8..31c035e817 100644 --- a/monai/transforms/inverse_batch_transform.py +++ b/monai/transforms/inverse_batch_transform.py @@ -88,7 +88,7 @@ def __init__( self.detach = detach self.pad_batch = pad_batch self.fill_value = fill_value - self.pad_collation_used = loader.collate_fn.__doc__ == pad_list_data_collate.__doc__ + self.pad_collation_used = loader.collate_fn.__name__ == pad_list_data_collate.__name__ def __call__(self, data: Dict[str, Any]) -> Any: decollated_data = decollate_batch(data, detach=self.detach, pad=self.pad_batch, fill_value=self.fill_value) diff --git a/tests/test_testtimeaugmentation.py b/tests/test_testtimeaugmentation.py index 8815354052..21186adc3c 100644 --- a/tests/test_testtimeaugmentation.py +++ b/tests/test_testtimeaugmentation.py @@ -74,7 +74,7 @@ def tearDown(self) -> None: set_determinism(None) def test_test_time_augmentation(self): - input_size = (20, 20) + input_size = (20, 40) # test different input data shape to pad list collate keys = ["image", "label"] num_training_ims = 10 From 706fb9bb533dc03cf275fdd96cb96992f011d45b Mon Sep 17 00:00:00 2001 From: monai-bot Date: Thu, 3 Feb 2022 15:50:12 +0000 Subject: [PATCH 2/4] [MONAI] python code formatting Signed-off-by: monai-bot --- monai/data/nifti_writer.py | 8 ++++++-- monai/transforms/spatial/array.py | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/monai/data/nifti_writer.py b/monai/data/nifti_writer.py index 1ffae31183..b6defa9836 100644 --- a/monai/data/nifti_writer.py +++ b/monai/data/nifti_writer.py @@ -115,7 +115,9 @@ def write_nifti( if allclose(affine, target_affine, atol=1e-3): # type: ignore # no affine changes, save (data, affine) - results_img = nib.Nifti1Image(data.astype(output_dtype, copy=False), to_affine_nd(3, target_affine)) # type: ignore + results_img = nib.Nifti1Image( + data.astype(output_dtype, copy=False), to_affine_nd(3, target_affine) + ) # type: ignore nib.save(results_img, file_name) return @@ -163,6 +165,8 @@ def write_nifti( ) data_np = data_torch.squeeze(0).squeeze(0).detach().cpu().numpy() - results_img = nib.Nifti1Image(data_np.astype(output_dtype, copy=False), to_affine_nd(3, target_affine)) # type: ignore + results_img = nib.Nifti1Image( + data_np.astype(output_dtype, copy=False), to_affine_nd(3, target_affine) + ) # type: ignore nib.save(results_img, file_name) return diff --git a/monai/transforms/spatial/array.py b/monai/transforms/spatial/array.py index 206847df17..46aaae66f0 100644 --- a/monai/transforms/spatial/array.py +++ b/monai/transforms/spatial/array.py @@ -236,7 +236,9 @@ def __call__( _t_r[idx, -1] = (max(d_dst, 2) - 1.0) / 2.0 xform = xform @ _t_r if not USE_COMPILED: - _t_l = normalize_transform(in_spatial_size, xform.device, xform.dtype, align_corners=True) # type: ignore + _t_l = normalize_transform( + in_spatial_size, xform.device, xform.dtype, align_corners=True + ) # type: ignore xform = _t_l @ xform # type: ignore affine_xform = Affine( affine=xform, spatial_size=spatial_size, norm_coords=False, image_only=True, dtype=_dtype From 01db7276a18c0b9a10040288dbb084869983e5ef Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Fri, 4 Feb 2022 00:00:13 +0800 Subject: [PATCH 3/4] [DLMED] fix flake8 Signed-off-by: Nic Ma --- monai/data/nifti_writer.py | 8 ++++---- monai/transforms/spatial/array.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/monai/data/nifti_writer.py b/monai/data/nifti_writer.py index b6defa9836..606b0732b3 100644 --- a/monai/data/nifti_writer.py +++ b/monai/data/nifti_writer.py @@ -116,8 +116,8 @@ def write_nifti( if allclose(affine, target_affine, atol=1e-3): # type: ignore # no affine changes, save (data, affine) results_img = nib.Nifti1Image( - data.astype(output_dtype, copy=False), to_affine_nd(3, target_affine) - ) # type: ignore + data.astype(output_dtype, copy=False), to_affine_nd(3, target_affine) # type: ignore + ) nib.save(results_img, file_name) return @@ -166,7 +166,7 @@ def write_nifti( data_np = data_torch.squeeze(0).squeeze(0).detach().cpu().numpy() results_img = nib.Nifti1Image( - data_np.astype(output_dtype, copy=False), to_affine_nd(3, target_affine) - ) # type: ignore + data_np.astype(output_dtype, copy=False), to_affine_nd(3, target_affine) # type: ignore + ) nib.save(results_img, file_name) return diff --git a/monai/transforms/spatial/array.py b/monai/transforms/spatial/array.py index 46aaae66f0..b7cb5015ed 100644 --- a/monai/transforms/spatial/array.py +++ b/monai/transforms/spatial/array.py @@ -237,8 +237,8 @@ def __call__( xform = xform @ _t_r if not USE_COMPILED: _t_l = normalize_transform( - in_spatial_size, xform.device, xform.dtype, align_corners=True - ) # type: ignore + in_spatial_size, xform.device, xform.dtype, align_corners=True # type: ignore + ) xform = _t_l @ xform # type: ignore affine_xform = Affine( affine=xform, spatial_size=spatial_size, norm_coords=False, image_only=True, dtype=_dtype From a6d88290058e22ef8b98dc3f4764284f75a7e203 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Fri, 4 Feb 2022 08:07:34 +0800 Subject: [PATCH 4/4] [DLMED] update according to comments Signed-off-by: Nic Ma --- monai/transforms/inverse_batch_transform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monai/transforms/inverse_batch_transform.py b/monai/transforms/inverse_batch_transform.py index 31c035e817..ae0317cea8 100644 --- a/monai/transforms/inverse_batch_transform.py +++ b/monai/transforms/inverse_batch_transform.py @@ -88,7 +88,7 @@ def __init__( self.detach = detach self.pad_batch = pad_batch self.fill_value = fill_value - self.pad_collation_used = loader.collate_fn.__name__ == pad_list_data_collate.__name__ + self.pad_collation_used = loader.collate_fn.__doc__ == pad_list_data_collate.__doc__ def __call__(self, data: Dict[str, Any]) -> Any: decollated_data = decollate_batch(data, detach=self.detach, pad=self.pad_batch, fill_value=self.fill_value)