braindecode 1.5.0.dev1013__tar.gz → 1.5.0.dev1015__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 (171) hide show
  1. {braindecode-1.5.0.dev1013/braindecode.egg-info → braindecode-1.5.0.dev1015}/PKG-INFO +1 -1
  2. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/emg2qwerty.py +207 -7
  3. braindecode-1.5.0.dev1015/braindecode/version.py +1 -0
  4. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015/braindecode.egg-info}/PKG-INFO +1 -1
  5. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/whats_new.rst +20 -0
  6. braindecode-1.5.0.dev1013/braindecode/version.py +0 -1
  7. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/LICENSE.txt +0 -0
  8. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/MANIFEST.in +0 -0
  9. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/NOTICE.txt +0 -0
  10. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/README.rst +0 -0
  11. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/__init__.py +0 -0
  12. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/augmentation/__init__.py +0 -0
  13. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/augmentation/base.py +0 -0
  14. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/augmentation/functional.py +0 -0
  15. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/augmentation/transforms.py +0 -0
  16. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/classifier.py +0 -0
  17. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/__init__.py +0 -0
  18. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/base.py +0 -0
  19. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/bbci.py +0 -0
  20. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/bcicomp.py +0 -0
  21. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/bids/__init__.py +0 -0
  22. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/bids/datasets.py +0 -0
  23. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/bids/format.py +0 -0
  24. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/bids/hub.py +0 -0
  25. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/bids/hub_format.py +0 -0
  26. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/bids/hub_io.py +0 -0
  27. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/bids/hub_validation.py +0 -0
  28. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/bids/iterable.py +0 -0
  29. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/chb_mit.py +0 -0
  30. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/mne.py +0 -0
  31. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/moabb.py +0 -0
  32. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/nmt.py +0 -0
  33. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/registry.py +0 -0
  34. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/siena.py +0 -0
  35. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
  36. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/sleep_physionet.py +0 -0
  37. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/tuh.py +0 -0
  38. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/utils.py +0 -0
  39. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datasets/xy.py +0 -0
  40. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datautil/__init__.py +0 -0
  41. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datautil/channel_utils.py +0 -0
  42. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datautil/hub_formats.py +0 -0
  43. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datautil/serialization.py +0 -0
  44. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/datautil/util.py +0 -0
  45. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/eegneuralnet.py +0 -0
  46. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/functional/__init__.py +0 -0
  47. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/functional/functions.py +0 -0
  48. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/functional/initialization.py +0 -0
  49. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/__init__.py +0 -0
  50. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/atcnet.py +0 -0
  51. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/attentionbasenet.py +0 -0
  52. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/attn_sleep.py +0 -0
  53. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/base.py +0 -0
  54. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/bendr.py +0 -0
  55. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/biot.py +0 -0
  56. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/brainmodule.py +0 -0
  57. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/cbramod.py +0 -0
  58. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/codebrain.py +0 -0
  59. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/config.py +0 -0
  60. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/contrawr.py +0 -0
  61. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/ctnet.py +0 -0
  62. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/deep4.py +0 -0
  63. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/deepsleepnet.py +0 -0
  64. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/dgcnn.py +0 -0
  65. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/eegconformer.py +0 -0
  66. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/eeginception_erp.py +0 -0
  67. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/eeginception_mi.py +0 -0
  68. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/eegitnet.py +0 -0
  69. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/eegminer.py +0 -0
  70. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/eegnet.py +0 -0
  71. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/eegnex.py +0 -0
  72. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/eegpt.py +0 -0
  73. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/eegsimpleconv.py +0 -0
  74. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/eegsym.py +0 -0
  75. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/eegtcnet.py +0 -0
  76. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/fbcnet.py +0 -0
  77. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/fblightconvnet.py +0 -0
  78. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/fbmsnet.py +0 -0
  79. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/hybrid.py +0 -0
  80. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/ifnet.py +0 -0
  81. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/interpolated.py +0 -0
  82. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/labram.py +0 -0
  83. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/luna.py +0 -0
  84. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/medformer.py +0 -0
  85. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/meta_neuromotor.py +0 -0
  86. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/msvtnet.py +0 -0
  87. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/patchedtransformer.py +0 -0
  88. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/reve.py +0 -0
  89. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/sccnet.py +0 -0
  90. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/shallow_fbcsp.py +0 -0
  91. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/signal_jepa.py +0 -0
  92. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/sinc_shallow.py +0 -0
  93. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
  94. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
  95. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/sparcnet.py +0 -0
  96. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/sstdpn.py +0 -0
  97. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/summary.csv +0 -0
  98. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/syncnet.py +0 -0
  99. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/tcn.py +0 -0
  100. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/tidnet.py +0 -0
  101. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/tsinception.py +0 -0
  102. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/usleep.py +0 -0
  103. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/models/util.py +0 -0
  104. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/modules/__init__.py +0 -0
  105. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/modules/activation.py +0 -0
  106. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/modules/attention.py +0 -0
  107. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/modules/blocks.py +0 -0
  108. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/modules/convolution.py +0 -0
  109. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/modules/filter.py +0 -0
  110. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/modules/interpolation.py +0 -0
  111. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/modules/layers.py +0 -0
  112. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/modules/linear.py +0 -0
  113. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/modules/parametrization.py +0 -0
  114. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/modules/stats.py +0 -0
  115. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/modules/util.py +0 -0
  116. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/modules/wrapper.py +0 -0
  117. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/preprocessing/__init__.py +0 -0
  118. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
  119. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/preprocessing/mne_preprocess.py +0 -0
  120. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/preprocessing/preprocess.py +0 -0
  121. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/preprocessing/util.py +0 -0
  122. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/preprocessing/windowers.py +0 -0
  123. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/regressor.py +0 -0
  124. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/samplers/__init__.py +0 -0
  125. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/samplers/base.py +0 -0
  126. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/samplers/ssl.py +0 -0
  127. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/training/__init__.py +0 -0
  128. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/training/callbacks.py +0 -0
  129. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/training/losses.py +0 -0
  130. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/training/scoring.py +0 -0
  131. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/util.py +0 -0
  132. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/visualization/__init__.py +0 -0
  133. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/visualization/attribution.py +0 -0
  134. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/visualization/confusion_matrices.py +0 -0
  135. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/visualization/frequency.py +0 -0
  136. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/visualization/metrics.py +0 -0
  137. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/visualization/sanity.py +0 -0
  138. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode/visualization/topology.py +0 -0
  139. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode.egg-info/SOURCES.txt +0 -0
  140. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode.egg-info/dependency_links.txt +0 -0
  141. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode.egg-info/requires.txt +0 -0
  142. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/braindecode.egg-info/top_level.txt +0 -0
  143. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/Makefile +0 -0
  144. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/_templates/autosummary/class.rst +0 -0
  145. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
  146. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/_templates/autosummary/function.rst +0 -0
  147. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
  148. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/api.rst +0 -0
  149. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/cite.rst +0 -0
  150. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/conf.py +0 -0
  151. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/help.rst +0 -0
  152. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/index.rst +0 -0
  153. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/install/install.rst +0 -0
  154. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/install/install_pip.rst +0 -0
  155. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/install/install_source.rst +0 -0
  156. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/models/categorization/attention.rst +0 -0
  157. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/models/categorization/channel.rst +0 -0
  158. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/models/categorization/convolution.rst +0 -0
  159. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/models/categorization/filterbank.rst +0 -0
  160. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/models/categorization/gnn.rst +0 -0
  161. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/models/categorization/interpretable.rst +0 -0
  162. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/models/categorization/lbm.rst +0 -0
  163. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/models/categorization/recurrent.rst +0 -0
  164. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/models/categorization/spd.rst +0 -0
  165. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/models/models.rst +0 -0
  166. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/models/models_categorization.rst +0 -0
  167. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/models/models_table.rst +0 -0
  168. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/models/models_visualization.rst +0 -0
  169. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/docs/sg_execution_times.rst +0 -0
  170. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/pyproject.toml +0 -0
  171. {braindecode-1.5.0.dev1013 → braindecode-1.5.0.dev1015}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: braindecode
