diff options
author | Théo de la Hogue | 2022-05-10 11:19:43 +0200 |
---|---|---|
committer | Théo de la Hogue | 2022-05-10 11:19:43 +0200 |
commit | f59fae48f03fc29b315b9ea750c01e147697e3ff (patch) | |
tree | 36ed8096bbf6d36045aebfb9a28d25d4d8b4bbeb /src/argaze/GazeFeatures.py | |
parent | 5c734e16bb35377d786f14bf9181044e67025a0a (diff) | |
download | argaze-f59fae48f03fc29b315b9ea750c01e147697e3ff.zip argaze-f59fae48f03fc29b315b9ea750c01e147697e3ff.tar.gz argaze-f59fae48f03fc29b315b9ea750c01e147697e3ff.tar.bz2 argaze-f59fae48f03fc29b315b9ea750c01e147697e3ff.tar.xz |
Exporting new movements.csv and movements.mp4 files.
Diffstat (limited to 'src/argaze/GazeFeatures.py')
-rw-r--r-- | src/argaze/GazeFeatures.py | 57 |
1 files changed, 52 insertions, 5 deletions
diff --git a/src/argaze/GazeFeatures.py b/src/argaze/GazeFeatures.py index 32ec571..d7466df 100644 --- a/src/argaze/GazeFeatures.py +++ b/src/argaze/GazeFeatures.py @@ -22,6 +22,7 @@ class TimeStampedGazePositions(DataStructures.TimeStampedBuffer): class Fixation(): """Define gaze fixation.""" + index: int duration: float dispersion: float centroid: GazePosition @@ -31,12 +32,18 @@ class TimeStampedFixations(DataStructures.TimeStampedBuffer): """Define timestamped buffer to store fixations.""" def __setitem__(self, key, value: Fixation): + """Force value to be a Fixation""" + + if not isinstance(value, Fixation): + raise ValueError('value must be a Fixation') + super().__setitem__(key, value) @dataclass class Saccade(): """Define gaze saccade.""" + index: int duration: float start_position: GazePosition end_position: GazePosition @@ -46,11 +53,31 @@ class TimeStampedSaccades(DataStructures.TimeStampedBuffer): def __setitem__(self, key, value: Saccade): """Force value to be a Saccade""" + if not isinstance(value, Saccade): raise ValueError('value must be a Saccade') super().__setitem__(key, value) +@dataclass +class Movement(): + """Define movement.""" + + index: int + type: str + position: GazePosition + +class TimeStampedMovements(DataStructures.TimeStampedBuffer): + """Define timestamped buffer to store movement.""" + + def __setitem__(self, key, value: Movement): + """Force value to be a Movement""" + + if not isinstance(value, Movement): + raise ValueError('value must be a Movement') + + super().__setitem__(key, value) + class MovementIdentifier(): """Abstract class to define what should provide a movement identifier.""" @@ -67,21 +94,31 @@ class MovementIdentifier(): def identify(self): - fixations = GazeFeatures.TimeStampedFixations() - saccades = GazeFeatures.TimeStampedSaccades() + fixations = TimeStampedFixations() + saccades = TimeStampedSaccades() + movements = TimeStampedMovement() for ts, item in self: if isinstance(item, GazeFeatures.Fixation): + fixations[ts] = item + for ts, position in item.positions.items(): + + movements[ts] = Movement(item.index, type(item).__name__, position) + elif isinstance(item, GazeFeatures.Saccade): + saccades[ts] = item + movements[ts] = Movement(item.index, type(item).__name__, item.start_position) + movements[ts + item.duration] = Movement(item.index, type(item).__name__, item.end_position) + else: continue - return fixations, saccades + return fixations, saccades, movements class DispersionBasedMovementIdentifier(MovementIdentifier): """Implementation of the I-DT algorithm as described in: @@ -105,6 +142,9 @@ class DispersionBasedMovementIdentifier(MovementIdentifier): self.__last_fixation = None self.__last_fixation_ts = -1 + self.__fixations_count = 0 + self.__saccades_count = 0 + def __getEuclideanDispersion(self, ts_gaze_positions_list): """Euclidian dispersion algorithm""" @@ -201,7 +241,9 @@ class DispersionBasedMovementIdentifier(MovementIdentifier): for (ts, gp) in ts_gaze_positions_list: ts_gaze_positions[round(ts)] = gp - new_fixation = Fixation(round(duration), dispersion, (round(cx), round(cy)), ts_gaze_positions) + self.__fixations_count += 1 + + new_fixation = Fixation(self.__fixations_count, round(duration), dispersion, (round(cx), round(cy)), ts_gaze_positions) new_fixation_ts = ts_list[0] if self.__last_fixation != None: @@ -211,7 +253,12 @@ class DispersionBasedMovementIdentifier(MovementIdentifier): if new_saccade_duration > 0: - new_saccade = Saccade(round(new_saccade_duration), self.__last_fixation.positions.pop_last()[1], new_fixation.positions.pop_first()[1]) + start_position_ts, start_position = self.__last_fixation.positions.pop_last() + end_position_ts, end_position = new_fixation.positions.pop_first() + + self.__saccades_count += 1 + + new_saccade = Saccade(self.__saccades_count, round(new_saccade_duration), start_position, end_position) yield round(new_saccade_ts), new_saccade |