Skip to content

Commit

Permalink
Merge pull request #68 from unfoldtoolbox/betterSeries
Browse files Browse the repository at this point in the history
plot_topoplotseries improvements
  • Loading branch information
behinger authored Sep 11, 2023
2 parents 27dc20d + 7d04af1 commit af04ea8
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 16 deletions.
43 changes: 32 additions & 11 deletions src/eeg-series.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -69,11 +73,14 @@ 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,
col_labels = false,
row_labels = false,
rasterize_heatmap = true,
topoplot_attributes...)

# cannot be made easier right now, but Simon promised a simpler solution "soonish"
Expand All @@ -86,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
Expand All @@ -116,12 +123,26 @@ 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]
labels = df_single[:, label]
# select data
d_vec = df_single[:, col_y]
d_vec = df_single[:, 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) && col_labels
ax.xlabel = string(df_single.time[1])
ax.xlabelvisible = true
end
if c == 1 && length(select_row)>1 && row_labels
#@show df_single
ax.ylabel = string(df_single.row[1])
ax.ylabelvisible = true
end
end
end
colgap!(fig.layout, 0)
Expand Down
20 changes: 15 additions & 5 deletions src/plot_topoplotseries.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ 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))`
## 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:
Expand All @@ -39,16 +40,25 @@ function plot_topoplotseries!(f::Union{GridPosition,Figure}, plotData::DataFrame
plotData.label = plotData.channel
end

eeg_topoplot_series!(f, plotData, Δbin;
col_y=config.mapping.y,
col_label=:label,
ftopo = eeg_topoplot_series!(f, plotData, Δbin;
y=config.mapping.y,
label=:label,
col=config.mapping.col,
row=config.mapping.row,
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...
)

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
3 changes: 3 additions & 0 deletions src/plotconfig.jl
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ function PlotConfig(T::Val{:topoplotseries})
cfg = PlotConfig(:topoplot)
config_kwargs!(cfg, extra=(
combinefun=mean,
col_labels=true,
row_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
Expand Down

0 comments on commit af04ea8

Please sign in to comment.