Braindecode 1.8.0.dev180516540__tar.gz → 1.8.0.dev180935432__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.0.dev180516540/braindecode.egg-info → braindecode-1.8.0.dev180935432}/PKG-INFO +2 -2
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/base.py +0 -3
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/functional/functions.py +3 -4
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/base.py +3 -3
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/luna.py +4 -29
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/summary.csv +1 -1
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/usleep.py +7 -3
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/zuna.py +11 -25
- braindecode-1.8.0.dev180935432/braindecode/version.py +1 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432/braindecode.egg-info}/PKG-INFO +2 -2
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode.egg-info/SOURCES.txt +0 -1
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode.egg-info/requires.txt +1 -1
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/whats_new.rst +1 -26
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/pyproject.toml +1 -1
- braindecode-1.8.0.dev180516540/braindecode/datasets/_notebook_viewer.py +0 -255
- braindecode-1.8.0.dev180516540/braindecode/version.py +0 -1
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/LICENSE.txt +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/MANIFEST.in +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/NOTICE.txt +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/README.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/__init__.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/augmentation/__init__.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/augmentation/base.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/augmentation/functional.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/augmentation/transforms.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/classifier.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/__init__.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/bbci.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/bcicomp.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/bids/__init__.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/bids/datasets.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/bids/format.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/bids/hub.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/bids/hub_format.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/bids/hub_io.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/bids/hub_validation.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/bids/iterable.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/chb_mit.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/collate.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/mne.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/moabb.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/nmt.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/registry.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/siena.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/sleep_physionet.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/tuh.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/utils.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/xy.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datautil/__init__.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datautil/channel_utils.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datautil/hub_formats.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datautil/serialization.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datautil/util.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/eegneuralnet.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/functional/__init__.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/functional/initialization.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/__init__.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/atcnet.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/attentionbasenet.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/attn_sleep.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/bendr.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/biot.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/brainmodule.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/cbramod.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/codebrain.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/config.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/contrawr.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/ctnet.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/dance.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/deep4.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/deepsleepnet.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/dgcnn.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/eegconformer.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/eegdino.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/eeginception_erp.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/eeginception_mi.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/eegitnet.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/eegminer.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/eegnet.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/eegnex.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/eegpt.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/eegsimpleconv.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/eegsym.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/eegtcnet.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/emg2qwerty.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/fbcnet.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/fblightconvnet.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/fbmsnet.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/hybrid.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/ifnet.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/interpolated.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/labram.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/medformer.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/meta_neuromotor.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/msvtnet.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/mvpformer.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/patchedtransformer.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/reve.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/sccnet.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/shallow_fbcsp.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/signal_jepa.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/sinc_shallow.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/sparcnet.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/sstdpn.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/steegformer.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/syncnet.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/tcformer.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/tcn.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/tidnet.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/tsinception.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/util.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/modules/__init__.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/modules/activation.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/modules/attention.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/modules/blocks.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/modules/convolution.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/modules/dance_modules.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/modules/filter.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/modules/interpolation.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/modules/layers.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/modules/linear.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/modules/parametrization.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/modules/stats.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/modules/util.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/modules/wrapper.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/preprocessing/__init__.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/preprocessing/mne_preprocess.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/preprocessing/preprocess.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/preprocessing/util.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/preprocessing/windowers.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/regressor.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/samplers/__init__.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/samplers/base.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/samplers/ssl.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/training/__init__.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/training/callbacks.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/training/losses.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/training/scoring.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/util.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/visualization/__init__.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/visualization/attribution.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/visualization/confusion_matrices.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/visualization/frequency.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/visualization/metrics.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/visualization/sanity.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/visualization/topology.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode.egg-info/dependency_links.txt +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode.egg-info/top_level.txt +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/Makefile +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/_templates/autosummary/class.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/_templates/autosummary/function.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/api.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/cite.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/conf.py +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/help.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/index.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/install/install.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/install/install_pip.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/install/install_source.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/models/categorization/attention.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/models/categorization/channel.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/models/categorization/convolution.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/models/categorization/filterbank.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/models/categorization/gnn.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/models/categorization/interpretable.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/models/categorization/lbm.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/models/categorization/recurrent.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/models/categorization/spd.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/models/models.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/models/models_categorization.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/models/models_table.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/models/models_visualization.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/docs/sg_execution_times.rst +0 -0
- {braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/setup.cfg +0 -0
{braindecode-1.8.0.dev180516540/braindecode.egg-info → braindecode-1.8.0.dev180935432}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: braindecode
|
|
3
|
-
Version: 1.8.0.
|
|
3
|
+
Version: 1.8.0.dev180935432
|
|
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>
|
|
@@ -34,6 +34,7 @@ Requires-Dist: pandas
|
|
|
34
34
|
Requires-Dist: wfdb>=4.3.1
|
|
35
35
|
Requires-Dist: linear_attention_transformer
|
|
36
36
|
Requires-Dist: docstring_inheritance
|
|
37
|
+
Requires-Dist: rotary_embedding_torch
|
|
37
38
|
Requires-Dist: pydantic>=2.0
|
|
38
39
|
Provides-Extra: moabb
|
|
39
40
|
Requires-Dist: moabb>=1.4.3; extra == "moabb"
|
|
@@ -50,7 +51,6 @@ Requires-Dist: pytest-cov; extra == "tests"
|
|
|
50
51
|
Requires-Dist: codecov; extra == "tests"
|
|
51
52
|
Requires-Dist: pytest_cases; extra == "tests"
|
|
52
53
|
Requires-Dist: mypy; extra == "tests"
|
|
53
|
-
Requires-Dist: ipython; extra == "tests"
|
|
54
54
|
Requires-Dist: transformers>=4.57.0; extra == "tests"
|
|
55
55
|
Requires-Dist: bids_validator; extra == "tests"
|
|
56
56
|
Provides-Extra: typing
|
{braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/base.py
RENAMED
|
@@ -32,7 +32,6 @@ from mne.utils.docs import deprecated
|
|
|
32
32
|
from torch.utils.data import ConcatDataset, Dataset, IterableDataset
|
|
33
33
|
from typing_extensions import TypeVar
|
|
34
34
|
|
|
35
|
-
from ._notebook_viewer import plot as _viewer_plot
|
|
36
35
|
from .bids.hub import HubDatasetMixin
|
|
37
36
|
from .bids.hub_io import _restore_nan_from_json
|
|
38
37
|
from .registry import register_dataset
|
|
@@ -1175,8 +1174,6 @@ class BaseConcatDataset(ConcatDataset, HubDatasetMixin, Generic[T]):
|
|
|
1175
1174
|
If True, defer computing cumulative sizes until length or item access.
|
|
1176
1175
|
"""
|
|
1177
1176
|
|
|
1178
|
-
plot = _viewer_plot # eegdash-viewer embed; a direct member so the API docs list it
|
|
1179
|
-
|
|
1180
1177
|
datasets: list[T]
|
|
1181
1178
|
|
|
1182
1179
|
def __init__(
|
|
@@ -40,7 +40,7 @@ def drop_path(
|
|
|
40
40
|
x : torch.Tensor
|
|
41
41
|
input tensor
|
|
42
42
|
drop_prob : float, optional
|
|
43
|
-
probability of
|
|
43
|
+
survival rate (i.e. probability of being kept), by default 0.0
|
|
44
44
|
training : bool, optional
|
|
45
45
|
whether the model is in training mode, by default False
|
|
46
46
|
scale_by_keep : bool, optional
|
|
@@ -68,10 +68,9 @@ def drop_path(
|
|
|
68
68
|
shape = (x.shape[0],) + (1,) * (
|
|
69
69
|
x.ndim - 1
|
|
70
70
|
) # work with diff dim tensors, not just 2D ConvNets
|
|
71
|
-
|
|
72
|
-
random_tensor = torch.bernoulli(probabilities).to(dtype=x.dtype)
|
|
71
|
+
random_tensor = x.new_empty(shape).bernoulli_(keep_prob)
|
|
73
72
|
if keep_prob > 0.0 and scale_by_keep:
|
|
74
|
-
random_tensor
|
|
73
|
+
random_tensor.div_(keep_prob)
|
|
75
74
|
return x * random_tensor
|
|
76
75
|
|
|
77
76
|
|
{braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/base.py
RENAMED
|
@@ -80,7 +80,7 @@ class _BraindecodeDocstringMeta(NumpyDocstringInheritanceInitMeta):
|
|
|
80
80
|
unwrapped function and correctly inherits ``cls.__doc__``.
|
|
81
81
|
"""
|
|
82
82
|
|
|
83
|
-
def __init__(cls, class_name, class_bases, class_dict
|
|
83
|
+
def __init__(cls, class_name, class_bases, class_dict):
|
|
84
84
|
super().__init__(class_name, class_bases, class_dict)
|
|
85
85
|
# Only wrap subclass __init__s, not EEGModuleMixin itself.
|
|
86
86
|
# Wrapping the mixin would cause super().__init__() calls to
|
|
@@ -214,8 +214,6 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
|
|
|
214
214
|
__jit_unused_properties__ = ["chs_info"]
|
|
215
215
|
|
|
216
216
|
def __init_subclass__(cls, **kwargs):
|
|
217
|
-
license = kwargs.pop("license", "bsd-3-clause")
|
|
218
|
-
|
|
219
217
|
# TorchScript only honours ``__jit_ignored_attributes__`` for
|
|
220
218
|
# properties defined directly on the concrete class: it collects them
|
|
221
219
|
# with ``vars(type(module))``, which skips inherited ones. Rebinding
|
|
@@ -255,6 +253,8 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
|
|
|
255
253
|
)
|
|
256
254
|
repo_url = kwargs.pop("repo_url", "https://braindecode.org")
|
|
257
255
|
library_name = kwargs.pop("library_name", "braindecode")
|
|
256
|
+
license = kwargs.pop("license", "bsd-3-clause")
|
|
257
|
+
|
|
258
258
|
# Register a coder so that type[nn.Module] parameters
|
|
259
259
|
# (e.g. activation=nn.ELU) are serialized as importable
|
|
260
260
|
# strings in config.json and decoded back on load.
|
{braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/luna.py
RENAMED
|
@@ -20,6 +20,7 @@ import torch.fft as fft
|
|
|
20
20
|
import torch.nn as nn
|
|
21
21
|
import torch.nn.functional as F
|
|
22
22
|
from einops import rearrange
|
|
23
|
+
from rotary_embedding_torch import RotaryEmbedding
|
|
23
24
|
|
|
24
25
|
from braindecode.models.base import EEGModuleMixin
|
|
25
26
|
from braindecode.models.util import extract_channel_locations_from_chs_info
|
|
@@ -534,7 +535,7 @@ class _RotarySelfAttentionBlock(nn.Module):
|
|
|
534
535
|
self.dim = dim
|
|
535
536
|
self.num_heads = num_heads
|
|
536
537
|
head_dim = dim // num_heads
|
|
537
|
-
self.rotary_emb =
|
|
538
|
+
self.rotary_emb = RotaryEmbedding(dim=head_dim, learned_freq=False)
|
|
538
539
|
|
|
539
540
|
self.scale = qk_scale or head_dim**-0.5
|
|
540
541
|
|
|
@@ -544,17 +545,6 @@ class _RotarySelfAttentionBlock(nn.Module):
|
|
|
544
545
|
self.proj = nn.Linear(dim, dim)
|
|
545
546
|
self.proj_drop = nn.Dropout(proj_drop)
|
|
546
547
|
|
|
547
|
-
def _rotate_queries_or_keys(self, tensor: torch.Tensor) -> torch.Tensor:
|
|
548
|
-
"""Apply full-head RoPE without concatenating empty boundary views."""
|
|
549
|
-
seq_len = tensor.shape[-2]
|
|
550
|
-
positions = torch.arange(seq_len, device=tensor.device, dtype=tensor.dtype)
|
|
551
|
-
freqs = self.rotary_emb(positions)
|
|
552
|
-
|
|
553
|
-
pairs = tensor.reshape(*tensor.shape[:-1], -1, 2)
|
|
554
|
-
rotated = torch.stack((-pairs[..., 1], pairs[..., 0]), dim=-1).flatten(-2)
|
|
555
|
-
transformed = tensor * freqs.cos() + rotated * freqs.sin()
|
|
556
|
-
return transformed.to(tensor.dtype)
|
|
557
|
-
|
|
558
548
|
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
|
559
549
|
B, N, C = x.shape
|
|
560
550
|
qkv = (
|
|
@@ -563,8 +553,8 @@ class _RotarySelfAttentionBlock(nn.Module):
|
|
|
563
553
|
.permute(2, 0, 3, 1, 4)
|
|
564
554
|
) # (K, B, H, N, D)
|
|
565
555
|
q, k, v = qkv[0], qkv[1], qkv[2]
|
|
566
|
-
q = self.
|
|
567
|
-
k = self.
|
|
556
|
+
q = self.rotary_emb.rotate_queries_or_keys(q)
|
|
557
|
+
k = self.rotary_emb.rotate_queries_or_keys(k)
|
|
568
558
|
# Calculate attention scores
|
|
569
559
|
attn_weights = (q @ k.transpose(-2, -1)) * self.scale # (B, H, N, N)
|
|
570
560
|
|
|
@@ -580,21 +570,6 @@ class _RotarySelfAttentionBlock(nn.Module):
|
|
|
580
570
|
return self.proj_drop(self.proj(attn))
|
|
581
571
|
|
|
582
572
|
|
|
583
|
-
class _RotaryEmbedding(nn.Module):
|
|
584
|
-
"""Minimal language RoPE frequency generator used by LUNA."""
|
|
585
|
-
|
|
586
|
-
def __init__(self, dim: int, theta: float = 10000.0) -> None:
|
|
587
|
-
super().__init__()
|
|
588
|
-
frequencies = 1.0 / (
|
|
589
|
-
theta ** (torch.arange(0, dim, 2, dtype=torch.float32) / dim)
|
|
590
|
-
)
|
|
591
|
-
self.freqs = nn.Parameter(frequencies, requires_grad=False)
|
|
592
|
-
|
|
593
|
-
def forward(self, positions: torch.Tensor) -> torch.Tensor:
|
|
594
|
-
angles = positions.to(self.freqs.dtype).unsqueeze(-1) * self.freqs
|
|
595
|
-
return angles.repeat_interleave(2, dim=-1)
|
|
596
|
-
|
|
597
|
-
|
|
598
573
|
class _FeedForwardBlock(nn.Module):
|
|
599
574
|
def __init__(self, dim: int, hidden_dim: int, dropout: float = 0.0) -> None:
|
|
600
575
|
super().__init__()
|
{braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/summary.csv
RENAMED
|
@@ -31,7 +31,7 @@ SincShallowNet,Motor Imagery,Prediction,250,"n_chans, n_outputs, n_times, sfreq"
|
|
|
31
31
|
ShallowFBCSPNet,General,Prediction,250,"n_chans, n_outputs, n_times",46084,"ShallowFBCSPNet(n_chans=22, n_outputs=4, n_times=1000, sfreq=250)","Convolution",EEG
|
|
32
32
|
SleepStagerBlanco2020,Sleep Staging,Prediction,100,"n_chans, n_outputs, n_times",2845,"SleepStagerBlanco2020(n_chans=2, n_outputs=5, n_times=3000, sfreq=100)","Convolution",EEG
|
|
33
33
|
SleepStagerChambon2018,Sleep Staging,Prediction,128,"n_chans, n_outputs, n_times, sfreq",5835,"SleepStagerChambon2018(n_chans=2, n_outputs=5, n_times=3840, sfreq=128)","Convolution",EEG
|
|
34
|
-
AttnSleep,Sleep Staging,Prediction,100,"n_chans, n_outputs, n_times, sfreq",
|
|
34
|
+
AttnSleep,Sleep Staging,Prediction,100,"n_chans, n_outputs, n_times, sfreq",719925,"AttnSleep(n_chans=2, n_outputs=5, n_times=3000, sfreq=100)","Convolution, Attention/Transformer",EEG
|
|
35
35
|
SPARCNet,Epilepsy,Prediction,200,"n_chans, n_outputs, n_times",1141921,"SPARCNet(n_chans=16, n_outputs=6, n_times=2000, sfreq=200)","Convolution",EEG
|
|
36
36
|
SyncNet,"Emotion Recognition, Alcoholism",Prediction,256,"n_chans, n_outputs, n_times",554,"SyncNet(n_chans=62, n_outputs=3, n_times=5120, sfreq=256)","Interpretability",EEG
|
|
37
37
|
TSception,Emotion Recognition,Prediction,256,"n_chans, n_outputs, n_times, sfreq",2187206,"TSception(n_chans=62, n_outputs=3, n_times=5120, sfreq=256)","Convolution",EEG
|
{braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/usleep.py
RENAMED
|
@@ -431,7 +431,11 @@ class _DecoderBlock(nn.Module):
|
|
|
431
431
|
) -> tuple[torch.Tensor, torch.Tensor]:
|
|
432
432
|
"""Crops two tensors to their lowest-common-dimension along an axis."""
|
|
433
433
|
dim_cropped = min(x1.shape[axis], x2.shape[axis])
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
434
|
+
|
|
435
|
+
x1_cropped = torch.index_select(
|
|
436
|
+
x1, dim=axis, index=torch.arange(dim_cropped).to(device=x1.device)
|
|
437
|
+
)
|
|
438
|
+
x2_cropped = torch.index_select(
|
|
439
|
+
x2, dim=axis, index=torch.arange(dim_cropped).to(device=x1.device)
|
|
437
440
|
)
|
|
441
|
+
return x1_cropped, x2_cropped
|
{braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/models/zuna.py
RENAMED
|
@@ -11,6 +11,7 @@ from typing import Optional
|
|
|
11
11
|
import torch
|
|
12
12
|
from einops import rearrange
|
|
13
13
|
from einops.layers.torch import Rearrange
|
|
14
|
+
from rotary_embedding_torch import RotaryEmbedding
|
|
14
15
|
from torch import nn
|
|
15
16
|
from torch.nn import functional
|
|
16
17
|
|
|
@@ -274,11 +275,18 @@ class ZUNA(EEGModuleMixin, nn.Module):
|
|
|
274
275
|
(channel_position_indices, coarse_time_indices.unsqueeze(1)), dim=1
|
|
275
276
|
)
|
|
276
277
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
278
|
+
rotary_embedding = RotaryEmbedding(
|
|
279
|
+
# rotary_embedding_torch cannot construct dim=2 directly because
|
|
280
|
+
# of its theta-rescaling formula; dim=4 followed by slicing is
|
|
281
|
+
# equivalent for the single-frequency dim=2 case.
|
|
282
|
+
dim=max(rotary_axis_dim, 4),
|
|
280
283
|
theta=rope_theta,
|
|
284
|
+
cache_if_possible=False,
|
|
281
285
|
)
|
|
286
|
+
with torch.no_grad():
|
|
287
|
+
rotary_frequency_table = rotary_embedding(
|
|
288
|
+
torch.arange(max_seqlen, dtype=torch.float32)
|
|
289
|
+
)[:, :rotary_axis_dim]
|
|
282
290
|
token_rotary_frequencies = rearrange(
|
|
283
291
|
rotary_frequency_table[token_position_indices],
|
|
284
292
|
"token coordinate rotary_frequency -> token (coordinate rotary_frequency)",
|
|
@@ -336,28 +344,6 @@ class ZUNA(EEGModuleMixin, nn.Module):
|
|
|
336
344
|
)
|
|
337
345
|
|
|
338
346
|
|
|
339
|
-
def _build_rotary_frequency_table(
|
|
340
|
-
positions: torch.Tensor, *, axis_dim: int, theta: float
|
|
341
|
-
) -> torch.Tensor:
|
|
342
|
-
"""Build ZUNA's per-axis rotary frequencies with native PyTorch."""
|
|
343
|
-
embedding_dim = max(axis_dim, 4)
|
|
344
|
-
inverse_frequencies = 1.0 / (
|
|
345
|
-
theta
|
|
346
|
-
** (
|
|
347
|
-
torch.arange(
|
|
348
|
-
0,
|
|
349
|
-
embedding_dim,
|
|
350
|
-
2,
|
|
351
|
-
device=positions.device,
|
|
352
|
-
dtype=torch.float32,
|
|
353
|
-
)
|
|
354
|
-
/ embedding_dim
|
|
355
|
-
)
|
|
356
|
-
)
|
|
357
|
-
angles = positions.to(torch.float32).unsqueeze(-1) * inverse_frequencies
|
|
358
|
-
return angles.repeat_interleave(2, dim=-1)[:, :axis_dim]
|
|
359
|
-
|
|
360
|
-
|
|
361
347
|
class _RotaryPositionEmbedding(nn.Module):
|
|
362
348
|
def __init__(self):
|
|
363
349
|
super().__init__()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.8.0.dev180935432"
|
{braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432/braindecode.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: braindecode
|
|
3
|
-
Version: 1.8.0.
|
|
3
|
+
Version: 1.8.0.dev180935432
|
|
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>
|
|
@@ -34,6 +34,7 @@ Requires-Dist: pandas
|
|
|
34
34
|
Requires-Dist: wfdb>=4.3.1
|
|
35
35
|
Requires-Dist: linear_attention_transformer
|
|
36
36
|
Requires-Dist: docstring_inheritance
|
|
37
|
+
Requires-Dist: rotary_embedding_torch
|
|
37
38
|
Requires-Dist: pydantic>=2.0
|
|
38
39
|
Provides-Extra: moabb
|
|
39
40
|
Requires-Dist: moabb>=1.4.3; extra == "moabb"
|
|
@@ -50,7 +51,6 @@ Requires-Dist: pytest-cov; extra == "tests"
|
|
|
50
51
|
Requires-Dist: codecov; extra == "tests"
|
|
51
52
|
Requires-Dist: pytest_cases; extra == "tests"
|
|
52
53
|
Requires-Dist: mypy; extra == "tests"
|
|
53
|
-
Requires-Dist: ipython; extra == "tests"
|
|
54
54
|
Requires-Dist: transformers>=4.57.0; extra == "tests"
|
|
55
55
|
Requires-Dist: bids_validator; extra == "tests"
|
|
56
56
|
Provides-Extra: typing
|
{braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode.egg-info/SOURCES.txt
RENAMED
|
@@ -20,7 +20,6 @@ braindecode/augmentation/base.py
|
|
|
20
20
|
braindecode/augmentation/functional.py
|
|
21
21
|
braindecode/augmentation/transforms.py
|
|
22
22
|
braindecode/datasets/__init__.py
|
|
23
|
-
braindecode/datasets/_notebook_viewer.py
|
|
24
23
|
braindecode/datasets/base.py
|
|
25
24
|
braindecode/datasets/bbci.py
|
|
26
25
|
braindecode/datasets/bcicomp.py
|
{braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode.egg-info/requires.txt
RENAMED
|
@@ -10,6 +10,7 @@ pandas
|
|
|
10
10
|
wfdb>=4.3.1
|
|
11
11
|
linear_attention_transformer
|
|
12
12
|
docstring_inheritance
|
|
13
|
+
rotary_embedding_torch
|
|
13
14
|
pydantic>=2.0
|
|
14
15
|
|
|
15
16
|
[all]
|
|
@@ -60,7 +61,6 @@ pytest-cov
|
|
|
60
61
|
codecov
|
|
61
62
|
pytest_cases
|
|
62
63
|
mypy
|
|
63
|
-
ipython
|
|
64
64
|
transformers>=4.57.0
|
|
65
65
|
bids_validator
|
|
66
66
|
|
|
@@ -28,12 +28,6 @@ Current 1.8.0 (GitHub)
|
|
|
28
28
|
Enhancements
|
|
29
29
|
============
|
|
30
30
|
|
|
31
|
-
- Add :meth:`braindecode.datasets.BaseConcatDataset.plot` (every dataset, ``BIDSDataset`` included): show a recording in the
|
|
32
|
-
`eegdash-viewer <https://github.com/eegdash/eegdash-viewer>`_ inside a
|
|
33
|
-
Jupyter cell — serverless (bytes inlined, viewer from CDN), with the
|
|
34
|
-
synchronized hand-pose panel when a ``*_desc-pose.json`` sidecar is present
|
|
35
|
-
(:gh:`1133` by `Bruno Aristimunha`_)
|
|
36
|
-
|
|
37
31
|
- Preserve the recording-local row of each canonical MNE annotation as
|
|
38
32
|
``i_trial_in_dataset`` in event-window metadata, keeping it aligned with
|
|
39
33
|
targets and annotation extras through event mapping, duration filtering,
|
|
@@ -73,30 +67,11 @@ API and behavior changes
|
|
|
73
67
|
Requirements
|
|
74
68
|
============
|
|
75
69
|
|
|
76
|
-
-
|
|
77
|
-
generation used by :class:`braindecode.models.LUNA` and
|
|
78
|
-
:class:`braindecode.models.ZUNA` is now implemented directly with PyTorch.
|
|
79
|
-
(:gh:`1136` by `Bruno Aristimunha`_)
|
|
70
|
+
- None yet
|
|
80
71
|
|
|
81
72
|
Bug fixes
|
|
82
73
|
==========
|
|
83
74
|
|
|
84
|
-
- Sample stochastic-depth masks with out-of-place
|
|
85
|
-
:func:`torch.bernoulli` instead of in-place ``Tensor.bernoulli_``. This keeps
|
|
86
|
-
the same per-sample Bernoulli mask and scaling while avoiding lazy
|
|
87
|
-
recipe-cache offset failures on Gaudi accelerators. The
|
|
88
|
-
:func:`braindecode.functional.drop_path` documentation now also correctly
|
|
89
|
-
describes ``drop_prob`` as the probability of dropping a path. By `Bruno
|
|
90
|
-
Aristimunha`_.
|
|
91
|
-
|
|
92
|
-
- Make :class:`braindecode.models.LUNA` rotary attention portable to
|
|
93
|
-
accelerators that reject concatenations containing empty tensor views, while
|
|
94
|
-
preserving its pretrained-checkpoint parameter keys and numerical behavior.
|
|
95
|
-
Also crop mismatched :class:`braindecode.models.USleep` decoder tensors with
|
|
96
|
-
views instead of allocating index tensors, avoiding unsupported accelerator
|
|
97
|
-
lowering without changing the selected samples. (:gh:`1136` by `Bruno
|
|
98
|
-
Aristimunha`_)
|
|
99
|
-
|
|
100
75
|
- Fix the docstrings of :class:`braindecode.models.ATCNet`,
|
|
101
76
|
:class:`braindecode.models.AttnSleep`, :class:`braindecode.models.CTNet`,
|
|
102
77
|
:class:`braindecode.models.EEGSimpleConv`, :class:`braindecode.models.IFNet`,
|
|
@@ -57,6 +57,7 @@ dependencies = [
|
|
|
57
57
|
'wfdb>=4.3.1', # requests comes transitively via mne→pooch and wfdb
|
|
58
58
|
'linear_attention_transformer',
|
|
59
59
|
'docstring_inheritance', # we get einops from here
|
|
60
|
+
'rotary_embedding_torch',
|
|
60
61
|
'pydantic>=2.0',
|
|
61
62
|
]
|
|
62
63
|
|
|
@@ -84,7 +85,6 @@ tests = [
|
|
|
84
85
|
'codecov',
|
|
85
86
|
'pytest_cases',
|
|
86
87
|
'mypy',
|
|
87
|
-
'ipython',
|
|
88
88
|
"transformers>=4.57.0",
|
|
89
89
|
"bids_validator",
|
|
90
90
|
]
|
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
# Authors: Bruno Aristimunha <b.aristimunha@gmail.com>
|
|
2
|
-
#
|
|
3
|
-
# License: BSD (3-clause)
|
|
4
|
-
"""Serverless in-notebook viewer for file-backed recordings.
|
|
5
|
-
|
|
6
|
-
The bytes on disk behind a dataset element are inlined in the cell output
|
|
7
|
-
as base64 and handed to the deployed eegdash-viewer over its ``postMessage``
|
|
8
|
-
bridge (``docs/embedding.md`` in https://github.com/eegdash/eegdash-viewer):
|
|
9
|
-
no server, no CORS. The output is an iframe plus an inline script, so it
|
|
10
|
-
renders when the cell ran in your session or the saved notebook is trusted
|
|
11
|
-
(``jupyter trust``).
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
from __future__ import annotations
|
|
15
|
-
|
|
16
|
-
import base64
|
|
17
|
-
import json
|
|
18
|
-
import os
|
|
19
|
-
import uuid
|
|
20
|
-
from pathlib import Path
|
|
21
|
-
from urllib.parse import urlsplit
|
|
22
|
-
|
|
23
|
-
import mne_bids
|
|
24
|
-
from mne.utils import _soft_import
|
|
25
|
-
|
|
26
|
-
CDN = "https://eegdash.github.io/eegdash-viewer"
|
|
27
|
-
MAX_BYTES = 64 * 2**20 # base64 output per call; it is saved with the notebook
|
|
28
|
-
EXTENSIONS = {
|
|
29
|
-
".set",
|
|
30
|
-
".edf",
|
|
31
|
-
".bdf",
|
|
32
|
-
".vhdr",
|
|
33
|
-
".fif",
|
|
34
|
-
".snirf",
|
|
35
|
-
".nwb",
|
|
36
|
-
} # viewer readers
|
|
37
|
-
_BIDS = {"eeg", "ieeg", "emg", "meg", "nirs"}
|
|
38
|
-
_SIBLINGS = {".vhdr": (".eeg", ".vmrk"), ".set": (".fdt",)} # travel with the header
|
|
39
|
-
_HEADER = {s: h for h, ss in _SIBLINGS.items() for s in ss} # data file -> header
|
|
40
|
-
|
|
41
|
-
_SCRIPT = """<iframe id=%(id)s title="eegdash trace viewer" style="width:100%%;height:%(height)spx;
|
|
42
|
-
border:1px solid var(--jp-border-color1,#d9dce1);border-radius:6px;background:transparent"></iframe>
|
|
43
|
-
<script>
|
|
44
|
-
(function () {
|
|
45
|
-
var self = document.currentScript, id = %(id)s; // Lab re-runs scripts in place; VS Code/nbclassic elsewhere
|
|
46
|
-
var frame = (self && self.previousElementSibling && self.previousElementSibling.tagName === "IFRAME")
|
|
47
|
-
? self.previousElementSibling : document.getElementById(id);
|
|
48
|
-
if (!frame) { console.error("eegdash viewer: output iframe " + id + " not found"); return; }
|
|
49
|
-
var payload = %(payload)s, origin = %(origin)s, files = null, pose = null;
|
|
50
|
-
function decode(b64) {
|
|
51
|
-
if (Uint8Array.fromBase64) return Uint8Array.fromBase64(b64);
|
|
52
|
-
var bin = atob(b64), out = new Uint8Array(bin.length);
|
|
53
|
-
for (var i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
54
|
-
return out;
|
|
55
|
-
}
|
|
56
|
-
function send(target) {
|
|
57
|
-
try {
|
|
58
|
-
if (!files) {
|
|
59
|
-
files = payload.files.map(function (f) { return new File([decode(f.b64)], f.name); });
|
|
60
|
-
pose = payload.pose ? "data:application/json;base64," + payload.pose : null;
|
|
61
|
-
payload = null;
|
|
62
|
-
}
|
|
63
|
-
frame.contentWindow.postMessage({ type: "eegdash-viewer:open", files: files, pose: pose }, target || origin);
|
|
64
|
-
} catch (err) {
|
|
65
|
-
frame.insertAdjacentHTML("afterend", '<div style="font:12px system-ui;color:#b3261e">eegdash viewer: '
|
|
66
|
-
+ String(err.message).replace(/</g, "<") + "</div>");
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
window.addEventListener("message", function onMessage(e) {
|
|
70
|
-
if (e.source === frame.contentWindow && e.data && e.data.type === "eegdash-viewer:ready") send(e.origin);
|
|
71
|
-
else if (!frame.isConnected) window.removeEventListener("message", onMessage);
|
|
72
|
-
});
|
|
73
|
-
frame.src = %(src)s; // after the listener, so "ready" can never precede it
|
|
74
|
-
})();
|
|
75
|
-
</script>"""
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
def recording_files(recording: Path) -> tuple[list[Path], Path | None]:
|
|
79
|
-
"""``(files, pose)`` to inline for a recording: the header first, then the
|
|
80
|
-
split-format siblings, the BIDS-inherited ``_channels.tsv``/``_events.tsv``
|
|
81
|
-
(``mne_bids`` parses the name; plain names get none) and, separately, the
|
|
82
|
-
``<prefix>_desc-pose.json`` hand-pose sidecar next to it. Symlinks keep
|
|
83
|
-
their name (git-annex/datalad)."""
|
|
84
|
-
rec = Path(recording)
|
|
85
|
-
if not rec.exists():
|
|
86
|
-
raise ValueError(
|
|
87
|
-
f"{rec.name}: file not found (a datalad symlink may need `datalad get`)"
|
|
88
|
-
)
|
|
89
|
-
if (
|
|
90
|
-
rec.is_dir()
|
|
91
|
-
or rec.suffix.lower() not in EXTENSIONS
|
|
92
|
-
or rec.stem.endswith("_epo")
|
|
93
|
-
):
|
|
94
|
-
raise ValueError(
|
|
95
|
-
f"{rec.name}: the viewer opens raw recordings in {' '.join(sorted(EXTENSIONS))}"
|
|
96
|
-
)
|
|
97
|
-
sidecars: list[Path | None] = []
|
|
98
|
-
try:
|
|
99
|
-
bids = mne_bids.get_bids_path_from_fname(rec, check=False)
|
|
100
|
-
if bids.subject is not None: # hyphen-free names parse, but are not BIDS
|
|
101
|
-
sidecars = [
|
|
102
|
-
bids.find_matching_sidecar(
|
|
103
|
-
suffix=s, extension=".tsv", on_error="ignore"
|
|
104
|
-
)
|
|
105
|
-
for s in ("channels", "events")
|
|
106
|
-
]
|
|
107
|
-
except (
|
|
108
|
-
KeyError,
|
|
109
|
-
ValueError,
|
|
110
|
-
): # not a BIDS name / unknown entity somewhere in the tree
|
|
111
|
-
pass
|
|
112
|
-
files = [rec]
|
|
113
|
-
for p in [
|
|
114
|
-
rec.with_suffix(e) for e in _SIBLINGS.get(rec.suffix.lower(), ())
|
|
115
|
-
] + sidecars:
|
|
116
|
-
if p and p.is_file():
|
|
117
|
-
if p not in files:
|
|
118
|
-
files.append(p)
|
|
119
|
-
elif p and p.is_symlink(): # dangling: git-annex/datalad content not fetched
|
|
120
|
-
raise ValueError(f"{p.name}: dangling symlink (try `datalad get`)")
|
|
121
|
-
stem, _, token = rec.stem.rpartition("_")
|
|
122
|
-
pose = rec.with_name((stem if token in _BIDS else rec.stem) + "_desc-pose.json")
|
|
123
|
-
return files, pose if pose.is_file() else None
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
def build_viewer_html(
|
|
127
|
-
recording: Path,
|
|
128
|
-
*,
|
|
129
|
-
height: int = 520,
|
|
130
|
-
cdn_url: str = CDN,
|
|
131
|
-
max_bytes: int = MAX_BYTES,
|
|
132
|
-
) -> str:
|
|
133
|
-
"""Viewer iframe + inlined bytes + bridge script for one recording."""
|
|
134
|
-
url = urlsplit(cdn_url)
|
|
135
|
-
if (
|
|
136
|
-
url.scheme not in ("http", "https")
|
|
137
|
-
or not url.netloc
|
|
138
|
-
or url.username
|
|
139
|
-
or url.query
|
|
140
|
-
or url.fragment
|
|
141
|
-
or url.path.endswith(("index.html", "index.htm"))
|
|
142
|
-
):
|
|
143
|
-
raise ValueError(
|
|
144
|
-
f"cdn_url must be the viewer's base http(s) URL, got {cdn_url!r}"
|
|
145
|
-
)
|
|
146
|
-
files, pose = recording_files(recording)
|
|
147
|
-
encoded = sum(
|
|
148
|
-
4 * -(-p.stat().st_size // 3) for p in files + ([pose] if pose else [])
|
|
149
|
-
)
|
|
150
|
-
if encoded > max_bytes:
|
|
151
|
-
raise ValueError(
|
|
152
|
-
f"{files[0].name}: {encoded / 2**20:.1f} MiB of base64 would be inlined into the "
|
|
153
|
-
f"notebook output (max_bytes={max_bytes / 2**20:.1f} MiB); crop/downsample or raise it"
|
|
154
|
-
)
|
|
155
|
-
rec = files[0]
|
|
156
|
-
# The viewer picks the recording by its *_<datatype>.<ext> name: plain names
|
|
157
|
-
# are posted as <stem>_eeg<ext>, an EEGLAB .fdt next to the posted .set name.
|
|
158
|
-
head = (
|
|
159
|
-
rec.name
|
|
160
|
-
if rec.stem.rpartition("_")[2] in _BIDS
|
|
161
|
-
else f"{rec.stem}_eeg{rec.suffix.lower()}"
|
|
162
|
-
)
|
|
163
|
-
names = [head] + [
|
|
164
|
-
head.rsplit("_", 1)[0] + "_eeg.fdt" if p.suffix.lower() == ".fdt" else p.name
|
|
165
|
-
for p in files[1:]
|
|
166
|
-
]
|
|
167
|
-
b64 = [base64.b64encode(p.read_bytes()).decode() for p in files]
|
|
168
|
-
literals = {
|
|
169
|
-
"id": f"eegdash-viewer-{uuid.uuid4().hex[:8]}",
|
|
170
|
-
"height": int(height),
|
|
171
|
-
"payload": {
|
|
172
|
-
"files": [{"name": n, "b64": b} for n, b in zip(names, b64)],
|
|
173
|
-
"pose": base64.b64encode(pose.read_bytes()).decode() if pose else None,
|
|
174
|
-
},
|
|
175
|
-
"origin": f"{url.scheme}://{url.netloc}",
|
|
176
|
-
"src": f"{url.geturl().rstrip('/')}/index.html?embed=1",
|
|
177
|
-
}
|
|
178
|
-
return _SCRIPT % {
|
|
179
|
-
k: json.dumps(v).replace("<", "\\u003c") for k, v in literals.items()
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
def _recording(dataset, index: int) -> Path:
|
|
184
|
-
"""File behind ``dataset.datasets[index]``: the one its mne ``raw`` reads (a
|
|
185
|
-
data file maps back to its header; lazily downloading datasets fetch it when
|
|
186
|
-
``raw`` is accessed) or the recorded ``description["path"]``."""
|
|
187
|
-
ds = dataset.datasets[index]
|
|
188
|
-
names = [
|
|
189
|
-
Path(f)
|
|
190
|
-
for f in getattr(getattr(ds, "raw", None), "filenames", None) or ()
|
|
191
|
-
if isinstance(f, (str, os.PathLike))
|
|
192
|
-
]
|
|
193
|
-
if len(names) > 1:
|
|
194
|
-
raise ValueError(
|
|
195
|
-
f"{type(dataset).__name__}[{index}]: split recordings are not supported"
|
|
196
|
-
)
|
|
197
|
-
desc = getattr(ds, "description", None) # dict or pandas Series
|
|
198
|
-
recorded = desc.get("path") if desc is not None else None
|
|
199
|
-
path = (
|
|
200
|
-
names[0]
|
|
201
|
-
if names
|
|
202
|
-
else Path(recorded)
|
|
203
|
-
if isinstance(recorded, (str, os.PathLike))
|
|
204
|
-
else None
|
|
205
|
-
)
|
|
206
|
-
if path is None:
|
|
207
|
-
raise ValueError(
|
|
208
|
-
f"{type(dataset).__name__}[{index}] is not backed by a recording file"
|
|
209
|
-
)
|
|
210
|
-
header = path.with_suffix(_HEADER.get(path.suffix.lower(), path.suffix))
|
|
211
|
-
return header if header.is_file() else path
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
def plot(
|
|
215
|
-
dataset,
|
|
216
|
-
index: int = 0,
|
|
217
|
-
*,
|
|
218
|
-
height: int = 520,
|
|
219
|
-
cdn_url: str = CDN,
|
|
220
|
-
max_bytes: int = MAX_BYTES,
|
|
221
|
-
):
|
|
222
|
-
"""Show one recording in the eegdash-viewer inside a Jupyter cell.
|
|
223
|
-
|
|
224
|
-
Serverless: the recording bytes (as on disk) are inlined in the output and
|
|
225
|
-
pushed to the viewer at ``cdn_url`` over ``postMessage``; the output renders
|
|
226
|
-
when the cell ran in your session or the notebook is trusted. A
|
|
227
|
-
``*_desc-pose.json`` sidecar next to the recording adds the synchronized
|
|
228
|
-
hand-pose panel. Needs IPython (soft dependency).
|
|
229
|
-
|
|
230
|
-
Parameters
|
|
231
|
-
----------
|
|
232
|
-
index : int
|
|
233
|
-
Recording to display.
|
|
234
|
-
height : int
|
|
235
|
-
Viewer height in pixels.
|
|
236
|
-
cdn_url : str
|
|
237
|
-
Base URL of a deployed eegdash-viewer.
|
|
238
|
-
max_bytes : int
|
|
239
|
-
Refuse to inline more than this much base64 (default 64 MiB); the
|
|
240
|
-
payload is saved with the notebook and, like any cell output, stays
|
|
241
|
-
referenced by IPython's ``Out`` history for the session.
|
|
242
|
-
|
|
243
|
-
Returns
|
|
244
|
-
-------
|
|
245
|
-
IPython.display.HTML
|
|
246
|
-
"""
|
|
247
|
-
ipython = _soft_import("IPython", purpose=f"{type(dataset).__name__}.plot()")
|
|
248
|
-
return ipython.display.HTML(
|
|
249
|
-
build_viewer_html(
|
|
250
|
-
_recording(dataset, index),
|
|
251
|
-
height=height,
|
|
252
|
-
cdn_url=cdn_url,
|
|
253
|
-
max_bytes=max_bytes,
|
|
254
|
-
)
|
|
255
|
-
)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "1.8.0.dev180516540"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/augmentation/base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/__init__.py
RENAMED
|
File without changes
|
{braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/bbci.py
RENAMED
|
File without changes
|
{braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/bcicomp.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{braindecode-1.8.0.dev180516540 → braindecode-1.8.0.dev180935432}/braindecode/datasets/bids/hub.py
RENAMED
|
File without changes
|
|
File without changes
|