Repository: Project-MONAI/MONAI
File: tests/inferers/test_sliding_window_inference.py (Python)

Code before:
            np.testing.assert_allclose(rr.cpu().numpy(), ee, rtol=1e-4)

        result_dict = SlidingWindowInferer(
            roi_shape, sw_batch_size, overlap=0.5, mode="constant", cval=-1, progress=has_tqdm
        )(inputs, compute_dict)
        for rr, _ in zip(result_dict, expected_dict):
            np.testing.assert_allclose(result_dict[rr].cpu().numpy(), expected_dict[rr], rtol=1e-4)

    def test_strict_shape_validation(self):
        """Test strict shape validation to ensure inputs match roi_size dimensions."""
        device = "cpu"
        roi_size = (16, 16, 16)
        sw_batch_size = 4

        def predictor(data):
            return data

        # Case 1: Input has fewer dimensions than expected (e.g., missing Batch or Channel)
        # 3D roi_size requires 5D input (B, C, D, H, W), giving 4D here.
        inputs_4d = torch.randn((1, 16, 16, 16), device=device)
        with self.assertRaisesRegex(ValueError, "inputs must have 5 dimensions"):
            sliding_window_inference(inputs_4d, roi_size, sw_batch_size, predictor)

        # Case 2: Input is 3D (missing Batch AND Channel)
        inputs_3d = torch.randn((16, 16, 16), device=device)
        with self.assertRaisesRegex(ValueError, "inputs must have 5 dimensions"):
            sliding_window_inference(inputs_3d, roi_size, sw_batch_size, predictor)


class TestSlidingWindowInferenceCond(unittest.TestCase):
    @parameterized.expand(TEST_CASES)
    def test_sliding_window_default(self, image_shape, roi_shape, sw_batch_size, overlap, mode, device):
        n_total = np.prod(image_shape)
        if mode == "constant":
            inputs = torch.arange(n_total, dtype=torch.float).reshape(*image_shape)
        else:
            inputs = torch.ones(*image_shape, dtype=torch.float)
        if device.type == "cuda" and not torch.cuda.is_available():
            device = torch.device("cpu:0")

        # condition
        condition = torch.ones(*image_shape, dtype=torch.float)

        def compute(data, condition):
            return data + condition

        if mode == "constant":
            expected_val = np.arange(n_total, dtype=np.float32).reshape(*image_shape) + 1.0
        else:
            expected_val = np.ones(image_shape, dtype=np.float32) + 1.0


Review comment (suggestion):
```suggestion
        with self.assertRaisesRegex(ValueError, "Inputs must have 5 dimensions"):
```

Code after:
            np.testing.assert_allclose(rr.cpu().numpy(), ee, rtol=1e-4)

        result_dict = SlidingWindowInferer(
            roi_shape, sw_batch_size, overlap=0.5, mode="constant", cval=-1, progress=has_tqdm
        )(inputs, compute_dict)
        for rr, _ in zip(result_dict, expected_dict):
            np.testing.assert_allclose(result_dict[rr].cpu().numpy(), expected_dict[rr], rtol=1e-4)

    def test_strict_shape_validation(self):
        """Test strict shape validation to ensure inputs match roi_size dimensions."""
        device = "cpu"
        roi_size = (16, 16, 16)
        sw_batch_size = 4

        def predictor(data):
            return data

        # Case 1: Input has fewer dimensions than expected (e.g., missing Batch or Channel)
        # 3D roi_size requires 5D input (B, C, D, H, W), giving 4D here.
        inputs_4d = torch.randn((1, 16, 16, 16), device=device)
        with self.assertRaisesRegex(ValueError, "Inputs must have 5 dimensions"):
            sliding_window_inference(inputs_4d, roi_size, sw_batch_size, predictor)

        # Case 2: Input is 3D (missing Batch AND Channel)
        inputs_3d = torch.randn((16, 16, 16), device=device)
        with self.assertRaisesRegex(ValueError, "Inputs must have 5 dimensions"):
            sliding_window_inference(inputs_3d, roi_size, sw_batch_size, predictor)


class TestSlidingWindowInferenceCond(unittest.TestCase):
    @parameterized.expand(TEST_CASES)
    def test_sliding_window_default(self, image_shape, roi_shape, sw_batch_size, overlap, mode, device):
        n_total = np.prod(image_shape)
        if mode == "constant":
            inputs = torch.arange(n_total, dtype=torch.float).reshape(*image_shape)
        else:
            inputs = torch.ones(*image_shape, dtype=torch.float)
        if device.type == "cuda" and not torch.cuda.is_available():
            device = torch.device("cpu:0")

        # condition
        condition = torch.ones(*image_shape, dtype=torch.float)

        def compute(data, condition):
            return data + condition

        if mode == "constant":
            expected_val = np.arange(n_total, dtype=np.float32).reshape(*image_shape) + 1.0
        else:
            expected_val = np.ones(image_shape, dtype=np.float32) + 1.0