braindecode 1.5.0.dev983__tar.gz → 1.5.0.dev984__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.5.0.dev983/braindecode.egg-info → braindecode-1.5.0.dev984}/PKG-INFO +1 -1
  2. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/base.py +80 -19
  3. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/attentionbasenet.py +3 -2
  4. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/syncnet.py +17 -13
  5. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/tsinception.py +1 -1
  6. braindecode-1.5.0.dev984/braindecode/version.py +1 -0
  7. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984/braindecode.egg-info}/PKG-INFO +1 -1
  8. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/whats_new.rst +19 -1
  9. braindecode-1.5.0.dev983/braindecode/version.py +0 -1
  10. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/LICENSE.txt +0 -0
  11. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/MANIFEST.in +0 -0
  12. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/NOTICE.txt +0 -0
  13. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/README.rst +0 -0
  14. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/__init__.py +0 -0
  15. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/augmentation/__init__.py +0 -0
  16. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/augmentation/base.py +0 -0
  17. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/augmentation/functional.py +0 -0
  18. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/augmentation/transforms.py +0 -0
  19. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/classifier.py +0 -0
  20. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/__init__.py +0 -0
  21. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/bbci.py +0 -0
  22. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/bcicomp.py +0 -0
  23. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/bids/__init__.py +0 -0
  24. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/bids/datasets.py +0 -0
  25. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/bids/format.py +0 -0
  26. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/bids/hub.py +0 -0
  27. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/bids/hub_format.py +0 -0
  28. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/bids/hub_io.py +0 -0
  29. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/bids/hub_validation.py +0 -0
  30. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/bids/iterable.py +0 -0
  31. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/chb_mit.py +0 -0
  32. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/mne.py +0 -0
  33. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/moabb.py +0 -0
  34. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/nmt.py +0 -0
  35. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/registry.py +0 -0
  36. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/siena.py +0 -0
  37. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/sleep_physio_challe_18.py +0 -0
  38. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/sleep_physionet.py +0 -0
  39. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/tuh.py +0 -0
  40. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/utils.py +0 -0
  41. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datasets/xy.py +0 -0
  42. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datautil/__init__.py +0 -0
  43. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datautil/channel_utils.py +0 -0
  44. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datautil/hub_formats.py +0 -0
  45. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datautil/serialization.py +0 -0
  46. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/datautil/util.py +0 -0
  47. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/eegneuralnet.py +0 -0
  48. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/functional/__init__.py +0 -0
  49. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/functional/functions.py +0 -0
  50. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/functional/initialization.py +0 -0
  51. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/__init__.py +0 -0
  52. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/atcnet.py +0 -0
  53. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/attn_sleep.py +0 -0
  54. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/base.py +0 -0
  55. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/bendr.py +0 -0
  56. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/biot.py +0 -0
  57. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/brainmodule.py +0 -0
  58. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/cbramod.py +0 -0
  59. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/config.py +0 -0
  60. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/contrawr.py +0 -0
  61. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/ctnet.py +0 -0
  62. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/deep4.py +0 -0
  63. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/deepsleepnet.py +0 -0
  64. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/dgcnn.py +0 -0
  65. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/eegconformer.py +0 -0
  66. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/eeginception_erp.py +0 -0
  67. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/eeginception_mi.py +0 -0
  68. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/eegitnet.py +0 -0
  69. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/eegminer.py +0 -0
  70. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/eegnet.py +0 -0
  71. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/eegnex.py +0 -0
  72. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/eegpt.py +0 -0
  73. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/eegsimpleconv.py +0 -0
  74. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/eegsym.py +0 -0
  75. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/eegtcnet.py +0 -0
  76. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/fbcnet.py +0 -0
  77. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/fblightconvnet.py +0 -0
  78. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/fbmsnet.py +0 -0
  79. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/hybrid.py +0 -0
  80. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/ifnet.py +0 -0
  81. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/labram.py +0 -0
  82. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/luna.py +0 -0
  83. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/medformer.py +0 -0
  84. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/msvtnet.py +0 -0
  85. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/patchedtransformer.py +0 -0
  86. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/reve.py +0 -0
  87. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/sccnet.py +0 -0
  88. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/shallow_fbcsp.py +0 -0
  89. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/signal_jepa.py +0 -0
  90. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/sinc_shallow.py +0 -0
  91. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
  92. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
  93. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/sparcnet.py +0 -0
  94. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/sstdpn.py +0 -0
  95. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/summary.csv +0 -0
  96. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/tcn.py +0 -0
  97. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/tidnet.py +0 -0
  98. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/usleep.py +0 -0
  99. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/models/util.py +0 -0
  100. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/modules/__init__.py +0 -0
  101. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/modules/activation.py +0 -0
  102. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/modules/attention.py +0 -0
  103. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/modules/blocks.py +0 -0
  104. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/modules/convolution.py +0 -0
  105. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/modules/filter.py +0 -0
  106. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/modules/layers.py +0 -0
  107. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/modules/linear.py +0 -0
  108. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/modules/parametrization.py +0 -0
  109. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/modules/stats.py +0 -0
  110. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/modules/util.py +0 -0
  111. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/modules/wrapper.py +0 -0
  112. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/preprocessing/__init__.py +0 -0
  113. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/preprocessing/eegprep_preprocess.py +0 -0
  114. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/preprocessing/mne_preprocess.py +0 -0
  115. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/preprocessing/preprocess.py +0 -0
  116. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/preprocessing/util.py +0 -0
  117. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/preprocessing/windowers.py +0 -0
  118. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/regressor.py +0 -0
  119. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/samplers/__init__.py +0 -0
  120. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/samplers/base.py +0 -0
  121. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/samplers/ssl.py +0 -0
  122. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/training/__init__.py +0 -0
  123. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/training/callbacks.py +0 -0
  124. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/training/losses.py +0 -0
  125. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/training/scoring.py +0 -0
  126. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/util.py +0 -0
  127. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/visualization/__init__.py +0 -0
  128. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/visualization/confusion_matrices.py +0 -0
  129. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode/visualization/gradients.py +0 -0
  130. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode.egg-info/SOURCES.txt +0 -0
  131. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode.egg-info/dependency_links.txt +0 -0
  132. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode.egg-info/requires.txt +0 -0
  133. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/braindecode.egg-info/top_level.txt +0 -0
  134. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/Makefile +0 -0
  135. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/_templates/autosummary/class.rst +0 -0
  136. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/_templates/autosummary/class_in_subdir.rst +0 -0
  137. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/_templates/autosummary/function.rst +0 -0
  138. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/_templates/autosummary/function_in_subdir.rst +0 -0
  139. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/api.rst +0 -0
  140. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/cite.rst +0 -0
  141. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/conf.py +0 -0
  142. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/help.rst +0 -0
  143. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/index.rst +0 -0
  144. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/install/install.rst +0 -0
  145. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/install/install_pip.rst +0 -0
  146. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/install/install_source.rst +0 -0
  147. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/models/categorization/attention.rst +0 -0
  148. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/models/categorization/channel.rst +0 -0
  149. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/models/categorization/convolution.rst +0 -0
  150. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/models/categorization/filterbank.rst +0 -0
  151. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/models/categorization/gnn.rst +0 -0
  152. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/models/categorization/interpretable.rst +0 -0
  153. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/models/categorization/lbm.rst +0 -0
  154. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/models/categorization/recurrent.rst +0 -0
  155. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/models/categorization/spd.rst +0 -0
  156. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/models/models.rst +0 -0
  157. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/models/models_categorization.rst +0 -0
  158. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/models/models_table.rst +0 -0
  159. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/models/models_visualization.rst +0 -0
  160. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/docs/sg_execution_times.rst +0 -0
  161. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/pyproject.toml +0 -0
  162. {braindecode-1.5.0.dev983 → braindecode-1.5.0.dev984}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: braindecode
