knitr::opts_chunk$set( collapse = TRUE, comment = "#>" )
One key strength of the preprocessing framework within eyeris
is its modularity.
While we encourage most users to use the glassbox()
function for simplicity and reproducibility, advanced users can create custom preprocessing steps that
seamlessly integrate into the pipeline.
This vignette walks you through the structure required to write your own
eyeris
-compatible preprocessing functions.
Under the hood, each preprocessing function in eyeris
is a wrapper around a
core operation that gets tracked, versioned, and stored using the
pipeline_handler()
.
Custom pipeline steps must conform to the eyeris
protocol for maximum compatibility with the downstream functions we provide.
Following the eyeris
protocol also ensures:
- all operations follow a predictable structure, and
- that new pupil data columns based on previous operations in the chain are able
to be dynamically constructed within the core timeseries
data frame.
For instance:
pupil_raw -> pupil_raw_deblink -> pupil_raw_deblink_detransient -> ...
If you're unfamiliar with how these columns are structured and tracked,
first check out the companion vignette:
📦 Anatomy of an eyeris
Object.
eyeris
Let’s say you want to write a new eyeris
extension function called winsorize()
to apply winsorization to extreme
pupil values.
This function should accept a data frame x
, a string prev_op
(i.e., the name
of the previous pupil column), and any custom parameters.
winsorize_pupil <- function(x, prev_op, lower = 0.01, upper = 0.99) { vec <- x[[prev_op]] q <- quantile(vec, probs = c(lower, upper), na.rm = TRUE) vec[vec < q[1]] <- q[1] vec[vec > q[2]] <- q[2] vec }
eyeris::pipeline_handler()
The pipeline_handler()
enables your function to automatically:
eyeris
list object's params
field,timeseries
list of data frames, andlatest
pointer.#' Winsorize pupil values #' #' Applies winsorization to extreme pupil values within each block. #' #' @param eyeris An `eyeris` object created by [load_asc()]. #' @param lower Lower quantile threshold. Default is 0.01. #' @param upper Upper quantile threshold. Default is 0.99. #' #' @return Updated `eyeris` object with new winsorized pupil column. winsorize <- function(eyeris, lower = 0.01, upper = 0.99) { pipeline_handler( eyeris, winsorize_pupil, "winsorize", lower = lower, upper = upper ) }
eyeris
class object.eyeris
to refer to (i.e., the one
for the column name, plots, etc.).prev_op
when
creating the function winsorize_pupil
in step 1.You should now be able to use your new function extension as a component within
a new custom eyeris
pipeline declaration. To illustrate:
system.file("extdata", "memory.asc", package = "eyeris") |> eyeris::load_asc(block = "auto") |> eyeris::deblink(extend = 50) |> winsorize()
"winsorize"
) to the
column and log structure:pipeline_handler(..., "winsorize")
winsorize()
wrapper function, andwinsorize_pupil()
logic implementation function.pupil_raw_*_winsorize
as the new output column!prev_op
,
not on any hardcoded column names!pipeline_handler()
is
looking out for a vector it can transpose into the new column that will be added
to the timeseries
data frame within the resulting eyeris
object.eyeris$timeseries[[1]]
) to debug before integrating
it with the eyeris
pipeline protocol.We hope you are now convinced at the power and extensibility the eyeris
protocol enables! As we demonstrated here, with just a little bit of structure,
you can create custom extension steps tailored to your specific analysis
needs -- all while preserving the reproducibility and organizational core
principles eyeris
was designed and built around.
If you'd like to contribute new steps to eyeris
, feel free to open a pull
request or discussion on GitHub!
eyeris
citation("eyeris")
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.