Plot saccadic main sequence#

In this notebook we show how you can load a dataset, compute all the necessary properties and the plot the main sequence.

What you will learn in this tutorial:#

  • how to prepare your data to plot the saccadic main sequence

  • how to create a main sequence plot of your saccade events and style it to your liking

Loading and preprocessing your data#

We import pymovements as the alias pm for convenience.

[1]:
import pymovements as pm
/home/docs/checkouts/readthedocs.org/user_builds/pymovements/envs/v0.19.0/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()
Using already downloaded and verified file: data/ToyDataset/downloads/pymovements-toy-dataset.zip
Extracting pymovements-toy-dataset.zip to data/ToyDataset/raw
100%|██████████| 20/20 [00:00<00:00, 38.87it/s]
[2]:
<pymovements.dataset.dataset.Dataset at 0x7f988c232430>

Now, you have to convert the raw x and y coordinates in pixels to degrees in visual angle.

[3]:
dataset.pix2deg()
100%|██████████| 20/20 [00:01<00:00, 18.21it/s]
[3]:
<pymovements.dataset.dataset.Dataset at 0x7f988c232430>

Next we can convert these positions into velocitites.

[4]:
dataset.pos2vel()
100%|██████████| 20/20 [00:00<00:00, 36.79it/s]
[4]:
<pymovements.dataset.dataset.Dataset at 0x7f988c232430>

Let’s check if we now have all our expected columns:

[5]:
dataset.gaze[0]
[5]:
Experiment(sampling_rate=1000, screen=Screen(width_px=1280, height_px=1024, width_cm=38, height_cm=30.20, distance_cm=68, origin=upper left), eyetracker=None)
shape: (17_223, 8)
┌─────────┬───────────┬───────────┬─────────┬─────────┬───────────┬────────────────┬───────────────┐
│ time    ┆ stimuli_x ┆ stimuli_y ┆ text_id ┆ page_id ┆ pixel     ┆ position       ┆ velocity      │
│ ---     ┆ ---       ┆ ---       ┆ ---     ┆ ---     ┆ ---       ┆ ---            ┆ ---           │
│ i64     ┆ f64       ┆ f64       ┆ i64     ┆ i64     ┆ list[f64] ┆ list[f64]      ┆ list[f64]     │
╞═════════╪═══════════╪═══════════╪═════════╪═════════╪═══════════╪════════════════╪═══════════════╡
│ 1988145 ┆ -1.0      ┆ -1.0      ┆ 0       ┆ 1       ┆ [206.8,   ┆ [-10.697598,   ┆ [null, null]  │
│         ┆           ┆           ┆         ┆         ┆ 152.4]    ┆ -8.852399]     ┆               │
│ 1988146 ┆ -1.0      ┆ -1.0      ┆ 0       ┆ 1       ┆ [206.9,   ┆ [-10.695183,   ┆ [null, null]  │
│         ┆           ┆           ┆         ┆         ┆ 152.1]    ┆ -8.859678]     ┆               │
│ 1988147 ┆ -1.0      ┆ -1.0      ┆ 0       ┆ 1       ┆ [207.0,   ┆ [-10.692768,   ┆ [1.610194,    │
│         ┆           ┆           ┆         ┆         ┆ 151.8]    ┆ -8.866956]     ┆ -5.256267]    │
│ 1988148 ┆ -1.0      ┆ -1.0      ┆ 0       ┆ 1       ┆ [207.1,   ┆ [-10.690352,   ┆ [0.402548,    │
│         ┆           ┆           ┆         ┆         ┆ 151.7]    ┆ -8.869381]     ┆ -4.447465]    │
│ 1988149 ┆ -1.0      ┆ -1.0      ┆ 0       ┆ 1       ┆ [207.0,   ┆ [-10.692768,   ┆ [0.402561,    │
│         ┆           ┆           ┆         ┆         ┆ 151.5]    ┆ -8.874233]     ┆ -3.234462]    │
│ …       ┆ …         ┆ …         ┆ …       ┆ …       ┆ …         ┆ …              ┆ …             │
│ 2005363 ┆ -1.0      ┆ -1.0      ┆ 0       ┆ 1       ┆ [361.0,   ┆ [-6.932438,    ┆ [-63.266374,  │
│         ┆           ┆           ┆         ┆         ┆ 415.4]    ┆ -2.386672]     ┆ -21.085616]   │
│ 2005364 ┆ -1.0      ┆ -1.0      ┆ 0       ┆ 1       ┆ [358.0,   ┆ [-7.006376,    ┆ [-63.249652,  │
│         ┆           ┆           ┆         ┆         ┆ 414.5]    ┆ -2.408998]     ┆ -19.431326]   │
│ 2005365 ┆ -1.0      ┆ -1.0      ┆ 0       ┆ 1       ┆ [355.8,   ┆ [-7.060582,    ┆ [-60.359624,  │
│         ┆           ┆           ┆         ┆         ┆ 413.8]    ┆ -2.426362]     ┆ -15.710061]   │
│ 2005366 ┆ -1.0      ┆ -1.0      ┆ 0       ┆ 1       ┆ [353.1,   ┆ [-7.12709,     ┆ [null, null]  │
│         ┆           ┆           ┆         ┆         ┆ 413.2]    ┆ -2.441245]     ┆               │
│ 2005367 ┆ -1.0      ┆ -1.0      ┆ 0       ┆ 1       ┆ [351.2,   ┆ [-7.173881,    ┆ [null, null]  │
│         ┆           ┆           ┆         ┆         ┆ 412.9]    ┆ -2.448686]     ┆               │
└─────────┴───────────┴───────────┴─────────┴─────────┴───────────┴────────────────┴───────────────┘

