From c877940289e22f9cce5e4e6ba9eaed7a05314ade Mon Sep 17 00:00:00 2001 From: Théo de la Hogue Date: Wed, 3 Apr 2024 15:45:01 +0200 Subject: Renaming logging doc file into recording. Updating examples. --- docs/user_guide/gaze_analysis_pipeline/logging.md | 152 -------------------- .../user_guide/gaze_analysis_pipeline/recording.md | 156 +++++++++++++++++++++ mkdocs.yml | 2 +- src/argaze/utils/demo/gaze_analysis_pipeline.json | 2 +- src/argaze/utils/demo/recorders.py | 2 +- 5 files changed, 159 insertions(+), 155 deletions(-) delete mode 100644 docs/user_guide/gaze_analysis_pipeline/logging.md create mode 100644 docs/user_guide/gaze_analysis_pipeline/recording.md diff --git a/docs/user_guide/gaze_analysis_pipeline/logging.md b/docs/user_guide/gaze_analysis_pipeline/logging.md deleted file mode 100644 index 6ef3a85..0000000 --- a/docs/user_guide/gaze_analysis_pipeline/logging.md +++ /dev/null @@ -1,152 +0,0 @@ -Record gaze analysis -================= - -[ArFrame](../../argaze.md/#argaze.ArFeatures.ArFrame) and [ArLayer](../../argaze.md/#argaze.ArFeatures.ArLayer) analysis can be recorded by registering observers to their **look** method. - -## Export gaze analysis to CSV file - -[ArFrame](../../argaze.md/#argaze.ArFeatures.ArFrame) and [ArLayer](../../argaze.md/#argaze.ArFeatures.ArLayer) have an *observers* attribute to enable pipeline execution recording. - -Here is an extract from the JSON ArFrame configuration file where recording is enabled for the [ArFrame](../../argaze.md/#argaze.ArFeatures.ArFrame) and for one [ArLayer](../../argaze.md/#argaze.ArFeatures.ArLayer) by loaded classes from Python files: - -```json -{ - "name": "My FullHD screen", - "size": [1920, 1080], - "observers": { - "my_recorders.ScanPathAnalysisRecorder": { - "path": "./scan_path_metrics.csv" - }, - ... - "layers": { - "MyLayer": { - "observers": { - "my_recorders.AOIScanPathAnalysisRecorder": { - "path": "./aoi_scan_path_metrics.csv" - } - }, - ... - } - } -} -``` - -!!! 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_recorders.py* file: - -```python -from argaze.utils import UtilsFeatures - -class ScanPathAnalysisRecorder(UtilsFeatures.FileWriter): - - def __init__(self, **kwargs): - - # Init FileWriter - super().__init__(**kwargs) - - # Edit hearder line - self.header = "Timestamp (ms)", "Duration (ms)", "Steps number" - - def on_look(self, timestamp, ar_frame, exception): - """Record scan path metrics""" - - if ar_frame.is_analysis_available(): - - analysis = ar_frame.analysis() - - data = ( - timestamp, - analysis['argaze.GazeAnalysis.Basic.ScanPathAnalyzer'].path_duration, - analysis['argaze.GazeAnalysis.Basic.ScanPathAnalyzer'].steps_number - ) - - # Write to file - self.write(data) - -class AOIScanPathAnalysisRecorder(UtilsFeatures.FileWriter): - - def __init__(self, **kwargs): - - # Init FileWriter - super().__init__(**kwargs) - - # Edit header line - self.header = "Timestamp (ms)", "NGram counts" - - def on_look(self, timestamp, ar_layer, exception): - """Record aoi scan path metrics.""" - - if ar_layer.is_analysis_available(): - - data = ( - timestamp, - ar_layer.analysis['argaze.GazeAnalysis.NGram.AOIScanPathAnalyzer'].ngrams_count - ) - - # Write to file - self.write(data) -``` - -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: - -|Timestamp (ms)|Duration (ms)|Steps number| -|:-------------|:------------|:-----------| -|3460 |1750 |2 | -|4291 |2623 |3 | -|4769 |3107 |4 | -|6077 |4411 |5 | -|6433 |4760 |6 | -|7719 |6050 |7 | -|... |... |... | - -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: {}}"| -|... |... | - -!!! note "" - - Learn to [script the pipeline](./advanced_topics/scripting.md) to know more about [ArFrame](../../argaze.md/#argaze.ArFeatures.ArFrame) and [ArLayers](../../argaze.md/#argaze.ArFeatures.ArLayer) attributes. - -### Export gaze analysis to video file - -As explained in [pipeline steps visualisation chapter](visualisation.md), it is possible to get [ArFrame.image](../../argaze.md/#argaze.ArFeatures.ArFrame.image) once timestamped gaze positions have been processed by [ArFrame.look](../../argaze.md/#argaze.ArFeatures.ArFrame.look) method. - -Here is the JSON ArFrame configuration file where [ArFrame](../../argaze.md/#argaze.ArFeatures.ArFrame) observers are extended with a new my_frame_logger.VideoRecorder instance: - -```json -{ - "name": "My FullHD screen", - "size": [1920, 1080], - "observers": { - ... - "my_frame_logger.VideoRecorder": { - "path": "./video.mp4", - "width": 1920, - "height": 1080, - "fps": 15 - }, - ... -} -``` - -Here is *my_frame_logger.py* file extended with a new VideoRecorder class: - -```python -... - -class VideoRecorder(DataFeatures.PipelineStepObserver, UtilsFeatures.VideoWriter): - - def on_look(self, timestamp, ar_frame, exception): - """Record frame image into video file.""" - - self.write(ar_frame.image()) - -``` - -Assuming that [ArFrame.image_parameters](../../argaze.md/#argaze.ArFeatures.ArFrame.image_parameters) are provided, ***video.mp4*** file would be created. \ No newline at end of file diff --git a/docs/user_guide/gaze_analysis_pipeline/recording.md b/docs/user_guide/gaze_analysis_pipeline/recording.md new file mode 100644 index 0000000..72aee58 --- /dev/null +++ b/docs/user_guide/gaze_analysis_pipeline/recording.md @@ -0,0 +1,156 @@ +Record gaze analysis +================= + +[ArFrame](../../argaze.md/#argaze.ArFeatures.ArFrame) and [ArLayer](../../argaze.md/#argaze.ArFeatures.ArLayer) analysis can be recorded by registering observers to their **look** method. + +## Export gaze analysis to CSV file + +[ArFrame](../../argaze.md/#argaze.ArFeatures.ArFrame) and [ArLayer](../../argaze.md/#argaze.ArFeatures.ArLayer) have an **observers** attribute to enable pipeline execution recording. + +Here is an extract from the JSON ArFrame configuration file where recording is enabled for the [ArFrame](../../argaze.md/#argaze.ArFeatures.ArFrame) and for one [ArLayer](../../argaze.md/#argaze.ArFeatures.ArLayer) by loaded classes from Python files: + +```json +{ + "name": "My FullHD screen", + "size": [1920, 1080], + "observers": { + "my_recorders.ScanPathAnalysisRecorder": { + "path": "./scan_path_metrics.csv" + }, + ... + "layers": { + "MyLayer": { + "observers": { + "my_recorders.AOIScanPathAnalysisRecorder": { + "path": "./aoi_scan_path_metrics.csv" + } + }, + ... + } + } +} +``` + +!!! 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_recorders.py* file: + +```python +from argaze.utils import UtilsFeatures + +class ScanPathAnalysisRecorder(UtilsFeatures.FileWriter): + + def __init__(self, **kwargs): + + # Init FileWriter + super().__init__(**kwargs) + + # Edit hearder line + self.header = "Timestamp (ms)", "Duration (ms)", "Steps number" + + def on_look(self, timestamp, ar_frame, exception): + """Record scan path metrics""" + + if ar_frame.is_analysis_available(): + + analysis = ar_frame.analysis() + + data = ( + timestamp, + analysis['argaze.GazeAnalysis.Basic.ScanPathAnalyzer'].path_duration, + analysis['argaze.GazeAnalysis.Basic.ScanPathAnalyzer'].steps_number + ) + + # Write to file + self.write(data) + +class AOIScanPathAnalysisRecorder(UtilsFeatures.FileWriter): + + def __init__(self, **kwargs): + + # Init FileWriter + super().__init__(**kwargs) + + # Edit header line + self.header = "Timestamp (ms)", "NGram counts" + + def on_look(self, timestamp, ar_layer, exception): + """Record aoi scan path metrics.""" + + if ar_layer.is_analysis_available(): + + data = ( + timestamp, + ar_layer.analysis['argaze.GazeAnalysis.NGram.AOIScanPathAnalyzer'].ngrams_count + ) + + # Write to file + self.write(data) +``` + +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: + +|Timestamp (ms)|Duration (ms)|Steps number| +|:-------------|:------------|:-----------| +|3460 |1750 |2 | +|4291 |2623 |3 | +|4769 |3107 |4 | +|6077 |4411 |5 | +|6433 |4760 |6 | +|7719 |6050 |7 | +|... |... |... | + +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: {}}"| +|... |... | + +!!! note "" + + Learn to [script the pipeline](./advanced_topics/scripting.md) to know more about [ArFrame](../../argaze.md/#argaze.ArFeatures.ArFrame) and [ArLayers](../../argaze.md/#argaze.ArFeatures.ArLayer) attributes. + +### Export gaze analysis to video file + +As explained in [pipeline steps visualisation chapter](visualisation.md), it is possible to get [ArFrame.image](../../argaze.md/#argaze.ArFeatures.ArFrame.image) once timestamped gaze positions have been processed by [ArFrame.look](../../argaze.md/#argaze.ArFeatures.ArFrame.look) method. + +Here is the JSON ArFrame configuration file where [ArFrame](../../argaze.md/#argaze.ArFeatures.ArFrame) observers are extended with a new my_recorders.VideoRecorder instance: + +```json +{ + "name": "My FullHD screen", + "size": [1920, 1080], + "observers": { + ... + "my_recorders.FrameImageRecorder": { + "path": "./video.mp4", + "width": 1920, + "height": 1080, + "fps": 15 + }, + ... +} +``` + +Here is *my_recorders.py* file extended with a new VideoRecorder class: + +```python +... + +class FrameImageRecorder(UtilsFeatures.VideoWriter): + + def __init__(self, **kwargs): + + # Init VideoWriter + super().__init__(**kwargs) + + def on_look(self, timestamp, ar_frame, exception): + """Record frame image into video file.""" + + self.write(ar_frame.image()) +``` + +Assuming that [ArFrame.image_parameters](../../argaze.md/#argaze.ArFeatures.ArFrame.image_parameters) are provided, ***video.mp4*** file would be created. \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 8eb2fcf..a5305aa 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -11,7 +11,7 @@ nav: - user_guide/gaze_analysis_pipeline/aoi_2d_description.md - user_guide/gaze_analysis_pipeline/aoi_analysis.md - user_guide/gaze_analysis_pipeline/visualisation.md - - user_guide/gaze_analysis_pipeline/logging.md + - user_guide/gaze_analysis_pipeline/recording.md - user_guide/gaze_analysis_pipeline/heatmap.md - user_guide/gaze_analysis_pipeline/background.md - Pipeline Modules: diff --git a/src/argaze/utils/demo/gaze_analysis_pipeline.json b/src/argaze/utils/demo/gaze_analysis_pipeline.json index 291b3e1..fb8a93a 100644 --- a/src/argaze/utils/demo/gaze_analysis_pipeline.json +++ b/src/argaze/utils/demo/gaze_analysis_pipeline.json @@ -121,7 +121,7 @@ "recorders.ScanPathAnalysisRecorder": { "path": "_export/records/scan_path_metrics.csv" }, - "recorders.VideoRecorder": { + "recorders.FrameImageRecorder": { "path": "_export/records/video.mp4", "width": 1920, "height": 1080, diff --git a/src/argaze/utils/demo/recorders.py b/src/argaze/utils/demo/recorders.py index ec3baa3..0debc12 100644 --- a/src/argaze/utils/demo/recorders.py +++ b/src/argaze/utils/demo/recorders.py @@ -74,7 +74,7 @@ class ScanPathAnalysisRecorder(UtilsFeatures.FileWriter): self.write(log) -class VideoRecorder(UtilsFeatures.VideoWriter): +class FrameImageRecorder(UtilsFeatures.VideoWriter): def __init__(self, **kwargs): -- cgit v1.1