aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/user_guide/gaze_analysis_pipeline/advanced_topics/scripting.md22
-rw-r--r--src/argaze.test/GazeAnalysis/DispersionThresholdIdentification.py2
-rw-r--r--src/argaze.test/GazeAnalysis/VelocityThresholdIdentification.py2
-rw-r--r--src/argaze/ArFeatures.py13
-rw-r--r--src/argaze/GazeAnalysis/DeviationCircleCoverage.py34
-rw-r--r--src/argaze/GazeAnalysis/DispersionThresholdIdentification.py16
-rw-r--r--src/argaze/GazeAnalysis/FocusPointInside.py16
-rw-r--r--src/argaze/GazeAnalysis/VelocityThresholdIdentification.py15
-rw-r--r--src/argaze/GazeFeatures.py27
-rw-r--r--src/argaze/utils/demo_data/demo_frame_logger.py8
10 files changed, 74 insertions, 81 deletions
diff --git a/docs/user_guide/gaze_analysis_pipeline/advanced_topics/scripting.md b/docs/user_guide/gaze_analysis_pipeline/advanced_topics/scripting.md
index 4935847..19d277f 100644
--- a/docs/user_guide/gaze_analysis_pipeline/advanced_topics/scripting.md
+++ b/docs/user_guide/gaze_analysis_pipeline/advanced_topics/scripting.md
@@ -74,21 +74,21 @@ Calling [ArFrame.look](../../../argaze.md/#argaze.ArFeatures.ArFrame.look) metho
try:
# Look ArFrame at a timestamped gaze position
- ar_frame.look(timestamp, gaze_position):
+ ar_frame.look(timestamped_gaze_position):
# Do something with last gaze position
- ... ar_frame.last_gaze_position
+ ... ar_frame.last_gaze_position()
# Check if a gaze movement has been identified
- if ar_frame.last_gaze_movement and ar_frame.last_gaze_movement.is_finished():
+ if ar_frame.last_gaze_movement() and ar_frame.last_gaze_movement().is_finished():
# Do something with identified fixation
- if GazeFeatures.is_fixation(ar_frame.last_gaze_movement):
+ if GazeFeatures.is_fixation(ar_frame.last_gaze_movement()):
...
# Do something with identified saccade
- elif GazeFeatures.is_saccade(ar_frame.last_gaze_movement):
+ elif GazeFeatures.is_saccade(ar_frame.last_gaze_movement()):
...
@@ -103,7 +103,7 @@ Calling [ArFrame.look](../../../argaze.md/#argaze.ArFeatures.ArFrame.look) metho
for layer_name, ar_layer in ar_frame.layers.items():
# Do something with last looked aoi name
- ... ar_frame.last_looked_aoi_name
+ ... ar_frame.last_looked_aoi_name()
if ar_layer.is_analysis_available():
@@ -119,11 +119,11 @@ Calling [ArFrame.look](../../../argaze.md/#argaze.ArFeatures.ArFrame.look) metho
Let's understand the meaning of each data.
-### *ar_frame.last_gaze_position*
+### *ar_frame.last_gaze_position()*
This is the last calibrated [GazePosition](../../../argaze.md/#argaze.GazeFeatures.GazePosition) returned by [GazePositionCalibrator](../../../argaze.md/#argaze.GazeFeatures.GazePositionCalibrator) if one is instanciated else, it is the last given [GazePosition](../../../argaze.md/#argaze.GazeFeatures.GazePosition).
-### *ar_frame.last_gaze_movement*
+### *ar_frame.last_gaze_movement()*
Last [GazeMovement](../../../argaze.md/#argaze.GazeFeatures.GazeMovement) identified by [ArFrame.gaze_movement_identifier](../../../argaze.md/#argaze.ArFeatures.ArFrame) object from incoming consecutive timestamped gaze positions. If no gaze movement have been identified, it returns an empty [GazeMovement](../../../argaze.md/#argaze.GazeFeatures.GazeMovement).
@@ -134,19 +134,19 @@ Then, the last gaze movement type can be tested thanks to [GazeFeatures.is_fixat
### *ar_frame.is_analysis_available()*
-This method allows to know when new scan path analysis are available.
+To know when new scan path analysis is available.
### *ar_frame.analysis()*
This an iterator to access to all scan path analysis.
-### *ar_layer.last_looked_aoi_name*
+### *ar_layer.last_looked_aoi_name()*
The name of the last aoi matching done by [AoiMatcher](../../../argaze.md/#argaze.GazeFeatures.AoiMatcher) if one is instanciated else, it is a None value.
### *ar_layer.is_analysis_available()*
-This flag allows to know when new aoi scan path analysis are available.
+To know when new aoi scan path analysis is available.
### *ar_layer.analysis()*
diff --git a/src/argaze.test/GazeAnalysis/DispersionThresholdIdentification.py b/src/argaze.test/GazeAnalysis/DispersionThresholdIdentification.py
index 0bb8ed7..1c54bd1 100644
--- a/src/argaze.test/GazeAnalysis/DispersionThresholdIdentification.py
+++ b/src/argaze.test/GazeAnalysis/DispersionThresholdIdentification.py
@@ -381,7 +381,7 @@ class TestDispersionThresholdIdentificationClass(unittest.TestCase):
# Check that last gaze position date of current fixation is equal to given gaze position date
# NOTE: This is not true for saccade as, for I-DT, there is a minimal time window while the gaze movement is unknown
- current_gaze_movement = gaze_movement_identifier.current_gaze_movement
+ current_gaze_movement = gaze_movement_identifier.current_gaze_movement()
if current_gaze_movement:
if GazeFeatures.is_fixation(current_gaze_movement):
diff --git a/src/argaze.test/GazeAnalysis/VelocityThresholdIdentification.py b/src/argaze.test/GazeAnalysis/VelocityThresholdIdentification.py
index 1c7f7e3..051265c 100644
--- a/src/argaze.test/GazeAnalysis/VelocityThresholdIdentification.py
+++ b/src/argaze.test/GazeAnalysis/VelocityThresholdIdentification.py
@@ -308,7 +308,7 @@ class TestVelocityThresholdIdentificationClass(unittest.TestCase):
self.assertNotEqual(finished_gaze_movement[-1].timestamp, gaze_position.timestamp)
# Check that last gaze position date of current movement is equal to given gaze position date
- current_gaze_movement = gaze_movement_identifier.current_gaze_movement
+ current_gaze_movement = gaze_movement_identifier.current_gaze_movement()
if current_gaze_movement:
self.assertEqual(current_gaze_movement[-1].timestamp, gaze_position.timestamp)
diff --git a/src/argaze/ArFeatures.py b/src/argaze/ArFeatures.py
index b5d1012..b3fb0e2 100644
--- a/src/argaze/ArFeatures.py
+++ b/src/argaze/ArFeatures.py
@@ -194,7 +194,6 @@ class ArLayer(DataFeatures.SharedObject, DataFeatures.PipelineStepObject):
"""Get layer's draw parameters dictionary."""
return self.__draw_parameters
- @property
def last_looked_aoi_name(self) -> str:
"""Get last looked aoi name."""
return self.__looked_aoi_name
@@ -613,12 +612,10 @@ class ArFrame(DataFeatures.SharedObject, DataFeatures.PipelineStepObject):
"""Get frame's image parameters dictionary."""
return self.__image_parameters
- @property
def last_gaze_position(self) -> object:
"""Get last calibrated gaze position"""
return self.__calibrated_gaze_position
- @property
def last_gaze_movement(self) -> object:
"""Get last identified gaze movement"""
return self.__identified_gaze_movement
@@ -951,7 +948,7 @@ class ArFrame(DataFeatures.SharedObject, DataFeatures.PipelineStepObject):
# No valid finished gaze movement: optionnaly stop in progress identification filtering
elif self.__gaze_movement_identifier is not None and not self.__filter_in_progress_identification:
- self.__identified_gaze_movement = self.__gaze_movement_identifier.current_gaze_movement
+ self.__identified_gaze_movement = self.__gaze_movement_identifier.current_gaze_movement()
# Update heatmap
if self.__heatmap is not None:
@@ -1021,16 +1018,16 @@ class ArFrame(DataFeatures.SharedObject, DataFeatures.PipelineStepObject):
# Draw current fixation if required
if draw_fixations is not None and self.__gaze_movement_identifier is not None:
- if self.__gaze_movement_identifier.current_fixation:
+ if self.__gaze_movement_identifier.current_fixation():
- self.__gaze_movement_identifier.current_fixation.draw(image, **draw_fixations)
+ self.__gaze_movement_identifier.current_fixation().draw(image, **draw_fixations)
# Draw current saccade if required
if draw_saccades is not None and self.__gaze_movement_identifier is not None:
- if self.__gaze_movement_identifier.current_saccade:
+ if self.__gaze_movement_identifier.current_saccade():
- self.__gaze_movement_identifier.current_saccade.draw(image, **draw_saccades)
+ self.__gaze_movement_identifier.current_saccade().draw(image, **draw_saccades)
# Draw layers if required
if draw_layers is not None:
diff --git a/src/argaze/GazeAnalysis/DeviationCircleCoverage.py b/src/argaze/GazeAnalysis/DeviationCircleCoverage.py
index c4c5b33..cea3e7a 100644
--- a/src/argaze/GazeAnalysis/DeviationCircleCoverage.py
+++ b/src/argaze/GazeAnalysis/DeviationCircleCoverage.py
@@ -9,7 +9,6 @@ __copyright__ = "Copyright 2023, Ecole Nationale de l'Aviation Civile (ENAC)"
__license__ = "BSD"
from typing import TypeVar, Tuple
-from dataclasses import dataclass, field
import math
from argaze import GazeFeatures, DataFeatures
@@ -21,19 +20,25 @@ import cv2
GazeMovementType = TypeVar('GazeMovement', bound="GazeMovement")
# Type definition for type annotation convenience
-@dataclass
class AOIMatcher(GazeFeatures.AOIMatcher):
- """Matching algorithm based on fixation's deviation circle coverage over AOI."""
+ """Matching algorithm based on fixation's deviation circle coverage over AOI.
- coverage_threshold: float = field(default = 0.)
- """Minimal coverage ratio to consider a fixation over an AOI (1 means that whole fixation's deviation circle have to be over the AOI)."""
+ Parameters:
+ coverage_threshold: Minimal coverage ratio to consider a fixation over an AOI (1 means that whole fixation's deviation circle have to be over the AOI).
+ """
+ def __init__(self, coverage_threshold: float = 0, **kwargs):
- def __post_init__(self):
+ super().__init__(**kwargs)
- super().__init__()
+ self.__coverage_threshold = coverage_threshold
self.__reset()
+ @property
+ def coverage_threshold(self):
+ """Get aoi matcher coverage threshold."""
+ return self.__coverage_threshold
+
def __reset(self):
self.__look_count = 0
@@ -60,7 +65,7 @@ class AOIMatcher(GazeFeatures.AOIMatcher):
# BAD: we use deviation_max attribute which is an attribute of DispersionThresholdIdentification.Fixation class
region, _, circle_ratio = aoi.circle_intersection(gaze_movement.focus, gaze_movement.deviation_max)
- if name not in self.exclude and circle_ratio > self.coverage_threshold:
+ if name not in self.exclude and circle_ratio > self.__coverage_threshold:
# Sum circle ratio to update aoi coverage
try:
@@ -136,13 +141,13 @@ class AOIMatcher(GazeFeatures.AOIMatcher):
self.__matched_gaze_movement.draw(image, **draw_matched_fixation)
# Draw matched aoi
- if self.looked_aoi.all() is not None:
+ if self.looked_aoi().all() is not None:
if update_looked_aoi:
try:
- self.__looked_aoi_data = (self.looked_aoi_name, aoi_scene[self.looked_aoi_name])
+ self.__looked_aoi_data = (self.looked_aoi_name(), aoi_scene[self.looked_aoi_name()])
except KeyError:
@@ -151,7 +156,7 @@ class AOIMatcher(GazeFeatures.AOIMatcher):
# Draw looked aoi if required
if draw_looked_aoi is not None:
- self.looked_aoi.draw(image, **draw_looked_aoi)
+ self.looked_aoi().draw(image, **draw_looked_aoi)
# Draw matched region if required
if draw_matched_region is not None:
@@ -161,22 +166,19 @@ class AOIMatcher(GazeFeatures.AOIMatcher):
# Draw looked aoi name if required
if looked_aoi_name_color is not None:
- top_left_corner_pixel = numpy.rint(self.looked_aoi.bounding_box[0]).astype(int) + looked_aoi_name_offset
- cv2.putText(image, self.looked_aoi_name, top_left_corner_pixel, cv2.FONT_HERSHEY_SIMPLEX, 1, looked_aoi_name_color, 1, cv2.LINE_AA)
+ top_left_corner_pixel = numpy.rint(self.looked_aoi().bounding_box[0]).astype(int) + looked_aoi_name_offset
+ cv2.putText(image, self.looked_aoi_name(), top_left_corner_pixel, cv2.FONT_HERSHEY_SIMPLEX, 1, looked_aoi_name_color, 1, cv2.LINE_AA)
- @property
def looked_aoi(self) -> AOIFeatures.AreaOfInterest:
"""Get most likely looked aoi for current fixation (e.g. the aoi with the highest coverage mean value)"""
return self.__looked_aoi_data[1]
- @property
def looked_aoi_name(self) -> str:
"""Get most likely looked aoi name for current fixation (e.g. the aoi with the highest coverage mean value)"""
return self.__looked_aoi_data[0]
- @property
def looked_probabilities(self) -> dict:
"""Get probabilities to be looked by current fixation for each aoi.
diff --git a/src/argaze/GazeAnalysis/DispersionThresholdIdentification.py b/src/argaze/GazeAnalysis/DispersionThresholdIdentification.py
index 745b62c..08c5fc2 100644
--- a/src/argaze/GazeAnalysis/DispersionThresholdIdentification.py
+++ b/src/argaze/GazeAnalysis/DispersionThresholdIdentification.py
@@ -145,7 +145,7 @@ class GazeMovementIdentifier(GazeFeatures.GazeMovementIdentifier):
# Ignore empty gaze position
if not gaze_position:
- return GazeFeatures.GazeMovement() if not terminate else self.current_fixation.finish()
+ return GazeFeatures.GazeMovement() if not terminate else self.current_fixation().finish()
# Check if too much time elapsed since last valid gaze position
if self.__valid_positions:
@@ -155,7 +155,7 @@ class GazeMovementIdentifier(GazeFeatures.GazeMovementIdentifier):
if (gaze_position.timestamp - ts_last) > self.__duration_min_threshold:
# Get last movement
- last_movement = self.current_gaze_movement.finish()
+ last_movement = self.current_gaze_movement().finish()
# Clear all former gaze positions
self.__valid_positions = GazeFeatures.TimeStampedGazePositions()
@@ -189,7 +189,7 @@ class GazeMovementIdentifier(GazeFeatures.GazeMovementIdentifier):
self.__saccade_positions.append(self.__valid_positions[0])
# Finish last saccade
- last_saccade = self.current_saccade.finish()
+ last_saccade = self.current_saccade().finish()
# Clear saccade positions
self.__saccade_positions = GazeFeatures.TimeStampedGazePositions()
@@ -198,7 +198,7 @@ class GazeMovementIdentifier(GazeFeatures.GazeMovementIdentifier):
self.__fixation_positions = self.__valid_positions.copy()
# Output last saccade
- return last_saccade if not terminate else self.current_fixation.finish()
+ return last_saccade if not terminate else self.current_fixation().finish()
# Valid gaze positions deviation too wide
else:
@@ -212,7 +212,7 @@ class GazeMovementIdentifier(GazeFeatures.GazeMovementIdentifier):
self.__saccade_positions.append(self.__fixation_positions[-1])
# Finish last fixation
- last_fixation = self.current_fixation.finish()
+ last_fixation = self.current_fixation().finish()
# Clear fixation positions
self.__fixation_positions = GazeFeatures.TimeStampedGazePositions()
@@ -224,7 +224,7 @@ class GazeMovementIdentifier(GazeFeatures.GazeMovementIdentifier):
self.__valid_positions.append(gaze_position)
# Output last fixation
- return last_fixation if not terminate else self.current_saccade.finish()
+ return last_fixation if not terminate else self.current_saccade().finish()
# Move oldest valid position into saccade positions
self.__saccade_positions.append(self.__valid_positions.pop(0))
@@ -232,7 +232,6 @@ class GazeMovementIdentifier(GazeFeatures.GazeMovementIdentifier):
# Always return empty gaze movement at least
return GazeFeatures.GazeMovement()
- @property
def current_gaze_movement(self) -> GazeMovementType:
# It shouldn't have a current fixation and a current saccade at the same time
@@ -248,7 +247,7 @@ class GazeMovementIdentifier(GazeFeatures.GazeMovementIdentifier):
# Always return empty gaze movement at least
return GazeFeatures.GazeMovement()
- @property
+
def current_fixation(self) -> FixationType:
if self.__fixation_positions:
@@ -258,7 +257,6 @@ class GazeMovementIdentifier(GazeFeatures.GazeMovementIdentifier):
# Always return empty gaze movement at least
return GazeFeatures.GazeMovement()
- @property
def current_saccade(self) -> SaccadeType:
if len(self.__saccade_positions) > 1:
diff --git a/src/argaze/GazeAnalysis/FocusPointInside.py b/src/argaze/GazeAnalysis/FocusPointInside.py
index 0358fae..56fee76 100644
--- a/src/argaze/GazeAnalysis/FocusPointInside.py
+++ b/src/argaze/GazeAnalysis/FocusPointInside.py
@@ -9,7 +9,6 @@ __copyright__ = "Copyright 2023, Ecole Nationale de l'Aviation Civile (ENAC)"
__license__ = "BSD"
from typing import TypeVar, Tuple
-from dataclasses import dataclass, field
import math
from argaze import GazeFeatures, DataFeatures
@@ -21,13 +20,12 @@ import cv2
GazeMovementType = TypeVar('GazeMovement', bound="GazeMovement")
# Type definition for type annotation convenience
-@dataclass
class AOIMatcher(GazeFeatures.AOIMatcher):
"""Matching algorithm based on fixation's focus point."""
- def __post_init__(self):
+ def __init__(self, **kwargs):
- super().__init__()
+ super().__init__(**kwargs)
self.__reset()
@@ -82,26 +80,24 @@ class AOIMatcher(GazeFeatures.AOIMatcher):
self.__matched_gaze_movement.draw(image, **draw_matched_fixation)
# Draw matched aoi
- if self.looked_aoi.all() is not None:
+ if self.looked_aoi().all() is not None:
# Draw looked aoi if required
if draw_looked_aoi is not None:
- self.looked_aoi.draw(image, **draw_looked_aoi)
+ self.looked_aoi().draw(image, **draw_looked_aoi)
# Draw looked aoi name if required
if looked_aoi_name_color is not None:
- top_left_corner_pixel = numpy.rint(self.looked_aoi.bounding_box[0]).astype(int) + looked_aoi_name_offset
- cv2.putText(image, self.looked_aoi_name, top_left_corner_pixel, cv2.FONT_HERSHEY_SIMPLEX, 1, looked_aoi_name_color, 1, cv2.LINE_AA)
+ top_left_corner_pixel = numpy.rint(self.looked_aoi().bounding_box[0]).astype(int) + looked_aoi_name_offset
+ cv2.putText(image, self.looked_aoi_name(), top_left_corner_pixel, cv2.FONT_HERSHEY_SIMPLEX, 1, looked_aoi_name_color, 1, cv2.LINE_AA)
- @property
def looked_aoi(self) -> AOIFeatures.AreaOfInterest:
"""Get most likely looked aoi for current fixation."""
return self.__looked_aoi_data[1]
- @property
def looked_aoi_name(self) -> str:
"""Get most likely looked aoi name for current fixation."""
diff --git a/src/argaze/GazeAnalysis/VelocityThresholdIdentification.py b/src/argaze/GazeAnalysis/VelocityThresholdIdentification.py
index bfe04fa..64fd3d0 100644
--- a/src/argaze/GazeAnalysis/VelocityThresholdIdentification.py
+++ b/src/argaze/GazeAnalysis/VelocityThresholdIdentification.py
@@ -145,7 +145,7 @@ class GazeMovementIdentifier(GazeFeatures.GazeMovementIdentifier):
# Ignore empty gaze position
if not gaze_position:
- return GazeFeatures.GazeMovement() if not terminate else self.current_fixation.finish()
+ return GazeFeatures.GazeMovement() if not terminate else self.current_fixation().finish()
# Store first valid position
if self.__last_ts < 0:
@@ -163,7 +163,7 @@ class GazeMovementIdentifier(GazeFeatures.GazeMovementIdentifier):
self.__last_position = gaze_position
# Get last movement
- last_movement = self.current_gaze_movement.finish()
+ last_movement = self.current_gaze_movement().finish()
# Clear all former gaze positions
self.__fixation_positions = GazeFeatures.TimeStampedGazePositions()
@@ -191,7 +191,7 @@ class GazeMovementIdentifier(GazeFeatures.GazeMovementIdentifier):
self.__saccade_positions.append(self.__fixation_positions[-1])
# Create last fixation
- last_fixation = self.current_fixation.finish()
+ last_fixation = self.current_fixation().finish()
# Clear fixation positions
self.__fixation_positions = GazeFeatures.TimeStampedGazePositions()
@@ -200,7 +200,7 @@ class GazeMovementIdentifier(GazeFeatures.GazeMovementIdentifier):
self.__saccade_positions.append(gaze_position)
# Output last fixation
- return last_fixation if not terminate else self.current_saccade.finish()
+ return last_fixation if not terminate else self.current_saccade().finish()
# Velocity is less or equals to threshold
else:
@@ -214,7 +214,7 @@ class GazeMovementIdentifier(GazeFeatures.GazeMovementIdentifier):
self.__fixation_positions.append(self.__saccade_positions[-1])
# Create last saccade
- last_saccade = self.current_saccade.finish()
+ last_saccade = self.current_saccade().finish()
# Clear fixation positions
self.__saccade_positions = GazeFeatures.TimeStampedGazePositions()
@@ -223,12 +223,11 @@ class GazeMovementIdentifier(GazeFeatures.GazeMovementIdentifier):
self.__fixation_positions.append(gaze_position)
# Output last saccade
- return last_saccade if not terminate else self.current_fixation.finish()
+ return last_saccade if not terminate else self.current_fixation().finish()
# Always return empty gaze movement at least
return GazeFeatures.GazeMovement()
- @property
def current_gaze_movement(self) -> GazeMovementType:
# It shouldn't have a current fixation and a current saccade at the same time
@@ -245,7 +244,6 @@ class GazeMovementIdentifier(GazeFeatures.GazeMovementIdentifier):
# Always return empty gaze movement at least
return GazeFeatures.GazeMovement()
- @property
def current_fixation(self) -> FixationType:
if self.__fixation_positions:
@@ -255,7 +253,6 @@ class GazeMovementIdentifier(GazeFeatures.GazeMovementIdentifier):
# Always return empty gaze movement at least
return GazeFeatures.GazeMovement()
- @property
def current_saccade(self) -> SaccadeType:
if len(self.__saccade_positions) > 1:
diff --git a/src/argaze/GazeFeatures.py b/src/argaze/GazeFeatures.py
index cdd29a3..ac9b69d 100644
--- a/src/argaze/GazeFeatures.py
+++ b/src/argaze/GazeFeatures.py
@@ -577,19 +577,16 @@ class GazeMovementIdentifier(DataFeatures.PipelineStepObject):
raise NotImplementedError('identify() method not implemented')
- @property
def current_gaze_movement(self) -> GazeMovementType:
"""Get the current identified gaze movement (finished or in progress) if it exists otherwise, an empty gaze movement."""
raise NotImplementedError('current_gaze_movement getter not implemented')
- @property
def current_fixation(self) -> FixationType:
"""Get the current identified fixation (finished or in progress) if it exists otherwise, an empty gaze movement."""
raise NotImplementedError('current_fixation getter not implemented')
- @property
def current_saccade(self) -> SaccadeType:
"""Get the current identified saccade (finished or in progress) if it exists otherwise, an empty gaze movement."""
@@ -857,16 +854,25 @@ class ScanPathAnalyzer(DataFeatures.PipelineStepObject):
raise NotImplementedError('analyze() method not implemented')
-@dataclass
class AOIMatcher(DataFeatures.PipelineStepObject):
"""Abstract class to define what should provide an AOI matcher algorithm."""
- exclude: list[str] = field(default_factory = list)
+ def __init__(self, exclude: list[str] = [], **kwargs):
- def __init__(self):
+ super().__init__(**kwargs)
- super().__init__()
+ self.__exclude = exclude
+ @property
+ def exclude(self):
+ """Get list of AOI to exclude from matching."""
+ return self.__exclude
+
+ @exclude.setter
+ def exclude(self, exclude: list[str]):
+ """Set list of AOI to exclude from matching."""
+ self.__exclude = exclude
+
def match(self, aoi_scene: AOIFeatures.AOIScene, gaze_movement: GazeMovement) -> Tuple[str, AOIFeatures.AreaOfInterest]:
"""Which AOI is looked in the scene?"""
@@ -882,17 +888,14 @@ class AOIMatcher(DataFeatures.PipelineStepObject):
raise NotImplementedError('draw() method not implemented')
- @property
def looked_aoi(self) -> AOIFeatures.AreaOfInterest:
"""Get most likely looked aoi."""
- raise NotImplementedError('looked_aoi getter not implemented')
+ raise NotImplementedError('looked_aoi() method not implemented')
- @property
def looked_aoi_name(self) -> str:
"""Get most likely looked aoi name."""
-
- raise NotImplementedError('looked_aoi_name getter not implemented')
+ raise NotImplementedError('looked_aoi_name() method not implemented')
AOIScanStepType = TypeVar('AOIScanStep', bound="AOIScanStep")
# Type definition for type annotation convenience
diff --git a/src/argaze/utils/demo_data/demo_frame_logger.py b/src/argaze/utils/demo_data/demo_frame_logger.py
index 2bb4bdc..151f57b 100644
--- a/src/argaze/utils/demo_data/demo_frame_logger.py
+++ b/src/argaze/utils/demo_data/demo_frame_logger.py
@@ -16,13 +16,13 @@ class FixationLogger(DataFeatures.PipelineStepObserver, UtilsFeatures.FileWriter
"""Log fixations."""
# Log fixations
- if GazeFeatures.is_fixation(frame.last_gaze_movement) and frame.last_gaze_movement.is_finished():
+ if GazeFeatures.is_fixation(frame.last_gaze_movement()) and frame.last_gaze_movement().is_finished():
log = (
timestamp,
- frame.last_gaze_movement.focus,
- frame.last_gaze_movement.duration,
- frame.layers['demo_layer'].last_looked_aoi_name
+ frame.last_gaze_movement().focus,
+ frame.last_gaze_movement().duration,
+ frame.layers['demo_layer'].last_looked_aoi_name()
)
self.write(log)