load_generic: Load pupillometry data from a non-EyeLink eye tracker

View source: R/pipeline-loadgeneric.R

load_genericR Documentation

Load pupillometry data from a non-EyeLink eye tracker

Description

Construct a valid eyeris S3 object from standardized data frames so that data from eye trackers other than SR Research EyeLink can enter the eyeris preprocessing pipeline. While load_asc() parses EyeLink .asc files specifically, load_generic() provides a tracker-agnostic ingestion path: you supply the raw samples (and, optionally, event messages, gaze coordinates, and blink intervals) as plain R data frames, and load_generic() assembles them into the same object structure that the rest of eyeris (including glassbox()) expects.

Usage

load_generic(
  pupil,
  events = NULL,
  blinks = NULL,
  gaze = NULL,
  sample_rate = NULL,
  time_unit = c("ms", "s"),
  block = "auto",
  eye = c("L", "R", "LR"),
  pupil_type = c("area", "diameter"),
  screen_width = NA_real_,
  screen_height = NA_real_,
  tracker = "generic",
  model = NA_character_,
  mapping = NULL,
  path = NULL,
  verbose = TRUE
)

Arguments

pupil

A data frame of raw samples. Must contain a timestamp column and a pupil-size column (see mapping). May optionally contain gaze coordinate and block columns.

events

An optional data frame of event messages with a timestamp column (on the same clock as pupil) and a message-text column. If NULL (default), the object is created with empty event tables.

blinks

An optional data frame of blink intervals with start and end timestamp columns. If NULL (default), empty blink tables are created. Note that blink padding via deblink() does not depend on this table.

gaze

An optional data frame of gaze coordinate samples (timestamp, x, y), used only when gaze is exported separately from pupil size. It is left-joined onto pupil by timestamp. If NULL (default), gaze is taken from pupil if those columns are present, otherwise filled with NA.

sample_rate

Numeric sampling rate of the tracker in Hz. If NULL (default), it is inferred from the median spacing of the pupil timestamps; inference is reported and we recommend supplying the true rate explicitly.

time_unit

Unit of all timestamp columns (in pupil, events, gaze, and blinks). Either "ms" (milliseconds, the default, matching EyeLink) or "s" (seconds). Timestamps are stored internally in milliseconds.

block

Block specification, mirroring load_asc():

  • "auto" (default): if the pupil data contains a block column with more than one unique value, the data are split into multiple blocks; otherwise a single block (block_1) is created.

  • NULL: omit the block column and create a single block.

  • Numeric value: assign this block number to all samples.

eye

Which eye the data correspond to: "L" (left, default), "R" (right), or "LR" (both, e.g., averaged). Recorded as metadata.

pupil_type

Pupil measurement units: "area" (default) or "diameter". Recorded as metadata (the type column).

screen_width, screen_height

Optional screen dimensions in pixels, used for gaze heatmaps and gaze-based confounds. Leave as NA (default) if unknown; the gaze heatmap is simply skipped.

tracker

Character label for the source tracker/system (default "generic"). Recorded in info$version.

model

Optional character label for the specific tracker model. Recorded in info$model.

mapping

An optional named list remapping the default column names to the ones present in your data frames. Recognized names are time, pupil, eye_x, eye_y, text, stime, etime, and block. For example, mapping = list(time = "t_ms", pupil = "pup_size").

path

Optional character path/identifier stored in the object's file slot (used in report titles). Defaults to the value of tracker.

verbose

Logical. Whether to print verbose output (default TRUE).

Details

eyeris was designed to be extensible, but historically load_asc() was the only implemented loader. load_generic() closes that gap. Native support for specific tracker formats (e.g., Tobii, SMI, Pupil Labs, GazePoint) can be layered on top of this function incrementally: a format-specific reader only needs to produce the standardized data frames documented below and then call load_generic().

The resulting object is structurally identical to one returned by load_asc(), so it is a drop-in input to glassbox() and the individual preprocessing steps (deblink(), detransient(), interpolate(), lpfilt(), downsample(), bin(), detrend(), zscore()), epoch(), bidsify(), and the plotting methods.

