Skip to contents

fMRI event models

An “event model” is a description of an fMRI experiment, which consists of a collection of experimental “events” (stimuli/conditions/responses) which are embedded in an experimental design. By convolving each event type with a hemodynamic response function we from a set of regressors that are used to model and make inferences about the BOLD response.

A simple fMRI design

Consider a basic design, consisting of four stimulus types, each repeated 4 times over the course of a single scanning run. The stimuli are pictures of faces, scenes, tools and object presented for 2s a piece in a pseudorandom order. There is a uniformly distributed (4-7s) inter-stimulus interval (ISI) separating each stimulus presentation.

## 
## Attaching package: 'fmrireg'
## The following object is masked from 'package:stats':
## 
##     convolve
cond <- c("face", "scene", "tool", "object")
NSTIM <- length(cond)*4

Now we contruct a “design table” by randomly sampling from the four conditions:

simple_design <- data.frame(stim=factor(sample(rep(cond, 4))), 
                     ISI=sample(4:7, NSTIM, replace=TRUE), 
                     run=rep(1, NSTIM),
                     trial=factor(1:NSTIM))

Event onsets are calculated as the cumulative sum of the ISI variables. Then we construct a sampling_frame which define the temporal sampling and block structure of the experiment. Here we have only 1 block and a repetition frequency (TR) of 2.

simple_design$onset <- cumsum(simple_design$ISI+2) -2
TR <- 2
sframe <- sampling_frame(blocklens=70, TR)

Now the fun part. We create an event_model that describes the experimental model in terms of the stimulus onsets, conditions, and hemodynamic response function (‘hrf’).

emodel <- event_model(onset ~ fmrireg::hrf(stim, basis=fmrireg::HRF_SPMG1), data=simple_design, block = ~ run, sampling_frame=sframe)
print(emodel)
## 
## ╔══════════════════════════════════════════╗
## ║           fMRI Event Model               ║
## ╚══════════════════════════════════════════╝
## 
##  Model Formula:
##    onset ~ fmrireg::hrf(stim, basis = fmrireg::HRF_SPMG1) 
## 
## 📈 Model Summary:
##   • Number of Terms: 1 
##   • Total Events: 16 
##   • Design Matrix Columns: 4 
##   • Number of Blocks: 1 
## 
## 📋 Event Table Preview:
##   • Variables: stim, ISI, run, trial, onset 
##     stim ISI run trial onset
## 1   face   6   1     1     6
## 2   tool   4   1     2    12
## 3 object   4   1     3    18
##   ... ( 13  more rows )
## 
## 🔍 Model Terms:
## 
##   Term 1 : stim 
##     • Conditions: stim[face], stim[object], stim[scene], stim[tool] 
##     • HRF Type: SPMG1 
##     • Basis Functions: 1

And we can plot the model:

plot(emodel)

A simple fMRI design with multiple blocks

cond <- c("face", "scene", "tool", "object")
NSTIM <- length(cond)*4

## construct a design table with two blocks
design1 <- data.frame(stim=factor(sample(rep(cond, 4))), 
                     ISI=sample(4:7, 16, replace=TRUE), 
                     run=rep(1, NSTIM))
design2 <- data.frame(stim=factor(sample(rep(cond, 4))), 
                     ISI=sample(4:7, 16, replace=TRUE), 
                     run=rep(2, NSTIM))
design1$onset <- cumsum(design1$ISI+2) -2
design2$onset <- cumsum(design2$ISI+2) -2

design <- rbind(design1, design2)

## create a 'sampling_frame' describing the temporal outline of the scan consisting of 70 images collected every once every 2 seconds.
TR <- 2
sframe <- sampling_frame(blocklens=c(70,70), TR)

