braindecode 1.3.0.dev177069446__py3-none-any.whl

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 (124) hide show
  1. braindecode/__init__.py +9 -0
  2. braindecode/augmentation/__init__.py +52 -0
  3. braindecode/augmentation/base.py +225 -0
  4. braindecode/augmentation/functional.py +1300 -0
  5. braindecode/augmentation/transforms.py +1356 -0
  6. braindecode/classifier.py +258 -0
  7. braindecode/datasets/__init__.py +44 -0
  8. braindecode/datasets/base.py +823 -0
  9. braindecode/datasets/bbci.py +693 -0
  10. braindecode/datasets/bcicomp.py +193 -0
  11. braindecode/datasets/bids/__init__.py +54 -0
  12. braindecode/datasets/bids/datasets.py +239 -0
  13. braindecode/datasets/bids/format.py +717 -0
  14. braindecode/datasets/bids/hub.py +987 -0
  15. braindecode/datasets/bids/hub_format.py +717 -0
  16. braindecode/datasets/bids/hub_io.py +197 -0
  17. braindecode/datasets/bids/hub_validation.py +114 -0
  18. braindecode/datasets/bids/iterable.py +220 -0
  19. braindecode/datasets/chb_mit.py +163 -0
  20. braindecode/datasets/mne.py +170 -0
  21. braindecode/datasets/moabb.py +219 -0
  22. braindecode/datasets/nmt.py +313 -0
  23. braindecode/datasets/registry.py +120 -0
  24. braindecode/datasets/siena.py +162 -0
  25. braindecode/datasets/sleep_physio_challe_18.py +411 -0
  26. braindecode/datasets/sleep_physionet.py +125 -0
  27. braindecode/datasets/tuh.py +591 -0
  28. braindecode/datasets/utils.py +67 -0
  29. braindecode/datasets/xy.py +96 -0
  30. braindecode/datautil/__init__.py +62 -0
  31. braindecode/datautil/channel_utils.py +114 -0
  32. braindecode/datautil/hub_formats.py +180 -0
  33. braindecode/datautil/serialization.py +359 -0
  34. braindecode/datautil/util.py +154 -0
  35. braindecode/eegneuralnet.py +372 -0
  36. braindecode/functional/__init__.py +22 -0
  37. braindecode/functional/functions.py +251 -0
  38. braindecode/functional/initialization.py +47 -0
  39. braindecode/models/__init__.py +117 -0
  40. braindecode/models/atcnet.py +830 -0
  41. braindecode/models/attentionbasenet.py +727 -0
  42. braindecode/models/attn_sleep.py +549 -0
  43. braindecode/models/base.py +574 -0
  44. braindecode/models/bendr.py +493 -0
  45. braindecode/models/biot.py +537 -0
  46. braindecode/models/brainmodule.py +845 -0
  47. braindecode/models/config.py +233 -0
  48. braindecode/models/contrawr.py +319 -0
  49. braindecode/models/ctnet.py +541 -0
  50. braindecode/models/deep4.py +376 -0
  51. braindecode/models/deepsleepnet.py +417 -0
  52. braindecode/models/eegconformer.py +475 -0
  53. braindecode/models/eeginception_erp.py +379 -0
  54. braindecode/models/eeginception_mi.py +379 -0
  55. braindecode/models/eegitnet.py +302 -0
  56. braindecode/models/eegminer.py +256 -0
  57. braindecode/models/eegnet.py +359 -0
  58. braindecode/models/eegnex.py +354 -0
  59. braindecode/models/eegsimpleconv.py +201 -0
  60. braindecode/models/eegsym.py +917 -0
  61. braindecode/models/eegtcnet.py +337 -0
  62. braindecode/models/fbcnet.py +225 -0
  63. braindecode/models/fblightconvnet.py +315 -0
  64. braindecode/models/fbmsnet.py +338 -0
  65. braindecode/models/hybrid.py +126 -0
  66. braindecode/models/ifnet.py +443 -0
  67. braindecode/models/labram.py +1316 -0
  68. braindecode/models/luna.py +891 -0
  69. braindecode/models/medformer.py +760 -0
  70. braindecode/models/msvtnet.py +377 -0
  71. braindecode/models/patchedtransformer.py +640 -0
  72. braindecode/models/reve.py +843 -0
  73. braindecode/models/sccnet.py +280 -0
  74. braindecode/models/shallow_fbcsp.py +212 -0
  75. braindecode/models/signal_jepa.py +1122 -0
  76. braindecode/models/sinc_shallow.py +339 -0
  77. braindecode/models/sleep_stager_blanco_2020.py +169 -0
  78. braindecode/models/sleep_stager_chambon_2018.py +159 -0
  79. braindecode/models/sparcnet.py +426 -0
  80. braindecode/models/sstdpn.py +869 -0
  81. braindecode/models/summary.csv +47 -0
  82. braindecode/models/syncnet.py +234 -0
  83. braindecode/models/tcn.py +275 -0
  84. braindecode/models/tidnet.py +397 -0
  85. braindecode/models/tsinception.py +295 -0
  86. braindecode/models/usleep.py +439 -0
  87. braindecode/models/util.py +369 -0
  88. braindecode/modules/__init__.py +92 -0
  89. braindecode/modules/activation.py +86 -0
  90. braindecode/modules/attention.py +883 -0
  91. braindecode/modules/blocks.py +160 -0
  92. braindecode/modules/convolution.py +330 -0
  93. braindecode/modules/filter.py +654 -0
  94. braindecode/modules/layers.py +216 -0
  95. braindecode/modules/linear.py +70 -0
  96. braindecode/modules/parametrization.py +38 -0
  97. braindecode/modules/stats.py +87 -0
  98. braindecode/modules/util.py +85 -0
  99. braindecode/modules/wrapper.py +90 -0
  100. braindecode/preprocessing/__init__.py +271 -0
  101. braindecode/preprocessing/eegprep_preprocess.py +1317 -0
  102. braindecode/preprocessing/mne_preprocess.py +240 -0
  103. braindecode/preprocessing/preprocess.py +579 -0
  104. braindecode/preprocessing/util.py +177 -0
  105. braindecode/preprocessing/windowers.py +1037 -0
  106. braindecode/regressor.py +234 -0
  107. braindecode/samplers/__init__.py +18 -0
  108. braindecode/samplers/base.py +399 -0
  109. braindecode/samplers/ssl.py +263 -0
  110. braindecode/training/__init__.py +23 -0
  111. braindecode/training/callbacks.py +23 -0
  112. braindecode/training/losses.py +105 -0
  113. braindecode/training/scoring.py +477 -0
  114. braindecode/util.py +419 -0
  115. braindecode/version.py +1 -0
  116. braindecode/visualization/__init__.py +8 -0
  117. braindecode/visualization/confusion_matrices.py +289 -0
  118. braindecode/visualization/gradients.py +62 -0
  119. braindecode-1.3.0.dev177069446.dist-info/METADATA +230 -0
  120. braindecode-1.3.0.dev177069446.dist-info/RECORD +124 -0
  121. braindecode-1.3.0.dev177069446.dist-info/WHEEL +5 -0
  122. braindecode-1.3.0.dev177069446.dist-info/licenses/LICENSE.txt +31 -0
  123. braindecode-1.3.0.dev177069446.dist-info/licenses/NOTICE.txt +20 -0
  124. braindecode-1.3.0.dev177069446.dist-info/top_level.txt +1 -0
