From ad194f863f0a8e19a9e428ef0c906d9692977892 Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Wed, 2 Aug 2023 16:04:47 +0000 Subject: [PATCH 01/17] g --- src/plot_topoplotseries.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plot_topoplotseries.jl b/src/plot_topoplotseries.jl index 3d41210b8..c67938b37 100644 --- a/src/plot_topoplotseries.jl +++ b/src/plot_topoplotseries.jl @@ -37,7 +37,7 @@ function plot_topoplotseries!(f::Union{GridPosition, Figure}, plotData::DataFram eeg_topoplot_series!(f, plotData, Δbin; col_y = config.mapping.y, - col_label=:label, + col_label=plotData.label, col = config.mapping.col, row = config.mapping.row, combinefun = config.extra.combinefun, From f59a683d51494c8b64b6e45565b88f2ff621a44e Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Thu, 3 Aug 2023 13:49:22 +0000 Subject: [PATCH 02/17] toposeries bug --- src/plot_topoplotseries.jl | 32 ++++++++++++++++++-------------- test/runtests.jl | 4 ++++ test/test_toposeries.jl | 9 +++++++++ 3 files changed, 31 insertions(+), 14 deletions(-) create mode 100644 test/test_toposeries.jl diff --git a/src/plot_topoplotseries.jl b/src/plot_topoplotseries.jl index c67938b37..f69fad023 100644 --- a/src/plot_topoplotseries.jl +++ b/src/plot_topoplotseries.jl @@ -20,31 +20,35 @@ Plot a Topoplot Series. The input `f` """ -plot_topoplotseries(plotData::DataFrame,Δbin::Real;kwargs...) = plot_topoplotseries!(Figure(), plotData, Δbin; kwargs...) +plot_topoplotseries(plotData::DataFrame, Δbin::Real; kwargs...) = plot_topoplotseries!(Figure(), plotData, Δbin; kwargs...) -function plot_topoplotseries!(f::Union{GridPosition, Figure}, plotData::DataFrame, Δbin; positions=nothing, labels=nothing, kwargs...) +function plot_topoplotseries!(f::Union{GridPosition,Figure}, plotData::DataFrame, Δbin; positions=nothing, labels=nothing, kwargs...) config = PlotConfig(:topoplotseries) - config_kwargs!(config;kwargs...) - + config_kwargs!(config; kwargs...) + plotData = deepcopy(plotData) # resolve columns with data config.mapping = resolveMappings(plotData, config.mapping) - positions = getTopoPositions(;positions=positions, labels=label) - + positions = getTopoPositions(; positions=positions, labels=labels) - eeg_topoplot_series!(f, plotData, Δbin; - col_y = config.mapping.y, - col_label=plotData.label, - col = config.mapping.col, - row = config.mapping.row, - combinefun = config.extra.combinefun, + + if "label" ∉ names(plotData) + plotData.label = plotData.channel + end + + eeg_topoplot_series!(f, plotData, Δbin;/ + col_y=config.mapping.y, + col_label=:label, + col=config.mapping.col, + row=config.mapping.row, + combinefun=config.extra.combinefun, positions=positions, config.visual... - ) + ) return f - + end diff --git a/test/runtests.jl b/test/runtests.jl index b2433cf55..302bea461 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,4 +4,8 @@ include("setup.jl") @testset "UnfoldMakie.jl" begin include("test_plot_circulareegtopoplot.jl") +end + +@testset "UnfoldMakie.jl" begin + include("test_toposeries.jl") end \ No newline at end of file diff --git a/test/test_toposeries.jl b/test/test_toposeries.jl new file mode 100644 index 000000000..2d1e99d60 --- /dev/null +++ b/test/test_toposeries.jl @@ -0,0 +1,9 @@ +# include("../UnfoldMakie/test/test_toposeries.jl") +#include("setup.jl") +@testset "testing calculateBBox" begin + data, positions = TopoPlots.example_data() + df = UnfoldMakie.eeg_matrix_to_dataframe(data[:, :, 1], string.(1:length(positions))); + Δbin=80 + UnfoldMakie.plot_topoplotseries(df, Δbin; positions=positions) + +end From 2a4ba062205c785f491ac3fe65d91e642c49c3e5 Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Thu, 3 Aug 2023 14:09:03 +0000 Subject: [PATCH 03/17] bug --- src/plot_topoplotseries.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plot_topoplotseries.jl b/src/plot_topoplotseries.jl index f69fad023..0839ab726 100644 --- a/src/plot_topoplotseries.jl +++ b/src/plot_topoplotseries.jl @@ -39,7 +39,7 @@ function plot_topoplotseries!(f::Union{GridPosition,Figure}, plotData::DataFrame plotData.label = plotData.channel end - eeg_topoplot_series!(f, plotData, Δbin;/ + eeg_topoplot_series!(f, plotData, Δbin; col_y=config.mapping.y, col_label=:label, col=config.mapping.col, From 798036b1881d58d787034e6f8a069226554c72f1 Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Thu, 3 Aug 2023 14:36:01 +0000 Subject: [PATCH 04/17] missed this detail --- test/setup.jl | 3 ++- test/test_plot_circulareegtopoplot.jl | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/test/setup.jl b/test/setup.jl index 49072b6c2..081e4ec6d 100644 --- a/test/setup.jl +++ b/test/setup.jl @@ -1,5 +1,6 @@ +using UnfoldMakie using Test using CairoMakie using GeometryBasics using DataFrames -using UnfoldMakie \ No newline at end of file +using TopoPlots \ No newline at end of file diff --git a/test/test_plot_circulareegtopoplot.jl b/test/test_plot_circulareegtopoplot.jl index b78261085..6bcd3f36f 100644 --- a/test/test_plot_circulareegtopoplot.jl +++ b/test/test_plot_circulareegtopoplot.jl @@ -1,3 +1,5 @@ +#include("setup.jl") + @testset "error cases and warns" begin @testset "out of error bounds" begin @@ -12,12 +14,11 @@ @testset "tooManyBoundsErr" begin testdf = DataFrame( - effect = [[4.0,1.0],[4.0,3.0],[4.0,3.0]], + estimate = [[4.0,1.0],[4.0,3.0],[4.0,3.0]], predictor = [70,80,90], ) - @test_throws ErrorException plot_circulareegtopoplot(testdf; extra=(;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; extra=(;predictorBounds=[0,100,360]), positions = [Point(1.0,2.0), Point(1.0,2.0), Point(1.0,2.0)],) end end From 34ffe33857855eb6984379a53e976527dd8836e3 Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Thu, 3 Aug 2023 15:02:26 +0000 Subject: [PATCH 05/17] upd project --- test/Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Project.toml b/test/Project.toml index e566201c5..d63cbdd90 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -3,3 +3,4 @@ CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +TopoPlots = "2bdbdf9c-dbd8-403f-947b-1a4e0dd41a7a" From 980c8f3528a3ed575cbd3b4fd78facc8f30a0cc8 Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Tue, 8 Aug 2023 14:31:05 +0000 Subject: [PATCH 06/17] erpimage --- src/plot_erpimage.jl | 53 +++++++++++++++++++++++++++++------------- src/plotconfig.jl | 54 +++++++++++++------------------------------ test/runtests.jl | 4 ++++ test/setup.jl | 1 + test/test_erpimage.jl | 10 ++++++++ 5 files changed, 68 insertions(+), 54 deletions(-) create mode 100644 test/test_erpimage.jl diff --git a/src/plot_erpimage.jl b/src/plot_erpimage.jl index 4210593b6..eaba9add3 100644 --- a/src/plot_erpimage.jl +++ b/src/plot_erpimage.jl @@ -2,46 +2,67 @@ """ - function plot_erpimage!(f::Union{GridPosition, Figure}, data::Matrix{Float64};kwargs...) - function plot_erpimage(data::Matrix{Float64};kwargs...) + function plot_erpimage!(f::Union{GridPosition, Figure}, data::Matrix{Float64}; kwargs...) + function plot_erpimage(data::Matrix{Float64}; kwargs...) Plot an ERP image. ## Arguments: - `f::Union{GridPosition, Figure}`: Figure or GridPosition that the plot should be drawn into - `plotData::Matrix{Float64}`: Data for the plot visualization -## Extra Data Behavior (...;extra=(;[key]=value)): -`erpBlur` (Number, `10`) - Number indicating how much blur is applied to the image; using Gaussian blur of the ImageFiltering module. +## Keyword Arguments +`blurwidth` (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. `sortData` (bool, `false`) - 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. +`ploterp`: (bool, `false`) - Indicating whether the plot should add a line plot below the ERP image, showing the mean of the data. ## Return Value: The input `f` """ + +# no times + no figure? plot_erpimage(plotData::Matrix{<:Real}; kwargs...) = plot_erpimage!(Figure(), plotData; kwargs...) -function plot_erpimage!(f::Union{GridPosition,Figure}, plotData::Matrix{<:Real}; kwargs...) + +# no times? +plot_erpimage!(f::Figure, plotData::Matrix{<:Real}; kwargs...) = plot_erpimage!(f, 1:size(plotData, 1), plotData; kwargs...) + +# no figure? +plot_erpimage(times::AbstractVector, plotData::Matrix{<:Real}; kwargs...) = plot_erpimage!(Figure(), times, plotData; kwargs...) + +function plot_erpimage!(f::Union{GridPosition,Figure}, times::AbstractVector, plotData::Matrix{<:Real}; sortvalues=nothing, sortpermutation=nothing, ploterp=true, blurwidth=10, kwargs...) config = PlotConfig(:erpimage) - config_kwargs!(config; kwargs...) + UnfoldMakie.config_kwargs!(config; kwargs...) + + !isnothing(sortpermutation) ? @assert(sortpermutation isa Vector{Int}) : "" ax = Axis(f[1:4, 1]; config.axis...) + if isnothing(sortpermutation) + if isnothing(sortvalues) + sortpermutation = 1:size(plotData, 2) + else + sortpermutation = sortperm(sortvalues) + + end + end + + filtered_data = UnfoldMakie.imfilter(plotData[:, sortpermutation], UnfoldMakie.Kernel.gaussian((0, max(blurwidth, 0)))) - filtered_data = imfilter(plotData, Kernel.gaussian((0, max(config.extra.erpBlur, 0)))) - if config.extra.sortData - ix = sortperm([a[1] for a in argmax(plotData, dims=1)][1, :]) # ix - trials sorted by time of maximum spike - hm = heatmap!(ax, (filtered_data[:, ix]); config.visual...) - else - hm = heatmap!(ax, (filtered_data[:, :]); config.visual...) + + yvals = 1:size(filtered_data, 2) + if !isnothing(sortvalues) + yvals = [minimum(sortvalues), maximum(sortvalues)] end - applyLayoutSettings!(config; fig=f, hm=hm, ax=ax, plotArea=(4, 1)) + hm = heatmap!(ax, times, yvals, filtered_data; config.visual...) + + UnfoldMakie.applyLayoutSettings!(config; fig=f, hm=hm, ax=ax, plotArea=(4, 1)) - if config.extra.meanPlot + if ploterp # UserInput subConfig = deepcopy(config) config_kwargs!(subConfig; layout=(; @@ -62,4 +83,4 @@ function plot_erpimage!(f::Union{GridPosition,Figure}, plotData::Matrix{<:Real}; return f -end \ No newline at end of file +end diff --git a/src/plotconfig.jl b/src/plotconfig.jl index 595f3910e..c67721180 100644 --- a/src/plotconfig.jl +++ b/src/plotconfig.jl @@ -56,43 +56,6 @@ function PlotConfig()# defaults end -#= -function updateConfig(cfg::PlotConfig;kwargs) - - this.layout! = function (;kwargs...) - # position affects multiple values in legendData - kwargsVals = values(kwargs) - if haskey(kwargsVals, :legendPosition) - if kwargsVals.legendPosition == :right - sdtLegVal = (;tellwidth = true, tellheight = false, orientation = :vertical) - sdtBarVal = (;tellwidth = true, tellheight = false) - elseif kwargsVals.legendPosition == :bottom - sdtLegVal = (;tellwidth = false, tellheight = true, orientation = :horizontal) - sdtBarVal = (;tellwidth = false, tellheight = true, vertical=false, flipaxis=false) - end - this.legendData = merge(this.legendData, sdtLegVal) - this.colorbarData = merge(this.colorbarData, sdtBarVal) - end - - this.layoutData = merge(this.layoutData, kwargs) - return this - end - - this.axis! = function (;kwargs...) - if :xlabel ∈ keys(kwargs) - this.layoutData = merge(this.layoutData, (;xlabelFromMapping = nothing)) - end - if :ylabel ∈ keys(kwargs) - this.layoutData = merge(this.layoutData, (;ylabelFromMapping = nothing)) - end - this.axisData = merge(this.axisData, kwargs) - - return this - end - return this - -end -=# """ Takes a kwargs named tuple of Key => NamedTuple and merges the fields with the defaults @@ -130,6 +93,21 @@ function PlotConfig(T::Val{:circeegtopo}) return cfg end + +function PlotConfig(T::Val{:topoarray}) + cfg = PlotConfig(:erp) + + config_kwargs!(cfg; extra=(; + ), layout=(; + ), colorbar=(; + ), mapping=(; + ), axis=(; + )) + return cfg +end + + + function PlotConfig(T::Val{:topoplot}) cfg = PlotConfig() @@ -268,7 +246,7 @@ function resolveMappings(plotData, mappingData) else return (nothing ∈ collect(choices)) ? # is it allowed to return nothing? nothing : - @error("default columns for $key = $choices not found, user must provide one by using plotconfig.mapping=()") + @error("default columns for $key = $choices not found, user must provide one by using plot_plotname(...;mapping=(; $key=:yourColumnName))") end end # have to use Dict here because NamedTuples break when trying to map them with keys/indices diff --git a/test/runtests.jl b/test/runtests.jl index 302bea461..03cbab2e1 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -8,4 +8,8 @@ end @testset "UnfoldMakie.jl" begin include("test_toposeries.jl") +end + +@testset "UnfoldMakie.jl" begin + include("test_erpimage.jl") end \ No newline at end of file diff --git a/test/setup.jl b/test/setup.jl index 081e4ec6d..9063fd0db 100644 --- a/test/setup.jl +++ b/test/setup.jl @@ -1,4 +1,5 @@ using UnfoldMakie +using UnfoldSim using Test using CairoMakie using GeometryBasics diff --git a/test/test_erpimage.jl b/test/test_erpimage.jl new file mode 100644 index 000000000..e5f7d4dbc --- /dev/null +++ b/test/test_erpimage.jl @@ -0,0 +1,10 @@ +include("setup.jl") +@testset "testing calculateBBox" begin + data, evts = UnfoldSim.predef_eeg(;noiselevel=10, return_epoched=true) + plot_erpimage(data; ploterp = false,) +end + +@testset "testing calculateBBox" begin + data, evts = UnfoldSim.predef_eeg(;noiselevel=10, return_epoched=true) + plot_erpimage(data; ploterp = true,) +end From 3dcde5fe10b70e76196bdd2384a8e35edbd67f24 Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Tue, 8 Aug 2023 14:50:20 +0000 Subject: [PATCH 07/17] erpimage docfile update --- docs/src/tutorials/erpimage.md | 6 +++--- test/test_erpimage.jl | 11 ++++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/docs/src/tutorials/erpimage.md b/docs/src/tutorials/erpimage.md index 012706745..61a90e47e 100644 --- a/docs/src/tutorials/erpimage.md +++ b/docs/src/tutorials/erpimage.md @@ -18,7 +18,7 @@ include("../../example_data.jl") The following code will result in the default configuration. ```@example main -data,evts = UnfoldSim.predef_eeg(;noiselevel=10,return_epoched=true) +data, evts = UnfoldSim.predef_eeg(; noiselevel=10, return_epoched=true) plot_erpimage(data) ``` @@ -33,11 +33,11 @@ Since ERP images use a `Matrix` as an input, the library does not need any infor (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. +- ploterp (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. ```@example main plot_erpimage(data; - extra = (meanPlot = true,), + extra = (ploterp = true,), colorbar = (label = "Voltage [µV]",), visual = (colormap = :viridis, colorrange = (-40, 40))) diff --git a/test/test_erpimage.jl b/test/test_erpimage.jl index e5f7d4dbc..89dc791b4 100644 --- a/test/test_erpimage.jl +++ b/test/test_erpimage.jl @@ -1,10 +1,15 @@ -include("setup.jl") -@testset "testing calculateBBox" begin +#include("setup.jl") +@testset "testing no bottom erp plot" begin data, evts = UnfoldSim.predef_eeg(;noiselevel=10, return_epoched=true) plot_erpimage(data; ploterp = false,) end -@testset "testing calculateBBox" begin +@testset "testing with bottom erp plot" begin data, evts = UnfoldSim.predef_eeg(;noiselevel=10, return_epoched=true) plot_erpimage(data; ploterp = true,) end + +@testset "testing no bottom erp plot in extra mode" begin + data, evts = UnfoldSim.predef_eeg(;noiselevel=10, return_epoched=true) + plot_erpimage(data; extra = (ploterp = true,),) +end From f0ab09dfb856d63e1061210461ca38912bba2155 Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Tue, 8 Aug 2023 15:38:17 +0000 Subject: [PATCH 08/17] detail --- test/Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Project.toml b/test/Project.toml index d63cbdd90..d771c941d 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -4,3 +4,4 @@ DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" TopoPlots = "2bdbdf9c-dbd8-403f-947b-1a4e0dd41a7a" +UnfoldSim = "ed8ae6d2-84d3-44c6-ab46-0baf21700804" From 526e2dcc3f4f88aaa574dcaba2f04fecdc45705b Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Wed, 9 Aug 2023 15:33:24 +0000 Subject: [PATCH 09/17] aspect for topoplot --- src/plot_topoplot.jl | 3 +-- test/runtests.jl | 5 +++++ test/test_topoplot.jl | 5 +++++ 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 test/test_topoplot.jl diff --git a/src/plot_topoplot.jl b/src/plot_topoplot.jl index 2a789f66d..2601929f2 100644 --- a/src/plot_topoplot.jl +++ b/src/plot_topoplot.jl @@ -20,7 +20,7 @@ function plot_topoplot!(f::Union{GridPosition,Figure}, plotData::Union{DataFrame config = PlotConfig(:topoplot) config_kwargs!(config; kwargs...) # potentially should be combined - axis = Axis(f[1, 1]; config.axis...) + axis = Axis(f[1, 1]; aspect=DataAspect(), config.axis...) if !(plotData isa Vector) @@ -28,7 +28,6 @@ function plot_topoplot!(f::Union{GridPosition,Figure}, plotData::Union{DataFrame plotData = plotData[:, config.mapping.y] end - positions = getTopoPositions(; positions=positions, labels=labels) eeg_topoplot!(axis, plotData, labels; positions, config.visual...) diff --git a/test/runtests.jl b/test/runtests.jl index 03cbab2e1..eb647a757 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -12,4 +12,9 @@ end @testset "UnfoldMakie.jl" begin include("test_erpimage.jl") +end + + +@testset "UnfoldMakie.jl" begin + include("test_topoplot.jl") end \ No newline at end of file diff --git a/test/test_topoplot.jl b/test/test_topoplot.jl new file mode 100644 index 000000000..261258242 --- /dev/null +++ b/test/test_topoplot.jl @@ -0,0 +1,5 @@ +include("setup.jl") +@testset "testing topoplot" begin + data, positions = TopoPlots.example_data() + plot_topoplot(data[:, 150, 1]; positions=positions, t=150) +end From 6b6831df1707d0ef8af03e71828fd024f59b6a15 Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Tue, 5 Sep 2023 05:45:35 +0000 Subject: [PATCH 10/17] upd erpimage, now with sorting --- src/plot_erpimage.jl | 24 +++++++++++++----------- test/test_erpimage.jl | 38 ++++++++++++++++++++++++++++++++------ 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/src/plot_erpimage.jl b/src/plot_erpimage.jl index eaba9add3..0a441448c 100644 --- a/src/plot_erpimage.jl +++ b/src/plot_erpimage.jl @@ -23,35 +23,36 @@ Non-Positive values deactivate the blur. The input `f` """ - # no times + no figure? -plot_erpimage(plotData::Matrix{<:Real}; kwargs...) = plot_erpimage!(Figure(), plotData; kwargs...) +plot_erpimage(plotData::Matrix{<:Real}; kwargs...) = plot_erpimage2!(Figure(), plotData; kwargs...) # no times? -plot_erpimage!(f::Figure, plotData::Matrix{<:Real}; kwargs...) = plot_erpimage!(f, 1:size(plotData, 1), plotData; kwargs...) +plot_erpimage!(f::Figure, plotData::Matrix{<:Real}; kwargs...) = plot_erpimage2!(f, 1:size(plotData, 1), plotData; kwargs...) # no figure? -plot_erpimage(times::AbstractVector, plotData::Matrix{<:Real}; kwargs...) = plot_erpimage!(Figure(), times, plotData; kwargs...) +plot_erpimage(times::AbstractVector, plotData::Matrix{<:Real}; kwargs...) = plot_erpimage2!(Figure(), times, plotData; kwargs...) -function plot_erpimage!(f::Union{GridPosition,Figure}, times::AbstractVector, plotData::Matrix{<:Real}; sortvalues=nothing, sortpermutation=nothing, ploterp=true, blurwidth=10, kwargs...) +function plot_erpimage!(f::Union{GridPosition,Figure}, times::AbstractVector, plotData::Matrix{<:Real}; sortvalues=nothing, sortix=nothing, kwargs...) config = PlotConfig(:erpimage) UnfoldMakie.config_kwargs!(config; kwargs...) - !isnothing(sortpermutation) ? @assert(sortpermutation isa Vector{Int}) : "" + !isnothing(sortix) ? @assert(sortix isa Vector{Int}) : "" ax = Axis(f[1:4, 1]; config.axis...) - if isnothing(sortpermutation) + if isnothing(sortix) if isnothing(sortvalues) - sortpermutation = 1:size(plotData, 2) + sortix = 1:size(plotData, 2) else - sortpermutation = sortperm(sortvalues) + sortix = sortperm(sortvalues) end end - filtered_data = UnfoldMakie.imfilter(plotData[:, sortpermutation], UnfoldMakie.Kernel.gaussian((0, max(blurwidth, 0)))) + filtered_data = UnfoldMakie.imfilter(plotData[:, sortix], UnfoldMakie.Kernel.gaussian((0, max(config.extra.erpBlur, 0)))) + #if config.extra.sortix + # ix = sortperm([a[1] for a in argmax(plotData, dims=1)][1, :]) # ix - trials sorted by time of maximum spike yvals = 1:size(filtered_data, 2) if !isnothing(sortvalues) @@ -62,7 +63,7 @@ function plot_erpimage!(f::Union{GridPosition,Figure}, times::AbstractVector, pl UnfoldMakie.applyLayoutSettings!(config; fig=f, hm=hm, ax=ax, plotArea=(4, 1)) - if ploterp + if config.extra.meanPlot # UserInput subConfig = deepcopy(config) config_kwargs!(subConfig; layout=(; @@ -84,3 +85,4 @@ function plot_erpimage!(f::Union{GridPosition,Figure}, times::AbstractVector, pl return f end + diff --git a/test/test_erpimage.jl b/test/test_erpimage.jl index 89dc791b4..7a956da5e 100644 --- a/test/test_erpimage.jl +++ b/test/test_erpimage.jl @@ -1,15 +1,41 @@ #include("setup.jl") @testset "testing no bottom erp plot" begin - data, evts = UnfoldSim.predef_eeg(;noiselevel=10, return_epoched=true) - plot_erpimage(data; ploterp = false,) + data, evts = UnfoldSim.predef_eeg(; noiselevel=10, return_epoched=true) + plot_erpimage(data; ploterp=false) end @testset "testing with bottom erp plot" begin - data, evts = UnfoldSim.predef_eeg(;noiselevel=10, return_epoched=true) - plot_erpimage(data; ploterp = true,) + data, evts = UnfoldSim.predef_eeg(; noiselevel=10, return_epoched=true) + plot_erpimage(data; ploterp=true) end @testset "testing no bottom erp plot in extra mode" begin - data, evts = UnfoldSim.predef_eeg(;noiselevel=10, return_epoched=true) - plot_erpimage(data; extra = (ploterp = true,),) + data, evts = UnfoldSim.predef_eeg(; noiselevel=10, return_epoched=true) + plot_erpimage(data; extra=(ploterp=true,)) 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 +=# \ No newline at end of file From 1196190c9f443130e46872ad811b6f6da7fea6df Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Tue, 5 Sep 2023 06:08:03 +0000 Subject: [PATCH 11/17] upd erpimage, now with sorting2 --- src/plot_erpimage.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plot_erpimage.jl b/src/plot_erpimage.jl index 0a441448c..6289f3c5c 100644 --- a/src/plot_erpimage.jl +++ b/src/plot_erpimage.jl @@ -24,13 +24,13 @@ The input `f` """ # no times + no figure? -plot_erpimage(plotData::Matrix{<:Real}; kwargs...) = plot_erpimage2!(Figure(), plotData; kwargs...) +plot_erpimage(plotData::Matrix{<:Real}; kwargs...) = plot_erpimage!(Figure(), plotData; kwargs...) # no times? -plot_erpimage!(f::Figure, plotData::Matrix{<:Real}; kwargs...) = plot_erpimage2!(f, 1:size(plotData, 1), plotData; kwargs...) +plot_erpimage!(f::Figure, plotData::Matrix{<:Real}; kwargs...) = plot_erpimage!(f, 1:size(plotData, 1), plotData; kwargs...) # no figure? -plot_erpimage(times::AbstractVector, plotData::Matrix{<:Real}; kwargs...) = plot_erpimage2!(Figure(), times, plotData; kwargs...) +plot_erpimage(times::AbstractVector, plotData::Matrix{<:Real}; kwargs...) = plot_erpimage!(Figure(), times, plotData; kwargs...) function plot_erpimage!(f::Union{GridPosition,Figure}, times::AbstractVector, plotData::Matrix{<:Real}; sortvalues=nothing, sortix=nothing, kwargs...) config = PlotConfig(:erpimage) From 7081271ad37d6ec95723f9661589a13220fdca9d Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Tue, 5 Sep 2023 06:09:35 +0000 Subject: [PATCH 12/17] upd erpimage, now with sorting3 --- src/plot_erpimage.jl | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/plot_erpimage.jl b/src/plot_erpimage.jl index 6289f3c5c..1471e2ff5 100644 --- a/src/plot_erpimage.jl +++ b/src/plot_erpimage.jl @@ -50,10 +50,6 @@ function plot_erpimage!(f::Union{GridPosition,Figure}, times::AbstractVector, pl filtered_data = UnfoldMakie.imfilter(plotData[:, sortix], UnfoldMakie.Kernel.gaussian((0, max(config.extra.erpBlur, 0)))) - - #if config.extra.sortix - # ix = sortperm([a[1] for a in argmax(plotData, dims=1)][1, :]) # ix - trials sorted by time of maximum spike - yvals = 1:size(filtered_data, 2) if !isnothing(sortvalues) yvals = [minimum(sortvalues), maximum(sortvalues)] @@ -72,9 +68,6 @@ function plot_erpimage!(f::Union{GridPosition,Figure}, times::AbstractVector, pl axis=(; ylabel=config.colorbar.label === nothing ? "" : config.colorbar.label)) - - #limits = (config.axis.limits[1], config.axis.limits[2], nothing, nothing))) - axisOffset = (config.layout.showLegend && config.layout.legendPosition == :bottom) ? 1 : 0 subAxis = Axis(f[5+axisOffset, 1]; subConfig.axis...) From 7f7df7439d779bf7a0db7fe08f51fdf216a147e5 Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Tue, 5 Sep 2023 12:41:05 +0000 Subject: [PATCH 13/17] move to config --- src/plot_topoplot.jl | 2 +- src/plotconfig.jl | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plot_topoplot.jl b/src/plot_topoplot.jl index 2601929f2..36ecadafd 100644 --- a/src/plot_topoplot.jl +++ b/src/plot_topoplot.jl @@ -20,7 +20,7 @@ function plot_topoplot!(f::Union{GridPosition,Figure}, plotData::Union{DataFrame config = PlotConfig(:topoplot) config_kwargs!(config; kwargs...) # potentially should be combined - axis = Axis(f[1, 1]; aspect=DataAspect(), config.axis...) + axis = Axis(f[1, 1]; config.axis...) if !(plotData isa Vector) diff --git a/src/plotconfig.jl b/src/plotconfig.jl index c67721180..48ceaea9f 100644 --- a/src/plotconfig.jl +++ b/src/plotconfig.jl @@ -128,6 +128,8 @@ function PlotConfig(T::Val{:topoplot}) x=(nothing,), positions=(:pos, :positions, :position, nothing), # Point / Array / Tuple labels=(:labels, :label, :sensor, nothing) # String + ), axis=(; + aspect=DataAspect() )) return cfg end From 31b0f26310e441ad0f62bb02e92f9a96bb370552 Mon Sep 17 00:00:00 2001 From: Vladimir Mikheev Date: Wed, 6 Sep 2023 14:15:47 +0000 Subject: [PATCH 14/17] markersize, relate weidth and height of topo, drop the grid --- src/plot_erp.jl | 5 ++-- src/plotconfig.jl | 3 ++ test/example_data.jl | 66 ++++++++++++++++++++++++++++++++++++++++++ test/test_butterfly.jl | 6 ++++ 4 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 test/example_data.jl create mode 100644 test/test_butterfly.jl diff --git a/src/plot_erp.jl b/src/plot_erp.jl index 5aaea6e89..4685961b6 100644 --- a/src/plot_erp.jl +++ b/src/plot_erp.jl @@ -131,11 +131,12 @@ function plot_erp!(f::Union{GridPosition,Figure}, plotData::DataFrame; positions # add topoLegend if (config.extra.topoLegend) - topoAxis = Axis(f_grid, width=Relative(0.25), height=Relative(0.25), halign=0.05, valign=0.95, aspect=1) + topoAxis = Axis(f_grid, width=Relative(config.extra.topowidth), height=Relative(config.extra.topoheigth), halign=0.05, valign=0.95, aspect=1) topoplotLegend(config, topoAxis, allPositions) end # no extra legend mainAxis = Axis(f_grid; config.axis...) + hidedecorations!(mainAxis, label = false, ticks = false, ticklabels = false) if isnothing(colors) drawing = draw!(mainAxis, plotEquation) @@ -184,7 +185,7 @@ function topoplotLegend(config, axis, allPositions) colorrange=(0, length(allPositions)), # add the 0 for the white-first color colormap=specialColors, head=(color=:black, linewidth=1, model=topoMatrix), - label_scatter=(markersize=10, strokewidth=0.5,)) + label_scatter=(markersize=config.extra.markersize, strokewidth=0.5,)) hidedecorations!(current_axis()) hidespines!(current_axis()) diff --git a/src/plotconfig.jl b/src/plotconfig.jl index 48ceaea9f..4095f8c12 100644 --- a/src/plotconfig.jl +++ b/src/plotconfig.jl @@ -170,6 +170,9 @@ function PlotConfig(T::Val{:butterfly}) showLegend=false ), extra=(; topoLegend=true, + markersize=10, + topowidth=0.25, + topoheigth=0.25, topoPositionToColorFunction=x -> posToColorRomaO(x) ), mapping=(; color=(:channel, :channels, :trial, :trials,), diff --git a/test/example_data.jl b/test/example_data.jl new file mode 100644 index 000000000..2cc0d5e09 --- /dev/null +++ b/test/example_data.jl @@ -0,0 +1,66 @@ +using UnfoldSim +using TopoPlots +using Unfold +""" +Makes use of TopoPlots example data (originating from eegvis matlab toolbox). +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") + + 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 + + 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 diff --git a/test/test_butterfly.jl b/test/test_butterfly.jl new file mode 100644 index 000000000..38cdd2bae --- /dev/null +++ b/test/test_butterfly.jl @@ -0,0 +1,6 @@ +include("setup.jl") +@testset "markersize change" begin + include("example_data.jl") + data, pos = example_data("TopoPlots.jl") + plot_butterfly(data; positions=pos, extra=(markersize = 10, topoheigth=0.4, topowidth=0.4)) +end From adaae37c46867399b449c261681751b90362d53f Mon Sep 17 00:00:00 2001 From: "behinger (s-ccs 001)" Date: Mon, 11 Sep 2023 16:55:38 +0000 Subject: [PATCH 15/17] removed the double script example_data, loaded the docs one --- test/example_data.jl | 66 ----------------------------------------- test/setup.jl | 4 ++- test/test_toposeries.jl | 3 +- 3 files changed, 4 insertions(+), 69 deletions(-) delete mode 100644 test/example_data.jl diff --git a/test/example_data.jl b/test/example_data.jl deleted file mode 100644 index 2cc0d5e09..000000000 --- a/test/example_data.jl +++ /dev/null @@ -1,66 +0,0 @@ -using UnfoldSim -using TopoPlots -using Unfold -""" -Makes use of TopoPlots example data (originating from eegvis matlab toolbox). -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") - - 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 - - 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 diff --git a/test/setup.jl b/test/setup.jl index 9063fd0db..1fb043909 100644 --- a/test/setup.jl +++ b/test/setup.jl @@ -4,4 +4,6 @@ using Test using CairoMakie using GeometryBasics using DataFrames -using TopoPlots \ No newline at end of file +using TopoPlots + +include("../docs/example_data.jl") \ No newline at end of file diff --git a/test/test_toposeries.jl b/test/test_toposeries.jl index 2d1e99d60..324df5148 100644 --- a/test/test_toposeries.jl +++ b/test/test_toposeries.jl @@ -1,5 +1,4 @@ -# include("../UnfoldMakie/test/test_toposeries.jl") -#include("setup.jl") + @testset "testing calculateBBox" begin data, positions = TopoPlots.example_data() df = UnfoldMakie.eeg_matrix_to_dataframe(data[:, :, 1], string.(1:length(positions))); From 8d6002b76395ba1beda7852c59b7dc1dcffec98a Mon Sep 17 00:00:00 2001 From: "behinger (s-ccs 001)" Date: Mon, 11 Sep 2023 16:57:08 +0000 Subject: [PATCH 16/17] more cleanup --- test/test_butterfly.jl | 2 +- test/test_topoplot.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_butterfly.jl b/test/test_butterfly.jl index 38cdd2bae..26d24c757 100644 --- a/test/test_butterfly.jl +++ b/test/test_butterfly.jl @@ -1,4 +1,4 @@ -include("setup.jl") + @testset "markersize change" begin include("example_data.jl") data, pos = example_data("TopoPlots.jl") diff --git a/test/test_topoplot.jl b/test/test_topoplot.jl index 261258242..8f5c09b07 100644 --- a/test/test_topoplot.jl +++ b/test/test_topoplot.jl @@ -1,4 +1,4 @@ -include("setup.jl") + @testset "testing topoplot" begin data, positions = TopoPlots.example_data() plot_topoplot(data[:, 150, 1]; positions=positions, t=150) From 23a772f90e5611d84d317b33a1b83ded4e80b2a9 Mon Sep 17 00:00:00 2001 From: "behinger (s-ccs 001)" Date: Mon, 11 Sep 2023 17:21:46 +0000 Subject: [PATCH 17/17] need Unfold in test because of example_data --- test/Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Project.toml b/test/Project.toml index d771c941d..56a844000 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -4,4 +4,5 @@ DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" TopoPlots = "2bdbdf9c-dbd8-403f-947b-1a4e0dd41a7a" +Unfold = "181c99d8-e21b-4ff3-b70b-c233eddec679" UnfoldSim = "ed8ae6d2-84d3-44c6-ab46-0baf21700804"