This example is designed to give you a better feel for how the non-decision time in a DDM influences responding. It is written using R Markdown. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see http://rmarkdown.rstudio.com.
You can download the code file used to create this page at http://decisionneurolab.com/resources/Intro_to_DDM/exercises/nondecision.Rmd.
Author: Cendri Hutcherson
Date last modified: May 1, 2019
Last parameter of the basic DDM! Woo, you’re almost there! Are you as excited as I am?!! Well, too bad, because the non-decision time is pretty much the most boring parameter of the lot. Still, it’s worth seeing how it works, and understanding its implications.
Let’s start by modifying the ddm function we wrote in our previous example to include a non-decision time. This really won’t take much. It involves adding an input argument ndt to the code, and adding the value of ndt to the RT at the end (in step 6). That’s it.
ddm = function(driftrate = .08, threshold = .15, ndt = .3, noise = .1, precision = .001){
# function ddm:
# driftrate: average strength of the evidence
# threshold: the choice-determining threshold
# ndt: the non-decision time
# noise: standard deviation of the evidence, by convention set to .1
# precision: the size of the time-step for accumulating evidence (default = .001s)
# 1. start at time t = 1
t = 1
# 2. start with evidence at 0
accumulatedEvidence = 0
# 3. use a while loop that will break when the evidence passes +/- the threshold
while(abs(accumulatedEvidence[t]) < threshold){
t = t+1
# 4. take a noisy sample, scaled for the temporal precision with which we are estimating
noisySample = driftrate*precision + rnorm(1, mean = 0, sd = noise*sqrt(precision))
# 5. add it to the previous evidence
accumulatedEvidence[t] = accumulatedEvidence[t - 1] + noisySample
}
# 6. return a data structure with the choice, the RT (in s), and the observed accumulated evidence
choiceInfo = list(choice = sign(accumulatedEvidence[t]), rt = t*precision + ndt, drift = accumulatedEvidence)
}
Let’s see what this does now:
simAndPlot = function(driftrate = .08, threshold = .15, ndt = .3, nSim = 1000){
# initialize vectors to hold the simulated choices and RTs
Choices = RTs = vector(mode = 'numeric', length = nSim)
# run the simulations and save the data
for(sim in 1:nSim){
temp = ddm(driftrate = driftrate, threshold = threshold, ndt = ndt)
Choices[sim] = temp$choice
RTs[sim] = temp$rt
}
# Plot the data!
# 1. Get the frequencies of YES and NO responses in specific RT bins, determined by the maximum RT
maxRT = ceiling(max(RTs))
rtBins = seq(0,maxRT, length = 40)
freqYes = hist(RTs[Choices == 1], breaks = rtBins, plot = FALSE)$counts
freqNo = hist(RTs[Choices == -1], breaks = rtBins, plot = FALSE)$counts
# 2. plot the frequencies
par(mfrow = c(2,1), mar = c(0,4,5,1) + .2)
yMax = ceiling(max(c(freqYes, freqNo)/50))*50
hist(RTs[Choices == 1], breaks = rtBins, ylim = c(0,yMax), main = '', xaxt = 'n'
, col = 'red')
par(mar = c(4,4,1,1) + .2)
hist(RTs[Choices == -1], breaks = rtBins, ylim = c(yMax,0), main = '', xlab = 'RT'
, col = 'blue')
# 3. Add descriptive text to the plot
text(maxRT * .5, yMax * .4, paste('% YES: ', format(mean(Choices == 1), digits = 3)), adj = 0)
text(maxRT * .5, yMax * .6, paste('Ave. YES RT: ', format(mean(RTs[Choices == 1]), digits = 3)), adj = 0)
text(maxRT * .5, yMax * .8, paste('Ave. NO RT: ', format(mean(RTs[Choices == -1]), digits = 3)), adj = 0)
}
# plot with defaults (non-decision = .3)
simAndPlot()
# plot with a shorter non-decision time (ndt = .1)
simAndPlot(ndt = .1)
# plot with a longer non-decision time (ndt = .5)
simAndPlot(ndt = .8)
Note if and how the non-decision time affects the choices and rts.