Scan path ========= [GazeFeatures](../../../argaze/#argaze.GazeFeatures) defines classes to handle successive fixations/saccades and analyse their spatial or temporal properties. ## Fixation based scan path ### Definition The [ScanPath](../../../argaze/#argaze.GazeFeatures.ScanPath) class is defined as a list of [ScanSteps](../../../argaze/#argaze.GazeFeatures.ScanStep) which are defined as a fixation and a consecutive saccade. ![Fixation based scan path](../../img/scan_path.png) As fixations and saccades are identified, the scan path is built by calling respectively [append_fixation](../../../argaze/#argaze.GazeFeatures.ScanPath.append_fixation) and [append_saccade](../../../argaze/#argaze.GazeFeatures.ScanPath.append_saccade) methods. ### Analysis [GazeFeatures](../../../argaze/#argaze.GazeFeatures) defines abstract [ScanPathAnalyzer](../../../argaze/#argaze.GazeFeatures.ScanPathAnalyzer) classe to let add various analysis algorithms. Some scan path analysis are available thanks to [GazeAnalysis](../../../argaze/#argaze.GazeAnalysis) submodule: * [K-Coefficient](../../../argaze/#argaze.GazeAnalysis.KCoefficient) * [Nearest Neighbor Index](../../../argaze/#argaze.GazeAnalysis.NearestNeighborIndex) * [Exploit Explore Ratio](../../../argaze/#argaze.GazeAnalysis.ExploitExploreRatio) ### Example Here is a sample of code to illustrate how to built a scan path and analyze it: ``` python from argaze import GazeFeatures from argaze.GazeAnalysis import KCoefficient # Create a empty scan path scan_path = GazeFeatures.ScanPath() # Create a K coefficient analyzer kc_analyzer = KCoefficient.ScanPathAnalyzer() # Assuming a gaze movement is identified at ts time ...: # Fixation identified if GazeFeatures.is_fixation(gaze_movement): # Append fixation to scan path : no step is created scan_path.append_fixation(ts, gaze_movement) # Saccade identified elif GazeFeatures.is_saccade(gaze_movement): # Append saccade to scan path : a new step should be created new_step = scan_path.append_saccade(data_ts, gaze_movement) # Analyse scan path if new_step: K = kc_analyzer.analyze(scan_path) # Do something with K metric ... ``` ## AOI based scan path ### Definition The [AOIScanPath](../../../argaze/#argaze.GazeFeatures.AOIScanPath) class is defined as a list of [AOIScanSteps](../../../argaze/#argaze.GazeFeatures.AOIScanStep) which are defined as set of consecutives fixations looking at a same Area Of Interest (AOI) and a consecutive saccade. ![AOI based scan path](../../img/aoi_scan_path.png) As fixations and saccades are identified, the scan path is built by calling respectively [append_fixation](../../../argaze/#argaze.GazeFeatures.AOIScanPath.append_fixation) and [append_saccade](../../../argaze/#argaze.GazeFeatures.AOIScanPath.append_saccade) methods. ### Analysis [GazeFeatures](../../../argaze/#argaze.GazeFeatures) defines abstract [AOIScanPathAnalyzer](../../../argaze/#argaze.GazeFeatures.AOIScanPathAnalyzer) classe to let add various analysis algorithms. Some scan path analysis are available thanks to [GazeAnalysis](../../../argaze/#argaze.GazeAnalysis) submodule: * [Transition matrix](../../../argaze/#argaze.GazeAnalysis.TransitionMatrix) * [Entropy](../../../argaze/#argaze.GazeAnalysis.Entropy) * [Lempel-Ziv complexity](../../../argaze/#argaze.GazeAnalysis.LempelZivComplexity) * [N-Gram](../../../argaze/#argaze.GazeAnalysis.NGram) * [K-modified coefficient](../../../argaze/#argaze.GazeAnalysis.KCoefficient) ### Example Here is a sample of code to illustrate how to built a AOI scan path and analyze it: ``` python from argaze import GazeFeatures from argaze.GazeAnalysis import LempelZivComplexity # Assuming all AOI names are listed ... # Create a empty AOI scan path aoi_scan_path = GazeFeatures.AOIScanPath(aoi_names) # Create a Lempel-Ziv complexity analyzer lzc_analyzer = LempelZivComplexity.AOIScanPathAnalyzer() # Assuming a gaze movement is identified at ts time ...: # Fixation identified if GazeFeatures.is_fixation(gaze_movement): # Assuming fixation is detected as inside an AOI ... # Append fixation to AOI scan path : a new step should be created new_step = aoi_scan_path.append_fixation(ts, gaze_movement, looked_aoi_name) # Analyse AOI scan path if new_step: LZC = kc_analyzer.analyze(aoi_scan_path) # Do something with LZC metric ... # Saccade identified elif GazeFeatures.is_saccade(gaze_movement): # Append saccade to scan path : no step is created aoi_scan_path.append_saccade(data_ts, gaze_movement) ``` ### Advanced The [AOIScanPath](../../../argaze/#argaze.GazeFeatures.AOIScanPath) class provides some advanced features to analyse it. #### Letter sequence When a new [AOIScanStep](../../../argaze/#argaze.GazeFeatures.AOIScanStep) is created, the [AOIScanPath](../../../argaze/#argaze.GazeFeatures.AOIScanPath) internally affects a unique letter index related to its AOI to ease pattern analysis. Then, the [AOIScanPath letter_sequence](../../../argaze/#argaze.GazeFeatures.AOIScanPath.letter_sequence) property returns the concatenation of each [AOIScanStep](../../../argaze/#argaze.GazeFeatures.AOIScanStep) letter. The [AOIScanPath get_letter_aoi](../../../argaze/#argaze.GazeFeatures.AOIScanPath.get_letter_aoi) method helps to get back the AOI related to a letter index. ``` python # Assuming the following AOI scan path is built: Foo > Bar > Shu > Foo aoi_scan_path = ... # Letter sequence representation should be: 'ABCA' print(aoi_scan_path.letter_sequence) # Output should be: 'Bar' print(aoi_scan_path.get_letter_aoi('B')) ``` #### Transition matrix When a new [AOIScanStep](../../../argaze/#argaze.GazeFeatures.AOIScanStep) is created, the [AOIScanPath](../../../argaze/#argaze.GazeFeatures.AOIScanPath) internally counts the number of transitions from an AOI to another AOI to ease Markov chain analysis. Then, the [AOIScanPath transition_matrix](../../../argaze/#argaze.GazeFeatures.AOIScanPath.transition_matrix) property returns a [Pandas DataFrame](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.html) where indexes are transition departures and columns are transition destinations. Here is an exemple of transition matrix for the following [AOIScanPath](../../../argaze/#argaze.GazeFeatures.AOIScanPath): Foo > Bar > Shu > Foo > Bar | |Foo|Bar|Shu| |:--|:--|:--|:--| |Foo|0 |2 |0 | |Bar|0 |0 |1 | |Shu|1 |0 |0 | #### Fixations count The [AOIScanPath fixations_count](../../../argaze/#argaze.GazeFeatures.AOIScanPath.fixations_count) method returns the total number of fixations in the whole scan path and a dictionary to get the fixations count per AOI.