3
- Version: 1.5.0.dev1013
3
+ Version: 1.5.0.dev1015
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>
@@ -56,7 +56,11 @@ class EMG2QwertyNet(EEGModuleMixin, nn.Module):
56
56
  Returns ``(batch, T_out, n_outputs)``. With ``n_times=8000`` and
57
57
  defaults, ``T_out=373``. For :class:`~torch.nn.CTCLoss`, transpose
58
58
  to ``(T_out, batch, n_outputs)``; use :meth:`compute_output_lengths`
59
- for emission lengths.
59
+ for emission lengths. Pass ``return_features=True`` to return the
60
+ pre-classifier encoder representation as a
61
+ ``{"features": (batch, T_out, num_features), "cls_token": None}``
62
+ dict, matching the BIOT / signal-JEPA convention used by downstream
63
+ wrappers (e.g. neuroai's ``DownstreamWrapperModel``).
60
64
 
61
65
  .. rubric:: Paper training recipe
62
66
 
@@ -69,7 +73,9 @@ class EMG2QwertyNet(EEGModuleMixin, nn.Module):
69
73
  local minimum).
70
74
  - **Augmentation**: per-band electrode rotations by -1/0/+1 positions,
71
75
  ±60-sample temporal jitter, and SpecAugment [park2019specaug]_ on
