Saving and Loading Event Data#

What you will learn in this tutorial:#

  • how to save your event data

  • how to load your event data

Preparations#

We import pymovements as the alias pm for convenience.

[1]:
import pymovements as pm
/home/docs/checkouts/readthedocs.org/user_builds/pymovements/envs/v0.20.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, 45.42it/s]
[2]:
<pymovements.dataset.dataset.Dataset at 0x7deb43fae400>

Now let’s do some preprocessing:

[3]:
dataset.pix2deg()
dataset.pos2vel()

dataset.gaze[0]
100%|██████████| 20/20 [00:00<00:00, 22.12it/s]
100%|██████████| 20/20 [00:00<00:00, 45.36it/s]
[3]:
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]     ┆               │
└─────────┴───────────┴───────────┴─────────┴─────────┴───────────┴────────────────┴───────────────┘

Detect some events:

[4]:
dataset.detect_events('ivt')

dataset.events[0]
20it [00:00, 79.46it/s]
[4]:
shape: (73, 6)
┌─────────┬─────────┬──────────┬─────────┬─────────┬──────────┐
│ text_id ┆ page_id ┆ name     ┆ onset   ┆ offset  ┆ duration │
│ ---     ┆ ---     ┆ ---      ┆ ---     ┆ ---     ┆ ---      │
│ i64     ┆ i64     ┆ str      ┆ i64     ┆ i64     ┆ i64      │
╞═════════╪═════════╪══════════╪═════════╪═════════╪══════════╡
│ 0       ┆ 1       ┆ fixation ┆ 1988147 ┆ 1988322 ┆ 175      │
│ 0       ┆ 1       ┆ fixation ┆ 1988351 ┆ 1988546 ┆ 195      │
│ 0       ┆ 1       ┆ fixation ┆ 1988592 ┆ 1988736 ┆ 144      │
│ 0       ┆ 1       ┆ fixation ┆ 1988788 ┆ 1989013 ┆ 225      │
│ 0       ┆ 1       ┆ fixation ┆ 1989060 ┆ 1989170 ┆ 110      │
│ …       ┆ …       ┆ …        ┆ …       ┆ …       ┆ …        │
│ 0       ┆ 1       ┆ fixation ┆ 2004132 ┆ 2004331 ┆ 199      │
│ 0       ┆ 1       ┆ fixation ┆ 2004399 ┆ 2004687 ┆ 288      │
│ 0       ┆ 1       ┆ fixation ┆ 2004714 ┆ 2004878 ┆ 164      │
│ 0       ┆ 1       ┆ fixation ┆ 2004931 ┆ 2005109 ┆ 178      │
│ 0       ┆ 1       ┆ fixation ┆ 2005138 ┆ 2005287 ┆ 149      │
└─────────┴─────────┴──────────┴─────────┴─────────┴──────────┘
[5]:
dataset.detect_events('microsaccades')

dataset.events[0]
20it [00:00, 48.37it/s]
[5]:
shape: (215, 6)
┌─────────┬─────────┬──────────┬─────────┬─────────┬──────────┐
│ text_id ┆ page_id ┆ name     ┆ onset   ┆ offset  ┆ duration │
│ ---     ┆ ---     ┆ ---      ┆ ---     ┆ ---     ┆ ---      │
│ i64     ┆ i64     ┆ str      ┆ i64     ┆ i64     ┆ i64      │
╞═════════╪═════════╪══════════╪═════════╪═════════╪══════════╡
│ 0       ┆ 1       ┆ fixation ┆ 1988147 ┆ 1988322 ┆ 175      │
│ 0       ┆ 1       ┆ fixation ┆ 1988351 ┆ 1988546 ┆ 195      │
│ 0       ┆ 1       ┆ fixation ┆ 1988592 ┆ 1988736 ┆ 144      │
│ 0       ┆ 1       ┆ fixation ┆ 1988788 ┆ 1989013 ┆ 225      │
│ 0       ┆ 1       ┆ fixation ┆ 1989060 ┆ 1989170 ┆ 110      │
│ …       ┆ …       ┆ …        ┆ …       ┆ …       ┆ …        │
│ 0       ┆ 1       ┆ saccade  ┆ 2005110 ┆ 2005126 ┆ 16       │
│ 0       ┆ 1       ┆ saccade  ┆ 2005128 ┆ 2005138 ┆ 10       │
│ 0       ┆ 1       ┆ saccade  ┆ 2005288 ┆ 2005345 ┆ 57       │
│ 0       ┆ 1       ┆ saccade  ┆ 2005347 ┆ 2005356 ┆ 9        │
│ 0       ┆ 1       ┆ saccade  ┆ 2005359 ┆ 2005365 ┆ 6        │
└─────────┴─────────┴──────────┴─────────┴─────────┴──────────┘

