aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThéo de la Hogue2022-05-04 16:09:47 +0200
committerThéo de la Hogue2022-05-04 16:09:47 +0200
commitfc999063417c8f56f03ac120e3b4f482c8f4ed86 (patch)
treecfe0f646adcfff284a7d457d02fbe06fb827f21e
parent84dca2911026699e2c36a3add622f219721a8bf1 (diff)
downloadargaze-fc999063417c8f56f03ac120e3b4f482c8f4ed86.zip
argaze-fc999063417c8f56f03ac120e3b4f482c8f4ed86.tar.gz
argaze-fc999063417c8f56f03ac120e3b4f482c8f4ed86.tar.bz2
argaze-fc999063417c8f56f03ac120e3b4f482c8f4ed86.tar.xz
Removing TimeStampedVisualScanSteps class as it not possible to have two timestamps equal.
-rw-r--r--src/argaze/GazeFeatures.py56
-rw-r--r--src/argaze/utils/export_tobii_segment_aruco_visual_scan.py4
2 files changed, 36 insertions, 24 deletions
diff --git a/src/argaze/GazeFeatures.py b/src/argaze/GazeFeatures.py
index 723b289..ebe6fe5 100644
--- a/src/argaze/GazeFeatures.py
+++ b/src/argaze/GazeFeatures.py
@@ -7,6 +7,7 @@ from argaze import DataStructures
from argaze.AreaOfInterest import AOIFeatures
import numpy
+import pandas
GazePosition = tuple
"""Define gaze position as a tuple of coordinates."""
@@ -225,53 +226,61 @@ class DispersionBasedMovementIdentifier(MovementIdentifier):
@dataclass
class VisualScanStep():
- """Define a visual scan step as a duration, the name of the area of interest and where gaze looked at in each frame during the step."""
+ """Define a visual scan step as a start timestamp, duration, the name of the area of interest and where gaze looked at in each frame during the step."""
+ timestamp: int
duration: float
area: str
look_at: DataStructures.TimeStampedBuffer
-class TimeStampedVisualScanSteps(DataStructures.TimeStampedBuffer):
- """Define timestamped buffer to store visual scan steps."""
-
- def __setitem__(self, key, value: VisualScanStep):
- """Force value to be a VisualScanStep"""
- if type(value) != VisualScanStep:
- raise ValueError('value must be a VisualScanStep')
-
- super().__setitem__(key, value)
-
class VisualScanGenerator():
"""Abstract class to define when an aoi starts to be looked and when it stops."""
+ visual_scan_steps: list
+
def __init__(self, ts_aoi_scenes: AOIFeatures.TimeStampedAOIScenes):
if type(ts_aoi_scenes) != AOIFeatures.TimeStampedAOIScenes:
raise ValueError('argument must be a TimeStampedAOIScenes')
+ self.visual_scan_steps = []
+
+ for step in self:
+
+ if step == None:
+ continue
+
+ self.visual_scan_steps.append(step)
+
def __iter__(self):
raise NotImplementedError('__iter__() method not implemented')
- def build(self):
+ def steps(self):
+ return self.visual_scan_steps
- visual_scan_steps = TimeStampedVisualScanSteps()
+ def as_dataframe(self):
+ """Convert buffer as pandas dataframe."""
- for ts, step in self:
+ df = pandas.DataFrame.from_dict(self.visual_scan_steps)
+ df.set_index('timestamp', inplace=True)
+ df.sort_values(by=['timestamp'], inplace=True)
- if step == None:
- continue
+ return df
+
+ def export_as_csv(self, filepath):
+ """Write buffer content into a csv file."""
+ try:
- visual_scan_steps[ts] = step
+ self.as_dataframe().to_csv(filepath, index=True)
- return TimeStampedVisualScanSteps(sorted(visual_scan_steps.items()))
+ except:
+ raise RuntimeError(f'Can\' write {filepath}')
class PointerBasedVisualScan(VisualScanGenerator):
"""Build visual scan on the basis of which AOI are looked."""
def __init__(self, ts_aoi_scenes: AOIFeatures.TimeStampedAOIScenes, ts_gaze_positions: TimeStampedGazePositions):
- super().__init__(ts_aoi_scenes)
-
# process identification on a copy
self.__ts_aoi_scenes = ts_aoi_scenes.copy()
self.__ts_gaze_positions = ts_gaze_positions.copy()
@@ -279,6 +288,9 @@ class PointerBasedVisualScan(VisualScanGenerator):
# a dictionary to store when an aoi starts to be looked
self.__step_dict = {}
+ # build visual scan
+ super().__init__(ts_aoi_scenes)
+
def __iter__(self):
"""Visual scan generator function."""
@@ -313,7 +325,7 @@ class PointerBasedVisualScan(VisualScanGenerator):
ts_start = self.__step_dict[name]['start']
# aoi stops to be looked
- yield round(ts_start), VisualScanStep(round(ts_current - ts_start), name, self.__step_dict[name]['look_at'])
+ yield VisualScanStep(round(ts_start), round(ts_current - ts_start), name, self.__step_dict[name]['look_at'])
# forget the aoi
del self.__step_dict[name]
@@ -328,7 +340,7 @@ class PointerBasedVisualScan(VisualScanGenerator):
ts_start = step['start']
# aoi stops to be looked
- yield round(ts_start), VisualScanStep(round(ts_current - ts_start), name, step['look_at'])
+ yield VisualScanStep(round(ts_start), round(ts_current - ts_start), name, step['look_at'])
class FixationBasedVisualScan(VisualScanGenerator):
"""Build visual scan on the basis of timestamped fixations."""
diff --git a/src/argaze/utils/export_tobii_segment_aruco_visual_scan.py b/src/argaze/utils/export_tobii_segment_aruco_visual_scan.py
index 5d93beb..4622b00 100644
--- a/src/argaze/utils/export_tobii_segment_aruco_visual_scan.py
+++ b/src/argaze/utils/export_tobii_segment_aruco_visual_scan.py
@@ -178,9 +178,9 @@ def main():
print(f'\nAOIs video saved into {video_filepath}')
# Build visual scan based on a pointer position
- visual_scan = GazeFeatures.PointerBasedVisualScan(ts_aois_scenes, ts_gaze_positions).build()
+ visual_scan = GazeFeatures.PointerBasedVisualScan(ts_aois_scenes, ts_gaze_positions)
- print(f'{len(visual_scan)} visual scan steps found')
+ print(f'{len(visual_scan.steps())} visual scan steps found')
# Export visual scan
visual_scan.export_as_csv(visual_scan_filepath)