Braindecode 1.3.2.dev183987088__tar.gz → 1.3.2.dev184103859__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 (162) hide show
  1. {braindecode-1.3.2.dev183987088/braindecode.egg-info → braindecode-1.3.2.dev184103859}/PKG-INFO +3 -3
  2. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/bids/hub.py +2 -7
  3. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/__init__.py +0 -2
  4. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/base.py +81 -142
  5. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/cbramod.py +5 -19
  6. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/config.py +29 -29
  7. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/luna.py +7 -8
  8. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/patchedtransformer.py +3 -5
  9. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/reve.py +3 -23
  10. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/shallow_fbcsp.py +8 -16
  11. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/util.py +2 -133
  12. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/modules/__init__.py +1 -2
  13. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/modules/activation.py +0 -20
  14. braindecode-1.3.2.dev184103859/braindecode/version.py +1 -0
  15. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859/braindecode.egg-info}/PKG-INFO +3 -3
  16. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode.egg-info/requires.txt +2 -2
  17. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/conf.py +7 -0
  18. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/models/models_categorization.rst +1 -2
  19. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/whats_new.rst +2 -32
  20. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/pyproject.toml +2 -11
  21. braindecode-1.3.2.dev183987088/braindecode/version.py +0 -1
  22. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/LICENSE.txt +0 -0
  23. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/MANIFEST.in +0 -0
  24. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/NOTICE.txt +0 -0
  25. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/README.rst +0 -0
  26. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/__init__.py +0 -0
  27. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/augmentation/__init__.py +0 -0
  28. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/augmentation/base.py +0 -0
  29. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/augmentation/functional.py +0 -0
  30. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/augmentation/transforms.py +0 -0
  31. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/classifier.py +0 -0
  32. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/__init__.py +0 -0
  33. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/base.py +0 -0
  34. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/bbci.py +0 -0
  35. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/bcicomp.py +0 -0
  36. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/bids/__init__.py +0 -0
  37. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/bids/datasets.py +0 -0
  38. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/bids/format.py +0 -0
  39. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/bids/hub_format.py +0 -0
  40. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/bids/hub_io.py +0 -0
  41. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/bids/hub_validation.py +0 -0
  42. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/bids/iterable.py +0 -0
  43. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/chb_mit.py +0 -0
  44. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/mne.py +0 -0
  45. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/moabb.py +0 -0
  46. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/nmt.py +0 -0
  47. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/registry.py +0 -0
  48. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/siena.py +0 -0
  49. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
  50. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/sleep_physionet.py +0 -0
  51. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/tuh.py +0 -0
  52. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/utils.py +0 -0
  53. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datasets/xy.py +0 -0
  54. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datautil/__init__.py +0 -0
  55. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datautil/channel_utils.py +0 -0
  56. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datautil/hub_formats.py +0 -0
  57. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datautil/serialization.py +0 -0
  58. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/datautil/util.py +0 -0
  59. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/eegneuralnet.py +0 -0
  60. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/functional/__init__.py +0 -0
  61. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/functional/functions.py +0 -0
  62. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/functional/initialization.py +0 -0
  63. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/atcnet.py +0 -0
  64. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/attentionbasenet.py +0 -0
  65. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/attn_sleep.py +0 -0
  66. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/bendr.py +0 -0
  67. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/biot.py +0 -0
  68. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/brainmodule.py +0 -0
  69. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/contrawr.py +0 -0
  70. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/ctnet.py +0 -0
  71. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/deep4.py +0 -0
  72. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/deepsleepnet.py +0 -0
  73. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/dgcnn.py +0 -0
  74. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/eegconformer.py +0 -0
  75. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/eeginception_erp.py +0 -0
  76. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/eeginception_mi.py +0 -0
  77. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/eegitnet.py +0 -0
  78. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/eegminer.py +0 -0
  79. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/eegnet.py +0 -0
  80. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/eegnex.py +0 -0
  81. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/eegpt.py +0 -0
  82. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/eegsimpleconv.py +0 -0
  83. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/eegsym.py +0 -0
  84. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/eegtcnet.py +0 -0
  85. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/fbcnet.py +0 -0
  86. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/fblightconvnet.py +0 -0
  87. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/fbmsnet.py +0 -0
  88. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/hybrid.py +0 -0
  89. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/ifnet.py +0 -0
  90. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/labram.py +0 -0
  91. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/medformer.py +0 -0
  92. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/msvtnet.py +0 -0
  93. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/sccnet.py +0 -0
  94. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/signal_jepa.py +0 -0
  95. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/sinc_shallow.py +0 -0
  96. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
  97. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
  98. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/sparcnet.py +0 -0
  99. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/sstdpn.py +0 -0
  100. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/summary.csv +0 -0
  101. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/syncnet.py +0 -0
  102. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/tcn.py +0 -0
  103. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/tidnet.py +0 -0
  104. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/tsinception.py +0 -0
  105. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/models/usleep.py +0 -0
  106. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/modules/attention.py +0 -0
  107. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/modules/blocks.py +0 -0
  108. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/modules/convolution.py +0 -0
  109. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/modules/filter.py +0 -0
  110. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/modules/layers.py +0 -0
  111. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/modules/linear.py +0 -0
  112. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/modules/parametrization.py +0 -0
  113. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/modules/stats.py +0 -0
  114. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/modules/util.py +0 -0
  115. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/modules/wrapper.py +0 -0
  116. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/preprocessing/__init__.py +0 -0
  117. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
  118. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/preprocessing/mne_preprocess.py +0 -0
  119. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/preprocessing/preprocess.py +0 -0
  120. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/preprocessing/util.py +0 -0
  121. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/preprocessing/windowers.py +0 -0
  122. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/regressor.py +0 -0
  123. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/samplers/__init__.py +0 -0
  124. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/samplers/base.py +0 -0
  125. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/samplers/ssl.py +0 -0
  126. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/training/__init__.py +0 -0
  127. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/training/callbacks.py +0 -0
  128. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/training/losses.py +0 -0
  129. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/training/scoring.py +0 -0
  130. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/util.py +0 -0
  131. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/visualization/__init__.py +0 -0
  132. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/visualization/confusion_matrices.py +0 -0
  133. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode/visualization/gradients.py +0 -0
  134. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode.egg-info/SOURCES.txt +0 -0
  135. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode.egg-info/dependency_links.txt +0 -0
  136. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/braindecode.egg-info/top_level.txt +0 -0
  137. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/Makefile +0 -0
  138. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/_templates/autosummary/class.rst +0 -0
  139. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
  140. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/_templates/autosummary/function.rst +0 -0
  141. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
  142. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/api.rst +0 -0
  143. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/cite.rst +0 -0
  144. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/help.rst +0 -0
  145. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/index.rst +0 -0
  146. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/install/install.rst +0 -0
  147. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/install/install_pip.rst +0 -0
  148. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/install/install_source.rst +0 -0
  149. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/models/categorization/attention.rst +0 -0
  150. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/models/categorization/channel.rst +0 -0
  151. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/models/categorization/convolution.rst +0 -0
  152. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/models/categorization/filterbank.rst +0 -0
  153. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/models/categorization/gnn.rst +0 -0
  154. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/models/categorization/interpretable.rst +0 -0
  155. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/models/categorization/lbm.rst +0 -0
  156. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/models/categorization/recurrent.rst +0 -0
  157. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/models/categorization/spd.rst +0 -0
  158. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/models/models.rst +0 -0
  159. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/models/models_table.rst +0 -0
  160. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/models/models_visualization.rst +0 -0
  161. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/docs/sg_execution_times.rst +0 -0
  162. {braindecode-1.3.2.dev183987088 → braindecode-1.3.2.dev184103859}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: braindecode
