braindecode 1.8.1.dev168929986__tar.gz → 1.8.1.dev169077960__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 (217) hide show
  1. {braindecode-1.8.1.dev168929986/braindecode.egg-info → braindecode-1.8.1.dev169077960}/PKG-INFO +1 -1
  2. braindecode-1.8.1.dev169077960/braindecode/__init__.py +53 -0
  3. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/base.py +90 -9
  4. braindecode-1.8.1.dev169077960/braindecode/models/__init__.py +133 -0
  5. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/base.py +51 -2
  6. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/bendr.py +4 -6
  7. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/config.py +0 -5
  8. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/luna.py +19 -1
  9. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/util.py +41 -17
  10. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/modules/blocks.py +17 -10
  11. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/modules/parametrization.py +10 -2
  12. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/util.py +2 -1
  13. braindecode-1.8.1.dev169077960/braindecode/version.py +1 -0
  14. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960/braindecode.egg-info}/PKG-INFO +1 -1
  15. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/user_guide/cropped_inference.rst +19 -0
  16. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/whats_new.rst +45 -0
  17. braindecode-1.8.1.dev168929986/braindecode/__init__.py +0 -9
  18. braindecode-1.8.1.dev168929986/braindecode/models/__init__.py +0 -197
  19. braindecode-1.8.1.dev168929986/braindecode/version.py +0 -1
  20. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/LICENSE.txt +0 -0
  21. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/MANIFEST.in +0 -0
  22. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/NOTICE.txt +0 -0
  23. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/README.rst +0 -0
  24. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/augmentation/__init__.py +0 -0
  25. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/augmentation/base.py +0 -0
  26. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/augmentation/functional.py +0 -0
  27. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/augmentation/transforms.py +0 -0
  28. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/classifier.py +0 -0
  29. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/__init__.py +0 -0
  30. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/_notebook_viewer.py +0 -0
  31. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/bbci.py +0 -0
  32. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/bcicomp.py +0 -0
  33. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/bids/__init__.py +0 -0
  34. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/bids/datasets.py +0 -0
  35. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/bids/hub.py +0 -0
  36. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/bids/hub_format.py +0 -0
  37. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/bids/hub_io.py +0 -0
  38. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/bids/hub_validation.py +0 -0
  39. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/bids/iterable.py +0 -0
  40. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/chb_mit.py +0 -0
  41. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/collate.py +0 -0
  42. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/mne.py +0 -0
  43. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/moabb.py +0 -0
  44. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/nmt.py +0 -0
  45. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/registry.py +0 -0
  46. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/siena.py +0 -0
  47. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
  48. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/sleep_physionet.py +0 -0
  49. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/tuh.py +0 -0
  50. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/utils.py +0 -0
  51. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datasets/xy.py +0 -0
  52. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datautil/__init__.py +0 -0
  53. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datautil/channel_utils.py +0 -0
  54. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datautil/hub_formats.py +0 -0
  55. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datautil/serialization.py +0 -0
  56. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/datautil/util.py +0 -0
  57. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/eegneuralnet.py +0 -0
  58. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/functional/__init__.py +0 -0
  59. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/functional/_lfilter.py +0 -0
  60. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/functional/_real_dft.py +0 -0
  61. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/functional/attention.py +0 -0
  62. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/functional/channel_mask.py +0 -0
  63. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/functional/functions.py +0 -0
  64. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/functional/initialization.py +0 -0
  65. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/functional/patches.py +0 -0
  66. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/atcnet.py +0 -0
  67. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/attentionbasenet.py +0 -0
  68. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/attn_sleep.py +0 -0
  69. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/axon.py +0 -0
  70. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/barista.py +0 -0
  71. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/biot.py +0 -0
  72. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/brainbert.py +0 -0
  73. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/brainmodule.py +0 -0
  74. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/brainomni.py +0 -0
  75. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/brant.py +0 -0
  76. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/cbramod.py +1 -1
  77. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/codebrain.py +0 -0
  78. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/contrawr.py +0 -0
  79. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/csbrain.py +0 -0
  80. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/ctnet.py +0 -0
  81. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/dance.py +0 -0
  82. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/deep4.py +0 -0
  83. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/deepsleepnet.py +0 -0
  84. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/dgcnn.py +0 -0
  85. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/diver1.py +0 -0
  86. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/duin.py +0 -0
  87. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/eeg_clip.py +0 -0
  88. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/eegconformer.py +0 -0
  89. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/eegdino.py +0 -0
  90. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/eeginception_erp.py +0 -0
  91. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/eeginception_mi.py +0 -0
  92. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/eegitnet.py +0 -0
  93. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/eegminer.py +0 -0
  94. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/eegnet.py +0 -0
  95. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/eegnex.py +0 -0
  96. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/eegpt.py +0 -0
  97. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/eegsimpleconv.py +0 -0
  98. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/eegsym.py +0 -0
  99. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/eegtcnet.py +0 -0
  100. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/emg2qwerty.py +0 -0
  101. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/epint.py +0 -0
  102. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/fbcnet.py +0 -0
  103. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/fblightconvnet.py +0 -0
  104. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/fbmsnet.py +0 -0
  105. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/gcnsnet.py +0 -0
  106. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/guetschel2026.py +0 -0
  107. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/hybrid.py +0 -0
  108. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/ifnet.py +0 -0
  109. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/labram.py +1 -1
  110. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/mapa.py +0 -0
  111. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/medformer.py +0 -0
  112. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/meta_neuromotor.py +0 -0
  113. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/mirepnet.py +0 -0
  114. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/mscformer.py +0 -0
  115. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/msvtnet.py +0 -0
  116. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/mvpformer.py +0 -0
  117. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/neuropose.py +0 -0
  118. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/neurorvq.py +0 -0
  119. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/neurorvq_tokenizer.py +0 -0
  120. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/patchedtransformer.py +0 -0
  121. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/popt.py +0 -0
  122. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/reve.py +0 -0
  123. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/sccnet.py +0 -0
  124. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/seizure_transformer.py +0 -0
  125. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/sensingdynamics.py +0 -0
  126. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/shallow_fbcsp.py +0 -0
  127. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/signal_jepa.py +0 -0
  128. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/sinc_shallow.py +0 -0
  129. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
  130. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
  131. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/sleepfm.py +0 -0
  132. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/sparcnet.py +0 -0
  133. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/sstdpn.py +0 -0
  134. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/steegformer.py +0 -0
  135. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/summary.csv +0 -0
  136. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/syncnet.py +0 -0
  137. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/tcformer.py +0 -0
  138. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/tcn.py +0 -0
  139. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/tfm_tokenizer.py +0 -0
  140. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/tidnet.py +0 -0
  141. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/tmsanet.py +0 -0
  142. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/tsinception.py +0 -0
  143. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/usleep.py +0 -0
  144. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/vemg2pose.py +0 -0
  145. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/models/zuna.py +0 -0
  146. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/modules/__init__.py +0 -0
  147. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/modules/activation.py +0 -0
  148. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/modules/attention.py +0 -0
  149. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/modules/channels.py +0 -0
  150. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/modules/convolution.py +0 -0
  151. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/modules/dance_modules.py +0 -0
  152. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/modules/filter.py +0 -0
  153. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/modules/layers.py +0 -0
  154. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/modules/linear.py +0 -0
  155. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/modules/linear_attention.py +0 -0
  156. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/modules/quantization.py +0 -0
  157. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/modules/stats.py +0 -0
  158. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/modules/util.py +0 -0
  159. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/modules/wrapper.py +0 -0
  160. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/preprocessing/__init__.py +0 -0
  161. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
  162. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/preprocessing/mne_preprocess.py +0 -0
  163. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/preprocessing/preprocess.py +0 -0
  164. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/preprocessing/util.py +0 -0
  165. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/preprocessing/windowers.py +0 -0
  166. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/regressor.py +0 -0
  167. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/samplers/__init__.py +0 -0
  168. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/samplers/base.py +0 -0
  169. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/samplers/ssl.py +0 -0
  170. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/training/__init__.py +0 -0
  171. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/training/_trial_aggregation.py +0 -0
  172. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/training/callbacks.py +0 -0
  173. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/training/losses.py +0 -0
  174. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/training/scoring.py +0 -0
  175. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/visualization/__init__.py +0 -0
  176. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/visualization/activations.py +0 -0
  177. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/visualization/attribution.py +0 -0
  178. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/visualization/confusion_matrices.py +0 -0
  179. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/visualization/frequency.py +0 -0
  180. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/visualization/metrics.py +0 -0
  181. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/visualization/sanity.py +0 -0
  182. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode/visualization/topology.py +0 -0
  183. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode.egg-info/SOURCES.txt +0 -0
  184. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode.egg-info/dependency_links.txt +0 -0
  185. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode.egg-info/requires.txt +0 -0
  186. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/braindecode.egg-info/top_level.txt +0 -0
  187. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/Makefile +0 -0
  188. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/_templates/autosummary/class.rst +0 -0
  189. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
  190. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/_templates/autosummary/function.rst +0 -0
  191. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
  192. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/agent_docs.rst +0 -0
  193. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/api.rst +0 -0
  194. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/cite.rst +0 -0
  195. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/conf.py +0 -0
  196. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/help.rst +0 -0
  197. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/index.rst +0 -0
  198. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/install/install.rst +0 -0
  199. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/install/install_pip.rst +0 -0
  200. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/install/install_source.rst +0 -0
  201. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/models/categorization/attention.rst +0 -0
  202. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/models/categorization/channel.rst +0 -0
  203. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/models/categorization/convolution.rst +0 -0
  204. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/models/categorization/filterbank.rst +0 -0
  205. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/models/categorization/gnn.rst +0 -0
  206. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/models/categorization/interpretable.rst +0 -0
  207. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/models/categorization/lbm.rst +0 -0
  208. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/models/categorization/recurrent.rst +0 -0
  209. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/models/categorization/spd.rst +0 -0
  210. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/models/models.rst +0 -0
  211. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/models/models_categorization.rst +0 -0
  212. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/models/models_table.rst +0 -0
  213. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/models/models_visualization.rst +0 -0
  214. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/sg_execution_times.rst +0 -0
  215. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/docs/user_guide/channel_strategies.rst +0 -0
  216. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/pyproject.toml +0 -0
  217. {braindecode-1.8.1.dev168929986 → braindecode-1.8.1.dev169077960}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: braindecode
