From 8e5dba2318e86f6dbd787ad2c59ab86686e19215 Mon Sep 17 00:00:00 2001 From: Théo de la Hogue Date: Wed, 27 Mar 2024 17:09:13 +0100 Subject: Propagating context entrance. --- src/argaze/ArFeatures.py | 31 +++++---- src/argaze/DataFeatures.py | 87 ++++++++++++++++-------- src/argaze/utils/eyetrackers/TobiiProGlasses2.py | 5 +- 3 files changed, 77 insertions(+), 46 deletions(-) diff --git a/src/argaze/ArFeatures.py b/src/argaze/ArFeatures.py index 8e9e63e..d78d80a 100644 --- a/src/argaze/ArFeatures.py +++ b/src/argaze/ArFeatures.py @@ -29,6 +29,7 @@ import math from argaze import DataFeatures, GazeFeatures from argaze.AreaOfInterest import * from argaze.GazeAnalysis import * +from argaze.utils import UtilsFeatures import numpy import cv2 @@ -1365,14 +1366,14 @@ class ArContext(DataFeatures.PipelineStepObject): @DataFeatures.PipelineStepInit def __init__(self, **kwargs): - logging.debug('ArContext.__init__') - DataFeatures.PipelineStepObject.__init__(self) # Init private attributes self.__pipeline = None self.__exceptions = DataFeatures.TimestampedExceptions() + self.__process_gaze_position_chrono = UtilsFeatures.TimeProbe() + # Init protected attributes self._image_parameters = DEFAULT_ARCONTEXT_IMAGE_PARAMETERS @@ -1413,22 +1414,17 @@ class ArContext(DataFeatures.PipelineStepObject): "image_parameters": self._image_parameters } + @DataFeatures.PipelineStepEnter def __enter__(self): - """ - Define abstract __enter__ method to use device as a context. + """Enter into ArContext.""" + + self.__process_gaze_position_chrono.start() - !!! warning - This method is called provided that the ArContext is created using a with statement. - """ return self + @DataFeatures.PipelineStepEnter def __exit__(self, type, value, traceback): - """ - Define abstract __exit__ method to use device as a context. - - !!! warning - This method is called provided that the ArContext is created using a with statement. - """ + """Exit from ArContext.""" pass def _process_gaze_position(self, timestamp: int|float, x: int|float = None, y: int|float = None, precision: int|float = None): @@ -1436,6 +1432,13 @@ class ArContext(DataFeatures.PipelineStepObject): logging.debug('%s._process_gaze_position', type(self).__name__) + lap_time, nb_laps, elapsed_time = gaze_position_processing_chrono.lap() + + if elapsed_time > 1e3: + + gaze_positions_frequency = nb_laps + gaze_position_processing_chrono.restart() + if issubclass(type(self.__pipeline), ArFrame): try: @@ -1508,7 +1511,7 @@ class ArContext(DataFeatures.PipelineStepObject): if draw_times: info_stack += 1 - cv2.putText(image, f'{image.timestamp}ms', (20, info_stack * 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 1, cv2.LINE_AA) + cv2.putText(image, f'Frame at {image.timestamp}ms', (20, info_stack * 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 1, cv2.LINE_AA) if issubclass(type(self.__pipeline), ArCamera): diff --git a/src/argaze/DataFeatures.py b/src/argaze/DataFeatures.py index a8ede6f..674a8d9 100644 --- a/src/argaze/DataFeatures.py +++ b/src/argaze/DataFeatures.py @@ -619,23 +619,68 @@ class TimestampedImages(TimestampedObjectsList): TimestampedObjectsList.__init__(self, TimestampedImage, images) def PipelineStepInit(method): - """Define a decorator use into PipelineStepObject class to declare pipeline step init method.""" + """Define a decorator use into PipelineStepObject class to wrap pipeline step __init__ method.""" def wrapper(self, **kwargs): - """Wrap pipeline step init method to update PipelineStepObject attributes with arguments after init call. + """Wrap pipeline __init__ init method to update PipelineStepObject attributes with arguments after init call. Parameters: kwargs: any arguments defined by PipelineStepMethodInit. """ - method(self, **kwargs) PipelineStepObject.update_attributes(self, kwargs) return wrapper +def PipelineStepEnter(method): + """Define a decorator use into PipelineStepObject class to wrap pipeline step __enter__ method.""" + + def wrapper(self): + """Wrap pipeline step __enter__ method to call super, observers and children __enter__ method.""" + + PipelineStepObject.__enter__(self) + + method(self) + + # Start children pipeline step objects + for child in self.children: + + child.__enter__() + + # Start observers + for observer in self.observers: + + observer.__enter__() + + return self + + return wrapper + +def PipelineStepExit(method): + """Define a decorator use into PipelineStepObject class to wrap pipeline step __exit__ method.""" + + def wrapper(self, exception_type, exception_value, exception_traceback): + """Wrap pipeline step __exit__ method to call super, observers and children __exit__ method.""" + + PipelineStepObject.__exit__(self, exception_type, exception_value, exception_traceback) + + # Stop observers + for observer in self.observers: + + observer.__exit__(exception_type, exception_value, exception_traceback) + + # Stop children pipeline step objects + for child in self.children: + + child.__exit__(exception_type, exception_value, exception_traceback) + + method(self, exception_type, exception_value, exception_traceback) + + return wrapper + def PipelineStepAttributeSetter(method): - """Define a decorator use into PipelineStepObject class to declare pipeline step attribute setter.""" + """Define a decorator use into PipelineStepObject class to wrap pipeline step attribute setter.""" def wrapper(self, new_value, unwrap: bool = False): """Wrap pipeline step attribute setter to load attribute from file. @@ -719,13 +764,12 @@ class PipelineStepObject(): Define class to assess pipeline step methods execution time and observe them. """ - @PipelineStepInit def __init__(self, **kwargs): """Initialize PipelineStepObject.""" logging.debug('%s.__init__', type(self).__name__) - # Init private attribute + # Init private attributes self.__name = None self.__observers = [] self.__execution_times = {} @@ -733,37 +777,20 @@ class PipelineStepObject(): # Parent attribute will be setup later by parent it self self.__parent = None + # Update attributes + self.update_attributes(kwargs) + def __enter__(self): - """At with statement start.""" + """Define default method to enter into pipeline step object context.""" logging.debug('%s.__enter__', type(self).__name__) - # Start children pipeline step objects - for child in self.children: - - child.__enter__() - - # Start observers - for observer in self.__observers: - - observer.__enter__() - return self - def __exit__(self, exception_type, exception_value, exception_traceback): - """At with statement end.""" - - logging.debug('%s.__exit__', type(self).__name__) - - # End observers - for observer in self.__observers: - - observer.__exit__(exception_type, exception_value, exception_traceback) - - # End children pipeline step objects - for child in self.children: + def __exit__(self, type, value, traceback): + """Define default method to exit from pipeline step object context.""" - child.__exit__(exception_type, exception_value, exception_traceback) + logging.debug('PipelineStepObject.__exit__') def update_attributes(self, object_data: dict): """Update pipeline step object attributes with dictionary.""" diff --git a/src/argaze/utils/eyetrackers/TobiiProGlasses2.py b/src/argaze/utils/eyetrackers/TobiiProGlasses2.py index f2c1b6a..8b92fef 100644 --- a/src/argaze/utils/eyetrackers/TobiiProGlasses2.py +++ b/src/argaze/utils/eyetrackers/TobiiProGlasses2.py @@ -459,11 +459,11 @@ class LiveStream(ArFeatures.ArContext): logging.debug('> new %s participant created: %s', self.__participant_name, self.__participant_id) + @DataFeatures.PipelineStepEnter def __enter__(self): logging.info('Tobii Pro Glasses 2 connexion starts...') - logging.debug('%s.__enter__', type(self).__name__) - + # Update current configuration with configuration patch logging.debug('> updating configuration') @@ -535,6 +535,7 @@ class LiveStream(ArFeatures.ArContext): return self + @DataFeatures.PipelineStepExit def __exit__(self, exception_type, exception_value, exception_traceback): logging.debug('%s.__exit__', type(self).__name__) -- cgit v1.1