Repository: Project-MONAI/MONAI

Issue:
distance_transform_edt not always working with cuCIM backend
**Describe the bug**
The distance_transform_edt returns all zero in special cases when cuCIM is installed and used as a backend. 
This happens when convert_to_cupy() decides that the data array needs to be copied [here:](https://github.com/Project-MONAI/MONAI/blob/16d4e2fcdbc6a7be5bf9df02fc12f34eee5f26b9/monai/transforms/utils.py#L2199)

**To Reproduce**
```
!pip install torch
!pip install cucim
!pip install monai
!pip install numpy

from monai.transforms import distance_transform_edt
import torch
import numpy as np

# create a c-contiguous array
mask = np.zeros((1, 4, 4))

# make it f-contiguous to force convert_to_cupy to copy the data array later on
mask2 = np.asfortranarray(mask)

# convert to torch tensor to make distance_transform_edt use cuCIM backend
mask = torch.tensor(mask, device='cuda')
mask2 = torch.tensor(mask2, device='cuda')

# set half of the mask to foreground
mask[0, 0:2, :,] = 1
mask2[0, 0:2, :,] = 1

# confirm masks are the same
print(mask)
print(mask2)

# calculate distance transform
edt = distance_transform_edt(mask)
edt2 = distance_transform_edt(mask2)

# check if the results are the same
print(edt)
print(edt2)
```
```
tensor([[[1., 1., 1., 1.],
         [1., 1., 1., 1.],
         [0., 0., 0., 0.],
         [0., 0., 0., 0.]]], device='cuda:0', dtype=torch.float64)
tensor([[[1., 1., 1., 1.],
         [1., 1., 1., 1.],
         [0., 0., 0., 0.],
         [0., 0., 0., 0.]]], device='cuda:0', dtype=torch.float64)
tensor([[[2., 2., 2., 2.],
         [1., 1., 1., 1.],
         [0., 0., 0., 0.],
         [0., 0., 0., 0.]]], device='cuda:0')
tensor([[[0., 0., 0., 0.],
         [0., 0., 0., 0.],
         [0., 0., 0., 0.],
         [0., 0., 0., 0.]]], device='cuda:0')
```

**Expected behavior**
Results should be the same, but the second output is all zero.
distance_transform_edt not always working with cuCIM backend
**Describe the bug**
The distance_transform_edt returns all zero in special cases when cuCIM is installed and used as a backend. 
This happens when convert_to_cupy() decides that the data array needs to be copied [here:](https://github.com/Project-MONAI/MONAI/blob/16d4e2fcdbc6a7be5bf9df02fc12f34eee5f26b9/monai/transforms/utils.py#L2199)

**To Reproduce**
```
!pip install torch
!pip install cucim
!pip install monai
!pip install numpy

from monai.transforms import distance_transform_edt
import torch
import numpy as np

# create a c-contiguous array
mask = np.zeros((1, 4, 4))

# make it f-contiguous to force convert_to_cupy to copy the data array later on
mask2 = np.asfortranarray(mask)

# convert to torch tensor to make distance_transform_edt use cuCIM backend
mask = torch.tensor(mask, device='cuda')
mask2 = torch.tensor(mask2, device='cuda')

# set half of the mask to foreground
mask[0, 0:2, :,] = 1
mask2[0, 0:2, :,] = 1

# confirm masks are the same
print(mask)
print(mask2)

# calculate distance transform
edt = distance_transform_edt(mask)
edt2 = distance_transform_edt(mask2)

# check if the results are the same
print(edt)
print(edt2)
```
```
tensor([[[1., 1., 1., 1.],
         [1., 1., 1., 1.],
         [0., 0., 0., 0.],
         [0., 0., 0., 0.]]], device='cuda:0', dtype=torch.float64)
tensor([[[1., 1., 1., 1.],
         [1., 1., 1., 1.],
         [0., 0., 0., 0.],
         [0., 0., 0., 0.]]], device='cuda:0', dtype=torch.float64)
tensor([[[2., 2., 2., 2.],
         [1., 1., 1., 1.],
         [0., 0., 0., 0.],
         [0., 0., 0., 0.]]], device='cuda:0')
tensor([[[0., 0., 0., 0.],
         [0., 0., 0., 0.],
         [0., 0., 0., 0.],
         [0., 0., 0., 0.]]], device='cuda:0')
```

**Expected behavior**
Results should be the same, but the second output is all zero.


Discussion:

Resolving patch:
diff --git a/monai/transforms/utils.py b/monai/transforms/utils.py
--- a/monai/transforms/utils.py
+++ b/monai/transforms/utils.py
@@ -2190,7 +2190,7 @@ def distance_transform_edt(
         if return_distances:
             dtype = torch.float64 if float64_distances else torch.float32
             if distances is None:
-                distances = torch.zeros_like(img, dtype=dtype)  # type: ignore
+                distances = torch.zeros_like(img, memory_format=torch.contiguous_format, dtype=dtype)  # type: ignore
             else:
                 if not isinstance(distances, torch.Tensor) and distances.device != img.device:
                     raise TypeError("distances must be a torch.Tensor on the same device as img")


Test patch:
diff --git a/tests/test_clip_intensity_percentiles.py b/tests/test_clip_intensity_percentiles.py
--- a/tests/test_clip_intensity_percentiles.py
+++ b/tests/test_clip_intensity_percentiles.py
@@ -18,7 +18,6 @@
 from monai.transforms import ClipIntensityPercentiles
 from monai.transforms.utils import soft_clip
 from monai.transforms.utils_pytorch_numpy_unification import clip, percentile
-from monai.utils.type_conversion import convert_to_tensor
 from tests.utils import TEST_NDARRAYS, NumpyImageTestCase2D, NumpyImageTestCase3D, assert_allclose
 
 
@@ -30,7 +29,7 @@ def test_hard_clipping_two_sided(self, p):
         im = p(self.imt)
         result = hard_clipper(im)
         lower, upper = percentile(im, (5, 95))
-        expected = clip(convert_to_tensor(im), lower, upper)
+        expected = clip(im, lower, upper)
         assert_allclose(result, p(expected), type_test="tensor", rtol=1e-4, atol=0)
 
     @parameterized.expand([[p] for p in TEST_NDARRAYS])