3
- Version: 1.8.1.dev168929986
3
+ Version: 1.8.1.dev169077960
4
4
  Summary: Deep learning software to decode EEG, ECG or MEG signals
5
5
  Author-email: Robin Tibor Schirrmeister <robintibor@gmail.com>, Bruno Aristimunha Pinto <b.aristimunha@gmail.com>, Alexandre Gramfort <agramfort@meta.com>
6
6
  Maintainer-email: Alexandre Gramfort <agramfort@meta.com>, Bruno Aristimunha Pinto <b.aristimunha@gmail.com>, Robin Tibor Schirrmeister <robintibor@gmail.com>
@@ -0,0 +1,53 @@
1
+ import importlib
2
+ from typing import TYPE_CHECKING
3
+
4
+ from .version import __version__
5
+
6
+ if TYPE_CHECKING: # type checkers and IDEs see the classes; runtime uses __getattr__
7
+ from .classifier import EEGClassifier
8
+ from .regressor import EEGRegressor
9
+
10
+ __all__ = [
11
+ "__version__",
12
+ "EEGClassifier",
13
+ "EEGRegressor",
14
+ ]
15
+
16
+ # Subpackages reachable as ``braindecode.<name>`` after a bare ``import braindecode``.
17
+ _SUBMODULES = frozenset(
18
+ {
19
+ "augmentation",
20
+ "classifier",
21
+ "datasets",
22
+ "datautil",
23
+ "eegneuralnet",
24
+ "functional",
25
+ "models",
26
+ "modules",
27
+ "preprocessing",
28
+ "regressor",
29
+ "samplers",
30
+ "training",
31
+ "util",
32
+ "visualization",
33
+ }
34
+ )
35
+
36
+ if not TYPE_CHECKING: # hidden from checkers so misspelled names stay errors
37
+
38
+ def __getattr__(name):
39
+ # PEP 562: skorch, the datasets and the models load on first use.
40
+ if name == "EEGClassifier":
41
+ from .classifier import EEGClassifier
42
+
43
+ return EEGClassifier
44
+ if name == "EEGRegressor":
45
+ from .regressor import EEGRegressor
46
+
47
+ return EEGRegressor
48
+ if name in _SUBMODULES:
49
+ return importlib.import_module(f".{name}", __name__)
50
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
51
+
52
+ def __dir__():
53
+ return sorted(set(globals()) | set(__all__) | _SUBMODULES)
@@ -26,6 +26,7 @@ from itertools import chain
26
26
  from operator import attrgetter
