braindecode 1.3.2.dev170848736__tar.gz → 1.3.2.dev173417708__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {braindecode-1.3.2.dev170848736/braindecode.egg-info → braindecode-1.3.2.dev173417708}/PKG-INFO +37 -7
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/README.rst +36 -6
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/base.py +396 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/mne.py +48 -4
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/eegpt.py +190 -19
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/labram.py +327 -77
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/util.py +1 -1
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/modules/__init__.py +2 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/modules/convolution.py +20 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/preprocessing/windowers.py +312 -78
- braindecode-1.3.2.dev173417708/braindecode/version.py +1 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/visualization/gradients.py +7 -7
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708/braindecode.egg-info}/PKG-INFO +37 -7
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/cite.rst +42 -4
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/conf.py +1 -1
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/whats_new.rst +29 -3
- braindecode-1.3.2.dev170848736/braindecode/version.py +0 -1
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/LICENSE.txt +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/MANIFEST.in +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/NOTICE.txt +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/__init__.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/augmentation/__init__.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/augmentation/base.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/augmentation/functional.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/augmentation/transforms.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/classifier.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/__init__.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/bbci.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/bcicomp.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/bids/__init__.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/bids/datasets.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/bids/format.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/bids/hub.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/bids/hub_format.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/bids/hub_io.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/bids/hub_validation.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/bids/iterable.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/chb_mit.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/moabb.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/nmt.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/registry.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/siena.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/sleep_physionet.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/tuh.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/utils.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/xy.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datautil/__init__.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datautil/channel_utils.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datautil/hub_formats.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datautil/serialization.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datautil/util.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/eegneuralnet.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/functional/__init__.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/functional/functions.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/functional/initialization.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/__init__.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/atcnet.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/attentionbasenet.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/attn_sleep.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/base.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/bendr.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/biot.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/brainmodule.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/cbramod.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/config.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/contrawr.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/ctnet.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/deep4.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/deepsleepnet.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/eegconformer.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/eeginception_erp.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/eeginception_mi.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/eegitnet.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/eegminer.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/eegnet.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/eegnex.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/eegsimpleconv.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/eegsym.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/eegtcnet.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/fbcnet.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/fblightconvnet.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/fbmsnet.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/hybrid.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/ifnet.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/luna.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/medformer.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/msvtnet.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/patchedtransformer.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/reve.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/sccnet.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/shallow_fbcsp.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/signal_jepa.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/sinc_shallow.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/sparcnet.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/sstdpn.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/summary.csv +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/syncnet.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/tcn.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/tidnet.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/tsinception.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/models/usleep.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/modules/activation.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/modules/attention.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/modules/blocks.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/modules/filter.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/modules/layers.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/modules/linear.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/modules/parametrization.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/modules/stats.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/modules/util.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/modules/wrapper.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/preprocessing/__init__.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/preprocessing/mne_preprocess.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/preprocessing/preprocess.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/preprocessing/util.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/regressor.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/samplers/__init__.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/samplers/base.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/samplers/ssl.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/training/__init__.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/training/callbacks.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/training/losses.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/training/scoring.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/util.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/visualization/__init__.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/visualization/confusion_matrices.py +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode.egg-info/SOURCES.txt +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode.egg-info/dependency_links.txt +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode.egg-info/requires.txt +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode.egg-info/top_level.txt +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/Makefile +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/_templates/autosummary/class.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/_templates/autosummary/function.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/api.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/help.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/index.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/install/install.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/install/install_pip.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/install/install_source.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/models/categorization/attention.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/models/categorization/channel.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/models/categorization/convolution.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/models/categorization/filterbank.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/models/categorization/gnn.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/models/categorization/interpretable.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/models/categorization/lbm.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/models/categorization/recurrent.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/models/categorization/spd.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/models/models.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/models/models_categorization.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/models/models_table.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/models/models_visualization.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/docs/sg_execution_times.rst +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/pyproject.toml +0 -0
- {braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/setup.cfg +0 -0
{braindecode-1.3.2.dev170848736/braindecode.egg-info → braindecode-1.3.2.dev173417708}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: braindecode
|
|
3
|
-
Version: 1.3.2.
|
|
3
|
+
Version: 1.3.2.dev173417708
|
|
4
4
|
Summary: Deep learning software to decode EEG, ECG or MEG signals
|
|
5
5
|
Author-email: Robin Tibor Schirrmeister <robintibor@gmail.com>, Bruno Aristimunha Pinto <b.aristimunha@gmail.com>, Alexandre Gramfort <agramfort@meta.com>
|
|
6
6
|
Maintainer-email: Alexandre Gramfort <agramfort@meta.com>, Bruno Aristimunha Pinto <b.aristimunha@gmail.com>, Robin Tibor Schirrmeister <robintibor@gmail.com>
|
|
@@ -84,8 +84,8 @@ Requires-Dist: braindecode[eegprep]; extra == "all"
|
|
|
84
84
|
Requires-Dist: braindecode[typing]; extra == "all"
|
|
85
85
|
Dynamic: license-file
|
|
86
86
|
|
|
87
|
-
.. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.
|
|
88
|
-
:target: https://doi.org/10.5281/zenodo.
|
|
87
|
+
.. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.17699192.svg
|
|
88
|
+
:target: https://doi.org/10.5281/zenodo.17699192
|
|
89
89
|
:alt: DOI
|
|
90
90
|
|
|
91
91
|
.. image:: https://github.com/braindecode/braindecode/workflows/docs/badge.svg
|
|
@@ -173,13 +173,43 @@ https://github.com/braindecode/braindecode/blob/master/CONTRIBUTING.md
|
|
|
173
173
|
Citing
|
|
174
174
|
########
|
|
175
175
|
|
|
176
|
-
If you use Braindecode in scientific work, please cite the software using the
|
|
177
|
-
shown in the badge below:
|
|
176
|
+
If you use Braindecode in scientific work, please cite the software using the global
|
|
177
|
+
Zenodo DOI shown in the badge below:
|
|
178
178
|
|
|
179
|
-
.. image:: https://zenodo.org/badge/
|
|
180
|
-
:target: https://doi.org/10.5281/zenodo.
|
|
179
|
+
.. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.17699192.svg
|
|
180
|
+
:target: https://doi.org/10.5281/zenodo.17699192
|
|
181
181
|
:alt: DOI
|
|
182
182
|
|
|
183
|
+
You can use the following BibTeX entry:
|
|
184
|
+
|
|
185
|
+
.. code-block:: bibtex
|
|
186
|
+
|
|
187
|
+
@software{braindecode,
|
|
188
|
+
author = {Aristimunha, Bruno and
|
|
189
|
+
Guetschel, Pierre and
|
|
190
|
+
Wimpff, Martin and
|
|
191
|
+
Gemein, Lukas and
|
|
192
|
+
Rommel, Cedric and
|
|
193
|
+
Banville, Hubert and
|
|
194
|
+
Sliwowski, Maciej and
|
|
195
|
+
Wilson, Daniel and
|
|
196
|
+
Brandt, Simon and
|
|
197
|
+
Gnassounou, Théo and
|
|
198
|
+
Paillard, Joseph and
|
|
199
|
+
{Junqueira Lopes}, Bruna and
|
|
200
|
+
Sedlar, Sara and
|
|
201
|
+
Moreau, Thomas and
|
|
202
|
+
Chevallier, Sylvain and
|
|
203
|
+
Gramfort, Alexandre and
|
|
204
|
+
Schirrmeister, Robin Tibor},
|
|
205
|
+
title = {Braindecode: toolbox for decoding raw electrophysiological brain data
|
|
206
|
+
with deep learning models},
|
|
207
|
+
url = {https://github.com/braindecode/braindecode},
|
|
208
|
+
doi = {10.5281/zenodo.17699192},
|
|
209
|
+
publisher = {Zenodo},
|
|
210
|
+
license = {BSD-3-Clause},
|
|
211
|
+
}
|
|
212
|
+
|
|
183
213
|
Additionally, we highly encourage you to cite the article that originally introduced the
|
|
184
214
|
Braindecode library and has served as a foundational reference for many works on deep
|
|
185
215
|
learning with EEG recordings. Please use the following reference:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
.. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.
|
|
2
|
-
:target: https://doi.org/10.5281/zenodo.
|
|
1
|
+
.. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.17699192.svg
|
|
2
|
+
:target: https://doi.org/10.5281/zenodo.17699192
|
|
3
3
|
:alt: DOI
|
|
4
4
|
|
|
5
5
|
.. image:: https://github.com/braindecode/braindecode/workflows/docs/badge.svg
|
|
@@ -87,13 +87,43 @@ https://github.com/braindecode/braindecode/blob/master/CONTRIBUTING.md
|
|
|
87
87
|
Citing
|
|
88
88
|
########
|
|
89
89
|
|
|
90
|
-
If you use Braindecode in scientific work, please cite the software using the
|
|
91
|
-
shown in the badge below:
|
|
90
|
+
If you use Braindecode in scientific work, please cite the software using the global
|
|
91
|
+
Zenodo DOI shown in the badge below:
|
|
92
92
|
|
|
93
|
-
.. image:: https://zenodo.org/badge/
|
|
94
|
-
:target: https://doi.org/10.5281/zenodo.
|
|
93
|
+
.. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.17699192.svg
|
|
94
|
+
:target: https://doi.org/10.5281/zenodo.17699192
|
|
95
95
|
:alt: DOI
|
|
96
96
|
|
|
97
|
+
You can use the following BibTeX entry:
|
|
98
|
+
|
|
99
|
+
.. code-block:: bibtex
|
|
100
|
+
|
|
101
|
+
@software{braindecode,
|
|
102
|
+
author = {Aristimunha, Bruno and
|
|
103
|
+
Guetschel, Pierre and
|
|
104
|
+
Wimpff, Martin and
|
|
105
|
+
Gemein, Lukas and
|
|
106
|
+
Rommel, Cedric and
|
|
107
|
+
Banville, Hubert and
|
|
108
|
+
Sliwowski, Maciej and
|
|
109
|
+
Wilson, Daniel and
|
|
110
|
+
Brandt, Simon and
|
|
111
|
+
Gnassounou, Théo and
|
|
112
|
+
Paillard, Joseph and
|
|
113
|
+
{Junqueira Lopes}, Bruna and
|
|
114
|
+
Sedlar, Sara and
|
|
115
|
+
Moreau, Thomas and
|
|
116
|
+
Chevallier, Sylvain and
|
|
117
|
+
Gramfort, Alexandre and
|
|
118
|
+
Schirrmeister, Robin Tibor},
|
|
119
|
+
title = {Braindecode: toolbox for decoding raw electrophysiological brain data
|
|
120
|
+
with deep learning models},
|
|
121
|
+
url = {https://github.com/braindecode/braindecode},
|
|
122
|
+
doi = {10.5281/zenodo.17699192},
|
|
123
|
+
publisher = {Zenodo},
|
|
124
|
+
license = {BSD-3-Clause},
|
|
125
|
+
}
|
|
126
|
+
|
|
97
127
|
Additionally, we highly encourage you to cite the article that originally introduced the
|
|
98
128
|
Braindecode library and has served as a foundational reference for many works on deep
|
|
99
129
|
learning with EEG recordings. Please use the following reference:
|
{braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/base.py
RENAMED
|
@@ -11,11 +11,13 @@
|
|
|
11
11
|
from __future__ import annotations
|
|
12
12
|
|
|
13
13
|
import bisect
|
|
14
|
+
import html as _html
|
|
14
15
|
import json
|
|
15
16
|
import os
|
|
16
17
|
import shutil
|
|
17
18
|
import warnings
|
|
18
19
|
from abc import abstractmethod
|
|
20
|
+
from collections import Counter
|
|
19
21
|
from collections.abc import Callable
|
|
20
22
|
from glob import glob
|
|
21
23
|
from typing import Any, Generic, Iterable, no_type_check
|
|
@@ -42,6 +44,256 @@ def _create_description(description) -> pd.Series:
|
|
|
42
44
|
return description
|
|
43
45
|
|
|
44
46
|
|
|
47
|
+
def _html_row(label, value):
|
|
48
|
+
"""Generate a single HTML table row."""
|
|
49
|
+
label = _html.escape(str(label))
|
|
50
|
+
value = _html.escape(str(value))
|
|
51
|
+
return f"<tr><td><b>{label}</b></td><td>{value}</td></tr>"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
_METADATA_INTERNAL_COLS = {
|
|
55
|
+
"i_window_in_trial",
|
|
56
|
+
"i_start_in_trial",
|
|
57
|
+
"i_stop_in_trial",
|
|
58
|
+
"target",
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _metadata_summary(metadata):
|
|
63
|
+
"""Summarize window metadata into a dict.
|
|
64
|
+
|
|
65
|
+
Returns a dict with keys: n_windows, target_info, extra_columns,
|
|
66
|
+
window_info, is_lazy.
|
|
67
|
+
"""
|
|
68
|
+
is_lazy = not isinstance(metadata, pd.DataFrame)
|
|
69
|
+
|
|
70
|
+
if is_lazy:
|
|
71
|
+
n_windows = len(metadata)
|
|
72
|
+
columns = list(metadata.columns) if hasattr(metadata, "columns") else []
|
|
73
|
+
extra_columns = [str(c) for c in columns if c not in _METADATA_INTERNAL_COLS]
|
|
74
|
+
return {
|
|
75
|
+
"n_windows": n_windows,
|
|
76
|
+
"target_info": None,
|
|
77
|
+
"extra_columns": extra_columns,
|
|
78
|
+
"window_info": None,
|
|
79
|
+
"is_lazy": True,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
n_windows = len(metadata)
|
|
83
|
+
extra_columns = [
|
|
84
|
+
str(c) for c in metadata.columns if c not in _METADATA_INTERNAL_COLS
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
target_info = None
|
|
88
|
+
if "target" in metadata.columns:
|
|
89
|
+
targets = metadata["target"]
|
|
90
|
+
n_unique = targets.nunique()
|
|
91
|
+
if n_unique <= 10:
|
|
92
|
+
counts = targets.value_counts().sort_index().to_dict()
|
|
93
|
+
target_info = f"{n_unique} unique ({counts})"
|
|
94
|
+
else:
|
|
95
|
+
target_info = f"{n_unique} unique targets"
|
|
96
|
+
|
|
97
|
+
window_info = None
|
|
98
|
+
if "i_start_in_trial" in metadata.columns and "i_stop_in_trial" in metadata.columns:
|
|
99
|
+
sizes = metadata["i_stop_in_trial"] - metadata["i_start_in_trial"]
|
|
100
|
+
if len(sizes) == 0:
|
|
101
|
+
pass
|
|
102
|
+
elif (min_s := int(sizes.min())) == (max_s := int(sizes.max())):
|
|
103
|
+
window_info = {"min": min_s, "max": max_s, "uniform": True}
|
|
104
|
+
else:
|
|
105
|
+
window_info = {"min": min_s, "max": max_s, "uniform": False}
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
"n_windows": n_windows,
|
|
109
|
+
"target_info": target_info,
|
|
110
|
+
"extra_columns": extra_columns,
|
|
111
|
+
"window_info": window_info,
|
|
112
|
+
"is_lazy": False,
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _concat_metadata_summary(datasets):
|
|
117
|
+
"""Aggregate metadata summary across datasets without full concatenation.
|
|
118
|
+
|
|
119
|
+
Returns a dict with keys: window_info, target_info, extra_columns.
|
|
120
|
+
"""
|
|
121
|
+
overall_min = None
|
|
122
|
+
overall_max = None
|
|
123
|
+
target_counts = Counter()
|
|
124
|
+
extra_cols = set()
|
|
125
|
+
|
|
126
|
+
for ds in datasets:
|
|
127
|
+
if hasattr(ds, "windows"):
|
|
128
|
+
md = ds.windows.metadata
|
|
129
|
+
elif hasattr(ds, "metadata"):
|
|
130
|
+
md = ds.metadata
|
|
131
|
+
else:
|
|
132
|
+
continue
|
|
133
|
+
if md is None or len(md) == 0:
|
|
134
|
+
continue
|
|
135
|
+
|
|
136
|
+
extra_cols.update(
|
|
137
|
+
str(c) for c in md.columns if c not in _METADATA_INTERNAL_COLS
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
if "i_start_in_trial" in md.columns and "i_stop_in_trial" in md.columns:
|
|
141
|
+
sizes = md["i_stop_in_trial"] - md["i_start_in_trial"]
|
|
142
|
+
if len(sizes) > 0:
|
|
143
|
+
ds_min, ds_max = int(sizes.min()), int(sizes.max())
|
|
144
|
+
overall_min = (
|
|
145
|
+
ds_min if overall_min is None else min(overall_min, ds_min)
|
|
146
|
+
)
|
|
147
|
+
overall_max = (
|
|
148
|
+
ds_max if overall_max is None else max(overall_max, ds_max)
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
if "target" in md.columns:
|
|
152
|
+
target_counts.update(md["target"].value_counts().to_dict())
|
|
153
|
+
|
|
154
|
+
window_info = None
|
|
155
|
+
if overall_min is not None:
|
|
156
|
+
window_info = {
|
|
157
|
+
"min": overall_min,
|
|
158
|
+
"max": overall_max,
|
|
159
|
+
"uniform": overall_min == overall_max,
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
target_info = None
|
|
163
|
+
if target_counts:
|
|
164
|
+
n_unique = len(target_counts)
|
|
165
|
+
if n_unique <= 10:
|
|
166
|
+
sorted_counts = dict(sorted(target_counts.items()))
|
|
167
|
+
target_info = f"{n_unique} unique ({sorted_counts})"
|
|
168
|
+
else:
|
|
169
|
+
target_info = f"{n_unique} unique targets"
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
"window_info": window_info,
|
|
173
|
+
"target_info": target_info,
|
|
174
|
+
"extra_columns": sorted(extra_cols),
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def _channel_info(mne_obj):
|
|
179
|
+
"""Extract channel summary from an mne object.
|
|
180
|
+
|
|
181
|
+
Returns (n_ch, type_str, sfreq).
|
|
182
|
+
"""
|
|
183
|
+
info = mne_obj.info
|
|
184
|
+
n_ch = info["nchan"]
|
|
185
|
+
sfreq = info["sfreq"]
|
|
186
|
+
ch_types = mne_obj.get_channel_types()
|
|
187
|
+
type_counts = Counter(ch_types)
|
|
188
|
+
type_str = ", ".join(f"{cnt} {t.upper()}" for t, cnt in sorted(type_counts.items()))
|
|
189
|
+
return n_ch, type_str, sfreq
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def _window_info(crop_inds, sfreq):
|
|
193
|
+
"""Extract window size from crop indices.
|
|
194
|
+
|
|
195
|
+
Returns (win_samples, win_secs) or None if crop_inds is empty.
|
|
196
|
+
"""
|
|
197
|
+
if len(crop_inds) == 0:
|
|
198
|
+
return None
|
|
199
|
+
first = crop_inds[0]
|
|
200
|
+
win_samples = int(first[2] - first[1])
|
|
201
|
+
win_secs = win_samples / sfreq
|
|
202
|
+
return win_samples, win_secs
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
class _ReprBuilder:
|
|
206
|
+
"""Lightweight builder that renders both text and HTML from the same data."""
|
|
207
|
+
|
|
208
|
+
def __init__(self, cls_name, type_display=None):
|
|
209
|
+
self._cls_name = cls_name
|
|
210
|
+
self._type_display = type_display or cls_name
|
|
211
|
+
self._header_parts = []
|
|
212
|
+
self._header_rows = []
|
|
213
|
+
self._items = []
|
|
214
|
+
|
|
215
|
+
def add_header(self, header_text, label, value):
|
|
216
|
+
"""Add to both the compact ``<ClassName | ...>`` line and an HTML row."""
|
|
217
|
+
self._header_parts.append(header_text)
|
|
218
|
+
self._header_rows.append((label, value))
|
|
219
|
+
return self
|
|
220
|
+
|
|
221
|
+
def add_row(self, label, value):
|
|
222
|
+
"""Add a detail row (text: `` label: value``, HTML: ``<tr>``)."""
|
|
223
|
+
self._items.append(("row", label, value))
|
|
224
|
+
return self
|
|
225
|
+
|
|
226
|
+
def add_footnote(self, text):
|
|
227
|
+
"""Add a footnote (text: `` (text)``, HTML: italic ``<td colspan=2>``)."""
|
|
228
|
+
self._items.append(("footnote", text, None))
|
|
229
|
+
return self
|
|
230
|
+
|
|
231
|
+
def to_repr(self):
|
|
232
|
+
if self._header_parts:
|
|
233
|
+
parts = " | ".join(self._header_parts)
|
|
234
|
+
lines = [f"<{self._cls_name} | {parts}>"]
|
|
235
|
+
else:
|
|
236
|
+
lines = [f"<{self._cls_name}>"]
|
|
237
|
+
for kind, label, value in self._items:
|
|
238
|
+
if kind == "row":
|
|
239
|
+
lines.append(f" {label}: {value}")
|
|
240
|
+
else:
|
|
241
|
+
lines.append(f" ({label})")
|
|
242
|
+
return "\n".join(lines)
|
|
243
|
+
|
|
244
|
+
def to_html(self):
|
|
245
|
+
rows = [_html_row("Type", self._type_display)]
|
|
246
|
+
for label, value in self._header_rows:
|
|
247
|
+
rows.append(_html_row(label, value))
|
|
248
|
+
for kind, label, value in self._items:
|
|
249
|
+
if kind == "row":
|
|
250
|
+
html_label = label[0].upper() + label[1:]
|
|
251
|
+
rows.append(_html_row(html_label, value))
|
|
252
|
+
else:
|
|
253
|
+
rows.append(
|
|
254
|
+
f"<tr><td colspan='2'><i>{_html.escape(str(label))}</i></td></tr>"
|
|
255
|
+
)
|
|
256
|
+
table_rows = "\n".join(rows)
|
|
257
|
+
esc_name = _html.escape(str(self._cls_name))
|
|
258
|
+
return (
|
|
259
|
+
f"<table border='1' class='dataframe'>\n"
|
|
260
|
+
f" <thead><tr><th colspan='2'>{esc_name}</th></tr></thead>\n"
|
|
261
|
+
f" <tbody>\n{table_rows}\n </tbody>\n</table>"
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def _build_windowed_repr(
|
|
266
|
+
cls_name, n_windows, mne_obj, crop_inds, description, metadata
|
|
267
|
+
):
|
|
268
|
+
"""Build repr for EEGWindowsDataset and WindowsDataset."""
|
|
269
|
+
b = _ReprBuilder(cls_name)
|
|
270
|
+
n_ch, type_str, sfreq = _channel_info(mne_obj)
|
|
271
|
+
b.add_header(f"{n_windows} windows", "Windows", n_windows)
|
|
272
|
+
b.add_header(f"{n_ch} ch ({type_str})", "Channels", f"{n_ch} ({type_str})")
|
|
273
|
+
wi = _window_info(crop_inds, sfreq)
|
|
274
|
+
if wi is not None:
|
|
275
|
+
win_samples, win_secs = wi
|
|
276
|
+
b.add_header(
|
|
277
|
+
f"{win_samples} samples/win ({win_secs:.3f} s)",
|
|
278
|
+
"Window size",
|
|
279
|
+
f"{win_samples} samples ({win_secs:.3f} s)",
|
|
280
|
+
)
|
|
281
|
+
b.add_header(f"{sfreq:.1f} Hz", "Sfreq", f"{sfreq:.1f} Hz")
|
|
282
|
+
if description is not None:
|
|
283
|
+
desc_items = ", ".join(f"{k}={v}" for k, v in description.items())
|
|
284
|
+
b.add_row("description", desc_items)
|
|
285
|
+
if metadata is not None:
|
|
286
|
+
summary = _metadata_summary(metadata)
|
|
287
|
+
if summary["is_lazy"]:
|
|
288
|
+
b.add_row("metadata", f"lazy ({summary['n_windows']} windows)")
|
|
289
|
+
else:
|
|
290
|
+
if summary["target_info"]:
|
|
291
|
+
b.add_row("targets", summary["target_info"])
|
|
292
|
+
if summary["extra_columns"]:
|
|
293
|
+
b.add_row("extra metadata", ", ".join(summary["extra_columns"]))
|
|
294
|
+
return b
|
|
295
|
+
|
|
296
|
+
|
|
45
297
|
class RecordDataset(Dataset[tuple[np.ndarray, int | str, tuple[int, int, int]]]):
|
|
46
298
|
def __init__(
|
|
47
299
|
self,
|
|
@@ -94,6 +346,15 @@ class RecordDataset(Dataset[tuple[np.ndarray, int | str, tuple[int, int, int]]])
|
|
|
94
346
|
raise ValueError("Transform needs to be a callable.")
|
|
95
347
|
self._transform = value
|
|
96
348
|
|
|
349
|
+
def _build_repr(self):
|
|
350
|
+
return _ReprBuilder(type(self).__name__)
|
|
351
|
+
|
|
352
|
+
def __repr__(self):
|
|
353
|
+
return self._build_repr().to_repr()
|
|
354
|
+
|
|
355
|
+
def _repr_html_(self):
|
|
356
|
+
return self._build_repr().to_html()
|
|
357
|
+
|
|
97
358
|
|
|
98
359
|
# Type of the datasets contained in BaseConcatDataset
|
|
99
360
|
T = TypeVar("T", bound=RecordDataset)
|
|
@@ -148,6 +409,23 @@ class RawDataset(RecordDataset):
|
|
|
148
409
|
def __len__(self):
|
|
149
410
|
return len(self.raw)
|
|
150
411
|
|
|
412
|
+
def _build_repr(self):
|
|
413
|
+
b = _ReprBuilder(type(self).__name__)
|
|
414
|
+
n_ch, type_str, sfreq = _channel_info(self.raw)
|
|
415
|
+
n_times = len(self.raw.times)
|
|
416
|
+
duration = n_times / sfreq
|
|
417
|
+
b.add_header(f"{n_ch} ch ({type_str})", "Channels", f"{n_ch} ({type_str})")
|
|
418
|
+
b.add_header(f"{sfreq:.1f} Hz", "Sfreq", f"{sfreq:.1f} Hz")
|
|
419
|
+
b.add_header(
|
|
420
|
+
f"{n_times} samples ({duration:.1f} s)",
|
|
421
|
+
"Samples",
|
|
422
|
+
f"{n_times} ({duration:.1f} s)",
|
|
423
|
+
)
|
|
424
|
+
if self.description is not None:
|
|
425
|
+
desc_items = ", ".join(f"{k}={v}" for k, v in self.description.items())
|
|
426
|
+
b.add_row("description", desc_items)
|
|
427
|
+
return b
|
|
428
|
+
|
|
151
429
|
def _target_name(self, target_name):
|
|
152
430
|
if target_name is not None and not isinstance(target_name, (str, tuple, list)):
|
|
153
431
|
raise ValueError("target_name has to be None, str, tuple or list")
|
|
@@ -291,6 +569,16 @@ class EEGWindowsDataset(RecordDataset):
|
|
|
291
569
|
def __len__(self):
|
|
292
570
|
return len(self.crop_inds)
|
|
293
571
|
|
|
572
|
+
def _build_repr(self):
|
|
573
|
+
return _build_windowed_repr(
|
|
574
|
+
type(self).__name__,
|
|
575
|
+
len(self),
|
|
576
|
+
self.raw,
|
|
577
|
+
self.crop_inds,
|
|
578
|
+
self.description,
|
|
579
|
+
self.metadata,
|
|
580
|
+
)
|
|
581
|
+
|
|
294
582
|
|
|
295
583
|
@register_dataset
|
|
296
584
|
class WindowsDataset(RecordDataset):
|
|
@@ -383,6 +671,16 @@ class WindowsDataset(RecordDataset):
|
|
|
383
671
|
def __len__(self) -> int:
|
|
384
672
|
return len(self.windows.events)
|
|
385
673
|
|
|
674
|
+
def _build_repr(self):
|
|
675
|
+
return _build_windowed_repr(
|
|
676
|
+
type(self).__name__,
|
|
677
|
+
len(self),
|
|
678
|
+
self.windows,
|
|
679
|
+
self.crop_inds,
|
|
680
|
+
self.description,
|
|
681
|
+
self.windows.metadata,
|
|
682
|
+
)
|
|
683
|
+
|
|
386
684
|
|
|
387
685
|
@register_dataset
|
|
388
686
|
class BaseConcatDataset(ConcatDataset, HubDatasetMixin, Generic[T]):
|
|
@@ -887,3 +1185,101 @@ class BaseConcatDataset(ConcatDataset, HubDatasetMixin, Generic[T]):
|
|
|
887
1185
|
target_file_path = os.path.join(sub_dir, "target_name.json")
|
|
888
1186
|
with open(target_file_path, "w") as f:
|
|
889
1187
|
json.dump({"target_name": ds.target_name}, f)
|
|
1188
|
+
|
|
1189
|
+
@staticmethod
|
|
1190
|
+
def _signal_summary(ds):
|
|
1191
|
+
"""Return (mne_obj, is_windowed) from a dataset."""
|
|
1192
|
+
if hasattr(ds, "windows"):
|
|
1193
|
+
mne_obj = ds.windows
|
|
1194
|
+
elif hasattr(ds, "raw"):
|
|
1195
|
+
mne_obj = ds.raw
|
|
1196
|
+
else:
|
|
1197
|
+
return None, False
|
|
1198
|
+
is_windowed = hasattr(ds, "crop_inds")
|
|
1199
|
+
return mne_obj, is_windowed
|
|
1200
|
+
|
|
1201
|
+
def _build_repr(self):
|
|
1202
|
+
n_ds = len(self.datasets)
|
|
1203
|
+
b = _ReprBuilder("BaseConcatDataset")
|
|
1204
|
+
if n_ds == 0:
|
|
1205
|
+
b.add_header("0 datasets", "Recordings", 0)
|
|
1206
|
+
return b
|
|
1207
|
+
|
|
1208
|
+
n_total = len(self)
|
|
1209
|
+
ds_type = type(self.datasets[0]).__name__
|
|
1210
|
+
first_ds = self.datasets[0]
|
|
1211
|
+
mne_obj, is_windowed = self._signal_summary(first_ds)
|
|
1212
|
+
|
|
1213
|
+
b._type_display = f"BaseConcatDataset of {ds_type}"
|
|
1214
|
+
b.add_header(f"{n_ds} {ds_type}(s)", "Recordings", n_ds)
|
|
1215
|
+
b.add_header(f"{n_total} total samples", "Total samples", n_total)
|
|
1216
|
+
|
|
1217
|
+
if mne_obj is not None:
|
|
1218
|
+
n_ch, type_str, sfreq = _channel_info(mne_obj)
|
|
1219
|
+
b.add_row("Sfreq*", f"{sfreq:.1f} Hz")
|
|
1220
|
+
b.add_row("Channels*", f"{n_ch} ({type_str})")
|
|
1221
|
+
|
|
1222
|
+
ch_names = mne_obj.info["ch_names"]
|
|
1223
|
+
if len(ch_names) <= 10:
|
|
1224
|
+
ch_str = ", ".join(ch_names)
|
|
1225
|
+
else:
|
|
1226
|
+
ch_str = (
|
|
1227
|
+
", ".join(ch_names[:10]) + f", ... (+{len(ch_names) - 10} more)"
|
|
1228
|
+
)
|
|
1229
|
+
b.add_row("Ch. names*", ch_str)
|
|
1230
|
+
|
|
1231
|
+
montage = mne_obj.get_montage()
|
|
1232
|
+
if montage is not None:
|
|
1233
|
+
b.add_row("Montage*", montage.get_positions()["coord_frame"])
|
|
1234
|
+
|
|
1235
|
+
if not is_windowed:
|
|
1236
|
+
n_times = len(mne_obj.times)
|
|
1237
|
+
duration = n_times / sfreq
|
|
1238
|
+
b.add_row("Duration*", f"{duration:.1f} s")
|
|
1239
|
+
|
|
1240
|
+
b.add_footnote("* from first recording")
|
|
1241
|
+
|
|
1242
|
+
desc = self.description
|
|
1243
|
+
if desc is not None and not desc.empty:
|
|
1244
|
+
col_str = ", ".join(str(c) for c in desc.columns)
|
|
1245
|
+
b.add_row(
|
|
1246
|
+
"Description",
|
|
1247
|
+
f"{desc.shape[0]} recordings × {desc.shape[1]} columns [{col_str}]",
|
|
1248
|
+
)
|
|
1249
|
+
|
|
1250
|
+
if is_windowed:
|
|
1251
|
+
try:
|
|
1252
|
+
summary = _concat_metadata_summary(self.datasets)
|
|
1253
|
+
if summary["window_info"] is not None and mne_obj is not None:
|
|
1254
|
+
wi = summary["window_info"]
|
|
1255
|
+
if wi["uniform"]:
|
|
1256
|
+
win_secs = wi["min"] / sfreq
|
|
1257
|
+
b.add_row(
|
|
1258
|
+
"Window",
|
|
1259
|
+
f"{wi['min']} samples ({win_secs:.3f} s)",
|
|
1260
|
+
)
|
|
1261
|
+
else:
|
|
1262
|
+
min_secs = wi["min"] / sfreq
|
|
1263
|
+
max_secs = wi["max"] / sfreq
|
|
1264
|
+
b.add_row(
|
|
1265
|
+
"Window",
|
|
1266
|
+
f"{wi['min']}-{wi['max']} samples"
|
|
1267
|
+
f" ({min_secs:.3f}-{max_secs:.3f} s)",
|
|
1268
|
+
)
|
|
1269
|
+
if summary["target_info"]:
|
|
1270
|
+
b.add_row("Targets", summary["target_info"])
|
|
1271
|
+
if summary["extra_columns"]:
|
|
1272
|
+
b.add_row(
|
|
1273
|
+
"Extra meta",
|
|
1274
|
+
", ".join(summary["extra_columns"]),
|
|
1275
|
+
)
|
|
1276
|
+
except (TypeError, AttributeError):
|
|
1277
|
+
pass
|
|
1278
|
+
|
|
1279
|
+
return b
|
|
1280
|
+
|
|
1281
|
+
def __repr__(self):
|
|
1282
|
+
return self._build_repr().to_repr()
|
|
1283
|
+
|
|
1284
|
+
def _repr_html_(self):
|
|
1285
|
+
return self._build_repr().to_html()
|
{braindecode-1.3.2.dev170848736 → braindecode-1.3.2.dev173417708}/braindecode/datasets/mne.py
RENAMED
|
@@ -100,6 +100,11 @@ def create_from_mne_epochs(
|
|
|
100
100
|
window_size_samples: int,
|
|
101
101
|
window_stride_samples: int,
|
|
102
102
|
drop_last_window: bool,
|
|
103
|
+
descriptions: list[dict | pd.Series] | None = None,
|
|
104
|
+
mapping: dict[str | int, int] | None = None,
|
|
105
|
+
preload: bool = False,
|
|
106
|
+
picks: str | list | slice | None = None,
|
|
107
|
+
drop_bad_windows: bool = True,
|
|
103
108
|
) -> BaseConcatDataset:
|
|
104
109
|
"""Create WindowsDatasets from mne.Epochs.
|
|
105
110
|
|
|
@@ -114,6 +119,25 @@ def create_from_mne_epochs(
|
|
|
114
119
|
drop_last_window : bool
|
|
115
120
|
whether or not have a last overlapping window, when
|
|
116
121
|
windows do not equally divide the continuous signal
|
|
122
|
+
descriptions : array-like | None
|
|
123
|
+
list of dicts or pandas.Series with additional information about
|
|
124
|
+
the epochs. If None, no description is added. Length must match
|
|
125
|
+
``list_of_epochs``. Each description is applied to all windows
|
|
126
|
+
generated from the corresponding Epochs object.
|
|
127
|
+
mapping : dict(str | int: int) | None
|
|
128
|
+
Mapping from event description to target value. Keys can be
|
|
129
|
+
integers (matching ``epochs.events[:, 2]``) or their string
|
|
130
|
+
representations. If None, targets are set to the raw integer
|
|
131
|
+
event codes. If a mapping is provided and an event code is not
|
|
132
|
+
found in the mapping, the original event code is kept as-is.
|
|
133
|
+
preload : bool
|
|
134
|
+
if True, preload the data of the Epochs objects.
|
|
135
|
+
picks : str | list | slice | None
|
|
136
|
+
channels to include. If None, all available channels are used.
|
|
137
|
+
drop_bad_windows : bool
|
|
138
|
+
If True, call `.drop_bad()` on the resulting mne.Epochs object.
|
|
139
|
+
This allows identifying windows that fall outside of the valid
|
|
140
|
+
signal range. Defaults to True.
|
|
117
141
|
|
|
118
142
|
Returns
|
|
119
143
|
-------
|
|
@@ -126,8 +150,15 @@ def create_from_mne_epochs(
|
|
|
126
150
|
|
|
127
151
|
_check_windowing_arguments(0, 0, window_size_samples, window_stride_samples)
|
|
128
152
|
|
|
153
|
+
if descriptions is not None:
|
|
154
|
+
if len(descriptions) != len(list_of_epochs):
|
|
155
|
+
raise ValueError(
|
|
156
|
+
f"length of 'list_of_epochs' ({len(list_of_epochs)}) and "
|
|
157
|
+
f"'descriptions' ({len(descriptions)}) has to match"
|
|
158
|
+
)
|
|
159
|
+
|
|
129
160
|
list_of_windows_ds = []
|
|
130
|
-
for epochs in list_of_epochs:
|
|
161
|
+
for i, epochs in enumerate(list_of_epochs):
|
|
131
162
|
event_descriptions = epochs.events[:, 2]
|
|
132
163
|
original_trial_starts = epochs.events[:, 0]
|
|
133
164
|
stop = len(epochs.times) - window_size_samples
|
|
@@ -142,6 +173,15 @@ def create_from_mne_epochs(
|
|
|
142
173
|
fake_events = [[start, window_size_samples, -1] for start in starts]
|
|
143
174
|
|
|
144
175
|
for trial_i, trial in enumerate(epochs):
|
|
176
|
+
# resolve target using mapping if provided
|
|
177
|
+
event_code = event_descriptions[trial_i]
|
|
178
|
+
if mapping is not None:
|
|
179
|
+
target = mapping.get(
|
|
180
|
+
event_code, mapping.get(str(event_code), event_code)
|
|
181
|
+
)
|
|
182
|
+
else:
|
|
183
|
+
target = event_code
|
|
184
|
+
|
|
145
185
|
metadata = pd.DataFrame(
|
|
146
186
|
{
|
|
147
187
|
"i_window_in_trial": np.arange(len(fake_events)),
|
|
@@ -149,7 +189,7 @@ def create_from_mne_epochs(
|
|
|
149
189
|
"i_stop_in_trial": starts
|
|
150
190
|
+ original_trial_starts[trial_i]
|
|
151
191
|
+ window_size_samples,
|
|
152
|
-
"target": len(fake_events) * [
|
|
192
|
+
"target": len(fake_events) * [target],
|
|
153
193
|
}
|
|
154
194
|
)
|
|
155
195
|
# window size - 1, since tmax is inclusive
|
|
@@ -160,11 +200,15 @@ def create_from_mne_epochs(
|
|
|
160
200
|
tmin=0,
|
|
161
201
|
tmax=(window_size_samples - 1) / epochs.info["sfreq"],
|
|
162
202
|
metadata=metadata,
|
|
203
|
+
preload=preload,
|
|
204
|
+
picks=picks,
|
|
163
205
|
)
|
|
164
206
|
|
|
165
|
-
|
|
207
|
+
if drop_bad_windows:
|
|
208
|
+
mne_epochs.drop_bad(reject=None, flat=None)
|
|
166
209
|
|
|
167
|
-
|
|
210
|
+
desc = descriptions[i] if descriptions is not None else None
|
|
211
|
+
windows_ds = WindowsDataset(mne_epochs, description=desc)
|
|
168
212
|
list_of_windows_ds.append(windows_ds)
|
|
169
213
|
|
|
170
214
|
return BaseConcatDataset(list_of_windows_ds)
|