Detecting your events and compute properties#

In the next step we have to detect our saccades and compute the event properties amplitude and peak_velocity.

We can run the microsaccade detection algorithm with its default parameters:

[6]:
dataset.detect_events('microsaccades')
20it [00:00, 36.94it/s]
[6]:
<pymovements.dataset.dataset.Dataset at 0x7f988c232430>

Next we compute the event properties ‘amplitude’ and ‘peak velocity’ for the detected saccades.

[7]:
dataset.compute_event_properties(['amplitude', 'peak_velocity'])
20it [00:03,  6.19it/s]
[7]:
<pymovements.dataset.dataset.Dataset at 0x7f988c232430>

Let’s verify that we have detected some saccades and have the desired columns available.

[8]:
dataset.events[0]
[8]:
shape: (142, 8)
┌─────────┬─────────┬─────────┬─────────┬─────────┬──────────┬───────────┬───────────────┐
│ text_id ┆ page_id ┆ name    ┆ onset   ┆ offset  ┆ duration ┆ amplitude ┆ peak_velocity │
│ ---     ┆ ---     ┆ ---     ┆ ---     ┆ ---     ┆ ---      ┆ ---       ┆ ---           │
│ i64     ┆ i64     ┆ str     ┆ i64     ┆ i64     ┆ i64      ┆ f64       ┆ f64           │
╞═════════╪═════════╪═════════╪═════════╪═════════╪══════════╪═══════════╪═══════════════╡
│ 0       ┆ 1       ┆ saccade ┆ 1988323 ┆ 1988337 ┆ 14       ┆ 1.236741  ┆ 129.856451    │
│ 0       ┆ 1       ┆ saccade ┆ 1988342 ┆ 1988350 ┆ 8        ┆ 0.330748  ┆ 50.527286     │
│ 0       ┆ 1       ┆ saccade ┆ 1988547 ┆ 1988567 ┆ 20       ┆ 2.391184  ┆ 200.144558    │
│ 0       ┆ 1       ┆ saccade ┆ 1988571 ┆ 1988582 ┆ 11       ┆ 0.476811  ┆ 56.048003     │
│ 0       ┆ 1       ┆ saccade ┆ 1988737 ┆ 1988760 ┆ 23       ┆ 3.285115  ┆ 249.67823     │
│ …       ┆ …       ┆ …       ┆ …       ┆ …       ┆ …        ┆ …         ┆ …             │
│ 0       ┆ 1       ┆ saccade ┆ 2005110 ┆ 2005126 ┆ 16       ┆ 1.405354  ┆ 137.917594    │
│ 0       ┆ 1       ┆ saccade ┆ 2005128 ┆ 2005138 ┆ 10       ┆ 0.44098   ┆ 61.197926     │
│ 0       ┆ 1       ┆ saccade ┆ 2005288 ┆ 2005345 ┆ 57       ┆ 14.682541 ┆ 352.550667    │
│ 0       ┆ 1       ┆ saccade ┆ 2005347 ┆ 2005356 ┆ 9        ┆ 0.629861  ┆ 85.484987     │
│ 0       ┆ 1       ┆ saccade ┆ 2005359 ┆ 2005365 ┆ 6        ┆ 0.368268  ┆ 66.68761      │
└─────────┴─────────┴─────────┴─────────┴─────────┴──────────┴───────────┴───────────────┘

Plot the main sequence#

Now we just pass the event dataframe to the plotting function:

[9]:
# only showing the first three event dataframes here.
# note that you can adjust the styling of the plot, e.g. setting a low
# alpha value allows you to see overlapping data points
for event_df in dataset.events[:3]:
    pm.plotting.main_sequence_plot(
        event_df,
        title='Main sequence plot for '
        f'text {event_df[0, "text_id"]}, '
        f'page {event_df[0, "page_id"]}',
        alpha=0.3,
        color='green',
        marker='x',
        marker_size=30,
    )
../_images/tutorials_plot-main-sequence_22_0.png
../_images/tutorials_plot-main-sequence_22_1.png
../_images/tutorials_plot-main-sequence_22_2.png

What you have learned in this tutorial:#

  • how to prepare your data to plot a main sequence

  • how to create a main sequence plot by using main_sequence_plot