27
27
  from pathlib import Path
28
28
  from typing import Any, Generic, Iterable, no_type_check
29
+ from uuid import uuid4
29
30
 
30
31
  import mne
31
32
  import mne.io
@@ -343,6 +344,9 @@ def _read_fif_window(raw, start, stop, willneed=False):
343
344
  return np.multiply(picked, raw._cals[:, np.newaxis], order="C")
344
345
 
345
346
 
347
+ _COALESCED_MAX_BYTES = 2 * 1024 * 1024
348
+
349
+
346
350
  def _window_info(crop_inds, sfreq):
347
351
  """Extract window size from crop indices.
348
352
 
@@ -479,14 +483,14 @@ def _zarr_to_memmap(zarr_path, group_name):
479
483
  ``SIGBUS`` when workers page-faulted on the unlinked inode.
480
484
 
481
485
  Under ``N`` concurrent writers, every racer materialises the data
482
- into its own per-pid temp file and then tries to publish it; at
486
+ into its own per-call temp file and then tries to publish it; at
483
487
  most one ``os.link`` wins, and the losers silently ``unlink``
484
488
  their temp file in a ``finally`` block. The wasted I/O scales
485
489
  with the number of racers; for the workloads braindecode targets
486
490
  (a handful of concurrent workers per group) it is negligible.
487
491
 
488
492
  Crash recovery: if a writer dies mid-run the only debris is a
489
- ``<group>.<pid>.tmp.npy`` file. Such files are namespaced by pid
493
+ ``<group>.<uuid>.tmp.npy`` file. Such files are unique per call
490
494
  so they can never collide with a live writer, they are never
491
495
  read by the fast path, and they do not prevent subsequent
492
496
  callers from producing a correct result. Caches written by
@@ -504,7 +508,10 @@ def _zarr_to_memmap(zarr_path, group_name):
504
508
 
505
509
  cache_dir.mkdir(parents=True, exist_ok=True)
506
510
  arr = zarr.open(zarr_path, mode="r")[group_name]["data"]
507
- tmp_path = cache_dir / f"{group_name}.{os.getpid()}.tmp.npy"
511
+ # Unique per call, not per pid: threads of one process must not share it.
512
+ # Exclusive creation, not tempfile.mkstemp, which would make it 0600.
513
+ tmp_path = cache_dir / f"{group_name}.{uuid4().hex}.tmp.npy"
514
+ tmp_path.open("xb").close()
508
515
  try:
509
516
  # Write chunk-by-chunk to avoid materialising the whole zarr
510
517
  # array in RAM.
@@ -531,9 +538,9 @@ def _zarr_to_memmap(zarr_path, group_name):
531
538
  # canonical one; ours is discarded in the finally block.
532
539
  pass
533
540
  finally:
534
- # Always remove our private per-pid temp file. It is
535
- # namespaced by pid so this cannot clobber a concurrent
536
- # writer's in-progress tmp file.
541
+ # Always remove our private per-call temp file. Its name is
542
+ # unique per call so this cannot clobber a concurrent writer's
543
+ # in-progress tmp file.
537
544
  try:
538
545
  os.unlink(tmp_path)
539
546
  except FileNotFoundError:
@@ -953,6 +960,10 @@ class EEGWindowsDataset(_ZarrMixin, RecordDataset):
953
960
  X = self.raw._getitem(
954
961
  (slice(None), slice(i_start, i_stop)), return_times=False
955
962
  )
963
+ return self._finish_window(index, crop_inds, X)
964
+
965
+ def _finish_window(self, index, crop_inds, X):
966
+ """Item ``index`` from its raw samples ``X``, copied before the transform."""
956
967
  X = np.array(X, dtype="float32")
957
968
  if self.transform is not None:
958
969
  X = self.transform(X)
@@ -1344,11 +1355,24 @@ class BaseConcatDataset(ConcatDataset, HubDatasetMixin, Generic[T]):
1344
1355
  Optional function to call on targets before returning them.
1345
1356
  lazy : bool, default False
1346
1357
  If True, defer computing cumulative sizes until length or item access.
1358
+ coalesce_reads : bool, default False
1359
+ Opt in to reading a :class:`~torch.utils.data.DataLoader` batch of
1360
+ consecutive, overlapping windows of one lazy (``preload=False``) FIF
1361
+ recording as one union of samples instead of one read per window.
1362
+ Only a batch of consecutive ascending indices into one
1363
+ :class:`~braindecode.datasets.EEGWindowsDataset` (not a subclass)
1364
+ whose union is at most a third of the summed window samples and at
1365
+ most 2 MiB as float64 is read this way; every other batch takes the
1366
+ default path. Outputs, order and random number use equal the
1367
+ default's. It was faster only for heavily overlapping windows and
1368
+ slower for some other layouts (numbers in :ref:`whats_new`), so it is off
1369
+ by default. Containers returned by ``split`` default to ``False``.
1347
1370
  """
