Type: Package
Title: Extract Saccades via an Ensemble of Methods Approach
Version: 0.1.3
Date: 2023-09-06
Description: A modular and extendable approach to extract (micro)saccades from gaze samples via an ensemble of methods. Although there is an agreement about a general definition of a saccade, the more specific details are harder to agree upon. Therefore, there are numerous algorithms that extract saccades based on various heuristics, which differ in the assumptions about velocity, acceleration, etc. The package uses three methods (Engbert and Kliegl (2003) <doi:10.1016/S0042-6989(03)00084-1>, Otero-Millan et al. (2014)<doi:10.1167/14.2.18>, and Nyström and Holmqvist (2010) <doi:10.3758/BRM.42.1.188>) to label individual samples and then applies a majority vote approach to identify saccades. The package includes three methods but can be extended via custom functions. It also uses a modular approach to compute velocity and acceleration from noisy samples. Finally, you can obtain methods votes per gaze sample instead of saccades.
License: GPL (≥ 3)
URL: https://github.com/alexander-pastukhov/saccadr/, https://alexander-pastukhov.github.io/saccadr/
BugReports: https://github.com/alexander-pastukhov/saccadr/issues/
Imports: magrittr, Rcpp (≥ 1.0.8)
LinkingTo: Rcpp
Encoding: UTF-8
LazyData: true
RoxygenNote: 7.2.3
VignetteBuilder: knitr
Depends: R (≥ 4.1.0), dplyr, rlang, cluster, signal, tidyr
Suggests: rmarkdown, knitr, ggplot2, spelling, testthat (≥ 3.0.0)
Language: en-US
Config/testthat/edition: 3
NeedsCompilation: yes
Packaged: 2023-09-06 14:13:09 UTC; ba7dr4
Author: Alexander Pastukhov ORCID iD [aut, cre]
Maintainer: Alexander Pastukhov <pastukhov.alexander@gmail.com>
Repository: CRAN
Date/Publication: 2023-09-06 15:30:02 UTC

saccadr: Extract Saccades via an Ensemble of Methods Approach

Description

Extract (Micro)Saccades From Gaze Samples.

Author(s)

Maintainer: Alexander Pastukhov pastukhov.alexander@gmail.com (ORCID)

See Also

Useful links:


Pipe operator

Description

See magrittr::%>% for details.

Usage

lhs %>% rhs

Arguments

lhs

A value or the magrittr placeholder.

rhs

A function call using the magrittr semantics.

Value

The result of calling 'rhs(lhs)'.


Compute velocity via Engbert & Kliegl (2003) algorithm.

Description

Compute velocity via Engbert & Kliegl (2003) algorithm. See formula #1 in the manuscript.

Usage

compute_velocity_ek(x, trial, time_window_in_samples, delta_t)

Arguments

x

Vector of coordinates

trial

Vector with trial labels, so that velocity is computed only within trials.

time_window_in_samples

Width of window for velocity computation in samples.

delta_t

Duration of a single frame (1 / sampling rate).

Value

Velocity vector


Differentiate x and y and compute change amplitude via an algorithm proposed by Engbert & Kliegl (2003)

Description

Differentiate x and y and compute change amplitude via an algorithm proposed by Engbert & Kliegl (2003)

Usage

diff_ek(x, y, trial, sample_rate, options = NULL)

Arguments

x

vector with x coordinates in degrees of visual angle

y

vector with y coordinates in degrees of visual angle

trial

vector with trial index

sample_rate

sample rate in Hz

options

List with method specific options, see Details.

Details

Method options, please refer to Engbert & Kliegl (2003) for details on parameters and the rationale for default values.

Value

data.frame with columns x, y, and amp

See Also

compute_velocity_ek

Examples

diff_ek(rnorm(1000), rnorm(1000), rep(1, 1000), 250, list("ek_velocity_time_window" = 20))

Differentiate x and y and compute change amplitude via an algorithm proposed by Nyström and Holmqvist (2010) doi:10.3758/BRM.42.1.188

Description

