Braindecode 1.3.0.dev171478045__tar.gz → 1.3.0.dev171850369__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 (137) hide show
  1. {braindecode-1.3.0.dev171478045/braindecode.egg-info → braindecode-1.3.0.dev171850369}/PKG-INFO +2 -4
  2. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/augmentation/functional.py +54 -154
  3. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/augmentation/transforms.py +2 -2
  4. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/datasets/base.py +1 -1
  5. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/datasets/sleep_physio_challe_18.py +1 -2
  6. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/datautil/serialization.py +6 -11
  7. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/eegneuralnet.py +0 -2
  8. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/__init__.py +0 -6
  9. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/atcnet.py +1 -1
  10. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/attentionbasenet.py +0 -2
  11. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/base.py +2 -280
  12. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/biot.py +0 -2
  13. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/labram.py +69 -170
  14. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/signal_jepa.py +27 -109
  15. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/summary.csv +0 -3
  16. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/util.py +0 -3
  17. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/preprocessing/preprocess.py +2 -11
  18. braindecode-1.3.0.dev171850369/braindecode/version.py +1 -0
  19. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369/braindecode.egg-info}/PKG-INFO +2 -4
  20. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode.egg-info/SOURCES.txt +0 -3
  21. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode.egg-info/requires.txt +1 -4
  22. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/api.rst +7 -6
  23. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/install/install.rst +1 -1
  24. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/models/categorization/attention.rst +2 -2
  25. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/models/categorization/channel.rst +2 -2
  26. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/models/categorization/convolution.rst +2 -2
  27. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/models/categorization/filterbank.rst +3 -3
  28. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/models/categorization/gnn.rst +6 -3
  29. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/models/categorization/interpretable.rst +3 -3
  30. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/models/categorization/lbm.rst +2 -2
  31. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/models/categorization/recurrent.rst +3 -3
  32. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/models/categorization/spd.rst +3 -3
  33. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/whats_new.rst +1 -13
  34. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/pyproject.toml +1 -2
  35. braindecode-1.3.0.dev171478045/braindecode/models/bendr.py +0 -469
  36. braindecode-1.3.0.dev171478045/braindecode/models/patchedtransformer.py +0 -640
  37. braindecode-1.3.0.dev171478045/braindecode/models/sstdpn.py +0 -869
  38. braindecode-1.3.0.dev171478045/braindecode/version.py +0 -1
  39. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/LICENSE.txt +0 -0
  40. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/MANIFEST.in +0 -0
  41. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/NOTICE.txt +0 -0
  42. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/README.rst +0 -0
  43. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/__init__.py +0 -0
  44. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/augmentation/__init__.py +0 -0
  45. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/augmentation/base.py +0 -0
  46. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/classifier.py +0 -0
  47. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/datasets/__init__.py +0 -0
  48. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/datasets/bbci.py +0 -0
  49. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/datasets/bcicomp.py +0 -0
  50. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/datasets/bids.py +0 -0
  51. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/datasets/experimental.py +0 -0
  52. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/datasets/mne.py +0 -0
  53. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/datasets/moabb.py +0 -0
  54. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/datasets/nmt.py +0 -0
  55. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/datasets/sleep_physionet.py +0 -0
  56. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/datasets/tuh.py +0 -0
  57. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/datasets/xy.py +0 -0
  58. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/datautil/__init__.py +0 -0
  59. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/datautil/util.py +0 -0
  60. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/functional/__init__.py +0 -0
  61. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/functional/functions.py +0 -0
  62. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/functional/initialization.py +0 -0
  63. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/attn_sleep.py +0 -0
  64. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/contrawr.py +0 -0
  65. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/ctnet.py +0 -0
  66. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/deep4.py +0 -0
  67. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/deepsleepnet.py +0 -0
  68. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/eegconformer.py +0 -0
  69. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/eeginception_erp.py +0 -0
  70. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/eeginception_mi.py +0 -0
  71. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/eegitnet.py +0 -0
  72. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/eegminer.py +0 -0
  73. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/eegnet.py +0 -0
  74. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/eegnex.py +0 -0
  75. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/eegsimpleconv.py +0 -0
  76. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/eegtcnet.py +0 -0
  77. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/fbcnet.py +0 -0
  78. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/fblightconvnet.py +0 -0
  79. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/fbmsnet.py +0 -0
  80. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/hybrid.py +0 -0
  81. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/ifnet.py +0 -0
  82. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/msvtnet.py +0 -0
  83. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/sccnet.py +0 -0
  84. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/shallow_fbcsp.py +0 -0
  85. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/sinc_shallow.py +0 -0
  86. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/sleep_stager_blanco_2020.py +0 -0
  87. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/sleep_stager_chambon_2018.py +0 -0
  88. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/sparcnet.py +0 -0
  89. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/syncnet.py +0 -0
  90. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/tcn.py +0 -0
  91. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/tidnet.py +0 -0
  92. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/tsinception.py +0 -0
  93. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/models/usleep.py +0 -0
  94. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/modules/__init__.py +0 -0
  95. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/modules/activation.py +0 -0
  96. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/modules/attention.py +0 -0
  97. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/modules/blocks.py +0 -0
  98. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/modules/convolution.py +0 -0
  99. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/modules/filter.py +0 -0
  100. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/modules/layers.py +0 -0
  101. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/modules/linear.py +0 -0
  102. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/modules/parametrization.py +0 -0
  103. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/modules/stats.py +0 -0
  104. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/modules/util.py +0 -0
  105. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/modules/wrapper.py +0 -0
  106. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/preprocessing/__init__.py +0 -0
  107. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/preprocessing/mne_preprocess.py +0 -0
  108. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/preprocessing/windowers.py +0 -0
  109. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/regressor.py +0 -0
  110. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/samplers/__init__.py +0 -0
  111. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/samplers/base.py +0 -0
  112. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/samplers/ssl.py +0 -0
  113. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/training/__init__.py +0 -0
  114. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/training/callbacks.py +0 -0
  115. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/training/losses.py +0 -0
  116. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/training/scoring.py +0 -0
  117. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/util.py +0 -0
  118. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/visualization/__init__.py +0 -0
  119. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/visualization/confusion_matrices.py +0 -0
  120. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode/visualization/gradients.py +0 -0
  121. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode.egg-info/dependency_links.txt +0 -0
  122. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/braindecode.egg-info/top_level.txt +0 -0
  123. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/Makefile +0 -0
  124. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/_templates/autosummary/class.rst +0 -0
  125. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/_templates/autosummary/function.rst +0 -0
  126. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/cite.rst +0 -0
  127. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/conf.py +0 -0
  128. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/help.rst +0 -0
  129. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/index.rst +0 -0
  130. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/install/install_pip.rst +0 -0
  131. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/install/install_source.rst +0 -0
  132. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/models/models.rst +0 -0
  133. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/models/models_categorization.rst +0 -0
  134. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/models/models_table.rst +0 -0
  135. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/models/models_visualization.rst +0 -0
  136. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/docs/sg_execution_times.rst +0 -0
  137. {braindecode-1.3.0.dev171478045 → braindecode-1.3.0.dev171850369}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: braindecode
