braindecode 0.5.1__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 (69) hide show
  1. Braindecode-0.5.1.dist-info/LICENSE.txt +31 -0
  2. Braindecode-0.5.1.dist-info/METADATA +133 -0
  3. Braindecode-0.5.1.dist-info/RECORD +69 -0
  4. Braindecode-0.5.1.dist-info/WHEEL +5 -0
  5. Braindecode-0.5.1.dist-info/top_level.txt +2 -0
  6. braindecode/__init__.py +4 -0
  7. braindecode/classifier.py +258 -0
  8. braindecode/datasets/__init__.py +7 -0
  9. braindecode/datasets/base.py +293 -0
  10. braindecode/datasets/bbci.py +679 -0
  11. braindecode/datasets/moabb.py +110 -0
  12. braindecode/datasets/sleep_physionet.py +103 -0
  13. braindecode/datasets/tuh.py +230 -0
  14. braindecode/datautil/__init__.py +11 -0
  15. braindecode/datautil/mne.py +136 -0
  16. braindecode/datautil/preprocess.py +364 -0
  17. braindecode/datautil/serialization.py +111 -0
  18. braindecode/datautil/util.py +36 -0
  19. braindecode/datautil/windowers.py +435 -0
  20. braindecode/datautil/xy.py +77 -0
  21. braindecode/models/__init__.py +12 -0
  22. braindecode/models/deep4.py +252 -0
  23. braindecode/models/eegnet.py +339 -0
  24. braindecode/models/eegresnet.py +232 -0
  25. braindecode/models/functions.py +43 -0
  26. braindecode/models/hybrid.py +103 -0
  27. braindecode/models/modules.py +150 -0
  28. braindecode/models/shallow_fbcsp.py +158 -0
  29. braindecode/models/sleep_stager_chambon_2018.py +113 -0
  30. braindecode/models/tcn.py +143 -0
  31. braindecode/models/util.py +66 -0
  32. braindecode/regressor.py +240 -0
  33. braindecode/samplers/__init__.py +5 -0
  34. braindecode/samplers/base.py +78 -0
  35. braindecode/samplers/ssl.py +118 -0
  36. braindecode/training/__init__.py +8 -0
  37. braindecode/training/callbacks.py +21 -0
  38. braindecode/training/losses.py +17 -0
  39. braindecode/training/scoring.py +296 -0
  40. braindecode/util.py +362 -0
  41. braindecode/version.py +1 -0
  42. braindecode/visualization/__init__.py +5 -0
  43. braindecode/visualization/gradients.py +53 -0
  44. test/__init__.py +0 -0
  45. test/acceptance_tests/__init__.py +0 -0
  46. test/acceptance_tests/test_cropped_decoding.py +171 -0
  47. test/acceptance_tests/test_eeg_classifier.py +255 -0
  48. test/acceptance_tests/test_model_architectures.py +54 -0
  49. test/acceptance_tests/test_trialwise_decoding.py +168 -0
  50. test/unit_tests/__init__.py +0 -0
  51. test/unit_tests/datasets/__init__.py +0 -0
  52. test/unit_tests/datasets/test_dataset.py +227 -0
  53. test/unit_tests/datasets/test_mne.py +145 -0
  54. test/unit_tests/datasets/test_sleep_physionet.py +23 -0
  55. test/unit_tests/datasets/test_tuh.py +97 -0
  56. test/unit_tests/datasets/test_xy.py +31 -0
  57. test/unit_tests/datautil/__init__.py +0 -0
  58. test/unit_tests/datautil/test_preprocess.py +270 -0
  59. test/unit_tests/datautil/test_serialization.py +127 -0
  60. test/unit_tests/datautil/test_windowers.py +519 -0
  61. test/unit_tests/models/__init__.py +0 -0
  62. test/unit_tests/models/test_models.py +136 -0
  63. test/unit_tests/models/test_util.py +22 -0
  64. test/unit_tests/test_eeg_classifier.py +73 -0
  65. test/unit_tests/test_eeg_regressor.py +72 -0
  66. test/unit_tests/test_scoring.py +282 -0
  67. test/unit_tests/test_util.py +30 -0
  68. test/unit_tests/visualization/__init__.py +0 -0
  69. test/unit_tests/visualization/test_gradients.py +38 -0