72
- the log-spectrogram.
76
+ the log-spectrogram. SpecAugment is built into the model
77
+ (``spec_augment=True``) and only fires in training mode; the
78
+ time/frequency-jitter pieces are dataset-side augmentations.
73
79
  - **Decoding**: greedy CTC. Upstream also reports a 6-gram KenLM
74
80
  beam decoder, not ported here.
75
81
 
@@ -145,6 +151,37 @@ class EMG2QwertyNet(EEGModuleMixin, nn.Module):
145
151
  layers and again after the second :class:`~torch.nn.Linear`.
146
152
  Default ``0.0`` matches the upstream paper recipe (no dropout).
147
153
  Set ``> 0`` for regularized training.
154
+ spec_augment : bool
155
+ If ``True``, apply SpecAugment [park2019specaug]_ time/frequency
156
+ masking on the log-spectrogram during training only. Disabled in
157
+ ``eval`` mode and absent from the parameter / state-dict count.
158
+ Defaults to ``False``; set to ``True`` to match the upstream
159
+ emg2qwerty paper recipe.
160
+ n_time_masks : int
161
+ Maximum number of time masks applied per call. Each forward pass
162
+ samples a uniform integer in ``[0, n_time_masks]``. Defaults to
163
+ ``3`` (Sivakumar et al. Sec 5.2).
164
+ time_mask_param : int
165
+ Maximum time-mask width in spectrogram frames. Defaults to ``25``.
166
+ n_freq_masks : int
167
+ Maximum number of frequency masks applied per call. Each forward
168
+ pass samples a uniform integer in ``[0, n_freq_masks]``. Defaults
169
+ to ``2``.
170
+ freq_mask_param : int
171
+ Maximum frequency-mask width in STFT bins. Defaults to ``4``.
172
+ spec_augment_prob : float
173
+ Probability of running SpecAugment on a given training batch
174
+ (Bernoulli gate before sampling mask counts). Defaults to ``1.0``.
175
+ return_feature : bool
176
+ If ``True``, ``forward`` returns a tuple
177
+ ``(emissions, features)`` instead of just ``emissions`` —
178
+ :class:`braindecode.models.BIOT`-style legacy feature path. Lets
179
+ configuration-driven downstream wrappers (e.g. neuroai's
180
+ ``DownstreamWrapperModel`` with ``model_output_key=1``) pick up
181
+ the encoder representation without passing a runtime kwarg.
182
+ Defaults to ``False``. Mutually compatible with the runtime
183
+ ``return_features`` (plural) flag, which still wins when set
184
+ to ``True``.
148
185
 
