Skip to content
Open
Show file tree
Hide file tree
Changes from 143 commits
Commits
Show all changes
178 commits
Select commit Hold shift + click to select a range
8405a1a
FormulaOnsets
behinger Feb 23, 2024
afc69d7
initial sequence tryout
behinger Feb 25, 2024
49db0ba
fix bug in predef_eeg
behinger Feb 25, 2024
41d7306
fix \beta missing
behinger Feb 26, 2024
8e6de75
merge
behinger Feb 28, 2024
cd489c4
forgot the end
behinger Feb 28, 2024
6c35f3c
half way through to success for sequence designs or something
behinger Feb 28, 2024
809dc2e
everythinig except sequencelength seems to be working now
behinger Feb 28, 2024
31c69e6
added string sequence tests
behinger Feb 28, 2024
54e9334
small doc update
behinger Mar 1, 2024
7114cd6
added jitter to the '_' trial divisor
behinger Mar 9, 2024
b4a8ac8
generalized LinearModelComponent to arbitrary functions instead of ve…
behinger Mar 10, 2024
0c3a11d
bugfix with endless loop due to multiple dispatch
behinger Mar 10, 2024
de8c2a8
function component for multi-subject
behinger Mar 10, 2024
57a7f68
forgot to define offset in LinearModelFunction
behinger Mar 11, 2024
85f037b
Improve documentation especially quickstart, home and power analysis
jschepers Jul 10, 2024
2c65a7f
adapted the order of reference overviews and adapted titles
jschepers Jul 18, 2024
ee9e00a
Updated quickstart page
jschepers Jul 22, 2024
ac0d3bd
minor changes
jschepers Jul 22, 2024
373e535
fixed docstrings for predef_eeg and predef_2x2
jschepers Jul 23, 2024
b073526
added draft of design types reference page
jschepers Jul 23, 2024
89c09a1
Update quickstart.jl
behinger Jul 24, 2024
1e2694f
Add UnfoldSim logo to the documentation
jschepers Jul 24, 2024
9ab04aa
Finished experimental design reference page
jschepers Jul 24, 2024
5671e2e
Replace logo file
jschepers Jul 25, 2024
10c77a3
Update logo file
jschepers Jul 25, 2024
ea25ddc
Delete docs/src/assets/logo.svg
jschepers Jul 25, 2024
e0c2310
Add logo as png file
jschepers Jul 25, 2024
34ce887
Added intro paragraph for Simulate ERP tutorial
jschepers Jul 30, 2024
b5a60bf
Improved docstrings for single- and multi-subject design
jschepers Jul 30, 2024
b81b605
Fixed simulate docstring
jschepers Jul 30, 2024
369faff
Added cross references in docstrings
jschepers Jul 31, 2024
541cf67
Added intro sentences, matched titles and sidebar, reordered pages an…
jschepers Jul 31, 2024
f449083
Update noise.jl
behinger Jul 26, 2024
fe00ec2
Update src/noise.jl
behinger Jul 26, 2024
f93a3c1
Update src/noise.jl
behinger Jul 26, 2024
aca3fd2
Update src/noise.jl
jschepers Jul 31, 2024
e868a14
add empty line for formatting reasons
jschepers Jul 31, 2024
43dd57c
Update docs/literate/reference/noisetypes.jl
jschepers Aug 1, 2024
68ce722
Update docs/literate/reference/overview.jl
jschepers Aug 1, 2024
2dfd44b
Update docs/literate/reference/overview.jl
jschepers Aug 1, 2024
2c34e5e
Update docs/literate/reference/noisetypes.jl
jschepers Aug 1, 2024
8848209
Merge branch 'main' into sequence
behinger Aug 7, 2024
9749685
merge joss doc changes
behinger Aug 7, 2024
3a3bd3d
added docstring
behinger Aug 9, 2024
43e28e8
merge
behinger Aug 9, 2024
f5300c3
Merge branch 'main' into onsetFormulas
behinger Aug 9, 2024
b8d85b9
renamed to have the formula at the end
behinger Aug 9, 2024
b204234
merge sequence & componentfunction
behinger Aug 9, 2024
04a1ed3
Merge branch 'onsetFormulas' into v4.0
behinger Aug 9, 2024
e05a9c6
merge fix, double definition of function
behinger Aug 9, 2024
8aa7591
component function test + docstring
behinger Aug 9, 2024
395b5ee
better docs
behinger Aug 9, 2024
da51a16
added unittests
behinger Aug 9, 2024
9603df9
fixed small wording
behinger Sep 3, 2024
612786a
fix tutorial with v0.3 renaming of simulate to simulate_component
behinger Sep 3, 2024
272eb02
fix newComponent tutorial
behinger Sep 3, 2024
360b0eb
add GroundTruth desing and needed functions
ReneSkukies Oct 16, 2024
f082ce4
implement EffectsDesign; implement Tests; export Design
ReneSkukies Oct 28, 2024
ba10e1d
fix size(EffectsDesign) bug
ReneSkukies Oct 28, 2024
f5facfe
fix bug in EffectsDesign test
ReneSkukies Oct 28, 2024
7a0fffc
Add tutorial
ReneSkukies Oct 29, 2024
0e7df88
Apply suggestions from code review
ReneSkukies Oct 29, 2024
a10d5a9
Update getGroundTruth.jl tutorial
ReneSkukies Oct 29, 2024
5b53765
Merge branch 'main' into v4.0
behinger Nov 6, 2024
6685d8d
Merge branch 'v4.0' into GroundTruth
ReneSkukies Nov 7, 2024
523f90b
Apply suggestions from code review
ReneSkukies Nov 7, 2024
5fb95bf
Update design.jl with empty line in the end
ReneSkukies Nov 7, 2024
d3fa46e
Merge branch 'main' into v4.0
behinger Nov 15, 2024
5574425
fix sequence design rng
behinger Nov 28, 2024
1966fbe
fix sequence test
behinger Nov 28, 2024
fa6f78b
fix rng docs
behinger Nov 28, 2024
b9cde99
finish gt tutorial
ReneSkukies Nov 29, 2024
60b8941
fix #124, explicitly cast the dict
behinger Dec 13, 2024
01a1e44
not sure where this error came in...
behinger Dec 13, 2024
33bc2b6
hanning upgrade
behinger Dec 13, 2024
5d38311
checking stuff
behinger Dec 13, 2024
25009e4
Apply suggestions from code review
ReneSkukies Jan 17, 2025
1a133ae
Merge pull request #112 from unfoldtoolbox/GroundTruth
ReneSkukies Jan 17, 2025
e14765b
merge the real v0.4 released
behinger Feb 27, 2025
7996783
rename offset/basis -> get_offset/get_basis; fix test ommitted begin
behinger Feb 27, 2025
d5c7b4d
fix: code duplications
behinger Feb 27, 2025
c528f6a
refactor: get_basis, fix basis docstring
behinger Feb 27, 2025
73409f4
fix: format docstring; fix: remove size(design) replace with length(d…
behinger Feb 27, 2025
08b0738
relax compat
behinger Feb 27, 2025
ddbafdf
remove unused type-field
behinger Feb 27, 2025
1de2186
added docstring warning for irregular size
behinger Feb 27, 2025
36b1920
fix maxget_offset bug & get_basis with rng
behinger Mar 20, 2025
e610041
test: get_basis
behinger Mar 20, 2025
2cbad0b
added docstring with rng
behinger Mar 20, 2025
f49004d
fix: added a comment on the basisfunction-rng two inputs
behinger Mar 20, 2025
9be7376
tests+fix: min/maxoffset, negative minoffset bug
behinger Mar 20, 2025
d1defe0
fix docustring simulation missing
behinger Mar 27, 2025
c23c317
fix mention onsetformulas at top
behinger Mar 27, 2025
6ccd668
fix better assert msg
behinger Mar 27, 2025
c28fbc1
Apply suggestions from code review
behinger Mar 27, 2025
89c3454
Update src/component.jl
behinger Mar 27, 2025
157932f
fix n_channel docstring
behinger Mar 27, 2025
d7a87a2
Merge branch 'v4.0' of https://github.com/unfoldtoolbox/UnfoldSim.jl …
behinger Mar 27, 2025
cfb46b8
Update src/component.jl
behinger Mar 27, 2025
0bb23fc
removed unnecessary interface
behinger Mar 27, 2025
82603d8
Merge branch 'v4.0' of https://github.com/unfoldtoolbox/UnfoldSim.jl …
behinger Mar 27, 2025
96c3fc5
fix component fucntion tutorial issues
behinger Mar 27, 2025
ea7b288
improved sequence-tutorial
behinger Mar 27, 2025
ad13734
better docfix
behinger Mar 27, 2025
755daaa
typo docstring
behinger Mar 31, 2025
8513184
better effects design docstring
behinger Mar 31, 2025
ef9556d
empty line + documented 2*maxlength
behinger Mar 31, 2025
c6b719f
added docstrings
behinger Mar 31, 2025
adc225d
slight fix
behinger Mar 31, 2025
f0037f7
Update src/design.jl
behinger Mar 31, 2025
2b7930c
Update test/design.jl
behinger Apr 11, 2025
34be071
adapt to UnfoldMixedModels
behinger Apr 11, 2025
5908840
remove compat, add unfoldmixedmodels, fix-up groundtrutheffectsdesign…
behinger Apr 11, 2025
0e2a446
Merge branch 'v4.0' of https://github.com/unfoldtoolbox/UnfoldSim.jl …
behinger Apr 11, 2025
37539f2
JuliaFormatter: Apply suggestions from code review
jschepers Apr 11, 2025
2b8f600
JuliaFormatter: Apply suggestions from code review
jschepers Apr 11, 2025
c9afd8a
fix up ground truth marginal effects tutorial
behinger Apr 11, 2025
4adb5fd
Merge branch 'v4.0' of https://github.com/unfoldtoolbox/UnfoldSim.jl …
behinger Apr 11, 2025
a8d4d08
fix size of sequencedesign, added rng to all size/length functions
behinger Mar 27, 2025
d6d64a6
fix size of sequencedesign, added rng to all size/length functions, f…
behinger Mar 27, 2025
5416d4d
JuliaFormatter: Apply suggestions from code review
jschepers Apr 11, 2025
3947c57
workaround UnfoldMakie fix
behinger Apr 11, 2025
991ab38
Merge branch 'v4.0' of https://github.com/unfoldtoolbox/UnfoldSim.jl …
behinger Apr 11, 2025
02d38c7
fix length/size after typedef
behinger Apr 11, 2025
7a0f81f
missing rng
behinger Apr 11, 2025
b345da4
fix a missing rng
behinger Apr 11, 2025
a8c3801
un-ambiguate size
behinger Apr 11, 2025
b43a5a1
export ShiftOnsetByOne
behinger Apr 11, 2025
a6f4e3c
add a unittest
behinger Apr 11, 2025
0c78de8
Fix method ambiguity
jschepers Apr 15, 2025
878c019
Fix UnfoldMixedModels name space issue and add RNGs
jschepers Apr 15, 2025
ca9af4c
Merge branch 'v4.0' into fix#124
behinger May 16, 2025
6109b13
Format docstrings
jschepers Jun 11, 2025
fb14397
Adapt CI workflow to run for PRs to all branches not just main
jschepers Jun 11, 2025
89ee8e0
Fix ShiftOnsetByOne test
jschepers Jun 11, 2025
8f27939
More docstring formatting + fixing ambiguous links
jschepers Jun 12, 2025
c8fbae8
Update src/component.jl
behinger Jun 12, 2025
33ca351
merged v4.0 & completed code-review
behinger Jun 27, 2025
4bf0034
Apply suggestions from code review
jschepers Jul 4, 2025
f291a95
Merge pull request #154 from unfoldtoolbox/ShiftOnsetByOne
jschepers Jul 7, 2025
badd2db
Combine changed docstring with docstring on main
jschepers Oct 10, 2025
d6101c3
Apply suggestions from code review
behinger Oct 13, 2025
885e0f2
fix component offset bug, add tests
behinger Mar 31, 2025
3b65091
Replace max_length_continuoustime calculation with new version + add …
jschepers Oct 8, 2025
45ed602
Add get_offset methods for vectors and sequences and adapt max_length…
jschepers Oct 8, 2025
0229392
Add test for get_offset for vectors and sequences and for the combina…
jschepers Oct 9, 2025
b89fab7
Adapt the get_offset function for sequence dicts to return a dict ins…
jschepers Oct 9, 2025
86623ef
Apply suggestions from code review
behinger Oct 13, 2025
cedde16
Apply suggestions from code review
behinger Oct 13, 2025
05f699f
Apply suggestions from code review
jschepers Oct 13, 2025
c697004
Merge branch 'fix#124' into hanningfix
jschepers Oct 13, 2025
f5d21b7
Remove that CI should only run for the main branch
jschepers Oct 13, 2025
34521a5
Enable CI for all PRs not just the ones on main
jschepers Oct 13, 2025
564be7b
Replace hard-coded value
jschepers Oct 13, 2025
5faf54b
Include test/bases.jl in tests
jschepers Oct 14, 2025
b5d2d00
Fix tests
jschepers Oct 14, 2025
61b7d36
Apply suggestions from reviewdog
jschepers Oct 14, 2025
5b3cfc4
Merge pull request #128 from unfoldtoolbox/hanningfix
jschepers Oct 14, 2025
3227b90
add simulation call
behinger Oct 15, 2025
0d8d5d1
added two more tests, just in case
behinger Oct 15, 2025
683b273
Add short docstring for limit_basis function
jschepers Oct 15, 2025
a1ea003
Fix multi-component sequence test
jschepers Oct 29, 2025
ac7201b
Fix typo
jschepers Oct 29, 2025
d173c46
Merge pull request #127 from unfoldtoolbox/fix#124
jschepers Oct 29, 2025
82a2e6a
Include missing test scripts
jschepers Nov 3, 2025
72131a1
Resolved merge conflics
jschepers Nov 3, 2025
4381233
Format EffectsDesign docstring + update link
jschepers Nov 4, 2025
ea91727
Format generate_events docstring for EffectsDesign, added type for RNG
jschepers Nov 4, 2025
48968af
Remove unnecessary code
jschepers Nov 4, 2025
75bed90
Minor revisions EffectsDesign how to page
jschepers Nov 5, 2025
6f704f5
Minor revisions EffectsDesign how to page
jschepers Nov 5, 2025
8249bce
Minor formatting and language changes
jschepers Nov 5, 2025
27b5f15
Format SequenceDesign doc string
jschepers Nov 5, 2025
62fcc24
Formatting
jschepers Nov 6, 2025
dfc267d
Apply suggestions from reviewdog
jschepers Nov 6, 2025
75c9477
Fix brackets messed up by Review dog
jschepers Nov 6, 2025
c66bdb5
Apply suggestions from code review
behinger Nov 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ on:
- main
tags: '*'
pull_request:
branches:
- main
concurrency:
# Skip intermediate builds: always.
# Cancel intermediate builds: only if it is a pull request build.
Expand Down
5 changes: 3 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ version = "0.4.0"

[deps]
Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"
Automa = "67c07d97-cdcb-5c2c-af73-a7f9c32a568b"
DSP = "717857b8-e6f2-59f4-9121-6e50c889abd2"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
Expand All @@ -23,7 +24,7 @@ ToeplitzMatrices = "c751599d-da0a-543b-9d20-d0a503d91d24"

[compat]
Artifacts = "1"
DSP = "0.7"
DSP = "0.7,0.8"
DataFrames = "1"
Distributions = "0.25"
FileIO = "1"
Expand All @@ -34,7 +35,7 @@ MixedModels = "4"
MixedModelsSim = "0.2"
Parameters = "0.12"
Random = "1"
SignalAnalysis = "0.4, 0.5,0.6"
SignalAnalysis = "0.4, 0.5,0.6,0.7,0.8,0.9,0.10"
Statistics = "1"
StatsModels = "0.6,0.7"
ToeplitzMatrices = "0.7, 0.8"
Expand Down
4 changes: 1 addition & 3 deletions docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,5 @@ StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
TimerOutputs = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f"
Unfold = "181c99d8-e21b-4ff3-b70b-c233eddec679"
UnfoldMakie = "69a5ce3b-64fb-4f22-ae69-36dd4416af2a"
UnfoldMixedModels = "019ae9e0-8363-565c-86e5-97a5a2fe84f4"
UnfoldSim = "ed8ae6d2-84d3-44c6-ab46-0baf21700804"

[compat]
Unfold = "0.7"
69 changes: 69 additions & 0 deletions docs/literate/HowTo/componentfunction.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# # Component Basisfunctions
# HowTo use functions that depend on the `design` and return per-event basis-vectors, instead of the same basis vector for all events.


# ### Setup
# ```@raw html
# <details>
# <summary>Click to expand</summary>
# ```
## Load required packages
using UnfoldSim
using Unfold
using Random
using DSP
using CairoMakie, UnfoldMakie
# ```@raw html
# </details >
# ```


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)),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this example, the magnitude does not really matter, but do I understand it correctly that the duration is ~20s?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's 20 to 120 samples => 0.2 to 1.2s

),
);