@@ -0,0 +1,435 @@
1
+ """Get epochs from mne.Raw
2
+ """
3
+
4
+ # Authors: Hubert Banville <hubert.jbanville@gmail.com>
5
+ # Lukas Gemein <l.gemein@gmail.com>
6
+ # Simon Brandt <simonbrandt@protonmail.com>
7
+ # David Sabbagh <dav.sabbagh@gmail.com>
8
+ #
9
+ # License: BSD (3-clause)
10
+
11
+ import warnings
12
+
13
+ import numpy as np
14
+ import mne
15
+ import pandas as pd
16
+ from joblib import Parallel, delayed
17
+
18
+ from ..datasets.base import WindowsDataset, BaseConcatDataset
19
+
20
+
21
+ def create_windows_from_events(
22
+ concat_ds, trial_start_offset_samples, trial_stop_offset_samples,
23
+ window_size_samples=None, window_stride_samples=None,
24
+ drop_last_window=False, mapping=None, preload=False,
25
+ drop_bad_windows=True, picks=None, reject=None, flat=None,
26
+ on_missing='error', n_jobs=1):
27
+ """Create windows based on events in mne.Raw.
28
+
29
+ This function extracts windows of size window_size_samples in the interval
30
+ [trial onset + trial_start_offset_samples, trial onset + trial duration +
31
+ trial_stop_offset_samples] around each trial, with a separation of
32
+ window_stride_samples between consecutive windows. If the last window
33
+ around an event does not end at trial_stop_offset_samples and
34
+ drop_last_window is set to False, an additional overlapping window that
35
+ ends at trial_stop_offset_samples is created.
36
+
37
+ Windows are extracted from the interval defined by the following:
38
+
39
+ trial onset +
40
+ trial onset duration
41
+ |--------------------|------------------------------|---------------------|
42
+ trial onset - trial onset +
43
+ trial_start_offset_samples duration +
44
+ trial_stop_offset_samples
45
+
46
+ Parameters
47
+ ----------
48
+ concat_ds: BaseConcatDataset
49
+ A concat of base datasets each holding raw and description.
50
+ trial_start_offset_samples: int
51
+ Start offset from original trial onsets, in samples.
52
+ trial_stop_offset_samples: int
53
+ Stop offset from original trial stop, in samples.
54
+ window_size_samples: int | None
55
+ Window size. If None, the window size is inferred from the original
56
+ trial size of the first trial and trial_start_offset_samples and
57
+ trial_stop_offset_samples.
58
+ window_stride_samples: int | None
59
+ Stride between windows, in samples. If None, the window stride is
60
+ inferred from the original trial size of the first trial and
61
+ trial_start_offset_samples and trial_stop_offset_samples.
62
+ drop_last_window: bool
63
+ If False, an additional overlapping window that ends at
64
+ trial_stop_offset_samples will be extracted around each event when the
65
+ last window does not end exactly at trial_stop_offset_samples.
66
+ mapping: dict(str: int)
67
+ Mapping from event description to numerical target value.
68
+ preload: bool
69
+ If True, preload the data of the Epochs objects. This is useful to
70
+ reduce disk reading overhead when returning windows in a training
71
+ scenario, however very large data might not fit into memory.
72
+ drop_bad_windows: bool
73
+ If True, call `.drop_bad()` on the resulting mne.Epochs object. This
74
+ step allows identifying e.g., windows that fall outside of the
75
+ continuous recording. It is suggested to run this step here as otherwise
76
+ the BaseConcatDataset has to be updated as well.
77
+ picks: str | list | slice | None
78
+ Channels to include. If None, all available channels are used. See
79
+ mne.Epochs.
80
+ reject: dict | None
81
+ Epoch rejection parameters based on peak-to-peak amplitude. If None, no
82
+ rejection is done based on peak-to-peak amplitude. See mne.Epochs.
83
+ flat: dict | None
84
+ Epoch rejection parameters based on flatness of signals. If None, no
85
+ rejection based on flatness is done. See mne.Epochs.
86
+ on_missing: str
87
+ What to do if one or several event ids are not found in the recording.
88
+ Valid keys are ‘error’ | ‘warning’ | ‘ignore’. See mne.Epochs.
89
+ n_jobs: int
90
+ Number of jobs to use to parallelize the windowing.
91
+
92
+ Returns
93
+ -------
94
+ windows_ds: WindowsDataset
95
+ Dataset containing the extracted windows.
96
+ """
97
+ _check_windowing_arguments(
98
+ trial_start_offset_samples, trial_stop_offset_samples,
99
+ window_size_samples, window_stride_samples)
100
+
101
+ # If user did not specify mapping, we extract all events from all datasets
102
+ # and map them to increasing integers starting from 0
103
+ infer_mapping = mapping is None
104
+ mapping = dict() if infer_mapping else mapping
105
+ infer_window_size_stride = window_size_samples is None
106
+
107
+ list_of_windows_ds = Parallel(n_jobs=n_jobs)(
108
+ delayed(_create_windows_from_events)(
109
+ ds, infer_mapping, infer_window_size_stride,
110
+ trial_start_offset_samples, trial_stop_offset_samples,
111
+ window_size_samples, window_stride_samples, drop_last_window,
112
+ mapping, preload, drop_bad_windows, picks, reject, flat,
113
+ 'error') for ds in concat_ds.datasets)
114
+
115
+ return BaseConcatDataset(list_of_windows_ds)
116
+
117
+
118
+ def create_fixed_length_windows(
119
+ concat_ds, start_offset_samples, stop_offset_samples,
120
+ window_size_samples, window_stride_samples, drop_last_window,
121
+ mapping=None, preload=False, drop_bad_windows=True, picks=None,
122
+ reject=None, flat=None, on_missing='error', n_jobs=1):
123
+ """Windower that creates sliding windows.
124
+
125
+ Parameters
126
+ ----------
127
+ concat_ds: ConcatDataset
128
+ A concat of base datasets each holding raw and descpription.
129
+ start_offset_samples: int
130
+ Start offset from beginning of recording in samples.
131
+ stop_offset_samples: int | None
132
+ Stop offset from beginning of recording in samples. If None, set to be
133
+ the end of the recording.
134
+ window_size_samples: int
135
+ Window size.
136
+ window_stride_samples: int
137
+ Stride between windows.
138
+ drop_last_window: bool
139
+ Whether or not have a last overlapping window, when windows do not
140
+ equally divide the continuous signal.
141
+ mapping: dict(str: int)
142
+ Mapping from event description to target value.
143
+ preload: bool
144
+ If True, preload the data of the Epochs objects.
145
+ drop_bad_windows: bool
146
+ If True, call `.drop_bad()` on the resulting mne.Epochs object. This
147
+ step allows identifying e.g., windows that fall outside of the
148
+ continuous recording. It is suggested to run this step here as
149
+ otherwise the BaseConcatDataset has to be updated as well.
150
+ picks: str | list | slice | None
151
+ Channels to include. If None, all available channels are used. See
152
+ mne.Epochs.
153
+ reject: dict | None
154
+ Epoch rejection parameters based on peak-to-peak amplitude. If None, no
155
+ rejection is done based on peak-to-peak amplitude. See mne.Epochs.
156
+ flat: dict | None
157
+ Epoch rejection parameters based on flatness of signals. If None, no
158
+ rejection based on flatness is done. See mne.Epochs.
159
+ on_missing: str
160
+ What to do if one or several event ids are not found in the recording.
161
+ Valid keys are ‘error’ | ‘warning’ | ‘ignore’. See mne.Epochs.
162
+ n_jobs: int
163
+ Number of jobs to use to parallelize the windowing.
164
+
165
+ Returns
166
+ -------
167
+ windows_ds: WindowsDataset
168
+ Dataset containing the extracted windows.
169
+ """
170
+ _check_windowing_arguments(
171
+ start_offset_samples, stop_offset_samples,
172
+ window_size_samples, window_stride_samples)
173
+ if stop_offset_samples == 0:
174
+ warnings.warn(
175
+ 'Meaning of `trial_stop_offset_samples`=0 has changed, use `None` '
176
+ 'to indicate end of trial/recording. Using `None`.')
177
+ stop_offset_samples = None
178
+
179
+ list_of_windows_ds = Parallel(n_jobs=n_jobs)(
180
+ delayed(_create_fixed_length_windows)(
181
+ ds, start_offset_samples, stop_offset_samples, window_size_samples,
182
+ window_stride_samples, drop_last_window, mapping, preload,
183
+ drop_bad_windows, picks, reject, flat, on_missing)
184
+ for ds in concat_ds.datasets)
185
+
186
+ return BaseConcatDataset(list_of_windows_ds)
187
+
188
+
189
+ def _create_windows_from_events(
190
+ ds, infer_mapping, infer_window_size_stride,
191
+ trial_start_offset_samples, trial_stop_offset_samples,
192
+ window_size_samples=None, window_stride_samples=None,
193
+ drop_last_window=False, mapping=None, preload=False,
194
+ drop_bad_windows=True, picks=None, reject=None, flat=None,
195
+ on_missing='error'):
196
+ """Create WindowsDataset from BaseDataset based on events.
197
+
198
+ Parameters
199
+ ----------
200
+ ds : BaseDataset
201
+ Dataset containing continuous data and description.
202
+ infer_mapping : bool
203
+ If True, extract all events from all datasets and map them to
204
+ increasing integers starting from 0.
205
+ infer_window_size_stride : bool
206
+ If True, infer the stride from the original trial size of the first
207
+ trial and trial_start_offset_samples and trial_stop_offset_samples.
208
+
209
+ See `create_windows_from_events` for description of other parameters.
210
+
211
+ Returns
212
+ -------
213
+ WindowsDataset :
214
+ Windowed dataset.
215
+ """
216
+ if infer_mapping:
217
+ unique_events = np.unique(ds.raw.annotations.description)
218
+ new_unique_events = [x for x in unique_events if x not in mapping]
219
+ # mapping event descriptions to integers from 0 on
220
+ max_id_mapping = len(mapping)
221
+ mapping.update(
222
+ {v: k + max_id_mapping for k, v in enumerate(new_unique_events)}
223
+ )
224
+
225
+ events, events_id = mne.events_from_annotations(ds.raw, mapping)
226
+ onsets = events[:, 0]
227
+ # Onsets are relative to the beginning of the recording
228
+ filtered_durations = np.array(
229
+ [a['duration'] for a in ds.raw.annotations
230
+ if a['description'] in events_id]
231
+ )
232
+ stops = onsets + (filtered_durations * ds.raw.info['sfreq']).astype(int)
233
+ # XXX This could probably be simplified by using chunk_duration in
234
+ # `events_from_annotations`
235
+
236
+ last_samp = ds.raw.first_samp + ds.raw.n_times
237
+ if stops[-1] + trial_stop_offset_samples > last_samp:
238
+ raise ValueError(
239
+ '"trial_stop_offset_samples" too large. Stop of last trial '
240
+ f'({stops[-1]}) + "trial_stop_offset_samples" '
241
+ f'({trial_stop_offset_samples}) must be smaller than length of'
242
+ f' recording ({len(ds)}).')
243
+
244
+ if infer_window_size_stride:
245
+ # window size is trial size
246
+ if window_size_samples is None:
247
+ window_size_samples = stops[0] + trial_stop_offset_samples - (
248
+ onsets[0] + trial_start_offset_samples)
249
+ window_stride_samples = window_size_samples
250
+ this_trial_sizes = (stops + trial_stop_offset_samples) - (
251
+ onsets + trial_start_offset_samples)
252
+ # Maybe actually this is not necessary?
253
+ # We could also just say we just assume window size=trial size
254
+ # in case not given, without this condition...
255
+ # but then would have to change functions overall
256
+ # to deal with varying window sizes hmmhmh
257
+ assert np.all(this_trial_sizes == window_size_samples), (
258
+ 'All trial sizes should be the same if you do not supply a window '
259
+ 'size.')
260
+
261
+ description = events[:, -1]
262
+
263
+ i_trials, i_window_in_trials, starts, stops = _compute_window_inds(
264
+ onsets, stops, trial_start_offset_samples,
265
+ trial_stop_offset_samples, window_size_samples,
266
+ window_stride_samples, drop_last_window)
267
+
268
+ events = [[start, window_size_samples, description[i_trials[i_start]]]
269
+ for i_start, start in enumerate(starts)]
270
+ events = np.array(events)
271
+
272
+ if any(np.diff(events[:, 0]) <= 0):
273
+ raise NotImplementedError('Trial overlap not implemented.')
274
+
275
+ description = events[:, -1]
276
+
277
+ metadata = pd.DataFrame({
278
+ 'i_window_in_trial': i_window_in_trials,
279
+ 'i_start_in_trial': starts,
280
+ 'i_stop_in_trial': stops,
281
+ 'target': description})
282
+
283
+ # window size - 1, since tmax is inclusive
284
+ mne_epochs = mne.Epochs(
285
+ ds.raw, events, events_id, baseline=None, tmin=0,
286
+ tmax=(window_size_samples - 1) / ds.raw.info['sfreq'],
287
+ metadata=metadata, preload=preload, picks=picks, reject=reject,
288
+ flat=flat, on_missing=on_missing)
289
+
290
+ if drop_bad_windows:
291
+ mne_epochs.drop_bad()
292
+
293
+ return WindowsDataset(mne_epochs, ds.description)
294
+
295
+
296
+ def _create_fixed_length_windows(
297
+ ds, start_offset_samples, stop_offset_samples, window_size_samples,
298
+ window_stride_samples, drop_last_window, mapping=None, preload=False,
299
+ drop_bad_windows=True, picks=None, reject=None, flat=None,
300
+ on_missing='error'):
301
+ """Create WindowsDataset from BaseDataset with sliding windows.
302
+
303
+ Parameters
304
+ ----------
305
+ ds : BaseDataset
306
+ Dataset containing continuous data and description.
307
+
308
+ See `create_fixed_length_windows` for description of other parameters.
309
+
310
+ Returns
311
+ -------
312
+ WindowsDataset :
313
+ Windowed dataset.
314
+ """
315
+ stop = ds.raw.n_times \
316
+ if stop_offset_samples is None else stop_offset_samples
317
+ stop = stop - window_size_samples + ds.raw.first_samp
318
+ # already includes last incomplete window start
319
+ starts = np.arange(
320
+ ds.raw.first_samp + start_offset_samples, stop + 1,
321
+ window_stride_samples)
322
+
323
+ if not drop_last_window and starts[-1] < stop:
324
+ # if last window does not end at trial stop, make it stop there
325
+ starts = np.append(starts, stop)
326
+
327
+ # TODO: handle multi-target case / non-integer target case
328
+ target = -1 if ds.target is None else ds.target
329
+ if mapping is not None:
330
+ target = mapping[target]
331
+
332
+ fake_events = [[start, window_size_samples, -1] for start in starts]
333
+ metadata = pd.DataFrame({
334
+ 'i_window_in_trial': np.arange(len(fake_events)),
335
+ 'i_start_in_trial': starts,
336
+ 'i_stop_in_trial': starts + window_size_samples,
337
+ 'target': len(fake_events) * [target]
338
+ })
339
+
340
+ # window size - 1, since tmax is inclusive
341
+ mne_epochs = mne.Epochs(
342
+ ds.raw, fake_events, baseline=None, tmin=0,
343
+ tmax=(window_size_samples - 1) / ds.raw.info['sfreq'],
344
+ metadata=metadata, preload=preload, picks=picks, reject=reject,
345
+ flat=flat, on_missing=on_missing)
346
+
347
+ if drop_bad_windows:
348
+ mne_epochs.drop_bad()
349
+
350
+ return WindowsDataset(mne_epochs, ds.description)
351
+
352
+
353
+ def _compute_window_inds(
354
+ starts, stops, start_offset, stop_offset, size, stride,
355
+ drop_last_window):
356
+ """Compute window start and stop indices.
357
+
358
+ Create window starts from trial onsets (shifted by start_offset) to trial
359
+ end (shifted by stop_offset) separated by stride, as long as window size
360
+ fits into trial.
361
+
362
+ Parameters
363
+ ----------
364
+ starts: array-like
365
+ Trial starts in samples.
366
+ stops: array-like
367
+ Trial stops in samples.
368
+ start_offset: int
369
+ Start offset from original trial onsets in samples.
370
+ stop_offset: int
371
+ Stop offset from original trial stop in samples.
372
+ size: int
373
+ Window size.
374
+ stride: int
375
+ Stride between windows.
376
+ drop_last_window: bool
377
+ Toggles of shifting last window within range or dropping last samples.
378
+
379
+ Returns
380
+ -------
381
+ result_lists: (list, list, list, list)
382
+ Trial, i_window_in_trial, start sample and stop sample of windows.
383
+ """
384
+ starts = np.array([starts]) if isinstance(starts, int) else starts
385
+ stops = np.array([stops]) if isinstance(stops, int) else stops
386
+
387
+ starts += start_offset
388
+ stops += stop_offset
389
+
390
+ i_window_in_trials, i_trials, window_starts = [], [], []
391
+ for start_i, (start, stop) in enumerate(zip(starts, stops)):
392
+ # Generate possible window starts with given stride between original
393
+ # trial onsets (shifted by start_offset) and stops
394
+ possible_starts = np.arange(start, stop, stride)
395
+
396
+ # Possible window start is actually a start, if window size fits in
397
+ # trial start and stop
398
+ for i_window, s in enumerate(possible_starts):
399
+ if (s + size) <= stop:
400
+ window_starts.append(s)
401
+ i_window_in_trials.append(i_window)
402
+ i_trials.append(start_i)
403
+
404
+ # If the last window start + window size is not the same as
405
+ # stop + stop_offset, create another window that overlaps and stops
406
+ # at onset + stop_offset
407
+ if not drop_last_window:
408
+ if window_starts[-1] + size != stop:
409
+ window_starts.append(stop - size)
410
+ i_window_in_trials.append(i_window_in_trials[-1] + 1)
411
+ i_trials.append(start_i)
412
+
413
+ # Update stops to now be event stops instead of trial stops
414
+ window_stops = np.array(window_starts) + size
415
+ if not (len(i_window_in_trials) == len(window_starts) == len(window_stops)):
416
+ raise ValueError(f'{len(i_window_in_trials)} == '
417
+ f'{len(window_starts)} == {len(window_stops)}')
418
+
419
+ return i_trials, i_window_in_trials, window_starts, window_stops
420
+
421
+
422
+ def _check_windowing_arguments(
423
+ trial_start_offset_samples, trial_stop_offset_samples,
424
+ window_size_samples, window_stride_samples):
425
+ assert isinstance(trial_start_offset_samples, (int, np.integer))
426
+ assert (isinstance(trial_stop_offset_samples, (int, np.integer)) or
427
+ (trial_stop_offset_samples is None))
428
+ assert isinstance(window_size_samples, (int, np.integer, type(None)))
429
+ assert isinstance(window_stride_samples, (int, np.integer, type(None)))
430
+ assert (window_size_samples is None) == (window_stride_samples is None)
431
+ if window_size_samples is not None:
432
+ assert window_size_samples > 0, (
433
+ "window size has to be larger than 0")
434
+ assert window_stride_samples > 0, (
435
+ "window stride has to be larger than 0")
@@ -0,0 +1,77 @@
1
+ import numpy as np
2
+ import pandas as pd
3
+ import logging
4
+ import mne
5
+
6
+ from braindecode.datasets.base import BaseDataset, BaseConcatDataset
7
+ from braindecode.datautil.windowers import (
8
+ create_fixed_length_windows,)
9
+
10
+ log = logging.getLogger(__name__)
11
+
12
+
13
+ def create_from_X_y(
14
+ X, y, drop_last_window, sfreq=None, ch_names=None, window_size_samples=None,
15
+ window_stride_samples=None):
16
+ """Create a BaseConcatDataset of WindowsDatasets from X and y to be used for
17
+ decoding with skorch and braindecode, where X is a list of pre-cut trials
18
+ and y are corresponding targets.
19
+
20
+ Parameters
21
+ ----------
22
+ X: array-like
23
+ list of pre-cut trials as n_trials x n_channels x n_times
24
+ y: array-like
25
+ targets corresponding to the trials
26
+ sfreq: common sampling frequency of all trials
27
+ ch_names: array-like
28
+ channel names of the trials
29
+ drop_last_window: bool
30
+ whether or not have a last overlapping window, when
31
+ windows/windows do not equally divide the continuous signal
32
+ window_size_samples: int
33
+ window size
34
+ window_stride_samples: int
35
+ stride between windows
36
+
37
+ Returns
38
+ -------
39
+ windows_datasets: BaseConcatDataset
40
+ X and y transformed to a dataset format that is compatible with skorch
41
+ and braindecode
42
+ """
43
+ n_samples_per_x = []
44
+ base_datasets = []
45
+ if sfreq is None:
46
+ sfreq = 100
47
+ log.info("No sampling frequency given, set to 100 Hz.")
48
+ if ch_names is None:
49
+ ch_names = [str(i) for i in range(X.shape[1])]
50
+ log.info(f"No channel names given, set to 0-{X.shape[1]}).")
51
+
52
+
53
+ for x, target in zip(X, y):
54
+ n_samples_per_x.append(x.shape[1])
55
+ info = mne.create_info(ch_names=ch_names, sfreq=sfreq)
56
+ raw = mne.io.RawArray(x, info)
57
+ base_dataset = BaseDataset(raw, pd.Series({"target": target}),
58
+ target_name="target")
59
+ base_datasets.append(base_dataset)
60
+ base_datasets = BaseConcatDataset(base_datasets)
61
+
62
+ if window_size_samples is None and window_stride_samples is None:
63
+ if not len(np.unique(n_samples_per_x)) == 1:
64
+ raise ValueError(f"if 'window_size_samples' and "
65
+ f"'window_stride_samples' are None, "
66
+ f"all trials have to have the same length")
67
+ window_size_samples = n_samples_per_x[0]
68
+ window_stride_samples = n_samples_per_x[0]
69
+ windows_datasets = create_fixed_length_windows(
70
+ base_datasets,
71
+ start_offset_samples=0,
72
+ stop_offset_samples=None,
73
+ window_size_samples=window_size_samples,
74
+ window_stride_samples=window_stride_samples,
75
+ drop_last_window=drop_last_window
76
+ )
77
+ return windows_datasets
@@ -0,0 +1,12 @@
1
+ """
2
+ Some predefined network architectures for EEG decoding.
3
+ """
4
+
5
+ from .deep4 import Deep4Net
6
+ from .eegnet import EEGNetv4, EEGNetv1
7
+ from .hybrid import HybridNet
8
+ from .shallow_fbcsp import ShallowFBCSPNet
9
+ from .eegresnet import EEGResNet
10
+ from .tcn import TCN
11
+ from .sleep_stager_chambon_2018 import SleepStagerChambon2018
12
+ from .util import get_output_shape