3
- Version: 1.3.0.dev171478045
3
+ Version: 1.3.0.dev171850369
4
4
  Summary: Deep learning software to decode EEG, ECG or MEG signals
5
5
  Author-email: Robin Tibor Schirrmeister <robintibor@gmail.com>
6
6
  Maintainer-email: Alexandre Gramfort <agramfort@meta.com>, Bruno Aristimunha Pinto <b.aristimunha@gmail.com>, Robin Tibor Schirrmeister <robintibor@gmail.com>
@@ -40,8 +40,6 @@ Requires-Dist: linear_attention_transformer
40
40
  Requires-Dist: docstring_inheritance
41
41
  Provides-Extra: moabb
42
42
  Requires-Dist: moabb>=1.2.0; extra == "moabb"
43
- Provides-Extra: hug
44
- Requires-Dist: huggingface_hub[torch]>=0.20.0; extra == "hug"
45
43
  Provides-Extra: tests
46
44
  Requires-Dist: pytest; extra == "tests"
47
45
  Requires-Dist: pytest-cov; extra == "tests"
@@ -67,7 +65,7 @@ Requires-Dist: pre-commit; extra == "docs"
67
65
  Requires-Dist: openneuro-py; extra == "docs"
68
66
  Requires-Dist: plotly; extra == "docs"
69
67
  Provides-Extra: all
70
- Requires-Dist: braindecode[docs,hug,moabb,tests]; extra == "all"
68
+ Requires-Dist: braindecode[docs,moabb,tests]; extra == "all"
71
69
  Dynamic: license-file
72
70
 
73
71
  .. image:: https://badges.gitter.im/braindecodechat/community.svg
@@ -4,13 +4,9 @@
4
4
  #
5
5
  # License: BSD (3-clause)
6
6
 
7
- from __future__ import annotations
8
-
9
7
  from numbers import Real
10
- from typing import Literal
11
8
 
12
9
  import numpy as np
13
- import numpy.typing as npt
14
10
  import torch
15
11
  from mne.filter import notch_filter
16
12
  from scipy.interpolate import Rbf
@@ -19,7 +15,7 @@ from torch.fft import fft, ifft
19
15
  from torch.nn.functional import one_hot, pad
20
16
 
21
17
 
