Motivation
Despite decades of pupillometry research, many established packages and workflows unfortunately lack design principles based on (F)indability (A)ccessbility (I)nteroperability (R)eusability (FAIR) principles. eyeris
, on the other hand follows a thoughtful design philosophy that results in an intuitive, modular, performant, and extensible pupillometry data preprocessing framework. Much of these design principles were heavily inspired by Nipype
.
eyeris
also provides a highly opinionated pipeline for tonic and phasic pupillometry preprocessing (inspired by fMRIPrep
). These opinions are the product of many hours of discussions from core members and signal processing experts from the Stanford Memory Lab (Shawn Schwartz, Mingjian He, Haopei Yang, Alice Xue, and Anthony Wagner).
eyeris
also introduces a BIDS
-like structure for organizing derivative (preprocessed) pupillometry data, as well as an intuitive workflow for inspecting preprocessed pupillometry epochs within beautiful, interactive HTML report files (see demonstration below ⬇️)! The package also includes gaze heatmaps that show the distribution of eye coordinates across the entire screen area, helping you assess data quality and participant attention patterns. These heatmaps are automatically generated in the BIDS reports and can also be created manually.
Installation
stable release from CRAN
You can install the stable release of eyeris
from CRAN with:
install.packages("eyeris")
or
# install.packages("pak")
pak::pak("eyeris")
development version from GitHub
You can install the development version of eyeris
from GitHub with:
# install.packages("devtools")
devtools::install_github("shawntz/eyeris", ref = "dev")
Example
the glassbox()
“prescription” function
This is a basic example of how to use eyeris
out of the box with our very opinionated set of steps and parameters that one should start out with when preprocessing pupillometry data. Critically, this is a “glassbox” – as opposed to a “blackbox” – since each step and parameter implemented herein is fully open and accessible to you. We designed each pipeline step / function to be like legos – they are intentionally and carefully designed in a way that allows you to flexibly construct and compare different pipelines.
We hope you enjoy! -shawn
set.seed(32)
library(eyeris)
demo_data <- eyelink_asc_demo_dataset()
eyeris_preproc <- glassbox(
demo_data,
lpfilt = list(plot_freqz = FALSE)
)
#> ✔ [ OK ] - Running eyeris::load_asc()
#> ℹ [ INFO ] - Processing block: block_1
#> ✔ [ OK ] - Running eyeris::deblink() for block_1
#> ✔ [ OK ] - Running eyeris::detransient() for block_1
#> ✔ [ OK ] - Running eyeris::interpolate() for block_1
#> ✔ [ OK ] - Running eyeris::lpfilt() for block_1
#> ! [ SKIP ] - Skipping eyeris::downsample() for block_1
#> ! [ SKIP ] - Skipping eyeris::bin() for block_1
#> ! [ SKIP ] - Skipping eyeris::detrend() for block_1
#> ✔ [ OK ] - Running eyeris::zscore() for block_1
#> ✔ [ OK ] - Running eyeris::summarize_confounds()
final pre-post correction of pupillary signal (raw ➡ preprocessed)
start_time <- min(eyeris_preproc$timeseries$block_1$time_secs)
end_time <- max(eyeris_preproc$timeseries$block_1$time_secs)
plot(eyeris_preproc,
steps = c(1, 5),
preview_window = c(start_time, end_time),
add_progressive_summary = TRUE
)
#> ! [ INFO ] - Plotting block 1 from possible blocks: 1
#> ℹ [ INFO ] - Plotting with sampling rate: 1000 Hz
Logging eyeris Commands with eyelogger()
The eyelogger()
utility lets you run any eyeris
command (or block of R code) while automatically capturing all console output and errors to timestamped log files. This is especially useful for reproducibility, debugging, or running batch jobs.
How it works: - All standard output (stdout
) and standard error (stderr
) are saved to log files in a directory you specify (or a temporary directory by default). - Each run produces two log files: - <timestamp>.out
: all console output - <timestamp>.err
: all warnings and errors
Usage
You can wrap any eyeris
command or block of code in eyelogger({ ... })
:
library(eyeris)
# log a simple code block with messages, warnings, and prints
eyelogger({
message("eyeris `glassbox()` completed successfully.")
warning("eyeris `glassbox()` completed with warnings.")
print("some eyeris-related information.")
})
# log a real eyeris pipeline run, saving logs to a custom directory
log_dir <- file.path(tempdir(), "eyeris_logs")
eyelogger({
glassbox(eyelink_asc_demo_dataset(), interactive_preview = FALSE)
}, log_dir = log_dir)
Parameters
-
eyeris_cmd
: The code to run (wrap in{}
for multiple lines). -
log_dir
: Directory to save logs (default: a temporary directory). -
timestamp_format
: Format for log file names (default:"%Y%m%d_%H%M%S"
).
Contributing to eyeris
Thank you for considering contributing to the open-source eyeris
R package; there are many ways one could contribute to eyeris
.
We believe the best preprocessing practices emerge from collective expertise and rigorous discussion. Please see the contribution guidelines for more information on how to get started..
Code of Conduct
Please note that the eyeris project is released with a Contributor Code of Conduct. By contributing to this project, you agree to abide by its terms.
Suggestions, questions, issues?
Please use the issues tab (https://github.com/shawntz/eyeris/issues) to make note of any bugs, comments, suggestions, feedback, etc… all are welcomed and appreciated, thanks!
📚 Citing eyeris
If you use the eyeris
package in your research, please consider citing our preprint!
Run the following in R to get the citation:
citation("eyeris")
#> To cite package 'eyeris' in publications use:
#>
#> Schwartz ST, Yang H, Xue AM, He M (2025). "eyeris: A flexible,
#> extensible, and reproducible pupillometry preprocessing framework in
#> R." _bioRxiv_, 1-37. doi:10.1101/2025.06.01.657312
#> <https://doi.org/10.1101/2025.06.01.657312>.
#>
#> A BibTeX entry for LaTeX users is
#>
#> @Article{,
#> title = {eyeris: A flexible, extensible, and reproducible pupillometry preprocessing framework in R},
#> author = {Shawn T Schwartz and Haopei Yang and Alice M Xue and Mingjian He},
#> journal = {bioRxiv},
#> year = {2025},
#> pages = {1--37},
#> doi = {10.1101/2025.06.01.657312},
#> }