# edfImport
This library provides a simple interface to import contents of the EDF files __generated by Eyelink eye-tracker__ into Matlab. If you don't know what are EDF files generated by Eyelink, you don't need this library (_i.e._, there are other file types that also have EDF extension). It imports events and/or samples, automatically parsing them into separate trials. In addition to that, several post-processing functions can be used to extract selected events (fixations, saccades and blinks), variable values (`TRIAL_VAR` events) and microsaccades.
If you find any bugs, please email me at <Pastukhov.Alexander@gmail.com>.
## Prerequisite
This library relies on EDF API provided by SR-Research on their support web-site [www.sr-support.com](http://www.sr-support.com). This library was tested to work with version 2.5 of EDF API.
For details on structures and fields please consult EDF API manual. Note, that there are some discrepancies between the manual and the actual library implementation. For example in the `FSAMPLE` structure the manual lists `status` field. However, it is not defined in the library itself.
Another important note: although MATLAB creates any value as double by default, it is very stringent on how it handles the types when they are defined. So, for example, if you will subtract time fields you will never get a negative value, as they are defined as `unsigned`. To override it just use `double(variable)` to convert it to double.
## Installation
Clone the repo: `git clone https://github.com/alexander-pastukhov/edfImport.git` or download the ZIP and extract it into the folder of your liking. Add this folder to Matlab's path.
## Compilation
Precompiled mex files (32- and 64-bit Windows Matlab only) are included but you can compile them yourself by running `edfCompile.m` script. You might need to setup the compiler for your system first: Run `mex -setup` and follow the instructions. Please check paths to include files (`*.h` files) and libraries (`*.dll` files for Windows, `*.lib` files for OS X) that are specified in the `edfCompile.m` file. Default locations are as follows:
#### For Windows 32 bit (typical installation):
* includes: c:\Program Files (x86)\SR Research\EyeLink\Includes\eyelink\ (formerly in C:\Program Files\SR Research\EyeLink\EDF_Access_API\Example)
* library: c:\Program Files (x86)\SR Research\EyeLink\libs\ (formerly in C:\Program Files\SR Research\EyeLink\EDF_Access_API\lib\win32)
#### For Windows 64 bit (typical installation):
* includes: c:\Program Files (x86)\SR Research\EyeLink\Includes\eyelink\ (formerly in C:\Program Files (x86)\SR Research\EyeLink\EDF_Access_API\Example)
* library: c:\Program Files (x86)\SR Research\EyeLink\libs\x64\ (formerly in C:\Program Files (x86)\SR Research\EyeLink\EDF_Access_API\lib\win32)
#### For Mac OS X (typical installtion):
* includes: /Library/Frameworks/edfapi.framework/Headers/
* library: /Library/Frameworks/edfapi.framework/
I have never tested it on Linux, but compilation should be straightforward. Write me if you need help with it.
## How to use
To import data from the EDF file call `edfImport` function, e.g.:
```matlab
Trials= edfImport('test.edf', [1 1 1], '');
```
This will import all events and samples into vector `Trials` structures (see section [Trial structure](#trial-structure) for details). Next you can call `edfExtractInterestingEvents` to extract fixations, saccades, blinks and button presses recorded by the eye tracker; `edfExtractMicrosaccades` to extract microsaccades based on raw eyes positions; `edfExtractVariable` for variables and values stored during recording.
## Known limitations
While `edfExtractVariables` function can automatically extract variable values, it assumes that they were recorded using `TRIAL_VAR` message. Combination of `TRIAL_VAR_LABELS` and `TRIALS_VAR_DATA` currently is not supported.
## License
Code released under the MIT license.
---
# Reference
## Functions
### edfImport
Imports events and/or samples from the EDF file.
__Syntax__
```matlab
Trials= edfImport(Filename, Options, SampleFields, TrimSamplesToCorrectNumber)
Trials= edfImport(Filename, Options, SampleFields)
Trials= edfImport(Filename, Options)
Trials= edfImport(Filename)
[Trials, Preamble]= edfImport(...)
```
__Description__
```matlab
Trials= edfImport(Filename, Options, SampleFields, TrimSamplesToCorrectNumber)
```
imports events and/or samples from the file `Filename`. `Options` argument is a vector with following flags [`consistency` `load_events` `load_samples`], where
`consistency`:
* 0: no consistency check
* 1: check consistency and report (_default_)
* 2: check consistency and fix
`load_events`:
* 0: do not load events
* 1: load events (_default_)
`load_samples`"
* 0: do not load samples (_default_)
* 1: load samples
`SampleFields` is a space-separated list of `FSAMPLE` structure fields to be imported. If `load_samples` is 0 this argument is ignored. To import all fields omit `SampleField` argument or pass an empty string.
`TrimSamplesToCorrectNumber` (_default_: __true__): truncates samples to the real number of imported samples. Arrays may be longer as they are pre-allocated by computing the number of samples based on recording duration and sampling frequency. Typically, you may get one (last) empty sample.
```matlab
Trials= edfImport(Filename, Options)
```
if `load_samples` is 1, imports all `FSAMPLE` fields.
```matlab
Trials= edfImport(Filename)
```
uses default `Options= [1 1 0]`.
```matlab
[Trials, Preamble]= edfImport(...)
```
additionally imports `Preamble` of the EDF file (see EDF API manual for details).
__Examples__
Importing events only from the file `test.edf`:
```matlab
Trials= edfImport('test.edf');
```
Importing everything:
```matlab
Trials= edfImport('test.edf', [1 1 1]);
```
Importing selected \textit{FSAMPLE} fields
```matlab
Trials= edfImport('test.edf', [1 1 1], 'time gx gy rx ry');
```
### edfExtractInterestingEvents
Extract fixations, saccades, blinks and button presses from events and places them into new fields within `Trial` structure.
__Syntax__
```matlab
Trials= edfExtractInterestingEvents(Trials)
```
__Description__
Extracts fixations, saccades and blinks from events and places them, respectively, into `Fixations`, `Saccades`, and `Blinks` field in the updated `Trials` structure. New substructures contain the following fields (see details in EDF API manual):
* Fixations: eye, sttime, entime, time, gavx, gavy, PixInDegX, PixInDegY
* Saccades: eye, sttime, entime, time, gstx, gsty, genx, geny, avel, pvel, ampl, phi, PixInDegX, PixInDegY
* Blinks: eye, sttime, entime, time
* Buttons: ID, Pressed, time
### edfExtractMicrosaccades
Extracts microsaccades from the raw eye positions data using algorithm described in [Engbert & Kliegl (2003)](http://dx.doi.org/10.1016/S0042-6989(03)00084-1). If you use this function, please cite _Engbert, R. and R. Kliegl (2003). "Microsaccades uncover the orientation of covert attention." Vision Res 43(9): 1035-45._
__Syntax__
```matlab
Trials= edfExtractMicrosaccadesForTrial(Trials,VelocityBraketMS, VelocityThreshold, MinimalDurationMS, MinimalSeparationMS)
Trials= edfExtractMicrosaccadesForTrial(Trials)
```
__Description__
Extracts microsaccades using raw eye positions. This requires that `Samples` field exists (_i.e._, samples were imported) and the following fields are present: `time`, `gx`, `gy`. Refresh rate of the camera for recording is taken from `Trials().Header.rec.sample_rate` field.
Additional options and their default values (used if the option is omitted), for more details consult Engbert & Kliegl (2003).
* `VelocityBraketMS`: time span around current sample with which to compute the velocity in milliseconds. _Default: 20 ms._
* `VelocityThreshold`: velocity threshold for microsaccade detection in medians. _Default: 6._
* `MinimalDurationMS`: minimal microsaccade duration in milliseconds. _Default: 12 ms._
* `MinimalSeparationMS`: minimal time in milliseconds allowed between two microsaccades, otherwise they are merged. _Default: 12 ms._
For information on the appended `Microsaccades` structure see [Trial structure](#trial-structure).
## edfExtractVariables
Extracts variables and their values from `TRIAL_VAR` messages. Note `TRIAL_VAR_LABELS` and `TRIAL_VAR_DATA` are currently not supported.
__Syntax__
```matlab
Trials= edfExtractVariables(Trials)
```
__Description__
Extracts variables and their values from `TRIAL_VAR` messages (in `Events` structure) and stores them into a new field `Variables` with each variable being a new subfield. During recording variables can be saved using either space-separated format `TRIAL_VAR VarName VarValue` or using a MATLAB-compatible syntax `TRIAL_VAR VarName=VarValue`. In the latter case you can use any MATLAB-legal expression for `VarValue`.
### edfExtractKeyEventsTiming
Extracts time of the events recorded with `KEY_EVENT` message.
__Syntax__
```matlab
Trials= edfExtractKeyEventsTiming(Trials)
```
__Description__
This is a non-standard function. In order to have precise timing of experimental events in eye-tracker time units, I record them using `eyemsg_printf("KEY_EVENT SomeImportantEvent")`. This way I know exactly when it happened and later use this function to extract the timing. Information is stored in the new field `KeyEvents` with each event name being a new subfield and timing in eye tracker time units stored as a value. For example `KEY_EVENT MaskOnset` becomes `Trials(iT).KeyEvents.MaskOnset= T;` (there `T` is the time of the event). Note, you can use event codes like `KEY_EVENT FrameOnset(1)` and `KEY_EVENT FrameOnset(2)`, in this case you will get a two element vector `KeyEvents.FrameOnset= [T1 T2]`.
### edfCheckFixationStability
Verifies that all fixations happen within a safe radius around the fixation mark.
__Syntax__
```matlab
Trials= edfCheckFixationStability(Trials, Fixation, ValidRadius)
```
__Description__
Checks fixations for each trial to verify that they are within a safe radius away from the fixation. `Fixation` is a 2 element vector for the fixation position on the screen __in pixels__: [x, y]. `ValidRadius` is a maximum tolerable deviation from fixation __in degress of visual angle__. Each trial is appended with a new `Valid` field, which is 1 if trial is valid and 0, if some fixations fell outside of the safe radius.
## Trial structure
Each trial structure could contain following fields/substructures. Which fields are available depends on what kind of processing was done.
* __Header__: this is a `TRIAL` structure, for details see EDF API manual.
* __Events__: this is a `FEVENT` structure, for details see EDF API manual.
* __Samples__: this is a `FSAMPLE` structure with an additional field `RealNumberOfSamples`, for details see EDF API manual. Note, only fields which you chose to import, when calling `edfImport`, will be present plus `RealNumberOfSamples`. Latter contains real number of imported samples and is used by `edfImport` function to truncate fields to eliminate empty samples (see [edfImport](#edfImport) for details).
* __StartTime__: time of the first sample recording (the trial itself starts earlier). Added by [edfExtractInterestingEvents](#edfExtractInterestingEvents) function.
* __Fixations__: information about all fixations, as detected by the eye tracker. Fields indclude: eye, sttime, entime, time, gavx, gavy, PixInDegX, PixInDegY. Added by [edfExtractInterestingEvents](#edfExtractInterestingEvents) function.
* __Saccades__: information about all saccades, as detected by the eye tracker. Fields indclude: eye, sttime, entime, time, gstx, gsty, genx, geny, avel, pvel, ampl, phi, PixInDegX, PixInDegY. Added by [edfExtractInterestingEvents](#edfExtractInterestingEvents).
* __Blinks__: information about all blinks, as detected by the eye tracker. Fields include: eye, sttime, entime, time. Added by [edfExtractInterestingEvents](#edfExtractInterestingEvents)..
* __Microsaccades__: information about extracted microsaccades. Added by [edfExtractMicrosaccades](#edfExtractMicrosaccades). Subfields:
* _Start_: index of the microsaccade start in Samples.
* _End_: index of the microsaccade end in Samples.
* _StartTime_: start of the microsaccade in eye tracker time.
* _EndTime_: end of the microsaccade in eye tracker time.
* _DeltaX_: horizontal component.
* _DeltaY_: vertical component.
* _vPeak_:} peak velocity.
* _Amplitude_: amplitude (traveled distance).
* _Phi_: direction in degrees (not radians).
* _Duration_: in milliseconds.
* __Variables__: contains all variables and values stored during recording with `TRIAL\_VAR` eye tracker command. Added by [edfExtractVariables](#edfExtractVariables)
function.
* __KeyEvents__: contains names (as fields) and time (as values) of key events recorded with a custom `KEY_EVENT` message. Added by [edfExtractKeyEventsTiming](#edfExtractKeyEventsTiming) function.
* __Valid__: generated by [edfCheckFixationStability](#edfCheckFixationStability). 1 if trial is valid, 0 if some fixation occured outside of the safe radius.
## Service functions
### edfMexImport
Imports information from EDF file. Don't call it directly, please use wrapper [edfImport](#edfImport) which has safety checks for passed arguments.
### edfSelectSampleFields
Converts list of space-separated names of `FSAMPLE` structure fields into a boolean array of flags, later passed to [edfImport](#edfImport) function. Used by [edfImport](#edfImport).
### edfCompile
OS-sensitive script for library compilation. Modify it to suite your environment.
### edfFindTrialRecordingStart
Locates beginning of samples recording, used by [edfExtractMicrosaccades](edfExtractMicrosaccades).