aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThéo de la Hogue2023-05-10 15:11:55 +0200
committerThéo de la Hogue2023-05-10 15:11:55 +0200
commitdb46ad2f06512a6ed3b398c54558470b85e41d26 (patch)
tree864a90f09ebe7e5cf7672480dffb20a142daa174
parentdb65cd2c55a66f76760f1460d3209bcfa0b4df34 (diff)
downloadargaze-db46ad2f06512a6ed3b398c54558470b85e41d26.zip
argaze-db46ad2f06512a6ed3b398c54558470b85e41d26.tar.gz
argaze-db46ad2f06512a6ed3b398c54558470b85e41d26.tar.bz2
argaze-db46ad2f06512a6ed3b398c54558470b85e41d26.tar.xz
Adding fucntion tot test fixation or saccade. Adding focus attribute to fixation.
-rw-r--r--src/argaze/GazeFeatures.py39
1 files changed, 30 insertions, 9 deletions
diff --git a/src/argaze/GazeFeatures.py b/src/argaze/GazeFeatures.py
index 2510cb2..95d90e1 100644
--- a/src/argaze/GazeFeatures.py
+++ b/src/argaze/GazeFeatures.py
@@ -54,17 +54,25 @@ class GazePosition():
return self.precision is not None
+ def distance(self, gaze_position) -> float:
+ """Distance to another gaze positions."""
+
+ distance = (self.value[0] - gaze_position.value[0])**2 + (self.value[1] - gaze_position.value[1])**2
+ distance = numpy.sqrt(distance)
+
+ return distance
+
def overlap(self, gaze_position, both=False) -> float:
"""Does this gaze position overlap another gaze position considering its precision?
Set both to True to test if the other gaze position overlaps this one too."""
- dist = (self.value[0] - gaze_position.value[0])**2 + (self.value[1] - gaze_position.value[1])**2
- dist = numpy.sqrt(dist)
+ distance = (self.value[0] - gaze_position.value[0])**2 + (self.value[1] - gaze_position.value[1])**2
+ distance = numpy.sqrt(distance)
if both:
- return dist < min(self.precision, gaze_position.precision)
+ return distance < min(self.precision, gaze_position.precision)
else:
- return dist < self.precision
+ return distance < self.precision
def draw(self, frame, color=(0, 255, 255), draw_precision=True):
"""Draw gaze position point and precision circle."""
@@ -171,10 +179,18 @@ class GazeMovement():
class Fixation(GazeMovement):
"""Define abstract fixation as gaze movement."""
+ focus: tuple = field(init=False)
+ """Representative position of the fixation."""
+
def __post_init__(self):
super().__post_init__()
+def is_fixation(gaze_movement):
+ """Is a gaze movement a fixation?"""
+
+ return type(gaze_movement).__bases__[0] == Fixation or type(gaze_movement) == Fixation
+
class Saccade(GazeMovement):
"""Define abstract saccade as gaze movement."""
@@ -182,6 +198,11 @@ class Saccade(GazeMovement):
super().__post_init__()
+def is_saccade(gaze_movement):
+ """Is a gaze movement a saccade?"""
+
+ return type(gaze_movement).__bases__[0] == Saccade or type(gaze_movement) == Saccade
+
TimeStampedGazeMovementsType = TypeVar('TimeStampedGazeMovements', bound="TimeStampedGazeMovements")
# Type definition for type annotation convenience
@@ -260,7 +281,7 @@ class GazeMovementIdentifier():
gaze_movement = self.identify(ts, gaze_position, terminate=(ts == last_ts))
- if isinstance(gaze_movement, Fixation):
+ if is_fixation(gaze_movement):
start_ts, start_position = gaze_movement.positions.first
@@ -270,7 +291,7 @@ class GazeMovementIdentifier():
ts_status[ts] = GazeStatus.from_position(position, 'Fixation', len(ts_fixations))
- elif isinstance(gaze_movement, Saccade):
+ elif is_saccade(gaze_movement):
start_ts, start_position = gaze_movement.positions.first
@@ -316,13 +337,13 @@ class VisualScanStep():
def __post_init__(self):
# First movement have to be a fixation
- if type(self.first_fixation).__bases__[0] != Fixation and type(self.first_fixation) != Fixation:
+ if not is_fixation(self.first_fixation):
raise VisualScanStepError('First step movement is not a fixation', self.aoi)
# Last movement have to be a saccade
- if type(self.last_saccade).__bases__[0] != Saccade and type(self.last_saccade) != Saccade:
-
+ if not is_saccade(self.last_saccade):
+
raise VisualScanStepError('Last step movement is not a saccade', self.aoi)
@property