braindecode 1.5.0.dev182195895__tar.gz → 1.5.1.dev1023__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.5.0.dev182195895 → braindecode-1.5.1.dev1023}/NOTICE.txt +5 -0
- {braindecode-1.5.0.dev182195895/braindecode.egg-info → braindecode-1.5.1.dev1023}/PKG-INFO +6 -2
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/augmentation/__init__.py +2 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/augmentation/functional.py +141 -9
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/augmentation/transforms.py +97 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/base.py +119 -1
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/sleep_physionet.py +15 -1
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/__init__.py +16 -3
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/base.py +16 -4
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/bendr.py +92 -28
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/biot.py +61 -1
- braindecode-1.5.1.dev1023/braindecode/models/codebrain.py +977 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/config.py +5 -4
- braindecode-1.5.1.dev1023/braindecode/models/emg2qwerty.py +914 -0
- braindecode-1.5.1.dev1023/braindecode/models/interpolated.py +182 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/labram.py +249 -269
- braindecode-1.5.1.dev1023/braindecode/models/meta_neuromotor.py +1774 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/reve.py +1 -1
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/signal_jepa.py +463 -38
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/summary.csv +7 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/util.py +151 -20
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/modules/__init__.py +2 -0
- braindecode-1.5.1.dev1023/braindecode/modules/interpolation.py +201 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/preprocessing/eegprep_preprocess.py +51 -6
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/preprocessing/preprocess.py +38 -17
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/preprocessing/windowers.py +13 -4
- braindecode-1.5.1.dev1023/braindecode/version.py +1 -0
- braindecode-1.5.1.dev1023/braindecode/visualization/__init__.py +45 -0
- braindecode-1.5.1.dev1023/braindecode/visualization/attribution.py +152 -0
- braindecode-1.5.1.dev1023/braindecode/visualization/frequency.py +89 -0
- braindecode-1.5.1.dev1023/braindecode/visualization/metrics.py +414 -0
- braindecode-1.5.1.dev1023/braindecode/visualization/sanity.py +117 -0
- braindecode-1.5.1.dev1023/braindecode/visualization/topology.py +64 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023/braindecode.egg-info}/PKG-INFO +6 -2
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode.egg-info/SOURCES.txt +10 -1
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode.egg-info/requires.txt +6 -1
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/api.rst +106 -4
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/cite.rst +2 -2
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/conf.py +34 -2
- braindecode-1.5.1.dev1023/docs/index.rst +749 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/whats_new.rst +210 -12
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/pyproject.toml +4 -1
- braindecode-1.5.0.dev182195895/braindecode/version.py +0 -1
- braindecode-1.5.0.dev182195895/braindecode/visualization/__init__.py +0 -8
- braindecode-1.5.0.dev182195895/braindecode/visualization/gradients.py +0 -62
- braindecode-1.5.0.dev182195895/docs/index.rst +0 -48
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/LICENSE.txt +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/MANIFEST.in +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/README.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/__init__.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/augmentation/base.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/classifier.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/__init__.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/bbci.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/bcicomp.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/bids/__init__.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/bids/datasets.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/bids/format.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/bids/hub.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/bids/hub_format.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/bids/hub_io.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/bids/hub_validation.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/bids/iterable.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/chb_mit.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/mne.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/moabb.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/nmt.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/registry.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/siena.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/tuh.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/utils.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/xy.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datautil/__init__.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datautil/channel_utils.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datautil/hub_formats.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datautil/serialization.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datautil/util.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/eegneuralnet.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/functional/__init__.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/functional/functions.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/functional/initialization.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/atcnet.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/attentionbasenet.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/attn_sleep.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/brainmodule.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/cbramod.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/contrawr.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/ctnet.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/deep4.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/deepsleepnet.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/dgcnn.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/eegconformer.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/eeginception_erp.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/eeginception_mi.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/eegitnet.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/eegminer.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/eegnet.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/eegnex.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/eegpt.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/eegsimpleconv.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/eegsym.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/eegtcnet.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/fbcnet.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/fblightconvnet.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/fbmsnet.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/hybrid.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/ifnet.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/luna.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/medformer.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/msvtnet.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/patchedtransformer.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/sccnet.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/shallow_fbcsp.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/sinc_shallow.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/sparcnet.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/sstdpn.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/syncnet.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/tcn.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/tidnet.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/tsinception.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/models/usleep.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/modules/activation.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/modules/attention.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/modules/blocks.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/modules/convolution.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/modules/filter.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/modules/layers.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/modules/linear.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/modules/parametrization.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/modules/stats.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/modules/util.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/modules/wrapper.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/preprocessing/__init__.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/preprocessing/mne_preprocess.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/preprocessing/util.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/regressor.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/samplers/__init__.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/samplers/base.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/samplers/ssl.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/training/__init__.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/training/callbacks.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/training/losses.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/training/scoring.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/util.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/visualization/confusion_matrices.py +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode.egg-info/dependency_links.txt +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode.egg-info/top_level.txt +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/Makefile +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/_templates/autosummary/class.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/_templates/autosummary/function.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/help.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/install/install.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/install/install_pip.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/install/install_source.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/models/categorization/attention.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/models/categorization/channel.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/models/categorization/convolution.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/models/categorization/filterbank.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/models/categorization/gnn.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/models/categorization/interpretable.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/models/categorization/lbm.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/models/categorization/recurrent.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/models/categorization/spd.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/models/models.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/models/models_categorization.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/models/models_table.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/models/models_visualization.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/docs/sg_execution_times.rst +0 -0
- {braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/setup.cfg +0 -0
|
@@ -11,9 +11,14 @@ All files within the `src/` directory are licensed under the BSD-3-Clause Licens
|
|
|
11
11
|
The following components are licensed under the Creative Commons Attribution-NonCommercial 4.0 International License:
|
|
12
12
|
|
|
13
13
|
- `braindecode/models/eegminer.py`
|
|
14
|
+
- `braindecode/models/meta_neuromotor.py`
|
|
14
15
|
|
|
15
16
|
As well as class later imported into the `braindecode.models.module` named as GeneralizedGaussianFilter.
|
|
16
17
|
|
|
18
|
+
The `meta_neuromotor.py` file is a derivative of
|
|
19
|
+
`facebookresearch/generic-neuromotor-interface`, released by Meta Platforms,
|
|
20
|
+
Inc. under CC BY-NC 4.0, and inherits the same noncommercial terms.
|
|
21
|
+
|
|
17
22
|
## License Links
|
|
18
23
|
|
|
19
24
|
- [BSD-3-Clause License](https://opensource.org/licenses/BSD-3-Clause)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: braindecode
|
|
3
|
-
Version: 1.5.
|
|
3
|
+
Version: 1.5.1.dev1023
|
|
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>
|
|
@@ -43,6 +43,8 @@ Requires-Dist: eegprep[eeglabio]>=0.2.23; extra == "eegprep"
|
|
|
43
43
|
Provides-Extra: hub
|
|
44
44
|
Requires-Dist: huggingface_hub[torch]>=0.20.0; extra == "hub"
|
|
45
45
|
Requires-Dist: zarr>=3.0; extra == "hub"
|
|
46
|
+
Provides-Extra: viz
|
|
47
|
+
Requires-Dist: captum>=0.7.0; extra == "viz"
|
|
46
48
|
Provides-Extra: tests
|
|
47
49
|
Requires-Dist: pytest; extra == "tests"
|
|
48
50
|
Requires-Dist: pytest-cov; extra == "tests"
|
|
@@ -61,6 +63,7 @@ Requires-Dist: sphinx-autodoc-typehints; extra == "docs"
|
|
|
61
63
|
Requires-Dist: sphinx-autobuild; extra == "docs"
|
|
62
64
|
Requires-Dist: sphinxcontrib-bibtex; extra == "docs"
|
|
63
65
|
Requires-Dist: sphinx_sitemap; extra == "docs"
|
|
66
|
+
Requires-Dist: sphinxext-opengraph; extra == "docs"
|
|
64
67
|
Requires-Dist: pydata_sphinx_theme; extra == "docs"
|
|
65
68
|
Requires-Dist: numpydoc; extra == "docs"
|
|
66
69
|
Requires-Dist: memory_profiler; extra == "docs"
|
|
@@ -70,7 +73,7 @@ Requires-Dist: sphinx_design; extra == "docs"
|
|
|
70
73
|
Requires-Dist: lightning; extra == "docs"
|
|
71
74
|
Requires-Dist: seaborn; extra == "docs"
|
|
72
75
|
Requires-Dist: pre-commit; extra == "docs"
|
|
73
|
-
Requires-Dist: openneuro-py; extra == "docs"
|
|
76
|
+
Requires-Dist: openneuro-py>=2026.4.0; extra == "docs"
|
|
74
77
|
Requires-Dist: plotly; extra == "docs"
|
|
75
78
|
Requires-Dist: shap; extra == "docs"
|
|
76
79
|
Requires-Dist: nbformat; extra == "docs"
|
|
@@ -82,6 +85,7 @@ Requires-Dist: braindecode[docs]; extra == "all"
|
|
|
82
85
|
Requires-Dist: braindecode[hub]; extra == "all"
|
|
83
86
|
Requires-Dist: braindecode[eegprep]; extra == "all"
|
|
84
87
|
Requires-Dist: braindecode[typing]; extra == "all"
|
|
88
|
+
Requires-Dist: braindecode[viz]; extra == "all"
|
|
85
89
|
Dynamic: license-file
|
|
86
90
|
|
|
87
91
|
.. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.17699192.svg
|
{braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/augmentation/__init__.py
RENAMED
|
@@ -4,6 +4,7 @@ from . import functional
|
|
|
4
4
|
from .base import AugmentedDataLoader, Compose, IdentityTransform, Transform
|
|
5
5
|
from .transforms import (
|
|
6
6
|
AmplitudeScale,
|
|
7
|
+
BandRotation,
|
|
7
8
|
BandstopFilter,
|
|
8
9
|
ChannelsDropout,
|
|
9
10
|
ChannelsReref,
|
|
@@ -47,6 +48,7 @@ __all__ = [
|
|
|
47
48
|
"SegmentationReconstruction",
|
|
48
49
|
"MaskEncoding",
|
|
49
50
|
"AmplitudeScale",
|
|
51
|
+
"BandRotation",
|
|
50
52
|
"ChannelsReref",
|
|
51
53
|
"functional",
|
|
52
54
|
]
|
{braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/augmentation/functional.py
RENAMED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
# Alexandre Gramfort <alexandre.gramfort@inria.fr>
|
|
3
3
|
# Gustavo Rodrigues <gustavenrique01@gmail.com>
|
|
4
4
|
# Bruna Lopes <brunajaflopes@gmail.com>
|
|
5
|
+
# Sarthak Tayal <sarthaktayal2@gmail.com>
|
|
5
6
|
#
|
|
6
7
|
# License: BSD (3-clause)
|
|
7
8
|
|
|
@@ -1265,10 +1266,11 @@ def amplitude_scale(
|
|
|
1265
1266
|
y : torch.Tensor
|
|
1266
1267
|
EEG labels for the example or batch.
|
|
1267
1268
|
scale : tuple of floats
|
|
1268
|
-
Interval from which
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1269
|
+
Interval ``(low, high)`` from which the per (sample, channel)
|
|
1270
|
+
scaling value is uniformly sampled.
|
|
1271
|
+
random_state : int | numpy.random.RandomState | None, optional
|
|
1272
|
+
Seed used to instantiate the numpy random number generator that
|
|
1273
|
+
draws the scaling values. Defaults to None.
|
|
1272
1274
|
|
|
1273
1275
|
Returns
|
|
1274
1276
|
-------
|
|
@@ -1285,16 +1287,146 @@ def amplitude_scale(
|
|
|
1285
1287
|
Learning Research 136:238-253
|
|
1286
1288
|
"""
|
|
1287
1289
|
|
|
1288
|
-
rng
|
|
1289
|
-
|
|
1290
|
+
# use the same numpy rng path as the rest of this module. the previous
|
|
1291
|
+
# torch.Generator + manual_seed path crashed on None and on the
|
|
1292
|
+
# numpy RandomState that Transform passes in via self.rng.
|
|
1293
|
+
rng = check_random_state(random_state)
|
|
1290
1294
|
batch_size, n_channels, _ = X.shape
|
|
1291
1295
|
|
|
1292
|
-
# Parameter for scaling amplitude / channel / trial
|
|
1293
1296
|
l, h = scale
|
|
1294
|
-
s =
|
|
1295
|
-
|
|
1297
|
+
s = torch.as_tensor(
|
|
1298
|
+
rng.uniform(low=l, high=h, size=(batch_size, n_channels, 1)),
|
|
1299
|
+
device=X.device,
|
|
1300
|
+
dtype=X.dtype,
|
|
1296
1301
|
)
|
|
1297
1302
|
|
|
1298
1303
|
X = s * X
|
|
1299
1304
|
|
|
1300
1305
|
return X, y
|
|
1306
|
+
|
|
1307
|
+
|
|
1308
|
+
def band_rotation(
|
|
1309
|
+
X: torch.Tensor,
|
|
1310
|
+
y: torch.Tensor,
|
|
1311
|
+
num_bands: int = 2,
|
|
1312
|
+
electrodes_per_band: int = 16,
|
|
1313
|
+
band_offsets: tuple[int, ...] = (-1, 0, 1),
|
|
1314
|
+
max_temporal_jitter: int = 0,
|
|
1315
|
+
circular_jitter: bool = True,
|
|
1316
|
+
random_state: int | np.random.RandomState | None = None,
|
|
1317
|
+
) -> tuple[torch.Tensor, torch.Tensor]:
|
|
1318
|
+
"""Per-band electrode rotation + inter-band temporal jitter.
|
|
1319
|
+
|
|
1320
|
+
Models small wristband rotation between sessions and relative timing
|
|
1321
|
+
noise between two arms. Introduced in [Sivakumar2024]_ for the
|
|
1322
|
+
emg2qwerty CTC keystroke decoding task: each electrode band gets its
|
|
1323
|
+
own circular roll along the channel axis (``Uniform(band_offsets)``
|
|
1324
|
+
positions), and band 1 also gets a sample-level temporal shift
|
|
1325
|
+
(``Uniform(-max_temporal_jitter, +max_temporal_jitter)``) along the
|
|
1326
|
+
time axis.
|
|
1327
|
+
|
|
1328
|
+
Channel layout assumes ``(B, num_bands * electrodes_per_band, T)`` with
|
|
1329
|
+
bands contiguous along the channel axis. Same offset / shift is
|
|
1330
|
+
applied to every sample in the batch (one set of parameters per call).
|
|
1331
|
+
|
|
1332
|
+
Parameters
|
|
1333
|
+
----------
|
|
1334
|
+
X : torch.Tensor
|
|
1335
|
+
EMG input batch of shape ``(B, C, T)`` with
|
|
1336
|
+
``C == num_bands * electrodes_per_band``.
|
|
1337
|
+
y : torch.Tensor
|
|
1338
|
+
Labels (returned unchanged).
|
|
1339
|
+
num_bands : int, optional
|
|
1340
|
+
Number of electrode bands (e.g. ``2`` for left + right wristband).
|
|
1341
|
+
Must be ``>= 1``. Defaults to 2.
|
|
1342
|
+
electrodes_per_band : int, optional
|
|
1343
|
+
Electrodes per band (e.g. ``16``). Must be ``>= 1``. Defaults
|
|
1344
|
+
to 16.
|
|
1345
|
+
band_offsets : tuple of int, optional
|
|
1346
|
+
Per-band roll values to sample from uniformly. ``(-1, 0, 1)``
|
|
1347
|
+
covers ±1-electrode misalignment. Must be non-empty. Defaults
|
|
1348
|
+
to ``(-1, 0, 1)``.
|
|
1349
|
+
max_temporal_jitter : int, optional
|
|
1350
|
+
Max ±-sample temporal shift applied to band 1 only when
|
|
1351
|
+
``num_bands >= 2``. Defaults to 0 (disabled). Must be ``>= 0``.
|
|
1352
|
+
circular_jitter : bool, optional
|
|
1353
|
+
If True (the default, paper-faithful), the temporal jitter is a
|
|
1354
|
+
circular ``torch.roll`` — samples shifted off one edge wrap to
|
|
1355
|
+
the other. If False, the gap left by the shift is zero-padded
|
|
1356
|
+
and the shifted-off samples are dropped, avoiding wrap-around
|
|
1357
|
+
discontinuity at the cost of a small zeroed margin. Has no
|
|
1358
|
+
effect when ``max_temporal_jitter == 0``.
|
|
1359
|
+
random_state : int | numpy.random.RandomState, optional
|
|
1360
|
+
Seed / generator for sampling rotation + jitter values.
|
|
1361
|
+
|
|
1362
|
+
Returns
|
|
1363
|
+
-------
|
|
1364
|
+
torch.Tensor
|
|
1365
|
+
Transformed inputs.
|
|
1366
|
+
torch.Tensor
|
|
1367
|
+
Labels (unchanged).
|
|
1368
|
+
|
|
1369
|
+
References
|
|
1370
|
+
----------
|
|
1371
|
+
.. [Sivakumar2024] Sivakumar, V., Seely, J., Du, A., Bittner, S. R.,
|
|
1372
|
+
Berenzweig, A., Bolarinwa, A., Gramfort, A., & Mandel, M. I. (2024).
|
|
1373
|
+
"emg2qwerty: A Large Dataset with Baselines for Touch Typing using
|
|
1374
|
+
Surface Electromyography." *NeurIPS Datasets and Benchmarks Track*.
|
|
1375
|
+
"""
|
|
1376
|
+
if num_bands < 1:
|
|
1377
|
+
raise ValueError(f"num_bands must be >= 1, got {num_bands}")
|
|
1378
|
+
if electrodes_per_band < 1:
|
|
1379
|
+
raise ValueError(f"electrodes_per_band must be >= 1, got {electrodes_per_band}")
|
|
1380
|
+
# Normalise to a tuple before truth-testing so callers can pass any
|
|
1381
|
+
# sequence-like (incl. ``np.ndarray``) without hitting numpy's
|
|
1382
|
+
# ambiguous-truth-value error on ``if not band_offsets``.
|
|
1383
|
+
band_offsets = tuple(band_offsets)
|
|
1384
|
+
if not band_offsets:
|
|
1385
|
+
raise ValueError("band_offsets must be non-empty")
|
|
1386
|
+
if not all(isinstance(o, (int, np.integer)) for o in band_offsets):
|
|
1387
|
+
raise ValueError(f"band_offsets must contain integers, got {band_offsets!r}")
|
|
1388
|
+
if max_temporal_jitter < 0:
|
|
1389
|
+
raise ValueError(f"max_temporal_jitter must be >= 0, got {max_temporal_jitter}")
|
|
1390
|
+
expected_channels = num_bands * electrodes_per_band
|
|
1391
|
+
if X.shape[1] != expected_channels:
|
|
1392
|
+
raise ValueError(
|
|
1393
|
+
f"X.shape[1]={X.shape[1]} != num_bands * electrodes_per_band="
|
|
1394
|
+
f"{expected_channels}"
|
|
1395
|
+
)
|
|
1396
|
+
|
|
1397
|
+
rng = check_random_state(random_state)
|
|
1398
|
+
band_offsets_arr = np.asarray(band_offsets)
|
|
1399
|
+
out = X.clone()
|
|
1400
|
+
|
|
1401
|
+
# Per-band channel-axis rolls. A vectorized ``torch.gather`` was
|
|
1402
|
+
# benchmarked and is ~16 % slower for the typical ``num_bands == 2``
|
|
1403
|
+
# case on CPU (the index tensor is larger than what two contiguous
|
|
1404
|
+
# rolls touch); the gather only wins past ``num_bands >= 8``.
|
|
1405
|
+
for b in range(num_bands):
|
|
1406
|
+
offset = int(rng.choice(band_offsets_arr))
|
|
1407
|
+
if offset:
|
|
1408
|
+
sl = slice(b * electrodes_per_band, (b + 1) * electrodes_per_band)
|
|
1409
|
+
out[:, sl, :] = torch.roll(out[:, sl, :], offset, dims=1)
|
|
1410
|
+
|
|
1411
|
+
# Inter-band temporal jitter — paper recipe applies it to band 1 only.
|
|
1412
|
+
if max_temporal_jitter > 0 and num_bands >= 2:
|
|
1413
|
+
shift = int(rng.randint(-max_temporal_jitter, max_temporal_jitter + 1))
|
|
1414
|
+
if shift:
|
|
1415
|
+
sl = slice(electrodes_per_band, 2 * electrodes_per_band)
|
|
1416
|
+
band1 = out[:, sl, :]
|
|
1417
|
+
if circular_jitter:
|
|
1418
|
+
# Paper-faithful circular shift; wraps end-of-window
|
|
1419
|
+
# samples to the start (and vice versa).
|
|
1420
|
+
out[:, sl, :] = torch.roll(band1, shift, dims=2)
|
|
1421
|
+
else:
|
|
1422
|
+
# Crop-and-pad shift: drop samples that fall off one end,
|
|
1423
|
+
# zero-pad the gap on the other. Avoids the wrap-around
|
|
1424
|
+
# discontinuity at the cost of a ``|shift|``-sample margin.
|
|
1425
|
+
shifted = torch.zeros_like(band1)
|
|
1426
|
+
if shift > 0:
|
|
1427
|
+
shifted[:, :, shift:] = band1[:, :, :-shift]
|
|
1428
|
+
else: # shift < 0
|
|
1429
|
+
shifted[:, :, :shift] = band1[:, :, -shift:]
|
|
1430
|
+
out[:, sl, :] = shifted
|
|
1431
|
+
|
|
1432
|
+
return out, y
|
{braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/augmentation/transforms.py
RENAMED
|
@@ -16,6 +16,7 @@ from mne.channels import make_standard_montage
|
|
|
16
16
|
from .base import Transform
|
|
17
17
|
from .functional import (
|
|
18
18
|
amplitude_scale,
|
|
19
|
+
band_rotation,
|
|
19
20
|
bandstop_filter,
|
|
20
21
|
channels_dropout,
|
|
21
22
|
channels_permute,
|
|
@@ -1356,3 +1357,99 @@ class AmplitudeScale(Transform):
|
|
|
1356
1357
|
def get_augmentation_params(self, *batch):
|
|
1357
1358
|
"""Return transform parameters."""
|
|
1358
1359
|
return {"random_state": self.rng, "scale": self.scale}
|
|
1360
|
+
|
|
1361
|
+
|
|
1362
|
+
class BandRotation(Transform):
|
|
1363
|
+
"""Per-band electrode rotation + inter-band temporal jitter.
|
|
1364
|
+
|
|
1365
|
+
Models small wristband rotation between sessions and relative timing
|
|
1366
|
+
noise between two arms. Introduced in [Sivakumar2024]_ for the
|
|
1367
|
+
emg2qwerty surface-EMG keystroke decoding task: the channel axis is
|
|
1368
|
+
laid out as ``(B, num_bands * electrodes_per_band, T)`` with bands
|
|
1369
|
+
contiguous, each band gets a uniform circular roll along the channel
|
|
1370
|
+
axis, and when ``num_bands >= 2``, band 1 also gets a sample-level
|
|
1371
|
+
temporal shift. The same offset / shift is applied to every sample
|
|
1372
|
+
in a transformed sub-batch (one set of parameters per call).
|
|
1373
|
+
|
|
1374
|
+
Parameters
|
|
1375
|
+
----------
|
|
1376
|
+
probability : float
|
|
1377
|
+
Float setting the probability of applying the operation.
|
|
1378
|
+
num_bands : int, optional
|
|
1379
|
+
Number of electrode bands (e.g. ``2`` for left + right wristband).
|
|
1380
|
+
Must be ``>= 1``. Defaults to 2.
|
|
1381
|
+
electrodes_per_band : int, optional
|
|
1382
|
+
Electrodes per band (e.g. ``16``). Must be ``>= 1``. Defaults
|
|
1383
|
+
to 16.
|
|
1384
|
+
band_offsets : tuple of int, optional
|
|
1385
|
+
Per-band roll values to sample from uniformly. ``(-1, 0, 1)``
|
|
1386
|
+
covers ±1-electrode misalignment. Must be non-empty. Defaults
|
|
1387
|
+
to ``(-1, 0, 1)``.
|
|
1388
|
+
max_temporal_jitter : int, optional
|
|
1389
|
+
Max ±-sample temporal shift applied to band 1. Defaults to 0
|
|
1390
|
+
(jitter disabled). Must be ``>= 0``. The emg2qwerty paper uses
|
|
1391
|
+
120 samples (60 ms at 2 kHz).
|
|
1392
|
+
circular_jitter : bool, optional
|
|
1393
|
+
If True (default, paper-faithful) the jitter is a circular roll;
|
|
1394
|
+
if False the gap left by the shift is zero-padded. See
|
|
1395
|
+
:func:`band_rotation`.
|
|
1396
|
+
random_state : int | numpy.random.RandomState, optional
|
|
1397
|
+
Seed for the rotation / jitter sampler. Defaults to None.
|
|
1398
|
+
|
|
1399
|
+
References
|
|
1400
|
+
----------
|
|
1401
|
+
.. [Sivakumar2024] Sivakumar, V., Seely, J., Du, A., Bittner, S. R.,
|
|
1402
|
+
Berenzweig, A., Bolarinwa, A., Gramfort, A., & Mandel, M. I. (2024).
|
|
1403
|
+
"emg2qwerty: A Large Dataset with Baselines for Touch Typing using
|
|
1404
|
+
Surface Electromyography." *NeurIPS Datasets and Benchmarks Track*.
|
|
1405
|
+
"""
|
|
1406
|
+
|
|
1407
|
+
operation = staticmethod(band_rotation) # type: ignore[assignment]
|
|
1408
|
+
|
|
1409
|
+
def __init__(
|
|
1410
|
+
self,
|
|
1411
|
+
probability,
|
|
1412
|
+
num_bands=2,
|
|
1413
|
+
electrodes_per_band=16,
|
|
1414
|
+
band_offsets=(-1, 0, 1),
|
|
1415
|
+
max_temporal_jitter=0,
|
|
1416
|
+
circular_jitter=True,
|
|
1417
|
+
random_state=None,
|
|
1418
|
+
):
|
|
1419
|
+
super().__init__(probability=probability, random_state=random_state)
|
|
1420
|
+
# Up-front parameter validation; the underlying ``band_rotation``
|
|
1421
|
+
# also re-checks at call time, but raising here surfaces config
|
|
1422
|
+
# mistakes when the Transform is built rather than on the first
|
|
1423
|
+
# batch.
|
|
1424
|
+
if num_bands < 1:
|
|
1425
|
+
raise ValueError(f"num_bands must be >= 1, got {num_bands}")
|
|
1426
|
+
if electrodes_per_band < 1:
|
|
1427
|
+
raise ValueError(
|
|
1428
|
+
f"electrodes_per_band must be >= 1, got {electrodes_per_band}"
|
|
1429
|
+
)
|
|
1430
|
+
band_offsets = tuple(band_offsets)
|
|
1431
|
+
if not band_offsets:
|
|
1432
|
+
raise ValueError("band_offsets must be non-empty")
|
|
1433
|
+
if not all(isinstance(o, (int, np.integer)) for o in band_offsets):
|
|
1434
|
+
raise ValueError(
|
|
1435
|
+
f"band_offsets must contain integers, got {band_offsets!r}"
|
|
1436
|
+
)
|
|
1437
|
+
if max_temporal_jitter < 0:
|
|
1438
|
+
raise ValueError(
|
|
1439
|
+
f"max_temporal_jitter must be >= 0, got {max_temporal_jitter}"
|
|
1440
|
+
)
|
|
1441
|
+
self.num_bands = num_bands
|
|
1442
|
+
self.electrodes_per_band = electrodes_per_band
|
|
1443
|
+
self.band_offsets = band_offsets
|
|
1444
|
+
self.max_temporal_jitter = max_temporal_jitter
|
|
1445
|
+
self.circular_jitter = circular_jitter
|
|
1446
|
+
|
|
1447
|
+
def get_augmentation_params(self, *batch):
|
|
1448
|
+
return {
|
|
1449
|
+
"num_bands": self.num_bands,
|
|
1450
|
+
"electrodes_per_band": self.electrodes_per_band,
|
|
1451
|
+
"band_offsets": self.band_offsets,
|
|
1452
|
+
"max_temporal_jitter": self.max_temporal_jitter,
|
|
1453
|
+
"circular_jitter": self.circular_jitter,
|
|
1454
|
+
"random_state": self.rng,
|
|
1455
|
+
}
|
|
@@ -18,7 +18,7 @@ import shutil
|
|
|
18
18
|
import warnings
|
|
19
19
|
from abc import abstractmethod
|
|
20
20
|
from collections import Counter
|
|
21
|
-
from collections.abc import Callable
|
|
21
|
+
from collections.abc import Callable, Hashable
|
|
22
22
|
from glob import glob
|
|
23
23
|
from pathlib import Path
|
|
24
24
|
from typing import Any, Generic, Iterable, no_type_check
|
|
@@ -1340,6 +1340,124 @@ class BaseConcatDataset(ConcatDataset, HubDatasetMixin, Generic[T]):
|
|
|
1340
1340
|
raise TypeError("target_transform must be a callable.")
|
|
1341
1341
|
self._target_transform = fn
|
|
1342
1342
|
|
|
1343
|
+
def set_target(self, column: Hashable) -> "BaseConcatDataset":
|
|
1344
|
+
"""Use ``column`` as the target ``y`` for every subdataset.
|
|
1345
|
+
|
|
1346
|
+
Dispatches on the subdataset type:
|
|
1347
|
+
|
|
1348
|
+
* For :class:`WindowsDataset` / :class:`EEGWindowsDataset`,
|
|
1349
|
+
``column`` is looked up in per-window ``metadata`` first, then in
|
|
1350
|
+
the per-record ``description`` (broadcast to every window). The
|
|
1351
|
+
resolved values overwrite ``ds.metadata['target']`` and ``ds.y``.
|
|
1352
|
+
For :class:`WindowsDataset`, the underlying ``ds.windows.metadata``
|
|
1353
|
+
is kept in sync so ``get_metadata()`` and the repr reflect the
|
|
1354
|
+
new target.
|
|
1355
|
+
* For :class:`RawDataset`, ``column`` must exist on the
|
|
1356
|
+
``description``. ``ds.target_name`` is set to ``column`` so
|
|
1357
|
+
``__getitem__`` reads ``description[column]`` as ``y`` on every
|
|
1358
|
+
access — no rebuild needed.
|
|
1359
|
+
|
|
1360
|
+
Parameters
|
|
1361
|
+
----------
|
|
1362
|
+
column : Hashable
|
|
1363
|
+
Name of a metadata column or description field (BIDS entity,
|
|
1364
|
+
participants.tsv extra, ...). Typically a string, but any
|
|
1365
|
+
hashable that pandas accepts as a column label is allowed.
|
|
1366
|
+
|
|
1367
|
+
Returns
|
|
1368
|
+
-------
|
|
1369
|
+
self : BaseConcatDataset
|
|
1370
|
+
|
|
1371
|
+
Raises
|
|
1372
|
+
------
|
|
1373
|
+
TypeError
|
|
1374
|
+
If any subdataset is not a :class:`WindowsDataset`,
|
|
1375
|
+
:class:`EEGWindowsDataset`, or :class:`RawDataset`, or if a
|
|
1376
|
+
windowed subdataset has lazy (non-DataFrame) metadata.
|
|
1377
|
+
ValueError
|
|
1378
|
+
If ``column`` is not present on a subdataset's metadata or
|
|
1379
|
+
description, or if a windowed subdataset has
|
|
1380
|
+
``targets_from='channels'`` (which would make this a silent
|
|
1381
|
+
no-op since ``__getitem__`` reads y from misc channels, not
|
|
1382
|
+
from ``metadata['target']``).
|
|
1383
|
+
"""
|
|
1384
|
+
for i, ds in enumerate(self.datasets):
|
|
1385
|
+
if isinstance(ds, (WindowsDataset, EEGWindowsDataset)):
|
|
1386
|
+
if not isinstance(ds.metadata, pd.DataFrame):
|
|
1387
|
+
# _LazyDataFrame (lazy_metadata=True) does not implement
|
|
1388
|
+
# .copy()/__setitem__, so the in-place write below would
|
|
1389
|
+
# raise AttributeError. Surface the precondition cleanly.
|
|
1390
|
+
raise TypeError(
|
|
1391
|
+
"set_target requires a materialized metadata "
|
|
1392
|
+
f"DataFrame; datasets[{i}].metadata is "
|
|
1393
|
+
f"{type(ds.metadata).__name__}. Re-window with "
|
|
1394
|
+
"lazy_metadata=False to use set_target."
|
|
1395
|
+
)
|
|
1396
|
+
if getattr(ds, "targets_from", "metadata") != "metadata":
|
|
1397
|
+
# __getitem__ would read y from misc channels; writing
|
|
1398
|
+
# metadata['target']/ds.y would be a silent no-op.
|
|
1399
|
+
raise ValueError(
|
|
1400
|
+
f"datasets[{i}] has targets_from="
|
|
1401
|
+
f"{ds.targets_from!r}; set_target only applies when "
|
|
1402
|
+
"targets_from='metadata' (otherwise __getitem__ "
|
|
1403
|
+
"derives y from misc channels and would ignore the "
|
|
1404
|
+
"rewritten target column)."
|
|
1405
|
+
)
|
|
1406
|
+
n = len(ds)
|
|
1407
|
+
md = ds.metadata
|
|
1408
|
+
if column in md.columns:
|
|
1409
|
+
values = md[column].iloc[:n].to_list()
|
|
1410
|
+
elif (
|
|
1411
|
+
isinstance(ds.description, pd.Series)
|
|
1412
|
+
and column in ds.description.index
|
|
1413
|
+
):
|
|
1414
|
+
values = [ds.description[column]] * n
|
|
1415
|
+
else:
|
|
1416
|
+
desc_keys = (
|
|
1417
|
+
list(ds.description.index)
|
|
1418
|
+
if isinstance(ds.description, pd.Series)
|
|
1419
|
+
else []
|
|
1420
|
+
)
|
|
1421
|
+
raise ValueError(
|
|
1422
|
+
f"Column {column!r} not found on datasets[{i}]: "
|
|
1423
|
+
f"metadata cols={list(md.columns)}, "
|
|
1424
|
+
f"description keys={desc_keys}."
|
|
1425
|
+
)
|
|
1426
|
+
# In-place write so the WindowsDataset's metadata and the
|
|
1427
|
+
# underlying mne.Epochs.metadata (which start as the same
|
|
1428
|
+
# object reference) both reflect the new target. Defensive
|
|
1429
|
+
# second write covers the case where they got de-aliased
|
|
1430
|
+
# earlier by a caller-side reassignment.
|
|
1431
|
+
md["target"] = values
|
|
1432
|
+
windows_obj = getattr(ds, "_windows", None)
|
|
1433
|
+
if windows_obj is not None and windows_obj.metadata is not md:
|
|
1434
|
+
windows_obj.metadata["target"] = values
|
|
1435
|
+
# values is already a fresh list (Series.to_list() / [x] * n);
|
|
1436
|
+
# no defensive copy needed — pandas keeps its own representation
|
|
1437
|
+
# for md["target"] so mutating ds.y won't reach back into it.
|
|
1438
|
+
ds.y = values
|
|
1439
|
+
elif isinstance(ds, RawDataset):
|
|
1440
|
+
if (
|
|
1441
|
+
not isinstance(ds.description, pd.Series)
|
|
1442
|
+
or column not in ds.description.index
|
|
1443
|
+
):
|
|
1444
|
+
desc_keys = (
|
|
1445
|
+
list(ds.description.index)
|
|
1446
|
+
if isinstance(ds.description, pd.Series)
|
|
1447
|
+
else []
|
|
1448
|
+
)
|
|
1449
|
+
raise ValueError(
|
|
1450
|
+
f"Column {column!r} not found on datasets[{i}] "
|
|
1451
|
+
f"description (keys={desc_keys})."
|
|
1452
|
+
)
|
|
1453
|
+
ds.target_name = column
|
|
1454
|
+
else:
|
|
1455
|
+
raise TypeError(
|
|
1456
|
+
"set_target requires WindowsDataset, EEGWindowsDataset, "
|
|
1457
|
+
f"or RawDataset; datasets[{i}] is {type(ds).__name__}."
|
|
1458
|
+
)
|
|
1459
|
+
return self
|
|
1460
|
+
|
|
1343
1461
|
def _outdated_save(self, path, overwrite=False):
|
|
1344
1462
|
"""This is a copy of the old saving function, that had inconsistent.
|
|
1345
1463
|
|
{braindecode-1.5.0.dev182195895 → braindecode-1.5.1.dev1023}/braindecode/datasets/sleep_physionet.py
RENAMED
|
@@ -6,10 +6,12 @@
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
8
|
import os
|
|
9
|
+
import time
|
|
9
10
|
|
|
10
11
|
import mne
|
|
11
12
|
import numpy as np
|
|
12
13
|
import pandas as pd
|
|
14
|
+
import requests
|
|
13
15
|
from mne.datasets.sleep_physionet.age import fetch_data
|
|
14
16
|
|
|
15
17
|
from .base import BaseConcatDataset, RawDataset
|
|
@@ -59,7 +61,19 @@ class SleepPhysionet(BaseConcatDataset):
|
|
|
59
61
|
if recording_ids is None:
|
|
60
62
|
recording_ids = [1, 2]
|
|
61
63
|
|
|
62
|
-
|
|
64
|
+
max_attempts = 5
|
|
65
|
+
retry_delay_s = 10
|
|
66
|
+
|
|
67
|
+
for attempt in range(max_attempts):
|
|
68
|
+
try:
|
|
69
|
+
paths = fetch_data(
|
|
70
|
+
subject_ids, recording=recording_ids, on_missing="warn"
|
|
71
|
+
)
|
|
72
|
+
break
|
|
73
|
+
except requests.exceptions.RequestException:
|
|
74
|
+
if attempt == max_attempts - 1:
|
|
75
|
+
raise
|
|
76
|
+
time.sleep(retry_delay_s)
|
|
63
77
|
|
|
64
78
|
all_base_ds = list()
|
|
65
79
|
for p in paths:
|
|
@@ -4,10 +4,11 @@ from .atcnet import ATCNet
|
|
|
4
4
|
from .attentionbasenet import AttentionBaseNet
|
|
5
5
|
from .attn_sleep import AttnSleep
|
|
6
6
|
from .base import EEGModuleMixin
|
|
7
|
-
from .bendr import BENDR
|
|
8
|
-
from .biot import BIOT
|
|
7
|
+
from .bendr import BENDR, InterpolatedBENDR
|
|
8
|
+
from .biot import BIOT, InterpolatedBIOT
|
|
9
9
|
from .brainmodule import BrainModule
|
|
10
10
|
from .cbramod import CBraMod
|
|
11
|
+
from .codebrain import CodeBrain
|
|
11
12
|
from .contrawr import ContraWR
|
|
12
13
|
from .ctnet import CTNet
|
|
13
14
|
from .deep4 import Deep4Net
|
|
@@ -24,20 +25,24 @@ from .eegpt import EEGPT
|
|
|
24
25
|
from .eegsimpleconv import EEGSimpleConv
|
|
25
26
|
from .eegsym import EEGSym
|
|
26
27
|
from .eegtcnet import EEGTCNet
|
|
28
|
+
from .emg2qwerty import EMG2QwertyNet
|
|
27
29
|
from .fbcnet import FBCNet
|
|
28
30
|
from .fblightconvnet import FBLightConvNet
|
|
29
31
|
from .fbmsnet import FBMSNet
|
|
30
32
|
from .hybrid import HybridNet
|
|
31
33
|
from .ifnet import IFNet
|
|
32
|
-
from .
|
|
34
|
+
from .interpolated import InterpolatedModel
|
|
35
|
+
from .labram import InterpolatedLaBraM, Labram
|
|
33
36
|
from .luna import LUNA
|
|
34
37
|
from .medformer import MEDFormer
|
|
38
|
+
from .meta_neuromotor import MetaNeuromotorHand
|
|
35
39
|
from .msvtnet import MSVTNet
|
|
36
40
|
from .patchedtransformer import PBT
|
|
37
41
|
from .reve import REVE
|
|
38
42
|
from .sccnet import SCCNet
|
|
39
43
|
from .shallow_fbcsp import ShallowFBCSPNet
|
|
40
44
|
from .signal_jepa import (
|
|
45
|
+
InterpolatedSignalJEPA,
|
|
41
46
|
SignalJEPA,
|
|
42
47
|
SignalJEPA_Contextual,
|
|
43
48
|
SignalJEPA_PostLocal,
|
|
@@ -72,6 +77,7 @@ __all__ = [
|
|
|
72
77
|
"BIOT",
|
|
73
78
|
"BENDR",
|
|
74
79
|
"CBraMod",
|
|
80
|
+
"CodeBrain",
|
|
75
81
|
"ContraWR",
|
|
76
82
|
"CTNet",
|
|
77
83
|
"Deep4Net",
|
|
@@ -90,11 +96,18 @@ __all__ = [
|
|
|
90
96
|
"EEGSimpleConv",
|
|
91
97
|
"EEGTCNet",
|
|
92
98
|
"DGCNN",
|
|
99
|
+
"EMG2QwertyNet",
|
|
93
100
|
"FBCNet",
|
|
94
101
|
"FBLightConvNet",
|
|
95
102
|
"FBMSNet",
|
|
103
|
+
"MetaNeuromotorHand",
|
|
96
104
|
"HybridNet",
|
|
97
105
|
"IFNet",
|
|
106
|
+
"InterpolatedBENDR",
|
|
107
|
+
"InterpolatedBIOT",
|
|
108
|
+
"InterpolatedLaBraM",
|
|
109
|
+
"InterpolatedModel",
|
|
110
|
+
"InterpolatedSignalJEPA",
|
|
98
111
|
"Labram",
|
|
99
112
|
"LUNA",
|
|
100
113
|
"extract_channel_locations_from_chs_info",
|
|
@@ -33,13 +33,25 @@ huggingface_hub = _soft_import(
|
|
|
33
33
|
HAS_HF_HUB = huggingface_hub is not False
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
_HF_INSTALL_HINT = (
|
|
37
|
+
"requires the `huggingface_hub` package. "
|
|
38
|
+
"Install with: pip install 'braindecode[hub]'"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class _BaseHubMixinStub:
|
|
43
|
+
@classmethod
|
|
44
|
+
def from_pretrained(cls, *args, **kwargs):
|
|
45
|
+
raise ImportError(f"{cls.__name__}.from_pretrained() {_HF_INSTALL_HINT}")
|
|
46
|
+
|
|
47
|
+
def push_to_hub(self, *args, **kwargs):
|
|
48
|
+
raise ImportError(f"{type(self).__name__}.push_to_hub() {_HF_INSTALL_HINT}")
|
|
38
49
|
|
|
39
50
|
|
|
40
51
|
# Define base class for hub mixin
|
|
41
|
-
|
|
42
|
-
|
|
52
|
+
_BaseHubMixin: Type = (
|
|
53
|
+
huggingface_hub.PyTorchModelHubMixin if HAS_HF_HUB else _BaseHubMixinStub
|
|
54
|
+
)
|
|
43
55
|
|
|
44
56
|
|
|
45
57
|
def deprecated_args(obj, *old_new_args):
|