---
title: "Race Models"
description: "A step-by-step race model workflow in EMC2 using the LBA"
author: "Niek Stevenson"
output: rmarkdown::html_document
bibliography: refs.bib
vignette: >
  %\VignetteIndexEntry{"Race Models"}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, echo = FALSE}
rm(list = ls())
library(EMC2)
set.seed(11)
```

## Introduction

This vignette shows a single-subject race-model workflow in *EMC2* using the
Linear Ballistic Accumulator (LBA). In *EMC2*, the Racing Diffusion Model
(RDM) and Lognormal Race Model (LNR) are also race models and use a similar
design logic. Here we use a simulated Stroop task to illustrate how to set this
up. 

The steps are:

1. Specify a race-model design with multiple responses and stimulus identities
2. Inspect sampled parameters and their mapping to design cells
3. Simulate data
4. Define priors and create an `emc` object
5. Fit the model
6. Summarize posterior estimates and run posterior predictive checks

For parameter details and transformations, see `?LBA`.

## 1. Specify a Race-Model Design

We define a three-choice Stroop task with stimulus identity `S` (`red`, `green`,
`blue`) and matching response levels. In race models, *EMC2* internally builds
an accumulator factor `lR` (one accumulator per response option). We define
`matchfun` to indicate whether the stimulus identity matches each accumulator,
which creates the latent match factor `lM`. By adding `S` to the drift rate we
account for differences in color processing. Similarly, by adding `B ~ LR`
we account for a-priori preferences for responding certain colors.

```{r}
matchfun <- function(d) d$S == d$lR

# "Average/difference" coding for the TRUE/FALSE lM factor
ADmat <- matrix(c(-1/2, 1/2), ncol = 1, dimnames = list(NULL, "d"))

design_lba <- design(
  factors = list(subjects = 1, S = c("red", "green", "blue")),
  Rlevels = c("red", "green", "blue"),
  matchfun = matchfun,
  formula = list(v ~ lM + S, B ~ lR, A ~ 1, t0 ~ 1, sv ~ 1),
  contrasts = list(v = list(lM = ADmat)),
  constants = c(sv = log(1)),
  model = LBA
)
```

`design()` combines model and experimental structure into an `emc.design`
object.

## 2. Inspect Parameters and Mapping

`sampled_pars()` returns the free parameters implied by the design.

```{r}
sampled_pars(design_lba)
```

`mapped_pars()` shows how those parameters map back to design cells. Here:

- `v_lMd` captures match-vs-mismatch drift differences
- `v_Sgreen` and `v_Sblue` capture stimulus-identity shifts in drift
- `B_lRgreen` and `B_lRblue` capture response-specific threshold bias

```{r}
mapped_pars(design_lba)
```

In this example we simulate data, but you can replace this with your empirical
data. We first define true parameter values on the transformed scale and inspect
the numeric mapping:

```{r}
p_vector <- sampled_pars(design_lba)
p_vector[] <- c(
  v = 1.4,
  v_lMd = 1.8,
  v_Sgreen = 0.15,
  v_Sblue = -0.1,
  B = log(0.7),
  B_lRgreen = 0.1,
  B_lRblue = -0.1,
  A = log(0.3),
  t0 = log(0.25)
)

mapped_pars(design_lba, p_vector)
```

To visualize the implied design-level behavior:

```{r, message=FALSE, fig.alt = "Design-level LBA trajectories for three stimulus identities"}
plot_design(design_lba, p_vector = p_vector, factors = list(v = "S", B = "lR"), plot_factor = "lR", layout = c(1,3))
```

## 3. Simulate Data

`make_data()` simulates trial-level responses and response times from the
specified design and parameter values.

```{r, results = "hide"}
dat <- make_data(parameters = p_vector, design = design_lba, n_trials = 80)
```

A quick check of the simulated defective densities by stimulus identity:

```{r, fig.alt = "Defective density plots for three-choice race model simulated data"}
plot_density(dat, factors = "S", layout = c(1,3))
```

## 4. Set Prior and Build EMC Object

`prior()` defines prior settings for parameters in this design. As always, be
mindful that some parameters are represented on transformed scales, see `?LBA`.

```{r, results = "hide"}
prior_lba <- prior(
  design = design_lba,
  type = "single",
  pmean = c(
    v = 1.2,
    v_lMd = 1.5,
    v_Sgreen = 0,
    v_Sblue = 0,
    B = log(0.8),
    B_lRgreen = 0,
    B_lRblue = 0,
    A = log(0.25),
    t0 = log(0.2)
  ),
  psd = c(
    v = .5,
    v_lMd = .6,
    v_Sgreen = .4,
    v_Sblue = .4,
    B = .25,
    B_lRgreen = .25,
    B_lRblue = .25,
    A = .25,
    t0 = .15
  )
)
```

Inspecting implied priors is a useful sanity check:

```{r, fig.alt = "Prior densities for three-choice LBA example"}
plot(prior_lba, N = 1e3)
```

Next we construct the `emc` object. `make_emc()` combines data, design, and
prior into the object expected by `fit()`.

```{r, results = "hide"}
emc <- make_emc(dat, design_lba, prior_list = prior_lba, type = "single")
```

## 5. Fit

The following call is how you can fit this model and save intermediate output:

```{r, eval = FALSE}
emc <- fit(emc, fileName = "data/race-models.RData")
```

```{r, include = FALSE}
load("data/race-models.RData")
```

## 6. Summarize and Check Model Fit

`summary()` reports quantiles, `Rhat`, and ESS for estimated parameters:

```{r}
summary(emc)
```

`plot_pars()` compares posterior densities with the generating values:

```{r, fig.alt = "Posterior parameter densities against true values for three-choice LBA", fig.height = 9}
plot_pars(emc, true_pars = p_vector, use_prior_lim = FALSE)
```

Finally, we generate posterior predictive datasets and compare CDFs:

```{r, results = "hide"}
pp <- predict(emc)
```

```{r, fig.alt = "Posterior predictive defective CDF by stimulus identity in three-choice LBA"}
plot_cdf(dat, pp, factors = "S", layout = c(1,3))
```

This same race-model workflow extends naturally to the other race models `RDM` and `LNR`; the core
steps (`design()` -> `prior()` -> `make_emc()` -> `fit()` -> predictive checks)
remain the same.
