Note
Go to the end to download the full example code.
Tutorial 0: Getting Started#
This tutorial takes you through a basic working example of how to use this codebase, including all the different components, up to the results generation. If you’d like to know about the statistics and plotting, see the next tutorial.
# Authors: Vinay Jayaram <vinayjayaram13@gmail.com>
#
# License: BSD (3-clause)
Introduction#
To use the codebase you need an evaluation and a paradigm, some algorithms, and a list of datasets to run it all on. You can find those in the following submodules; detailed tutorials are given for each of them.
import numpy as np
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
from sklearn.metrics import accuracy_score, roc_auc_score
from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import make_pipeline
from sklearn.svm import SVC
If you would like to specify the logging level when it is running, you can use the standard python logging commands through the top-level moabb module
import moabb
from moabb.datasets import BNCI2014_001, utils
from moabb.evaluations import CrossSessionEvaluation
from moabb.paradigms import LeftRightImagery
from moabb.pipelines.features import LogVariance
In order to create pipelines within a script, you will likely need at least the make_pipeline function. They can also be specified via a .yml file. Here we will make a couple pipelines just for convenience
moabb.set_log_level("info")
Create pipelines#
We create two pipelines: channel-wise log variance followed by LDA, and channel-wise log variance followed by a cross-validated SVM (note that a cross-validation via scikit-learn cannot be described in a .yml file). For later in the process, the pipelines need to be in a dictionary where the key is the name of the pipeline and the value is the Pipeline object
pipelines = {}
pipelines["AM+LDA"] = make_pipeline(LogVariance(), LDA())
parameters = {"C": np.logspace(-2, 2, 10)}
clf = GridSearchCV(SVC(kernel="linear"), parameters)
pipe = make_pipeline(LogVariance(), clf)
pipelines["AM+SVM"] = pipe
Datasets#
Datasets can be specified in many ways: Each paradigm has a property ‘datasets’ which returns the datasets that are appropriate for that paradigm
print(LeftRightImagery().datasets)
[<moabb.datasets.bnci.bnci_2014.BNCI2014_001 object at 0x7f393ef0fc40>, <moabb.datasets.bnci.bnci_2014.BNCI2014_004 object at 0x7f393ef0f820>, <moabb.datasets.beetl.Beetl2021_A object at 0x7f393ef0fb50>, <moabb.datasets.beetl.Beetl2021_B object at 0x7f393ef0f850>, <moabb.datasets.gigadb.Cho2017 object at 0x7f393ef0f790>, <moabb.datasets.dreyer2023.Dreyer2023 object at 0x7f393ef0f670>, <moabb.datasets.dreyer2023.Dreyer2023A object at 0x7f393ef0f5e0>, <moabb.datasets.dreyer2023.Dreyer2023B object at 0x7f393ef0fb20>, <moabb.datasets.dreyer2023.Dreyer2023C object at 0x7f393ef0f7c0>, <moabb.datasets.mpi_mi.GrosseWentrup2009 object at 0x7f393f57aa10>, <moabb.datasets.Lee2019.Lee2019_MI object at 0x7f393f57aa40>, <moabb.datasets.liu2024.Liu2024 object at 0x7f393f371750>, <moabb.datasets.physionet_mi.PhysionetMI object at 0x7f393ef0f5b0>, <moabb.datasets.schirrmeister2017.Schirrmeister2017 object at 0x7f393f960c70>, <moabb.datasets.bbci_eeg_fnirs.Shin2017A object at 0x7f393ef0f700>, <moabb.datasets.stieger2021.Stieger2021 object at 0x7f393ef0f550>, <moabb.datasets.Weibo2014.Weibo2014 object at 0x7f393ef0fa90>, <moabb.datasets.Zhou2016.Zhou2016 object at 0x7f393ef0fbe0>]
Or you can run a search through the available datasets:
print(utils.dataset_search(paradigm="imagery", min_subjects=6))
[<moabb.datasets.alex_mi.AlexMI object at 0x7f393ef0f790>, <moabb.datasets.bnci.bnci_2014.BNCI2014_001 object at 0x7f393ef0ffa0>, <moabb.datasets.bnci.bnci_2014.BNCI2014_002 object at 0x7f393ef0fb50>, <moabb.datasets.bnci.bnci_2014.BNCI2014_004 object at 0x7f393ef0ffd0>, <moabb.datasets.bnci.bnci_2015.BNCI2015_001 object at 0x7f393ef0f850>, <moabb.datasets.bnci.bnci_2015.BNCI2015_004 object at 0x7f393ef0ff40>, <moabb.datasets.bnci.bnci_2019.BNCI2019_001 object at 0x7f393ef0ff70>, <moabb.datasets.bnci.bnci_2020.BNCI2020_001 object at 0x7f393ef0fd90>, <moabb.datasets.bnci.bnci_2022_001.BNCI2022_001 object at 0x7f393ef0ff10>, <moabb.datasets.bnci.bnci_2024_001.BNCI2024_001 object at 0x7f393ef0fe20>, <moabb.datasets.bnci.bnci_2025.BNCI2025_001 object at 0x7f393ef0fd00>, <moabb.datasets.bnci.bnci_2025.BNCI2025_002 object at 0x7f393ef0fe50>, <moabb.datasets.gigadb.Cho2017 object at 0x7f393ef0fe80>, <moabb.datasets.dreyer2023.Dreyer2023 object at 0x7f393ef0fd60>, <moabb.datasets.dreyer2023.Dreyer2023A object at 0x7f393ef0fca0>, <moabb.datasets.dreyer2023.Dreyer2023B object at 0x7f393ef0f580>, <moabb.datasets.dreyer2023.Dreyer2023C object at 0x7f393ef0f9d0>, <moabb.datasets.fake.FakeDataset object at 0x7f393ef0f100>, <moabb.datasets.mpi_mi.GrosseWentrup2009 object at 0x7f393ef0f8e0>, <moabb.datasets.Lee2019.Lee2019_MI object at 0x7f393ef0fa60>, <moabb.datasets.liu2024.Liu2024 object at 0x7f393ef0f3d0>, <moabb.datasets.upper_limb.Ofner2017 object at 0x7f393ef0fd30>, <moabb.datasets.physionet_mi.PhysionetMI object at 0x7f393ef0f760>, <moabb.datasets.schirrmeister2017.Schirrmeister2017 object at 0x7f393ef0f7f0>, <moabb.datasets.bbci_eeg_fnirs.Shin2017A object at 0x7f393ef0f6d0>, <moabb.datasets.bbci_eeg_fnirs.Shin2017B object at 0x7f393ef0f8b0>, <moabb.datasets.stieger2021.Stieger2021 object at 0x7f393ef0f430>, <moabb.datasets.Weibo2014.Weibo2014 object at 0x7f393ef0f250>]
Or you can simply make your own list (which we do here due to computational constraints)
dataset = BNCI2014_001()
dataset.subject_list = dataset.subject_list[:2]
datasets = [dataset]
Paradigm#
Paradigms define the events, epoch time, bandpass, and other preprocessing parameters. They have defaults that you can read in the documentation, or you can simply set them as we do here. A single paradigm defines a method for going from continuous data to trial data of a fixed size. To learn more look at the tutorial Exploring Paradigms
fmin = 8
fmax = 35
# You can inject custom scoring directly into the paradigm (single or multi-metric).
custom_scorer = [
accuracy_score,
(roc_auc_score, {"needs_threshold": True}),
]
paradigm = LeftRightImagery(fmin=fmin, fmax=fmax, scorer=custom_scorer)
Evaluation#
An evaluation defines how the training and test sets are chosen. This could be cross-validated within a single recording, or across days, or sessions, or subjects. This also is the correct place to specify multiple threads.
evaluation = CrossSessionEvaluation(
paradigm=paradigm, datasets=datasets, suffix="examples", overwrite=False
)
results = evaluation.process(pipelines)
BNCI2014-001-CrossSession: 0%| | 0/2 [00:00<?, ?it/s][codecarbon WARNING @ 12:34:13] Multiple instances of codecarbon are allowed to run at the same time.
BNCI2014-001-CrossSession: 50%|█████ | 1/2 [00:05<00:05, 5.72s/it]
BNCI2014-001-CrossSession: 100%|██████████| 2/2 [00:08<00:00, 4.14s/it]
BNCI2014-001-CrossSession: 100%|██████████| 2/2 [00:08<00:00, 4.38s/it]
2026-03-01 12:34:17,864 INFO MainThread moabb.evaluations.base AM+LDA | BNCI2014-001 | 1 | 0train: Score 0.729
2026-03-01 12:34:17,997 INFO MainThread moabb.evaluations.base AM+LDA | BNCI2014-001 | 1 | 1test: Score 0.715
2026-03-01 12:34:18,131 INFO MainThread moabb.evaluations.base AM+SVM | BNCI2014-001 | 1 | 0train: Score 0.743
2026-03-01 12:34:18,281 INFO MainThread moabb.evaluations.base AM+SVM | BNCI2014-001 | 1 | 1test: Score 0.715
2026-03-01 12:34:18,432 INFO MainThread moabb.evaluations.base AM+LDA | BNCI2014-001 | 2 | 0train: Score 0.597
2026-03-01 12:34:18,563 INFO MainThread moabb.evaluations.base AM+LDA | BNCI2014-001 | 2 | 1test: Score 0.521
2026-03-01 12:34:18,696 INFO MainThread moabb.evaluations.base AM+SVM | BNCI2014-001 | 2 | 0train: Score 0.500
2026-03-01 12:34:18,845 INFO MainThread moabb.evaluations.base AM+SVM | BNCI2014-001 | 2 | 1test: Score 0.500
Results are returned as a pandas DataFrame. When multiple metrics are provided, MOABB adds a primary score plus one column per metric (e.g., score_accuracy_score, score_roc_auc_score).
print(results.head())
score time ... pipeline codecarbon_task_name
0 0.729167 0.010415 ... AM+LDA 7ba82537-4356-46b8-95be-68f248732615
1 0.715278 0.008561 ... AM+LDA d8db0d13-517f-4e1e-97f0-6fc5b5d37535
2 0.597222 0.008468 ... AM+LDA 7ef8bd5e-aa6a-45b3-92f9-6e68ec214065
3 0.520833 0.008438 ... AM+LDA cba360a2-9426-44a9-bd87-b371708f27cb
4 0.743056 0.130731 ... AM+SVM 76c7de95-c968-4063-81ae-9ab452b71dfd
[5 rows x 13 columns]
Total running time of the script: (0 minutes 12.265 seconds)