12 June 2019

Introduction

Introduction

  • A package to pre-process and then analyze simple pupil experiments in R
  • The best way to download it is to open up R in RStudio, download devtools
  • Then:
devtools::install_github('samhforbes/PupillometryR')

Why Pupillometry?

  • A powerful insight into cognition
  • Gives us a direct, physiological response
  • Relatively easy (and cheap!) to collect with a eye-tracker
  • A strong alternative to measures like total looking time

Why R?

  • Becoming more popular with psychologists, particularly those using eye-tracking
  • Thus flexible & familiar!
  • Allows integration with other packages
  • Excellent plotting tools with ggplot2

Why PupillometryR?

  • The goal was to create an integrated pipeline for pupillometry
  • Aimed to simplify some of the decisions in pre-processing
  • Not many pipelines available for flexible, start to finish analysis
  • Much of psychophysics has been MATLAB based, leaving R users out
  • Usable with any eyetracker brand

What does it add (ie what do we get)?

  • Clear and automated options for pre-processing
  • Flexible analysis techniques
  • Easy to understand pipeline
  • Stong data vis game!

Today

  • Discuss when pupillometry is suitable
  • Focus on how to do a pupillometric analysis with real data
  • Look at the advantages of different analysis techniques
  • Discuss visualising data
  • Hopefully, show you how easy it is!

When is pupillometry a bad idea

  • flashing screens
  • changing colours
  • dramatically moving objects
  • variable room brightness
  • subjects with artificially dilated pupils

When is pupillometry a good idea

  • Hopefully, most of the rest of the time!
  • Stable targets (eg many word learning experiments)
  • Stimuli of equal brightness
  • When we need powerful answers from few trials (eg many categorisation or violation of expectation experiments)

Getting set up

Getting started

  • Have a close look at the pupil data.
  • Eyetrackers have a couple of different ways of dealing with this, so it’s important to know a few things:

    1. What unit of measurement is being used
    2. What value is given to missing data or blinks (typically ., -1, or NA)
    3. What framerate were you recording at, and is this consistent.

What data do you need?

A dataframe containing:

  1. Pupil size from one or two eyes (eyelink people watch out)
  2. A column for time
  3. A column for condition
  4. Columns for subject and trial

Some data

library(PupillometryR)
data("pupil_data")
head(pupil_data)
##   ID Trial   RPupil   LPupil Timebin      Time Type
## 1  1 Easy1 3.233615 2.935160       1  16.66667 Easy
## 2  1 Easy1 3.216972 2.919698       2  33.33333 Easy
## 3  1 Easy1 3.205405 2.924402       3  50.00000 Easy
## 4  1 Easy1 3.217505 2.935777       4  66.66667 Easy
## 5  1 Easy1 3.214905 2.928921       5  83.33333 Easy
## 6  1 Easy1 3.211777 2.922048       6 100.00000 Easy

Some data

  • Data comes from Sylvain Sirois’ MATLAB fda tutorial
  • 9 adult participants (need to drop 1)
  • participants shown hard and easy maths problems
  • Tobii TX120 at 60Hz

Set up data

#Check that IDs are not numeric
pupil_data$ID <- as.character(pupil_data$ID)
#remove participant number 8, who had problematic data
pupil_data <- subset(pupil_data, ID != 8)
#blinks were registered as -1, so replace with NAs
pupil_data$LPupil[pupil_data$LPupil == -1] <- NA
pupil_data$RPupil[pupil_data$RPupil == -1] <- NA
# for pretty plots
library(ggplot2)
theme_set(theme_classic(base_size = 12))

Pre-processing

Format the data

  • Put the data into pupillometryR format for further analysis
Sdata <- make_pupillometryr_data(data = pupil_data,
                                 subject = ID,
                                 trial = Trial,
                                 time = Time,
                                 condition = Type)

Missing data

  • We can use subset_data to trim our time course
  • We can handle missing data as well:
new_data <- replace_missing_data(data = Sdata)
## Warning in replace_missing_data(data = Sdata): replace_missing_data will
## only help if you have missing timepoints, and a reliable time column.
head(new_data)
##   ID Trial      Time   RPupil   LPupil Timebin Type
## 1  1 Easy1  16.66667 3.233615 2.935160       1 Easy
## 2  1 Easy1  33.33333 3.216972 2.919698       2 Easy
## 3  1 Easy1  50.00000 3.205405 2.924402       3 Easy
## 4  1 Easy1  66.66667 3.217505 2.935777       4 Easy
## 5  1 Easy1  83.33333 3.214905 2.928921       5 Easy
## 6  1 Easy1 100.00000 3.211777 2.922048       6 Easy

Visualising raw data

plot(new_data, pupil = LPupil, group = 'condition')
## Warning: Removed 3639 rows containing non-finite values (stat_summary).

Visualising raw data

plot(new_data, pupil = LPupil, group = 'subject') 
## Warning: Removed 3639 rows containing non-finite values (stat_summary).

Regress pupils

regressed_data <- regress_data(data = new_data,
                               pupil1 = RPupil,
                               pupil2 = LPupil)

mean_data <- calculate_mean_pupil_size(data = regressed_data, 
                                       pupil1 = RPupil, 
                                       pupil2 = LPupil)

Regress pupils

plot(mean_data, pupil = mean_pupil, group = 'subject')
## Warning: Removed 3710 rows containing non-finite values (stat_summary).