braindecode 1.8.1.dev174129228__tar.gz → 1.8.1.dev174246559__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.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/NOTICE.txt +1 -0
- {braindecode-1.8.1.dev174129228/braindecode.egg-info → braindecode-1.8.1.dev174246559}/PKG-INFO +1 -1
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/classifier.py +6 -5
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/eegneuralnet.py +1 -1
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/functional/__init__.py +2 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/functional/functions.py +27 -2
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/__init__.py +6 -14
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/attn_sleep.py +0 -4
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/barista.py +4 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/base.py +88 -16
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/bendr.py +37 -52
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/biot.py +32 -55
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/brainbert.py +8 -3
- braindecode-1.8.1.dev174246559/braindecode/models/brainomni.py +917 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/brant.py +12 -10
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/cbramod.py +7 -2
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/codebrain.py +26 -16
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/config.py +1 -2
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/contrawr.py +4 -4
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/dgcnn.py +3 -1
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/diver1.py +8 -5
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/eegdino.py +18 -5
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/eegpt.py +5 -27
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/eegsym.py +17 -7
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/emg2qwerty.py +19 -2
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/labram.py +161 -157
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/luna.py +21 -9
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/mapa.py +6 -4
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/meta_neuromotor.py +25 -2
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/mirepnet.py +16 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/mvpformer.py +6 -1
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/neurorvq.py +156 -179
- braindecode-1.8.1.dev174246559/braindecode/models/neurorvq_tokenizer.py +582 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/popt.py +4 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/reve.py +9 -1
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/sensingdynamics.py +10 -5
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/signal_jepa.py +27 -19
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/sleepfm.py +28 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/steegformer.py +4 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/summary.csv +1 -5
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/syncnet.py +2 -2
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/tcformer.py +6 -5
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/util.py +25 -57
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/zuna.py +18 -9
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/modules/__init__.py +2 -4
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/modules/blocks.py +18 -5
- braindecode-1.8.1.dev174246559/braindecode/modules/channels.py +459 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/modules/filter.py +22 -30
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/modules/quantization.py +13 -10
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/modules/stats.py +6 -1
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/regressor.py +6 -5
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/training/scoring.py +6 -5
- braindecode-1.8.1.dev174246559/braindecode/version.py +1 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/visualization/topology.py +1 -1
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559/braindecode.egg-info}/PKG-INFO +1 -1
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode.egg-info/SOURCES.txt +4 -4
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/api.rst +19 -9
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/index.rst +1 -0
- braindecode-1.8.1.dev174246559/docs/user_guide/channel_strategies.rst +59 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/whats_new.rst +73 -14
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/pyproject.toml +3 -0
- braindecode-1.8.1.dev174129228/braindecode/models/brainomni.py +0 -1971
- braindecode-1.8.1.dev174129228/braindecode/models/interpolated.py +0 -185
- braindecode-1.8.1.dev174129228/braindecode/modules/channel_tokenizer.py +0 -215
- braindecode-1.8.1.dev174129228/braindecode/modules/interpolation.py +0 -201
- braindecode-1.8.1.dev174129228/braindecode/version.py +0 -1
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/LICENSE.txt +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/MANIFEST.in +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/README.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/__init__.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/augmentation/__init__.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/augmentation/base.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/augmentation/functional.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/augmentation/transforms.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/__init__.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/_notebook_viewer.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/base.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/bbci.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/bcicomp.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/bids/__init__.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/bids/datasets.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/bids/format.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/bids/hub.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/bids/hub_format.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/bids/hub_io.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/bids/hub_validation.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/bids/iterable.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/chb_mit.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/collate.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/mne.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/moabb.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/nmt.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/registry.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/siena.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/sleep_physionet.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/tuh.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/utils.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datasets/xy.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datautil/__init__.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datautil/channel_utils.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datautil/hub_formats.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datautil/serialization.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/datautil/util.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/functional/_real_dft.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/functional/initialization.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/atcnet.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/attentionbasenet.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/brainmodule.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/csbrain.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/ctnet.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/dance.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/deep4.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/deepsleepnet.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/eegconformer.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/eeginception_erp.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/eeginception_mi.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/eegitnet.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/eegminer.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/eegnet.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/eegnex.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/eegsimpleconv.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/eegtcnet.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/fbcnet.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/fblightconvnet.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/fbmsnet.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/hybrid.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/ifnet.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/medformer.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/mscformer.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/msvtnet.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/neuropose.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/patchedtransformer.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/sccnet.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/seizure_transformer.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/shallow_fbcsp.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/sinc_shallow.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/sparcnet.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/sstdpn.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/tcn.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/tidnet.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/tsinception.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/usleep.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/vemg2pose.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/modules/activation.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/modules/attention.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/modules/convolution.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/modules/dance_modules.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/modules/layers.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/modules/linear.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/modules/parametrization.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/modules/popt_modules.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/modules/util.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/modules/wrapper.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/preprocessing/__init__.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/preprocessing/mne_preprocess.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/preprocessing/preprocess.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/preprocessing/util.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/preprocessing/windowers.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/samplers/__init__.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/samplers/base.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/samplers/ssl.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/training/__init__.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/training/callbacks.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/training/losses.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/util.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/visualization/__init__.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/visualization/activations.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/visualization/attribution.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/visualization/confusion_matrices.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/visualization/frequency.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/visualization/metrics.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/visualization/sanity.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode.egg-info/dependency_links.txt +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode.egg-info/requires.txt +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode.egg-info/top_level.txt +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/Makefile +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/_templates/autosummary/class.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/_templates/autosummary/function.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/agent_docs.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/cite.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/conf.py +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/help.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/install/install.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/install/install_pip.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/install/install_source.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/models/categorization/attention.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/models/categorization/channel.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/models/categorization/convolution.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/models/categorization/filterbank.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/models/categorization/gnn.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/models/categorization/interpretable.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/models/categorization/lbm.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/models/categorization/recurrent.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/models/categorization/spd.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/models/models.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/models/models_categorization.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/models/models_table.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/models/models_visualization.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/docs/sg_execution_times.rst +0 -0
- {braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/setup.cfg +0 -0
|
@@ -16,6 +16,7 @@ The following components are licensed under the Creative Commons Attribution-Non
|
|
|
16
16
|
- `braindecode/models/sleepfm.py`
|
|
17
17
|
- `braindecode/models/brainmodule.py`
|
|
18
18
|
- `braindecode/models/neurorvq.py`
|
|
19
|
+
- `braindecode/models/neurorvq_tokenizer.py`
|
|
19
20
|
|
|
20
21
|
The `meta_neuromotor.py` file is a derivative of
|
|
21
22
|
`facebookresearch/generic-neuromotor-interface`, released by Meta Platforms,
|
{braindecode-1.8.1.dev174129228/braindecode.egg-info → braindecode-1.8.1.dev174246559}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: braindecode
|
|
3
|
-
Version: 1.8.1.
|
|
3
|
+
Version: 1.8.1.dev174246559
|
|
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>
|
|
@@ -212,11 +212,12 @@ class EEGClassifier(_EEGNeuralNet, NeuralNetClassifier):
|
|
|
212
212
|
the number of predictions depend on the chosen window size and the
|
|
213
213
|
receptive field of the network. If trials have different lengths,
|
|
214
214
|
a list with one (n_classes x n_predictions) array per trial.
|
|
215
|
-
trial_targets : np.ndarray
|
|
216
|
-
Ground-truth targets from the dataset
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
215
|
+
trial_targets : np.ndarray | list of np.ndarray
|
|
216
|
+
Ground-truth targets from the dataset. Only returned when
|
|
217
|
+
``return_targets=True``. An ``np.ndarray`` with a leading trial
|
|
218
|
+
dimension: ``(n_trials,)`` for scalar targets, with further
|
|
219
|
+
dimensions for multi-value or equal-length sequence targets. If
|
|
220
|
+
trial lengths differ, a list with one target array per trial.
|
|
220
221
|
"""
|
|
221
222
|
if not self.cropped:
|
|
222
223
|
warnings.warn(
|
{braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/eegneuralnet.py
RENAMED
|
@@ -144,7 +144,7 @@ class _EEGNeuralNet(NeuralNet, abc.ABC):
|
|
|
144
144
|
i_window_in_trials.append(i[0].cpu().numpy())
|
|
145
145
|
i_window_stops.append(i[2].cpu().numpy())
|
|
146
146
|
with torch.no_grad():
|
|
147
|
-
preds.append(to_numpy(self.module_
|
|
147
|
+
preds.append(to_numpy(self.module_(X.to(self.device))))
|
|
148
148
|
window_ys.append(y.cpu().numpy())
|
|
149
149
|
preds = np.concatenate(preds)
|
|
150
150
|
i_window_in_trials = np.concatenate(i_window_in_trials)
|
{braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/functional/__init__.py
RENAMED
|
@@ -11,6 +11,7 @@ from .functions import (
|
|
|
11
11
|
rotate_pairs,
|
|
12
12
|
safe_log,
|
|
13
13
|
sinusoidal_positional_encoding,
|
|
14
|
+
spectral_input,
|
|
14
15
|
square,
|
|
15
16
|
wavelet_decomposition,
|
|
16
17
|
)
|
|
@@ -29,6 +30,7 @@ __all__ = [
|
|
|
29
30
|
"rotate_pairs",
|
|
30
31
|
"safe_log",
|
|
31
32
|
"sinusoidal_positional_encoding",
|
|
33
|
+
"spectral_input",
|
|
32
34
|
"square",
|
|
33
35
|
"wavelet_decomposition",
|
|
34
36
|
"glorot_weight_zero_bias",
|
|
@@ -28,6 +28,32 @@ def identity(x):
|
|
|
28
28
|
return x
|
|
29
29
|
|
|
30
30
|
|
|
31
|
+
def spectral_input(x: torch.Tensor) -> torch.Tensor:
|
|
32
|
+
"""Prepare ``x`` for an FFT, STFT or eigendecomposition.
|
|
33
|
+
|
|
34
|
+
PyTorch has no complex bfloat16 dtype: CPU and MPS FFTs reject
|
|
35
|
+
bfloat16/float16, and Intel Gaudi (HPU) has no complex tensors at all.
|
|
36
|
+
This returns ``x`` in at least float32, moved to the CPU when it lives on
|
|
37
|
+
an HPU; float32/float64 CPU/CUDA inputs are returned as they are. Cast a
|
|
38
|
+
real result back with ``.to(x)`` (the input's dtype and device)::
|
|
39
|
+
|
|
40
|
+
spectrum = torch.fft.rfft(spectral_input(x), dim=-1).abs().to(x)
|
|
41
|
+
|
|
42
|
+
Parameters
|
|
43
|
+
----------
|
|
44
|
+
x : torch.Tensor
|
|
45
|
+
Real input of the spectral operation.
|
|
46
|
+
|
|
47
|
+
Returns
|
|
48
|
+
-------
|
|
49
|
+
torch.Tensor
|
|
50
|
+
``x`` in ``promote_types(x.dtype, float32)``, on the CPU for HPU inputs.
|
|
51
|
+
"""
|
|
52
|
+
if x.device.type == "hpu":
|
|
53
|
+
x = x.cpu()
|
|
54
|
+
return x.to(torch.promote_types(x.dtype, torch.float32))
|
|
55
|
+
|
|
56
|
+
|
|
31
57
|
def drop_path(
|
|
32
58
|
x, drop_prob: float = 0.0, training: bool = False, scale_by_keep: bool = True
|
|
33
59
|
):
|
|
@@ -176,8 +202,7 @@ def hilbert_freq(x: torch.Tensor, forward_fourier: bool = True) -> torch.Tensor:
|
|
|
176
202
|
# the complex-valued part in float32 and restore the real-valued contract
|
|
177
203
|
# at the boundary. Promoting before the FFT also covers backends that do
|
|
178
204
|
# not implement bfloat16 FFT kernels.
|
|
179
|
-
|
|
180
|
-
x = x.float()
|
|
205
|
+
x = spectral_input(x)
|
|
181
206
|
|
|
182
207
|
if forward_fourier:
|
|
183
208
|
seq_len = x.shape[-1]
|
{braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/__init__.py
RENAMED
|
@@ -5,8 +5,8 @@ from .attentionbasenet import AttentionBaseNet
|
|
|
5
5
|
from .attn_sleep import AttnSleep
|
|
6
6
|
from .barista import BaRISTA
|
|
7
7
|
from .base import EEGModuleMixin
|
|
8
|
-
from .bendr import BENDR
|
|
9
|
-
from .biot import BIOT
|
|
8
|
+
from .bendr import BENDR
|
|
9
|
+
from .biot import BIOT
|
|
10
10
|
from .brainbert import BrainBERT
|
|
11
11
|
from .brainmodule import BrainModule
|
|
12
12
|
from .brainomni import BrainOmni, BrainTokenizer
|
|
@@ -29,7 +29,7 @@ from .eegitnet import EEGITNet
|
|
|
29
29
|
from .eegminer import EEGMiner
|
|
30
30
|
from .eegnet import EEGNet
|
|
31
31
|
from .eegnex import EEGNeX
|
|
32
|
-
from .eegpt import EEGPT
|
|
32
|
+
from .eegpt import EEGPT
|
|
33
33
|
from .eegsimpleconv import EEGSimpleConv
|
|
34
34
|
from .eegsym import EEGSym
|
|
35
35
|
from .eegtcnet import EEGTCNet
|
|
@@ -39,8 +39,7 @@ from .fblightconvnet import FBLightConvNet
|
|
|
39
39
|
from .fbmsnet import FBMSNet
|
|
40
40
|
from .hybrid import HybridNet
|
|
41
41
|
from .ifnet import IFNet
|
|
42
|
-
from .
|
|
43
|
-
from .labram import InterpolatedLaBraM, Labram
|
|
42
|
+
from .labram import Labram
|
|
44
43
|
from .luna import LUNA
|
|
45
44
|
from .mapa import MAPA
|
|
46
45
|
from .medformer import MEDFormer
|
|
@@ -51,6 +50,7 @@ from .msvtnet import MSVTNet
|
|
|
51
50
|
from .mvpformer import MVPFormer
|
|
52
51
|
from .neuropose import NeuroPose
|
|
53
52
|
from .neurorvq import NeuroRVQ
|
|
53
|
+
from .neurorvq_tokenizer import NeuroRVQTokenizer
|
|
54
54
|
from .patchedtransformer import PBT
|
|
55
55
|
from .popt import PopulationTransformer
|
|
56
56
|
from .reve import REVE
|
|
@@ -59,7 +59,6 @@ from .seizure_transformer import SeizureTransformer
|
|
|
59
59
|
from .sensingdynamics import SensingDynamics
|
|
60
60
|
from .shallow_fbcsp import ShallowFBCSPNet
|
|
61
61
|
from .signal_jepa import (
|
|
62
|
-
InterpolatedSignalJEPA,
|
|
63
62
|
SignalJEPA,
|
|
64
63
|
SignalJEPA_Contextual,
|
|
65
64
|
SignalJEPA_PostLocal,
|
|
@@ -82,7 +81,6 @@ from .util import (
|
|
|
82
81
|
_init_models_dict,
|
|
83
82
|
build_model_config,
|
|
84
83
|
extract_channel_locations_from_chs_info,
|
|
85
|
-
interpolated_models_dict,
|
|
86
84
|
models_mandatory_parameters,
|
|
87
85
|
positions_from_chs_info,
|
|
88
86
|
)
|
|
@@ -118,7 +116,6 @@ __all__ = [
|
|
|
118
116
|
"EEGConformer",
|
|
119
117
|
"EEGDINO",
|
|
120
118
|
"EEGPT",
|
|
121
|
-
"InterpolatedEEGPT",
|
|
122
119
|
"EEGInceptionERP",
|
|
123
120
|
"EEGInceptionMI",
|
|
124
121
|
"EEGITNet",
|
|
@@ -139,11 +136,6 @@ __all__ = [
|
|
|
139
136
|
"MetaNeuromotorHand",
|
|
140
137
|
"HybridNet",
|
|
141
138
|
"IFNet",
|
|
142
|
-
"InterpolatedBENDR",
|
|
143
|
-
"InterpolatedBIOT",
|
|
144
|
-
"InterpolatedLaBraM",
|
|
145
|
-
"InterpolatedModel",
|
|
146
|
-
"InterpolatedSignalJEPA",
|
|
147
139
|
"Labram",
|
|
148
140
|
"LUNA",
|
|
149
141
|
"extract_channel_locations_from_chs_info",
|
|
@@ -153,6 +145,7 @@ __all__ = [
|
|
|
153
145
|
"MIRepNet",
|
|
154
146
|
"NeuroRVQ",
|
|
155
147
|
"MSCFormer",
|
|
148
|
+
"NeuroRVQTokenizer",
|
|
156
149
|
"MSVTNet",
|
|
157
150
|
"MVPFormer",
|
|
158
151
|
"PBT",
|
|
@@ -184,5 +177,4 @@ __all__ = [
|
|
|
184
177
|
"build_model_config",
|
|
185
178
|
"_init_models_dict",
|
|
186
179
|
"models_mandatory_parameters",
|
|
187
|
-
"interpolated_models_dict",
|
|
188
180
|
]
|
{braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/attn_sleep.py
RENAMED
|
@@ -436,7 +436,6 @@ class _MultiHeadedAttention(nn.Module):
|
|
|
436
436
|
h = int(h)
|
|
437
437
|
self.d_per_head = d_model // h
|
|
438
438
|
self.h = h
|
|
439
|
-
self.attn = torch.empty(0)
|
|
440
439
|
|
|
441
440
|
base_conv = CausalConv1d(
|
|
442
441
|
in_channels=after_reduced_cnn_size,
|
|
@@ -471,9 +470,6 @@ class _MultiHeadedAttention(nn.Module):
|
|
|
471
470
|
# recompute the weighted sum with dropped weights
|
|
472
471
|
x = torch.matmul(attn, value)
|
|
473
472
|
|
|
474
|
-
# stash the pre‑dropout weights if you need them
|
|
475
|
-
self.attn = attn_weights
|
|
476
|
-
|
|
477
473
|
# merge heads and project
|
|
478
474
|
x = x.transpose(1, 2).contiguous().view(nbatches, -1, self.h * self.d_per_head)
|
|
479
475
|
|
{braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/barista.py
RENAMED
|
@@ -205,6 +205,8 @@ class BaRISTA(EEGModuleMixin, nn.Module, license="other"):
|
|
|
205
205
|
pooling: str = "learned",
|
|
206
206
|
drop_prob: float = 0.1,
|
|
207
207
|
activation: type[nn.Module] = nn.GELU,
|
|
208
|
+
channel_strategy: str = "native",
|
|
209
|
+
channel_strategy_kwargs: dict | None = None,
|
|
208
210
|
):
|
|
209
211
|
super().__init__(
|
|
210
212
|
n_outputs=n_outputs,
|
|
@@ -213,6 +215,8 @@ class BaRISTA(EEGModuleMixin, nn.Module, license="other"):
|
|
|
213
215
|
n_times=n_times,
|
|
214
216
|
input_window_seconds=input_window_seconds,
|
|
215
217
|
sfreq=sfreq,
|
|
218
|
+
channel_strategy=channel_strategy,
|
|
219
|
+
channel_strategy_kwargs=channel_strategy_kwargs,
|
|
216
220
|
)
|
|
217
221
|
del n_outputs, n_chans, chs_info, n_times, input_window_seconds, sfreq
|
|
218
222
|
|
{braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/base.py
RENAMED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
|
+
import inspect
|
|
8
9
|
import json
|
|
9
10
|
import warnings
|
|
10
11
|
from collections import OrderedDict
|
|
@@ -24,6 +25,7 @@ from braindecode.models.util import (
|
|
|
24
25
|
resolve_type_kwargs,
|
|
25
26
|
track_model_init_kwargs,
|
|
26
27
|
)
|
|
28
|
+
from braindecode.modules.channels import ChannelLayer
|
|
27
29
|
from braindecode.version import __version__
|
|
28
30
|
|
|
29
31
|
huggingface_hub = _soft_import(
|
|
@@ -32,6 +34,16 @@ huggingface_hub = _soft_import(
|
|
|
32
34
|
|
|
33
35
|
HAS_HF_HUB = huggingface_hub is not False
|
|
34
36
|
|
|
37
|
+
# __init__ args that from_pretrained fills from config.json when not given.
|
|
38
|
+
_GEOMETRY_KWARGS = (
|
|
39
|
+
"n_outputs",
|
|
40
|
+
"n_chans",
|
|
41
|
+
"chs_info",
|
|
42
|
+
"n_times",
|
|
43
|
+
"input_window_seconds",
|
|
44
|
+
"sfreq",
|
|
45
|
+
)
|
|
46
|
+
|
|
35
47
|
|
|
36
48
|
_HF_INSTALL_HINT = (
|
|
37
49
|
"requires the `huggingface_hub` package. "
|
|
@@ -113,6 +125,17 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
|
|
|
113
125
|
Length of the input window in seconds.
|
|
114
126
|
sfreq : float
|
|
115
127
|
Sampling frequency of the EEG recordings.
|
|
128
|
+
channel_strategy : str, default="native"
|
|
129
|
+
How any montage reaches the backbone (pretrained models only; see
|
|
130
|
+
:doc:`/user_guide/channel_strategies`). ``"native"`` keeps the model as
|
|
131
|
+
it is. ``"exact"``, ``"zero"``, ``"nearest"``, ``"idw"``, ``"spline"``,
|
|
132
|
+
``"field"``, ``"source"``, ``"region"``, ``"wiener"`` (call
|
|
133
|
+
``model.channel_layer.fit`` first) or ``"latent"`` map the montage of ``chs_info`` (or of the
|
|
134
|
+
``chs_info`` given to ``forward``) onto the backbone's channels with a
|
|
135
|
+
:class:`~braindecode.modules.ChannelLayer`. Saved in the config.
|
|
136
|
+
``model(x)`` and ``model.forward(x)`` both apply the layer.
|
|
137
|
+
channel_strategy_kwargs : dict or None, default=None
|
|
138
|
+
Options of the strategy (e.g. ``{"reg": 1e-2}`` for ``"spline"``).
|
|
116
139
|
|
|
117
140
|
Raises
|
|
118
141
|
------
|
|
@@ -286,6 +309,8 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
|
|
|
286
309
|
n_times: Optional[int] = None, # type: ignore[assignment]
|
|
287
310
|
input_window_seconds: Optional[float] = None, # type: ignore[assignment]
|
|
288
311
|
sfreq: Optional[float] = None, # type: ignore[assignment]
|
|
312
|
+
channel_strategy: str = "native",
|
|
313
|
+
channel_strategy_kwargs: Optional[dict] = None,
|
|
289
314
|
):
|
|
290
315
|
# Deserialize chs_info if it comes as a list of dicts (from Hub)
|
|
291
316
|
if chs_info is not None and isinstance(chs_info, list):
|
|
@@ -308,6 +333,26 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
|
|
|
308
333
|
raise ValueError(
|
|
309
334
|
f"{n_times=} different from {input_window_seconds=} * {sfreq=}"
|
|
310
335
|
)
|
|
336
|
+
layer = None
|
|
337
|
+
if channel_strategy != "native": # the backbone is built on the target
|
|
338
|
+
target = self._channel_target or chs_info
|
|
339
|
+
if target is None:
|
|
340
|
+
raise ValueError(
|
|
341
|
+
f"channel_strategy={channel_strategy!r} needs chs_info."
|
|
342
|
+
)
|
|
343
|
+
target = [
|
|
344
|
+
c
|
|
345
|
+
if isinstance(c, dict)
|
|
346
|
+
else {"ch_name": c, "kind": "eeg", "loc": np.zeros(12)}
|
|
347
|
+
for c in target
|
|
348
|
+
]
|
|
349
|
+
kwargs = channel_strategy_kwargs or {}
|
|
350
|
+
layer = ChannelLayer(target, channel_strategy, chs_info, **kwargs)
|
|
351
|
+
chs_info, n_chans = layer.target, None
|
|
352
|
+
elif channel_strategy_kwargs:
|
|
353
|
+
raise ValueError(
|
|
354
|
+
"channel_strategy='native' takes no channel_strategy_kwargs."
|
|
355
|
+
)
|
|
311
356
|
|
|
312
357
|
self._input_window_seconds = input_window_seconds # type: ignore[assignment]
|
|
313
358
|
self._chs_info = chs_info # type: ignore[assignment]
|
|
@@ -334,6 +379,22 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
|
|
|
334
379
|
setattr(self, key, val)
|
|
335
380
|
|
|
336
381
|
super().__init__()
|
|
382
|
+
if layer is not None:
|
|
383
|
+
self.channel_layer = layer
|
|
384
|
+
# Instance attribute: model(x) and model.forward(x) both map x.
|
|
385
|
+
setattr(self, "forward", self._channel_forward)
|
|
386
|
+
|
|
387
|
+
def _channel_forward(self, *args, chs_info=None, ch_names=None, **kwargs):
|
|
388
|
+
"""``forward`` under a channel strategy: map ``x`` (recorded with
|
|
389
|
+
``chs_info``, default the model's) onto the target, then run the backbone."""
|
|
390
|
+
if chs_info is None and ch_names is not None: # LaBraM: names of x's channels
|
|
391
|
+
chs_info = [{"ch_name": n} for n in ch_names]
|
|
392
|
+
if args:
|
|
393
|
+
args = (self.channel_layer(args[0], chs_info)[0], *args[1:])
|
|
394
|
+
else: # x by keyword: the backbone's first input (x, X, eeg...)
|
|
395
|
+
x = list(inspect.signature(type(self).forward).parameters)[1]
|
|
396
|
+
kwargs[x] = self.channel_layer(kwargs[x], chs_info)[0]
|
|
397
|
+
return type(self).forward(self, *args, **kwargs)
|
|
337
398
|
|
|
338
399
|
@property
|
|
339
400
|
def n_outputs(self) -> int:
|
|
@@ -424,13 +485,16 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
|
|
|
424
485
|
with torch.inference_mode():
|
|
425
486
|
try:
|
|
426
487
|
return tuple(
|
|
427
|
-
self
|
|
488
|
+
type(self)
|
|
489
|
+
.forward( # the backbone, on its own channels
|
|
490
|
+
self,
|
|
428
491
|
torch.zeros(
|
|
429
492
|
self.input_shape,
|
|
430
493
|
dtype=next(self.parameters()).dtype, # type: ignore
|
|
431
494
|
device=next(self.parameters()).device, # type: ignore
|
|
432
|
-
)
|
|
433
|
-
)
|
|
495
|
+
),
|
|
496
|
+
)
|
|
497
|
+
.shape
|
|
434
498
|
)
|
|
435
499
|
except RuntimeError as exc:
|
|
436
500
|
if str(exc).endswith(
|
|
@@ -596,6 +660,9 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
|
|
|
596
660
|
)
|
|
597
661
|
|
|
598
662
|
mapping: Optional[Dict[str, str]] = None
|
|
663
|
+
#: Channels the backbone consumes under a ``channel_strategy`` (names or
|
|
664
|
+
#: ``chs_info``); ``None``: the model's own ``chs_info``.
|
|
665
|
+
_channel_target: Optional[list] = None
|
|
599
666
|
|
|
600
667
|
def load_state_dict(self, state_dict, *args, **kwargs):
|
|
601
668
|
mapping = self.mapping if self.mapping else {}
|
|
@@ -605,7 +672,10 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
|
|
|
605
672
|
new_state_dict[mapping[k]] = v
|
|
606
673
|
else:
|
|
607
674
|
new_state_dict[k] = v
|
|
608
|
-
|
|
675
|
+
# A backbone checkpoint has no weights for a trainable channel layer.
|
|
676
|
+
for k, v in super().state_dict().items():
|
|
677
|
+
if k.startswith("channel_layer.") and k not in new_state_dict:
|
|
678
|
+
new_state_dict[k] = v
|
|
609
679
|
return super().load_state_dict(new_state_dict, *args, **kwargs)
|
|
610
680
|
|
|
611
681
|
def to_dense_prediction_model(self, axis: tuple[int, ...] | int = (2, 3)) -> None:
|
|
@@ -781,18 +851,20 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
|
|
|
781
851
|
|
|
782
852
|
@classmethod
|
|
783
853
|
def from_pretrained(cls, *args, **kwargs):
|
|
784
|
-
# The Hub mixin fills
|
|
785
|
-
#
|
|
786
|
-
#
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
if
|
|
793
|
-
"
|
|
794
|
-
|
|
795
|
-
kwargs
|
|
854
|
+
# The Hub mixin fills only the __init__ args whose keys are absent,
|
|
855
|
+
# so drop explicit Nones (e.g. forwarded by a wrapper) to let the
|
|
856
|
+
# saved values fill them. Then pin the derived geometry arg so it
|
|
857
|
+
# cannot clash with the caller's one (e.g. caller chs_info vs saved
|
|
858
|
+
# n_chans) in __init__'s checks.
|
|
859
|
+
for key in _GEOMETRY_KWARGS:
|
|
860
|
+
if key in kwargs and kwargs[key] is None:
|
|
861
|
+
del kwargs[key]
|
|
862
|
+
if "chs_info" in kwargs:
|
|
863
|
+
kwargs.setdefault("n_chans", len(kwargs["chs_info"]))
|
|
864
|
+
elif "n_chans" in kwargs:
|
|
865
|
+
kwargs.setdefault("chs_info", None)
|
|
866
|
+
if "n_times" in kwargs or "sfreq" in kwargs:
|
|
867
|
+
kwargs.setdefault("input_window_seconds", None)
|
|
796
868
|
return super().from_pretrained(*args, **kwargs)
|
|
797
869
|
|
|
798
870
|
@classmethod
|
{braindecode-1.8.1.dev174129228 → braindecode-1.8.1.dev174246559}/braindecode/models/bendr.py
RENAMED
|
@@ -11,48 +11,48 @@ from einops.layers.torch import Rearrange
|
|
|
11
11
|
from torch import nn
|
|
12
12
|
|
|
13
13
|
from braindecode.models.base import EEGModuleMixin
|
|
14
|
-
from braindecode.modules.
|
|
14
|
+
from braindecode.modules.channels import ChannelLayer
|
|
15
15
|
|
|
16
16
|
# The 20 channels used to pre-train BENDR, in the order expected by the
|
|
17
17
|
# `braindecode/braindecode-bendr` checkpoint. The first 19 entries are the
|
|
18
18
|
# EEG channels taken verbatim from `dn3.transforms.instance.To1020.EEG_20_div`
|
|
19
19
|
# (https://github.com/SPOClab-ca/dn3/blob/master/dn3/transforms/instance.py).
|
|
20
|
-
# Their positions come from MNE's ``standard_1005`` montage
|
|
21
|
-
#
|
|
20
|
+
# Their positions come from MNE's ``standard_1005`` montage in the head
|
|
21
|
+
# frame, as ``raw.set_montage`` gives them (T5/T6 are legacy names that
|
|
22
|
+
# share positions with P7/P8 there).
|
|
22
23
|
#
|
|
23
24
|
# The 20th entry is ``SCALE``, a relative-amplitude statistic (not an
|
|
24
25
|
# electrode) appended by ``To1020(include_scale_ch=True)`` during
|
|
25
26
|
# pre-training. Since it has no physical position, the ``loc`` below is
|
|
26
|
-
# the centroid of the 19 EEG positions — purely a placeholder
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
# matrix. It is NOT the SCALE the pre-training pipeline computes
|
|
27
|
+
# the centroid of the 19 EEG positions — purely a placeholder for the
|
|
28
|
+
# spline that ``channel_strategy="native"`` applies to other montages.
|
|
29
|
+
# Any other ``channel_strategy`` leaves SCALE at zero unless the input has it. It is NOT the SCALE the pre-training pipeline computes
|
|
30
30
|
# (which is an RMS-like amplitude via ``dn3.MappingDeep1010``); users
|
|
31
31
|
# who need a faithful SCALE must compute it themselves and feed 20
|
|
32
32
|
# channels to :class:`BENDR` directly.
|
|
33
33
|
_BENDR_TARGET_CHS_TUPLES: list[tuple[str, tuple[float, float, float]]] = [
|
|
34
|
-
("FP1", (-0.
|
|
35
|
-
("FP2", (+0.
|
|
36
|
-
("F7", (-0.
|
|
37
|
-
("F3", (-0.
|
|
38
|
-
("FZ", (
|
|
39
|
-
("F4", (+0.
|
|
40
|
-
("F8", (+0.
|
|
41
|
-
("T7", (-0.
|
|
42
|
-
("C3", (-0.
|
|
43
|
-
("CZ", (
|
|
44
|
-
("C4", (+0.
|
|
45
|
-
("T8", (+0.
|
|
46
|
-
("T5", (-0.
|
|
47
|
-
("P3", (-0.
|
|
48
|
-
("PZ", (
|
|
49
|
-
("P4", (+0.
|
|
50
|
-
("T6", (+0.
|
|
51
|
-
("O1", (-0.
|
|
52
|
-
("O2", (+0.
|
|
34
|
+
("FP1", (-0.0309026, +0.1145852, +0.0278666)), # standard_1005
|
|
35
|
+
("FP2", (+0.0284095, +0.1153463, +0.0277213)), # standard_1005
|
|
36
|
+
("F7", (-0.0718766, +0.0731035, +0.0257905)), # standard_1005
|
|
37
|
+
("F3", (-0.0518090, +0.0866879, +0.0787141)), # standard_1005
|
|
38
|
+
("FZ", (-0.0012293, +0.0932745, +0.1026393)), # standard_1005
|
|
39
|
+
("F4", (+0.0502743, +0.0874384, +0.0772707)), # standard_1005
|
|
40
|
+
("F8", (+0.0714353, +0.0745051, +0.0251010)), # standard_1005
|
|
41
|
+
("T7", (-0.0859821, +0.0148716, +0.0311734)), # standard_1005
|
|
42
|
+
("C3", (-0.0671487, +0.0233582, +0.1045107)), # standard_1005
|
|
43
|
+
("CZ", (-0.0013741, +0.0276171, +0.1401995)), # standard_1005
|
|
44
|
+
("C4", (+0.0653289, +0.0235731, +0.1036924)), # standard_1005
|
|
45
|
+
("T8", (+0.0832614, +0.0152582, +0.0309730)), # standard_1005
|
|
46
|
+
("T5", (-0.0744580, -0.0421232, +0.0412736)), # standard_1005 (= P7)
|
|
47
|
+
("P3", (-0.0550382, -0.0442103, +0.0999090)), # standard_1005
|
|
48
|
+
("PZ", (-0.0017095, -0.0452130, +0.1266729)), # standard_1005
|
|
49
|
+
("P4", (+0.0536360, -0.0443345, +0.1005160)), # standard_1005
|
|
50
|
+
("T6", (+0.0710325, -0.0422600, +0.0411989)), # standard_1005 (= P8)
|
|
51
|
+
("O1", (-0.0315736, -0.0805684, +0.0547896)), # standard_1005
|
|
52
|
+
("O2", (+0.0276831, -0.0804888, +0.0547341)), # standard_1005
|
|
53
53
|
(
|
|
54
54
|
"SCALE",
|
|
55
|
-
(
|
|
55
|
+
(-0.0011601, +0.0194958, +0.0681445),
|
|
56
56
|
), # centroid of the 19 EEG positions (placeholder; see comment above)
|
|
57
57
|
]
|
|
58
58
|
|
|
@@ -251,6 +251,8 @@ class BENDR(EEGModuleMixin, nn.Module):
|
|
|
251
251
|
``4 * product(enc_downsample)`` samples (384 with default downsampling of 96x).
|
|
252
252
|
"""
|
|
253
253
|
|
|
254
|
+
_channel_target = BENDR_CHANNEL_ORDER
|
|
255
|
+
|
|
254
256
|
def __init__(
|
|
255
257
|
self,
|
|
256
258
|
# Signal related parameters
|
|
@@ -276,6 +278,8 @@ class BENDR(EEGModuleMixin, nn.Module):
|
|
|
276
278
|
start_token=-5, # Value for start token embedding
|
|
277
279
|
final_layer=True, # Whether to include the final linear layer
|
|
278
280
|
encoder_only=False, # If True, bypass contextualizer and use 4-chunk pooling
|
|
281
|
+
channel_strategy: str = "native",
|
|
282
|
+
channel_strategy_kwargs: dict | None = None,
|
|
279
283
|
):
|
|
280
284
|
super().__init__(
|
|
281
285
|
n_outputs=n_outputs,
|
|
@@ -284,6 +288,8 @@ class BENDR(EEGModuleMixin, nn.Module):
|
|
|
284
288
|
n_times=n_times,
|
|
285
289
|
input_window_seconds=input_window_seconds,
|
|
286
290
|
sfreq=sfreq,
|
|
291
|
+
channel_strategy=channel_strategy,
|
|
292
|
+
channel_strategy_kwargs=channel_strategy_kwargs,
|
|
287
293
|
)
|
|
288
294
|
|
|
289
295
|
# Keep these parameters if needed later, otherwise they are captured by the mixin
|
|
@@ -302,10 +308,8 @@ class BENDR(EEGModuleMixin, nn.Module):
|
|
|
302
308
|
user_names = [ch["ch_name"] for ch in _chs_info] # type: ignore[index]
|
|
303
309
|
canonical = BENDR_CHANNEL_ORDER
|
|
304
310
|
if [n.lower() for n in user_names] != [n.lower() for n in canonical]:
|
|
305
|
-
self.channel_tokenizer =
|
|
306
|
-
|
|
307
|
-
src_chs_info=_chs_info,
|
|
308
|
-
target_chs_info=_BENDR_TARGET_CHS_INFO,
|
|
311
|
+
self.channel_tokenizer = ChannelLayer(
|
|
312
|
+
_BENDR_TARGET_CHS_INFO, "spline", _chs_info, reg=0.0
|
|
309
313
|
)
|
|
310
314
|
backbone_n_chans = len(_BENDR_TARGET_CHS_INFO)
|
|
311
315
|
|
|
@@ -362,7 +366,7 @@ class BENDR(EEGModuleMixin, nn.Module):
|
|
|
362
366
|
|
|
363
367
|
def forward(self, x, return_features=False):
|
|
364
368
|
if self.channel_tokenizer is not None:
|
|
365
|
-
x = self.channel_tokenizer(x)
|
|
369
|
+
x = self.channel_tokenizer(x)[0]
|
|
366
370
|
encoded = self.encoder(x)
|
|
367
371
|
# encoded: [batch_size, encoder_h, n_encoded_times]
|
|
368
372
|
|
|
@@ -583,6 +587,7 @@ class _BENDRContextualizer(nn.Module):
|
|
|
583
587
|
(1, x.shape[1], x.shape[2]),
|
|
584
588
|
float(self.start_token),
|
|
585
589
|
device=x.device,
|
|
590
|
+
dtype=x.dtype,
|
|
586
591
|
requires_grad=False,
|
|
587
592
|
)
|
|
588
593
|
x = torch.cat([token_emb, x], dim=0)
|
|
@@ -607,23 +612,3 @@ class _BENDRContextualizer(nn.Module):
|
|
|
607
612
|
# x: [batch_size, in_features, seq_len + 1]
|
|
608
613
|
|
|
609
614
|
return x
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
# -----------------------------------------------------------------------------
|
|
613
|
-
# InterpolatedBENDR — experimental channel-interpolation variant of BENDR
|
|
614
|
-
# -----------------------------------------------------------------------------
|
|
615
|
-
# Wraps :class:`BENDR` with an MNE-backed channel-interpolation layer that
|
|
616
|
-
# projects arbitrary user ``chs_info`` to the canonical 20-channel BENDR
|
|
617
|
-
# input (:data:`_BENDR_TARGET_CHS_INFO` — the 19 pre-training EEG channels
|
|
618
|
-
# plus a ``SCALE`` placeholder at the centroid of those 19 positions).
|
|
619
|
-
# Frozen by default; set ``trainable=True`` to fine-tune the projection.
|
|
620
|
-
#
|
|
621
|
-
# NOTE: the ``SCALE`` target has no physical position, so the row of the
|
|
622
|
-
# interpolation matrix that produces it is a spatial spline of the user's
|
|
623
|
-
# EEG channels — *not* the dn3 ``MappingDeep1010`` RMS statistic the
|
|
624
|
-
# checkpoint saw during pre-training. Expect degraded zero-shot transfer
|
|
625
|
-
# from the SCALE channel; downstream fine-tuning should still work.
|
|
626
|
-
|
|
627
|
-
from braindecode.models.interpolated import InterpolatedModel # noqa: E402
|
|
628
|
-
|
|
629
|
-
InterpolatedBENDR = InterpolatedModel(BENDR, _BENDR_TARGET_CHS_INFO)
|