aboutsummaryrefslogtreecommitdiff
path: root/src/argaze.test/GazeFeatures.py
diff options
context:
space:
mode:
authorThéo de la Hogue2024-02-28 13:57:31 +0100
committerThéo de la Hogue2024-02-28 13:57:31 +0100
commit5f915a84f32405dc8bddae4ecbf95f4745af6fbc (patch)
treef882ba799e2fc8a824274fe32ac4ae48511690a9 /src/argaze.test/GazeFeatures.py
parentd6754148e3866cd8051ff01d1dbbd5534664bc2a (diff)
downloadargaze-5f915a84f32405dc8bddae4ecbf95f4745af6fbc.zip
argaze-5f915a84f32405dc8bddae4ecbf95f4745af6fbc.tar.gz
argaze-5f915a84f32405dc8bddae4ecbf95f4745af6fbc.tar.bz2
argaze-5f915a84f32405dc8bddae4ecbf95f4745af6fbc.tar.xz
More work on TimestampedGazePositions and GazeMovements.
Diffstat (limited to 'src/argaze.test/GazeFeatures.py')
-rw-r--r--src/argaze.test/GazeFeatures.py122
1 files changed, 59 insertions, 63 deletions
diff --git a/src/argaze.test/GazeFeatures.py b/src/argaze.test/GazeFeatures.py
index fdc140d..7d18976 100644
--- a/src/argaze.test/GazeFeatures.py
+++ b/src/argaze.test/GazeFeatures.py
@@ -39,28 +39,27 @@ def random_gaze_positions(size, frame_dimension: tuple[float, float] = (1, 1)):
return ts_gaze_positions
-@dataclass(frozen=True)
class TestFixation(GazeFeatures.Fixation):
"""Define basic fixation class for test."""
- def __post_init__(self):
+ def __init__(self, positions: GazeFeatures.TimeStampedGazePositions = (), finished: bool = False, message: str = None, **kwargs):
- super().__post_init__()
+ super().__init__(positions, finished, message, **kwargs)
- points = self.positions.values()
- points_x, points_y = [p[0] for p in points], [p[1] for p in points]
- points_array = numpy.column_stack([points_x, points_y])
- centroid_array = numpy.array([numpy.mean(points_x), numpy.mean(points_y)])
+ if positions:
- # Update frozen focus attribute using centroid
- object.__setattr__(self, 'focus', (centroid_array[0], centroid_array[1]))
+ positions_array = numpy.asarray(self.values())
+ centroid = numpy.mean(positions_array, axis=0)
+
+ # Update focus attribute using centroid
+ self.focus = (centroid[0], centroid[1])
-@dataclass(frozen=True)
class TestSaccade(GazeFeatures.Saccade):
"""Define basic saccade for test."""
- def __post_init__(self):
- super().__post_init__()
+ def __init__(self, positions: GazeFeatures.TimeStampedGazePositions = (), finished: bool = False, message: str = None, **kwargs):
+
+ super().__init__(positions, finished, message, **kwargs)
class TestGazePositionClass(unittest.TestCase):
"""Test GazePosition class."""
@@ -265,11 +264,11 @@ class TestTimeStampedGazePositionsClass(unittest.TestCase):
self.assertEqual(ts_gaze_positions[0].precision, 15)
self.assertEqual(bool(ts_gaze_positions[0]), True)
- # Check third gaze position is correctly stored and accessible as a UnvalidGazePosition
+ # Check third gaze position is correctly stored and accessible as a GazePosition
self.assertIsInstance(ts_gaze_positions[2], GazeFeatures.GazePosition)
self.assertEqual(numpy.isnan(ts_gaze_positions[2].precision), True)
self.assertEqual(bool(ts_gaze_positions[2]), False)
-
+
def test_as_dataframe(self):
"""Test inherited as_dataframe method."""
@@ -309,19 +308,19 @@ class TestTimeStampedGazePositionsClass(unittest.TestCase):
class TestGazeMovementClass(unittest.TestCase):
"""Test GazeMovement class."""
- @unittest.skip("DEBUG")
+
def test_new(self):
"""Test GazeMovement creation."""
abstract_gaze_movement = GazeFeatures.GazeMovement(random_gaze_positions(0))
# Check abstract GazeMovement
- self.assertEqual(len(abstract_gaze_movement.positions), 0)
- self.assertEqual(abstract_gaze_movement.duration, -1)
- self.assertEqual(abstract_gaze_movement.amplitude, -1)
- self.assertEqual(abstract_gaze_movement.valid, False)
+ self.assertEqual(len(abstract_gaze_movement), 0)
+ self.assertEqual(abstract_gaze_movement.duration, 0)
+ self.assertEqual(abstract_gaze_movement.amplitude, 0)
+ self.assertEqual(bool(abstract_gaze_movement), False)
self.assertEqual(abstract_gaze_movement.finished, False)
- @unittest.skip("DEBUG")
+
def test_finish(self):
"""Test GazeMovement finishing."""
@@ -340,25 +339,22 @@ class TestGazeMovementClass(unittest.TestCase):
self.assertEqual(abstract_gaze_movement.finished, True)
self.assertEqual(abstract_gaze_movement_ref.finished, True)
-class TestUnvalidGazeMovementClass(unittest.TestCase):
- """Test UnvalidGazeMovement class."""
- @unittest.skip("DEBUG")
- def test_new(self):
- """Test UnvalidGazeMovement creation."""
+ def test_message(self):
+ """Test GazeMovement creation with message only."""
- unvalid_gaze_movement = GazeFeatures.UnvalidGazeMovement('test')
+ gaze_movement = GazeFeatures.GazeMovement(message='test')
- # Check UnvalidGazeMovement
- self.assertEqual(len(unvalid_gaze_movement.positions), 0)
- self.assertEqual(unvalid_gaze_movement.duration, -1)
- self.assertEqual(unvalid_gaze_movement.amplitude, -1)
- self.assertEqual(unvalid_gaze_movement.valid, False)
- self.assertEqual(unvalid_gaze_movement.finished, False)
- self.assertEqual(unvalid_gaze_movement.message, 'test')
+ # Check GazeMovement
+ self.assertEqual(len(gaze_movement), 0)
+ self.assertEqual(gaze_movement.duration, 0)
+ self.assertEqual(gaze_movement.amplitude, 0)
+ self.assertEqual(bool(gaze_movement), False)
+ self.assertEqual(gaze_movement.finished, False)
+ self.assertEqual(gaze_movement.message, 'test')
class TestScanStepClass(unittest.TestCase):
"""Test ScanStep class."""
- @unittest.skip("DEBUG")
+
def test_new(self):
"""Test ScanStep creation."""
@@ -371,7 +367,7 @@ class TestScanStepClass(unittest.TestCase):
self.assertEqual(scan_step.first_fixation, fixation)
self.assertEqual(scan_step.last_saccade, saccade)
self.assertGreater(scan_step.duration, 0)
-
+
def build_scan_path(size, frame_dimension: tuple[float, float] = (1, 1)):
"""Build scan path"""
@@ -380,18 +376,18 @@ def build_scan_path(size, frame_dimension: tuple[float, float] = (1, 1)):
for i in range(size):
fixation = TestFixation(random_gaze_positions(10, frame_dimension))
- ts, _ = fixation.positions.first
+ ts, _ = fixation.first
scan_path.append_fixation(ts, fixation)
saccade = TestSaccade(random_gaze_positions(2, frame_dimension))
- ts, _ = saccade.positions.first
+ ts, _ = saccade.first
scan_path.append_saccade(ts, saccade)
return scan_path
class TestScanPathClass(unittest.TestCase):
"""Test ScanPath class."""
- @unittest.skip("DEBUG")
+
def test_new(self):
"""Test ScanPath creation."""
@@ -400,7 +396,7 @@ class TestScanPathClass(unittest.TestCase):
self.assertEqual(len(scan_path), 0)
self.assertEqual(scan_path.duration, 0)
- @unittest.skip("DEBUG")
+
def test_append(self):
"""Test ScanPath append methods."""
@@ -408,7 +404,7 @@ class TestScanPathClass(unittest.TestCase):
# Append a saccade that should be ignored
saccade = TestSaccade(random_gaze_positions(2))
- ts, _ = saccade.positions.first
+ ts = saccade[0].timestamp
new_step = scan_path.append_saccade(ts, saccade)
@@ -419,7 +415,7 @@ class TestScanPathClass(unittest.TestCase):
# Append first fixation
fixation_A = TestFixation(random_gaze_positions(10))
- ts, _ = fixation_A.positions.first
+ ts = fixation_A[0].timestamp
new_step = scan_path.append_fixation(ts, fixation_A)
@@ -430,7 +426,7 @@ class TestScanPathClass(unittest.TestCase):
# Append consecutive saccade
saccade_A = TestSaccade(random_gaze_positions(2))
- ts, _ = saccade_A.positions.first
+ ts = saccade_A[0].timestamp
new_step_A = scan_path.append_saccade(ts, saccade_A)
@@ -443,7 +439,7 @@ class TestScanPathClass(unittest.TestCase):
# Append 2 consecutive fixations then a saccade
fixation_B1 = TestFixation(random_gaze_positions(10))
- ts, _ = fixation_B1.positions.first
+ ts = fixation_B1[0].timestamp
new_step = scan_path.append_fixation(ts, fixation_B1)
@@ -453,7 +449,7 @@ class TestScanPathClass(unittest.TestCase):
self.assertEqual(new_step, None)
fixation_B2 = TestFixation(random_gaze_positions(10))
- ts, _ = fixation_B2.positions.first
+ ts = fixation_B2[0].timestamp
new_step = scan_path.append_fixation(ts, fixation_B2)
@@ -463,7 +459,7 @@ class TestScanPathClass(unittest.TestCase):
self.assertEqual(new_step, None)
saccade_B = TestSaccade(random_gaze_positions(2))
- ts, _ = saccade_B.positions.first
+ ts = saccade_B[0].timestamp
new_step_B = scan_path.append_saccade(ts, saccade_B)
@@ -476,19 +472,19 @@ class TestScanPathClass(unittest.TestCase):
class TestAOIScanStepClass(unittest.TestCase):
"""Test AOIScanStep class."""
- @unittest.skip("DEBUG")
+
def test_new(self):
"""Test AOIScanStep creation."""
movements = GazeFeatures.TimeStampedGazeMovements()
fixation = TestFixation(random_gaze_positions(10))
- ts, _ = fixation.positions.first
- movements[ts] = fixation
+ ts = fixation[0].timestamp
+ movements.append(fixation)
saccade = TestSaccade(random_gaze_positions(2))
- ts, _ = saccade.positions.first
- movements[ts] = saccade
+ ts = saccade[0].timestamp
+ movements.append(saccade)
aoi_scan_step = GazeFeatures.AOIScanStep(movements, 'Test')
@@ -505,12 +501,12 @@ class TestAOIScanStepClass(unittest.TestCase):
movements = GazeFeatures.TimeStampedGazeMovements()
saccade = TestSaccade(random_gaze_positions(2))
- ts, _ = saccade.positions.first
- movements[ts] = saccade
+ ts = saccade[0].timestamp
+ movements.append(saccade)
fixation = TestFixation(random_gaze_positions(10))
- ts, _ = fixation.positions.first
- movements[ts] = fixation
+ ts = fixation[0].timestamp
+ movements.append(fixation)
# Check that aoi scan step creation fail
with self.assertRaises(GazeFeatures.AOIScanStepError):
@@ -528,11 +524,11 @@ def build_aoi_scan_path(expected_aoi, aoi_path):
for aoi in aoi_path:
fixation = TestFixation(random_gaze_positions(10))
- ts, _ = fixation.positions.first
+ ts, _ = fixation.first
aoi_scan_path.append_fixation(ts, fixation, aoi)
saccade = TestSaccade(random_gaze_positions(2))
- ts, _ = saccade.positions.first
+ ts, _ = saccade.first
aoi_scan_path.append_saccade(ts, saccade)
return aoi_scan_path
@@ -555,7 +551,7 @@ class TestAOIScanPathClass(unittest.TestCase):
# Append fixation on A aoi
fixation_A = TestFixation(random_gaze_positions(10))
- ts, _ = fixation_A.positions.first
+ ts, _ = fixation_A.first
new_step = aoi_scan_path.append_fixation(ts, fixation_A, 'Foo')
@@ -566,7 +562,7 @@ class TestAOIScanPathClass(unittest.TestCase):
# Append saccade
saccade_A = TestSaccade(random_gaze_positions(2))
- ts, _ = saccade_A.positions.first
+ ts, _ = saccade_A.first
new_step = aoi_scan_path.append_saccade(ts, saccade_A)
@@ -577,7 +573,7 @@ class TestAOIScanPathClass(unittest.TestCase):
# Append fixation on B aoi
fixation_B = TestFixation(random_gaze_positions(10))
- ts, _ = fixation_B.positions.first
+ ts, _ = fixation_B.first
new_step_A = aoi_scan_path.append_fixation(ts, fixation_B, 'Bar')
@@ -588,8 +584,8 @@ class TestAOIScanPathClass(unittest.TestCase):
self.assertEqual(new_step_A.aoi, 'Foo')
self.assertEqual(new_step_A.letter, 'A')
- first_ts, _ = fixation_A.positions.first
- last_ts, _ = saccade_A.positions.last
+ first_ts, _ = fixation_A.first
+ last_ts, _ = saccade_A.last
self.assertEqual(new_step_A.duration, last_ts - first_ts)
@@ -603,7 +599,7 @@ class TestAOIScanPathClass(unittest.TestCase):
# Append fixation on A aoi
fixation = TestFixation(random_gaze_positions(10))
- ts, _ = fixation.positions.first
+ ts, _ = fixation.first
new_step = aoi_scan_path.append_fixation(ts, fixation, 'Foo')
@@ -613,7 +609,7 @@ class TestAOIScanPathClass(unittest.TestCase):
# Append fixation on B aoi
fixation = TestFixation(random_gaze_positions(10))
- ts, _ = fixation.positions.first
+ ts, _ = fixation.first
# Check that aoi scan step creation fail when fixation is appened after another fixation
with self.assertRaises(GazeFeatures.AOIScanStepError):