## create the event model d
emodel <- event_model(onset ~ hrf(stim), data=design, block = ~ run, sampling_frame=sframe)
print(emodel)
## 
## ╔══════════════════════════════════════════╗
## ║           fMRI Event Model               ║
## ╚══════════════════════════════════════════╝
## 
##  Model Formula:
##    onset ~ hrf(stim) 
## 
## 📈 Model Summary:
##   • Number of Terms: 1 
##   • Total Events: 32 
##   • Design Matrix Columns: 4 
##   • Number of Blocks: 2 
## 
## 📋 Event Table Preview:
##   • Variables: stim, ISI, run, onset 
##    stim ISI run onset
## 1  tool   4   1     4
## 2  face   4   1    10
## 3 scene   6   1    18
##   ... ( 29  more rows )
## 
## 🔍 Model Terms:
## 
##   Term 1 : stim 
##     • Conditions: stim[face], stim[object], stim[scene], stim[tool] 
##     • HRF Type: spmg1 
##     • Basis Functions: 1
plot(emodel)

A two-factor fMRI design with multiple blocks

cond1 <- c("face", "scene", "tool", "object")
cond2 <- c("attend", "ignore")
comb <- expand.grid(stim=cond1, task=cond2)
NSTIM <- nrow(comb) * 4

design <- do.call(rbind, lapply(1:2, function(i) {
  ind <- sample(rep(1:nrow(comb), length.out=NSTIM))
  d <- data.frame(stim=factor(comb$stim[ind]),
             task=factor(comb$task[ind]),
             ISI=sample(2:6, NSTIM, replace=TRUE), 
             run=rep(i, NSTIM))
  d$onset <- cumsum(d$ISI+2) -2
  d
}))

head(design)
##     stim   task ISI run onset
## 1   face ignore   6   1     6
## 2   tool ignore   3   1    11
## 3   tool attend   5   1    18
## 4 object attend   4   1    24
## 5   face attend   5   1    31
## 6 object ignore   3   1    36
## create a 'sampling_frame' describing the temporal outline of the scan consisting of 70 images collected every once every 2 seconds.
TR <- 2
sframe <- sampling_frame(blocklens=c(100,100), TR)

## create the event model d
emodel <- event_model(onset ~ hrf(stim, task), data=design, block = ~ run, sampling_frame=sframe)
print(emodel)
## 
## ╔══════════════════════════════════════════╗
## ║           fMRI Event Model               ║
## ╚══════════════════════════════════════════╝
## 
##  Model Formula:
##    onset ~ hrf(stim, task) 
## 
## 📈 Model Summary:
##   • Number of Terms: 1 
##   • Total Events: 64 
##   • Design Matrix Columns: 8 
##   • Number of Blocks: 2 
## 
## 📋 Event Table Preview:
##   • Variables: stim, task, ISI, run, onset 
##   stim   task ISI run onset
## 1 face ignore   6   1     6
## 2 tool ignore   3   1    11
## 3 tool attend   5   1    18
##   ... ( 61  more rows )
## 
## 🔍 Model Terms:
## 
##   Term 1 : stim..task 
##     • Conditions: stim[face]:task[attend], stim[object]:task[attend], stim[scene]:task[attend], stim[tool]:task[attend], stim[face]:task[ignore], stim[object]:task[ignore], stim[scene]:task[ignore], stim[tool]:task[ignore] 
##     • HRF Type: spmg1 
##     • Basis Functions: 1
plot(emodel)

TR <- 2
sframe <- sampling_frame(blocklens=70, TR)
simple_design$RT <- scale(rnorm(nrow(simple_design), mean=700, sd=100))[,1]


