-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sequence #83
base: main
Are you sure you want to change the base?
sequence #83
Changes from 2 commits
8405a1a
afc69d7
49db0ba
8e6de75
cd489c4
6c35f3c
809dc2e
31c69e6
54e9334
7114cd6
85f037b
2c65a7f
ee9e00a
ac0d3bd
373e535
b073526
89c09a1
1e2694f
9ab04aa
5671e2e
10c77a3
ea25ddc
e0c2310
34ce887
b5a60bf
b81b605
369faff
541cf67
f449083
fe00ec2
f93a3c1
aca3fd2
e868a14
43dd57c
68ce722
2dfd44b
2c34e5e
8848209
9749685
3a3bd3d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
using UnfoldSim | ||
using CairoMakie | ||
using StableRNGs | ||
|
||
# ## Stimulus - Response design | ||
|
||
# let's say we want to simulate a stimulus response, followed by a button press response. | ||
# First we generate the minimal design of the experiment by specifying our conditins (a one-condition-two-levels design in our case) | ||
design = SingleSubjectDesign(conditions = Dict(:condition => ["one", "two"])) | ||
generate_events(design) | ||
# next we use the `SequenceDesign` and nest our initial design in it. "SR_" is code for an "S" event and an "R" event - only single letter events are supported! The `_` is a signal for the Onset generator to generate a bigger pause - no overlap between adjacend `SR` pairs | ||
design = SequenceDesign(design, "SRR_") | ||
generate_events(design) | ||
# The main thing that happened is that the design was repeated for every event (each 'letter') of the sequence, and an `eventtype` column was added. | ||
# !!! hint | ||
# more advaned sequences exist, like "SR{1,3}", or "A[BC]" etc. | ||
|
||
# Finally, let's repeat the design 2 times | ||
design = RepeatDesign(design, 2) | ||
generate_events(design) | ||
|
||
# This results in 20 trials that nicely follow our sequence | ||
|
||
# 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, 2], | ||
); | ||
|
||
components = Dict('S' => [p1, n1], 'R' => [p3]) | ||
|
||
data, evts = simulate( | ||
StableRNG(1), | ||
design, | ||
components, | ||
UniformOnset(offset = 10, width = 100), | ||
NoNoise(), | ||
) | ||
lines(data) | ||
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -282,3 +282,25 @@ end | |||||||||
# - if `offset` < `length(signal.basis)` -> there might be overlap, depending on the other parameters of the onset distribution | ||||||||||
|
||||||||||
# [^1]: Wikipedia contributors. (2023, December 5). Log-normal distribution. In Wikipedia, The Free Encyclopedia. Retrieved 12:27, December 7, 2023, from https://en.wikipedia.org/w/index.php?title=Log-normal_distribution&oldid=1188400077# | ||||||||||
|
||||||||||
|
||||||||||
|
||||||||||
|
||||||||||
# ## Design-dependent `FormulaXOnset` | ||||||||||
|
||||||||||
# For additional control we provide `FormulaUniformOnset` and `FormulaLogNormalOnset` types, that allow to control all parameters by specifying formulas | ||||||||||
o = UnfoldSim.FormulaUniformOnset( | ||||||||||
width_formula = @formula(0 ~ 1 + cond), | ||||||||||
width_β = [50, 20], | ||||||||||
) | ||||||||||
events = generate_events(design) | ||||||||||
onsets = UnfoldSim.simulate_interonset_distances(MersenneTwister(42), o, design) | ||||||||||
|
||||||||||
f = Figure() | ||||||||||
ax = f[1, 1] = Axis(f) | ||||||||||
hist!(ax, onsets[events.cond.=="A"], bins = range(0, 100, step = 1), label = "cond: A") | ||||||||||
hist!(ax, onsets[events.cond.=="B"], bins = range(0, 100, step = 1), label = "cond: B") | ||||||||||
axislegend(ax) | ||||||||||
f | ||||||||||
|
||||||||||
# Voila - the inter-onset intervals are `20` samples longer for condition `B`, exactly as specified.` | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [JuliaFormatter] reported by reviewdog 🐶
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [JuliaFormatter] reported by reviewdog 🐶
Suggested change
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -147,6 +147,28 @@ | |||||
repeat::Int = 1 | ||||||
end | ||||||
|
||||||
|
||||||
@with_kw struct SequenceDesign{T} <: AbstractDesign | ||||||
design::T | ||||||
sequence::String = "" | ||||||
end | ||||||
|
||||||
UnfoldSim.generate_events(design::SequenceDesign{MultiSubjectDesign}) = | ||||||
error("not yet implemented") | ||||||
|
||||||
function UnfoldSim.generate_events(design::SequenceDesign) | ||||||
df = generate_events(design.design) | ||||||
nrows_df = size(df, 1) | ||||||
currentsequence = sequencestring(design.sequence) | ||||||
currentsequence = replace(currentsequence, "_" => "") | ||||||
df = repeat(df, inner = length(currentsequence)) | ||||||
df.event .= repeat(collect(currentsequence), nrows_df) | ||||||
|
||||||
return df | ||||||
|
||||||
end | ||||||
|
||||||
|
||||||
""" | ||||||
UnfoldSim.generate_events(design::RepeatDesign{T}) | ||||||
|
||||||
|
@@ -160,6 +182,28 @@ | |||||
return df | ||||||
|
||||||
end | ||||||
|
||||||
|
||||||
""" | ||||||
Internal helper design to subset a sequence design in its individual components | ||||||
""" | ||||||
struct SubselectDesign{T} <: AbstractDesign | ||||||
design::T | ||||||
key::Char | ||||||
end | ||||||
|
||||||
function generate_events(design::SubselectDesign) | ||||||
return subset(generate_events(design.design), :event => x -> x .== design.key) | ||||||
end | ||||||
|
||||||
|
||||||
Base.size(design::RepeatDesign{MultiSubjectDesign}) = | ||||||
size(design.design) .* (design.repeat, 1) | ||||||
Base.size(design::RepeatDesign{SingleSubjectDesign}) = size(design.design) .* design.repeat | ||||||
Base.size(design::SequenceDesign) = | ||||||
size(design.design) .* length(replace(design.sequence, "_" => "")) | ||||||
|
||||||
Base.size(design::RepeatDesign{SequenceDesign{SingleSubjectDesign}}) = | ||||||
size(design.design) .* design.repeat | ||||||
|
||||||
Base.size(design::SubselectDesign) = size(generate_events(design), 1) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [JuliaFormatter] reported by reviewdog 🐶
Suggested change
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[JuliaFormatter] reported by reviewdog 🐶