-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #29 from unfoldtoolbox/multichannel
multichannel
- Loading branch information
Showing
17 changed files
with
492 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[hartmut] | ||
git-tree-sha1 = "07d7f285b4fed914b2ab5dc25dae3e108b8ce35e" | ||
|
||
[[hartmut.download]] | ||
sha256 = "8fa88ed124e2307ad757956fcdf4f670193a6c58974f3adb8473b56afeb995a7" | ||
url = "https://gist.github.com/behinger/96973aae77e56a73ddeea83792bc52ad/raw/07d7f285b4fed914b2ab5dc25dae3e108b8ce35e.tar.gz" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
|
||
using UnfoldSim | ||
using UnfoldMakie | ||
using CairoMakie | ||
using DataFrames | ||
using Random | ||
|
||
## Specifcy design | ||
# We are using a one-level design for testing here. | ||
design = SingleSubjectDesign(conditions=Dict(:condA=>["levelA"])) | ||
|
||
# Next we generate two simple components at two different times without any formula attached (we have a single condition anyway) | ||
c = LinearModelComponent(;basis=p100(),formula = @formula(0~1),β = [1]); | ||
c2 = LinearModelComponent(;basis=p300(),formula = @formula(0~1),β = [1]); | ||
|
||
# next similar to the nested design above, we can nest the component in a `MultichannelComponent`. We could either provide the projection marix manually, e.g.: | ||
mc = UnfoldSim.MultichannelComponent(c, [1,2,-1,3,5,2.3,1]) | ||
|
||
# or maybe more convenient: use the pair-syntax: Headmodel=>Label which makes use of a headmodel (HaRTmuT is currently easily available in UnfoldSim) | ||
hart = headmodel(type="hartmut") | ||
mc = UnfoldSim.MultichannelComponent(c, hart=>"Left Postcentral Gyrus") | ||
mc2 = UnfoldSim.MultichannelComponent(c2, hart=>"Right Occipital Pole") | ||
|
||
# !!! hint | ||
# You could also specify a noise-specific component which is applied prior to projection & summing with other components | ||
# | ||
# finally we need to define the onsets of the signal | ||
onset = UniformOnset(;width=20,offset=4); | ||
|
||
## Simulation + Plotting | ||
# Now as usual we simulate data. Inspecting data shows our result is now indeed ~230 Electrodes large! Nice! | ||
data,events = simulate(MersenneTwister(1),design, [mc,mc2], onset, NoNoise()) | ||
size(data) | ||
|
||
# Let's plot using Butterfly & Topoplot | ||
# first we convert the electrodes to positions usable in TopoPlots.jl | ||
pos3d = hart.electrodes["pos"] | ||
pos3d = pos3d ./ (4*maximum(pos3d,dims=1))#.+0.5 # standardize | ||
pos2d = to_positions(pos3d') | ||
pos2d = [Point2f(p[1]+0.5,p[2]+0.5) for p in pos2d] | ||
|
||
# let's plot! | ||
f = Figure() | ||
df = DataFrame(:estimate => data[:],:channel => repeat(1:size(data,1),outer=size(data,2)),:time => repeat(1:size(data,2),inner=size(data,1))) | ||
plot_butterfly!(f[1,1:2],df;positions=pos2d) | ||
plot_topoplot!(f[2,1],df[df.time .== 28,:];positions=pos2d,visual=(;enlarge=0.5,label_scatter=false),axis=(;limits=((0,1),(0,0.9)))) | ||
plot_topoplot!(f[2,2],df[df.time .== 48,:];positions=pos2d,visual=(;enlarge=0.5,label_scatter=false),axis=(;limits=((0,1),(0,0.9)))) | ||
f | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# # Overview of functionality | ||
# UnfoldSim has many modules, here we try to collect them to provide you with an overview | ||
using UnfoldSim | ||
using InteractiveUtils | ||
|
||
# ## Design | ||
# Designs define the experimental design. They can be nested, e.g. `RepeatDesign(SingleSubjectDesign,10)` would repeat the generated design-dataframe 10x. | ||
subtypes(AbstractDesign) | ||
|
||
# ## Component | ||
# components define a signal. Some components can be nested, e.g. `LinearModelComponent|>MultichannelComponent`, see the multi-channel tutorial for more information | ||
subtypes(AbstractComponent) | ||
|
||
# ## Onsets | ||
# Onsets define the distance between events in the continuous signal | ||
subtypes(AbstractOnset) | ||
|
||
# ## Noise | ||
# Choose the noise you need! | ||
subtypes(AbstractNoise) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
|
||
|
||
struct Hartmut <: AbstractHeadmodel | ||
artefactual | ||
cortical | ||
electrodes | ||
end | ||
|
||
function Base.show(io::IO,h::Hartmut) | ||
src_label = h.cortical["label"] | ||
ele_label = h.electrodes["label"] | ||
art_label = h.artefactual["label"] | ||
|
||
println(io,"""HArtMuT-Headmodel | ||
$(length(ele_label)) electrodes: ($(ele_label[1]),$(ele_label[2])...) - hartmut.electrodes | ||
$(length(src_label)) source points: ($(src_label[1]),...) - hartmut.cortical | ||
$(length(art_label)) source points: ($(art_label[1]),...) - hartmut.artefactual | ||
In addition to UnfoldSim.jl please cite: | ||
$(hartmut_citation()) | ||
""") | ||
end | ||
|
||
"Returns citation-string for HArtMuT" | ||
hartmut_citation() = "HArtMuT: Harmening Nils, Klug Marius, Gramann Klaus and Miklody Daniel - 10.1088/1741-2552/aca8ce" | ||
|
||
"Returns the leadfield" | ||
leadfield(hart::Hartmut;type="cortical") = type == "cortical" ? hart.cortical["leadfield"] : hart.artefactual["leadfield"] | ||
orientation(hart::Hartmut;type="cortical") = type == "cortical" ? hart.cortical["orientation"] : hart.artefactual["orientation"] | ||
|
||
|
||
""" | ||
Load a headmodel, using Artifacts.jl automatically downloads the required files | ||
Currently only `type="hartmut"` is implemented | ||
""" | ||
function headmodel(;type="hartmut") | ||
if type == "hartmut" | ||
println("""Please cite: $(hartmut_citation())""") | ||
path = joinpath(artifact"hartmut", "hartmut.h5") | ||
h = h5open(path) | ||
|
||
|
||
weirdchan = ["Nk1","Nk2","Nk3","Nk4"] | ||
## getting index of these channels from imported hartmut model data, exclude them in the topoplot | ||
remove_indices = findall(l -> l ∈ weirdchan, h["electrodes"]|>read|>x->x["label"]); | ||
|
||
function sel_chan(x) | ||
|
||
if "leadfield" ∈ keys(x) | ||
x["leadfield"] = x["leadfield"][Not(remove_indices),:,:].*10e3 # this scaling factor seems to generate potentials with +-1 as max | ||
else | ||
x["label"] = x["label"][Not(remove_indices)] | ||
x["pos"] = x["pos"][Not(remove_indices),:] | ||
end | ||
return x | ||
end | ||
headmodel = Hartmut( | ||
h["artefacts"]|>read|>sel_chan, | ||
h["cortical"]|>read|>sel_chan, | ||
h["electrodes"]|>read|>sel_chan, | ||
) | ||
else | ||
error("unknown headmodel. currently only 'hartmut' allowed") | ||
end | ||
|
||
return headmodel | ||
end | ||
|
||
""" | ||
Extracts magnitude of the orientation-including leadfield. | ||
By default uses the orientation specified in the headmodel | ||
Fallback: along the third dimension using `norm` - the maximal projection | ||
""" | ||
magnitude(headmodel::AbstractHeadmodel) = magnitude(leadfield(headmodel)) | ||
|
||
""" | ||
Extract magnitude of 3-orientation-leadfield, | ||
`type` (default: "perpendicular") => uses the provided source-point orientations - otherwise falls back to `norm` | ||
""" | ||
magnitude(headmodel::Hartmut;type="perpendicular") = type == "perpendicular" ? magnitude(leadfield(headmodel),orientation(headmodel)) : magnitude(leadfield(headmodel)) | ||
|
||
|
||
function magnitude(lf::AbstractArray{T,3},orientation::AbstractArray{T,2}) where {T<:Real} | ||
si = size(lf); | ||
magnitude = fill(NaN,si[1:2]); | ||
for e=1:si[1] | ||
for s=1:si[2] | ||
magnitude[e,s] = lf[e,s,:]' * orientation[s,:] | ||
end | ||
end | ||
return magnitude | ||
end | ||
|
||
|
||
function magnitude(lf::AbstractArray{T,3}) where {T<:Real} | ||
si = size(lf); | ||
magnitude = fill(NaN,si[1:2]); | ||
for e=1:si[1] | ||
for s=1:si[2] | ||
magnitude[e,s] = norm(lf[e,s,:]); | ||
end | ||
end | ||
return magnitude | ||
end |
Oops, something went wrong.