## create the event model d
emodel <- event_model(onset ~ hrf(stim) + hrf(RT), data=simple_design, block = ~ run, sampling_frame=sframe)
print(emodel)
## 
## ╔══════════════════════════════════════════╗
## ║           fMRI Event Model               ║
## ╚══════════════════════════════════════════╝
## 
##  Model Formula:
##    onset ~ hrf(stim) + hrf(RT) 
## 
## 📈 Model Summary:
##   • Number of Terms: 2 
##   • Total Events: 16 
##   • Design Matrix Columns: 5 
##   • Number of Blocks: 1 
## 
## 📋 Event Table Preview:
##   • Variables: stim, ISI, run, trial, onset, RT 
##     stim ISI run trial onset         RT
## 1   face   6   1     1     6 -0.4982170
## 2   tool   4   1     2    12  0.6717969
## 3 object   4   1     3    18 -0.1475667
##   ... ( 13  more rows )
## 
## 🔍 Model Terms:
## 
##   Term 1 : stim 
##     • Conditions: stim[face], stim[object], stim[scene], stim[tool] 
##     • HRF Type: spmg1 
##     • Basis Functions: 1 
## 
##   Term 2 : RT 
##     • Conditions: RT 
##     • HRF Type: spmg1 
##     • Basis Functions: 1
plot(emodel, "RT")

TR <- 2
sframe <- sampling_frame(blocklens=70, TR)


simple_design$RT <- scale(rnorm(nrow(simple_design), mean=700, sd=100))

## create the event model d
emodel <- event_model(onset ~ hrf(stim) + hrf(stim, RT), data=simple_design, block = ~ run, sampling_frame=sframe)
print(emodel)
## 
## ╔══════════════════════════════════════════╗
## ║           fMRI Event Model               ║
## ╚══════════════════════════════════════════╝
## 
##  Model Formula:
##    onset ~ hrf(stim) + hrf(stim, RT) 
## 
## 📈 Model Summary:
##   • Number of Terms: 2 
##   • Total Events: 16 
##   • Design Matrix Columns: 8 
##   • Number of Blocks: 1 
## 
## 📋 Event Table Preview:
##   • Variables: stim, ISI, run, trial, onset, RT 
##     stim ISI run trial onset         RT
## 1   face   6   1     1     6 -0.4525721
## 2   tool   4   1     2    12  1.2814768
## 3 object   4   1     3    18  0.8778785
##   ... ( 13  more rows )
## 
## 🔍 Model Terms:
## 
##   Term 1 : stim 
##     • Conditions: stim[face], stim[object], stim[scene], stim[tool] 
##     • HRF Type: spmg1 
##     • Basis Functions: 1 
## 
##   Term 2 : stim..RT 
##     • Conditions: stim[face]:RT, stim[object]:RT, stim[scene]:RT, stim[tool]:RT 
##     • HRF Type: spmg1 
##     • Basis Functions: 1
plot(emodel, "stim:RT")

Trialwise event model to construct “beta-series” estimates

TR <- 2
sframe <- sampling_frame(blocklens=70, TR)

# create the event model d
emodel <- event_model(onset ~ trialwise(), data=simple_design, block = ~ run, sampling_frame=sframe)
print(emodel)
## 
## ╔══════════════════════════════════════════╗
## ║           fMRI Event Model               ║
## ╚══════════════════════════════════════════╝
## 
##  Model Formula:
##    onset ~ trialwise() 
## 
## 📈 Model Summary:
##   • Number of Terms: 1 
##   • Total Events: 16 
##   • Design Matrix Columns: 16 
##   • Number of Blocks: 1 
## 
## 📋 Event Table Preview:
##   • Variables: stim, ISI, run, trial, onset, RT 
##     stim ISI run trial onset         RT
## 1   face   6   1     1     6 -0.4525721
## 2   tool   4   1     2    12  1.2814768
## 3 object   4   1     3    18  0.8778785
##   ... ( 13  more rows )
## 
## 🔍 Model Terms:
## 
##   Term 1 : trialwise 
##     • Conditions: trialwise[01], trialwise[02], trialwise[03], trialwise[04], trialwise[05], trialwise[06], trialwise[07], trialwise[08], trialwise[09], trialwise[10], trialwise[11], trialwise[12], trialwise[13], trialwise[14], trialwise[15], trialwise[16] 
##     • HRF Type: spmg1 
##     • Basis Functions: 1
plot(emodel, "trialwise")