1348
1371
 
1349
1372
  plot = _viewer_plot # eegdash-viewer embed; a direct member so the API docs list it
1350
1373
 
1351
1374
  datasets: list[T]
1375
+ coalesce_reads: bool = False # default for pickles made before this option
1352
1376
 
1353
1377
  def __init__(
1354
1378
  self,
@@ -1358,6 +1382,7 @@ class BaseConcatDataset(ConcatDataset, HubDatasetMixin, Generic[T]):
1358
1382
  target_transform: Callable | None = None,
1359
1383
  *,
1360
1384
  lazy: bool = False,
1385
+ coalesce_reads: bool = False,
1361
1386
  ):
1362
1387
  # Adapted from torch.utils.data.ConcatDataset:
1363
1388
  # added lazy init to defer cumulative size computation until access,
@@ -1387,6 +1412,9 @@ class BaseConcatDataset(ConcatDataset, HubDatasetMixin, Generic[T]):
1387
1412
 
1388
1413
  self.target_transform = target_transform
1389
1414
  self._lazy = lazy
1415
+ if type(coalesce_reads) is not bool:
1416
+ raise TypeError("coalesce_reads must be a bool.")
1417
+ self.coalesce_reads = coalesce_reads
1390
1418
 
1391
1419
  @property
1392
1420
  def cumulative_sizes(self) -> list[int]:
@@ -1454,6 +1482,10 @@ class BaseConcatDataset(ConcatDataset, HubDatasetMixin, Generic[T]):
1454
1482
  another: on a network file system a batch read from cold files then
1455
1483
  costs about one round trip, not one per window.