3
- Version: 1.3.2.dev183987088
3
+ Version: 1.3.2.dev184103859
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>
@@ -22,7 +22,7 @@ Requires-Python: >=3.11
22
22
  Description-Content-Type: text/x-rst
23
23
  License-File: LICENSE.txt
24
24
  License-File: NOTICE.txt
25
- Requires-Dist: torch>=2.0
25
+ Requires-Dist: torch>=2.2
26
26
  Requires-Dist: torchaudio>=2.0
27
27
  Requires-Dist: mne>=1.11.0
28
28
  Requires-Dist: pandas<3.0.0
@@ -35,7 +35,7 @@ Requires-Dist: wfdb
35
35
  Requires-Dist: linear_attention_transformer
36
36
  Requires-Dist: docstring_inheritance
37
37
  Requires-Dist: rotary_embedding_torch
38
- Requires-Dist: pydantic>=2.0
38
+ Requires-Dist: pandas<3.0.0
39
39
  Provides-Extra: moabb
40
40
  Requires-Dist: moabb>=1.4.3; extra == "moabb"
41
41
  Provides-Extra: eegprep
@@ -845,16 +845,11 @@ class HubDatasetMixin:
845
845
 
846
846
  # Convert to MNE objects and create dataset
847
847
  info = Info.from_json_dict(info_dict)