149
186
  Examples
150
187
  --------
@@ -216,6 +253,13 @@ class EMG2QwertyNet(EEGModuleMixin, nn.Module):
216
253
  log_softmax: bool = False,
217
254
  activation: type[nn.Module] = nn.ReLU,
218
255
  drop_prob: float = 0.0,
256
+ spec_augment: bool = False,
257
+ n_time_masks: int = 3,
258
+ time_mask_param: int = 25,
259
+ n_freq_masks: int = 2,
260
+ freq_mask_param: int = 4,
261
+ spec_augment_prob: float = 1.0,
262
+ return_feature: bool = False,
219
263
  # Standard braindecode args
220
264
  n_times: int | None = None,
221
265
  input_window_seconds: float | None = None,
@@ -256,6 +300,7 @@ class EMG2QwertyNet(EEGModuleMixin, nn.Module):
256
300
  self.hop_length = hop_length
257
301
  self.kernel_width = kernel_width
258
302
  self.log_softmax = log_softmax
303
+ self.return_feature = return_feature
259
304
 
260
305
  n_freq_bins = n_fft // 2 + 1
261
306
  in_features = electrodes_per_band * n_freq_bins
@@ -269,6 +314,23 @@ class EMG2QwertyNet(EEGModuleMixin, nn.Module):
269
314
  log_eps=log_eps,
270
315
  )
271
316
 
317
+ # Built-in SpecAugment lives between the spectrogram and the BatchNorm
318
+ # so it operates on the log-power tensor (matches upstream emg2qwerty
319
+ # and the previous neuralbench callback). ``nn.Identity`` keeps the
320
+ # forward path symmetrical without contributing parameters or
321
+ # state-dict keys when SpecAugment is disabled.
322
+ self.spec_augment: nn.Module
323
+ if spec_augment:
324
+ self.spec_augment = _SpecAugment(
325
+ n_time_masks=n_time_masks,
326
+ time_mask_param=time_mask_param,
327
+ n_freq_masks=n_freq_masks,
328
+ freq_mask_param=freq_mask_param,
329
+ prob=spec_augment_prob,
330
+ )
331
+ else:
332
+ self.spec_augment = nn.Identity()
333
+
272
334
  # Indices 0/1/3 match upstream's ``TDSConvCTCModule.model``;
273
335
  # index 2 is a parameter-free Flatten; upstream's index 4 (head)
274
336
  # is broken out as ``self.final_layer`` and remapped via :attr:`mapping`.
@@ -298,7 +360,13 @@ class EMG2QwertyNet(EEGModuleMixin, nn.Module):
298
360
  isinstance(m, _TDSConv2dBlock) for m in self.model[3].tds_conv_blocks
299
361
  )
300
362
 