1456
1484
  """
1485
+ if self.coalesce_reads:
1486
+ coalesced = self._get_coalesced_items(indices)
1487
+ if coalesced is not None:
1488
+ return coalesced
1457
1489
  # ponytail: advises the whole batch at once; chunk it if a batch's
1458
1490
  # windows ever outgrow the page cache
1459
1491
  if hasattr(os, "posix_fadvise"):
@@ -1466,6 +1498,52 @@ class BaseConcatDataset(ConcatDataset, HubDatasetMixin, Generic[T]):
1466
1498
  _read_fif_window(ds.raw, start, stop, willneed=True)
1467
1499
  return [self[idx] for idx in indices]
1468
1500
 
1501
+ def _get_coalesced_items(self, indices):
1502
+ """The items cut from one read of their union, or None if not eligible."""
1503
+ n = len(indices)
1504
+ if (
1505
+ type(self) is not BaseConcatDataset # subclasses may override items
1506
+ or n < 2
1507
+ or type(indices[0]) is not int
1508
+ or indices[0] < 0
1509
+ or indices != list(range(indices[0], indices[0] + n))
1510
+ ):
1511
+ return None
1512
+ sizes = self._ensure_cumulative_sizes()
1513
+ k = bisect.bisect_right(sizes, indices[0])
1514
+ if k == len(sizes) or indices[-1] >= sizes[k]:
1515
+ return None # past the end, or across recordings
1516
+ ds = self.datasets[k]
1517
+ if (
1518
+ type(ds) is not EEGWindowsDataset
1519
+ or ds._zarr_data is not None
1520
+ or not isinstance(ds.crop_inds, np.ndarray) # lazy metadata
1521
+ or ds.raw.preload
1522
+ ):
1523
+ return None
1524
+ first = indices[0] - (sizes[k - 1] if k else 0)
1525
+ crops = ds.crop_inds[first : first + n]
1526
+ start, stop = int(crops[:, 1].min()), int(crops[:, 2].max())
1527
+ if (
1528
+ start < 0
1529
+ or stop > ds.raw.n_times
1530
+ or (crops[:, 2] <= crops[:, 1]).any()
1531
+ or 3 * (stop - start) > (crops[:, 2] - crops[:, 1]).sum()
1532
+ or (stop - start) * ds.raw.info["nchan"] * 8 > _COALESCED_MAX_BYTES
1533
+ ):
1534
+ return None
1535
+ union = _read_fif_window(ds.raw, start, stop)
1536
+ if union is None:
1537
+ return None
1538
+ items = []
1539
+ for i, crop in enumerate(crops.tolist(), first):
1540
+ X = union[:, crop[1] - start : crop[2] - start]
1541
+ item = ds._finish_window(i, crop, X)
1542
+ if self.target_transform is not None:
1543
+ item = item[:1] + (self.target_transform(item[1]),) + item[2:]
1544
+ items.append(item)
1545
+ return items
1546
+
1469
1547
  def __getitem__(self, idx: int | list):
1470
1548
  """
1471
1549
  ---
@@ -1583,15 +1661,17 @@ class BaseConcatDataset(ConcatDataset, HubDatasetMixin, Generic[T]):
1583
1661
  df = ds._windows.metadata
1584
1662
  else:
1585
1663
  df = ds.metadata
1664
+ # a dataset built without description has description None
1665
+ description = ds.description if ds.description is not None else {}
1586
1666
  if (
1587
1667
  "i_trial_in_dataset" in df.columns
1588
- and "i_trial_in_dataset" in ds.description
1668
+ and "i_trial_in_dataset" in description
1589
1669
  ):
1590
1670
  raise ValueError(
1591
1671
  "Dataset descriptions cannot contain the reserved window "
1592
1672
  "metadata key 'i_trial_in_dataset'."
1593
1673
  )