848
- targets = metadata["target"].values
849
- if np.issubdtype(targets.dtype, np.integer):
850
- event_ids = targets
851
- else:
852
- event_ids = np.ones(len(metadata), dtype=int)
853
848
  events = np.column_stack(
854
849
  [
855
- metadata["i_start_in_trial"].values.astype(int),
850
+ metadata["i_start_in_trial"].values,
856
851
  np.zeros(len(metadata), dtype=int),
857
- event_ids,
852
+ metadata["target"].values,
858
853
  ]
859
854
  )
860
855
  epochs = mne.EpochsArray(data, info, events=events, metadata=metadata)
@@ -55,7 +55,6 @@ from .tsinception import TSception
55
55
  from .usleep import USleep
56
56
  from .util import (
57
57
  _init_models_dict,
58
- build_model_config,
59
58
  extract_channel_locations_from_chs_info,
60
59
  models_mandatory_parameters,
61
60
  )
@@ -119,7 +118,6 @@ __all__ = [
119
118
  "TIDNet",
120
119
  "TSception",
121
120
  "USleep",
122
- "build_model_config",
123
121
  "_init_models_dict",
124
122
  "models_mandatory_parameters",
125
123
  ]
@@ -17,13 +17,6 @@ from docstring_inheritance import NumpyDocstringInheritanceInitMeta
17
17
  from mne.utils import _soft_import
18
18
  from torchinfo import ModelStatistics, summary
19
19
 
20
- from braindecode.models.util import (
21
- _EEG_PARAMS,
22
- _IMPORT_ADAPTER,
23
- build_model_config,
24
- resolve_type_kwargs,
25
- track_model_init_kwargs,
26
- )
27
20
  from braindecode.version import __version__
28
21
 
