Script the pipeline
All gaze analysis pipeline objects are accessible from a Python script. This could be particularly useful for real-time gaze interaction applications.
Load ArFrame configuration from dictionary
An ArFrame configuration can be loaded from a Python dictionary.
from argaze import ArFeatures, DataFeatures
# Set working directory to enable relative file path loading
DataFeatures.set_working_directory('path/to/folder')
# Edit a dict with ArFrame configuration
configuration = {
"name": "My FullHD screen",
"size": (1920, 1080),
...
"gaze_movement_identifier": {
...
},
"scan_path": {
...
},
"scan_path_analyzers": {
...
},
"heatmap": {
...
},
"layers": {
"MyLayer": {
...
},
...
},
"image_parameters": {
...
}
}
# Load ArFrame
with ArFeatures.ArFrame(**configuration) as ar_frame:
# Do something with ArFrame
...
Access to ArFrame and ArLayers attributes
Then, once the configuration is loaded, it is possible to access to its attributes: read ArFrame code reference to get a complete list of what is available.
Thus, the ArFrame.layers attribute allows to access each loaded layer and so, access to their attributes: read ArLayer code reference to get a complete list of what is available.
from argaze import ArFeatures
# Assuming the ArFrame is loaded
...
# Iterate over each ArFrame layers
for name, ar_layer in ar_frame.layers.items():
...
Pipeline execution
Timestamped GazePositions have to be passed one by one to the ArFrame.look method to execute the whole instantiated pipeline.
Mandatory
The ArFrame.look method must be called from a try block to catch pipeline exceptions.
# Assuming that timestamped gaze positions are available
...
try:
# Look ArFrame at a timestamped gaze position
ar_frame.look(timestamped_gaze_position)
# Do something with pipeline exception
except Exception as e:
...
Calling ArFrame.look method leads to update many data into the pipeline.
# Assuming that timestamped gaze positions are available
...
try:
# Look ArFrame at a timestamped gaze position
ar_frame.look(timestamped_gaze_position):
# Do something with last gaze position
... ar_frame.last_gaze_position()
# Check if a gaze movement has been identified
if ar_frame.last_gaze_movement() and ar_frame.last_gaze_movement().is_finished():
# Do something with identified fixation
if GazeFeatures.is_fixation(ar_frame.last_gaze_movement()):
...
# Do something with identified saccade
elif GazeFeatures.is_saccade(ar_frame.last_gaze_movement()):
...
# Do something with scan path analysis
if ar_frame.is_analysis_available():
for scan_path_analyzer_name, analyses in ar_frame.analysis().items():
for analysis_name, analysis in analyses.items():
...
# Do something with layers aoi scan path analysis
for layer_name, ar_layer in ar_frame.layers.items():
# Do something with last looked aoi name
... ar_frame.last_looked_aoi_name()
if ar_layer.is_analysis_available():
for aoi_scan_path_analyzer_name, analyses in ar_frame.analysis().items():
for analysis_name, analysis in analyses.items():
...
# Do something with pipeline exception
except Exception as e:
...
Let's understand the meaning of each data.
ar_frame.last_gaze_position()
This is the last calibrated GazePosition returned by GazePositionCalibrator if one is instanciated else, it is the last given GazePosition.
ar_frame.last_gaze_movement()
Last GazeMovement identified by ArFrame.gaze_movement_identifier object from incoming consecutive timestamped gaze positions. If no gaze movement have been identified, it returns an empty GazeMovement.
This could also be the current gaze movement if ArFrame.filter_in_progress_identification attribute is false. In that case, the last gaze movement finished flag is false.
Then, the last gaze movement type can be tested with GazeFeatures.is_fixation and GazeFeatures.is_saccade functions.
ar_frame.is_analysis_available()
To know when new scan path analysis is available.
ar_frame.analysis().items()
This an iterator to access to all scan path analysis. Notice that each scan path analyzer returns a dictionary containing possibly several analyses.
ar_layer.last_looked_aoi_name()
The name of the last aoi matching done by AoiMatcher if one is instanciated else, it is a None value.
ar_layer.is_analysis_available()
To know when new aoi scan path analysis is available.
ar_layer.analysis().items()
This an iterator to access to all aoi scan path analysis. Notice that each aoi scan path analyzer returns a dictionary containing possibly several analyses.
Setup ArFrame image parameters
ArFrame.image method parameters can be configured with a Python dictionary.
# Assuming ArFrame is loaded
...
# Edit a dict with ArFrame image parameters
image_parameters = {
"draw_scan_path": {
...
},
"draw_layers": {
"MyLayer": {
...
}
},
...
}
# Pass image parameters to ArFrame
ar_frame_image = ar_frame.image(**image_parameters)
# Do something with ArFrame image
...
Then, ArFrame.image method can be called in various situations.
Live window display
While timestamped gaze positions are processed by ArFrame.look method, it is possible to display the ArFrame image thanks to the OpenCV package.
import cv2
def main():
# Assuming ArFrame is loaded
...
# Create a window to display ArFrame
cv2.namedWindow(ar_frame.name, cv2.WINDOW_AUTOSIZE)
# Assuming that timestamped gaze positions are being processed by ArFrame.look method
...
# Update ArFrame image display
cv2.imshow(ar_frame.name, ar_frame.image())
# Wait 10 ms
cv2.waitKey(10)
if __name__ == '__main__':
main()