-
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
componentfunction #91
base: main
Are you sure you want to change the base?
Changes from all commits
8405a1a
afc69d7
49db0ba
8e6de75
cd489c4
6c35f3c
809dc2e
31c69e6
54e9334
7114cd6
b4a8ac8
0c3a11d
de8c2a8
57a7f68
43e28e8
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,39 @@ | ||
# # Component Functions | ||
# HowTo put arbitrary functions into components | ||
|
||
using UnfoldSim | ||
using Unfold | ||
using Random | ||
using DSP | ||
using CairoMakie, UnfoldMakie | ||
|
||
sfreq = 100; | ||
|
||
# ## Design | ||
# Let's generate a design with a categorical effect and a continuous duration effect | ||
design = UnfoldSim.SingleSubjectDesign(; | ||
conditions = Dict( | ||
:category => ["dog", "cat"], | ||
:duration => Int.(round.(20 .+ rand(100) .* sfreq)), | ||
), | ||
); | ||
|
||
|
||
# Instead of defining a boring vector basis function e.g. `[0,0,1,2,3,3,2,1,0,0,0]`, let's use function, generating random values for now. | ||
# !!! important | ||
# because any function depending on `design` can be used, two things have to be taken care of: | ||
# | ||
# 1. in case a random component exist, specify a `RNG`, the basis might be evaluated multiple times inside `simulate` | ||
# 2. a `maxlength` has to be specified via a tuple `(function.maxlength)`` | ||
mybasisfun = design -> hanning.(generate_events(design).duration) | ||
signal = LinearModelComponent(; | ||
basis = (mybasisfun, 100), | ||
formula = @formula(0 ~ 1 + category), | ||
β = [1, 0.5], | ||
); | ||
|
||
erp = UnfoldSim.simulate_component(MersenneTwister(1), signal, design); | ||
|
||
|
||
# Finally, let's plot it, sorted by duration | ||
plot_erpimage(erp, sortvalues = generate_events(design).duration) |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,68 @@ | ||||||
using Base: add_sum | ||||||
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"]))#|>x->RepeatDesign(x,4) | ||||||
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, "SR{1,2}_", 0, StableRNG(1)) | ||||||
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 are possible as well, like "SR{1,3}", or "A[BC]". Infinite sequences are not possible like "AB*" | ||||||
|
||||||
# Finally, let's repeat the design 2 times - because we can | ||||||
design = RepeatDesign(design, 4) | ||||||
generate_events(design) | ||||||
|
||||||
#design = UnfoldSim.AddSaccadeAmplitudeDesign4(design,:rt,Normal(0,1),MersenneTwister(1)) | ||||||
#generate_events(design) | ||||||
|
||||||
|
||||||
# This results in 12 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, 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, | ||||||
); | ||||||
|
||||||
components = Dict('S' => [p1, n1, p3], 'R' => [resp]) | ||||||
#components = [p1, n1, resp] | ||||||
data, evts = simulate( | ||||||
StableRNG(1), | ||||||
design, | ||||||
components, | ||||||
UniformOnset(offset = 40, width = 10), | ||||||
NoNoise(), | ||||||
) | ||||||
|
||||||
lines(data) | ||||||
vlines!(evts.latency, color = (:gray, 0.5)) | ||||||
xlims!(0, 500) | ||||||
current_figure() | ||||||
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 | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -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
|
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 🐶