moecog 0.1.0__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.
moecog-0.1.0/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Yifan Yu
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
moecog-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,260 @@
1
+ Metadata-Version: 2.4
2
+ Name: moecog
3
+ Version: 0.1.0
4
+ Summary: Mother of All ECoG Benchmarks — MOABB-style benchmarking for ECoG motor decoding
5
+ Author-email: Yifan Yu <yifanyu97@gmail.com>
6
+ License-Expression: BSD-3-Clause
7
+ Project-URL: Homepage, https://github.com/epyifany/MOECoG
8
+ Project-URL: Repository, https://github.com/epyifany/MOECoG
9
+ Project-URL: Issues, https://github.com/epyifany/MOECoG/issues
10
+ Keywords: ECoG,electrocorticography,BCI,brain-computer interface,motor decoding,benchmark,neuroscience,neural decoding
11
+ Classifier: Development Status :: 2 - Pre-Alpha
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Scientific/Engineering
20
+ Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
21
+ Requires-Python: >=3.10
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: mne>=1.5
25
+ Requires-Dist: numpy>=1.24
26
+ Requires-Dist: scipy>=1.10
27
+ Requires-Dist: scikit-learn>=1.3
28
+ Requires-Dist: pandas>=2.0
29
+ Requires-Dist: h5py>=3.8
30
+ Requires-Dist: pooch>=1.7
31
+ Requires-Dist: tqdm>=4.65
32
+ Provides-Extra: deep
33
+ Requires-Dist: torch>=2.0; extra == "deep"
34
+ Requires-Dist: braindecode>=0.8; extra == "deep"
35
+ Provides-Extra: nwb
36
+ Requires-Dist: pynwb>=2.5; extra == "nwb"
37
+ Requires-Dist: dandi>=0.55; extra == "nwb"
38
+ Provides-Extra: viz
39
+ Requires-Dist: matplotlib>=3.7; extra == "viz"
40
+ Requires-Dist: seaborn>=0.12; extra == "viz"
41
+ Provides-Extra: anatomy
42
+ Requires-Dist: nilearn>=0.10; extra == "anatomy"
43
+ Requires-Dist: nibabel>=5.0; extra == "anatomy"
44
+ Provides-Extra: dev
45
+ Requires-Dist: moecog[anatomy,deep,nwb,viz]; extra == "dev"
46
+ Requires-Dist: pytest>=7.4; extra == "dev"
47
+ Requires-Dist: pytest-cov>=4.1; extra == "dev"
48
+ Requires-Dist: ruff>=0.1; extra == "dev"
49
+ Provides-Extra: all
50
+ Requires-Dist: moecog[anatomy,deep,nwb,viz]; extra == "all"
51
+ Dynamic: license-file
52
+
53
+ # MOECoG — Mother of All ECoG Benchmarks
54
+
55
+ A MOABB-style benchmarking framework for electrocorticographic (ECoG) motor decoding.
56
+
57
+ > *"ECoG isn't just the future — it's the testable present."*
58
+
59
+ ## Vision
60
+
61
+ [MOABB](https://github.com/NeuroTechX/moabb) transformed EEG-BCI research by making algorithm comparison reproducible and fair. **MOECoG does the same for ECoG motor decoding** — the signal modality at the critical intersection of clinical viability (long-term stability, lower surgical risk) and high-performance neural control (high-gamma access, mm-scale spatial resolution).
62
+
63
+ This project will be successful when we read in an abstract:
64
+
65
+ > *"...the proposed method obtained a correlation of 0.82 on MOECoG, outperforming the state of the art by 12%..."*
66
+
67
+ ## Why ECoG Needs Its Own Benchmark
68
+
69
+ | Property | EEG (MOABB) | ECoG (MOECoG) |
70
+ |---|---|---|
71
+ | Signal type | Scalp potentials | Cortical surface potentials |
72
+ | Key features | mu/beta ERD/ERS | High-gamma broadband (>70 Hz) + beta suppression |
73
+ | Spatial resolution | ~cm | ~mm |
74
+ | Electrode geometry | Standard montages (10-20) | Patient-specific grids/strips |
75
+ | Primary tasks | Classification (L/R imagery) | Both classification AND continuous regression |
76
+ | Cross-subject | Standard channel alignment | Requires anatomical registration |
77
+ | Noise profile | EMG, EOG artifacts | Epileptiform activity, referencing |
78
+
79
+ MOABB's paradigm/dataset/evaluation/pipeline abstraction is brilliant — but its assumptions (fixed channel montages, epoched classification, standard frequency bands) break down for ECoG.
80
+
81
+ ## Architecture
82
+
83
+ MOECoG follows MOABB's 4-concept design, adapted for ECoG:
84
+
85
+ ```
86
+ +--------------+ +---------------+ +---------------+ +---------------+
87
+ | Dataset |--->| Paradigm |--->| Evaluation |--->| Pipeline |
88
+ | | | | | | | |
89
+ | Raw ECoG + | | Motor Imagery | | WithinSubject | | Feature ext. |
90
+ | electrode | | Finger Flex | | CrossSession | | + Classifier |
91
+ | positions + | | Arm Reach | | Transfer | | or Regressor |
92
+ | anatomy | | Grasp Type | | | | |
93
+ +--------------+ +---------------+ +---------------+ +---------------+
94
+ ```
95
+
96
+ ### Key Differences from MOABB
97
+
98
+ - **Dual-task paradigms:** Classification (which finger?) AND regression (finger trajectory)
99
+ - **Anatomical electrode registration:** Patient-specific grids mapped to MNI/FreeSurfer atlas
100
+ - **Broadband feature extraction:** High-gamma (70-150 Hz), beta (13-30 Hz), phase-amplitude coupling
101
+ - **Continuous decoding metrics:** Correlation coefficient (r), R-squared, normalized MSE — not just accuracy
102
+ - **Naturalistic movement support:** Not just cued trials but free/spontaneous movements (AJILE12)
103
+
104
+ ## Included Datasets
105
+
106
+ ### Tier 1: Core Benchmark
107
+
108
+ Motor-specific, public, well-documented.
109
+
110
+ | ID | Dataset | Source | Subjects | Task | Channels | Modality |
111
+ |---|---|---|---|---|---|---|
112
+ | MillerFingerFlex | BCI Competition IV Dataset 4 | Miller & Schalk | 3 | Individual finger flexion (5-class regression) | 48-64 | ECoG grid |
113
+ | MillerLibrary | Stanford/Mayo ECoG Library | Miller 2019, *Nature Human Behaviour* | 34 | 16 experiments (motor, sensory, language, visual) | Varies | ECoG grid |
114
+ | AJILE12 | Annotated Joints in Long-term ECoG | Peterson et al. 2022, *Scientific Data* | 12 | Naturalistic wrist movements | >=64 | ECoG grid |
115
+
116
+ ### Tier 2: Extended Benchmark
117
+
118
+ | ID | Dataset | Source | Subjects | Task |
119
+ |---|---|---|---|---|
120
+ | BCITetraplegia | BCI and Tetraplegia (WIMAGINE) | Benabid/Costecalde et al. | 1 (chronic) | 4-class motor imagery, 2D cursor |
121
+ | GraspECoG | Natural grasp types | Various (Pistohl, Bleichner) | Varies | Grasp classification |
122
+ | MoveAgain | Blackrock/BrainGate ECoG subsets | If released publicly | Varies | Arm/hand movement |
123
+
124
+ ### Tier 3: Cross-Modality Comparison
125
+
126
+ | ID | Dataset | Why included |
127
+ |---|---|---|
128
+ | MOABB_MI | MOABB motor imagery EEG datasets | Direct EEG vs ECoG comparison on matched paradigms |
129
+
130
+ ## Paradigms
131
+
132
+ ### FingerFlexionRegression
133
+
134
+ - **Task:** Predict continuous finger flexion trajectories from ECoG
135
+ - **Metrics:** Pearson r, R-squared, NRMSE per finger
136
+ - **Datasets:** MillerFingerFlex, MillerLibrary (motor subset)
137
+ - **Baseline:** BCI Competition IV Dataset 4 leaderboard
138
+
139
+ ### MotorImageryClassification
140
+
141
+ - **Task:** Classify imagined/attempted movements (L/R hand, feet, tongue, etc.)
142
+ - **Metrics:** Accuracy, ROC-AUC, Cohen's kappa
143
+ - **Datasets:** MillerLibrary (motor imagery subset), BCITetraplegia
144
+
145
+ ### NaturalisticReachDecoding
146
+
147
+ - **Task:** Decode wrist movement onset and trajectory from unconstrained behavior
148
+ - **Metrics:** Event detection F1, trajectory r, latency
149
+ - **Datasets:** AJILE12
150
+
151
+ ### GraspClassification
152
+
153
+ - **Task:** Classify grasp types or hand gestures from sensorimotor ECoG
154
+ - **Metrics:** Accuracy, confusion matrix analysis
155
+ - **Datasets:** GraspECoG, MillerLibrary (gesture subset)
156
+
157
+ ## Evaluation Strategies
158
+
159
+ | Strategy | Description | Use Case |
160
+ |---|---|---|
161
+ | WithinSubjectCV | K-fold within single subject | Standard single-patient decoding |
162
+ | CrossSessionEval | Train on session A, test on session B | Stability / recalibration assessment |
163
+ | CrossSubjectTransfer | Leave-one-subject-out (with atlas projection) | Generalization / zero-shot transfer |
164
+ | TemporalStabilityEval | Chronological split (early to late) | Long-term signal stability |
165
+
166
+ ## Baseline Pipelines
167
+
168
+ ### Feature Extraction
169
+
170
+ - **LogBandPower** — Log power in canonical bands (mu, beta, low-gamma, high-gamma)
171
+ - **BroadbandChange** — Miller's broadband spectral change method
172
+ - **PAC** — Phase-amplitude coupling (theta/gamma, beta/high-gamma)
173
+ - **CSP_ECoG** — Common Spatial Patterns adapted for patient-specific grids
174
+ - **TimeFrequency** — Continuous wavelet / multitaper spectrograms
175
+
176
+ ### Decoders
177
+
178
+ - **LDA / SVM / LogisticRegression** — Classical classifiers
179
+ - **Ridge / Kalman** — Linear regressors for trajectory decoding
180
+ - **ECoGNet** — Lightweight CNN for ECoG (braindecode-compatible)
181
+ - **FingerFlex** — Convolutional encoder-decoder (Lomtev et al.)
182
+ - **HTNet** — Transfer learning across subjects via Hilbert transform
183
+
184
+ ## Quick Start
185
+
186
+ ```python
187
+ import moecog
188
+ from moecog.datasets import MillerFingerFlex
189
+ from moecog.paradigms import FingerFlexionRegression
190
+ from moecog.evaluations import WithinSubjectCV
191
+ from moecog.pipelines.features import LogBandPower
192
+ from sklearn.linear_model import Ridge
193
+ from sklearn.pipeline import make_pipeline
194
+
195
+ # Define pipeline
196
+ pipelines = {
197
+ "LogBandPower+Ridge": make_pipeline(LogBandPower(), Ridge(alpha=1.0))
198
+ }
199
+
200
+ # Load data
201
+ dataset = MillerFingerFlex()
202
+ paradigm = FingerFlexionRegression(fmin=1, fmax=150)
203
+ evaluation = WithinSubjectCV(paradigm=paradigm, datasets=[dataset], n_splits=5)
204
+
205
+ # Run benchmark
206
+ results = evaluation.process(pipelines)
207
+ print(results.groupby("pipeline")["score"].mean())
208
+ ```
209
+
210
+ ## Installation
211
+
212
+ ```bash
213
+ pip install moecog
214
+ ```
215
+
216
+ Or for development:
217
+
218
+ ```bash
219
+ git clone https://github.com/epyifany/MOECoG.git
220
+ cd MOECoG
221
+ pip install -e ".[dev]"
222
+ ```
223
+
224
+ ### Dependencies
225
+
226
+ **Core:**
227
+ - `mne >= 1.5` — ECoG signal handling, coordinate transforms
228
+ - `numpy`, `scipy`, `scikit-learn` — Core ML
229
+ - `pandas` — Results management
230
+ - `h5py` — Persistent results storage
231
+ - `pooch` — Robust data downloading
232
+
233
+ **Optional:**
234
+ - `torch`, `braindecode` — Deep learning baselines (`pip install moecog[deep]`)
235
+ - `pynwb`, `dandi` — NWB data access for AJILE12 (`pip install moecog[nwb]`)
236
+ - `nilearn`, `nibabel` — Anatomical registration (`pip install moecog[anatomy]`)
237
+ - `matplotlib`, `seaborn` — Visualization (`pip install moecog[viz]`)
238
+
239
+ ## Citation
240
+
241
+ If you use MOECoG in your research, please cite:
242
+
243
+ ```bibtex
244
+ @software{moecog2025,
245
+ title = {MOECoG: Mother of All ECoG Benchmarks},
246
+ author = {Yu, Yifan},
247
+ year = {2025},
248
+ url = {https://github.com/epyifany/MOECoG}
249
+ }
250
+ ```
251
+
252
+ And the foundational datasets:
253
+
254
+ - Miller, K.J. "A library of human electrocorticographic data and analyses." *Nature Human Behaviour* 3(11), 1225-1235 (2019).
255
+ - Peterson, S.M. et al. "AJILE12: Long-term naturalistic human intracranial neural recordings and pose." *Scientific Data* 9, 184 (2022).
256
+ - Schalk, G. et al. BCI Competition IV Dataset 4.
257
+
258
+ ## License
259
+
260
+ BSD-3-Clause (matching MOABB)
moecog-0.1.0/README.md ADDED
@@ -0,0 +1,208 @@
1
+ # MOECoG — Mother of All ECoG Benchmarks
2
+
3
+ A MOABB-style benchmarking framework for electrocorticographic (ECoG) motor decoding.
4
+
5
+ > *"ECoG isn't just the future — it's the testable present."*
6
+
7
+ ## Vision
8
+
9
+ [MOABB](https://github.com/NeuroTechX/moabb) transformed EEG-BCI research by making algorithm comparison reproducible and fair. **MOECoG does the same for ECoG motor decoding** — the signal modality at the critical intersection of clinical viability (long-term stability, lower surgical risk) and high-performance neural control (high-gamma access, mm-scale spatial resolution).
10
+
11
+ This project will be successful when we read in an abstract:
12
+
13
+ > *"...the proposed method obtained a correlation of 0.82 on MOECoG, outperforming the state of the art by 12%..."*
14
+
15
+ ## Why ECoG Needs Its Own Benchmark
16
+
17
+ | Property | EEG (MOABB) | ECoG (MOECoG) |
18
+ |---|---|---|
19
+ | Signal type | Scalp potentials | Cortical surface potentials |
20
+ | Key features | mu/beta ERD/ERS | High-gamma broadband (>70 Hz) + beta suppression |
21
+ | Spatial resolution | ~cm | ~mm |
22
+ | Electrode geometry | Standard montages (10-20) | Patient-specific grids/strips |
23
+ | Primary tasks | Classification (L/R imagery) | Both classification AND continuous regression |
24
+ | Cross-subject | Standard channel alignment | Requires anatomical registration |
25
+ | Noise profile | EMG, EOG artifacts | Epileptiform activity, referencing |
26
+
27
+ MOABB's paradigm/dataset/evaluation/pipeline abstraction is brilliant — but its assumptions (fixed channel montages, epoched classification, standard frequency bands) break down for ECoG.
28
+
29
+ ## Architecture
30
+
31
+ MOECoG follows MOABB's 4-concept design, adapted for ECoG:
32
+
33
+ ```
34
+ +--------------+ +---------------+ +---------------+ +---------------+
35
+ | Dataset |--->| Paradigm |--->| Evaluation |--->| Pipeline |
36
+ | | | | | | | |
37
+ | Raw ECoG + | | Motor Imagery | | WithinSubject | | Feature ext. |
38
+ | electrode | | Finger Flex | | CrossSession | | + Classifier |
39
+ | positions + | | Arm Reach | | Transfer | | or Regressor |
40
+ | anatomy | | Grasp Type | | | | |
41
+ +--------------+ +---------------+ +---------------+ +---------------+
42
+ ```
43
+
44
+ ### Key Differences from MOABB
45
+
46
+ - **Dual-task paradigms:** Classification (which finger?) AND regression (finger trajectory)
47
+ - **Anatomical electrode registration:** Patient-specific grids mapped to MNI/FreeSurfer atlas
48
+ - **Broadband feature extraction:** High-gamma (70-150 Hz), beta (13-30 Hz), phase-amplitude coupling
49
+ - **Continuous decoding metrics:** Correlation coefficient (r), R-squared, normalized MSE — not just accuracy
50
+ - **Naturalistic movement support:** Not just cued trials but free/spontaneous movements (AJILE12)
51
+
52
+ ## Included Datasets
53
+
54
+ ### Tier 1: Core Benchmark
55
+
56
+ Motor-specific, public, well-documented.
57
+
58
+ | ID | Dataset | Source | Subjects | Task | Channels | Modality |
59
+ |---|---|---|---|---|---|---|
60
+ | MillerFingerFlex | BCI Competition IV Dataset 4 | Miller & Schalk | 3 | Individual finger flexion (5-class regression) | 48-64 | ECoG grid |
61
+ | MillerLibrary | Stanford/Mayo ECoG Library | Miller 2019, *Nature Human Behaviour* | 34 | 16 experiments (motor, sensory, language, visual) | Varies | ECoG grid |
62
+ | AJILE12 | Annotated Joints in Long-term ECoG | Peterson et al. 2022, *Scientific Data* | 12 | Naturalistic wrist movements | >=64 | ECoG grid |
63
+
64
+ ### Tier 2: Extended Benchmark
65
+
66
+ | ID | Dataset | Source | Subjects | Task |
67
+ |---|---|---|---|---|
68
+ | BCITetraplegia | BCI and Tetraplegia (WIMAGINE) | Benabid/Costecalde et al. | 1 (chronic) | 4-class motor imagery, 2D cursor |
69
+ | GraspECoG | Natural grasp types | Various (Pistohl, Bleichner) | Varies | Grasp classification |
70
+ | MoveAgain | Blackrock/BrainGate ECoG subsets | If released publicly | Varies | Arm/hand movement |
71
+
72
+ ### Tier 3: Cross-Modality Comparison
73
+
74
+ | ID | Dataset | Why included |
75
+ |---|---|---|
76
+ | MOABB_MI | MOABB motor imagery EEG datasets | Direct EEG vs ECoG comparison on matched paradigms |
77
+
78
+ ## Paradigms
79
+
80
+ ### FingerFlexionRegression
81
+
82
+ - **Task:** Predict continuous finger flexion trajectories from ECoG
83
+ - **Metrics:** Pearson r, R-squared, NRMSE per finger
84
+ - **Datasets:** MillerFingerFlex, MillerLibrary (motor subset)
85
+ - **Baseline:** BCI Competition IV Dataset 4 leaderboard
86
+
87
+ ### MotorImageryClassification
88
+
89
+ - **Task:** Classify imagined/attempted movements (L/R hand, feet, tongue, etc.)
90
+ - **Metrics:** Accuracy, ROC-AUC, Cohen's kappa
91
+ - **Datasets:** MillerLibrary (motor imagery subset), BCITetraplegia
92
+
93
+ ### NaturalisticReachDecoding
94
+
95
+ - **Task:** Decode wrist movement onset and trajectory from unconstrained behavior
96
+ - **Metrics:** Event detection F1, trajectory r, latency
97
+ - **Datasets:** AJILE12
98
+
99
+ ### GraspClassification
100
+
101
+ - **Task:** Classify grasp types or hand gestures from sensorimotor ECoG
102
+ - **Metrics:** Accuracy, confusion matrix analysis
103
+ - **Datasets:** GraspECoG, MillerLibrary (gesture subset)
104
+
105
+ ## Evaluation Strategies
106
+
107
+ | Strategy | Description | Use Case |
108
+ |---|---|---|
109
+ | WithinSubjectCV | K-fold within single subject | Standard single-patient decoding |
110
+ | CrossSessionEval | Train on session A, test on session B | Stability / recalibration assessment |
111
+ | CrossSubjectTransfer | Leave-one-subject-out (with atlas projection) | Generalization / zero-shot transfer |
112
+ | TemporalStabilityEval | Chronological split (early to late) | Long-term signal stability |
113
+
114
+ ## Baseline Pipelines
115
+
116
+ ### Feature Extraction
117
+
118
+ - **LogBandPower** — Log power in canonical bands (mu, beta, low-gamma, high-gamma)
119
+ - **BroadbandChange** — Miller's broadband spectral change method
120
+ - **PAC** — Phase-amplitude coupling (theta/gamma, beta/high-gamma)
121
+ - **CSP_ECoG** — Common Spatial Patterns adapted for patient-specific grids
122
+ - **TimeFrequency** — Continuous wavelet / multitaper spectrograms
123
+
124
+ ### Decoders
125
+
126
+ - **LDA / SVM / LogisticRegression** — Classical classifiers
127
+ - **Ridge / Kalman** — Linear regressors for trajectory decoding
128
+ - **ECoGNet** — Lightweight CNN for ECoG (braindecode-compatible)
129
+ - **FingerFlex** — Convolutional encoder-decoder (Lomtev et al.)
130
+ - **HTNet** — Transfer learning across subjects via Hilbert transform
131
+
132
+ ## Quick Start
133
+
134
+ ```python
135
+ import moecog
136
+ from moecog.datasets import MillerFingerFlex
137
+ from moecog.paradigms import FingerFlexionRegression
138
+ from moecog.evaluations import WithinSubjectCV
139
+ from moecog.pipelines.features import LogBandPower
140
+ from sklearn.linear_model import Ridge
141
+ from sklearn.pipeline import make_pipeline
142
+
143
+ # Define pipeline
144
+ pipelines = {
145
+ "LogBandPower+Ridge": make_pipeline(LogBandPower(), Ridge(alpha=1.0))
146
+ }
147
+
148
+ # Load data
149
+ dataset = MillerFingerFlex()
150
+ paradigm = FingerFlexionRegression(fmin=1, fmax=150)
151
+ evaluation = WithinSubjectCV(paradigm=paradigm, datasets=[dataset], n_splits=5)
152
+
153
+ # Run benchmark
154
+ results = evaluation.process(pipelines)
155
+ print(results.groupby("pipeline")["score"].mean())
156
+ ```
157
+
158
+ ## Installation
159
+
160
+ ```bash
161
+ pip install moecog
162
+ ```
163
+
164
+ Or for development:
165
+
166
+ ```bash
167
+ git clone https://github.com/epyifany/MOECoG.git
168
+ cd MOECoG
169
+ pip install -e ".[dev]"
170
+ ```
171
+
172
+ ### Dependencies
173
+
174
+ **Core:**
175
+ - `mne >= 1.5` — ECoG signal handling, coordinate transforms
176
+ - `numpy`, `scipy`, `scikit-learn` — Core ML
177
+ - `pandas` — Results management
178
+ - `h5py` — Persistent results storage
179
+ - `pooch` — Robust data downloading
180
+
181
+ **Optional:**
182
+ - `torch`, `braindecode` — Deep learning baselines (`pip install moecog[deep]`)
183
+ - `pynwb`, `dandi` — NWB data access for AJILE12 (`pip install moecog[nwb]`)
184
+ - `nilearn`, `nibabel` — Anatomical registration (`pip install moecog[anatomy]`)
185
+ - `matplotlib`, `seaborn` — Visualization (`pip install moecog[viz]`)
186
+
187
+ ## Citation
188
+
189
+ If you use MOECoG in your research, please cite:
190
+
191
+ ```bibtex
192
+ @software{moecog2025,
193
+ title = {MOECoG: Mother of All ECoG Benchmarks},
194
+ author = {Yu, Yifan},
195
+ year = {2025},
196
+ url = {https://github.com/epyifany/MOECoG}
197
+ }
198
+ ```
199
+
200
+ And the foundational datasets:
201
+
202
+ - Miller, K.J. "A library of human electrocorticographic data and analyses." *Nature Human Behaviour* 3(11), 1225-1235 (2019).
203
+ - Peterson, S.M. et al. "AJILE12: Long-term naturalistic human intracranial neural recordings and pose." *Scientific Data* 9, 184 (2022).
204
+ - Schalk, G. et al. BCI Competition IV Dataset 4.
205
+
206
+ ## License
207
+
208
+ BSD-3-Clause (matching MOABB)
@@ -0,0 +1,6 @@
1
+ """MOECoG — Mother of All ECoG Benchmarks.
2
+
3
+ A MOABB-style benchmarking framework for electrocorticographic (ECoG) motor decoding.
4
+ """
5
+
6
+ __version__ = "0.1.0"
@@ -0,0 +1 @@
1
+ """Analysis — results storage, statistics, and visualization."""
@@ -0,0 +1,8 @@
1
+ """ECoG dataset loaders."""
2
+
3
+ from .base import BaseECoGDataset, ElectrodeInfo
4
+
5
+ __all__ = [
6
+ "BaseECoGDataset",
7
+ "ElectrodeInfo",
8
+ ]
@@ -0,0 +1,161 @@
1
+ """Base class for all ECoG datasets."""
2
+
3
+ from abc import ABC, abstractmethod
4
+ from dataclasses import dataclass, field
5
+ from pathlib import Path
6
+
7
+ import numpy as np
8
+
9
+
10
+ @dataclass
11
+ class ElectrodeInfo:
12
+ """Patient-specific electrode metadata.
13
+
14
+ Parameters
15
+ ----------
16
+ positions : np.ndarray, shape (n_channels, 3)
17
+ Electrode coordinates (MNI or native space).
18
+ labels : list of str
19
+ Channel names.
20
+ hemisphere : list of str or None
21
+ Hemisphere per electrode ("L" or "R").
22
+ lobe : list of str or None
23
+ Anatomical lobe per electrode.
24
+ gyrus : list of str or None
25
+ Gyrus per electrode.
26
+ brodmann_area : list of int or None
27
+ Brodmann area per electrode.
28
+ grid_type : str
29
+ Electrode array type: "grid", "strip", or "depth".
30
+ spacing_mm : float
31
+ Inter-electrode distance in millimeters.
32
+ """
33
+
34
+ positions: np.ndarray
35
+ labels: list[str]
36
+ hemisphere: list[str] | None = None
37
+ lobe: list[str] | None = None
38
+ gyrus: list[str] | None = None
39
+ brodmann_area: list[int] | None = None
40
+ grid_type: str = "grid"
41
+ spacing_mm: float = 10.0
42
+
43
+
44
+ class BaseECoGDataset(ABC):
45
+ """Base class for all ECoG datasets.
46
+
47
+ Every concrete dataset must implement:
48
+ - ``_get_single_subject_data(subject)``
49
+ - ``data_path(subject)``
50
+ - ``get_electrode_info(subject)``
51
+
52
+ Parameters
53
+ ----------
54
+ subjects : list of int
55
+ Available subject IDs.
56
+ sessions_per_subject : int
57
+ Number of recording sessions per subject.
58
+ events : dict or None
59
+ Mapping of event names to integer codes. None for pure regression datasets.
60
+ code : str
61
+ Unique dataset identifier string.
62
+ paradigm : str
63
+ Paradigm type: "motor_regression", "motor_imagery", or "naturalistic".
64
+ interval : list of float or None
65
+ Epoch window [tmin, tmax] in seconds. None for continuous data.
66
+ sfreq : float
67
+ Sampling frequency in Hz.
68
+ doi : str or None
69
+ DOI of the associated publication.
70
+ """
71
+
72
+ def __init__(
73
+ self,
74
+ subjects: list[int],
75
+ sessions_per_subject: int,
76
+ events: dict[str, int] | None,
77
+ code: str,
78
+ paradigm: str,
79
+ interval: list[float] | None,
80
+ sfreq: float,
81
+ doi: str | None = None,
82
+ ):
83
+ self.subject_list = subjects
84
+ self.n_sessions = sessions_per_subject
85
+ self.event_id = events
86
+ self.code = code
87
+ self.paradigm_type = paradigm
88
+ self.interval = interval
89
+ self.sfreq = sfreq
90
+ self.doi = doi
91
+
92
+ def get_data(self, subjects=None):
93
+ """Load data for one or more subjects.
94
+
95
+ Parameters
96
+ ----------
97
+ subjects : list of int or None
98
+ Subject IDs to load. If None, loads all subjects.
99
+
100
+ Returns
101
+ -------
102
+ dict
103
+ Nested dict: ``{subject: {session: {run: mne.io.Raw}}}``.
104
+ """
105
+ subjects = subjects or self.subject_list
106
+ data = {}
107
+ for subject in subjects:
108
+ data[subject] = self._get_single_subject_data(subject)
109
+ return data
110
+
111
+ @abstractmethod
112
+ def _get_single_subject_data(self, subject):
113
+ """Load all sessions and runs for a single subject.
114
+
115
+ Parameters
116
+ ----------
117
+ subject : int
118
+ Subject identifier.
119
+
120
+ Returns
121
+ -------
122
+ dict
123
+ ``{session_id: {run_id: mne.io.Raw}}``.
124
+ """
125
+
126
+ @abstractmethod
127
+ def data_path(self, subject):
128
+ """Return local file paths for a subject's data, downloading if needed.
129
+
130
+ Parameters
131
+ ----------
132
+ subject : int
133
+ Subject identifier.
134
+
135
+ Returns
136
+ -------
137
+ list of Path
138
+ Local paths to the data files.
139
+ """
140
+
141
+ @abstractmethod
142
+ def get_electrode_info(self, subject):
143
+ """Return electrode metadata for a subject.
144
+
145
+ Parameters
146
+ ----------
147
+ subject : int
148
+ Subject identifier.
149
+
150
+ Returns
151
+ -------
152
+ ElectrodeInfo
153
+ Electrode positions and anatomical labels.
154
+ """
155
+
156
+ def __repr__(self):
157
+ return (
158
+ f"{self.__class__.__name__}(code={self.code!r}, "
159
+ f"subjects={len(self.subject_list)}, "
160
+ f"sessions={self.n_sessions})"
161
+ )
@@ -0,0 +1,7 @@
1
+ """Evaluation strategies for ECoG benchmarking."""
2
+
3
+ from .base import BaseEvaluation
4
+
5
+ __all__ = [
6
+ "BaseEvaluation",
7
+ ]