1594
- if "i_dataset" in df.columns or "i_dataset" in ds.description:
1674
+ if "i_dataset" in df.columns or "i_dataset" in description:
1595
1675
  raise ValueError(
1596
1676
  "Window metadata and dataset descriptions cannot contain the "
1597
1677
  "key 'i_dataset', which get_metadata() reserves for the "
@@ -1607,7 +1687,8 @@ class BaseConcatDataset(ConcatDataset, HubDatasetMixin, Generic[T]):
1607
1687
  if isinstance(df, pd.DataFrame):
1608
1688
  # copy so the description columns stay out of the dataset
1609
1689
  df = df.copy()
1610
- for k, v in ds.description.items():
1690
+ description = ds.description if ds.description is not None else {}
1691
+ for k, v in description.items():
1611
1692
  df[k] = v
1612
1693
  df["i_dataset"] = i_ds
1613
1694
  all_dfs.append(df)
@@ -0,0 +1,133 @@
1
+ """Some predefined network architectures for EEG decoding."""
2
+
3
+ import ast
4
+ import importlib
5
+ from typing import TYPE_CHECKING
6
+
7
+ _LAZY: dict[str, str] # public name -> submodule, read below from the imports
8
+
9
+ # A new model needs one import line here. It gives type checkers the class and,
10
+ # read back at runtime, the lazy name -> submodule map and ``__all__``; so these
11
+ # imports are used although no code names them.
12
+ # ruff: noqa: F401
13
+ if TYPE_CHECKING:
14
+ from .atcnet import ATCNet
15
+ from .attentionbasenet import AttentionBaseNet
16
+ from .attn_sleep import AttnSleep
17
+ from .axon import AXON
18
+ from .barista import BaRISTA
19
+ from .base import EEGModuleMixin
20
+ from .bendr import BENDR
21
+ from .biot import BIOT
22
+ from .brainbert import BrainBERT
23
+ from .brainmodule import BrainModule
24
+ from .brainomni import BrainOmni, BrainTokenizer
25
+ from .brant import Brant
26
+ from .cbramod import CBraMod
27
+ from .codebrain import CodeBrain
28
+ from .contrawr import ContraWR
29
+ from .csbrain import CSBrain
30
+ from .ctnet import CTNet
31
+ from .dance import DANCE
32
+ from .deep4 import Deep4Net
33
+ from .deepsleepnet import DeepSleepNet
34
+ from .dgcnn import DGCNN
35
+ from .diver1 import DIVER1
36
+ from .duin import DuIN
37
+ from .eeg_clip import EEGCLIP
38
+ from .eegconformer import EEGConformer
39
+ from .eegdino import EEGDINO
40
+ from .eeginception_erp import EEGInceptionERP
41
+ from .eeginception_mi import EEGInceptionMI
42
+ from .eegitnet import EEGITNet
43
+ from .eegminer import EEGMiner
44
+ from .eegnet import EEGNet
45
+ from .eegnex import EEGNeX
46
+ from .eegpt import EEGPT
47
+ from .eegsimpleconv import EEGSimpleConv
48
+ from .eegsym import EEGSym
49
+ from .eegtcnet import EEGTCNet
50
+ from .emg2qwerty import EMG2QwertyNet
51
+ from .epint import EpiNT
52
+ from .fbcnet import FBCNet
53
+ from .fblightconvnet import FBLightConvNet
54
+ from .fbmsnet import FBMSNet
55
+ from .gcnsnet import GCNsNet
56
+ from .guetschel2026 import Guetschel2026
57
+ from .hybrid import HybridNet
58
+ from .ifnet import IFNet
59
+ from .labram import Labram
60
+ from .luna import LUNA
61
+ from .mapa import MAPA
62
+ from .medformer import MEDFormer
63
+ from .meta_neuromotor import MetaNeuromotorHand
64
+ from .mirepnet import MIRepNet
65
+ from .mscformer import MSCFormer
66
+ from .msvtnet import MSVTNet
67
+ from .mvpformer import MVPFormer
68
+ from .neuropose import NeuroPose
69
+ from .neurorvq import NeuroRVQ
70
+ from .neurorvq_tokenizer import NeuroRVQTokenizer
71
+ from .patchedtransformer import PBT
72
+ from .popt import PopulationTransformer
73
+ from .reve import REVE
74
+ from .sccnet import SCCNet
75
+ from .seizure_transformer import SeizureTransformer
76
+ from .sensingdynamics import SensingDynamics
77
+ from .shallow_fbcsp import ShallowFBCSPNet
78
+ from .signal_jepa import (
79
+ SignalJEPA,
80
+ SignalJEPA_Contextual,
81
+ SignalJEPA_PostLocal,
82
+ SignalJEPA_PreLocal,
83
+ )
84
+ from .sinc_shallow import SincShallowNet
85
+ from .sleep_stager_blanco_2020 import SleepStagerBlanco2020
86
+ from .sleep_stager_chambon_2018 import SleepStagerChambon2018
87
+ from .sleepfm import SleepFM, SleepFMStager
88
+ from .sparcnet import SPARCNet
89
+ from .sstdpn import SSTDPN
90
+ from .steegformer import STEEGFormer
91
+ from .syncnet import SyncNet
92
+ from .tcformer import TCFormer
93
+ from .tcn import BDTCN, TCN
94
+ from .tfm_tokenizer import TFMTokenizer, TFMTokenizerOutput
95
+ from .tidnet import TIDNet
96
+ from .tmsanet import TMSANet
97
+ from .tsinception import TSception
98
+ from .usleep import USleep
99
+ from .util import (
100
+ _init_models_dict,
101
+ build_model_config,
102
+ extract_channel_locations_from_chs_info,
103
+ models_mandatory_parameters,
104
+ positions_from_chs_info,
105
+ )
106
+ from .vemg2pose import VEMG2Pose
107
+ from .zuna import ZUNA
108
+ else: # hidden from checkers so misspelled names stay errors
109
+
110
+ def _type_checking_imports():
111
+ # ponytail: needs this file's source, as get_summary_table needs summary.csv.
112
+ with open(__file__, "rb") as source:
113
+ tree = ast.parse(source.read())
114
+ block = next(node for node in tree.body if isinstance(node, ast.If))
115
+ return {alias.name: imp.module for imp in block.body for alias in imp.names}
116
+
117
+ # Each submodule is imported on first attribute access (PEP 562), so
118
+ # ``import braindecode`` does not load every model.
119
+ _LAZY = _type_checking_imports()
120
+ __all__ = list(_LAZY)
121
+
122
+ def __getattr__(name):
123
+ if name in _LAZY:
124
+ value = getattr(importlib.import_module(f".{_LAZY[name]}", __name__), name)
125
+ elif name in _LAZY.values():
126
+ value = importlib.import_module(f".{name}", __name__)
127
+ else:
128
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
129
+ globals()[name] = value
130
+ return value
131
+
132
+ def __dir__():
133
+ return sorted(set(globals()) | set(__all__))
@@ -8,6 +8,7 @@ from __future__ import annotations
8
8
  import functools
9
9
  import inspect
10
10
  import json
11
+ import logging
11
12
  import warnings
12
13
  from collections import OrderedDict
13
14
  from pathlib import Path, PurePosixPath, PureWindowsPath
@@ -35,6 +36,7 @@ huggingface_hub = _soft_import(
35
36
  )
36
37
 
37
38
  HAS_HF_HUB = huggingface_hub is not False
39
+ log = logging.getLogger(__name__)
38
40
 
39
41
  # __init__ args that from_pretrained fills from config.json when not given.
40
42
  _GEOMETRY_KWARGS = (
@@ -61,6 +63,26 @@ def _validate_weights_filename(filename):
61
63
  raise ValueError("filename must be a relative weight path without traversal")
62
64
 
63
65
 
66
+ def _load_card_data(pretrained_model_name_or_path, **kwargs):
67
+ """Metadata of a checkpoint's model card (``README.md``), or None.
68
+
69
+ Best effort: the card is informational, so a missing or unreadable card
70
+ (offline, no README, bad YAML) never blocks loading the weights.
71
+ """
72
+ keys = ("revision", "cache_dir", "force_download", "token", "local_files_only")
73
+ try:
74
+ card = Path(pretrained_model_name_or_path) / "README.md"
75
+ if not card.parent.is_dir():
76
+ card = huggingface_hub.hf_hub_download(
77
+ str(pretrained_model_name_or_path),
78
+ "README.md",
79
+ **{k: kwargs[k] for k in keys if k in kwargs},
80
+ )
81
+ return huggingface_hub.ModelCard.load(card, ignore_metadata_errors=True).data
82
+ except Exception:
83
+ return None
84
+
85
+
64
86
  def _local_weights_path(model_id, filename):
65
87
  """Reject local weight paths (including symlinks) outside the model folder."""
66
88
  root = Path(model_id).resolve()
@@ -212,6 +234,11 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
212
234
  there will be an attempt to infer them from the other parameters.
213
235
  """
214
236
 
237
+ #: Hub model card metadata (:class:`huggingface_hub.ModelCardData`) of the
238
+ #: checkpoint, set by :meth:`from_pretrained` when the card can be read,
239
+ #: e.g. ``model.card_data.datasets`` lists the data the weights saw.
240
+ card_data = None
241
+
215
242
  #: Template for model-specific Hub integration notes appended by
216
243
  #: ``__init_subclass__``. ``{name}`` is replaced with the concrete
217
244
  #: model class name.
@@ -234,10 +261,11 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
234
261
  model = {name}(n_chans=22, n_outputs=4, n_times=1000)
235
262
  # ... training code ...
236
263
 
237
- # Push to the Hub
264
+ # Push to the Hub; ``datasets`` and ``base_model`` go to the card
238
265
  model.push_to_hub(
239
266
  repo_id="username/my-{name_lower}-model",
240
267
  commit_message="Initial model upload",
268
+ model_card_kwargs={{"datasets": ["BNCI2014_001"]}},
241
269
  )
242
270
 
243
271
  **Loading a model from the Hub:**
@@ -248,6 +276,8 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
248
276
 
249
277
  # Load pretrained model
250
278
  model = {name}.from_pretrained("username/my-{name_lower}-model")
279
+ # Data the weights were trained on, from the Hub model card
280
+ print(model.card_data.datasets if model.card_data else None)
251
281
 
252
282
  # Load with a different number of outputs (head is rebuilt automatically)
253
283
  model = {name}.from_pretrained("username/my-{name_lower}-model", n_outputs=4)
@@ -1015,7 +1045,26 @@ class EEGModuleMixin(_BaseHubMixin, metaclass=_BraindecodeDocstringMeta):
1015
1045
  kwargs.setdefault("chs_info", None)
1016
1046
  if "n_times" in kwargs or "sfreq" in kwargs:
1017
1047
  kwargs.setdefault("input_window_seconds", None)
1018
- return super().from_pretrained(*args, **kwargs)
1048
+ model = super().from_pretrained(*args, **kwargs)
1049
+ card_data = _load_card_data(*args, **kwargs)
1050
+ if card_data is not None:
1051
+ model.card_data = card_data
1052
+ if card_data.datasets:
1053
+ log.info(
1054
+ "%s weights were trained on (model card): %s",
1055
+ cls.__name__,
1056
+ card_data.datasets,
1057
+ )
1058
+ return model
1059
+
1060
+ def generate_model_card(self, *args, **kwargs):
1061
+ # ``model_card_kwargs`` only fill the card's Jinja template; also
1062
+ # write these two to its YAML header so the Hub indexes them.
1063
+ card = super().generate_model_card(*args, **kwargs)
1064
+ for key in ("datasets", "base_model"):
1065
+ if key in kwargs:
1066
+ setattr(card.data, key, kwargs[key])
1067
+ return card
1019
1068
 
1020
1069
  @classmethod
1021
1070
  def _from_pretrained(
@@ -1,5 +1,6 @@
1
1
  # Authors: Bruno Aristimunha <b.aristimunha@gmail.com>
2
2
  # Sarthak Tayal <sarthaktayal2@gmail.com>
3
+ # Anton Soloviev <anton@praviel.com>
3
4
  #
4
5
  # License: BSD (3-clause)
5
6
 
@@ -569,8 +570,9 @@ class _BENDRContextualizer(nn.Module):
569
570
  [copy.deepcopy(encoder_layer) for _ in range(layers)]
570
571
  )
571
572
 
572
- # Add final LayerNorm after all transformer layers (paper specification)
573
- self.norm = nn.LayerNorm(self.transformer_dim)
573
+ # Retained for compatibility with released state dicts. The original
574
+ # contextualizer defines this norm but does not apply it in forward.
575
+ self.norm = nn.LayerNorm(self.transformer_dim).requires_grad_(False)
574
576
 
575
577
  # --- Output Layer --- (Project back down to in_features)
576
578
  # Paper uses Conv1d with kernel=1 (equivalent to Linear but expects (B,C,T) input)
@@ -630,10 +632,6 @@ class _BENDRContextualizer(nn.Module):
630
632
  x = layer(x)
631
633
  # x: [seq_len + 1, batch_size, transformer_dim]
632
634
 
633
- # Apply final LayerNorm (T-Fixup: norm only at the end)
634
- x = self.norm(x)
635
- # x: [seq_len + 1, batch_size, transformer_dim]
636
-
637
635
  # Permute to (B, C, T) format for Conv1d output layer
638
636
  x = x.permute(1, 2, 0)
639
637
  # x: [batch_size, transformer_dim, seq_len + 1]
@@ -12,8 +12,6 @@ from braindecode.models.base import EEGModuleMixin
12
12
  from braindecode.models.util import (
13
13
  SigArgName,
14
14
  _get_model_class,
15
- _init_models_dict,
16
- models_dict,
17
15
  models_mandatory_parameters,
18
16
  resolve_config_type,
19
17
  )
@@ -216,9 +214,6 @@ def make_model_config(
216
214
  # and define __all__ based on generated classes
217
215
  __all__ = ["make_model_config"]
218
216
 
219
- if not models_dict:
220
- _init_models_dict()
221
-
222
217
  models_configs: list[type[BaseBraindecodeModelConfig]] = []
223
218
  for model_name, req, _ in models_mandatory_parameters:
224
219
  model_cls = _get_model_class(model_name)
@@ -14,6 +14,7 @@ the LICENSE Of this file is APACHE-2.0.
14
14
  """
15
15
 
16
16
  import math
17
+ import warnings
17
18
  from functools import partial
18
19
  from typing import Any, Dict, Optional, Tuple, Type
19
20
 
@@ -146,7 +147,6 @@ class LUNA(EEGModuleMixin, nn.Module, license="apache-2.0"):
146
147
  input_window_seconds: Optional[float] = None,
147
148
  # Model-specific parameters
148
149
  patch_size: int = 40,
149
- on_non_divisible: str = "pad",
150
150
  num_queries: int = 4,
151
151
  embed_dim: int = 64,
152
152
  depth: int = 8,
@@ -157,6 +157,7 @@ class LUNA(EEGModuleMixin, nn.Module, license="apache-2.0"):
157
157
  drop_prob_chan: float = 0.0,
158
158
  attn_drop: float = 0.0,
159
159
  activation: Type[nn.Module] = nn.GELU,
160
+ on_non_divisible: str = "pad",
160
161
  channel_strategy: str = "native",
161
162
  channel_strategy_kwargs: dict | None = None,
162
163
  ):
@@ -284,6 +285,23 @@ class LUNA(EEGModuleMixin, nn.Module, license="apache-2.0"):
284
285
  self.apply(_init_weights)
285
286
  self.fix_init_weight()
286
287
 
288
+ def initialize_weights(self) -> None:
289
+ """Re-run LUNA's own weight initialization.
290
+
291
+ .. deprecated:: 2.0
292
+ ``initialize_weights`` was renamed to the private
293
+ ``_init_parameters`` and will be removed in a future release.
294
+ Use :meth:`reset_parameters`, which first resets every layer to
295
+ its PyTorch default and then applies this initialization.
296
+ """
297
+ warnings.warn(
298
+ "LUNA.initialize_weights() is deprecated and will be removed in a "
299
+ "future release; use LUNA.reset_parameters() instead.",
300
+ DeprecationWarning,
301
+ stacklevel=2,
302
+ )
303
+ self._init_parameters()
304
+
287
305
  def fix_init_weight(self) -> None:
288
306
  def rescale(param: torch.Tensor, layer_id: int) -> None:
289
307
  param.div_(math.sqrt(2.0 * layer_id))