BIDSEEG Pipeline is a semi-automated Python workflow for reproducible EEG and behavioral data analysis in computational neuroscience and psychiatry. It supports end-to-end processing of BIDS-formatted EEG data, from preprocessing and artifact correction (including optimized ICA) to conventional spectral analysis, spectral parameterization, and trial-wise event-related potentials (ERP) and instantaneous alpha frequency (IAF) estimation. Integrated generalized and hierarchical drift-diffusion modelling (Hierarchical Sequential Sampling Modeling (HSSM)) enables researchers to investigate how experimental manipulations, trial-level neural measures, such as ERP-amplitudes, oscillatory activity, or psychiatric metrics such as symptom seveery, relate to modelled latent decision-making processes. The pipeline is configured through a single JSON file, providing an accessible framework for multimodal EEG–behavior analyses without requiring extensive programming expertise.
This repository contains the analysis pipeline for the BIDS EEG dataset hosted on OpenNeuro:
- OpenNeuro accession:
ds008083 - Dataset page: https://openneuro.org/datasets/ds008083/versions/1.0.0
- Dataset version used in this pipeline:
v1.0.0 - Dataset DOI:
10.18112/openneuro.ds008083.v1.0.0
The raw BIDS dataset is not stored in this GitHub repository. It should be downloaded from here OpenNeuro before running the pipeline.
The pipeline implements 6 analysis modules (plus optional BIDSification):
1 Preprocessing (a_preprocessing_module.py):
- Preprocessing BIDSified EEG data including downsampling, rereferencing, linenoise removal and filtering.
1.5 ICA Preprocessing (x_ica_preprocessing_module.py, optional):
- Separate preprocessing stream dedicated to ICA decomposition (see Two-stage ICA below). Fits ICA on ICA-optimized data, classifies components with ICLabel, and saves weights for module 2.
2 Artifact Correction/Rejection (b_ArtifactCorrection_module.py):
- Data epoching, ICA application (pretrained weights from module 1.5 or fresh fit on analysis data), bad channel interpolation (RANSAC), bad epoch deletion (autoreject).
3 EEG Analysis: - Computation of time-frequency representations, consecutive cluster-based permutation tests and spectral parameterization analysis (SpecParam, former FOOOF).
4 Behavioral Analysis: - Signal detection theory analysis and generalized drift diffusion modelling (+ predictive checks and parameter recovery study for parameter validation).
5 Hierarchical Bayesian Modelling (HSSM): - Hierarchical Bayesian drift-diffusion modelling across all subjects at once. Drift rate varies by experimental condition and motion coherence with a per-participant random intercept (partial pooling). Returns full posterior distributions with convergence diagnostics (R-hat, ESS) instead of per-subject point estimates.
0.1 BIDSification:
- If your data is not in BIDS-format yet, using z_BIDSification_module.py you can convert data from any output format (e.g. BrainVision) into BIDS (Brain Imaging Data Structure).
ICA quality depends strongly on how the data is filtered, epoched, and cleaned before decomposition. Fitting ICA on the same filtered, analysis-ready epochs used for ERP/TFR can blur or remove the very artifacts you want to separate. For instance, an analysis epoch could contain systematically half a blink, which might remain in the data as artifactual component.
This pipeline therefore supports a two-stage ICA workflow (see Dimigen, 2020 and Hülsemann et al., 2025):
| Stage | Module | What it does |
|---|---|---|
| 1 — Train ICA | x_ica_preprocessing_module.py |
Reads raw BIDS (bids_root_in) and runs ICA-specific preprocessing: band-pass (default 1–60 Hz), downsampling, epoching, optional bad-channel masking, amplitude rejection, extended infomax ICA + ICLabel. Saves weights and exclusion metadata to derivatives/BIDSprocessed/sub-*/ses-*/eeg/*_proc-00ICAweights_*. Independent of module 1 filter settings. |
| 2 — Analysis preprocessing | a_preprocessing_module.py |
Your analysis filters (e.g. 0.1–40 Hz), rereferencing, etc. Writes 01rawfilter and later steps to derivatives/BIDSprocessed/. |
| 3 — Apply ICA | b_ArtifactCorrection_module.py |
Loads analysis-preprocessed data (01rawfilter), epochs it, and applies the saved ICA weights (no refit). Then continues with interpolation and autoreject as usual. |
Why separate streams? ICA benefits from a wider passband and longer epochs than typical ERP analysis. Training on dedicated ICA-preprocessed data and applying the weights to analysis-preprocessed epochs gives cleaner component separation without changing your downstream filter settings.
When to use it: Enable when automatic ICA on analysis data leaves residual eye/muscle artifacts, or when you want reproducible, inspectable ICA weights per subject. With well-tuned ICA preprocessing you may be able to rely less on aggressive RANSAC/autoreject downstream and reduce general data preprocessing, because: "EEG is better left alone" - Delorme (2023)
When to skip it: Set ICA_preprocessing.perform to false and ICA_preprocessing.apply_pretrained_weights to false in inputs.json — module 2 will fit ICA directly on analysis epochs ('standard', single-stage behaviour).
The pipeline is best executed within a conda environment. Follow the subsequent for successful setup.
Using the appropriate commands for your OS, e.g. Windows, MacOS, install conda from Miniconda Install and follow the installation guide.
Testing the installation: When the installation finishes, open your terminal application (find this by typing "terminal" into your computer's launchpad). Test your installation by running:
conda listIf conda has been installed correctly, a list of installed packages will appear.
We recommend using a interpreter like Visual Studio Code or cursor. You may install VS Code from here and follow the installation guide. Pipeline input can edited via .json-file and executed via the terminal within VS Code.
For Windows-Users: We recommend using open VS Code from out your Anaconda Prompt. Open your Anaconda Prompt and run:
codethat way you have access to your conda environments in the terminal within VS Code
For Mac-Users: Just open VS Code from your applications.
After creating and activating the environment, clone the pipeline repository:
git clone https://github.com/jonathanbuc/BIDSEEG_Pipeline.gitNext, install the OpenNeuro CLI, handling data down- and upload in OpenNeuro from out your terminal.
deno install -A --global jsr:@openneuro/cli -n openneuroexecuting the download_openneuro.sh file like the following will download the raw BIDS data to ./data/BIDShierPriors of your repository clone.
cd /path/to/BIDSEEG_Pipeline
./scripts/download_openneuro.sh-> Now simply open a new terminal Terminal/New Terminal and proceed with steps 1.3 and 1.4
In your terminal, check if you are in your repository *BIDSEEG_pipeline
If not, navigate to the eeg pipeline via cd path/to/BIDSEEG_pipeline i.e., cd C:\Users\YourName\Research\EEGresearch\BIDSEEG_pipeline
Install the provided conda environment via the .yml file. Be sure to execute the command within the EEGpipeline directory.
conda env create -f environment_setup.yml--> Note, 'mne-env' is the default name of the conda environment you are creating within the EEGpipeline directory. You can define a different name by changing name: mne-env within the environment_setup.yml file
To activate your conda environment, run:
conda activate 'mne-env'To deactivate your conda environment, run:
conda deactivate--> IMPORTANT: Consult the ExperimentGuide_HierarchicalPriors.md file to gain a better understanding of the input structure.
- inputs.json is the dictionary that provides values for each of the subsequent steps (preprocessing, artifact correction, analysis)
- while exploring the pipeline, you may change the values in this file to see differences across different changes (i.e., change "samplingrate_down": 250 --> 500).
- please note, to use the updated inputs.json file, you must save the file to execute new commands. Save = ctl + s
The data/BIDShierPriors contains 3 subjects from Buchholz & Hesselmann (in review) - Hierarchical Priors Shape Dynamic Evidence Accumulation and Aperiodic EEG Activity as testing data for an initial run (steps 2.1–2.5).
Note on the demo data. The shipped EEG is a 250 Hz downsampled version of the 3-subject demo (the rate the preprocessing module downsamples to anyway), kept small enough for Git LFS. It is sufficient to run the whole pipeline end-to-end from a clean clone. The exact provenance — raw BrainVision →
z_BIDSification_module.py→ resample to 250 Hz — is documented inscripts/make_demo_data.py. The small per-subject behavioral logs and trait questionnaire live underdata/sourcedata/; the large raw EEG is not tracked.
IMPORTANT: Consider the ExperimentGuide_HierarchicalPriors.md, which provides a thorough linkage of the experiment and this pipeline. We recommend using this file as guideline when proceeding with steps 2.1–2.4. This file can also be used for a replication of the respective study.
To preprocess the BIDSified data, run:
python a_preprocessing_module.py inputs.jsonRun this before artifact correction when using pretrained ICA weights (the default in inputs.json). It reads directly from raw BIDS — not from module 1 output — so it can run before or after a_preprocessing_module.py, but both module 1 and module 1.5 must finish before module 2.
python x_ica_preprocessing_module.py inputs.jsonThis fits ICA per subject on ICA-dedicated preprocessing and writes:
*_proc-00ICAweights_ica.fif— ICA weight matrix*_proc-00ICAweights_metadata.json— excluded component indices, ICLabel probabilities, bad channels- diagnostic IC plots under
derivatives/BIDSprocessed/ICA/
Enable / configure in inputs.json → ICA_preprocessing:
"ICA_preprocessing": {
"perform": true,
"apply_pretrained_weights": true,
"low_cutoff": 1,
"high_cutoff": 60,
"filter_method": "fir",
"line_method": "band_stop",
"downsample_to": 250,
"rereference": "average",
"drop_ref_channel": null,
"reject_amplitude_uv": 1000,
"ICA_method": "infomax",
"n_components": 20,
"max_iter": 200,
"random_state_seed": 1943,
"ch_interpolation_method": "none",
"epoch_dict": {
"S_1": 1,
"S_2": 2,
"S_4": 4
},
"tmin": -1.0,
"tmax": 2.5,
"rej_thresholds": {
"muscle artifact": 0.6,
"eye blink": 0.25,
"heart beat": 0.6,
"line noise": 0.75,
"channel noise": 0.75
},
}| Key | Meaning |
|---|---|
perform |
Run x_ica_preprocessing_module.py (set false to skip training) |
apply_pretrained_weights |
Module 2 loads saved weights instead of fitting ICA anew |
low_cutoff / high_cutoff |
Band-pass for ICA training only (not analysis filters) |
epoch_dict |
dictionairy storing event trial_type (key) and values (value) |
tmin / tmax |
max and min time (sec) for epochs relative to trigger in epoch_dict |
ch_interpolation_method |
Bad channels before ICA: "none", "ransac", or "neighbor_corr" |
rej_thresholds |
Per-label ICLabel probability thresholds for IC exclusion |
Order matters: Run
a_preprocessingandx_ica_preprocessingbeforeb_ArtifactCorrection. Module 2 requires00ICAweightsfiles whenapply_pretrained_weightsistrue, and loads analysis-preprocessed data from module 1 (01rawfilter).
To perform artifact correction/rejection, run:
python b_ArtifactCorrection_module.py inputs.jsonWith apply_pretrained_weights: true, ICA is applied (not refit) using weights from step 2.2. Set perform.ICA to true in inputs.json so ICA correction runs at all.
To perform EEG analysis, run:
python c_EEGAnalysis_module.py inputs.jsonTo perform behavioral analysis, run:
python d_BehavAnalysis_module.py inputs.jsonWhere module 4 fits a separate drift-diffusion model per subject, this module fits one hierarchical Bayesian DDM across all subjects at once. Drift rate is modelled as a function of experimental condition and motion coherence, with each participant getting their own random intercept (partial pooling), and the output is a full posterior distribution per parameter — so you can make direct probability statements ("95% credible that high-level priors raise drift rate") rather than relying on a t-test over point estimates.
Prerequisites:
- Run module 4 first. HSSM reads the group behavioral table
.../results/groupBehavioral/behavioraldata_hierprior.csvthatd_BehavAnalysis_module.pywrites. Without it the module stops with aFileNotFoundError. - The
hssmpackage must be installed (it ships with theenvironment_setup.ymlenvironment; if you built your env before HSSM was added, runpip install hssm).
Enable it. HSSM is off by default because Markov-Chain-Monte-Carlo sampling is slow (expect
~15–60 min for the full dataset). Switch it on in inputs.json:
"perform": {
"compute_hssm": true
}Run it:
python e_HSSM_module.py inputs.jsonConfigure it. All knobs live in inputs.json → Analysis.hssm:
"hssm": {
"model_type": "ddm", // DDM variant to fit
"sampler": "nuts_numpyro", // "mcmc" (PyMC) or "nuts_numpyro" (faster, JAX)
"draws": 1000, // posterior samples to keep per chain
"tune": 1000, // warm-up steps (discarded)
"chains": 2, // independent chains (for R-hat convergence check)
"cores": 2, // CPU cores for parallel chains
"target_accept": 0.9, // NUTS acceptance target; raise toward 0.99 if you see divergences
"prior_settings": "safe", // HSSM's regularising default priors
"link_settings": "log_logit",
"formula_v": "v ~ 1 + exp * coh_level + (1|participant)" // drift-rate regression formula
}The formula_v is the scientific heart of the model. exp is the condition column
(base/lowlevel/highlevel), coh_level is motion coherence, exp * coh_level includes their
interaction, and (1|participant) adds the per-subject random intercept. To test a direct
EEG–behavior link you would point drift rate at a trial-level EEG predictor instead, e.g.
"v ~ alpha_power + (1|participant)" — just make sure that column is present in the behavioral
table.
Outputs (written to .../results/groupBehavioral/):
hssm_posterior_summary.csv— mean, SD, 95% HDI, R-hat and ESS for every parameter.hssm_trace.png— diagnostic trace plots; converged chains look like overlapping "hairy caterpillars" and R-hat should be ≈ 1.0.
For the statistics behind this module (Bayesian vs. MLE, NUTS, partial pooling, and what each DDM parameter means), see
docs/learning/03-hssm-integration.mdand04-hssm-explained.md.