From e23f36b3f15f291daed077dc7d04d07939f1b7ed Mon Sep 17 00:00:00 2001 From: Théo de la Hogue Date: Wed, 13 Sep 2023 21:02:28 +0200 Subject: Moving AOI exclusion into AOI matcher. --- src/argaze/ArFeatures.py | 27 +++------------------- src/argaze/GazeAnalysis/DeviationCircleCoverage.py | 4 ++-- src/argaze/GazeAnalysis/FocusPointInside.py | 4 ++-- src/argaze/GazeFeatures.py | 5 +++- 4 files changed, 11 insertions(+), 29 deletions(-) diff --git a/src/argaze/ArFeatures.py b/src/argaze/ArFeatures.py index 901b6da..40e8516 100644 --- a/src/argaze/ArFeatures.py +++ b/src/argaze/ArFeatures.py @@ -100,7 +100,6 @@ class ArLayer(): Parameters: name: name of the layer - aoi_color: color to used in draw method aoi_scene: AOI scene description aoi_matcher: AOI matcher object aoi_scan_path: AOI scan path object @@ -110,7 +109,6 @@ class ArLayer(): """ name: str - aoi_color: tuple = field(default=(0, 0, 0)) aoi_scene: AOIFeatures.AOIScene = field(default_factory=AOIFeatures.AOIScene) aoi_matcher: GazeFeatures.AOIMatcher = field(default_factory=GazeFeatures.AOIMatcher) aoi_scan_path: GazeFeatures.AOIScanPath = field(default_factory=GazeFeatures.AOIScanPath) @@ -166,24 +164,6 @@ class ArLayer(): new_layer_name = None - # Load aoi color - try: - - new_aoi_color = layer_data.pop('aoi_color') - - except KeyError: - - new_aoi_color = (0, 0, 0) - - # Load optional aoi filter - try: - - aoi_exclude_list = layer_data.pop('aoi_exclude') - - except KeyError: - - aoi_exclude_list = [] - # Load aoi scene try: @@ -198,12 +178,12 @@ class ArLayer(): # JSON file format for 2D or 3D dimension if file_format == 'json': - new_aoi_scene = AOIFeatures.AOIScene.from_json(filepath).copy(exclude=aoi_exclude_list) + new_aoi_scene = AOIFeatures.AOIScene.from_json(filepath).copy() # OBJ file format for 3D dimension only elif file_format == 'obj': - new_aoi_scene = AOI3DScene.AOI3DScene.from_obj(filepath).copy(exclude=aoi_exclude_list) + new_aoi_scene = AOI3DScene.AOI3DScene.from_obj(filepath).copy() # dict: else: @@ -324,7 +304,6 @@ class ArLayer(): # Create layer return ArLayer(new_layer_name, \ - new_aoi_color, \ new_aoi_scene, \ new_aoi_matcher, \ new_aoi_scan_path, \ @@ -418,7 +397,7 @@ class ArLayer(): # Update looked aoi thanks to aoi matcher # Note: don't filter finished/unfinished fixation/saccade as we don't know how the aoi matcher works internally - looked_aoi_name, looked_aoi = self.aoi_matcher.match(self.aoi_scene, gaze_movement, exclude=[self.name]) + looked_aoi_name, looked_aoi = self.aoi_matcher.match(self.aoi_scene, gaze_movement) # Assess aoi matching time in ms execution_times['aoi_matcher'] = (time.perf_counter() - matching_start) * 1e3 diff --git a/src/argaze/GazeAnalysis/DeviationCircleCoverage.py b/src/argaze/GazeAnalysis/DeviationCircleCoverage.py index e8c4838..7b230c4 100644 --- a/src/argaze/GazeAnalysis/DeviationCircleCoverage.py +++ b/src/argaze/GazeAnalysis/DeviationCircleCoverage.py @@ -38,7 +38,7 @@ class AOIMatcher(GazeFeatures.AOIMatcher): self.__matched_gaze_movement = None self.__matched_region = None - def match(self, aoi_scene, gaze_movement, exclude=[]) -> Tuple[str, AOIFeatures.AreaOfInterest]: + def match(self, aoi_scene, gaze_movement) -> Tuple[str, AOIFeatures.AreaOfInterest]: """Returns AOI with the maximal fixation's deviation circle coverage if above coverage threshold.""" if GazeFeatures.is_fixation(gaze_movement): @@ -54,7 +54,7 @@ class AOIMatcher(GazeFeatures.AOIMatcher): # BAD: we use deviation_max attribute which is an atttribute of DispersionThresholdIdentification.Fixation class region, _, circle_ratio = aoi.circle_intersection(gaze_movement.focus, gaze_movement.deviation_max) - if name not in exclude and circle_ratio > 0: + if name not in self.exclude and circle_ratio > 0: # Sum circle ratio to update aoi coverage try: diff --git a/src/argaze/GazeAnalysis/FocusPointInside.py b/src/argaze/GazeAnalysis/FocusPointInside.py index 8261869..f48caae 100644 --- a/src/argaze/GazeAnalysis/FocusPointInside.py +++ b/src/argaze/GazeAnalysis/FocusPointInside.py @@ -31,14 +31,14 @@ class AOIMatcher(GazeFeatures.AOIMatcher): self.__looked_aoi_data = (None, None) self.__matched_gaze_movement = None - def match(self, aoi_scene, gaze_movement, exclude=[]) -> Tuple[str, AOIFeatures.AreaOfInterest]: + def match(self, aoi_scene, gaze_movement) -> Tuple[str, AOIFeatures.AreaOfInterest]: """Returns AOI containing fixation focus point.""" if GazeFeatures.is_fixation(gaze_movement): for name, aoi in aoi_scene.items(): - if name not in exclude and aoi.contains_point(gaze_movement.focus): + if name not in self.exclude and aoi.contains_point(gaze_movement.focus): # Update looked aoi data self.__looked_aoi_data = (name, aoi) diff --git a/src/argaze/GazeFeatures.py b/src/argaze/GazeFeatures.py index c49dc09..eeefcc9 100644 --- a/src/argaze/GazeFeatures.py +++ b/src/argaze/GazeFeatures.py @@ -718,10 +718,13 @@ class ScanPathAnalyzer(): raise NotImplementedError('analyze() method not implemented') +@dataclass class AOIMatcher(): """Abstract class to define what should provide an AOI matcher algorithm.""" - def match(self, aoi_scene: AOIFeatures.AOIScene, gaze_movement: GazeMovement, exclude=[]) -> Tuple[str, AOIFeatures.AreaOfInterest]: + exclude: list[str] = field() + + def match(self, aoi_scene: AOIFeatures.AOIScene, gaze_movement: GazeMovement) -> Tuple[str, AOIFeatures.AreaOfInterest]: """Which AOI is looked in the scene?""" raise NotImplementedError('match() method not implemented') -- cgit v1.1