nsd_eye_tracking_time_seriesR suggested. Python is not needed for the main workflow.Canonical course conventions live in project_guidelines.md. That file is the source of truth for the four required workflow files (
week1_explore.qmd,week2_operationalize_clean.qmd,week3_model.qmd,week4_storytelling.qmd), thedata/model_data.rds->data/model_results.rdspipeline, the raw-data policy, quality-check requirements, decision logs, and contribution tracking. Read it before starting and treat anything below as project-specific guidance on top of those conventions.
![]()
Example from an NSD eye-tracking run: gaze traces from six usable 3-second repeated presentations of the same target image. Each panel maps gaze onto the actual image as a 4.0 x 4.0 degree square, matching the helper relationship x_plot = (x + 2) / 4 and y_plot = (2 - y) / 4. Color shows seconds after image onset; white and black dots mark the first and last usable samples.
Eye-tracking is a good time-series project because the raw object is a dense signal: time, horizontal gaze, vertical gaze, pupil area, blinks, saccades, and task messages. The small scientific question is about movement during image viewing. The programming lesson is how to turn raw signal files into a regular, filtered, event-aligned time series.
Students should learn four things:
.mat
preprocessing, and a student-created RDS cache expose different parts of the
provenance chain.The core research question is intentionally modest:
Is the filtered gaze-velocity signal lower during target-image viewing windows than during nearby periods when that target is not on screen?
The project should not become a full psychology project about why someone looked at a particular surfer, object, or region. It should also not make preprocessing the research question. Filtering is part of the method. A filter-width change can be a sensitivity check, but the main question is about gaze movement during an experimental event.
The fixation/saccade literature is still useful, but mainly as a warning about language. If students label low-velocity periods, they should call them computational candidates and report the rule. They should not claim that their code has discovered true fixations.
| Dimension | This project teaches |
|---|---|
| Data structure | Regularly sampled gaze and pupil time series, missing samples, event windows, blink/saccade intervals, and run-level metadata. |
| Storage system | Scientific repository on AWS plus a small local RDS cache created from the NSD MATLAB file. |
| File formats | EyeLink .edf, MATLAB .mat, JPG inspection plots, PNG stimulus images, and RDS/CSV outputs created by students. |
| Encoding | Binary eye-tracker files, MATLAB arrays, numeric time-series tables, and image-based quality-control plots. |
| Model | A small AR(1)/ARIMA-style model with an event indicator: filtered gaze velocity as the outcome and image_on as an external regressor. |
| Key aspects to explain | Sampling rate, missing samples, blinks, filtering, velocity, event alignment, autocorrelation, AR(1) errors, aggregation to 100 ms bins, one continuous modeling segment, and sensitivity to one filtering choice. |
Use the Natural Scenes Dataset (NSD) eye-tracking data so this project shares provenance with the neuroimaging project but teaches a different data structure. NSD access requires accepting the NSD data terms.
Start with one subject, one run, and one repeated target image. A good teaching subset is:
s3://natural-scenes-dataset/nsddata_timeseries/ppdata/subj01/eyedata_preprocessed.mats3://natural-scenes-dataset/nsddata_timeseries/ppdata/subj01/eyedata/s3://natural-scenes-dataset/nsddata/inspections/eyetrackinginspections/pupil_subj01_nsdimagery_run01.jpg
and
s3://natural-scenes-dataset/nsddata/inspections/eyetrackinginspections/XY_subj01_nsdimagery_run01.jpgs3://natural-scenes-dataset/nsddata/experiments/nsdimagery/designmatrixGLMsingle.mat
and the relevant pair-list file, such as B_pair_list.mats3://natural-scenes-dataset/nsddata/experiments/nsdimagery/rawtargetimages/Here “repeated target image” means that the same stimulus appears multiple times
within the run. In the example figure, shared0385_nsd28752.png is scheduled at
eight separate onsets in run 2. Each onset starts a 3-second image-presentation
period, followed by a 1-second rest/fixation period. These are repeated
presentations of the same image, not eight different screen regions.
Do not download the full 37 GB nsd_stimuli.hdf5, all subjects, all EDF
files, or any fMRI beta files for this project.
The raw .edf files are the device-native EyeLink recordings. They are important
for provenance and for the Week 1 open-format discussion. They are not the
recommended main input because direct EDF parsing in R adds too much tool
friction. The .mat file is the practical starting point because it preserves
the time-series structure students need while keeping the course workflow small.
R.matlab, dplyr, tidyr, ggplot2, readr.diff(), stats::filter(), stats::runmed(),
stats::acf(), stats::arima(), is.finite(), and aggregate().forecast.Students should learn what filters do before applying one:
For the class version, require one simple filter for the final analysis. A centered moving average over 5 to 11 samples is enough. The sensitivity check can be a second window width, not a large preprocessing contest.
Start from the AWS repository and the downloaded .mat file. The goal is to
understand what the raw scientific object is before filtering anything.
Week 1 exact data checklist:
eyedata_preprocessed.mat for subj01.nsdimagery design/pair-list files needed to identify
one repeated target-image window.data/model_data.rds only after students
have documented which raw fields it came from.Week 1 questions:
.mat
preprocessing make easier, and what are the consequences of relying on
proprietary binary formats rather than open, documented, analysis-ready
formats?Prepare for roundtable in week 2:
.mat -> RDS. Which decisions are visible
at each step, and which are harder to audit?Operationalize the research question by building one small, regular time-series table.
nsdimagery design file to create an image_on indicator for the
selected target-image windows.diff().log_velocity_filtered = log1p(velocity_filtered) so the highly
skewed velocity signal is easier to model.data/model_data.rds with only the columns needed for Week 3:
time_sec, event_id, time_from_onset, image_on, valid_fraction,
velocity_raw, velocity_filtered, log_velocity_filtered, and optional
pupil_filtered.Prepare for roundtable in week 3:
image_on variable was made from the design file.Fit a small time-series model. Do not fit ordinary sample-level OLS as the main model, because adjacent samples are autocorrelated.
Recommended model:
fit_data <- model_data[
is.finite(model_data$log_velocity_filtered) &
is.finite(model_data$image_on),
]
fit <- arima(
fit_data$log_velocity_filtered,
order = c(1, 0, 0),
xreg = fit_data$image_on
)
Here order = c(1, 0, 0) is an AR(1) model: the current value is allowed to
depend on the previous value. The image_on coefficient answers the simple
research question. A negative coefficient means gaze movement is lower while the
target image is on screen, after accounting for short-range autocorrelation.
Use a continuous, equally spaced time series for this model. Event-aligned
windows are useful for visualization, but they should not be concatenated for the
AR(1) fit.
Students should also show:
log_velocity_filtered;image_on;Avoid a black-box auto.arima() search unless the group can explain why it chose
the final model. A fixed AR(1) is enough for this course.
Prepare for roundtable in week 4:
Visualize and tell a story about the time-series pipeline.
The final story should make a course-level argument:
A time-series result is not only a model output. It depends on the raw file format, sampling rate, missing-data handling, filtering, event alignment, autocorrelation, and the exact comparison window.