22
- def identity(X: torch.Tensor, y: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor]:
18
+ def identity(X, y):
23
19
  """Identity operation.
24
20
 
25
21
  Parameters
@@ -39,7 +35,7 @@ def identity(X: torch.Tensor, y: torch.Tensor) -> tuple[torch.Tensor, torch.Tens
39
35
  return X, y
40
36
 
41
37
 
42
- def time_reverse(X: torch.Tensor, y: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor]:
38
+ def time_reverse(X, y):
43
39
  """Flip the time axis of each input.
44
40
 
45
41
  Parameters
@@ -59,7 +55,7 @@ def time_reverse(X: torch.Tensor, y: torch.Tensor) -> tuple[torch.Tensor, torch.
59
55
  return torch.flip(X, [-1]), y
60
56
 
61
57
 
62
- def sign_flip(X: torch.Tensor, y: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor]:
58
+ def sign_flip(X, y):
63
59
  """Flip the sign axis of each input.
64
60
 
65
61
  Parameters
@@ -79,13 +75,7 @@ def sign_flip(X: torch.Tensor, y: torch.Tensor) -> tuple[torch.Tensor, torch.Ten
79
75
  return -X, y
80
76
 
81
77
 
82
- def _new_random_fft_phase_odd(
83
- batch_size: int,
84
- c: int,
85
- n: int,
86
- device: torch.device,
87
- random_state: int | np.random.RandomState | None,
88
- ) -> torch.Tensor:
78
+ def _new_random_fft_phase_odd(batch_size, c, n, device, random_state):
89
79
  rng = check_random_state(random_state)
90
80
  random_phase = torch.from_numpy(
91
81
  2j * np.pi * rng.random((batch_size, c, (n - 1) // 2))
@@ -100,13 +90,7 @@ def _new_random_fft_phase_odd(
100
90
  )
101
91
 
102
92
 
103
- def _new_random_fft_phase_even(
104
- batch_size: int,
105
- c: int,
106
- n: int,
107
- device: torch.device,
108
- random_state: int | np.random.RandomState | None,
109
- ) -> torch.Tensor:
93
+ def _new_random_fft_phase_even(batch_size, c, n, device, random_state):
110
94
  rng = check_random_state(random_state)
111
95
  random_phase = torch.from_numpy(
112
96
  2j * np.pi * rng.random((batch_size, c, n // 2 - 1))
@@ -125,13 +109,7 @@ def _new_random_fft_phase_even(
125
109
  _new_random_fft_phase = {0: _new_random_fft_phase_even, 1: _new_random_fft_phase_odd}
126
110
 
127
111
 
128
- def ft_surrogate(
129
- X: torch.Tensor,
130
- y: torch.Tensor,
131
- phase_noise_magnitude: float,
132
- channel_indep: bool,
133
- random_state: int | np.random.RandomState | None = None,
134
- ) -> tuple[torch.Tensor, torch.Tensor]:
112
+ def ft_surrogate(X, y, phase_noise_magnitude, channel_indep, random_state=None):
135
113
  """FT surrogate augmentation of a single EEG channel, as proposed in [1]_.
136
114
 
137
115
  Function copied from https://github.com/cliffordlab/sleep-convolutions-tf
@@ -197,9 +175,7 @@ def ft_surrogate(
197
175
  return transformed_X, y
198
176
 
199
177
 
200
- def _pick_channels_randomly(
201
- X: torch.Tensor, p_pick: float, random_state: int | np.random.RandomState | None
202
- ) -> torch.Tensor:
178
+ def _pick_channels_randomly(X, p_pick, random_state):
203
179
  rng = check_random_state(random_state)
204
180
  batch_size, n_channels, _ = X.shape
205
181
  # allows to use the same RNG
@@ -212,12 +188,7 @@ def _pick_channels_randomly(
212
188
  return torch.sigmoid(1000 * (unif_samples - p_pick))
213
189
 
214
190
 
215
- def channels_dropout(
216
- X: torch.Tensor,
217
- y: torch.Tensor,
218
- p_drop: float,
219
- random_state: int | np.random.RandomState | None = None,
220
- ) -> tuple[torch.Tensor, torch.Tensor]:
191
+ def channels_dropout(X, y, p_drop, random_state=None):
221
192
  """Randomly set channels to flat signal.
222
193
 
223
194
  Part of the CMSAugment policy proposed in [1]_
@@ -251,9 +222,7 @@ def channels_dropout(
251
222
  return X * mask.unsqueeze(-1), y
252
223
 
253
224
 
254
- def _make_permutation_matrix(
255
- X: torch.Tensor, mask: torch.Tensor, random_state: int | np.random.Generator | None
256
- ) -> torch.Tensor:
225
+ def _make_permutation_matrix(X, mask, random_state):
257
226
  rng = check_random_state(random_state)
258
227
  batch_size, n_channels, _ = X.shape
259
228
  hard_mask = mask.round()
@@ -272,12 +241,7 @@ def _make_permutation_matrix(
272
241
  return batch_permutations
273
242
 
274
243
 
275
- def channels_shuffle(
276
- X: torch.Tensor,
277
- y: torch.Tensor,
278
- p_shuffle: float,
279
- random_state: int | np.random.RandomState | None = None,
280
- ) -> tuple[torch.Tensor, torch.Tensor]:
244
+ def channels_shuffle(X, y, p_shuffle, random_state=None):
281
245
  """Randomly shuffle channels in EEG data matrix.
282
246
 
283
247
  Part of the CMSAugment policy proposed in [1]_
@@ -316,12 +280,7 @@ def channels_shuffle(
316
280
  return torch.matmul(batch_permutations, X), y
317
281
 
318
282
 
319
- def gaussian_noise(
320
- X: torch.Tensor,
321
- y: torch.Tensor,
322
- std: float,
323
- random_state: int | np.random.RandomState | None = None,
324
- ) -> tuple[torch.Tensor, torch.Tensor]:
283
+ def gaussian_noise(X, y, std, random_state=None):
325
284
  """Randomly add white Gaussian noise to all channels.
326
285
 
327
286
  Suggested e.g. in [1]_, [2]_ and [3]_
@@ -373,9 +332,7 @@ def gaussian_noise(
373
332
  return transformed_X, y
374
333
 
375
334
 
376
- def channels_permute(
377
- X: torch.Tensor, y: torch.Tensor, permutation: list[int]
378
- ) -> tuple[torch.Tensor, torch.Tensor]:
335
+ def channels_permute(X, y, permutation):
379
336
  """Permute EEG channels according to fixed permutation matrix.
380
337
 
381
338
  Suggested e.g. in [1]_
@@ -405,12 +362,7 @@ def channels_permute(
405
362
  return X[..., permutation, :], y
406
363
 
407
364
 
408
- def smooth_time_mask(
409
- X: torch.Tensor,
410
- y: torch.Tensor,
411
- mask_start_per_sample: torch.Tensor,
412
- mask_len_samples: int,
413
- ) -> tuple[torch.Tensor, torch.Tensor]:
365
+ def smooth_time_mask(X, y, mask_start_per_sample, mask_len_samples):
414
366
  """Smoothly replace a contiguous part of all channels by zeros.
415
367
 
416
368
  Originally proposed in [1]_ and [2]_
@@ -460,13 +412,7 @@ def smooth_time_mask(
460
412
  return X * mask, y
461
413
 
462
414
 
463
- def bandstop_filter(
464
- X: torch.Tensor,
465
- y: torch.Tensor,
466
- sfreq: float,
467
- bandwidth: float,
468
- freqs_to_notch: npt.ArrayLike | None,
469
- ) -> tuple[torch.Tensor, torch.Tensor]:
415
+ def bandstop_filter(X, y, sfreq, bandwidth, freqs_to_notch):
470
416
  """Apply a band-stop filter with desired bandwidth at the desired frequency
471
417
  position.
472
418
 
@@ -505,7 +451,7 @@ def bandstop_filter(
505
451
  Representation Learning for Electroencephalogram Classification. In
506
452
  Machine Learning for Health (pp. 238-253). PMLR.
507
453
  """
508
- if bandwidth == 0 or freqs_to_notch is None:
454
+ if bandwidth == 0:
509
455
  return X, y
510
456
  transformed_X = X.clone()
511
457
  for c, (sample, notched_freq) in enumerate(zip(transformed_X, freqs_to_notch)):
@@ -523,7 +469,7 @@ def bandstop_filter(
523
469
  return transformed_X, y
524
470
 
525
471
 
526
- def _analytic_transform(x: torch.Tensor) -> torch.Tensor:
472
+ def _analytic_transform(x):
527
473
  if torch.is_complex(x):
528
474
  raise ValueError("x must be real.")
529
475
 
@@ -540,12 +486,12 @@ def _analytic_transform(x: torch.Tensor) -> torch.Tensor:
540
486
  return ifft(f * h, dim=-1)
541
487
 
542
488
 
543
- def _nextpow2(n: int) -> int:
489
+ def _nextpow2(n):
544
490
  """Return the first integer N such that 2**N >= abs(n)."""
545
491
  return int(np.ceil(np.log2(np.abs(n))))
546
492
 
547
493
 
548
- def _frequency_shift(X: torch.Tensor, fs: float, f_shift: float) -> torch.Tensor:
494
+ def _frequency_shift(X, fs, f_shift):
549
495
  """
550
496
  Shift the specified signal by the specified frequency.
551
497
 
@@ -558,13 +504,9 @@ def _frequency_shift(X: torch.Tensor, fs: float, f_shift: float) -> torch.Tensor
558
504
  t = torch.arange(N_padded, device=X.device) / fs
559
505
  padded = pad(X, (0, N_padded - N_orig))
560
506
  analytical = _analytic_transform(padded)
561
- if isinstance(f_shift, torch.Tensor):
562
- _f_shift = f_shift
563
- elif isinstance(f_shift, (float, int, np.ndarray, list)):
564
- _f_shift = torch.as_tensor(f_shift).float()
565
- else:
566
- raise ValueError(f"Invalid f_shift type: {type(f_shift)}")
567
- f_shift_stack = _f_shift.repeat(N_padded, n_channels, 1)
507
+ if isinstance(f_shift, (float, int, np.ndarray, list)):
508
+ f_shift = torch.as_tensor(f_shift).float()
509
+ f_shift_stack = f_shift.repeat(N_padded, n_channels, 1)
568
510
  reshaped_f_shift = f_shift_stack.permute(
569
511
  *torch.arange(f_shift_stack.ndim - 1, -1, -1)
570
512
  )
@@ -572,9 +514,7 @@ def _frequency_shift(X: torch.Tensor, fs: float, f_shift: float) -> torch.Tensor
572
514
  return shifted[..., :N_orig].real.float()
573
515
 
574
516
 
575
- def frequency_shift(
576
- X: torch.Tensor, y: torch.Tensor, delta_freq: float, sfreq: float
577
- ) -> tuple[torch.Tensor, torch.Tensor]:
517
+ def frequency_shift(X, y, delta_freq, sfreq):
578
518
  """Adds a shift in the frequency domain to all channels.
579
519
 
580
520
  Note that here, the shift is the same for all channels of a single example.
@@ -605,7 +545,7 @@ def frequency_shift(
605
545
  return transformed_X, y
606
546
 
607
547
 
608
- def _torch_normalize_vectors(rr: torch.Tensor) -> torch.Tensor:
548
+ def _torch_normalize_vectors(rr):
609
549
  """Normalize surface vertices."""
610
550
  norm = torch.linalg.norm(rr, axis=1, keepdim=True)
611
551
  mask = norm > 0
@@ -614,9 +554,7 @@ def _torch_normalize_vectors(rr: torch.Tensor) -> torch.Tensor:
614
554
  return new_rr
615
555
 
616
556
 
617
- def _torch_legval(
618
- x: torch.Tensor, c: torch.Tensor, tensor: bool = True
619
- ) -> torch.Tensor:
557
+ def _torch_legval(x, c, tensor=True):
620
558
  """
621
559
  Evaluate a Legendre series at points x.
622
560
  If `c` is of length `n + 1`, this function returns the value:
@@ -724,9 +662,7 @@ def _torch_legval(
724
662
  return c0 + c1 * x
725
663
 
726
664
 
727
- def _torch_calc_g(
728
- cosang: torch.Tensor, stiffness: float = 4, n_legendre_terms: int = 50
729
- ) -> torch.Tensor:
665
+ def _torch_calc_g(cosang, stiffness=4, n_legendre_terms=50):
730
666
  """Calculate spherical spline g function between points on a sphere.
731
667
 
732
668
  Parameters
@@ -782,25 +718,23 @@ def _torch_calc_g(
782
718
  return _torch_legval(cosang, [0] + factors)
783
719
 
784
720
 
785
- def _torch_make_interpolation_matrix(
786
- pos_from: torch.Tensor, pos_to: torch.Tensor, alpha: float = 1e-5
787
- ) -> torch.Tensor:
721
+ def _torch_make_interpolation_matrix(pos_from, pos_to, alpha=1e-5):
788
722
  """Compute interpolation matrix based on spherical splines.
789
723
 
790
724
  Implementation based on [1]_
791
725
 
792
726
  Parameters
793
727
  ----------
794
- pos_from : torch.Tensor of float, shape(n_good_sensors, 3)
728
+ pos_from : np.ndarray of float, shape(n_good_sensors, 3)
795
729
  The positions to interpolate from.
796
- pos_to : torch.Tensor of float, shape(n_bad_sensors, 3)
730
+ pos_to : np.ndarray of float, shape(n_bad_sensors, 3)
797
731
  The positions to interpolate.
798
732
  alpha : float
799
733
  Regularization parameter. Defaults to 1e-5.
800
734
 
801
735
  Returns
802
736
  -------
803
- interpolation : torch.Tensor of float, shape(len(pos_from), len(pos_to))
737
+ interpolation : np.ndarray of float, shape(len(pos_from), len(pos_to))
804
738
  The interpolation matrix that maps good signals to the location
805
739
  of bad signals.
806
740
 
@@ -888,12 +822,7 @@ def _torch_make_interpolation_matrix(
888
822
  return interpolation
889
823
 
890
824
 
891
- def _rotate_signals(
892
- X: torch.Tensor,
893
- rotations: list[torch.Tensor],
894
- sensors_positions_matrix: torch.Tensor,
895
- spherical: bool = True,
896
- ) -> torch.Tensor:
825
+ def _rotate_signals(X, rotations, sensors_positions_matrix, spherical=True):
897
826
  sensors_positions_matrix = sensors_positions_matrix.to(X.device)
898
827
  rot_sensors_matrices = [
899
828
  rotation.matmul(sensors_positions_matrix) for rotation in rotations
@@ -924,29 +853,22 @@ def _rotate_signals(
924
853
  return transformed_X
925
854
 
926
855
 
927
- def _make_rotation_matrix(
928
- axis: Literal["x", "y", "z"],
929
- angle: float | int | np.ndarray | list | torch.Tensor,
930
- degrees: bool = True,
931
- ) -> torch.Tensor:
856
+ def _make_rotation_matrix(axis, angle, degrees=True):
932
857
  assert axis in ["x", "y", "z"], "axis should be either x, y or z."
933
- if isinstance(angle, torch.Tensor):
934
- _angle = angle
935
- elif isinstance(angle, (float, int, np.ndarray, list)):
936
- _angle = torch.as_tensor(angle)
937
- else:
938
- raise ValueError(f"Invalid angle type: {type(angle)}")
858
+
859
+ if isinstance(angle, (float, int, np.ndarray, list)):
860
+ angle = torch.as_tensor(angle)
939
861
 
940
862
  if degrees:
941
- _angle = _angle * np.pi / 180
863
+ angle = angle * np.pi / 180
942
864
 
943
- device = _angle.device
865
+ device = angle.device
944
866
  zero = torch.zeros(1, device=device)
945
867
  rot = torch.stack(
946
868
  [
947
869
  torch.as_tensor([1, 0, 0], device=device),
948
- torch.hstack([zero, torch.cos(_angle), -torch.sin(_angle)]),
949
- torch.hstack([zero, torch.sin(_angle), torch.cos(_angle)]),
870
+ torch.hstack([zero, torch.cos(angle), -torch.sin(angle)]),
871
+ torch.hstack([zero, torch.sin(angle), torch.cos(angle)]),
950
872
  ]
951
873
  )
952
874
  if axis == "x":
@@ -959,14 +881,7 @@ def _make_rotation_matrix(
959
881
  return rot[:, [1, 2, 0]]
960
882
 
961
883
 
962
- def sensors_rotation(
963
- X: torch.Tensor,
964
- y: torch.Tensor,
965
- sensors_positions_matrix: torch.Tensor,
966
- axis: Literal["x", "y", "z"],
967
- angles: npt.ArrayLike,
968
- spherical_splines: bool,
969
- ) -> tuple[torch.Tensor, torch.Tensor]:
884
+ def sensors_rotation(X, y, sensors_positions_matrix, axis, angles, spherical_splines):
970
885
  """Interpolates EEG signals over sensors rotated around the desired axis
971
886
  with the desired angle.
972
887
 
@@ -978,7 +893,7 @@ def sensors_rotation(
978
893
  EEG input example or batch.
979
894
  y : torch.Tensor
980
895
  EEG labels for the example or batch.
981
- sensors_positions_matrix : torch.Tensor
896
+ sensors_positions_matrix : numpy.ndarray
982
897
  Matrix giving the positions of each sensor in a 3D cartesian coordinate
983
898
  system. Should have shape (3, n_channels), where n_channels is the
984
899
  number of channels. Standard 10-20 positions can be obtained from
@@ -1009,9 +924,7 @@ def sensors_rotation(
1009
924
  return rotated_X, y
1010
925
 
1011
926
 
1012
- def mixup(
1013
- X: torch.Tensor, y: torch.Tensor, lam: torch.Tensor, idx_perm: torch.Tensor
1014
- ) -> tuple[torch.Tensor, torch.Tensor]:
927
+ def mixup(X, y, lam, idx_perm):
1015
928
  """Mixes two channels of EEG data.
1016
929
 
1017
930
  See [1]_ for details.
@@ -1060,13 +973,8 @@ def mixup(
1060
973
 
1061
974
 
1062
975
  def segmentation_reconstruction(
1063
- X: torch.Tensor,
1064
- y: torch.Tensor,
1065
- n_segments: int,
1066
- data_classes: list[tuple[int, torch.Tensor]],
1067
- rand_indices: npt.ArrayLike,
1068
- idx_shuffle: npt.ArrayLike,
1069
- ) -> tuple[torch.Tensor, torch.Tensor]:
976
+ X, y, n_segments, data_classes, rand_indices, idx_shuffle
977
+ ):
1070
978
  """Segment and reconstruct EEG data from [1]_.
1071
979
 
1072
980
  See [1]_ for details.
@@ -1079,8 +987,6 @@ def segmentation_reconstruction(
1079
987
  EEG labels for the example or batch.
1080
988
  n_segments : int
1081
989
  Number of segments to use in the batch.
1082
- data_classes: list[tuple[int, torch.Tensor]]
1083
- List of tuples. Each tuple contains the class index and the corresponding EEG data.
1084
990
  rand_indices: array-like
1085
991
  Array of indices that indicates which trial to use in each segment.
1086
992
  idx_shuffle: array-like
@@ -1099,8 +1005,8 @@ def segmentation_reconstruction(
1099
1005
  """
1100
1006
 
1101
1007
  # Initialize lists to store augmented data and corresponding labels
1102
- aug_data: list[torch.Tensor] = []
1103
- aug_label: list[torch.Tensor] = []
1008
+ aug_data = []
1009
+ aug_label = []
1104
1010
 
1105
1011
  # Iterate through each class to separate and augment data
1106
1012
  for class_index, X_class in data_classes:
@@ -1124,26 +1030,20 @@ def segmentation_reconstruction(
1124
1030
  aug_data.append(X_aug)
1125
1031
  aug_label.append(torch.full((n_trials,), class_index))
1126
1032
  # Concatenate the augmented data and labels
1127
- concat_aug_data = torch.cat(aug_data, dim=0)
1128
- concat_aug_data = concat_aug_data.to(dtype=X.dtype, device=X.device)
1129
- concat_aug_data = concat_aug_data[idx_shuffle]
1033
+ aug_data = torch.cat(aug_data, dim=0)
1034
+ aug_data = aug_data.to(dtype=X.dtype, device=X.device)
1035
+ aug_data = aug_data[idx_shuffle]
1130
1036
 
1131
1037
  if y is not None:
1132
- concat_label = torch.cat(aug_label, dim=0)
1133
- concat_label = concat_label.to(dtype=y.dtype, device=y.device)
1134
- concat_label = concat_label[idx_shuffle]
1135
- return concat_aug_data, concat_label
1038
+ aug_label = torch.cat(aug_label, dim=0)
1039
+ aug_label = aug_label.to(dtype=y.dtype, device=y.device)
1040
+ aug_label = aug_label[idx_shuffle]
1041
+ return aug_data, aug_label
1136
1042
 
1137
- return concat_aug_data, None
1043
+ return aug_data, y
1138
1044
 
1139
1045
 
1140
- def mask_encoding(
1141
- X: torch.Tensor,
1142
- y: torch.Tensor,
1143
- time_start: torch.Tensor,
1144
- segment_length: int,
1145
- n_segments: int,
1146
- ) -> tuple[torch.Tensor, torch.Tensor]:
1046
+ def mask_encoding(X, y, time_start, segment_length, n_segments):
1147
1047
  """Mark encoding from Ding et al. (2024) from [ding2024]_.
1148
1048
 
1149
1049
  Replaces a contiguous part (or parts) of all channels by zeros
@@ -161,10 +161,10 @@ class ChannelsDropout(Transform):
161
161
  ----------
162
162
  probability: float
163
163
  Float setting the probability of applying the operation.
164
- p_drop: float | None, optional
164
+ proba_drop: float | None, optional
165
165
  Float between 0 and 1 setting the probability of dropping each channel.
166
166
  Defaults to 0.2.
167
- random_state: int | numpy.random.RandomState, optional
167
+ random_state: int | numpy.random.Generator, optional
168
168
  Seed to be used to instantiate numpy random number generator instance.
169
169
  Used to decide whether or not to transform given the probability
170
170
  argument and to sample channels to erase. Defaults to None.
@@ -815,7 +815,7 @@ class BaseConcatDataset(ConcatDataset):
815
815
  @staticmethod
816
816
  def _save_description(sub_dir, description):
817
817
  description_file_path = os.path.join(sub_dir, "description.json")
818
- description.to_json(description_file_path, default_handler=str)
818
+ description.to_json(description_file_path)
819
819
 
820
820
  @staticmethod
821
821
  def _save_kwargs(sub_dir, ds):
@@ -22,6 +22,7 @@ from mne.datasets.utils import _get_path
22
22
  from mne.utils import warn
23
23
 
24
24
  from braindecode.datasets import BaseConcatDataset, BaseDataset
25
+ from braindecode.preprocessing.preprocess import _preprocess
25
26
 
26
27
  PC18_DIR = op.join(op.dirname(__file__), "data", "pc18")
27
28
  PC18_RECORDS = op.join(PC18_DIR, "sleep_records.csv")
@@ -406,8 +407,6 @@ class SleepPhysionetChallenge2018(BaseConcatDataset):
406
407
  base_dataset = BaseDataset(raw_file, desc)
407
408
 
408
409
  if preproc is not None:
409
- from braindecode.preprocessing.preprocess import _preprocess
410
-
411
410
  _preprocess(base_dataset, None, preproc)
412
411
 
413
412
  return base_dataset
@@ -138,17 +138,12 @@ def _load_signals(fif_file, preload, is_raw):
138
138
  with open(pkl_file, "rb") as f:
139
139
  signals = pickle.load(f)
140
140
 
141
- if all(f.exists() for f in signals.filenames):
142
- if preload:
143
- signals.load_data()
144
- return signals
145
- else: # This may happen if the file has been moved together with the pickle file.
146
- warnings.warn(
147
- f"Pickle file {pkl_file} exists, but the referenced fif "
148
- "file(s) do not exist. Will read the fif file(s) directly "
149
- "and re-create the pickle file.",
150
- UserWarning,
151
- )
141
+ # If the file has been moved together with the pickle file, make sure
142
+ # the path links to correct fif file.
143
+ signals._fname = str(fif_file)
144
+ if preload:
145
+ signals.load_data()
146
+ return signals
152
147
 
153
148
  # If pickle didn't exist read via mne (likely slower) and save pkl after
154
149
  if is_raw:
@@ -189,8 +189,6 @@ class _EEGNeuralNet(NeuralNet, abc.ABC):
189
189
  "Skipping setting signal-related parameters from data."
190
190
  )
191
191
  return
192
- if classes is None:
193
- classes = getattr(self, "classes", None)
194
192
  # get kwargs from signal:
195
193
  signal_kwargs = dict()
196
194
  # Using shape to work both with torch.tensor and numpy.array:
@@ -6,7 +6,6 @@ from .atcnet import ATCNet
6
6
  from .attentionbasenet import AttentionBaseNet
7
7
  from .attn_sleep import AttnSleep
8
8
  from .base import EEGModuleMixin
9
- from .bendr import BENDR
10
9
  from .biot import BIOT
11
10
  from .contrawr import ContraWR
12
11
  from .ctnet import CTNet
@@ -28,7 +27,6 @@ from .hybrid import HybridNet
28
27
  from .ifnet import IFNet
29
28
  from .labram import Labram
30
29
  from .msvtnet import MSVTNet
31
- from .patchedtransformer import PBT
32
30
  from .sccnet import SCCNet
33
31
  from .shallow_fbcsp import ShallowFBCSPNet
34
32
  from .signal_jepa import (
@@ -41,7 +39,6 @@ from .sinc_shallow import SincShallowNet
41
39
  from .sleep_stager_blanco_2020 import SleepStagerBlanco2020
42
40
  from .sleep_stager_chambon_2018 import SleepStagerChambon2018
43
41
  from .sparcnet import SPARCNet
44
- from .sstdpn import SSTDPN
45
42
  from .syncnet import SyncNet
46
43
  from .tcn import BDTCN, TCN
47
44
  from .tidnet import TIDNet
@@ -59,7 +56,6 @@ __all__ = [
59
56
  "AttentionBaseNet",
60
57
  "EEGModuleMixin",
61
58
  "BIOT",
62
- "BENDR",
63
59
  "ContraWR",
64
60
  "CTNet",
65
61
  "Deep4Net",
@@ -81,7 +77,6 @@ __all__ = [
81
77
  "IFNet",
82
78
  "Labram",
83
79
  "MSVTNet",
84
- "PBT",
85
80
  "SCCNet",
86
81
  "ShallowFBCSPNet",
87
82
  "SignalJEPA",
@@ -89,7 +84,6 @@ __all__ = [
89
84
  "SignalJEPA_PostLocal",
90
85
  "SignalJEPA_PreLocal",
91
86
  "SincShallowNet",
92
- "SSTDPN",
93
87
  "SleepStagerBlanco2020",
94
88
  "SleepStagerChambon2018",
95
89
  "SPARCNet",
@@ -408,7 +408,7 @@ class ATCNet(EEGModuleMixin, nn.Module):
408
408
 
409
409
  self.out_fun = nn.Identity()
410
410
 
411
- def forward(self, X: torch.Tensor) -> torch.Tensor:
411
+ def forward(self, X):
412
412
  # Dimension: (batch_size, C, T)
413
413
  X = self.ensuredims(X)
414
414
  # Dimension: (batch_size, C, T, 1)
@@ -381,8 +381,6 @@ class AttentionBaseNet(EEGModuleMixin, nn.Module):
381
381
  for k, pl, ps in zip(kernel_lengths, pool_lengths, pool_strides):
382
382
  out = math.floor(out + 2 * (k // 2) - k + 1)
383
383
  out = math.floor((out - pl) / ps + 1)
384
- # Ensure output is at least 1 to avoid zero-sized tensors
385
- out = max(1, out)
386
384
  seq_lengths.append(int(out))
387
385
  return seq_lengths
388
386