diff --git a/monai/transforms/compose.py b/monai/transforms/compose.py index 04fb12b463..45e706e143 100644 --- a/monai/transforms/compose.py +++ b/monai/transforms/compose.py @@ -221,7 +221,10 @@ def __init__( elif weights is None or isinstance(weights, float): weights = [1.0 / len(self.transforms)] * len(self.transforms) if len(weights) != len(self.transforms): - raise AssertionError("transforms and weights should be same size if both specified as sequences.") + raise ValueError( + "transforms and weights should be same size if both specified as sequences, " + f"got {len(weights)} and {len(self.transforms)}." + ) self.weights = ensure_tuple(self._normalize_probabilities(weights)) def _normalize_probabilities(self, weights): @@ -229,9 +232,9 @@ def _normalize_probabilities(self, weights): return weights weights = np.array(weights) if np.any(weights < 0): - raise AssertionError("Probabilities must be greater than or equal to zero.") + raise ValueError(f"Probabilities must be greater than or equal to zero, got {weights}.") if np.all(weights == 0): - raise AssertionError("At least one probability must be greater than zero.") + raise ValueError(f"At least one probability must be greater than zero, got {weights}.") weights = weights / weights.sum() return list(weights) @@ -278,7 +281,9 @@ def inverse(self, data): if isinstance(data[key], monai.data.MetaTensor) or self.trace_key(key) in data: index = self.pop_transform(data, key)[TraceKeys.EXTRA_INFO]["index"] else: - raise RuntimeError("Inverse only implemented for Mapping (dictionary) or MetaTensor data.") + raise RuntimeError( + f"Inverse only implemented for Mapping (dictionary) or MetaTensor data, got type {type(data)}." + ) if index is None: # no invertible transforms have been applied return data @@ -342,7 +347,9 @@ def inverse(self, data): if isinstance(data[key], monai.data.MetaTensor) or self.trace_key(key) in data: applied_order = self.pop_transform(data, key)[TraceKeys.EXTRA_INFO]["applied_order"] else: - raise RuntimeError("Inverse only implemented for Mapping (dictionary) or MetaTensor data.") + raise RuntimeError( + f"Inverse only implemented for Mapping (dictionary) or MetaTensor data, got type {type(data)}." + ) if applied_order is None: # no invertible transforms have been applied return data diff --git a/monai/transforms/croppad/batch.py b/monai/transforms/croppad/batch.py index 095edbadf6..bd8e7bf50f 100644 --- a/monai/transforms/croppad/batch.py +++ b/monai/transforms/croppad/batch.py @@ -117,7 +117,7 @@ def __call__(self, batch: Any): @staticmethod def inverse(data: dict) -> dict[Hashable, np.ndarray]: if not isinstance(data, Mapping): - raise RuntimeError("Inverse can only currently be applied on dictionaries.") + raise RuntimeError(f"Inverse can only currently be applied on dictionaries, got type {type(data)}.") d = dict(data) for key in d: diff --git a/monai/transforms/intensity/array.py b/monai/transforms/intensity/array.py index 1980ef508b..c22eed3b65 100644 --- a/monai/transforms/intensity/array.py +++ b/monai/transforms/intensity/array.py @@ -206,12 +206,12 @@ def __call__(self, img: NdarrayOrTensor, randomize: bool = True) -> NdarrayOrTen img[i] = self._add_noise(d, mean=_mean[i], std=_std[i] * d.std() if self.relative else _std[i]) else: if not isinstance(self.mean, (int, float)): - raise RuntimeError("If channel_wise is False, mean must be a float or int number.") + raise RuntimeError(f"If channel_wise is False, mean must be a float or int, got {type(self.mean)}.") if not isinstance(self.std, (int, float)): - raise RuntimeError("If channel_wise is False, std must be a float or int number.") + raise RuntimeError(f"If channel_wise is False, std must be a float or int, got {type(self.std)}.") std = self.std * img.std().item() if self.relative else self.std if not isinstance(std, (int, float)): - raise RuntimeError("std must be a float or int number.") + raise RuntimeError(f"std must be a float or int number, got {type(std)}.") img = self._add_noise(img, mean=self.mean, std=std) return img @@ -265,7 +265,7 @@ def __init__(self, offsets: tuple[float, float] | float, safe: bool = False, pro if isinstance(offsets, (int, float)): self.offsets = (min(-offsets, offsets), max(-offsets, offsets)) elif len(offsets) != 2: - raise ValueError("offsets should be a number or pair of numbers.") + raise ValueError(f"offsets should be a number or pair of numbers, got {offsets}.") else: self.offsets = (min(offsets), max(offsets)) self._offset = self.offsets[0] @@ -381,7 +381,7 @@ def __init__( if isinstance(factors, (int, float)): self.factors = (min(-factors, factors), max(-factors, factors)) elif len(factors) != 2: - raise ValueError("factors should be a number or pair of numbers.") + raise ValueError(f"factors should be a number or pair of numbers, got {factors}.") else: self.factors = (min(factors), max(factors)) self.factor = self.factors[0] @@ -488,7 +488,7 @@ def __init__(self, factors: tuple[float, float] | float, prob: float = 0.1, dtyp if isinstance(factors, (int, float)): self.factors = (min(-factors, factors), max(-factors, factors)) elif len(factors) != 2: - raise ValueError("factors should be a number or pair of numbers.") + raise ValueError(f"factors should be a number or pair of numbers, got {factors}.") else: self.factors = (min(factors), max(factors)) self.factor = self.factors[0] @@ -545,7 +545,7 @@ def __init__( ) -> None: RandomizableTransform.__init__(self, prob) if degree < 1: - raise ValueError("degree should be no less than 1.") + raise ValueError(f"degree should be no less than 1, got {degree}.") self.degree = degree self.coeff_range = coeff_range self.dtype = dtype @@ -725,7 +725,7 @@ class ThresholdIntensity(Transform): def __init__(self, threshold: float, above: bool = True, cval: float = 0.0) -> None: if not isinstance(threshold, (int, float)): - raise ValueError("threshold must be a float or int number.") + raise ValueError(f"threshold must be a float or int number, got {type(threshold)} {threshold}.") self.threshold = threshold self.above = above self.cval = cval @@ -812,7 +812,7 @@ class AdjustContrast(Transform): def __init__(self, gamma: float) -> None: if not isinstance(gamma, (int, float)): - raise ValueError("gamma must be a float or int number.") + raise ValueError(f"gamma must be a float or int number, got {type(gamma)} {gamma}.") self.gamma = gamma def __call__(self, img: NdarrayOrTensor) -> NdarrayOrTensor: @@ -847,7 +847,7 @@ def __init__(self, prob: float = 0.1, gamma: Sequence[float] | float = (0.5, 4.5 if isinstance(gamma, (int, float)): if gamma <= 0.5: raise ValueError( - "if gamma is single number, must greater than 0.5 and value is picked from (0.5, gamma)" + f"if gamma is a number, must greater than 0.5 and value is picked from (0.5, gamma), got {gamma}" ) self.gamma = (0.5, gamma) elif len(gamma) != 2: diff --git a/monai/transforms/io/array.py b/monai/transforms/io/array.py index 5e7e3cff88..a91f21e220 100644 --- a/monai/transforms/io/array.py +++ b/monai/transforms/io/array.py @@ -289,7 +289,7 @@ def __call__(self, filename: Sequence[PathLike] | PathLike, reader: ImageReader img_array, meta_data = reader.get_data(img) img_array = convert_to_dst_type(img_array, dst=img_array, dtype=self.dtype)[0] if not isinstance(meta_data, dict): - raise ValueError("`meta_data` must be a dict.") + raise ValueError(f"`meta_data` must be a dict, got type {type(meta_data)}.") # make sure all elements in metadata are little endian meta_data = switch_endianness(meta_data, "<") diff --git a/monai/transforms/io/dictionary.py b/monai/transforms/io/dictionary.py index 407ca24716..9f75444dc6 100644 --- a/monai/transforms/io/dictionary.py +++ b/monai/transforms/io/dictionary.py @@ -142,7 +142,9 @@ def __init__( raise TypeError(f"meta_key_postfix must be a str but is {type(meta_key_postfix).__name__}.") self.meta_keys = ensure_tuple_rep(None, len(self.keys)) if meta_keys is None else ensure_tuple(meta_keys) if len(self.keys) != len(self.meta_keys): - raise ValueError("meta_keys should have the same length as keys.") + raise ValueError( + f"meta_keys should have the same length as keys, got {len(self.keys)} and {len(self.meta_keys)}." + ) self.meta_key_postfix = ensure_tuple_rep(meta_key_postfix, len(self.keys)) self.overwriting = overwriting @@ -162,10 +164,12 @@ def __call__(self, data, reader: ImageReader | None = None): d[key] = data else: if not isinstance(data, (tuple, list)): - raise ValueError("loader must return a tuple or list (because image_only=False was used).") + raise ValueError( + f"loader must return a tuple or list (because image_only=False was used), got {type(data)}." + ) d[key] = data[0] if not isinstance(data[1], dict): - raise ValueError("metadata must be a dict.") + raise ValueError(f"metadata must be a dict, got {type(data[1])}.") meta_key = meta_key or f"{key}_{meta_key_postfix}" if meta_key in d and not self.overwriting: raise KeyError(f"Metadata with key {meta_key} already exists and overwriting=False.") diff --git a/monai/transforms/post/array.py b/monai/transforms/post/array.py index a514c43536..8e0c642d8b 100644 --- a/monai/transforms/post/array.py +++ b/monai/transforms/post/array.py @@ -216,7 +216,7 @@ def __call__( to_onehot = self.to_onehot if to_onehot is None else to_onehot if to_onehot is not None: if not isinstance(to_onehot, int): - raise ValueError("the number of classes for One-Hot must be an integer.") + raise ValueError(f"the number of classes for One-Hot must be an integer, got {type(to_onehot)}.") img_t = one_hot( img_t, num_classes=to_onehot, dim=self.kwargs.get("dim", 0), dtype=self.kwargs.get("dtype", torch.float) ) diff --git a/monai/transforms/spatial/array.py b/monai/transforms/spatial/array.py index 947ef05650..e26a15e1dc 100644 --- a/monai/transforms/spatial/array.py +++ b/monai/transforms/spatial/array.py @@ -1639,7 +1639,9 @@ def __init__( self.min_zoom = ensure_tuple(min_zoom) self.max_zoom = ensure_tuple(max_zoom) if len(self.min_zoom) != len(self.max_zoom): - raise AssertionError("min_zoom and max_zoom must have same length.") + raise ValueError( + f"min_zoom and max_zoom must have same length, got {len(self.min_zoom)} and {len(self.max_zoom)}." + ) self.mode: InterpolateMode = look_up_option(mode, InterpolateMode) self.padding_mode = padding_mode self.align_corners = align_corners diff --git a/monai/transforms/transform.py b/monai/transforms/transform.py index 470f72566c..9dd87ecf83 100644 --- a/monai/transforms/transform.py +++ b/monai/transforms/transform.py @@ -329,7 +329,7 @@ def lazy_evaluation(self): @lazy_evaluation.setter def lazy_evaluation(self, lazy_evaluation: bool): if not isinstance(lazy_evaluation, bool): - raise TypeError("'lazy_evaluation must be a bool but is of " f"type {type(lazy_evaluation)}'") + raise TypeError(f"lazy_evaluation must be a bool but is of type {type(lazy_evaluation)}") self.lazy_evaluation = lazy_evaluation diff --git a/monai/transforms/utility/array.py b/monai/transforms/utility/array.py index d1e07f7b88..44aecb94d9 100644 --- a/monai/transforms/utility/array.py +++ b/monai/transforms/utility/array.py @@ -161,7 +161,7 @@ class AsChannelFirst(Transform): def __init__(self, channel_dim: int = -1) -> None: if not (isinstance(channel_dim, int) and channel_dim >= -1): - raise AssertionError("invalid channel dimension.") + raise ValueError(f"invalid channel dimension ({channel_dim}).") self.channel_dim = channel_dim def __call__(self, img: NdarrayOrTensor) -> NdarrayOrTensor: @@ -191,7 +191,7 @@ class AsChannelLast(Transform): def __init__(self, channel_dim: int = 0) -> None: if not (isinstance(channel_dim, int) and channel_dim >= -1): - raise AssertionError("invalid channel dimension.") + raise ValueError(f"invalid channel dimension ({channel_dim}).") self.channel_dim = channel_dim def __call__(self, img: NdarrayOrTensor) -> NdarrayOrTensor: @@ -303,7 +303,7 @@ class RepeatChannel(Transform): def __init__(self, repeats: int) -> None: if repeats <= 0: - raise AssertionError("repeats count must be greater than 0.") + raise ValueError(f"repeats count must be greater than 0, got {repeats}.") self.repeats = repeats def __call__(self, img: NdarrayOrTensor) -> NdarrayOrTensor: @@ -328,7 +328,7 @@ class RemoveRepeatedChannel(Transform): def __init__(self, repeats: int) -> None: if repeats <= 0: - raise AssertionError("repeats count must be greater than 0.") + raise ValueError(f"repeats count must be greater than 0, got {repeats}.") self.repeats = repeats @@ -337,7 +337,7 @@ def __call__(self, img: NdarrayOrTensor) -> NdarrayOrTensor: Apply the transform to `img`, assuming `img` is a "channel-first" array. """ if img.shape[0] < 2: - raise AssertionError("Image must have more than one channel") + raise ValueError(f"Image must have more than one channel, got {img.shape[0]} channels.") out: NdarrayOrTensor = convert_to_tensor(img[:: self.repeats, :], track_meta=get_track_meta()) return out @@ -718,7 +718,7 @@ def __init__( """ if not isinstance(prefix, str): - raise AssertionError("prefix must be a string.") + raise ValueError(f"prefix must be a string, got {type(prefix)}.") self.prefix = prefix self.data_type = data_type self.data_shape = data_shape diff --git a/monai/transforms/utils.py b/monai/transforms/utils.py index e2cc7ed905..6560899318 100644 --- a/monai/transforms/utils.py +++ b/monai/transforms/utils.py @@ -401,7 +401,7 @@ def weighted_patch_samples( """ if w is None: - raise ValueError("w must be an ND array.") + raise ValueError("w must be an ND array, got None.") if r_state is None: r_state = np.random.RandomState() img_size = np.asarray(w.shape, dtype=int) @@ -447,7 +447,10 @@ def correct_crop_centers( spatial_size = fall_back_tuple(spatial_size, default=label_spatial_shape) if any(np.subtract(label_spatial_shape, spatial_size) < 0): if not allow_smaller: - raise ValueError("The size of the proposed random crop ROI is larger than the image size.") + raise ValueError( + "The size of the proposed random crop ROI is larger than the image size, " + f"got ROI size {spatial_size} and label image size {label_spatial_shape} respectively." + ) spatial_size = tuple(min(l, s) for l, s in zip(label_spatial_shape, spatial_size)) # Select subregion to assure valid roi @@ -555,12 +558,14 @@ def generate_label_classes_crop_centers( rand_state = np.random.random.__self__ # type: ignore if num_samples < 1: - raise ValueError("num_samples must be an int number and greater than 0.") + raise ValueError(f"num_samples must be an int number and greater than 0, got {num_samples}.") ratios_: list[float | int] = ([1] * len(indices)) if ratios is None else ratios if len(ratios_) != len(indices): - raise ValueError("random crop ratios must match the number of indices of classes.") + raise ValueError( + f"random crop ratios must match the number of indices of classes, got {len(ratios_)} and {len(indices)}." + ) if any(i < 0 for i in ratios_): - raise ValueError("ratios should not contain negative number.") + raise ValueError(f"ratios should not contain negative number, got {ratios_}.") for i, array in enumerate(indices): if len(array) == 0: @@ -925,7 +930,7 @@ def generate_spatial_bounding_box( margin = ensure_tuple_rep(margin, ndim) for m in margin: if m < 0: - raise ValueError("margin value should not be negative number.") + raise ValueError(f"margin value should not be negative number, got {margin}.") box_start = [0] * ndim box_end = [0] * ndim @@ -1065,7 +1070,7 @@ def get_unique_labels(img: NdarrayOrTensor, is_onehot: bool, discard: int | Iter applied_labels = {i for i, s in enumerate(img) if s.sum() > 0} else: if n_channels != 1: - raise ValueError("If input not one-hotted, should only be 1 channel.") + raise ValueError(f"If input not one-hotted, should only be 1 channel, got {n_channels}.") applied_labels = set(unique(img).tolist()) if discard is not None: for i in ensure_tuple(discard):