Repository: Project-MONAI/MONAI

Issue:
compatibility with torch 1.10.0
**Is your feature request related to a problem? Please describe.**
pytorch 1.10 is available, would be great to include it in the testing pipelines.

test error from test_testtimeaugmentation
**Describe the bug**
from nightly build, probably a torch 1.5 only issue:

```
======================================================================
ERROR: test_requires_meta_dict (tests.test_testtimeaugmentation.TestTestTimeAugmentation)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/jenkins/agent/workspace/Monai-pytorch-versions/monai/data/utils.py", line 271, in list_data_collate
    ret[k] = default_collate([d[k] for d in data])
  File "/opt/conda/lib/python3.6/site-packages/torch/utils/data/_utils/collate.py", line 79, in default_collate
    return [default_collate(samples) for samples in transposed]
  File "/opt/conda/lib/python3.6/site-packages/torch/utils/data/_utils/collate.py", line 79, in <listcomp>
    return [default_collate(samples) for samples in transposed]
  File "/opt/conda/lib/python3.6/site-packages/torch/utils/data/_utils/collate.py", line 74, in default_collate
    return {key: default_collate([d[key] for d in batch]) for key in elem}
  File "/opt/conda/lib/python3.6/site-packages/torch/utils/data/_utils/collate.py", line 74, in <dictcomp>
    return {key: default_collate([d[key] for d in batch]) for key in elem}
  File "/opt/conda/lib/python3.6/site-packages/torch/utils/data/_utils/collate.py", line 74, in default_collate
    return {key: default_collate([d[key] for d in batch]) for key in elem}
  File "/opt/conda/lib/python3.6/site-packages/torch/utils/data/_utils/collate.py", line 74, in <dictcomp>
    return {key: default_collate([d[key] for d in batch]) for key in elem}
  File "/opt/conda/lib/python3.6/site-packages/torch/utils/data/_utils/collate.py", line 64, in default_collate
    return default_collate([torch.as_tensor(b) for b in batch])
  File "/opt/conda/lib/python3.6/site-packages/torch/utils/data/_utils/collate.py", line 55, in default_collate
    return torch.stack(batch, 0, out=out)
RuntimeError: Expected object of scalar type double but got scalar type float for sequence element 1.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/jenkins/agent/workspace/Monai-pytorch-versions/tests/test_testtimeaugmentation.py", line 155, in test_requires_meta_dict
    tta(self.get_data(1, (20, 20), include_label=False))
  File "/home/jenkins/agent/workspace/Monai-pytorch-versions/monai/data/test_time_augmentation.py", line 173, in __call__
    for batch_data in tqdm(dl) if has_tqdm and self.progress else dl:
  File "/opt/conda/lib/python3.6/site-packages/tqdm/std.py", line 1180, in __iter__
    for obj in iterable:
  File "/opt/conda/lib/python3.6/site-packages/torch/utils/data/dataloader.py", line 345, in __next__
    data = self._next_data()
  File "/opt/conda/lib/python3.6/site-packages/torch/utils/data/dataloader.py", line 385, in _next_data
    data = self._dataset_fetcher.fetch(index)  # may raise StopIteration
  File "/opt/conda/lib/python3.6/site-packages/torch/utils/data/_utils/fetch.py", line 47, in fetch
    return self.collate_fn(data)
  File "/home/jenkins/agent/workspace/Monai-pytorch-versions/monai/data/utils.py", line 446, in pad_list_data_collate
    return PadListDataCollate(method=method, mode=mode, **np_kwargs)(batch)
  File "/home/jenkins/agent/workspace/Monai-pytorch-versions/monai/transforms/croppad/batch.py", line 119, in __call__
    return list_data_collate(batch)
  File "/home/jenkins/agent/workspace/Monai-pytorch-versions/monai/data/utils.py", line 284, in list_data_collate
    raise RuntimeError(re_str) from re
RuntimeError: Expected object of scalar type double but got scalar type float for sequence element 1.

----------------------------------------------------------------------
```

```
================================
Printing MONAI config...
================================
MONAI version: 0.7.0+71.g7da61305
Numpy version: 1.18.1
Pytorch version: 1.5.1
MONAI flags: HAS_EXT = True, USE_COMPILED = True
MONAI rev id: 7da613056fec29ee764857a417d4cca61f07986b

Optional dependencies:
Pytorch Ignite version: 0.4.6
Nibabel version: 3.2.1
scikit-image version: 0.15.0
Pillow version: 8.4.0
Tensorboard version: 2.1.0
gdown version: 4.2.0
TorchVision version: 0.6.1
tqdm version: 4.62.3
lmdb version: 0.98
psutil version: 5.6.7
pandas version: 0.24.2
einops version: 0.3.2
transformers version: 4.11.3
mlflow version: 1.20.2

```


