From d15a1db2890fba4740e6b9248aa9f19e53794009 Mon Sep 17 00:00:00 2001 From: Talhax55z Date: Tue, 22 Sep 2026 21:06:07 +0500 Subject: [PATCH 1/4] Add anisotropic edge-case tests for SegResNetDS shape validation --- tests/test_segresnet_ds.py | 98 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 tests/test_segresnet_ds.py diff --git a/tests/test_segresnet_ds.py b/tests/test_segresnet_ds.py new file mode 100644 index 00000000000..bcc9f547d59 --- /dev/null +++ b/tests/test_segresnet_ds.py @@ -0,0 +1,98 @@ +import unittest +import torch +from parameterized import parameterized + +from monai.networks.nets import SegResNetDS + + +class TestSegResNetDSShapeLogic(unittest.TestCase): + """Tests for shape_factor() and is_valid_shape() in SegResNetDS.""" + + # ---- shape_factor, isotropic (resolution=None) ---- + @parameterized.expand([ + # (spatial_dims, blocks_down, expected_factor) + (2, [1, 2, 2, 4], [8, 8]), + (3, [1, 2, 2, 4], [8, 8, 8]), + (3, [1, 2, 4], [4, 4, 4]), + ]) + def test_shape_factor_isotropic(self, spatial_dims, blocks_down, expected): + model = SegResNetDS( + spatial_dims=spatial_dims, + in_channels=1, + out_channels=1, + blocks_down=blocks_down, + resolution=None, + ) + actual = [int(x) for x in model.shape_factor()] + self.assertEqual(actual, expected) + + # ---- shape_factor, anisotropic (resolution set) ---- + @parameterized.expand([ + # (spatial_dims, blocks_down, resolution, expected_factor) + (3, [1, 2, 2, 4], [1, 1, 5], [8, 8, 2]), + (3, [1, 2, 2, 4], [1, 2, 3], [8, 4, 4]), + ]) + def test_shape_factor_anisotropic(self, spatial_dims, blocks_down, resolution, expected): + model = SegResNetDS( + spatial_dims=spatial_dims, + in_channels=1, + out_channels=1, + blocks_down=blocks_down, + resolution=resolution, + ) + actual = [int(x) for x in model.shape_factor()] + self.assertEqual(actual, expected) + + # ---- is_valid_shape, valid inputs ---- + @parameterized.expand([ + # (spatial_dims, blocks_down, resolution, input_shape) + (2, [1, 2, 2, 4], None, (1, 1, 16, 16)), + (3, [1, 2, 2, 4], None, (1, 1, 16, 16, 16)), + (3, [1, 2, 2, 4], [1, 1, 5], (1, 1, 16, 16, 16)), + (3, [1, 2, 2, 4], [1, 2, 3], (1, 1, 16, 16, 16)), + ]) + def test_is_valid_shape_true(self, spatial_dims, blocks_down, resolution, shape): + model = SegResNetDS( + spatial_dims=spatial_dims, + in_channels=1, + out_channels=1, + blocks_down=blocks_down, + resolution=resolution, + ) + x = torch.zeros(shape) + self.assertTrue(model.is_valid_shape(x)) + + # ---- is_valid_shape, invalid inputs ---- + @parameterized.expand([ + (3, [1, 2, 2, 4], None, (1, 1, 15, 16, 16)), # 15 not divisible by 8 + (3, [1, 2, 2, 4], None, (1, 1, 7, 7, 7)), # 7 not divisible by 8 + (3, [1, 2, 2, 4], [1, 1, 5], (1, 1, 16, 15, 16)), # 15 not divisible by 8 + (3, [1, 2, 2, 4], [1, 2, 3], (1, 1, 16, 16, 15)), # 15 not divisible by 4 + ]) + def test_is_valid_shape_false(self, spatial_dims, blocks_down, resolution, shape): + model = SegResNetDS( + spatial_dims=spatial_dims, + in_channels=1, + out_channels=1, + blocks_down=blocks_down, + resolution=resolution, + ) + x = torch.zeros(shape) + self.assertFalse(model.is_valid_shape(x)) + + # ---- integration: forward pass raises on invalid shape ---- + def test_forward_raises_on_invalid_shape(self): + model = SegResNetDS( + spatial_dims=3, + in_channels=1, + out_channels=1, + blocks_down=[1, 2, 2, 4], + resolution=None, + ) + x = torch.zeros(1, 1, 15, 16, 16) # 15 not divisible by 8 + with self.assertRaises(ValueError): + model(x) + + +if __name__ == "__main__": + unittest.main() From b11fe2a4d8c8b801a0e9e9ce9982b81abc5275ed Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 22 Sep 2026 16:09:24 +0000 Subject: [PATCH 2/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_segresnet_ds.py | 91 +++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 51 deletions(-) diff --git a/tests/test_segresnet_ds.py b/tests/test_segresnet_ds.py index bcc9f547d59..74b0ba1a46d 100644 --- a/tests/test_segresnet_ds.py +++ b/tests/test_segresnet_ds.py @@ -1,4 +1,7 @@ +from __future__ import annotations + import unittest + import torch from parameterized import parameterized @@ -9,86 +12,72 @@ class TestSegResNetDSShapeLogic(unittest.TestCase): """Tests for shape_factor() and is_valid_shape() in SegResNetDS.""" # ---- shape_factor, isotropic (resolution=None) ---- - @parameterized.expand([ - # (spatial_dims, blocks_down, expected_factor) - (2, [1, 2, 2, 4], [8, 8]), - (3, [1, 2, 2, 4], [8, 8, 8]), - (3, [1, 2, 4], [4, 4, 4]), - ]) + @parameterized.expand( + [ + # (spatial_dims, blocks_down, expected_factor) + (2, [1, 2, 2, 4], [8, 8]), + (3, [1, 2, 2, 4], [8, 8, 8]), + (3, [1, 2, 4], [4, 4, 4]), + ] + ) def test_shape_factor_isotropic(self, spatial_dims, blocks_down, expected): model = SegResNetDS( - spatial_dims=spatial_dims, - in_channels=1, - out_channels=1, - blocks_down=blocks_down, - resolution=None, + spatial_dims=spatial_dims, in_channels=1, out_channels=1, blocks_down=blocks_down, resolution=None ) actual = [int(x) for x in model.shape_factor()] self.assertEqual(actual, expected) # ---- shape_factor, anisotropic (resolution set) ---- - @parameterized.expand([ - # (spatial_dims, blocks_down, resolution, expected_factor) - (3, [1, 2, 2, 4], [1, 1, 5], [8, 8, 2]), - (3, [1, 2, 2, 4], [1, 2, 3], [8, 4, 4]), - ]) + @parameterized.expand( + [ + # (spatial_dims, blocks_down, resolution, expected_factor) + (3, [1, 2, 2, 4], [1, 1, 5], [8, 8, 2]), + (3, [1, 2, 2, 4], [1, 2, 3], [8, 4, 4]), + ] + ) def test_shape_factor_anisotropic(self, spatial_dims, blocks_down, resolution, expected): model = SegResNetDS( - spatial_dims=spatial_dims, - in_channels=1, - out_channels=1, - blocks_down=blocks_down, - resolution=resolution, + spatial_dims=spatial_dims, in_channels=1, out_channels=1, blocks_down=blocks_down, resolution=resolution ) actual = [int(x) for x in model.shape_factor()] self.assertEqual(actual, expected) # ---- is_valid_shape, valid inputs ---- - @parameterized.expand([ - # (spatial_dims, blocks_down, resolution, input_shape) - (2, [1, 2, 2, 4], None, (1, 1, 16, 16)), - (3, [1, 2, 2, 4], None, (1, 1, 16, 16, 16)), - (3, [1, 2, 2, 4], [1, 1, 5], (1, 1, 16, 16, 16)), - (3, [1, 2, 2, 4], [1, 2, 3], (1, 1, 16, 16, 16)), - ]) + @parameterized.expand( + [ + # (spatial_dims, blocks_down, resolution, input_shape) + (2, [1, 2, 2, 4], None, (1, 1, 16, 16)), + (3, [1, 2, 2, 4], None, (1, 1, 16, 16, 16)), + (3, [1, 2, 2, 4], [1, 1, 5], (1, 1, 16, 16, 16)), + (3, [1, 2, 2, 4], [1, 2, 3], (1, 1, 16, 16, 16)), + ] + ) def test_is_valid_shape_true(self, spatial_dims, blocks_down, resolution, shape): model = SegResNetDS( - spatial_dims=spatial_dims, - in_channels=1, - out_channels=1, - blocks_down=blocks_down, - resolution=resolution, + spatial_dims=spatial_dims, in_channels=1, out_channels=1, blocks_down=blocks_down, resolution=resolution ) x = torch.zeros(shape) self.assertTrue(model.is_valid_shape(x)) # ---- is_valid_shape, invalid inputs ---- - @parameterized.expand([ - (3, [1, 2, 2, 4], None, (1, 1, 15, 16, 16)), # 15 not divisible by 8 - (3, [1, 2, 2, 4], None, (1, 1, 7, 7, 7)), # 7 not divisible by 8 - (3, [1, 2, 2, 4], [1, 1, 5], (1, 1, 16, 15, 16)), # 15 not divisible by 8 - (3, [1, 2, 2, 4], [1, 2, 3], (1, 1, 16, 16, 15)), # 15 not divisible by 4 - ]) + @parameterized.expand( + [ + (3, [1, 2, 2, 4], None, (1, 1, 15, 16, 16)), # 15 not divisible by 8 + (3, [1, 2, 2, 4], None, (1, 1, 7, 7, 7)), # 7 not divisible by 8 + (3, [1, 2, 2, 4], [1, 1, 5], (1, 1, 16, 15, 16)), # 15 not divisible by 8 + (3, [1, 2, 2, 4], [1, 2, 3], (1, 1, 16, 16, 15)), # 15 not divisible by 4 + ] + ) def test_is_valid_shape_false(self, spatial_dims, blocks_down, resolution, shape): model = SegResNetDS( - spatial_dims=spatial_dims, - in_channels=1, - out_channels=1, - blocks_down=blocks_down, - resolution=resolution, + spatial_dims=spatial_dims, in_channels=1, out_channels=1, blocks_down=blocks_down, resolution=resolution ) x = torch.zeros(shape) self.assertFalse(model.is_valid_shape(x)) # ---- integration: forward pass raises on invalid shape ---- def test_forward_raises_on_invalid_shape(self): - model = SegResNetDS( - spatial_dims=3, - in_channels=1, - out_channels=1, - blocks_down=[1, 2, 2, 4], - resolution=None, - ) + model = SegResNetDS(spatial_dims=3, in_channels=1, out_channels=1, blocks_down=[1, 2, 2, 4], resolution=None) x = torch.zeros(1, 1, 15, 16, 16) # 15 not divisible by 8 with self.assertRaises(ValueError): model(x) From 61d1f985c3715a3993086af4a82a8c143f49d3ba Mon Sep 17 00:00:00 2001 From: Talhax55z Date: Tue, 22 Sep 2026 21:43:07 +0500 Subject: [PATCH 3/4] Add Google-style docstrings to SegResNetDS test methods --- tests/test_segresnet_ds.py | 40 +++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/tests/test_segresnet_ds.py b/tests/test_segresnet_ds.py index bcc9f547d59..d53ec0de89a 100644 --- a/tests/test_segresnet_ds.py +++ b/tests/test_segresnet_ds.py @@ -16,6 +16,14 @@ class TestSegResNetDSShapeLogic(unittest.TestCase): (3, [1, 2, 4], [4, 4, 4]), ]) def test_shape_factor_isotropic(self, spatial_dims, blocks_down, expected): + """ + Test shape_factor() calculation for isotropic (resolution=None) configurations. + + Args: + spatial_dims: Number of spatial dimensions (2 or 3). + blocks_down: List of integers defining the downsampling blocks. + expected: Expected divisor factors per spatial dimension. + """ model = SegResNetDS( spatial_dims=spatial_dims, in_channels=1, @@ -33,6 +41,15 @@ def test_shape_factor_isotropic(self, spatial_dims, blocks_down, expected): (3, [1, 2, 2, 4], [1, 2, 3], [8, 4, 4]), ]) def test_shape_factor_anisotropic(self, spatial_dims, blocks_down, resolution, expected): + """ + Test shape_factor() calculation for anisotropic (resolution set) configurations. + + Args: + spatial_dims: Number of spatial dimensions. + blocks_down: List of integers defining the downsampling blocks. + resolution: List of resolutions for anisotropic scaling. + expected: Expected divisor factors per spatial dimension. + """ model = SegResNetDS( spatial_dims=spatial_dims, in_channels=1, @@ -52,6 +69,15 @@ def test_shape_factor_anisotropic(self, spatial_dims, blocks_down, resolution, e (3, [1, 2, 2, 4], [1, 2, 3], (1, 1, 16, 16, 16)), ]) def test_is_valid_shape_true(self, spatial_dims, blocks_down, resolution, shape): + """ + Test is_valid_shape() returns True for inputs with valid shapes. + + Args: + spatial_dims: Number of spatial dimensions. + blocks_down: List of integers defining the downsampling blocks. + resolution: List of resolutions for anisotropic scaling. + shape: Input tensor shape to validate. + """ model = SegResNetDS( spatial_dims=spatial_dims, in_channels=1, @@ -70,6 +96,15 @@ def test_is_valid_shape_true(self, spatial_dims, blocks_down, resolution, shape) (3, [1, 2, 2, 4], [1, 2, 3], (1, 1, 16, 16, 15)), # 15 not divisible by 4 ]) def test_is_valid_shape_false(self, spatial_dims, blocks_down, resolution, shape): + """ + Test is_valid_shape() returns False for inputs with invalid shapes. + + Args: + spatial_dims: Number of spatial dimensions. + blocks_down: List of integers defining the downsampling blocks. + resolution: List of resolutions for anisotropic scaling. + shape: Input tensor shape to validate. + """ model = SegResNetDS( spatial_dims=spatial_dims, in_channels=1, @@ -82,6 +117,9 @@ def test_is_valid_shape_false(self, spatial_dims, blocks_down, resolution, shape # ---- integration: forward pass raises on invalid shape ---- def test_forward_raises_on_invalid_shape(self): + """ + Test that the forward pass raises ValueError when the input shape is invalid. + """ model = SegResNetDS( spatial_dims=3, in_channels=1, @@ -95,4 +133,4 @@ def test_forward_raises_on_invalid_shape(self): if __name__ == "__main__": - unittest.main() + unittest.main() \ No newline at end of file From e7e978bf50f50b6516dc11b7e1b38a681a84afda Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 22 Sep 2026 16:47:04 +0000 Subject: [PATCH 4/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_segresnet_ds.py | 93 +++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 52 deletions(-) diff --git a/tests/test_segresnet_ds.py b/tests/test_segresnet_ds.py index d53ec0de89a..6c7de768f27 100644 --- a/tests/test_segresnet_ds.py +++ b/tests/test_segresnet_ds.py @@ -1,4 +1,7 @@ +from __future__ import annotations + import unittest + import torch from parameterized import parameterized @@ -9,12 +12,14 @@ class TestSegResNetDSShapeLogic(unittest.TestCase): """Tests for shape_factor() and is_valid_shape() in SegResNetDS.""" # ---- shape_factor, isotropic (resolution=None) ---- - @parameterized.expand([ - # (spatial_dims, blocks_down, expected_factor) - (2, [1, 2, 2, 4], [8, 8]), - (3, [1, 2, 2, 4], [8, 8, 8]), - (3, [1, 2, 4], [4, 4, 4]), - ]) + @parameterized.expand( + [ + # (spatial_dims, blocks_down, expected_factor) + (2, [1, 2, 2, 4], [8, 8]), + (3, [1, 2, 2, 4], [8, 8, 8]), + (3, [1, 2, 4], [4, 4, 4]), + ] + ) def test_shape_factor_isotropic(self, spatial_dims, blocks_down, expected): """ Test shape_factor() calculation for isotropic (resolution=None) configurations. @@ -25,21 +30,19 @@ def test_shape_factor_isotropic(self, spatial_dims, blocks_down, expected): expected: Expected divisor factors per spatial dimension. """ model = SegResNetDS( - spatial_dims=spatial_dims, - in_channels=1, - out_channels=1, - blocks_down=blocks_down, - resolution=None, + spatial_dims=spatial_dims, in_channels=1, out_channels=1, blocks_down=blocks_down, resolution=None ) actual = [int(x) for x in model.shape_factor()] self.assertEqual(actual, expected) # ---- shape_factor, anisotropic (resolution set) ---- - @parameterized.expand([ - # (spatial_dims, blocks_down, resolution, expected_factor) - (3, [1, 2, 2, 4], [1, 1, 5], [8, 8, 2]), - (3, [1, 2, 2, 4], [1, 2, 3], [8, 4, 4]), - ]) + @parameterized.expand( + [ + # (spatial_dims, blocks_down, resolution, expected_factor) + (3, [1, 2, 2, 4], [1, 1, 5], [8, 8, 2]), + (3, [1, 2, 2, 4], [1, 2, 3], [8, 4, 4]), + ] + ) def test_shape_factor_anisotropic(self, spatial_dims, blocks_down, resolution, expected): """ Test shape_factor() calculation for anisotropic (resolution set) configurations. @@ -51,23 +54,21 @@ def test_shape_factor_anisotropic(self, spatial_dims, blocks_down, resolution, e expected: Expected divisor factors per spatial dimension. """ model = SegResNetDS( - spatial_dims=spatial_dims, - in_channels=1, - out_channels=1, - blocks_down=blocks_down, - resolution=resolution, + spatial_dims=spatial_dims, in_channels=1, out_channels=1, blocks_down=blocks_down, resolution=resolution ) actual = [int(x) for x in model.shape_factor()] self.assertEqual(actual, expected) # ---- is_valid_shape, valid inputs ---- - @parameterized.expand([ - # (spatial_dims, blocks_down, resolution, input_shape) - (2, [1, 2, 2, 4], None, (1, 1, 16, 16)), - (3, [1, 2, 2, 4], None, (1, 1, 16, 16, 16)), - (3, [1, 2, 2, 4], [1, 1, 5], (1, 1, 16, 16, 16)), - (3, [1, 2, 2, 4], [1, 2, 3], (1, 1, 16, 16, 16)), - ]) + @parameterized.expand( + [ + # (spatial_dims, blocks_down, resolution, input_shape) + (2, [1, 2, 2, 4], None, (1, 1, 16, 16)), + (3, [1, 2, 2, 4], None, (1, 1, 16, 16, 16)), + (3, [1, 2, 2, 4], [1, 1, 5], (1, 1, 16, 16, 16)), + (3, [1, 2, 2, 4], [1, 2, 3], (1, 1, 16, 16, 16)), + ] + ) def test_is_valid_shape_true(self, spatial_dims, blocks_down, resolution, shape): """ Test is_valid_shape() returns True for inputs with valid shapes. @@ -79,22 +80,20 @@ def test_is_valid_shape_true(self, spatial_dims, blocks_down, resolution, shape) shape: Input tensor shape to validate. """ model = SegResNetDS( - spatial_dims=spatial_dims, - in_channels=1, - out_channels=1, - blocks_down=blocks_down, - resolution=resolution, + spatial_dims=spatial_dims, in_channels=1, out_channels=1, blocks_down=blocks_down, resolution=resolution ) x = torch.zeros(shape) self.assertTrue(model.is_valid_shape(x)) # ---- is_valid_shape, invalid inputs ---- - @parameterized.expand([ - (3, [1, 2, 2, 4], None, (1, 1, 15, 16, 16)), # 15 not divisible by 8 - (3, [1, 2, 2, 4], None, (1, 1, 7, 7, 7)), # 7 not divisible by 8 - (3, [1, 2, 2, 4], [1, 1, 5], (1, 1, 16, 15, 16)), # 15 not divisible by 8 - (3, [1, 2, 2, 4], [1, 2, 3], (1, 1, 16, 16, 15)), # 15 not divisible by 4 - ]) + @parameterized.expand( + [ + (3, [1, 2, 2, 4], None, (1, 1, 15, 16, 16)), # 15 not divisible by 8 + (3, [1, 2, 2, 4], None, (1, 1, 7, 7, 7)), # 7 not divisible by 8 + (3, [1, 2, 2, 4], [1, 1, 5], (1, 1, 16, 15, 16)), # 15 not divisible by 8 + (3, [1, 2, 2, 4], [1, 2, 3], (1, 1, 16, 16, 15)), # 15 not divisible by 4 + ] + ) def test_is_valid_shape_false(self, spatial_dims, blocks_down, resolution, shape): """ Test is_valid_shape() returns False for inputs with invalid shapes. @@ -106,11 +105,7 @@ def test_is_valid_shape_false(self, spatial_dims, blocks_down, resolution, shape shape: Input tensor shape to validate. """ model = SegResNetDS( - spatial_dims=spatial_dims, - in_channels=1, - out_channels=1, - blocks_down=blocks_down, - resolution=resolution, + spatial_dims=spatial_dims, in_channels=1, out_channels=1, blocks_down=blocks_down, resolution=resolution ) x = torch.zeros(shape) self.assertFalse(model.is_valid_shape(x)) @@ -120,17 +115,11 @@ def test_forward_raises_on_invalid_shape(self): """ Test that the forward pass raises ValueError when the input shape is invalid. """ - model = SegResNetDS( - spatial_dims=3, - in_channels=1, - out_channels=1, - blocks_down=[1, 2, 2, 4], - resolution=None, - ) + model = SegResNetDS(spatial_dims=3, in_channels=1, out_channels=1, blocks_down=[1, 2, 2, 4], resolution=None) x = torch.zeros(1, 1, 15, 16, 16) # 15 not divisible by 8 with self.assertRaises(ValueError): model(x) if __name__ == "__main__": - unittest.main() \ No newline at end of file + unittest.main()