301
- def forward(self, x: torch.Tensor) -> torch.Tensor:
363
+ def forward(
364
+ self, x: torch.Tensor, return_features: bool = False
365
+ ) -> (
366
+ torch.Tensor
367
+ | dict[str, torch.Tensor | None]
368
+ | tuple[torch.Tensor, torch.Tensor]
369
+ ):
302
370
  """Run the full pipeline.
303
371
 
304
372
  Parameters
@@ -307,12 +375,37 @@ class EMG2QwertyNet(EEGModuleMixin, nn.Module):
307
375
  Raw EMG of shape ``(batch, n_chans=32, n_times)``. ``n_times``
308
376
  must be at least the encoder's receptive field, ``n_fft +
309
377
  n_conv_blocks * (kernel_width - 1) * hop_length``.
378
+ return_features : bool
379
+ If ``True``, return a ``dict`` with the encoder representation
380
+ instead of the classification emissions. The encoder is the
381
+ full TDS-Conv stack up to (but not including)
382
+ ``self.final_layer`` — i.e. what downstream wrappers want
383
+ when they apply their own probe/aggregation. Matches the
384
+ BIOT / signal-JEPA convention so the same neuroai
385
+ ``DownstreamWrapperModel(model_output_key="features")``
386
+ can consume it. Wins over the constructor-time
387
+ ``return_feature`` flag when set.
310
388
 
311
389
  Returns
312
390
  -------
313
- emissions : torch.Tensor
314
- Shape ``(batch, T_out, n_outputs)``. Log-probabilities if
391
+ torch.Tensor or dict or tuple
392
+ Default (``return_features=False``, init
393
+ ``return_feature=False``): ``torch.Tensor`` of shape
394
+ ``(batch, T_out, n_outputs)``. Log-probabilities if
315
395
  ``log_softmax=True``, otherwise logits.
396
+
397
+ If runtime ``return_features=True``: ``dict`` with
398
+ ``"features"`` (shape ``(batch, T_out, num_features)``,
399
+ where ``num_features = num_bands * mlp_features[-1]``) and
400
+ ``"cls_token"`` (always ``None`` — TDS-Conv has no
401
+ ``[CLS]``).
402
+
403
+ If init ``return_feature=True`` and runtime
404
+ ``return_features=False``: tuple ``(emissions, features)``
405
+ where ``features`` has shape ``(batch, T_out,
406
+ num_features)``. Same layout BIOT exposes for
407
+ configuration-driven feature extraction (e.g. neuroai's
408
+ ``model_output_key=1``).
316
409
  """
317
410
  if x.ndim != 3 or x.shape[-2] != self.n_chans:
318
411
  raise ValueError(
@@ -331,11 +424,24 @@ class EMG2QwertyNet(EEGModuleMixin, nn.Module):
331
424
  f"kernel_width={self.kernel_width})."
332
425
  )
333
426
  spectrogram = self.spectrogram(x)
427
+ spectrogram = self.spec_augment(spectrogram)
334
428
  encoded = self.model(spectrogram)
429
+ # ``encoded`` is (T_out, B, num_features); only materialise the
430
+ # batch-first features tensor in the branches that actually return
431
+ # it, so the default emissions-only path skips the extra transpose
432
+ # + contiguous copy on every forward.
433
+ if return_features:
434
+ return {
435
+ "features": encoded.transpose(0, 1).contiguous(),
436
+ "cls_token": None,
437
+ }
335
438
  emissions = self.final_layer(encoded)
336
439
  if self.log_softmax:
337
440
  emissions = F.log_softmax(emissions, dim=-1)
338
- return emissions.transpose(0, 1).contiguous()
441
+ emissions = emissions.transpose(0, 1).contiguous()
442
+ if self.return_feature:
443
+ return emissions, encoded.transpose(0, 1).contiguous()
444
+ return emissions
339
445
 
340
446
  def reset_head(self, n_outputs: int) -> None:
