From bc63357d0d5426037397531fba1d43d671225654 Mon Sep 17 00:00:00 2001 From: "behinger (s-ccs 001)" Date: Mon, 11 Sep 2023 16:44:59 +0000 Subject: [PATCH 1/3] fixes #66,#67,#64,#63 --- src/eeg-series.jl | 14 +++++++++++++- src/plot_topoplotseries.jl | 13 +++++++++++-- src/plotconfig.jl | 2 ++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/eeg-series.jl b/src/eeg-series.jl index 7ceaa22f5..71ac034b7 100644 --- a/src/eeg-series.jl +++ b/src/eeg-series.jl @@ -74,6 +74,8 @@ function eeg_topoplot_series!(fig, data::DataFrame, col=:time, row=nothing, combinefun=mean, + bin_labels = false, + rasterize_heatmap = true, topoplot_attributes...) # cannot be made easier right now, but Simon promised a simpler solution "soonish" @@ -116,12 +118,22 @@ function eeg_topoplot_series!(fig, data::DataFrame, sel = sel .&& (data_mean[:, row] .== select_row[r]) # subselect end df_single = data_mean[sel, :] + # select labels labels = df_single[:, col_label] # select data d_vec = df_single[:, col_y] # plot it - eeg_topoplot!(ax, d_vec, labels; topoplot_attributes...) + ax2 = eeg_topoplot!(ax, d_vec, labels; topoplot_attributes...) + + if rasterize_heatmap + ax2.plots[1].plots[1].rasterize = true + end + if r == length(select_row) && bin_labels + ax.xlabel = string(df_single.time[1]) + ax.xlabelvisible = true + + end end end colgap!(fig.layout, 0) diff --git a/src/plot_topoplotseries.jl b/src/plot_topoplotseries.jl index 0839ab726..5e3d2a2f7 100644 --- a/src/plot_topoplotseries.jl +++ b/src/plot_topoplotseries.jl @@ -13,7 +13,8 @@ Plot a Topoplot Series. ## Extra Data Behavior (...;extra=(;[key]=value)): `combinefun` (default `mean`) can be used to specify how the samples within `Δbin` are combined. - +`bin_labels` (default `true`) - plot the time-window bin size as xlabels at the last row of the plot +`rasterize_heatmaps` (deault `true`) - when saving a svg - enforce rasterization of the plot heatmap. This has the benefit that all lines/points are vectors, except the interpolated heatmap. This is typically what you want, because else you get ~500x500 vectors per topoplot, which makes everything super slow... ## Return Value: @@ -39,16 +40,24 @@ function plot_topoplotseries!(f::Union{GridPosition,Figure}, plotData::DataFrame plotData.label = plotData.channel end - eeg_topoplot_series!(f, plotData, Δbin; + ftopo = eeg_topoplot_series!(f, plotData, Δbin; col_y=config.mapping.y, col_label=:label, col=config.mapping.col, row=config.mapping.row, + bin_labels = config.extra.bin_labels, + rasterize_heatmap = config.extra.rasterize_heatmap, combinefun=config.extra.combinefun, positions=positions, config.visual... ) + if config.layout.showLegend + @show "leegeeend" + d = ftopo.content[1].scene.plots[1] + + Colorbar(f[1,end+1],colormap=d.colormap,colorrange=d.colorrange,height=100) + end return f end diff --git a/src/plotconfig.jl b/src/plotconfig.jl index 48ceaea9f..fb61ae09e 100644 --- a/src/plotconfig.jl +++ b/src/plotconfig.jl @@ -137,6 +137,8 @@ function PlotConfig(T::Val{:topoplotseries}) cfg = PlotConfig(:topoplot) config_kwargs!(cfg, extra=( combinefun=mean, + bin_labels=true, + rasterize_heatmaps=true ), layout=( showLegend=false, # what does it mean to have a topoplotseries legend? ), visual=(; label_text=false # true doesnt work again From 501d1aab1cf7908b46e409211d6a5e03bbe26ce6 Mon Sep 17 00:00:00 2001 From: "behinger (s-ccs 001)" Date: Mon, 11 Sep 2023 16:52:44 +0000 Subject: [PATCH 2/3] docs fix #64 --- src/eeg-series.jl | 35 ++++++++++++++++++++++------------- src/plot_topoplotseries.jl | 11 ++++++----- src/plotconfig.jl | 3 ++- 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/src/eeg-series.jl b/src/eeg-series.jl index 71ac034b7..b9d72e912 100644 --- a/src/eeg-series.jl +++ b/src/eeg-series.jl @@ -14,16 +14,18 @@ end """ function eeg_topoplot_series(data::DataFrame, Δbin; - col_y=:estimate, - col_label=:label, + y=:estimate, + label=:label, col=:time, row=nothing, figure = NamedTuple(), combinefun=mean, + row_labels = false, + col_labels = false, topoplot_attributes... ) Plot a series of topoplots. The function automatically takes the `combinefun=mean` over the `:time`` column of `data` in `Δbin` steps. -Dataframe `data` needs columns `:time` and `col_y(=:erp)`, and `col_label(=:label)`. +Dataframe `data` needs columns `:time` and `y(=:erp)`, and `label(=:label)`. If `data` is a `Matrix`, it is automatically cast to a dataframe, time-bins are then in samples, labels are `string.(1:size(data,1))` ` Δbin in `:time`-units, specifise the time-steps. @@ -32,6 +34,8 @@ All other keyword arguments are forwarded to the EEG_TopoPlot (eeg_toplot) recip `col` and `row` specify the field to split by columns and rows. By default `col=:time`, to split by the time field and `row=nothing`. Useful to split by a condition e.g. `...(...,col=:time, row=:condition)` would result in multiple (as many as different values in df.condition) rows of topoplot series `figure` allows to include information for the figure generation. Alternatively you can provide a fig object `eeg_topoplot_series!(fig,data::DataFrame,Δbin; kwargs..)` + `row_labels` and `col_labels` indicate whether there should be labels in the the plots in the first column indicating the row-value and in the last row to indicate the time (typically timerange) + # Examples Desc ```julia-repl @@ -69,12 +73,13 @@ see eeg_topoplot_series(data,Δbin) for help """ function eeg_topoplot_series!(fig, data::DataFrame, Δbin; - col_y=:erp, - col_label=:label, + y=:erp, + label=:label, col=:time, row=nothing, combinefun=mean, - bin_labels = false, + col_labels = false, + row_labels = false, rasterize_heatmap = true, topoplot_attributes...) @@ -88,12 +93,12 @@ function eeg_topoplot_series!(fig, data::DataFrame, # aggregate the data over time-bins data_mean = df_timebin(data, Δbin; - col_y=col_y, + col_y=y, fun=combinefun, - grouping=[col_label, col, row]) + grouping=[label, col, row]) # using same colormap + contour levels for all plots - (q_min, q_max) = Statistics.quantile(data_mean[:, col_y], [0.001, 0.999]) + (q_min, q_max) = Statistics.quantile(data_mean[:, y], [0.001, 0.999]) # make them symmetrical q_min = q_max = max(abs(q_min), abs(q_max)) q_min = -q_min @@ -120,19 +125,23 @@ function eeg_topoplot_series!(fig, data::DataFrame, df_single = data_mean[sel, :] # select labels - labels = df_single[:, col_label] + labels = df_single[:, label] # select data - d_vec = df_single[:, col_y] + d_vec = df_single[:, y] # plot it ax2 = eeg_topoplot!(ax, d_vec, labels; topoplot_attributes...) if rasterize_heatmap ax2.plots[1].plots[1].rasterize = true end - if r == length(select_row) && bin_labels + if r == length(select_row) && col_labels ax.xlabel = string(df_single.time[1]) ax.xlabelvisible = true - + end + if c == 1 && row_labels + #@show df_single + ax.ylabel = string(df_single.row[1]) + ax.ylabelvisible = true end end end diff --git a/src/plot_topoplotseries.jl b/src/plot_topoplotseries.jl index 5e3d2a2f7..eb5560f69 100644 --- a/src/plot_topoplotseries.jl +++ b/src/plot_topoplotseries.jl @@ -7,7 +7,7 @@ Plot a Topoplot Series. ## Arguments: - `f::Union{GridPosition, Figure}`: Figure or GridPosition that the plot should be drawn into - `plotData::DataFrame`: DataFrame with data, needs a `time` column -- `Δbin::Real`: A number for how many samples should be moved together to one topoplot +- `Δbin::Real`: A number for how large one bin should be. Δbin is in units of the `plotData.time` column - `kwargs...`: Additional styling behavior. Often used: `plot_topoplotseries(df;mapping=(;col=:time,row=:conditionA))` @@ -41,12 +41,13 @@ function plot_topoplotseries!(f::Union{GridPosition,Figure}, plotData::DataFrame end ftopo = eeg_topoplot_series!(f, plotData, Δbin; - col_y=config.mapping.y, - col_label=:label, + y=config.mapping.y, + label=:label, col=config.mapping.col, row=config.mapping.row, - bin_labels = config.extra.bin_labels, - rasterize_heatmap = config.extra.rasterize_heatmap, + col_labels = config.extra.col_labels, + row_labels = config.extra.row_labels, + rasterize_heatmaps = config.extra.rasterize_heatmaps, combinefun=config.extra.combinefun, positions=positions, config.visual... diff --git a/src/plotconfig.jl b/src/plotconfig.jl index fb61ae09e..865ff9ca4 100644 --- a/src/plotconfig.jl +++ b/src/plotconfig.jl @@ -137,7 +137,8 @@ function PlotConfig(T::Val{:topoplotseries}) cfg = PlotConfig(:topoplot) config_kwargs!(cfg, extra=( combinefun=mean, - bin_labels=true, + col_labels=true, + row_labels = true, rasterize_heatmaps=true ), layout=( showLegend=false, # what does it mean to have a topoplotseries legend? From 7d04af1b8fd94a45611a405c694ab66b59cb8986 Mon Sep 17 00:00:00 2001 From: "behinger (s-ccs 001)" Date: Mon, 11 Sep 2023 17:24:25 +0000 Subject: [PATCH 3/3] damn forgot about single row case, no ylabel possible there --- src/eeg-series.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/eeg-series.jl b/src/eeg-series.jl index b9d72e912..1245ba57f 100644 --- a/src/eeg-series.jl +++ b/src/eeg-series.jl @@ -138,7 +138,7 @@ function eeg_topoplot_series!(fig, data::DataFrame, ax.xlabel = string(df_single.time[1]) ax.xlabelvisible = true end - if c == 1 && row_labels + if c == 1 && length(select_row)>1 && row_labels #@show df_single ax.ylabel = string(df_single.row[1]) ax.ylabelvisible = true