
Downsample pupil time series with anti-aliasing filtering
Source:R/pipeline-downsample.R
downsample.RdThis function downsamples pupillometry data by applying an anti-aliasing filter before decimation. Unlike binning, downsampling preserves the original temporal dynamics without averaging within bins.
Arguments
- eyeris
An object of class
eyerisderived fromload_asc().- target_fs
The target sampling frequency in Hz after downsampling.
- plot_freqz
Boolean flag for displaying filter frequency response (default FALSE).
- rp
Passband ripple in dB (default 1).
- rs
Stopband attenuation in dB (default 35).
- call_info
A list of call information and parameters. If not provided, it will be generated from the function call.
Details
Downsampling reduces the sampling frequency by decimating data points.
The function automatically designs an anti-aliasing filter using the
lpfilt() function with carefully chosen parameters:
ws(stopband frequency) = Fs_new / 2 (Nyquist freq of new sampling rate)wp(passband frequency) = ws - max(5, Fs_nq * 0.2)An error is raised if
wp < 4to prevent loss of pupillary responses
The resulting time points will be: 0, 1/X, 2/X, 3/X, ..., etc. where X is the new sampling frequency.
When the input contains gaps longer than the interpolation limit (see
interpolate()'s max_gap_ms) that were left as NA, those gaps
are temporarily filled so the anti-aliasing filter can run and then masked
back to NA. This can slightly bias the valid samples immediately adjacent
to each gap toward the interpolated values, so a warning is emitted in this
case. If that bias is a concern, consider disabling this step
(glassbox(downsample = FALSE)).
Note
This function is part of the glassbox() preprocessing pipeline and is not
intended for direct use in most cases. Provide parameters via
downsample = list(...).
Advanced users may call it directly if needed.
See also
glassbox() for the recommended way to run this step as
part of the full eyeris glassbox preprocessing pipeline.
bin() for binning functionality.
For a complete, end-to-end reference pipeline that demonstrates how all
eyeris preprocessing functions are chained together in practice, see the
"Building Blocks Under the Hood" section of the Anatomy of an eyeris
Object vignette — vignette("anatomy", package = "eyeris") — as
well as the Complete Pupillometry Pipeline Walkthrough vignette:
vignette("complete-pipeline", package = "eyeris").
Examples
demo_data <- eyelink_asc_demo_dataset()
# downsample pupil data recorded at 1000 Hz to 100 Hz with the default params
demo_data |>
eyeris::glassbox(downsample = list(target_fs = 100)) |>
plot(seed = 0)
#> ✔ [2026-07-19 07:15:05] [OKAY] Running eyeris::load_asc()
#> ✔ [2026-07-19 07:15:05] [OKAY] Running eyeris::resample()
#> ℹ [2026-07-19 07:15:05] [INFO] Processing block: block_1
#> ✔ [2026-07-19 07:15:05] [OKAY] Running eyeris::deblink() for block_1
#> ✔ [2026-07-19 07:15:05] [OKAY] Running eyeris::detransient() for block_1
#> ✔ [2026-07-19 07:15:05] [OKAY] Running eyeris::interpolate() for block_1
#> ! [2026-07-19 07:15:05] [WARN] Interpolation now leaves gaps longer than 250 ms
#> as `NA` instead of interpolating across them (following Kret & Sjak-Shie,
#> 2018). This is a change in default behavior from eyeris <= 3.2.0 and may affect
#> your results. To restore the previous behavior, set `interpolate =
#> list(max_gap_ms = Inf)` in `glassbox()` (or `max_gap_ms = Inf` in
#> `interpolate()`).
#> ✔ [2026-07-19 07:15:05] [OKAY] Running eyeris::lpfilt() for block_1
#> ✔ [2026-07-19 07:15:05] [OKAY] Running eyeris::downsample() for block_1
#> ✔ [2026-07-19 07:15:05] [OKAY] Decimating sampling rate from 1000 Hz --> 100
#> Hz...
#> ! [2026-07-19 07:15:05] [WARN] Skipping eyeris::bin() for block_1
#> ! [2026-07-19 07:15:05] [WARN] Skipping eyeris::detrend() for block_1
#> ✔ [2026-07-19 07:15:05] [OKAY] Running eyeris::zscore() for block_1
#> ℹ [2026-07-19 07:15:05] [INFO] Block processing summary:
#> ℹ [2026-07-19 07:15:05] [INFO] block_1: OK (steps: 7, latest:
#> pupil_raw_deblink_detransient_interpolate_lpfilt_downsample_z)
#> ✔ [2026-07-19 07:15:05] [OKAY] Running eyeris::summarize_confounds()
#> ℹ [2026-07-19 07:15:05] [INFO] Plotting block 1 with sampling rate 100 Hz from
#> possible blocks: 1