braindecode 1.6.1.dev1073__tar.gz → 1.6.1.dev1079__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.6.1.dev1073/braindecode.egg-info → braindecode-1.6.1.dev1079}/PKG-INFO +1 -1
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/__init__.py +2 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/base.py +109 -0
- braindecode-1.6.1.dev1079/braindecode/datasets/collate.py +105 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/eegneuralnet.py +8 -1
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/functional/__init__.py +2 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/functional/functions.py +39 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/__init__.py +2 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/biot.py +3 -10
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/brainmodule.py +185 -54
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/medformer.py +4 -22
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/steegformer.py +2 -8
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/summary.csv +61 -61
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/util.py +42 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/modules/__init__.py +6 -1
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/modules/activation.py +34 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/modules/layers.py +126 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/preprocessing/mne_preprocess.py +129 -12
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/training/scoring.py +8 -1
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/util.py +36 -1
- braindecode-1.6.1.dev1079/braindecode/version.py +1 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079/braindecode.egg-info}/PKG-INFO +1 -1
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode.egg-info/SOURCES.txt +1 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/api.rst +4 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/conf.py +14 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/models/models_table.rst +4 -1
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/whats_new.rst +45 -0
- braindecode-1.6.1.dev1073/braindecode/version.py +0 -1
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/LICENSE.txt +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/MANIFEST.in +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/NOTICE.txt +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/README.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/__init__.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/augmentation/__init__.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/augmentation/base.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/augmentation/functional.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/augmentation/transforms.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/classifier.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/bbci.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/bcicomp.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/bids/__init__.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/bids/datasets.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/bids/format.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/bids/hub.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/bids/hub_format.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/bids/hub_io.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/bids/hub_validation.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/bids/iterable.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/chb_mit.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/mne.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/moabb.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/nmt.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/registry.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/siena.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/sleep_physionet.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/tuh.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/utils.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datasets/xy.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datautil/__init__.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datautil/channel_utils.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datautil/hub_formats.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datautil/serialization.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/datautil/util.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/functional/initialization.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/atcnet.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/attentionbasenet.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/attn_sleep.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/base.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/bendr.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/cbramod.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/codebrain.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/config.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/contrawr.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/ctnet.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/deep4.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/deepsleepnet.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/dgcnn.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/eegconformer.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/eegdino.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/eeginception_erp.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/eeginception_mi.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/eegitnet.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/eegminer.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/eegnet.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/eegnex.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/eegpt.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/eegsimpleconv.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/eegsym.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/eegtcnet.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/emg2qwerty.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/fbcnet.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/fblightconvnet.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/fbmsnet.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/hybrid.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/ifnet.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/interpolated.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/labram.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/luna.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/meta_neuromotor.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/msvtnet.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/patchedtransformer.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/reve.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/sccnet.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/shallow_fbcsp.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/signal_jepa.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/sinc_shallow.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/sparcnet.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/sstdpn.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/syncnet.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/tcformer.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/tcn.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/tidnet.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/tsinception.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/models/usleep.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/modules/attention.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/modules/blocks.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/modules/convolution.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/modules/filter.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/modules/interpolation.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/modules/linear.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/modules/parametrization.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/modules/stats.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/modules/util.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/modules/wrapper.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/preprocessing/__init__.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/preprocessing/preprocess.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/preprocessing/util.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/preprocessing/windowers.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/regressor.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/samplers/__init__.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/samplers/base.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/samplers/ssl.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/training/__init__.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/training/callbacks.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/training/losses.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/visualization/__init__.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/visualization/attribution.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/visualization/confusion_matrices.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/visualization/frequency.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/visualization/metrics.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/visualization/sanity.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode/visualization/topology.py +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode.egg-info/dependency_links.txt +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode.egg-info/requires.txt +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/braindecode.egg-info/top_level.txt +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/Makefile +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/_templates/autosummary/class.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/_templates/autosummary/function.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/cite.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/help.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/index.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/install/install.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/install/install_pip.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/install/install_source.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/models/categorization/attention.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/models/categorization/channel.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/models/categorization/convolution.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/models/categorization/filterbank.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/models/categorization/gnn.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/models/categorization/interpretable.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/models/categorization/lbm.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/models/categorization/recurrent.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/models/categorization/spd.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/models/models.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/models/models_categorization.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/models/models_visualization.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/docs/sg_execution_times.rst +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/pyproject.toml +0 -0
- {braindecode-1.6.1.dev1073 → braindecode-1.6.1.dev1079}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: braindecode
|
|
3
|
-
Version: 1.6.1.
|
|
3
|
+
Version: 1.6.1.dev1079
|
|
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>
|
|
@@ -10,6 +10,7 @@ from .base import (
|
|
|
10
10
|
from .bcicomp import BCICompetitionIVDataset4
|
|
11
11
|
from .bids import BIDSDataset, BIDSEpochsDataset
|
|
12
12
|
from .chb_mit import CHBMIT
|
|
13
|
+
from .collate import pad_channels_collate
|
|
13
14
|
from .mne import create_from_mne_epochs, create_from_mne_raw
|
|
14
15
|
from .moabb import BNCI2014_001, HGD, MOABBDataset
|
|
15
16
|
from .nmt import NMT
|
|
@@ -42,4 +43,5 @@ __all__ = [
|
|
|
42
43
|
"SleepPhysionetChallenge2018",
|
|
43
44
|
"create_from_X_y",
|
|
44
45
|
"BCICompetitionIVDataset4",
|
|
46
|
+
"pad_channels_collate",
|
|
45
47
|
]
|
|
@@ -192,6 +192,31 @@ def _channel_info(mne_obj):
|
|
|
192
192
|
return n_ch, type_str, sfreq
|
|
193
193
|
|
|
194
194
|
|
|
195
|
+
def _compute_ch_pos(info, targets_from):
|
|
196
|
+
"""Return ``(n_ch, 3)`` float32 electrode positions aligned to ``X``'s rows.
|
|
197
|
+
|
|
198
|
+
Positions are the MNE head-frame coordinates ``info["chs"][i]["loc"][:3]``
|
|
199
|
+
(meters) -- the same representation braindecode models already consume (see
|
|
200
|
+
e.g. ``signal_jepa``/``REVE``). When ``targets_from != "metadata"`` the
|
|
201
|
+
window's misc channels are dropped from ``X`` in ``__getitem__``, so the
|
|
202
|
+
matching misc rows are dropped here too. Emits a one-time ``UserWarning`` if
|
|
203
|
+
no channel carries a real position (no montage set).
|
|
204
|
+
"""
|
|
205
|
+
pos = np.asarray([ch["loc"][:3] for ch in info["chs"]], dtype="float32")
|
|
206
|
+
if targets_from != "metadata":
|
|
207
|
+
misc_mask = np.asarray(info.get_channel_types()) == "misc"
|
|
208
|
+
pos = pos[~misc_mask]
|
|
209
|
+
has_pos = np.isfinite(pos).all(axis=1) & np.any(pos != 0, axis=1)
|
|
210
|
+
if pos.size and not has_pos.any():
|
|
211
|
+
warnings.warn(
|
|
212
|
+
"Returning channel positions but no montage is set: all positions "
|
|
213
|
+
"are zero/non-finite. Call ``raw.set_montage(...)`` (or set a "
|
|
214
|
+
"montage during preprocessing) before enabling ``return_ch_pos``.",
|
|
215
|
+
UserWarning,
|
|
216
|
+
)
|
|
217
|
+
return pos
|
|
218
|
+
|
|
219
|
+
|
|
195
220
|
def _window_info(crop_inds, sfreq):
|
|
196
221
|
"""Extract window size from crop indices.
|
|
197
222
|
|
|
@@ -448,6 +473,10 @@ class RecordDataset(Dataset[tuple[np.ndarray, int | str, tuple[int, int, int]]])
|
|
|
448
473
|
):
|
|
449
474
|
self._description = _create_description(description)
|
|
450
475
|
self.transform = transform
|
|
476
|
+
# Opt-in: when True, ``__getitem__`` appends channel positions (n_ch, 3).
|
|
477
|
+
# Default off keeps the public ``(X, y, crop_inds)`` contract intact.
|
|
478
|
+
self.return_ch_pos = False
|
|
479
|
+
self._ch_pos = None
|
|
451
480
|
|
|
452
481
|
@abstractmethod
|
|
453
482
|
def __len__(self) -> int:
|
|
@@ -750,6 +779,20 @@ class EEGWindowsDataset(_ZarrMixin, RecordDataset):
|
|
|
750
779
|
@raw.setter
|
|
751
780
|
def raw(self, value):
|
|
752
781
|
self._raw = value
|
|
782
|
+
self._ch_pos = None # invalidate cached positions
|
|
783
|
+
|
|
784
|
+
@property
|
|
785
|
+
def ch_pos(self):
|
|
786
|
+
"""Electrode positions ``(n_ch, 3)`` (x, y, z) aligned to ``X``'s channels.
|
|
787
|
+
|
|
788
|
+
Cached MNE head-frame coordinates in meters. Rows match the channels
|
|
789
|
+
returned by :meth:`__getitem__` (misc target channels excluded when
|
|
790
|
+
``targets_from="channels"``). All-zero/NaN when no montage is set.
|
|
791
|
+
"""
|
|
792
|
+
if self._ch_pos is None:
|
|
793
|
+
info = self._raw.info if self._raw is not None else self._make_mne_info()
|
|
794
|
+
self._ch_pos = _compute_ch_pos(info, self.targets_from)
|
|
795
|
+
return self._ch_pos
|
|
753
796
|
|
|
754
797
|
def __getitem__(self, index: int):
|
|
755
798
|
"""Get a window and its target.
|
|
@@ -793,6 +836,8 @@ class EEGWindowsDataset(_ZarrMixin, RecordDataset):
|
|
|
793
836
|
y = X[misc_mask, :]
|
|
794
837
|
y = y.copy()
|
|
795
838
|
X = X[~misc_mask, :]
|
|
839
|
+
if self.return_ch_pos:
|
|
840
|
+
return X, y, crop_inds, self.ch_pos
|
|
796
841
|
return X, y, crop_inds
|
|
797
842
|
|
|
798
843
|
def __len__(self):
|
|
@@ -1016,6 +1061,24 @@ class WindowsDataset(_ZarrMixin, RecordDataset):
|
|
|
1016
1061
|
@windows.setter
|
|
1017
1062
|
def windows(self, value):
|
|
1018
1063
|
self._windows = value
|
|
1064
|
+
self._ch_pos = None # invalidate cached positions
|
|
1065
|
+
|
|
1066
|
+
@property
|
|
1067
|
+
def ch_pos(self):
|
|
1068
|
+
"""Electrode positions ``(n_ch, 3)`` (x, y, z) aligned to ``X``'s channels.
|
|
1069
|
+
|
|
1070
|
+
Cached MNE head-frame coordinates in meters. Rows match the channels
|
|
1071
|
+
returned by :meth:`__getitem__` (misc target channels excluded when
|
|
1072
|
+
``targets_from="channels"``). All-zero/NaN when no montage is set.
|
|
1073
|
+
"""
|
|
1074
|
+
if self._ch_pos is None:
|
|
1075
|
+
info = (
|
|
1076
|
+
self._windows.info
|
|
1077
|
+
if self._windows is not None
|
|
1078
|
+
else self._make_mne_info()
|
|
1079
|
+
)
|
|
1080
|
+
self._ch_pos = _compute_ch_pos(info, self.targets_from)
|
|
1081
|
+
return self._ch_pos
|
|
1019
1082
|
|
|
1020
1083
|
@staticmethod
|
|
1021
1084
|
def _can_use_fast_get_epoch_from_raw(epochs: mne.BaseEpochs) -> bool:
|
|
@@ -1068,6 +1131,8 @@ class WindowsDataset(_ZarrMixin, RecordDataset):
|
|
|
1068
1131
|
# necessary to cast as list to get list of three tensors from batch,
|
|
1069
1132
|
# otherwise get single 2d-tensor...
|
|
1070
1133
|
crop_inds = self.crop_inds[index].tolist()
|
|
1134
|
+
if self.return_ch_pos:
|
|
1135
|
+
return X, y, crop_inds, self.ch_pos
|
|
1071
1136
|
return X, y, crop_inds
|
|
1072
1137
|
|
|
1073
1138
|
def __len__(self) -> int:
|
|
@@ -1458,6 +1523,50 @@ class BaseConcatDataset(ConcatDataset, HubDatasetMixin, Generic[T]):
|
|
|
1458
1523
|
)
|
|
1459
1524
|
return self
|
|
1460
1525
|
|
|
1526
|
+
def set_return_ch_pos(self, value: bool = True) -> "BaseConcatDataset":
|
|
1527
|
+
"""Toggle returning electrode positions from every subdataset.
|
|
1528
|
+
|
|
1529
|
+
When enabled, each windowed subdataset's ``__getitem__`` appends a
|
|
1530
|
+
``(n_ch, 3)`` array of electrode positions (x, y, z), so a batch yields
|
|
1531
|
+
``(X, y, crop_inds, ch_pos)``. Heterogeneous (variable-channel)
|
|
1532
|
+
collections additionally need
|
|
1533
|
+
:func:`braindecode.datasets.pad_channels_collate` as the DataLoader
|
|
1534
|
+
``collate_fn``. Default-off: leaves the ``(X, y, crop_inds)`` contract
|
|
1535
|
+
untouched.
|
|
1536
|
+
|
|
1537
|
+
Parameters
|
|
1538
|
+
----------
|
|
1539
|
+
value : bool
|
|
1540
|
+
Whether to return channel positions (default ``True``).
|
|
1541
|
+
|
|
1542
|
+
Returns
|
|
1543
|
+
-------
|
|
1544
|
+
self : BaseConcatDataset
|
|
1545
|
+
"""
|
|
1546
|
+
for ds in self.datasets:
|
|
1547
|
+
ds.return_ch_pos = value
|
|
1548
|
+
return self
|
|
1549
|
+
|
|
1550
|
+
@property
|
|
1551
|
+
def ch_pos(self):
|
|
1552
|
+
"""Electrode positions ``(n_ch, 3)`` from the first recording.
|
|
1553
|
+
|
|
1554
|
+
Convenience accessor mirroring how the repr reports channel info "from
|
|
1555
|
+
first recording". For per-sample positions in a heterogeneous
|
|
1556
|
+
collection, enable :meth:`set_return_ch_pos` and read them from the
|
|
1557
|
+
batch instead.
|
|
1558
|
+
"""
|
|
1559
|
+
if not self.datasets:
|
|
1560
|
+
raise ValueError("Empty BaseConcatDataset has no channel positions.")
|
|
1561
|
+
first = self.datasets[0]
|
|
1562
|
+
if not hasattr(first, "ch_pos"):
|
|
1563
|
+
raise AttributeError(
|
|
1564
|
+
f"{type(first).__name__} does not expose channel positions; "
|
|
1565
|
+
"ch_pos is available on windowed datasets (EEGWindowsDataset / "
|
|
1566
|
+
"WindowsDataset)."
|
|
1567
|
+
)
|
|
1568
|
+
return first.ch_pos
|
|
1569
|
+
|
|
1461
1570
|
def _outdated_save(self, path, overwrite=False):
|
|
1462
1571
|
"""This is a copy of the old saving function, that had inconsistent.
|
|
1463
1572
|
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""Collate functions for braindecode datasets.
|
|
2
|
+
|
|
3
|
+
:func:`pad_channels_collate` makes a :class:`~braindecode.datasets.BaseConcatDataset`
|
|
4
|
+
that mixes recordings with *different channel sets* (heterogeneous montages)
|
|
5
|
+
batchable: it pads every sample's channels to the batch maximum and emits a
|
|
6
|
+
boolean channel mask. Pair it with ``set_return_ch_pos(True)`` so each sample
|
|
7
|
+
carries its electrode positions -- channel identity is then encoded by the
|
|
8
|
+
positions, not by row index, which is exactly what position-aware models
|
|
9
|
+
(e.g. ``REVE``) consume.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
# Authors: The braindecode developers
|
|
13
|
+
#
|
|
14
|
+
# License: BSD (3-clause)
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import numpy as np
|
|
19
|
+
import torch
|
|
20
|
+
from torch.utils.data._utils.collate import default_collate
|
|
21
|
+
|
|
22
|
+
__all__ = ["pad_channels_collate"]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def pad_channels_collate(batch, pad_value: float = 0.0, pos_pad_value: float = 0.0):
|
|
26
|
+
"""Collate variable-channel windows by padding channels to the batch maximum.
|
|
27
|
+
|
|
28
|
+
Each item of ``batch`` is the tuple returned by a windowed dataset's
|
|
29
|
+
``__getitem__``: either ``(X, y, crop_inds)`` or, when
|
|
30
|
+
``return_ch_pos=True`` (see
|
|
31
|
+
:meth:`braindecode.datasets.BaseConcatDataset.set_return_ch_pos`),
|
|
32
|
+
``(X, y, crop_inds, ch_pos)``. Signals with different numbers of channels
|
|
33
|
+
are zero-padded along the channel axis to ``max_ch`` (the largest channel
|
|
34
|
+
count in the batch) so they can be stacked into a single tensor, and a
|
|
35
|
+
boolean ``ch_mask`` marks the real (non-padded) channels.
|
|
36
|
+
|
|
37
|
+
The time dimension is assumed uniform (fixed-length windows); a
|
|
38
|
+
:class:`ValueError` is raised otherwise.
|
|
39
|
+
|
|
40
|
+
This makes a heterogeneous collection **batchable**. *Consuming* the result
|
|
41
|
+
(so a model ignores padded channels) requires a position/channel-aware
|
|
42
|
+
model; fixed-geometry models (e.g. ``ShallowFBCSPNet``) structurally need a
|
|
43
|
+
constant channel count and cannot use variable batches.
|
|
44
|
+
|
|
45
|
+
Parameters
|
|
46
|
+
----------
|
|
47
|
+
batch : list of tuple
|
|
48
|
+
Samples from a windowed dataset (see above).
|
|
49
|
+
pad_value : float
|
|
50
|
+
Value used to pad the signal ``X`` channel rows (default ``0.0``).
|
|
51
|
+
pos_pad_value : float
|
|
52
|
+
Value used to pad the position ``ch_pos`` rows (default ``0.0``).
|
|
53
|
+
|
|
54
|
+
Returns
|
|
55
|
+
-------
|
|
56
|
+
X : torch.Tensor
|
|
57
|
+
Padded signals, shape ``(batch, max_ch, n_times)``.
|
|
58
|
+
y : torch.Tensor
|
|
59
|
+
Targets, collated with ``default_collate``.
|
|
60
|
+
crop_inds : list
|
|
61
|
+
Crop indices, collated with ``default_collate``.
|
|
62
|
+
ch_pos : torch.Tensor
|
|
63
|
+
Only when the samples include positions. Padded positions, shape
|
|
64
|
+
``(batch, max_ch, 3)``.
|
|
65
|
+
ch_mask : torch.Tensor
|
|
66
|
+
Boolean mask, shape ``(batch, max_ch)``; ``True`` for real channels,
|
|
67
|
+
``False`` for padding.
|
|
68
|
+
"""
|
|
69
|
+
if len(batch) == 0:
|
|
70
|
+
raise ValueError("pad_channels_collate received an empty batch.")
|
|
71
|
+
|
|
72
|
+
has_pos = len(batch[0]) >= 4
|
|
73
|
+
Xs = [np.asarray(item[0]) for item in batch]
|
|
74
|
+
|
|
75
|
+
n_times = Xs[0].shape[1]
|
|
76
|
+
if any(x.shape[1] != n_times for x in Xs):
|
|
77
|
+
raise ValueError(
|
|
78
|
+
"pad_channels_collate only pads the channel axis; all windows must "
|
|
79
|
+
f"share the same number of time samples, got {sorted({x.shape[1] for x in Xs})}."
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
bsz = len(batch)
|
|
83
|
+
max_ch = max(x.shape[0] for x in Xs)
|
|
84
|
+
|
|
85
|
+
X_out = torch.full((bsz, max_ch, n_times), pad_value, dtype=torch.float32)
|
|
86
|
+
ch_mask = torch.zeros((bsz, max_ch), dtype=torch.bool)
|
|
87
|
+
pos_out = (
|
|
88
|
+
torch.full((bsz, max_ch, 3), pos_pad_value, dtype=torch.float32)
|
|
89
|
+
if has_pos
|
|
90
|
+
else None
|
|
91
|
+
)
|
|
92
|
+
for i, (item, x) in enumerate(zip(batch, Xs)):
|
|
93
|
+
c = x.shape[0]
|
|
94
|
+
X_out[i, :c] = torch.as_tensor(x, dtype=torch.float32)
|
|
95
|
+
ch_mask[i, :c] = True
|
|
96
|
+
if pos_out is not None:
|
|
97
|
+
pos_out[i, :c] = torch.as_tensor(np.asarray(item[3]), dtype=torch.float32)
|
|
98
|
+
|
|
99
|
+
# y and crop_inds carry no channel axis -> standard collation.
|
|
100
|
+
y = default_collate([item[1] for item in batch])
|
|
101
|
+
crop_inds = default_collate([item[2] for item in batch])
|
|
102
|
+
|
|
103
|
+
if pos_out is not None:
|
|
104
|
+
return X_out, y, crop_inds, pos_out, ch_mask
|
|
105
|
+
return X_out, y, crop_inds, ch_mask
|
|
@@ -134,7 +134,14 @@ class _EEGNeuralNet(NeuralNet, abc.ABC):
|
|
|
134
134
|
i_window_in_trials = []
|
|
135
135
|
i_window_stops = []
|
|
136
136
|
window_ys = []
|
|
137
|
-
for
|
|
137
|
+
for batch in self.get_iterator(dataset, drop_index=False):
|
|
138
|
+
if len(batch) > 3:
|
|
139
|
+
raise ValueError(
|
|
140
|
+
"Cropped prediction does not support channel positions; "
|
|
141
|
+
"disable return_ch_pos (set_return_ch_pos(False)) for cropped "
|
|
142
|
+
"evaluation."
|
|
143
|
+
)
|
|
144
|
+
X, y, i = batch[0], batch[1], batch[2]
|
|
138
145
|
i_window_in_trials.append(i[0].cpu().numpy())
|
|
139
146
|
i_window_stops.append(i[2].cpu().numpy())
|
|
140
147
|
with torch.no_grad():
|
|
@@ -5,6 +5,7 @@ from .functions import (
|
|
|
5
5
|
identity,
|
|
6
6
|
plv_time,
|
|
7
7
|
safe_log,
|
|
8
|
+
sinusoidal_positional_encoding,
|
|
8
9
|
square,
|
|
9
10
|
)
|
|
10
11
|
from .initialization import glorot_weight_zero_bias, rescale_parameter
|
|
@@ -16,6 +17,7 @@ __all__ = [
|
|
|
16
17
|
"identity",
|
|
17
18
|
"plv_time",
|
|
18
19
|
"safe_log",
|
|
20
|
+
"sinusoidal_positional_encoding",
|
|
19
21
|
"square",
|
|
20
22
|
"glorot_weight_zero_bias",
|
|
21
23
|
"rescale_parameter",
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
#
|
|
3
3
|
# License: BSD (3-clause)
|
|
4
4
|
|
|
5
|
+
import math
|
|
6
|
+
|
|
5
7
|
import torch
|
|
6
8
|
import torch.nn.functional as F
|
|
7
9
|
|
|
@@ -249,3 +251,40 @@ def plv_time(x, forward_fourier=True, epsilon: float = 1e-6):
|
|
|
249
251
|
)
|
|
250
252
|
|
|
251
253
|
return plv_matrix
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def sinusoidal_positional_encoding(n_positions: int, dim: int) -> torch.Tensor:
|
|
257
|
+
r"""Fixed sine/cosine positional-encoding table of shape ``(n_positions, dim)``.
|
|
258
|
+
|
|
259
|
+
The standard encoding of Vaswani et al. (2017): for position :math:`p` and
|
|
260
|
+
channel :math:`i`, :math:`pe[p, 2i] = \sin(p / 10000^{2i/d})` and
|
|
261
|
+
:math:`pe[p, 2i+1] = \cos(p / 10000^{2i/d})`. PyTorch ships no sinusoidal
|
|
262
|
+
encoding (``nn.Embedding`` is a *learned* lookup), so braindecode models that
|
|
263
|
+
need one share this primitive instead of re-deriving it. An odd ``dim`` is
|
|
264
|
+
computed on the next even width and truncated, reproducing the per-model
|
|
265
|
+
wrappers (e.g. :class:`~braindecode.models.medformer` odd-``d_model``).
|
|
266
|
+
|
|
267
|
+
Parameters
|
|
268
|
+
----------
|
|
269
|
+
n_positions : int
|
|
270
|
+
Number of positions (sequence length) to encode.
|
|
271
|
+
dim : int
|
|
272
|
+
Embedding dimension of each position.
|
|
273
|
+
|
|
274
|
+
Returns
|
|
275
|
+
-------
|
|
276
|
+
torch.Tensor
|
|
277
|
+
``(n_positions, dim)`` float table; callers add their own batch axis,
|
|
278
|
+
dropout, or offset.
|
|
279
|
+
"""
|
|
280
|
+
dim_even = dim + (dim % 2)
|
|
281
|
+
position = torch.arange(n_positions).unsqueeze(1).float()
|
|
282
|
+
div_term = torch.exp(
|
|
283
|
+
torch.arange(0, dim_even, 2).float() * (-math.log(10000.0) / dim_even)
|
|
284
|
+
)
|
|
285
|
+
pe = torch.zeros(n_positions, dim_even)
|
|
286
|
+
pe[:, 0::2] = torch.sin(position * div_term)
|
|
287
|
+
pe[:, 1::2] = torch.cos(position * div_term)
|
|
288
|
+
# ``.contiguous()`` so an odd-``dim`` truncation owns tight storage -- a
|
|
289
|
+
# non-contiguous view over the padded width breaks safetensors buffer saving.
|
|
290
|
+
return pe[:, :dim].contiguous()
|
|
@@ -66,6 +66,7 @@ from .util import (
|
|
|
66
66
|
build_model_config,
|
|
67
67
|
extract_channel_locations_from_chs_info,
|
|
68
68
|
models_mandatory_parameters,
|
|
69
|
+
positions_from_chs_info,
|
|
69
70
|
)
|
|
70
71
|
|
|
71
72
|
# Call this last in order to make sure the dataset list is populated with
|
|
@@ -115,6 +116,7 @@ __all__ = [
|
|
|
115
116
|
"Labram",
|
|
116
117
|
"LUNA",
|
|
117
118
|
"extract_channel_locations_from_chs_info",
|
|
119
|
+
"positions_from_chs_info",
|
|
118
120
|
"MEDFormer",
|
|
119
121
|
"MSVTNet",
|
|
120
122
|
"PBT",
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import math
|
|
2
1
|
from warnings import warn
|
|
3
2
|
|
|
4
3
|
import numpy as np
|
|
@@ -6,6 +5,7 @@ import torch
|
|
|
6
5
|
import torch.nn as nn
|
|
7
6
|
from linear_attention_transformer import LinearAttentionTransformer
|
|
8
7
|
|
|
8
|
+
from braindecode.functional import sinusoidal_positional_encoding
|
|
9
9
|
from braindecode.models.base import EEGModuleMixin
|
|
10
10
|
|
|
11
11
|
# -----------------------------------------------------------------------------
|
|
@@ -388,15 +388,8 @@ class _PositionalEncoding(nn.Module):
|
|
|
388
388
|
def __init__(self, emb_size: int, drop_prob: float = 0.1, max_len: int = 1000):
|
|
389
389
|
super(_PositionalEncoding, self).__init__()
|
|
390
390
|
|
|
391
|
-
# Compute the positional encodings once
|
|
392
|
-
pe =
|
|
393
|
-
position = torch.arange(0, max_len).unsqueeze(1).float()
|
|
394
|
-
div_term = torch.exp(
|
|
395
|
-
torch.arange(0, emb_size, 2).float() * -(math.log(10000.0) / emb_size)
|
|
396
|
-
)
|
|
397
|
-
pe[:, 0::2] = torch.sin(position * div_term)
|
|
398
|
-
pe[:, 1::2] = torch.cos(position * div_term)
|
|
399
|
-
pe = pe.unsqueeze(0)
|
|
391
|
+
# Compute the positional encodings once (shared sinusoidal primitive).
|
|
392
|
+
pe = sinusoidal_positional_encoding(max_len, emb_size).unsqueeze(0)
|
|
400
393
|
self.register_buffer("pe", pe)
|
|
401
394
|
self.dropout = nn.Dropout(p=drop_prob)
|
|
402
395
|
|