3
- Version: 1.5.0.dev983
3
+ Version: 1.5.0.dev984
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>
@@ -298,34 +298,95 @@ def _build_windowed_repr(
298
298
 
299
299
 
300
300
  def _zarr_to_memmap(zarr_path, group_name):
301
- """Decompress a zarr array to a float64 ``.npy`` memmap (one-time, atomic).
302
-
303
- Saved as float64 so MNE objects can wrap the memmap zero-copy
304
- (MNE requires float64 internally). Copy-on-write mode (``'c'``)
305
- means preprocessing writes go to RAM, the file stays untouched.
301
+ """Materialise a zarr array as a float64 ``.npy`` memmap, race-free.
302
+
303
+ Decompress the ``group_name`` array inside ``zarr_path`` into a
304
+ float64 ``.npy`` file inside a sibling ``.<zarr>_memmap/`` cache
305
+ directory and return the path to that file. The dtype is float64
306
+ because MNE objects wrap the memmap zero-copy and MNE requires
307
+ float64 internally. Callers open the result with
308
+ ``np.load(path, mmap_mode='c')`` so preprocessing writes land in
309
+ anonymous copy-on-write pages and never mutate the on-disk file.
310
+
311
+ Concurrency contract
312
+ --------------------
313
+ Safe to call from any number of threads or processes concurrently
314
+ on the same ``(zarr_path, group_name)``, on local POSIX, NFSv3,
315
+ Lustre and SMB. The published ``.npy`` file is **created exactly
316
+ once and never replaced**: subsequent callers either hit the
317
+ already-materialised file on the fast path or lose the
318
+ publication race and discard their own copy.
319
+
320
+ The atomic publication step is ``os.link``, not ``rename``.
321
+ ``os.link(tmp, dst)`` either creates ``dst`` pointing at ``tmp``'s
322
+ inode or fails with :class:`FileExistsError` when ``dst`` already
323
+ exists — the "create only if absent" primitive we need, available
324
+ on every POSIX filesystem. ``rename`` was the wrong primitive:
325
+ it atomically *replaces* its destination, which unlinks the inode
326
+ that concurrent readers may already have ``mmap``'d. On NFSv3
327
+ that produced ``.nfsXXXX`` silly-rename files and intermittent
328
+ ``SIGBUS`` when workers page-faulted on the unlinked inode.
329
+
330
+ Under ``N`` concurrent writers, every racer materialises the data
331
+ into its own per-pid temp file and then tries to publish it; at
332
+ most one ``os.link`` wins, and the losers silently ``unlink``
333
+ their temp file in a ``finally`` block. The wasted I/O scales
334
+ with the number of racers; for the workloads braindecode targets
335
+ (a handful of concurrent workers per group) it is negligible.
336
+
337
+ Crash recovery: if a writer dies mid-run the only debris is a
338
+ ``<group>.<pid>.tmp.npy`` file. Such files are namespaced by pid
339
+ so they can never collide with a live writer, they are never
340
+ read by the fast path, and they do not prevent subsequent
341
+ callers from producing a correct result. Caches written by
342
+ earlier braindecode versions remain valid: the fast path only
343
+ requires ``<group>.npy`` to exist.
306
344
  """
307
345
  zarr_p = Path(zarr_path)
308
346
  cache_dir = zarr_p.parent / f".{zarr_p.name}_memmap"
309
347
  npy_path = cache_dir / f"{group_name}.npy"
310
348
 
311
- if not npy_path.exists():
312
- arr = zarr.open(zarr_path, mode="r")[group_name]["data"]
313
- cache_dir.mkdir(parents=True, exist_ok=True)
314
- tmp_path = cache_dir / f"{group_name}.{os.getpid()}.tmp.npy"
315
- # Write chunk-by-chunk to avoid materializing the full array in RAM
349
+ # Fast path: the file is already fully materialised. A single
350
+ # stat() is all the steady-state workload pays.
351
+ if npy_path.exists():
352
+ return npy_path
353
+
354
+ cache_dir.mkdir(parents=True, exist_ok=True)
355
+ arr = zarr.open(zarr_path, mode="r")[group_name]["data"]
356
+ tmp_path = cache_dir / f"{group_name}.{os.getpid()}.tmp.npy"
357
+ try:
358
+ # Write chunk-by-chunk to avoid materialising the whole zarr
359
+ # array in RAM.
316
360
  mm = np.lib.format.open_memmap(
317
361
  tmp_path, mode="w+", dtype=np.float64, shape=arr.shape
318
362
  )
319
- chunk0 = arr.chunks[0] if hasattr(arr, "chunks") else arr.shape[0]
320
- for start in range(0, arr.shape[0], chunk0):
321
- end = min(start + chunk0, arr.shape[0])
322
- mm[start:end] = np.asarray(arr[start:end], dtype=np.float64)
323
- mm.flush()
324
- del mm
325
363
  try:
326
- tmp_path.rename(npy_path)
327
- except OSError:
328
- tmp_path.unlink(missing_ok=True)
364
+ chunk0 = arr.chunks[0] if hasattr(arr, "chunks") else arr.shape[0]
365
+ for start in range(0, arr.shape[0], chunk0):
366
+ end = min(start + chunk0, arr.shape[0])
367
+ mm[start:end] = np.asarray(arr[start:end], dtype=np.float64)
368
+ mm.flush()
369
+ finally:
370
+ del mm
371
+
372
+ # Atomic publication. ``os.link`` never replaces an existing
373
+ # destination, so the published inode is immutable for the
374
+ # lifetime of the cache directory. Concurrent readers never
375
+ # see their mmap'd inode vanish from under them.
376
+ try:
377
+ os.link(tmp_path, npy_path)
378
+ except FileExistsError:
379
+ # Another writer beat us to it. Their file is the
380
+ # canonical one; ours is discarded in the finally block.
381
+ pass
382
+ finally:
383
+ # Always remove our private per-pid temp file. It is
384
+ # namespaced by pid so this cannot clobber a concurrent
385
+ # writer's in-progress tmp file.
386
+ try:
387
+ os.unlink(tmp_path)
388
+ except FileNotFoundError:
389
+ pass
329
390
 
330
391
  return npy_path
331
392
 
@@ -1,5 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
+ # Authors: Sarthak Tayal <sarthaktayal2@gmail.com>
4
+ #
5
+ # License: BSD (3-clause)
3
6
  import math
4
7
 
5
8
  from einops.layers.torch import Rearrange
@@ -275,8 +278,6 @@ class AttentionBaseNet(EEGModuleMixin, nn.Module):
275
278
  activation: type[nn.Module] = nn.ELU,
276
279
  extra_params: bool = False,
277
280
  ):
278
- super(AttentionBaseNet, self).__init__()
279
-
280
281
  super().__init__(
281
282
  n_outputs=n_outputs,
282
283
  n_chans=n_chans,
@@ -1,3 +1,7 @@
1
+ # Authors: Sarthak Tayal <sarthaktayal2@gmail.com>
2
+ #
3
+ # License: BSD (3-clause)
4
+
1
5
  import torch
2
6
  import torch.nn as nn
3
7
  import torch.nn.functional as F
@@ -51,11 +55,11 @@ class SyncNet(EEGModuleMixin, nn.Module):
51
55
  The initialization range for omega parameters using uniform
52
56
  distribution. Default is (0, 1).
53
57
  beta_init_values : tuple of float, optional
54
- The initialization range for beta parameters using uniform
55
- distribution. Default is (0, 1). Default is (0, 0.05).
58
+ The initialization range for beta (decay) parameters using uniform
59
+ distribution. Default is (0, 0.05).
56
60
  phase_init_values : tuple of float, optional
57
- The initialization range for phase parameters using `normal`
58
- distribution. Default is (0, 1). Default is (0, 0.05).
61
+ The initialization mean and standard deviation for phase
62
+ parameters using normal distribution. Default is (0, 0.05).
59
63
 
60
64
 
61
65
  Notes
@@ -146,12 +150,12 @@ class SyncNet(EEGModuleMixin, nn.Module):
146
150
  # Phase Shift
147
151
  self.phi_ini = nn.Parameter(
148
152
  torch.FloatTensor(1, 1, self.n_chans, self.num_filters).normal_(
149
- self.beta_init_values[0], self.beta_init_values[1]
153
+ self.phase_init_values[0], self.phase_init_values[1]
150
154
  )
151
155
  )
152
156
  self.beta = nn.Parameter(
153
157
  torch.FloatTensor(1, 1, 1, self.num_filters).uniform_(
154
- self.phase_init_values[0], self.phase_init_values[1]
158
+ self.beta_init_values[0], self.beta_init_values[1]
155
159
  )
156
160
  )
157
161
 
@@ -185,21 +189,21 @@ class SyncNet(EEGModuleMixin, nn.Module):
185
189
  # Output: (batch_size, n_chans, 1, n_times)
186
190
 
187
191
  # Compute the oscillatory component
192
+ # Shape: (1, filter_width, n_chans, num_filters)
188
193
  W_osc = self.amplitude * torch.cos(self.t * self.omega + self.phi_ini)
189
- # W_osc is (1, filter_width, n_chans, 1)
190
194
 
191
195
  # Compute the decay component
192
- t_squared = torch.pow(self.t, 2) # Shape: (filter_width,)
193
- t_squared_beta = t_squared * self.beta # Shape: (filter_width, num_filters)
196
+ # Shape: (1, filter_width, 1, num_filters)
197
+ t_squared = torch.pow(self.t, 2)
198
+ t_squared_beta = t_squared * self.beta
194
199
  W_decay = torch.exp(-t_squared_beta)
195
- # W_osc is (1, filter_width, 1, 1)
196
200
 
197
201
  # Combine oscillatory and decay components
198
- # W shape: (1, n_chans, num_filters, filter_width)
202
+ # Shape: (1, filter_width, n_chans, num_filters)
199
203
  W = W_osc * W_decay
200
- # W shape will be: (1, filter_width, n_chans, 1)
201
204
 
202
- W = W.view(self.num_filters, self.n_chans, 1, self.filter_width)
205
+ # Permute to conv2d weight shape (out_channels, in_channels, kH, kW)
206
+ W = W.permute(3, 2, 0, 1).contiguous()
203
207
 
204
208
  # Apply convolution
205
209
  x_padded = self.pad_input(x.float())
@@ -1,4 +1,4 @@
1
- # Authors: Bruno Aristimunha <b.aristimunha>
1
+ # Authors: Bruno Aristimunha <b.aristimunha@gmail.com>
2
2
  #
3
3
  # License: BSD (3-clause)
4
4
 
@@ -0,0 +1 @@
1
+ __version__ = "1.5.0.dev984"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: braindecode
3
- Version: 1.5.0.dev983
3
+ Version: 1.5.0.dev984
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>
@@ -41,7 +41,25 @@ Requirements
41
41
  Bug fixes
42
42
  ==========
43
43
 
44
- - None yet
44
+ - Fix :class:`braindecode.models.SyncNet` swapped parameter initialization where
45
+ ``phi_ini`` (phase shift) was using ``beta_init_values`` and ``beta`` (decay) was
46
+ using ``phase_init_values``, replaced incorrect ``.view()`` reshape with ``.permute()``
47
+ for proper conv2d filter weight layout, and fixed duplicate default values in docstring
48
+ (by `Sarthak Tayal`_)
49
+ - Fix :class:`braindecode.models.AttentionBaseNet` redundant
50
+ ``super().__init__()`` call that ran the parent ``nn.Module.__init__`` twice
51
+ (by `Sarthak Tayal`_)
52
+ - Fix incomplete author email in :class:`braindecode.models.TSception` header
53
+ (by `Sarthak Tayal`_)
54
+ - Fix a time-of-check-time-of-use race in
55
+ :func:`braindecode.datasets.base._zarr_to_memmap` that caused
56
+ concurrent workers to repeatedly ``rename``-replace the published
57
+ ``.npy`` cache, producing wasted I/O on local filesystems and
58
+ ``.nfsXXXX`` silly-rename files plus ``SIGBUS`` crashes on NFSv3.
59
+ The published file is now created exactly once via ``os.link`` and
60
+ is never replaced, making the cache safe under arbitrary
61
+ concurrent access on local POSIX, NFSv3, Lustre and SMB
62
+ (:gh:`986` by `Pierre Guetschel`_)
45
63
 
46
64
  Code health
47
65
  ============
@@ -1 +0,0 @@
1
- __version__ = "1.5.0.dev983"