braindecode 1.8.1.dev174129228__tar.gz → 1.8.1.dev174246559__tar.gz

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