braindecode 1.8.1.dev183052608__tar.gz → 1.8.1.dev183240691__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.dev183052608/braindecode.egg-info → braindecode-1.8.1.dev183240691}/PKG-INFO +1 -1
- braindecode-1.8.1.dev183240691/braindecode/__init__.py +53 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/base.py +10 -6
- braindecode-1.8.1.dev183240691/braindecode/models/__init__.py +133 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/config.py +0 -5
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/eegconformer.py +66 -1
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/labram.py +1 -5
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/luna.py +6 -6
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/util.py +41 -17
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/util.py +2 -1
- braindecode-1.8.1.dev183240691/braindecode/version.py +1 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691/braindecode.egg-info}/PKG-INFO +1 -1
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/whats_new.rst +36 -0
- braindecode-1.8.1.dev183052608/braindecode/__init__.py +0 -9
- braindecode-1.8.1.dev183052608/braindecode/models/__init__.py +0 -197
- braindecode-1.8.1.dev183052608/braindecode/version.py +0 -1
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/LICENSE.txt +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/MANIFEST.in +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/NOTICE.txt +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/README.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/augmentation/__init__.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/augmentation/base.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/augmentation/functional.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/augmentation/transforms.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/classifier.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/__init__.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/_notebook_viewer.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/bbci.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/bcicomp.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/bids/__init__.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/bids/datasets.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/bids/hub.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/bids/hub_format.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/bids/hub_io.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/bids/hub_validation.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/bids/iterable.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/chb_mit.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/collate.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/mne.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/moabb.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/nmt.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/registry.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/siena.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/sleep_physionet.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/tuh.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/utils.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/xy.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datautil/__init__.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datautil/channel_utils.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datautil/hub_formats.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datautil/serialization.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datautil/util.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/eegneuralnet.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/functional/__init__.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/functional/_lfilter.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/functional/_real_dft.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/functional/attention.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/functional/channel_mask.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/functional/functions.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/functional/initialization.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/functional/patches.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/atcnet.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/attentionbasenet.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/attn_sleep.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/axon.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/barista.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/base.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/bendr.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/biot.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/brainbert.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/brainmodule.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/brainomni.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/brant.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/cbramod.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/codebrain.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/contrawr.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/csbrain.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/ctnet.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/dance.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/deep4.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/deepsleepnet.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/dgcnn.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/diver1.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/duin.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/eeg_clip.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/eegdino.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/eeginception_erp.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/eeginception_mi.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/eegitnet.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/eegminer.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/eegnet.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/eegnex.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/eegpt.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/eegsimpleconv.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/eegsym.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/eegtcnet.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/emg2qwerty.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/epint.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/fbcnet.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/fblightconvnet.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/fbmsnet.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/gcnsnet.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/guetschel2026.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/hybrid.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/ifnet.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/mapa.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/medformer.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/meta_neuromotor.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/mirepnet.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/mscformer.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/msvtnet.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/mvpformer.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/neuropose.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/neurorvq.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/neurorvq_tokenizer.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/patchedtransformer.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/popt.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/reve.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/sccnet.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/seizure_transformer.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/sensingdynamics.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/shallow_fbcsp.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/signal_jepa.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/sinc_shallow.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/sleepfm.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/sparcnet.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/sstdpn.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/steegformer.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/summary.csv +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/syncnet.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/tcformer.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/tcn.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/tfm_tokenizer.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/tidnet.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/tmsanet.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/tsinception.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/usleep.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/vemg2pose.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/zuna.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/modules/__init__.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/modules/activation.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/modules/attention.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/modules/blocks.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/modules/channels.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/modules/convolution.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/modules/dance_modules.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/modules/filter.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/modules/layers.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/modules/linear.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/modules/linear_attention.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/modules/parametrization.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/modules/quantization.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/modules/stats.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/modules/util.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/modules/wrapper.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/preprocessing/__init__.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/preprocessing/mne_preprocess.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/preprocessing/preprocess.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/preprocessing/util.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/preprocessing/windowers.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/regressor.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/samplers/__init__.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/samplers/base.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/samplers/ssl.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/training/__init__.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/training/_trial_aggregation.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/training/callbacks.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/training/losses.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/training/scoring.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/visualization/__init__.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/visualization/activations.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/visualization/attribution.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/visualization/confusion_matrices.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/visualization/frequency.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/visualization/metrics.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/visualization/sanity.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/visualization/topology.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode.egg-info/SOURCES.txt +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode.egg-info/dependency_links.txt +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode.egg-info/requires.txt +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode.egg-info/top_level.txt +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/Makefile +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/_templates/autosummary/class.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/_templates/autosummary/function.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/agent_docs.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/api.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/cite.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/conf.py +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/help.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/index.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/install/install.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/install/install_pip.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/install/install_source.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/models/categorization/attention.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/models/categorization/channel.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/models/categorization/convolution.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/models/categorization/filterbank.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/models/categorization/gnn.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/models/categorization/interpretable.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/models/categorization/lbm.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/models/categorization/recurrent.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/models/categorization/spd.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/models/models.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/models/models_categorization.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/models/models_table.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/models/models_visualization.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/sg_execution_times.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/user_guide/channel_strategies.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/docs/user_guide/cropped_inference.rst +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/pyproject.toml +0 -0
- {braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/setup.cfg +0 -0
{braindecode-1.8.1.dev183052608/braindecode.egg-info → braindecode-1.8.1.dev183240691}/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.dev183240691
|
|
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>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import importlib
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
3
|
+
|
|
4
|
+
from .version import __version__
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING: # type checkers and IDEs see the classes; runtime uses __getattr__
|
|
7
|
+
from .classifier import EEGClassifier
|
|
8
|
+
from .regressor import EEGRegressor
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"__version__",
|
|
12
|
+
"EEGClassifier",
|
|
13
|
+
"EEGRegressor",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
# Subpackages reachable as ``braindecode.<name>`` after a bare ``import braindecode``.
|
|
17
|
+
_SUBMODULES = frozenset(
|
|
18
|
+
{
|
|
19
|
+
"augmentation",
|
|
20
|
+
"classifier",
|
|
21
|
+
"datasets",
|
|
22
|
+
"datautil",
|
|
23
|
+
"eegneuralnet",
|
|
24
|
+
"functional",
|
|
25
|
+
"models",
|
|
26
|
+
"modules",
|
|
27
|
+
"preprocessing",
|
|
28
|
+
"regressor",
|
|
29
|
+
"samplers",
|
|
30
|
+
"training",
|
|
31
|
+
"util",
|
|
32
|
+
"visualization",
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
if not TYPE_CHECKING: # hidden from checkers so misspelled names stay errors
|
|
37
|
+
|
|
38
|
+
def __getattr__(name):
|
|
39
|
+
# PEP 562: skorch, the datasets and the models load on first use.
|
|
40
|
+
if name == "EEGClassifier":
|
|
41
|
+
from .classifier import EEGClassifier
|
|
42
|
+
|
|
43
|
+
return EEGClassifier
|
|
44
|
+
if name == "EEGRegressor":
|
|
45
|
+
from .regressor import EEGRegressor
|
|
46
|
+
|
|
47
|
+
return EEGRegressor
|
|
48
|
+
if name in _SUBMODULES:
|
|
49
|
+
return importlib.import_module(f".{name}", __name__)
|
|
50
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
51
|
+
|
|
52
|
+
def __dir__():
|
|
53
|
+
return sorted(set(globals()) | set(__all__) | _SUBMODULES)
|
{braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/datasets/base.py
RENAMED
|
@@ -26,6 +26,7 @@ from itertools import chain
|
|
|
26
26
|
from operator import attrgetter
|
|
27
27
|
from pathlib import Path
|
|
28
28
|
from typing import Any, Generic, Iterable, no_type_check
|
|
29
|
+
from uuid import uuid4
|
|
29
30
|
|
|
30
31
|
import mne
|
|
31
32
|
import mne.io
|
|
@@ -479,14 +480,14 @@ def _zarr_to_memmap(zarr_path, group_name):
|
|
|
479
480
|
``SIGBUS`` when workers page-faulted on the unlinked inode.
|
|
480
481
|
|
|
481
482
|
Under ``N`` concurrent writers, every racer materialises the data
|
|
482
|
-
into its own per-
|
|
483
|
+
into its own per-call temp file and then tries to publish it; at
|
|
483
484
|
most one ``os.link`` wins, and the losers silently ``unlink``
|
|
484
485
|
their temp file in a ``finally`` block. The wasted I/O scales
|
|
485
486
|
with the number of racers; for the workloads braindecode targets
|
|
486
487
|
(a handful of concurrent workers per group) it is negligible.
|
|
487
488
|
|
|
488
489
|
Crash recovery: if a writer dies mid-run the only debris is a
|
|
489
|
-
``<group>.<
|
|
490
|
+
``<group>.<uuid>.tmp.npy`` file. Such files are unique per call
|
|
490
491
|
so they can never collide with a live writer, they are never
|
|
491
492
|
read by the fast path, and they do not prevent subsequent
|
|
492
493
|
callers from producing a correct result. Caches written by
|
|
@@ -504,7 +505,10 @@ def _zarr_to_memmap(zarr_path, group_name):
|
|
|
504
505
|
|
|
505
506
|
cache_dir.mkdir(parents=True, exist_ok=True)
|
|
506
507
|
arr = zarr.open(zarr_path, mode="r")[group_name]["data"]
|
|
507
|
-
|
|
508
|
+
# Unique per call, not per pid: threads of one process must not share it.
|
|
509
|
+
# Exclusive creation, not tempfile.mkstemp, which would make it 0600.
|
|
510
|
+
tmp_path = cache_dir / f"{group_name}.{uuid4().hex}.tmp.npy"
|
|
511
|
+
tmp_path.open("xb").close()
|
|
508
512
|
try:
|
|
509
513
|
# Write chunk-by-chunk to avoid materialising the whole zarr
|
|
510
514
|
# array in RAM.
|
|
@@ -531,9 +535,9 @@ def _zarr_to_memmap(zarr_path, group_name):
|
|
|
531
535
|
# canonical one; ours is discarded in the finally block.
|
|
532
536
|
pass
|
|
533
537
|
finally:
|
|
534
|
-
# Always remove our private per-
|
|
535
|
-
#
|
|
536
|
-
#
|
|
538
|
+
# Always remove our private per-call temp file. Its name is
|
|
539
|
+
# unique per call so this cannot clobber a concurrent writer's
|
|
540
|
+
# in-progress tmp file.
|
|
537
541
|
try:
|
|
538
542
|
os.unlink(tmp_path)
|
|
539
543
|
except FileNotFoundError:
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"""Some predefined network architectures for EEG decoding."""
|
|
2
|
+
|
|
3
|
+
import ast
|
|
4
|
+
import importlib
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
_LAZY: dict[str, str] # public name -> submodule, read below from the imports
|
|
8
|
+
|
|
9
|
+
# A new model needs one import line here. It gives type checkers the class and,
|
|
10
|
+
# read back at runtime, the lazy name -> submodule map and ``__all__``; so these
|
|
11
|
+
# imports are used although no code names them.
|
|
12
|
+
# ruff: noqa: F401
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from .atcnet import ATCNet
|
|
15
|
+
from .attentionbasenet import AttentionBaseNet
|
|
16
|
+
from .attn_sleep import AttnSleep
|
|
17
|
+
from .axon import AXON
|
|
18
|
+
from .barista import BaRISTA
|
|
19
|
+
from .base import EEGModuleMixin
|
|
20
|
+
from .bendr import BENDR
|
|
21
|
+
from .biot import BIOT
|
|
22
|
+
from .brainbert import BrainBERT
|
|
23
|
+
from .brainmodule import BrainModule
|
|
24
|
+
from .brainomni import BrainOmni, BrainTokenizer
|
|
25
|
+
from .brant import Brant
|
|
26
|
+
from .cbramod import CBraMod
|
|
27
|
+
from .codebrain import CodeBrain
|
|
28
|
+
from .contrawr import ContraWR
|
|
29
|
+
from .csbrain import CSBrain
|
|
30
|
+
from .ctnet import CTNet
|
|
31
|
+
from .dance import DANCE
|
|
32
|
+
from .deep4 import Deep4Net
|
|
33
|
+
from .deepsleepnet import DeepSleepNet
|
|
34
|
+
from .dgcnn import DGCNN
|
|
35
|
+
from .diver1 import DIVER1
|
|
36
|
+
from .duin import DuIN
|
|
37
|
+
from .eeg_clip import EEGCLIP
|
|
38
|
+
from .eegconformer import EEGConformer
|
|
39
|
+
from .eegdino import EEGDINO
|
|
40
|
+
from .eeginception_erp import EEGInceptionERP
|
|
41
|
+
from .eeginception_mi import EEGInceptionMI
|
|
42
|
+
from .eegitnet import EEGITNet
|
|
43
|
+
from .eegminer import EEGMiner
|
|
44
|
+
from .eegnet import EEGNet
|
|
45
|
+
from .eegnex import EEGNeX
|
|
46
|
+
from .eegpt import EEGPT
|
|
47
|
+
from .eegsimpleconv import EEGSimpleConv
|
|
48
|
+
from .eegsym import EEGSym
|
|
49
|
+
from .eegtcnet import EEGTCNet
|
|
50
|
+
from .emg2qwerty import EMG2QwertyNet
|
|
51
|
+
from .epint import EpiNT
|
|
52
|
+
from .fbcnet import FBCNet
|
|
53
|
+
from .fblightconvnet import FBLightConvNet
|
|
54
|
+
from .fbmsnet import FBMSNet
|
|
55
|
+
from .gcnsnet import GCNsNet
|
|
56
|
+
from .guetschel2026 import Guetschel2026
|
|
57
|
+
from .hybrid import HybridNet
|
|
58
|
+
from .ifnet import IFNet
|
|
59
|
+
from .labram import Labram
|
|
60
|
+
from .luna import LUNA
|
|
61
|
+
from .mapa import MAPA
|
|
62
|
+
from .medformer import MEDFormer
|
|
63
|
+
from .meta_neuromotor import MetaNeuromotorHand
|
|
64
|
+
from .mirepnet import MIRepNet
|
|
65
|
+
from .mscformer import MSCFormer
|
|
66
|
+
from .msvtnet import MSVTNet
|
|
67
|
+
from .mvpformer import MVPFormer
|
|
68
|
+
from .neuropose import NeuroPose
|
|
69
|
+
from .neurorvq import NeuroRVQ
|
|
70
|
+
from .neurorvq_tokenizer import NeuroRVQTokenizer
|
|
71
|
+
from .patchedtransformer import PBT
|
|
72
|
+
from .popt import PopulationTransformer
|
|
73
|
+
from .reve import REVE
|
|
74
|
+
from .sccnet import SCCNet
|
|
75
|
+
from .seizure_transformer import SeizureTransformer
|
|
76
|
+
from .sensingdynamics import SensingDynamics
|
|
77
|
+
from .shallow_fbcsp import ShallowFBCSPNet
|
|
78
|
+
from .signal_jepa import (
|
|
79
|
+
SignalJEPA,
|
|
80
|
+
SignalJEPA_Contextual,
|
|
81
|
+
SignalJEPA_PostLocal,
|
|
82
|
+
SignalJEPA_PreLocal,
|
|
83
|
+
)
|
|
84
|
+
from .sinc_shallow import SincShallowNet
|
|
85
|
+
from .sleep_stager_blanco_2020 import SleepStagerBlanco2020
|
|
86
|
+
from .sleep_stager_chambon_2018 import SleepStagerChambon2018
|
|
87
|
+
from .sleepfm import SleepFM, SleepFMStager
|
|
88
|
+
from .sparcnet import SPARCNet
|
|
89
|
+
from .sstdpn import SSTDPN
|
|
90
|
+
from .steegformer import STEEGFormer
|
|
91
|
+
from .syncnet import SyncNet
|
|
92
|
+
from .tcformer import TCFormer
|
|
93
|
+
from .tcn import BDTCN, TCN
|
|
94
|
+
from .tfm_tokenizer import TFMTokenizer, TFMTokenizerOutput
|
|
95
|
+
from .tidnet import TIDNet
|
|
96
|
+
from .tmsanet import TMSANet
|
|
97
|
+
from .tsinception import TSception
|
|
98
|
+
from .usleep import USleep
|
|
99
|
+
from .util import (
|
|
100
|
+
_init_models_dict,
|
|
101
|
+
build_model_config,
|
|
102
|
+
extract_channel_locations_from_chs_info,
|
|
103
|
+
models_mandatory_parameters,
|
|
104
|
+
positions_from_chs_info,
|
|
105
|
+
)
|
|
106
|
+
from .vemg2pose import VEMG2Pose
|
|
107
|
+
from .zuna import ZUNA
|
|
108
|
+
else: # hidden from checkers so misspelled names stay errors
|
|
109
|
+
|
|
110
|
+
def _type_checking_imports():
|
|
111
|
+
# ponytail: needs this file's source, as get_summary_table needs summary.csv.
|
|
112
|
+
with open(__file__, "rb") as source:
|
|
113
|
+
tree = ast.parse(source.read())
|
|
114
|
+
block = next(node for node in tree.body if isinstance(node, ast.If))
|
|
115
|
+
return {alias.name: imp.module for imp in block.body for alias in imp.names}
|
|
116
|
+
|
|
117
|
+
# Each submodule is imported on first attribute access (PEP 562), so
|
|
118
|
+
# ``import braindecode`` does not load every model.
|
|
119
|
+
_LAZY = _type_checking_imports()
|
|
120
|
+
__all__ = list(_LAZY)
|
|
121
|
+
|
|
122
|
+
def __getattr__(name):
|
|
123
|
+
if name in _LAZY:
|
|
124
|
+
value = getattr(importlib.import_module(f".{_LAZY[name]}", __name__), name)
|
|
125
|
+
elif name in _LAZY.values():
|
|
126
|
+
value = importlib.import_module(f".{name}", __name__)
|
|
127
|
+
else:
|
|
128
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
129
|
+
globals()[name] = value
|
|
130
|
+
return value
|
|
131
|
+
|
|
132
|
+
def __dir__():
|
|
133
|
+
return sorted(set(globals()) | set(__all__))
|
{braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/config.py
RENAMED
|
@@ -12,8 +12,6 @@ from braindecode.models.base import EEGModuleMixin
|
|
|
12
12
|
from braindecode.models.util import (
|
|
13
13
|
SigArgName,
|
|
14
14
|
_get_model_class,
|
|
15
|
-
_init_models_dict,
|
|
16
|
-
models_dict,
|
|
17
15
|
models_mandatory_parameters,
|
|
18
16
|
resolve_config_type,
|
|
19
17
|
)
|
|
@@ -216,9 +214,6 @@ def make_model_config(
|
|
|
216
214
|
# and define __all__ based on generated classes
|
|
217
215
|
__all__ = ["make_model_config"]
|
|
218
216
|
|
|
219
|
-
if not models_dict:
|
|
220
|
-
_init_models_dict()
|
|
221
|
-
|
|
222
217
|
models_configs: list[type[BaseBraindecodeModelConfig]] = []
|
|
223
218
|
for model_name, req, _ in models_mandatory_parameters:
|
|
224
219
|
model_cls = _get_model_class(model_name)
|
{braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/eegconformer.py
RENAMED
|
@@ -7,6 +7,7 @@ import torch
|
|
|
7
7
|
import torch.nn.functional as F
|
|
8
8
|
from einops.layers.torch import Rearrange
|
|
9
9
|
from torch import Tensor, nn
|
|
10
|
+
from torch.utils.checkpoint import checkpoint
|
|
10
11
|
|
|
11
12
|
from braindecode.models.base import EEGModuleMixin, _too_short_input_error
|
|
12
13
|
from braindecode.modules import (
|
|
@@ -181,6 +182,15 @@ class EEGConformer(EEGModuleMixin, nn.Module):
|
|
|
181
182
|
activation_transfor: nn.Module
|
|
182
183
|
Activation function as parameter, applied at the FeedForwardBlock module
|
|
183
184
|
inside the transformer. Default is nn.GeLU
|
|
185
|
+
activation_checkpointing : bool, default=False
|
|
186
|
+
Recompute the transformer blocks during backward (non-reentrant, RNG
|
|
187
|
+
preserved) to save training memory at the cost of extra compute.
|
|
188
|
+
Outputs and gradients were bit-identical to ``False`` in eager tests on
|
|
189
|
+
PyTorch 2.14.1 CPU. Only eager, gradient-enabled training is
|
|
190
|
+
checkpointed; the BatchNorm stem is never recomputed. There, hooks
|
|
191
|
+
(module or global) and buffers inside the transformer raise an error,
|
|
192
|
+
since recomputation would run them twice. Scripting, tracing, export
|
|
193
|
+
and compilation require ``False``.
|
|
184
194
|
|
|
185
195
|
References
|
|
186
196
|
----------
|
|
@@ -193,6 +203,9 @@ class EEGConformer(EEGModuleMixin, nn.Module):
|
|
|
193
203
|
https://github.com/eeyhsong/EEG-Conformer
|
|
194
204
|
"""
|
|
195
205
|
|
|
206
|
+
# Old full-object checkpoints restore state without calling __init__.
|
|
207
|
+
activation_checkpointing = False
|
|
208
|
+
|
|
196
209
|
def __init__(
|
|
197
210
|
self,
|
|
198
211
|
n_outputs=None,
|
|
@@ -213,6 +226,8 @@ class EEGConformer(EEGModuleMixin, nn.Module):
|
|
|
213
226
|
chs_info=None,
|
|
214
227
|
input_window_seconds=None,
|
|
215
228
|
sfreq=None,
|
|
229
|
+
*,
|
|
230
|
+
activation_checkpointing=False,
|
|
216
231
|
):
|
|
217
232
|
super().__init__(
|
|
218
233
|
n_outputs=n_outputs,
|
|
@@ -237,6 +252,7 @@ class EEGConformer(EEGModuleMixin, nn.Module):
|
|
|
237
252
|
)
|
|
238
253
|
|
|
239
254
|
self.return_features = return_features
|
|
255
|
+
self.activation_checkpointing = activation_checkpointing
|
|
240
256
|
|
|
241
257
|
self.patch_embedding = _PatchEmbedding(
|
|
242
258
|
n_filters_time=n_filters_time,
|
|
@@ -277,10 +293,24 @@ class EEGConformer(EEGModuleMixin, nn.Module):
|
|
|
277
293
|
|
|
278
294
|
self.final_layer = nn.Linear(self.fc.hidden_channels, self.n_outputs)
|
|
279
295
|
|
|
296
|
+
def compile(self, *args, **kwargs):
|
|
297
|
+
# Reject before installing a native compiled call (including estimator
|
|
298
|
+
# ownership). Explicit disable=True still selects ordinary eager math.
|
|
299
|
+
if self.activation_checkpointing and not kwargs.get("disable", False):
|
|
300
|
+
raise RuntimeError("activation_checkpointing requires eager execution")
|
|
301
|
+
return super().compile(*args, **kwargs)
|
|
302
|
+
|
|
280
303
|
def forward(self, x: Tensor) -> Tensor:
|
|
304
|
+
if self.activation_checkpointing:
|
|
305
|
+
if torch.jit.is_scripting():
|
|
306
|
+
raise RuntimeError("activation_checkpointing requires eager execution")
|
|
307
|
+
self._activation_checkpointing_requires_eager_execution()
|
|
281
308
|
x = torch.unsqueeze(x, dim=1) # add one extra dimension
|
|
282
309
|
x = self.patch_embedding(x)
|
|
283
|
-
|
|
310
|
+
if self.activation_checkpointing and self.training and torch.is_grad_enabled():
|
|
311
|
+
feature = self._checkpoint_transformer(x)
|
|
312
|
+
else:
|
|
313
|
+
feature = self.transformer(x)
|
|
284
314
|
|
|
285
315
|
if self.return_features:
|
|
286
316
|
return feature
|
|
@@ -289,6 +319,41 @@ class EEGConformer(EEGModuleMixin, nn.Module):
|
|
|
289
319
|
x = self.final_layer(x)
|
|
290
320
|
return x
|
|
291
321
|
|
|
322
|
+
@torch.jit.unused
|
|
323
|
+
def _activation_checkpointing_requires_eager_execution(self):
|
|
324
|
+
if torch.jit.is_tracing() or torch.compiler.is_compiling():
|
|
325
|
+
raise RuntimeError("activation_checkpointing requires eager execution")
|
|
326
|
+
|
|
327
|
+
# torch._dynamo.forbid_in_graph without importing Dynamo: torch.compile
|
|
328
|
+
# fails here instead of falling back to eager checkpointing.
|
|
329
|
+
_activation_checkpointing_requires_eager_execution._dynamo_forbidden = True # type: ignore[attr-defined]
|
|
330
|
+
|
|
331
|
+
@torch.jit.unused
|
|
332
|
+
def _checkpoint_transformer(self, x: Tensor) -> Tensor:
|
|
333
|
+
from torch.nn.modules import module as global_hooks
|
|
334
|
+
|
|
335
|
+
hooks = (
|
|
336
|
+
"_forward_hooks",
|
|
337
|
+
"_forward_pre_hooks",
|
|
338
|
+
"_backward_hooks",
|
|
339
|
+
"_backward_pre_hooks",
|
|
340
|
+
)
|
|
341
|
+
if any(getattr(global_hooks, "_global" + name) for name in hooks):
|
|
342
|
+
raise RuntimeError(
|
|
343
|
+
"activation_checkpointing requires pure execution without global hooks"
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
# Recheck: users can attach hooks or replace children after construction.
|
|
347
|
+
for module in self.transformer.modules():
|
|
348
|
+
if module._buffers or any(getattr(module, name) for name in hooks):
|
|
349
|
+
raise RuntimeError(
|
|
350
|
+
"activation_checkpointing requires pure transformer blocks "
|
|
351
|
+
"without hooks or buffers"
|
|
352
|
+
)
|
|
353
|
+
for block in self.transformer:
|
|
354
|
+
x = checkpoint(block, x, use_reentrant=False, preserve_rng_state=True)
|
|
355
|
+
return x
|
|
356
|
+
|
|
292
357
|
def get_fc_size(self):
|
|
293
358
|
try:
|
|
294
359
|
out = self.patch_embedding(torch.ones((1, 1, self.n_chans, self.n_times)))
|
{braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/labram.py
RENAMED
|
@@ -1392,11 +1392,7 @@ class _Attention(nn.Module):
|
|
|
1392
1392
|
if qkv_bias is not None:
|
|
1393
1393
|
qkv = qkv + qkv_bias.to(qkv.dtype) # keep autocast dtype
|
|
1394
1394
|
qkv = qkv.reshape(B, N, 3, self.num_heads, -1).permute(2, 0, 3, 1, 4)
|
|
1395
|
-
q, k, v = (
|
|
1396
|
-
qkv[0],
|
|
1397
|
-
qkv[1],
|
|
1398
|
-
qkv[2],
|
|
1399
|
-
) # make torchscript happy (cannot use tensor as tuple) (B, H, N, C)
|
|
1395
|
+
q, k, v = qkv.unbind(0) # (B, H, N, C); TorchScript cannot unpack qkv
|
|
1400
1396
|
if self.q_norm is not None:
|
|
1401
1397
|
q = self.q_norm(q).type_as(v)
|
|
1402
1398
|
if self.k_norm is not None:
|
{braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/luna.py
RENAMED
|
@@ -594,16 +594,15 @@ class _RotarySelfAttentionBlock(nn.Module):
|
|
|
594
594
|
self.proj = nn.Linear(dim, dim)
|
|
595
595
|
self.proj_drop = nn.Dropout(proj_drop)
|
|
596
596
|
|
|
597
|
-
def
|
|
598
|
-
"""
|
|
597
|
+
def _rotary_tables(self, tensor: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor]:
|
|
598
|
+
"""Build RoPE tables for one forward; no cache, the frequencies may train."""
|
|
599
599
|
seq_len = tensor.shape[-2]
|
|
600
600
|
positions = torch.arange(seq_len, device=tensor.device, dtype=tensor.dtype)
|
|
601
601
|
freqs = self.rotary_emb(positions)
|
|
602
602
|
|
|
603
603
|
# Keep the full-head reshape (including its empty-input boundary).
|
|
604
604
|
tensor.reshape(list(tensor.shape[:-1]) + [-1, 2])
|
|
605
|
-
|
|
606
|
-
return transformed.to(tensor.dtype)
|
|
605
|
+
return freqs.cos(), freqs.sin()
|
|
607
606
|
|
|
608
607
|
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
|
609
608
|
B, N, C = x.shape
|
|
@@ -615,8 +614,9 @@ class _RotarySelfAttentionBlock(nn.Module):
|
|
|
615
614
|
# unbind, not qkv[0..2]: the backward of three selects writes three
|
|
616
615
|
# zero-filled copies of the whole qkv tensor and sums them.
|
|
617
616
|
q, k, v = qkv.unbind(0)
|
|
618
|
-
|
|
619
|
-
|
|
617
|
+
cos, sin = self._rotary_tables(q) # k has the shape of q
|
|
618
|
+
q = apply_rotary(q, cos, sin).to(q.dtype)
|
|
619
|
+
k = apply_rotary(k, cos, sin).to(k.dtype)
|
|
620
620
|
attn = F.scaled_dot_product_attention(
|
|
621
621
|
q,
|
|
622
622
|
k,
|
{braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691}/braindecode/models/util.py
RENAMED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
# License: BSD (3-clause)
|
|
6
6
|
import inspect
|
|
7
7
|
import math
|
|
8
|
+
import sys
|
|
8
9
|
import warnings
|
|
9
10
|
from collections.abc import Callable as CallableABC
|
|
10
11
|
from copy import deepcopy
|
|
@@ -12,6 +13,7 @@ from functools import lru_cache, wraps
|
|
|
12
13
|
from pathlib import Path
|
|
13
14
|
from types import SimpleNamespace
|
|
14
15
|
from typing import (
|
|
16
|
+
TYPE_CHECKING,
|
|
15
17
|
Any,
|
|
16
18
|
Callable,
|
|
17
19
|
Dict,
|
|
@@ -26,10 +28,8 @@ from typing import (
|
|
|
26
28
|
|
|
27
29
|
import mne
|
|
28
30
|
import numpy as np
|
|
29
|
-
import pandas as pd
|
|
30
31
|
import torch # noqa: F401 # exposed so TorchScript can resolve ``torch`` through the BatchNorm-guard wrapper's __globals__
|
|
31
32
|
from mne.io.constants import FIFF
|
|
32
|
-
from sklearn.metrics import pairwise_distances_argmin
|
|
33
33
|
from torch import nn
|
|
34
34
|
from torchaudio.transforms import Resample
|
|
35
35
|
|
|
@@ -49,7 +49,27 @@ _KIND_TO_CH_TYPE = {
|
|
|
49
49
|
INTRACRANIAL_CH_TYPES = frozenset({"seeg", "dbs", "ecog"})
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
models_dict
|
|
52
|
+
# Read through ``models_dict`` (module ``__getattr__`` below), which fills it on
|
|
53
|
+
# first access so importing braindecode does not import every model.
|
|
54
|
+
_models_dict: dict[str, Any] = {}
|
|
55
|
+
# Annotations only, for type checkers; the values come from ``__getattr__``.
|
|
56
|
+
models_dict: dict[str, Any]
|
|
57
|
+
_summary_table: "pd.DataFrame"
|
|
58
|
+
|
|
59
|
+
if TYPE_CHECKING:
|
|
60
|
+
import pandas as pd
|
|
61
|
+
else: # hidden from checkers so misspelled names stay errors
|
|
62
|
+
|
|
63
|
+
def __getattr__(name):
|
|
64
|
+
if name == "models_dict":
|
|
65
|
+
if not _models_dict:
|
|
66
|
+
_init_models_dict()
|
|
67
|
+
return _models_dict
|
|
68
|
+
if name == "_summary_table": # read summary.csv once, on first access
|
|
69
|
+
table = globals()[name] = get_summary_table()
|
|
70
|
+
return table
|
|
71
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
72
|
+
|
|
53
73
|
|
|
54
74
|
# Resolve serialized classes by exact lookup, never by importing a config path.
|
|
55
75
|
# Include public aliases and the defining paths emitted by get_config().
|
|
@@ -261,14 +281,18 @@ def resolve_type_kwargs(cls, kwargs):
|
|
|
261
281
|
|
|
262
282
|
|
|
263
283
|
def _init_models_dict():
|
|
264
|
-
|
|
284
|
+
from braindecode import models
|
|
285
|
+
from braindecode.models.base import EEGModuleMixin
|
|
265
286
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
)
|
|
271
|
-
|
|
287
|
+
# Plain getattr over every public name: a model that fails to import raises here.
|
|
288
|
+
found = {}
|
|
289
|
+
for name in sorted(models._LAZY):
|
|
290
|
+
obj = getattr(models, name)
|
|
291
|
+
is_model = inspect.isclass(obj) and issubclass(obj, EEGModuleMixin)
|
|
292
|
+
if is_model and obj is not EEGModuleMixin:
|
|
293
|
+
found[name] = obj
|
|
294
|
+
# One update() publishes every entry at once, so no thread sees a partial dict.
|
|
295
|
+
_models_dict.update(found)
|
|
272
296
|
|
|
273
297
|
|
|
274
298
|
def _get_model_class(model_name: str):
|
|
@@ -292,10 +316,9 @@ def _get_model_class(model_name: str):
|
|
|
292
316
|
ValueError
|
|
293
317
|
If ``model_name`` is not a registered model.
|
|
294
318
|
"""
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
return models_dict[model_name]
|
|
319
|
+
registry = sys.modules[__name__].models_dict # also honours a patched models_dict
|
|
320
|
+
if model_name in registry:
|
|
321
|
+
return registry[model_name]
|
|
299
322
|
raise ValueError(f"Unknown model name {model_name!r}.")
|
|
300
323
|
|
|
301
324
|
|
|
@@ -897,6 +920,8 @@ def get_summary_table(dir_name=None):
|
|
|
897
920
|
|
|
898
921
|
path = dir_path / "summary.csv"
|
|
899
922
|
|
|
923
|
+
import pandas as pd
|
|
924
|
+
|
|
900
925
|
df = pd.read_csv(
|
|
901
926
|
path,
|
|
902
927
|
header=0,
|
|
@@ -1095,6 +1120,8 @@ def resolve_channel_indices(
|
|
|
1095
1120
|
if not np.isfinite(norms).all() or np.any(norms <= 1e-7):
|
|
1096
1121
|
return None
|
|
1097
1122
|
directions = radial / norms
|
|
1123
|
+
from sklearn.metrics import pairwise_distances_argmin
|
|
1124
|
+
|
|
1098
1125
|
nearest = pairwise_distances_argmin(
|
|
1099
1126
|
directions[: len(locations)], directions[len(locations) :], metric=metric
|
|
1100
1127
|
)
|
|
@@ -1274,6 +1301,3 @@ def channel_types_from_chs_info(
|
|
|
1274
1301
|
else:
|
|
1275
1302
|
types.append("unknown")
|
|
1276
1303
|
return types
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
_summary_table = get_summary_table()
|
|
@@ -12,7 +12,6 @@ import h5py
|
|
|
12
12
|
import mne
|
|
13
13
|
import numpy as np
|
|
14
14
|
import torch
|
|
15
|
-
from sklearn.utils import check_random_state
|
|
16
15
|
from torch import Tensor
|
|
17
16
|
|
|
18
17
|
|
|
@@ -299,6 +298,8 @@ def create_mne_dummy_raw(
|
|
|
299
298
|
save_fname : dict | None
|
|
300
299
|
Dictionary containing the name the raw data was saved to.
|
|
301
300
|
"""
|
|
301
|
+
from sklearn.utils import check_random_state
|
|
302
|
+
|
|
302
303
|
random_state = check_random_state(random_state)
|
|
303
304
|
data = random_state.rand(n_channels, n_times)
|
|
304
305
|
ch_names = [f"ch{i}" for i in range(n_channels)]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.8.1.dev183240691"
|
{braindecode-1.8.1.dev183052608 → braindecode-1.8.1.dev183240691/braindecode.egg-info}/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.dev183240691
|
|
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>
|
|
@@ -28,6 +28,39 @@ Current 1.8.1 (2026-08-31)
|
|
|
28
28
|
Enhancements
|
|
29
29
|
============
|
|
30
30
|
|
|
31
|
+
- ``import braindecode`` and ``import braindecode.models`` no longer import
|
|
32
|
+
every model, the estimators, scikit-learn and pandas up front: the model
|
|
33
|
+
classes, :class:`braindecode.EEGClassifier`, :class:`~braindecode.EEGRegressor`,
|
|
34
|
+
the subpackages and ``models_dict`` load on first access (PEP 562 module
|
|
35
|
+
``__getattr__``), with the same names, ``__all__`` and model registry. On
|
|
36
|
+
CPU with torch 2.14.1, ``import braindecode`` took 5 ms instead of 3.1 s and
|
|
37
|
+
``from braindecode.models import EEGNet`` 1.6 s instead of 3.1 s. A new model
|
|
38
|
+
needs one import line, in the ``if TYPE_CHECKING:`` block of
|
|
39
|
+
``braindecode/models/__init__.py``, as the new-model checklist says (by
|
|
40
|
+
`Bruno Aristimunha`_).
|
|
41
|
+
- :class:`braindecode.models.LUNA` reuses differentiable rotary tables within
|
|
42
|
+
each attention forward (no persistent cache); :class:`braindecode.models.Labram`
|
|
43
|
+
splits its fused qkv projection with ``unbind`` instead of three selects.
|
|
44
|
+
Parameters, checkpoint keys and numerical computations are preserved; LUNA
|
|
45
|
+
trainable-frequency gradients can differ by floating-point accumulation
|
|
46
|
+
rounding, and rotary-module hooks run once rather than twice per forward
|
|
47
|
+
(by `Bruno Aristimunha`_).
|
|
48
|
+
- :class:`braindecode.models.EEGConformer` takes the opt-in, keyword-only
|
|
49
|
+
``activation_checkpointing=False``: non-reentrant activation checkpointing
|
|
50
|
+
recomputes pure transformer blocks during backward with RNG preservation.
|
|
51
|
+
Outputs, gradients and an optimizer step were bit-identical to checkpointing
|
|
52
|
+
off in eager tests on PyTorch 2.14.1 CPU; old pickled models still load.
|
|
53
|
+
Checkpointing requires eager execution; unsupported configurations are
|
|
54
|
+
explicitly rejected (see the parameter documentation). On an Intel Xeon
|
|
55
|
+
Gold 6230R CPU with four PyTorch/BLAS threads,
|
|
56
|
+
FP32, embedding dimension 64, eight heads, six layers and dropout, five paired
|
|
57
|
+
fresh processes at input shape ``[8, 22, 8192]`` measured 55.39% lower peak
|
|
58
|
+
process RSS (median paired ratio 0.446142) and 73.14% extra train-step time
|
|
59
|
+
(median paired ratio 1.731425) at equal batch. The largest passing integer
|
|
60
|
+
batch under a 4 GiB peak process RSS budget increased from 17 to 68 in a
|
|
61
|
+
fresh-process capacity search; this machine/runtime-qualified, one-run
|
|
62
|
+
boundary is a memory-capacity result, not an equal-batch speed improvement
|
|
63
|
+
(by `Bruno Aristimunha`_).
|
|
31
64
|
- Add :func:`braindecode.training.iter_trial_predictions`,
|
|
32
65
|
:func:`~braindecode.training.iter_trial_prediction_chunks` and
|
|
33
66
|
:class:`~braindecode.training.TrialPredictionChunk` to stream cropped
|
|
@@ -524,6 +557,9 @@ Requirements
|
|
|
524
557
|
Bug fixes
|
|
525
558
|
==========
|
|
526
559
|
|
|
560
|
+
- Zarr cache creation reserves a unique temporary file per call (exclusive
|
|
561
|
+
creation), so threads of one process no longer share one; permissions and
|
|
562
|
+
existing caches are unchanged (by `Bruno Aristimunha`_).
|
|
527
563
|
- :class:`braindecode.training.PostEpochTrainScoring` restores the saved CPU
|
|
528
564
|
Torch RNG state even when its reevaluation fails (by `Bruno Aristimunha`_).
|
|
529
565
|
- :class:`braindecode.modules.FilterBankLayer`, and so :class:`braindecode.models.FBCNet`, :class:`braindecode.models.FBMSNet`, :class:`braindecode.models.FBLightConvNet` and :class:`braindecode.models.IFNet`, script again with PyTorch 2.15, where ``torch.jit.script`` failed inside :func:`torchaudio.functional.lfilter` ("Expression of type dots cannot be used in a type expression"). Eager filtering still calls torchaudio; the scripted graph runs the same operations as before, so outputs are unchanged (:gh:`1501` by `Bruno Aristimunha`_).
|