The three standardized data frames

Following the conceptual model that most trackers export, load_generic() accepts three core data frames (plus an optional fourth for gaze that is exported separately):

  1. pupil (required) – the raw sample stream. Must contain a timestamp column and a pupil-size column. May also carry gaze coordinate columns (eye_x, eye_y) if your tracker exports samples as one wide table.

  2. events (optional) – experimental event messages. Must contain a timestamp column (on the same clock as pupil) and a message-text column. Required only if you intend to epoch on event messages later.

  3. blinks (optional) – blink intervals reported by the tracker. Must contain blink start and end timestamp columns. Note that blink padding via deblink() does not depend on this table – it reconstructs missing/blink regions directly from NA (and 0) values in the pupil column – so this table is purely for record-keeping and export.

A fourth, gaze, data frame is accepted for the less common case where gaze coordinates are exported separately from pupil size (timestamp + x/y columns); it is joined onto pupil by timestamp. If your pupil data frame already contains gaze columns, leave this NULL.

If a column in your data frames does not use the default name expected by load_generic(), remap it via the mapping argument (see below) rather than renaming your data by hand.

Column requirements and defaults

By default load_generic() looks for these columns (override any of them with mapping):

data frame role default column
pupil timestamp time
pupil pupil size pupil
pupil gaze x (optional) eye_x
pupil gaze y (optional) eye_y
pupil block (optional) block
events timestamp time
events message text text
blinks blink start stime
blinks blink end etime
gaze timestamp time
gaze gaze x eye_x
gaze gaze y eye_y

Handling tracker quirks

eyeris assumes EyeLink-style regularly-sampled data. Two practical notes for other trackers:

  • Missing samples. deblink() reconstructs missing/blink regions directly from NA (and 0) values in the pupil column – it does not require the blinks table. If your tracker drops samples or encodes missing pupil data some other way, set those samples to NA in the pupil column so deblinking and the confound calculations behave correctly.

  • Irregular sampling. If consecutive timestamps are not uniformly spaced, load_generic() emits a warning, because several downstream steps assume a fixed sampling interval. (A fuller guardrail is tracked separately.)

Value

An object of S3 class eyeris with the same structure as load_asc():

  1. file: The path identifier for the source data.

  2. timeseries: A named list of per-block data frames of raw time series data (time_orig, time_secs, time_scaled, eye_x, eye_y, eye, hz, type, pupil_raw).

  3. events: A named list of per-block event-message data frames.

  4. blinks: A named list of per-block blink data frames.

  5. info: Tracker metadata (sample.rate, mono, left, right, pupil.dtype, version, model, screen.x, screen.y).

  6. latest: eyeris pointer for tracking pipeline run history.

  7. binocular, binocular_mode, decimated.sample.rate, params.

See Also

load_asc() for loading SR Research EyeLink .asc files.

glassbox() for running the full eyeris preprocessing pipeline on the object returned by this function.

Examples

# build three small standardized data frames from any non-EyeLink tracker
set.seed(1)
n <- 1000
samples <- data.frame(
  time = seq(0, by = 1, length.out = n), # 1000 Hz -> 1 ms spacing
  pupil = 1000 + cumsum(rnorm(n, 0, 5)),
  eye_x = 960 + rnorm(n, 0, 10),
  eye_y = 540 + rnorm(n, 0, 10)
)

events <- data.frame(
  time = c(100, 500),
  text = c("TRIALID 1", "TRIALID 2")
)

# construct a valid eyeris object
eye <- eyeris::load_generic(
  pupil = samples,
  events = events,
  sample_rate = 1000,
  screen_width = 1920,
  screen_height = 1080,
  tracker = "my-tracker"
)

# ...and run it straight through the glassbox pipeline
eye |>
  eyeris::glassbox(lpfilt = list(plot_freqz = FALSE))


eyeris documentation built on Aug. 1, 2026, 1:07 a.m.