29
22
  huggingface_hub = _soft_import(
@@ -59,25 +52,7 @@ def deprecated_args(obj, *old_new_args):
59
52
  return out_args
60
53
 
61
54
 
62
- class _BraindecodeDocstringMeta(NumpyDocstringInheritanceInitMeta):
63
- """Defer ``__init__`` wrapping until after docstring inheritance.
64
-
65
- ``NumpyDocstringInheritanceInitMeta`` uses ``inspect.unwrap()``
66
- internally, which bypasses ``@wraps`` wrappers. By wrapping
67
- ``__init__`` *after* docstring processing, the metaclass sees the
68
- unwrapped function and correctly inherits ``cls.__doc__``.
69
- """
70
-
71
- def __init__(cls, class_name, class_bases, class_dict):
72
- super().__init__(class_name, class_bases, class_dict)
73
- # Only wrap subclass __init__s, not EEGModuleMixin itself.
74
- # Wrapping the mixin would cause super().__init__() calls to
75
- # overwrite _braindecode_init_kwargs captured by the subclass.
76
- if any(isinstance(b, _BraindecodeDocstringMeta) for b in class_bases):
77
- track_model_init_kwargs(cls)
78
-
79
-
80
- class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
55
+ class EEGModuleMixin(_BaseHubMixin, metaclass=NumpyDocstringInheritanceInitMeta):
81
56
  """
82
57
  Mixin class for all EEG models in braindecode.
83
58
 
@@ -155,15 +130,19 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
155
130
  the model weights. This ensures that loaded models are correctly configured
156
131
  for their original data specifications.
157
132
 
158
- All model parameters (both EEG-specific and model-specific such as
159
- dropout rates, activation functions, number of filters) are automatically
160
- saved to the Hub and restored when loading.
133
+ .. important::
134
+ Currently, only EEG-specific parameters (n_outputs, n_chans, n_times,
135
+ input_window_seconds, sfreq, chs_info) are saved to the Hub.
136
+ Model-specific parameters (e.g., dropout rates, activation functions,
137
+ number of filters) are not preserved and will use their default values
138
+ when loading from the Hub.
139
+ Full parameter serialization will be addressed in a future update.
161
140
  """
162
141
 
163
142
  def __init_subclass__(cls, **kwargs):
164
143
  # Append model-specific Hub integration notes to the docstring.
165
- # This runs before the metaclass __init__, so the Hub notes will
166
- # be included in the docstring that the metaclass processes.
144
+ # This runs after the metaclass, so we concatenate rather than
145
+ # override any existing Notes section in the subclass.
167
146
  if cls.__doc__ is not None:
168
147
  hub_notes = cls._HUB_NOTES_TEMPLATE.format(
169
148
  name=cls.__name__,
@@ -189,19 +168,6 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
189
168
  repo_url = kwargs.pop("repo_url", "https://braindecode.org")
190
169
  library_name = kwargs.pop("library_name", "braindecode")
191
170
  license = kwargs.pop("license", "bsd-3-clause")
192
-
193
- # Register a coder so that type[nn.Module] parameters
194
- # (e.g. activation=nn.ELU) are serialized as importable
195
- # strings in config.json and decoded back on load.
196
- coders = kwargs.pop("coders", None) or {}
197
- coders.setdefault(
198
- type,
199
- (
200
- lambda t: f"{t.__module__}.{t.__qualname__}",
201
- lambda data: _IMPORT_ADAPTER.validate_python(data),
202
- ),
203
- )
204
-
205
171
  # TODO: model_card_template can be added in the future for custom model cards
206
172
  super().__init_subclass__(
207
173
  tags=tags,
@@ -209,7 +175,6 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
209
175
  repo_url=repo_url,
210
176
  library_name=library_name,
211
177
  license=license,
212
- coders=coders,
213
178
  **kwargs,
214
179
  )
215
180
 
@@ -251,17 +216,6 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
251
216
  self._n_times = n_times # type: ignore[assignment]
252
217
  self._sfreq = sfreq # type: ignore[assignment]
253
218
 
254
- # Back-fill instance attributes from _hub_mixin_config for any
255
- # params the subclass didn't store on self. Skip EEG params
256
- # (stored as self._*) and descriptors (properties).
257
- for key, val in getattr(self, "_hub_mixin_config", {}).items():
258
- if key in _EEG_PARAMS:
259
- continue
260
- if hasattr(getattr(type(self), key, None), "__get__"):
261
- continue
262
- if not hasattr(self, key):
263
- setattr(self, key, val)
264
-
265
219
  super().__init__()
266
220
 
267
221
  @property
@@ -372,76 +326,6 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
372
326
  raise ValueError(msg) from exc
373
327
  raise exc
374
328
 
375
- def get_config(self) -> dict:
376
- """Return a JSON-serializable dict of all ``__init__`` parameters.
377
-
378
- The returned dictionary can be saved to a JSON file and later
379
- used with :meth:`from_config` to reconstruct the model (without
380
- weights). It is also used internally by :meth:`push_to_hub` to
381
- persist the full model configuration.
382
-
383
- Returns
384
- -------
385
- dict
386
- All ``__init__`` parameters, JSON-serializable.
387
- ``type[nn.Module]`` parameters (e.g. ``activation``) are
388
- encoded as importable dotted-path strings.
389
-
390
- Examples
391
- --------
392
- >>> import json
393
- >>> from braindecode.models import EEGNet
394
- >>> model = EEGNet(n_chans=22, n_times=1000, n_outputs=4, F1=16)
395
- >>> config = model.get_config()
396
- >>> config["F1"]
397
- 16
398
- >>> # Save to disk
399
- >>> with open("config.json", "w") as f:
400
- ... json.dump(config, f)
401
-
402
- .. versionadded:: 1.4
403
- """
404
- return build_model_config(self)
405
-
406
- @classmethod
407
- def from_config(cls, config: dict) -> "EEGModuleMixin":
408
- """Create a model instance from a configuration dict.
409
-
410
- This is the inverse of :meth:`get_config`. Weights are **not**
411
- loaded -- use :meth:`from_pretrained` for that.
412
-
413
- Parameters
414
- ----------
415
- config : dict
416
- Configuration dict as returned by :meth:`get_config`.
417
-
418
- Returns
419
- -------
420
- EEGModuleMixin
421
- A new model instance.
422
-
423
- Examples
424
- --------
425
- >>> import json
426
- >>> from braindecode.models import EEGNet
427
- >>> model = EEGNet(n_chans=22, n_times=1000, n_outputs=4, F1=16)
428
- >>> config = model.get_config()
429
- >>> # Reconstruct (without weights)
430
- >>> model2 = EEGNet.from_config(config)
431
- >>> model2.F1
432
- 16
433
- >>> # Or from a JSON file
434
- >>> with open("config.json") as f:
435
- ... config = json.load(f)
436
- >>> model3 = EEGNet.from_config(config)
437
-
438
- .. versionadded:: 1.4
439
- """
440
- config = dict(config) # shallow copy
441
- config.pop("braindecode_version", None)
442
- resolve_type_kwargs(cls, config)
443
- return cls(**config)
444
-
445
329
  mapping: Optional[Dict[str, str]] = None
446
330
 
447
331
  def load_state_dict(self, state_dict, *args, **kwargs):
@@ -546,22 +430,54 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
546
430
 
547
431
  @staticmethod
548
432
  def _serialize_chs_info(chs_info):
549
- """Serialize MNE channel info (``info["chs"]``) to JSON-compatible dicts."""
433
+ """
434
+ Serialize MNE channel info to JSON-compatible format.
435
+
436
+ Parameters
437
+ ----------
438
+ chs_info : list of dict or None
439
+ Channel information from MNE Info object.
440
+
441
+ Returns
442
+ -------
443
+ list of dict or None
444
+ Serialized channel information that can be saved to JSON.
445
+ """
550
446
  if chs_info is None:
551
447
  return None
552
- _INT_FIELDS = ("kind", "coil_type", "unit")
553
- _FLOAT_FIELDS = ("cal", "range")
448
+
554
449
  serialized = []
555
450
  for ch in chs_info:
556
- ch_dict = {"ch_name": ch.get("ch_name", "")}
557
- for key in _INT_FIELDS:
558
- val = ch.get(key)
559
- if val is not None:
560
- ch_dict[key] = val if isinstance(val, str) else int(val)
561
- for key in _FLOAT_FIELDS:
562
- val = ch.get(key)
563
- if val is not None:
564
- ch_dict[key] = float(val)
451
+ # Extract serializable fields from MNE channel info
452
+ ch_dict = {
453
+ "ch_name": ch.get("ch_name", ""),
454
+ }
455
+
456
+ # Handle kind field - can be either string or integer
457
+ kind_val = ch.get("kind")
458
+ if kind_val is not None:
459
+ ch_dict["kind"] = (
460
+ kind_val if isinstance(kind_val, str) else int(kind_val)
461
+ )
462
+
463
+ # Add numeric fields with safe conversion
464
+ coil_type = ch.get("coil_type")
465
+ if coil_type is not None:
466
+ ch_dict["coil_type"] = int(coil_type)
467
+
468
+ unit = ch.get("unit")
469
+ if unit is not None:
470
+ ch_dict["unit"] = int(unit)
471
+
472
+ cal = ch.get("cal")
473
+ if cal is not None:
474
+ ch_dict["cal"] = float(cal)
475
+
476
+ range_val = ch.get("range")
477
+ if range_val is not None:
478
+ ch_dict["range"] = float(range_val)
479
+
480
+ # Serialize location array if present
565
481
  if "loc" in ch and ch["loc"] is not None:
566
482
  ch_dict["loc"] = (
567
483
  ch["loc"].tolist()
@@ -569,19 +485,35 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
569
485
  else list(ch["loc"])
570
486
  )
571
487
  serialized.append(ch_dict)
488
+
572
489
  return serialized
573
490
 
574
491
  @staticmethod
575
492
  def _deserialize_chs_info(chs_info_dict):
576
- """Deserialize JSON channel dicts back to MNE-compatible format."""
493
+ """
494
+ Deserialize channel info from JSON-compatible format to MNE-like structure.
495
+
496
+ Parameters
497
+ ----------
498
+ chs_info_dict : list of dict or None
499
+ Serialized channel information.
500
+
501
+ Returns
502
+ -------
503
+ list of dict or None
504
+ Deserialized channel information compatible with MNE.
505
+ """
577
506
  if chs_info_dict is None:
578
507
  return None
508
+
579
509
  deserialized = []
580
510
  for ch_dict in chs_info_dict:
581
511
  ch = ch_dict.copy()
512
+ # Convert location back to numpy array if present
582
513
  if "loc" in ch and ch["loc"] is not None:
583
514
  ch["loc"] = np.array(ch["loc"])
584
515
  deserialized.append(ch)
516
+
585
517
  return deserialized
586
518
 
587
519
  def _save_pretrained(self, save_directory):
@@ -601,8 +533,16 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
601
533
 
602
534
  save_directory = Path(save_directory)
603
535
 
604
- config = build_model_config(self)
605
- config["braindecode_version"] = __version__
536
+ # Collect EEG-specific configuration
537
+ config = {
538
+ "n_outputs": self._n_outputs,
539
+ "n_chans": self._n_chans,
540
+ "n_times": self._n_times,
541
+ "input_window_seconds": self._input_window_seconds,
542
+ "sfreq": self._sfreq,
543
+ "chs_info": self._serialize_chs_info(self._chs_info),
544
+ "braindecode_version": __version__,
545
+ }
606
546
 
607
547
  # Save to config.json
608
548
  config_path = save_directory / "config.json"
@@ -641,7 +581,6 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
641
581
  **model_kwargs,
642
582
  ):
643
583
  model_kwargs.pop("braindecode_version", None)
644
- resolve_type_kwargs(cls, model_kwargs)
645
584
  return super()._from_pretrained( # type: ignore
646
585
  model_id=model_id,
647
586
  revision=revision,
@@ -207,25 +207,11 @@ class CBraMod(EEGModuleMixin, nn.Module):
207
207
 
208
208
  self._weights_init()
209
209
 
210
- try:
211
- n_times = self.n_times
212
- n_chans = self.n_chans
213
- except ValueError:
214
- n_times = None
215
- n_chans = None
216
-
217
- if return_encoder_output:
218
- self.final_layer = nn.Identity()
219
- elif n_times is not None and n_chans is not None:
220
- n_patch = n_times // patch_size
221
- flat_dim = n_chans * n_patch * emb_dim
222
- self.final_layer = nn.Sequential(
223
- nn.Flatten(), nn.Linear(flat_dim, self.n_outputs)
224
- )
225
- else:
226
- self.final_layer = nn.Sequential(
227
- nn.Flatten(), nn.LazyLinear(self.n_outputs)
228
- )
210
+ self.final_layer = (
211
+ nn.Identity()
212
+ if return_encoder_output
213
+ else nn.Sequential(nn.Flatten(), nn.LazyLinear(self.n_outputs))
214
+ )
229
215
 
230
216
  def _weights_init(self):
231
217
  for m in self.modules():
@@ -4,16 +4,13 @@ from types import UnionType
4
4
  from typing import Annotated, Any, Literal, Union, get_args, get_origin
5
5
 
6
6
  import numpy as np
7
- import pydantic
7
+ from mne.utils import _soft_import
8
8
  from typing_extensions import TypedDict
9
9
 
10
10
  from braindecode.models.base import EEGModuleMixin
11
- from braindecode.models.util import (
12
- SigArgName,
13
- _init_models_dict,
14
- models_dict,
15
- models_mandatory_parameters,
16
- )
11
+ from braindecode.models.util import SigArgName, models_dict, models_mandatory_parameters
12
+
13
+ pydantic = _soft_import(name="pydantic", purpose="model configuration", strict=False)
17
14
 
18
15
  try:
19
16
  from numpydantic import NDArray, Shape
@@ -60,12 +57,8 @@ SIGNAL_ARGS_TYPES = {
60
57
  }
61
58
 
62
59
 
63
- class BaseBraindecodeModelConfig(pydantic.BaseModel):
64
- """Base class for braindecode model pydantic configs."""
65
-
60
+ class BaseBraindecodeModelConfig(pydantic.BaseModel): # type: ignore
66
61
  def create_instance(self) -> EEGModuleMixin:
67
- if self.model_name_ not in models_dict:
68
- _init_models_dict()
69
62
  model_cls = models_dict[self.model_name_]
70
63
  kwargs = self.model_dump(mode="python", exclude={"model_name_"})
71
64
  if kwargs.get("n_chans") is not None and kwargs.get("chs_info") is not None:
@@ -97,6 +90,13 @@ def make_model_config(
97
90
  type
98
91
  A pydantic BaseModel subclass representing the model config.
99
92
  """
93
+ if not pydantic:
94
+ raise ImportError(
95
+ "pydantic is required to use make_model_config. "
96
+ "Please install braindecode[typing]."
97
+ )
98
+
99
+ # ironically, we need to ignore the type here to have the soft dependency.
100
100
 
101
101
  @pydantic.model_validator(mode="before")
102
102
  def validate_signal_params(cls, data: Any):
@@ -207,23 +207,23 @@ def make_model_config(
207
207
  # and define __all__ based on generated classes
208
208
  __all__ = ["make_model_config"]
209
209
 
210
- if not models_dict:
211
- _init_models_dict()
212
-
213
- models_configs: list[type[BaseBraindecodeModelConfig]] = []
214
- for model_name, req, _ in models_mandatory_parameters:
215
- model_cls = models_dict[model_name]
216
- model_cfg = make_model_config(model_cls, req)
217
- globals()[model_cfg.__name__] = model_cfg
218
- __all__.append(model_cfg.__name__)
219
- models_configs.append(model_cfg)
220
-
221
- BraindecodeModelConfig = Annotated[ # type: ignore[valid-type]
222
- Union[tuple(models_configs)],
223
- pydantic.Field(
224
- discriminator="model_name_", description="Braindecode model configuration"
225
- ),
226
- ]
210
+ if not pydantic:
211
+ pass
212
+ else:
213
+ models_configs: list[type[BaseBraindecodeModelConfig]] = []
214
+ for model_name, req, _ in models_mandatory_parameters:
215
+ model_cls = models_dict[model_name]
216
+ model_cfg = make_model_config(model_cls, req)
217
+ globals()[model_cfg.__name__] = model_cfg
218
+ __all__.append(model_cfg.__name__)
219
+ models_configs.append(model_cfg)
220
+
221
+ BraindecodeModelConfig = Annotated[ # type: ignore
222
+ Union[tuple(models_configs)],
223
+ pydantic.Field(
224
+ discriminator="model_name_", description="Braindecode model configuration"
225
+ ),
226
+ ]
227
227
 
228
228
  # # Example usage:
229
229
  #
@@ -7,7 +7,6 @@ Retrieved from https://openreview.net/forum?id=uazfjnFL0G
7
7
 
8
8
  Original Authors: Berkay Döner, Thorir Mar Ingolfsson
9
9
  Braindecode Adaptation: Bruno Aristimunha
10
- Contributions: Sarthak Tayal <sarthaktayal2@gmail.com>
11
10
 
12
11
  the LICENSE Of this file is APACHE-2.0.
13
12
  """
@@ -83,8 +82,11 @@ class LUNA(EEGModuleMixin, nn.Module):
83
82
 
84
83
  # Load pre-trained encoder weights
85
84
  state_dict = load_file(model_path)
86
- # load_state_dict applies model.mapping automatically
87
- model.load_state_dict(state_dict, strict=False)
85
+ # Apply key mapping for pretrained weights
86
+ mapping = model.mapping.copy()
87
+ mapping["cross_attn.temparature"] = "cross_attn.temperature"
88
+ mapped_state_dict = {mapping.get(k, k): v for k, v in state_dict.items()}
89
+ model.load_state_dict(mapped_state_dict, strict=False)
88
90
 
89
91
  To push your own trained model to the Hub:
90
92
 
@@ -168,7 +170,6 @@ class LUNA(EEGModuleMixin, nn.Module):
168
170
  "channel_location_embedder.0.fc2.bias": "channel_location_embedder.fc2.bias",
169
171
  "channel_location_embedder.0.norm.weight": "channel_location_embedder.norm.weight",
170
172
  "channel_location_embedder.0.norm.bias": "channel_location_embedder.norm.bias",
171
- "cross_attn.temparature": "cross_attn.temperature", # typo in pretrained weights
172
173
  }
173
174
 
174
175
  # Model parameters
@@ -314,10 +315,8 @@ class LUNA(EEGModuleMixin, nn.Module):
314
315
  channel_locations_emb = self.channel_location_embedder(channel_locations)
315
316
 
316
317
  x_tokenized = rearrange(x_masked, "B (C t) D -> (B t) C D", C=num_channels)
317
- channel_locations_emb = (
318
- channel_locations_emb.repeat_interleave( # was repeat(), wrong dim ordering
319
- num_patches_per_channel, dim=0
320
- )
318
+ channel_locations_emb = channel_locations_emb.repeat(
319
+ num_patches_per_channel, 1, 1
321
320
  )
322
321
  x_tokenized = x_tokenized + channel_locations_emb
323
322
 
@@ -4,7 +4,6 @@
4
4
  from __future__ import annotations
5
5
 
6
6
  import math
7
- import warnings
8
7
  from typing import Optional, Tuple
9
8
 
10
9
  import torch
@@ -497,10 +496,9 @@ class _TransformerEncoderLayer(nn.Module):
497
496
 
498
497
  if dim_feedforward is None:
499
498
  dim_feedforward = 4 * embed_dim
500
- warnings.warn(
501
- "dim_feedforward is set to 4*embed_dim, the default in "
502
- "Vaswani et al. (Attention is all you need)",
503
- stacklevel=2,
499
+ # note: preserve the original behaviour (print) from the provided code
500
+ print(
501
+ "dim_feedforward is set to 4*embed_dim, the default in Vaswani et al. (Attention is all you need)"
504
502
  )
505
503
 
506
504
  self.layer_norm_att = _LayerNorm(embed_dim, bias=bias)
@@ -16,16 +16,7 @@ import torch
16
16
  import torch.nn.functional as F
17
17
  from einops import rearrange
18
18
  from torch import nn
19
-
20
- # Safe import for older PyTorch versions (Support for Intel-based Macs)
21
- try:
22
- from torch.nn.attention import SDPBackend, sdpa_kernel
23
-
24
- HAS_SDPA = True
25
- except ImportError:
26
- HAS_SDPA = False
27
- SDPBackend = None
28
- sdpa_kernel = None
19
+ from torch.nn.attention import SDPBackend, sdpa_kernel
29
20
 
30
21
  from braindecode.models.base import EEGModuleMixin
31
22
 
@@ -539,22 +530,11 @@ class FeedForward(nn.Module):
539
530
 
540
531
 
541
532
  class ClassicalAttention(nn.Module):
542
- def __init__(self, heads: int, use_sdpa: bool | None = None):
533
+ def __init__(self, heads: int, use_sdpa: bool = True):
543
534
  super().__init__()
535
+ self.use_sdpa = use_sdpa
544
536
  self.heads = heads
545
537
 
546
- if use_sdpa is None:
547
- self.use_sdpa = HAS_SDPA
548
- elif use_sdpa is True and not HAS_SDPA:
549
- logger.warning(
550
- "SDPA (Scaled Dot Product Attention) was requested, but it is not "
551
- "available in your current PyTorch version. Falling back to naive "
552
- "implementation. Please upgrade to PyTorch >= 2.2 for SDPA support."
553
- )
554
- self.use_sdpa = False
555
- else:
556
- self.use_sdpa = use_sdpa
557
-
558
538
  def forward(self, qkv: torch.Tensor) -> torch.Tensor:
559
539
  # Split concatenated QKV into separate tensors
560
540
  # qkv shape: (batch, seq_len, 3 * heads * head_dim)
@@ -2,21 +2,19 @@
2
2
  #
3
3
  # License: BSD (3-clause)
4
4
 
5
- from __future__ import annotations
6
-
7
- from collections.abc import Callable
5
+ from typing import Callable
8
6
 
9
7
  from einops.layers.torch import Rearrange
10
8
  from torch import nn
11
9
  from torch.nn import init
12
10
 
11
+ from braindecode.functional import square
13
12
  from braindecode.models.base import EEGModuleMixin
14
13
  from braindecode.modules import (
15
14
  CombinedConv,
16
15
  Ensure4d,
17
16
  Expression,
18
17
  SafeLog,
19
- Square,
20
18
  SqueezeFinalOutput,
21
19
  )
22
20
 
@@ -47,14 +45,12 @@ class ShallowFBCSPNet(EEGModuleMixin, nn.Sequential):
47
45
  final_conv_length: int | str
48
46
  Length of the final convolution layer.
49
47
  If set to "auto", length of the input signal must be specified.
50
- conv_nonlin: type[nn.Module] | Callable
51
- Non-linear module class to be used after convolution layers.
52
- For backward compatibility, callables are also accepted and wrapped
53
- with :class:`~braindecode.modules.Expression`.
48
+ conv_nonlin: callable
49
+ Non-linear function to be used after convolution layers.
54
50
  pool_mode: str
55
51
  Method to use on pooling layers. "max" or "mean".
56
- activation_pool_nonlin: type[nn.Module]
57
- Non-linear module class to be used after pooling layers.
52
+ activation_pool_nonlin: callable
53
+ Non-linear function to be used after pooling layers.
58
54
  split_first_layer: bool
59
55
  Split first layer into temporal and spatial layers (True) or just use temporal (False).
60
56
  There would be no non-linearity between the split layers.
@@ -87,7 +83,7 @@ class ShallowFBCSPNet(EEGModuleMixin, nn.Sequential):
87
83
  pool_time_length=75,
88
84
  pool_time_stride=15,
89
85
  final_conv_length="auto",
90
- conv_nonlin: type[nn.Module] | Callable = Square,
86
+ conv_nonlin: Callable = square,
91
87
  pool_mode="mean",
92
88
  activation_pool_nonlin: type[nn.Module] = SafeLog,
93
89
  split_first_layer=True,
@@ -167,11 +163,7 @@ class ShallowFBCSPNet(EEGModuleMixin, nn.Sequential):
167
163
  n_filters_conv, momentum=self.batch_norm_alpha, affine=True
168
164
  ),
169
165
  )
170
- if isinstance(self.conv_nonlin, type):
171
- self.add_module("conv_nonlin_exp", self.conv_nonlin())
172
- else:
173
- # Backward compat: accept a callable (e.g. square function)
174
- self.add_module("conv_nonlin_exp", Expression(self.conv_nonlin))
166
+ self.add_module("conv_nonlin_exp", Expression(self.conv_nonlin))
175
167
  self.add_module(
176
168
  "pool",
177
169
  pool_class(