aboutsummaryrefslogtreecommitdiff
path: root/src/argaze/GazeAnalysis/ExploitExploreRatio.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/argaze/GazeAnalysis/ExploitExploreRatio.py')
-rw-r--r--src/argaze/GazeAnalysis/ExploitExploreRatio.py63
1 files changed, 63 insertions, 0 deletions
diff --git a/src/argaze/GazeAnalysis/ExploitExploreRatio.py b/src/argaze/GazeAnalysis/ExploitExploreRatio.py
new file mode 100644
index 0000000..eba8ec2
--- /dev/null
+++ b/src/argaze/GazeAnalysis/ExploitExploreRatio.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+
+"""Implementation of exploit vs explore ratio algorithm as described in:
+
+ **Goldberg J. H., Kotval X. P. (1999).**
+ *Computer interface evaluation using eye movements: methods and constructs.*
+ International Journal of Industrial Ergonomics (631–645).
+ [https://doi.org/10.1016/S0169-8141(98)00068-7](https://doi.org/10.1016/S0169-8141\\(98\\)00068-7)
+
+ **Dehais F., Peysakhovich V., Scannella S., Fongue J., Gateau T. (2015).**
+ *Automation surprise in aviation: Real-time solutions.*
+ Proceedings of the 33rd annual ACM conference on Human Factors in Computing Systems (2525–2534).
+ [https://doi.org/10.1145/2702123.2702521](https://doi.org/10.1145/2702123.2702521)
+"""
+
+__author__ = "Théo de la Hogue"
+__credits__ = []
+__copyright__ = "Copyright 2023, Ecole Nationale de l'Aviation Civile (ENAC)"
+__license__ = "BSD"
+
+from dataclasses import dataclass
+
+from argaze import GazeFeatures
+
+import numpy
+
+@dataclass
+class ScanPathAnalyzer(GazeFeatures.ScanPathAnalyzer):
+
+ def __post_init__(self):
+
+ pass
+
+ def analyze(self, scan_path: GazeFeatures.ScanPathType, long_fixation_duration_threshold: float = 0.) -> float:
+ """Analyze scan path."""
+
+ assert(len(scan_path) > 1)
+
+ short_fixations_durations = []
+ long_fixations_durations = []
+ saccades_durations = []
+
+ for scan_step in scan_path:
+
+ if scan_step.first_fixation.duration > long_fixation_duration_threshold:
+
+ long_fixations_durations.append(scan_step.first_fixation.duration)
+
+ else:
+
+ short_fixations_durations.append(scan_step.first_fixation.duration)
+
+ saccades_durations.append(scan_step.last_saccade.duration)
+
+ short_fixations_duration = numpy.array(short_fixations_durations).sum()
+ long_fixations_duration = numpy.array(long_fixations_durations).sum()
+ saccades_duration = numpy.array(saccades_durations).sum()
+
+ print(short_fixations_duration, long_fixations_duration, saccades_duration)
+
+ assert(saccades_duration + short_fixations_duration > 0)
+
+ return long_fixations_duration / (saccades_duration + short_fixations_duration)