341
447
  """Replace the classification head for a new vocabulary size.
@@ -411,7 +517,13 @@ class EMG2QwertyNet(EEGModuleMixin, nn.Module):
411
517
  dummy_input = torch.zeros(
412
518
  1, self.n_chans, n_times, dtype=dtype, device=device
413
519
  )
414
- return tuple(self.forward(dummy_input).shape)
520
+ # ``return_features=False`` keeps the dict path off; the init
521
+ # ``return_feature`` flag may still produce a tuple, so unpack
522
+ # the emissions explicitly to report the public output shape.
523
+ out = self.forward(dummy_input, return_features=False)
524
+ emissions = out[0] if isinstance(out, tuple) else out
525
+ assert isinstance(emissions, torch.Tensor)
526
+ return tuple(emissions.shape)
415
527
 
416
528
 
417
529
  class _LogSpectrogram(nn.Module):
@@ -483,6 +595,94 @@ class _LogSpectrogram(nn.Module):
483
595
  ).movedim(-1, 0)
484
596
 
485
597
 
598
+ class _SpecAugment(nn.Module):
599
+ r"""SpecAugment masking on the log-spectrogram during training.
600
+
601
+ Applies up to ``n_time_masks`` × ``time_mask_param``-frame time
602
+ bands and ``n_freq_masks`` × ``freq_mask_param``-bin frequency
603
+ bands. Masks are independent per ``(sample × band × electrode)``
604
+ triple — same recipe as the upstream emg2qwerty
605
+ :class:`emg2qwerty.transforms.SpecAugment` dataset transform
606
+ (Sivakumar et al. Sec 5.2 / NeurIPS 2024), which is
607
+ :func:`torchaudio.functional.mask_along_axis_iid`-style masking
608
+ sampled per leading dim of a spectrogram with shape
609
+ ``(..., freq, time)``. No-op outside ``training``.
610
+
611
+ The mask fill value is the on-device mean of the spectrogram —
612
+ ``log(power=1)=0`` would sit well above the typical log-power
613
+ distribution and inject artificial spikes — and stays a 0-D
614
+ tensor so the forward pass adds no host round-trip on GPU.
615
+ """
616
+
617
+ def __init__(
618
+ self,
619
+ n_time_masks: int = 3,
620
+ time_mask_param: int = 25,
621
+ n_freq_masks: int = 2,
622
+ freq_mask_param: int = 4,
623
+ prob: float = 1.0,
624
+ ) -> None:
625
+ super().__init__()
626
+ if n_time_masks < 0 or n_freq_masks < 0:
627
+ raise ValueError(
628
+ f"n_time_masks and n_freq_masks must be >= 0; got "
629
+ f"n_time_masks={n_time_masks}, n_freq_masks={n_freq_masks}."
630
+ )
631
+ if time_mask_param < 0 or freq_mask_param < 0:
632
+ raise ValueError(
633
+ f"time_mask_param and freq_mask_param must be >= 0; got "
634
+ f"time_mask_param={time_mask_param}, "
635
+ f"freq_mask_param={freq_mask_param}."
636
+ )
637
+ if not 0.0 <= prob <= 1.0:
638
+ raise ValueError(f"prob must be in [0, 1]; got {prob}.")
639
+ self.n_time_masks = n_time_masks
640
+ self.time_mask_param = time_mask_param
641
+ self.n_freq_masks = n_freq_masks
642
+ self.freq_mask_param = freq_mask_param
643
+ self.prob = prob
644
+ # ``iid_masks=True`` so masking is sampled over every leading dim
645
+ # except the trailing ``(freq, time)`` pair — i.e. one mask per
646
+ # ``(sample × band × electrode)`` on a 5-D
647
+ # ``(B, num_bands, electrodes, freq, T)`` input. Matches upstream
648
+ # emg2qwerty's per-``(band × electrode)`` dataset-time recipe.
649
+ self.time_mask = ta_transforms.TimeMasking(time_mask_param, iid_masks=True)
650
+ self.freq_mask = ta_transforms.FrequencyMasking(freq_mask_param, iid_masks=True)
651
+
652
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
653
+ # ``x``: (T_spec, B, num_bands, electrodes, freq).
654
+ if (
655
+ not self.training
656
+ or self.prob <= 0.0
657
+ or (self.n_time_masks == 0 and self.n_freq_masks == 0)
658
+ ):
659
+ return x
660
+ # All RNG draws use ``x.device`` so reproducibility seeds the same
661
+ # stream regardless of whether the user calls ``torch.manual_seed``
662
+ # or ``torch.cuda.manual_seed`` — and so torchaudio's internal
663
+ # device-side RNG and our Python-level gate stay in sync. ``.item()``
664
+ # still forces a host sync for the Python ``if``/loop bound, but
665
+ # that is unavoidable for control flow.
666
+ if self.prob < 1.0 and torch.rand((), device=x.device).item() >= self.prob:
667
+ return x
668
+ # ``torchaudio`` masking expects ``(..., freq, time)``; here that means
669
+ # ``(B, num_bands, electrodes, freq, T_spec)``. Move time to the end
670
+ # rather than reshaping into 4D, because ``mask_along_axis_iid`` draws
671
+ # one mask per leading-axis index, so the 5-D layout already gives the
672
+ # desired per-``(B × num_bands × electrodes)`` independence.
673
+ spec = x.movedim(0, -1).contiguous()
674
+ # 0-D on-device tensor — ``masked_fill`` / ``torch.where`` accept it
675
+ # without a host sync.
676
+ mask_value = spec.mean()
677
+ n_t = int(torch.randint(self.n_time_masks + 1, (), device=x.device).item())
678
+ for _ in range(n_t):
679
+ spec = self.time_mask(spec, mask_value=mask_value)
680
+ n_f = int(torch.randint(self.n_freq_masks + 1, (), device=x.device).item())
681
+ for _ in range(n_f):
682
+ spec = self.freq_mask(spec, mask_value=mask_value)
683
+ return spec.movedim(-1, 0)
684
+
685
+
486
686
  class _SpectrogramNorm(nn.Module):
487
687
  r""":class:`~torch.nn.BatchNorm2d` over (band × electrode) channels.
