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 0x7fd893f63a60>, <moabb.datasets.bnci.bnci_2014.BNCI2014_004 object at 0x7fd893f63640>, <moabb.datasets.beetl.Beetl2021_A object at 0x7fd894efe050>, <moabb.datasets.beetl.Beetl2021_B object at 0x7fd893f62ce0>, <moabb.datasets.brandl2020.Brandl2020 object at 0x7fd893f63d90>, <moabb.datasets.chang2025.Chang2025 object at 0x7fd893f61e40>, <moabb.datasets.gigadb.Cho2017 object at 0x7fd8940ff790>, <moabb.datasets.dreyer2023.Dreyer2023 object at 0x7fd8940ff340>, <moabb.datasets.dreyer2023.Dreyer2023A object at 0x7fd893f63b80>, <moabb.datasets.dreyer2023.Dreyer2023B object at 0x7fd894ebab30>, <moabb.datasets.dreyer2023.Dreyer2023C object at 0x7fd894eb9540>, <moabb.datasets.forenzo2023.Forenzo2023 object at 0x7fd894eb9930>, <moabb.datasets.mpi_mi.GrosseWentrup2009 object at 0x7fd893e1a080>, <moabb.datasets.guttmann_flury2025.GuttmannFlury2025_ME object at 0x7fd894eb9e70>, <moabb.datasets.guttmann_flury2025.GuttmannFlury2025_MI object at 0x7fd8940ff280>, <moabb.datasets.hefmi_ich2025.HefmiIch2025 object at 0x7fd893e18b20>, <moabb.datasets.kaya2018.Kaya2018 object at 0x7fd893e1a6e0>, <moabb.datasets.kumar2024.Kumar2024 object at 0x7fd893e1a800>, <moabb.datasets.Lee2019.Lee2019_MI object at 0x7fd8940fee00>, <moabb.datasets.liu2024.Liu2024 object at 0x7fd893e19cf0>, <moabb.datasets.physionet_mi.PhysionetMI object at 0x7fd8940ff550>, <moabb.datasets.schirrmeister2017.Schirrmeister2017 object at 0x7fd8940ff880>, <moabb.datasets.bbci_eeg_fnirs.Shin2017A object at 0x7fd8940fe2f0>, <moabb.datasets.stieger2021.Stieger2021 object at 0x7fd8940fd660>, <moabb.datasets.wairagkar2018.Wairagkar2018 object at 0x7fd8940fea10>, <moabb.datasets.Weibo2014.Weibo2014 object at 0x7fd8940fd2a0>, <moabb.datasets.wu2020.Wu2020 object at 0x7fd8940ff0d0>, <moabb.datasets.yang2025.Yang2025 object at 0x7fd893e2efe0>, <moabb.datasets.Zhou2016.Zhou2016 object at 0x7fd893e2d990>, <moabb.datasets.zhou2020.Zhou2020 object at 0x7fd893e2fdc0>]
Or you can run a search through the available datasets:
print(utils.dataset_search(paradigm="imagery", min_subjects=6))
[<moabb.datasets.aguilera_rodriguez2025.AguileraRodriguez2025 object at 0x7fd893f63130>, <moabb.datasets.alex_mi.AlexMI object at 0x7fd893f62770>, <moabb.datasets.bcicomp2020_upper_limb.BCIComp2020UpperLimb object at 0x7fd893f62080>, <moabb.datasets.bnci.bnci_2014.BNCI2014_001 object at 0x7fd893f62bf0>, <moabb.datasets.bnci.bnci_2014.BNCI2014_002 object at 0x7fd893f61ba0>, <moabb.datasets.bnci.bnci_2014.BNCI2014_004 object at 0x7fd893f63a60>, <moabb.datasets.bnci.bnci_2015.BNCI2015_001 object at 0x7fd893f62f80>, <moabb.datasets.bnci.bnci_2015.BNCI2015_004 object at 0x7fd893f62230>, <moabb.datasets.bnci.bnci_2019.BNCI2019_001 object at 0x7fd893f626e0>, <moabb.datasets.bnci.bnci_2020.BNCI2020_001 object at 0x7fd893f62020>, <moabb.datasets.bnci.bnci_2022_001.BNCI2022_001 object at 0x7fd893f62ce0>, <moabb.datasets.bnci.bnci_2024_001.BNCI2024_001 object at 0x7fd893f62830>, <moabb.datasets.bnci.bnci_2025.BNCI2025_001 object at 0x7fd893f62f50>, <moabb.datasets.bnci.bnci_2025.BNCI2025_002 object at 0x7fd893f63250>, <moabb.datasets.brandl2020.Brandl2020 object at 0x7fd893f620b0>, <moabb.datasets.chang2025.Chang2025 object at 0x7fd893f639a0>, <moabb.datasets.gigadb.Cho2017 object at 0x7fd893f62620>, <moabb.datasets.dreyer2023.Dreyer2023 object at 0x7fd893f621a0>, <moabb.datasets.dreyer2023.Dreyer2023A object at 0x7fd893f614b0>, <moabb.datasets.dreyer2023.Dreyer2023B object at 0x7fd893f63640>, <moabb.datasets.dreyer2023.Dreyer2023C object at 0x7fd893f61e40>, <moabb.datasets.fake.FakeDataset object at 0x7fd893f619f0>, <moabb.datasets.forenzo2023.Forenzo2023 object at 0x7fd893f62ef0>, <moabb.datasets.gao2026.Gao2026 object at 0x7fd893f63d90>, <moabb.datasets.mpi_mi.GrosseWentrup2009 object at 0x7fd893f63b80>, <moabb.datasets.guttmann_flury2025.GuttmannFlury2025_ME object at 0x7fd893e2d990>, <moabb.datasets.guttmann_flury2025.GuttmannFlury2025_MI object at 0x7fd893e2fdc0>, <moabb.datasets.hefmi_ich2025.HefmiIch2025 object at 0x7fd893e2fa60>, <moabb.datasets.jeong2020.Jeong2020 object at 0x7fd893e2efe0>, <moabb.datasets.kaya2018.Kaya2018 object at 0x7fd893e2f0a0>, <moabb.datasets.kumar2024.Kumar2024 object at 0x7fd893e2c4c0>, <moabb.datasets.Lee2019.Lee2019_MI object at 0x7fd893e2e3e0>, <moabb.datasets.liu2024.Liu2024 object at 0x7fd893e2fa00>, <moabb.datasets.liu2025.Liu2025 object at 0x7fd893e2f5b0>, <moabb.datasets.ma2020.Ma2020 object at 0x7fd893e2d180>, <moabb.datasets.nguyen2017.Nguyen2017_L object at 0x7fd893e2d300>, <moabb.datasets.nguyen2017.Nguyen2017_S object at 0x7fd893e2fd00>, <moabb.datasets.nguyen2017.Nguyen2017_SL object at 0x7fd893e2f070>, <moabb.datasets.nguyen2017.Nguyen2017_V object at 0x7fd893e2e8f0>, <moabb.datasets.nieto2022.Nieto2022 object at 0x7fd893e2cf70>, <moabb.datasets.upper_limb.Ofner2017 object at 0x7fd893e2cc10>, <moabb.datasets.physionet_mi.PhysionetMI object at 0x7fd893e2df60>, <moabb.datasets.pressel2016.Pressel2016 object at 0x7fd893e2c190>, <moabb.datasets.rozado2015.Rozado2015 object at 0x7fd893e2ef50>, <moabb.datasets.schirrmeister2017.Schirrmeister2017 object at 0x7fd893e2c070>, <moabb.datasets.bbci_eeg_fnirs.Shin2017A object at 0x7fd893e2c040>, <moabb.datasets.bbci_eeg_fnirs.Shin2017B object at 0x7fd893e2c850>, <moabb.datasets.stieger2021.Stieger2021 object at 0x7fd893e2cb80>, <moabb.datasets.tavakolan2017.Tavakolan2017 object at 0x7fd893e2e200>, <moabb.datasets.triana_guzman2024.TrianaGuzman2024 object at 0x7fd893e2dd20>, <moabb.datasets.wairagkar2018.Wairagkar2018 object at 0x7fd893e2c220>, <moabb.datasets.Weibo2014.Weibo2014 object at 0x7fd893e2f280>, <moabb.datasets.wu2020.Wu2020 object at 0x7fd893e2feb0>, <moabb.datasets.yang2025.Yang2025 object at 0x7fd893e2f220>, <moabb.datasets.yi2025.Yi2025 object at 0x7fd893e2c430>, <moabb.datasets.zhang2017.Zhang2017 object at 0x7fd893e2dcf0>, <moabb.datasets.zhou2020.Zhou2020 object at 0x7fd893e2d240>, <moabb.datasets.zuo2025.Zuo2025 object at 0x7fd893e2d480>]
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)
2026-05-20 23:18:16,089 INFO MainThread moabb.evaluations.base AM+LDA | BNCI2014-001 | 1 | 0train: Score 0.729
2026-05-20 23:18:16,090 INFO MainThread moabb.evaluations.base AM+SVM | BNCI2014-001 | 1 | 0train: Score 0.743
2026-05-20 23:18:16,090 INFO MainThread moabb.evaluations.base AM+LDA | BNCI2014-001 | 1 | 1test: Score 0.715
2026-05-20 23:18:16,090 INFO MainThread moabb.evaluations.base AM+SVM | BNCI2014-001 | 1 | 1test: Score 0.715
2026-05-20 23:18:16,090 INFO MainThread moabb.evaluations.base AM+LDA | BNCI2014-001 | 2 | 0train: Score 0.597
2026-05-20 23:18:16,090 INFO MainThread moabb.evaluations.base AM+SVM | BNCI2014-001 | 2 | 0train: Score 0.500
2026-05-20 23:18:16,090 INFO MainThread moabb.evaluations.base AM+LDA | BNCI2014-001 | 2 | 1test: Score 0.521
2026-05-20 23:18:16,090 INFO MainThread moabb.evaluations.base AM+SVM | BNCI2014-001 | 2 | 1test: Score 0.500
/home/runner/work/moabb/moabb/moabb/analysis/results.py:189: H5pyDeprecationWarning: Creating a dataset without passing data or dtype is deprecated. Pass an explicit dtype. Using dtype='f4' will keep the current default behaviour.
dset.create_dataset(
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.743056 0.134940 ... AM+SVM 0385ea54-5ff7-4e6e-ba83-e79506089772
1 0.715278 0.128467 ... AM+SVM e57dcda8-17a9-4edd-bd67-5d48538560c7
2 0.500000 0.238500 ... AM+SVM 186990c2-7472-4920-96ff-70c3acb7b6dd
3 0.500000 0.156745 ... AM+SVM d37e0079-9d2d-4e08-a317-3a0828d773b8
4 0.729167 0.015173 ... AM+LDA d3eac3fc-f0e0-4718-bad8-e6c6e0774431
[5 rows x 15 columns]
Total running time of the script: (0 minutes 32.943 seconds)
Estimated memory usage: 816 MB