diff --git a/Project.toml b/Project.toml
index d27ac0ac6..d65c797c9 100644
--- a/Project.toml
+++ b/Project.toml
@@ -1,10 +1,11 @@
name = "UnfoldMakie"
uuid = "69a5ce3b-64fb-4f22-ae69-36dd4416af2a"
authors = ["Vladimir Mikheev", "Daniel Baumgartner", "SΓΆren DΓΆring", "Niklas GΓ€rtner", "Furkan Lokman", "Benedikt Ehinger"]
-version = "0.5.7"
+version = "0.5.8"
[deps]
AlgebraOfGraphics = "cbdf2221-f076-402e-a563-3d30da359d67"
+BSplineKit = "093aae92-e908-43d7-9660-e50ee39d5a0a"
CategoricalArrays = "324d7699-5711-5eae-9e2f-1d82baa6b597"
ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
ColorTypes = "3da002f7-5984-5a60-b8a6-cbb66c0b333f"
@@ -34,6 +35,7 @@ UnfoldMakiePyMNEExt = "PyMNE"
[compat]
AlgebraOfGraphics = "0.7, 0.8"
+BSplineKit = "0.16, 0.17"
CategoricalArrays = "0.10"
ColorSchemes = "3"
ColorTypes = "0.11"
diff --git a/README.md b/README.md
index 9bb492988..8a85c4828 100644
--- a/README.md
+++ b/README.md
@@ -17,9 +17,15 @@
| | |||||
A toolbox for visualizations of EEG/ERP data and Unfold.jl models.
-Based on the [Unfold](https://github.com/unfoldtoolbox/unfold.jl/) and [Makie](https://makie.juliaplots.org/stable/), it grants users high performance, and highly customizable plots.
-We currently support:
+Based on three libraries
+- [Unfold](https://github.com/unfoldtoolbox/unfold.jl/) - for performing deconvolution regression;
+- [Makie](https://makie.juliaplots.org/stable/) - very flexible visualisation library ([Maki-e](https://en.wikipedia.org/wiki/Maki-e) means "visualisation" on Japanese);
+- [Algebra of Graphics](https://github.com/MakieOrg/AlgebraOfGraphics.jl) - Makie-based visualisation library, allowing flexible mapping.
+
+This grants users high performance, and highly customizable plots.
+
+We currently support 9 general ERP plots:
- ![icon_erpplot_20px](https://github.com/unfoldtoolbox/UnfoldMakie.jl/assets/10183650/22c8472d-df78-46d7-afe8-e1e4e7b04313)
ERP plots
@@ -37,9 +43,11 @@ ERP images
Channel images
- ![icon_parallel_20px](https://github.com/unfoldtoolbox/UnfoldMakie.jl/assets/10183650/dab097c3-bcd6-4405-a44b-71cbe3e5fac9)
Parallel coordinates
-- Design matrices
- Circular topoplots
+And 2 Unfold-specific plots:
+- Design matrices
+- Splines plot
## Install
@@ -113,8 +121,8 @@ If you use these visualizations, please cite:
Benedikt Ehinger π π» π π€ π π§ π¬ π β οΈ β
|
- Daniel Baumgartner π» π |
Vladimir Mikheev π π» π π€ π§ π β οΈ β
|
+ Daniel Baumgartner π» π |
Niklas GΓ€rtner π» π |
Soren Doring π» π |
Fadil Furkan Lokman π» π |
diff --git a/docs/Project.toml b/docs/Project.toml
index 7064ee367..b07f03b59 100644
--- a/docs/Project.toml
+++ b/docs/Project.toml
@@ -1,5 +1,6 @@
[deps]
AlgebraOfGraphics = "cbdf2221-f076-402e-a563-3d30da359d67"
+BSplineKit = "093aae92-e908-43d7-9660-e50ee39d5a0a"
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
@@ -23,4 +24,5 @@ UnfoldSim = "ed8ae6d2-84d3-44c6-ab46-0baf21700804"
XML2_jll = "02c8fc9c-b97f-50b9-bbe4-9be30ff0a78a"
[compat]
-AlgebraOfGraphics = "0.7, 0.8"
\ No newline at end of file
+AlgebraOfGraphics = "0.7, 0.8"
+BSplineKit = "0.16, 0.17"
diff --git a/docs/example_data.jl b/docs/example_data.jl
index 082bae000..e76b123c7 100644
--- a/docs/example_data.jl
+++ b/docs/example_data.jl
@@ -6,24 +6,34 @@ using Random
"""
example_data(String)
-Creates example data. Currently, 7 datasets are available.
-- `TopoPlots.jl` (default) - tidy DataFrame from `TopoPlots.jl` with 2 conditions, 64 channels and 800 ms time range.
-- `UnfoldLinearModel`
-- `UnfoldLinearModelMultiChannel`
-- `UnfoldLinearModelContinuousTime`
-- `7channels`
-- `UnfoldTimeExpanded`
-- `sort_data` - includes DataFrame EEG recordings `dat` and `evts` with event variables occured during experiment. `evts` could be used for sorting EEG data in ERP image.
+Creates example data or model. Currently, 3 datasets and 6 models are available.
+
+Datasets:
+- `TopoPlots.jl` (default) - 2 DataFrames from `TopoPlots.jl`:\\
+ - DataFrame with estimate, time, 64 channels, topopositions, sterror and pvalue and 800 ms time range.\\
+ - Posiions for 64 electrodes.
+- `UnfoldLinearModelMultiChannel` - DataFrame with 5 channels, 3 coefnames, sterror, time and estimate.
+- `sort_data` - 2 DataFrames:
+ - `dat` for EEG recordings and `evts` with event variables occured during experiment.\\
+ - `evts` could be used for sorting EEG data in ERP image.
+
+Models:
+- `UnfoldLinearModel` - Model with formula `1 + condition + continuous`.
+- `UnfoldLinearModelContinuousTime` - Model with formula `timeexpand(1 + condition + continuous)` for times [0.0, 0.01 ... 0.5].
+- `UnfoldLinearModelwith1Spline` - Model with formula `1 + condition + spl(continuous, 4)`.
+- `UnfoldLinearModelwith2Splines` - Model with formula ` 1 + condition + spl(continuous, 4) + spl(continuous2, 6)`.
+- `7channels` - Model with formula `timeexpand(1 + condA)` for times [-0.1, -0.09 ... 0.5].
+- `UnfoldTimeExpanded` - Model with formula `timeexpand(1 + condition + continuous)` for times [-0.4, -0.39 ... 0.8].
+
**Return Value:** `DataFrame`.
"""
function example_data(example = "TopoPlots.jl")
-
if example == "UnfoldLinearModel"
# load and generate a simulated Unfold Design
data, evts = UnfoldSim.predef_eeg(; noiselevel = 12, return_epoched = true)
data = reshape(data, (1, size(data)...))
f = @formula 0 ~ 1 + condition + continuous
- # generate ModelStruct
+ # generate ModelStruct
se_solver = (x, y) -> Unfold.solver_default(x, y, stderror = true)
return fit(
UnfoldModel,
@@ -72,6 +82,38 @@ function example_data(example = "TopoPlots.jl")
basis = firbasis([0, 0.5], 100)
# generate ModelStruct
return fit(UnfoldModel, [Any => (f, basis)], evts, data)
+ elseif example == "UnfoldLinearModelwith1Spline"
+ # load and generate a simulated Unfold Design
+ data, evts = UnfoldSim.predef_eeg(; noiselevel = 12, return_epoched = true)
+ data = reshape(data, (1, size(data)...))
+ evts.continuous2 .=
+ log10.(6 .+ rand(MersenneTwister(1), length(evts.continuous))) .^ 2
+ f = @formula 0 ~ 1 + condition + spl(continuous, 4)
+ # generate ModelStruct
+ se_solver = (x, y) -> Unfold.solver_default(x, y, stderror = true)
+ return fit(
+ UnfoldModel,
+ [Any => (f, range(0, length = size(data, 2), step = 1 / 100))],
+ evts,
+ data;
+ solver = se_solver,
+ )
+ elseif example == "UnfoldLinearModelwith2Splines"
+ # load and generate a simulated Unfold Design
+ data, evts = UnfoldSim.predef_eeg(; noiselevel = 12, return_epoched = true)
+ data = reshape(data, (1, size(data)...))
+ evts.continuous2 .=
+ log10.(6 .+ rand(MersenneTwister(1), length(evts.continuous))) .^ 2
+ f = @formula 0 ~ 1 + condition + spl(continuous, 4) + spl(continuous2, 6)
+ # generate ModelStruct
+ se_solver = (x, y) -> Unfold.solver_default(x, y, stderror = true)
+ return fit(
+ UnfoldModel,
+ [Any => (f, range(0, length = size(data, 2), step = 1 / 100))],
+ evts,
+ data;
+ solver = se_solver,
+ )
elseif example == "7channels"
design =
SingleSubjectDesign(conditions = Dict(:condA => ["levelA", "levelB"])) |>
@@ -89,7 +131,6 @@ function example_data(example = "TopoPlots.jl")
f = @formula 0 ~ 1 + condA
bf_dict = [Any => (f, basisfunction)]
return fit(UnfoldModel, bf_dict, evnts, df)
-
elseif example == "UnfoldTimeExpanded"
df, evts = UnfoldSim.predef_eeg()
f = @formula 0 ~ 1 + condition + continuous
diff --git a/docs/literate/explanations/positions.jl b/docs/literate/explanations/positions.jl
index f1623215b..c927b62c7 100644
--- a/docs/literate/explanations/positions.jl
+++ b/docs/literate/explanations/positions.jl
@@ -4,7 +4,7 @@
using UnfoldMakie
using CairoMakie
using TopoPlots
-using PyMNE
+using PyMNE;
# # Get positions from MNE
diff --git a/docs/literate/how_to/hide_deco.jl b/docs/literate/how_to/hide_deco.jl
index 99d8c67d8..02eb0f1b2 100644
--- a/docs/literate/how_to/hide_deco.jl
+++ b/docs/literate/how_to/hide_deco.jl
@@ -32,8 +32,7 @@ plot_butterfly!(
data;
positions = pos,
topomarkersize = 10,
- topoheight = 0.4,
- topowidth = 0.4,
+ topo_axis = (; height = Relative(0.4), width = Relative(0.4)),
axis = (; title = "With decorations"),
)
plot_butterfly!(
@@ -41,8 +40,7 @@ plot_butterfly!(
data;
positions = pos,
topomarkersize = 10,
- topoheight = 0.4,
- topowidth = 0.4,
+ topo_axis = (; height = Relative(0.4), width = Relative(0.4)),
axis = (; title = "Without decorations"),
layout = (; hidedecorations = (:label => true, :ticks => true, :ticklabels => true)),
)
diff --git a/docs/literate/how_to/mult_vis_in_fig.jl b/docs/literate/how_to/mult_vis_in_fig.jl
index 079339dc0..bfc65d2bd 100644
--- a/docs/literate/how_to/mult_vis_in_fig.jl
+++ b/docs/literate/how_to/mult_vis_in_fig.jl
@@ -69,14 +69,7 @@ pvals = DataFrame(
to = [0.2, 0.5], # if coefname not specified, line should be black
coefname = ["(Intercept)", "category: face"],
)
-plot_erp!(
- f[2, 1:2],
- results,
- categorical_color = false,
- categorical_group = false,
- significance = pvals,
- stderror = true,
-)
+plot_erp!(f[2, 1:2], results, significance = pvals, stderror = true)
plot_designmatrix!(f[2, 3], designmatrix(uf))
@@ -94,18 +87,14 @@ res_effects = effects(Dict(:continuous => -5:0.5:5), uf_deconv)
plot_erp!(
f[2, 4:5],
res_effects;
- categorical_color = false,
- categorical_group = true,
- mapping = (; y = :yhat, color = :continuous, group = :continuous),
+ mapping = (; y = :yhat, color = :continuous, group = :continuous => nonnumeric),
legend = (; nbanks = 2),
- layout = (; show_legend = true, legend_position = :right),
)
plot_parallelcoordinates(
f[3, 2:3],
uf_5chan;
mapping = (; color = :coefname),
- layout = (; legend_position = :right),
)
plot_erpimage!(f[1, 4:5], times, d_singletrial)
@@ -157,8 +146,7 @@ plot_butterfly!(
d_topo;
positions = pos,
topomarkersize = 10,
- topoheight = 0.4,
- topowidth = 0.4,
+ topo_axis = (; height = Relative(0.4), width = Relative(0.4)),
)
hlines!(0, color = :gray, linewidth = 1)
vlines!(0, color = :gray, linewidth = 1)
diff --git a/docs/literate/how_to/position2color.jl b/docs/literate/how_to/position2color.jl
index 87ac447f4..3d3448005 100644
--- a/docs/literate/how_to/position2color.jl
+++ b/docs/literate/how_to/position2color.jl
@@ -2,6 +2,7 @@
# You want to change the colors of the lines and markers on the inserted topoplot.
# To do that you need to change the color scheme (aka color map) of the butterfly plot.
+# You can find th elist of colormaps for Makie [here](https://docs.makie.org/v0.21/explanations/colors).
# # Setup
@@ -19,15 +20,15 @@ plot_butterfly(results; positions = positions)
# # Color schemes
# ## MNE style
-#=
-We can change the color scale by specifying a function that maps from an `(x, y)` tuple to a color. UnfoldMakie currently provides three different color scales:
-- `pos2colorRGB` (same as MNE-Python),
-- `pos2colorHSV` (HSV color space),
-- `pos2colorRomaO`.
+# We can change the color scale by specifying a function that maps from an `(x, y)` tuple to a color.
+# `UnfoldMakie` currently provides three different color scales:
+# - `pos2colorRGB` (same as MNE-Python),
+# - `pos2colorHSV` (HSV color space),
+# - `pos2colorRomaO`.
+
+# While `RGB` & `HSV` have the advantage of being 2D color maps, `Roma0` has the advantage of being perceptually uniform.
+# Also you can specify a uniform color.
-While `RGB` & `HSV` have the advantage of being 2D color maps, `Roma0` has the advantage of being perceptually uniform.
-Also you can specify a uniform color.
-=#
plot_butterfly(
results;
diff --git a/docs/literate/intro/code_principles.jl b/docs/literate/intro/code_principles.jl
index 3ac8df4b5..6f15e4aaf 100644
--- a/docs/literate/intro/code_principles.jl
+++ b/docs/literate/intro/code_principles.jl
@@ -3,9 +3,9 @@
# Here we will write about principles which we developed through our publication.
-#- Code should be clear and concise
-#- Variables inside the code should have meaningful names
-#- Every function exposed to the user should have documentation that specifies all parameters, types, input and output arguments.
-#- Most people will not look at the defaults, so it is very important to nudge users to show important details with a picture or text.
-#- Function naming should be based on some theory and naming conventions.
-#- You should avoid functions longer 50 lines
+# - Code should be clear and concise.
+# - Variables inside the code should have meaningful names.
+# - Every function exposed to the user should have documentation that specifies all parameters, types, input and output arguments.
+# - Most people will not look at the defaults, so it is very important to nudge users to label important details of the plot.
+# - Function naming should be based on some theory and naming conventions.
+# - You should avoid functions longer 50 lines.
diff --git a/docs/literate/tutorials/butterfly.jl b/docs/literate/tutorials/butterfly.jl
index edf54b478..043170874 100644
--- a/docs/literate/tutorials/butterfly.jl
+++ b/docs/literate/tutorials/butterfly.jl
@@ -38,7 +38,12 @@ plot_butterfly(df; positions = pos)
# You want to change size of topomarkers and size of topoplot:
-plot_butterfly(df; positions = pos, topomarkersize = 10, topoheight = 0.4, topowidth = 0.4)
+plot_butterfly(
+ df;
+ positions = pos,
+ topomarkersize = 10,
+ topo_axis = (; height = Relative(0.4), width = Relative(0.4)),
+)
# You want to add vline and hline:
diff --git a/docs/literate/tutorials/designmatrix.jl b/docs/literate/tutorials/designmatrix.jl
index b6552e800..d6a34dc4b 100644
--- a/docs/literate/tutorials/designmatrix.jl
+++ b/docs/literate/tutorials/designmatrix.jl
@@ -11,7 +11,7 @@ using CairoMakie
# Data
include("../../../example_data.jl")
-uf = example_data("UnfoldLinearModel")
+uf = example_data("UnfoldLinearModel");
# # Plot Designmatrices
diff --git a/docs/literate/tutorials/erp.jl b/docs/literate/tutorials/erp.jl
index 9f3f8a9ea..684564687 100644
--- a/docs/literate/tutorials/erp.jl
+++ b/docs/literate/tutorials/erp.jl
@@ -13,7 +13,7 @@ using CairoMakie
using DataFramesMeta
using UnfoldSim
using UnfoldMakie
-include("../../../example_data.jl")
+include("../../../example_data.jl");
# Data generation
@@ -36,6 +36,9 @@ res_effects = effects(Dict(:continuous => -5:0.5:5), m);
# ## Figure plotting
plot_erp(results)
+# To change legend title use `mapping.color`:
+plot_erp(results, mapping = (; color = :coefname => "Conditions"))
+
# # Additional features
# ## Effect plot
@@ -53,9 +56,7 @@ plot_erp(results)
plot_erp(
res_effects;
mapping = (; y = :yhat, color = :continuous, group = :continuous),
- layout = (; show_legend = false),
- categorical_color = false, # perceives color (here: continuous) as contionus
- categorical_group = true, # separates lines, if `false` all lines will be connected
+ layout = (; use_colorbar = false),
)
# ## Significance lines
@@ -68,8 +69,8 @@ plot_erp(
m = example_data("UnfoldLinearModel")
results = coeftable(m)
significancevalues = DataFrame(
- from = [0.1, 0.3],
- to = [0.5, 0.7],
+ from = [0.01, 0.2],
+ to = [0.3, 0.4],
coefname = ["(Intercept)", "condition: face"], # if coefname not specified, line should be black
)
plot_erp(results; :significance => significancevalues)
@@ -110,7 +111,7 @@ text!(0.98, 0.2, text = "* Confidence\nintervals", align = (:right, :top))
f
# There are two ways to implement it.
-# First is using `:stderror = true' after `;`.
+# First is using `:stderror = true` after `;`.
results.se_low = results.estimate .- 0.5
results.se_high = results.estimate .+ 0.15
diff --git a/docs/literate/tutorials/splines.jl b/docs/literate/tutorials/splines.jl
new file mode 100644
index 000000000..7ae9e57d8
--- /dev/null
+++ b/docs/literate/tutorials/splines.jl
@@ -0,0 +1,31 @@
+# # [Spline plot](@id spline_vis)
+# **Spline plot** is a plot type for visualisation of terms in an UnfoldModel.
+# Two subplots are generated for each spline term: 1) the basis function of the spline; 2) the density of the underlying covariate.
+
+# Multiple spline terms are arranged across columns.
+# Dashed lines indicate spline knots.
+
+# # Setup
+# Package and data loading
+
+using Unfold, UnfoldMakie
+using BSplineKit, DataFrames
+
+
+include("../../../example_data.jl")
+df, pos = example_data("TopoPlots.jl")
+m1 = example_data("UnfoldLinearModelwith1Spline");
+m2 = example_data("UnfoldLinearModelwith2Splines");
+
+
+# Spline plot with one spline term:
+plot_splines(m1)
+
+# Spline plot with two spline terms:
+plot_splines(m2)
+
+# # Configurations of Spline plot
+
+# ```@docs
+# plot_splines
+# ```
diff --git a/docs/literate/tutorials/topoplot.jl b/docs/literate/tutorials/topoplot.jl
index abb67b0c2..2e62370d7 100644
--- a/docs/literate/tutorials/topoplot.jl
+++ b/docs/literate/tutorials/topoplot.jl
@@ -16,7 +16,7 @@ using DataFrames
# Data loading
-dat, positions = TopoPlots.example_data()
+dat, positions = TopoPlots.example_data();
# The size of `data` is 64Γ400Γ3. This means:
# - 64 channels;
@@ -91,8 +91,11 @@ plot_topoplot!(
)
f
+# # Highlighting channels
+plot_topoplot(dat[:, 50, 1]; positions, high_chan = [1, 2])
+
# # Configurations of Topoplot
# ```@docs
# plot_topoplot
-# ```
\ No newline at end of file
+# ```
diff --git a/docs/literate/tutorials/topoplotseries.jl b/docs/literate/tutorials/topoplotseries.jl
index 9c12cb578..410b30735 100644
--- a/docs/literate/tutorials/topoplotseries.jl
+++ b/docs/literate/tutorials/topoplotseries.jl
@@ -25,11 +25,21 @@ nothing #hide
# `bin_width` - specify the interval between topoplots
bin_width = 80
-plot_topoplotseries(df; bin_width, positions = positions)
+plot_topoplotseries(
+ df;
+ bin_width,
+ positions = positions,
+ axis = (; xlabel = "Time windows [s]"),
+)
# `bin_num` - specify the number of topoplots
-plot_topoplotseries(df; bin_num = 5, positions = positions)
+plot_topoplotseries(
+ df;
+ bin_num = 5,
+ positions = positions,
+ axis = (; xlabel = "Time windows [s]"),
+)
# # Categorical and contionous x-values
# By deafult x-value is `time`, but it could be any contionous (i.g. saccade amplitude) or categorical (any experimental variable) value.
diff --git a/docs/make.jl b/docs/make.jl
index 43a140fe4..b73e949d9 100644
--- a/docs/make.jl
+++ b/docs/make.jl
@@ -40,7 +40,7 @@ makedocs(;
"Plot types" => "generated/intro/plot_types.md",
"Code principles" => "generated/intro/code_principles.md",
],
- "Visualization Types" => [
+ "ERP Visualizations" => [
"ERP plot" => "generated/tutorials/erp.md",
"Butterfly plot" => "generated/tutorials/butterfly.md",
"Topoplot" => "generated/tutorials/topoplot.md",
@@ -49,9 +49,12 @@ makedocs(;
"ERP image" => "generated/tutorials/erpimage.md",
"Channel image" => "generated/tutorials/channel_image.md",
"Parallel coordinates" => "generated/tutorials/parallelcoordinates.md",
- "Design matrix" => "generated/tutorials/designmatrix.md",
"Circular topoplots" => "generated/tutorials/circ_topo.md",
],
+ "Unfold-specific Visualisations" => [
+ "Design matrix" => "generated/tutorials/designmatrix.md",
+ "Spline plot" => "generated/tutorials/splines.md",
+ ],
"How To" => [
"Change colormap of Butterfly plot" => "generated/how_to/position2color.md",
"Hide decorations and axis spines" => "generated/how_to/hide_deco.md",
diff --git a/docs/src/index.md b/docs/src/index.md
index 2b5c9834b..1a6d58890 100644
--- a/docs/src/index.md
+++ b/docs/src/index.md
@@ -8,7 +8,7 @@ This is the documentation of the UnfoldMakie.jl package for the Julia programmin
## Highlights of UnfoldMakie.jl
-- **10 plot functions for displaying ERPs.**
+- **11 plot functions for displaying ERPs.**
Each plot emphasizes certain dimensions while collapsing others.
- **Fast plotting**
Plot one figure with 20 topoplots in 1 second? No problemo!
@@ -17,6 +17,6 @@ The package is primarily based on [Unfold.jl](https://github.com/unfoldtoolbox/u
- **Many usage examples**
You can find many user-friendly examples of how to use and adapt the plots in this documentation.
- **Scientific colormaps by default**
-According to our study [(Mikheev, 2024)](https://apertureneuro.org/article/116386-the-art-of-brainwaves-a-survey-on-event-related-potential-visualization-practices), 40% of EEG researchers do not know about the issue of scientific color maps. By default, we use `Reverse(:RdBu)` (based on [colorbrewer](https://colorbrewer2.org/#type=sequential&scheme=BuGn&n=3)) and `Roma` (based on [Sceintific Colormaps](https://www.fabiocrameri.ch/colourmaps/) by Fabio Crameri) as default color maps.
+According to our study [(Mikheev, 2024)](https://apertureneuro.org/article/116386-the-art-of-brainwaves-a-survey-on-event-related-potential-visualization-practices), 40% of EEG researchers do not know about the issue of scientific color maps. As default color maps we use `Reverse(:RdBu)` (based on [colorbrewer](https://colorbrewer2.org/#type=sequential&scheme=BuGn&n=3)) and `Roma` (based on [Sceintific Colormaps](https://www.fabiocrameri.ch/colourmaps/) by Fabio Crameri).
- **Interactivity**
Several plots make use of `Observables.jl` which allows fast updating of the underlying data. Several plots already have predefined interactive features, e.g. you can click on labels to enable / disable them. See `plot_topoplotseries` and `plot_erpimage` for examples.
diff --git a/src/UnfoldMakie.jl b/src/UnfoldMakie.jl
index 596419461..4336b863b 100644
--- a/src/UnfoldMakie.jl
+++ b/src/UnfoldMakie.jl
@@ -48,6 +48,7 @@ end
include("plotconfig.jl")
include("docstring_template.jl")
+include("supportive_defaults.jl")
include("eeg_series.jl")
include("plot_topoplotseries.jl")
@@ -55,6 +56,7 @@ include("plot_topoplotseries.jl")
include("plot_erp.jl")
include("plot_butterfly.jl")
include("plot_designmatrix.jl")
+include("plot_splines.jl")
include("plot_topoplot.jl")
include("plot_erpimage.jl")
include("plot_parallelcoordinates.jl")
@@ -71,6 +73,8 @@ export PlotConfig
export plot_designmatrix
export plot_designmatrix!
+export plot_splines
+export plot_splines!
export plot_erp
export plot_erp!
export plot_erpimage
@@ -95,4 +99,5 @@ export to_positions
export eeg_array_to_dataframe
export eeg_topoplot_series
export nonnumeric # reexport from AoG
+
end
diff --git a/src/docstring_template.jl b/src/docstring_template.jl
index 93572e216..86848601d 100644
--- a/src/docstring_template.jl
+++ b/src/docstring_template.jl
@@ -14,6 +14,7 @@ function _docstring(cfg_symb::Symbol)
:circtopos => `Topoplot.eeg_topoplot`,
:topoplot => `Topoplot.eeg_topoplot`,
:topoplotseries => `Topoplot.eeg_topoplot`,
+ :splines => `Makie.series`,
)
visuallink2 = Dict(
:erp => "https://docs.makie.org/stable/reference/plots/lines/",
@@ -26,6 +27,7 @@ function _docstring(cfg_symb::Symbol)
:circtopos => "https://makieorg.github.io/TopoPlots.jl/stable/eeg/",
:topoplot => "https://makieorg.github.io/TopoPlots.jl/stable/eeg/",
:topoplotseries => "https://makieorg.github.io/TopoPlots.jl/stable/eeg/",
+ :splines => "https://docs.makie.org/stable/reference/plots/series",
)
cbarstring =
(cfg_symb == :erp || cfg_symb == :butterfly) ?
@@ -35,8 +37,10 @@ function _docstring(cfg_symb::Symbol)
:figure => "use `kwargs...` of [`Makie.Figure`](https://docs.makie.org/stable/explanations/figure/)",
:axis => "use `kwargs...` of [`Makie.Axis`](https://docs.makie.org/stable/reference/blocks/axis/)",
:legend => "use `kwargs...` of [`Makie.Legend`](https://docs.makie.org/stable/reference/blocks/legend/)",
- :colorbar => "use `kwargs...` of $cbarstring",
+ :layout => "check this [page](https://unfoldtoolbox.github.io/UnfoldMakie.jl/dev/generated/how_to/hide_deco/)",
+ :mapping => "use any mapping from [`AlgebraOfGraphics`](https://aog.makie.org/stable/layers/mapping/)",
:visual => "use `kwargs...` of [$(visuallink[cfg_symb])]($(visuallink2[cfg_symb]))",
+ :colorbar => "use `kwargs...` of $cbarstring",
)
for k = 1:length(fn)
namedtpl = string(Base.getfield(cfg, fn[k]))
@@ -51,7 +55,7 @@ function _docstring(cfg_symb::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))`.\\
+ For example, `plot_x(...; colorbar = (; vertical = true, label = "Test"))`.\\
Multiple defaults will be cycled until match.
Placing `;` is important!
@@ -59,12 +63,3 @@ function _docstring(cfg_symb::Symbol)
$(out)
"""
end
-#=
-"""
- $(TYPEDSIGNATURES)
-$(_docstring(:erp))
-
-"""
-function plot_new()
- return "b"
-end =#
diff --git a/src/layout_helper.jl b/src/layout_helper.jl
index 628bf8267..f6a67f228 100644
--- a/src/layout_helper.jl
+++ b/src/layout_helper.jl
@@ -9,43 +9,12 @@ function apply_layout_settings!(
hm = nothing,
drawing = nothing,
ax = nothing,
- plotArea = (1, 1),
+ plot_area = (1, 1),
)
if isnothing(ax)
ax = current_axis()
end
- if (config.layout.show_legend)
- if isnothing(fig)
- @error "Legend needs `Figure` parameter"
- else
- # 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.use_colorbar) #not sure this line is useful
- if isnothing(hm)
- Colorbar(
- legend_position;
- colormap = config.visual.colormap,
- config.colorbar...,
- )
- else
- Colorbar(legend_position, hm; config.colorbar...)
- end
- else # for PCP
- title_pcp = getproperty.(Ref(config.legend), :title) # pop title
- config.legend = dropnames(config.legend, (:title,)) # delete title
- Legend(legend_position, ax, title_pcp; config.legend...)
- end
- else
- legend!(legend_position, drawing; config.legend...)
- colorbar!(legend_position, drawing; config.colorbar...)
- end
- end
- end
-
if :hidespines β keys(config.layout) && !isnothing(config.layout.hidespines)
Makie.hidespines!(ax, config.layout.hidespines...)
end
@@ -58,6 +27,4 @@ Makie.hidedecorations!(ax::Matrix{AxisEntries}; kwargs...) =
Makie.hidedecorations!.(ax; kwargs...)
Makie.hidespines!(ax::Matrix{AxisEntries}, args...) = Makie.hidespines!.(ax, args...)
-#hidedecorations!(ax::AxisEntries;kwargs...) = Makie.hidedecorations!.(ax.axis;kwargs...)
Makie.hidespines!(ax::AxisEntries, args...) = Makie.hidespines!.(ax.axis, args...)
-#hidespinses!(ax:Axis,args...) = hiespines!.(Ref(ax),args...)
diff --git a/src/plot_butterfly.jl b/src/plot_butterfly.jl
index 6346eac0b..33508f4af 100644
--- a/src/plot_butterfly.jl
+++ b/src/plot_butterfly.jl
@@ -26,12 +26,15 @@ Plot a Butterfly plot.
Show an inlay topoplot with corresponding electrodes. Requires `positions`.
- `topomarkersize::Real = 10` \\
Change the size of the electrode markers in topoplot.
-- `topowidth::Real = 0.25` \\
- Change the width of inlay topoplot.
-- `topoheight::Real = 0.25` \\
- Change the height of inlay topoplot.
- `topopositions_to_color::x -> pos_to_color_RomaO(x)`\\
Change the line colors.
+- `topo_axis::NamedTuple = (;)`\\
+ Here you can flexibly change configurations of the topoplot axis.\\
+ To see all options just type `?Axis` in REPL.\\
+ Defaults: $(supportive_defaults(:topo_default))
+- `mapping = (;)`\\
+ For highlighting specific channels.\\
+ Example: `mapping = (; color = :highlight))`, where `:highlight` is variable with appopriate mapping.
**Return Value:** `Figure` displaying Butterfly plot.
@@ -48,12 +51,8 @@ function plot_butterfly!(
labels = nothing,
topolegend = true,
topomarkersize = 10,
- topowidth = 0.35,
- topoheight = 0.35,
- topohalign = 0.05,
- topovalign = 0.95,
- topoaspect = 1,
topopositions_to_color = x -> pos_to_color_RomaO(x),
+ topo_axis = (;),
mapping = (;),
kwargs...,
)
@@ -93,6 +92,7 @@ function plot_butterfly!(
colors = get_topo_color(all_positions, topopositions_to_color)
end
end
+
# Categorical mapping
# convert color column into string to prevent wrong grouping
if (:group β keys(config.mapping))
@@ -111,15 +111,12 @@ function plot_butterfly!(
end
mapp = AlgebraOfGraphics.mapping()
-
- if (:color β keys(config.mapping))
- mapp = mapp * AlgebraOfGraphics.mapping(; config.mapping.color)
- end
-
- if (:group β keys(config.mapping))
- mapp = mapp * AlgebraOfGraphics.mapping(; config.mapping.group)
+ for i in [:color, :group]
+ if (i β keys(config.mapping))
+ tmp = getindex(config.mapping, i)
+ mapp = mapp * AlgebraOfGraphics.mapping(; i => tmp)
+ end
end
-
# remove x / y
mapping_others = deleteKeys(config.mapping, [:x, :y, :positions, :lables])
xy_mapp =
@@ -131,25 +128,17 @@ function plot_butterfly!(
f_grid = f[1, 1]
if (topolegend)
- topoAxis = Axis(
- f_grid,
- width = Relative(topowidth),
- height = Relative(topoheight),
- halign = topohalign,
- valign = topovalign,
- aspect = topoaspect,
- )
+ topo_axis = update_axis(supportive_defaults(:topo_default); topo_axis...)
ix = unique(i -> plot_data[:, config.mapping.group[1]][i], 1:size(plot_data, 1))
topoplot_legend(
- topoAxis,
+ Axis(f_grid; topo_axis...),
topomarkersize,
plot_data[ix, config.mapping.color[1]],
colors,
all_positions,
)
end
-
if isnothing(colors)
drawing = draw!(f_grid, plot_equation; axis = config.axis)
else
@@ -163,3 +152,56 @@ function plot_butterfly!(
apply_layout_settings!(config; fig = f, ax = drawing, drawing = drawing)
return f
end
+
+
+# topopositions_to_color = colors?
+function topoplot_legend(axis, topomarkersize, unique_val, colors, all_positions)
+ all_positions = unique(all_positions)
+ topo_matrix = eeg_head_matrix(all_positions, (0.5, 0.5), 0.5)
+
+ un = unique(unique_val)
+ special_colors =
+ ColorScheme(vcat(RGB(1, 1, 1.0), colors[map(x -> findfirst(x .== un), unique_val)]))
+
+ xlims!(low = -0.2, high = 1.2)
+ ylims!(low = -0.2, high = 1.2)
+
+ topoplot = eeg_topoplot!(
+ axis,
+ 1:length(all_positions), # go from 1:npos
+ string.(1:length(all_positions));
+ positions = all_positions,
+ interpolation = NullInterpolator(), # inteprolator that returns only 0, which is put to white in the special_colorsmap
+ colorrange = (0, length(all_positions)), # add the 0 for the white-first color
+ colormap = special_colors,
+ head = (color = :black, linewidth = 1, model = topo_matrix),
+ label_scatter = (markersize = topomarkersize, strokewidth = 0.5),
+ )
+ hidespines!(axis)
+ hidedecorations!(axis)
+ return topoplot
+end
+
+function eeg_head_matrix(positions, center, radius)
+ oldCenter = mean(positions)
+ oldRadius, _ = findmax(x -> norm(x .- oldCenter), positions)
+ radF = radius / oldRadius
+ return Makie.Mat4f(
+ radF,
+ 0,
+ 0,
+ 0,
+ 0,
+ radF,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1,
+ 0,
+ center[1] - oldCenter[1] * radF,
+ center[2] - oldCenter[2] * radF,
+ 0,
+ 1,
+ )
+end
diff --git a/src/plot_circular_topoplots.jl b/src/plot_circular_topoplots.jl
index 635a8bc14..05f2744f7 100644
--- a/src/plot_circular_topoplots.jl
+++ b/src/plot_circular_topoplots.jl
@@ -83,10 +83,9 @@ function plot_circular_topoplots!(
# setting the colorbar to the bottom right of the box.
# Relative values got determined by checking what subjectively looks best
Colorbar(
- f[1, 2],
- colormap = config.colorbar.colormap,
+ f[1, 2];
colorrange = (min, max),
- label = config.colorbar.label,
+ config.colorbar...,
height = @lift Fixed($(pixelarea(ax.scene)).widths[2])
)
plot_topo_plots!(
@@ -102,7 +101,6 @@ function plot_circular_topoplots!(
)
apply_layout_settings!(config; ax = ax)
-
# set the scene's background color according to config
#set_theme!(Theme(backgroundcolor = config.axisData.backgroundcolor))
return f
diff --git a/src/plot_erp.jl b/src/plot_erp.jl
index 63bcfc17c..c1ba6e8be 100644
--- a/src/plot_erp.jl
+++ b/src/plot_erp.jl
@@ -19,10 +19,6 @@ Plot an ERP plot.
## Keyword arguments (kwargs)
-- `categorical_color::Bool = true`\\
- Treat `:color` as categorical variable in case of numeric `:color` column.
-- `categorical_group::Bool = true`\\
- Treat `:group` as categorical variable in case of numeric `:group` column.
- `stderror::Bool = false`\\
Add an error ribbon, with lower and upper limits based on the `:stderror` column.
- `significance::DataFrame = nothing`\\
@@ -55,13 +51,18 @@ function plot_erp!(
plot_data::Union{DataFrame,AbstractMatrix,AbstractVector{<:Number}};
positions = nothing,
labels = nothing,
- categorical_color = true,
- categorical_group = true,
+ categorical_color = nothing,
+ categorical_group = nothing,
stderror = false, # XXX if it exists, should be plotted
significance = nothing,
mapping = (;),
kwargs...,
)
+ if !(isnothing(categorical_color) && isnothing(categorical_group))
+ @warn "categorical_color and categorical_group have been deprecated.
+ To switch to categorical colors, please use `mapping(..., color = :mycolorcolum => nonnumeric)`.
+ `group` is now automatically cast to nonnumeric."
+ end
config = PlotConfig(:erp)
config_kwargs!(config; mapping, kwargs...)
plot_data = deepcopy(plot_data)
@@ -84,41 +85,40 @@ function plot_erp!(
plot_data.group = plot_data.group .|> a -> isnothing(a) ? :fixef : a
end
- # check if stderror values exist and create new columns with high and low band
- 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
- # Categorical mapping
- # convert color column into string to prevent wrong grouping
- if categorical_color && (:color β keys(config.mapping))
- config.mapping =
- merge(config.mapping, (; color = config.mapping.color => nonnumeric))
- end
-
- # converts group column into string
- if categorical_group && (:group β keys(config.mapping))
- config.mapping =
- merge(config.mapping, (; group = config.mapping.group => nonnumeric))
- end
+ # automatically convert col & group to nonnumeric
if (
:col β keys(config.mapping) &&
+ !isa(config.mapping.col, Pair) &&
typeof(plot_data[:, config.mapping.col]) <: AbstractVector{<:Number}
)
config.mapping = merge(config.mapping, (; col = config.mapping.col => nonnumeric))
end
- mapp = AlgebraOfGraphics.mapping()
-
- if (:color β keys(config.mapping))
- mapp = mapp * AlgebraOfGraphics.mapping(; config.mapping.color)
+ if (
+ :group β keys(config.mapping) &&
+ !isa(config.mapping.group, Pair) &&
+ typeof(plot_data[:, config.mapping.group]) <: AbstractVector{<:Number}
+ )
+ config.mapping =
+ merge(config.mapping, (; group = config.mapping.group => nonnumeric))
end
- if (:group β keys(config.mapping))
- mapp = mapp * AlgebraOfGraphics.mapping(; config.mapping.group)
+ # check if stderror values exist and create new columns with high and low band
+ 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
+ mapp = AlgebraOfGraphics.mapping()
+
+ # mapping for stderrors
+ for i in [:color, :group, :col, :row, :layout]
+ if (i β keys(config.mapping))
+ tmp = getindex(config.mapping, i)
+ mapp = mapp * AlgebraOfGraphics.mapping(; i => tmp)
+ end
+ end
# remove x / y
mapping_others = deleteKeys(config.mapping, [:x, :y, :positions, :lables])
@@ -126,6 +126,7 @@ function plot_erp!(
AlgebraOfGraphics.mapping(config.mapping.x, config.mapping.y; mapping_others...)
basic = visual(Lines; config.visual...) * xy_mapp
# add band of sdterrors
+
if stderror
m_se = AlgebraOfGraphics.mapping(config.mapping.x, :se_low, :se_high)
basic = basic + visual(Band, alpha = 0.5) * m_se
@@ -140,78 +141,21 @@ function plot_erp!(
plot_equation = basic * mapp
- f_grid = f[1, 1:4]
-
- # draw a standart ERP lineplot
+ f_grid = f[1, 1] = GridLayout()
drawing = draw!(f_grid, plot_equation; axis = config.axis)
if config.layout.show_legend == true
config_kwargs!(config; mapping, layout = (; show_legend = false))
if config.layout.use_legend == true
- legend!(f[:, 5], drawing; config.legend...)
+ legend!(f_grid[:, end+1], drawing; config.legend...)
end
if config.layout.use_colorbar == true
- N = config.layout.use_legend == false ? 5 : 6
- colorbar!(f[:, N], drawing; config.colorbar...)
+ colorbar!(f_grid[:, end+1], drawing; config.colorbar...)
end
end
apply_layout_settings!(config; fig = f, ax = drawing, drawing = drawing)
return f
end
-function eeg_head_matrix(positions, center, radius)
- oldCenter = mean(positions)
- oldRadius, _ = findmax(x -> norm(x .- oldCenter), positions)
- radF = radius / oldRadius
- return Makie.Mat4f(
- radF,
- 0,
- 0,
- 0,
- 0,
- radF,
- 0,
- 0,
- 0,
- 0,
- 1,
- 0,
- center[1] - oldCenter[1] * radF,
- center[2] - oldCenter[2] * radF,
- 0,
- 1,
- )
-end
-
-# topopositions_to_color = colors?
-function topoplot_legend(axis, topomarkersize, unique_val, colors, all_positions)
- all_positions = unique(all_positions)
-
- topo_matrix = eeg_head_matrix(all_positions, (0.5, 0.5), 0.5)
-
- un = unique(unique_val)
- special_colors =
- ColorScheme(vcat(RGB(1, 1, 1.0), colors[map(x -> findfirst(x .== un), unique_val)]))
-
- xlims!(low = -0.2, high = 1.2)
- ylims!(low = -0.2, high = 1.2)
- topoplot = eeg_topoplot!(
- axis,
- 1:length(all_positions), # go from 1:npos
- string.(1:length(all_positions));
- positions = all_positions,
- interpolation = NullInterpolator(), # inteprolator that returns only 0, which is put to white in the special_colorsmap
- colorrange = (0, length(all_positions)), # add the 0 for the white-first color
- colormap = special_colors,
- head = (color = :black, linewidth = 1, model = topo_matrix),
- label_scatter = (markersize = topomarkersize, strokewidth = 0.5),
- )
-
- hidedecorations!(current_axis())
- hidespines!(current_axis())
-
- return topoplot
-end
-
function add_significance(plot_data, significance, config)
p = deepcopy(significance)
diff --git a/src/plot_erpgrid.jl b/src/plot_erpgrid.jl
index ef06456ac..fa994f9ff 100644
--- a/src/plot_erpgrid.jl
+++ b/src/plot_erpgrid.jl
@@ -13,6 +13,22 @@ Plot an ERP image.
Electrode positions.
- `ch_names::Vector{String}`\\
Vector with channel names.
+- `hlines_grid_axis::NamedTuple = (;)`\\
+ Here you can flexibly change configurations of the hlines on all subaxes.\\
+ To see all options just type `?hlines` in REPL.\\
+ Defaults: $(supportive_defaults(:hlines_grid_default))
+- `vlines_grid_axis::NamedTuple = (;)`\\
+ Here you can flexibly change configurations of the vlines on all subaxes.\\
+ To see all options just type `?vlines` in REPL.\\
+ Defaults: $(supportive_defaults(:vlines_grid_default))
+- `lines_grid_axis::NamedTuple = (;)`\\
+ Here you can flexibly change configurations of the lines on all subaxes.\\
+ To see all options just type `?lines` in REPL.\\
+ Defaults: $(supportive_defaults(:lines_grid_default))
+- `labels_grid_axis::NamedTuple = (;)`\\
+ Here you can flexibly change configurations of the labels on all subaxes.\\
+ To see all options just type `?text` in REPL.\\
+ Defaults: $(supportive_defaults(:labels_grid_default))
## Keyword arguments (kwargs)
- `drawlabels::Bool = false`\\
@@ -48,6 +64,10 @@ function plot_erpgrid!(
ch_names::Vector{String};
drawlabels = false,
times = -1:size(data, 2)-2, #arbitrary
+ labels_grid_axis = (;),
+ hlines_grid_axis = (;),
+ vlines_grid_axis = (;),
+ lines_grid_axis = (;),
kwargs...,
)
config = PlotConfig(:erpgrid)
@@ -72,6 +92,8 @@ function plot_erpgrid!(
axlist = []
rel_zeropoint = argmin(abs.(times)) ./ length(times)
+ labels_grid_axis =
+ update_axis(supportive_defaults(:labels_grid_default); labels_grid_axis...)
for (ix, p) in enumerate(eachcol(positions))
x = p[1]
y = p[2]
@@ -83,29 +105,26 @@ function plot_erpgrid!(
valign = y,
)
if drawlabels
- text!(
- ax,
- rel_zeropoint + 0.1,
- 1,
- color = :gray,
- fontsize = 12,
- text = ch_names[ix],
- align = (:left, :top),
- space = :relative,
- )
+ text!(ax, rel_zeropoint + 0.1, 1; text = ch_names[ix], labels_grid_axis...)
end
# todo: add label if not nothing
push!(axlist, ax)
end
- # todo: make optional + be able to specify the linewidth + color
- hlines!.(axlist, Ref([0.0]), color = :gray, linewidth = 0.5)
- vlines!.(axlist, Ref([0.0]), color = :gray, linewidth = 0.5)
+ hlines_grid_axis =
+ update_axis(supportive_defaults(:hlines_grid_default); hlines_grid_axis...)
+ vlines_grid_axis =
+ update_axis(supportive_defaults(:vlines_grid_default); vlines_grid_axis...)
+ lines_grid_axis =
+ update_axis(supportive_defaults(:lines_grid_default); lines_grid_axis...)
+
+ hlines!.(axlist, Ref([0.0]); hlines_grid_axis...)
+ vlines!.(axlist, Ref([0.0]); vlines_grid_axis...)
times = isnothing(times) ? (1:size(data, 2)) : times
# todo: add customizable kwargs
- h = lines!.(axlist, Ref(times), eachrow(data))
+ h = lines!.(axlist, Ref(times), eachrow(data); lines_grid_axis...)
linkaxes!(axlist...)
hidedecorations!.(axlist)
@@ -119,14 +138,20 @@ function plot_erpgrid!(
xstart = [Point2f(0), Point2f(0)]
xdir = [Vec2f(0, 0.1), Vec2f(0.1, 0)]
arrows!(xstart, xdir, arrowsize = 10)
- text!(0.02, 0, text = config.axis.xlabel, align = (:left, :top), fontsize = 12)
+ text!(
+ 0.02,
+ 0,
+ text = config.axis.xlabel,
+ fontsize = config.axis.fontsize,
+ align = (:left, :top),
+ )
text!(
-0.008,
0.01,
text = config.axis.ylabel,
+ fontsize = config.axis.fontsize,
align = (:left, :baseline),
rotation = Ο / 2,
- fontsize = 12,
)
f
end
diff --git a/src/plot_erpimage.jl b/src/plot_erpimage.jl
index 5cf4d1abb..e08cb9388 100644
--- a/src/plot_erpimage.jl
+++ b/src/plot_erpimage.jl
@@ -33,10 +33,12 @@ Plot an ERP image.
If `sortvalues = true` the default text will change to "Sorted trials", but it could be changed to any values specified manually.
- `meanplot_axis::NamedTuple = (;)`\\
Here you can flexibly change configurations of meanplot.\\
- To see all options just type `?Axis` in REPL.
+ To see all options just type `?Axis` in REPL.\\
+ Defaults: $(supportive_defaults(:meanplot_default))
- `sortplot_axis::NamedTuple = (;)`\\
Here you can flexibly change configurations of meanplot.\\
- To see all options just type `?Axis` in REPL.
+ To see all options just type `?Axis` in REPL.\\
+ Defaults: $(supportive_defaults(:sortplot_default))
$(_docstring(:erpimage))
@@ -125,7 +127,7 @@ function plot_erpimage!(
)
end
hidespines!(ax, :r, :t)
- apply_layout_settings!(config; fig = f, hm = hm, ax = ax, plotArea = (4, 1))
+ apply_layout_settings!(config; fig = f, hm = hm, ax = ax, plot_area = (4, 1))
return f
end
@@ -134,13 +136,11 @@ function ei_meanplot(ax, data, config, f, ga, times, meanplot_axis)
ax.xticklabelsvisible = false
trace = @lift(mean($data, dims = 2)[:, 1])
+ meanplot_axis = update_axis(supportive_defaults(:meanplot_default); meanplot_axis...)
+
axbottom = Axis(
ga[5, 1:4];
- height = 100,
ylabel = config.colorbar.label === nothing ? "" : config.colorbar.label,
- xlabel = "Time [s]",
- xlabelpadding = 0,
- xautolimitmargin = (0, 0),
limits = @lift((
minimum($times),
maximum($times),
@@ -163,11 +163,10 @@ function ei_sortvalue(sortvalues, f, ax, hm, config, sortval_xlabel, sortplot_ax
error("`show_sortval` can not take `sortvalues` with all NaN-values")
end
gb = f[1, 3] = GridLayout()
+ sortplot_axis = update_axis(supportive_defaults(:sortplot_default); sortplot_axis...)
axleft = Axis(
gb[1:4, 1:5];
xlabel = sortval_xlabel,
- ylabelvisible = true,
- yticklabelsvisible = false,
#xautolimitmargin = (-1, 1),
#yautolimitmargin = (1, 100),
xticks = @lift([
@@ -188,7 +187,6 @@ function ei_sortvalue(sortvalues, f, ax, hm, config, sortval_xlabel, sortplot_ax
hidedecorations!(axempty)
hidespines!(axempty)
hidespines!(axleft, :r, :t)
- #scatter!(axleft, xs, ys)
lines!(axleft, xs, ys)
if config.layout.use_colorbar != false
Colorbar(
diff --git a/src/plot_parallelcoordinates.jl b/src/plot_parallelcoordinates.jl
index 9192148c1..72d822324 100644
--- a/src/plot_parallelcoordinates.jl
+++ b/src/plot_parallelcoordinates.jl
@@ -8,7 +8,6 @@ Plot a PCP (parallel coordinates plot).\\
Dimensions: conditions, channels, time, trials.
## Arguments:
-
- `f::Union{GridPosition, GridLayout, Figure}`
`Figure`, `GridLayout`, or `GridPosition` to draw the plot.
- `data::Union{DataFrame, AbstractMatrix}`\\
@@ -101,7 +100,7 @@ function plot_parallelcoordinates(
end
UnfoldMakie.config_kwargs!(config; visual = (; color = c))
- f, ax, axlist, hlines = parallelcoordinates(
+ f1, ax, axlist, hlines = parallelcoordinates(
f,
d5;
normalize = normalize,
@@ -119,7 +118,10 @@ function plot_parallelcoordinates(
fontsize = 20,
font = :bold,
)
- apply_layout_settings!(config; fig = f, ax = ax)
+ if config.layout.show_legend
+ Legend(f[1, 2], ax, config.legend.title; config.legend...)
+ end
+ apply_layout_settings!(config; fig = f1, ax = ax)
return isa(f, Figure) ? Makie.FigureAxisPlot(f, [ax, axlist], hlines[1]) :
Makie.AxisPlot([ax, axlist], hlines[1])
@@ -165,7 +167,6 @@ function parallelcoordinates(
minlist = minimum(plotdata)
maxlist = maximum(plotdata)
end
- # @debug plotdata
# edge bending / bundling
if !bend
@@ -175,7 +176,10 @@ function parallelcoordinates(
x_plotdata = range(1, x_pos[end], step = 0.05)
plotdata_int = Array{Float64}(undef, length(x_plotdata), size(plotdata, 2))
for k = 1:size(plotdata, 2)
- itp = interpolate(plotdata[:, k], BSpline(Cubic(Interpolations.Line(OnGrid()))))
+ itp = Interpolations.interpolate(
+ plotdata[:, k],
+ BSpline(Cubic(Interpolations.Line(OnGrid()))),
+ )
plotdata_int[:, k] = itp.(x_plotdata)
end
end
@@ -189,14 +193,12 @@ function parallelcoordinates(
# categorical colors
un_c = unique(color)
color_ix = [findfirst(un_c .== c) for c in color]
- #@assert length(un_c) == 1 "Only single color found, please don't specify color, "
if length(un_c) == 1
- @warn "Only single unique value found in the specified color vector"
- color = cgrad(colormap, 2)[color_ix]
+ @warn "Only single unique value found in the specified color vector."
+ color = cgrad(colormap, 2)[color_ix] # color gradient
else
color = cgrad(colormap, length(un_c))[color_ix]
end
- #crange = [1,length(unique(color))]
else
# continuous color
crange = [minimum(color), maximum(color)]
@@ -206,7 +208,6 @@ function parallelcoordinates(
# plot the lines - this way it will be easy to curve them too
hlines = []
for (ix, r) in enumerate(eachcol(plotdata_int))
-
h = lines!(
ax,
x_plotdata,
@@ -345,7 +346,6 @@ Used to inject extrema ticks and round them if necessary.
struct PCPTicks end
function Makie.get_ticks(ticks::PCPTicks, scale, formatter, vmin, vmax)
- #@debug "get_ticks custom",vmin,vmax
tickvalues = Makie.get_tickvalues(Makie.WilkinsonTicks(5), scale, vmin, vmax)
ticklabels_without = Makie.get_ticklabels(formatter, tickvalues)
diff --git a/src/plot_splines.jl b/src/plot_splines.jl
new file mode 100644
index 000000000..7041ad3a2
--- /dev/null
+++ b/src/plot_splines.jl
@@ -0,0 +1,106 @@
+using BSplineKit, Unfold
+
+"""
+ plot_splines(m::UnfoldModel; kwargs...)
+ plot_splines!(f::Union{GridPosition, GridLayout, Figure}, m::UnfoldModel; kwargs...)
+
+Visualization of spline terms in an UnfoldModel. Two subplots are generated for each spline term:\\
+1) the basis function of the spline; 2) the density of the underlying covariate.\\
+
+Multiple spline terms are arranged across columns.\\
+Dashed lines indicate spline knots.
+
+## Arguments:
+
+- `f::Union{GridPosition, GridLayout, Figure}`
+ `Figure`, `GridLayout`, or `GridPosition` to draw the plot.
+- `m::UnfoldModel`\\
+ UnfoldModel with splines.
+- `spline_axis::NamedTuple = (;)`\\
+ Here you can flexibly change configurations of spline subplots.\\
+ To see all options just type `?Axis` in REPL.\\
+ Defaults: $(supportive_defaults(:spline_default))
+- `density_axis::NamedTuple = (;)`\\
+ Here you can flexibly change configurations of density subplots.\\
+ To see all options just type `?Axis` in REPL.\\
+ Defaults: $(supportive_defaults(:density_default))
+- `superlabel_config::NamedTuple = (;)`\\
+ Here you can flexibly change configurations of the Label on the top of the plot.\\
+ To see all options just type `?Label` in REPL.\\
+ Defaults: $(supportive_defaults(:superlabel_default))
+
+$(_docstring(:splines))
+
+**Return Value:** `Figure` with splines and their density for basis functions.
+"""
+plot_splines(m::UnfoldModel; kwargs...) = plot_splines(Figure(), m; kwargs...)
+
+function plot_splines(
+ f::Union{GridPosition,GridLayout,Figure},
+ m::UnfoldModel;
+ spline_axis = (;),
+ density_axis = (;),
+ superlabel_config = (;),
+ kwargs...,
+)
+ config = PlotConfig(:splines)
+ config_kwargs!(config; kwargs...)
+ spline_axis, density_axis, superlabel_config =
+ supportive_axes_management(spline_axis, density_axis, superlabel_config)
+
+ ga = f[1, 1] = GridLayout()
+
+ terms = Unfold.formulas(m)[1].rhs.terms
+ spl_title = join(terms, " + ")
+
+ splFunction = Base.get_extension(Unfold, :UnfoldBSplineKitExt).splFunction
+ spl_ix = findall(isa.(terms, Unfold.AbstractSplineTerm))
+ @assert !isempty(spl_ix) "No spline term is found in UnfoldModel. Does your UnfoldModel really have a `spl(...)` or other `AbstractSplineTerm`?"
+
+ spline_terms = [terms[i] for i in spl_ix]
+ subplot_id = 1
+ for spline_term in spline_terms
+ x_range = range(
+ spline_term.breakpoints[1],
+ stop = spline_term.breakpoints[end],
+ length = 100,
+ )
+ basis_set = splFunction(x_range, spline_term)
+
+ if subplot_id > 1
+ spline_axis = update_axis(spline_axis; ylabelvisible = false)
+ density_axis = update_axis(density_axis; ylabelvisible = false)
+ end
+ a1 = Axis(ga[1, subplot_id]; title = string(spline_term), spline_axis...)
+ series!(
+ x_range,
+ basis_set',
+ color = resample_cmap(config.visual.colormap, size(basis_set')[1]),
+ ) # continuous color map used
+ vlines!(
+ spline_term.breakpoints;
+ ymin = extrema(basis_set')[1],
+ ymax = extrema(basis_set')[2],
+ linestyle = :dash,
+ )
+ a2 = Axis(ga[2, subplot_id]; xlabel = string(spline_term.term.sym), density_axis...)
+ density!(
+ Unfold.events(designmatrix(m))[1][:, spline_term.term.sym];
+ color = :transparent,
+ strokecolor = :black,
+ strokewidth = 1,
+ )
+ linkxaxes!(a1, a2)
+ subplot_id = subplot_id + 1
+ end
+ Label(ga[1, 1:end, Top()], spl_title; superlabel_config...)
+ f
+end
+
+function supportive_axes_management(spline_axis, density_axis, superlabel_config)
+ spline_axis = update_axis(supportive_defaults(:spline_default); spline_axis...)
+ density_axis = update_axis(supportive_defaults(:density_default); density_axis...)
+ superlabel_config =
+ update_axis(supportive_defaults(:superlabel_default); superlabel_config...)
+ return spline_axis, density_axis, superlabel_config
+end
diff --git a/src/plot_topoplot.jl b/src/plot_topoplot.jl
index 0747b2d61..4df4551b6 100644
--- a/src/plot_topoplot.jl
+++ b/src/plot_topoplot.jl
@@ -1,5 +1,6 @@
"""
plot_topoplot!(f::Union{GridPosition, GridLayout, Figure}, data::Union{<:AbstractDataFrame,<:AbstractVector}; positions::Vector, labels = nothing, kwargs...)
+using Interpolations: positions
plot_topoplot(data::Union{<:AbstractDataFrame,<:AbstractVector}; position::Vector, labels = nothing, kwargs...)
Plot a topoplot.
@@ -12,6 +13,8 @@ Plot a topoplot.
Positions used if `data` is not a `DataFrame`. Positions are generated from `labels` if `positions = nothing`.
- `labels::Vector{String} = nothing`\\
Labels used if `data` is not a DataFrame.
+- `high_chan = nothing` - channnel(s) to highlight by color.
+- `high_color = :darkgreen` - color for highlighting.
$(_docstring(:topoplot))
@@ -25,6 +28,8 @@ function plot_topoplot!(
data::Union{<:AbstractDataFrame,<:AbstractVector};
labels = nothing,
positions = nothing,
+ high_chan = nothing,
+ high_color = :darkgreen,
kwargs...,
)
config = PlotConfig(:topoplot)
@@ -41,14 +46,35 @@ function plot_topoplot!(
positions = TopoPlots.labels2positions(labels)
end
positions = get_topo_positions(; positions = positions, labels = labels)
- eeg_topoplot!(axis, data, labels; positions, config.visual...)
+ if isa(high_chan, Int) || isa(high_chan, Vector{Int64})
+ x = zeros(length(positions))
+ isa(high_chan, Int) ? x[high_chan] = 1 : x[high_chan] .= 1
+ clist = [:gray, high_color][Int.(x .+ 1)] #color for highlighting
+ eeg_topoplot!(
+ axis,
+ data,
+ labels;
+ positions,
+ config.visual...,
+ label_scatter = (;
+ color = clist,
+ markersize = ((x .+ 0.25) .* 40) ./ 5, # make adjustabel for users
+ ),
+ )
+ else
+ eeg_topoplot!(axis, data, labels; positions, config.visual...)
+ end
+
+ if config.layout.use_colorbar == true
+ Colorbar(f[1, 2]; colormap = config.visual.colormap, config.colorbar...)
+ end
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 = (; use_colorbar = false, show_legend = false))
+ config_kwargs!(config, layout = (; use_colorbar = false))
else
config_kwargs!(config, colorbar = (; limits = clims))
end
diff --git a/src/plot_topoplotseries.jl b/src/plot_topoplotseries.jl
index ea2335e7d..494c11489 100644
--- a/src/plot_topoplotseries.jl
+++ b/src/plot_topoplotseries.jl
@@ -42,9 +42,12 @@ Multiple miniature topoplots in regular distances.
`mapping.col` - specify x-value, can be any continuous or categorical variable.\\
`mapping.row` - specify y-value, can be any continuous or categorical variable (not implemented yet).\\
`mapping.layout` - arranges topoplots by rows when equals `:time`.\\
-- `visual.colorrange::2-element Vector{Int64}`, `colorbar.colorrange::2-element Vector{Int64}`\\
- First is resposnible for colorrange in topoplots, second - in colorbars. Ideally they should be the same.
+- `visual.colorrange::2-element Vector{Int64}`\\
+ Resposnible for colorrange in topoplots and in colorbar.
+
+Code description:
+-
$(_docstring(:topoplotseries))
**Return Value:** `Figure` displaying the Topoplot series.
@@ -77,13 +80,14 @@ function plot_topoplotseries!(
config = PlotConfig(:topoplotseries)
# overwrite all defaults by user specified values
config_kwargs!(config; kwargs...)
+
# resolve columns with data
config.mapping = resolve_mappings(to_value(data), config.mapping)
data_copy = deepcopy(to_value(data)) # deepcopy prevents overwriting initial data
cat_or_cont_columns =
eltype(data_copy[!, config.mapping.col]) <: Number ? "cont" : "cat"
if cat_or_cont_columns == "cat"
- # overwrite Time windows [s] default if categorical
+ # overwrite 'Time windows [s]' default if categorical
n_topoplots =
number_of_topoplots(data_copy; bin_width, bin_num, bins = 0, config.mapping)
ix =
@@ -132,22 +136,19 @@ function plot_topoplotseries!(
config.visual...,
positions,
)
- if (config.colorbar.colorrange !== nothing)
- config_kwargs!(config)
- else
- config_kwargs!(
- config,
- visual = (; colorrange = colorrange),
- colorbar = (; colorrange = colorrange),
- )
- end
- if !config.layout.use_colorbar
- config_kwargs!(config, layout = (; use_colorbar = false, show_legend = false))
- end
+ config_kwargs!(
+ config,
+ visual = (; colorrange = colorrange),
+ colorbar = (; colorrange = colorrange),
+ )
+
ax = Axis(
f[1, 1];
(p for p in pairs(config.axis) if p[1] != :xlim_topo && p[1] != :ylim_topo)...,
)
+ if config.layout.use_colorbar == true
+ Colorbar(f[1, 2]; colormap = config.visual.colormap, config.colorbar...)
+ end
apply_layout_settings!(config; fig = f, ax = ax)
return f
end
diff --git a/src/plotconfig.jl b/src/plotconfig.jl
index 7d895a44f..ac1961aad 100644
--- a/src/plotconfig.jl
+++ b/src/plotconfig.jl
@@ -28,8 +28,7 @@ function PlotConfig()# defaults
(;), # axis
(; # layout
show_legend = true,
- legend_position = :right,
- use_colorbar = false, # ideally should be deleted
+ use_colorbar = true,
),
(#maping
x = (:time,),
@@ -42,47 +41,18 @@ function PlotConfig()# defaults
orientation = :vertical,
tellwidth = true,
tellheight = false,
+ halign = :right,
+ valign = :center,
),
(;#colorbar
vertical = true,
tellwidth = true,
tellheight = false,
+ labelrotation = -Ο / 2,
),
)
end
-"""
- config_kwargs!(cfg::PlotConfig; kwargs...)
-Takes named tuple of `Key => NamedTuple` as kwargs and merges the fields with the defaults.
-"""
-function config_kwargs!(cfg::PlotConfig; kwargs...)
-
- is_namedtuple = [isa(t, NamedTuple) for t in values(kwargs)]
- @assert(
- all(is_namedtuple),
- """ Keyword argument specification (kwargs...). Specified config groups must be from `NamedTuple`, 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 needed. The second is incorrect 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 arguments must be used directly as keyword arguments."
- ) : ""
- applyTo = keyList[in.(keyList, Ref(list))]
- for k β applyTo
- setfield!(cfg, k, merge(getfield(cfg, k), kwargs[k]))
- end
-end
-
PlotConfig(T::Symbol) = PlotConfig(Val{T}())
@@ -92,7 +62,11 @@ function PlotConfig(T::Val{:circtopos})
config_kwargs!(
cfg;
layout = (; show_legend = false),
- colorbar = (; label = "Voltage [Β΅V]", colormap = Reverse(:RdBu)),
+ colorbar = (;
+ labelrotation = -Ο / 2,
+ label = "Voltage [Β΅V]",
+ colormap = Reverse(:RdBu),
+ ),
mapping = (;),
axis = (;
label = ""
@@ -108,7 +82,6 @@ function PlotConfig(T::Val{:topoplot})
config_kwargs!(
cfg;
layout = (
- show_legend = true,
use_colorbar = true,
hidespines = (),
hidedecorations = (Dict(:label => false)),
@@ -126,7 +99,7 @@ function PlotConfig(T::Val{:topoplot})
positions = (:pos, :positions, :position, nothing), # Point / Array / Tuple
labels = (:labels, :label, :sensor, nothing), # String
),
- colorbar = (; flipaxis = true, labelrotation = -Ο / 2, label = "Voltage [Β΅V]"),
+ colorbar = (; flipaxis = true, label = "Voltage [Β΅V]"),
axis = (; xlabel = "", aspect = DataAspect()),
)
return cfg
@@ -151,12 +124,7 @@ function PlotConfig(T::Val{:topoplotseries})
yrectzoom = false,
),
layout = (; use_colorbar = true),
- colorbar = (;
- flipaxis = true,
- labelrotation = -Ο / 2,
- label = "Voltage [Β΅V]",
- colorrange = nothing,
- ),
+ colorbar = (; flipaxis = true, label = "Voltage [Β΅V]", colorrange = nothing),
visual = (;
label_text = false, # true doesnt work again
colormap = Reverse(:RdBu),
@@ -178,7 +146,19 @@ function PlotConfig(T::Val{:designmat})
ylabel = "Trials",
xticklabelrotation = round(pi / 8, digits = 2),
),
- colorbar = (; flipaxis = true, labelrotation = -Ο / 2, label = ""),
+ colorbar = (; flipaxis = true, label = ""),
+ )
+ return cfg
+end
+
+function PlotConfig(T::Val{:splines})
+ cfg = PlotConfig()
+ config_kwargs!(
+ cfg;
+ layout = (;),
+ axis = (;),
+ visual = (; colormap = :viridis),
+ legend = (; title = "Splines", framevisible = false),
)
return cfg
end
@@ -225,19 +205,14 @@ function PlotConfig(T::Val{:erp})
:ticklabels => false,
)),
),
- legend = (;
- tellwidth = false,
- halign = :right,
- valign = :center,
- framevisible = false,
- ),
+ legend = (; framevisible = false),
axis = (
xlabel = "Time [s]",
ylabel = "Voltage [Β΅V]",
yticklabelsize = 14,
xtickformat = "{:.1f}",
),
- colorbar = (; label = "", flipaxis = true, labelrotation = -Ο / 2),
+ colorbar = (; label = "", flipaxis = true),
)
return cfg
@@ -255,6 +230,7 @@ function PlotConfig(T::Val{:erpgrid})
ylabel = "Voltage [Β΅V]",
xlim = [-0.04, 1],
ylim = [-0.04, 1],
+ fontsize = 12,
),
)
return cfg
@@ -265,7 +241,7 @@ function PlotConfig(T::Val{:channelimage})
config_kwargs!(
cfg;
#layout = (; use_colorbar = true),
- colorbar = (; label = "Voltage [Β΅V]", labelrotation = -Ο / 2),
+ colorbar = (; label = "Voltage [Β΅V]"),
axis = (xlabel = "Time [s]", ylabel = "Channels", yticklabelsize = 14),
visual = (; colormap = Reverse("RdBu")), #cork
)
@@ -275,8 +251,8 @@ function PlotConfig(T::Val{:erpimage})
cfg = PlotConfig()
config_kwargs!(
cfg;
- layout = (; use_colorbar = true, show_legend = false),
- colorbar = (; label = "Voltage [Β΅V]", labelrotation = -Ο / 2),
+ layout = (; use_colorbar = true),
+ colorbar = (; label = "Voltage [Β΅V]"),
axis = (xlabel = "Time [s]", ylabel = "Trials"),
visual = (; colormap = Reverse("RdBu")),
)
@@ -294,6 +270,7 @@ function PlotConfig(T::Val{:paracoord})
axis = (; xlabel = "Channels", ylabel = "Time", title = ""),
legend = (; title = "Conditions", merge = true, framevisible = false), # fontsize = 14),
mapping = (; x = :channel),
+ layout = (; show_legend = true),
)
return cfg
end
@@ -325,3 +302,34 @@ function resolve_mappings(plot_data, mapping_data) # check mapping_data in PlotC
end
return (; mapping_dict...)
end
+
+"""
+ config_kwargs!(cfg::PlotConfig; kwargs...)
+Takes NamedTuple of `Key => NamedTuple` as kwargs and merges the fields with the defaults.
+"""
+function config_kwargs!(cfg::PlotConfig; kwargs...)
+
+ is_namedtuple = [isa(t, NamedTuple) for t in values(kwargs)]
+ @assert(
+ all(is_namedtuple),
+ """ Keyword argument specification (kwargs...). Specified config groups must be from `NamedTuple`, 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 needed. The second is incorrect and its call is ignored."""
+ )
+ field_list = fieldnames(PlotConfig) #[:layout, :visual, :mapping, :legend, :colorbar, :axis]
+ key_list = collect(keys(kwargs))
+ :extra β key_list ?
+ @warn(
+ "Extra is deprecated in 0.4, and extra keyword arguments must be used directly as keyword arguments."
+ ) : ""
+ apply_to = key_list[in.(key_list, Ref(field_list))]
+ for k β apply_to
+ setfield!(cfg, k, merge(getfield(cfg, k), kwargs[k]))
+ end
+end
diff --git a/src/supportive_defaults.jl b/src/supportive_defaults.jl
new file mode 100644
index 000000000..f6427141c
--- /dev/null
+++ b/src/supportive_defaults.jl
@@ -0,0 +1,63 @@
+
+"""
+ supportive_defaults(cfg_symb::Symbol)
+
+Default configurations for the supporting axis. Similar to PlotConfig, but these configurations are not shared by all plots.\\
+Such supporting axes allow users to flexibly see defaults in docstrings and manipulate them using corresponding axes.
+
+For developers: to make them updateable in the function, use `update_axis`.
+**Return value:** `NamedTuple`.
+"""
+function supportive_defaults(cfg_symb::Symbol)
+ # plot_splines
+ if cfg_symb == :spline_default
+ return (;
+ ylabel = "Spline value",
+ xlabelvisible = false,
+ xticklabelsvisible = false,
+ ylabelvisible = true,
+ )
+ elseif cfg_symb == :density_default
+ return (; xautolimitmargin = (0, 0), ylabel = "Density value")
+ elseif cfg_symb == :superlabel_default
+ return (; fontsize = 20, padding = (0, 0, 40, 0))
+ # plot_butterfly
+ elseif cfg_symb == :topo_default
+ return (;
+ width = Relative(0.35),
+ height = Relative(0.35),
+ halign = 0.05,
+ valign = 0.95,
+ aspect = 1,
+ )
+ # plot_erpimage
+ elseif cfg_symb == :meanplot_default
+ return (;
+ height = 100,
+ xlabel = "Time [s]",
+ xlabelpadding = 0,
+ xautolimitmargin = (0, 0),
+ )
+ elseif cfg_symb == :sortplot_default
+ return (; ylabelvisible = true, yticklabelsvisible = false)
+ # plot_erpgrid
+ elseif cfg_symb == :hlines_grid_default
+ return (; color = :gray, linewidth = 0.5)
+ elseif cfg_symb == :vlines_grid_default
+ return (; color = :gray, linewidth = 0.5, ymin = 0.2, ymax = 0.8)
+ elseif cfg_symb == :lines_grid_default
+ return (; color = :deepskyblue3)
+ elseif cfg_symb == :labels_grid_default
+ return (; color = :gray, fontsize = 12, align = (:left, :top), space = :relative)
+ end
+end
+
+"""
+ update_axis(support_axis::NamedTuple; kwargs...)
+Update values of `NamedTuple{key = value}`.\\
+Used for supportive axes to make users be able to flexibly change them.
+"""
+function update_axis(support_axis::NamedTuple; kwargs...)
+ support_axis = (; support_axis..., kwargs...)
+ return support_axis
+end
diff --git a/test/Project.toml b/test/Project.toml
index 51872b03f..181e9f34a 100644
--- a/test/Project.toml
+++ b/test/Project.toml
@@ -1,5 +1,6 @@
[deps]
AlgebraOfGraphics = "cbdf2221-f076-402e-a563-3d30da359d67"
+BSplineKit = "093aae92-e908-43d7-9660-e50ee39d5a0a"
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
@@ -10,3 +11,7 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
TopoPlots = "2bdbdf9c-dbd8-403f-947b-1a4e0dd41a7a"
Unfold = "181c99d8-e21b-4ff3-b70b-c233eddec679"
UnfoldSim = "ed8ae6d2-84d3-44c6-ab46-0baf21700804"
+
+[compat]
+AlgebraOfGraphics = "0.7, 0.8"
+BSplineKit = "0.16, 0.17"
diff --git a/test/runtests.jl b/test/runtests.jl
index 976f86f0c..ceafcb803 100644
--- a/test/runtests.jl
+++ b/test/runtests.jl
@@ -54,6 +54,10 @@ end
include("test_dm.jl")
end
+@testset "Spline plots" begin
+ include("test_splines.jl")
+end
+
@testset "Complex plots" begin
include("test_complexplots.jl")
end
diff --git a/test/test_butterfly.jl b/test/test_butterfly.jl
index 8115eafcc..0d8d162ef 100644
--- a/test/test_butterfly.jl
+++ b/test/test_butterfly.jl
@@ -25,7 +25,7 @@ end
plot_butterfly!(f[1, 1], mat; positions = pos)
end
-@testset "butterfly: witout topolegend" begin
+@testset "butterfly: without topolegend" begin
plot_butterfly(
df;
positions = pos,
@@ -39,9 +39,8 @@ end
plot_butterfly(
df;
positions = pos,
- topomarkersize = 10,
- topoheight = 0.4,
- topowidth = 0.4,
+ topomarkersize = 70,
+ topo_axis = (; height = Relative(0.4), width = Relative(0.4)),
)
end
@@ -70,8 +69,7 @@ end
f[1, 1],
df;
positions = pos,
- topoheight = 0.4,
- topowidth = 0.4,
+ topo_axis = (; height = Relative(0.4), width = Relative(0.4)),
layout = (;
hidedecorations = (:label => true, :ticks => true, :ticklabels => true)
),
diff --git a/test/test_complexplots.jl b/test/test_complexplots.jl
index 82ca44a53..4837419bf 100644
--- a/test/test_complexplots.jl
+++ b/test/test_complexplots.jl
@@ -34,8 +34,7 @@
d_topo;
positions = pos,
topomarkersize = 10,
- topoheight = 0.4,
- topowidth = 0.4,
+ topo_axis = (; height = Relative(0.4), width = Relative(0.4)),
)
hlines!(0, color = :gray, linewidth = 1)
vlines!(0, color = :gray, linewidth = 1)
@@ -110,21 +109,13 @@ end
uf_5chan = example_data("UnfoldLinearModelMultiChannel")
d_singletrial, _ = UnfoldSim.predef_eeg(; return_epoched = true)
-
pvals = DataFrame(
from = [0.1, 0.15],
to = [0.2, 0.5],
# if coefname not specified, line should be black
coefname = ["(Intercept)", "category: face"],
)
- plot_erp!(
- f[1, 1],
- results,
- categorical_color = false,
- categorical_group = false,
- significance = pvals,
- stderror = true,
- )
+ plot_erp!(f[1, 1], results, significance = pvals, stderror = true)
plot_butterfly!(f[1, 2], d_topo, positions = positions)
plot_topoplot!(f[2, 1], data[:, 150, 1]; positions = positions)
@@ -181,14 +172,7 @@ end
# if coefname not specified, line should be black
coefname = ["(Intercept)", "category: face"],
)
- plot_erp!(
- f[2, 1:2],
- results,
- categorical_color = false,
- categorical_group = false,
- significance = pvals,
- stderror = true,
- )
+ plot_erp!(f[2, 1:2], results, significance = pvals, stderror = true)
plot_designmatrix!(f[2, 3], designmatrix(uf))
@@ -206,10 +190,7 @@ end
plot_erp!(
f[2, 4:5],
res_effects;
- categorical_color = false,
- categorical_group = true,
- mapping = (; y = :yhat, color = :continuous, group = :continuous),
- layout = (; show_legend = true),
+ mapping = (; y = :yhat, color = :continuous, group = :continuous => nonnumeric),
)
plot_parallelcoordinates(f[3, 2:3], uf_5chan; mapping = (; color = :coefname))
diff --git a/test/test_erp.jl b/test/test_erp.jl
index 5f19b9bf8..b48a0a843 100644
--- a/test/test_erp.jl
+++ b/test/test_erp.jl
@@ -1,11 +1,16 @@
+using Unfold: stderror
using AlgebraOfGraphics: group
include("../docs/example_data.jl")
m = example_data("UnfoldLinearModel")
+
results = coeftable(m)
res_effects = effects(Dict(:continuous => -5:0.5:5), m)
res_effects2 = effects(Dict(:condition => ["car", "face"], :continuous => -5:5), m)
dat, positions = TopoPlots.example_data()
+m7 = example_data("7channels")
+results7 = coeftable(m7)
+
@testset "ERP plot: DataFrame data" begin
plot_erp(results)
end
@@ -18,19 +23,27 @@ end
plot_erp(dat[1, :, 1])
end
+@testset "ERP plot: rename xlabel" begin
+ plot_erp(results; axis = (; xlabel = "test"))
+end
+
+@testset "ERP plot: xlabelvisible" begin
+ plot_erp(results; axis = (; xlabelvisible = false, xticklabelsvisible = false))
+end
+
@testset "ERP plot: Array data with times vector" begin
times = range(0, step = 100, length = size(dat, 2))
plot_erp(times, dat[1, :, 1], axis = (; xtickformat = "{:d}"))
end
@testset "ERP plot: stderror error" begin
- plot_erp(results; :stderror => true)
+ plot_erp(results; stderror = true)
end
@testset "ERP plot: standart errors in GridLayout" begin
f = Figure(size = (1200, 1400))
ga = f[1, 1] = GridLayout()
- plot_erp!(ga, results; :stderror => true)
+ plot_erp!(ga, results; stderror = true)
f
end
@@ -40,24 +53,31 @@ end
plot_erp(results; mapping = (; col = :group))
end
+@testset "ERP plot: faceting by two columns with stderror" begin
+ results = coeftable(m)
+ results.group = push!(repeat(["A", "B"], inner = 67), "A")
+ plot_erp(results; mapping = (; col = :group), stderror = true)
+end
+
@testset "ERP plot: with and withour error ribbons" begin
results = coeftable(m)
- f = Figure()
results.coefname =
replace(results.coefname, "condition: face" => "face", "(Intercept)" => "car")
results = filter(row -> row.coefname != "continuous", results)
+
+ f = Figure()
plot_erp!(
f[1, 1],
results;
- axis = (title = "Bad example", titlegap = 12),
- :stderror => false,
+ axis = (; title = "Bad example", titlegap = 12),
+ stderror = false,
mapping = (; color = :coefname => "Conditions"),
)
plot_erp!(
f[2, 1],
results;
axis = (title = "Good example", titlegap = 12),
- :stderror => true,
+ stderror = true,
mapping = (; color = :coefname => "Conditions"),
)
@@ -81,50 +101,23 @@ end
# if coefname not specified, line should be black
coefname = ["(Intercept)", "category: face"],
)
- plot_erp!(
- ga,
- results;
- categorical_color = false,
- categorical_group = false,
- significance = pvals,
- stderror = true,
- )
+ plot_erp!(ga, results; significance = pvals, stderror = true)
f
end
@testset "ERP plot with significance" begin
pvals = DataFrame(
- from = [0.1, 0.3],
- to = [0.5, 0.7],
+ from = [0.01, 0.2],
+ to = [0.3, 0.4],
coefname = ["(Intercept)", "condition: face"], # if coefname not specified, line should be black
)
plot_erp(results; :significance => pvals)
end
@testset "ERP plot: 7 channels faceted" begin
- m7 = example_data("7channels")
- results7 = coeftable(m7)
plot_erp(results7, mapping = (; col = :channel, group = :channel))
end
-
-@testset "ERP plot: with colorbar and legend" begin
- plot_erp(
- res_effects2;
- mapping = (; color = :continuous, linestyle = :condition, group = :continuous),
- categorical_color = false,
- )
-end
-
-#= @testset "ERP plot: with colorbar and legend 2" begin
- plot_erp(
- res_effects2;
- mapping = (; color = :continuous, group = :continuous),
- categorical_color = false,
- categorical_group = false,
- )
-end =#
-
@testset "ERP plot: rename legend" begin
f = Figure()
results = coeftable(m)
@@ -132,11 +125,50 @@ end =#
replace(results.coefname, "condition: face" => "face", "(Intercept)" => "car")
results = filter(row -> row.coefname != "continuous", results)
plot_erp!(
- f[1, 1],
+ f,
results;
axis = (title = "Bad example", titlegap = 12),
- :stderror => false,
mapping = (; color = :coefname => "Conditions"),
)
f
end
+
+@testset "ERP plot: Facet sorting" begin
+ data, evts = UnfoldSim.predef_eeg()
+
+ m = fit(
+ UnfoldModel,
+ [
+ "car" => (@formula(0 ~ 1 + continuous), firbasis((-0.1, 1), 100)),
+ "face" => (@formula(0 ~ 1 + continuous), firbasis((-0.1, 1), 100)),
+ ],
+ evts,
+ data;
+ eventcolumn = :condition,
+ )
+ eff = effects(Dict(:continuous => 75:20:300), m)
+
+ sorting1 = ["face", "car"] # check
+ sorting2 = ["car", "face"]
+
+ f = Figure()
+ plot_erp!(
+ f[1, 1],
+ eff;
+ mapping = (;
+ col = :eventname => sorter(sorting1),
+ color = :continuous,
+ group = :continuous,
+ ),
+ )
+ plot_erp!(
+ f[2, 1],
+ eff;
+ mapping = (;
+ col = :eventname => sorter(sorting2),
+ color = :continuous,
+ group = :continuous,
+ ),
+ )
+ f
+end
diff --git a/test/test_erp_effects.jl b/test/test_erp_effects.jl
index 59eb817eb..dc8b2e17d 100644
--- a/test/test_erp_effects.jl
+++ b/test/test_erp_effects.jl
@@ -5,62 +5,48 @@ m = example_data("UnfoldLinearModel")
res_effects = effects(Dict(:continuous => -5:0.5:5), m)
res_effects2 = effects(Dict(:condition => ["car", "face"], :continuous => -5:5), m)
-@testset "Effect plot" begin #where is legend here??
- plot_erp(
- res_effects;
- mapping = (; y = :yhat, color = :continuous, group = :continuous),
- legend = (; nbanks = 2),
- categorical_color = false,
- categorical_group = true,
- )
+@testset "Effect plot" begin
+ plot_erp(res_effects; mapping = (; y = :yhat, color = :continuous, group = :continuous))
end
-@testset "Effect plot: faceted" begin #bug
+@testset "Effect plot: faceted" begin
res_effects = effects(Dict(:continuous => -5:0.5:5), m)
res_effects.channel = push!(repeat(["1", "2"], 472), "1")
- plot_erp(res_effects; mapping = (; y = :yhat, color = :continuous, col = :channel))
+ plot_erp(
+ res_effects;
+ mapping = (; y = :yhat, color = :continuous => nonnumeric, col = :channel),
+ legend = (; nbanks = 2),
+ )
end
@testset "Effect plot: faceted channels" begin #bug
res_effects = effects(Dict(:continuous => -5:0.5:5), m)
res_effects.channel = push!(repeat(["1", "2"], 472), "1")
- #res_effects.channel = float.(push!(repeat([1, 2], 472), 1))
- plot_erp(res_effects; mapping = (; y = :yhat, group = :channel, col = :channel))
-end
-
-@testset "Effect plot: no colorbar and legend" begin
plot_erp(
- res_effects2;
- mapping = (; color = :continuous, linestyle = :condition, group = :continuous),
- layout = (; show_legend = true, use_legend = false, use_colorbar = false),
- categorical_color = false,
+ res_effects;
+ mapping = (;
+ y = :yhat,
+ color = :continuous => nonnumeric,
+ group = :channel,
+ col = :channel => nonnumeric,
+ ),
+ legend = (; nbanks = 2),
)
end
-@testset "Effect plot: no colorbar" begin
+@testset "Effect plot: no colorbar and yes legend" begin
plot_erp(
res_effects2;
mapping = (; color = :continuous, linestyle = :condition, group = :continuous),
layout = (; use_legend = true, use_colorbar = false),
- categorical_color = false,
)
end
-@testset "Effect plot: no legend" begin
+@testset "Effect plot: yes colorbar and no legend" begin
plot_erp(
res_effects2;
mapping = (; color = :continuous, linestyle = :condition, group = :continuous),
layout = (; use_legend = false, use_colorbar = true),
- categorical_color = false,
- )
-end
-
-@testset "Effect plot: no colorbar and no legend" begin
- plot_erp(
- res_effects2;
- mapping = (; color = :continuous, linestyle = :condition, group = :continuous),
- layout = (; use_legend = false, use_colorbar = false),
- categorical_color = false,
)
end
@@ -69,26 +55,22 @@ end
res_effects2;
mapping = (; color = :continuous, linestyle = :condition, group = :continuous),
layout = (; use_legend = true, use_colorbar = true),
- categorical_color = false,
)
end
-
-@testset "Effect plot: should be no gap instead of legend" begin
+@testset "Effect plot: no colorbar and no legend" begin
plot_erp(
res_effects2;
- mapping = (; color = :continuous, group = :continuous),
- categorical_color = false,
+ mapping = (; color = :continuous, linestyle = :condition, group = :continuous),
+ layout = (; use_legend = false, use_colorbar = false),
)
end
-
@testset "Effect plot: move legend" begin
plot_erp(
res_effects2;
mapping = (; color = :continuous, linestyle = :condition, group = :continuous),
- legend = (; valign = :bottom, halign = :right, tellwidth = false),
- categorical_color = false,
+ legend = (; valign = :bottom, halign = :right),
axis = (
title = "Marginal effects",
titlegap = 12,
@@ -104,14 +86,18 @@ end
@testset "Effect plot: xlabelvisible is not working" begin
eff_same = effects(Dict(:condition => ["car", "face"], :duration => 200), m)
+
+ plot_erp(results; axis = (; xlabelvisible = false, xticklabelsvisible = false))
plot_erp(
- res_effects2;
- mapping = (; col = :eventname),#, color = :condition), why it doesn't work???
+ eff_same;
+ mapping = (; col = :condition, color = :time),
axis = (;
+ xlabel = "test",
titlevisible = false,
xlabelvisible = false,
ylabelvisible = false,
yticklabelsvisible = false,
+ xticklabelsvisible = false,
),
)
end
diff --git a/test/test_erpgrid.jl b/test/test_erpgrid.jl
index a7caf4fbd..d574a361e 100644
--- a/test/test_erpgrid.jl
+++ b/test/test_erpgrid.jl
@@ -25,6 +25,35 @@ end
plot_erpgrid(data[1:6, :], pos[1:6], raw_ch_names[1:6]; drawlabels = true)
end
+@testset "erpgrid: customizable labels" begin
+ plot_erpgrid(
+ data[1:6, :],
+ pos[1:6],
+ raw_ch_names[1:6];
+ drawlabels = true,
+ labels_grid_axis = (; color = :red),
+ )
+end
+
+@testset "erpgrid: customizable vlines and hlines" begin
+ plot_erpgrid(
+ data[1:6, :],
+ pos[1:6],
+ raw_ch_names[1:6];
+ hlines_grid_axis = (; color = :red),
+ vlines_grid_axis = (; color = :green),
+ )
+end
+
+@testset "erpgrid: customizable lines" begin
+ plot_erpgrid(
+ data[1:6, :],
+ pos[1:6],
+ raw_ch_names[1:6];
+ lines_grid_axis = (; color = :red),
+ )
+end
+
@testset "erpgrid: GridPosition" begin
f = Figure()
plot_erpgrid!(f[1, 1], data, pos)
diff --git a/test/test_pcp.jl b/test/test_pcp.jl
index 84a3063b8..bdf13257e 100644
--- a/test/test_pcp.jl
+++ b/test/test_pcp.jl
@@ -1,5 +1,6 @@
include("../docs/example_data.jl") # we need more specified example data
results_plot, positions = example_data()
+
@testset "PCP: data input DataFrame" begin
plot_parallelcoordinates(results_plot)
end
@@ -15,6 +16,14 @@ end
plot_parallelcoordinates(results_plot; mapping = (color = :coefname, y = :estimate))
end
+@testset "PCP: show_legend = false" begin
+ plot_parallelcoordinates(
+ results_plot;
+ mapping = (color = :coefname, y = :estimate),
+ layout = (; show_legend = false),
+ )
+end
+
@testset "PCP: Figure, 64 channels, 1 condition, bigger size" begin
plot_parallelcoordinates(
Figure(size = (1200, 800)),
@@ -71,7 +80,7 @@ end
plot_parallelcoordinates(
uf_5chan;
mapping = (; color = :coefname),
- layout = (; legend_position = :right),
+ legend = (; valign = :center),
)
end
@@ -170,7 +179,6 @@ end
f[1, 1],
uf_5chan;
mapping = (; color = :coefname),
- layout = (; legend_position = :right),
visual = (; alpha = 0.1),
axis = (; title = "alpha = 0.1"),
)
@@ -178,7 +186,6 @@ end
f[2, 1],
uf_5chan,
mapping = (; color = :coefname),
- layout = (; legend_position = :right),
visual = (; alpha = 0.9),
axis = (; title = "alpha = 0.9"),
)
@@ -202,22 +209,3 @@ end
)
f
end
-
-begin
- f = Figure()
- plot_parallelcoordinates(
- f[1, 1],
- subset(results_plot, :channel => x -> x .< 10);
- mapping = (; color = :coefname),
- axis = (; title = "normalize = nothing"),
- )
- plot_parallelcoordinates(
- f[2, 1],
- subset(results_plot, :channel => x -> x .< 10);
- mapping = (; color = :coefname),
- normalize = :minmax,
- axis = (; title = "normalize = :minmax"),
- )
- f
-
-end
diff --git a/test/test_splines.jl b/test/test_splines.jl
new file mode 100644
index 000000000..e6e7c6a85
--- /dev/null
+++ b/test/test_splines.jl
@@ -0,0 +1,36 @@
+using BSplineKit, Unfold
+m0 = example_data("UnfoldLinearModel")
+m1 = example_data("UnfoldLinearModelwith1Spline")
+m2 = example_data("UnfoldLinearModelwith2Splines")
+
+@testset "Spline plot: no splines" begin
+ err1 = nothing
+ t() = error(plot_splines(m0))
+ try
+ t()
+ catch err1
+ end
+ @test err1 == AssertionError(
+ "No spline term is found in UnfoldModel. Does your UnfoldModel really have a `spl(...)` or other `AbstractSplineTerm`?",
+ )
+end
+
+@testset "Spline plot: basic" begin
+ plot_splines(m1)
+end
+
+@testset "Spline plot: two spline terms" begin
+ plot_splines(m2)
+end
+
+@testset "Spline plot: spline_axis check" begin
+ plot_splines(m2; spline_axis = (; ylabel = "test"))
+end
+
+@testset "Spline plot: density_axis check" begin
+ plot_splines(m2, density_axis = (; ylabel = "test"))
+end
+
+@testset "Spline plot: superlabel_axis check" begin
+ plot_splines(m2; superlabel_config = (; fontsize = 60))
+end
diff --git a/test/test_topoplot.jl b/test/test_topoplot.jl
index 76508b89c..f9518fcb3 100644
--- a/test/test_topoplot.jl
+++ b/test/test_topoplot.jl
@@ -25,8 +25,16 @@ end
plot_topoplot(d1; positions = rand(Point2f, 10))
end
+@testset "topoplot: highliht an electrode" begin
+ plot_topoplot(dat[:, 50, 1]; positions, high_chan = 2)
+end
+
+@testset "topoplot: highliht several electrodes" begin
+ plot_topoplot(dat[:, 50, 1]; positions, high_chan = [1, 2])
+end
+
@testset "topoplot: no legend" begin
- plot_topoplot(dat[:, 50, 1]; positions = positions, layout = (; show_legend = false))
+ plot_topoplot(dat[:, 50, 1]; positions = positions, layout = (; use_colorbar = false))
end
@testset "topoplot: xlabel" begin
diff --git a/test/test_toposeries1.jl b/test/test_toposeries1.jl
index 775ee60d2..ead15dc40 100644
--- a/test/test_toposeries1.jl
+++ b/test/test_toposeries1.jl
@@ -12,6 +12,10 @@ end
plot_topoplotseries(df; bin_num = 5, positions = positions)
end
+@testset "toposeries: bin_num" begin
+ plot_topoplotseries(df; bin_num = 5, positions = positions, axis = (; xlabel = "test"))
+end
+
@testset "toposeries: checking other y value" begin
df.cont = df.time .* 3
plot_topoplotseries(df; bin_num = 5, positions = positions, mapping = (; col = :cont))
@@ -145,7 +149,7 @@ end
df;
bin_width,
positions = positions,
- colorbar = (; colorrange = (-3, 3)),
+ visual = (; colorrange = (-3, 3)),
)
end
diff --git a/test/test_toposeries2.jl b/test/test_toposeries2.jl
index f15d5597f..e6b84d4d2 100644
--- a/test/test_toposeries2.jl
+++ b/test/test_toposeries2.jl
@@ -29,7 +29,6 @@ end
)
end
-
@testset "error checking: bin_width and bin_num specified" begin
err1 = nothing
t() = error(plot_topoplotseries(df; bin_width = 80, bin_num = 5, positions = positions))
@@ -99,17 +98,19 @@ end
mapping = (; col = :condition),
)
end
-
-#= @testset "4 condtions in rows" begin # TBD
+#=
+@testset "4 condtions in rows" begin # TBD
df = UnfoldMakie.eeg_array_to_dataframe(dat[:, 1:4, 1], string.(1:length(positions)))
df.condition = repeat(["A", "B", "C", "D"], size(df, 1) Γ· 4)
plot_topoplotseries(
df;
+ bin_num = 3,
positions = positions,
mapping = (; row = :condition),
)
-end =#
+end
+=#
@testset "topoplot axes configuration" begin # TBD
df = UnfoldMakie.eeg_array_to_dataframe(dat[:, 1:4, 1], string.(1:length(positions)))
@@ -129,7 +130,6 @@ end =#
)
end
-
@testset "change xlabel" begin
df = UnfoldMakie.eeg_array_to_dataframe(dat[:, 1:2, 1], string.(1:length(positions)))
df.condition = repeat(["A", "B"], size(df, 1) Γ· 2)
@@ -177,3 +177,10 @@ end
interactive_scatter = obs_tuple,
)
end
+#=
+@testset "interactive data in eeg_array_to_dataframe" begin
+ data_obs3 = Observable(UnfoldMakie.eeg_array_to_dataframe(rand(10, 20)))
+ plot_topoplotseries!(Figure(), data_obs3; bin_num = 5, positions = rand(Point2f, 10))
+ data_obs3[] = UnfoldMakie.eeg_array_to_dataframe(rand(10, 20))
+end
+=#