Braindecode 1.6.1__tar.gz → 1.6.1.dev1034__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/braindecode.egg-info → braindecode-1.6.1.dev1034}/PKG-INFO +2 -2
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/augmentation/base.py +19 -67
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/augmentation/functional.py +30 -44
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/__init__.py +0 -2
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/base.py +0 -109
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/bids/hub.py +1 -41
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/moabb.py +10 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/eegneuralnet.py +1 -49
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/functional/__init__.py +0 -8
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/functional/functions.py +0 -159
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/__init__.py +2 -11
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/atcnet.py +1 -118
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/attn_sleep.py +10 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/biot.py +10 -3
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/brainmodule.py +54 -185
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/eegitnet.py +12 -33
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/eegnet.py +10 -1
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/eegsym.py +96 -72
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/eegtcnet.py +27 -62
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/fbmsnet.py +5 -18
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/medformer.py +22 -4
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/msvtnet.py +3 -7
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/sinc_shallow.py +2 -2
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/sstdpn.py +4 -10
- braindecode-1.6.1.dev1034/braindecode/models/summary.csv +58 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/tsinception.py +11 -1
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/util.py +2 -50
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/modules/__init__.py +2 -8
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/modules/activation.py +0 -34
- braindecode-1.6.1.dev1034/braindecode/modules/blocks.py +160 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/modules/filter.py +19 -80
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/modules/layers.py +0 -126
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/preprocessing/mne_preprocess.py +8 -152
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/training/scoring.py +1 -8
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/util.py +1 -36
- braindecode-1.6.1.dev1034/braindecode/version.py +1 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034/braindecode.egg-info}/PKG-INFO +2 -2
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode.egg-info/SOURCES.txt +0 -5
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode.egg-info/requires.txt +1 -1
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/api.rst +0 -10
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/conf.py +0 -14
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/index.rst +4 -5
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/models/models_table.rst +3 -8
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/whats_new.rst +3 -192
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/pyproject.toml +1 -7
- braindecode-1.6.1/braindecode/datasets/collate.py +0 -105
- braindecode-1.6.1/braindecode/models/eegdino.py +0 -533
- braindecode-1.6.1/braindecode/models/mvpformer.py +0 -750
- braindecode-1.6.1/braindecode/models/steegformer.py +0 -654
- braindecode-1.6.1/braindecode/models/summary.csv +0 -62
- braindecode-1.6.1/braindecode/models/tcformer.py +0 -643
- braindecode-1.6.1/braindecode/modules/blocks.py +0 -317
- braindecode-1.6.1/braindecode/version.py +0 -1
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/LICENSE.txt +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/MANIFEST.in +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/NOTICE.txt +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/README.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/__init__.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/augmentation/__init__.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/augmentation/transforms.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/classifier.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/bbci.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/bcicomp.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/bids/__init__.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/bids/datasets.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/bids/format.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/bids/hub_format.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/bids/hub_io.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/bids/hub_validation.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/bids/iterable.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/chb_mit.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/mne.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/nmt.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/registry.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/siena.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/sleep_physionet.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/tuh.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/utils.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datasets/xy.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datautil/__init__.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datautil/channel_utils.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datautil/hub_formats.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datautil/serialization.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/datautil/util.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/functional/initialization.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/attentionbasenet.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/base.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/bendr.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/cbramod.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/codebrain.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/config.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/contrawr.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/ctnet.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/deep4.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/deepsleepnet.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/dgcnn.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/eegconformer.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/eeginception_erp.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/eeginception_mi.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/eegminer.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/eegnex.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/eegpt.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/eegsimpleconv.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/emg2qwerty.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/fbcnet.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/fblightconvnet.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/hybrid.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/ifnet.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/interpolated.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/labram.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/luna.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/meta_neuromotor.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/patchedtransformer.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/reve.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/sccnet.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/shallow_fbcsp.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/signal_jepa.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/sparcnet.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/syncnet.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/tcn.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/tidnet.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/models/usleep.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/modules/attention.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/modules/convolution.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/modules/interpolation.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/modules/linear.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/modules/parametrization.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/modules/stats.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/modules/util.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/modules/wrapper.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/preprocessing/__init__.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/preprocessing/preprocess.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/preprocessing/util.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/preprocessing/windowers.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/regressor.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/samplers/__init__.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/samplers/base.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/samplers/ssl.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/training/__init__.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/training/callbacks.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/training/losses.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/visualization/__init__.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/visualization/attribution.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/visualization/confusion_matrices.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/visualization/frequency.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/visualization/metrics.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/visualization/sanity.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode/visualization/topology.py +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode.egg-info/dependency_links.txt +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/braindecode.egg-info/top_level.txt +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/Makefile +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/_templates/autosummary/class.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/_templates/autosummary/function.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/cite.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/help.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/install/install.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/install/install_pip.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/install/install_source.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/models/categorization/attention.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/models/categorization/channel.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/models/categorization/convolution.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/models/categorization/filterbank.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/models/categorization/gnn.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/models/categorization/interpretable.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/models/categorization/lbm.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/models/categorization/recurrent.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/models/categorization/spd.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/models/models.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/models/models_categorization.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/models/models_visualization.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/docs/sg_execution_times.rst +0 -0
- {braindecode-1.6.1 → braindecode-1.6.1.dev1034}/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.dev1034
|
|
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>
|
|
@@ -46,7 +46,7 @@ Requires-Dist: zarr>=3.0; extra == "hub"
|
|
|
46
46
|
Provides-Extra: viz
|
|
47
47
|
Requires-Dist: captum>=0.7.0; extra == "viz"
|
|
48
48
|
Provides-Extra: tests
|
|
49
|
-
Requires-Dist: pytest
|
|
49
|
+
Requires-Dist: pytest; extra == "tests"
|
|
50
50
|
Requires-Dist: pytest-cov; extra == "tests"
|
|
51
51
|
Requires-Dist: codecov; extra == "tests"
|
|
52
52
|
Requires-Dist: pytest_cases; extra == "tests"
|
|
@@ -105,15 +105,7 @@ class Transform(torch.nn.Module):
|
|
|
105
105
|
mask = self._get_mask(out_X.shape[0], out_X.device)
|
|
106
106
|
num_valid = mask.sum().long()
|
|
107
107
|
|
|
108
|
-
if num_valid
|
|
109
|
-
# Fast path: every sample is augmented (e.g. ``probability=1.0``,
|
|
110
|
-
# the common case). Operate on the whole batch and skip the boolean
|
|
111
|
-
# gather/scatter (``out_X[mask]`` then ``out_X[mask] = ...``), which
|
|
112
|
-
# would otherwise copy the batch twice.
|
|
113
|
-
out_X, out_y = self.operation(
|
|
114
|
-
out_X, out_y, **self.get_augmentation_params(out_X, out_y)
|
|
115
|
-
)
|
|
116
|
-
elif num_valid > 0:
|
|
108
|
+
if num_valid > 0:
|
|
117
109
|
# Uses the mask to define the output
|
|
118
110
|
out_X[mask, ...], tr_y = self.operation(
|
|
119
111
|
out_X[mask, ...],
|
|
@@ -176,47 +168,23 @@ class Compose(Transform):
|
|
|
176
168
|
return X, y
|
|
177
169
|
|
|
178
170
|
|
|
179
|
-
|
|
180
|
-
"""
|
|
181
|
-
|
|
182
|
-
A picklable callable (so it works with ``num_workers > 0``, unlike a
|
|
183
|
-
closure) that collates the batch once and then either augments it in place
|
|
184
|
-
or grows it.
|
|
171
|
+
def _make_collateable(transform, device=None):
|
|
172
|
+
"""Wraps a transform to make it collateable.
|
|
185
173
|
|
|
186
|
-
|
|
187
|
-
----------
|
|
188
|
-
transform : Transform
|
|
189
|
-
Transform applied to the collated ``(X, y)``.
|
|
190
|
-
device : str | torch.device | None, optional
|
|
191
|
-
Device the batch is moved to before transforming. Defaults to None.
|
|
192
|
-
n_augmentation : int, optional
|
|
193
|
-
``0`` (default) applies the transform in place (batch size unchanged).
|
|
194
|
-
``> 0`` keeps the clean originals and appends ``n_augmentation``
|
|
195
|
-
independently transformed copies, returning ``(X, y)`` of
|
|
196
|
-
``(1 + n_augmentation)`` times the original size.
|
|
174
|
+
with device control.
|
|
197
175
|
"""
|
|
198
176
|
|
|
199
|
-
def
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
if self.n_augmentation == 0:
|
|
211
|
-
return (*self.transform(X, y), *collated[2:])
|
|
212
|
-
# Fixed expansion: keep the clean originals, then append
|
|
213
|
-
# ``n_augmentation`` independently transformed copies.
|
|
214
|
-
xs, ys = [X], [y]
|
|
215
|
-
for _ in range(self.n_augmentation):
|
|
216
|
-
aug_X, aug_y = self.transform(X, y)
|
|
217
|
-
xs.append(aug_X)
|
|
218
|
-
ys.append(aug_y)
|
|
219
|
-
return torch.cat(xs), torch.cat(ys)
|
|
177
|
+
def _collate_fn(batch):
|
|
178
|
+
collated_batch = default_collate(batch)
|
|
179
|
+
X, y = collated_batch[:2]
|
|
180
|
+
|
|
181
|
+
if device is not None:
|
|
182
|
+
X = X.to(device)
|
|
183
|
+
y = y.to(device)
|
|
184
|
+
|
|
185
|
+
return (*transform(X, y), *collated_batch[2:])
|
|
186
|
+
|
|
187
|
+
return _collate_fn
|
|
220
188
|
|
|
221
189
|
|
|
222
190
|
class AugmentedDataLoader(DataLoader):
|
|
@@ -230,44 +198,28 @@ class AugmentedDataLoader(DataLoader):
|
|
|
230
198
|
Transform or sequence of Transform to be applied to each batch.
|
|
231
199
|
device : str | torch.device | None, optional
|
|
232
200
|
Device on which to transform the data. Defaults to None.
|
|
233
|
-
n_augmentation : int, optional
|
|
234
|
-
Number of augmented copies to append to each batch (fixed expansion).
|
|
235
|
-
When ``0`` (default) the transforms are applied in place and the batch
|
|
236
|
-
keeps its size (stochastic-per-epoch augmentation, backwards-compatible).
|
|
237
|
-
When ``> 0`` each batch becomes ``(1 + n_augmentation)`` times larger:
|
|
238
|
-
the clean originals are kept and ``n_augmentation`` independently
|
|
239
|
-
transformed copies are appended. This expresses augmentations defined as
|
|
240
|
-
a fixed set-expansion (e.g. the EEG-Inception MI 6x training set,
|
|
241
|
-
``n_augmentation=5``). In this mode batches are returned as ``(X, y)``.
|
|
242
201
|
**kwargs : dict, optional
|
|
243
202
|
keyword arguments to pass to standard DataLoader class.
|
|
244
203
|
"""
|
|
245
204
|
|
|
246
|
-
def __init__(
|
|
247
|
-
self, dataset, transforms=None, device=None, n_augmentation=0, **kwargs
|
|
248
|
-
):
|
|
205
|
+
def __init__(self, dataset, transforms=None, device=None, **kwargs):
|
|
249
206
|
if "collate_fn" in kwargs:
|
|
250
207
|
raise ValueError(
|
|
251
208
|
"collate_fn cannot be used in this context because it is used "
|
|
252
209
|
"to pass transform"
|
|
253
210
|
)
|
|
254
|
-
if n_augmentation < 0:
|
|
255
|
-
raise ValueError("n_augmentation must be a non-negative integer.")
|
|
256
211
|
if transforms is None or (
|
|
257
212
|
isinstance(transforms, list) and len(transforms) == 0
|
|
258
213
|
):
|
|
259
|
-
|
|
214
|
+
self.collated_tr = _make_collateable(IdentityTransform(), device=device)
|
|
260
215
|
elif isinstance(transforms, (Transform, nn.Module)):
|
|
261
|
-
|
|
216
|
+
self.collated_tr = _make_collateable(transforms, device=device)
|
|
262
217
|
elif isinstance(transforms, list):
|
|
263
|
-
|
|
218
|
+
self.collated_tr = _make_collateable(Compose(transforms), device=device)
|
|
264
219
|
else:
|
|
265
220
|
raise TypeError(
|
|
266
221
|
"transforms can be either a Transform object "
|
|
267
222
|
"or a list of Transform objects."
|
|
268
223
|
)
|
|
269
224
|
|
|
270
|
-
self.collated_tr = _AugmentationCollate(
|
|
271
|
-
transform, device=device, n_augmentation=n_augmentation
|
|
272
|
-
)
|
|
273
225
|
super().__init__(dataset, collate_fn=self.collated_tr, **kwargs)
|
|
@@ -18,7 +18,7 @@ from mne.filter import notch_filter
|
|
|
18
18
|
from scipy.interpolate import Rbf
|
|
19
19
|
from sklearn.utils import check_random_state
|
|
20
20
|
from torch.fft import fft, ifft
|
|
21
|
-
from torch.nn.functional import pad
|
|
21
|
+
from torch.nn.functional import one_hot, pad
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
def identity(X: torch.Tensor, y: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor]:
|
|
@@ -253,34 +253,25 @@ def channels_dropout(
|
|
|
253
253
|
return X * mask.unsqueeze(-1), y
|
|
254
254
|
|
|
255
255
|
|
|
256
|
-
def
|
|
256
|
+
def _make_permutation_matrix(
|
|
257
257
|
X: torch.Tensor, mask: torch.Tensor, random_state: int | np.random.Generator | None
|
|
258
258
|
) -> torch.Tensor:
|
|
259
|
-
"""Per-sample channel permutation that shuffles only the masked channels.
|
|
260
|
-
|
|
261
|
-
Returns a ``(batch, n_channels)`` index permutation: output channel ``i`` is
|
|
262
|
-
taken from input channel ``perm[b, i]``. Masked channels are permuted among
|
|
263
|
-
their own positions; unmasked channels keep their place.
|
|
264
|
-
|
|
265
|
-
The per-sample ``rng.permutation`` is kept (rather than a vectorized random
|
|
266
|
-
draw) so the output is bit-for-bit identical to the previous one-hot/matmul
|
|
267
|
-
implementation — vectorizing the draw would change seeded results. The win
|
|
268
|
-
is downstream: the caller gathers with this index instead of building
|
|
269
|
-
``(batch, n_channels, n_channels)`` one-hot matrices and a matmul.
|
|
270
|
-
"""
|
|
271
259
|
rng = check_random_state(random_state)
|
|
272
260
|
batch_size, n_channels, _ = X.shape
|
|
273
|
-
hard_mask = mask.round()
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
261
|
+
hard_mask = mask.round()
|
|
262
|
+
batch_permutations = torch.empty(
|
|
263
|
+
batch_size, n_channels, n_channels, device=X.device
|
|
264
|
+
)
|
|
265
|
+
for b, mask in enumerate(hard_mask):
|
|
266
|
+
channels_to_shuffle = torch.arange(n_channels, device=X.device)
|
|
267
|
+
channels_to_shuffle = channels_to_shuffle[mask.bool()]
|
|
268
|
+
reordered_channels = torch.tensor(
|
|
269
|
+
rng.permutation(channels_to_shuffle.cpu()), device=X.device
|
|
282
270
|
)
|
|
283
|
-
|
|
271
|
+
channels_permutation = torch.arange(n_channels, device=X.device)
|
|
272
|
+
channels_permutation[channels_to_shuffle] = reordered_channels
|
|
273
|
+
batch_permutations[b, ...] = one_hot(channels_permutation)
|
|
274
|
+
return batch_permutations
|
|
284
275
|
|
|
285
276
|
|
|
286
277
|
def channels_shuffle(
|
|
@@ -323,11 +314,8 @@ def channels_shuffle(
|
|
|
323
314
|
if p_shuffle == 0:
|
|
324
315
|
return X, y
|
|
325
316
|
mask = _pick_channels_randomly(X, 1 - p_shuffle, random_state)
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
# one-hot permutation matrices and a (batch, C, C) @ (batch, C, T) matmul.
|
|
329
|
-
perm = perm.unsqueeze(-1).expand(-1, -1, X.shape[-1])
|
|
330
|
-
return torch.gather(X, 1, perm), y
|
|
317
|
+
batch_permutations = _make_permutation_matrix(X, mask, random_state)
|
|
318
|
+
return torch.matmul(batch_permutations, X), y
|
|
331
319
|
|
|
332
320
|
|
|
333
321
|
def gaussian_noise(
|
|
@@ -1200,21 +1188,19 @@ def mask_encoding(
|
|
|
1200
1188
|
32 (2024): 875-886.
|
|
1201
1189
|
"""
|
|
1202
1190
|
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
)
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
return X.masked_fill(time_mask.unsqueeze(1), 0), y
|
|
1191
|
+
batch_indices = torch.arange(X.shape[0]).repeat_interleave(n_segments)
|
|
1192
|
+
start_indices = time_start.flatten()
|
|
1193
|
+
mask_indices = start_indices[:, None] + torch.arange(segment_length)
|
|
1194
|
+
|
|
1195
|
+
# Create a boolean mask with the same shape as X
|
|
1196
|
+
mask = torch.zeros_like(X, dtype=torch.bool)
|
|
1197
|
+
for batch_index, grouped_mask_indices in zip(batch_indices, mask_indices):
|
|
1198
|
+
mask[batch_index, :, grouped_mask_indices] = True
|
|
1199
|
+
|
|
1200
|
+
# Apply the mask to set the values to 0
|
|
1201
|
+
X[mask] = 0
|
|
1202
|
+
|
|
1203
|
+
return X, y # Return the masked tensor and labels
|
|
1218
1204
|
|
|
1219
1205
|
|
|
1220
1206
|
def channels_rereference(
|
|
@@ -10,7 +10,6 @@ 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
|
|
14
13
|
from .mne import create_from_mne_epochs, create_from_mne_raw
|
|
15
14
|
from .moabb import BNCI2014_001, HGD, MOABBDataset
|
|
16
15
|
from .nmt import NMT
|
|
@@ -43,5 +42,4 @@ __all__ = [
|
|
|
43
42
|
"SleepPhysionetChallenge2018",
|
|
44
43
|
"create_from_X_y",
|
|
45
44
|
"BCICompetitionIVDataset4",
|
|
46
|
-
"pad_channels_collate",
|
|
47
45
|
]
|
|
@@ -192,31 +192,6 @@ 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
|
-
|
|
220
195
|
def _window_info(crop_inds, sfreq):
|
|
221
196
|
"""Extract window size from crop indices.
|
|
222
197
|
|
|
@@ -473,10 +448,6 @@ class RecordDataset(Dataset[tuple[np.ndarray, int | str, tuple[int, int, int]]])
|
|
|
473
448
|
):
|
|
474
449
|
self._description = _create_description(description)
|
|
475
450
|
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
|
|
480
451
|
|
|
481
452
|
@abstractmethod
|
|
482
453
|
def __len__(self) -> int:
|
|
@@ -779,20 +750,6 @@ class EEGWindowsDataset(_ZarrMixin, RecordDataset):
|
|
|
779
750
|
@raw.setter
|
|
780
751
|
def raw(self, value):
|
|
781
752
|
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
|
|
796
753
|
|
|
797
754
|
def __getitem__(self, index: int):
|
|
798
755
|
"""Get a window and its target.
|
|
@@ -836,8 +793,6 @@ class EEGWindowsDataset(_ZarrMixin, RecordDataset):
|
|
|
836
793
|
y = X[misc_mask, :]
|
|
837
794
|
y = y.copy()
|
|
838
795
|
X = X[~misc_mask, :]
|
|
839
|
-
if self.return_ch_pos:
|
|
840
|
-
return X, y, crop_inds, self.ch_pos
|
|
841
796
|
return X, y, crop_inds
|
|
842
797
|
|
|
843
798
|
def __len__(self):
|
|
@@ -1061,24 +1016,6 @@ class WindowsDataset(_ZarrMixin, RecordDataset):
|
|
|
1061
1016
|
@windows.setter
|
|
1062
1017
|
def windows(self, value):
|
|
1063
1018
|
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
|
|
1082
1019
|
|
|
1083
1020
|
@staticmethod
|
|
1084
1021
|
def _can_use_fast_get_epoch_from_raw(epochs: mne.BaseEpochs) -> bool:
|
|
@@ -1131,8 +1068,6 @@ class WindowsDataset(_ZarrMixin, RecordDataset):
|
|
|
1131
1068
|
# necessary to cast as list to get list of three tensors from batch,
|
|
1132
1069
|
# otherwise get single 2d-tensor...
|
|
1133
1070
|
crop_inds = self.crop_inds[index].tolist()
|
|
1134
|
-
if self.return_ch_pos:
|
|
1135
|
-
return X, y, crop_inds, self.ch_pos
|
|
1136
1071
|
return X, y, crop_inds
|
|
1137
1072
|
|
|
1138
1073
|
def __len__(self) -> int:
|
|
@@ -1523,50 +1458,6 @@ class BaseConcatDataset(ConcatDataset, HubDatasetMixin, Generic[T]):
|
|
|
1523
1458
|
)
|
|
1524
1459
|
return self
|
|
1525
1460
|
|
|
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
|
-
|
|
1570
1461
|
def _outdated_save(self, path, overwrite=False):
|
|
1571
1462
|
"""This is a copy of the old saving function, that had inconsistent.
|
|
1572
1463
|
|
|
@@ -327,7 +327,6 @@ class HubDatasetMixin:
|
|
|
327
327
|
|
|
328
328
|
n_recordings = len(self.datasets)
|
|
329
329
|
first_ds = self.datasets[0]
|
|
330
|
-
descriptions = [ds.description for ds in self.datasets]
|
|
331
330
|
|
|
332
331
|
# Get dataset-specific info based on type using registry
|
|
333
332
|
dataset_type = get_dataset_type(first_ds)
|
|
@@ -359,9 +358,6 @@ class HubDatasetMixin:
|
|
|
359
358
|
raise TypeError(f"Unsupported dataset type: {dataset_type}")
|
|
360
359
|
|
|
361
360
|
# Create README content and save
|
|
362
|
-
license_value, license_needs_update = _infer_license_from_descriptions(
|
|
363
|
-
descriptions
|
|
364
|
-
)
|
|
365
361
|
readme_content = _generate_readme_content(
|
|
366
362
|
format_info=format_info,
|
|
367
363
|
n_recordings=n_recordings,
|
|
@@ -370,8 +366,6 @@ class HubDatasetMixin:
|
|
|
370
366
|
data_type=data_type,
|
|
371
367
|
n_windows=n_windows,
|
|
372
368
|
total_duration=total_duration,
|
|
373
|
-
license=license_value,
|
|
374
|
-
license_needs_update=license_needs_update,
|
|
375
369
|
)
|
|
376
370
|
|
|
377
371
|
# Save README
|
|
@@ -973,8 +967,6 @@ def _generate_readme_content(
|
|
|
973
967
|
n_windows: int,
|
|
974
968
|
total_duration: float | None = None,
|
|
975
969
|
format: str = "zarr",
|
|
976
|
-
license: str = "please-specify",
|
|
977
|
-
license_needs_update: bool = True,
|
|
978
970
|
):
|
|
979
971
|
"""Generate README.md content for a dataset uploaded to the Hub.
|
|
980
972
|
|
|
@@ -996,10 +988,6 @@ def _generate_readme_content(
|
|
|
996
988
|
Total duration in seconds across all recordings.
|
|
997
989
|
format : str
|
|
998
990
|
Storage format (default: "zarr").
|
|
999
|
-
license : str
|
|
1000
|
-
Dataset license string to write in YAML front matter.
|
|
1001
|
-
license_needs_update : bool
|
|
1002
|
-
Whether to append a reminder comment next to the license field.
|
|
1003
991
|
|
|
1004
992
|
Returns
|
|
1005
993
|
-------
|
|
@@ -1015,10 +1003,6 @@ def _generate_readme_content(
|
|
|
1015
1003
|
str(timedelta(seconds=int(total_duration))) if total_duration else "N/A"
|
|
1016
1004
|
)
|
|
1017
1005
|
|
|
1018
|
-
license_line = f"license: {license}"
|
|
1019
|
-
if license_needs_update:
|
|
1020
|
-
license_line += " # Please update this field to reflect your dataset's license"
|
|
1021
|
-
|
|
1022
1006
|
return f"""---
|
|
1023
1007
|
tags:
|
|
1024
1008
|
- braindecode
|
|
@@ -1026,7 +1010,7 @@ tags:
|
|
|
1026
1010
|
- neuroscience
|
|
1027
1011
|
- brain-computer-interface
|
|
1028
1012
|
- deep-learning
|
|
1029
|
-
|
|
1013
|
+
license: unknown
|
|
1030
1014
|
---
|
|
1031
1015
|
|
|
1032
1016
|
# EEG Dataset
|
|
@@ -1122,27 +1106,3 @@ if hasattr(dataset.datasets[0], "bids_channels"):
|
|
|
1122
1106
|
|
|
1123
1107
|
*Created with [braindecode](https://braindecode.org)*
|
|
1124
1108
|
"""
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
def _infer_license_from_descriptions(
|
|
1128
|
-
descriptions: list[pd.Series | None],
|
|
1129
|
-
) -> tuple[str, bool]:
|
|
1130
|
-
"""Infer a single dataset license from descriptions.
|
|
1131
|
-
|
|
1132
|
-
Returns inferred license and whether a manual update reminder is needed.
|
|
1133
|
-
"""
|
|
1134
|
-
licenses = set()
|
|
1135
|
-
for description in descriptions:
|
|
1136
|
-
if description is None:
|
|
1137
|
-
continue
|
|
1138
|
-
raw_license = description.get("license", None)
|
|
1139
|
-
if raw_license is None:
|
|
1140
|
-
continue
|
|
1141
|
-
normalized = str(raw_license).strip()
|
|
1142
|
-
if normalized and normalized.lower() != "nan":
|
|
1143
|
-
licenses.add(normalized)
|
|
1144
|
-
|
|
1145
|
-
if len(licenses) == 1:
|
|
1146
|
-
return next(iter(licenses)), False
|
|
1147
|
-
|
|
1148
|
-
return "please-specify", True
|
|
@@ -15,6 +15,7 @@ from typing import Any
|
|
|
15
15
|
|
|
16
16
|
import mne
|
|
17
17
|
import pandas as pd
|
|
18
|
+
from mne.utils import deprecated
|
|
18
19
|
|
|
19
20
|
from braindecode.util import _update_moabb_docstring
|
|
20
21
|
|
|
@@ -207,3 +208,12 @@ class HGD(MOABBDataset):
|
|
|
207
208
|
|
|
208
209
|
def __init__(self, subject_ids):
|
|
209
210
|
super().__init__("Schirrmeister2017", subject_ids=subject_ids)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
@deprecated(
|
|
214
|
+
"`BNCI2014001` was renamed to `BNCI2014_001` in v1.13; this alias will be removed in v1.14."
|
|
215
|
+
)
|
|
216
|
+
class BNCI2014001(BNCI2014_001):
|
|
217
|
+
"""Deprecated alias for BNCI2014001."""
|
|
218
|
+
|
|
219
|
+
pass
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
import abc
|
|
8
8
|
import inspect
|
|
9
9
|
import logging
|
|
10
|
-
import warnings
|
|
11
10
|
from typing import Literal
|
|
12
11
|
|
|
13
12
|
import mne
|
|
@@ -42,7 +41,6 @@ def _get_model(model: str):
|
|
|
42
41
|
|
|
43
42
|
class _EEGNeuralNet(NeuralNet, abc.ABC):
|
|
44
43
|
signal_args_set_ = False
|
|
45
|
-
_warned_drop_last_ = False
|
|
46
44
|
|
|
47
45
|
@property
|
|
48
46
|
def log(self):
|
|
@@ -134,14 +132,7 @@ class _EEGNeuralNet(NeuralNet, abc.ABC):
|
|
|
134
132
|
i_window_in_trials = []
|
|
135
133
|
i_window_stops = []
|
|
136
134
|
window_ys = []
|
|
137
|
-
for
|
|
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]
|
|
135
|
+
for X, y, i in self.get_iterator(dataset, drop_index=False):
|
|
145
136
|
i_window_in_trials.append(i[0].cpu().numpy())
|
|
146
137
|
i_window_stops.append(i[2].cpu().numpy())
|
|
147
138
|
with torch.no_grad():
|
|
@@ -276,44 +267,6 @@ class _EEGNeuralNet(NeuralNet, abc.ABC):
|
|
|
276
267
|
X = X.get_data(units="uV")
|
|
277
268
|
return super().get_dataset(X, y)
|
|
278
269
|
|
|
279
|
-
def get_iterator(self, dataset, training=False):
|
|
280
|
-
iterator = super().get_iterator(dataset, training=training)
|
|
281
|
-
# Warn (once per fit) if drop_last would discard every training batch,
|
|
282
|
-
# e.g. a training set smaller than batch_size. This silently skips
|
|
283
|
-
# training without raising any error, which is hard to diagnose.
|
|
284
|
-
if training and not self._warned_drop_last_:
|
|
285
|
-
self._warn_if_training_batches_dropped(iterator)
|
|
286
|
-
return iterator
|
|
287
|
-
|
|
288
|
-
def _warn_if_training_batches_dropped(self, loader):
|
|
289
|
-
"""Warn if ``drop_last`` discards all training batches.
|
|
290
|
-
|
|
291
|
-
With ``iterator_train__drop_last=True`` (the braindecode default), a
|
|
292
|
-
training set smaller than ``batch_size`` yields zero batches, so no
|
|
293
|
-
forward/backward pass runs and the model is left untrained without any
|
|
294
|
-
error. We inspect the resolved training ``DataLoader`` (after
|
|
295
|
-
``train_split`` has been applied), so the count reflects the actual
|
|
296
|
-
number of training examples.
|
|
297
|
-
"""
|
|
298
|
-
self._warned_drop_last_ = True
|
|
299
|
-
if not getattr(loader, "drop_last", False):
|
|
300
|
-
return
|
|
301
|
-
batch_size = getattr(loader, "batch_size", None)
|
|
302
|
-
try:
|
|
303
|
-
n_train = len(loader.dataset)
|
|
304
|
-
except TypeError:
|
|
305
|
-
return # e.g. an IterableDataset whose length is unknown
|
|
306
|
-
if not batch_size or n_train == 0 or n_train >= batch_size:
|
|
307
|
-
return
|
|
308
|
-
warnings.warn(
|
|
309
|
-
f"The training set has {n_train} example(s), which is smaller than "
|
|
310
|
-
f"batch_size={batch_size}. With iterator_train__drop_last=True "
|
|
311
|
-
f"(the braindecode default), all training batches are dropped and "
|
|
312
|
-
f"the model is not trained. Reduce batch_size to at most {n_train}, "
|
|
313
|
-
f"or pass iterator_train__drop_last=False.",
|
|
314
|
-
UserWarning,
|
|
315
|
-
)
|
|
316
|
-
|
|
317
270
|
def partial_fit(self, X, y=None, classes=None, **fit_params):
|
|
318
271
|
"""Fit the module.
|
|
319
272
|
|
|
@@ -413,7 +366,6 @@ class _EEGNeuralNet(NeuralNet, abc.ABC):
|
|
|
413
366
|
the module and to the ``self.train_split`` call.
|
|
414
367
|
"""
|
|
415
368
|
# this needs to be executed before the net is initialized:
|
|
416
|
-
self._warned_drop_last_ = False # re-check on every fresh fit
|
|
417
369
|
if not self.signal_args_set_:
|
|
418
370
|
self._set_signal_args(X, y, classes=None)
|
|
419
371
|
self.signal_args_set_ = True
|
|
@@ -1,30 +1,22 @@
|
|
|
1
1
|
from .functions import (
|
|
2
2
|
_get_gaussian_kernel1d,
|
|
3
|
-
daubechies_filters,
|
|
4
3
|
drop_path,
|
|
5
|
-
dwt_max_level,
|
|
6
4
|
hilbert_freq,
|
|
7
5
|
identity,
|
|
8
6
|
plv_time,
|
|
9
7
|
safe_log,
|
|
10
|
-
sinusoidal_positional_encoding,
|
|
11
8
|
square,
|
|
12
|
-
wavelet_decomposition,
|
|
13
9
|
)
|
|
14
10
|
from .initialization import glorot_weight_zero_bias, rescale_parameter
|
|
15
11
|
|
|
16
12
|
__all__ = [
|
|
17
13
|
"_get_gaussian_kernel1d",
|
|
18
|
-
"daubechies_filters",
|
|
19
14
|
"drop_path",
|
|
20
|
-
"dwt_max_level",
|
|
21
15
|
"hilbert_freq",
|
|
22
16
|
"identity",
|
|
23
17
|
"plv_time",
|
|
24
18
|
"safe_log",
|
|
25
|
-
"sinusoidal_positional_encoding",
|
|
26
19
|
"square",
|
|
27
|
-
"wavelet_decomposition",
|
|
28
20
|
"glorot_weight_zero_bias",
|
|
29
21
|
"rescale_parameter",
|
|
30
22
|
]
|