diff --git a/src/globox/annotation.py b/src/globox/annotation.py index 254a091..128f6b3 100644 --- a/src/globox/annotation.py +++ b/src/globox/annotation.py @@ -33,8 +33,12 @@ def __init__( """ if image_size is not None: img_w, img_h = image_size - assert img_w > 0 and img_h > 0 - assert int(img_w) == img_w and int(img_h) == img_h + assert ( + img_w > 0 and img_h > 0 + ), f"Image size '({img_h}, {img_w})' should be positive." + assert ( + int(img_w) == img_w and int(img_h) == img_h + ), f"Image size '({img_h}, {img_w})' components should be integers." self._image_id = image_id self._image_size = image_size @@ -54,8 +58,12 @@ def image_size(self) -> "Optional[tuple[int, int]]": def image_size(self, image_size: "Optional[tuple[int, int]]"): if image_size is not None: img_w, img_h = image_size - assert img_w > 0 and img_h > 0 - assert int(img_w) == img_w and int(img_h) == img_h + assert ( + img_w > 0 and img_h > 0 + ), f"Image size '({img_h}, {img_w})' should be positive." + assert ( + int(img_w) == img_w and int(img_h) == img_h + ), f"Image size '({img_h}, {img_w})' components should be integers." self._image_size = image_size @property @@ -102,7 +110,9 @@ def from_txt( path = Path(file_path).expanduser().resolve() if image_id is None: - assert image_extension.startswith(".") + assert image_extension.startswith( + "." + ), f"Image extension '{image_extension}' should start with a dot." image_id = path.with_suffix(image_extension).name try: @@ -610,7 +620,7 @@ def to_via_json( ) -> dict: path = Path(image_folder).expanduser().resolve() - assert path.is_dir() + assert path.is_dir(), f"Filepath '{path}' is not a folder or does not exist." image_id = self.image_id image_path = path / image_id diff --git a/src/globox/annotationset.py b/src/globox/annotationset.py index 2993301..462d135 100644 --- a/src/globox/annotationset.py +++ b/src/globox/annotationset.py @@ -187,7 +187,9 @@ def from_folder( ) -> "AnnotationSet": folder = Path(folder).expanduser().resolve() - assert folder.is_dir() + assert ( + folder.is_dir() + ), f"Filepath '{folder}' is not a folder or does not exist." files = list(glob(folder, extension, recursive=recursive)) return AnnotationSet.from_iter(parser, files, verbose=verbose) @@ -213,8 +215,12 @@ def from_txt( folder = Path(folder).expanduser().resolve() - assert folder.is_dir() - assert image_extension.startswith(".") + assert ( + folder.is_dir() + ), f"Filepath '{folder}' is not a folder or does not exist." + assert image_extension.startswith( + "." + ), f"Image extension '{image_extension}' should start with a dot." if relative: assert image_folder is not None, ( @@ -224,7 +230,9 @@ def from_txt( if image_folder is not None: image_folder = Path(image_folder).expanduser().resolve() - assert image_folder.is_dir() + assert ( + image_folder.is_dir() + ), f"Filepath '{image_folder}' is not a folder or does not exist." def _get_annotation(file: Path) -> Annotation: image_id = file.with_suffix(image_extension).name @@ -840,7 +848,7 @@ def save_coco( if path.suffix == "": path = path.with_suffix(".json") - assert path.suffix == ".json" + assert path.suffix == ".json", f"Path '{path}' suffix should be '.json'." content = self.to_coco( label_to_id=label_to_id, @@ -858,7 +866,7 @@ def save_openimage(self, path: PathLike, *, verbose: bool = False): if path.suffix == "": path = path.with_suffix(".csv") - assert path.suffix == ".csv" + assert path.suffix == ".csv", f"Path '{path}' suffix should be '.csv'." fields = ( "ImageID", @@ -937,7 +945,7 @@ def save_cvat(self, path: PathLike, *, verbose: bool = False): if path.suffix == "": path = path.with_suffix(".xml") - assert path.suffix == ".xml" + assert path.suffix == ".xml", f"Path '{path}' suffix should be '.xml'." content = self.to_cvat(verbose=verbose) content = et.tostring(content, encoding="unicode") @@ -981,7 +989,7 @@ def save_via_json( if path.suffix == "": path = path.with_suffix(".json") - assert path.suffix == ".json" + assert path.suffix == ".json", f"Path '{path}' suffix should be '.json'." output = self.to_via_json( image_folder=image_folder, diff --git a/src/globox/boundingbox.py b/src/globox/boundingbox.py index e693c2c..6feb19b 100644 --- a/src/globox/boundingbox.py +++ b/src/globox/boundingbox.py @@ -608,7 +608,7 @@ def to_cvat(self) -> et.Element: def to_via_json( self, *, label_key: str = "label_id", confidence_key: str = "confidence" ) -> dict: - assert label_key != confidence_key + assert label_key != confidence_key, f"Label key '{label_key}' and confidence key '{confidence_key}' should be different." shape_attributes = { "name": "rect", diff --git a/src/globox/cli.py b/src/globox/cli.py index 960a0b3..b1ca95e 100644 --- a/src/globox/cli.py +++ b/src/globox/cli.py @@ -367,7 +367,9 @@ def evaluate( def main(): args = parse_args() - assert args.threads is None or args.threads > 0 + assert ( + args.threads is None or args.threads > 0 + ), f"The number of threads '{args.threads}' should either be None or be greater than 0." mode = args.mode if mode == "convert": diff --git a/src/globox/errors.py b/src/globox/errors.py index 53418b0..601ef14 100644 --- a/src/globox/errors.py +++ b/src/globox/errors.py @@ -1,11 +1,7 @@ from pathlib import Path -class BaseException(Exception): - pass - - -class UnknownImageFormat(BaseException): +class UnknownImageFormat(Exception): pass diff --git a/src/globox/evaluation.py b/src/globox/evaluation.py index 7ebf3cc..dd2a2b7 100644 --- a/src/globox/evaluation.py +++ b/src/globox/evaluation.py @@ -34,8 +34,10 @@ def __init__( self._npos = npos self._cache: dict[str, Any] = {} - assert self._npos >= 0 - assert len(self._tps) == len(self._scores) + assert self._npos >= 0, f"'npos' ({npos}) should be greater than or equal to 0." + assert len(self._tps) == len( + self._scores + ), f"The number of 'tps' ({len(self._tps)}) should be equal to the number of 'scores' ({len(self._scores)})." def __iadd__(self, other: "PartialEvaluationItem") -> "PartialEvaluationItem": self._tps += other._tps @@ -442,7 +444,9 @@ def evaluate_annotation( size_range: "tuple[float, float]", labels: Optional[Iterable[str]] = None, ) -> PartialEvaluation: - assert prediction.image_id == ground_truth.image_id + assert ( + prediction.image_id == ground_truth.image_id + ), f"The prediction image id '{prediction.image_id}' should be the same as the ground truth image id '{ground_truth.image_id}'." preds = grouping(prediction.boxes, lambda box: box.label) refs = grouping(ground_truth.boxes, lambda box: box.label) @@ -468,10 +472,18 @@ def evaluate_boxes( max_detections: int, size_range: "tuple[float, float]", ) -> PartialEvaluationItem: - assert all(p.is_detection for p in predictions) - assert all(g.is_ground_truth for g in ground_truths) - assert all_equal(p.label for p in predictions) - assert all_equal(g.label for g in ground_truths) + assert all( + p.is_detection for p in predictions + ), f"Prediction annotations should not contain ground truth annotations." + assert all( + g.is_ground_truth for g in ground_truths + ), f"Ground truth annotations should not contain prediction annotations." + assert all_equal( + p.label for p in predictions + ), f"The prediction boxes should have the same label." + assert all_equal( + g.label for g in ground_truths + ), f"The ground truth boxes should have the same label." cls._assert_params(iou_threshold, max_detections, size_range) @@ -523,11 +535,17 @@ def evaluate_boxes( def _assert_params( iou_threshold: float, max_detections: int, size_range: "tuple[float, float]" ): - assert 0.0 <= iou_threshold <= 1.0 - assert max_detections >= 0 + assert ( + 0.0 <= iou_threshold <= 1.0 + ), f"the IoU threshold ({iou_threshold}) should be between 0 and 1." + assert ( + max_detections >= 0 + ), f"The maximum number of detections ({max_detections}) should be positive." low, high = size_range - assert low >= 0.0 and high >= low + assert ( + low >= 0.0 and high >= low + ), f"The size range '({low}, {high})' should be positive and non-empty, i.e. 0 < size_range[0] <= size_range[1]." def clear_cache(self): self._cached_evaluate.cache_clear() diff --git a/src/globox/file_utils.py b/src/globox/file_utils.py index 662d944..06b270e 100644 --- a/src/globox/file_utils.py +++ b/src/globox/file_utils.py @@ -16,7 +16,7 @@ def glob( assert all( e.startswith(".") for e in extensions - ), "Parameter `extension` should start with a dot." + ), f"Parameter `extensions' ({extensions}) should all start with a dot." path = Path(folder).expanduser().resolve()