supervision/test/dataset/test_utils.py

242 lines
7.1 KiB
Python

from contextlib import ExitStack as DoesNotRaise
from typing import List, TypeVar, Optional, Tuple, Dict
import pytest
from supervision import Detections
from supervision.dataset.utils import train_test_split, merge_class_lists, build_class_index_mapping, \
map_detections_class_id
from test.utils import mock_detections
T = TypeVar("T")
@pytest.mark.parametrize(
'data, train_ratio, random_state, shuffle, expected_result, exception',
[
(
[],
0.5,
None,
False,
([], []),
DoesNotRaise()
), # empty data
(
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
0.5,
None,
False,
([0, 1, 2, 3, 4], [5, 6, 7, 8, 9]),
DoesNotRaise()
), # data with 10 numbers and 50% train split
(
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
1.0,
None,
False,
([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], []),
DoesNotRaise()
), # data with 10 numbers and 100% train split
(
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
0.0,
None,
False,
([], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
DoesNotRaise()
), # data with 10 numbers and 0% train split
(
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'],
0.5,
None,
False,
(['a', 'b', 'c', 'd', 'e'], ['f', 'g', 'h', 'i', 'j']),
DoesNotRaise()
), # data with 10 chars and 50% train split
(
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
0.5,
23,
True,
([7, 8, 5, 6, 3], [2, 9, 0, 1, 4]),
DoesNotRaise()
), # data with 10 numbers and 50% train split with 23 random seed
(
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
0.5,
32,
True,
([4, 6, 0, 8, 9], [5, 7, 2, 3, 1]),
DoesNotRaise()
), # data with 10 numbers and 50% train split with 23 random seed
]
)
def test_train_test_split(
data: List[T],
train_ratio: float,
random_state: int,
shuffle: bool,
expected_result: Optional[Tuple[List[T], List[T]]],
exception: Exception
) -> None:
with exception:
result = train_test_split(data=data, train_ratio=train_ratio, random_state=random_state, shuffle=shuffle)
assert result == expected_result
@pytest.mark.parametrize(
'class_lists, expected_result, exception',
[
(
[],
[],
DoesNotRaise()
), # empty class lists
(
[
['dog', 'person']
],
['dog', 'person'],
DoesNotRaise()
), # single class list; already alphabetically sorted
(
[
['person', 'dog']
],
['dog', 'person'],
DoesNotRaise()
), # single class list; not alphabetically sorted
(
[
['dog', 'person'],
['dog', 'person']
],
['dog', 'person'],
DoesNotRaise()
), # two class lists; the same classes; already alphabetically sorted
(
[
['dog', 'person'],
['cat']
],
['cat', 'dog', 'person'],
DoesNotRaise()
), # two class lists; different classes; already alphabetically sorted
]
)
def test_merge_class_maps(class_lists: List[List[str]], expected_result: List[str], exception: Exception) -> None:
with exception:
result = merge_class_lists(class_lists=class_lists)
assert result == expected_result
@pytest.mark.parametrize(
'source_classes, target_classes, expected_result, exception',
[
(
[],
[],
{},
DoesNotRaise()
), # empty class lists
(
[],
['dog', 'person'],
{},
DoesNotRaise()
), # empty source class list
(
['dog', 'person'],
[],
None,
pytest.raises(ValueError)
), # empty target class list
(
['dog', 'person'],
['dog', 'person'],
{0: 0, 1: 1},
DoesNotRaise()
), # same class lists
(
['dog', 'person'],
['person', 'dog'],
{0: 1, 1: 0},
DoesNotRaise()
), # same class lists but not alphabetically sorted
(
['dog', 'person'],
['cat', 'dog', 'person'],
{0: 1, 1: 2},
DoesNotRaise()
), # source class list is a subset of target class list
(
['dog', 'person'],
['cat', 'dog'],
None,
pytest.raises(ValueError)
), # source class list is not a subset of target class list
]
)
def test_build_class_index_mapping(
source_classes: List[str],
target_classes: List[str],
expected_result: Optional[Dict[int, int]],
exception: Exception
) -> None:
with exception:
result = build_class_index_mapping(source_classes=source_classes, target_classes=target_classes)
assert result == expected_result
@pytest.mark.parametrize(
'source_to_target_mapping, detections, expected_result, exception',
[
(
{},
mock_detections(xyxy=[[0, 0, 10, 10]], class_id=[0]),
None,
pytest.raises(ValueError)
), # empty mapping
(
{0: 1},
mock_detections(xyxy=[[0, 0, 10, 10]], class_id=[0]),
mock_detections(xyxy=[[0, 0, 10, 10]], class_id=[1]),
DoesNotRaise()
), # single mapping
(
{0: 1, 1: 2},
mock_detections(xyxy=[[0, 0, 10, 10]], class_id=[0]),
mock_detections(xyxy=[[0, 0, 10, 10]], class_id=[1]),
DoesNotRaise()
), # multiple mappings
(
{0: 1, 1: 2},
mock_detections(xyxy=[[0, 0, 10, 10], [0, 0, 10, 10]], class_id=[0, 1]),
mock_detections(xyxy=[[0, 0, 10, 10], [0, 0, 10, 10]], class_id=[1, 2]),
DoesNotRaise()
), # multiple mappings
(
{0: 1, 1: 2},
mock_detections(xyxy=[[0, 0, 10, 10]], class_id=[2]),
None,
pytest.raises(ValueError)
), # class_id not in mapping
(
{0: 1, 1: 2},
mock_detections(xyxy=[[0, 0, 10, 10]], class_id=[0], confidence=[0.5]),
mock_detections(xyxy=[[0, 0, 10, 10]], class_id=[1], confidence=[0.5]),
DoesNotRaise(),
), # confidence is not None
]
)
def test_map_detections_class_id(
source_to_target_mapping: Dict[int, int],
detections: Detections,
expected_result: Optional[Detections],
exception: Exception
) -> None:
with exception:
result = map_detections_class_id(source_to_target_mapping=source_to_target_mapping, detections=detections)
assert result == expected_result