From 902604c94da4458a56d3c2dabb5a2d2808d69b9e Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Mon, 17 Jun 2024 15:07:36 +0100 Subject: [PATCH 01/11] Updating use of MAX_SEED to match Numpy 2.0 requirements Signed-off-by: Eric Kerfoot --- monai/data/dataset.py | 2 +- monai/data/image_dataset.py | 2 +- monai/transforms/compose.py | 2 +- monai/transforms/croppad/dictionary.py | 2 +- monai/utils/misc.py | 5 ++--- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/monai/data/dataset.py b/monai/data/dataset.py index 79e066303e..2e8e20f593 100644 --- a/monai/data/dataset.py +++ b/monai/data/dataset.py @@ -1371,7 +1371,7 @@ def __len__(self) -> int: return len(self.dataset) def randomize(self, data: Any | None = None) -> None: - self._seed = self.R.randint(MAX_SEED, dtype="uint32") + self._seed = self.R.randint(MAX_SEED + 1, dtype="uint32") def __getitem__(self, index: int): self.randomize() diff --git a/monai/data/image_dataset.py b/monai/data/image_dataset.py index 6c8ddcf8de..36abc307b7 100644 --- a/monai/data/image_dataset.py +++ b/monai/data/image_dataset.py @@ -97,7 +97,7 @@ def __len__(self) -> int: return len(self.image_files) def randomize(self, data: Any | None = None) -> None: - self._seed = self.R.randint(MAX_SEED, dtype="uint32") + self._seed = self.R.randint(MAX_SEED + 1, dtype="uint32") def __getitem__(self, index: int): self.randomize() diff --git a/monai/transforms/compose.py b/monai/transforms/compose.py index 236d3cc4c5..cf9c44e5d1 100644 --- a/monai/transforms/compose.py +++ b/monai/transforms/compose.py @@ -260,7 +260,7 @@ def set_random_state(self, seed: int | None = None, state: np.random.RandomState for _transform in self.transforms: if not isinstance(_transform, Randomizable): continue - _transform.set_random_state(seed=self.R.randint(MAX_SEED, dtype="uint32")) + _transform.set_random_state(seed=self.R.randint(MAX_SEED + 1, dtype="uint32")) return self def randomize(self, data: Any | None = None) -> None: diff --git a/monai/transforms/croppad/dictionary.py b/monai/transforms/croppad/dictionary.py index be9441dc4a..6ede25d5d9 100644 --- a/monai/transforms/croppad/dictionary.py +++ b/monai/transforms/croppad/dictionary.py @@ -678,7 +678,7 @@ def lazy(self, value: bool) -> None: self.cropper.lazy = value def randomize(self, data: Any | None = None) -> None: - self.sub_seed = self.R.randint(MAX_SEED, dtype="uint32") + self.sub_seed = self.R.randint(MAX_SEED + 1, dtype="uint32") def __call__( self, data: Mapping[Hashable, torch.Tensor], lazy: bool | None = None diff --git a/monai/utils/misc.py b/monai/utils/misc.py index ab9fe259aa..2efc62ebf1 100644 --- a/monai/utils/misc.py +++ b/monai/utils/misc.py @@ -81,8 +81,7 @@ _seed = None _flag_deterministic = torch.backends.cudnn.deterministic _flag_cudnn_benchmark = torch.backends.cudnn.benchmark -NP_MAX = np.iinfo(np.uint32).max -MAX_SEED = NP_MAX + 1 # 2**32, the actual seed should be in [0, MAX_SEED - 1] for uint32 +MAX_SEED = np.iinfo(np.uint32).max def zip_with(op, *vals, mapfunc=map): @@ -314,7 +313,7 @@ def get_seed() -> int | None: def set_determinism( - seed: int | None = NP_MAX, + seed: int | None = MAX_SEED, use_deterministic_algorithms: bool | None = None, additional_settings: Sequence[Callable[[int], Any]] | Callable[[int], Any] | None = None, ) -> None: From ea641bc51565a5091219b00d2850c9c4694e29be Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Mon, 17 Jun 2024 15:50:14 +0100 Subject: [PATCH 02/11] Try this fix instead Signed-off-by: Eric Kerfoot --- monai/data/dataset.py | 2 +- monai/data/image_dataset.py | 2 +- monai/transforms/compose.py | 2 +- monai/transforms/croppad/dictionary.py | 2 +- monai/transforms/transform.py | 2 +- monai/utils/misc.py | 5 +++-- 6 files changed, 8 insertions(+), 7 deletions(-) diff --git a/monai/data/dataset.py b/monai/data/dataset.py index 30c8810a45..871b523289 100644 --- a/monai/data/dataset.py +++ b/monai/data/dataset.py @@ -1353,7 +1353,7 @@ def __len__(self) -> int: return len(self.dataset) def randomize(self, data: Any | None = None) -> None: - self._seed = self.R.randint(MAX_SEED + 1, dtype="uint32") + self._seed = self.R.randint(MAX_SEED, dtype="uint32") def __getitem__(self, index: int): self.randomize() diff --git a/monai/data/image_dataset.py b/monai/data/image_dataset.py index 36abc307b7..6c8ddcf8de 100644 --- a/monai/data/image_dataset.py +++ b/monai/data/image_dataset.py @@ -97,7 +97,7 @@ def __len__(self) -> int: return len(self.image_files) def randomize(self, data: Any | None = None) -> None: - self._seed = self.R.randint(MAX_SEED + 1, dtype="uint32") + self._seed = self.R.randint(MAX_SEED, dtype="uint32") def __getitem__(self, index: int): self.randomize() diff --git a/monai/transforms/compose.py b/monai/transforms/compose.py index cf9c44e5d1..236d3cc4c5 100644 --- a/monai/transforms/compose.py +++ b/monai/transforms/compose.py @@ -260,7 +260,7 @@ def set_random_state(self, seed: int | None = None, state: np.random.RandomState for _transform in self.transforms: if not isinstance(_transform, Randomizable): continue - _transform.set_random_state(seed=self.R.randint(MAX_SEED + 1, dtype="uint32")) + _transform.set_random_state(seed=self.R.randint(MAX_SEED, dtype="uint32")) return self def randomize(self, data: Any | None = None) -> None: diff --git a/monai/transforms/croppad/dictionary.py b/monai/transforms/croppad/dictionary.py index 6ede25d5d9..be9441dc4a 100644 --- a/monai/transforms/croppad/dictionary.py +++ b/monai/transforms/croppad/dictionary.py @@ -678,7 +678,7 @@ def lazy(self, value: bool) -> None: self.cropper.lazy = value def randomize(self, data: Any | None = None) -> None: - self.sub_seed = self.R.randint(MAX_SEED + 1, dtype="uint32") + self.sub_seed = self.R.randint(MAX_SEED, dtype="uint32") def __call__( self, data: Mapping[Hashable, torch.Tensor], lazy: bool | None = None diff --git a/monai/transforms/transform.py b/monai/transforms/transform.py index 3d09cea545..2da2988d1b 100644 --- a/monai/transforms/transform.py +++ b/monai/transforms/transform.py @@ -204,7 +204,7 @@ def set_random_state(self, seed: int | None = None, state: np.random.RandomState """ if seed is not None: _seed = id(seed) if not isinstance(seed, (int, np.integer)) else seed - _seed = _seed % MAX_SEED + _seed = np.int64(_seed) % MAX_SEED # need to account for Numpy2.0 which doesn't silently convert to int64 self.R = np.random.RandomState(_seed) return self diff --git a/monai/utils/misc.py b/monai/utils/misc.py index 2efc62ebf1..ab9fe259aa 100644 --- a/monai/utils/misc.py +++ b/monai/utils/misc.py @@ -81,7 +81,8 @@ _seed = None _flag_deterministic = torch.backends.cudnn.deterministic _flag_cudnn_benchmark = torch.backends.cudnn.benchmark -MAX_SEED = np.iinfo(np.uint32).max +NP_MAX = np.iinfo(np.uint32).max +MAX_SEED = NP_MAX + 1 # 2**32, the actual seed should be in [0, MAX_SEED - 1] for uint32 def zip_with(op, *vals, mapfunc=map): @@ -313,7 +314,7 @@ def get_seed() -> int | None: def set_determinism( - seed: int | None = MAX_SEED, + seed: int | None = NP_MAX, use_deterministic_algorithms: bool | None = None, additional_settings: Sequence[Callable[[int], Any]] | Callable[[int], Any] | None = None, ) -> None: From bee1fa1a8f0cc71dc81b6ea183b9b019ba1d63ac Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Mon, 17 Jun 2024 15:57:57 +0100 Subject: [PATCH 03/11] Try _this_ fix Signed-off-by: Eric Kerfoot --- monai/transforms/transform.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/monai/transforms/transform.py b/monai/transforms/transform.py index 2da2988d1b..15c2499a73 100644 --- a/monai/transforms/transform.py +++ b/monai/transforms/transform.py @@ -203,8 +203,8 @@ def set_random_state(self, seed: int | None = None, state: np.random.RandomState """ if seed is not None: - _seed = id(seed) if not isinstance(seed, (int, np.integer)) else seed - _seed = np.int64(_seed) % MAX_SEED # need to account for Numpy2.0 which doesn't silently convert to int64 + _seed = np.int64(id(seed) if not isinstance(seed, (int, np.integer)) else seed) + _seed = _seed % MAX_SEED # need to account for Numpy2.0 which doesn't silently convert to int64 self.R = np.random.RandomState(_seed) return self From bd4a78fa69778beff9ecacf34a86a4b9211eb45c Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Mon, 17 Jun 2024 16:32:04 +0100 Subject: [PATCH 04/11] ptp fix Signed-off-by: Eric Kerfoot --- monai/data/utils.py | 2 +- monai/transforms/spatial/functional.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/monai/data/utils.py b/monai/data/utils.py index 585f02ec9e..846dcc369a 100644 --- a/monai/data/utils.py +++ b/monai/data/utils.py @@ -924,7 +924,7 @@ def compute_shape_offset( corners = in_affine_ @ corners all_dist = corners_out[:-1].copy() corners_out = corners_out[:-1] / corners_out[-1] - out_shape = np.round(corners_out.ptp(axis=1)) if scale_extent else np.round(corners_out.ptp(axis=1) + 1.0) + out_shape = np.round(np.ptp(corners_out, axis=1)) if scale_extent else np.round(np.ptp(corners_out, axis=1) + 1.0) offset = None for i in range(corners.shape[1]): min_corner = np.min(all_dist - all_dist[:, i : i + 1], 1) diff --git a/monai/transforms/spatial/functional.py b/monai/transforms/spatial/functional.py index add4e7f5ea..22726f06a5 100644 --- a/monai/transforms/spatial/functional.py +++ b/monai/transforms/spatial/functional.py @@ -373,7 +373,7 @@ def rotate(img, angle, output_shape, mode, padding_mode, align_corners, dtype, l if output_shape is None: corners = np.asarray(np.meshgrid(*[(0, dim) for dim in im_shape], indexing="ij")).reshape((len(im_shape), -1)) corners = transform[:-1, :-1] @ corners # type: ignore - output_shape = np.asarray(corners.ptp(axis=1) + 0.5, dtype=int) + output_shape = np.asarray(np.ptp(corners, axis=1) + 0.5, dtype=int) else: output_shape = np.asarray(output_shape, dtype=int) shift = create_translate(input_ndim, ((np.array(im_shape) - 1) / 2).tolist()) From 03265d6f67b35aaf0f157f149fa8bc13d503433e Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Thu, 25 Jul 2024 18:17:22 +0100 Subject: [PATCH 05/11] Enable numpy 2 for testing Signed-off-by: Eric Kerfoot --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index aae455f58c..7f62b36520 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ torch>=1.9 -numpy>=1.20,<=1.26.0 +numpy>=1.25 From 55b78f4db304fe4052c4a6648fd9d6aaf7f786be Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Thu, 25 Jul 2024 18:33:56 +0100 Subject: [PATCH 06/11] Addressing numpy 2 issues Signed-off-by: Eric Kerfoot --- monai/transforms/io/array.py | 2 +- tests/test_meta_tensor.py | 2 +- tests/test_signal_fillempty.py | 4 ++-- tests/test_signal_fillemptyd.py | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/monai/transforms/io/array.py b/monai/transforms/io/array.py index e0ecc127f2..7c0e8f7123 100644 --- a/monai/transforms/io/array.py +++ b/monai/transforms/io/array.py @@ -86,7 +86,7 @@ def switch_endianness(data, new="<"): if new not in ("<", ">"): raise NotImplementedError(f"Not implemented option new={new}.") if current_ != new: - data = data.byteswap().newbyteorder(new) + data = data.byteswap().view(data.dtype.newbyteorder(new)) elif isinstance(data, tuple): data = tuple(switch_endianness(x, new) for x in data) elif isinstance(data, list): diff --git a/tests/test_meta_tensor.py b/tests/test_meta_tensor.py index f31a07eba4..60b6019703 100644 --- a/tests/test_meta_tensor.py +++ b/tests/test_meta_tensor.py @@ -448,7 +448,7 @@ def test_shape(self): def test_astype(self): t = MetaTensor([1.0], affine=torch.tensor(1), meta={"fname": "filename"}) - for np_types in ("float32", "np.float32", "numpy.float32", np.float32, float, "int", np.compat.long, np.uint16): + for np_types in ("float32", "np.float32", "numpy.float32", np.float32, float, "int", np.uint16): self.assertIsInstance(t.astype(np_types), np.ndarray) for pt_types in ("torch.float", torch.float, "torch.float64"): self.assertIsInstance(t.astype(pt_types), torch.Tensor) diff --git a/tests/test_signal_fillempty.py b/tests/test_signal_fillempty.py index a3ee623cc5..2be4bd8600 100644 --- a/tests/test_signal_fillempty.py +++ b/tests/test_signal_fillempty.py @@ -30,7 +30,7 @@ class TestSignalFillEmptyNumpy(unittest.TestCase): def test_correct_parameters_multi_channels(self): self.assertIsInstance(SignalFillEmpty(replacement=0.0), SignalFillEmpty) sig = np.load(TEST_SIGNAL) - sig[:, 123] = np.NAN + sig[:, 123] = np.nan fillempty = SignalFillEmpty(replacement=0.0) fillemptysignal = fillempty(sig) self.assertTrue(not np.isnan(fillemptysignal).any()) @@ -42,7 +42,7 @@ class TestSignalFillEmptyTorch(unittest.TestCase): def test_correct_parameters_multi_channels(self): self.assertIsInstance(SignalFillEmpty(replacement=0.0), SignalFillEmpty) sig = convert_to_tensor(np.load(TEST_SIGNAL)) - sig[:, 123] = convert_to_tensor(np.NAN) + sig[:, 123] = convert_to_tensor(np.nan) fillempty = SignalFillEmpty(replacement=0.0) fillemptysignal = fillempty(sig) self.assertTrue(not torch.isnan(fillemptysignal).any()) diff --git a/tests/test_signal_fillemptyd.py b/tests/test_signal_fillemptyd.py index ee8c571ef8..7710279495 100644 --- a/tests/test_signal_fillemptyd.py +++ b/tests/test_signal_fillemptyd.py @@ -30,7 +30,7 @@ class TestSignalFillEmptyNumpy(unittest.TestCase): def test_correct_parameters_multi_channels(self): self.assertIsInstance(SignalFillEmptyd(replacement=0.0), SignalFillEmptyd) sig = np.load(TEST_SIGNAL) - sig[:, 123] = np.NAN + sig[:, 123] = np.nan data = {} data["signal"] = sig fillempty = SignalFillEmptyd(keys=("signal",), replacement=0.0) @@ -46,7 +46,7 @@ class TestSignalFillEmptyTorch(unittest.TestCase): def test_correct_parameters_multi_channels(self): self.assertIsInstance(SignalFillEmptyd(replacement=0.0), SignalFillEmptyd) sig = convert_to_tensor(np.load(TEST_SIGNAL)) - sig[:, 123] = convert_to_tensor(np.NAN) + sig[:, 123] = convert_to_tensor(np.nan) data = {} data["signal"] = sig fillempty = SignalFillEmptyd(keys=("signal",), replacement=0.0) From 0bc721a4bc462f17ab9d3c5478d2f33fcd8d5202 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Thu, 25 Jul 2024 18:42:51 +0100 Subject: [PATCH 07/11] Addressing numpy 2 issues Signed-off-by: Eric Kerfoot --- tests/test_nifti_endianness.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_nifti_endianness.py b/tests/test_nifti_endianness.py index 4475d8aaab..f8531dc08f 100644 --- a/tests/test_nifti_endianness.py +++ b/tests/test_nifti_endianness.py @@ -82,7 +82,7 @@ def test_switch(self): # verify data types after = switch_endianness(before) np.testing.assert_allclose(after.astype(float), expected_float) - before = np.array(["1.12", "-9.2", "42"], dtype=np.string_) + before = np.array(["1.12", "-9.2", "42"], dtype=np.bytes_) after = switch_endianness(before) np.testing.assert_array_equal(before, after) From 5c0b5f6e30748545ef8783f95dac8281ddac7ca8 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Fri, 16 Aug 2024 17:36:04 +0100 Subject: [PATCH 08/11] Adjusting Requirements --- environment-dev.yml | 4 ++-- requirements.txt | 2 +- setup.cfg | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/environment-dev.yml b/environment-dev.yml index d23958baba..0438abdb9f 100644 --- a/environment-dev.yml +++ b/environment-dev.yml @@ -5,10 +5,10 @@ channels: - nvidia - conda-forge dependencies: - - numpy>=1.20 + - numpy>=1.25,<2.0 - pytorch>=1.9 - torchvision - - pytorch-cuda=11.6 + - pytorch-cuda>=11.6 - pip - pip: - -r requirements-dev.txt diff --git a/requirements.txt b/requirements.txt index 7f62b36520..af535ff331 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ torch>=1.9 -numpy>=1.25 +numpy>=1.25,<2.0 diff --git a/setup.cfg b/setup.cfg index 2115c30a7f..ccd8fdd192 100644 --- a/setup.cfg +++ b/setup.cfg @@ -42,7 +42,7 @@ setup_requires = ninja install_requires = torch>=1.9 - numpy>=1.20 + numpy>=1.25,<2.0 [options.extras_require] all = From 4beec1b5dcbb0085e94a04fa564c7de950c60814 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Fri, 16 Aug 2024 17:36:38 +0100 Subject: [PATCH 09/11] DCO Remediation Commit for Eric Kerfoot I, Eric Kerfoot , hereby add my Signed-off-by to this commit: 5c0b5f6e30748545ef8783f95dac8281ddac7ca8 Signed-off-by: Eric Kerfoot From ea68381c38f9726c27f17a5e2c5739a735a91dc7 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Mon, 19 Aug 2024 12:52:50 +0100 Subject: [PATCH 10/11] Update Numpy version Signed-off-by: Eric Kerfoot --- environment-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/environment-dev.yml b/environment-dev.yml index 0438abdb9f..a4651ec7e4 100644 --- a/environment-dev.yml +++ b/environment-dev.yml @@ -5,7 +5,7 @@ channels: - nvidia - conda-forge dependencies: - - numpy>=1.25,<2.0 + - numpy>=1.24,<2.0 - pytorch>=1.9 - torchvision - pytorch-cuda>=11.6 From 065a3e4d2bcac5793f3e8fe8cc2054fb85d0a65a Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Mon, 19 Aug 2024 16:12:29 +0100 Subject: [PATCH 11/11] Update Numpy version Signed-off-by: Eric Kerfoot --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index af535ff331..e184322c13 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ torch>=1.9 -numpy>=1.25,<2.0 +numpy>=1.24,<2.0 diff --git a/setup.cfg b/setup.cfg index ccd8fdd192..1ce4a3f34c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -42,7 +42,7 @@ setup_requires = ninja install_requires = torch>=1.9 - numpy>=1.25,<2.0 + numpy>=1.24,<2.0 [options.extras_require] all =