diff options
author | Théo de la Hogue | 2024-02-29 16:40:52 +0100 |
---|---|---|
committer | Théo de la Hogue | 2024-02-29 16:40:52 +0100 |
commit | addbaaef4265688916f355d4cde24c96f0605cf9 (patch) | |
tree | 56913dc313697f794eef9691760baad9a4df2273 /src/argaze.test/GazeAnalysis/VelocityThresholdIdentification.py | |
parent | 9c42e9f1ee8208e14dadcb73cf030a9baef236ed (diff) | |
parent | ac8cc60d27a57c892354214b04327878b511cc44 (diff) | |
download | argaze-addbaaef4265688916f355d4cde24c96f0605cf9.zip argaze-addbaaef4265688916f355d4cde24c96f0605cf9.tar.gz argaze-addbaaef4265688916f355d4cde24c96f0605cf9.tar.bz2 argaze-addbaaef4265688916f355d4cde24c96f0605cf9.tar.xz |
Merge branch 'fast_idt' into logging
Diffstat (limited to 'src/argaze.test/GazeAnalysis/VelocityThresholdIdentification.py')
-rw-r--r-- | src/argaze.test/GazeAnalysis/VelocityThresholdIdentification.py | 127 |
1 files changed, 53 insertions, 74 deletions
diff --git a/src/argaze.test/GazeAnalysis/VelocityThresholdIdentification.py b/src/argaze.test/GazeAnalysis/VelocityThresholdIdentification.py index 425d592..262cfc0 100644 --- a/src/argaze.test/GazeAnalysis/VelocityThresholdIdentification.py +++ b/src/argaze.test/GazeAnalysis/VelocityThresholdIdentification.py @@ -17,8 +17,8 @@ from argaze.GazeAnalysis import VelocityThresholdIdentification import numpy -def build_gaze_fixation(size: int, start_position: tuple, deviation_max: float, min_time: float, max_time: float, start_ts: float = 0., validity: list = []): - """ Generate N TimeStampedGazePositions strating from a starting position for testing purpose. +def build_gaze_fixation(size: int, center: tuple, deviation_max: float, min_time: float, max_time: float, start_ts: float = 0., validity: list = []): + """ Generate N TimeStampedGazePsoitions dispersed around a center point for testing purpose. Timestamps are current time after random sleep (second). GazePositions are random values. """ @@ -26,8 +26,6 @@ def build_gaze_fixation(size: int, start_position: tuple, deviation_max: float, start_time = time.time() - last_valid_position = start_position - for i in range(0, size): # Sleep a random time @@ -43,21 +41,19 @@ def build_gaze_fixation(size: int, start_position: tuple, deviation_max: float, if valid: # Edit gaze position - random_x = last_valid_position[0] + deviation_max * (random.random() - 0.5) / math.sqrt(2) - random_y = last_valid_position[1] + deviation_max * (random.random() - 0.5) / math.sqrt(2) - + random_x = center[0] + deviation_max * (random.random() - 0.5) / math.sqrt(2) + random_y = center[1] + deviation_max * (random.random() - 0.5) / math.sqrt(2) gaze_position = GazeFeatures.GazePosition((random_x, random_y)) - # Remember last valid gaze position - last_valid_position = gaze_position.value - else: - gaze_position = GazeFeatures.UnvalidGazePosition() + gaze_position = GazeFeatures.GazePosition() + + # Timestamp gaze position + gaze_position.timestamp = time.time() - start_time + start_ts # Store gaze position - ts = time.time() - start_time + start_ts - ts_gaze_positions[ts] = gaze_position + ts_gaze_positions.append(gaze_position) return ts_gaze_positions @@ -91,11 +87,13 @@ def build_gaze_saccade(size: int, center_A: tuple, center_B: tuple, min_time: fl else: - gaze_position = GazeFeatures.UnvalidGazePosition() + gaze_position = GazeFeatures.GazePosition() + + # Timestamp gaze position + gaze_position.timestamp = time.time() - start_time + start_ts # Store gaze position - ts = time.time() - start_time + start_ts - ts_gaze_positions[ts] = gaze_position + ts_gaze_positions.append(gaze_position) return ts_gaze_positions @@ -122,9 +120,9 @@ class TestVelocityThresholdIdentificationClass(unittest.TestCase): self.assertEqual(len(ts_status), size - 1) # Check fixation - ts, fixation = ts_fixations.pop_first() + fixation = ts_fixations.pop(0) - self.assertEqual(len(fixation.positions.keys()), size - 1) + self.assertEqual(len(fixation), size - 1) self.assertGreaterEqual(fixation.duration, (size - 2) * min_time) self.assertLessEqual(fixation.duration, (size - 2) * max_time) self.assertLessEqual(fixation.finished, True) @@ -141,9 +139,9 @@ class TestVelocityThresholdIdentificationClass(unittest.TestCase): velocity_max = deviation_max / min_time ts_gaze_positions_A = build_gaze_fixation(size, center_A, deviation_max, min_time, max_time) - ts_gaze_positions_B = build_gaze_fixation(size, center_B, deviation_max, min_time, max_time, start_ts=ts_gaze_positions_A.last[0]) + ts_gaze_positions_B = build_gaze_fixation(size, center_B, deviation_max, min_time, max_time, start_ts=ts_gaze_positions_A[-1].timestamp) - ts_gaze_positions = ts_gaze_positions_A.append(ts_gaze_positions_B) + ts_gaze_positions = ts_gaze_positions_A + ts_gaze_positions_B gaze_movement_identifier = VelocityThresholdIdentification.GazeMovementIdentifier(velocity_max_threshold=velocity_max, duration_min_threshold=max_time*2) ts_fixations, ts_saccades, ts_status = gaze_movement_identifier.browse(ts_gaze_positions) @@ -154,42 +152,36 @@ class TestVelocityThresholdIdentificationClass(unittest.TestCase): self.assertEqual(len(ts_status), size * 2 - 1) # Check first fixation - ts, fixation = ts_fixations.pop_first() + fixation = ts_fixations.pop(0) - self.assertEqual(len(fixation.positions.keys()), size - 1) + self.assertEqual(len(fixation), size - 1) self.assertGreaterEqual(fixation.duration, (size - 2) * min_time) self.assertLessEqual(fixation.duration, (size - 2) * max_time) self.assertLessEqual(fixation.finished, True) # Check first saccade - ts, saccade = ts_saccades.pop_first() + saccade = ts_saccades.pop(0) - self.assertEqual(len(saccade.positions.keys()), 2) + self.assertEqual(len(saccade), 2) self.assertGreaterEqual(saccade.duration, min_time) self.assertLessEqual(saccade.duration, max_time) self.assertLessEqual(saccade.finished, True) # Check that last position of a movement is equal to first position of next movement - last_ts, last_position = fixation.positions.last - first_ts, first_position = saccade.positions.first - - self.assertEqual(last_ts, first_ts) - self.assertEqual(last_position.value, first_position.value) + self.assertEqual(fixation[-1].timestamp, saccade[0].timestamp) + self.assertEqual(fixation[-1].value, saccade[0].value) # Check second fixation - ts, fixation = ts_fixations.pop_first() + fixation = ts_fixations.pop(0) - self.assertEqual(len(fixation.positions.keys()), size) + self.assertEqual(len(fixation), size) self.assertGreaterEqual(fixation.duration, (size - 1) * min_time) self.assertLessEqual(fixation.duration, (size - 1) * max_time) self.assertLessEqual(fixation.finished, True) # Check that last position of a movement is equal to first position of next movement - last_ts, last_position = saccade.positions.last - first_ts, first_position = fixation.positions.first - - self.assertEqual(last_ts, first_ts) - self.assertEqual(last_position.value, first_position.value) + self.assertEqual(saccade[-1].timestamp, fixation[0].timestamp) + self.assertEqual(saccade[-1].value, fixation[0].value) def test_fixation_and_short_saccade_identification(self): """Test VelocityThresholdIdentification fixation and saccade identification.""" @@ -205,10 +197,10 @@ class TestVelocityThresholdIdentificationClass(unittest.TestCase): velocity_max = deviation_max / min_time ts_gaze_positions_A = build_gaze_fixation(size, center_A, deviation_max, min_time, max_time) - ts_move_positions = build_gaze_saccade(move, out_A, center_B, min_time, min_time, start_ts=ts_gaze_positions_A.last[0]) - ts_gaze_positions_B = build_gaze_fixation(size, center_B, deviation_max, min_time, max_time, start_ts=ts_move_positions.last[0]) + ts_move_positions = build_gaze_saccade(move, out_A, center_B, min_time, min_time, start_ts=ts_gaze_positions_A[-1].timestamp) + ts_gaze_positions_B = build_gaze_fixation(size, center_B, deviation_max, min_time, max_time, start_ts=ts_move_positions[-1].timestamp) - ts_gaze_positions = ts_gaze_positions_A.append(ts_move_positions).append(ts_gaze_positions_B) + ts_gaze_positions = ts_gaze_positions_A + ts_move_positions + ts_gaze_positions_B gaze_movement_identifier = VelocityThresholdIdentification.GazeMovementIdentifier(velocity_max_threshold=velocity_max, duration_min_threshold=max_time*2) ts_fixations, ts_saccades, ts_status = gaze_movement_identifier.browse(ts_gaze_positions) @@ -219,42 +211,36 @@ class TestVelocityThresholdIdentificationClass(unittest.TestCase): self.assertEqual(len(ts_status), 2 * size + move - 1) # Check first fixation - ts, fixation = ts_fixations.pop_first() + fixation = ts_fixations.pop(0) - self.assertEqual(len(fixation.positions.keys()), size - 1) # BUG: NOT ALWAYS TRUE !!! + self.assertEqual(len(fixation), size - 1) # BUG: NOT ALWAYS TRUE !!! self.assertGreaterEqual(fixation.duration, (size - 2) * min_time) self.assertLessEqual(fixation.duration, (size - 2) * max_time) self.assertLessEqual(fixation.finished, True) # Check first saccade - ts, saccade = ts_saccades.pop_first() + saccade = ts_saccades.pop(0) - self.assertEqual(len(saccade.positions.keys()), move + 2) + self.assertEqual(len(saccade), move + 2) self.assertGreaterEqual(saccade.duration, (move + 1) * min_time) self.assertLessEqual(saccade.duration, (move + 1) * max_time) self.assertLessEqual(saccade.finished, True) # Check that last position of a movement is equal to first position of next movement - last_ts, last_position = fixation.positions.last - first_ts, first_position = saccade.positions.first - - self.assertEqual(last_ts, first_ts) - self.assertEqual(last_position.value, first_position.value) + self.assertEqual(fixation[-1].timestamp, saccade[0].timestamp) + self.assertEqual(fixation[-1].value, saccade[0].value) # Check second fixation - ts, fixation = ts_fixations.pop_first() + fixation = ts_fixations.pop(0) - self.assertEqual(len(fixation.positions.keys()), size) + self.assertEqual(len(fixation), size) self.assertGreaterEqual(fixation.duration, (size - 1) * min_time) self.assertLessEqual(fixation.duration, (size - 1) * max_time) self.assertLessEqual(fixation.finished, True) # Check that last position of a movement is equal to first position of next movement - last_ts, last_position = saccade.positions.last - first_ts, first_position = fixation.positions.first - - self.assertEqual(last_ts, first_ts) - self.assertEqual(last_position.value, first_position.value) + self.assertEqual(saccade[-1], fixation[0]) + self.assertEqual(saccade[-1].value, fixation[0].value) def test_invalid_gaze_position(self): """Test VelocityThresholdIdentification fixation and saccade identification with invalid gaze position.""" @@ -278,17 +264,17 @@ class TestVelocityThresholdIdentificationClass(unittest.TestCase): self.assertEqual(len(ts_status), len(validity)-5) # Check first fixation - ts, fixation = ts_fixations.pop_first() + fixation = ts_fixations.pop(0) - self.assertEqual(len(fixation.positions.keys()), 6) + self.assertEqual(len(fixation), 6) self.assertGreaterEqual(fixation.duration, 5 * min_time) self.assertLessEqual(fixation.duration, 5 * max_time) self.assertLessEqual(fixation.finished, True) # Check second fixation - ts, fixation = ts_fixations.pop_first() + fixation = ts_fixations.pop(0) - self.assertEqual(len(fixation.positions.keys()), 4) + self.assertEqual(len(fixation), 4) self.assertGreaterEqual(fixation.duration, 3 * min_time) self.assertLessEqual(fixation.duration, 3 * max_time) self.assertLessEqual(fixation.finished, True) @@ -305,34 +291,27 @@ class TestVelocityThresholdIdentificationClass(unittest.TestCase): velocity_max = deviation_max / min_time ts_gaze_positions_A = build_gaze_fixation(size, center_A, deviation_max, min_time, max_time) - ts_gaze_positions_B = build_gaze_fixation(size, center_B, deviation_max, min_time, max_time, start_ts=ts_gaze_positions_A.last[0]) + ts_gaze_positions_B = build_gaze_fixation(size, center_B, deviation_max, min_time, max_time, start_ts=ts_gaze_positions_A[-1].timestamp) - ts_gaze_positions = ts_gaze_positions_A.append(ts_gaze_positions_B) + ts_gaze_positions = ts_gaze_positions_A + ts_gaze_positions_B gaze_movement_identifier = VelocityThresholdIdentification.GazeMovementIdentifier(velocity_max_threshold=velocity_max, duration_min_threshold=max_time*2) - - # Get last ts to terminate identification on last gaze position - last_ts, _ = ts_gaze_positions.last # Iterate on gaze positions - for ts, gaze_position in ts_gaze_positions.items(): + for gaze_position in ts_gaze_positions: - finished_gaze_movement = gaze_movement_identifier.identify(ts, gaze_position, terminate=(ts == last_ts)) + finished_gaze_movement = gaze_movement_identifier.identify(gaze_position.timestamp, gaze_position, terminate=(gaze_position.timestamp == ts_gaze_positions[-1])) # Check that last gaze position date is not equal to given gaze position date - if finished_gaze_movement.valid: + if finished_gaze_movement: - last_ts, _ = finished_gaze_movement.positions.last - - self.assertNotEqual(last_ts, ts) + self.assertNotEqual(finished_gaze_movement[-1].timestamp, gaze_position.timestamp) # Check that last gaze position date of current movement is equal to given gaze position date current_gaze_movement = gaze_movement_identifier.current_gaze_movement - if current_gaze_movement.valid: - - last_ts, _ = current_gaze_movement.positions.last + if current_gaze_movement: - self.assertEqual(last_ts, ts) + self.assertEqual(current_gaze_movement[-1].timestamp, gaze_position.timestamp) if __name__ == '__main__': |