Detecting Gaze Events#
What you will learn in this tutorial:#
how to detect saccades using the microsaccades algorithm
how to detect fixations using the I-DT and I-VT algorithms
Preparations#
We import pymovements
as the alias pm
for convenience.
[1]:
import polars as pl
import pymovements as pm
/home/docs/checkouts/readthedocs.org/user_builds/pymovements/envs/stable/lib/python3.9/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
from .autonotebook import tqdm as notebook_tqdm
Let’s start by downloading our ToyDataset
and loading in its data:
[2]:
dataset = pm.Dataset('ToyDataset', path='data/ToyDataset')
dataset.download()
dataset.load()
Downloading http://github.com/aeye-lab/pymovements-toy-dataset/zipball/6cb5d663317bf418cec0c9abe1dde5085a8a8ebd/ to data/ToyDataset/downloads/pymovements-toy-dataset.zip
pymovements-toy-dataset.zip: 100%|██████████| 3.06M/3.06M [00:00<00:00, 3.58MB/s]
Checking integrity of pymovements-toy-dataset.zip
Extracting pymovements-toy-dataset.zip to data/ToyDataset/raw
100%|██████████| 20/20 [00:00<00:00, 20.52it/s]
[2]:
<pymovements.dataset.dataset.Dataset at 0x7fbd8b487760>
Now let’s do some basic preprocessing:
[3]:
dataset.pix2deg()
dataset.pos2vel('smooth')
dataset.gaze[0].frame.head()
100%|██████████| 20/20 [00:01<00:00, 10.41it/s]
100%|██████████| 20/20 [00:01<00:00, 19.61it/s]
[3]:
time | stimuli_x | stimuli_y | text_id | page_id | pixel | position | velocity |
---|---|---|---|---|---|---|---|
f32 | f32 | f32 | i64 | i64 | list[f32] | list[f32] | list[f32] |
1.988145e6 | -1.0 | -1.0 | 0 | 1 | [206.800003, 152.399994] | [-10.697598, -8.8524] | [null, null] |
1.988146e6 | -1.0 | -1.0 | 0 | 1 | [206.899994, 152.100006] | [-10.695184, -8.859678] | [null, null] |
1.988147e6 | -1.0 | -1.0 | 0 | 1 | [207.0, 151.800003] | [-10.692768, -8.866957] | [1.610438, -5.256017] |
1.988148e6 | -1.0 | -1.0 | 0 | 1 | [207.100006, 151.699997] | [-10.690351, -8.869382] | [0.40261, -4.447301] |
1.988149e6 | -1.0 | -1.0 | 0 | 1 | [207.0, 151.5] | [-10.692768, -8.874233] | [0.402451, -3.234386] |
Detecting Events#
pymovements provides a range of event detection methods for several types of gaze events.
See the reference for pymovements.events to get an overview of all the supported methods.
For this tutorial we will use the microsaccades
algorithm for detecting saccades and the I-DT and I-VT algorithms for detecting fixations.
We start out by detecting saccades.
[4]:
dataset.detect_events('microsaccades', minimum_duration=12)
20it [00:00, 25.46it/s]
[4]:
<pymovements.dataset.dataset.Dataset at 0x7fbd8b487760>
The detected events are added as rows with the name saccade
to the event dataframe:
[5]:
dataset.events[0].frame.head()
[5]:
text_id | page_id | name | onset | offset | duration |
---|---|---|---|---|---|
i64 | i64 | str | i64 | i64 | i64 |
0 | 1 | "saccade" | 1988323 | 1988337 | 14 |
0 | 1 | "saccade" | 1988547 | 1988567 | 20 |
0 | 1 | "saccade" | 1988737 | 1988760 | 23 |
0 | 1 | "saccade" | 1988765 | 1988777 | 12 |
0 | 1 | "saccade" | 1989014 | 1989031 | 17 |
Next we will detect fixations using the I-DT and I-VT algorithms.
To be able to differentiate between the detected events, we specify custom event names for each algorithm:
[6]:
dataset.detect_events('idt', dispersion_threshold=2.7, name='fixation.idt')
dataset.detect_events('ivt', velocity_threshold=20, name='fixation.ivt')
20it [00:17, 1.15it/s]
20it [00:00, 35.55it/s]
[6]:
<pymovements.dataset.dataset.Dataset at 0x7fbd8b487760>
This has added new rows with the fixation events to the event dataframe.
[7]:
dataset.events[0].frame.filter(pl.col('name') == 'fixation.idt').head()
[7]:
text_id | page_id | name | onset | offset | duration |
---|---|---|---|---|---|
i64 | i64 | str | i64 | i64 | i64 |
0 | 1 | "fixation.idt" | 1988145 | 1988563 | 418 |
0 | 1 | "fixation.idt" | 1988564 | 1988750 | 186 |
0 | 1 | "fixation.idt" | 1988751 | 1989178 | 427 |
0 | 1 | "fixation.idt" | 1989179 | 1989436 | 257 |
0 | 1 | "fixation.idt" | 1989437 | 1989600 | 163 |
[8]:
dataset.events[0].frame.filter(pl.col('name') == 'fixation.ivt').head()
[8]:
text_id | page_id | name | onset | offset | duration |
---|---|---|---|---|---|
i64 | i64 | str | i64 | i64 | i64 |
0 | 1 | "fixation.ivt" | 1988147 | 1988322 | 175 |
0 | 1 | "fixation.ivt" | 1988351 | 1988546 | 195 |
0 | 1 | "fixation.ivt" | 1988592 | 1988736 | 144 |
0 | 1 | "fixation.ivt" | 1988788 | 1989013 | 225 |
0 | 1 | "fixation.ivt" | 1989060 | 1989170 | 110 |
What you have learned in this tutorial:#
detecting saccades by using the microsaccades algorithm
detecting fixations by using the I-DT and I-VT algorithms