-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_trails_drawing_metrics.py
More file actions
116 lines (85 loc) · 3.77 KB
/
test_trails_drawing_metrics.py
File metadata and controls
116 lines (85 loc) · 3.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
"""Test cases for drawing_metrics.py functions."""
import numpy as np
import pandas as pd
import pytest
from graphomotor.core import models
from graphomotor.features.trails import drawing_metrics
from graphomotor.io import reader
def test_get_total_errors() -> None:
"""Test ValueError when total_number_of_errors column doesn't exist."""
invalid_df = pd.DataFrame({"some_other_column": [0, 1, 2]})
drawing = models.Drawing(
data=invalid_df, task_name="trails", metadata={"id": "5555555"}
)
with pytest.raises(
ValueError,
match="Drawing data does not contain 'total_number_of_errors' column.",
):
drawing_metrics.get_total_errors(drawing)
def test_valid_total_errors() -> None:
"""Test case with valid total_number_of_errors column."""
filepath = "tests/sample_data/[5000000]648b6b868819c1120b4f6ce3-trail4.csv"
drawing = reader.load_drawing_data(filepath)
result = drawing_metrics.get_total_errors(drawing)
assert result == {"total_errors": 1.0}
def test_percent_accurate_paths_missing_columns() -> None:
"""Test ValueError when required columns are missing."""
invalid_df = pd.DataFrame({"some_other_column": [0, 1, 2]})
drawing = models.Drawing(
data=invalid_df, task_name="trails", metadata={"id": "5555555"}
)
with pytest.raises(
ValueError,
match="DataFrame must contain 'correct_path' and 'actual_path' columns.",
):
drawing_metrics.percent_accurate_paths(drawing)
def test_percent_accurate_paths_sample_data() -> None:
"""Test percent_accurate_paths with sample drawing data."""
filepath = "tests/sample_data/[5000000]648b6b868819c1120b4f6ce3-trail4.csv"
drawing = reader.load_drawing_data(filepath)
result = drawing_metrics.percent_accurate_paths(drawing)
assert result == {"percent_accurate_paths": 100.0}
def test_smoothness_less_than_three_points() -> None:
"""Less than 3 points cannot define curvature."""
points = pd.DataFrame({"x": [0, 1], "y": [0, 1]})
assert drawing_metrics.calculate_smoothness(points) == 0.0
def test_smoothness_straight_line() -> None:
"""Collinear points have zero curvature."""
points = pd.DataFrame({"x": [0, 1, 2, 3], "y": [0, 0, 0, 0]})
assert drawing_metrics.calculate_smoothness(points) == 0.0
def test_smoothness_single_right_angle() -> None:
"""A single 90-degree corner should produce a large smoothness value.
(non-zero), since sharp turns are penalized.
"""
points = pd.DataFrame({"x": [0, 1, 1], "y": [0, 0, 1]})
expected = np.pi / 2
smoothness = drawing_metrics.calculate_smoothness(points)
assert np.isclose(smoothness, expected)
def test_smoothness_varied_angles() -> None:
"""Multiple angles should produce RMS curvature.
Path has a 90° turn followed by a 45° turn.
"""
points = pd.DataFrame({"x": [0, 1, 1, 2], "y": [0, 0, 1, 2]})
c1 = np.pi / 2
c2 = (np.pi / 4) / ((1 + np.sqrt(2)) / 2)
expected = np.sqrt((c1**2 + c2**2) / 2)
smoothness = drawing_metrics.calculate_smoothness(points)
assert np.isclose(smoothness, expected)
def test_smoothness_zero_length_segments() -> None:
"""Zero-length segments should be skipped; no angles → smoothness 0."""
points = pd.DataFrame({"x": [0, 1, 1, 2], "y": [0, 0, 0, 0]})
smoothness = drawing_metrics.calculate_smoothness(points)
assert smoothness == 0.0
def test_smoothness_single_180_degree_turn() -> None:
"""A single 180-degree turn should produce a very large smoothness value.
Since it represents maximal curvature.
"""
points = pd.DataFrame(
{
"x": [0, 1, 0],
"y": [0, 0, 0],
}
)
expected = np.pi
smoothness = drawing_metrics.calculate_smoothness(points)
assert np.isclose(smoothness, expected)