Discussion:

Resolving patch:
diff --git a/monai/utils/misc.py b/monai/utils/misc.py
--- a/monai/utils/misc.py
+++ b/monai/utils/misc.py
@@ -22,7 +22,7 @@
 import numpy as np
 import torch
 
-from monai.utils.module import get_torch_version_tuple, version_leq
+from monai.utils.module import version_leq
 
 __all__ = [
     "zip_with",
@@ -256,13 +256,11 @@ def set_determinism(
     else:  # restore the original flags
         torch.backends.cudnn.deterministic = _flag_deterministic
         torch.backends.cudnn.benchmark = _flag_cudnn_benchmark
-
     if use_deterministic_algorithms is not None:
-        torch_ver = get_torch_version_tuple()
-        if torch_ver >= (1, 9):
+        if hasattr(torch, "use_deterministic_algorithms"):
             torch.use_deterministic_algorithms(use_deterministic_algorithms)
-        elif torch_ver >= (1, 7):
-            torch.set_deterministic(use_deterministic_algorithms)  # beta feature
+        elif hasattr(torch, "set_deterministic"):
+            torch.set_deterministic(use_deterministic_algorithms)  # type: ignore
         else:
             warnings.warn("use_deterministic_algorithms=True, but PyTorch version is too old to set the mode.")
 
@@ -279,9 +277,7 @@ def list_to_dict(items):
     def _parse_var(s):
         items = s.split("=", maxsplit=1)
         key = items[0].strip(" \n\r\t'")
-        value = None
-        if len(items) > 1:
-            value = items[1].strip(" \n\r\t'")
+        value = items[1].strip(" \n\r\t'") if len(items) > 1 else None
         return key, value
 
     d = {}


Test patch:
diff --git a/monai/data/test_time_augmentation.py b/monai/data/test_time_augmentation.py
--- a/monai/data/test_time_augmentation.py
+++ b/monai/data/test_time_augmentation.py
@@ -159,7 +159,7 @@ def __call__(
             raise ValueError("num_examples should be multiple of batch size.")
 
         # generate batch of data of size == batch_size, dataset and dataloader
-        data_in = [d] * num_examples
+        data_in = [deepcopy(d) for _ in range(num_examples)]
         ds = Dataset(data_in, self.transform)
         dl = DataLoader(ds, self.num_workers, batch_size=self.batch_size, collate_fn=pad_list_data_collate)
 
diff --git a/tests/test_autoencoder.py b/tests/test_autoencoder.py
--- a/tests/test_autoencoder.py
+++ b/tests/test_autoencoder.py
@@ -23,7 +23,7 @@
 
 TEST_CASE_0 = [  # single channel 2D, batch 4, no residual
     {
-        "dimensions": 2,
+        "spatial_dims": 2,
         "in_channels": 1,
         "out_channels": 1,
         "channels": (4, 8, 16),
@@ -35,14 +35,14 @@
 ]
 
 TEST_CASE_1 = [  # single channel 2D, batch 4
-    {"dimensions": 2, "in_channels": 1, "out_channels": 1, "channels": (4, 8, 16), "strides": (2, 2, 2)},
+    {"spatial_dims": 2, "in_channels": 1, "out_channels": 1, "channels": (4, 8, 16), "strides": (2, 2, 2)},
     (1, 1, 128, 128),
     (1, 1, 128, 128),
 ]
 
 TEST_CASE_2 = [  # 3-channel 2D, batch 4, LeakyReLU activation
     {
-        "dimensions": 2,
+        "spatial_dims": 2,
         "in_channels": 3,
         "out_channels": 3,
         "channels": (4, 8, 16),
@@ -54,7 +54,7 @@
 ]
 
 TEST_CASE_3 = [  # 4-channel 3D, batch 4
-    {"dimensions": 3, "in_channels": 4, "out_channels": 3, "channels": (4, 8, 16), "strides": (2, 2, 2)},
+    {"spatial_dims": 3, "in_channels": 4, "out_channels": 3, "channels": (4, 8, 16), "strides": (2, 2, 2)},
     (1, 4, 128, 128, 128),
     (1, 3, 128, 128, 128),
 ]
@@ -63,7 +63,7 @@
 
 
 TEST_CASE_FAIL = {  # 2-channel 2D, should fail because of stride/channel mismatch.
-    "dimensions": 2,
+    "spatial_dims": 2,
     "in_channels": 2,
     "out_channels": 2,
     "channels": (4, 8, 16),
diff --git a/tests/test_basic_unet.py b/tests/test_basic_unet.py
--- a/tests/test_basic_unet.py
+++ b/tests/test_basic_unet.py
@@ -20,7 +20,7 @@
 
 CASES_1D = []
 for mode in ["pixelshuffle", "nontrainable", "deconv", None]:
-    kwargs = {"dimensions": 1, "in_channels": 5, "out_channels": 8}
+    kwargs = {"spatial_dims": 1, "in_channels": 5, "out_channels": 8}
     if mode is not None:
         kwargs["upsample"] = mode  # type: ignore
     CASES_1D.append([kwargs, (10, 5, 33), (10, 8, 33)])
@@ -33,7 +33,7 @@
             CASES_2D.append(
                 [
                     {
-                        "dimensions": 2,
+                        "spatial_dims": 2,
                         "in_channels": in_channels,
                         "out_channels": out_channels,
                         "features": (12, 12, 13, 14, 15, 16),
@@ -46,7 +46,7 @@
 CASES_3D = [
     [  # single channel 3D, batch 2
         {
-            "dimensions": 3,
+            "spatial_dims": 3,
             "in_channels": 1,
             "out_channels": 2,
             "features": (16, 20, 21, 22, 23, 11),
@@ -57,7 +57,7 @@
     ],
     [  # 2-channel 3D, batch 3
         {
-            "dimensions": 3,
+            "spatial_dims": 3,
             "in_channels": 2,
             "out_channels": 7,
             "features": (14, 15, 16, 17, 18, 11),
@@ -68,7 +68,7 @@
     ],
     [  # 4-channel 3D, batch 5
         {
-            "dimensions": 3,
+            "spatial_dims": 3,
             "in_channels": 4,
             "out_channels": 2,
             "features": (14, 15, 16, 17, 18, 10),
diff --git a/tests/test_generate_param_groups.py b/tests/test_generate_param_groups.py
--- a/tests/test_generate_param_groups.py
+++ b/tests/test_generate_param_groups.py
@@ -69,7 +69,7 @@ class TestGenerateParamGroups(unittest.TestCase):
     def test_lr_values(self, input_param, expected_values, expected_groups):
         device = "cuda" if torch.cuda.is_available() else "cpu"
         net = Unet(
-            dimensions=3, in_channels=1, out_channels=3, channels=(16, 32, 64), strides=(2, 2), num_res_units=1
+            spatial_dims=3, in_channels=1, out_channels=3, channels=(16, 32, 64), strides=(2, 2), num_res_units=1
         ).to(device)
 
         params = generate_param_groups(network=net, **input_param)
@@ -85,7 +85,7 @@ def test_wrong(self):
         """overlapped"""
         device = "cuda" if torch.cuda.is_available() else "cpu"
         net = Unet(
-            dimensions=3, in_channels=1, out_channels=3, channels=(16, 32, 64), strides=(2, 2), num_res_units=1
+            spatial_dims=3, in_channels=1, out_channels=3, channels=(16, 32, 64), strides=(2, 2), num_res_units=1
         ).to(device)
 
         params = generate_param_groups(
diff --git a/tests/test_integration_stn.py b/tests/test_integration_stn.py
--- a/tests/test_integration_stn.py
+++ b/tests/test_integration_stn.py
@@ -103,7 +103,7 @@ def setUp(self):
     def tearDown(self):
         set_determinism(seed=None)
 
-    @TimedCall(seconds=60)
+    @TimedCall(seconds=100)
     def test_training(self):
         """
         check that the quality AffineTransform backpropagation
diff --git a/tests/test_invertd.py b/tests/test_invertd.py
--- a/tests/test_invertd.py
+++ b/tests/test_invertd.py
@@ -73,7 +73,7 @@ def test_invert(self):
         data = [{"image": im_fname, "label": seg_fname} for _ in range(12)]
 
         # num workers = 0 for mac or gpu transforms
-        num_workers = 0 if sys.platform == "darwin" or torch.cuda.is_available() else 2
+        num_workers = 0 if sys.platform != "linux" or torch.cuda.is_available() else 2
 
         dataset = CacheDataset(data, transform=transform, progress=False)
         loader = DataLoader(dataset, num_workers=num_workers, batch_size=5)
@@ -162,7 +162,8 @@ def test_invert(self):
         # 25300: 2 workers (cpu, non-macos)
         # 1812: 0 workers (gpu or macos)
         # 1824: torch 1.5.1
-        self.assertTrue((reverted.size - n_good) in (34007, 1812, 1824), "diff. in 3 possible values")
+        # 1821: windows torch 1.10.0
+        self.assertTrue((reverted.size - n_good) in (34007, 1812, 1824, 1821), f"diff.  {reverted.size - n_good}")
 
         set_determinism(seed=None)
 
diff --git a/tests/test_subpixel_upsample.py b/tests/test_subpixel_upsample.py
--- a/tests/test_subpixel_upsample.py
+++ b/tests/test_subpixel_upsample.py
@@ -24,20 +24,20 @@
     for dim in range(1, 4):
         for factor in range(1, 3):
             test_case = [
-                {"dimensions": dim, "in_channels": inch, "scale_factor": factor},
+                {"spatial_dims": dim, "in_channels": inch, "scale_factor": factor},
                 (2, inch, *([8] * dim)),
                 (2, inch, *([8 * factor] * dim)),
             ]
             TEST_CASE_SUBPIXEL.append(test_case)
 
 TEST_CASE_SUBPIXEL_2D_EXTRA = [
-    {"dimensions": 2, "in_channels": 2, "scale_factor": 3},
+    {"spatial_dims": 2, "in_channels": 2, "scale_factor": 3},
     (2, 2, 8, 4),  # different size for H and W
     (2, 2, 24, 12),
 ]
 
 TEST_CASE_SUBPIXEL_3D_EXTRA = [
-    {"dimensions": 3, "in_channels": 1, "scale_factor": 2},
+    {"spatial_dims": 3, "in_channels": 1, "scale_factor": 2},
     (2, 1, 16, 8, 4),  # different size for H, W and D
     (2, 1, 32, 16, 8),
 ]
@@ -47,7 +47,7 @@
 )
 
 TEST_CASE_SUBPIXEL_CONV_BLOCK_EXTRA = [
-    {"dimensions": 3, "in_channels": 1, "scale_factor": 2, "conv_block": conv_block},
+    {"spatial_dims": 3, "in_channels": 1, "scale_factor": 2, "conv_block": conv_block},
     (2, 1, 16, 8, 4),  # different size for H, W and D
     (2, 1, 32, 16, 8),
 ]
diff --git a/tests/test_threadcontainer.py b/tests/test_threadcontainer.py
--- a/tests/test_threadcontainer.py
+++ b/tests/test_threadcontainer.py
@@ -102,7 +102,7 @@ def test_plot(self):
         with tempfile.TemporaryDirectory() as tempdir:
             tempimg = f"{tempdir}/threadcontainer_plot_test.png"
             fig.savefig(tempimg)
-            comp = compare_images(f"{testing_dir}/threadcontainer_plot_test.png", tempimg, 1e-2)
+            comp = compare_images(f"{testing_dir}/threadcontainer_plot_test.png", tempimg, 5e-2)
 
             self.assertIsNone(comp, comp)  # None indicates test passed
 
diff --git a/tests/test_unet.py b/tests/test_unet.py
--- a/tests/test_unet.py
+++ b/tests/test_unet.py
@@ -23,7 +23,7 @@
 
 TEST_CASE_0 = [  # single channel 2D, batch 16, no residual
     {
-        "dimensions": 2,
+        "spatial_dims": 2,
         "in_channels": 1,
         "out_channels": 3,
         "channels": (16, 32, 64),
@@ -36,7 +36,7 @@
 
 TEST_CASE_1 = [  # single channel 2D, batch 16
     {
-        "dimensions": 2,
+        "spatial_dims": 2,
         "in_channels": 1,
         "out_channels": 3,
         "channels": (16, 32, 64),
@@ -49,7 +49,7 @@
 
 TEST_CASE_2 = [  # single channel 3D, batch 16
     {
-        "dimensions": 3,
+        "spatial_dims": 3,
         "in_channels": 1,
         "out_channels": 3,
         "channels": (16, 32, 64),
@@ -62,7 +62,7 @@
 
 TEST_CASE_3 = [  # 4-channel 3D, batch 16
     {
-        "dimensions": 3,
+        "spatial_dims": 3,
         "in_channels": 4,
         "out_channels": 3,
         "channels": (16, 32, 64),
@@ -75,7 +75,7 @@
 
 TEST_CASE_4 = [  # 4-channel 3D, batch 16, batch normalization
     {
-        "dimensions": 3,
+        "spatial_dims": 3,
         "in_channels": 4,
         "out_channels": 3,
         "channels": (16, 32, 64),
@@ -89,7 +89,7 @@
 
 TEST_CASE_5 = [  # 4-channel 3D, batch 16, LeakyReLU activation
     {
-        "dimensions": 3,
+        "spatial_dims": 3,
         "in_channels": 4,
         "out_channels": 3,
         "channels": (16, 32, 64),
@@ -103,7 +103,7 @@
 
 TEST_CASE_6 = [  # 4-channel 3D, batch 16, LeakyReLU activation explicit
     {
-        "dimensions": 3,
+        "spatial_dims": 3,
         "in_channels": 4,
         "out_channels": 3,
         "channels": (16, 32, 64),
@@ -120,7 +120,7 @@
 ILL_CASES = [
     [
         {  # len(channels) < 2
-            "dimensions": 2,
+            "spatial_dims": 2,
             "in_channels": 1,
             "out_channels": 3,
             "channels": (16,),
@@ -130,7 +130,7 @@
     ],
     [
         {  # len(strides) < len(channels) - 1
-            "dimensions": 2,
+            "spatial_dims": 2,
             "in_channels": 1,
             "out_channels": 3,
             "channels": (8, 8, 8),
@@ -139,8 +139,8 @@
         }
     ],
     [
-        {  # len(kernel_size) = 3, dimensions = 2
-            "dimensions": 2,
+        {  # len(kernel_size) = 3, spatial_dims = 2
+            "spatial_dims": 2,
             "in_channels": 1,
             "out_channels": 3,
             "channels": (8, 8, 8),
@@ -149,8 +149,8 @@
         }
     ],
     [
-        {  # len(up_kernel_size) = 2, dimensions = 3
-            "dimensions": 3,
+        {  # len(up_kernel_size) = 2, spatial_dims = 3
+            "spatial_dims": 3,
             "in_channels": 1,
             "out_channels": 3,
             "channels": (8, 8, 8),
diff --git a/tests/test_varautoencoder.py b/tests/test_varautoencoder.py
--- a/tests/test_varautoencoder.py
+++ b/tests/test_varautoencoder.py
@@ -23,7 +23,7 @@
 
 TEST_CASE_0 = [  # single channel 2D, batch 4, no residual
     {
-        "dimensions": 2,
+        "spatial_dims": 2,
         "in_shape": (1, 128, 128),
         "out_channels": 1,
         "latent_size": 2,
@@ -37,7 +37,7 @@
 
 TEST_CASE_1 = [  # single channel 2D, batch 4
     {
-        "dimensions": 2,
+        "spatial_dims": 2,
         "in_shape": (1, 128, 128),
         "out_channels": 1,
         "latent_size": 2,
@@ -50,7 +50,7 @@
 
 TEST_CASE_2 = [  # 3-channel 2D, batch 4, LeakyReLU activation
     {
-        "dimensions": 2,
+        "spatial_dims": 2,
         "in_shape": (3, 128, 128),
         "out_channels": 3,
         "latent_size": 2,
@@ -64,7 +64,7 @@
 
 TEST_CASE_3 = [  # 4-channel 3D, batch 4
     {
-        "dimensions": 3,
+        "spatial_dims": 3,
         "in_shape": (4, 128, 128, 128),
         "out_channels": 3,
         "latent_size": 2,
@@ -88,7 +88,7 @@ def test_shape(self, input_param, input_shape, expected_shape):
 
     def test_script(self):
         net = VarAutoEncoder(
-            dimensions=2, in_shape=(1, 32, 32), out_channels=1, latent_size=2, channels=(4, 8), strides=(2, 2)
+            spatial_dims=2, in_shape=(1, 32, 32), out_channels=1, latent_size=2, channels=(4, 8), strides=(2, 2)
         )
         test_data = torch.randn(2, 1, 32, 32)
         test_script_save(net, test_data)