eegdash 0.3.7.dev177024734__tar.gz → 0.3.8__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.
Potentially problematic release.
This version of eegdash might be problematic. Click here for more details.
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/MANIFEST.in +1 -1
- {eegdash-0.3.7.dev177024734/eegdash.egg-info → eegdash-0.3.8}/PKG-INFO +11 -5
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/README.md +9 -4
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/docs/Makefile +2 -2
- eegdash-0.3.8/docs/build/html/_downloads/06c8d94b7e0b8be2de39fdc122dd12bb/tutorial_challenge_2.ipynb +388 -0
- eegdash-0.3.8/docs/build/html/_downloads/2c592649a2079630923cb072bc1beaf3/tutorial_eoec.ipynb +187 -0
- eegdash-0.3.8/docs/build/html/_downloads/9c3f6685782eda7736ccb2b49cd04723/tutorial_eegdash_offline.ipynb +72 -0
- eegdash-0.3.8/docs/build/html/_downloads/9f4f54b7e99e554f34ea4efcf2a8337e/tutorial_challenge_1.ipynb +283 -0
- eegdash-0.3.8/docs/build/html/_downloads/f3cf56a30a7c06a2eccae3b5b3d28e35/tutorial_feature_extractor_open_close_eye.ipynb +253 -0
- eegdash-0.3.8/docs/source/api/eegdash.api.rst +7 -0
- eegdash-0.3.8/docs/source/api/eegdash.bids_eeg_metadata.rst +7 -0
- eegdash-0.3.8/docs/source/api/eegdash.const.rst +7 -0
- eegdash-0.3.8/docs/source/api/eegdash.data_utils.rst +7 -0
- eegdash-0.3.8/docs/source/api/eegdash.dataset.dataset.rst +7 -0
- eegdash-0.3.8/docs/source/api/eegdash.dataset.registry.rst +7 -0
- eegdash-0.3.8/docs/source/api/eegdash.dataset.rst +16 -0
- eegdash-0.3.8/docs/source/api/eegdash.features.datasets.rst +7 -0
- eegdash-0.3.8/docs/source/api/eegdash.features.decorators.rst +7 -0
- eegdash-0.3.8/docs/source/api/eegdash.features.extractors.rst +7 -0
- eegdash-0.3.8/docs/source/api/eegdash.features.feature_bank.complexity.rst +7 -0
- eegdash-0.3.8/docs/source/api/eegdash.features.feature_bank.connectivity.rst +7 -0
- eegdash-0.3.8/docs/source/api/eegdash.features.feature_bank.csp.rst +7 -0
- eegdash-0.3.8/docs/source/api/eegdash.features.feature_bank.dimensionality.rst +7 -0
- eegdash-0.3.8/docs/source/api/eegdash.features.feature_bank.rst +21 -0
- eegdash-0.3.8/docs/source/api/eegdash.features.feature_bank.signal.rst +7 -0
- eegdash-0.3.8/docs/source/api/eegdash.features.feature_bank.spectral.rst +7 -0
- eegdash-0.3.8/docs/source/api/eegdash.features.feature_bank.utils.rst +7 -0
- eegdash-0.3.8/docs/source/api/eegdash.features.inspect.rst +7 -0
- eegdash-0.3.8/docs/source/api/eegdash.features.rst +28 -0
- eegdash-0.3.8/docs/source/api/eegdash.features.serialization.rst +7 -0
- eegdash-0.3.8/docs/source/api/eegdash.features.utils.rst +7 -0
- eegdash-0.3.8/docs/source/api/eegdash.mongodb.rst +7 -0
- eegdash-0.3.8/docs/source/api/eegdash.paths.rst +7 -0
- eegdash-0.3.8/docs/source/api/eegdash.rst +30 -0
- eegdash-0.3.8/docs/source/api/eegdash.utils.rst +7 -0
- eegdash-0.3.8/docs/source/api/modules.rst +7 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/docs/source/conf.py +69 -1
- eegdash-0.3.8/docs/source/generated/auto_examples/core/sg_execution_times.rst +43 -0
- eegdash-0.3.8/docs/source/generated/auto_examples/core/tutorial_eegdash_offline.ipynb +72 -0
- eegdash-0.3.8/docs/source/generated/auto_examples/core/tutorial_eegdash_offline.rst +331 -0
- eegdash-0.3.8/docs/source/generated/auto_examples/core/tutorial_eoec.ipynb +187 -0
- eegdash-0.3.8/docs/source/generated/auto_examples/core/tutorial_eoec.rst +595 -0
- eegdash-0.3.8/docs/source/generated/auto_examples/core/tutorial_feature_extractor_open_close_eye.ipynb +253 -0
- eegdash-0.3.8/docs/source/generated/auto_examples/core/tutorial_feature_extractor_open_close_eye.rst +4392 -0
- eegdash-0.3.8/docs/source/generated/auto_examples/eeg2025/sg_execution_times.rst +40 -0
- eegdash-0.3.8/docs/source/generated/auto_examples/eeg2025/tutorial_challenge_1.ipynb +283 -0
- eegdash-0.3.8/docs/source/generated/auto_examples/eeg2025/tutorial_challenge_1.rst +615 -0
- eegdash-0.3.8/docs/source/generated/auto_examples/eeg2025/tutorial_challenge_2.ipynb +388 -0
- eegdash-0.3.8/docs/source/generated/auto_examples/eeg2025/tutorial_challenge_2.rst +530 -0
- eegdash-0.3.8/docs/source/generated/auto_examples/index.rst +178 -0
- eegdash-0.3.8/docs/source/generated/auto_examples/sg_execution_times.rst +37 -0
- eegdash-0.3.8/docs/source/sg_execution_times.rst +43 -0
- eegdash-0.3.8/eegdash/__init__.py +10 -0
- eegdash-0.3.8/eegdash/api.py +1047 -0
- eegdash-0.3.8/eegdash/bids_eeg_metadata.py +254 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/eegdash/const.py +48 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/eegdash/data_utils.py +177 -45
- eegdash-0.3.8/eegdash/dataset/__init__.py +4 -0
- {eegdash-0.3.7.dev177024734/eegdash → eegdash-0.3.8/eegdash/dataset}/dataset.py +53 -10
- eegdash-0.3.8/eegdash/dataset/dataset_summary.csv +256 -0
- {eegdash-0.3.7.dev177024734/eegdash → eegdash-0.3.8/eegdash/dataset}/registry.py +3 -3
- eegdash-0.3.8/eegdash/hbn/__init__.py +17 -0
- eegdash-0.3.8/eegdash/hbn/windows.py +305 -0
- eegdash-0.3.8/eegdash/paths.py +28 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/eegdash/utils.py +1 -1
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8/eegdash.egg-info}/PKG-INFO +11 -5
- eegdash-0.3.8/eegdash.egg-info/SOURCES.txt +107 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/eegdash.egg-info/requires.txt +1 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/pyproject.toml +8 -6
- eegdash-0.3.8/tests/test_cache_folder_suffix.py +59 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/tests/test_challenge_kwargs.py +1 -1
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/tests/test_correctness.py +1 -1
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/tests/test_dataset.py +36 -6
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/tests/test_dataset_registration.py +3 -1
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/tests/test_functional.py +1 -1
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/tests/test_minirelease.py +1 -1
- eegdash-0.3.8/tests/test_offline.py +156 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/tests/test_query.py +3 -2
- eegdash-0.3.7.dev177024734/eegdash/__init__.py +0 -10
- eegdash-0.3.7.dev177024734/eegdash/api.py +0 -979
- eegdash-0.3.7.dev177024734/eegdash/data_config.py +0 -34
- eegdash-0.3.7.dev177024734/eegdash/dataset_summary.csv +0 -256
- eegdash-0.3.7.dev177024734/eegdash.egg-info/SOURCES.txt +0 -56
- eegdash-0.3.7.dev177024734/tests/test_database.py +0 -0
- eegdash-0.3.7.dev177024734/tests/test_offline.py +0 -51
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/LICENSE +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/docs/source/dataset_summary.rst +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/docs/source/index.rst +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/docs/source/install/install.rst +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/docs/source/install/install_pip.rst +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/docs/source/install/install_source.rst +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/docs/source/overview.rst +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/eegdash/features/__init__.py +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/eegdash/features/datasets.py +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/eegdash/features/decorators.py +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/eegdash/features/extractors.py +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/eegdash/features/feature_bank/__init__.py +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/eegdash/features/feature_bank/complexity.py +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/eegdash/features/feature_bank/connectivity.py +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/eegdash/features/feature_bank/csp.py +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/eegdash/features/feature_bank/dimensionality.py +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/eegdash/features/feature_bank/signal.py +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/eegdash/features/feature_bank/spectral.py +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/eegdash/features/feature_bank/utils.py +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/eegdash/features/inspect.py +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/eegdash/features/serialization.py +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/eegdash/features/utils.py +0 -0
- {eegdash-0.3.7.dev177024734/eegdash → eegdash-0.3.8/eegdash/hbn}/preprocessing.py +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/eegdash/mongodb.py +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/eegdash.egg-info/dependency_links.txt +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/eegdash.egg-info/top_level.txt +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/setup.cfg +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/tests/test_api.py +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/tests/test_eegdash.py +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/tests/test_init.py +0 -0
- {eegdash-0.3.7.dev177024734 → eegdash-0.3.8}/tests/test_mongo_connection.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: eegdash
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.8
|
|
4
4
|
Summary: EEG data for machine learning
|
|
5
5
|
Author-email: Young Truong <dt.young112@gmail.com>, Arnaud Delorme <adelorme@gmail.com>, Aviv Dotan <avivd220@gmail.com>, Oren Shriki <oren70@gmail.com>, Bruno Aristimunha <b.aristimunha@gmail.com>
|
|
6
6
|
License-Expression: GPL-3.0-only
|
|
@@ -40,6 +40,7 @@ Requires-Dist: h5io>=0.2.4
|
|
|
40
40
|
Requires-Dist: pymatreader
|
|
41
41
|
Requires-Dist: eeglabio
|
|
42
42
|
Requires-Dist: tabulate
|
|
43
|
+
Requires-Dist: docstring_inheritance
|
|
43
44
|
Provides-Extra: tests
|
|
44
45
|
Requires-Dist: pytest; extra == "tests"
|
|
45
46
|
Requires-Dist: pytest-cov; extra == "tests"
|
|
@@ -106,7 +107,7 @@ EEGDash queries return a **Pytorch Dataset** formatted to facilitate machine lea
|
|
|
106
107
|
|
|
107
108
|
## Data preprocessing
|
|
108
109
|
|
|
109
|
-
EEGDash datasets are processed using the popular [
|
|
110
|
+
EEGDash datasets are processed using the popular [braindecode](https://braindecode.org/stable/index.html) library. In fact, EEGDash datasets are braindecode datasets, which are themselves PyTorch datasets. This means that any preprocessing possible on braindecode datasets is also possible on EEGDash datasets. Refer to [braindecode](https://braindecode.org/stable/index.html) tutorials for guidance on preprocessing EEG data.
|
|
110
111
|
|
|
111
112
|
## EEG-Dash usage
|
|
112
113
|
|
|
@@ -129,7 +130,7 @@ ds_NDARDB033FW5 = EEGDashDataset(
|
|
|
129
130
|
)
|
|
130
131
|
```
|
|
131
132
|
|
|
132
|
-
This will search and download the metadata for the task **RestingState** for subject **NDARDB033FW5** in BIDS dataset **ds005514**. The actual data will not be downloaded at this stage. Following standard practice, data is only downloaded once it is processed. The **ds_NDARDB033FW5** object is a fully functional
|
|
133
|
+
This will search and download the metadata for the task **RestingState** for subject **NDARDB033FW5** in BIDS dataset **ds005514**. The actual data will not be downloaded at this stage. Following standard practice, data is only downloaded once it is processed. The **ds_NDARDB033FW5** object is a fully functional braindecode dataset, which is itself a PyTorch dataset. This [tutorial](https://github.com/sccn/EEGDash/blob/develop/notebooks/tutorial_eoec.ipynb) shows how to preprocess the EEG data, extracting portions of the data containing eyes-open and eyes-closed segments, then perform eyes-open vs. eyes-closed classification using a (shallow) deep-learning model.
|
|
133
134
|
|
|
134
135
|
To use the data from multiple subjects, enter:
|
|
135
136
|
|
|
@@ -145,7 +146,13 @@ This will search and download the metadata for the task 'RestingState' for all s
|
|
|
145
146
|
|
|
146
147
|
### Automatic caching
|
|
147
148
|
|
|
148
|
-
EEGDash
|
|
149
|
+
By default, EEGDash caches downloaded data under a single, consistent folder:
|
|
150
|
+
|
|
151
|
+
- If ``EEGDASH_CACHE_DIR`` is set in your environment, that path is used.
|
|
152
|
+
- Else, if MNE’s ``MNE_DATA`` config is set, that path is used to align with other EEG tooling.
|
|
153
|
+
- Otherwise, ``.eegdash_cache`` in the current working directory is used.
|
|
154
|
+
|
|
155
|
+
This means that if you run the tutorial [scripts](https://github.com/sccn/EEGDash/tree/develop/notebooks), the data will only be downloaded the first time the script is executed and reused thereafter.
|
|
149
156
|
|
|
150
157
|
## Education -- Coming soon...
|
|
151
158
|
|
|
@@ -159,4 +166,3 @@ EEG-DaSh is a collaborative initiative between the United States and Israel, sup
|
|
|
159
166
|
|
|
160
167
|
|
|
161
168
|
|
|
162
|
-
|
|
@@ -36,7 +36,7 @@ EEGDash queries return a **Pytorch Dataset** formatted to facilitate machine lea
|
|
|
36
36
|
|
|
37
37
|
## Data preprocessing
|
|
38
38
|
|
|
39
|
-
EEGDash datasets are processed using the popular [
|
|
39
|
+
EEGDash datasets are processed using the popular [braindecode](https://braindecode.org/stable/index.html) library. In fact, EEGDash datasets are braindecode datasets, which are themselves PyTorch datasets. This means that any preprocessing possible on braindecode datasets is also possible on EEGDash datasets. Refer to [braindecode](https://braindecode.org/stable/index.html) tutorials for guidance on preprocessing EEG data.
|
|
40
40
|
|
|
41
41
|
## EEG-Dash usage
|
|
42
42
|
|
|
@@ -59,7 +59,7 @@ ds_NDARDB033FW5 = EEGDashDataset(
|
|
|
59
59
|
)
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
This will search and download the metadata for the task **RestingState** for subject **NDARDB033FW5** in BIDS dataset **ds005514**. The actual data will not be downloaded at this stage. Following standard practice, data is only downloaded once it is processed. The **ds_NDARDB033FW5** object is a fully functional
|
|
62
|
+
This will search and download the metadata for the task **RestingState** for subject **NDARDB033FW5** in BIDS dataset **ds005514**. The actual data will not be downloaded at this stage. Following standard practice, data is only downloaded once it is processed. The **ds_NDARDB033FW5** object is a fully functional braindecode dataset, which is itself a PyTorch dataset. This [tutorial](https://github.com/sccn/EEGDash/blob/develop/notebooks/tutorial_eoec.ipynb) shows how to preprocess the EEG data, extracting portions of the data containing eyes-open and eyes-closed segments, then perform eyes-open vs. eyes-closed classification using a (shallow) deep-learning model.
|
|
63
63
|
|
|
64
64
|
To use the data from multiple subjects, enter:
|
|
65
65
|
|
|
@@ -75,7 +75,13 @@ This will search and download the metadata for the task 'RestingState' for all s
|
|
|
75
75
|
|
|
76
76
|
### Automatic caching
|
|
77
77
|
|
|
78
|
-
EEGDash
|
|
78
|
+
By default, EEGDash caches downloaded data under a single, consistent folder:
|
|
79
|
+
|
|
80
|
+
- If ``EEGDASH_CACHE_DIR`` is set in your environment, that path is used.
|
|
81
|
+
- Else, if MNE’s ``MNE_DATA`` config is set, that path is used to align with other EEG tooling.
|
|
82
|
+
- Otherwise, ``.eegdash_cache`` in the current working directory is used.
|
|
83
|
+
|
|
84
|
+
This means that if you run the tutorial [scripts](https://github.com/sccn/EEGDash/tree/develop/notebooks), the data will only be downloaded the first time the script is executed and reused thereafter.
|
|
79
85
|
|
|
80
86
|
## Education -- Coming soon...
|
|
81
87
|
|
|
@@ -89,4 +95,3 @@ EEG-DaSh is a collaborative initiative between the United States and Israel, sup
|
|
|
89
95
|
|
|
90
96
|
|
|
91
97
|
|
|
92
|
-
|
|
@@ -11,7 +11,7 @@ help:
|
|
|
11
11
|
|
|
12
12
|
.PHONY: apidoc
|
|
13
13
|
apidoc:
|
|
14
|
-
@sphinx
|
|
14
|
+
@python -m sphinx.ext.apidoc -o "$(APIDIR)" "../$(PKG)" -f -e -M
|
|
15
15
|
|
|
16
16
|
# Standard build runs examples
|
|
17
17
|
html: apidoc
|
|
@@ -28,4 +28,4 @@ Makefile: ;
|
|
|
28
28
|
|
|
29
29
|
%: Makefile
|
|
30
30
|
@python prepare_summary_tables.py ../eegdash/ $(BUILDDIR)
|
|
31
|
-
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
31
|
+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
eegdash-0.3.8/docs/build/html/_downloads/06c8d94b7e0b8be2de39fdc122dd12bb/tutorial_challenge_2.ipynb
ADDED
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "code",
|
|
5
|
+
"execution_count": null,
|
|
6
|
+
"metadata": {
|
|
7
|
+
"collapsed": false
|
|
8
|
+
},
|
|
9
|
+
"outputs": [],
|
|
10
|
+
"source": [
|
|
11
|
+
"# For tips on running notebooks in Google Colab:\n# `pip install eegdash`\n%matplotlib inline"
|
|
12
|
+
]
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"cell_type": "markdown",
|
|
16
|
+
"metadata": {},
|
|
17
|
+
"source": [
|
|
18
|
+
"\n# Challenge 2: Predicting the p-factor from EEG\n :depth: 2\n"
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"cell_type": "markdown",
|
|
23
|
+
"metadata": {},
|
|
24
|
+
"source": [
|
|
25
|
+
"<img src=\"https://colab.research.google.com/assets/colab-badge.svg\" target=\"https://colab.research.google.com/github/eeg2025/startkit/blob/main/challenge_2.ipynb\" alt=\"Open In Colab\">\n\n"
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"cell_type": "markdown",
|
|
30
|
+
"metadata": {},
|
|
31
|
+
"source": [
|
|
32
|
+
"## Overview\n\n"
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"cell_type": "code",
|
|
37
|
+
"execution_count": null,
|
|
38
|
+
"metadata": {
|
|
39
|
+
"collapsed": false
|
|
40
|
+
},
|
|
41
|
+
"outputs": [],
|
|
42
|
+
"source": [
|
|
43
|
+
"# The psychopathology factor (P-factor) is a widely recognized construct in mental health research, representing a common underlying dimension of psychopathology across various disorders.\n# Currently, the P-factor is often assessed using self-report questionnaires or clinician ratings, which can be subjective, prone to bias, and time-consuming.\n# **The Challenge 2** consists of developing a model to predict the P-factor from EEG recordings.\n\n# The challenge encourages learning physiologically meaningful signal representations and discovery of reproducible biomarkers.\n# Models of any size should emphasize robust, interpretable features that generalize across subjects,\n# sessions, and acquisition sites.\n\n# Unlike a standard in-distribution classification task, this regression problem stresses out-of-distribution robustness\n# and extrapolation. The goal is not only to minimize error on seen subjects, but also to transfer effectively to unseen data.\n\n# Ensure the dataset is available locally. If not, see the\n# `dataset download guide <https://eeg2025.github.io/data/#downloading-the-data>`__."
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"cell_type": "markdown",
|
|
48
|
+
"metadata": {},
|
|
49
|
+
"source": [
|
|
50
|
+
"## Contents of this start kit\n\n"
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"cell_type": "code",
|
|
55
|
+
"execution_count": null,
|
|
56
|
+
"metadata": {
|
|
57
|
+
"collapsed": false
|
|
58
|
+
},
|
|
59
|
+
"outputs": [],
|
|
60
|
+
"source": [
|
|
61
|
+
"# 0. Understand the P-factor regression task.\n# 1. Loading the data.\n# 2. Wrap the data into a PyTorch-compatible dataset.\n# 3. Define, train and save a model.\n\n# .. note:: If you need additional explanations on the\n# `EEGChallengeDataset <https://eeglab.org/EEGDash/api/eegdash.html#eegdash.EEGChallengeDataset>`__\n# class, dataloading, `braindecode <https://braindecode.org/stable/models/models_table.html>`__'s\n# deep learning models, or brain decoding in general, please refer to the\n# start-kit of challenge 1 which delves deeper into these topics.\n\n# More contents will be released during the competition inside the [`eegdash`](https://eeglab.org/EEGDash/overview.html) [examples webpage](https://eeglab.org/EEGDash/generated/auto_examples/index.html).\n\n# We will establish direct communication channels with you over the next two months, resolve platform issues, and discuss other details.\n\n# We are going to do weekly one-hour support time to help teams that may have difficulties with any technical aspects that may arise.\n\n# We will have closer communication starting next week, 08/09/2025.\n\n# Before we begin, I just want to make a deal with you, ok?\n\n# This is a community competition with a strong open-source foundation. When I say open-source, I mean volunteer work.\n\n# So, if you see something that does not work or could be improved, first, **please be kind**, and we will fix it together on GitHub, okay?\n\n# The entire decoding community will only go further when we stop solving the same problems over and over again, and start working together."
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"cell_type": "markdown",
|
|
66
|
+
"metadata": {},
|
|
67
|
+
"source": [
|
|
68
|
+
"::\n\n ----\n | The tutorial assumes some prior knowledge of deep learning concepts and EEG concepts:|\n | --- |\n |* Standard neural network architectures, e.g., convolutional neural networks|\n |* Optimization by batch gradient descent and backpropagation|\n |* Overfitting, early stopping, regularisation |\n |* Some knowledge of pytorch |\n |* That you know what EEG is |\n |* That you have basic familiarity with EEG preprocessing |\n |* Like and support open-source :) |\n ----\n\n"
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"cell_type": "markdown",
|
|
73
|
+
"metadata": {},
|
|
74
|
+
"source": [
|
|
75
|
+
"Install dependencies on colab\n -----------------------------\n tags:[\"hide-input\"]\n!pip install braindecode\n!pip install eegdash\n\n"
|
|
76
|
+
]
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"cell_type": "markdown",
|
|
80
|
+
"metadata": {},
|
|
81
|
+
"source": [
|
|
82
|
+
"## Imports\ntags:[\"hide-input\"]\n\n"
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"cell_type": "code",
|
|
87
|
+
"execution_count": null,
|
|
88
|
+
"metadata": {
|
|
89
|
+
"collapsed": false
|
|
90
|
+
},
|
|
91
|
+
"outputs": [],
|
|
92
|
+
"source": [
|
|
93
|
+
"from pathlib import Path\nimport math\nimport os\nimport random\nfrom joblib import Parallel, delayed\n\nimport torch\nfrom torch.utils.data import DataLoader\nfrom torch import optim\nfrom torch.nn.functional import l1_loss\nfrom braindecode.preprocessing import create_fixed_length_windows\nfrom braindecode.datasets.base import EEGWindowsDataset, BaseConcatDataset, BaseDataset\nfrom braindecode.models import EEGNeX\nfrom eegdash import EEGChallengeDataset"
|
|
94
|
+
]
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"cell_type": "markdown",
|
|
98
|
+
"metadata": {},
|
|
99
|
+
"source": [
|
|
100
|
+
"<div class=\"alert alert-danger\"><h4>Warning</h4><p>In case of Colab, before starting, make sure you're on a GPU instance\n for faster training! If running on Google Colab, please request a GPU runtime\n by clicking `Runtime/Change runtime type` in the top bar menu, then selecting\n 'T4 GPU' under 'Hardware accelerator'.</p></div>\n\n"
|
|
101
|
+
]
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"cell_type": "markdown",
|
|
105
|
+
"metadata": {},
|
|
106
|
+
"source": [
|
|
107
|
+
"## Identify whether a CUDA-enabled GPU is available\ntags:[\"hide-input\"]\n\n"
|
|
108
|
+
]
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"cell_type": "code",
|
|
112
|
+
"execution_count": null,
|
|
113
|
+
"metadata": {
|
|
114
|
+
"collapsed": false
|
|
115
|
+
},
|
|
116
|
+
"outputs": [],
|
|
117
|
+
"source": [
|
|
118
|
+
"device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\nif device == \"cuda\":\n msg = \"CUDA-enabled GPU found. Training should be faster.\"\nelse:\n msg = (\n \"No GPU found. Training will be carried out on CPU, which might be \"\n \"slower.\\n\\nIf running on Google Colab, you can request a GPU runtime by\"\n \" clicking\\n`Runtime/Change runtime type` in the top bar menu, then \"\n \"selecting 'T4 GPU'\\nunder 'Hardware accelerator'.\"\n )\nprint(msg)"
|
|
119
|
+
]
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"cell_type": "markdown",
|
|
123
|
+
"metadata": {},
|
|
124
|
+
"source": [
|
|
125
|
+
"## 0. Understanding the P-factor regression task.\n\nThe psychopathology factor (P-factor) is a widely recognized construct in mental health research, representing a common underlying dimension of psychopathology across various disorders.\nThe P-factor is thought to reflect the shared variance among different psychiatric conditions, suggesting that individuals with higher P-factor scores may be more vulnerable to a range of mental health issues.\nCurrently, the P-factor is often assessed using self-report questionnaires or clinician ratings, which can be subjective, prone to bias, and time-consuming.\nIn the dataset of this challenge, the P-factor was assessed using the Child Behavior Checklist (CBCL) [McElroy et al., (2017)](https://doi.org/10.1111/jcpp.12849).\n\n"
|
|
126
|
+
]
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"cell_type": "code",
|
|
130
|
+
"execution_count": null,
|
|
131
|
+
"metadata": {
|
|
132
|
+
"collapsed": false
|
|
133
|
+
},
|
|
134
|
+
"outputs": [],
|
|
135
|
+
"source": [
|
|
136
|
+
"# The goal of Challenge 2 is to develop a model to predict the P-factor from EEG recordings.\n# **The feasibility of using EEG data for this purpose is still an open question**.\n# The solution may involve finding meaningful representations of the EEG data that correlate with the P-factor scores.\n# The challenge encourages learning physiologically meaningful signal representations and discovery of reproducible biomarkers.\n# If contestants are successful in this task, it could pave the way for more objective and efficient assessments of the P-factor in clinical settings."
|
|
137
|
+
]
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"cell_type": "markdown",
|
|
141
|
+
"metadata": {},
|
|
142
|
+
"source": [
|
|
143
|
+
"## 1. Loading the data\n\n"
|
|
144
|
+
]
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"cell_type": "code",
|
|
148
|
+
"execution_count": null,
|
|
149
|
+
"metadata": {
|
|
150
|
+
"collapsed": false
|
|
151
|
+
},
|
|
152
|
+
"outputs": [],
|
|
153
|
+
"source": [
|
|
154
|
+
"# A. Define local path and (down)load the data\n# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n# In this challenge 2 example, we load the EEG 2025 release using EEG Dash.\n\n# > **Note:** in this example notebook, we load the contrast change detection task from one mini release only as an example. Naturally, you are encouraged to train your models on all complete releases, using data from all the tasks you deem relevant."
|
|
155
|
+
]
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"cell_type": "markdown",
|
|
159
|
+
"metadata": {},
|
|
160
|
+
"source": [
|
|
161
|
+
"The first step is to define the cache folder!\n\n"
|
|
162
|
+
]
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"cell_type": "code",
|
|
166
|
+
"execution_count": null,
|
|
167
|
+
"metadata": {
|
|
168
|
+
"collapsed": false
|
|
169
|
+
},
|
|
170
|
+
"outputs": [],
|
|
171
|
+
"source": [
|
|
172
|
+
"DATA_DIR = Path(\"~/eegdash/eeg2025_competition\")\n\n# Creating the path if it does not exist\nDATA_DIR.mkdir(parents=True, exist_ok=True)\n\n# We define the list of releases to load.\n# Here, only release 5 is loaded.\nrelease_list = [\"R5\"]\n\nall_datasets_list = [\n EEGChallengeDataset(\n release=release,\n task=\"contrastChangeDetection\",\n mini=True,\n description_fields=[\n \"subject\",\n \"session\",\n \"run\",\n \"task\",\n \"age\",\n \"gender\",\n \"sex\",\n \"p_factor\",\n ],\n cache_dir=DATA_DIR,\n )\n for release in release_list\n]\nprint(\"Datasets loaded\")\nsub_rm = [\"NDARWV769JM7\"]"
|
|
173
|
+
]
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"cell_type": "markdown",
|
|
177
|
+
"metadata": {},
|
|
178
|
+
"source": [
|
|
179
|
+
"### B. Combine the datasets into a single one\n\n"
|
|
180
|
+
]
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
"cell_type": "code",
|
|
184
|
+
"execution_count": null,
|
|
185
|
+
"metadata": {
|
|
186
|
+
"collapsed": false
|
|
187
|
+
},
|
|
188
|
+
"outputs": [],
|
|
189
|
+
"source": [
|
|
190
|
+
"# Here, we combine the datasets from the different releases into a single\n# ``BaseConcatDataset`` object."
|
|
191
|
+
]
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"cell_type": "code",
|
|
195
|
+
"execution_count": null,
|
|
196
|
+
"metadata": {
|
|
197
|
+
"collapsed": false
|
|
198
|
+
},
|
|
199
|
+
"outputs": [],
|
|
200
|
+
"source": [
|
|
201
|
+
"all_datasets = BaseConcatDataset(all_datasets_list)\nprint(all_datasets.description)\n\nraws = Parallel(n_jobs=os.cpu_count())(\n delayed(lambda d: d.raw)(d) for d in all_datasets.datasets\n)"
|
|
202
|
+
]
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"cell_type": "markdown",
|
|
206
|
+
"metadata": {},
|
|
207
|
+
"source": [
|
|
208
|
+
"### C. Inspect your data\n\n"
|
|
209
|
+
]
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"cell_type": "code",
|
|
213
|
+
"execution_count": null,
|
|
214
|
+
"metadata": {
|
|
215
|
+
"collapsed": false
|
|
216
|
+
},
|
|
217
|
+
"outputs": [],
|
|
218
|
+
"source": [
|
|
219
|
+
"# We can check what is inside the dataset consuming the\n# MNE-object inside the Braindecode dataset.\n#\n# The following snippet, if uncommented, will show the first 10 seconds of the raw EEG signal.\n# We can also inspect the data further by looking at the events and annotations.\n# We strongly recommend you to take a look into the details and check how the events are structured."
|
|
220
|
+
]
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
"cell_type": "markdown",
|
|
224
|
+
"metadata": {},
|
|
225
|
+
"source": [
|
|
226
|
+
"raw = all_datasets.datasets[0].raw # mne.io.Raw object\nprint(raw.info)\n\n"
|
|
227
|
+
]
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
"cell_type": "code",
|
|
231
|
+
"execution_count": null,
|
|
232
|
+
"metadata": {
|
|
233
|
+
"collapsed": false
|
|
234
|
+
},
|
|
235
|
+
"outputs": [],
|
|
236
|
+
"source": [
|
|
237
|
+
"# raw.plot(duration=10, scalings=\"auto\", show=True)\n\n# print(raw.annotations)\n\nSFREQ = 100"
|
|
238
|
+
]
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
"cell_type": "markdown",
|
|
242
|
+
"metadata": {},
|
|
243
|
+
"source": [
|
|
244
|
+
"## 2. Wrap the data into a PyTorch-compatible dataset\n\n"
|
|
245
|
+
]
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
"cell_type": "code",
|
|
249
|
+
"execution_count": null,
|
|
250
|
+
"metadata": {
|
|
251
|
+
"collapsed": false
|
|
252
|
+
},
|
|
253
|
+
"outputs": [],
|
|
254
|
+
"source": [
|
|
255
|
+
"# The class below defines a dataset wrapper that will extract 2-second windows,\n# uniformly sampled over the whole signal. In addition, it will add useful information\n# about the extracted windows, such as the p-factor, the subject or the task."
|
|
256
|
+
]
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
"cell_type": "code",
|
|
260
|
+
"execution_count": null,
|
|
261
|
+
"metadata": {
|
|
262
|
+
"collapsed": false
|
|
263
|
+
},
|
|
264
|
+
"outputs": [],
|
|
265
|
+
"source": [
|
|
266
|
+
"class DatasetWrapper(BaseDataset):\n def __init__(self, dataset: EEGWindowsDataset, crop_size_samples: int, seed=None):\n self.dataset = dataset\n self.crop_size_samples = crop_size_samples\n self.rng = random.Random(seed)\n\n def __len__(self):\n return len(self.dataset)\n\n def __getitem__(self, index):\n X, _, crop_inds = self.dataset[index]\n\n # P-factor label:\n p_factor = self.dataset.description[\"p_factor\"]\n p_factor = float(p_factor)\n\n # Additional information:\n infos = {\n \"subject\": self.dataset.description[\"subject\"],\n \"sex\": self.dataset.description[\"sex\"],\n \"age\": float(self.dataset.description[\"age\"]),\n \"task\": self.dataset.description[\"task\"],\n \"session\": self.dataset.description.get(\"session\", None) or \"\",\n \"run\": self.dataset.description.get(\"run\", None) or \"\",\n }\n\n # Randomly crop the signal to the desired length:\n i_window_in_trial, i_start, i_stop = crop_inds\n assert i_stop - i_start >= self.crop_size_samples, f\"{i_stop=} {i_start=}\"\n start_offset = self.rng.randint(0, i_stop - i_start - self.crop_size_samples)\n i_start = i_start + start_offset\n i_stop = i_start + self.crop_size_samples\n X = X[:, start_offset : start_offset + self.crop_size_samples]\n\n return X, p_factor, (i_window_in_trial, i_start, i_stop), infos"
|
|
267
|
+
]
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
"cell_type": "markdown",
|
|
271
|
+
"metadata": {},
|
|
272
|
+
"source": [
|
|
273
|
+
"We filter out certain recordings, create fixed length windows and finally make use of our `DatasetWrapper`.\n\n"
|
|
274
|
+
]
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
"cell_type": "markdown",
|
|
278
|
+
"metadata": {},
|
|
279
|
+
"source": [
|
|
280
|
+
"Filter out recordings that are too short\n\n"
|
|
281
|
+
]
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
"cell_type": "code",
|
|
285
|
+
"execution_count": null,
|
|
286
|
+
"metadata": {
|
|
287
|
+
"collapsed": false
|
|
288
|
+
},
|
|
289
|
+
"outputs": [],
|
|
290
|
+
"source": [
|
|
291
|
+
"all_datasets = BaseConcatDataset(\n [\n ds\n for ds in all_datasets.datasets\n if ds.description.subject not in sub_rm\n and ds.raw.n_times >= 4 * SFREQ\n and len(ds.raw.ch_names) == 129\n and not math.isnan(ds.description[\"p_factor\"])\n ]\n)\n\n# Create 4-seconds windows with 2-seconds stride\nwindows_ds = create_fixed_length_windows(\n all_datasets,\n window_size_samples=4 * SFREQ,\n window_stride_samples=2 * SFREQ,\n drop_last_window=True,\n)\n\n# Wrap each sub-dataset in the windows_ds\nwindows_ds = BaseConcatDataset(\n [DatasetWrapper(ds, crop_size_samples=2 * SFREQ) for ds in windows_ds.datasets]\n)"
|
|
292
|
+
]
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
"cell_type": "markdown",
|
|
296
|
+
"metadata": {},
|
|
297
|
+
"source": [
|
|
298
|
+
"## 3. Define, train and save a model\n\n"
|
|
299
|
+
]
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
"cell_type": "code",
|
|
303
|
+
"execution_count": null,
|
|
304
|
+
"metadata": {
|
|
305
|
+
"collapsed": false
|
|
306
|
+
},
|
|
307
|
+
"outputs": [],
|
|
308
|
+
"source": [
|
|
309
|
+
"# Now we have our pytorch dataset necessary for the training!\n#\n# Below, we define a simple EEGNeX model from Braindecode.\n# All the braindecode models expect the input to be of shape (batch_size, n_channels, n_times)\n# and have a test coverage about the behavior of the model.\n# However, you can use any pytorch model you want."
|
|
310
|
+
]
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
"cell_type": "markdown",
|
|
314
|
+
"metadata": {},
|
|
315
|
+
"source": [
|
|
316
|
+
"Initialize model\n\n"
|
|
317
|
+
]
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
"cell_type": "code",
|
|
321
|
+
"execution_count": null,
|
|
322
|
+
"metadata": {
|
|
323
|
+
"collapsed": false
|
|
324
|
+
},
|
|
325
|
+
"outputs": [],
|
|
326
|
+
"source": [
|
|
327
|
+
"model = EEGNeX(n_chans=129, n_outputs=1, n_times=2 * SFREQ).to(device)\n\n# Specify optimizer\noptimizer = optim.Adamax(params=model.parameters(), lr=0.002)\n\nprint(model)"
|
|
328
|
+
]
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
"cell_type": "markdown",
|
|
332
|
+
"metadata": {},
|
|
333
|
+
"source": [
|
|
334
|
+
"Finally, we can train our model. Here we define a simple training loop using pure PyTorch.\n\n"
|
|
335
|
+
]
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
"cell_type": "code",
|
|
339
|
+
"execution_count": null,
|
|
340
|
+
"metadata": {
|
|
341
|
+
"collapsed": false
|
|
342
|
+
},
|
|
343
|
+
"outputs": [],
|
|
344
|
+
"source": [
|
|
345
|
+
"# > In this example, we only train for a single epoch. Feel free to increase the number of epochs."
|
|
346
|
+
]
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
"cell_type": "markdown",
|
|
350
|
+
"metadata": {},
|
|
351
|
+
"source": [
|
|
352
|
+
"Create PyTorch Dataloader\n\n"
|
|
353
|
+
]
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
"cell_type": "code",
|
|
357
|
+
"execution_count": null,
|
|
358
|
+
"metadata": {
|
|
359
|
+
"collapsed": false
|
|
360
|
+
},
|
|
361
|
+
"outputs": [],
|
|
362
|
+
"source": [
|
|
363
|
+
"num_workers = (\n 0 # Set num_workers to 0 to avoid multiprocessing issues in notebooks/tutorials.\n)\ndataloader = DataLoader(\n windows_ds, batch_size=128, shuffle=True, num_workers=num_workers\n)\n\nn_epochs = 1\n\n# Train model for 1 epoch\nfor epoch in range(n_epochs):\n for idx, batch in enumerate(dataloader):\n # Reset gradients\n optimizer.zero_grad()\n\n # Unpack the batch\n X, y, crop_inds, infos = batch\n X = X.to(dtype=torch.float32, device=device)\n y = y.to(dtype=torch.float32, device=device).unsqueeze(1)\n\n # Forward pass\n y_pred = model(X)\n\n # Compute loss\n loss = l1_loss(y_pred, y)\n print(f\"Epoch {0} - step {idx}, loss: {loss.item()}\")\n\n # Gradient backpropagation\n loss.backward()\n optimizer.step()\n\n# Finally, we can save the model for later use\ntorch.save(model.state_dict(), \"weights_challenge_2.pt\")\nprint(\"Model saved as 'weights_challenge_2.pt'\")"
|
|
364
|
+
]
|
|
365
|
+
}
|
|
366
|
+
],
|
|
367
|
+
"metadata": {
|
|
368
|
+
"kernelspec": {
|
|
369
|
+
"display_name": "Python 3",
|
|
370
|
+
"language": "python",
|
|
371
|
+
"name": "python3"
|
|
372
|
+
},
|
|
373
|
+
"language_info": {
|
|
374
|
+
"codemirror_mode": {
|
|
375
|
+
"name": "ipython",
|
|
376
|
+
"version": 3
|
|
377
|
+
},
|
|
378
|
+
"file_extension": ".py",
|
|
379
|
+
"mimetype": "text/x-python",
|
|
380
|
+
"name": "python",
|
|
381
|
+
"nbconvert_exporter": "python",
|
|
382
|
+
"pygments_lexer": "ipython3",
|
|
383
|
+
"version": "3.11.0"
|
|
384
|
+
}
|
|
385
|
+
},
|
|
386
|
+
"nbformat": 4,
|
|
387
|
+
"nbformat_minor": 0
|
|
388
|
+
}
|