488
688
 
@@ -0,0 +1 @@
1
+ __version__ = "1.5.0.dev1015"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: braindecode
3
- Version: 1.5.0.dev1013
3
+ Version: 1.5.0.dev1015
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>
@@ -36,6 +36,26 @@ Enhancements
36
36
  noise between two arms, from the emg2qwerty paper (Sivakumar et al.,
37
37
  NeurIPS 2024). By `Bruno Aristimunha`_.
38
38
 
39
+ - Build SpecAugment (Park et al., Interspeech 2019) into
40
+ :class:`braindecode.models.EMG2QwertyNet` as a parameter-free submodule
41
+ gated by a new ``spec_augment`` constructor flag (default ``False``).
42
+ When enabled, applies up to ``n_time_masks`` × ``time_mask_param``
43
+ time bands and ``n_freq_masks`` × ``freq_mask_param`` frequency bands
44
+ on the log-spectrogram during ``train()`` only, with masks sampled
45
+ IID per ``(sample × band × electrode)`` triple — same recipe as the
46
+ upstream ``emg2qwerty.transforms.SpecAugment`` dataset transform. The
47
+ mask fill value stays a 0-D on-device tensor (``spec.mean()``) so the
48
+ forward pass adds no host round-trip on GPU. Also adds a
49
+ ``return_features`` runtime flag to
50
+ :meth:`braindecode.models.EMG2QwertyNet.forward` (returns
51
+ ``{"features": (B, T_out, num_features), "cls_token": None}``,
52
+ BIOT / signal-JEPA convention) and a matching ``return_feature``
53
+ constructor flag (returns ``(emissions, features)`` tuple, BIOT-style
54
+ legacy path) so downstream wrappers — such as neuroai's
55
+ ``DownstreamWrapperModel`` — can pick up the encoder representation
56
+ via ``model_output_key="features"`` (dict) or ``model_output_key=1``
57
+ (tuple) without changes to their call site. By `Bruno Aristimunha`_.
58
+
39
59
  - Add :meth:`braindecode.datasets.BaseConcatDataset.set_target` to swap
40
60
  any per-window metadata column or per-record description field
41
61
  (e.g. a BIDS entity, a participants.tsv extra) into the dataset's
@@ -1 +0,0 @@
1
- __version__ = "1.5.0.dev1013"