Repository: Project-MONAI/MONAI

Issue:
SSIMLoss result does not have gradient
**Describe the bug**
SSIMLoss result does not have gradient
@PedroFerreiradaCosta 
@wyli 

**To Reproduce**
```
import torch
from monai.losses.ssim_loss import SSIMLoss

x = torch.ones([1,1,10,10])/2
y = torch.ones([1,1,10,10])/2
y.requires_grad_(True)
data_range = x.max().unsqueeze(0)
loss = SSIMLoss(spatial_dims=2)(x,y,data_range)
print(loss.requires_grad)
```

**Expected behavior**
`loss.requires_grad` will be False. But it should be True

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Environment**

Ensuring you use the relevant python executable, please paste the output of:

```
python -c 'import monai; monai.config.print_debug_info()'
```

**Additional context**
Add any other context about the problem here.



Discussion:

Resolving patch:
diff --git a/monai/losses/ssim_loss.py b/monai/losses/ssim_loss.py
--- a/monai/losses/ssim_loss.py
+++ b/monai/losses/ssim_loss.py
@@ -81,13 +81,15 @@ def forward(self, x: torch.Tensor, y: torch.Tensor, data_range: torch.Tensor) ->
                 print(1-SSIMLoss(spatial_dims=3)(x,y,data_range))
         """
         if x.shape[0] == 1:
-            ssim_value: torch.Tensor = SSIMMetric(data_range, self.win_size, self.k1, self.k2, self.spatial_dims)(x, y)
+            ssim_value: torch.Tensor = SSIMMetric(
+                data_range, self.win_size, self.k1, self.k2, self.spatial_dims
+            )._compute_tensor(x, y)
         elif x.shape[0] > 1:
 
             for i in range(x.shape[0]):
-                ssim_val: torch.Tensor = SSIMMetric(data_range, self.win_size, self.k1, self.k2, self.spatial_dims)(
-                    x[i : i + 1], y[i : i + 1]
-                )
+                ssim_val: torch.Tensor = SSIMMetric(
+                    data_range, self.win_size, self.k1, self.k2, self.spatial_dims
+                )._compute_tensor(x[i : i + 1], y[i : i + 1])
                 if i == 0:
                     ssim_value = ssim_val
                 else:


Test patch:
diff --git a/tests/test_ssim_loss.py b/tests/test_ssim_loss.py
--- a/tests/test_ssim_loss.py
+++ b/tests/test_ssim_loss.py
@@ -34,6 +34,14 @@
     TESTS3D.append((x.to(device), y1.to(device), data_range.to(device), torch.tensor(1.0).unsqueeze(0).to(device)))
     TESTS3D.append((x.to(device), y2.to(device), data_range.to(device), torch.tensor(0.0).unsqueeze(0).to(device)))
 
+x = torch.ones([1, 1, 10, 10]) / 2
+y = torch.ones([1, 1, 10, 10]) / 2
+y.requires_grad_(True)
+data_range = x.max().unsqueeze(0)
+TESTS2D_GRAD = []
+for device in [None, "cpu", "cuda"] if torch.cuda.is_available() else [None, "cpu"]:
+    TESTS2D_GRAD.append([x.to(device), y.to(device), data_range.to(device)])
+
 
 class TestSSIMLoss(unittest.TestCase):
     @parameterized.expand(TESTS2D)
@@ -42,6 +50,11 @@ def test2d(self, x, y, drange, res):
         self.assertTrue(isinstance(result, torch.Tensor))
         self.assertTrue(torch.abs(res - result).item() < 0.001)
 
+    @parameterized.expand(TESTS2D_GRAD)
+    def test_grad(self, x, y, drange):
+        result = 1 - SSIMLoss(spatial_dims=2)(x, y, drange)
+        self.assertTrue(result.requires_grad)
+
     @parameterized.expand(TESTS3D)
     def test3d(self, x, y, drange, res):
         result = 1 - SSIMLoss(spatial_dims=3)(x, y, drange)