eyelink-reader 0.1.4
A package to import eye tracking recording generated by SR Research Eyelink eye tracker from EDF-files.
Requires Python: >=3.8


# eyelink_reader
[![DOI](https://zenodo.org/badge/882465451.svg)](https://doi.org/10.5281/zenodo.14262527)

**eyelink_reader** is a Python library to import eye tracking recording from  EDF-files generated by [SR Research](https://www.sr-research.com) EyeLink eye tracker. It includes options to import events and/or recorded samples and pasring of individual events such as saccades, fixations, blinks, recorded variables, triggers, and areas-of-interest. Please read documentation at [eyelink-reader.readthedocs.io](https://eyelink-reader.readthedocs.io/).

# Installation

Please note that these instructions may be outdate, i.e., if SR Research changes its software. If that is the case, please [raise an issue](https://github.com/alexander-pastukhov/eyelink_reader/issues).

## Install SR Research EyeLink Developers Kit

This package relies on _edfapi_ library that is as part of the *EyeLink Developers Kit*, which can be downloaded from [www.sr-research.com/support](https://www.sr-research.com/support) website. Note that you need to register and wait for your account to be activated. Next, follow instructions to install *EyeLink Developers Kit* for your platform. The forum thread should be under _SR Support Forum › Downloads › EyeLink Developers Kit / API › Download: EyeLink Developers Kit / API Downloads (Windows, macOS, Linux)_.

**Please note that this package will not work without Eyelink Developers Kit!**

## Specify location of the *edfapi* library

The package looks for _edfapi_ either in the global environment (i.e., the folder is added to the `PATH`) or in a typical path for the OS. The typical locations are:

* For Windows: `c:/Program Files (x86)/SR Research/EyeLink/libs/x64`
* For Mac OSX: `/Library/Frameworks`
* For Linux: `edpapi` library is install in `/usr/lib`, so is in the global path.

If you installed _EyeLink Developers Kit_ using defaults, the typical paths should work. However, you may have used a different folder for installation (relevant primarily for Windows) or it is possible that SR Research changed the defaults. In this case, you can specify path to the library as a parameter or set `EDFAPI_LIB` environment variable.

## Install package via pip
```
pip install eyelink_reader
```

# Usage

All the functionality in encapsulated in the [EDFFile](https://eyelink-reader.readthedocs.io/#edffile-class) class. The minimal call that imports events but not samples and parses all possible events is
```python
from eyelink_reader import EDFFile

gaze = EDFFile("test.edf")
```

## Importing samples

To import samples with all fields use
```python
gaze = EDFFile("test.edf", loadsamples=True)
```

In most cases, you probably only want a subset of fields, which you can specify via `sample_fields` parameter (for the list of fields see [Samples](https://eyelink-reader.readthedocs.io/#samples)). For example, you can only import sample time and eye position in screen coordinates, as shown below. For binocular fields, such as `gx` that are split into `gxL` and `gxR` in [Samples](https://eyelink-reader.readthedocs.io/#samples) table, you only need to specify the common name `gx`.
```python
gaze = EDFFile("test.edf", loadsamples=True, sample_fields=["time", "gx", "gy"])
```

## Specifying custom trial start and end messages
By default, the library assumes that trial start and end are marked by standard messages `"TRIALID"` and `"TRIAL_RESULT"`, respectively. However, you can pass custom messages via `start_marker_string` and `end_marker_string` parameters.
```python
gaze = EDFFile("test.edf", start_marker_string="TRIALID", end_marker_string="TRIAL_RESULT")
```

## Verbose loading
For large files loading may take some seconds. If you want to monitor the process, you can enable a progress bar via `verbose=True`:
```python
gaze = EDFFile("test.edf", loadsamples=True, verbose=True)
```

## Specifying _edfapi_ library path
As described in the [section above](#specify-location-of-the-edfapi-library), [EDFFile](https://eyelink-reader.readthedocs.io/#edffile-class) searches for _edfapi_ library in the global path, path in `EDFAPI_LIB` environtment library, and a typical path for the OS. However, you can also pass the path via `libpath` parameter:
```python
gaze = EDFFile("test.edf", libpath="c:/Program Files (x86)/SR Research/EyeLink/libs/x64")
```

## Parsing specific events
The [events](https://eyelink-reader.readthedocs.io/#Events) attrbiute of [EDFFile](https://eyelink-reader.readthedocs.io/#edffile-class) is a table that contains all recorded events. For convenience, they can be parsed into

* [saccades](https://eyelink-reader.readthedocs.io/#saccades)
* [fixations](https://eyelink-reader.readthedocs.io/#fixations)
* [blinks](https://eyelink-reader.readthedocs.io/#blinks)
* [variables](https://eyelink-reader.readthedocs.io/#variables), see also [Parsing variables](#parsing-variables) section for details.
* [triggers](https://eyelink-reader.readthedocs.io/#triggers), see also [Parsing triggers](#parsing-triggers) section for details.
* [aois](https://eyelink-reader.readthedocs.io/#aois) (areas-of-interest), see also [Parsing AOIs](#parsing-aois) section for details.

A specific set of events to be parsed and extract is specified via `parse_events` parameter. Use `parse_events="all"` to extract all event types (default behavior) and `parse_events=None`, if you do not want events to be parsed. If you only want a subset of events to be parse, pass their names as a list.
```python
# does not parse any event
gaze = EDFFile("test.edf", parse_events=None)

# parses all events
gaze = EDFFile("test.edf", parse_events="all")

# also parses all events, as default is parse_events="all"
gaze = EDFFile("test.edf")


# also parses all events, as all are included in the list
gaze = EDFFile("test.edf",
    parse_events=("saccades", "fixations", "blinks", "variables", "triggers", "aois"))

# only extracts gaze events: saccades, fixations, and blinks
gaze = EDFFile("test.edf", parse_events=("saccades", "fixations", "blinks"))
```

## Parsing variables
Trial variabels are recorded using messages in `!V TRIAL_VAR <variable> <value>` format. Note that _value_ can contain white spaces, but variable name cannot. For example, message `!V TRIAL_VAR Filename Face 01.png` will be parsed into `Filename="Face 01.png"`. If `wide_variables=True` (default), the library pivots table, so that each trial corrresponds to a single row with column `trial` and one column per variable. Note that the library does not attempt to guess column types, so all values are represented as strings. If `wide_variables=False` or there was an exception generated by pivot opeation, the table is in the long format with columns `trial`, `variable`, and `value`. 

## Parsing triggers
Triggers are custom messages with format `<trigger-marker> <label>`. The marker can be specified via `trigger_marker` parameter and its default value is `"TRIGGER"`. 

```python
gaze = EDFFile("test.edf", trigger_marker="TRIGGER")
```

The label can contain white space but marker cannot, so the label for the message `"TRIGGER Initial exposure"` will be `"Initial exposure"`. The triggers are stored in a table with columns `trial`,  `sttime`, `sttime_rel`, and `label`, see also [triggers](https://eyelink-reader.readthedocs.io/#triggers) output table.

## Parsing AOIs
Rectangular areas of interest are described via a message with format `"!V IAREA RECTANGLE <aoi_index> <left> <top> <right> <bottom> <label>"`, the `label` can contain white spaces. For output table details see [areas-of-interest](https://eyelink-reader.readthedocs.io/#areas-of-interest) table.