From 3f31f6f20bc77d015e56c15407f0ed9510613c8f Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Tue, 14 Nov 2023 13:54:33 +0000 Subject: [PATCH 01/12] revised topoplotseries and test all --- src/plot_topoplotseries.jl | 32 +++++++++++++------------------- src/plotconfig.jl | 4 ++-- test/test_all.jl | 18 ++++++++---------- test/test_erpimage.jl | 10 +++++++++- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/plot_topoplotseries.jl b/src/plot_topoplotseries.jl index 2758f05e6..8a667cf25 100644 --- a/src/plot_topoplotseries.jl +++ b/src/plot_topoplotseries.jl @@ -71,28 +71,22 @@ function plot_topoplotseries!( if config.layout.useColorbar if typeof(ftopo) == Figure d = ftopo.content[1].scene.plots[1] - Colorbar( - f[1, end+1], - colormap = d.colormap, - colorrange = d.colorrange, - height = config.colorbar.height, - flipaxis = config.colorbar.flipaxis, - labelrotation = config.colorbar.labelrotation, - label = config.colorbar.label, - ) + f_colorbar = f[1, end+1] + else - # println(fieldnames(typeof((axlist[1])))) + #@debug axlist + f_colorbar = f[:, :][1, length(axlist)+1] d = axlist[1].scene.plots[1].attributes - Colorbar( - f[:, :][1, length(axlist)+1], - colormap = d.colormap, - colorrange = d.colorrange, - height = config.colorbar.height, - flipaxis = config.colorbar.flipaxis, - labelrotation = config.colorbar.labelrotation, - label = config.colorbar.label, - ) end + Colorbar( + f_colorbar, + colormap = d.colormap, + colorrange = d.colorrange, + #height = config.colorbar.height, + flipaxis = config.colorbar.flipaxis, + labelrotation = config.colorbar.labelrotation, + label = config.colorbar.label, + ) end return f diff --git a/src/plotconfig.jl b/src/plotconfig.jl index addf46d35..7aebc8184 100644 --- a/src/plotconfig.jl +++ b/src/plotconfig.jl @@ -141,9 +141,9 @@ function PlotConfig(T::Val{:topoplotseries}) cfg, layout = (useColorbar = true,), colorbar = (; - height = 300, # why even should i made it manually? + #height = 300, flipaxis = true, - labelrotation = 4.7, + labelrotation = -π/2, label = "Voltage [µV]" ), visual = (; diff --git a/test/test_all.jl b/test/test_all.jl index 42e5637f0..789641483 100644 --- a/test/test_all.jl +++ b/test/test_all.jl @@ -1,14 +1,13 @@ @testset "8 plots" begin f = Figure(resolution=(1200, 1400)) - ga = f[1, 1] = GridLayout() - gc = f[2, 1] = GridLayout() - ge = f[3, 1] = GridLayout() - gg = f[4, 1] = GridLayout() - geh = f[1:4, 2] = GridLayout() - gb = geh[1, 1] = GridLayout() - gd = geh[2, 1] = GridLayout() - gf = geh[3, 1] = GridLayout() - gh = geh[4, 1] = GridLayout() + ga = f[1, 1] + gc = f[2, 1] + ge = f[3, 1] + gg = f[4, 1] + gb = f[1, 2] + gd = f[2, 2] + gf = f[3, 2] + gh = f[4, 2] include("../docs/example_data.jl") d_topo, pos = example_data("TopoPlots.jl") @@ -55,7 +54,6 @@ f end - @testset "8 plots with a Figure" begin f = Figure(resolution=(1200, 1400)) diff --git a/test/test_erpimage.jl b/test/test_erpimage.jl index fda7b0e6b..a09c94cb4 100644 --- a/test/test_erpimage.jl +++ b/test/test_erpimage.jl @@ -21,7 +21,15 @@ end #save("erpimage.eps", f) end - +@testset "testing better sorting" begin + using UnfoldSim + dat,evts = UnfoldSim.predef_eeg(;onset=LogNormalOnset(μ=3.5,σ=0.4),noiselevel=5) + dat_e,times = Unfold.epoch(dat,evts,[-0.1,1],100) + evts,dat_e = Unfold.dropMissingEpochs(evts,dat_e) + evts.Δlatency = diff(vcat(evts.latency,0)) + dat_e = dat_e[1,:,:] + plot_erpimage(times,dat_e;sortvalues=evts.Δlatency) +end #= @testset "testing better sorting" begin From 6f4e1dd26f85de9170d89908d26ca3fe9b73886e Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Tue, 14 Nov 2023 14:46:07 +0000 Subject: [PATCH 02/12] erp image sorted in test_all --- test/test_all.jl | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test/test_all.jl b/test/test_all.jl index 789641483..b0c7650af 100644 --- a/test/test_all.jl +++ b/test/test_all.jl @@ -40,7 +40,14 @@ plot_topoplotseries!(gd, df, 80; positions=positions, visual=(label_scatter=false,), layout = (; useColorbar=true)) plot_erpgrid!(ge, data[:, :, 1], positions) - plot_erpimage!(gf, times, d_singletrial) + + dat, evts = UnfoldSim.predef_eeg(;onset=LogNormalOnset(μ=3.5, σ=0.4), noiselevel = 5) + dat_e, times = Unfold.epoch(dat,evts, [-0.1,1], 100) + evts, dat_e = Unfold.dropMissingEpochs(evts, dat_e) + evts.Δlatency = diff(vcat(evts.latency, 0)) + dat_e = dat_e[1,:,:] + plot_erpimage!(gf, times, dat_e; sortvalues=evts.Δlatency) + #plot_erpimage!(gf, times, d_singletrial) plot_parallelcoordinates!(gh, uf_5chan, [1, 2, 3, 4, 5]; mapping=(; color=:coefname), layout=(; legendPosition=:bottom), legend=(; tellwidth =false)) From e2551663e24fa1206d5560a4e98f74681b85c1ba Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Tue, 14 Nov 2023 14:46:32 +0000 Subject: [PATCH 03/12] first draft --- src/plot_channelimage.jl | 45 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/plot_channelimage.jl diff --git a/src/plot_channelimage.jl b/src/plot_channelimage.jl new file mode 100644 index 000000000..2fc01203e --- /dev/null +++ b/src/plot_channelimage.jl @@ -0,0 +1,45 @@ +function plot_channelimage!( + f::Union{GridPosition,GridLayout,Figure}, + position::Vector{Point{2, Float32}}, + plotData::Matrix{<:Real} + raw_ch_names::Vector{String}; + kwargs..., + ) + #= raw = PyMNE.io.read_raw_eeglab(p, preload=true) + dat_e = load("data/dat_e.jld2")["1"] + mon = PyMNE.channels.make_standard_montage("standard_1020") + raw.set_channel_types(Dict("HEOG_left"=>"eog","HEOG_right"=>"eog","VEOG_lower"=>"eog")) + raw.set_montage(mon,match_case=false) + pos = PyMNE.channels.make_eeg_layout(raw.info).pos + pos = pyconvert(Array,pos) + pos = [Point2f(pos[k,1], pos[k,2]) for k in 1:size(pos,1)] + raw_ch_names = pyconvert(Array, raw.ch_names) =# + + x = [i[1] for i in position] + y = [i[2] for i in position] + + x = round.(x; digits=2) + y = Integer.(round.((y .- mean(y)) * 20)) * -1 + x = Integer.(round.((x .- mean(x)) * 20)) + d = zip(x, y, raw_ch_names, 1:20) + a = sort!(DataFrame(d), [:2, :1], rev=[true, false]) + b = a[!, :4] + c = a[!, :3] + c = pyconvert(Array, c) + c = [string(x) for x in c] + + ix = range(-0.3, 1.2, length = size(plotData, 2)) + iy = 1:20 + iz = mean(plotData, dims=3)[b, :, 1]' + + gin = f[1, 1] = GridLayout() + ax = Axis(gin[1, 1], xlabel = "Time [s]", ylabel = "Channels") + hm = CairoMakie.heatmap!(ix, iy, iz, + colormap="cork") + ax.yticks = iy + ax.ytickformat = xc -> c + ax.yticklabelsize = 14 + + CairoMakie.Colorbar(gin[1, 2], hm, label = "Voltage [µV]") + return f +end \ No newline at end of file From 19884ab05969e4655942c0b1a830c37b7ec2ed42 Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev <33777074+vladdez@users.noreply.github.com> Date: Tue, 14 Nov 2023 15:08:59 +0000 Subject: [PATCH 04/12] Update plot_channelimage.jl --- src/plot_channelimage.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plot_channelimage.jl b/src/plot_channelimage.jl index 2fc01203e..15ae51c1c 100644 --- a/src/plot_channelimage.jl +++ b/src/plot_channelimage.jl @@ -1,7 +1,7 @@ function plot_channelimage!( f::Union{GridPosition,GridLayout,Figure}, position::Vector{Point{2, Float32}}, - plotData::Matrix{<:Real} + plotData::Matrix{<:Real}, raw_ch_names::Vector{String}; kwargs..., ) @@ -42,4 +42,4 @@ function plot_channelimage!( CairoMakie.Colorbar(gin[1, 2], hm, label = "Voltage [µV]") return f -end \ No newline at end of file +end From 5fe7c02d390feea9b4354e0af8f522e5cbe4591f Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Fri, 24 Nov 2023 13:48:08 +0000 Subject: [PATCH 05/12] first successfull test --- src/UnfoldMakie.jl | 3 ++ src/plot_channelimage.jl | 60 +++++++++++++++++++++------------------ test/test_channelimage.jl | 11 +++++++ 3 files changed, 47 insertions(+), 27 deletions(-) create mode 100644 test/test_channelimage.jl diff --git a/src/UnfoldMakie.jl b/src/UnfoldMakie.jl index e742859f4..2bf17072e 100644 --- a/src/UnfoldMakie.jl +++ b/src/UnfoldMakie.jl @@ -43,6 +43,7 @@ include("plot_erpimage.jl") include("plot_parallelcoordinates.jl") include("plot_circulareegtopoplot.jl") include("plot_erpgrid.jl") +include("plot_channelimage.jl") include("layout_helper.jl") include("eeg_positions.jl") @@ -71,6 +72,8 @@ export plot_topoplotseries export plot_topoplotseries! export plot_erpgrid export plot_erpgrid! +export plot_channelimage +export plot_channelimage! export to_positions export nonnumeric # reexport from AoG diff --git a/src/plot_channelimage.jl b/src/plot_channelimage.jl index 2fc01203e..64ee5cbc7 100644 --- a/src/plot_channelimage.jl +++ b/src/plot_channelimage.jl @@ -1,45 +1,51 @@ +plot_channelimage( + data::Matrix{<:Real}, + position::Vector{Point{2,Float32}}, + ch_names::Vector{String}; + kwargs..., +) = plot_channelimage!(Figure(), data, position, ch_names; kwargs...) + function plot_channelimage!( f::Union{GridPosition,GridLayout,Figure}, - position::Vector{Point{2, Float32}}, - plotData::Matrix{<:Real} - raw_ch_names::Vector{String}; + data::Matrix{<:Real}, + position::Vector{Point{2,Float32}}, + ch_names::Vector{String}; kwargs..., - ) - #= raw = PyMNE.io.read_raw_eeglab(p, preload=true) - dat_e = load("data/dat_e.jld2")["1"] - mon = PyMNE.channels.make_standard_montage("standard_1020") - raw.set_channel_types(Dict("HEOG_left"=>"eog","HEOG_right"=>"eog","VEOG_lower"=>"eog")) - raw.set_montage(mon,match_case=false) - pos = PyMNE.channels.make_eeg_layout(raw.info).pos - pos = pyconvert(Array,pos) - pos = [Point2f(pos[k,1], pos[k,2]) for k in 1:size(pos,1)] - raw_ch_names = pyconvert(Array, raw.ch_names) =# +) + #= raw = PyMNE.io.read_raw_eeglab(p, preload=true) + dat_e = load("data/dat_e.jld2")["1"] + mon = PyMNE.channels.make_standard_montage("standard_1020") + raw.set_channel_types(Dict("HEOG_left"=>"eog","HEOG_right"=>"eog","VEOG_lower"=>"eog")) + raw.set_montage(mon,match_case=false) + pos = PyMNE.channels.make_eeg_layout(raw.info).pos + pos = pyconvert(Array,pos) + pos = [Point2f(pos[k,1], pos[k,2]) for k in 1:size(pos,1)] + ch_names = pyconvert(Array, raw.ch_names) =# x = [i[1] for i in position] y = [i[2] for i in position] - - x = round.(x; digits=2) - y = Integer.(round.((y .- mean(y)) * 20)) * -1 - x = Integer.(round.((x .- mean(x)) * 20)) - d = zip(x, y, raw_ch_names, 1:20) - a = sort!(DataFrame(d), [:2, :1], rev=[true, false]) + + x = round.(x; digits = 2) + y = Integer.(round.((y .- mean(y)) * 20)) * -1 + x = Integer.(round.((x .- mean(x)) * 20)) + d = zip(x, y, ch_names, 1:20) + a = sort!(DataFrame(d), [:2, :1], rev = [true, false]) b = a[!, :4] c = a[!, :3] - c = pyconvert(Array, c) + #c = pyconvert(Array, c) c = [string(x) for x in c] - - ix = range(-0.3, 1.2, length = size(plotData, 2)) + + ix = range(-0.3, 1.2, length = size(data, 2)) iy = 1:20 - iz = mean(plotData, dims=3)[b, :, 1]' + iz = mean(data, dims = 3)[b, :, 1]' gin = f[1, 1] = GridLayout() ax = Axis(gin[1, 1], xlabel = "Time [s]", ylabel = "Channels") - hm = CairoMakie.heatmap!(ix, iy, iz, - colormap="cork") + hm = Makie.heatmap!(ix, iy, iz, colormap = "cork") ax.yticks = iy ax.ytickformat = xc -> c ax.yticklabelsize = 14 - CairoMakie.Colorbar(gin[1, 2], hm, label = "Voltage [µV]") + Makie.Colorbar(gin[1, 2], hm, label = "Voltage [µV]") return f -end \ No newline at end of file +end diff --git a/test/test_channelimage.jl b/test/test_channelimage.jl new file mode 100644 index 000000000..6f9ffed52 --- /dev/null +++ b/test/test_channelimage.jl @@ -0,0 +1,11 @@ +data, pos = TopoPlots.example_data() +data = data[:, :, 1] +pos = pos[1:30] +raw_ch_names = ["FP1", "F3", "F7", "FC3", "C3", "C5", "P3", "P7", "P9", "PO7", +"PO3", "O1", "Oz", "Pz", "CPz", "FP2", "Fz", "F4", "F8", "FC4", "FCz", "Cz", +"C4", "C6", "P4", "P8", "P10", "PO8", "PO4", "O2"] + +@testset "channel image basic" begin + plot_channelimage(data, pos, raw_ch_names) + +end From 1fabe0a6be603938b0b0f4ec2626d75c349496b0 Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Fri, 24 Nov 2023 14:05:14 +0000 Subject: [PATCH 06/12] upd to main --- .all-contributorsrc | 111 ++++++++++++++++ Project.toml | 6 +- README.md | 36 +++-- docs/example_data.jl | 146 +++++++++++++-------- docs/literate/tutorials/circTopo.jl | 10 +- docs/literate/tutorials/erp.jl | 25 ++-- docs/make.jl | 31 ++--- docs/run_liveserver.jl | 8 +- docs/src/how_to/mult_vis_in_fig.md | 15 ++- docs/src/how_to/position2color.md | 11 +- docs/src/tutorials/butterfly.md | 24 ++-- docs/src/tutorials/designmatrix.md | 24 ++-- docs/src/tutorials/erpimage.md | 34 +++-- docs/src/tutorials/topoplotseries.md | 24 +++- src/docstringtemplate.jl | 6 +- src/layout_helper.jl | 18 +-- src/plot_channelimage.jl | 10 -- src/plot_circulareegtopoplot.jl | 80 +++++------ src/plot_designmatrix.jl | 69 +++++----- src/plot_erp.jl | 118 +++++++++-------- src/plot_erpgrid.jl | 28 ++-- src/plot_erpimage.jl | 45 ++++--- src/plot_parallelcoordinates.jl | 42 +++--- src/plot_topoplot.jl | 28 ++-- src/plot_topoplotseries.jl | 70 +++++----- src/plotconfig.jl | 28 ++-- test/Project.toml | 1 + test/runtests.jl | 25 ++-- test/setup.jl | 1 + test/test_butterfly.jl | 28 +++- test/{test_all.jl => test_complexplots.jl} | 62 ++++----- test/test_dm.jl | 4 +- test/test_erp.jl | 42 ++++-- test/test_erpimage.jl | 8 +- test/test_pcp.jl | 2 +- test/test_plot_circulareegtopoplot.jl | 6 +- test/test_pp.jl | 18 --- test/test_toposeries.jl | 4 +- 38 files changed, 734 insertions(+), 514 deletions(-) create mode 100644 .all-contributorsrc rename test/{test_all.jl => test_complexplots.jl} (83%) delete mode 100644 test/test_pp.jl diff --git a/.all-contributorsrc b/.all-contributorsrc new file mode 100644 index 000000000..c14c4dde1 --- /dev/null +++ b/.all-contributorsrc @@ -0,0 +1,111 @@ +{ + "files": [ + "README.md" + ], + "imageSize": 100, + "commit": false, + "commitType": "docs", + "commitConvention": "angular", + "contributors": [ + { + "login": "behinger", + "name": "Benedikt Ehinger", + "avatar_url": "https://avatars.githubusercontent.com/u/10183650?v=4", + "profile": "http://www.benediktehinger.de", + "contributions": [ + "bug", + "code", + "doc", + "ideas", + "infra", + "maintenance", + "question", + "review", + "test", + "tutorial" + ] + }, + { + "login": "Link250", + "name": "Quantum", + "avatar_url": "https://avatars.githubusercontent.com/u/4541950?v=4", + "profile": "https://github.com/Link250", + "contributions": [ + "code", + "doc" + ] + }, + { + "login": "vladdez", + "name": "Vladimir Mikheev", + "avatar_url": "https://avatars.githubusercontent.com/u/33777074?v=4", + "profile": "https://github.com/vladdez", + "contributions": [ + "bug", + "code", + "doc", + "ideas", + "maintenance", + "review", + "test", + "tutorial" + ] + }, + { + "login": "NiklasMGaertner", + "name": "NiklasMGaertner", + "avatar_url": "https://avatars.githubusercontent.com/u/54365174?v=4", + "profile": "https://github.com/NiklasMGaertner", + "contributions": [ + "code", + "doc" + ] + }, + { + "login": "SorenDoring", + "name": "SorenDoring", + "avatar_url": "https://avatars.githubusercontent.com/u/54365184?v=4", + "profile": "https://github.com/SorenDoring", + "contributions": [ + "code", + "doc" + ] + }, + { + "login": "lokmanfl", + "name": "lokmanfl", + "avatar_url": "https://avatars.githubusercontent.com/u/44772645?v=4", + "profile": "https://github.com/lokmanfl", + "contributions": [ + "code", + "doc" + ] + }, + { + "login": "jschepers", + "name": "Judith Schepers", + "avatar_url": "https://avatars.githubusercontent.com/u/22366977?v=4", + "profile": "https://github.com/jschepers", + "contributions": [ + "bug", + "ideas", + "doc" + ] + }, + { + "login": "ReneSkukies", + "name": "René Skukies", + "avatar_url": "https://avatars.githubusercontent.com/u/57703446?v=4", + "profile": "https://reneskukies.de/", + "contributions": [ + "doc" + ] + } + ], + "contributorsPerLine": 7, + "skipCi": true, + "repoType": "github", + "repoHost": "https://github.com", + "projectName": "UnfoldMakie.jl", + "projectOwner": "unfoldtoolbox" +} diff --git a/Project.toml b/Project.toml index f8eec9edf..4125c9079 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "UnfoldMakie" uuid = "69a5ce3b-64fb-4f22-ae69-36dd4416af2a" -authors = ["Vladimir Mikheev", "Daniel Baumgartner", "Sören Döring", "Niklas Gärtner","Furkan Lokman","Benedikt Ehinger"] +authors = ["Vladimir Mikheev", "Daniel Baumgartner", "Sören Döring", "Niklas Gärtner", "Furkan Lokman", "Benedikt Ehinger"] version = "0.3.6" [deps] @@ -41,10 +41,10 @@ DataFrames = "1" DataStructures = "0.18" DocStringExtensions = "0.9" GeometryBasics = "0.4" -GridLayoutBase = "0.9" +GridLayoutBase = "0.9, 0.10" ImageFiltering = "0.7" LinearAlgebra = "1" -Makie = "0.17, 0.18, 0.19" +Makie = "0.17, 0.18, 0.19, 0.20" PyMNE = "0.2" SparseArrays = "1" StaticArrays = "1" diff --git a/README.md b/README.md index 29c21fc9c..e0b40038f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ # ![UnfoldMakie - Advanced EEG and ERP Plotting](https://github.com/unfoldtoolbox/UnfoldMakie.jl/assets/57703446/26b770b3-afa0-4652-b654-82d2f737f42f) + +[![All Contributors](https://img.shields.io/badge/all_contributors-8-orange.svg?style=flat-square)](#contributors-) + [![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://unfoldtoolbox.github.io/UnfoldMakie.jl/dev) @@ -99,14 +102,31 @@ If you make use of theses visualizations, please cite: [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.6531996.svg)](https://doi.org/10.5281/zenodo.6531996) -## Contributors (alphabetically) - -- **Daniel Baumgartner** -- **Benedikt Ehinger** -- **Sören Döring** -- **Niklas Gärtner** -- **Furkan Lokman** -- **Vladimir Mikheev** +## Contributors + + + + + + + + + + + + + + + + + + +
Benedikt Ehinger
Benedikt Ehinger

🐛 💻 📖 🤔 🚇 🚧 💬 👀 ⚠️
Quantum
Quantum

💻 📖
Vladimir Mikheev
Vladimir Mikheev

🐛 💻 📖 🤔 🚧 👀 ⚠️
NiklasMGaertner
NiklasMGaertner

💻 📖
SorenDoring
SorenDoring

💻 📖
lokmanfl
lokmanfl

💻 📖
Judith Schepers
Judith Schepers

🐛 🤔 📖
René Skukies
René Skukies

📖
+ + + + + ## Acknowledgements diff --git a/docs/example_data.jl b/docs/example_data.jl index 2cc0d5e09..92106a3e1 100644 --- a/docs/example_data.jl +++ b/docs/example_data.jl @@ -7,60 +7,96 @@ type == "TopoPlots.jl"(default) Returns tidy DataFrame with two conditions, 64 channels and 800ms of data. This is an average over many subjects. """ -function example_data(example="TopoPlots.jl") +function example_data(example = "TopoPlots.jl") - if example == "UnfoldLinearModel" - # load and generate a simulated Unfold Design - data,evts = UnfoldSim.predef_eeg(;noiselevel=10,return_epoched=true) - data = reshape(data,1,size(data)...) - f = @formula 0~1+condition+continuous - # generate ModelStruct - se_solver =(x,y)->Unfold.solver_default(x,y,stderror=true) - return fit(UnfoldModel,(Dict(Any=>(f,range(0,length=size(data,2),step=1/100)))) ,evts,data;solver=se_solver) - elseif example == "UnfoldLinearModelMultiChannel" - # load and generate a simulated Unfold Design - cAll = DataFrame() - sfreq = 100 - for ch = 1:5 - data,evts = UnfoldSim.predef_eeg(;p1 = (p100(;sfreq=sfreq), @formula(0~1),[5],Dict()), - - n1 = (n170(;sfreq=sfreq), @formula(0~1+condition),[5,-ch*0.5],Dict()), - p3 = (p300(;sfreq=sfreq), @formula(0~1+continuous),[ch,1],Dict()), - return_epoched=true) - data = reshape(data,1,size(data)...) - f = @formula 0~1+condition+continuous - # generate ModelStruct - - m= fit(UnfoldModel,(Dict(Any=>(f,range(0,length=size(data,2),step=1/100)))) ,evts,data) - d = coeftable(m) - d.channel .= ch - cAll = append!(cAll,d) - end - return cAll + if example == "UnfoldLinearModel" + # load and generate a simulated Unfold Design + data, evts = UnfoldSim.predef_eeg(; noiselevel = 10, return_epoched = true) + data = reshape(data, 1, size(data)...) + f = @formula 0 ~ 1 + condition + continuous + # generate ModelStruct + se_solver = (x, y) -> Unfold.solver_default(x, y, stderror = true) + return fit( + UnfoldModel, + (Dict(Any => (f, range(0, length = size(data, 2), step = 1 / 100)))), + evts, + data; + solver = se_solver, + ) + elseif example == "UnfoldLinearModelMultiChannel" + # load and generate a simulated Unfold Design + cAll = DataFrame() + sfreq = 100 + for ch = 1:5 + data, evts = UnfoldSim.predef_eeg(; + p1 = (p100(; sfreq = sfreq), @formula(0 ~ 1), [5], Dict()), + n1 = ( + n170(; sfreq = sfreq), + @formula(0 ~ 1 + condition), + [5, -ch * 0.5], + Dict(), + ), + p3 = (p300(; sfreq = sfreq), @formula(0 ~ 1 + continuous), [ch, 1], Dict()), + return_epoched = true, + ) + data = reshape(data, 1, size(data)...) + f = @formula 0 ~ 1 + condition + continuous + # generate ModelStruct - elseif example == "UnfoldLinearModelContinuousTime" - # load and generate a simulated Unfold Design - data,evts = UnfoldSim.predef_eeg(;) - data = reshape(data,1,size(data)...) - f = @formula 0~1+condition+continuous - basis = firbasis([0,0.5],100) - # generate ModelStruct - return fit(UnfoldModel,Dict(Any=>(f,basis)) ,evts,data) - - elseif example == "TopoPlots.jl" - data,chanlocs = TopoPlots.example_data(); - df = DataFrame(estimate=Float64[],time=Float64[],channel=Int64[],coefname=String[],topoPositions=[],se=Float64[],pval=Float64[]) - pos = TopoPlots.points2mat(chanlocs) - for ch = 1:size(data,1) - for t = 1:size(data,2) - append!(df,DataFrame(estimate=data[ch,t,1],se=data[ch,t,2],pval=data[ch,t,3],time=t,channel=ch,coefname="A",topoPositions=(pos[1,ch],pos[2,ch]))) - - - end - end - df.time = range(-0.3,0.5,step=1/500)[Int.(df.time)] - return df,chanlocs - else - error("unknown example data") - end -end \ No newline at end of file + m = fit( + UnfoldModel, + (Dict(Any => (f, range(0, length = size(data, 2), step = 1 / 100)))), + evts, + data, + ) + d = coeftable(m) + d.channel .= ch + cAll = append!(cAll, d) + end + return cAll + + elseif example == "UnfoldLinearModelContinuousTime" + # load and generate a simulated Unfold Design + data, evts = UnfoldSim.predef_eeg(;) + data = reshape(data, 1, size(data)...) + f = @formula 0 ~ 1 + condition + continuous + basis = firbasis([0, 0.5], 100) + # generate ModelStruct + return fit(UnfoldModel, Dict(Any => (f, basis)), evts, data) + + elseif example == "TopoPlots.jl" + data, chanlocs = TopoPlots.example_data() + df = DataFrame( + estimate = Float64[], + time = Float64[], + channel = Int64[], + coefname = String[], + topo_positions = [], + se = Float64[], + pval = Float64[], + ) + pos = TopoPlots.points2mat(chanlocs) + for ch = 1:size(data, 1) + for t = 1:size(data, 2) + append!( + df, + DataFrame( + estimate = data[ch, t, 1], + se = data[ch, t, 2], + pval = data[ch, t, 3], + time = t, + channel = ch, + coefname = "A", + topo_positions = (pos[1, ch], pos[2, ch]), + ), + ) + + + end + end + df.time = range(-0.3, 0.5, step = 1 / 500)[Int.(df.time)] + return df, chanlocs + else + error("unknown example data") + end +end diff --git a/docs/literate/tutorials/circTopo.jl b/docs/literate/tutorials/circTopo.jl index 39ca91d3c..3f009663d 100644 --- a/docs/literate/tutorials/circTopo.jl +++ b/docs/literate/tutorials/circTopo.jl @@ -15,18 +15,18 @@ data, pos = TopoPlots.example_data(); dat = data[:, 240, 1] df = DataFrame( :estimate => eachcol(Float64.(data[:, 100:40:300, 1])), - :circularVariable => [0, 50, 80, 120, 180, 210], + :circular_variable => [0, 50, 80, 120, 180, 210], :time => 100:40:300, ) df = flatten(df, :estimate); # # Our first plot! -# note how the plots are at the angles of circularVariable` +# note how the plots are at the angles of circular_variable` plot_circulareegtopoplot( df; positions = pos, - axis = (; label = "Sac Incoming"), - predictor = :circularVariable, + axis = (; label = "Incoming saccade"), + predictor = :circular_variable, ) @@ -37,6 +37,6 @@ plot_circulareegtopoplot( positions = pos, axis = (; label = "Time?!"), predictor = :time, - predictorBounds = [80, 320], + predictor_bounds = [80, 320], ) diff --git a/docs/literate/tutorials/erp.jl b/docs/literate/tutorials/erp.jl index 3077b7fcb..e88a08963 100644 --- a/docs/literate/tutorials/erp.jl +++ b/docs/literate/tutorials/erp.jl @@ -1,6 +1,6 @@ # ## [Line Plot Visualization](@id lp_vis) -# Here we discuss line plot visualization. +# Here we discuss ERP plot visualization. # Make sure you have looked into the [installation instructions](@ref install_instruct). # ## Include used Modules @@ -15,7 +15,7 @@ using UnfoldSim using UnfoldMakie # ## Setup -# Let's generate some data and fit a model of a 2-level categorical and a continuous predictor with interaction. +# Let's generate some data. We'll fit a model with a 2 level categorical predictor and a continuous predictor with interaction. data, evts = UnfoldSim.predef_eeg(; noiselevel = 12, return_epoched = true) data = reshape(data, (1, size(data)...)) f = @formula 0 ~ 1 + condition + continuous @@ -40,7 +40,7 @@ plot_erp(results; :stderror => true,) # `plot_erp` use a `DataFrame` as an input, the library needs to know the names of the columns used for plotting. # There are multiple default values, that are checked in that order if they exist in the `DataFrame`, a custom name can be chosen using -# `plot_erp(...;mapping=(; :y=:myEstimate)` +# `plot_erp(...; mapping=(; :y=:my_estimate)` # :x Default is `(:x, :time)`. # :y Default is `(:y, :estimate, :yhat)`. @@ -50,10 +50,11 @@ plot_erp(results; :stderror => true,) # ## key values # `plot_erp(...; =,...)`. -# - categoricalColor (boolean, true) - in case of numeric `:color` column, is color a continuous or categorical variable? -# - categoricalGroup (boolean, true) - in case of numeric `:group` column, treat `:group` as categorical variable by default -# - stderror (boolean, false) - add an error-ribbon based on the `:stderror` column -# - pvalue (see below) +# - categorical_color (boolean, true) - in case of numeric `:color` column, treat `:color` as continuous or categorical variable. +# - categorical_group (boolean, true) - in case of numeric `:group` column, treat `:group` as categorical variable by default. +# - `topolegend` (bool, `false`): add an inlay topoplot with corresponding electrodes. +# - `stderror` (bool, `false`): add an error ribbon, with lower and upper limits based on the `:stderror` column. +# - `pvalue` (Array, `[]`): show a pvalue (see below). # Using some general configurations we can pretty up the default visualization. Here we use the following configuration: @@ -61,13 +62,11 @@ plot_erp( res_effects; mapping = (; y = :yhat, color = :continuous, group = :continuous), legend = (; nbanks = 2), - layout = (; showLegend = true, legendPosition = :right), - categoricalColor = false, categoricalGroup = true, + layout = (; showLegend = true, legend_position = :right), + categorical_color = false, categorical_group = true, ) - - # In the following we will use this "pretty" line plot as a basis for looking into configuration options. # ## pvalue (array) @@ -77,11 +76,11 @@ plot_erp( # # Is an array of p-values. If array not empty, plot shows colored lines under the plot representing the p-values. # Default is `[]` (an empty array). -# Shown below is an example in which `pvalue` are given: +# Below is an example in which `pvalue` are given: # pvals = DataFrame( # from=[0.1,0.3], # to=[0.5,0.7], -# coefname=["(Intercept)","condition: face"] # if coefname not specified, line should be black +# coefname=["(Intercept)", "condition: face"] # if coefname not specified, line should be black # ) # # plot_erp(results; :pvalue=>pvals) diff --git a/docs/make.jl b/docs/make.jl index 9b42fed8f..1844d78a4 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -22,20 +22,20 @@ for subfolder ∈ ["explanations", "HowTo", "tutorials", "reference"] end -DocMeta.setdocmeta!(UnfoldMakie, :DocTestSetup, :(using UnfoldMakie); recursive=true) +DocMeta.setdocmeta!(UnfoldMakie, :DocTestSetup, :(using UnfoldMakie); recursive = true) makedocs(; - modules=[UnfoldMakie], - authors="Benedikt Ehinger, Vladimir Mikheev, Daniel Baumgartner, Niklas Gärtner, Sören Döring", - repo="https://github.com/unfoldtoolbox/UnfoldMakie.jl/blob/{commit}{path}#{line}", - sitename="UnfoldMakie.jl", - warnonly = :cross_references, - format=Documenter.HTML(; - prettyurls=get(ENV, "CI", "false") == "true", - canonical="https://unfoldtoolbox.github.io/UnfoldMakie.jl", - assets=String[] + modules = [UnfoldMakie], + authors = "Benedikt Ehinger, Vladimir Mikheev, Daniel Baumgartner, Niklas Gärtner, Sören Döring", + repo = "https://github.com/unfoldtoolbox/UnfoldMakie.jl/blob/{commit}{path}#{line}", + sitename = "UnfoldMakie.jl", + warnonly = :cross_references, + format = Documenter.HTML(; + prettyurls = get(ENV, "CI", "false") == "true", + canonical = "https://unfoldtoolbox.github.io/UnfoldMakie.jl", + assets = String[], ), - pages=[ + pages = [ "UnfoldMakie Documentation" => "index.md", "Visualizations-Types" => [ "ERP plot" => "generated/tutorials/erp.md", @@ -55,16 +55,11 @@ makedocs(; "Show out of Bounds Label" => "how_to/show_oob_labels.md", ], "Reference" => [ - "Convert 3D positions / montages to 2D layouts" => "generated/reference/positions.md" - + "Convert 3D positions / montages to 2D layouts" => "generated/reference/positions.md", ], "API" => "api.md", "Utilities" => "helper.md", ], - ) -deploydocs(; - repo="github.com/unfoldtoolbox/UnfoldMakie.jl", - devbranch="main" -) +deploydocs(; repo = "github.com/unfoldtoolbox/UnfoldMakie.jl", devbranch = "main") diff --git a/docs/run_liveserver.jl b/docs/run_liveserver.jl index 352fd6a33..85879e690 100644 --- a/docs/run_liveserver.jl +++ b/docs/run_liveserver.jl @@ -1,3 +1,7 @@ using LiveServer -servedocs(skip_dir=joinpath("src","generated"),literate_dir=joinpath("literate"),literate=joinpath("literate"),foldername=".") - +servedocs( + skip_dir = joinpath("src", "generated"), + literate_dir = joinpath("literate"), + literate = joinpath("literate"), + foldername = ".", +) diff --git a/docs/src/how_to/mult_vis_in_fig.md b/docs/src/how_to/mult_vis_in_fig.md index b740d02df..1df4c4f51 100644 --- a/docs/src/how_to/mult_vis_in_fig.md +++ b/docs/src/how_to/mult_vis_in_fig.md @@ -26,7 +26,7 @@ This section discusses how users can incorporate multiple plots into a single fi By using the !-version of the plotting function and inserting a grid position instead of an entire figure, we can create multiple coordinated views. -We start by creating a figure with Makie.Figure. +We will start by creating a figure with Makie.Figure. `f = Figure()` @@ -60,8 +60,8 @@ pvals = DataFrame( coefname=["(Intercept)", "category: face"] ) plot_erp!(f[2, 1:2], results, - categoricalColor=false, - categoricalGroup=false, + categorical_color=false, + categorical_group=false, pvalue=pvals, stderror=true) @@ -73,16 +73,17 @@ plot_topoplotseries!(f[4, 1:3], d_topo, 0.1; positions=positions, mapping=(; lab res_effects = effects(Dict(:continuous => -5:0.5:5), uf_deconv) -plot_erp!(f[2, 4:5], res_effects; categoricalColor=false, categoricalGroup=true, +plot_erp!(f[2, 4:5], res_effects; categorical_color=false, categorical_group=true, mapping=(; y=:yhat, color=:continuous, group=:continuous), legend=(; nbanks=2), - layout=(; showLegend=true, legendPosition=:right)) + layout=(; show_legend=true, legend_position=:right)) -plot_parallelcoordinates!(f[3, 2:3], uf_5chan, [1, 2, 3, 4, 5]; mapping=(; color=:coefname), layout=(; legendPosition=:bottom)) +plot_parallelcoordinates!(f[3, 2:3], uf_5chan, [1, 2, 3, 4, 5]; mapping=(; color=:coefname), + layout=(; legend_position=:bottom)) plot_erpimage!(f[1, 4:5], times, d_singletrial) plot_circulareegtopoplot!(f[3:4, 4:5], d_topo[in.(d_topo.time, Ref(-0.3:0.1:0.5)), :]; - positions=positions, predictor=:time, predictorBounds=[-0.3, 0.5]) + positions=positions, predictor=:time, predictor_bounds=[-0.3, 0.5]) f ``` diff --git a/docs/src/how_to/position2color.md b/docs/src/how_to/position2color.md index 44daa3fad..2f51b5c6b 100644 --- a/docs/src/how_to/position2color.md +++ b/docs/src/how_to/position2color.md @@ -21,17 +21,20 @@ We can switch the colorscale of the position-map, by giving a function that maps ### Similar to MNE ```@example main -plot_butterfly(results; positions=positions, extra=(; topoPositionToColorFunction = pos -> UnfoldMakie.posToColorRGB(pos))) +plot_butterfly(results; + positions=positions, + topopositions_to_color = pos -> UnfoldMakie.posToColorRGB(pos) +) ``` ### HSV-Space ```@example main -plot_butterfly(results; positions=positions, extra=(; topoPositionToColorFunction=UnfoldMakie.posToColorHSV)) +plot_butterfly(results; positions=positions, topopositions_to_color=UnfoldMakie.posToColorHSV) ``` ### Uniform Color To highlight the flexibility, we can also make all lines `gray`, or any other arbitrary color, or function of electrode-`position`. + ```@example main -using Colors -plot_butterfly(results; positions=positions, extra=(; topoPositionToColorFunction = x -> Colors.RGB(0.5))) +plot_butterfly(results; positions=positions, topopositions_to_color = x -> Colors.RGB(0.5)) ``` \ No newline at end of file diff --git a/docs/src/tutorials/butterfly.md b/docs/src/tutorials/butterfly.md index 435876bda..0bb090186 100644 --- a/docs/src/tutorials/butterfly.md +++ b/docs/src/tutorials/butterfly.md @@ -37,7 +37,7 @@ plot_butterfly(df; positions=pos) ## Column Mappings for Butterfly Plots -Since butterfly plots use a `DataFrame` as input, the library needs to know the names of the columns used for plotting. You can set these mapping values by calling `plot_butterfly(...; mapping=(; :x=:time,))`, that is, by specifying a `NamedTuple` (note the `;` right after the opening parentheses). +Since butterfly plots use a `DataFrame` as input, the library needs to know the names of the columns used for plotting. You can set these mapping values by calling `plot_butterfly(...; mapping=(; :x=:time))`, that is, by specifying a `NamedTuple` (note the `;` right after the opening parentheses). While there are several default values that will be checked in that order if they exist in the `DataFrame`, a custom name may need to be chosen: @@ -54,21 +54,17 @@ Default is `(:labels, :label, :topoLabels, :sensor, :nothing)` ## Configurations for Butterfly Plots - Here we look into possible options for configuring the butterfly plot visualization using `(...; =, ...)`. -This is the list of unique configuration (key values): - - -- topoLegend (boolean) - -### topoLegend (boolean) -Indicating whether the topo legend is displayed. -Default is `true`. - -For more general options look into the `Plot Configuration` section of the documentation. +## key values +- `butterfly` (bool, `true`): create a butterfly plot. +- `topolegend` (bool, `true`): show an inlay topoplot with corresponding electrodes. +- `topomarkersize` (Real, `10`): change the size of the markers, topoplot-inlay electrodes. +- `topowidth` (Real, `0.25`): change the size of the inlay topoplot width. +- `topoheigth` (Real, `0.25`): change the size of the inlay topoplot height. +- `topopositions_to_color` (function, ´x -> posToColorRomaO(x)´). -Since the configurations for line plots can be applied to butterfly plots as well. -[Here](@ref lp_vis) you can find the configurations for line plots, +Since the configurations for ERP plots can be applied to butterfly plots as well. +[Here](@ref lp_vis) you can find the configurations for ERP plots. diff --git a/docs/src/tutorials/designmatrix.md b/docs/src/tutorials/designmatrix.md index 155741133..cabc46d63 100644 --- a/docs/src/tutorials/designmatrix.md +++ b/docs/src/tutorials/designmatrix.md @@ -1,6 +1,6 @@ # [Designmatrix Visualization](@id dm_vis) -Here we discuss designmatrix visualization. +Here we discuss design matrix visualization. Make sure you have looked into the [installation instructions](@ref install_instruct) section. ## Include used Modules @@ -31,20 +31,18 @@ plot_designmatrix(designmatrix(uf)) # kwargs `plot_designmatrix(...; ...)`. -- sortData (boolean,false) - Indicating whether the data is sorted; using sortslices() of Base Julia. +- `sort_data` (bool, `true`): indicates whether the data is sorted; using sortslices() of Base Julia. - -In order to make the designmatrix easier to read, you may want to sort it. +To make the design matrix easier to read, you may want to sort it. ``` plot_designmatrix(designmatrix(uf); sortData=true) ``` -- standardizeData (boolean, false) - Indicating whether the data is standardized, mapping the values between 0 and 1. -- xTicks (number, nothing) - -Indicating the number of labels on the x-axis. Behavior if specified in configuration: - - xTicks = 0: no labels are placed. - - xTicks = 1: first possible label is placed. - - xTicks = 2: first and last possible labels are placed. - - 2 < xTicks < number of labels: xTicks-2 labels are placed between the first and last. - - xTicks ≥ number of labels: all labels are placed. \ No newline at end of file +- `standardize_data` (bool,`true`): indicates whether the data is standardized by pointwise division of the data with its sampled standard deviation. +- `sort_data` (bool, `true`): indicates whether the data is sorted; using sortslices() of Base Julia. +- `xticks` (`nothing`): returns the number of labels on the x-axis. Behavior is set in the configuration: + - xticks = 0: no labels are placed. + - xticks = 1: first possible label is placed. + - xticks = 2: first and last possible labels are placed. + - 2 < xticks < `number of labels`: equally distribute the labels. + - xticks ≥ `number of labels`: all labels are placed. diff --git a/docs/src/tutorials/erpimage.md b/docs/src/tutorials/erpimage.md index 6f7e034ad..18dcb15da 100644 --- a/docs/src/tutorials/erpimage.md +++ b/docs/src/tutorials/erpimage.md @@ -14,7 +14,7 @@ include("../../example_data.jl") ``` -## Plot ERP Images +## Plot ERP image The following code will result in the default configuration. ```@example main @@ -22,21 +22,37 @@ data, evts = UnfoldSim.predef_eeg(; noiselevel=10, return_epoched=true) plot_erpimage(data) ``` -## Column Mappings for ERP Images +## Column Mappings for ERP image Since ERP images use a `Matrix` as an input, the library does not need any informations about the mapping. -- erpBlur (number, 10) - Is a number indicating how much blur is applied to the image; using Gaussian blur of the ImageFiltering module. Negative values deactivate the blur. - -- sortvalues - Indicating whether the data is sorted; using sortperm() of Base Julia -(sortperm() computes a permutation of the array's indices that puts the array into sorted order). - -- meanPlot (bool, false) - Indicating whether the plot should add a line plot below the ERP image, showing the mean of the data. If limits are set in the axis values both plots will be aligned. +- `erpblur` (Number, `10`): number indicating how much blur is applied to the image; using Gaussian blur of the ImageFiltering module. +Non-Positive values deactivate the blur. +- `sortvalues` (bool, `false`): parameter over which plot will be sorted. Using sortperm() of Base Julia. + - sortperm() computes a permutation of the array's indices that puts the array into sorted order. +- `meanplot` (bool, `false`): Indicating whether the plot should add a line plot below the ERP image, showing the mean of the data. ```@example main plot_erpimage(data; - meanPlot = true, + meanplot = true, colorbar = (label = "Voltage [µV]",), visual = (colormap = :viridis, colorrange = (-40, 40))) ``` + +## Sorted ERP image + +First, generate a data. Second, specify the necessary sorting parameter. + +```@example main + dat, evts = UnfoldSim.predef_eeg(; + onset=LogNormalOnset(μ=3.5, σ=0.4), + noiselevel=5 + ) + dat_e, times = Unfold.epoch(dat, evts, [-0.1,1], 100) + evts, dat_e = Unfold.dropMissingEpochs(evts, dat_e) + evts.Δlatency = diff(vcat(evts.latency, 0)) + dat_e = dat_e[1,:,:] + + plot_erpimage(times, dat_e; sortvalues=evts.Δlatency) +``` \ No newline at end of file diff --git a/docs/src/tutorials/topoplotseries.md b/docs/src/tutorials/topoplotseries.md index ff88fe472..03ab94302 100644 --- a/docs/src/tutorials/topoplotseries.md +++ b/docs/src/tutorials/topoplotseries.md @@ -1,4 +1,4 @@ -# [Topo Plot SeriesVisualization](@id tpseries_vis) +# [Topoplot Series Visualization](@id tpseries_vis) ## Include used Modules @@ -10,9 +10,9 @@ using DataFrames using CairoMakie using TopoPlots ``` -## Plot Topo Plots Series +## Plot Topoplot Series -### Giving the Data +### Example data In case you do not already have data, you can get example data from the `TopoPlots` module. You can do it like this: @@ -26,11 +26,25 @@ nothing #hide Δbin = 80 plot_topoplotseries(df, Δbin; positions = positions) ``` +### Arguments usage -Without colorbar: +- `f::Union{GridPosition, GridLayout, Figure}`: Figure or GridPosition that the plot should be drawn into. +- `data::DataFrame`: DataFrame with data, needs a `time` column. +- `Δbin::Real`: A number for how large one time bin should be. Δbin is in units of the `data.time` column. + +### Key arguments +- `combinefun` (default: `mean`) - can be used to specify how the samples within `Δbin` are combined. +- `rasterize_heatmaps` (default: `true`) - enforce rasterization of the plot heatmap when saving in svg format. + This has the benefit that all lines/points are vectors, except the interpolated heatmap. + This is typically what you want, otherwise you get ~500x500 vectors per topoplot, which makes everything super slow. +- `col_labels`, `row_labels` - shows column and row labels. +- labels (default: `nothing`) - . +- positions (default: `nothing`) - . + +Disabling colorbar: ```@example main -plot_topoplotseries(df, Δbin; positions=positions, layout = (; useColorbar=false)) +plot_topoplotseries(df, Δbin; positions=positions, layout = (; use_colorbar=false)) ``` ### Positions diff --git a/src/docstringtemplate.jl b/src/docstringtemplate.jl index 62999f799..aea66ab9d 100644 --- a/src/docstringtemplate.jl +++ b/src/docstringtemplate.jl @@ -36,16 +36,14 @@ function _docstring(cfgsymb::Symbol) return """## Shared plot configuration options The shared plot options can be used as follows: - `type=(;key=value,...))` - for example `plot_x(...,layout=(showLegend=true,legendPosition=:right))`. Multiple defaults will be cycled until match. + `type=(; key=value,...))` - for example `plot_x(..., layout=(show_legend=true, legend_position=:right))`. + Multiple defaults will be cycled until match. $(out) """ end - - - """ $(TYPEDSIGNATURES) $(_docstring(:erp)) diff --git a/src/layout_helper.jl b/src/layout_helper.jl index 2415c88b2..fe21a1540 100644 --- a/src/layout_helper.jl +++ b/src/layout_helper.jl @@ -4,25 +4,25 @@ function applyLayoutSettings!(config::PlotConfig; fig=nothing, hm=nothing, ax = current_axis() end - if (config.layout.showLegend) + if (config.layout.show_legend) if isnothing(fig) @error "Legend needs figure parameter" else - # set f[] position depending on legendPosition - legendPosition = config.layout.legendPosition == :right ? fig[1:plotArea[1], plotArea[2]+1] : fig[plotArea[1]+1, 1:plotArea[2]] + # set f[] position depending on legend_position + legend_position = config.layout.legend_position == :right ? fig[1:plotArea[1], plotArea[2]+1] : fig[plotArea[1]+1, 1:plotArea[2]] if isnothing(drawing) - if (config.layout.useColorbar) + if (config.layout.use_colorbar) if isnothing(hm) - Colorbar(legendPosition; colormap=config.visual.colormap, config.colorbar...) + Colorbar(legend_position; colormap=config.visual.colormap, config.colorbar...) else - Colorbar(legendPosition, hm; config.colorbar...) + Colorbar(legend_position, hm; config.colorbar...) end else - Legend(legendPosition, ax; config.legend...) + Legend(legend_position, ax; config.legend...) end else - legend!(legendPosition, drawing; config.legend...) - colorbar!(legendPosition, drawing; config.colorbar...) + legend!(legend_position, drawing; config.legend...) + colorbar!(legend_position, drawing; config.colorbar...) end end end diff --git a/src/plot_channelimage.jl b/src/plot_channelimage.jl index 64ee5cbc7..70696177f 100644 --- a/src/plot_channelimage.jl +++ b/src/plot_channelimage.jl @@ -12,15 +12,6 @@ function plot_channelimage!( ch_names::Vector{String}; kwargs..., ) - #= raw = PyMNE.io.read_raw_eeglab(p, preload=true) - dat_e = load("data/dat_e.jld2")["1"] - mon = PyMNE.channels.make_standard_montage("standard_1020") - raw.set_channel_types(Dict("HEOG_left"=>"eog","HEOG_right"=>"eog","VEOG_lower"=>"eog")) - raw.set_montage(mon,match_case=false) - pos = PyMNE.channels.make_eeg_layout(raw.info).pos - pos = pyconvert(Array,pos) - pos = [Point2f(pos[k,1], pos[k,2]) for k in 1:size(pos,1)] - ch_names = pyconvert(Array, raw.ch_names) =# x = [i[1] for i in position] y = [i[2] for i in position] @@ -32,7 +23,6 @@ function plot_channelimage!( a = sort!(DataFrame(d), [:2, :1], rev = [true, false]) b = a[!, :4] c = a[!, :3] - #c = pyconvert(Array, c) c = [string(x) for x in c] ix = range(-0.3, 1.2, length = size(data, 2)) diff --git a/src/plot_circulareegtopoplot.jl b/src/plot_circulareegtopoplot.jl index c3291f899..2a303e552 100644 --- a/src/plot_circulareegtopoplot.jl +++ b/src/plot_circulareegtopoplot.jl @@ -1,19 +1,19 @@ """ - plot_circulareegtopoplot(plotData::DataFrame; kwargs...) - plot_circulareegtopoplot!(figlike, plotData::DataFrame; kwargs...) + plot_circulareegtopoplot(data::DataFrame; kwargs...) + plot_circulareegtopoplot!(f, data::DataFrame; kwargs...) Plot a circular EEG topoplot. ## Arguments: -- `figlike::Union{GridPosition, GridLayout, Figure}`: Figure or GridPosition that the plot should be drawn into -- `plotData::DataFrame`: Dataframe with keys for data (looks for `:y,:yhat, :estimate`, and :position (looks for `:pos, :positions, :position`), -- `predictor` (optional; default :predictor) the circular predictor value, defines position of topoplot, is mapped around `predictorBounds` -- `predictorBounds`: Default: `[0,360]` - The bounds of the predictor. This is relevant for the axis labels. -- `centerlabel`: default "", the text in the center of the cricle -- `positions` (nothing) - positions for the [`plot_topoplot`](@Ref) -- `labels` (nothing) - labels for the [`plot_topoplot`](@Ref) +- `f::Union{GridPosition, GridLayout, Figure}`: Figure, GridLayout or GridPosition that the plot should be drawn into +- `data::DataFrame`: DataFrame with keys for data (looks for `:y, :yhat, :estimate`), and :position (looks for `:pos, :position, :positions`), +- `predictor` (optional; default: predictor): the circular predictor value, defines position of topoplot, is mapped around `predictor_bounds` +- `predictor_bounds` (default: `[0,360]`): the bounds of the predictor. This is relevant for the axis labels. +- `positions` (default: nothing): positions for the [`plot_topoplot`](@Ref) +- `center_label` (default: ""): the text in the center of the cricle +- `labels` (default: nothing): labels for the [`plot_topoplot`](@Ref) -- `kwargs...`: Additional styling behavior, see below. +- `kwargs...`: additional styling behavior, see below. $(_docstring(:circeegtopo)) @@ -24,47 +24,47 @@ $(_docstring(:circeegtopo)) A figure containing the circular topoplot at given layout position """ -plot_circulareegtopoplot(plotData::DataFrame; kwargs...) = - plot_circulareegtopoplot!(Figure(), plotData; kwargs...) -plot_circulareegtopoplot!(f, plotData::DataFrame; kwargs...) = - plot_circulareegtopoplot!(f, plotData; kwargs...) +plot_circulareegtopoplot(data::DataFrame; kwargs...) = + plot_circulareegtopoplot!(Figure(), data; kwargs...) +plot_circulareegtopoplot!(f, data::DataFrame; kwargs...) = + plot_circulareegtopoplot!(f, data; kwargs...) function plot_circulareegtopoplot!( f::Union{GridPosition,GridLayout,Figure}, - plotData::DataFrame; + data::DataFrame; predictor = :predictor, + predictor_bounds = [0, 360], positions = nothing, labels = nothing, - centerlabel = "", - predictorBounds = [0, 360], + center_label = "", kwargs..., ) config = PlotConfig(:circeegtopo) config_kwargs!(config; kwargs...) - config.mapping = resolveMappings(plotData, config.mapping) + config.mapping = resolveMappings(data, config.mapping) positions = getTopoPositions(; positions = positions, labels = labels) # moving the values of the predictor to a different array to perform boolean queries on them - predictorValues = plotData[:, predictor] + predictorValues = data[:, predictor] - if (length(predictorBounds) != 2) - error("predictorBounds needs exactly two values") + if (length(predictor_bounds) != 2) + error("predictor_bounds needs exactly two values") end - if (predictorBounds[1] >= predictorBounds[2]) + if (predictor_bounds[1] >= predictor_bounds[2]) error( - "predictorBounds[1] needs to be smaller than predictorBounds[2]", + "predictor_bounds[1] needs to be smaller than predictor_bounds[2]", ) end if ( - (length(predictorValues[predictorValues.predictorBounds[2]]) != 0) + (length(predictorValues[predictorValues.predictor_bounds[2]]) != 0) ) error( - "all values in the plotData's effect column have to be within the predictorBounds range", + "all values in the data's effect column have to be within the predictor_bounds range", ) end if (all(predictorValues .<= 2 * pi)) - @warn "insert the predictor values in degrees instead of radian, or change predictorBounds" + @warn "insert the predictor values in degrees instead of radian, or change predictor_bounds" end ax = Axis(f[1, 1]; aspect = 1) @@ -72,17 +72,17 @@ function plot_circulareegtopoplot!( hidedecorations!(ax) hidespines!(ax) - plotCircularAxis!(ax, predictorBounds, centerlabel) + plotCircularAxis!(ax, predictor_bounds, center_label) limits!(ax, -3.5, 3.5, -3.5, 3.5) - min, max = calculateGlobalMaxValues(plotData[:, config.mapping.y], predictorValues) + min, max = calculateGlobalMaxValues(data[:, config.mapping.y], predictorValues) positions = getTopoPositions(; positions = positions, labels = labels) plotTopoPlots!( ax, - plotData[:, config.mapping.y], + data[:, config.mapping.y], positions, predictorValues, - predictorBounds, + predictor_bounds, min, max, ) @@ -104,10 +104,10 @@ function plot_circulareegtopoplot!( return f end -function calculateGlobalMaxValues(plotData, predictor) +function calculateGlobalMaxValues(data, predictor) x = combine( - groupby(DataFrame(:e => plotData, :p => predictor), :p), + groupby(DataFrame(:e => data, :p => predictor), :p), :e => (x -> maximum(abs.(quantile!(x, [0.01, 0.99])))) => :localMaxVal, ) @@ -116,7 +116,7 @@ function calculateGlobalMaxValues(plotData, predictor) return (-globalMaxVal, globalMaxVal) end -function plotCircularAxis!(ax, predictorBounds, label) +function plotCircularAxis!(ax, predictor_bounds, label) # the axis position is always the middle of the # screen (means it uses the GridLayout's full size) #circleAxis = Axis(f,aspect = 1)#typeof(f) == Figure ? Axis(f[1:f.layout.size[1],1:f.layout.size[2]], aspect = 1, backgroundcolor = bgcolor) : Axis(f[1,1], aspect = 1, backgroundcolor = bgcolor) @@ -148,7 +148,7 @@ function plotCircularAxis!(ax, predictorBounds, label) ) text!( circlepoints_labels, - text = calculateAxisLabels(predictorBounds), + text = calculateAxisLabels(predictor_bounds), align = (:center, :center), #textsize = round(minsize*0.03) ) @@ -157,12 +157,12 @@ function plotCircularAxis!(ax, predictorBounds, label) end # four labels around the circle, middle values are the 0.25, 0.5, and 0.75 quantiles -function calculateAxisLabels(predictorBounds) - nonboundlabels = quantile(predictorBounds, [0.25, 0.5, 0.75]) +function calculateAxisLabels(predictor_bounds) + nonboundlabels = quantile(predictor_bounds, [0.25, 0.5, 0.75]) # third label is on the left and it tends to cover the circle # so added some blank spaces to tackle that return [ - string(trunc(Int, predictorBounds[1])), + string(trunc(Int, predictor_bounds[1])), string(trunc(Int, nonboundlabels[1])), string(trunc(Int, nonboundlabels[2]), " "), string(trunc(Int, nonboundlabels[3])), @@ -174,7 +174,7 @@ function plotTopoPlots!( data, positions, predictorValues, - predictorBounds, + predictor_bounds, globalmin, globalmax, ) @@ -183,7 +183,7 @@ function plotTopoPlots!( gp = groupby(df, :p) for g in gp - bbox = calculateBBox([0, 0], [1, 1], g.p[1], predictorBounds) + bbox = calculateBBox([0, 0], [1, 1], g.p[1], predictor_bounds) # convet BBox to rect rect = ( diff --git a/src/plot_designmatrix.jl b/src/plot_designmatrix.jl index ed0ff3805..50d761fc0 100644 --- a/src/plot_designmatrix.jl +++ b/src/plot_designmatrix.jl @@ -1,73 +1,70 @@ """ - plot_designmatrix!(f::Union{GridPosition, GridLayout, Figure}, plotData::Unfold.DesignMatrix; kwargs...) - plot_designmatrix(plotData::Unfold.DesignMatrix; kwargs...) + plot_designmatrix!(f::Union{GridPosition, GridLayout, Figure}, data::Unfold.DesignMatrix; kwargs...) + plot_designmatrix(data::Unfold.DesignMatrix; kwargs...) Plot a designmatrix. ## Arguments: -- `f::Union{GridPosition, GridLayout, Figure}`: Figure or GridPosition (e.g. f[2, 3]) that the plot should be drawn into. New axis is created. -- `plotData::Unfold.DesignMatrix`: Data for the plot visualization. +- `f::Union{GridPosition, GridLayout, Figure}`: Figure or GridPosition (e.g. f[2, 3]) in which the plot will be placed into. A new axis is created. +- `data::Unfold.DesignMatrix`: data for the plot visualization. ## kwargs -- `standardizeData`: (bool,`true`) - Indicating whether the data is standardized by pointwise division of the data with its sampled standard deviation. -- `sortData`: (bool, `true`) - Indicating whether the data is sorted; using sortslices() of Base Julia. -- `xTicks`: (`nothing`) - -Indicating the number of labels on the x-axis. -Behavior if specified in configuration: -- xTicks = 0: no labels are placed. -- xTicks = 1: first possible label is placed. -- xTicks = 2: first and last possible labels are placed. -- 2 < xTicks < `number of labels`: Equally distribute the labels. -- xTicks ≥ `number of labels`: all labels are placed. +- `standardize_data` (bool,`true`): indicates whether the data is standardized by pointwise division of the data with its sampled standard deviation. +- `sort_data` (bool, `true`): indicates whether the data is sorted; using sortslices() of Base Julia. +- `xticks` (`nothing`): returns the number of labels on the x-axis. Behavior is set in the configuration: + - `xticks` = 0: no labels are placed. + - `xticks` = 1: first possible label is placed. + - `xticks` = 2: first and last possible labels are placed. + - 2 < `xticks` < `number of labels`: equally distribute the labels. + - `xticks` ≥ `number of labels`: all labels are placed. $(_docstring(:designmat)) ## Return Value: A figure displaying the designmatrix. """ -plot_designmatrix(plotData::Unfold.DesignMatrix; kwargs...) = - plot_designmatrix!(Figure(), plotData; kwargs...) +plot_designmatrix(data::Unfold.DesignMatrix; kwargs...) = + plot_designmatrix!(Figure(), data; kwargs...) function plot_designmatrix!( f::Union{GridPosition,GridLayout,Figure}, - plotData::Unfold.DesignMatrix; - xTicks = nothing, - sortData = false, - standardizeData = false, + data::Unfold.DesignMatrix; + xticks = nothing, + sort_data = false, + standardize_data = false, kwargs..., ) config = PlotConfig(:designmat) config_kwargs!(config; kwargs...) - designmat = Unfold.get_Xs(plotData) - if standardizeData + designmat = Unfold.get_Xs(data) + if standardize_data designmat = designmat ./ std(designmat, dims = 1) designmat[isinf.(designmat)] .= 1.0 end if isa(designmat, SparseMatrixCSC) - if sortData - @warn "Sorting does not make sense for timeexpanded designmatrices. sortData has been set to `false`" + if sort_data + @warn "Sorting does not make sense for time-expanded designmatrices. sort_data has been set to `false`" - sortData = false + sort_data = false end designmat = Matrix(designmat[end÷2-2000:end÷2+2000, :]) end - if sortData + if sort_data designmat = Base.sortslices(designmat, dims = 1) end - labels = Unfold.get_coefnames(plotData) + labels = Unfold.get_coefnames(data) lLength = length(labels) - # only change xTicks if we want less then all - if (xTicks !== nothing && xTicks < lLength) - @assert(xTicks >= 0, "xTicks shouldn't be negative") - # sections between xTicks - sectionSize = (lLength - 2) / (xTicks - 1) + # only change xticks if we want less then all + if (xticks !== nothing && xticks < lLength) + @assert(xticks >= 0, "xticks shouldn't be negative") + # sections between xticks + sectionSize = (lLength - 2) / (xticks - 1) newLabels = [] # first tick. Empty if 0 ticks - if xTicks >= 1 + if xticks >= 1 push!(newLabels, labels[1]) else push!(newLabels, "") @@ -76,7 +73,7 @@ function plot_designmatrix!( # fill in ticks in the middle for i = 1:(lLength-2) # checks if we're at the end of a section, but NO tick on the very last section - if i % sectionSize < 1 && i < ((xTicks - 1) * sectionSize) + if i % sectionSize < 1 && i < ((xticks - 1) * sectionSize) push!(newLabels, labels[i+1]) else push!(newLabels, "") @@ -84,7 +81,7 @@ function plot_designmatrix!( end # last tick at the end - if xTicks >= 2 + if xticks >= 2 push!(newLabels, labels[lLength-1]) else push!(newLabels, "") diff --git a/src/plot_erp.jl b/src/plot_erp.jl index a249e6e74..317b9fb79 100644 --- a/src/plot_erp.jl +++ b/src/plot_erp.jl @@ -2,24 +2,25 @@ using DataFrames using TopoPlots using LinearAlgebra """ - plot_erp!(f::Union{GridPosition, GridLayout, Figure}, plotData::DataFrame; kwargs...) - plot_erp(plotData::DataFrame; kwargs...) + plot_erp!(f::Union{GridPosition, GridLayout, Figure}, plot_data::DataFrame; kwargs...) + plot_erp(plot_data::DataFrame; kwargs...) Plot an ERP plot. ## Arguments: -- `f::Union{GridPosition, GridLayout, Figure}`: Figure or GridPosition that the plot should be drawn into -- `plotData::DataFrame`: Data for the line plot visualization. -- `kwargs...`: Additional styling behavior. Often used: `plot_erp(df; mapping=(; color=:coefname, col=:conditionA))` +- `f::Union{GridPosition, GridLayout, Figure}`: Figure, GridLayout or GridPosition that the plot should be drawn into. +- `plot_data::DataFrame`: Data for the line plot visualization. +- `kwargs...`: Additional styling behavior. Often used: `plot_erp(df; mapping=(; color=:coefname, col=:conditionA))`. ## kwargs (...; ...): -- `categoricalColor` (bool, `true`) - Indicates whether the column referenced in mapping.color should be used nonnumerically. -- `categoricalGroup` (bool, `true`) - Indicates whether the column referenced in mapping.group should be used nonnumerically. -- `topoLegend` (bool, `false`) - Indicating whether a topo plot is used as a legend. -- `stderror` (bool, `false`) - Indicating whether the plot should show a colored band showing lower and higher estimates based on the stderror. -- `pvalue` (Array, `[]`) - example: `DataFrame(from=[0.1,0.3], to=[0.5,0.7], coefname=["(Intercept)", "condition:face"])` - if coefname not specified, the lines will be black +- `categorical_color` (bool, `true`): in case of numeric `:color` column, treat `:color` as continuous or categorical variable. +- `categorical_group` (bool, `true`): in case of numeric `:group` column, treat `:group` as categorical variable by default. +- `topolegend` (bool, `false`): add an inlay topoplot with corresponding electrodes. +- `stderror` (bool, `false`): add an error ribbon, with lower and upper limits based on the `:stderror` column. +- `pvalue` (Array, `[]`): show a pvalue. + - example: `DataFrame(from=[0.1, 0.3], to=[0.5, 0.7], coefname=["(Intercept)", "condition:face"])` - if coefname is not specified, the lines will be black $(_docstring(:erp)) @@ -29,37 +30,39 @@ $(_docstring(:erp)) - f - Figure() or the inputed `f` """ -plot_erp(plotData::DataFrame; kwargs...) = plot_erp!(Figure(), plotData, ; kwargs...) +plot_erp(plot_data::DataFrame; kwargs...) = plot_erp!(Figure(), plot_data, ; kwargs...) """ -Plot Butterfly +Plot a butterfly plot -$(_docstring(:butterfly)) - -## key-word arguments +## kwargs (...; ...): -- `topomarkersize` (Real, `10`) - change the size of the markers, topoplot-inlay electrodes -- `topowidth` (Real, `0.25`) - change the size of the inlay topoplot width -- `topoheigth` (Real, `0.25`) - change the size of the inlay topoplot height +- `butterfly` (bool, `true`): create a butterfly plot. +- `topolegend` (bool, `true`): show an inlay topoplot with corresponding electrodes. +- `topomarkersize` (Real, `10`): change the size of the markers, topoplot-inlay electrodes. +- `topowidth` (Real, `0.25`): change the size of the inlay topoplot width. +- `topoheigth` (Real, `0.25`): change the size of the inlay topoplot height. +- `topopositions_to_color` (function, ´x -> posToColorRomaO(x)´). +$(_docstring(:butterfly)) see also [`plot_erp`](@Ref) """ -plot_butterfly(plotData::DataFrame; kwargs...) = - plot_butterfly!(Figure(), plotData; kwargs...) +plot_butterfly(plot_data::DataFrame; kwargs...) = + plot_butterfly!(Figure(), plot_data; kwargs...) plot_butterfly!( f::Union{GridPosition,GridLayout,<:Figure}, - plotData::DataFrame; + plot_data::DataFrame; kwargs..., ) = plot_erp!( f, - plotData; + plot_data; butterfly = true, - topoLegend = true, + topolegend = true, topomarkersize = 10, topowidth = 0.25, topoheigth = 0.25, - topoPositionToColorFunction = x -> posToColorRomaO(x), + topopositions_to_color = x -> posToColorRomaO(x), kwargs..., ) @@ -67,19 +70,19 @@ plot_butterfly!( function plot_erp!( f::Union{GridPosition,GridLayout,Figure}, - plotData::DataFrame; + plot_data::DataFrame; positions = nothing, labels = nothing, - categoricalColor = true, - categoricalGroup = true, + categorical_color = true, + categorical_group = true, stderror = false, # XXX if it exists, should be plotted pvalue = [], butterfly = false, - topoLegend = nothing, + topolegend = nothing, topomarkersize = nothing, topowidth = nothing, topoheigth = nothing, - topoPositionToColorFunction = nothing, + topopositions_to_color = nothing, kwargs..., ) config = PlotConfig(:erp) @@ -89,10 +92,10 @@ function plot_erp!( config_kwargs!(config; kwargs...) end - plotData = deepcopy(plotData) # XXX why? + plot_data = deepcopy(plot_data) # XXX why? # resolve columns with data - config.mapping = resolveMappings(plotData, config.mapping) + config.mapping = resolveMappings(plot_data, config.mapping) #remove mapping values with `nothing` deleteKeys(nt::NamedTuple{names}, keys) where {names} = NamedTuple{filter(x -> x ∉ keys, names)}(nt) @@ -103,40 +106,40 @@ function plot_erp!( # turn "nothing" from group columns into :fixef - if "group" ∈ names(plotData) - plotData.group = plotData.group .|> a -> isnothing(a) ? :fixef : a + if "group" ∈ names(plot_data) + plot_data.group = plot_data.group .|> a -> isnothing(a) ? :fixef : a end # check if stderror values exist and create new collumsn with high and low band - if "stderror" ∈ names(plotData) && stderror - plotData.stderror = plotData.stderror .|> a -> isnothing(a) ? 0.0 : a - plotData[!, :se_low] = plotData[:, config.mapping.y] .- plotData.stderror - plotData[!, :se_high] = plotData[:, config.mapping.y] .+ plotData.stderror + if "stderror" ∈ names(plot_data) && stderror + plot_data.stderror = plot_data.stderror .|> a -> isnothing(a) ? 0.0 : a + plot_data[!, :se_low] = plot_data[:, config.mapping.y] .- plot_data.stderror + plot_data[!, :se_high] = plot_data[:, config.mapping.y] .+ plot_data.stderror end # Get topocolors for butterfly if (butterfly) if isnothing(positions) && isnothing(labels) - topoLegend = false - #colors = config.visual.colormap# get(colorschemes[config.visual.colormap],range(0,1,length=nrow(plotData))) + topolegend = false + #colors = config.visual.colormap# get(colorschemes[config.visual.colormap],range(0,1,length=nrow(plot_data))) colors = nothing #config.mapping = merge(config.mapping,(;color=config.)) else allPositions = getTopoPositions(; positions = positions, labels = labels) - colors = getTopoColor(allPositions, topoPositionToColorFunction) + colors = getTopoColor(allPositions, topopositions_to_color) end end # Categorical mapping # convert color column into string, so no wrong grouping happens - if categoricalColor && (:color ∈ keys(config.mapping)) + if categorical_color && (:color ∈ keys(config.mapping)) config.mapping = merge(config.mapping, (; color = config.mapping.color => nonnumeric)) end # converts group column into string - if categoricalGroup && (:group ∈ keys(config.mapping)) + if categorical_group && (:group ∈ keys(config.mapping)) config.mapping = merge(config.mapping, (; group = config.mapping.group => nonnumeric)) end @@ -163,11 +166,11 @@ function plot_erp!( basic = basic + visual(Band, alpha = 0.5) * m_se end - basic = basic * data(plotData) + basic = basic * data(plot_data) # add the pvalues if !isempty(pvalue) - basic = basic + addPvalues(plotData, pvalue, config) + basic = basic + addPvalues(plot_data, pvalue, config) end plotEquation = basic * mapp @@ -175,9 +178,9 @@ function plot_erp!( f_grid = f[1, 1] # butterfly plot is drawn slightly different if butterfly - # add topoLegend + # add topolegend - if (topoLegend) + if (topolegend) topoAxis = Axis( f_grid, width = Relative(topowidth), @@ -189,7 +192,7 @@ function plot_erp!( topoplotLegend( topoAxis, topomarkersize, - topoPositionToColorFunction, + topopositions_to_color, allPositions, ) end @@ -227,14 +230,14 @@ function eegHeadMatrix(positions, center, radius) ) end -function topoplotLegend(axis, topomarkersize, topoPositionToColorFunction, allPositions) +function topoplotLegend(axis, topomarkersize, topopositions_to_color, allPositions) allPositions = unique(allPositions) topoMatrix = eegHeadMatrix(allPositions, (0.5, 0.5), 0.5) # colorscheme where first entry is 0, and exactly length(positions)+1 entries specialColors = ColorScheme( - vcat(RGB(1, 1, 1.0), [topoPositionToColorFunction(pos) for pos in allPositions]...), + vcat(RGB(1, 1, 1.0), [topopositions_to_color(pos) for pos in allPositions]...), ) xlims!(low = -0.2, high = 1.2) @@ -257,15 +260,15 @@ function topoplotLegend(axis, topomarkersize, topoPositionToColorFunction, allPo return topoplot end -function addPvalues(plotData, pvalue, config) +function addPvalues(plot_data, pvalue, config) p = deepcopy(pvalue) # for now, add them to the fixed effect if "group" ∉ names(p) # group not specified using first - if "group" ∈ names(plotData) - p[!, :group] .= plotData[1, :group] - if length(unique(plotData.group)) > 1 + if "group" ∈ names(plot_data) + p[!, :group] .= plot_data[1, :group] + if length(unique(plot_data.group)) > 1 @warn "multiple groups found, choosing first one" end else @@ -282,16 +285,17 @@ function addPvalues(plotData, pvalue, config) end # define an index to dodge the lines vertically - scaleY = [minimum(plotData.estimate), maximum(plotData.estimate)] + scaleY = [minimum(plot_data.estimate), maximum(plot_data.estimate)] stepY = scaleY[2] - scaleY[1] posY = stepY * -0.05 + scaleY[1] - Δt = diff(plotData.time[1:2])[1] + Δt = diff(plot_data.time[1:2])[1] Δy = 0.01 p[!, :segments] = [ Makie.Rect( Makie.Vec(x, posY + stepY * (Δy * (n - 1))), Makie.Vec(y - x + Δt, 0.5 * Δy * stepY), ) for (x, y, n) in zip(p.from, p.to, p.sigindex) - ] - return (data(p) * mapping(:segments) * visual(Poly)) + ] + res = data(p) * mapping(:segments) * visual(Poly) + return (res) end diff --git a/src/plot_erpgrid.jl b/src/plot_erpgrid.jl index de5dbd696..06abdf879 100644 --- a/src/plot_erpgrid.jl +++ b/src/plot_erpgrid.jl @@ -4,32 +4,32 @@ Plot an ERP image. ## Arguments: -- `f::Union{GridPosition, GridLayout, Figure}`: Figure or GridPosition that the plot should be drawn into; -- `plotData::Matrix{<:Real}`: Data for the plot visualization; +- `f::Union{GridPosition, GridLayout, Figure}`: Figure or GridPosition that the plot should be drawn into. +- `data::Matrix{<:Real}`: data for the plot visualization. - `pos::Vector{Point{2,Float}}`: electrode positions. ## Keyword Arguments -- `drawLabels` (bool, `false`) - Draw channels labels over each waveform. -- `times`: (Vector, `1:size(plotData, 2)`) - Vector of size() +- `drawlabels` (bool, `false`): draw channels labels over each waveform. +- `times`: (Vector, `1:size(data, 2)`): vector of size(). ## Return Value: The input `f` """ # no figure? -plot_erpgrid(plotData::Matrix{<:Real}, pos; kwargs...) = - plot_erpgrid!(Figure(), plotData, pos; kwargs...) +plot_erpgrid(data::Matrix{<:Real}, pos; kwargs...) = + plot_erpgrid!(Figure(), data, pos; kwargs...) function plot_erpgrid!( f::Union{GridPosition,GridLayout,Figure}, - plotData::Matrix{<:Real}, + data::Matrix{<:Real}, pos; - drawLabels = false, - times = -1:size(plotData, 2)-2, #arbitrary strat just for fun + drawlabels = false, + times = -1:size(data, 2)-2, #arbitrary strat just for fun kwargs..., ) - chanNum = size(plotData, 1) - plotData = plotData[1:chanNum, :] + chanNum = size(data, 1) + data = data[1:chanNum, :] pos = hcat([[p[1], p[2]] for p in pos]...) pos = pos[:, 1:chanNum] @@ -52,7 +52,7 @@ function plot_erpgrid!( halign = x, valign = y, )# title = raw_ch_names[1:30]) - if drawLabels + if drawlabels text!( ax, rel_zeropoint + 0.1, @@ -72,10 +72,10 @@ function plot_erpgrid!( hlines!.(axlist, Ref([0.0]), color = :gray, linewidth = 0.5) vlines!.(axlist, Ref([0.0]), color = :gray, linewidth = 0.5) - times = isnothing(times) ? (1:size(plotData, 2)) : times + times = isnothing(times) ? (1:size(data, 2)) : times # todo: add customizable kwargs - h = lines!.(axlist, Ref(times), eachrow(plotData)) + h = lines!.(axlist, Ref(times), eachrow(data)) linkaxes!(axlist...) hidedecorations!.(axlist) diff --git a/src/plot_erpimage.jl b/src/plot_erpimage.jl index dcfca82c8..bd1a9de3b 100644 --- a/src/plot_erpimage.jl +++ b/src/plot_erpimage.jl @@ -8,16 +8,15 @@ Plot an ERP image. ## Arguments: - `f::Union{GridPosition, GridLayout, Figure}`: Figure or GridPosition that the plot should be drawn into -- `plotData::Matrix{Float64}`: Data for the plot visualization +- `plot::Matrix{Float64}`: Data for the plot visualization ## Keyword Arguments -`erpBlur` (Number, `10`) - Number indicating how much blur is applied to the image; using Gaussian blur of the ImageFiltering module. +- `erpblur` (Number, `10`): number indicating how much blur is applied to the image; using Gaussian blur of the ImageFiltering module. Non-Positive values deactivate the blur. - -`sortvalues` (bool, `false`) - parameter over which plot will be sorted. Using sortperm() of Base Julia -(sortperm() computes a permutation of the array's indices that puts the array into sorted order). - -`meanPlot`: (bool, `false`) - Indicating whether the plot should add a line plot below the ERP image, showing the mean of the data. +- `sortix` (default: `nothing`): . +- `sortvalues` (bool, `false`): parameter over which plot will be sorted. Using sortperm() of Base Julia. + - sortperm() computes a permutation of the array's indices that puts the array into sorted order. +- `meanplot` (bool, `false`): Indicating whether the plot should add a line plot below the ERP image, showing the mean of the data. $(_docstring(:erpimage)) @@ -26,26 +25,26 @@ The input `f` """ # no times + no figure? -plot_erpimage(plotData::Matrix{<:Real}; kwargs...) = - plot_erpimage!(Figure(), plotData; kwargs...) +plot_erpimage(plot::Matrix{<:Real}; kwargs...) = + plot_erpimage!(Figure(), plot; kwargs...) # no times? -plot_erpimage!(f::Union{GridPosition,GridLayout,Figure}, plotData::Matrix{<:Real}; kwargs...) = - plot_erpimage!(f, 1:size(plotData, 1), plotData; kwargs...) +plot_erpimage!(f::Union{GridPosition,GridLayout,Figure}, plot::Matrix{<:Real}; kwargs...) = + plot_erpimage!(f, 1:size(plot, 1), plot; kwargs...) # no figure? -plot_erpimage(times::AbstractVector, plotData::Matrix{<:Real}; kwargs...) = - plot_erpimage!(Figure(), times, plotData; kwargs...) +plot_erpimage(times::AbstractVector, plot::Matrix{<:Real}; kwargs...) = + plot_erpimage!(Figure(), times, plot; kwargs...) function plot_erpimage!( f::Union{GridPosition,GridLayout,Figure}, times::AbstractVector, - plotData::Matrix{<:Real}; + plot::Matrix{<:Real}; sortvalues = nothing, sortix = nothing, - meanPlot = false, - erpBlur = 10, + meanplot = false, + erpblur = 10, kwargs..., ) config = PlotConfig(:erpimage) @@ -56,7 +55,7 @@ function plot_erpimage!( ax = Axis(f[1:4, 1]; config.axis...) if isnothing(sortix) if isnothing(sortvalues) - sortix = 1:size(plotData, 2) + sortix = 1:size(plot, 2) else sortix = sortperm(sortvalues) @@ -64,8 +63,8 @@ function plot_erpimage!( end filtered_data = UnfoldMakie.imfilter( - plotData[:, sortix], - UnfoldMakie.Kernel.gaussian((0, max(erpBlur, 0))), + plot[:, sortix], + UnfoldMakie.Kernel.gaussian((0, max(erpblur, 0))), ) yvals = 1:size(filtered_data, 2) @@ -77,22 +76,22 @@ function plot_erpimage!( UnfoldMakie.applyLayoutSettings!(config; fig = f, hm = hm, ax = ax, plotArea = (4, 1)) - if meanPlot + if meanplot # UserInput subConfig = deepcopy(config) config_kwargs!( subConfig; - layout = (; showLegend = false), + layout = (; show_legend = false), axis = (; ylabel = config.colorbar.label === nothing ? "" : config.colorbar.label ), ) axisOffset = - (config.layout.showLegend && config.layout.legendPosition == :bottom) ? 1 : 0 + (config.layout.show_legend && config.layout.legend_position == :bottom) ? 1 : 0 subAxis = Axis(f[5+axisOffset, 1]; subConfig.axis...) - lines!(subAxis, mean(plotData, dims = 2)[:, 1]) + lines!(subAxis, mean(plot, dims = 2)[:, 1]) applyLayoutSettings!(subConfig; fig = f, ax = subAxis) end diff --git a/src/plot_parallelcoordinates.jl b/src/plot_parallelcoordinates.jl index 52aeaf815..1551a0e29 100644 --- a/src/plot_parallelcoordinates.jl +++ b/src/plot_parallelcoordinates.jl @@ -1,34 +1,34 @@ """ plot_parallelcoordinates!(f::Union{GridPosition, GridLayout, Figure}, - plotData::DataFrame, config::PlotConfig; channels::Vector{Int64}) + data::DataFrame, config::PlotConfig; channels::Vector{Int64}) Plot a PCP (parallel coordinates plot). ## Arguments: -- `f::Union{GridPosition, GridLayout, Figure}`: Figure or GridPosition that the plot should be drawn into -- `plotData::DataFrame`: Data for the plot visualization. -- `config::PlotConfig`: Instance of PlotConfig being applied to the visualization. +- `f::Union{GridPosition, GridLayout, Figure}`: Figure or GridPosition that the plot should be drawn into. +- `data::DataFrame`: data for the plot visualization. +- `config::PlotConfig`: instance of PlotConfig being applied to the visualization. - `channels::Vector{Int64}`: vector with all the channels representing an axis used in the PCP in given order. PCP has problems with size changes of the view window. -By adapting the padding, aspect ratio and tick label size in px for a new use case, the PCP can even be added into a Coordinated Multiple Views System +By adapting the padding, aspect ratio and tick label size in px for a new use case, the PCP can even be added into a complex figures. -- `pc_aspect_ratio` Default : `0.55` -- `pc_right_padding` Default : `15` -- `pc_left_padding` Default : `25` -- `pc_top_padding` Default : `26` -- `pc_bottom_padding` Default : `16` -- `pc_tick_label_size` Default : `14` +- `pc_aspect_ratio` (default: `0.55`) - +- `pc_right_padding` (default: `15`) - +- `pc_left_padding` (default: `25`) - +- `pc_top_padding` (default: `26`) - +- `pc_bottom_padding` (default: `16`) - +- `pc_tick_label_size` (default: `14`) - $(_docstring(:paracoord)) ## Return Value: The input `f` """ -plot_parallelcoordinates(plotData::DataFrame, channels::Vector{Int64}; kwargs...) = - plot_parallelcoordinates!(Figure(), plotData, channels; kwargs...) +plot_parallelcoordinates(data::DataFrame, channels::Vector{Int64}; kwargs...) = + plot_parallelcoordinates!(Figure(), data, channels; kwargs...) function plot_parallelcoordinates!( f::Union{GridPosition,GridLayout,Figure}, - plotData::DataFrame, + data::DataFrame, channels::Vector{Int64}; pc_aspect_ratio = 0.55, pc_right_padding = 15, @@ -61,9 +61,9 @@ function plot_parallelcoordinates!( # colormap border (prevents from using outer parts of color map) bord = 0 - config.mapping = resolveMappings(plotData, config.mapping) + config.mapping = resolveMappings(data, config.mapping) - color = unique(plotData[:, config.mapping.color]) + color = unique(data[:, config.mapping.color]) catLeng = length(color) chaLeng = length(channels) @@ -97,7 +97,7 @@ function plot_parallelcoordinates!( # get extrema for each channel for cha in channels - tmp = filter(x -> (x[config.mapping.channel] == cha), plotData) + tmp = filter(x -> (x[config.mapping.channel] == cha), data) w = extrema.([tmp[:, config.mapping.y]]) append!(limits, w) append!(l_up, w[1][2]) @@ -120,7 +120,7 @@ function plot_parallelcoordinates!( labelfont = "Arial", ticklabelfont = "Arial", spinevisible = true, - labelrotation = 0.0, + labelrotation = 0.0, ticklabelsize = tick_label_size, minorticks = IntervalsBetween(2), endpoints = Point2f[(x_values[i], bottom_padding), (x_values[i], y_values[i])], @@ -130,11 +130,11 @@ function plot_parallelcoordinates!( end # Draw colored line through all channels for each time entry - for time in unique(plotData[:, config.mapping.time]) - tmp1 = filter(x -> (x[config.mapping.time] == time), plotData) #1 timepoint, 10 rows (2 conditions, 5 channels) + for time in unique(data[:, config.mapping.time]) + tmp1 = filter(x -> (x[config.mapping.time] == time), data) #1 timepoint, 10 rows (2 conditions, 5 channels) for cat in color # df with the order of the channels - dfInOrder = plotData[[], :] + dfInOrder = data[[], :] tmp2 = filter(x -> (x[config.mapping.color] == cat), tmp1) # create new dataframe with the right order diff --git a/src/plot_topoplot.jl b/src/plot_topoplot.jl index 5df7a5baa..166925157 100644 --- a/src/plot_topoplot.jl +++ b/src/plot_topoplot.jl @@ -1,13 +1,13 @@ """ - plot_topoplot!(f::Union{GridPosition, GridLayout, Figure}, plotData, ; positions=nothing, labels=nothing,kwargs...) - plot_topoplot(plotData,; positions=nothing, labels=nothing, kwargs...) + plot_topoplot!(f::Union{GridPosition, GridLayout, Figure}, data, ; positions=nothing, labels=nothing,kwargs...) + plot_topoplot(data,; positions=nothing, labels=nothing, kwargs...) Plot a topo plot. ## Arguments: - `f::Union{GridPosition, GridLayout, Figure}`: Figure or GridPosition (e.g. f[2, 3]) that the plot should be drawn into. New axis is created. -- `plotData::Union{DataFrame, Vector{Float32}}`: Data for the plot visualization. -- `positions::Vector{Point{2, Float32}}=nothing`: positions used if `plotData` is no DataFrame. If this is the case and `positions=nothing` then positions is generated from `labels`. -- `labels::Vector{String}=nothing`: labels used if `plotData` is no DataFrame. +- `data::Union{DataFrame, Vector{Float32}}`: data for the plot visualization. +- `positions::Vector{Point{2, Float32}}=nothing`: positions used if `data` is not a DataFrame. If this is the case and `positions=nothing` then positions are generated from `labels`. +- `labels::Vector{String} = nothing`: labels used if `data` is not a DataFrame. $(_docstring(:topoplot)) @@ -16,11 +16,11 @@ $(_docstring(:topoplot)) ## Return Value: A figure displaying the topo plot. """ -plot_topoplot(plotData::Union{DataFrame,Vector{Float32}}; kwargs...) = - plot_topoplot!(Figure(), plotData; kwargs...) +plot_topoplot(data::Union{DataFrame,Vector{Float32}}; kwargs...) = + plot_topoplot!(Figure(), data; kwargs...) function plot_topoplot!( f::Union{GridPosition,GridLayout,Figure}, - plotData::Union{DataFrame,<:AbstractVector}; + data::Union{DataFrame,<:AbstractVector}; positions = nothing, labels = nothing, kwargs..., @@ -31,21 +31,21 @@ function plot_topoplot!( axis = Axis(f[1, 1]; config.axis...) - if !(plotData isa Vector) - config.mapping = resolveMappings(plotData, config.mapping) - plotData = plotData[:, config.mapping.y] + if !(data isa Vector) + config.mapping = resolveMappings(data, config.mapping) + data = data[:, config.mapping.y] end positions = getTopoPositions(; positions = positions, labels = labels) - eeg_topoplot!(axis, plotData, labels; positions, config.visual...) + eeg_topoplot!(axis, data, labels; positions, config.visual...) - clims = (min(plotData...), max(plotData...)) + clims = (min(data...), max(data...)) if clims[1] ≈ clims[2] @warn """The min and max of the value represented by the color are the same, it seems that the data values are identical. We disable the color bar in this figure. Note: The identical min and max may cause an interpolation error when plotting the topoplot.""" - config_kwargs!(config, layout = (; useColorbar=false,showLegend=false)) + config_kwargs!(config, layout = (; use_colorbar=false, show_legend=false)) else config_kwargs!(config, colorbar = (; limits = clims)) end diff --git a/src/plot_topoplotseries.jl b/src/plot_topoplotseries.jl index 8a667cf25..f920e093d 100644 --- a/src/plot_topoplotseries.jl +++ b/src/plot_topoplotseries.jl @@ -1,19 +1,21 @@ """ - plot_topoplotseries!(f::Union{GridPosition, GridLayout, Figure}, plotData::DataFrame, Δbin::Real; kwargs...) - plot_topoplotseries!(plotData::DataFrame, Δbin::Real; kwargs...) + plot_topoplotseries!(f::Union{GridPosition, GridLayout, Figure}, data::DataFrame, Δbin::Real; kwargs...) + plot_topoplotseries!(data::DataFrame, Δbin::Real; kwargs...) Multiple miniature topoplots in regular distances ## Arguments: -- `f::Union{GridPosition, GridLayout, Figure}`: Figure or GridPosition that the plot should be drawn into -- `plotData::DataFrame`: DataFrame with data, needs a `time` column -- `Δbin::Real`: A number for how large one bin should be. Δbin is in units of the `plotData.time` column -- `combinefun` (default `mean`) can be used to specify how the samples within `Δbin` are combined. -- `rasterize_heatmaps` (deault `true`) - enforce rasterization of the plot heatmap when saving in svg format. - This has the benefit that all lines/points are vectors, except the interpolated heatmap. - This is typically what you want, because else you get ~500x500 vectors per topoplot, which makes everything super slow. +- `f::Union{GridPosition, GridLayout, Figure}`: Figure or GridPosition that the plot should be drawn into. +- `data::DataFrame`: DataFrame with data, needs a `time` column. +- `Δbin::Real`: A number for how large one time bin should be. Δbin is in units of the `data.time` column. +- `combinefun` (default: `mean`) - can be used to specify how the samples within `Δbin` are combined. +- `rasterize_heatmaps` (default: `true`) - enforce rasterization of the plot heatmap when saving in svg format. + This has the benefit that all lines/points are vectors, except the interpolated heatmap. + This is typically what you want, otherwise you get ~500x500 vectors per topoplot, which makes everything super slow. - `col_labels`, `row_labels` - shows column and row labels. +- labels (default: `nothing`) - . +- positions (default: `nothing`) - . $(_docstring(:topoplotseries)) @@ -21,12 +23,12 @@ $(_docstring(:topoplotseries)) The input `f` """ -plot_topoplotseries(plotData::DataFrame, Δbin::Real; kwargs...) = - plot_topoplotseries!(Figure(), plotData, Δbin; kwargs...) +plot_topoplotseries(data::DataFrame, Δbin::Real; kwargs...) = + plot_topoplotseries!(Figure(), data, Δbin; kwargs...) function plot_topoplotseries!( f::Union{GridPosition,GridLayout,Figure}, - plotData::DataFrame, + data::DataFrame, Δbin; positions = nothing, labels = nothing, @@ -40,21 +42,21 @@ function plot_topoplotseries!( config = PlotConfig(:topoplotseries) config_kwargs!(config; kwargs...) - plotData = deepcopy(plotData) + data = deepcopy(data) # resolve columns with data - config.mapping = resolveMappings(plotData, config.mapping) + config.mapping = resolveMappings(data, config.mapping) positions = getTopoPositions(; positions = positions, labels = labels) - if "label" ∉ names(plotData) - plotData.label = plotData.channel + if "label" ∉ names(data) + data.label = data.channel end ftopo, axlist = eeg_topoplot_series!( f, - plotData, + data, Δbin; y = config.mapping.y, label = :label, @@ -68,25 +70,31 @@ function plot_topoplotseries!( config.visual..., ) - if config.layout.useColorbar + if config.layout.use_colorbar if typeof(ftopo) == Figure d = ftopo.content[1].scene.plots[1] - f_colorbar = f[1, end+1] - + Colorbar( + f[1, end+1], + colormap = d.colormap, + colorrange = d.colorrange, + height = config.colorbar.height, + flipaxis = config.colorbar.flipaxis, + labelrotation = config.colorbar.labelrotation , + label = config.colorbar.label, + ) else - #@debug axlist - f_colorbar = f[:, :][1, length(axlist)+1] + # println(fieldnames(typeof((axlist[1])))) d = axlist[1].scene.plots[1].attributes + Colorbar( + f[:, :][1, length(axlist)+1], + colormap = d.colormap, + colorrange = d.colorrange, + height = config.colorbar.height, + flipaxis = config.colorbar.flipaxis, + labelrotation = config.colorbar.labelrotation , + label = config.colorbar.label, + ) end - Colorbar( - f_colorbar, - colormap = d.colormap, - colorrange = d.colorrange, - #height = config.colorbar.height, - flipaxis = config.colorbar.flipaxis, - labelrotation = config.colorbar.labelrotation, - label = config.colorbar.label, - ) end return f diff --git a/src/plotconfig.jl b/src/plotconfig.jl index 5be113b03..4c3febf4a 100644 --- a/src/plotconfig.jl +++ b/src/plotconfig.jl @@ -27,11 +27,11 @@ function PlotConfig()# defaults (;), #figure (;), # axis (; # layout - showLegend = true, - legendPosition = :right, + show_legend = true, + legend_position = :right, xlabelFromMapping = :x, ylabelFromMapping = :y, - useColorbar = false, + use_colorbar = false, ), (#maping x = (:time,), @@ -65,9 +65,9 @@ function config_kwargs!(cfg::PlotConfig; kwargs...) """ Keyword argument specification (kwargs...) Specified config groups must be NamedTuples', but $(keys(kwargs)[.!is_namedtuple]) was not. Maybe you forgot the semicolon (;) at the beginning of your specification? Compare these strings: - plot_example(...; layout = (; showColorbar=true)) + plot_example(...; layout = (; use_colorbar=true)) - plot_example(...; layout = (showColorbar=true)) + plot_example(...; layout = (use_colorbar=true)) The first is correct and creates a NamedTuple as required. The second is wrong and its call is ignored.""") list = fieldnames(PlotConfig)#[:layout,:visual,:mapping,:legend,:colorbar,:axis] @@ -90,7 +90,7 @@ function PlotConfig(T::Val{:circeegtopo}) config_kwargs!( cfg; - layout = (; showLegend = false), + layout = (; show_legend = false), colorbar = (; label = "Voltage [µV]", colormap = Reverse(:RdBu)), mapping = (;), axis = (; @@ -123,10 +123,10 @@ function PlotConfig(T::Val{:topoplot}) config_kwargs!( cfg; layout = ( - showLegend = true, + show_legend = true, xlabelFromMapping = nothing, ylabelFromMapping = nothing, - useColorbar = true, + use_colorbar = true, hidespines = (), hidedecorations = (), ), @@ -150,7 +150,7 @@ function PlotConfig(T::Val{:topoplotseries}) cfg = PlotConfig(:topoplot) config_kwargs!( cfg, - layout = (useColorbar = true,), + layout = (use_colorbar = true,), colorbar = (; #height = 300, flipaxis = true, @@ -169,7 +169,7 @@ function PlotConfig(T::Val{:designmat}) config_kwargs!( cfg; layout = (; - useColorbar = true, + use_colorbar = true, xlabelFromMapping = nothing, ylabelFromMapping = nothing, ), @@ -182,10 +182,10 @@ function PlotConfig(T::Val{:butterfly}) cfg = PlotConfig(:erp) config_kwargs!( cfg; - layout = (; showLegend = false), + layout = (; show_legend = false), mapping = (; color = (:channel, :channels, :trial, :trials), - positions = (:pos, :positions, :position, :topoPositions, :x, nothing), + positions = (:pos, :positions, :position, :topo_positions, :x, nothing), labels = (:labels, :label, :topoLabels, :sensor, nothing), ), ) @@ -196,7 +196,7 @@ function PlotConfig(T::Val{:erp}) config_kwargs!( cfg; mapping = (; color = (:color, :coefname, nothing)), - layout = (; showLegend = true, hidespines = (:r, :t)), + layout = (; show_legend = true, hidespines = (:r, :t)), legend = (; framevisible = false), ) @@ -206,7 +206,7 @@ function PlotConfig(T::Val{:erpimage}) cfg = PlotConfig() config_kwargs!( cfg; - layout = (; useColorbar = true), + layout = (; use_colorbar = true), colorbar = (; label = "Voltage [µV]", labelrotation = 4.7), axis = (xlabel = "Time", ylabel = "Sorted trials"), visual = (; colormap = Reverse("RdBu")), diff --git a/test/Project.toml b/test/Project.toml index 56a844000..4ab9756ab 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -1,5 +1,6 @@ [deps] CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" +Colors = "5ae59095-9a9b-59fe-a467-6f913c188581" DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/test/runtests.jl b/test/runtests.jl index 73726b65c..e85af7104 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -6,12 +6,13 @@ include("setup.jl") @testset "Test Config" begin include("test_config.jl") end -@testset "Circular EEG topoplot" begin - include("test_plot_circulareegtopoplot.jl") + +@testset "ERP plot" begin + include("test_erp.jl") end -@testset "TopoSeries" begin - include("test_toposeries.jl") +@testset "Butterfly" begin + include("test_butterfly.jl") end @testset "ERP Image" begin @@ -22,10 +23,18 @@ end include("test_topoplot.jl") end -@testset "Butterfly" begin - include("test_butterfly.jl") +@testset "Topoplot series" begin + include("test_toposeries.jl") +end + +@testset "Parallel coordinates plot" begin + include("test_pcp.jl") +end + +@testset "Circular EEG topoplot" begin + include("test_plot_circulareegtopoplot.jl") end -@testset "All plots" begin - include("test_all.jl") +@testset "Complex plots" begin + include("test_complexplots.jl") end \ No newline at end of file diff --git a/test/setup.jl b/test/setup.jl index 6a53f725a..a11159623 100644 --- a/test/setup.jl +++ b/test/setup.jl @@ -4,5 +4,6 @@ using CairoMakie using GeometryBasics using DataFrames using TopoPlots +using Colors include("../docs/example_data.jl") \ No newline at end of file diff --git a/test/test_butterfly.jl b/test/test_butterfly.jl index 1b786556e..1a5a0043b 100644 --- a/test/test_butterfly.jl +++ b/test/test_butterfly.jl @@ -1,13 +1,12 @@ +include("../docs/example_data.jl") +data, pos = example_data("TopoPlots.jl") + @testset "basic" begin - include("../docs/example_data.jl") - data, pos = example_data("TopoPlots.jl") plot_butterfly(data; positions = pos) end @testset "topomarkersize change" begin - include("../docs/example_data.jl") - data, pos = example_data("TopoPlots.jl") plot_butterfly( data; positions = pos, @@ -17,5 +16,26 @@ end ) end +@testset "changing color from ROMA to gray" begin + plot_butterfly( + data; + positions = pos, + topopositions_to_color = x -> Colors.RGB(0.5) + ) +end +@testset "changing color from ROMA to HSV" begin + plot_butterfly( + data; + positions = pos, + topopositions_to_color=UnfoldMakie.posToColorHSV + ) +end +@testset "changing color from ROMA to RGB" begin + plot_butterfly( + data; + positions = pos, + topopositions_to_color = pos -> UnfoldMakie.posToColorRGB(pos) + ) +end diff --git a/test/test_all.jl b/test/test_complexplots.jl similarity index 83% rename from test/test_all.jl rename to test/test_complexplots.jl index b0c7650af..18a8e4778 100644 --- a/test/test_all.jl +++ b/test/test_complexplots.jl @@ -38,7 +38,7 @@ plot_butterfly!(gb, d_topo; positions=pos, topomarkersize = 10, topoheigth = 0.4, topowidth = 0.4,) plot_topoplot!(gc, data[:,340,1]; positions = positions) plot_topoplotseries!(gd, df, 80; positions=positions, visual=(label_scatter=false,), - layout = (; useColorbar=true)) + layout = (; use_colorbar=true)) plot_erpgrid!(ge, data[:, :, 1], positions) dat, evts = UnfoldSim.predef_eeg(;onset=LogNormalOnset(μ=3.5, σ=0.4), noiselevel = 5) @@ -49,7 +49,7 @@ plot_erpimage!(gf, times, dat_e; sortvalues=evts.Δlatency) #plot_erpimage!(gf, times, d_singletrial) plot_parallelcoordinates!(gh, uf_5chan, [1, 2, 3, 4, 5]; - mapping=(; color=:coefname), layout=(; legendPosition=:bottom), legend=(; tellwidth =false)) + mapping=(; color=:coefname), layout=(; legend_position=:bottom), legend=(; tellwidth =false)) for (label, layout) in zip(["A", "B", "C", "D", "E", "F", "G", "H"], [ga, gb, gc, gd, ge, gf, gg, gh]) Label(layout[1, 1, TopLeft()], label, @@ -86,16 +86,15 @@ end stderror=true)) plot_butterfly!(f[1, 2], d_topo; positions=positions) - - plot_topoplot!(f[2, 1], data[:, 150, 1]; positions=positions, t=150) - plot_topoplotseries!(f[2, 2], d_topo, 0.1; positions=positions, layout = (; useColorbar=true)) + plot_topoplot!(f[2, 1], data[:, 150, 1]; positions=positions) + plot_topoplotseries!(f[2, 2], d_topo, 0.1; positions=positions, visual=(label_scatter=false,), layout = (; use_colorbar=true)) plot_erpgrid!(f[3, 1], data[:, :, 1], positions) - times = -0.099609375:0.001953125:1.0 plot_erpimage!(f[3, 2], times, d_singletrial) - plot_parallelcoordinates!(f[4, 2], uf_5chan, [1, 2, 3, 4, 5]; mapping=(; color=:coefname), layout=(; legendPosition=:bottom)) + plot_parallelcoordinates!(f[4, 2], uf_5chan, [1, 2, 3, 4, 5]; mapping=(; color=:coefname), + layout=(; legend_position=:bottom), legend=(; tellwidth =false)) for (label, layout) in zip(["A", "B", "C", "D", "E", "F", "G", "H"], [f[1, 1], f[1, 2], f[2, 1], f[2, 2], f[3, 1], f[3, 2], f[4, 1], f[4, 2]]) @@ -109,7 +108,7 @@ end end -@testset "testing combined figure" begin +@testset "testing combined figure (a Figure from mult_viz_in_fig from docs)" begin include("../docs/example_data.jl") d_topo, positions = example_data("TopoPlots.jl") uf_deconv = example_data("UnfoldLinearModelContinuousTime") @@ -117,6 +116,8 @@ end results = coeftable(uf) uf_5chan = example_data("UnfoldLinearModelMultiChannel") d_singletrial, _ = UnfoldSim.predef_eeg(; return_epoched=true) + data, positions = TopoPlots.example_data() + times = -0.099609375:0.001953125:1.0 f = Figure(resolution=(2000, 2000)) @@ -128,39 +129,30 @@ end # if coefname not specified, line should be black coefname=["(Intercept)", "category: face"] ) - plot_erp!(f[2, 1:2], results, extra=(; - categoricalColor=false, - categoricalGroup=false, + plot_erp!(f[2, 1:2], results, + categorical_color=false, + categorical_group=false, pvalue=pvals, - stderror=true)) - - + stderror=true) + plot_designmatrix!(f[2, 3], designmatrix(uf)) - - plot_topoplot!(f[3, 1], collect(1:64); positions=positions, visual=(; colormap=:viridis)) - plot_topoplotseries!(f[4, 1:3], d_topo, 0.1; positions=positions, layout = (; useColorbar=true)) - + + plot_topoplot!(f[3, 1], data[:, 150, 1]; positions=positions) + plot_topoplotseries!(f[4, 1:3], d_topo, 0.1; positions=positions, mapping=(; label=:channel)) + res_effects = effects(Dict(:continuous => -5:0.5:5), uf_deconv) - - plot_erp!(f[2, 4:5], res_effects; + + plot_erp!(f[2, 4:5], res_effects; categorical_color=false, categorical_group=true, mapping=(; y=:yhat, color=:continuous, group=:continuous), - extra=(; showLegend=true, - categoricalColor=false, - categoricalGroup=true), legend=(; nbanks=2), - layout=(; legendPosition=:right)) - - - - plot_parallelcoordinates!(f[3, 2:3], uf_5chan, [1, 2, 3, 4, 5]; mapping=(; color=:coefname), layout=(; legendPosition=:bottom)) - - times = -0.099609375:0.001953125:1.0 + layout=(; show_legend=true, legend_position=:right)) + + plot_parallelcoordinates!(f[3, 2:3], uf_5chan, [1, 2, 3, 4, 5]; mapping=(; color=:coefname), layout=(; legend_position=:bottom)) + plot_erpimage!(f[1, 4:5], times, d_singletrial) - plot_circulareegtopoplot!(f[3:4, 4:5], d_topo[in.(d_topo.time, Ref(-0.3:0.1:0.5)), :]; - positions=positions, predictor=:time, predictorBounds=[-0.3, 0.5]) - + positions=positions, predictor=:time, predictor_bounds=[-0.3, 0.5]) + f #save("test.png", f) -end - +end \ No newline at end of file diff --git a/test/test_dm.jl b/test/test_dm.jl index c12bdfd15..d5c8340db 100644 --- a/test/test_dm.jl +++ b/test/test_dm.jl @@ -6,13 +6,13 @@ uf = example_data("UnfoldLinearModel") end @testset "sort data" begin - plot_designmatrix(designmatrix(uf); sortData = true) + plot_designmatrix(designmatrix(uf); sort_data = true) end @testset "designmatrix plot in GridLayout" begin f = Figure(resolution=(1200, 1400)) ga = f[1, 1] = GridLayout() - plot_designmatrix!(ga, designmatrix(uf); sortData = true) + plot_designmatrix!(ga, designmatrix(uf); sort_data = true) f end diff --git a/test/test_erp.jl b/test/test_erp.jl index 30273fcdc..f7549c9ee 100644 --- a/test/test_erp.jl +++ b/test/test_erp.jl @@ -19,6 +19,33 @@ end +@testset "basic with res_effects without colorbar" begin + data, evts = UnfoldSim.predef_eeg(; noiselevel = 12, return_epoched = true) + data = reshape(data, (1, size(data)...)) + f = @formula 0 ~ 1 + condition + continuous + se_solver = (x, y) -> Unfold.solver_default(x, y, stderror = true) + + m = fit( + UnfoldModel, + Dict(Any => (f, range(0, step = 1 / 100, length = size(data, 2)))), + evts, + data, + solver = se_solver, + ) + results = coeftable(m) + res_effects = effects(Dict(:continuous => -5:0.5:5), m) + + # ## Plot the results + plot_erp( + res_effects; + mapping = (; y = :yhat, color = :continuous, group = :continuous), + legend = (; nbanks = 2), + layout = (; legend_position = :right, show_legend = false), + categorical_color = false, + categorical_group = true, + ) +end + @testset "basic with res_effects" begin data, evts = UnfoldSim.predef_eeg(; noiselevel = 12, return_epoched = true) data = reshape(data, (1, size(data)...)) @@ -40,10 +67,9 @@ end res_effects; mapping = (; y = :yhat, color = :continuous, group = :continuous), legend = (; nbanks = 2), - layout = (; legendPosition = :right), - showLegend = true, - categoricalColor = false, - categoricalGroup = true, + layout = (; legend_position = :right, show_legend = true), + categorical_color = false, + categorical_group = true, ) end @@ -62,11 +88,11 @@ end # if coefname not specified, line should be black coefname=["(Intercept)", "category: face"] ) - plot_erp!(ga, results, extra=(; - categoricalColor=false, - categoricalGroup=false, + plot_erp!(ga, results; + categorical_color=false, + categorical_group=false, pvalue=pvals, - stderror=true)) + stderror=true) f end diff --git a/test/test_erpimage.jl b/test/test_erpimage.jl index a09c94cb4..b718fbb00 100644 --- a/test/test_erpimage.jl +++ b/test/test_erpimage.jl @@ -6,18 +6,18 @@ end @testset "with mean erp plot" begin data, evts = UnfoldSim.predef_eeg(; noiselevel = 10, return_epoched = true) - plot_erpimage(data; meanPlot = true) + plot_erpimage(data; meanplot = true) end -@testset "changing erpBlur to zero" begin +@testset "changing erpblur to zero" begin data, evts = UnfoldSim.predef_eeg(; noiselevel = 10, return_epoched = true) - plot_erpimage(data; meanPlot = true, erpBlur = 0) + plot_erpimage(data; meanplot = true, erpblur = 0) end @testset "GridPosition" begin f = Figure() data, evts = UnfoldSim.predef_eeg(; noiselevel = 10, return_epoched = true) - plot_erpimage!(f[1, 1], data; meanPlot = true) + plot_erpimage!(f[1, 1], data; meanplot = true) #save("erpimage.eps", f) end diff --git a/test/test_pcp.jl b/test/test_pcp.jl index 581e808e1..4e9d6de03 100644 --- a/test/test_pcp.jl +++ b/test/test_pcp.jl @@ -13,6 +13,6 @@ end f = Figure() plot_parallelcoordinates!(f[1, 1], uf_5chan, [1, 2, 3, 4, 5]; - mapping=(; color=:coefname), layout=(; legendPosition=:bottom)) + mapping=(; color=:coefname), layout=(; legend_position=:bottom)) f end \ No newline at end of file diff --git a/test/test_plot_circulareegtopoplot.jl b/test/test_plot_circulareegtopoplot.jl index 1978a8474..203a35322 100644 --- a/test/test_plot_circulareegtopoplot.jl +++ b/test/test_plot_circulareegtopoplot.jl @@ -18,7 +18,7 @@ predictor = [70,80,90], ) - @test_throws ErrorException plot_circulareegtopoplot(testdf; predictorBounds=[0,100,360], positions = [Point(1.0,2.0), Point(1.0,2.0), Point(1.0,2.0)],) + @test_throws ErrorException plot_circulareegtopoplot(testdf; predictor_bounds=[0,100,360], positions = [Point(1.0,2.0), Point(1.0,2.0), Point(1.0,2.0)],) end end @@ -58,7 +58,7 @@ end df = flatten(df, :estimate); ga = f[1, 1] = GridLayout() plot_circulareegtopoplot!(ga, df; positions = pos, - axis = (; label = "Time?!"), predictor = :time, predictorBounds = [80, 320],) + axis = (; label = "Time?!"), predictor = :time, predictor_bounds = [80, 320],) f end @@ -66,6 +66,6 @@ end d_topo, positions = example_data("TopoPlots.jl") f = Figure(resolution=(2000, 2000)) plot_circulareegtopoplot!(f[3:4, 4:5], d_topo[in.(d_topo.time, Ref(-0.3:0.1:0.5)), :]; - positions=positions, predictor=:time, predictorBounds=[-0.3, 0.5]) + positions=positions, predictor=:time, predictor_bounds=[-0.3, 0.5]) f end \ No newline at end of file diff --git a/test/test_pp.jl b/test/test_pp.jl deleted file mode 100644 index 581e808e1..000000000 --- a/test/test_pp.jl +++ /dev/null @@ -1,18 +0,0 @@ - -@testset "Figure, 3 channels, 1 condition" begin - include("../docs/example_data.jl") - results_plot, positions = example_data(); - plot_parallelcoordinates(results_plot, [5, 3, 2]; # this selects channel 5,3 & 2 - mapping = (color = :coefname, y = :estimate)) -end - - -@testset "GridPosition" begin - uf_5chan = example_data("UnfoldLinearModelMultiChannel") - d_singletrial, _ = UnfoldSim.predef_eeg(; return_epoched=true) - - f = Figure() - plot_parallelcoordinates!(f[1, 1], uf_5chan, [1, 2, 3, 4, 5]; - mapping=(; color=:coefname), layout=(; legendPosition=:bottom)) - f -end \ No newline at end of file diff --git a/test/test_toposeries.jl b/test/test_toposeries.jl index 161ebd305..df7401bc8 100644 --- a/test/test_toposeries.jl +++ b/test/test_toposeries.jl @@ -13,7 +13,7 @@ end df, Δbin; positions = positions, - layout = (; useColorbar = false), + layout = (; use_colorbar = false), ) end @@ -30,7 +30,7 @@ end df, Δbin; positions = positions, - layout = (; useColorbar = true), + layout = (; use_colorbar = true), ) hidespines!(ax) hidedecorations!(ax, label = false) From a3a38e08a60c8de77a0ea6c4a34958b8cdcba3b5 Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Fri, 24 Nov 2023 17:06:33 +0000 Subject: [PATCH 07/12] channelimage in complex plot --- src/docstringtemplate.jl | 13 +++++----- src/plot_channelimage.jl | 39 ++++++++++++++++++++-------- src/plot_circulareegtopoplot.jl | 3 ++- src/plot_erpgrid.jl | 3 ++- src/plot_erpimage.jl | 45 +++++++++++++++++---------------- src/plot_topoplot.jl | 2 +- src/plot_topoplotseries.jl | 6 ++--- src/plotconfig.jl | 16 +++++++++--- test/runtests.jl | 6 ++++- test/test_channelimage.jl | 8 +++++- test/test_complexplots.jl | 5 +++- 11 files changed, 95 insertions(+), 51 deletions(-) diff --git a/src/docstringtemplate.jl b/src/docstringtemplate.jl index aea66ab9d..f37d4a84e 100644 --- a/src/docstringtemplate.jl +++ b/src/docstringtemplate.jl @@ -1,6 +1,6 @@ -function _docstring(cfgsymb::Symbol) +function _docstring(cfg_symb::Symbol) #pad = maximum(length(string(f)) for f in fieldnames(T)) - cfg = PlotConfig(cfgsymb) + cfg = PlotConfig(cfg_symb) fn = fieldnames(PlotConfig) out = "" @@ -8,6 +8,7 @@ function _docstring(cfgsymb::Symbol) :erp =>`Makie.lines`, :butterfly =>`Makie.lines`, :paracoord =>`Makie.lines`, + :erpgrid =>`Makie.lines`, :designmat => `Makie.heatmap`, :erpimage => `Makie.heatmap`, :channelimage => `Makie.heatmap`, @@ -15,17 +16,17 @@ function _docstring(cfgsymb::Symbol) :topoplot => `Topoplot.eeg_topoplot`, :topoplotseries => `Topoplot.eeg_topoplot` ) - cbarstring = (cfgsymb == :erp || cfgsymb == :butterfly) ? "[`AlgebraOfGraphics.colobar!`](@ref)" : "[`Makie.Colorbar`](@ref)" + cbarstring = (cfg_symb == :erp || cfg_symb == :butterfly) ? "[`AlgebraOfGraphics.colobar!`](@ref)" : "[`Makie.Colorbar`](@ref)" link = Dict( :figure => "use `kwargs...` of [`Makie.Figure`](@ref)", :axis => "use `kwargs...` of [`Makie.Axis`](@ref)", :legend => "use `kwargs...` of [`Makie.Legend`](@ref)", :colorbar => "use `kwargs...` of $cbarstring", - :visual => "use `kwargs...` of [`$(visuallink[cfgsymb])`](@ref)", + :visual => "use `kwargs...` of [`$(visuallink[cfg_symb])`](@ref)", ) for k = 1:length(fn) - namedtpl = Base.getfield(cfg,fn[k]) + namedtpl = Base.getfield(cfg, fn[k]) addlink = "" try addlink = "- *"*link[fn[k]]*"*" @@ -36,7 +37,7 @@ function _docstring(cfgsymb::Symbol) return """## Shared plot configuration options The shared plot options can be used as follows: - `type=(; key=value,...))` - for example `plot_x(..., layout=(show_legend=true, legend_position=:right))`. + `type = (; key=value, ...))` - for example `plot_x(..., layout = (show_legend=true, legend_position=:right))`. Multiple defaults will be cycled until match. $(out) diff --git a/src/plot_channelimage.jl b/src/plot_channelimage.jl index 70696177f..4fc7b91b3 100644 --- a/src/plot_channelimage.jl +++ b/src/plot_channelimage.jl @@ -1,9 +1,25 @@ -plot_channelimage( - data::Matrix{<:Real}, - position::Vector{Point{2,Float32}}, - ch_names::Vector{String}; - kwargs..., -) = plot_channelimage!(Figure(), data, position, ch_names; kwargs...) +""" + plot_channelimage!(f::Union{GridPosition, GridLayout, Figure}, data::Matrix{<:Real}, position::Vector{Point{2,Float32}}, ch_names::Vector{String}; kwargs...) + plot_channelimage(data::Matrix{<:Real}, position::Vector{Point{2,Float32}}, ch_names::Vector{String}; kwargs...) + +Channel image + +## Arguments: + +- `f::Union{GridPosition, GridLayout, Figure}`: Figure, GridLayout or GridPosition that the plot should be drawn into. +- `data::DataFrame`: DataFrame with data. +- `position` (Vector{Point{2,Float32}}): a vector with EEG layout coordinates. +- `ch_names` (Vector{String}): vector with channel names. + +$(_docstring(:channelimage)) + +## Return Value: +A figure displaying channel image + +""" + +plot_channelimage(data::Matrix{<:Real}, position::Vector{Point{2,Float32}}, ch_names::Vector{String}; kwargs...) = + plot_channelimage!(Figure(), data, position, ch_names; kwargs...) function plot_channelimage!( f::Union{GridPosition,GridLayout,Figure}, @@ -12,6 +28,9 @@ function plot_channelimage!( ch_names::Vector{String}; kwargs..., ) + config = PlotConfig(:channelimage) + config_kwargs!(config; kwargs...) + x = [i[1] for i in position] y = [i[2] for i in position] @@ -30,12 +49,12 @@ function plot_channelimage!( iz = mean(data, dims = 3)[b, :, 1]' gin = f[1, 1] = GridLayout() - ax = Axis(gin[1, 1], xlabel = "Time [s]", ylabel = "Channels") - hm = Makie.heatmap!(ix, iy, iz, colormap = "cork") + ax = Axis(gin[1, 1], xlabel = config.axis.xlabel, ylabel = config.axis.ylabel) + hm = Makie.heatmap!(ix, iy, iz, colormap = config.visual.colormap) ax.yticks = iy ax.ytickformat = xc -> c - ax.yticklabelsize = 14 + ax.yticklabelsize = config.axis.yticklabelsize - Makie.Colorbar(gin[1, 2], hm, label = "Voltage [µV]") + Makie.Colorbar(gin[1, 2], hm, label = config.colorbar.label, labelrotation = config.colorbar.labelrotation) return f end diff --git a/src/plot_circulareegtopoplot.jl b/src/plot_circulareegtopoplot.jl index 2a303e552..019d4d87f 100644 --- a/src/plot_circulareegtopoplot.jl +++ b/src/plot_circulareegtopoplot.jl @@ -1,6 +1,7 @@ """ - plot_circulareegtopoplot(data::DataFrame; kwargs...) plot_circulareegtopoplot!(f, data::DataFrame; kwargs...) + plot_circulareegtopoplot(data::DataFrame; kwargs...) + Plot a circular EEG topoplot. ## Arguments: diff --git a/src/plot_erpgrid.jl b/src/plot_erpgrid.jl index 06abdf879..4af354e4f 100644 --- a/src/plot_erpgrid.jl +++ b/src/plot_erpgrid.jl @@ -12,8 +12,9 @@ Plot an ERP image. - `drawlabels` (bool, `false`): draw channels labels over each waveform. - `times`: (Vector, `1:size(data, 2)`): vector of size(). + ## Return Value: -The input `f` +The figure displaying ERP grid """ # no figure? diff --git a/src/plot_erpimage.jl b/src/plot_erpimage.jl index bd1a9de3b..dcfca82c8 100644 --- a/src/plot_erpimage.jl +++ b/src/plot_erpimage.jl @@ -8,15 +8,16 @@ Plot an ERP image. ## Arguments: - `f::Union{GridPosition, GridLayout, Figure}`: Figure or GridPosition that the plot should be drawn into -- `plot::Matrix{Float64}`: Data for the plot visualization +- `plotData::Matrix{Float64}`: Data for the plot visualization ## Keyword Arguments -- `erpblur` (Number, `10`): number indicating how much blur is applied to the image; using Gaussian blur of the ImageFiltering module. +`erpBlur` (Number, `10`) - Number indicating how much blur is applied to the image; using Gaussian blur of the ImageFiltering module. Non-Positive values deactivate the blur. -- `sortix` (default: `nothing`): . -- `sortvalues` (bool, `false`): parameter over which plot will be sorted. Using sortperm() of Base Julia. - - sortperm() computes a permutation of the array's indices that puts the array into sorted order. -- `meanplot` (bool, `false`): Indicating whether the plot should add a line plot below the ERP image, showing the mean of the data. + +`sortvalues` (bool, `false`) - parameter over which plot will be sorted. Using sortperm() of Base Julia +(sortperm() computes a permutation of the array's indices that puts the array into sorted order). + +`meanPlot`: (bool, `false`) - Indicating whether the plot should add a line plot below the ERP image, showing the mean of the data. $(_docstring(:erpimage)) @@ -25,26 +26,26 @@ The input `f` """ # no times + no figure? -plot_erpimage(plot::Matrix{<:Real}; kwargs...) = - plot_erpimage!(Figure(), plot; kwargs...) +plot_erpimage(plotData::Matrix{<:Real}; kwargs...) = + plot_erpimage!(Figure(), plotData; kwargs...) # no times? -plot_erpimage!(f::Union{GridPosition,GridLayout,Figure}, plot::Matrix{<:Real}; kwargs...) = - plot_erpimage!(f, 1:size(plot, 1), plot; kwargs...) +plot_erpimage!(f::Union{GridPosition,GridLayout,Figure}, plotData::Matrix{<:Real}; kwargs...) = + plot_erpimage!(f, 1:size(plotData, 1), plotData; kwargs...) # no figure? -plot_erpimage(times::AbstractVector, plot::Matrix{<:Real}; kwargs...) = - plot_erpimage!(Figure(), times, plot; kwargs...) +plot_erpimage(times::AbstractVector, plotData::Matrix{<:Real}; kwargs...) = + plot_erpimage!(Figure(), times, plotData; kwargs...) function plot_erpimage!( f::Union{GridPosition,GridLayout,Figure}, times::AbstractVector, - plot::Matrix{<:Real}; + plotData::Matrix{<:Real}; sortvalues = nothing, sortix = nothing, - meanplot = false, - erpblur = 10, + meanPlot = false, + erpBlur = 10, kwargs..., ) config = PlotConfig(:erpimage) @@ -55,7 +56,7 @@ function plot_erpimage!( ax = Axis(f[1:4, 1]; config.axis...) if isnothing(sortix) if isnothing(sortvalues) - sortix = 1:size(plot, 2) + sortix = 1:size(plotData, 2) else sortix = sortperm(sortvalues) @@ -63,8 +64,8 @@ function plot_erpimage!( end filtered_data = UnfoldMakie.imfilter( - plot[:, sortix], - UnfoldMakie.Kernel.gaussian((0, max(erpblur, 0))), + plotData[:, sortix], + UnfoldMakie.Kernel.gaussian((0, max(erpBlur, 0))), ) yvals = 1:size(filtered_data, 2) @@ -76,22 +77,22 @@ function plot_erpimage!( UnfoldMakie.applyLayoutSettings!(config; fig = f, hm = hm, ax = ax, plotArea = (4, 1)) - if meanplot + if meanPlot # UserInput subConfig = deepcopy(config) config_kwargs!( subConfig; - layout = (; show_legend = false), + layout = (; showLegend = false), axis = (; ylabel = config.colorbar.label === nothing ? "" : config.colorbar.label ), ) axisOffset = - (config.layout.show_legend && config.layout.legend_position == :bottom) ? 1 : 0 + (config.layout.showLegend && config.layout.legendPosition == :bottom) ? 1 : 0 subAxis = Axis(f[5+axisOffset, 1]; subConfig.axis...) - lines!(subAxis, mean(plot, dims = 2)[:, 1]) + lines!(subAxis, mean(plotData, dims = 2)[:, 1]) applyLayoutSettings!(subConfig; fig = f, ax = subAxis) end diff --git a/src/plot_topoplot.jl b/src/plot_topoplot.jl index 166925157..c2f36fbd9 100644 --- a/src/plot_topoplot.jl +++ b/src/plot_topoplot.jl @@ -1,6 +1,6 @@ """ plot_topoplot!(f::Union{GridPosition, GridLayout, Figure}, data, ; positions=nothing, labels=nothing,kwargs...) - plot_topoplot(data,; positions=nothing, labels=nothing, kwargs...) + plot_topoplot(data; positions=nothing, labels=nothing, kwargs...) Plot a topo plot. ## Arguments: diff --git a/src/plot_topoplotseries.jl b/src/plot_topoplotseries.jl index f920e093d..f8a862419 100644 --- a/src/plot_topoplotseries.jl +++ b/src/plot_topoplotseries.jl @@ -1,5 +1,5 @@ """ - plot_topoplotseries!(f::Union{GridPosition, GridLayout, Figure}, data::DataFrame, Δbin::Real; kwargs...) + plot_topoplotseries(f::Union{GridPosition, GridLayout, Figure}, data::DataFrame, Δbin::Real; kwargs...) plot_topoplotseries!(data::DataFrame, Δbin::Real; kwargs...) Multiple miniature topoplots in regular distances @@ -77,7 +77,6 @@ function plot_topoplotseries!( f[1, end+1], colormap = d.colormap, colorrange = d.colorrange, - height = config.colorbar.height, flipaxis = config.colorbar.flipaxis, labelrotation = config.colorbar.labelrotation , label = config.colorbar.label, @@ -89,7 +88,6 @@ function plot_topoplotseries!( f[:, :][1, length(axlist)+1], colormap = d.colormap, colorrange = d.colorrange, - height = config.colorbar.height, flipaxis = config.colorbar.flipaxis, labelrotation = config.colorbar.labelrotation , label = config.colorbar.label, @@ -98,4 +96,4 @@ function plot_topoplotseries!( end return f -end +end \ No newline at end of file diff --git a/src/plotconfig.jl b/src/plotconfig.jl index 4c3febf4a..ee29eee37 100644 --- a/src/plotconfig.jl +++ b/src/plotconfig.jl @@ -59,7 +59,7 @@ end Takes a kwargs named tuple of Key => NamedTuple and merges the fields with the defaults """ function config_kwargs!(cfg::PlotConfig; kwargs...) - is_namedtuple = [isa(t,NamedTuple) for t in values(kwargs)] + is_namedtuple = [isa(t, NamedTuple) for t in values(kwargs)] @debug is_namedtuple @assert(all(is_namedtuple), """ Keyword argument specification (kwargs...) Specified config groups must be NamedTuples', but $(keys(kwargs)[.!is_namedtuple]) was not. @@ -70,7 +70,7 @@ function config_kwargs!(cfg::PlotConfig; kwargs...) plot_example(...; layout = (use_colorbar=true)) The first is correct and creates a NamedTuple as required. The second is wrong and its call is ignored.""") - list = fieldnames(PlotConfig)#[:layout,:visual,:mapping,:legend,:colorbar,:axis] + list = fieldnames(PlotConfig) #[:layout, :visual, :mapping, :legend, :colorbar, :axis] keyList = collect(keys(kwargs)) :extra ∈ keyList ? @warn("Extra is deprecated in 0.4 and extra-keyword args have to be used directly as key-word arguments") : "" applyTo = keyList[in.(keyList, Ref(list))] @@ -152,7 +152,6 @@ function PlotConfig(T::Val{:topoplotseries}) cfg, layout = (use_colorbar = true,), colorbar = (; - #height = 300, flipaxis = true, labelrotation = -π/2, label = "Voltage [µV]" @@ -202,6 +201,17 @@ function PlotConfig(T::Val{:erp}) return cfg end +function PlotConfig(T::Val{:channelimage}) + cfg = PlotConfig() + config_kwargs!( + cfg; + #layout = (; use_colorbar = true), + colorbar = (; label = "Voltage [µV]", labelrotation = 4.7), + axis = (xlabel = "Time [s]", ylabel = "Channels", yticklabelsize = 14), + visual = (; colormap = Reverse("RdBu")), #cork + ) + return cfg +end function PlotConfig(T::Val{:erpimage}) cfg = PlotConfig() config_kwargs!( diff --git a/test/runtests.jl b/test/runtests.jl index e85af7104..069c96c84 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -15,10 +15,14 @@ end include("test_butterfly.jl") end -@testset "ERP Image" begin +@testset "ERP image" begin include("test_erpimage.jl") end +@testset "Channel image" begin + include("test_channelimage.jl") +end + @testset "Topoplot" begin include("test_topoplot.jl") end diff --git a/test/test_channelimage.jl b/test/test_channelimage.jl index 6f9ffed52..77058c32f 100644 --- a/test/test_channelimage.jl +++ b/test/test_channelimage.jl @@ -6,6 +6,12 @@ raw_ch_names = ["FP1", "F3", "F7", "FC3", "C3", "C5", "P3", "P7", "P9", "PO7", "C4", "C6", "P4", "P8", "P10", "PO8", "PO4", "O2"] @testset "channel image basic" begin - plot_channelimage(data, pos, raw_ch_names) + plot_channelimage(data, pos, raw_ch_names; ) + +end + +@testset "channel image basic" begin + f = Figure() + plot_channelimage!(f, data[:, :, 1], positions[1:30], raw_ch_names; ) end diff --git a/test/test_complexplots.jl b/test/test_complexplots.jl index 18a8e4778..83209e538 100644 --- a/test/test_complexplots.jl +++ b/test/test_complexplots.jl @@ -19,6 +19,9 @@ times = -0.099609375:0.001953125:1.0 data, positions = TopoPlots.example_data() df = UnfoldMakie.eeg_matrix_to_dataframe(data[:,:,1], string.(1:length(positions))); + raw_ch_names = ["FP1", "F3", "F7", "FC3", "C3", "C5", "P3", "P7", "P9", "PO7", +"PO3", "O1", "Oz", "Pz", "CPz", "FP2", "Fz", "F4", "F8", "FC4", "FCz", "Cz", +"C4", "C6", "P4", "P8", "P10", "PO8", "PO4", "O2"] data_erp, evts = UnfoldSim.predef_eeg(; noiselevel = 12, return_epoched = true) data_erp = reshape(data_erp, (1, size(data_erp)...)) @@ -47,7 +50,7 @@ evts.Δlatency = diff(vcat(evts.latency, 0)) dat_e = dat_e[1,:,:] plot_erpimage!(gf, times, dat_e; sortvalues=evts.Δlatency) - #plot_erpimage!(gf, times, d_singletrial) + plot_channelimage!(gg, data[:, :, 1], positions[1:30], raw_ch_names; ) plot_parallelcoordinates!(gh, uf_5chan, [1, 2, 3, 4, 5]; mapping=(; color=:coefname), layout=(; legend_position=:bottom), legend=(; tellwidth =false)) From 7daf0b9ad072e34702d69621958decff7d86c87c Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Fri, 24 Nov 2023 17:27:53 +0000 Subject: [PATCH 08/12] strange bug fix --- src/plot_erpimage.jl | 44 +++++++++++++++++++++---------------------- src/plotconfig.jl | 43 ++++++++++++++++++------------------------ test/test_erpimage.jl | 38 +++++++------------------------------ 3 files changed, 46 insertions(+), 79 deletions(-) diff --git a/src/plot_erpimage.jl b/src/plot_erpimage.jl index dcfca82c8..2f7e99ae5 100644 --- a/src/plot_erpimage.jl +++ b/src/plot_erpimage.jl @@ -8,16 +8,15 @@ Plot an ERP image. ## Arguments: - `f::Union{GridPosition, GridLayout, Figure}`: Figure or GridPosition that the plot should be drawn into -- `plotData::Matrix{Float64}`: Data for the plot visualization +- `plot::Matrix{Float64}`: Data for the plot visualization ## Keyword Arguments -`erpBlur` (Number, `10`) - Number indicating how much blur is applied to the image; using Gaussian blur of the ImageFiltering module. +- `erpblur` (Number, `10`): number indicating how much blur is applied to the image; using Gaussian blur of the ImageFiltering module. Non-Positive values deactivate the blur. - -`sortvalues` (bool, `false`) - parameter over which plot will be sorted. Using sortperm() of Base Julia -(sortperm() computes a permutation of the array's indices that puts the array into sorted order). - -`meanPlot`: (bool, `false`) - Indicating whether the plot should add a line plot below the ERP image, showing the mean of the data. +- `sortix` (default: `nothing`): . +- `sortvalues` (bool, `false`): parameter over which plot will be sorted. Using sortperm() of Base Julia. + - sortperm() computes a permutation of the array's indices that puts the array into sorted order. +- `meanplot` (bool, `false`): Indicating whether the plot should add a line plot below the ERP image, showing the mean of the data. $(_docstring(:erpimage)) @@ -26,26 +25,25 @@ The input `f` """ # no times + no figure? -plot_erpimage(plotData::Matrix{<:Real}; kwargs...) = - plot_erpimage!(Figure(), plotData; kwargs...) +plot_erpimage(plot::Matrix{<:Real}; kwargs...) = plot_erpimage!(Figure(), plot; kwargs...) # no times? -plot_erpimage!(f::Union{GridPosition,GridLayout,Figure}, plotData::Matrix{<:Real}; kwargs...) = - plot_erpimage!(f, 1:size(plotData, 1), plotData; kwargs...) +plot_erpimage!(f::Union{GridPosition,GridLayout,Figure}, plot::Matrix{<:Real}; kwargs...) = + plot_erpimage!(f, 1:size(plot, 1), plot; kwargs...) # no figure? -plot_erpimage(times::AbstractVector, plotData::Matrix{<:Real}; kwargs...) = - plot_erpimage!(Figure(), times, plotData; kwargs...) +plot_erpimage(times::AbstractVector, plot::Matrix{<:Real}; kwargs...) = + plot_erpimage!(Figure(), times, plot; kwargs...) function plot_erpimage!( f::Union{GridPosition,GridLayout,Figure}, times::AbstractVector, - plotData::Matrix{<:Real}; + plot::Matrix{<:Real}; sortvalues = nothing, sortix = nothing, - meanPlot = false, - erpBlur = 10, + meanplot = false, + erpblur = 10, kwargs..., ) config = PlotConfig(:erpimage) @@ -56,7 +54,7 @@ function plot_erpimage!( ax = Axis(f[1:4, 1]; config.axis...) if isnothing(sortix) if isnothing(sortvalues) - sortix = 1:size(plotData, 2) + sortix = 1:size(plot, 2) else sortix = sortperm(sortvalues) @@ -64,8 +62,8 @@ function plot_erpimage!( end filtered_data = UnfoldMakie.imfilter( - plotData[:, sortix], - UnfoldMakie.Kernel.gaussian((0, max(erpBlur, 0))), + plot[:, sortix], + UnfoldMakie.Kernel.gaussian((0, max(erpblur, 0))), ) yvals = 1:size(filtered_data, 2) @@ -77,22 +75,22 @@ function plot_erpimage!( UnfoldMakie.applyLayoutSettings!(config; fig = f, hm = hm, ax = ax, plotArea = (4, 1)) - if meanPlot + if meanplot # UserInput subConfig = deepcopy(config) config_kwargs!( subConfig; - layout = (; showLegend = false), + layout = (; show_legend = false), axis = (; ylabel = config.colorbar.label === nothing ? "" : config.colorbar.label ), ) axisOffset = - (config.layout.showLegend && config.layout.legendPosition == :bottom) ? 1 : 0 + (config.layout.show_legend && config.layout.legend_position == :bottom) ? 1 : 0 subAxis = Axis(f[5+axisOffset, 1]; subConfig.axis...) - lines!(subAxis, mean(plotData, dims = 2)[:, 1]) + lines!(subAxis, mean(plot, dims = 2)[:, 1]) applyLayoutSettings!(subConfig; fig = f, ax = subAxis) end diff --git a/src/plotconfig.jl b/src/plotconfig.jl index ee29eee37..4421e66a2 100644 --- a/src/plotconfig.jl +++ b/src/plotconfig.jl @@ -51,28 +51,31 @@ function PlotConfig()# defaults tellheight = false, ), ) - end - """ Takes a kwargs named tuple of Key => NamedTuple and merges the fields with the defaults """ function config_kwargs!(cfg::PlotConfig; kwargs...) is_namedtuple = [isa(t, NamedTuple) for t in values(kwargs)] @debug is_namedtuple - @assert(all(is_namedtuple), - """ Keyword argument specification (kwargs...) Specified config groups must be NamedTuples', but $(keys(kwargs)[.!is_namedtuple]) was not. - Maybe you forgot the semicolon (;) at the beginning of your specification? Compare these strings: - - plot_example(...; layout = (; use_colorbar=true)) - - plot_example(...; layout = (use_colorbar=true)) - - The first is correct and creates a NamedTuple as required. The second is wrong and its call is ignored.""") + @assert( + all(is_namedtuple), + """ Keyword argument specification (kwargs...) Specified config groups must be NamedTuples', but $(keys(kwargs)[.!is_namedtuple]) was not. + Maybe you forgot the semicolon (;) at the beginning of your specification? Compare these strings: + + plot_example(...; layout = (; use_colorbar=true)) + + plot_example(...; layout = (use_colorbar=true)) + + The first is correct and creates a NamedTuple as required. The second is wrong and its call is ignored.""" + ) list = fieldnames(PlotConfig) #[:layout, :visual, :mapping, :legend, :colorbar, :axis] keyList = collect(keys(kwargs)) - :extra ∈ keyList ? @warn("Extra is deprecated in 0.4 and extra-keyword args have to be used directly as key-word arguments") : "" + :extra ∈ keyList ? + @warn( + "Extra is deprecated in 0.4 and extra-keyword args have to be used directly as key-word arguments" + ) : "" applyTo = keyList[in.(keyList, Ref(list))] for k ∈ applyTo setfield!(cfg, k, merge(getfield(cfg, k), kwargs[k])) @@ -105,13 +108,7 @@ end function PlotConfig(T::Val{:topoarray}) cfg = PlotConfig(:erp) - config_kwargs!( - cfg; - layout = (;), - colorbar = (;), - mapping = (;), - axis = (;), - ) + config_kwargs!(cfg; layout = (;), colorbar = (;), mapping = (;), axis = (;)) return cfg end @@ -151,11 +148,7 @@ function PlotConfig(T::Val{:topoplotseries}) config_kwargs!( cfg, layout = (use_colorbar = true,), - colorbar = (; - flipaxis = true, - labelrotation = -π/2, - label = "Voltage [µV]" - ), + colorbar = (; flipaxis = true, labelrotation = -π / 2, label = "Voltage [µV]"), visual = (; label_text = false # true doesnt work again ), @@ -195,7 +188,7 @@ function PlotConfig(T::Val{:erp}) config_kwargs!( cfg; mapping = (; color = (:color, :coefname, nothing)), - layout = (; show_legend = true, hidespines = (:r, :t)), + layout = (; show_legend = true, hidespines = (:r, :t)), legend = (; framevisible = false), ) diff --git a/test/test_erpimage.jl b/test/test_erpimage.jl index b718fbb00..612f8267a 100644 --- a/test/test_erpimage.jl +++ b/test/test_erpimage.jl @@ -23,35 +23,11 @@ end @testset "testing better sorting" begin using UnfoldSim - dat,evts = UnfoldSim.predef_eeg(;onset=LogNormalOnset(μ=3.5,σ=0.4),noiselevel=5) - dat_e,times = Unfold.epoch(dat,evts,[-0.1,1],100) - evts,dat_e = Unfold.dropMissingEpochs(evts,dat_e) - evts.Δlatency = diff(vcat(evts.latency,0)) - dat_e = dat_e[1,:,:] - plot_erpimage(times,dat_e;sortvalues=evts.Δlatency) + dat, evts = + UnfoldSim.predef_eeg(; onset = LogNormalOnset(μ = 3.5, σ = 0.4), noiselevel = 5) + dat_e, times = Unfold.epoch(dat, evts, [-0.1, 1], 100) + evts, dat_e = Unfold.dropMissingEpochs(evts, dat_e) + evts.Δlatency = diff(vcat(evts.latency, 0)) + dat_e = dat_e[1, :, :] + plot_erpimage(times, dat_e; sortvalues = evts.Δlatency) end -#= -@testset "testing better sorting" begin - - using PyMNE - using Unfold - using CSV - - - evts = CSV.read("/store/data/WLFO/derivatives/preproc_agert/sub-20/eeg/sub-20_task-WLFO_events.tsv", DataFrame) - evts.latency = evts.onset .* 512 - evts_fix = subset(evts, :type => x -> x .== "fixation") - raw = PyMNE.io.read_raw_eeglab("/store/data/WLFO/derivatives/preproc_agert/sub-20/eeg/sub-20_task-WLFO_eeg.set") - d, times = Unfold.epoch(pyconvert(Array, raw.get_data(units="uV")), evts_fix, (-0.1, 1), 512) - coalesce.(d[1, :, :], NaN) - f = Figure() - d_nan = coalesce.(d[1, :, :], NaN) - v = (; colorrange=(-10, 10)) - @show size(d_nan) - plot_erpimage!(f[1, 1], times, d_nan, visual=v) - plot_erpimage!(f[1, 2], times, d_nan; sortvalues=diff(evts_fix.onset ./ 100), visual=v) - plot_erpimage!(f[2, 1], times, d_nan; sortvalues=evts_fix.sac_startpos_x, visual=v) - plot_erpimage!(f[2, 2], times, d_nan; sortvalues=evts_fix.sac_amplitude, visual=v) - f -end -=# From 05515f91433f9f064477b6257e9a74c24c6fb9be Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Fri, 24 Nov 2023 17:42:24 +0000 Subject: [PATCH 09/12] small inconsistency in tests --- test/test_channelimage.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_channelimage.jl b/test/test_channelimage.jl index 77058c32f..ed808411c 100644 --- a/test/test_channelimage.jl +++ b/test/test_channelimage.jl @@ -10,8 +10,8 @@ raw_ch_names = ["FP1", "F3", "F7", "FC3", "C3", "C5", "P3", "P7", "P9", "PO7", end -@testset "channel image basic" begin +@testset "channel image with Figure" begin f = Figure() - plot_channelimage!(f, data[:, :, 1], positions[1:30], raw_ch_names; ) + plot_channelimage!(f, data, pos, raw_ch_names; ) end From 3fb638ec2a44a0a2b66076558f29caa0d2e506d0 Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Fri, 24 Nov 2023 18:10:29 +0000 Subject: [PATCH 10/12] reverse ERP image trials and sorted ERP image into combined plot --- docs/src/how_to/mult_vis_in_fig.md | 12 +++++++++--- docs/src/tutorials/erpimage.md | 2 +- test/test_complexplots.jl | 2 +- test/test_erpimage.jl | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/docs/src/how_to/mult_vis_in_fig.md b/docs/src/how_to/mult_vis_in_fig.md index 1df4c4f51..feb4a3375 100644 --- a/docs/src/how_to/mult_vis_in_fig.md +++ b/docs/src/how_to/mult_vis_in_fig.md @@ -17,9 +17,15 @@ uf_deconv = example_data("UnfoldLinearModelContinuousTime") uf = example_data("UnfoldLinearModel") results = coeftable(uf) uf_5chan = example_data("UnfoldLinearModelMultiChannel") -d_singletrial, _ = UnfoldSim.predef_eeg(; return_epoched=true) -times = -0.099609375:0.001953125:1.0 data, positions = TopoPlots.example_data() +dat, evts = UnfoldSim.predef_eeg(; + onset=LogNormalOnset(μ=3.5, σ=0.4), + noiselevel=5 + ) +dat_e, times = Unfold.epoch(dat, evts, [-0.1, 1], 100) +evts, dat_e = Unfold.dropMissingEpochs(evts, dat_e) +evts.Δlatency = diff(vcat(evts.latency, 0)) *-1 +dat_e = dat_e[1, :, :] nothing #hide ``` This section discusses how users can incorporate multiple plots into a single figure. @@ -81,7 +87,7 @@ plot_erp!(f[2, 4:5], res_effects; categorical_color=false, categorical_group=tru plot_parallelcoordinates!(f[3, 2:3], uf_5chan, [1, 2, 3, 4, 5]; mapping=(; color=:coefname), layout=(; legend_position=:bottom)) -plot_erpimage!(f[1, 4:5], times, d_singletrial) +plot_erpimage!(f[1, 4:5], times, dat_e; sortvalues=evts.Δlatency) plot_circulareegtopoplot!(f[3:4, 4:5], d_topo[in.(d_topo.time, Ref(-0.3:0.1:0.5)), :]; positions=positions, predictor=:time, predictor_bounds=[-0.3, 0.5]) diff --git a/docs/src/tutorials/erpimage.md b/docs/src/tutorials/erpimage.md index 18dcb15da..94ecc9bb3 100644 --- a/docs/src/tutorials/erpimage.md +++ b/docs/src/tutorials/erpimage.md @@ -51,7 +51,7 @@ First, generate a data. Second, specify the necessary sorting parameter. ) dat_e, times = Unfold.epoch(dat, evts, [-0.1,1], 100) evts, dat_e = Unfold.dropMissingEpochs(evts, dat_e) - evts.Δlatency = diff(vcat(evts.latency, 0)) + evts.Δlatency = diff(vcat(evts.latency, 0)) *-1 dat_e = dat_e[1,:,:] plot_erpimage(times, dat_e; sortvalues=evts.Δlatency) diff --git a/test/test_complexplots.jl b/test/test_complexplots.jl index 83209e538..3a9f4edae 100644 --- a/test/test_complexplots.jl +++ b/test/test_complexplots.jl @@ -47,7 +47,7 @@ dat, evts = UnfoldSim.predef_eeg(;onset=LogNormalOnset(μ=3.5, σ=0.4), noiselevel = 5) dat_e, times = Unfold.epoch(dat,evts, [-0.1,1], 100) evts, dat_e = Unfold.dropMissingEpochs(evts, dat_e) - evts.Δlatency = diff(vcat(evts.latency, 0)) + evts.Δlatency = diff(vcat(evts.latency, 0)) *-1 dat_e = dat_e[1,:,:] plot_erpimage!(gf, times, dat_e; sortvalues=evts.Δlatency) plot_channelimage!(gg, data[:, :, 1], positions[1:30], raw_ch_names; ) diff --git a/test/test_erpimage.jl b/test/test_erpimage.jl index 612f8267a..e2b2a60e3 100644 --- a/test/test_erpimage.jl +++ b/test/test_erpimage.jl @@ -27,7 +27,7 @@ end UnfoldSim.predef_eeg(; onset = LogNormalOnset(μ = 3.5, σ = 0.4), noiselevel = 5) dat_e, times = Unfold.epoch(dat, evts, [-0.1, 1], 100) evts, dat_e = Unfold.dropMissingEpochs(evts, dat_e) - evts.Δlatency = diff(vcat(evts.latency, 0)) + evts.Δlatency = diff(vcat(evts.latency, 0)) *-1 dat_e = dat_e[1, :, :] plot_erpimage(times, dat_e; sortvalues = evts.Δlatency) end From 7c049813660f5dd1542a57c6f2c1b90883f333b1 Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Wed, 29 Nov 2023 16:58:39 +0000 Subject: [PATCH 11/12] more example_data --- docs/example_data.jl | 8 ++++ docs/src/how_to/mult_vis_in_fig.md | 9 +--- test/test_erp.jl | 76 +++--------------------------- test/test_erpimage.jl | 9 +--- 4 files changed, 18 insertions(+), 84 deletions(-) diff --git a/docs/example_data.jl b/docs/example_data.jl index 92106a3e1..020593727 100644 --- a/docs/example_data.jl +++ b/docs/example_data.jl @@ -96,6 +96,14 @@ function example_data(example = "TopoPlots.jl") end df.time = range(-0.3, 0.5, step = 1 / 500)[Int.(df.time)] return df, chanlocs + elseif example == "sort_data" + dat, evts = + UnfoldSim.predef_eeg(; onset = LogNormalOnset(μ = 3.5, σ = 0.4), noiselevel = 5) + dat_e, times = Unfold.epoch(dat, evts, [-0.1, 1], 100) + evts, dat_e = Unfold.dropMissingEpochs(evts, dat_e) + evts.Δlatency = diff(vcat(evts.latency, 0)) *-1 + dat_e = dat_e[1, :, :] + return dat_e, evts, times else error("unknown example data") end diff --git a/docs/src/how_to/mult_vis_in_fig.md b/docs/src/how_to/mult_vis_in_fig.md index feb4a3375..35f9bc6f8 100644 --- a/docs/src/how_to/mult_vis_in_fig.md +++ b/docs/src/how_to/mult_vis_in_fig.md @@ -18,14 +18,7 @@ uf = example_data("UnfoldLinearModel") results = coeftable(uf) uf_5chan = example_data("UnfoldLinearModelMultiChannel") data, positions = TopoPlots.example_data() -dat, evts = UnfoldSim.predef_eeg(; - onset=LogNormalOnset(μ=3.5, σ=0.4), - noiselevel=5 - ) -dat_e, times = Unfold.epoch(dat, evts, [-0.1, 1], 100) -evts, dat_e = Unfold.dropMissingEpochs(evts, dat_e) -evts.Δlatency = diff(vcat(evts.latency, 0)) *-1 -dat_e = dat_e[1, :, :] +dat_e, evts, times = example_data("sort_data") nothing #hide ``` This section discusses how users can incorporate multiple plots into a single figure. diff --git a/test/test_erp.jl b/test/test_erp.jl index f7549c9ee..42ba53bfc 100644 --- a/test/test_erp.jl +++ b/test/test_erp.jl @@ -1,16 +1,6 @@ +include("../docs/example_data.jl") @testset "basic with results" begin - data, evts = UnfoldSim.predef_eeg(; noiselevel = 12, return_epoched = true) - data = reshape(data, (1, size(data)...)) - f = @formula 0 ~ 1 + condition + continuous - se_solver = (x, y) -> Unfold.solver_default(x, y, stderror = true) - - m = fit( - UnfoldModel, - Dict(Any => (f, range(0, step = 1 / 100, length = size(data, 2)))), - evts, - data, - solver = se_solver, - ) + m = example_data("UnfoldLinearModel") results = coeftable(m) res_effects = effects(Dict(:continuous => -5:0.5:5), m) @@ -20,18 +10,7 @@ end @testset "basic with res_effects without colorbar" begin - data, evts = UnfoldSim.predef_eeg(; noiselevel = 12, return_epoched = true) - data = reshape(data, (1, size(data)...)) - f = @formula 0 ~ 1 + condition + continuous - se_solver = (x, y) -> Unfold.solver_default(x, y, stderror = true) - - m = fit( - UnfoldModel, - Dict(Any => (f, range(0, step = 1 / 100, length = size(data, 2)))), - evts, - data, - solver = se_solver, - ) + m = example_data("UnfoldLinearModel") results = coeftable(m) res_effects = effects(Dict(:continuous => -5:0.5:5), m) @@ -47,18 +26,7 @@ end end @testset "basic with res_effects" begin - data, evts = UnfoldSim.predef_eeg(; noiselevel = 12, return_epoched = true) - data = reshape(data, (1, size(data)...)) - f = @formula 0 ~ 1 + condition + continuous - se_solver = (x, y) -> Unfold.solver_default(x, y, stderror = true) - - m = fit( - UnfoldModel, - Dict(Any => (f, range(0, step = 1 / 100, length = size(data, 2)))), - evts, - data, - solver = se_solver, - ) + m = example_data("UnfoldLinearModel") results = coeftable(m) res_effects = effects(Dict(:continuous => -5:0.5:5), m) @@ -99,17 +67,7 @@ end @testset "erp plot with error bands" begin - data_erp, evts = UnfoldSim.predef_eeg(; noiselevel = 12, return_epoched = true) - data_erp = reshape(data_erp, (1, size(data_erp)...)) - f = @formula 0 ~ 1 + condition + continuous - se_solver = (x, y) -> Unfold.solver_default(x, y, stderror = true); - m = fit( - UnfoldModel, - Dict(Any => (f, range(0, step = 1 / 100, length = size(data_erp, 2)))), - evts, - data_erp, - solver = se_solver, - ) + m = example_data("UnfoldLinearModel") results = coeftable(m) res_effects = effects(Dict(:continuous => -5:0.5:5), m); @@ -120,17 +78,7 @@ end f = Figure(resolution=(1200, 1400)) ga = f[1, 1] = GridLayout() - data_erp, evts = UnfoldSim.predef_eeg(; noiselevel = 12, return_epoched = true) - data_erp = reshape(data_erp, (1, size(data_erp)...)) - form = @formula 0 ~ 1 + condition + continuous - se_solver = (x, y) -> Unfold.solver_default(x, y, stderror = true); - m = fit( - UnfoldModel, - Dict(Any => (form, range(0, step = 1 / 100, length = size(data_erp, 2)))), - evts, - data_erp, - solver = se_solver, - ) + m = example_data("UnfoldLinearModel") results = coeftable(m) res_effects = effects(Dict(:continuous => -5:0.5:5), m); @@ -143,17 +91,7 @@ end f = Figure(resolution=(1200, 1400)) ga = f[1, 1] = GridLayout() - data_erp, evts = UnfoldSim.predef_eeg(; noiselevel = 12, return_epoched = true) - data_erp = reshape(data_erp, (1, size(data_erp)...)) - form = @formula 0 ~ 1 + condition + continuous - se_solver = (x, y) -> Unfold.solver_default(x, y, stderror = true); - m = fit( - UnfoldModel, - Dict(Any => (form, range(0, step = 1 / 100, length = size(data_erp, 2)))), - evts, - data_erp, - solver = se_solver, - ) + m = example_data("UnfoldLinearModel") results = coeftable(m) res_effects = effects(Dict(:continuous => -5:0.5:5), m); diff --git a/test/test_erpimage.jl b/test/test_erpimage.jl index e2b2a60e3..cacbfa100 100644 --- a/test/test_erpimage.jl +++ b/test/test_erpimage.jl @@ -22,12 +22,7 @@ end end @testset "testing better sorting" begin - using UnfoldSim - dat, evts = - UnfoldSim.predef_eeg(; onset = LogNormalOnset(μ = 3.5, σ = 0.4), noiselevel = 5) - dat_e, times = Unfold.epoch(dat, evts, [-0.1, 1], 100) - evts, dat_e = Unfold.dropMissingEpochs(evts, dat_e) - evts.Δlatency = diff(vcat(evts.latency, 0)) *-1 - dat_e = dat_e[1, :, :] + include("../docs/example_data.jl") + dat_e, evts, times = example_data("sort_data") plot_erpimage(times, dat_e; sortvalues = evts.Δlatency) end From b40c64a5ccb34041cd553eb6b94a6896fa9e9a00 Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Wed, 29 Nov 2023 16:59:29 +0000 Subject: [PATCH 12/12] del --- runner.jl | 62 ------------------------------------------------------- 1 file changed, 62 deletions(-) delete mode 100644 runner.jl diff --git a/runner.jl b/runner.jl deleted file mode 100644 index 8384b9042..000000000 --- a/runner.jl +++ /dev/null @@ -1,62 +0,0 @@ -using Pkg -#Pkg.activate("/store/users/mikheev/projects/unfold_dev/") -#Pkg.activate("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie") -Pkg.status() - -Pkg.instantiate() -Pkg.resolve() - - -pwd() -#include("dev/UnfoldMakie/test/test_toposeries.jl") -#include("test/test_toposeries.jl") - - -Pkg.activate("/store/users/mikheev/projects/unfold_dev/") -#Pkg.activate("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/test/") - -include("test/setup.jl") -using UnfoldMakie - -include("test/test_toposeries.jl") -#include("test/test_plot_circulareegtopoplot.jl") - -include("test/runtests.jl") - -include("test/test_erpimage.jl") -include("test/test_topoplot.jl") -include("test/test_all.jl") - -# docs] - -#Pkg.activate("/store/users/mikheev/projects/unfold_dev/UnfoldMakie/docs/") -#include("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/docs/make.jl") - -using JuliaFormatter -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/src/eeg_series.jl") -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/src/plot_circulareegtopoplot.jl") -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/src/plot_designmatrix.jl") -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/src/plot_erp.jl") -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/src/plot_erpimage.jl") -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/src/plot_parallelcoordinates.jl") -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/src/plot_topoplot.jl") -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/src/plot_topoplotseries.jl") -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/src/plot_erpgrid.jl") -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/src/plot_channelimage.jl") -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/src/plotconfig.jl") -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/src/UnfoldMakie.jl") - - -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/docs/src/tutorials/butterfly.md") -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/docs/src/literate/tutorials/circTopo.jl") -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/docs/src/literate/tutorials/erp.jl") -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/docs/example_data.jl") -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/docs/make.jl") -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/docs/run_liveserver.jl") - -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/test/test_dm.jl") -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/test/test_erp.jl") -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/test/test_erpimage.jl") -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/test/test_erpgrid.jl") -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/test/test_butterfly.jl") -format_file("/store/users/mikheev/projects/unfold_dev/dev/UnfoldMakie/test/test_toposeries.jl")