We now have event dataframes available with our detected event data.

Saving#

Saving your event data is as simple as:

[6]:
dataset.save_events()
100%|██████████| 20/20 [00:00<00:00, 2881.20it/s]
[6]:
<pymovements.dataset.dataset.Dataset at 0x7deb43fae400>

All of the event data is saved into this directory:

[7]:
dataset.paths.events
[7]:
PosixPath('data/ToyDataset/events')

Let’s confirm it by printing all the new files in this directory:

[8]:
print(list(dataset.paths.events.glob('*/*/*')))
[PosixPath('data/ToyDataset/events/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_1_1.feather'), PosixPath('data/ToyDataset/events/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_2_2.feather'), PosixPath('data/ToyDataset/events/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_2_3.feather'), PosixPath('data/ToyDataset/events/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_0_3.feather'), PosixPath('data/ToyDataset/events/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_1_4.feather'), PosixPath('data/ToyDataset/events/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_2_5.feather'), PosixPath('data/ToyDataset/events/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_3_2.feather'), PosixPath('data/ToyDataset/events/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_1_5.feather'), PosixPath('data/ToyDataset/events/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_0_4.feather'), PosixPath('data/ToyDataset/events/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_3_3.feather'), PosixPath('data/ToyDataset/events/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_3_5.feather'), PosixPath('data/ToyDataset/events/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_3_4.feather'), PosixPath('data/ToyDataset/events/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_2_1.feather'), PosixPath('data/ToyDataset/events/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_0_1.feather'), PosixPath('data/ToyDataset/events/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_3_1.feather'), PosixPath('data/ToyDataset/events/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_1_2.feather'), PosixPath('data/ToyDataset/events/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_0_2.feather'), PosixPath('data/ToyDataset/events/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_1_3.feather'), PosixPath('data/ToyDataset/events/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_2_4.feather'), PosixPath('data/ToyDataset/events/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_0_5.feather')]

All of the files have been saved into the Dataset.paths.events as feather files.

If we want to save the data into an alternative directory and also use a different file format like csv we can use the following:

[9]:
dataset.save_events(events_dirname='events_csv', extension='csv')
100%|██████████| 20/20 [00:00<00:00, 2382.32it/s]
[9]:
<pymovements.dataset.dataset.Dataset at 0x7deb43fae400>

Let’s confirm again by printing all the new files in this alternative directory:

[10]:
alternative_dirpath = dataset.path / 'events_csv'
print(list(alternative_dirpath.glob('*/*/*')))
[PosixPath('data/ToyDataset/events_csv/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_3_1.csv'), PosixPath('data/ToyDataset/events_csv/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_0_2.csv'), PosixPath('data/ToyDataset/events_csv/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_0_3.csv'), PosixPath('data/ToyDataset/events_csv/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_1_4.csv'), PosixPath('data/ToyDataset/events_csv/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_1_3.csv'), PosixPath('data/ToyDataset/events_csv/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_0_4.csv'), PosixPath('data/ToyDataset/events_csv/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_0_5.csv'), PosixPath('data/ToyDataset/events_csv/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_2_5.csv'), PosixPath('data/ToyDataset/events_csv/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_1_5.csv'), PosixPath('data/ToyDataset/events_csv/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_3_4.csv'), PosixPath('data/ToyDataset/events_csv/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_2_2.csv'), PosixPath('data/ToyDataset/events_csv/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_2_1.csv'), PosixPath('data/ToyDataset/events_csv/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_0_1.csv'), PosixPath('data/ToyDataset/events_csv/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_3_2.csv'), PosixPath('data/ToyDataset/events_csv/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_1_1.csv'), PosixPath('data/ToyDataset/events_csv/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_3_3.csv'), PosixPath('data/ToyDataset/events_csv/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_1_2.csv'), PosixPath('data/ToyDataset/events_csv/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_3_5.csv'), PosixPath('data/ToyDataset/events_csv/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_2_4.csv'), PosixPath('data/ToyDataset/events_csv/aeye-lab-pymovements-toy-dataset-6cb5d66/data/trial_2_3.csv')]

Loading#

Now let’s imagine that this preprocessing and saving was done in another file and we only want to load the preprocessed data.

We simulate this by initializing a new dataset object. We don’t need to download any additional data.

[11]:
preprocessed_dataset = pm.Dataset('ToyDataset', path='data/ToyDataset')

The preprocessed data can now simply be loaded by setting preprocessed to True:

[12]:
preprocessed_dataset.load(events=True)

dataset.events[0]
100%|██████████| 20/20 [00:00<00:00, 47.25it/s]
100%|██████████| 20/20 [00:00<00:00, 1681.32it/s]
[12]:
shape: (215, 6)
┌─────────┬─────────┬──────────┬─────────┬─────────┬──────────┐
│ text_id ┆ page_id ┆ name     ┆ onset   ┆ offset  ┆ duration │
│ ---     ┆ ---     ┆ ---      ┆ ---     ┆ ---     ┆ ---      │
│ i64     ┆ i64     ┆ str      ┆ i64     ┆ i64     ┆ i64      │
╞═════════╪═════════╪══════════╪═════════╪═════════╪══════════╡
│ 0       ┆ 1       ┆ fixation ┆ 1988147 ┆ 1988322 ┆ 175      │
│ 0       ┆ 1       ┆ fixation ┆ 1988351 ┆ 1988546 ┆ 195      │
│ 0       ┆ 1       ┆ fixation ┆ 1988592 ┆ 1988736 ┆ 144      │
│ 0       ┆ 1       ┆ fixation ┆ 1988788 ┆ 1989013 ┆ 225      │
│ 0       ┆ 1       ┆ fixation ┆ 1989060 ┆ 1989170 ┆ 110      │
│ …       ┆ …       ┆ …        ┆ …       ┆ …       ┆ …        │
│ 0       ┆ 1       ┆ saccade  ┆ 2005110 ┆ 2005126 ┆ 16       │
│ 0       ┆ 1       ┆ saccade  ┆ 2005128 ┆ 2005138 ┆ 10       │
│ 0       ┆ 1       ┆ saccade  ┆ 2005288 ┆ 2005345 ┆ 57       │
│ 0       ┆ 1       ┆ saccade  ┆ 2005347 ┆ 2005356 ┆ 9        │
│ 0       ┆ 1       ┆ saccade  ┆ 2005359 ┆ 2005365 ┆ 6        │
└─────────┴─────────┴──────────┴─────────┴─────────┴──────────┘

By default, the events directory and the feather extension will be chosen.

In case of alternative directory names or other file formats you can use the following:

[13]:
preprocessed_dataset.load(
    events=True,
    events_dirname='events_csv',
    extension='csv',
)
dataset.events[0]
100%|██████████| 20/20 [00:00<00:00, 46.43it/s]
100%|██████████| 20/20 [00:00<00:00, 1346.90it/s]
[13]:
shape: (215, 6)
┌─────────┬─────────┬──────────┬─────────┬─────────┬──────────┐
│ text_id ┆ page_id ┆ name     ┆ onset   ┆ offset  ┆ duration │
│ ---     ┆ ---     ┆ ---      ┆ ---     ┆ ---     ┆ ---      │
│ i64     ┆ i64     ┆ str      ┆ i64     ┆ i64     ┆ i64      │
╞═════════╪═════════╪══════════╪═════════╪═════════╪══════════╡
│ 0       ┆ 1       ┆ fixation ┆ 1988147 ┆ 1988322 ┆ 175      │
│ 0       ┆ 1       ┆ fixation ┆ 1988351 ┆ 1988546 ┆ 195      │
│ 0       ┆ 1       ┆ fixation ┆ 1988592 ┆ 1988736 ┆ 144      │
│ 0       ┆ 1       ┆ fixation ┆ 1988788 ┆ 1989013 ┆ 225      │
│ 0       ┆ 1       ┆ fixation ┆ 1989060 ┆ 1989170 ┆ 110      │
│ …       ┆ …       ┆ …        ┆ …       ┆ …       ┆ …        │
│ 0       ┆ 1       ┆ saccade  ┆ 2005110 ┆ 2005126 ┆ 16       │
│ 0       ┆ 1       ┆ saccade  ┆ 2005128 ┆ 2005138 ┆ 10       │
│ 0       ┆ 1       ┆ saccade  ┆ 2005288 ┆ 2005345 ┆ 57       │
│ 0       ┆ 1       ┆ saccade  ┆ 2005347 ┆ 2005356 ┆ 9        │
│ 0       ┆ 1       ┆ saccade  ┆ 2005359 ┆ 2005365 ┆ 6        │
└─────────┴─────────┴──────────┴─────────┴─────────┴──────────┘

What you have learned in this tutorial:#

  • saving your preprocesed data using Dataset.save_preprocessed()

  • load your preprocesed data using Dataset.load(preprocessed=True)

  • using custom directory names by specifying preprocessed_dirname

  • using other file formats than the default feather format by specifying extension