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>
This commit is contained in:
Omkar Kabde 2026-03-13 15:12:16 +05:30 committed by GitHub
parent 600099e8ab
commit cee411689d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 164 additions and 74 deletions

View File

@ -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 = (

View File

@ -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 (

View File

@ -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 = (

View File

@ -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 = (

View File

@ -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 = (

View File

@ -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: