From cee411689d1203324232c36fc8705e2980f2a8f5 Mon Sep 17 00:00:00 2001 From: Omkar Kabde Date: Fri, 13 Mar 2026 15:12:16 +0530 Subject: [PATCH] refactor: convert docstring examples to doctest format (#2173) * migrate docstrings (doctest - pycon) * Refine doctests in `mean_average_recall.py` and `f1_score.py` for consistent formatting * Expand doctests across metrics modules for detailed result output * Apply suggestions from code review --------- Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/supervision/metrics/f1_score.py | 48 ++++++++++++------ .../metrics/mean_average_precision.py | 32 ++++++++---- .../metrics/mean_average_recall.py | 47 +++++++++++------ src/supervision/metrics/precision.py | 50 +++++++++++++------ src/supervision/metrics/recall.py | 48 ++++++++++++------ src/supervision/utils/logger.py | 13 +++-- 6 files changed, 164 insertions(+), 74 deletions(-) diff --git a/src/supervision/metrics/f1_score.py b/src/supervision/metrics/f1_score.py index 92b527ea..9525a6dd 100644 --- a/src/supervision/metrics/f1_score.py +++ b/src/supervision/metrics/f1_score.py @@ -520,21 +520,39 @@ class F1ScoreResult: Format as a pretty string. Example: - ```python - print(f1_result) - # F1ScoreResult: - # Metric target: MetricTarget.BOXES - # Averaging method: AveragingMethod.WEIGHTED - # F1 @ 50: 0.7618 - # F1 @ 75: 0.7487 - # F1 @ thresh: [0.76175 0.76068 0.76068] - # IoU thresh: [0.5 0.55 0.6 ...] - # F1 per class: - # 0: [0.70968 0.70968 0.70968 ...] - # ... - # Small objects: ... - # Medium objects: ... - # Large objects: ... + ```pycon + >>> import numpy as np + >>> import supervision as sv + >>> from supervision.metrics import F1Score + >>> predictions = sv.Detections( + ... xyxy=np.array([[0, 0, 10, 10]]), + ... class_id=np.array([0]), + ... confidence=np.array([0.9]) + ... ) + >>> targets = sv.Detections( + ... xyxy=np.array([[0, 0, 10, 10]]), + ... class_id=np.array([0]) + ... ) + >>> f1_metric = F1Score() + >>> f1_result = f1_metric.update(predictions, targets).compute() + >>> print(f1_result) # doctest: +ELLIPSIS + F1ScoreResult: + Metric target: MetricTarget.BOXES + Averaging method: AveragingMethod.WEIGHTED + F1 @ 50: 1.0000 + F1 @ 75: 1.0000 + F1 @ thresh: [1. ... 1.] + IoU thresh: [0.5 0.55 ... 0.95] + F1 per class: + 0: [1. ... 1.] + ... + Medium objects: + F1ScoreResult: + Metric target: MetricTarget.BOXES + Averaging method: AveragingMethod.WEIGHTED + F1 @ 50: 0.0000 + ... + ``` """ out_str = ( diff --git a/src/supervision/metrics/mean_average_precision.py b/src/supervision/metrics/mean_average_precision.py index 6d063033..8d598da9 100644 --- a/src/supervision/metrics/mean_average_precision.py +++ b/src/supervision/metrics/mean_average_precision.py @@ -88,15 +88,29 @@ class MeanAveragePrecisionResult: Formats the evaluation output metrics to match the structure used by pycocotools Example: - ```python - print(map_result) - # MeanAveragePrecisionResult: - Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.464 - Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.637 - Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.203 - Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.284 - Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.497 - Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.629 + ```pycon + >>> import numpy as np + >>> import supervision as sv + >>> from supervision.metrics import MeanAveragePrecision + >>> predictions = sv.Detections( + ... xyxy=np.array([[0, 0, 10, 10]]), + ... class_id=np.array([0]), + ... confidence=np.array([0.9]) + ... ) + >>> targets = sv.Detections( + ... xyxy=np.array([[0, 0, 10, 10]]), + ... class_id=np.array([0]) + ... ) + >>> map_metric = MeanAveragePrecision() + >>> map_result = map_metric.update(predictions, targets).compute() + >>> print(map_result) # doctest: +ELLIPSIS + Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = ... + Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = ... + Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = ... + Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = ... + Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = ... + Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = ... + ``` """ if ( diff --git a/src/supervision/metrics/mean_average_recall.py b/src/supervision/metrics/mean_average_recall.py index ab74653e..01b80fd5 100644 --- a/src/supervision/metrics/mean_average_recall.py +++ b/src/supervision/metrics/mean_average_recall.py @@ -87,21 +87,38 @@ class MeanAverageRecallResult: Format as a pretty string. Example: - ```python - print(mar_results) - # MeanAverageRecallResult: - # Metric target: MetricTarget.BOXES - # mAR @ 1: 0.1362 - # mAR @ 10: 0.4239 - # mAR @ 100: 0.5241 - # max detections: [1 10 100] - # IoU thresh: [0.5 0.55 0.6 ...] - # mAR per class: - # 0: [0.78571 0.78571 0.78571 ...] - # ... - # Small objects: ... - # Medium objects: ... - # Large objects: ... + ```pycon + >>> import numpy as np + >>> import supervision as sv + >>> from supervision.metrics import MeanAverageRecall + >>> predictions = sv.Detections( + ... xyxy=np.array([[0, 0, 10, 10]]), + ... class_id=np.array([0]), + ... confidence=np.array([0.9]) + ... ) + >>> targets = sv.Detections( + ... xyxy=np.array([[0, 0, 10, 10]]), + ... class_id=np.array([0]) + ... ) + >>> mar_metric = MeanAverageRecall() + >>> mar_result = mar_metric.update(predictions, targets).compute() + >>> print(mar_result) # doctest: +ELLIPSIS + MeanAverageRecallResult: + Metric target: MetricTarget.BOXES + mAR @ 1: 1.0000 + mAR @ 10: 1.0000 + mAR @ 100: 1.0000 + max detections: [ 1 10 100] + IoU thresh: [0.5 0.55 ... 0.95] + mAR per class: + 0: [1. ... 1.] + ... + Medium objects: + MeanAverageRecallResult: + Metric target: MetricTarget.BOXES + mAR @ 1: 0.0000 + ... + ``` """ out_str = ( diff --git a/src/supervision/metrics/precision.py b/src/supervision/metrics/precision.py index 40f3b28c..223bfdbc 100644 --- a/src/supervision/metrics/precision.py +++ b/src/supervision/metrics/precision.py @@ -531,21 +531,41 @@ class PrecisionResult: Format as a pretty string. Example: - ```python - print(precision_result) - # PrecisionResult: - # Metric target: MetricTarget.BOXES - # Averaging method: AveragingMethod.WEIGHTED - # P @ 50: 0.8099 - # P @ 75: 0.7969 - # P @ thresh: [0.80992 0.80905 0.80905 ...] - # IoU thresh: [0.5 0.55 0.6 ...] - # Precision per class: - # 0: [0.64706 0.64706 0.64706 ...] - # ... - # Small objects: ... - # Medium objects: ... - # Large objects: ... + ```pycon + >>> import numpy as np + >>> import supervision as sv + >>> from supervision.metrics import Precision + >>> predictions = sv.Detections( + ... xyxy=np.array([[0, 0, 10, 10]]), + ... class_id=np.array([0]), + ... confidence=np.array([0.9]) + ... ) + >>> targets = sv.Detections( + ... xyxy=np.array([[0, 0, 10, 10]]), + ... class_id=np.array([0]) + ... ) + >>> precision_metric = Precision() + >>> precision_result = precision_metric.update( + ... predictions, targets + ... ).compute() + >>> print(precision_result) # doctest: +ELLIPSIS + PrecisionResult: + Metric target: MetricTarget.BOXES + Averaging method: AveragingMethod.WEIGHTED + P @ 50: 1.0000 + P @ 75: 1.0000 + P @ thresh: [1. ... 1.] + IoU thresh: [0.5 0.55 ... 0.95] + Precision per class: + 0: [1. ... 1.] + ... + Medium objects: + PrecisionResult: + Metric target: MetricTarget.BOXES + Averaging method: AveragingMethod.WEIGHTED + P @ 50: 0.0000 + ... + ``` """ out_str = ( diff --git a/src/supervision/metrics/recall.py b/src/supervision/metrics/recall.py index db0bad46..2d428cbb 100644 --- a/src/supervision/metrics/recall.py +++ b/src/supervision/metrics/recall.py @@ -529,21 +529,39 @@ class RecallResult: Format as a pretty string. Example: - ```python - print(recall_result) - # RecallResult: - # Metric target: MetricTarget.BOXES - # Averaging method: AveragingMethod.WEIGHTED - # R @ 50: 0.7615 - # R @ 75: 0.7462 - # R @ thresh: [0.76151 0.76011 0.76011 0.75732 ...] - # IoU thresh: [0.5 0.55 0.6 ...] - # Recall per class: - # 0: [0.78571 0.78571 0.78571 ...] - # ... - # Small objects: ... - # Medium objects: ... - # Large objects: ... + ```pycon + >>> import numpy as np + >>> import supervision as sv + >>> from supervision.metrics import Recall + >>> predictions = sv.Detections( + ... xyxy=np.array([[0, 0, 10, 10]]), + ... class_id=np.array([0]), + ... confidence=np.array([0.9]) + ... ) + >>> targets = sv.Detections( + ... xyxy=np.array([[0, 0, 10, 10]]), + ... class_id=np.array([0]) + ... ) + >>> recall_metric = Recall() + >>> recall_result = recall_metric.update(predictions, targets).compute() + >>> print(recall_result) # doctest: +ELLIPSIS + RecallResult: + Metric target: MetricTarget.BOXES + Averaging method: AveragingMethod.WEIGHTED + R @ 50: 1.0000 + R @ 75: 1.0000 + R @ thresh: [1. ... 1.] + IoU thresh: [0.5 0.55 ... 0.95] + Recall per class: + 0: [1. ... 1.] + ... + Medium objects: + RecallResult: + Metric target: MetricTarget.BOXES + Averaging method: AveragingMethod.WEIGHTED + R @ 50: 0.0000 + ... + ``` """ out_str = ( diff --git a/src/supervision/utils/logger.py b/src/supervision/utils/logger.py index 3a9f9d54..f6ac66e8 100644 --- a/src/supervision/utils/logger.py +++ b/src/supervision/utils/logger.py @@ -24,12 +24,15 @@ def _get_logger(name: str = "supervision", level: int | None = None) -> logging. A configured `logging.Logger` instance. Example: - ```python - from supervision.utils.logger import _get_logger + ```pycon + >>> from supervision.utils.logger import _get_logger + >>> import logging + >>> logger = _get_logger("test_logger", level=logging.INFO) + >>> logger.name + 'test_logger' + >>> logger.level == logging.INFO + True - logger = _get_logger(__name__) - logger.info("Processing started") - logger.warning("File not found, using default") ``` """ if level is None: