aboutsummaryrefslogtreecommitdiff
path: root/docs/user_guide/gaze_analysis/scan_path.md
blob: e00682fcb2a388cf41991bfe8bed52f60c229ace (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
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** and **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)

### 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** and **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.

#### String representation

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 str](/argaze/#argaze.GazeFeatures.AOIScanPath.__str__) representation 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 = ...

# String representation should be: 'ABCA'
print(str(aoi_scan_path))

# 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* 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.