STUDY Workflows#
EEGPrep includes standalone STUDY/session surfaces for common group-level workflows. These APIs mirror EEGLAB’s STUDY-facing names while storing cached measure data in EEGPrep-owned JSON-safe structures.
GUI Plus Console Flow#
Load two or more datasets, then use File > Create study > Using all loaded
datasets. eegprep-console will show STUDY and CURRENTSTUDY update
immediately. Continue with Study > Precompute channel measures and
Study > Plot channel measures when the selected datasets have compatible
metadata and shapes.
The same workflow in Python can reuse the sample epoched ICA dataset:
from pathlib import Path
from eegprep import pop_loadset, pop_precomp, pop_study
ALLEEG = [
pop_loadset(Path("sample_data") / "eeglab_data_epochs_ica.set"),
pop_loadset(Path("sample_data") / "eeglab_data_epochs_ica.set"),
]
for index, EEG in enumerate(ALLEEG, start=1):
EEG["subject"] = f"S{index:02d}"
EEG["condition"] = "tutorial"
STUDY, ALLEEG, com = pop_study(None, ALLEEG, name="Tutorial study", return_com=True)
STUDY, ALLEEG, com = pop_precomp(STUDY, ALLEEG, "channels", erp="on", return_com=True)
Implemented Workflows#
Create a STUDY from loaded datasets:
from eegprep import pop_study
STUDY, ALLEEG, com = pop_study(None, ALLEEG, name="My study", return_com=True)
Create a simple ERP STUDY:
from eegprep import pop_studyerp
STUDY, ALLEEG, com = pop_studyerp(ALLEEG, return_com=True)
Build and inspect design variables:
from eegprep import pop_importgroupvar, pop_listfactors, std_builddesignmat
STUDY, com = pop_importgroupvar(
STUDY,
1,
variable="age_group",
values={"S01": "young", "S02": "older"},
return_com=True,
)
factors = pop_listfactors(STUDY, constant="off")
design_matrix, labels, categorical = std_builddesignmat(
STUDY["design"][0],
[{"condition": "target", "rt": 300.0}, {"condition": "standard", "rt": 400.0}],
expanding=True,
)
Load and save EEGPrep .study files:
from eegprep import pop_loadstudy, pop_savestudy
STUDY, com = pop_savestudy(STUDY, EEG, "analysis.study", return_com=True)
STUDY, ALLEEG, com = pop_loadstudy("analysis.study", return_com=True)
Precompute and plot STUDY measures:
from eegprep import pop_chanplot, pop_precomp, std_erpplot, std_readitc
STUDY, ALLEEG, com = pop_precomp(
STUDY,
ALLEEG,
"channels",
erp="on",
spec="on",
return_com=True,
)
STUDY, com, fig = pop_chanplot(STUDY, ALLEEG, measure="erp", return_com=True)
STUDY, erpdata, erptimes, fig = std_erpplot(STUDY, ALLEEG, channels=[1])
STUDY, itcdata, itctimes, itcfreqs = std_readitc(STUDY, ALLEEG, channels=[1])
Plot functions arrange these caches into the selected design before returning
them. A one-factor design returns a list with one array per factor level. A
two-factor design returns data[condition][group]. Samples are the leading
axes and subjects or cluster members are on the last axis; for example, ERP
cells are times x cases and ERSP cells are frequencies x times x cases.
This matches the cell organization used by EEGLAB while keeping the arrays
directly usable from NumPy.
Channel measures are stored in STUDY.changrp. Component measures are stored
on the parent STUDY.cluster[0] entry so preclustering can read the same
cached arrays. Cached measure fields follow EEGLAB names such as erpdata,
specdata, erspdata, and itcdata. The selected design is recorded
in each measure group’s metadata. EEGPrep stores dataset-level averages, and
optionally single-trial values, in the current standalone cache rather than
EEGLAB sidecar measure files.
pop_chanplot reads cached channel and component measures through the same
std_readdata/std_erpplot/std_erspplot cache contract used by scripts,
so GUI and console plots slice axes and cached channel groups consistently.
Tutorial-scale workflows#
The current EEGLAB tutorial-wrapper workflows are covered end to end with deterministic generated signals. This includes grouped ERP statistics and topographies, component preclustering for an N400-style study, all-channel time-frequency analysis, scalp movies, and a generated P300 BIDS pipeline from export/import through filtering, average reference, rank-reduced Picard ICA, component rejection, epoching, and STUDY plotting. Generated fixtures keep ordinary CI independent of large tutorial downloads while retaining numerical assertions at each processing boundary.
Two optional boundaries remain explicit. pop_iclabel needs the ICLabel
model runtime; callers that already have compatible seven-class probabilities
can use pop_icflag and pop_subcomp independently. Dataset-level
spherical DIPFIT fitting and leadfield construction run standalone, while
MRI/BEM/LORETA workflows that require FieldTrip fail clearly until an external
source-analysis backend is configured.
Store reusable plot and statistics choices on the STUDY before plotting:
from eegprep import pop_erpparams, pop_statparams
STUDY = pop_erpparams(STUDY, timerange=[-200, 800], plotconditions="together")
STUDY = pop_statparams(STUDY, condstats="on", method="perm", naccu=2000)
Pass return_stats=True to std_erpplot, std_specplot,
std_erspplot, or std_itcplot to receive pgroup, pcond, and
pinter before the returned figure. These are p-values when threshold
is NaN and numeric significance masks when a finite threshold is set,
matching EEGLAB’s output contract. A sequence of thresholds produces EEGLAB’s
graded masks. mcorrect="fdr" applies
Benjamini-Hochberg correction.
The same masks are attached to fig.eegprep_plot_metadata["statistics"] so
downstream reporting code can inspect exactly what the plot highlighted.
Use savetrials="on" when a design factor varies between trials within one
dataset. The measure plots select trials from datasetinfo[*]["trialinfo"]
and aggregate them within each subject before forming condition and group
cells. erpdatatrials stores baseline-corrected amplitudes;
specdatatrials stores linear spectral density; erspdatatrials stores
linear, baseline-corrected power; and itcdatatrials stores phase in radians.
Spectrum and ERSP power are averaged before conversion to decibels, while ITC
uses circular phase averaging. These EEGPrep-owned cache fields remain
independent of an EEGLAB installation. A trial-level design without matching
single-trial caches raises an error instructing you to rerun std_precomp
with savetrials="on" instead of silently grouping dataset averages.
For component clusters, std_topoplot draws polarity-aligned centroid or
member scalp maps and caches topo, topoall, and topopol on each
plotted cluster.
The corresponding pop_erpimparams, pop_erspparams, pop_specparams,
and pop_dipparams functions store settings under STUDY["etc"] using
EEGLAB field names. Changing an ERP time range, spectrum frequency range, or
ERSP/ITC time-frequency range invalidates the affected cached measure fields;
run pop_precomp(..., recompute="on") before plotting them again.
Use std_checkfiles, std_checkdatasession, std_uniformfiles, and
std_uniformsetinds to audit loaded dataset consistency and cached measure
shapes before saving or plotting group-level results. std_savedat writes
explicit EEGPrep-owned JSON or MATLAB-compatible measure sidecars when a
workflow needs a durable array file outside the .study JSON.
Select datasets or trials from STUDY metadata:
from eegprep import std_getindvar, std_maketrialinfo, std_selectdataset
STUDY, trialinfo = std_maketrialinfo(STUDY, ALLEEG)
factors, factor_values, subjects, paired = std_getindvar(STUDY)
dataset_indices, trial_indices = std_selectdataset(
STUDY,
ALLEEG,
"condition",
["target"],
)
These helpers return EEGLAB-facing 1-based dataset and trial indices. Trial
metadata may be stored as row dictionaries or as EEGLAB-loaded columnar
{"factor": [values...]} dictionaries; STUDY selectors normalize both forms
before matching factor levels and numerical ranges. std_maketrialinfo uses
each epoch’s time-locking event, including custom fields such as reaction time,
and later STUDY synchronization preserves those derived rows.
The Study design editor edits subjects, design names, and independent
variables. New under the variable list opens Add variable. A continuous
trial factor such as rt is stored on STUDY.design with pairing off.
The dialog keeps that factor’s value list empty; std_makedesign fills the
observed values and keeps the first four variables. If the factor is missing
from STUDY trial metadata, OK also runs std_maketrialinfo. List factors
shows the first-level and second-level text for the selected design, and the
resave box writes the STUDY when it already has a file name. Cancel leaves the
STUDY unchanged.
Use std_substudy or
std_rmdat when a workflow needs to remove datasets; EEGPrep remaps STUDY
references and invalidates cached measure arrays after membership changes.
std_findsameica groups matching ICA decompositions within each subject.
This preserves the subject boundary used by STUDY designs instead of merging
identical test fixtures across subjects.
Precluster and cluster ICA components:
from eegprep import pop_clust, pop_clustedit, pop_preclust
STUDY, ALLEEG, com = pop_preclust(
STUDY,
ALLEEG,
preproc=[{"measure": "scalp", "npca": 3, "norm": 1, "weight": 1}],
return_com=True,
)
STUDY, com = pop_clust(STUDY, ALLEEG, clus_num=4, random_state=0, return_com=True)
STUDY, com, fig = pop_clustedit(STUDY, ALLEEG, action="plot", return_com=True)
Finite outliers values in pop_clust use the EEGLAB-compatible
robust_kmeans path and record ["robust_kmeans", clus_num] in each
created cluster’s algorithm provenance. Infinite outliers keeps the plain
k-means path. In both cases command history remains pasteable in
eegprep-console.
algorithm="kmeanscluster" numbers Cls k from the k-th
preclustering row. algorithm="kmeans" numbers Cls k from centroid
k of the lowest-SSE seeded start. The same random_state reproduces
the kmeans numbering.
DIPFIT Source Localization#
EEGPrep includes standalone DIPFIT-compatible spherical workflows for ICA component source localization. Configure DIPFIT metadata first, then run a coarse grid search, nonlinear refinement, and dipole plotting:
from eegprep.plugins.dipfit.pop_dipfit_settings import pop_dipfit_settings
from eegprep.plugins.dipfit.pop_dipfit_gridsearch import pop_dipfit_gridsearch
from eegprep.plugins.dipfit.pop_dipfit_nonlinear import pop_dipfit_nonlinear
from eegprep.plugins.dipfit.pop_dipplot import pop_dipplot
EEG, com = pop_dipfit_settings(EEG, model="standardBESA", return_com=True)
EEG, com = pop_dipfit_gridsearch(
EEG,
[1],
[-40, -20, 0, 20, 40],
[-40, -20, 0, 20, 40],
[20, 40, 60],
40,
return_com=True,
)
EEG, com = pop_dipfit_nonlinear(EEG, component=1, return_com=True)
figures, com = pop_dipplot(EEG, [1], summary="on", projlines="on", return_com=True)
The spherical backend fits an average-referenced leadfield, stores
posxyz, momxyz, rv, diffmap, sourcepot, and datapot in
EEG.dipfit.model, and keeps command history replayable from
eegprep-console. pop_multifit chains grid search, nonlinear fitting,
RV rejection, optional outside-head removal, and optional dipole plotting.
The deprecated EEGLAB aliases pop_dipfit_batch and pop_dipfit_manual
remain available for script compatibility.
pop_leadfield can compute spherical leadfields for explicit source points
provided as an Nx3 array, {"pos": ...} dictionary, or simple file with
source positions. MRI-derived BEM headmodel creation, AFNI atlas clipping, and
LORETA source analysis remain explicit backend limits and fail clearly rather
than producing placeholder source-localization outputs.
Session Synchronization#
The GUI and eegprep-console share STUDY and CURRENTSTUDY through
EEGPrepSession. Creating or loading a STUDY from the GUI sets
CURRENTSTUDY to 1. Retrieving a dataset from the Datasets menu returns
CURRENTSTUDY to 0 and records that transition in history.
Integration Notes#
Component ERP, spectrum, ERSP, and ITC arrays are cached on the parent
STUDY.cluster[0] entry. Preclustering reads those cached component arrays
and can also build scalp-map features directly from loaded ICA maps. MATLAB
parity checks focus on deterministic metadata and cluster structure; exact
numeric clustering labels can differ because EEGPrep uses deterministic
in-package k-means helpers rather than MATLAB’s Statistics Toolbox.
PAC, LIMO Design, And Neighbors#
EEGPrep includes a standalone PAC backend for practical channel workflows.
Use pac for epoched phase-amplitude coupling grids and pac_cont for
continuous sliding-window PAC. At the STUDY level, std_pac computes
EEGPrep-owned pacdata, pactimes, and pacfreqs caches on
STUDY.changrp. std_readpac slices those caches and std_pacplot
plots their magnitude using the same cache-reading contract as the other
STUDY measure plots.
Empirical p-value conventions are explicit. pac applies the common
(exceedances + 1) / (permutations + 1) finite-sample convention,
bootstat exposes exact permutation proportions for bootstrap helper tests,
and statistics helpers such as stat_surrogate_pvals follow EEGLAB’s
surrogate-tail convention with FDR correction available through the statistics
module. These definitions are intentionally not collapsed when they answer
different inferential questions.
EEGPrep provides a standalone LIMO-compatible path from design preparation to
core hierarchical statistics. std_limodesign builds categorical and
continuous matrices from pop_listfactors output and trial metadata,
including interaction and split-regressor descriptions. pop_limo uses the
active STUDY design to fit mass-univariate OLS, LIMO PCOut-weighted WLS, or
Tukey-bisquare IRLS models to epoched channel or component data. The
returned model dictionaries contain betas, fitted values, residuals, R²,
residual variance, standard errors, t statistics, p values, robust weights,
and their exact design matrix.
Pass outputdir to pop_limo to write versioned .npz model files.
These files never require pickle and can be reopened with
std_readfilelimo. std_limoresults and pop_limoresults compute and
store first-level contrasts, one-sample, paired and Welch two-sample tests,
mass-univariate regression, one-way ANOVA, ANCOVA, repeated-measures ANOVA,
and mean or inverse-variance-weighted summaries. Group statistics always use
the first axis as subjects; first-level parameter selection remains 1-based at
the EEGLAB-facing boundary.
std_prepare_neighbors creates a distance-based FieldTrip-like neighbor
list and a LIMO-compatible channel adjacency matrix from loaded channel
locations. std_interp interpolates requested missing channels across
STUDY datasets using EEGPrep’s existing channel interpolation backend.
Plotting localized cluster dipoles#
std_dipplot visualizes DIPFIT models that are already stored in each
dataset’s EEG["dipfit"]["model"] field. Cluster membership is read from
STUDY["cluster"] using EEGLAB-facing 1-based dataset and component
indices. The function returns the exact selected models and computed cluster
centroids alongside the figures, so positions, moments, and residual variance
remain inspectable outside the plot.
Use mode="joined" to draw selected cluster members and centroids together,
or mode="centroid" to draw only cluster centroids. The standard
apart, together, multicolor, and comps layouts are also
available. comps selects 1-based positions within the cluster membership
list, consistent with the EEGLAB std_plotcompdip convention. Set
plot=False to prepare and validate the same numerical plot inputs without
creating figures.
Limitations#
The standalone layer does not silently read version-dependent MATLAB LIMO
.mat structures. Convert them explicitly or use LIMO in MATLAB;
std_readfilelimo accepts only EEGPrep-owned .npz output. First-level
and group bootstrap, TFCE correction, factorial repeated-measures designs,
and LIMO’s result plotting/report interface remain explicit unsupported
boundaries. WLS follows LIMO’s PCOut residual projection and uses one robust
observation weight across the fitted channel/time grid. IRLS uses feature-wise
Tukey-bisquare weights.
std_dipplot does not compute dipole models: localize components first with
the EEGPrep DIPFIT workflow. The broader FieldTrip-dependent
std_dipoleclusters source workflow remains an explicit backend boundary.
See the Interactive Console guide for mixed GUI plus console usage and the GUI and Help Menus guide for menu inventory behavior.