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,227 @@
1
+ # Authors: Maciej Sliwowski <maciek.sliwowski@gmail.com>
2
+ # Lukas Gemein <l.gemein@gmail.com>
3
+ #
4
+ # License: BSD (3-clause)
5
+
6
+ import mne
7
+ import numpy as np
8
+ import pandas as pd
9
+ import pytest
10
+
11
+ from braindecode.datasets import WindowsDataset, BaseDataset, BaseConcatDataset
12
+ from braindecode.datasets.moabb import fetch_data_with_moabb
13
+ from braindecode.datautil.windowers import create_windows_from_events
14
+
15
+ # TODO: split file up into files with proper matching names
16
+ @pytest.fixture(scope="module")
17
+ # TODO: add test for transformers and case when subject_info is used
18
+ def set_up():
19
+ rng = np.random.RandomState(42)
20
+ info = mne.create_info(ch_names=['0', '1'], sfreq=50, ch_types='eeg')
21
+ raw = mne.io.RawArray(data=rng.randn(2, 1000), info=info)
22
+ desc = pd.Series({'pathological': True, 'gender': 'M', 'age': 48})
23
+ base_dataset = BaseDataset(raw, desc, target_name='age')
24
+
25
+ events = np.array([[100, 0, 1],
26
+ [200, 0, 2],
27
+ [300, 0, 1],
28
+ [400, 0, 4],
29
+ [500, 0, 3]])
30
+ window_idxs = [(0, 0, 100),
31
+ (0, 100, 200),
32
+ (1, 0, 100),
33
+ (2, 0, 100),
34
+ (2, 50, 150)]
35
+ i_window_in_trial, i_start_in_trial, i_stop_in_trial = list(
36
+ zip(*window_idxs))
37
+ metadata = pd.DataFrame(
38
+ {'sample': events[:, 0],
39
+ 'x': events[:, 1],
40
+ 'target': events[:, 2],
41
+ 'i_window_in_trial': i_window_in_trial,
42
+ 'i_start_in_trial': i_start_in_trial,
43
+ 'i_stop_in_trial': i_stop_in_trial})
44
+
45
+ mne_epochs = mne.Epochs(raw=raw, events=events, metadata=metadata)
46
+ windows_dataset = WindowsDataset(mne_epochs, desc)
47
+
48
+ return raw, base_dataset, mne_epochs, windows_dataset, events, window_idxs
49
+
50
+
51
+ @pytest.fixture(scope="module")
52
+ def concat_ds_targets():
53
+ raws, description = fetch_data_with_moabb(
54
+ dataset_name="BNCI2014001", subject_ids=4)
55
+ events, _ = mne.events_from_annotations(raws[0])
56
+ targets = events[:, -1] - 1
57
+ ds = [BaseDataset(raws[i], description.iloc[i]) for i in range(3)]
58
+ concat_ds = BaseConcatDataset(ds)
59
+ return concat_ds, targets
60
+
61
+
62
+ @pytest.fixture(scope='module')
63
+ def concat_windows_dataset(concat_ds_targets):
64
+ concat_ds, targets = concat_ds_targets
65
+ windows_ds = create_windows_from_events(
66
+ concat_ds=concat_ds, trial_start_offset_samples=0,
67
+ trial_stop_offset_samples=0, window_size_samples=100,
68
+ window_stride_samples=100, drop_last_window=False)
69
+
70
+ return windows_ds
71
+
72
+
73
+ def test_get_item(set_up):
74
+ _, _, mne_epochs, windows_dataset, events, window_idxs = set_up
75
+ for i, epoch in enumerate(mne_epochs.get_data()):
76
+ x, y, inds = windows_dataset[i]
77
+ np.testing.assert_allclose(epoch, x)
78
+ assert events[i, 2] == y, f'Y not equal for epoch {i}'
79
+ np.testing.assert_array_equal(window_idxs[i], inds,
80
+ f'window inds not equal for epoch {i}')
81
+
82
+
83
+ def test_len_windows_dataset(set_up):
84
+ _, _, mne_epochs, windows_dataset, _, _ = set_up
85
+ assert len(mne_epochs.events) == len(windows_dataset)
86
+
87
+
88
+ def test_len_base_dataset(set_up):
89
+ raw, base_dataset, _, _, _, _ = set_up
90
+ assert len(raw) == len(base_dataset)
91
+
92
+
93
+ def test_len_concat_dataset(concat_ds_targets):
94
+ concat_ds = concat_ds_targets[0]
95
+ assert len(concat_ds) == sum([len(c) for c in concat_ds.datasets])
96
+
97
+
98
+ def test_target_in_subject_info(set_up):
99
+ raw, _, _, _, _, _ = set_up
100
+ desc = pd.Series({'pathological': True, 'gender': 'M', 'age': 48})
101
+ with pytest.raises(ValueError, match="'does_not_exist' not in description"):
102
+ BaseDataset(raw, desc, target_name='does_not_exist')
103
+
104
+
105
+ def test_description_concat_dataset(concat_ds_targets):
106
+ concat_ds = concat_ds_targets[0]
107
+ assert isinstance(concat_ds.description, pd.DataFrame)
108
+ assert concat_ds.description.shape[0] == len(concat_ds.datasets)
109
+
110
+
111
+ def test_split_concat_dataset(concat_ds_targets):
112
+ concat_ds = concat_ds_targets[0]
113
+ splits = concat_ds.split('run')
114
+
115
+ for k, v in splits.items():
116
+ assert k == v.description['run'].values
117
+ assert isinstance(v, BaseConcatDataset)
118
+
119
+ assert len(concat_ds) == sum([len(v) for v in splits.values()])
120
+
121
+
122
+ def test_concat_concat_dataset(concat_ds_targets):
123
+ concat_ds, targets = concat_ds_targets
124
+ concat_ds1 = BaseConcatDataset(concat_ds.datasets[:2])
125
+ concat_ds2 = BaseConcatDataset(concat_ds.datasets[2:])
126
+ list_of_concat_ds = [concat_ds1, concat_ds2]
127
+ descriptions = pd.concat([ds.description for ds in list_of_concat_ds])
128
+ descriptions.reset_index(inplace=True, drop=True)
129
+ lens = [0] + [len(ds) for ds in list_of_concat_ds]
130
+ cumsums = [ds.cumulative_sizes for ds in list_of_concat_ds]
131
+ cumsums = [l
132
+ for i, cumsum in enumerate(cumsums)
133
+ for l in np.array(cumsum) + lens[i]]
134
+ concat_concat_ds = BaseConcatDataset(list_of_concat_ds)
135
+ assert len(concat_concat_ds) == sum(lens)
136
+ assert len(concat_concat_ds) == concat_concat_ds.cumulative_sizes[-1]
137
+ assert len(concat_concat_ds.datasets) == len(descriptions)
138
+ assert len(concat_concat_ds.description) == len(descriptions)
139
+ np.testing.assert_array_equal(cumsums, concat_concat_ds.cumulative_sizes)
140
+ pd.testing.assert_frame_equal(descriptions, concat_concat_ds.description)
141
+
142
+
143
+ def test_split_dataset_failure(concat_ds_targets):
144
+ concat_ds = concat_ds_targets[0]
145
+ with pytest.raises(KeyError):
146
+ concat_ds.split("test")
147
+
148
+ with pytest.raises(IndexError):
149
+ concat_ds.split([])
150
+
151
+ with pytest.raises(
152
+ AssertionError, match="datasets should not be an empty iterable"):
153
+ concat_ds.split([[]])
154
+
155
+ with pytest.raises(TypeError):
156
+ concat_ds.split([[[]]])
157
+
158
+ with pytest.raises(IndexError):
159
+ concat_ds.split([len(concat_ds.description)])
160
+
161
+
162
+ def test_split_dataset(concat_ds_targets):
163
+ concat_ds = concat_ds_targets[0]
164
+ splits = concat_ds.split("run")
165
+ assert len(splits) == len(concat_ds.description["run"].unique())
166
+
167
+ splits = concat_ds.split([1])
168
+ assert len(splits) == 1
169
+ assert len(splits["0"].datasets) == 1
170
+
171
+ splits = concat_ds.split([[2]])
172
+ assert len(splits) == 1
173
+ assert len(splits["0"].datasets) == 1
174
+
175
+ original_ids = [1, 2]
176
+ splits = concat_ds.split([[0], original_ids])
177
+ assert len(splits) == 2
178
+ assert list(splits["0"].description.index) == [0]
179
+ assert len(splits["0"].datasets) == 1
180
+ # when creating new BaseConcatDataset, index is reset
181
+ split_ids = [0, 1]
182
+ assert list(splits["1"].description.index) == split_ids
183
+ assert len(splits["1"].datasets) == 2
184
+
185
+ for i, ds in enumerate(splits["1"].datasets):
186
+ np.testing.assert_array_equal(
187
+ ds.raw.get_data(), concat_ds.datasets[original_ids[i]].raw.get_data())
188
+
189
+
190
+ def test_metadata(concat_windows_dataset):
191
+ md = concat_windows_dataset.get_metadata()
192
+ assert isinstance(md, pd.DataFrame)
193
+ assert all([c in md.columns
194
+ for c in concat_windows_dataset.description.columns])
195
+ assert md.shape[0] == len(concat_windows_dataset)
196
+
197
+
198
+ def test_no_metadata(concat_ds_targets):
199
+ with pytest.raises(TypeError, match='Metadata dataframe can only be'):
200
+ concat_ds_targets[0].get_metadata()
201
+
202
+
203
+ def test_on_the_fly_transforms_base_dataset(concat_ds_targets):
204
+ concat_ds, targets = concat_ds_targets
205
+ original_X = concat_ds[0][0]
206
+ factor = 10
207
+ transform = lambda x: x * factor
208
+ concat_ds.transform = transform
209
+ transformed_X = concat_ds[0][0]
210
+
211
+ assert (factor * original_X == transformed_X).all()
212
+
213
+ with pytest.raises(ValueError):
214
+ concat_ds.transform = 0
215
+
216
+
217
+ def test_on_the_fly_transforms_windows_dataset(concat_windows_dataset):
218
+ original_X = concat_windows_dataset[0][0]
219
+ factor = 10
220
+ transform = lambda x: x * factor
221
+ concat_windows_dataset.transform = transform
222
+ transformed_X = concat_windows_dataset[0][0]
223
+
224
+ assert (factor * original_X == transformed_X).all()
225
+
226
+ with pytest.raises(ValueError):
227
+ concat_windows_dataset.transform = 0
@@ -0,0 +1,145 @@
1
+ # Authors: Lukas Gemein <l.gemein@gmail.com>
2
+ #
3
+ # License: BSD-3
4
+
5
+
6
+ import numpy as np
7
+ import mne
8
+
9
+ from braindecode.datautil.mne import (
10
+ create_from_mne_raw, create_from_mne_epochs)
11
+
12
+ def test_create_from_single_raw():
13
+ n_channels = 50
14
+ n_times = 500
15
+ sfreq = 100
16
+
17
+ rng = np.random.RandomState(34834)
18
+ data = rng.rand(n_channels, n_times)
19
+ ch_names = [f'ch{i}' for i in range(n_channels)]
20
+ ch_types = ['eeg'] * n_channels
21
+ info = mne.create_info(ch_names=ch_names, sfreq=sfreq, ch_types=ch_types)
22
+ raw = mne.io.RawArray(data, info)
23
+
24
+ n_anns = 10
25
+ inds = np.linspace(0, n_times, n_anns, endpoint=False).astype(int)
26
+ onsets = raw.times[inds]
27
+ durations = np.ones(n_anns) * 0.2
28
+ descriptions = ['test_trial'] * len(durations)
29
+ anns = mne.Annotations(onsets, durations, descriptions)
30
+ raw = raw.set_annotations(anns)
31
+
32
+ windows = create_from_mne_raw([raw], 0, 0, 5, 2, False)
33
+
34
+ # windows per trial: 0-5,2-7,4-9,6-11,...,14-19,15-20
35
+ assert len(windows) == 9 * n_anns
36
+ for i_w, (x, y, (i_w_in_t, i_start, i_stop)) in enumerate(windows):
37
+ assert i_w_in_t == i_w % 9
38
+ i_t = i_w // 9
39
+ assert i_start == inds[i_t] + i_w_in_t * 2 - (i_w_in_t == 8)
40
+ assert i_stop == inds[i_t] + i_w_in_t * 2 - (i_w_in_t == 8) + 5
41
+ np.testing.assert_allclose(x, data[:, i_start:i_stop],
42
+ atol=1e-5, rtol=1e-5)
43
+
44
+
45
+ def test_create_from_two_raws_with_varying_trial_lengths():
46
+ n_channels = 50
47
+ n_times = 500
48
+ sfreq = 100
49
+ rng = np.random.RandomState(34834)
50
+ raws = []
51
+ datas = []
52
+ for i_raw in range(2):
53
+ data = rng.rand(n_channels, n_times)
54
+ ch_names = [f'ch{i}' for i in range(n_channels)]
55
+ ch_types = ['eeg'] * n_channels
56
+ info = mne.create_info(ch_names=ch_names, sfreq=sfreq, ch_types=ch_types)
57
+ raw = mne.io.RawArray(data, info)
58
+
59
+ n_anns = 10
60
+ inds = np.linspace(0, n_times, n_anns, endpoint=False).astype(int)
61
+ onsets = raw.times[inds]
62
+ if i_raw == 0:
63
+ trial_dur = 0.2 # in sec
64
+ else:
65
+ trial_dur = 0.1
66
+ durations = np.ones(n_anns) * trial_dur
67
+ descriptions = ['test_trial'] * len(durations)
68
+ anns = mne.Annotations(onsets, durations, descriptions)
69
+ raw = raw.set_annotations(anns)
70
+ raws.append(raw)
71
+ datas.append(data)
72
+
73
+ windows = create_from_mne_raw(raws, 0, 0, 5, 2, False)
74
+
75
+ # windows per trial: 0-5,2-7,4-9,6-11,...,14-19,15-20
76
+ # and then: 0-5,2-7,4-9,5-10
77
+ assert len(windows) == 9 * n_anns + 4 * n_anns
78
+ for i_w, (x, y, (i_w_in_t, i_start, i_stop)) in enumerate(windows):
79
+ if i_w < 9 * n_anns:
80
+ assert i_w_in_t == i_w % 9
81
+ i_t = i_w // 9
82
+ assert i_start == inds[i_t] + i_w_in_t * 2 - (i_w_in_t == 8)
83
+ assert i_stop == inds[i_t] + i_w_in_t * 2 - (i_w_in_t == 8) + 5
84
+ np.testing.assert_allclose(x, datas[0][:, i_start:i_stop],
85
+ atol=1e-5, rtol=1e-5)
86
+ else:
87
+ assert i_w_in_t == (i_w - n_anns * 9) % 4
88
+ i_t = ((i_w - n_anns * 9) // 4)
89
+ assert i_start == inds[i_t] + i_w_in_t * 2 - (i_w_in_t == 3)
90
+ assert i_stop == inds[i_t] + i_w_in_t * 2 - (i_w_in_t == 3) + 5
91
+
92
+
93
+ def test_create_from_mne_epochs():
94
+ n_channels = 50
95
+ n_times = 500
96
+ sfreq = 100
97
+ rng = np.random.RandomState(34834)
98
+ all_epochs = []
99
+ datas = []
100
+ for i_raw in range(2):
101
+ data = rng.rand(n_channels, n_times)
102
+ ch_names = [f'ch{i}' for i in range(n_channels)]
103
+ ch_types = ['eeg'] * n_channels
104
+ info = mne.create_info(ch_names=ch_names, sfreq=sfreq,
105
+ ch_types=ch_types)
106
+ raw = mne.io.RawArray(data, info)
107
+
108
+ n_anns = 10
109
+ inds = np.linspace(0, n_times, n_anns, endpoint=False).astype(int)
110
+ onsets = raw.times[inds]
111
+ if i_raw == 0:
112
+ trial_dur = 0.2 # in sec
113
+ else:
114
+ trial_dur = 0.1
115
+ durations = np.ones(n_anns) * trial_dur
116
+ descriptions = ['test_trial'] * len(durations)
117
+ anns = mne.Annotations(onsets, durations, descriptions)
118
+ raw = raw.set_annotations(anns)
119
+ events, event_id = mne.events_from_annotations(raw, )
120
+ epochs = mne.Epochs(raw, events, event_id=event_id, preload=True,
121
+ baseline=None,
122
+ tmin=0, tmax=trial_dur - 1e-2)
123
+ all_epochs.append(epochs)
124
+ datas.append(data)
125
+
126
+ windows = create_from_mne_epochs(all_epochs, window_size_samples=5,
127
+ window_stride_samples=2,
128
+ drop_last_window=False)
129
+
130
+ # windows per trial: 0-5,2-7,4-9,6-11,...,14-19,15-20
131
+ # and then: 0-5,2-7,4-9,5-10
132
+ assert len(windows) == 9 * n_anns + 4 * n_anns
133
+ for i_w, (x, y, (i_w_in_t, i_start, i_stop)) in enumerate(windows):
134
+ if i_w < 9 * n_anns:
135
+ assert i_w_in_t == i_w % 9
136
+ i_t = i_w // 9
137
+ assert i_start == inds[i_t] + i_w_in_t * 2 - (i_w_in_t == 8)
138
+ assert i_stop == inds[i_t] + i_w_in_t * 2 - (i_w_in_t == 8) + 5
139
+ np.testing.assert_allclose(x, datas[0][:, i_start:i_stop],
140
+ atol=1e-5, rtol=1e-5)
141
+ else:
142
+ assert i_w_in_t == (i_w - n_anns * 9) % 4
143
+ i_t = ((i_w - n_anns * 9) // 4)
144
+ assert i_start == inds[i_t] + i_w_in_t * 2 - (i_w_in_t == 3)
145
+ assert i_stop == inds[i_t] + i_w_in_t * 2 - (i_w_in_t == 3) + 5
@@ -0,0 +1,23 @@
1
+ from braindecode.datasets.sleep_physionet import SleepPhysionet
2
+ from braindecode.datasets.base import BaseConcatDataset
3
+
4
+
5
+ def test_sleep_physionet():
6
+ sp = SleepPhysionet(
7
+ subject_ids=[0], recording_ids=[1], preload=True, load_eeg_only=True)
8
+ assert isinstance(sp, BaseConcatDataset)
9
+
10
+
11
+ def test_all_signals():
12
+ sp = SleepPhysionet(
13
+ subject_ids=[0], recording_ids=[1], preload=True, load_eeg_only=False)
14
+ assert len(sp.datasets[0].raw.ch_names) == 7
15
+
16
+
17
+ def test_crop_wake():
18
+ sp = SleepPhysionet(
19
+ subject_ids=[0], recording_ids=[1], preload=True, load_eeg_only=True,
20
+ crop_wake_mins=30)
21
+ sfreq = sp.datasets[0].raw.info['sfreq']
22
+ duration_h = len(sp) / (3600 * sfreq)
23
+ assert duration_h < 7 and duration_h > 6
@@ -0,0 +1,97 @@
1
+ # Authors: Lukas Gemein <l.gemein@gmail.com>
2
+ #
3
+ # License: BSD-3
4
+
5
+ from braindecode.datasets.tuh import (
6
+ _parse_description_from_file_path, _create_chronological_description,
7
+ TUHAbnormal)
8
+
9
+
10
+ def test_parse_from_tuh_file_path():
11
+ file_path = ("v2.0.0/edf/01_tcp_ar/000/00000021/"
12
+ "s004_2013_08_15/00000021_s004_t000.edf")
13
+ description = _parse_description_from_file_path(file_path)
14
+ assert len(description) == 9
15
+ assert description['path'] == file_path
16
+ assert description['year'] == 2013
17
+ assert description['month'] == 8
18
+ assert description['day'] == 15
19
+ assert description['subject'] == 21
20
+ assert description['session'] == 4
21
+ assert description['segment'] == 0
22
+ assert description['reference'] == 'ar'
23
+ assert description['version'] == 'v2.0.0'
24
+
25
+
26
+ def test_parse_from_tuh_abnormal_file_path():
27
+ file_path = ("v2.0.0/edf/eval/abnormal/01_tcp_ar/107/00010782/"
28
+ "s002_2013_10_05/00010782_s002_t001.edf")
29
+ additional_description = (
30
+ TUHAbnormal._parse_additional_description_from_file_path(file_path))
31
+ assert len(additional_description) == 2
32
+ assert additional_description['pathological']
33
+ assert not additional_description['train']
34
+
35
+ file_path = ("v2.0.0/edf/train/normal/01_tcp_ar/107/00010782/"
36
+ "s002_2013_10_05/00010782_s002_t001.edf")
37
+ additional_description = (
38
+ TUHAbnormal._parse_additional_description_from_file_path(file_path))
39
+ assert len(additional_description) == 2
40
+ assert not additional_description['pathological']
41
+ assert additional_description['train']
42
+
43
+
44
+ def test_sort_chronologically():
45
+ file_paths = [
46
+ "v2.0.0/edf/train/normal/01_tcp_ar/108/00010832/s001_2013_10_03/"
47
+ "00010831_s002_t001.edf",
48
+ "v2.0.0/edf/train/abnormal/01_tcp_ar/000/00000068/s009_2011_09_12/"
49
+ "00000068_s009_t000.edf",
50
+ "v2.0.0/edf/train/abnormal/01_tcp_ar/000/00000016/s004_2012_02_08/"
51
+ "00000016_s004_t000.edf",
52
+ "v2.0.0/edf/train/normal/01_tcp_ar/108/00010839/s001_2013_11_22/"
53
+ "00010839_s001_t000.edf",
54
+ "v2.0.0/edf/train/abnormal/01_tcp_ar/000/00000068/s008_2010_09_28/"
55
+ "00000068_s008_t001.edf",
56
+ "v2.0.0/edf/train/normal/01_tcp_ar/108/00010832/s001_2013_10_03/"
57
+ "00010831_s002_t000.edf",
58
+ "v2.0.0/edf/train/abnormal/01_tcp_ar/000/00000016/s005_2013_07_12/"
59
+ "00000016_s005_t001.edf",
60
+ "v2.0.0/edf/train/normal/01_tcp_ar/108/00010810/s001_2013_10_03/"
61
+ "00010810_s001_t000.edf",
62
+ "v2.0.0/edf/train/normal/01_tcp_ar/108/00010831/s001_2013_10_03/"
63
+ "00010831_s001_t000.edf",
64
+ "v2.0.0/edf/train/abnormal/01_tcp_ar/000/00000019/s002_2013_07_18/"
65
+ "00000019_s002_t001.edf",
66
+ "v2.0.0/edf/train/normal/01_tcp_ar/108/00010816/s001_2013_10_03/"
67
+ "00010816_s001_t001.edf",
68
+ ]
69
+ description = _create_chronological_description(file_paths)
70
+ expected = [
71
+ "v2.0.0/edf/train/abnormal/01_tcp_ar/000/00000068/s008_2010_09_28/"
72
+ "00000068_s008_t001.edf",
73
+ "v2.0.0/edf/train/abnormal/01_tcp_ar/000/00000068/s009_2011_09_12/"
74
+ "00000068_s009_t000.edf",
75
+ "v2.0.0/edf/train/abnormal/01_tcp_ar/000/00000016/s004_2012_02_08/"
76
+ "00000016_s004_t000.edf",
77
+ "v2.0.0/edf/train/abnormal/01_tcp_ar/000/00000016/s005_2013_07_12/"
78
+ "00000016_s005_t001.edf",
79
+ "v2.0.0/edf/train/abnormal/01_tcp_ar/000/00000019/s002_2013_07_18/"
80
+ "00000019_s002_t001.edf",
81
+
82
+ "v2.0.0/edf/train/normal/01_tcp_ar/108/00010810/s001_2013_10_03/"
83
+ "00010810_s001_t000.edf",
84
+ "v2.0.0/edf/train/normal/01_tcp_ar/108/00010816/s001_2013_10_03/"
85
+ "00010816_s001_t001.edf",
86
+ "v2.0.0/edf/train/normal/01_tcp_ar/108/00010831/s001_2013_10_03/"
87
+ "00010831_s001_t000.edf",
88
+ "v2.0.0/edf/train/normal/01_tcp_ar/108/00010832/s001_2013_10_03/"
89
+ "00010831_s002_t000.edf",
90
+ "v2.0.0/edf/train/normal/01_tcp_ar/108/00010832/s001_2013_10_03/"
91
+ "00010831_s002_t001.edf",
92
+
93
+ "v2.0.0/edf/train/normal/01_tcp_ar/108/00010839/s001_2013_11_22/"
94
+ "00010839_s001_t000.edf",
95
+ ]
96
+ for p1, p2 in zip(expected, description.T.path):
97
+ assert p1 == p2
@@ -0,0 +1,31 @@
1
+ # Authors: Lukas Gemein <l.gemein@gmail.com>
2
+ #
3
+ # License: BSD-3
4
+
5
+ import numpy as np
6
+ from braindecode.datautil.xy import create_from_X_y
7
+
8
+
9
+ def test_crops_data_loader_explicit():
10
+
11
+ X = np.arange(0, 15)
12
+ y = [0]
13
+
14
+ n_time_in = 10
15
+ n_time_out = 4
16
+
17
+ expected_crops = [np.arange(0, 10), np.arange(4, 14), np.arange(5, 15)]
18
+
19
+ dataset = create_from_X_y(
20
+ X[None, None], y,
21
+ window_size_samples=n_time_in,
22
+ window_stride_samples=n_time_out,
23
+ drop_last_window=False
24
+ )
25
+
26
+ Xs, ys, i_s = zip(*list(dataset))
27
+
28
+ assert len(Xs) == len(ys) == 3
29
+
30
+ for actual, expected, in zip(Xs, expected_crops):
31
+ np.testing.assert_array_equal(actual.squeeze(), expected)
File without changes