diff options
author | Théo de la Hogue | 2023-06-15 16:59:25 +0200 |
---|---|---|
committer | Théo de la Hogue | 2023-06-15 16:59:25 +0200 |
commit | a097f0495ff95a410455a134082bb7a059a8da74 (patch) | |
tree | 47ebc73ff8d16e04810114c3230bfe97d5f8a14d /src | |
parent | a08cd2838e5c506f1af6f966f0681eae60a1573e (diff) | |
download | argaze-a097f0495ff95a410455a134082bb7a059a8da74.zip argaze-a097f0495ff95a410455a134082bb7a059a8da74.tar.gz argaze-a097f0495ff95a410455a134082bb7a059a8da74.tar.bz2 argaze-a097f0495ff95a410455a134082bb7a059a8da74.tar.xz |
Adding and testing GazeMovementIdentifier generator.
Diffstat (limited to 'src')
-rw-r--r-- | src/argaze.test/GazeAnalysis/DispersionThresholdIdentification.py | 36 | ||||
-rw-r--r-- | src/argaze/GazeFeatures.py | 27 |
2 files changed, 63 insertions, 0 deletions
diff --git a/src/argaze.test/GazeAnalysis/DispersionThresholdIdentification.py b/src/argaze.test/GazeAnalysis/DispersionThresholdIdentification.py index 712308a..eba80c8 100644 --- a/src/argaze.test/GazeAnalysis/DispersionThresholdIdentification.py +++ b/src/argaze.test/GazeAnalysis/DispersionThresholdIdentification.py @@ -311,6 +311,42 @@ class TestDispersionThresholdIdentificationClass(unittest.TestCase): self.assertGreaterEqual(fixation.duration, 2 * size * min_time) self.assertLessEqual(fixation.duration, 2 * size * max_time) + def test_identification_generator(self): + """Test DispersionThresholdIdentification identification using generator.""" + + size = 10 + center_A = (0, 0) + center_B = (50, 50) + deviation_max = 10 + min_time = 0.01 + max_time = 0.1 + + 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 = ts_gaze_positions_A.append(ts_gaze_positions_B) + + gaze_movement_identifier = DispersionThresholdIdentification.GazeMovementIdentifier(deviation_max_threshold=deviation_max, duration_min_threshold=max_time*2) + + fixation_count = 0 + + for ts, gaze_movement in gaze_movement_identifier(ts_gaze_positions): + + if GazeFeatures.is_fixation(gaze_movement): + + self.assertEqual(len(gaze_movement.positions.keys()), size-fixation_count) + self.assertLessEqual(gaze_movement.deviation_max, deviation_max) + self.assertGreaterEqual(gaze_movement.duration, size * min_time) + self.assertLessEqual(gaze_movement.duration, size * max_time) + + fixation_count += 1 + + elif GazeFeatures.is_saccade(gaze_movement): + + self.assertEqual(len(gaze_movement.positions.keys()), 1) + self.assertGreaterEqual(gaze_movement.duration, 0.) + self.assertLessEqual(gaze_movement.duration, 0.) + if __name__ == '__main__': unittest.main()
\ No newline at end of file diff --git a/src/argaze/GazeFeatures.py b/src/argaze/GazeFeatures.py index 870cd3c..cf1f7b8 100644 --- a/src/argaze/GazeFeatures.py +++ b/src/argaze/GazeFeatures.py @@ -405,6 +405,33 @@ class GazeMovementIdentifier(): return ts_fixations, ts_saccades, ts_status + def __call__(self, ts_gaze_positions: TimeStampedGazePositions) -> Tuple[int|float, GazeMovementType]: + """GazeMovement generator. + + Parameters: + ts_gaze_positions: timestamped gaze positions to process. + + Returns: + timestamp + gaze movement + """ + + assert(type(ts_gaze_positions) == TimeStampedGazePositions) + + # 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(): + + gaze_movement = self.identify(ts, gaze_position, terminate=(ts == last_ts)) + + if gaze_movement: + + start_ts, start_position = gaze_movement.positions.first + + yield start_ts, gaze_movement + ScanStepType = TypeVar('ScanStep', bound="ScanStep") # Type definition for type annotation convenience |