Topoplot Series
Topoplot series is a plot type for visualizing EEG activity in a given time frame or time interval. It can fully represent channel and channel location dimensions using contour lines. It can also partially represent the time dimension. Basically, it is a series of Topoplots.
Setup
Package loading
using Unfold
using UnfoldMakie
using DataFrames
using CairoMakie
using TopoPlots
using Statistics
Data input
data, positions = TopoPlots.example_data()
df = UnfoldMakie.eeg_array_to_dataframe(data[:, :, 1], string.(1:length(positions)));
Number of topoplots
There are two ways to specify the number of topoplots in a topoplot series: bin_width
- specify the interval between topoplots
bin_width = 80
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,
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.
f = Figure()
df_cat = UnfoldMakie.eeg_array_to_dataframe(data[:, 1:5, 1], string.(1:length(positions)))
df_cat.condition = repeat(["A", "B", "C", "D", "E"], size(df_cat, 1) ÷ 5)
plot_topoplotseries!(
f[1, 1],
df_cat;
nrows = 2,
mapping = (; col = :condition),
axis = (; xlabel = "Conditions"),
positions = positions,
)
f
Version with conditional mapping.row
is not yet implemented.
To create topoplot series with categorical values:
- Do not specify
bin_width
orbin_num
. - Put categorical value in
mapping.col
.
Additional features
Adjusting individual topoplots
By using topoplot_axes
you can flexibly change configurations of topoplots.
df_adj = UnfoldMakie.eeg_array_to_dataframe(data[:, 1:4, 1], string.(1:length(positions)))
df_adj.condition = repeat(["A", "B", "C", "D"], size(df_adj, 1) ÷ 4)
plot_topoplotseries(
df_adj;
nrows = 2,
positions = positions,
mapping = (; col = :condition),
axis = (; title = "axis title", xlabel = "Conditions"),
topoplot_axes = (;
rightspinevisible = true,
xlabelvisible = false,
title = "single topoplot title",
),
)
Adjusting column gaps
Using colgap
in with_theme
helps to adjust column gaps.
with_theme(colgap = 5) do
plot_topoplotseries(df, bin_num = 5; positions = positions)
end
However it doesn't work with subsets. Here you need to use topoplot_axes.limits
.
begin
f = Figure()
plot_topoplotseries!(
f[1, 1],
df,
bin_num = 5;
positions = positions,
topoplot_axes = (; limits = (-0.05, 1.05, -0.1, 1.05)),
)
f
end
Adjusting contours
Topographic contour is a line drawn on a topographic map to indicate an increase or decrease in voltage. A contour level is an area with a specific range of voltage. By default, the number of contour levels is 6, which means that the topography plot is divided into 6 areas depending on their voltage values.
plot_topoplotseries(
df;
bin_width,
positions = positions,
visual = (; enlarge = 0.9, contours = (; linewidth = 1, color = :black)),
)
Aggregating functions
In this example combinefun
is specified by mean
, median
and std
.
f = Figure(size = (500, 500))
plot_topoplotseries!(
f[1, 1],
df;
bin_width,
positions = positions,
combinefun = mean,
axis = (; xlabel = "", title = "combinefun = mean"),
)
plot_topoplotseries!(
f[2, 1],
df;
bin_width,
positions = positions,
combinefun = median,
axis = (; xlabel = "", title = "combinefun = median"),
)
plot_topoplotseries!(
f[3, 1],
df;
bin_width,
positions = positions,
combinefun = std,
axis = (; title = "combinefun = std"),
)
f
Multiple rows
Use nrows
to specify multiple rows.
f = Figure()
df_col = UnfoldMakie.eeg_array_to_dataframe(data[:, :, 1], string.(1:length(positions)))
plot_topoplotseries!(
f[1, 1:5],
df_col;
bin_num = 14,
nrows = 4,
positions = positions,
visual = (; label_scatter = false),
)
f
Channel labels
Use visual
to specify channel labelss and channels markers. visual.label_text = true
makes channel names visible.
begin
f = Figure()
df_col = UnfoldMakie.eeg_array_to_dataframe(data[1:4, :, 1], string.(1:4))
labs4 = ["s1", "s2", "s3", "s4"]
plot_topoplotseries!(
f[1, 1:5],
df_col;
bin_num = 2,
positions = positions[4:7],
labels = labs4,
visual = (;
label_scatter = (
markersize = 15,
color = "white",
strokecolor = "green",
strokewidth = 2,
),
label_text = true,
),
)
f
end
Configurations of Topoplot series
Also you can:
- Label the x-axis with
axis.xlabel
. - Hide electrode markers with
visual.label_scatter
. - Change the color map with
visual.colormap
. The default isReverse(:RdBu)
. - Adjust the limits of the topoplot boxes with
axis.xlim_topo
andaxis.ylim_topo
. By default both are(-0.25, 0.25)
. - Adjust the size of the figure with
Figure(size = (x, y))
. - Adjust the padding between topoplot labels and axis labels using
xlabelpadding
andylabelpadding
.
UnfoldMakie.plot_topoplotseries
— Functionplot_topoplotseries(f::Union{GridPosition, GridLayout, Figure}, data::Union{<:Observable{<:DataFrame},DataFrame}; kwargs...)
plot_topoplotseries!(data::Union{<:Observable{<:DataFrame},DataFrame}; kwargs...)
Multiple miniature topoplots in regular distances.
Arguments
f::Union{GridPosition, GridLayout, GridLayoutBase.GridSubposition, Figure}
Figure
,GridLayout
,GridPosition
, orGridLayoutBase.GridSubposition
to draw the plot.data::Union{<:Observable{<:DataFrame},DataFrame}
DataFrame with data or Observable DataFrame.
Requires atime
column by default, but can be overridden by specifyingmapping=(; x=:my_column)
with any continuous or categorical column.
Keyword arguments (kwargs)
bin_width::Real = nothing
Number specifing the width of bin of continuous x-value in its units.bin_num::Real = nothing
Number of topoplots.
Eitherbin_width
, orbin_num
should be specified. Error if they are both specified
Ifmapping.col
ormapping.row
are categoricalbin_width
andbin_num
stay asnothing
.combinefun::Function = mean
Specify how the samples withinbin_width
are summarised.
Example functions:mean
,median
,std
.rasterize_heatmaps::Bool = true
Force rasterization of the plot heatmap when saving insvg
format.
Except for the interpolated heatmap, all lines/points are vectors.
This is typically what you want, otherwise you get ~128x128 vectors per topoplot, which makes everything very slow.col_labels::Bool
,row_labels::Bool = true
Shows column and row labels for categorical values.positions::Vector{Point{2, Float32}} = nothing
Specify channel positions. Requires the list of x and y positions for all unique electrodes.labels::Vector{String} = nothing
Show labels for each electrode.interactive_scatter = nothing
Enable interactive mode.
If you createobs_tuple = Observable((0, 0, 0))
and pass it intointeractive_scatter
you can update the observable tuple with the indices of the clicked topoplot markers.
(0, 0, 0)
corresponds to the (row of topoplot layout, column of topoplot layout, electrode).topo_axis::NamedTuple = (;)
Here you can flexibly change configurations of topoplots.
To see all options just type?Axis
in REPL.mapping = (; col = :time
, row = nothing, layout = nothing)
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}
Resposnible for colorrange in topoplots and in colorbar.topo_attributes::NamedTuple = (;)
Here you can flexibly change configurations of the topoplot interoplation.
To see all options just type?Topoplot.topoplot
in REPL.
Defaults: interp_resolution = (128, 128), interpolation = CloughTocher()
Shared plot configuration options
The shared plot options can be used as follows: type = (; key = value, ...))
.
For example, plot_x(...; colorbar = (; vertical = true, label = "Test"))
.
Multiple defaults will be cycled until match.
Placing ;
is important!
figure = NamedTuple() - use kwargs...
of Makie.Figure
axis = (xlabel = "Time windows", aspect = Makie.DataAspect(), title = "", titlesize = 16, titlefont = :bold, ylabel = "", ylabelpadding = 25, xlabelpadding = 25, xpanlock = true, ypanlock = true, xzoomlock = true, yzoomlock = true, xrectzoom = false, yrectzoom = false) - use kwargs...
of Makie.Axis
layout = (show_legend = true, use_colorbar = true, hidespines = (), hidedecorations = Dict{Symbol, Bool}(:label => 0)) - check this page
mapping = (x = nothing, y = (:estimate, :yhat, :y), positions = (:pos, :positions, :position, nothing), labels = (:labels, :label, :sensor, nothing), col = (:time,), row = (nothing,)) - use any mapping from AlgebraOfGraphics
visual = (colormap = Makie.Reverse{Symbol}(:RdBu), contours = (color = :white, linewidth = 2), enlarge = 1, label_scatter = false, label_text = false, bounding_geometry = GeometryBasics.Circle, levels = nothing) - use kwargs...
of Topoplot.eeg_topoplot
legend = (orientation = :vertical, tellwidth = true, tellheight = false, halign = :right, valign = :center) - use kwargs...
of Makie.Legend
colorbar = (vertical = true, tellwidth = true, tellheight = false, labelrotation = -1.5707963267948966, flipaxis = true, label = "Voltage", colorrange = nothing) - use kwargs...
of Makie.Colorbar
Return Value: Figure
displaying the Topoplot series.
This page was generated using Literate.jl.