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).
Import and setup for preprocessing
Read in raw data file.
pupil_read()
Set Time variable relative to stimulus onset.
set_timing()
Remove unlikely pupil values
Deblink pupil data.
pupil_deblink()
Artifiact rejection.
pupil_artifact()
Evaluate and/or Remove trials
with large amounts of missing data.
pupil_missing()
Preprocess pupil data
Upasmple pupil data to 1000Hz.
pupil_upsample()
Smooth pupil data.
pupil_smooth()
Interpolate pupil data.
pupil_interpolate()
Baseline Correct pupil data.
pupil_baselinecorrect()
Evaluate the amount of missing data per trial
pupil_missing()
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.
# ---- 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())
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())
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