Sequence of events (e.g. SCR)
In this HowTo you will learn to simulate a "SR"-Sequence, a stimulus response, followed by a button press response.
Setup
Click to expand
# Load required packages
using UnfoldSim
using CairoMakie
using StableRNGsCreate sequence design
First we generate the minimal design of the experiment by specifying our conditions (a one-condition-two-levels design in our case)
design = SingleSubjectDesign(conditions = Dict(:condition => ["one", "two"]))
generate_events(design)| Row | condition |
|---|---|
| String | |
| 1 | one |
| 2 | two |
Next we use the SequenceDesign and nest our initial design in it. "SR_" is code for an "S" (stimulus) event and an "R" (response) event - only single letter events are supported! The "_" is a signal for the onset generator to generate a bigger pause - no overlap between adjacent "SR" pairs.
design = SequenceDesign(design, "SR_")
generate_events(StableRNG(1), design)| Row | condition | event |
|---|---|---|
| String | Char | |
| 1 | one | S |
| 2 | one | R |
| 3 | two | S |
| 4 | two | R |
The main thing that happened is that the design was repeated for every event (each 'letter') of the sequence, and an event column was added.
More advanced sequences are possible as well, like "SR{1,3}", or "A[BC]". Infinite sequences are not possible like "AB*".
Finally, let's repeat the current design 4 times
design = RepeatDesign(design, 4)
generate_events(StableRNG(1), design)| Row | condition | event |
|---|---|---|
| String | Char | |
| 1 | one | S |
| 2 | one | R |
| 3 | two | S |
| 4 | two | R |
| 5 | one | S |
| 6 | one | R |
| 7 | two | S |
| 8 | two | R |
| 9 | one | S |
| 10 | one | R |
| 11 | two | S |
| 12 | two | R |
| 13 | one | S |
| 14 | one | R |
| 15 | two | S |
| 16 | two | R |
This results in 16 trials that nicely follow our sequence.
There is a difference between SequenceDesign(RepeatDesign) and RepeatDesign(SequenceDesign) for variable sequences e.g. "A[BC]", where in the former case, one sequence is drawn e.g. "AC" and applied to all repeated rows, in the latter, one sequence for each repeat is drawn.
Specify components for sequence events
Next we have to specify for both events S and R what the responses should look like.
p1 = LinearModelComponent(;
basis = p100(),
formula = @formula(0 ~ 1 + condition),
β = [1, 0.5],
)
n1 = LinearModelComponent(;
basis = n170(),
formula = @formula(0 ~ 1 + condition),
β = [1, 0.5],
)
p3 = LinearModelComponent(;
basis = UnfoldSim.hanning(Int(0.5 * 100)), # sfreq = 100 for the other bases
formula = @formula(0 ~ 1 + condition),
β = [1, 0],
)
resp = LinearModelComponent(;
basis = UnfoldSim.hanning(Int(0.5 * 100)), # sfreq = 100 for the other bases
formula = @formula(0 ~ 1 + condition),
β = [1, 2],
offset = -10,
)We combine them into a dictionary with a sequence-Char as key
components = Dict('S' => [p1, n1, p3], 'R' => [resp])Dict{Char, Vector{LinearModelComponent}} with 2 entries:
'R' => [LinearModelComponent([0.0, 0.00410499, 0.0163526, 0.0365416, 0.064340…
'S' => [LinearModelComponent([0.0, 0.0, 0.0, 0.0, 0.0, 0.116978, 0.413176, 0.…Simulate data
Given the design and the components. we specify onset and noise and simulate data
data, evts = simulate(
StableRNG(1),
design,
components,
UniformOnset(offset = 40, width = 10),
NoNoise(),
)Finally we can plot the results
f, ax, h = lines(data)
vlines!(ax, evts.latency[evts.event .== 'S'], color = (:darkblue, 0.5))
vlines!(ax, evts.latency[evts.event .== 'R'], color = (:darkred, 0.5))
ax.xlabel = "Time [samples]"
ax.ylabel = "EEG [a.u]"
xlims!(ax, 0, 500)
f
As visible, the R response always follows the S response. Due to the "_" we have large breaks between the individual sequences.
This page was generated using Literate.jl.