Differentiate x and y and compute change amplitude via an algorithm proposed by Nyström and Holmqvist (2010) doi:10.3758/BRM.42.1.188. Note that both components and the amplitude are smoothed independently via a Savitzky-Golay filter, so the components may not (probably won't) add up to the amplitude. Note that filtering is sensitive to the presence of NA.

Usage

diff_nh(x, y, trial, sample_rate, options = NULL)

Arguments

x

vector with x coordinates in degrees of visual angle

y

vector with y coordinates in degrees of visual angle

trial

vector with trial index

sample_rate

sample rate in Hz

options

List with method specific options, see Details.

Details

Method options, please refer to Nyström and Holmqvist (2010) for details on parameters and the rationale for default values.

Value

data.frame with columns x, y, and amp

See Also

filter_via_savitzky_golay

Examples

diff_nh(rnorm(1000), rnorm(1000), rep(1, 1000), 250, list("nh_sg_filter_order" = 2))

Extract saccades from samples using votes from selected methods.

Description

Extract saccades from samples using votes from selected methods. Each method votes whether a given sample belongs to a saccade. Next, saccades are identified via a majority vote using the vote_threshold parameter, as well as a minimum duration and minimal temporal separation criteria. Please note that units of the gaze samples must be in degrees of visual angle. The units are important as some methods use specific (e.g., physiologically plausible) velocity and acceleration thresholds.

By default, ensemble includes methods proposed by Engbert & Kliegl (2003) ("ek"), Otero-Millan et al. ("om"), and Nyström & Holmqvist (2010) ("nh"), see Implemented Methods vignette. However, it can be extended via custom methods, see Using Custom Methods vignette.

By default, the function returns a table with identified saccades but can return a matrix with methods' votes per sample instead (return_votes = TRUE).

Usage

extract_saccades(
  x,
  y,
  sample_rate,
  trial = NULL,
  methods = list(method_ek, method_om, method_nh),
  velocity_function = saccadr::diff_ek,
  options = NULL,
  binocular = "merge",
  vote_threshold = ifelse(length(methods) == 1, 1, (length(methods) - 1)),
  minimal_duration_ms = 12,
  minimal_separation_ms = 12,
  return_votes = FALSE
)

Arguments

x

Horizontal coordinate, either a vector for monocular data or a two-column matrix for binocular data.

y

Vertical coordinate, either a vector for monocular data or a two-column matrix for binocular data.

sample_rate

Sampling rate in Hz. It is assumed to be common for the entire time series. If the time series contains chunks (trials) that were recorded using different acquisition rate (e.g., SR Research Eyelink allows to set different acquisition rate for each recording / trial), you would need to split the time series and analyze them separately.

trial

Optional vector with trial ID. If omitted, all samples are assumed to belong to a single trial. Velocity, acceleration, and saccades themselves are computed respecting trial borders.

methods

A list with saccade detection methods, can include external functions that implement sample classification (see Using Custom Methods vignette). Package methods include Engbert & Kliegl (2003) (method_ek), Otero-Millan et al. (2014) (method_om), Nyström and Holmqvist (2010) (method_nh). Defaults to the list of all internally implemented methods: list(method_ek, method_om, method_nh).

velocity_function

A handle to a function to compute velocity and acceleration. Defaults to a method suggested by Engbert & Kliegl (2003) diff_ek. The package also implements the method proposed by Nyström and Holmqvist (2010) diff_nh. See vignette "Velocity computation" for details and information on how to implement a custom method.

options

A named list with options for saccade detection (see method_ek, method_om, method_nh) and velocity (diff_ek, diff_nh) computation. See documentation on specific method for details.

binocular

Specifies how a binocular data is treated. Options are "cyclopean" (binocular data is converted to an average cyclopean image before saccades are extracted), "monocular" (saccades are extracted independently for each eye), "merge" (default, sample votes are obtained from both eyes and for all methods and then averaged. This way only binocular saccades, i.e., eye movements with a sufficient temporal overlap between eyes, are detected.).

vote_threshold

Value between 1 and N (where N is number of used methods) defining a vote threshold for a saccade. By default, all but one method threshold = N-1 must agree for a sample to be considered for a saccade. Threshold of 1 is applied if a single method is used.

minimal_duration_ms

Minimal duration of a saccade in milliseconds. Shorter candidate saccades are discarded,

minimal_separation_ms

Minimal time separation between saccades in milliseconds. Saccades that are separated by a shorter interval of "not a saccade" votes, will be merged including that period.

return_votes

Logical. Whether function should return extracted microsaccades (FALSE, default) or votes per sample (TRUE).

Details

Variables that describe saccade

Value

A data.frame with saccade properties (see details), if return_votes = FALSE. Alternatively, it returns votes per sample (return_votes = TRUE). For a monocular processing (monocular input, cyclopean or merged binocular data) it is a matrix with nrow(x) rows and length(methods) columns with 0/1 votes for each sample and method. For binocular processing, function returns a two element list with the similar matrices but per eye.

See Also

method_ek, method_om, method_nh, diff_ek, diff_nh

Examples

# Single trial
data(single_trial)
saccades <- extract_saccades(single_trial$x, single_trial$y, 500)

# Multiple trials
data(monocular_ten_trials)
saccades <- extract_saccades(monocular_ten_trials$x,
                             monocular_ten_trials$y, 
                             500,
                             trial = monocular_ten_trials$trial)
 
 # binocular saccades                            
 data("single_trial_binocular")
 saccades_b <- saccadr::extract_saccades(single_trial_binocular[, c('xL', 'xR')],
                                         single_trial_binocular[, c('yL', 'yR')],
                                         sample_rate = 1000)
                                         
 # cyclopean saccades from binocular data
saccades_c <- saccadr::extract_saccades(single_trial_binocular[, c('xL', 'xR')],
                                        single_trial_binocular[, c('yL', 'yR')],
                                        sample_rate = 1000,
                                        binocular = "cyclopean")

 # monocular saccades from binocular data
saccades_m <- saccadr::extract_saccades(single_trial_binocular[, c('xL', 'xR')],
                                       single_trial_binocular[, c('yL', 'yR')],
                                       sample_rate = 1000,
                                       binocular = "monocular")
                             
# Using a single method
saccades <- extract_saccades(single_trial$x, single_trial$y, 500, methods = method_om)

# Using two methods
saccades <- extract_saccades(single_trial$x,
                             single_trial$y,
                             500,
                             methods = list(method_ek, method_om))

#  Alternative velocity computation method
saccades <- extract_saccades(single_trial$x, single_trial$y, 500, velocity_function = diff_nh)

# A strict unanimous decision threshold
saccades <- extract_saccades(single_trial$x, single_trial$y, 500, vote_threshold = 3)

# A slacker criterion that at least one of the three methods must label sample as a saccade
saccades <- extract_saccades(single_trial$x, single_trial$y, 500, vote_threshold = 1)

# Only longish saccades are extracted
saccades <- extract_saccades(single_trial$x, single_trial$y, 500, minimal_duration_ms = 20)

Smooths signal using Savitzky-Golay and then shifts the filtered signal back

Description

Smooths signal using Savitzky-Golay and then shifts the filtered signal back

Usage

filter_via_savitzky_golay(x, sg_order)

Arguments

x

vector of float

sg_order

integer, order of the filter

Value

vector of float

Examples

filter_via_savitzky_golay(rnorm(1000), 2)

Converts inputs to matrix

Description

Converts inputs (vector, matrix, data.frame/tibble) to a matrix preserving number of columns

Usage

input_to_matrix(x)

Arguments

x

vector, matrix, data.frame/tibble

Value

matrix

Examples

input_to_matrix(1:5)

Extract saccades using an algorithm proposed by Engbert and Kliegl (2003) doi:10.1016/S0042-6989(03)00084-1

Description

Extract saccades using an algorithm proposed by Engbert and Kliegl (2003) doi:10.1016/S0042-6989(03)00084-1

Usage

method_ek(x, y, vel, acc, sample_rate, trial, options)

Arguments

x

Gaze x coordinate, _arbitrary units_ as threshold velocity is computed in units of standard deviation.

y

Gaze x coordinate, _arbitrary units_ as threshold velocity is computed in units of standard deviation.

vel

Velocity data.frame with columns x, y, amp.

acc

Acceleration data.frame with columns x, y, amp.

sample_rate

Sample rate in Hz.

trial

Trial id, so that trial borders are respected when computing velocity and saccades.

options

Named list with method options. See details for further information.

Details

Method options, please refer to Engbert and Kliegl (2003) for details on parameters and the rationale for default values.

Value

logical vector marking samples that belong to saccades

See Also

extract_saccades

Examples

# Do not run this function directly, use extract_saccades() instead

Extract saccades using an algorithm proposed by Nyström and Holmqvist (2010) doi:10.3758/BRM.42.1.188.

Description

Extract saccades using an algorithm proposed by Nyström and Holmqvist (2010) doi:10.3758/BRM.42.1.188.

Usage

method_nh(x, y, vel, acc, sample_rate, trial, options)

Arguments

x

Gaze x coordinate, _arbitrary units_ as threshold velocity is computed in units of standard deviation.

y

Gaze y coordinate, _arbitrary units_ as threshold velocity is computed in units of standard deviation.

vel

Velocity data.frame with columns x, y, amp.

acc

Acceleration data.frame with columns x, y, amp.

sample_rate

Sample rate in Hz.

trial

Trial id, so that trial borders are respected when computing velocity and saccades.

options

Named list with method options. See details for further information.

Details

Method options, please refer to Nyström and Holmqvist (2010) for details on parameters and the rationale for default values.

Value

logical vector marking samples that belong to saccades

See Also

extract_saccades

Examples

# Do not run this function directly, use extract_saccades() instead

Extract saccades using an algorithm proposed by Otero-Millan et al. (2014) doi:10.1167/14.2.18

Description

Extract saccades using an algorithm proposed by Otero-Millan et al. (2014) doi:10.1167/14.2.18

Usage

method_om(x, y, vel, acc, sample_rate, trial, options)

Arguments

x

Gaze x coordinate, _arbitrary units_ as threshold velocity is computed in units of standard deviation.

y

Gaze x coordinate, _arbitrary units_ as threshold velocity is computed in units of standard deviation.

vel

Velocity data.frame with columns x, y, amp.

acc

Acceleration data.frame with columns x, y, amp.

sample_rate

Sample rate in Hz.

trial

Trial id, so that trial borders are respected when computing velocity and saccades.

options

Named list with method options. See details for further information.

Details

Method options, please refer to Otero-Millan et al. (2014) for details on parameters and the rationale for default values.

Value

logical vector marking samples that belong to saccades

See Also

extract_saccades

Examples

# Do not run this function directly, use extract_saccades() instead

A monocular multi-trial recording

Description

A monocular recording, 10 trials, sampling rate 500 Hz.

Usage

monocular_ten_trials

Format

A data frame with 14353 rows and 4 variables:

trial

Trial index.

x

X coordinate in degrees of visual angle.

y

Y coordinate in degrees of visual angle.

time

Sample time in milliseconds.


Extract value for a named list or use default if key is missing

Description

Extract value for a named list or use default if key is missing

Usage

option_or_default(options, key, default)

Arguments

options

Named list

key

String key

default

Default value to be returned, if key is missing.

Value

Value from a list or default value

Examples

option_or_default(list("A" = 25), "A", 20)
option_or_default(list("A" = 25), "B", 20)

Compute standard deviation via median estimator.

Description

Compute standard deviation via median estimator. Please refer to formula #2 in Engbert & Kliegl (2003). Falls back on mean estimator, if computed standard deviation is smaller than .Machine$double.eps. Raises an error if the results using the mean estimator is still smaller than .Machine$double.eps.

Usage

sd_via_median_estimator(x, na.rm = FALSE)

Arguments

x

Numeric values

na.rm

Whether to exclude NA values, defaults to FALSE.

Value

float

Examples

sd_via_median_estimator(rnorm(100))

A single trial monocular samples recorded at 500 Hz.

Description

A single trial monocular samples recorded at 500 Hz.

Usage

single_trial

Format

A data frame with 1006 rows and 2 variables:

x

X coordinate in degrees of visual angle.

y

Y coordinate in degrees of visual angle.


A single trial binocular recording.

Description

A single trial binocular recording sampled at 1000 Hz.

Usage

single_trial_binocular

Format

A data frame with 2000 rows and 6 variables:

trial

Trial index.

time_rel

Sample time in milliseconds relative to the trial start.

xL

X coordinate for the left eye in degrees of visual angle.

xR

X coordinate for the right eye in degrees of visual angle.

yL

Y coordinate for the left eye in degrees of visual angle.

yR

Y coordinate for the right eye in degrees of visual angle.