From 69d4c0e31450fd5e0c0ec01d4cceaa55940e6262 Mon Sep 17 00:00:00 2001 From: Théo de la Hogue Date: Wed, 14 Jun 2023 12:05:07 +0200 Subject: Testing and documenting ExploitExploreRatio class. --- docs/user_guide/gaze_analysis/scan_path.md | 1 + .../GazeAnalysis/ExploitExploreRatio.py | 6 ++---- src/argaze/GazeAnalysis/ExploitExploreRatio.py | 10 ++++++--- src/argaze/utils/demo_gaze_features_run.py | 24 ++++++++++++++++++++++ 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/docs/user_guide/gaze_analysis/scan_path.md b/docs/user_guide/gaze_analysis/scan_path.md index 67600ac..c84c879 100644 --- a/docs/user_guide/gaze_analysis/scan_path.md +++ b/docs/user_guide/gaze_analysis/scan_path.md @@ -21,6 +21,7 @@ Some scan path analysis are available thanks to [GazeAnalysis](/argaze/#argaze.G * [K-Coefficient](/argaze/#argaze.GazeAnalysis.KCoefficient) * [Nearest Neighbor Index](/argaze/#argaze.GazeAnalysis.NearestNeighborIndex) +* [Exploit Explore Ratio](/argaze/#argaze.GazeAnalysis.ExploitExploreRatio) ### Example diff --git a/src/argaze.test/GazeAnalysis/ExploitExploreRatio.py b/src/argaze.test/GazeAnalysis/ExploitExploreRatio.py index febfec7..9cfcc0b 100644 --- a/src/argaze.test/GazeAnalysis/ExploitExploreRatio.py +++ b/src/argaze.test/GazeAnalysis/ExploitExploreRatio.py @@ -30,10 +30,8 @@ class TestScanPathAnalyzer(unittest.TestCase): xxr = xxr_analyzer.analyze(scan_path) - print(xxr) - - # Check exploit explore ratio - self.assertGreaterEqual(xxr, 0) + # Check exploit explore ratio: it should greater than 1 because of build_scan_path + self.assertGreaterEqual(xxr, 1.) if __name__ == '__main__': diff --git a/src/argaze/GazeAnalysis/ExploitExploreRatio.py b/src/argaze/GazeAnalysis/ExploitExploreRatio.py index eba8ec2..c5d2392 100644 --- a/src/argaze/GazeAnalysis/ExploitExploreRatio.py +++ b/src/argaze/GazeAnalysis/ExploitExploreRatio.py @@ -31,8 +31,12 @@ class ScanPathAnalyzer(GazeFeatures.ScanPathAnalyzer): pass - def analyze(self, scan_path: GazeFeatures.ScanPathType, long_fixation_duration_threshold: float = 0.) -> float: - """Analyze scan path.""" + def analyze(self, scan_path: GazeFeatures.ScanPathType, short_fixation_duration_threshold: float = 0.) -> float: + """Analyze scan path. + + Parameters: + short_fixation_duration_threshold: time below which a fixation is considered to be short and so as exploratory. + """ assert(len(scan_path) > 1) @@ -42,7 +46,7 @@ class ScanPathAnalyzer(GazeFeatures.ScanPathAnalyzer): for scan_step in scan_path: - if scan_step.first_fixation.duration > long_fixation_duration_threshold: + if scan_step.first_fixation.duration > short_fixation_duration_threshold: long_fixations_durations.append(scan_step.first_fixation.duration) diff --git a/src/argaze/utils/demo_gaze_features_run.py b/src/argaze/utils/demo_gaze_features_run.py index cbaf720..65952ec 100644 --- a/src/argaze/utils/demo_gaze_features_run.py +++ b/src/argaze/utils/demo_gaze_features_run.py @@ -107,6 +107,10 @@ def main(): nni_analysis = 0 enable_nni_analysis = False + xxr_analyzer = ExploitExploreRatio.ScanPathAnalyzer() + xxr_analysis = 0. + enable_xxr_analysis = False + gaze_movement_lock = threading.Lock() # Init timestamp @@ -125,6 +129,7 @@ def main(): nonlocal ngram_analysis nonlocal entropy_analysis nonlocal nni_analysis + nonlocal xxr_analysis # Edit millisecond timestamp data_ts = int((time.time() - start_ts) * 1e3) @@ -222,6 +227,10 @@ def main(): nni_analysis = nni_analyzer.analyze(raw_scan_path, window_size) + if enable_xxr_analysis: + + xxr_analysis = xxr_analyzer.analyze(raw_scan_path) + # Append saccade to aoi scan path aoi_scan_path.append_saccade(data_ts, gaze_movement) @@ -290,6 +299,11 @@ def main(): on_off = 'on' if enable_nni_analysis else 'off' display_hide = 'hide' if enable_nni_analysis else 'display' cv2.putText(aoi_matrix, f'Nearest neighbor index: {on_off} (Press \'i\' key to {display_hide})', (20, 320), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 255) if enable_nni_analysis else (255, 255, 255), 1, cv2.LINE_AA) + + # Write xxr help + on_off = 'on' if enable_xxr_analysis else 'off' + display_hide = 'hide' if enable_xxr_analysis else 'display' + cv2.putText(aoi_matrix, f'Exploit Explore Ratio: {on_off} (Press \'x\' key to {display_hide})', (20, 360), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 255) if enable_xxr_analysis else (255, 255, 255), 1, cv2.LINE_AA) # Check fixation identification if gaze_movement_identifier[identification_mode].current_fixation != None: @@ -403,6 +417,11 @@ def main(): cv2.putText(aoi_matrix, f'Nearest neighbor index: {nni_analysis:.3f}', (20, window_size[1]-320), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 255), 1, cv2.LINE_AA) + # Write XXR + if enable_xxr_analysis: + + cv2.putText(aoi_matrix, f'Exploit explore ratio: {xxr_analysis:.3f}', (20, window_size[1]-320), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 255), 1, cv2.LINE_AA) + # Unlock gaze movement identification gaze_movement_lock.release() @@ -468,6 +487,11 @@ def main(): enable_nni_analysis = not enable_nni_analysis + # Enable XXR analysis with 'x' key + if key_pressed == 120: + + enable_xxr_analysis = not enable_xxr_analysis + # Stop calibration by pressing 'Esc' key if key_pressed == 27: break -- cgit v1.1