# 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 - in our case a hanning window with the size depending on the experimental design's duration.
# !!! important
# Two things have to be taken care of:
# 1. in case a rng is required to e.g. generate the design, or your basisfunction depends on it, you have to specify a two-argument basis-function: `(rng,design)->...`
# 2. a `maxlength` has to be specified via a tuple `(function,maxlength)``
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# 2. a `maxlength` has to be specified via a tuple `(function,maxlength)``
# 2. a `maxlength` in samples 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);

# After simulation, we are ready to plot it. We expect that the simulated responses are scaled by the design's duration. To show it more effectively, we sort by duration.
##---
f = Figure()
df = UnfoldMakie.eeg_array_to_dataframe(erp')
df.duration = repeat(generate_events(design).duration, inner = size(erp, 1))
df.category = repeat(generate_events(design).category, inner = size(erp, 1))
plot_erp!(
f[1, 1],
df,
mapping = (; group = :group => nonnumeric, col = :category), # color = :duration, fails right nowUnfoldMakie#353
layout = (; legend_position = :left),
colorbar = (; label = "Duration"),
)
plot_erpimage!(
f[2, 1],
erp,
sortvalues = generate_events(design).duration,
layout = (; legend_position = :bottom),
)
f
Comment on lines +49 to +67
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest to hide the code for the figure or rather have it in an expandable/collapsible element, such that it can be opened if needed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And the legend of the figure needs fixing but we can postpone this and collect it in an issue: #99 (comment) (I added it already)


# The scaling by the two `condition` effect levels and the modified event duration by the `duration` are clearly visible
116 changes: 116 additions & 0 deletions docs/literate/HowTo/getGroundTruth.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# # Simulate ground truth marginalized Effects

# Often when testing some algorithm, we want to compare our results to a known ground truth. In the case of marginalized effects via the `Unfold.effects`/ `Effects.jl` interface, we can do this using an `EffectsDesign`.
# You can find more on what marginalized effects are here in the [Unfold.jl documentation](https://unfoldtoolbox.github.io/Unfold.jl/dev/generated/HowTo/effects/)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# # Simulate ground truth marginalized Effects
# Often when testing some algorithm, we want to compare our results to a known ground truth. In the case of marginalized effects via the `Unfold.effects`/ `Effects.jl` interface, we can do this using an `EffectsDesign`.
# You can find more on what marginalized effects are here in the [Unfold.jl documentation](https://unfoldtoolbox.github.io/Unfold.jl/dev/generated/HowTo/effects/)
# # Simulate ground truth marginal effects
# Often when testing some algorithm, we want to compare our results to a known ground truth. In the case of marginal effects via the `Unfold.effects`/ `Effects.jl` interface, we can do this using an `EffectsDesign`.
# You can find more on what marginal effects are here in the [Unfold.jl documentation](https://unfoldtoolbox.github.io/Unfold.jl/dev/generated/HowTo/effects/)


# ### Setup
# ```@raw html
# <details>
# <summary>Click to expand</summary>
# ```
## Load required packages
using UnfoldSim
using Unfold
using CairoMakie
using UnfoldMakie
using Random
# ```@raw html
# </details >
# ```
# ## Simulation
# First let's make up a SingleSubject simulation

# !!! note
# Getting a ground truth for a MultiSubjectDesign is not implemented yet

design =
SingleSubjectDesign(;
conditions = Dict(
:condition => ["bike", "face"],
:continuous => range(0, 5, length = 10),
),
) |> x -> RepeatDesign(x, 5);

# **n170** has a condition effect, faces are more negative than bikes
n1 = LinearModelComponent(;
basis = n170(),
formula = @formula(0 ~ 1 + condition),
β = [5, 3],
);
# **p300** has a continuous effect, higher continuous values will result in larger P300's.
# We include both a linear and a quadratic effect of the continuous variable.
p3 = LinearModelComponent(;
basis = p300(),
formula = @formula(0 ~ 1 + continuous + continuous^2),
β = [5, 1, 0.2],
);

components = [n1, p3]
data, evts = simulate(
MersenneTwister(1),
design,
components,
UniformOnset(; width = 0, offset = 1000),
PinkNoise(),
);

# ## Simulate marginalized effects directly
# To marginalize effects we first have to specify an effects dictionary and subsequently hand this dict plus the original design to `EffectsDesign()`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# ## Simulate marginalized effects directly
# To marginalize effects we first have to specify an effects dictionary and subsequently hand this dict plus the original design to `EffectsDesign()`
# ## Simulate marginal effects directly
# To simulate marginal effects, we first have to specify an effects dictionary and subsequently hand this dict plus the original design to `EffectsDesign()`


effects_dict = Dict(:condition => ["bike", "face"])

effects_design = EffectsDesign(design, effects_dict)

# !!! note
# We only specified the condition levels here, by default every unspecified variable will be set to a "typical" (i.e. the mean) value.

# And finally we can simulate our ground truth marginal effects

gt_data, gt_events = simulate(
MersenneTwister(1),
effects_design,
components,
NoOnset(),
NoNoise(),
return_epoched = true,
);
@show gt_events

# Additionally, we can get the simulated effects into a tidy dataframe using Unfold's `result_to_table`.
# Note that the data has to be reshaped into a channel X times X predictor form. (In our one channel example `size(gt_data) = (45,2)`, missing the channel dimension)

g = reshape(gt_data, 1, size(gt_data)...)
times = range(1, 45);
gt_effects = Unfold.result_to_table([g], [gt_events], [times], ["effects"])
first(gt_effects, 5)


# ## Compare with Unfold.jl results

m = fit(
UnfoldModel,
[
Any => (
@formula(0 ~ 1 + condition + spl(continuous, 4)),
firbasis(τ = [-0.1, 1], sfreq = 100, name = "basis"),
),
],
evts,
data,
);

ef = effects(effects_dict, m);

# !!! note
# The ground truth is shorter because the ground truth typically returns values between `[0 maxlength(components)]`, whereas in our unfold-model we included a baseline period of 0.1s.
# If you want to actually compare results with the ground truth, you could either us `UnfoldSim.pad_array()` or set the Unfold modelling window to `τ=[0,1]`

gt_effects.type .= "UnfoldSim effects"
ef.type .= "Unfold effects"

gt_effects.time = gt_effects.time ./ 100 .- 1 / 100
ef.continuous .= 2.5 # needed to be able to easily merge the two dataframes
comb = vcat(gt_effects, ef)
plot_erp(comb; mapping = (; color = :type, col = :condition))

# The simulated ground truth marginal effects, and the fitted marginal effects look similar as expected, but the fitted has some additional noise because of finite data (also as expected).
9 changes: 7 additions & 2 deletions docs/literate/HowTo/newComponent.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
# # Define a new component (with variable duration and shift)

# We want a new component that changes its duration and shift depending on a column in the event design. This is somewhat already implemented in the HRF + Pupil bases.
# !!! hint
# if you are just interested to use duration-dependency in your simulation, check out the component-function tutorial



# ### Setup
# ```@raw html
# <details>
# <summary>Click to expand</summary>
# ```
using UnfoldSim
import UnfoldSim.simulate_component
using Unfold
using Random
using DSP
Expand Down Expand Up @@ -39,7 +44,7 @@ end
Base.length(c::TimeVaryingComponent) = length(c.maxlength)

# While we could have put the TimeVaryingComponent.basisfunction directly into the simulate function, I thought this is a bit more modular
function UnfoldSim.simulate(rng, c::TimeVaryingComponent, design::AbstractDesign)
function UnfoldSim.simulate_component(rng, c::TimeVaryingComponent, design::AbstractDesign)
evts = generate_events(design)
return c.basisfunction(evts, c.maxlength)
end
Expand All @@ -62,7 +67,7 @@ function basis_shiftduration(evts, maxlength)
end

# ## Simulate data with the new component type
erp = UnfoldSim.simulate(
erp = UnfoldSim.simulate_component(
MersenneTwister(1),
TimeVaryingComponent(basis_shiftduration, 50),
design,
Expand Down
3 changes: 3 additions & 0 deletions docs/literate/HowTo/newDesign.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
# A design specifies how much data is generated, and how the event-table(s)
# should be generated. Already implemented examples are `MultiSubjectDesign` and `SingleSubjectDesign`.


# We need 3 things for a new design: a `struct<:AbstractDesign`, a `size` and a `generate_events` function.


# ### Setup
# ```@raw html
# <details>
Expand All @@ -15,6 +17,7 @@ using StableRNGs
using DataFrames
using Parameters
using Random

# ```@raw html
# </details>
# <br />
Expand Down
91 changes: 91 additions & 0 deletions docs/literate/HowTo/sequence.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# # Sequence of events (e.g. SCR)

# In this HoWTo we learn to simulate a "SR"-Sequence, a stimulus response, followed by a button press response.
# ### Setup
# ```@raw html
# <details>
# <summary>Click to expand</summary>
# ```
## Load required packages
using UnfoldSim
using CairoMakie
using StableRNGs
# ```@raw html
# </details >
# ```


#
# 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)
# 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)
# 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 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)

# This results in 16 trials that nicely follow our sequence

# !!! hint
# 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.


# 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,
)
nothing ## hide


# We combine them into a dictionary with a sequence-`Char` as key and simulate
components = Dict('S' => [p1, n1, p3], 'R' => [resp])

data, evts = simulate(
StableRNG(1),
design,
components,
UniformOnset(offset = 40, width = 10),
NoNoise(),
)
nothing ## hide

# 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.



2 changes: 2 additions & 0 deletions docs/literate/reference/designtypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ design_single_shuffled = SingleSubjectDesign(;
:stimulus_type => ["natural", "artificial"],
:contrast_level => range(0, 1, length = 3),
),

event_order_function = shuffle,

);
# ```@raw html
# <details>
Expand Down
Loading
Loading