This is a short overview on how to perform preprocessing on pupil data by building a sequence of functions using the pipe operator %>% or |>.

For more detailed instructions on each of the steps, see the detailed articles.

The recommended preprocessing steps and their order of operation varies among researchers. In general, the following preprocessing workflow and steps are recommended based on Geller et al. (2020), Kret and Sjak-Shie (2019), and Mathôt et al. (2018).

  1. Import and setup for preprocessing

  2. Remove unlikely pupil values

  3. Preprocess pupil data

These function will perform preprocessing on one data file at a time. You will need to perform preprocessing on an entire list of data files contained in a folder somewhere. You can either do this with purrr::map() or with a for loop.

purrr::map()

# ---- Setup -------------------------------------------------------------------
# packages
library(pupillometry)
library(purrr)
library(readr)

# directories
import_dir <- "data/raw"
output_dir <- "data/preprocessed"

# files
files_list <- list.files(import_dir, pattern = ".txt", full.names = TRUE)
# ------------------------------------------------------------------------------

# ---- Preprocess --------------------------------------------------------------
data_pupil <- files_list |>
  map(pupil_read, eyetracker = "tobii", eye_use = "left",
      include_col = c("RT", "accuracy", "condition"),
      quality_check_dir = output_dir) |>
  map(set_timing, onset_message = "Fixation_Onset") |>
  map(pupil_deblink, extend = 75) |>
  map(pupil_artifact, n = 8) |>
  map(pupil_artifact, n = 8) |> # recommended to do twice
  map(pupil_missing, missing_allowed = .90) |>
  map(pupil_upsample) |>
  map(pupil_smooth, type = "hann", n = 200) |>
  map(pupil_interpolate, type = "cubic-spline", maxgap = 750, hz = 1000) |>
  map(pupil_baselinecorrect, bc_onset_message = "Stimulus_Onset",
      baseline_duration = 200, type = "subtractive") |>
  map(pupil_missing)

# save preprocess data files
map(data_pupil,
    function(df) {
      file_name <- paste0("eyetracker_", df$Subject[1],
                          "_deblink.artifact.smooth.interpolate.bc.csv")
      write_csv(df, here(output_dir, file_name))
    })
# ------------------------------------------------------------------------------

# ---- Bin ---------------------------------------------------------------------
data_bin <- map(data_pupil, pupil_bin, bin_length = 20)

# save binned data files
map(data_bin, 
    function(df) {
      file_name <- paste0("eyetracker_", df$Subject[1], "_binned.csv")
      write_csv(df, here(output_dir, file_name))
    })
# ------------------------------------------------------------------------------

rm(list = ls())

For Loop

You can copy and paste this code and edit it as needed for your data

# ---- Setup -------------------------------------------------------------------
# packages
library(pupillometry)
library(readr)

# directories
import_dir <- "data/raw"
output_dir <- "data/preprocessed"

# files
files_list <- list.files(import_dir, pattern = ".txt", full.names = TRUE)
# ------------------------------------------------------------------------------

# ---- Preprocess --------------------------------------------------------------
for (file in files_list) {
  data_pupil <- file |>
    pupil_read(file, eyetracker = "eyelink", eye_use = "left",
               include_col = c("RT", "accuracy", "condition"),
               quality_check_dir = output_dir) |>
    set_timing(onset_message = "Stimulus_Onset") |>
    pupil_deblink(extend = 75) |>
    pupil_artifact(n = 8) |>
    pupil_missing(missing_allowed = .90) |>
    pupil_upsample() |>
    pupil_smooth(type = "hann", n = 250) |>
    pupil_interpolate(type = "cubic-spline", maxgap = 750, hz = 1000) |>
    pupil_baselinecorrect(bc_onset_message = "Stimulus_Onset",
                          baseline_duration = 200,
                          type = "subtractive") |>
    pupil_missing()
  
  ## save preprocessed data files
  output_file <- paste0(output_dir, "/eyetracker_", data_pupil$Subject[1], 
                       "_deblink.artifact.smooth.interpolate.bc.csv")
  write_csv(data_pupil, output_file)
  
  ## save binned data files
  data_bin <- pupil_bin(data_pupil, bin_length = 20)
  output_bin <- paste0(output_dir, "/eyetracker_", data_bin$Subject[1],
                       "_binned.csv")
  write_csv(data_bin, output_bin)
}


# ------------------------------------------------------------------------------

rm(list = ls())

References

Geller, J., Winn, M. B., Mahr, T., & Mirman, D. (2020). GazeR: A Package for Processing Gaze Position and Pupil Size Data. Behavior Research Methods, 52(5), 2232–2255. https://doi.org/10.3758/s13428-020-01374-8

Kret, M. E., & Sjak-Shie, E. E. (2019). Preprocessing pupil size data: Guidelines and code. Behavior Research Methods, 51(3), 1336–1342. https://doi.org/10.3758/s13428-018-1075-y

Mathôt, S., Fabius, J., Van Heusden, E., & Van der Stigchel, S. (2018). Safe and sensible preprocessing and baseline correction of pupil-size data. Behavior Research Methods, 50(1), 94–106. https://doi.org/10.3758/s13428-017-1007-2