@@ -0,0 +1,193 @@
1
+ # Authors: Maciej Sliwowski <maciek.sliwowski@gmail.com>
2
+ # Mohammed Fattouh <mo.fattouh@gmail.com>
3
+ #
4
+ # License: BSD (3-clause)
5
+
6
+ from __future__ import annotations
7
+
8
+ import glob
9
+ import os
10
+ import os.path as osp
11
+ from os import remove
12
+ from shutil import unpack_archive
13
+
14
+ import mne
15
+ import numpy as np
16
+ from mne.utils import verbose
17
+ from scipy.io import loadmat
18
+
19
+ from braindecode.datasets import BaseConcatDataset, RawDataset
20
+
21
+ DATASET_URL = (
22
+ "https://stacks.stanford.edu/file/druid:zk881ps0522/"
23
+ "BCI_Competion4_dataset4_data_fingerflexions.zip"
24
+ )
25
+
26
+
27
+ class BCICompetitionIVDataset4(BaseConcatDataset):
28
+ """BCI competition IV dataset 4.
29
+
30
+ Contains ECoG recordings for three patients moving fingers during the experiment.
31
+ Targets correspond to the time courses of the flexion of each of five fingers.
32
+ See http://www.bbci.de/competition/iv/desc_4.pdf and
33
+ http://www.bbci.de/competition/iv/ for the dataset and competition description.
34
+ ECoG library containing the dataset: https://searchworks.stanford.edu/view/zk881ps0522
35
+
36
+ Parameters
37
+ ----------
38
+ subject_ids : list(int) | int | None
39
+ (list of) int of subject(s) to be loaded. If None, load all available
40
+ subjects. Should be in range 1-3.
41
+
42
+ Notes
43
+ -----
44
+ When using this dataset please cite [1]_ .
45
+
46
+ References
47
+ ----------
48
+ .. [1] Miller, Kai J. "A library of human electrocorticographic data and analyses."
49
+ Nature human behaviour 3, no. 11 (2019): 1225-1235.
50
+ https://doi.org/10.1038/s41562-019-0678-3
51
+ """
52
+
53
+ possible_subjects = [1, 2, 3]
54
+
55
+ def __init__(self, subject_ids: list[int] | int | None = None):
56
+ data_path = self.download()
57
+ if isinstance(subject_ids, int):
58
+ subject_ids = [subject_ids]
59
+ if subject_ids is None:
60
+ subject_ids = self.possible_subjects
61
+ self._validate_subjects(subject_ids)
62
+ files_list = [f"{data_path}/sub{i}_comp.mat" for i in subject_ids]
63
+ datasets = []
64
+ for file_path in files_list:
65
+ raw_train, raw_test = self._load_data_to_mne(file_path)
66
+ desc_train = dict(
67
+ subject=file_path.split("/")[-1].split("sub")[1][0],
68
+ file_name=file_path.split("/")[-1],
69
+ session="train",
70
+ )
71
+ desc_test = dict(
72
+ subject=file_path.split("/")[-1].split("sub")[1][0],
73
+ file_name=file_path.split("/")[-1],
74
+ session="test",
75
+ )
76
+ datasets.append(RawDataset(raw_train, description=desc_train))
77
+ datasets.append(RawDataset(raw_test, description=desc_test))
78
+ super().__init__(datasets)
79
+
80
+ @staticmethod
81
+ def download(path=None, force_update=False, verbose=None):
82
+ """Download the dataset.
83
+
84
+ Parameters
85
+ ----------
86
+ path (None | str) – Location of where to look for the data storing location.
87
+ If None, the environment variable or config parameter
88
+ MNE_DATASETS_(dataset)_PATH is used. If it doesn't exist, the “~/mne_data”
89
+ directory is used. If the dataset is not found under the given path, the data
90
+ will be automatically downloaded to the specified folder.
91
+ force_update (bool) – Force update of the dataset even if a local copy exists.
92
+ verbose (bool, str, int, or None) – If not None, override default verbose level
93
+ (see mne.verbose())
94
+
95
+ Returns
96
+ -------
97
+ """
98
+ signature = "BCICompetitionIVDataset4"
99
+ folder_name = "BCI_Competion4_dataset4_data_fingerflexions"
100
+ # Check if the dataset already exists (unpacked). We have to do that manually
101
+ # because we are removing .zip file from disk to save disk space.
102
+
103
+ from moabb.datasets.download import get_dataset_path # keep soft dependency
104
+
105
+ path = get_dataset_path(signature, path)
106
+ key_dest = "MNE-{:s}-data".format(signature.lower())
107
+ # We do not use mne _url_to_local_path due to ':' in the url that causes problems on Windows
108
+ destination = osp.join(path, key_dest, folder_name)
109
+ if len(list(glob.glob(osp.join(destination, "*.mat")))) == 6:
110
+ return destination
111
+ data_path = _data_dl(
112
+ DATASET_URL,
113
+ osp.join(destination, folder_name, signature),
114
+ force_update=force_update,
115
+ )
116
+ unpack_archive(data_path, osp.dirname(destination))
117
+ # removes .zip file that the data was unpacked from
118
+ remove(data_path)
119
+ return destination
120
+
121
+ @staticmethod
122
+ def _prepare_targets(upsampled_targets, targets_stride):
123
+ original_targets = np.full_like(upsampled_targets, np.nan)
124
+ original_targets[::targets_stride] = upsampled_targets[::targets_stride]
125
+ return original_targets
126
+
127
+ def _load_data_to_mne(self, file_path):
128
+ data = loadmat(file_path)
129
+ test_labels = loadmat(file_path.replace("comp.mat", "testlabels.mat"))
130
+ train_data = data["train_data"]
131
+ test_data = data["test_data"]
132
+ upsampled_train_targets = data["train_dg"]
133
+ upsampled_test_targets = test_labels["test_dg"]
134
+
135
+ signal_sfreq = 1000
136
+ original_target_sfreq = 25
137
+ targets_stride = int(signal_sfreq / original_target_sfreq)
138
+
139
+ original_targets = self._prepare_targets(
140
+ upsampled_train_targets, targets_stride
141
+ )
142
+ original_test_targets = self._prepare_targets(
143
+ upsampled_test_targets, targets_stride
144
+ )
145
+
146
+ ch_names = [f"{i}" for i in range(train_data.shape[1])]
147
+ ch_names += [f"target_{i}" for i in range(original_targets.shape[1])]
148
+ ch_types = ["ecog" for _ in range(train_data.shape[1])]
149
+ ch_types += ["misc" for _ in range(original_targets.shape[1])]
150
+
151
+ info = mne.create_info(sfreq=signal_sfreq, ch_names=ch_names, ch_types=ch_types)
152
+ info["temp"] = dict(target_sfreq=original_target_sfreq)
153
+ train_data = np.concatenate([train_data, original_targets], axis=1)
154
+ test_data = np.concatenate([test_data, original_test_targets], axis=1)
155
+
156
+ raw_train = mne.io.RawArray(train_data.T, info=info)
157
+ raw_test = mne.io.RawArray(test_data.T, info=info)
158
+ # TODO: show how to resample targets
159
+ return raw_train, raw_test
160
+
161
+ def _validate_subjects(self, subject_ids):
162
+ if isinstance(subject_ids, (list, tuple)):
163
+ if not all((subject in self.possible_subjects for subject in subject_ids)):
164
+ raise ValueError(
165
+ f"Wrong subject_ids parameter. Possible values: {self.possible_subjects}. "
166
+ f"Provided {subject_ids}."
167
+ )
168
+ else:
169
+ raise ValueError(
170
+ "Wrong subject_ids format. Expected types: None, list, tuple, int."
171
+ )
172
+
173
+
174
+ @verbose
175
+ def _data_dl(url, destination, force_update=False, verbose=None):
176
+ # Code taken from moabb due to problem with ':' occurring in path
177
+ # On Windows ':' is a forbidden in folder name
178
+ # moabb/datasets/download.py
179
+
180
+ from pooch import file_hash, retrieve # keep soft dependency
181
+
182
+ if not osp.isfile(destination) or force_update:
183
+ if osp.isfile(destination):
184
+ os.remove(destination)
185
+ if not osp.isdir(osp.dirname(destination)):
186
+ os.makedirs(osp.dirname(destination))
187
+ known_hash = None
188
+ else:
189
+ known_hash = file_hash(destination)
190
+ data_path = retrieve(
191
+ url, known_hash, fname=osp.basename(url), path=osp.dirname(destination)
192
+ )
193
+ return data_path
@@ -0,0 +1,54 @@
1
+ # mypy: ignore-errors
2
+ """
3
+ BIDS (Brain Imaging Data Structure) integration for braindecode.
4
+
5
+ This subpackage provides:
6
+ - BIDS dataset loading (BIDSDataset, BIDSEpochsDataset)
7
+ - BIDS-like format utilities for Hub integration
8
+ - Hugging Face Hub push/pull functionality
9
+ - Validation utilities for Hub operations
10
+
11
+ More information on BIDS can be found at https://bids.neuroimaging.io
12
+ """
13
+
14
+ # Authors: Bruno Aristimunha <b.aristimunha@gmail.com>
15
+ # Pierre Guetschel <pierre.guetschel@gmail.com>
16
+ # Kuntal Kokate
17
+ #
18
+ # License: BSD (3-clause)
19
+
20
+ from typing import TYPE_CHECKING
21
+
22
+ # Only import hub at init level (needed by base.py)
23
+ # Other imports are deferred to avoid circular imports
24
+ from .hub import HubDatasetMixin
25
+
26
+ # For static type checkers (mypy), provide explicit imports
27
+ if TYPE_CHECKING:
28
+ from .datasets import BIDSDataset, BIDSEpochsDataset
29
+ from .iterable import BIDSIterableDataset
30
+
31
+
32
+ def __getattr__(name: str):
33
+ """Lazy imports to avoid circular dependencies."""
34
+ if name in ("BIDSDataset", "BIDSEpochsDataset"):
35
+ from .datasets import BIDSDataset, BIDSEpochsDataset
36
+
37
+ return {"BIDSDataset": BIDSDataset, "BIDSEpochsDataset": BIDSEpochsDataset}[
38
+ name
39
+ ]
40
+ elif name == "BIDSIterableDataset":
41
+ from .iterable import BIDSIterableDataset
42
+
43
+ return BIDSIterableDataset
44
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
45
+
46
+
47
+ __all__ = [
48
+ # Dataset classes
49
+ "BIDSDataset",
50
+ "BIDSEpochsDataset",
51
+ "BIDSIterableDataset",
52
+ # Hub integration
53
+ "HubDatasetMixin",
54
+ ]
@@ -0,0 +1,239 @@
1
+ # mypy: ignore-errors
2
+ """Dataset for loading BIDS.
3
+
4
+ More information on BIDS (Brain Imaging Data Structure) can be found at https://bids.neuroimaging.io
5
+ """
6
+
7
+ # Authors: Pierre Guetschel <pierre.guetschel@gmail.com>
8
+ #
9
+ # License: BSD (3-clause)
10
+
11
+ from __future__ import annotations
12
+
13
+ from dataclasses import dataclass, field
14
+ from pathlib import Path
15
+ from typing import Any
16
+
17
+ import mne
18
+ import mne_bids
19
+ import numpy as np
20
+ import pandas as pd
21
+ from joblib import Parallel, delayed
22
+
23
+ from ..base import BaseConcatDataset, RawDataset, WindowsDataset
24
+
25
+
26
+ def _description_from_bids_path(bids_path: mne_bids.BIDSPath) -> dict[str, Any]:
27
+ description = {"path": bids_path.fpath, **bids_path.entities}
28
+ description.update(
29
+ {
30
+ "suffix": bids_path.suffix,
31
+ "extension": bids_path.extension,
32
+ "datatype": bids_path.datatype,
33
+ }
34
+ )
35
+ return description
36
+
37
+
38
+ @dataclass
39
+ class BIDSDataset(BaseConcatDataset):
40
+ """Dataset for loading BIDS.
41
+
42
+ This class has the same parameters as the :func:`mne_bids.find_matching_paths` function
43
+ as it will be used to find the files to load. The default ``extensions`` parameter was changed.
44
+
45
+ More information on BIDS (Brain Imaging Data Structure)
46
+ can be found at https://bids.neuroimaging.io
47
+
48
+ .. Note::
49
+ For loading "unofficial" BIDS datasets containing epoched data,
50
+ you can use :class:`BIDSEpochsDataset`.
51
+
52
+ Parameters
53
+ ----------
54
+ root : pathlib.Path | str
55
+ The root of the BIDS path.
56
+ subjects : str | array-like of str | None
57
+ The subject ID. Corresponds to "sub".
58
+ sessions : str | array-like of str | None
59
+ The acquisition session. Corresponds to "ses".
60
+ tasks : str | array-like of str | None
61
+ The experimental task. Corresponds to "task".
62
+ acquisitions : str | array-like of str | None
63
+ The acquisition parameters. Corresponds to "acq".
64
+ runs : str | array-like of str | None
65
+ The run number. Corresponds to "run".
66
+ processings : str | array-like of str | None
67
+ The processing label. Corresponds to "proc".
68
+ recordings : str | array-like of str | None
69
+ The recording name. Corresponds to "rec".
70
+ spaces : str | array-like of str | None
71
+ The coordinate space for anatomical and sensor location
72
+ files (e.g., ``*_electrodes.tsv``, ``*_markers.mrk``).
73
+ Corresponds to "space".
74
+ Note that valid values for ``space`` must come from a list
75
+ of BIDS keywords as described in the BIDS specification.
76
+ splits : str | array-like of str | None
77
+ The split of the continuous recording file for ``.fif`` data.
78
+ Corresponds to "split".
79
+ descriptions : str | array-like of str | None
80
+ This corresponds to the BIDS entity ``desc``. It is used to provide
81
+ additional information for derivative data, e.g., preprocessed data
82
+ may be assigned ``description='cleaned'``.
83
+ suffixes : str | array-like of str | None
84
+ The filename suffix. This is the entity after the
85
+ last ``_`` before the extension. E.g., ``'channels'``.
86
+ The following filename suffix's are accepted:
87
+ 'meg', 'markers', 'eeg', 'ieeg', 'T1w',
88
+ 'participants', 'scans', 'electrodes', 'coordsystem',
89
+ 'channels', 'events', 'headshape', 'digitizer',
90
+ 'beh', 'physio', 'stim'
91
+ extensions : str | array-like of str | None
92
+ The extension of the filename. E.g., ``'.json'``.
93
+ By default, uses the ones accepted by :func:`mne_bids.read_raw_bids`.
94
+ datatypes : str | array-like of str | None
95
+ The BIDS data type, e.g., ``'anat'``, ``'func'``, ``'eeg'``, ``'meg'``,
96
+ ``'ieeg'``.
97
+ check : bool
98
+ If ``True``, only returns paths that conform to BIDS. If ``False``
99
+ (default), the ``.check`` attribute of the returned
100
+ :class:`mne_bids.BIDSPath` object will be set to ``True`` for paths that
101
+ do conform to BIDS, and to ``False`` for those that don't.
102
+ preload : bool
103
+ If True, preload the data. Defaults to False.
104
+ n_jobs : int
105
+ Number of jobs to run in parallel. Defaults to 1.
106
+ """
107
+
108
+ root: Path | str
109
+ subjects: str | list[str] | None = None
110
+ sessions: str | list[str] | None = None
111
+ tasks: str | list[str] | None = None
112
+ acquisitions: str | list[str] | None = None
113
+ runs: str | list[str] | None = None
114
+ processings: str | list[str] | None = None
115
+ recordings: str | list[str] | None = None
116
+ spaces: str | list[str] | None = None
117
+ splits: str | list[str] | None = None
118
+ descriptions: str | list[str] | None = None
119
+ suffixes: str | list[str] | None = None
120
+ extensions: str | list[str] | None = field(
121
+ default_factory=lambda: [
122
+ ".con",
123
+ ".sqd",
124
+ ".pdf",
125
+ ".fif",
126
+ ".ds",
127
+ ".vhdr",
128
+ ".set",
129
+ ".edf",
130
+ ".bdf",
131
+ ".EDF",
132
+ ".snirf",
133
+ ".cdt",
134
+ ".mef",
135
+ ".nwb",
136
+ ]
137
+ )
138
+ datatypes: str | list[str] | None = None
139
+ check: bool = False
140
+ preload: bool = False
141
+ n_jobs: int = 1
142
+
143
+ @property
144
+ def _filter_out_epochs(self):
145
+ return True
146
+
147
+ def __post_init__(self):
148
+ bids_paths = mne_bids.find_matching_paths(
149
+ root=self.root,
150
+ subjects=self.subjects,
151
+ sessions=self.sessions,
152
+ tasks=self.tasks,
153
+ acquisitions=self.acquisitions,
154
+ runs=self.runs,
155
+ processings=self.processings,
156
+ recordings=self.recordings,
157
+ spaces=self.spaces,
158
+ splits=self.splits,
159
+ descriptions=self.descriptions,
160
+ suffixes=self.suffixes,
161
+ extensions=self.extensions,
162
+ datatypes=self.datatypes,
163
+ check=self.check,
164
+ )
165
+ # Filter out .json files files:
166
+ # (argument ignore_json only available in mne-bids>=0.16)
167
+ bids_paths = [
168
+ bids_path for bids_path in bids_paths if bids_path.extension != ".json"
169
+ ]
170
+ # Filter out _epo.fif files:
171
+ if self._filter_out_epochs:
172
+ bids_paths = [
173
+ bids_path
174
+ for bids_path in bids_paths
175
+ if not (bids_path.suffix == "epo" and bids_path.extension == ".fif")
176
+ ]
177
+
178
+ all_base_ds = Parallel(n_jobs=self.n_jobs)(
179
+ delayed(self._get_dataset)(bids_path) for bids_path in bids_paths
180
+ )
181
+ super().__init__(all_base_ds)
182
+
183
+ def _get_dataset(self, bids_path: mne_bids.BIDSPath) -> RawDataset:
184
+ description = _description_from_bids_path(bids_path)
185
+ raw = mne_bids.read_raw_bids(bids_path, verbose=False)
186
+ if self.preload:
187
+ raw.load_data()
188
+ return RawDataset(raw, description)
189
+
190
+
191
+ class BIDSEpochsDataset(BIDSDataset):
192
+ """**Experimental** dataset for loading :class:`mne.Epochs` organised in BIDS.
193
+
194
+ The files must end with ``_epo.fif``.
195
+
196
+ .. Warning::
197
+ Epoched data is not officially supported in BIDS.
198
+
199
+ .. Note::
200
+ **Parameters:** This class has the same parameters as :class:`BIDSDataset` except
201
+ for arguments ``datatypes``, ``extensions`` and ``check`` which are fixed.
202
+ """
203
+
204
+ @property
205
+ def _filter_out_epochs(self):
206
+ return False
207
+
208
+ def __init__(self, *args, **kwargs):
209
+ super().__init__(
210
+ *args,
211
+ extensions=".fif",
212
+ suffixes="epo",
213
+ check=False,
214
+ **kwargs,
215
+ )
216
+
217
+ def _set_metadata(self, epochs: mne.BaseEpochs) -> None:
218
+ # events = mne.events_from_annotations(epochs
219
+ n_times = epochs.times.shape[0]
220
+ # id_event = {v: k for k, v in epochs.event_id.items()}
221
+ annotations = epochs.annotations
222
+ if annotations is not None:
223
+ target = annotations.description
224
+ else:
225
+ id_events = {v: k for k, v in epochs.event_id.items()}
226
+ target = [id_events[event_id] for event_id in epochs.events[:, -1]]
227
+ metadata_dict = {
228
+ "i_window_in_trial": np.zeros(len(epochs)),
229
+ "i_start_in_trial": np.zeros(len(epochs)),
230
+ "i_stop_in_trial": np.zeros(len(epochs)) + n_times,
231
+ "target": target,
232
+ }
233
+ epochs.metadata = pd.DataFrame(metadata_dict)
234
+
235
+ def _get_dataset(self, bids_path):
236
+ description = _description_from_bids_path(bids_path)
237
+ epochs = mne.read_epochs(bids_path.fpath)
238
+ self._set_metadata(epochs)
239
+ return WindowsDataset(epochs, description=description, targets_from="metadata")