From 0d7f4569e895ae3a08dfbaa33591302a5d966f66 Mon Sep 17 00:00:00 2001 From: Théo de la Hogue Date: Mon, 29 Jan 2024 17:01:21 +0100 Subject: Updating logging documentation. Updating demo scripts. --- docs/user_guide/gaze_analysis_pipeline/logging.md | 118 ++++++++++++---------- 1 file changed, 62 insertions(+), 56 deletions(-) (limited to 'docs/user_guide/gaze_analysis_pipeline/logging.md') diff --git a/docs/user_guide/gaze_analysis_pipeline/logging.md b/docs/user_guide/gaze_analysis_pipeline/logging.md index db3cf9a..c5fe15a 100644 --- a/docs/user_guide/gaze_analysis_pipeline/logging.md +++ b/docs/user_guide/gaze_analysis_pipeline/logging.md @@ -1,97 +1,103 @@ Log gaze analysis ================= -[ArFrame](../../argaze.md/#argaze.ArFeatures.ArFrame) and [ArLayer](../../argaze.md/#argaze.ArFeatures.ArLayer) logging are optional pipeline steps. They are executed at each new scan path step to update logs. +[ArFrame](../../argaze.md/#argaze.ArFeatures.ArFrame) and [ArLayer](../../argaze.md/#argaze.ArFeatures.ArLayer) analysis can be logged by registering observers to their **look** method. -## Enable ArFrame and ArLayer logging +## Enable ArFrame and ArLayer analysis logging -[ArFrame](../../argaze.md/#argaze.ArFeatures.ArFrame) and [ArLayer](../../argaze.md/#argaze.ArFeatures.ArLayer) have a log attribute to enable analysis logging. +[ArFrame](../../argaze.md/#argaze.ArFeatures.ArFrame) and [ArLayer](../../argaze.md/#argaze.ArFeatures.ArLayer) have an observers attribute to enable pipeline execution logging. -Here is an extract from the JSON ArFrame configuration file where logging is enabled for the [ArFrame](../../argaze.md/#argaze.ArFeatures.ArFrame) and for one [ArLayer](../../argaze.md/#argaze.ArFeatures.ArLayer): +Here is an extract from the JSON ArFrame configuration file where logging is enabled for the [ArFrame](../../argaze.md/#argaze.ArFeatures.ArFrame) and for one [ArLayer](../../argaze.md/#argaze.ArFeatures.ArLayer) by pointing to dedicated Python files: ```json { "name": "My FullHD screen", "size": [1920, 1080], - "log": true, + "observers": "my_frame_logger.py", ... "layers": { "MyLayer": { - "log": true, + "observers": "my_layer_logger.py", ... } } } ``` -Then, here is how to access to logs dictionaries: +!!! note + [ArFrame](../../argaze.md/#argaze.ArFeatures.ArFrame) and its [ArLayers](../../argaze.md/#argaze.ArFeatures.ArLayer) automatically notify **look** method observers after each call. + +Here is *my_frame_logger.py* file: ```python -# Assuming that all timestamped gaze positions have been processed by ArFrame.look method -... +from argaze import DataFeatures +from argaze.utils import UtilsFeatures -# Access to ArFame scan path analysis logs -for analysis, log in ar_frame.logs.items(): - - # Do something with scan path analysis log - ... +class ScanPathAnalysisLogger(DataFeatures.PipelineStepObserver, UtilsFeatures.FileWriter): -# Access to ArLayers AOI scan path analysis logs -for layer_name, layer in ar_frame.layers.items(): + def on_look(self, timestamp, frame): + """Log scan path metrics""" - for analysis, log in layer.logs.items(): + if frame.analysis_available: - # Do something with AOI scan path analysis log - ... + log = ( + timestamp, + frame.scan_path_analyzers['argaze.GazeAnalysis.Basic'].path_duration, + frame.scan_path_analyzers['argaze.GazeAnalysis.Basic'].steps_number + ) + + # Write to file + self.write(log) + +# Export logger as observer +__observers__ = { + "Scan path analysis logger": ScanPathAnalysisLogger(path="./scan_path_metrics.csv", header="Timestamp (ms), Duration (ms), Steps number") + } ``` -!!! note - [ArFrame](../../argaze.md/#argaze.ArFeatures.ArFrame) and its [ArLayers](../../argaze.md/#argaze.ArFeatures.ArLayer) logging are automatically done each time the [ArFrame.look](../../argaze.md/#argaze.ArFeatures.ArFrame.look) method is called. - [ArFrame](../../argaze.md/#argaze.ArFeatures.ArFrame) logging records each scan path analysis into a dedicated timestamped data buffer each time a new scan step happens. - [ArLayer](../../argaze.md/#argaze.ArFeatures.ArLayer) logging records each AOI scan path analysis into a dedicated timestamped data buffer each time a new AOI scan step happens. +Assuming that [ArGaze.GazeAnalysis.Basic](../../argaze.md/#argaze.GazeAnalysis.Basic) scan path analysis module is enabled for 'My FullHD screen' ArFrame, a ***scan_path_metrics.csv*** file would be created: -## Export gaze analysis logs to CSV file +|Timestamp (ms)|Duration (ms)|Steps number| +|:-------------|:------------|:-----------| +|3460 |1750 |2 | +|4291 |2623 |3 | +|4769 |3107 |4 | +|6077 |4411 |5 | +|6433 |4760 |6 | +|7719 |6050 |7 | +|... |... |... | -It is possible to convert gaze analysis log as [Pandas DataFrame](https://pandas.pydata.org/docs/getting_started/intro_tutorials/01_table_oriented.html#min-tut-01-tableoriented) object which can be writen into a CSV file. +Here is *my_layer_logger.py* file: ```python -import pandas +from argaze import DataFeatures +from argaze.utils import UtilsFeatures -# Assuming that all timestamped gaze positions have been processed by ArFrame.look method -... +class AOIScanPathAnalysisLogger(DataFeatures.PipelineStepObserver, UtilsFeatures.FileWriter): -# Export ArFame scan path analysis logs -for analysis, log in ar_frame.logs.items(): - - log.as_dataframe().to_csv(f'./{ar_frame.name}_{analysis}.csv') + def on_look(self, timestamp, layer): + """Log aoi scan path metrics""" -# Export ArLayers layers AOI scan path analysis logs -for layer_name, layer in ar_frame.layers.items(): + if layer.analysis_available: - for analysis, log in layer.logs.items(): + log = ( + timestamp, + layer.aoi_scan_path_analyzers['argaze.GazeAnalysis.NGram'].ngrams_count + ) - log.as_dataframe().to_csv(f'./{ar_frame.name}_{layer_name}_{analysis}.csv') + # Write to file + self.write(log) +# Export logger as observer +__observers__ = { + "AOI Scan path analysis logger": AOIScanPathAnalysisLogger(path="./aoi_scan_path_metrics.csv", header="Timestamp (ms), NGram counts") + } ``` -Assuming that [ArGaze.GazeAnalysis.Basic](../../argaze.md/#argaze.GazeAnalysis.Basic) scan path analysis module is enabled for 'My FullHD screen' ArFrame, a ***My FullHD screen_argaze.GazeAnalysis.Basic.csv*** file would be created: - -|timestamped|path_duration|step_fixation_durations_average|steps_number| -|:----------|:------------|:------------------------------|:-----------| -|3460 |1750 |563.0 |2 | -|4291 |2623 |652.0 |3 | -|4769 |3107 |544.0 |4 | -|6077 |4411 |652.8 |5 | -|6433 |4760 |595.1 |6 | -|7719 |6050 |652.8 |7 | -|... |... |... |... | - -Assuming that [ArGaze.GazeAnalysis.NGram](../../argaze.md/#argaze.GazeAnalysis.NGram) AOI scan path analysis module is enabled for 'MyLayer' ArLayer, a ***My FullHD screen_MyLayer_argaze.GazeAnalysis.NGram.csv*** file would be created: - -|timestamped|ngrams_count| -|:----------|:-----------| -|5687 |"{3: {}, 4: {}, 5: {}}"| -|6208 |"{3: {('LeftPanel', 'GeoSector', 'CircularWidget'): 1}, 4: {}, 5: {}}"| -|... |... | - +Assuming that [ArGaze.GazeAnalysis.NGram](../../argaze.md/#argaze.GazeAnalysis.NGram) AOI scan path analysis module is enabled for 'MyLayer' ArLayer, a ***aoi_scan_path_metrics.csv*** file would be created: +|Timestamp (ms)|NGram counts| +|:-------------|:-----------| +|5687 |"{3: {}, 4: {}, 5: {}}"| +|6208 |"{3: {('LeftPanel', 'GeoSector', 'CircularWidget'): 1}, 4: {}, 5: {}}"| +|... |... | -- cgit v1.1