aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/user_guide/gaze_analysis_pipeline/advanced_topics/module_loading.md (renamed from docs/user_guide/gaze_analysis_pipeline/advanced_topics/plugin_loading.md)11
-rw-r--r--docs/user_guide/gaze_analysis_pipeline/ar_frame_configuration_and_execution.md29
-rw-r--r--docs/user_guide/gaze_analysis_pipeline/ar_layer_configuration_and_execution.md23
-rw-r--r--docs/user_guide/gaze_analysis_pipeline/gaze_analysis_logging.md97
-rw-r--r--docs/user_guide/gaze_analysis_pipeline/heatmap_visualisation.md71
-rw-r--r--docs/user_guide/gaze_analysis_pipeline/introduction.md5
-rw-r--r--docs/user_guide/gaze_analysis_pipeline/timestamped_gaze_positions_edition.md9
7 files changed, 205 insertions, 40 deletions
diff --git a/docs/user_guide/gaze_analysis_pipeline/advanced_topics/plugin_loading.md b/docs/user_guide/gaze_analysis_pipeline/advanced_topics/module_loading.md
index 21e1f8b..0b45368 100644
--- a/docs/user_guide/gaze_analysis_pipeline/advanced_topics/plugin_loading.md
+++ b/docs/user_guide/gaze_analysis_pipeline/advanced_topics/module_loading.md
@@ -1,15 +1,15 @@
-Loading plugins from another package
+Loading modules from another package
====================================
-It possible to load GazeMovementIdentifier, ScanPathAnalyzer or AOIScanPathAnalyzer plugins from another [python package](https://docs.python.org/3/tutorial/modules.html#packages).
+It possible to load GazeMovementIdentifier, ScanPathAnalyzer or AOIScanPathAnalyzer modules from another [python package](https://docs.python.org/3/tutorial/modules.html#packages).
-To do so, simply prepend the package where to find the plugin into the JSON configuration file:
+To do so, simply prepend the package where to find the module into the JSON configuration file:
```
{
...
"gaze_movement_identifier": {
- "my_package.MyGazeMovementIdentifierMethod": {
+ "my_package.MyGazeMovementIdentifierAlgorithm": {
"specific_plugin_parameter": 0
}
},
@@ -40,7 +40,6 @@ import my_package
ar_frame = ArFeatures.ArFrame.from_json('./configuration.json')
# Print ArFrame attributes
-
-for name, scan_path_analyzer in ar_frame.scan_path_analyzers.items():
+for module, scan_path_analyzer in ar_frame.scan_path_analyzers.items():
print('scan path analyzer type:', type(scan_path_analyzer))
```
diff --git a/docs/user_guide/gaze_analysis_pipeline/ar_frame_configuration_and_execution.md b/docs/user_guide/gaze_analysis_pipeline/ar_frame_configuration_and_execution.md
index f1264c7..3e18f3e 100644
--- a/docs/user_guide/gaze_analysis_pipeline/ar_frame_configuration_and_execution.md
+++ b/docs/user_guide/gaze_analysis_pipeline/ar_frame_configuration_and_execution.md
@@ -29,11 +29,6 @@ Here is a simple JSON ArFrame configuration file example:
"ExploitExploreRatio": {
"short_fixation_duration_threshold": 0
}
- },
- "heatmap": {
- "size": [320, 180],
- "sigma": 0.025,
- "buffer": 0
}
}
```
@@ -54,8 +49,6 @@ print("scan path:", ar_frame.scan_path)
for module, analyzer in ar_frame.scan_path_analyzers.items():
print('scan path analyzer module:', module)
-
-print("heatmap:", ar_frame.heatmap)
```
Finally, here is what the program writes in console:
@@ -67,7 +60,6 @@ gaze movement identifier type: <class 'argaze.GazeAnalysis.DispersionThresholdId
scan path: []
scan path analyzer module: argaze.GazeAnalysis.Basic
scan path analyzer module: argaze.GazeAnalysis.ExploitExploreRatio
-heatmap: Heatmap(size=[320, 180], buffer=0, sigma=0.025)
```
Now, let's understand the meaning of each JSON entry.
@@ -80,15 +72,18 @@ The name of the [ArFrame](../../../argaze/#argaze.ArFeatures.ArFrame). Basically
The size of the [ArFrame](../../../argaze/#argaze.ArFeatures.ArFrame) defines the dimension of the rectangular area where gaze positions are projected. Be aware that gaze positions have to be in the same range of value.
+!!! warning
+ **ArGaze doesn't impose any spatial unit.** Gaze positions can either be integer or float, pixels, millimeters or what ever you need. The only concern is that all spatial values used in further configurations have to be all the same unit.
+
### Gaze Movement Identifier
The first [ArFrame](../../../argaze/#argaze.ArFeatures.ArFrame) pipeline step is to identify fixations or saccades from consecutive timestamped gaze positions.
![Gaze Movement Identifier](../../img/ar_frame_gaze_movement_identifier.png)
-The identification method can be selected by instantiating a particular [GazeMovementIdentifier](../../../argaze/#argaze.GazeFeatures.GazeMovementIdentifier) from the [argaze.GazeAnalysis](../../../argaze/#argaze.GazeAnalysis) submodule or [another python package](../advanced_topics/plugin_loading).
+The identification algorithm can be selected by instantiating a particular [GazeMovementIdentifier](../../../argaze/#argaze.GazeFeatures.GazeMovementIdentifier) from the [argaze.GazeAnalysis](../../../argaze/#argaze.GazeAnalysis) submodule or [from another python package](../advanced_topics/module_loading).
-In the example file, the choosen identification method is the [Dispersion Threshold Identification (I-DT)](../../../argaze/#argaze.GazeAnalysis.DispersionThresholdIdentification) which has two specific *deviation_max_threshold* and *duration_min_threshold* attributes.
+In the example file, the choosen identification algorithm is the [Dispersion Threshold Identification (I-DT)](../../../argaze/#argaze.GazeAnalysis.DispersionThresholdIdentification) which has two specific *deviation_max_threshold* and *duration_min_threshold* attributes.
!!! note
In ArGaze, [Fixation](../../../argaze/#argaze.GazeFeatures.Fixation) and [Saccade](../../../argaze/#argaze.GazeFeatures.Saccade) are considered as particular [GazeMovements](../../../argaze/#argaze.GazeFeatures.GazeMovement).
@@ -106,22 +101,14 @@ Once fixations and saccades are identified, they are automatically appended to t
The [ScanPath.duration_max](../../../argaze/#argaze.GazeFeatures.ScanPath.duration_max) attribute is the duration from which older scan steps are removed each time new scan steps are added.
-### Scan Path Analyzers
-
-Finally, the last [ArFrame](../../../argaze/#argaze.ArFeatures.ArFrame) pipeline step consists in passing the previously built [ScanPath](../../../argaze/#argaze.GazeFeatures.ScanPath) to each loaded [ScanPathAnalyzer](../../../argaze/#argaze.GazeFeatures.ScanPathAnalyzer).
-
-Each analysis algorithm can be selected by instantiating a particular [ScanPathAnalyzer](../../../argaze/#argaze.GazeFeatures.ScanPathAnalyzer) from the [argaze.GazeAnalysis](../../../argaze/#argaze.GazeAnalysis) submodule or [another python package](../advanced_topics/plugin_loading).
-
!!! note
JSON *scan_path* entry is not mandatory. If scan_path_analyzers entry is not empty, the ScanPath step is automatically enabled.
-### Heatmap
-
-This is an optional [ArFrame](../../../argaze/#argaze.ArFeatures.ArFrame) pipeline step. It is executed at each new gaze position to update Heatmap image.
+### Scan Path Analyzers
-![Heatmap](../../img/ar_frame_heatmap.png)
+Finally, the last [ArFrame](../../../argaze/#argaze.ArFeatures.ArFrame) pipeline step consists in passing the previously built [ScanPath](../../../argaze/#argaze.GazeFeatures.ScanPath) to each loaded [ScanPathAnalyzer](../../../argaze/#argaze.GazeFeatures.ScanPathAnalyzer).
-The Heatmap object have tree attributes to set its size, the sigma point spreading and optional buffer size (0 means no buffering).
+Each analysis algorithm can be selected by instantiating a particular [ScanPathAnalyzer](../../../argaze/#argaze.GazeFeatures.ScanPathAnalyzer) from the [argaze.GazeAnalysis](../../../argaze/#argaze.GazeAnalysis) submodule or [from another python package](../advanced_topics/module_loading).
## Pipeline execution
diff --git a/docs/user_guide/gaze_analysis_pipeline/ar_layer_configuration_and_execution.md b/docs/user_guide/gaze_analysis_pipeline/ar_layer_configuration_and_execution.md
index c9ca097..3503d1a 100644
--- a/docs/user_guide/gaze_analysis_pipeline/ar_layer_configuration_and_execution.md
+++ b/docs/user_guide/gaze_analysis_pipeline/ar_layer_configuration_and_execution.md
@@ -18,6 +18,7 @@ Here is the JSON ArFrame configuration file example where one layer is added:
...
"layers": {
"MyLayer": {
+ "aoi_color": [0, 0, 255],
"aoi_scene" : {
"upper_left_corner": [[0, 0], [960, 0], [960, 540], [0, 540]],
"upper_right_corner": [[960, 0], [1920, 0], [1920, 540], [960, 540]],
@@ -57,7 +58,9 @@ from argaze import ArFeatures
for name, ar_layer in ar_frame.layers.items():
print("name:", ar_layer.name)
+ print("AOI color:", ar_layer.aoi_color)
print("AOI scene:", ar_layer.aoi_scene)
+ print("AOI matcher type:", type(ar_layer.aoi_matcher))
print("AOI scan path:", ar_layer.aoi_scan_path)
for module, analyzer in ar_layer.aoi_scan_path_analyzers.items():
@@ -70,6 +73,7 @@ Finally, here is what the program writes in console:
...
name: MyLayer
+AOI color: [0, 0, 255]
AOI scene:
upper_left_corner:
[[0, 0], [960, 0], [960, 540], [0, 540]]
@@ -79,6 +83,7 @@ AOI scene:
[[0, 540], [960, 540], [960, 1080], [0, 1080]]
lower_right_corner:
[[960, 540], [1920, 540], [1920, 1080], [960, 1080]]
+AOI matcher type: <class 'argaze.GazeAnalysis.DeviationCircleCoverage.AOIMatcher'>
AOI scan path: []
AOI scan path analyzer module: argaze.GazeAnalysis.Basic
AOI scan path analyzer module: argaze.GazeAnalysis.TransitionMatrix
@@ -91,6 +96,10 @@ Now, let's understand the meaning of each JSON entry.
The name of the [ArLayer](../../../argaze/#argaze.ArFeatures.ArLayer). Basically useful for visualisation purpose.
+### AOI Color
+
+The color of [ArLayer](../../../argaze/#argaze.ArFeatures.ArLayer)'s AOI. Basically useful for visualisation purpose.
+
### AOI Scene
The [AOIScene](../../../argaze/#argaze.AreaOfInterest.AOIFeatures.AOIScene) defines a set of 2D [AreaOfInterest](../../../argaze/#argaze.AreaOfInterest.AOIFeatures.AreaOfInterest) registered by name.
@@ -103,9 +112,9 @@ The first [ArLayer](../../../argaze/#argaze.ArFeatures.ArLayer) pipeline step ai
![AOI Matcher](../../img/ar_layer_aoi_matcher.png)
-The matching method can be selected by instantiating a particular [AOIMatcher](../../../argaze/#argaze.GazeFeatures.AOIMatcher) from the [argaze.GazeAnalysis](../../../argaze/#argaze.GazeAnalysis) submodule or [another python package](../advanced_topics/plugin_loading).
+The matching algorithm can be selected by instantiating a particular [AOIMatcher](../../../argaze/#argaze.GazeFeatures.AOIMatcher) from the [argaze.GazeAnalysis](../../../argaze/#argaze.GazeAnalysis) submodule or [from another python package](../advanced_topics/module_loading).
-In the example file, the choosen matching method is the [Deviation Circle Coverage](../../../argaze/#argaze.GazeAnalysis.DeviationCircleCoverage) which has one specific *coverage_threshold* attribute.
+In the example file, the choosen matching algorithm is the [Deviation Circle Coverage](../../../argaze/#argaze.GazeAnalysis.DeviationCircleCoverage) which has one specific *coverage_threshold* attribute.
!!! warning
JSON *aoi_matcher* entry is mandatory. Otherwise, the AOIScanPath and AOIScanPathAnalyzers steps are disabled.
@@ -116,18 +125,18 @@ The second [ArLayer](../../../argaze/#argaze.ArFeatures.ArLayer) pipeline step a
![AOI Scan Path](../../img/ar_layer_aoi_scan_path.png)
-Once fixations and saccades are identified and fixations are matched to AOI, they are automatically appended to the AOIScanPath if required.
+Once identified gaze movements are matched to AOI, they are automatically appended to the AOIScanPath if required.
The [AOIScanPath.duration_max](../../../argaze/#argaze.GazeFeatures.AOIScanPath.duration_max) attribute is the duration from which older AOI scan steps are removed each time new AOI scan steps are added.
+!!! note
+ JSON *aoi_scan_path* entry is not mandatory. If aoi_scan_path_analyzers entry is not empty, the AOIScanPath step is automatically enabled.
+
### AOI Scan Path Analyzers
Finally, the last [ArLayer](../../../argaze/#argaze.ArFeatures.ArLayer) pipeline step consists in passing the previously built [AOIScanPath](../../../argaze/#argaze.GazeFeatures.AOIScanPath) to each loaded [AOIScanPathAnalyzer](../../../argaze/#argaze.GazeFeatures.AOIScanPathAnalyzer).
-Each analysis algorithm can be selected by instantiating a particular [AOIScanPathAnalyzer](../../../argaze/#argaze.GazeFeatures.AOIScanPathAnalyzer) from the [argaze.GazeAnalysis](../../../argaze/#argaze.GazeAnalysis) submodule or [another python package](../advanced_topics/plugin_loading).
-
-!!! note
- JSON *aoi_scan_path* entry is not mandatory. If aoi_scan_path_analyzers entry is not empty, the AOIScanPath step is automatically enabled.
+Each analysis algorithm can be selected by instantiating a particular [AOIScanPathAnalyzer](../../../argaze/#argaze.GazeFeatures.AOIScanPathAnalyzer) from the [argaze.GazeAnalysis](../../../argaze/#argaze.GazeAnalysis) submodule or [from another python package](../advanced_topics/module_loading).
## Pipeline execution
diff --git a/docs/user_guide/gaze_analysis_pipeline/gaze_analysis_logging.md b/docs/user_guide/gaze_analysis_pipeline/gaze_analysis_logging.md
new file mode 100644
index 0000000..d79e3a6
--- /dev/null
+++ b/docs/user_guide/gaze_analysis_pipeline/gaze_analysis_logging.md
@@ -0,0 +1,97 @@
+Log gaze analysis
+=================
+
+[ArFrame](../../../argaze/#argaze.ArFeatures.ArFrame) and [ArLayer](../../../argaze/#argaze.ArFeatures.ArLayer) logging are optional pipeline steps. They are executed at each new scan path step to update logs.
+
+## Enable ArFrame and ArLayer logging
+
+[ArFrame](../../../argaze/#argaze.ArFeatures.ArFrame) and [ArLayer](../../../argaze/#argaze.ArFeatures.ArLayer) have a log attribute to enable analysis logging.
+
+Here is the JSON ArFrame configuration file example where logging is enabled for the ArFrame and for one ArLayer:
+
+```json
+{
+ "name": "My FullHD screen",
+ "size": [1920, 1080],
+ "log": true,
+ ...
+ "layers": {
+ "MyLayer": {
+ "log": true,
+ ...
+ }
+ }
+}
+```
+
+Then, here is how to access to logs dictionaries:
+
+```python
+# Assuming that all timestamped gaze positions have been processed by ArFrame.look method
+...
+
+# Access to ArFame scan path analysis logs
+for analysis, log in ar_frame.logs.items():
+
+ # Do something with scan path analysis log
+ ...
+
+# Access to ArLayers AOI scan path analysis logs
+for layer_name, layer in ar_frame.layers.items():
+
+ for analysis, log in layer.logs.items():
+
+ # Do something with AOI scan path analysis log
+ ...
+```
+
+!!! note
+ [ArFrame](../../../argaze/#argaze.ArFeatures.ArFrame) and its [ArLayers](../../../argaze/#argaze.ArFeatures.ArLayer) logging are automatically done each time the [ArFrame.look](../../../argaze/#argaze.ArFeatures.ArFrame.look) method is called.
+ [ArFrame](../../../argaze/#argaze.ArFeatures.ArFrame) logging records each scan path analysis into a dedicated timestamped data buffer each time a new scan path step happens.
+ [ArLayer](../../../argaze/#argaze.ArFeatures.ArLayer) logging records each AOI scan path analysis into a dedicated timestamped data buffer each time a new AOI scan path step happens.
+
+## Export gaze analysis logs to CSV file
+
+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.
+
+```python
+import pandas
+
+# Assuming that all timestamped gaze positions have been processed by ArFrame.look method
+...
+
+# 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')
+
+# Export ArLayers layers AOI scan path analysis logs
+for layer_name, layer in ar_frame.layers.items():
+
+ for analysis, log in layer.logs.items():
+
+ log.as_dataframe().to_csv(f'./{ar_frame.name}_{layer_name}_{analysis}.csv')
+
+```
+
+Assuming that [ArGaze.GazeAnalysis.Basic](../../../argaze/#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/#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: {('upper_left_corner', 'lower_left_corner', 'lower_right_corner'): 1}, 4: {}, 5: {}}"|
+|... |... |
+
+
diff --git a/docs/user_guide/gaze_analysis_pipeline/heatmap_visualisation.md b/docs/user_guide/gaze_analysis_pipeline/heatmap_visualisation.md
new file mode 100644
index 0000000..24a8f32
--- /dev/null
+++ b/docs/user_guide/gaze_analysis_pipeline/heatmap_visualisation.md
@@ -0,0 +1,71 @@
+Visualize heatmap
+=================
+
+Heatmap is an optional [ArFrame](../../../argaze/#argaze.ArFeatures.ArFrame) pipeline step. It is executed at each new gaze position to update heatmap image.
+
+![Heatmap](../../img/ar_frame_heatmap.png)
+
+## Enable ArFrame heatmap
+
+[ArFrame](../../../argaze/#argaze.ArFeatures.ArFrame) heatmap visualization can be enabled thanks to a dedicated JSON entry.
+
+Here is the JSON ArFrame configuration file example where heatmap visualization is enabled:
+
+```json
+{
+ "name": "My FullHD screen",
+ "size": [1920, 1080],
+ ...
+ "heatmap": {
+ "size": [320, 180],
+ "sigma": 0.025,
+ "buffer": 0
+ }
+}
+```
+
+Then, here is how to access to heatmap object:
+
+```python
+
+# Assuming an ArFrame is loaded
+...
+
+print("heatmap:", ar_frame.heatmap)
+```
+
+Finally, here is what the program writes in console:
+
+```txt
+heatmap: Heatmap(size=[320, 180], buffer=0, sigma=0.025)
+```
+
+Now, let's understand the meaning of each JSON entry.
+
+### Size
+
+The heatmap image size in pixel. Higher size implies higher CPU load.
+
+### Sigma
+
+The gaussian point spreading to draw at each gaze position.
+
+![Point spread](../../img/point_spread.png)
+
+### Buffer
+
+The size of point spread images buffer (0 means no buffering) to visualize only last N gaze positions.
+
+## Export heatmap to PNG file
+
+Once timestamped gaze positions have been processed by [ArFrame.look](../../../argaze/#argaze.ArFeatures.ArFrame.look) method, it is possible to write heatmap image thanks to OpenCV package.
+
+```python
+import cv2
+
+# Assuming that timestamped gaze positions have been processed by ArFrame.look method
+...
+
+# Export heatmap image
+cv2.imwrite('./heatmap.png', ar_frame.heatmap.image)
+``` \ No newline at end of file
diff --git a/docs/user_guide/gaze_analysis_pipeline/introduction.md b/docs/user_guide/gaze_analysis_pipeline/introduction.md
index ee67c9d..e696088 100644
--- a/docs/user_guide/gaze_analysis_pipeline/introduction.md
+++ b/docs/user_guide/gaze_analysis_pipeline/introduction.md
@@ -12,8 +12,9 @@ To build your own gaze analysis pipeline, you need to know:
* [How to edit timestamped gaze positions](../timestamped_gaze_positions_edition),
* [How to deal with an ArFrame instance](../ar_frame_configuration_and_execution),
* [How to deal with an ArLayer instance](../ar_layer_configuration_and_execution),
-* [How to log resulted gaze analysis](../analysis).
+* [How to log resulted gaze analysis](../gaze_analysis_logging),
+* [How to visualize heatmap](../heatmap_visualisation).
More advanced features are also explained like:
-* [How to load plugin from another package](../advanced_topics/plugin_loading)
+* [How to load module from another package](../advanced_topics/module_loading)
diff --git a/docs/user_guide/gaze_analysis_pipeline/timestamped_gaze_positions_edition.md b/docs/user_guide/gaze_analysis_pipeline/timestamped_gaze_positions_edition.md
index e7deab2..3b30bf8 100644
--- a/docs/user_guide/gaze_analysis_pipeline/timestamped_gaze_positions_edition.md
+++ b/docs/user_guide/gaze_analysis_pipeline/timestamped_gaze_positions_edition.md
@@ -22,8 +22,8 @@ ts_gaze_positions = GazeFeatures.TimeStampedGazePositions.from_dataframe(datafra
# Iterate over timestamped gaze positions
for timestamp, gaze_position in ts_gaze_positions.items():
- # Do something with each timestamped gaze position
- ...
+ # Do something with each timestamped gaze position
+ ...
```
## Edit gaze positions from live stream
@@ -36,6 +36,7 @@ from argaze import GazeFeatures
# Assuming to be inside the function where timestamp_µs, gaze_x and gaze_y values are catched
...
+
# Edit a second timestamp from a microsecond second timestamp
timestamp = timestamp_µs * 1e-6
@@ -43,7 +44,7 @@ from argaze import GazeFeatures
gaze_position = GazeFeatures.GazePosition((gaze_x, gaze_y))
# Do something with each timestamped gaze position
- ...
+ ...
```
``` python
@@ -64,7 +65,7 @@ start_time = time.time()
gaze_position = GazeFeatures.GazePosition((gaze_x, gaze_y))
# Do something with each timestamped gaze position
- ...
+ ...
```
!!! warning