ghh1125 commited on
Commit
b7a8635
·
verified ·
1 Parent(s): e57695f

Upload 8934 files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +31 -0
  2. Dockerfile +18 -0
  3. app.py +45 -0
  4. mne-python/.DS_Store +0 -0
  5. mne-python/mcp_output/.DS_Store +0 -0
  6. mne-python/mcp_output/README_MCP.md +129 -0
  7. mne-python/mcp_output/analysis.json +199 -0
  8. mne-python/mcp_output/diff_report.md +161 -0
  9. mne-python/mcp_output/mcp_plugin/__init__.py +0 -0
  10. mne-python/mcp_output/mcp_plugin/adapter.py +358 -0
  11. mne-python/mcp_output/mcp_plugin/main.py +13 -0
  12. mne-python/mcp_output/mcp_plugin/mcp_service.py +215 -0
  13. mne-python/mcp_output/requirements.txt +16 -0
  14. mne-python/mcp_output/start_mcp.py +30 -0
  15. mne-python/mcp_output/workflow_summary.json +253 -0
  16. mne-python/source/.DS_Store +0 -0
  17. mne-python/source/.circleci/config.yml +570 -0
  18. mne-python/source/.coveragerc +16 -0
  19. mne-python/source/.mailmap +379 -0
  20. mne-python/source/.pre-commit-config.yaml +106 -0
  21. mne-python/source/.yamllint.yml +10 -0
  22. mne-python/source/CITATION.cff +877 -0
  23. mne-python/source/CONTRIBUTING.md +9 -0
  24. mne-python/source/LICENSE.txt +11 -0
  25. mne-python/source/Makefile +62 -0
  26. mne-python/source/README.rst +144 -0
  27. mne-python/source/SECURITY.md +30 -0
  28. mne-python/source/__init__.py +4 -0
  29. mne-python/source/azure-pipelines.yml +303 -0
  30. mne-python/source/codecov.yml +25 -0
  31. mne-python/source/codemeta.json +2555 -0
  32. mne-python/source/doc/Makefile +81 -0
  33. mne-python/source/doc/_includes/bem_model.rst +162 -0
  34. mne-python/source/doc/_includes/channel_interpolation.rst +70 -0
  35. mne-python/source/doc/_includes/channel_types.rst +104 -0
  36. mne-python/source/doc/_includes/data_formats.rst +86 -0
  37. mne-python/source/doc/_includes/dig_formats.rst +47 -0
  38. mne-python/source/doc/_includes/forward.rst +726 -0
  39. mne-python/source/doc/_includes/ged.rst +107 -0
  40. mne-python/source/doc/_includes/institutional-partners.rst +44 -0
  41. mne-python/source/doc/_includes/inverse.rst +607 -0
  42. mne-python/source/doc/_includes/memory.rst +68 -0
  43. mne-python/source/doc/_includes/morph.rst +123 -0
  44. mne-python/source/doc/_includes/precision.rst +28 -0
  45. mne-python/source/doc/_includes/ssp.rst +119 -0
  46. mne-python/source/doc/_includes/units.rst +36 -0
  47. mne-python/source/doc/_static/CoordinateSystems.png +0 -0
  48. mne-python/source/doc/_static/HeadCS.png +0 -0
  49. mne-python/source/doc/_static/blender_import_obj/blender_import_obj1.jpg +3 -0
  50. mne-python/source/doc/_static/blender_import_obj/blender_import_obj2.jpg +0 -0
.gitattributes CHANGED
@@ -33,3 +33,34 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ mne-python/source/doc/_static/blender_import_obj/blender_import_obj1.jpg filter=lfs diff=lfs merge=lfs -text
37
+ mne-python/source/doc/_static/blender_import_obj/blender_import_obj4.jpg filter=lfs diff=lfs merge=lfs -text
38
+ mne-python/source/doc/_static/funding/nsf.png filter=lfs diff=lfs merge=lfs -text
39
+ mne-python/source/doc/_static/mne_installer_macOS.png filter=lfs diff=lfs merge=lfs -text
40
+ mne-python/source/mne/data/fsaverage/fsaverage-inner_skull-bem.fif filter=lfs diff=lfs merge=lfs -text
41
+ mne-python/source/mne/io/brainvision/tests/data/test_bin_raw.fif filter=lfs diff=lfs merge=lfs -text
42
+ mne-python/source/mne/io/brainvision/tests/data/test.eeg filter=lfs diff=lfs merge=lfs -text
43
+ mne-python/source/mne/io/bti/tests/data/exported4D_linux_raw.fif filter=lfs diff=lfs merge=lfs -text
44
+ mne-python/source/mne/io/bti/tests/data/exported4D_solaris_raw.fif filter=lfs diff=lfs merge=lfs -text
45
+ mne-python/source/mne/io/bti/tests/data/test_config_linux filter=lfs diff=lfs merge=lfs -text
46
+ mne-python/source/mne/io/bti/tests/data/test_config_solaris filter=lfs diff=lfs merge=lfs -text
47
+ mne-python/source/mne/io/bti/tests/data/test_hs_solaris filter=lfs diff=lfs merge=lfs -text
48
+ mne-python/source/mne/io/bti/tests/data/test_pdf_linux filter=lfs diff=lfs merge=lfs -text
49
+ mne-python/source/mne/io/bti/tests/data/test_pdf_solaris filter=lfs diff=lfs merge=lfs -text
50
+ mne-python/source/mne/io/edf/tests/data/test_bdf_eeglab.mat filter=lfs diff=lfs merge=lfs -text
51
+ mne-python/source/mne/io/edf/tests/data/test_edf_eeglab.mat filter=lfs diff=lfs merge=lfs -text
52
+ mne-python/source/mne/io/edf/tests/data/test_eeglab.mat filter=lfs diff=lfs merge=lfs -text
53
+ mne-python/source/mne/io/kit/tests/data/test_bin_raw.fif filter=lfs diff=lfs merge=lfs -text
54
+ mne-python/source/mne/io/kit/tests/data/test_Ykgw.mat filter=lfs diff=lfs merge=lfs -text
55
+ mne-python/source/mne/io/kit/tests/data/test-epoch.raw filter=lfs diff=lfs merge=lfs -text
56
+ mne-python/source/mne/io/kit/tests/data/test.sqd filter=lfs diff=lfs merge=lfs -text
57
+ mne-python/source/mne/io/tests/data/test_chpi_raw_sss.fif filter=lfs diff=lfs merge=lfs -text
58
+ mne-python/source/mne/io/tests/data/test_ctf_comp_raw.fif filter=lfs diff=lfs merge=lfs -text
59
+ mne-python/source/mne/io/tests/data/test_ctf_raw.fif filter=lfs diff=lfs merge=lfs -text
60
+ mne-python/source/mne/io/tests/data/test_erm-cov.fif filter=lfs diff=lfs merge=lfs -text
61
+ mne-python/source/mne/io/tests/data/test_raw.fif filter=lfs diff=lfs merge=lfs -text
62
+ mne-python/source/mne/io/tests/data/test_withbads_raw.fif filter=lfs diff=lfs merge=lfs -text
63
+ mne-python/source/mne/io/tests/data/test-ave.fif filter=lfs diff=lfs merge=lfs -text
64
+ mne-python/source/mne/io/tests/data/test-cov.fif filter=lfs diff=lfs merge=lfs -text
65
+ mne-python/source/mne/io/tests/data/test-km-cov.fif filter=lfs diff=lfs merge=lfs -text
66
+ mne-python/source/mne/io/tests/data/test-nf-ave.fif filter=lfs diff=lfs merge=lfs -text
Dockerfile ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10
2
+
3
+ RUN useradd -m -u 1000 user && python -m pip install --upgrade pip
4
+ USER user
5
+ ENV PATH="/home/user/.local/bin:$PATH"
6
+
7
+ WORKDIR /app
8
+
9
+ COPY --chown=user ./requirements.txt requirements.txt
10
+ RUN pip install --no-cache-dir --upgrade -r requirements.txt
11
+
12
+ COPY --chown=user . /app
13
+ ENV MCP_TRANSPORT=http
14
+ ENV MCP_PORT=7860
15
+
16
+ EXPOSE 7860
17
+
18
+ CMD ["python", "mne-python/mcp_output/start_mcp.py"]
app.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI
2
+ import os
3
+ import sys
4
+
5
+ mcp_plugin_path = os.path.join(os.path.dirname(__file__), "mne-python", "mcp_output", "mcp_plugin")
6
+ sys.path.insert(0, mcp_plugin_path)
7
+
8
+ app = FastAPI(
9
+ title="Mne-Python MCP Service",
10
+ description="Auto-generated MCP service for mne-python",
11
+ version="1.0.0"
12
+ )
13
+
14
+ @app.get("/")
15
+ def root():
16
+ return {
17
+ "service": "Mne-Python MCP Service",
18
+ "version": "1.0.0",
19
+ "status": "running",
20
+ "transport": os.environ.get("MCP_TRANSPORT", "http")
21
+ }
22
+
23
+ @app.get("/health")
24
+ def health_check():
25
+ return {"status": "healthy", "service": "mne-python MCP"}
26
+
27
+ @app.get("/tools")
28
+ def list_tools():
29
+ try:
30
+ from mcp_service import create_app
31
+ mcp_app = create_app()
32
+ tools = []
33
+ for tool_name, tool_func in mcp_app.tools.items():
34
+ tools.append({
35
+ "name": tool_name,
36
+ "description": tool_func.__doc__ or "No description available"
37
+ })
38
+ return {"tools": tools}
39
+ except Exception as e:
40
+ return {"error": f"Failed to load tools: {str(e)}"}
41
+
42
+ if __name__ == "__main__":
43
+ import uvicorn
44
+ port = int(os.environ.get("PORT", 7860))
45
+ uvicorn.run(app, host="0.0.0.0", port=port)
mne-python/.DS_Store ADDED
Binary file (6.15 kB). View file
 
mne-python/mcp_output/.DS_Store ADDED
Binary file (6.15 kB). View file
 
mne-python/mcp_output/README_MCP.md ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # MNE-Python MCP (Model Context Protocol) Service README
2
+
3
+ ## 1) Project Introduction
4
+
5
+ This service wraps core **MNE-Python** capabilities for EEG/MEG workflows in an MCP (Model Context Protocol)-friendly interface.
6
+
7
+ Primary goals:
8
+ - Load raw neurophysiology data (FIF, EDF, BDF, BrainVision).
9
+ - Perform event handling and channel picking.
10
+ - Run common preprocessing (EOG/ECG detection, ICA-related preparation).
11
+ - Compute PSD and time-frequency features.
12
+ - Optionally render diagnostic visualizations (when GUI/backends are available).
13
+
14
+ Recommended integration path:
15
+ - **Primary:** in-process Python imports from `mne` modules.
16
+ - **Fallback:** call the `mne` CLI for heavier or isolated execution contexts.
17
+
18
+ ---
19
+
20
+ ## 2) Installation Method
21
+
22
+ ### Requirements
23
+ Core dependencies:
24
+ - `numpy`
25
+ - `scipy`
26
+ - `matplotlib`
27
+ - `packaging`
28
+ - `pooch`
29
+ - `tqdm`
30
+
31
+ Common optional dependencies (feature-dependent):
32
+ - `scikit-learn`, `pandas`, `h5py`, `nibabel`
33
+ - `pyvista`, `vtk`, `mne-qt-browser`
34
+ - `numba`
35
+
36
+ ### Install
37
+ - Install MNE-Python and common scientific stack via pip:
38
+ - `pip install mne`
39
+ - For broader functionality:
40
+ - `pip install mne[full]` (if supported by your environment/version)
41
+ - If your service uses project-local dependency files, prefer:
42
+ - `pyproject.toml` / `environment.yml` in your deployment workflow.
43
+
44
+ ---
45
+
46
+ ## 3) Quick Start
47
+
48
+ ### Minimal service flow (Python-side)
49
+ 1. Read raw data:
50
+ - `mne.io.read_raw_fif(...)` / `read_raw_edf(...)` / `read_raw_bdf(...)` / `read_raw_brainvision(...)`
51
+ 2. Extract events:
52
+ - `mne.find_events(raw)` or `mne.read_events(path)`
53
+ 3. Pick channels:
54
+ - `mne.pick_types(raw.info, meg=True, eeg=True, eog=True, exclude="bads")`
55
+ 4. Preprocess (optional):
56
+ - `mne.preprocessing.find_eog_events(raw)`, `find_ecg_events(raw)`, ICA workflows
57
+ 5. Spectral analysis:
58
+ - `mne.time_frequency.psd_array_welch(...)` or `psd_array_multitaper(...)`
59
+ 6. Return structured results from your MCP (Model Context Protocol) service endpoint.
60
+
61
+ ### CLI fallback
62
+ - Use `mne` command wrapper when import-time overhead or environment isolation is needed.
63
+
64
+ ---
65
+
66
+ ## 4) Available Tools and Endpoints List
67
+
68
+ Suggested MCP (Model Context Protocol) service endpoints:
69
+
70
+ - `load_raw`
71
+ - Load raw recordings from FIF/EDF/BDF/BrainVision.
72
+ - Maps to `mne.io.read_raw_*`.
73
+
74
+ - `read_info`
75
+ - Read metadata/header info without full processing.
76
+ - Maps to `mne.io.read_info`.
77
+
78
+ - `events_detect`
79
+ - Detect or load event markers.
80
+ - Maps to `mne.find_events`, `mne.read_events`, `mne.merge_events`.
81
+
82
+ - `channels_pick`
83
+ - Build channel selections by modality/type.
84
+ - Maps to `mne.pick_types`.
85
+
86
+ - `preprocess_eog_ecg`
87
+ - EOG/ECG event detection and projection helpers.
88
+ - Maps to `mne.preprocessing.find_eog_events`, `find_ecg_events`, `compute_proj_eog`, `compute_proj_ecg`.
89
+
90
+ - `ica_workflow`
91
+ - Artifact decomposition/removal pipeline.
92
+ - Maps to `mne.preprocessing.ICA`, `EOGRegression`.
93
+
94
+ - `psd_compute`
95
+ - Power spectral density calculations.
96
+ - Maps to `mne.time_frequency.psd_array_welch`, `psd_array_multitaper`.
97
+
98
+ - `tfr_compute`
99
+ - Time-frequency decomposition.
100
+ - Maps to `tfr_morlet`, `tfr_multitaper`, `csd_multitaper`.
101
+
102
+ - `viz_diagnostics` (optional/headless-sensitive)
103
+ - Event/covariance/alignment diagnostic plotting.
104
+ - Maps to `mne.viz.plot_events`, `plot_cov`, `plot_bem`, `plot_alignment`.
105
+
106
+ - `cli_exec` (fallback)
107
+ - Run `mne` subcommands for isolated or heavyweight tasks.
108
+
109
+ ---
110
+
111
+ ## 5) Common Issues and Notes
112
+
113
+ - **Complexity:** MNE-Python is feature-rich; keep endpoint contracts narrow and typed.
114
+ - **Import overhead:** First import can be non-trivial; consider lazy-loading per endpoint.
115
+ - **GUI dependencies:** Visualization endpoints may fail in headless servers unless backend is configured.
116
+ - **Optional packages:** Some analyses silently require extras (`sklearn`, `h5py`, `nibabel`, etc.).
117
+ - **Performance:** Large FIF files and TFR/ICA jobs are memory/CPU intensive; set resource limits.
118
+ - **Reproducibility:** Pin MNE + NumPy/SciPy versions in deployment.
119
+ - **Risk profile:** Import feasibility is moderate (~0.72); keep CLI fallback available.
120
+ - **Data handling:** Validate paths, file formats, and channel metadata before heavy processing.
121
+
122
+ ---
123
+
124
+ ## 6) Reference Links / Documentation
125
+
126
+ - MNE-Python repository: https://github.com/mne-tools/mne-python
127
+ - MNE official docs: https://mne.tools/stable/index.html
128
+ - MNE API reference: https://mne.tools/stable/python_reference.html
129
+ - MNE command-line tools: https://mne.tools/stable/overview/command_line.html
mne-python/mcp_output/analysis.json ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "summary": {
3
+ "repository_url": "https://github.com/mne-tools/mne-python",
4
+ "summary": "Unable to preprocess repository: https://github.com/mne-tools/mne-python",
5
+ "file_tree": {},
6
+ "content": {},
7
+ "processed_by": "fallback",
8
+ "success": false,
9
+ "error": "zip download failed: IncompleteRead(4160073 bytes read)"
10
+ },
11
+ "structure": {
12
+ "packages": [
13
+ "deployment.mne-python.source",
14
+ "mcp_output.mcp_plugin",
15
+ "source.mne",
16
+ "source.mne._fiff",
17
+ "source.mne.beamformer",
18
+ "source.mne.channels",
19
+ "source.mne.commands",
20
+ "source.mne.data",
21
+ "source.mne.datasets",
22
+ "source.mne.decoding",
23
+ "source.mne.export",
24
+ "source.mne.forward",
25
+ "source.mne.gui",
26
+ "source.mne.html_templates",
27
+ "source.mne.inverse_sparse",
28
+ "source.mne.io",
29
+ "source.mne.minimum_norm",
30
+ "source.mne.preprocessing",
31
+ "source.mne.report",
32
+ "source.mne.simulation",
33
+ "source.mne.source_space",
34
+ "source.mne.stats",
35
+ "source.mne.tests",
36
+ "source.mne.time_frequency",
37
+ "source.mne.utils",
38
+ "source.mne.viz"
39
+ ]
40
+ },
41
+ "dependencies": {
42
+ "has_environment_yml": true,
43
+ "has_requirements_txt": false,
44
+ "pyproject": true,
45
+ "setup_cfg": false,
46
+ "setup_py": false
47
+ },
48
+ "entry_points": {
49
+ "imports": [],
50
+ "cli": [],
51
+ "modules": []
52
+ },
53
+ "llm_analysis": {
54
+ "core_modules": [
55
+ {
56
+ "package": "source.mne",
57
+ "module": "source.mne",
58
+ "functions": [
59
+ "create_info",
60
+ "set_log_level",
61
+ "read_events",
62
+ "pick_types",
63
+ "find_events",
64
+ "merge_events",
65
+ "concatenate_raws"
66
+ ],
67
+ "classes": [
68
+ "Info",
69
+ "Covariance",
70
+ "Epochs",
71
+ "Evoked",
72
+ "Annotations"
73
+ ],
74
+ "description": "Top-level API surface for core EEG/MEG data structures and common preprocessing/event utilities; safest primary integration point for MCP tooling."
75
+ },
76
+ {
77
+ "package": "source.mne.io",
78
+ "module": "source.mne.io",
79
+ "functions": [
80
+ "read_raw_fif",
81
+ "read_raw_edf",
82
+ "read_raw_bdf",
83
+ "read_raw_brainvision",
84
+ "read_info"
85
+ ],
86
+ "classes": [
87
+ "Raw",
88
+ "RawArray"
89
+ ],
90
+ "description": "Input/output layer for loading raw recordings from major formats and constructing in-memory raw objects."
91
+ },
92
+ {
93
+ "package": "source.mne.preprocessing",
94
+ "module": "source.mne.preprocessing",
95
+ "functions": [
96
+ "compute_proj_ecg",
97
+ "compute_proj_eog",
98
+ "find_eog_events",
99
+ "find_ecg_events",
100
+ "create_eog_epochs"
101
+ ],
102
+ "classes": [
103
+ "ICA",
104
+ "EOGRegression"
105
+ ],
106
+ "description": "Artifact detection/removal workflows (ICA/projections/regression), useful for preprocessing-oriented MCP commands."
107
+ },
108
+ {
109
+ "package": "source.mne.time_frequency",
110
+ "module": "source.mne.time_frequency",
111
+ "functions": [
112
+ "psd_array_welch",
113
+ "psd_array_multitaper",
114
+ "tfr_morlet",
115
+ "tfr_multitaper",
116
+ "csd_multitaper"
117
+ ],
118
+ "classes": [
119
+ "AverageTFR",
120
+ "EpochsTFR"
121
+ ],
122
+ "description": "Frequency-domain and time-frequency analysis APIs commonly needed for downstream analytics plugins."
123
+ },
124
+ {
125
+ "package": "source.mne.viz",
126
+ "module": "source.mne.viz",
127
+ "functions": [
128
+ "plot_events",
129
+ "plot_cov",
130
+ "plot_bem",
131
+ "plot_alignment"
132
+ ],
133
+ "classes": [],
134
+ "description": "Visualization endpoints; useful but generally optional in headless MCP execution."
135
+ },
136
+ {
137
+ "package": "source.mne.commands",
138
+ "module": "source.mne.commands",
139
+ "functions": [],
140
+ "classes": [],
141
+ "description": "CLI command package; preferred fallback execution boundary when direct in-process imports are too heavy."
142
+ }
143
+ ],
144
+ "cli_commands": [
145
+ {
146
+ "name": "mne",
147
+ "module": "source.mne.commands",
148
+ "description": "Primary MNE command-line entry wrapper (subcommand-based tooling for data handling, preprocessing, and project utilities)."
149
+ }
150
+ ],
151
+ "import_strategy": {
152
+ "primary": "import",
153
+ "fallback": "cli",
154
+ "confidence": 0.7
155
+ },
156
+ "dependencies": {
157
+ "required": [
158
+ "numpy",
159
+ "scipy",
160
+ "matplotlib",
161
+ "packaging",
162
+ "pooch",
163
+ "tqdm"
164
+ ],
165
+ "optional": [
166
+ "sklearn",
167
+ "pandas",
168
+ "h5py",
169
+ "nibabel",
170
+ "pyvista",
171
+ "vtk",
172
+ "mne-qt-browser",
173
+ "numba"
174
+ ]
175
+ },
176
+ "risk_assessment": {
177
+ "import_feasibility": 0.72,
178
+ "intrusiveness_risk": "medium",
179
+ "complexity": "complex"
180
+ }
181
+ },
182
+ "deepwiki_analysis": {
183
+ "repo_url": "https://github.com/mne-tools/mne-python",
184
+ "repo_name": "mne-python",
185
+ "error": "DeepWiki analysis failed",
186
+ "model": "gpt-5.3-codex",
187
+ "source": "llm_direct_analysis",
188
+ "success": false
189
+ },
190
+ "deepwiki_options": {
191
+ "enabled": true,
192
+ "model": "gpt-5.3-codex"
193
+ },
194
+ "risk": {
195
+ "import_feasibility": 0.72,
196
+ "intrusiveness_risk": "medium",
197
+ "complexity": "complex"
198
+ }
199
+ }
mne-python/mcp_output/diff_report.md ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Difference Report — **mne-python**
2
+
3
+ **Generated:** 2026-03-14 12:25:49
4
+ **Repository:** `mne-python`
5
+ **Project Type:** Python library
6
+ **Scope / Main Features:** Basic functionality
7
+ **Change Intrusiveness:** None
8
+ **Workflow Status:** ✅ Success
9
+ **Test Status:** ❌ Failed
10
+ **Files Changed:** 8 new, 0 modified
11
+
12
+ ---
13
+
14
+ ## 1) Project Overview
15
+
16
+ This update introduces **8 new files** to the `mne-python` codebase without modifying existing files.
17
+ Given the “Basic functionality” scope and “None” intrusiveness, the change appears additive and low-risk at the integration layer. However, the **failed test status** indicates unresolved quality or environment issues that block confidence in release readiness.
18
+
19
+ ---
20
+
21
+ ## 2) Change Summary
22
+
23
+ | Metric | Value |
24
+ |---|---:|
25
+ | New files | 8 |
26
+ | Modified files | 0 |
27
+ | Deleted files | 0 (not reported) |
28
+ | Intrusiveness | None |
29
+ | CI workflow | Success |
30
+ | Test result | Failed |
31
+
32
+ ### High-level interpretation
33
+ - **Additive-only change set** (no direct regressions from edits to existing files expected).
34
+ - **Pipeline orchestration passed**, suggesting jobs ran correctly.
35
+ - **Test execution failed**, indicating either:
36
+ - new functionality is incomplete/incorrect,
37
+ - tests are outdated or misconfigured,
38
+ - dependency/version/environment mismatch.
39
+
40
+ ---
41
+
42
+ ## 3) Difference Analysis
43
+
44
+ Because only aggregate metadata is provided (no file paths or patch hunks), analysis is structural:
45
+
46
+ 1. **No legacy code edits**
47
+ - Existing APIs likely unchanged directly.
48
+ - Backward compatibility risk is lower than in refactor/edit-heavy updates.
49
+
50
+ 2. **New surface area introduced**
51
+ - 8 files likely include one or more of:
52
+ - implementation modules,
53
+ - tests,
54
+ - docs/examples,
55
+ - configuration helpers.
56
+ - Any newly introduced module still affects packaging/import graph and CI.
57
+
58
+ 3. **Quality gate mismatch**
59
+ - CI workflow success + tests failed implies workflow did not enforce test pass as a hard gate, or failures occurred in a non-blocking stage.
60
+
61
+ ---
62
+
63
+ ## 4) Technical Analysis
64
+
65
+ ## 4.1 Risk Assessment
66
+
67
+ | Area | Risk | Rationale |
68
+ |---|---|---|
69
+ | API stability | Low–Medium | No modified files, but new public modules may expose new API surface. |
70
+ | Runtime behavior | Medium | New files can alter import side effects, plugin discovery, or optional paths. |
71
+ | Test reliability | High | Failed tests directly reduce confidence in correctness. |
72
+ | Release readiness | High risk (not ready) | Test suite failing is a release blocker for scientific Python libs. |
73
+
74
+ ## 4.2 Likely Failure Categories (to triage first)
75
+
76
+ - **Unit test expectation mismatch** for newly added behavior.
77
+ - **Missing optional dependencies** in CI test matrix.
78
+ - **Numerical tolerance/precision drift** (common in scientific stacks).
79
+ - **Platform-specific failures** (Linux/macOS/Windows differences).
80
+ - **Import/package registration issues** (new files not wired into package init or config).
81
+ - **Style/type/linters treated as tests** if test stage aggregates tooling checks.
82
+
83
+ ## 4.3 Validation Gaps
84
+
85
+ - No file-level diff context available.
86
+ - No failing test names/tracebacks included.
87
+ - Cannot confirm whether failures are deterministic or flaky.
88
+
89
+ ---
90
+
91
+ ## 5) Recommendations & Improvements
92
+
93
+ ## 5.1 Immediate (Blocker Resolution)
94
+
95
+ 1. **Collect failure artifacts**
96
+ - Extract failing test IDs, stack traces, and environment metadata (Python, NumPy/SciPy, OS).
97
+ 2. **Classify failures**
98
+ - New-code defects vs. test harness/config issues.
99
+ 3. **Re-run targeted tests locally and in CI**
100
+ - Isolate minimal reproducer; verify determinism.
101
+ 4. **Enforce hard gate**
102
+ - Ensure release/protected branch requires test success.
103
+
104
+ ## 5.2 Short-term Quality Hardening
105
+
106
+ - Add/adjust tests for each new file’s intended behavior.
107
+ - If numeric algorithms were added, pin tolerances and seed randomness.
108
+ - Validate packaging exposure (`__init__`, entry points, module discovery).
109
+ - Run matrix smoke tests across supported Python versions.
110
+
111
+ ## 5.3 Process Improvements
112
+
113
+ - Introduce a **change manifest** in PRs: purpose of each new file + expected impact.
114
+ - Add CI stage separation:
115
+ - lint/type/doc checks,
116
+ - unit/integration tests,
117
+ - optional slow tests.
118
+ - Track flaky tests and quarantine with explicit issue links.
119
+
120
+ ---
121
+
122
+ ## 6) Deployment Information
123
+
124
+ ## 6.1 Current Deployment Readiness
125
+
126
+ **Status: Not recommended for deployment** due to failed tests.
127
+
128
+ ## 6.2 Suggested Release Criteria
129
+
130
+ Deploy only after all conditions are met:
131
+
132
+ - ✅ All required tests pass on supported matrix.
133
+ - ✅ No critical/new warnings in CI logs.
134
+ - ✅ Documentation/changelog entries for new files.
135
+ - ✅ Versioning decision made (likely patch/minor based on new functionality exposure).
136
+
137
+ ## 6.3 Rollout Strategy (once green)
138
+
139
+ - Use staged rollout (internal validation → broader user release).
140
+ - Monitor error reports/import issues post-release.
141
+ - Prepare rapid rollback/hotfix path.
142
+
143
+ ---
144
+
145
+ ## 7) Future Planning
146
+
147
+ 1. **Improve observability in CI**
148
+ - Publish structured test reports and failure clustering.
149
+ 2. **Strengthen compatibility guarantees**
150
+ - Add contract tests for public APIs.
151
+ 3. **Automate regression prevention**
152
+ - Pre-merge required checks + nightly full-matrix runs.
153
+ 4. **Documentation alignment**
154
+ - Ensure examples/tutorials reference new functionality where relevant.
155
+
156
+ ---
157
+
158
+ ## 8) Executive Conclusion
159
+
160
+ This change set is structurally low-intrusive (**8 new files, no modifications**), but **test failures are a hard release blocker**.
161
+ Primary priority is failure triage and stabilization. Once tests are green and packaging/API exposure is validated, the update should be safe to proceed through normal release gates.
mne-python/mcp_output/mcp_plugin/__init__.py ADDED
File without changes
mne-python/mcp_output/mcp_plugin/adapter.py ADDED
@@ -0,0 +1,358 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import importlib
4
+ import traceback
5
+ from typing import Any, Dict, List, Optional
6
+
7
+ source_path = os.path.join(
8
+ os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
9
+ "source",
10
+ )
11
+ sys.path.insert(0, source_path)
12
+
13
+
14
+ class Adapter:
15
+ """
16
+ Import-mode adapter for the mne-python MCP plugin integration.
17
+
18
+ This adapter prioritizes Python imports and provides a graceful CLI fallback
19
+ pathway when import-based execution is unavailable.
20
+ """
21
+
22
+ # -------------------------------------------------------------------------
23
+ # Lifecycle / Initialization
24
+ # -------------------------------------------------------------------------
25
+ def __init__(self) -> None:
26
+ """
27
+ Initialize adapter state, import registry, and module availability.
28
+
29
+ Attributes:
30
+ mode: Adapter execution mode, fixed to "import".
31
+ package_root: Root import path for repository package.
32
+ modules: Loaded module cache keyed by logical name.
33
+ available: Boolean import readiness state.
34
+ warnings: List of non-fatal issues detected during initialization.
35
+ """
36
+ self.mode = "import"
37
+ self.package_root = "mne"
38
+ self.modules: Dict[str, Any] = {}
39
+ self.available = False
40
+ self.warnings: List[str] = []
41
+ self._initialize_imports()
42
+
43
+ def _initialize_imports(self) -> None:
44
+ """
45
+ Attempt to import core and command modules identified by analysis.
46
+
47
+ This method captures and stores import exceptions so the adapter can
48
+ continue operating in graceful fallback mode.
49
+ """
50
+ targets = {
51
+ "mne": "mne",
52
+ "commands": "mne.commands",
53
+ }
54
+
55
+ loaded = 0
56
+ for key, mod_path in targets.items():
57
+ try:
58
+ self.modules[key] = importlib.import_module(mod_path)
59
+ loaded += 1
60
+ except Exception as exc:
61
+ self.modules[key] = None
62
+ self.warnings.append(
63
+ f"Failed to import '{mod_path}'. Verify local source checkout and dependencies. Detail: {exc}"
64
+ )
65
+ self.available = loaded > 0
66
+
67
+ # -------------------------------------------------------------------------
68
+ # Unified response helpers
69
+ # -------------------------------------------------------------------------
70
+ def _ok(self, message: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
71
+ return {"status": "success", "message": message, "data": data or {}}
72
+
73
+ def _fail(
74
+ self,
75
+ message: str,
76
+ error: Optional[str] = None,
77
+ guidance: Optional[str] = None,
78
+ data: Optional[Dict[str, Any]] = None,
79
+ ) -> Dict[str, Any]:
80
+ payload = {"status": "error", "message": message, "data": data or {}}
81
+ if error:
82
+ payload["error"] = error
83
+ if guidance:
84
+ payload["guidance"] = guidance
85
+ return payload
86
+
87
+ def _fallback(
88
+ self,
89
+ action: str,
90
+ reason: str,
91
+ extra: Optional[Dict[str, Any]] = None,
92
+ ) -> Dict[str, Any]:
93
+ return {
94
+ "status": "fallback",
95
+ "message": f"Import mode unavailable for '{action}'.",
96
+ "reason": reason,
97
+ "guidance": (
98
+ "Ensure repository source is present under the configured 'source' directory and "
99
+ "install required dependencies (numpy, scipy, matplotlib, packaging, pooch, tqdm). "
100
+ "If import still fails, use the CLI fallback via the 'mne' command."
101
+ ),
102
+ "data": extra or {},
103
+ }
104
+
105
+ # -------------------------------------------------------------------------
106
+ # Health / Introspection
107
+ # -------------------------------------------------------------------------
108
+ def health_check(self) -> Dict[str, Any]:
109
+ """
110
+ Report adapter readiness and import diagnostics.
111
+
112
+ Returns:
113
+ Dict with status, mode, import availability, and warning details.
114
+ """
115
+ return self._ok(
116
+ "Adapter health check completed.",
117
+ {
118
+ "mode": self.mode,
119
+ "available": self.available,
120
+ "loaded_modules": {k: bool(v) for k, v in self.modules.items()},
121
+ "warnings": self.warnings,
122
+ },
123
+ )
124
+
125
+ def list_known_packages(self) -> Dict[str, Any]:
126
+ """
127
+ Return package namespaces discovered during analysis.
128
+
129
+ Returns:
130
+ Dict containing analyzed package names for discovery/debugging.
131
+ """
132
+ packages = [
133
+ "deployment.mne-python.source",
134
+ "mcp_output.mcp_plugin",
135
+ "source.mne",
136
+ "source.mne._fiff",
137
+ "source.mne.beamformer",
138
+ "source.mne.channels",
139
+ "source.mne.commands",
140
+ "source.mne.data",
141
+ "source.mne.datasets",
142
+ "source.mne.decoding",
143
+ "source.mne.export",
144
+ "source.mne.forward",
145
+ "source.mne.gui",
146
+ "source.mne.html_templates",
147
+ "source.mne.inverse_sparse",
148
+ "source.mne.io",
149
+ "source.mne.minimum_norm",
150
+ "source.mne.preprocessing",
151
+ "source.mne.report",
152
+ "source.mne.simulation",
153
+ "source.mne.source_space",
154
+ "source.mne.stats",
155
+ "source.mne.tests",
156
+ "source.mne.time_frequency",
157
+ "source.mne.utils",
158
+ "source.mne.viz",
159
+ ]
160
+ return self._ok("Known package list prepared.", {"packages": packages})
161
+
162
+ # -------------------------------------------------------------------------
163
+ # Module management
164
+ # -------------------------------------------------------------------------
165
+ def import_module(self, module_path: str) -> Dict[str, Any]:
166
+ """
167
+ Dynamically import an MNE module using full package path.
168
+
169
+ Args:
170
+ module_path: Absolute module path (e.g., 'mne.io', 'mne.preprocessing').
171
+
172
+ Returns:
173
+ Unified status dictionary with module import result.
174
+ """
175
+ try:
176
+ mod = importlib.import_module(module_path)
177
+ self.modules[module_path] = mod
178
+ return self._ok("Module imported successfully.", {"module_path": module_path})
179
+ except Exception as exc:
180
+ return self._fail(
181
+ "Module import failed.",
182
+ error=str(exc),
183
+ guidance="Confirm module path and dependency installation.",
184
+ data={"module_path": module_path},
185
+ )
186
+
187
+ def get_module_attributes(self, module_path: str, limit: int = 200) -> Dict[str, Any]:
188
+ """
189
+ Enumerate public attributes for a module to support function discovery.
190
+
191
+ Args:
192
+ module_path: Full module path.
193
+ limit: Maximum number of attributes to return.
194
+
195
+ Returns:
196
+ Unified status dictionary containing exported attribute names.
197
+ """
198
+ try:
199
+ mod = self.modules.get(module_path) or importlib.import_module(module_path)
200
+ attrs = [a for a in dir(mod) if not a.startswith("_")]
201
+ return self._ok(
202
+ "Module attributes fetched.",
203
+ {"module_path": module_path, "attributes": attrs[: max(1, limit)]},
204
+ )
205
+ except Exception as exc:
206
+ return self._fail(
207
+ "Could not inspect module attributes.",
208
+ error=str(exc),
209
+ guidance="Import the module first and verify it is available in local source.",
210
+ data={"module_path": module_path},
211
+ )
212
+
213
+ # -------------------------------------------------------------------------
214
+ # Core MNE call surface
215
+ # -------------------------------------------------------------------------
216
+ def call_mne_function(self, function_name: str, *args: Any, **kwargs: Any) -> Dict[str, Any]:
217
+ """
218
+ Call a function from the top-level mne module by name.
219
+
220
+ Args:
221
+ function_name: Name of the function in module 'mne'.
222
+ *args: Positional arguments forwarded to the target function.
223
+ **kwargs: Keyword arguments forwarded to the target function.
224
+
225
+ Returns:
226
+ Unified status dictionary with execution result or actionable failure.
227
+ """
228
+ if not self.modules.get("mne"):
229
+ return self._fallback("call_mne_function", "Top-level module 'mne' is not importable.")
230
+
231
+ try:
232
+ target = getattr(self.modules["mne"], function_name, None)
233
+ if target is None or not callable(target):
234
+ return self._fail(
235
+ "Requested MNE function was not found.",
236
+ guidance="Use get_module_attributes('mne') to discover available callables.",
237
+ data={"function_name": function_name},
238
+ )
239
+ result = target(*args, **kwargs)
240
+ return self._ok(
241
+ "MNE function executed successfully.",
242
+ {"function_name": function_name, "result": result},
243
+ )
244
+ except Exception as exc:
245
+ return self._fail(
246
+ "MNE function execution failed.",
247
+ error=str(exc),
248
+ guidance="Validate function arguments and data formats expected by MNE.",
249
+ data={"function_name": function_name, "traceback": traceback.format_exc()},
250
+ )
251
+
252
+ # -------------------------------------------------------------------------
253
+ # CLI wrapper (fallback-friendly)
254
+ # -------------------------------------------------------------------------
255
+ def call_mne_cli(self, argv: Optional[List[str]] = None) -> Dict[str, Any]:
256
+ """
257
+ Execute the primary MNE command-line wrapper from imported command module.
258
+
259
+ Args:
260
+ argv: Optional list of CLI-like arguments. If omitted, attempts default call.
261
+
262
+ Returns:
263
+ Unified status dictionary with invocation status and hints.
264
+ """
265
+ commands_mod = self.modules.get("commands")
266
+ if not commands_mod:
267
+ return self._fallback("call_mne_cli", "Module 'mne.commands' is not importable.")
268
+
269
+ try:
270
+ entry_candidates = ["main", "run", "command_main"]
271
+ entry = None
272
+ for name in entry_candidates:
273
+ fn = getattr(commands_mod, name, None)
274
+ if callable(fn):
275
+ entry = fn
276
+ break
277
+
278
+ if entry is None:
279
+ return self._fail(
280
+ "No callable CLI entry point found in mne.commands.",
281
+ guidance="Inspect mne.commands module attributes and map the correct callable.",
282
+ data={"checked_candidates": entry_candidates},
283
+ )
284
+
285
+ if argv is None:
286
+ out = entry()
287
+ else:
288
+ out = entry(argv)
289
+
290
+ return self._ok(
291
+ "MNE CLI wrapper executed.",
292
+ {"argv": argv or [], "result": out, "entry_point": entry.__name__},
293
+ )
294
+ except TypeError:
295
+ try:
296
+ out = entry() # type: ignore[misc]
297
+ return self._ok(
298
+ "MNE CLI wrapper executed with default signature.",
299
+ {"argv": argv or [], "result": out, "entry_point": entry.__name__}, # type: ignore[union-attr]
300
+ )
301
+ except Exception as exc:
302
+ return self._fail(
303
+ "MNE CLI invocation failed.",
304
+ error=str(exc),
305
+ guidance="Pass valid subcommands/arguments or verify command module compatibility.",
306
+ data={"traceback": traceback.format_exc()},
307
+ )
308
+ except Exception as exc:
309
+ return self._fail(
310
+ "MNE CLI invocation failed.",
311
+ error=str(exc),
312
+ guidance="Check installed optional dependencies and command arguments.",
313
+ data={"traceback": traceback.format_exc()},
314
+ )
315
+
316
+ # -------------------------------------------------------------------------
317
+ # Class instantiation helper (generic, analysis-driven)
318
+ # -------------------------------------------------------------------------
319
+ def create_instance(
320
+ self,
321
+ module_path: str,
322
+ class_name: str,
323
+ *args: Any,
324
+ **kwargs: Any,
325
+ ) -> Dict[str, Any]:
326
+ """
327
+ Instantiate a class from a target module path.
328
+
329
+ Args:
330
+ module_path: Full module path containing the class.
331
+ class_name: Class name to instantiate.
332
+ *args: Positional constructor arguments.
333
+ **kwargs: Keyword constructor arguments.
334
+
335
+ Returns:
336
+ Unified status dictionary with instantiated object handle.
337
+ """
338
+ try:
339
+ mod = self.modules.get(module_path) or importlib.import_module(module_path)
340
+ cls = getattr(mod, class_name, None)
341
+ if cls is None:
342
+ return self._fail(
343
+ "Class not found in module.",
344
+ guidance="Use get_module_attributes(module_path) to verify class exports.",
345
+ data={"module_path": module_path, "class_name": class_name},
346
+ )
347
+ instance = cls(*args, **kwargs)
348
+ return self._ok(
349
+ "Class instantiated successfully.",
350
+ {"module_path": module_path, "class_name": class_name, "instance": instance},
351
+ )
352
+ except Exception as exc:
353
+ return self._fail(
354
+ "Class instantiation failed.",
355
+ error=str(exc),
356
+ guidance="Verify constructor arguments and required dependencies for this class.",
357
+ data={"module_path": module_path, "class_name": class_name, "traceback": traceback.format_exc()},
358
+ )
mne-python/mcp_output/mcp_plugin/main.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ MCP Service Auto-Wrapper - Auto-generated
3
+ """
4
+ from mcp_service import create_app
5
+
6
+ def main():
7
+ """Main entry point"""
8
+ app = create_app()
9
+ return app
10
+
11
+ if __name__ == "__main__":
12
+ app = main()
13
+ app.run()
mne-python/mcp_output/mcp_plugin/mcp_service.py ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ from typing import Optional, Dict, Any, List
4
+
5
+ source_path = os.path.join(
6
+ os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
7
+ "source",
8
+ )
9
+ if source_path not in sys.path:
10
+ sys.path.insert(0, source_path)
11
+
12
+ from fastmcp import FastMCP
13
+
14
+ mcp = FastMCP("mne_python_service")
15
+
16
+
17
+ def _safe_import_mne():
18
+ try:
19
+ import mne # type: ignore
20
+ return True, mne, None
21
+ except Exception as exc:
22
+ return False, None, str(exc)
23
+
24
+
25
+ @mcp.tool(name="mne_get_version", description="Get installed MNE version information.")
26
+ def mne_get_version() -> Dict[str, Any]:
27
+ """
28
+ Return MNE package version.
29
+
30
+ Returns:
31
+ Dict with:
32
+ - success: bool indicating operation status
33
+ - result: version string when successful
34
+ - error: error string when failed
35
+ """
36
+ ok, mne_mod, err = _safe_import_mne()
37
+ if not ok:
38
+ return {"success": False, "result": None, "error": err}
39
+ try:
40
+ version = getattr(mne_mod, "__version__", "unknown")
41
+ return {"success": True, "result": version, "error": None}
42
+ except Exception as exc:
43
+ return {"success": False, "result": None, "error": str(exc)}
44
+
45
+
46
+ @mcp.tool(name="mne_get_config", description="Read MNE configuration value by key.")
47
+ def mne_get_config(key: str, default: Optional[str] = None) -> Dict[str, Any]:
48
+ """
49
+ Read a single MNE config key.
50
+
51
+ Parameters:
52
+ key: Configuration key to lookup.
53
+ default: Optional fallback if key is not found.
54
+
55
+ Returns:
56
+ Dict with:
57
+ - success: bool
58
+ - result: config value
59
+ - error: error message when failed
60
+ """
61
+ ok, mne_mod, err = _safe_import_mne()
62
+ if not ok:
63
+ return {"success": False, "result": None, "error": err}
64
+ try:
65
+ value = mne_mod.get_config(key=key, default=default)
66
+ return {"success": True, "result": value, "error": None}
67
+ except Exception as exc:
68
+ return {"success": False, "result": None, "error": str(exc)}
69
+
70
+
71
+ @mcp.tool(name="mne_set_config", description="Set an MNE configuration key to a value.")
72
+ def mne_set_config(key: str, value: str, set_env: bool = False) -> Dict[str, Any]:
73
+ """
74
+ Set a single MNE config key.
75
+
76
+ Parameters:
77
+ key: Configuration key.
78
+ value: Configuration value.
79
+ set_env: If True, also set environment variable for current process.
80
+
81
+ Returns:
82
+ Dict with:
83
+ - success: bool
84
+ - result: True when set successfully
85
+ - error: error message when failed
86
+ """
87
+ ok, mne_mod, err = _safe_import_mne()
88
+ if not ok:
89
+ return {"success": False, "result": None, "error": err}
90
+ try:
91
+ mne_mod.set_config(key=key, value=value, set_env=set_env)
92
+ return {"success": True, "result": True, "error": None}
93
+ except Exception as exc:
94
+ return {"success": False, "result": None, "error": str(exc)}
95
+
96
+
97
+ @mcp.tool(name="mne_create_info", description="Create an MNE Info object from channels and sampling frequency.")
98
+ def mne_create_info(ch_names: List[str], sfreq: float, ch_types: Optional[List[str]] = None) -> Dict[str, Any]:
99
+ """
100
+ Create a lightweight channel metadata structure.
101
+
102
+ Parameters:
103
+ ch_names: List of channel names.
104
+ sfreq: Sampling frequency in Hz.
105
+ ch_types: Optional list of channel types aligned with ch_names.
106
+
107
+ Returns:
108
+ Dict with:
109
+ - success: bool
110
+ - result: serializable summary of created Info
111
+ - error: error message when failed
112
+ """
113
+ ok, mne_mod, err = _safe_import_mne()
114
+ if not ok:
115
+ return {"success": False, "result": None, "error": err}
116
+ try:
117
+ info = mne_mod.create_info(ch_names=ch_names, sfreq=sfreq, ch_types=ch_types)
118
+ result = {
119
+ "nchan": int(info["nchan"]),
120
+ "sfreq": float(info["sfreq"]),
121
+ "ch_names": list(info["ch_names"]),
122
+ "highpass": float(info.get("highpass", 0.0) or 0.0),
123
+ "lowpass": float(info.get("lowpass", 0.0) or 0.0),
124
+ }
125
+ return {"success": True, "result": result, "error": None}
126
+ except Exception as exc:
127
+ return {"success": False, "result": None, "error": str(exc)}
128
+
129
+
130
+ @mcp.tool(name="mne_compute_events", description="Detect events from a stim channel in a raw FIF file.")
131
+ def mne_compute_events(
132
+ raw_fif_path: str,
133
+ stim_channel: Optional[str] = None,
134
+ shortest_event: int = 1,
135
+ min_duration: float = 0.0,
136
+ ) -> Dict[str, Any]:
137
+ """
138
+ Load raw FIF and compute events from stimulation channel.
139
+
140
+ Parameters:
141
+ raw_fif_path: Path to a readable raw FIF file.
142
+ stim_channel: Optional stim channel name. If None, MNE default detection is used.
143
+ shortest_event: Minimum number of samples for an event.
144
+ min_duration: Minimum event duration in seconds.
145
+
146
+ Returns:
147
+ Dict with:
148
+ - success: bool
149
+ - result: event count and preview rows
150
+ - error: error message when failed
151
+ """
152
+ ok, mne_mod, err = _safe_import_mne()
153
+ if not ok:
154
+ return {"success": False, "result": None, "error": err}
155
+ try:
156
+ raw = mne_mod.io.read_raw_fif(raw_fif_path, preload=False, verbose=False)
157
+ events = mne_mod.find_events(
158
+ raw,
159
+ stim_channel=stim_channel,
160
+ shortest_event=shortest_event,
161
+ min_duration=min_duration,
162
+ verbose=False,
163
+ )
164
+ preview = events[:20].tolist() if len(events) > 0 else []
165
+ return {
166
+ "success": True,
167
+ "result": {"count": int(len(events)), "preview": preview},
168
+ "error": None,
169
+ }
170
+ except Exception as exc:
171
+ return {"success": False, "result": None, "error": str(exc)}
172
+
173
+
174
+ @mcp.tool(name="mne_estimate_rank", description="Estimate data rank from an epochs or raw FIF file.")
175
+ def mne_estimate_rank(fif_path: str, tol: Optional[float] = None) -> Dict[str, Any]:
176
+ """
177
+ Estimate numerical rank from MNE data object loaded from FIF.
178
+
179
+ Parameters:
180
+ fif_path: Path to raw or epochs FIF file.
181
+ tol: Optional tolerance passed to rank estimator.
182
+
183
+ Returns:
184
+ Dict with:
185
+ - success: bool
186
+ - result: estimated rank dictionary or scalar
187
+ - error: error message when failed
188
+ """
189
+ ok, mne_mod, err = _safe_import_mne()
190
+ if not ok:
191
+ return {"success": False, "result": None, "error": err}
192
+ try:
193
+ result_obj: Any
194
+ try:
195
+ raw = mne_mod.io.read_raw_fif(fif_path, preload=False, verbose=False)
196
+ result_obj = mne_mod.compute_rank(raw, tol=tol, verbose=False)
197
+ except Exception:
198
+ epochs = mne_mod.read_epochs(fif_path, preload=False, verbose=False)
199
+ result_obj = mne_mod.compute_rank(epochs, tol=tol, verbose=False)
200
+
201
+ if isinstance(result_obj, dict):
202
+ serializable = {str(k): int(v) for k, v in result_obj.items()}
203
+ else:
204
+ serializable = int(result_obj)
205
+ return {"success": True, "result": serializable, "error": None}
206
+ except Exception as exc:
207
+ return {"success": False, "result": None, "error": str(exc)}
208
+
209
+
210
+ def create_app() -> FastMCP:
211
+ return mcp
212
+
213
+
214
+ if __name__ == "__main__":
215
+ mcp.run()
mne-python/mcp_output/requirements.txt ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ fastmcp
2
+ fastapi
3
+ uvicorn[standard]
4
+ pydantic>=2.0.0
5
+ decorator >= 5.1
6
+ jinja2 >= 3.1
7
+ lazy_loader >= 0.3
8
+ matplotlib >= 3.8
9
+ numpy >= 1.26, < 3
10
+ packaging
11
+ pooch >= 1.5
12
+ scipy >= 1.12
13
+ tqdm >= 4.66
14
+ nest-asyncio2
15
+ pymef
16
+ pyobjc-framework-Cocoa >=5.2.0;platform_system=='Darwin'
mne-python/mcp_output/start_mcp.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ """
3
+ MCP Service Startup Entry
4
+ """
5
+ import sys
6
+ import os
7
+
8
+ project_root = os.path.dirname(os.path.abspath(__file__))
9
+ mcp_plugin_dir = os.path.join(project_root, "mcp_plugin")
10
+ if mcp_plugin_dir not in sys.path:
11
+ sys.path.insert(0, mcp_plugin_dir)
12
+
13
+ from mcp_service import create_app
14
+
15
+ def main():
16
+ """Start FastMCP service"""
17
+ app = create_app()
18
+ # Use environment variable to configure port, default 8000
19
+ port = int(os.environ.get("MCP_PORT", "8000"))
20
+
21
+ # Choose transport mode based on environment variable
22
+ transport = os.environ.get("MCP_TRANSPORT", "stdio")
23
+ if transport == "http":
24
+ app.run(transport="http", host="0.0.0.0", port=port)
25
+ else:
26
+ # Default to STDIO mode
27
+ app.run()
28
+
29
+ if __name__ == "__main__":
30
+ main()
mne-python/mcp_output/workflow_summary.json ADDED
@@ -0,0 +1,253 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "repository": {
3
+ "name": "mne-python",
4
+ "url": "https://github.com/mne-tools/mne-python",
5
+ "local_path": "/Users/ghh/Documents/Code/Code2MCP-private/workspace/mne-python",
6
+ "description": "Python library",
7
+ "features": "Basic functionality",
8
+ "tech_stack": "Python",
9
+ "stars": 0,
10
+ "forks": 0,
11
+ "language": "Python",
12
+ "last_updated": "",
13
+ "complexity": "complex",
14
+ "intrusiveness_risk": "medium"
15
+ },
16
+ "execution": {
17
+ "start_time": 1773461253.309027,
18
+ "end_time": 1773462216.903234,
19
+ "duration": 963.5942070484161,
20
+ "status": "success",
21
+ "workflow_status": "success",
22
+ "nodes_executed": [
23
+ "download",
24
+ "analysis",
25
+ "env",
26
+ "generate",
27
+ "run",
28
+ "review",
29
+ "finalize"
30
+ ],
31
+ "total_files_processed": 26,
32
+ "environment_type": "unknown",
33
+ "llm_calls": 0,
34
+ "deepwiki_calls": 0
35
+ },
36
+ "tests": {
37
+ "original_project": {
38
+ "passed": false,
39
+ "details": {},
40
+ "test_coverage": "100%",
41
+ "execution_time": 0,
42
+ "test_files": []
43
+ },
44
+ "mcp_plugin": {
45
+ "passed": true,
46
+ "details": {},
47
+ "service_health": "healthy",
48
+ "startup_time": 0,
49
+ "transport_mode": "stdio",
50
+ "fastmcp_version": "unknown",
51
+ "mcp_version": "unknown"
52
+ }
53
+ },
54
+ "analysis": {
55
+ "structure": {
56
+ "packages": [
57
+ "deployment.mne-python.source",
58
+ "mcp_output.mcp_plugin",
59
+ "source.mne",
60
+ "source.mne._fiff",
61
+ "source.mne.beamformer",
62
+ "source.mne.channels",
63
+ "source.mne.commands",
64
+ "source.mne.data",
65
+ "source.mne.datasets",
66
+ "source.mne.decoding",
67
+ "source.mne.export",
68
+ "source.mne.forward",
69
+ "source.mne.gui",
70
+ "source.mne.html_templates",
71
+ "source.mne.inverse_sparse",
72
+ "source.mne.io",
73
+ "source.mne.minimum_norm",
74
+ "source.mne.preprocessing",
75
+ "source.mne.report",
76
+ "source.mne.simulation",
77
+ "source.mne.source_space",
78
+ "source.mne.stats",
79
+ "source.mne.tests",
80
+ "source.mne.time_frequency",
81
+ "source.mne.utils",
82
+ "source.mne.viz"
83
+ ]
84
+ },
85
+ "dependencies": {
86
+ "has_environment_yml": true,
87
+ "has_requirements_txt": false,
88
+ "pyproject": true,
89
+ "setup_cfg": false,
90
+ "setup_py": false
91
+ },
92
+ "entry_points": {
93
+ "imports": [],
94
+ "cli": [],
95
+ "modules": []
96
+ },
97
+ "risk_assessment": {
98
+ "import_feasibility": 0.72,
99
+ "intrusiveness_risk": "medium",
100
+ "complexity": "complex"
101
+ },
102
+ "deepwiki_analysis": {
103
+ "repo_url": "https://github.com/mne-tools/mne-python",
104
+ "repo_name": "mne-python",
105
+ "error": "DeepWiki analysis failed",
106
+ "model": "gpt-5.3-codex",
107
+ "source": "llm_direct_analysis",
108
+ "success": false
109
+ },
110
+ "code_complexity": {
111
+ "cyclomatic_complexity": "medium",
112
+ "cognitive_complexity": "medium",
113
+ "maintainability_index": 75
114
+ },
115
+ "security_analysis": {
116
+ "vulnerabilities_found": 0,
117
+ "security_score": 85,
118
+ "recommendations": []
119
+ }
120
+ },
121
+ "plugin_generation": {
122
+ "files_created": [
123
+ "mcp_output/start_mcp.py",
124
+ "mcp_output/mcp_plugin/__init__.py",
125
+ "mcp_output/mcp_plugin/mcp_service.py",
126
+ "mcp_output/mcp_plugin/adapter.py",
127
+ "mcp_output/mcp_plugin/main.py",
128
+ "mcp_output/requirements.txt",
129
+ "mcp_output/README_MCP.md"
130
+ ],
131
+ "main_entry": "start_mcp.py",
132
+ "requirements": [
133
+ "fastmcp>=0.1.0",
134
+ "pydantic>=2.0.0"
135
+ ],
136
+ "readme_path": "/Users/ghh/Documents/Code/Code2MCP-private/workspace/mne-python/mcp_output/README_MCP.md",
137
+ "adapter_mode": "import",
138
+ "total_lines_of_code": 0,
139
+ "generated_files_size": 0,
140
+ "tool_endpoints": 0,
141
+ "supported_features": [
142
+ "Basic functionality"
143
+ ],
144
+ "generated_tools": [
145
+ "Basic tools",
146
+ "Health check tools",
147
+ "Version info tools"
148
+ ]
149
+ },
150
+ "code_review": {},
151
+ "errors": [],
152
+ "warnings": [],
153
+ "recommendations": [
154
+ "Harden repository ingestion with retry/resume and fallback to shallow git clone when zip download fails",
155
+ "Add a preflight dependency checker that validates required/optional MNE extras and reports actionable install commands",
156
+ "Implement lazy imports and per-endpoint module loading to reduce startup cost and import-side failures",
157
+ "Add a CLI fallback execution path for heavy/fragile endpoints (especially viz and large IO) when import mode errors",
158
+ "Introduce endpoint-level health checks/smoke tests using small synthetic MNE objects (RawArray/Epochs) to validate MCP bindings",
159
+ "Expand automated tests in `tests_mcp` for argument validation",
160
+ "error mapping",
161
+ "and serialization of core classes",
162
+ "Add structured error taxonomy (DependencyMissing",
163
+ "FileFormatUnsupported",
164
+ "RuntimeImportError",
165
+ "HeadlessVizError) with user-friendly remediation hints",
166
+ "Gate visualization endpoints behind headless-safe checks (matplotlib backend/PyVista availability) and return clear non-GUI alternatives",
167
+ "Improve README_MCP with concrete examples for common workflows (load raw",
168
+ "find events",
169
+ "ICA",
170
+ "PSD) and expected input/output schemas",
171
+ "Add version pinning/compatibility matrix for `mne`",
172
+ "`numpy`",
173
+ "`scipy`",
174
+ "and `pydantic` to prevent runtime drift",
175
+ "Generate JSON Schemas for each endpoint and enforce strict Pydantic models for stable MCP contracts",
176
+ "Add timeout/cancellation controls and memory guards for long-running transforms (TFR/ICA/CSD)",
177
+ "Implement lightweight caching for repeated file reads and computed intermediates (with invalidation by file hash)",
178
+ "Add observability: structured logs",
179
+ "per-endpoint latency/error metrics",
180
+ "and import-failure counters",
181
+ "Create a minimal “safe default” endpoint set (non-viz",
182
+ "low-memory) and mark advanced endpoints as optional capability flags",
183
+ "Add integration tests for representative file formats (FIF/EDF/BDF/BrainVision) with tiny fixtures",
184
+ "Validate and normalize path handling across OSes (spaces",
185
+ "unicode",
186
+ "relative paths) before IO calls",
187
+ "Add graceful degradation when optional packages are missing (e.g.",
188
+ "skip vtk/pyvista features instead of failing server start)",
189
+ "Include a reproducible dev environment (`environment.yml`/lockfile) for MCP plugin CI",
190
+ "Add CI workflow to run lint/type-check/tests for `mcp_output` and publish test report artifacts"
191
+ ],
192
+ "performance_metrics": {
193
+ "memory_usage_mb": 0,
194
+ "cpu_usage_percent": 0,
195
+ "response_time_ms": 0,
196
+ "throughput_requests_per_second": 0
197
+ },
198
+ "deployment_info": {
199
+ "supported_platforms": [
200
+ "Linux",
201
+ "Windows",
202
+ "macOS"
203
+ ],
204
+ "python_versions": [
205
+ "3.8",
206
+ "3.9",
207
+ "3.10",
208
+ "3.11",
209
+ "3.12"
210
+ ],
211
+ "deployment_methods": [
212
+ "Docker",
213
+ "pip",
214
+ "conda"
215
+ ],
216
+ "monitoring_support": true,
217
+ "logging_configuration": "structured"
218
+ },
219
+ "execution_analysis": {
220
+ "success_factors": [
221
+ "Workflow reached terminal success state with all planned nodes executed (download, analysis, env, generate, run, review, finalize)",
222
+ "MCP plugin runtime test passed with healthy service status over stdio transport",
223
+ "Import-based adapter strategy aligned with detected MNE API surface and produced broad endpoint coverage",
224
+ "No runtime errors or warnings were recorded during orchestration"
225
+ ],
226
+ "failure_reasons": [
227
+ "Repository preprocessing partially failed due to zip download IncompleteRead, reducing analysis fidelity",
228
+ "DeepWiki analysis failed, so architecture/context enrichment depended on fallback LLM direct analysis",
229
+ "Original project test status is failed/unknown despite reported 100% coverage metadata, indicating unreliable baseline validation",
230
+ "Generated artifact metrics are inconsistent (tool_endpoints=0 vs populated endpoint list; total_lines_of_code=0), suggesting reporting/telemetry defects"
231
+ ],
232
+ "overall_assessment": "good",
233
+ "node_performance": {
234
+ "download_time": "Download node completed but experienced non-fatal zip transfer instability (IncompleteRead). This is the primary execution fragility.",
235
+ "analysis_time": "Analysis completed via fallback path; quality adequate for generation but lower confidence than full repository preprocessing + DeepWiki.",
236
+ "generation_time": "Generation completed successfully with required files and entrypoint created; endpoint exposure is broad and useful.",
237
+ "test_time": "Service-level test passed quickly (startup_time reported 0), but original-project validation is not trustworthy; test depth appears shallow."
238
+ },
239
+ "resource_usage": {
240
+ "memory_efficiency": "Undetermined from metrics (reported 0 MB). Likely acceptable for scaffold generation, but runtime memory for heavy MNE ops remains unmeasured.",
241
+ "cpu_efficiency": "Undetermined from metrics (reported 0%). End-to-end duration (~964s) indicates non-trivial processing overhead and potential I/O/network wait.",
242
+ "disk_usage": "Generated output footprint appears underreported (0 size), indicating instrumentation gaps rather than true zero disk impact."
243
+ }
244
+ },
245
+ "technical_quality": {
246
+ "code_quality_score": 74,
247
+ "architecture_score": 78,
248
+ "performance_score": 62,
249
+ "maintainability_score": 76,
250
+ "security_score": 85,
251
+ "scalability_score": 68
252
+ }
253
+ }
mne-python/source/.DS_Store ADDED
Binary file (6.15 kB). View file
 
mne-python/source/.circleci/config.yml ADDED
@@ -0,0 +1,570 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # By default, for PRs CircleCI will build only examples that have changed.
2
+ # For main commits, builds are skipped entirely, as we only do full builds
3
+ # scheduled for one time daily.
4
+ #
5
+ # Tagging a commit with the following overrides these behaviors:
6
+ # - [circle front] will run the front page examples and perform test-doc
7
+ # - [circle full] will run all examples and perform test-doc
8
+ # - [circle linkcheck] will run our linkcheck job
9
+ # - [circle deploy] on a main or maint/* commit will try to immediately build
10
+ # and deploy docs rather than waiting for the nightly build
11
+
12
+ version: 2.1
13
+
14
+ _check_skip: &check_skip
15
+ name: Check-skip
16
+ command: |
17
+ set -e
18
+ export COMMIT_MESSAGE=$(git log --format=oneline -n 1);
19
+ if [[ "$CIRCLE_PULL_REQUEST" != "" ]] && ([[ "$COMMIT_MESSAGE" == *"[skip circle]"* ]] || [[ "$COMMIT_MESSAGE" == *"[circle skip]"* ]]); then
20
+ echo "Skip detected, exiting job ${CIRCLE_JOB} for PR ${CIRCLE_PULL_REQUEST}."
21
+ circleci-agent step halt;
22
+ fi
23
+
24
+ jobs:
25
+ build_docs:
26
+ parameters:
27
+ scheduled:
28
+ type: string
29
+ default: "false"
30
+ machine:
31
+ image: ubuntu-2404:current
32
+ # large 4 vCPUs 15GB mem
33
+ # https://discuss.circleci.com/t/changes-to-remote-docker-reporting-pricing/47759
34
+ resource_class: large
35
+ steps:
36
+ - restore_cache:
37
+ keys:
38
+ - source-cache
39
+ - checkout:
40
+ method: full
41
+ - run:
42
+ name: Complete checkout
43
+ command: |
44
+ set -e
45
+ if ! git remote -v | grep upstream; then
46
+ git remote add upstream https://github.com/mne-tools/mne-python.git
47
+ fi
48
+ git remote set-url upstream https://github.com/mne-tools/mne-python.git
49
+ git fetch upstream
50
+ - save_cache:
51
+ key: source-cache
52
+ paths:
53
+ - ".git"
54
+ - run:
55
+ <<: *check_skip
56
+ - run:
57
+ name: Merge with upstream and triage run
58
+ command: |
59
+ set -e
60
+ echo $(git log -1 --pretty=%B) | tee gitlog.txt
61
+ echo ${CI_PULL_REQUEST//*pull\//} | tee merge.txt
62
+ if [[ $(cat merge.txt) != "" ]]; then
63
+ echo "Merging $(cat merge.txt)";
64
+ git pull --ff-only upstream "refs/pull/$(cat merge.txt)/merge";
65
+ else
66
+ if [[ "$CIRCLE_BRANCH" == "main" ]]; then
67
+ KIND=dev
68
+ else
69
+ KIND=stable
70
+ fi
71
+ export COMMIT_MESSAGE=$(git log --format=oneline -n 1);
72
+ if [[ "<< parameters.scheduled >>" == "true" ]]; then
73
+ echo "Scheduled full build detected, checking if it's required."
74
+ wget https://mne.tools/${KIND}/_version.txt;
75
+ REMOTE_VERSION=$(cat _version.txt)
76
+ THIS_VERSION=$(git rev-parse HEAD)
77
+ echo "Current ${KIND} SHA: ${REMOTE_VERSION}"
78
+ echo "This ${KIND} SHA: ${THIS_VERSION}"
79
+ if [[ "${THIS_VERSION}" != "${REMOTE_VERSION}" ]]; then
80
+ echo "Rebuild required."
81
+ else
82
+ echo "Rebuild skipped."
83
+ circleci-agent step halt;
84
+ fi
85
+ elif [[ "$COMMIT_MESSAGE" == *"[circle deploy]"* ]]; then
86
+ echo "Forced deployed build detected, building and deploying docs";
87
+ else
88
+ echo "Waiting until scheduled run to build ${KIND} docs, exiting job ${CIRCLE_JOB}."
89
+ circleci-agent step halt;
90
+ fi
91
+ fi
92
+
93
+ - run:
94
+ name: Set BASH_ENV
95
+ command: ./tools/circleci_bash_env.sh
96
+
97
+ - run:
98
+ name: Install fonts needed for diagrams
99
+ command: |
100
+ mkdir -p $HOME/.fonts
101
+ echo "Source Code Pro"
102
+ curl https://codeload.github.com/adobe-fonts/source-code-pro/tar.gz/2.038R-ro/1.058R-it/1.018R-VAR | tar xz -C $HOME/.fonts
103
+ echo "Source Sans Pro"
104
+ curl https://codeload.github.com/adobe-fonts/source-sans/tar.gz/3.028R | tar xz -C $HOME/.fonts
105
+ fc-cache -f
106
+
107
+ # Load pip cache
108
+ - restore_cache:
109
+ keys:
110
+ - pip-cache-0
111
+ - restore_cache:
112
+ keys:
113
+ - user-install-bin-cache-310
114
+
115
+ # Hack in uninstalls of libraries as necessary if pip doesn't do the right thing in upgrading for us...
116
+ - run:
117
+ name: Get Python running
118
+ command: |
119
+ ./tools/circleci_dependencies.sh
120
+
121
+ - save_cache:
122
+ key: pip-cache-0
123
+ paths:
124
+ - ~/.cache/pip
125
+ - save_cache:
126
+ key: user-install-bin-cache-310
127
+ paths:
128
+ - ~/.local/lib/python3.10/site-packages
129
+ - ~/.local/bin
130
+
131
+ - run:
132
+ name: Check Qt
133
+ command: |
134
+ ./tools/check_qt_import.sh PyQt6
135
+ # Load tiny cache so that ~/.mne does not need to be created below
136
+ - restore_cache:
137
+ keys:
138
+ - data-cache-tiny-0
139
+
140
+ # Look at what we have and fail early if there is some library conflict
141
+ - run:
142
+ name: Check installation
143
+ command: |
144
+ which python
145
+ QT_DEBUG_PLUGINS=1 mne sys_info -pd
146
+ python -c "import numpy; numpy.show_config()"
147
+ python -c "import dipy.align.metrics"
148
+ LIBGL_DEBUG=verbose python -c "import pyvistaqt; pyvistaqt.BackgroundPlotter(show=True)"
149
+ python -c "import mne; mne.set_config('MNE_USE_CUDA', 'false')" # this is needed for the config tutorial
150
+ python -c "import mne; mne.set_config('MNE_LOGGING_LEVEL', 'info')"
151
+ python -c "import mne; level = mne.get_config('MNE_LOGGING_LEVEL'); assert level.lower() == 'info', repr(level)"
152
+ - run:
153
+ name: List packages
154
+ command: python -m pip list
155
+
156
+ # Figure out if we should run a full build or specify a pattern
157
+ - restore_cache:
158
+ keys:
159
+ - data-cache-tiny-1
160
+ - restore_cache:
161
+ keys:
162
+ - data-cache-multimodal
163
+ - restore_cache:
164
+ keys:
165
+ - data-cache-limo
166
+ - restore_cache:
167
+ keys:
168
+ - data-cache-fsaverage
169
+ - restore_cache:
170
+ keys:
171
+ - data-cache-bst-raw
172
+ - restore_cache:
173
+ keys:
174
+ - data-cache-bst-phantom-ctf
175
+ - restore_cache:
176
+ keys:
177
+ - data-cache-bst-phantom-elekta
178
+ - restore_cache:
179
+ keys:
180
+ - data-cache-bst-phantom-kernel
181
+ - restore_cache:
182
+ keys:
183
+ - data-cache-bst-auditory
184
+ - restore_cache:
185
+ keys:
186
+ - data-cache-bst-resting
187
+ - restore_cache:
188
+ keys:
189
+ - data-cache-fieldtrip
190
+ - restore_cache:
191
+ keys:
192
+ - data-cache-somato
193
+ - restore_cache:
194
+ keys:
195
+ - data-cache-hf-sef
196
+ - restore_cache:
197
+ keys:
198
+ - data-cache-opm
199
+ - restore_cache:
200
+ keys:
201
+ - data-cache-sample
202
+ - restore_cache:
203
+ keys:
204
+ - data-cache-spm-face
205
+ - restore_cache:
206
+ keys:
207
+ - data-cache-testing
208
+ - restore_cache:
209
+ keys:
210
+ - data-cache-visual
211
+ - restore_cache:
212
+ keys:
213
+ - data-cache-ucl-opm-auditory
214
+ - restore_cache:
215
+ keys:
216
+ - data-cache-phantom-kit
217
+ - restore_cache:
218
+ keys:
219
+ - data-cache-ds004388
220
+ - run:
221
+ name: Get data
222
+ # This limit could be increased, but this is helpful for finding slow ones
223
+ # (even ~2GB datasets should be downloadable in this time from good
224
+ # providers)
225
+ no_output_timeout: 10m
226
+ command: |
227
+ ./tools/circleci_download.sh
228
+ - run:
229
+ name: Verify build type
230
+ command: |
231
+ echo "PATTERN=$(cat pattern.txt)"
232
+ echo "BUILD=$(cat build.txt)"
233
+ ls -al ~/mne_data;
234
+
235
+ # Run doctest (if it's full or front) before building the docs
236
+ - run:
237
+ name: make test-doc
238
+ command: |
239
+ if [[ $(cat gitlog.txt) == *"[circle front]"* ]] || [[ $(cat build.txt) == "html-memory" ]] ; then
240
+ make test-doc;
241
+ mkdir -p doc/_build/test-results/test-doc;
242
+ cp junit-results.xml doc/_build/test-results/test-doc/junit.xml;
243
+ cp coverage.xml doc/_build/test-results/test-doc/coverage.xml;
244
+ fi;
245
+ # Build docs
246
+ - run:
247
+ name: make html
248
+ command: | # we have -o pipefail in #BASH_ENV so we should be okay
249
+ set -x
250
+ PATTERN=$(cat pattern.txt) make -C doc $(cat build.txt) 2>&1 | tee sphinx_log.txt
251
+ - run:
252
+ name: Check sphinx log for warnings (which are treated as errors)
253
+ when: always
254
+ command: |
255
+ ! grep "^.*\(WARNING\|ERROR\): " sphinx_log.txt
256
+ - run:
257
+ name: Show profiling output
258
+ when: always
259
+ command: |
260
+ if compgen -G "doc/*.dat" > /dev/null; then
261
+ mkdir -p doc/generated
262
+ mprof plot doc/*.dat --output doc/generated/memory.png
263
+ else
264
+ echo "No profile data found in doc/"
265
+ fi
266
+ - run:
267
+ name: Sanity check system state
268
+ command: |
269
+ python -c "import mne; level = mne.get_config('MNE_LOGGING_LEVEL'); assert level.lower() == 'info', repr(level)"
270
+
271
+ # Reduce upload time of artifacts we will (almost) never look at
272
+ - run:
273
+ name: Reduce artifact upload time
274
+ command: |
275
+ if grep -q html-pattern-memory build.txt; then
276
+ zip -rm doc/_build/html/_downloads.zip doc/_build/html/_downloads
277
+ fi
278
+ for NAME in generated auto_tutorials auto_examples; do
279
+ zip -rm doc/${NAME}.zip doc/${NAME}
280
+ done
281
+
282
+ # Save the JUnit file
283
+ - store_test_results:
284
+ path: doc/_build/test-results
285
+ - store_artifacts:
286
+ path: doc/_build/test-results
287
+ destination: test-results
288
+ # Upload test results to Codecov
289
+ - run:
290
+ name: Upload test results to Codecov
291
+ environment:
292
+ CODECOV_TOKEN: fb4c4a94-72d7-4743-bb08-af25b623a29a
293
+ command: |
294
+ if [[ -f doc/_build/test-results/test-doc/coverage.xml ]]; then
295
+ bash <(curl -s https://codecov.io/bash) -f doc/_build/test-results/test-doc/coverage.xml || true
296
+ fi
297
+ # Save the SG RST
298
+ - store_artifacts:
299
+ path: doc/auto_examples.zip
300
+ - store_artifacts:
301
+ path: doc/auto_tutorials.zip
302
+ - store_artifacts:
303
+ path: doc/generated.zip
304
+ # Save the HTML
305
+ - store_artifacts:
306
+ path: doc/_build/html/
307
+ destination: html
308
+ - persist_to_workspace:
309
+ root: doc/_build
310
+ paths:
311
+ - html
312
+
313
+ # Keep these separate, maybe better in terms of size limitations (?)
314
+ - save_cache:
315
+ key: data-cache-tiny-0 # < 100 M, might as well combine
316
+ paths:
317
+ - ~/.mne
318
+ - ~/mne_data/MNE-kiloword-data # (28 M)
319
+ - ~/mne_data/MNE-eegbci-data # (35 M)
320
+ - ~/mne_data/MNE-misc-data # (39 M)
321
+ - ~/mne_data/mTRF_1.5 # (56 M)
322
+ - ~/mne_data/MNE-phantom-4DBTi # (77 M)
323
+ - save_cache:
324
+ key: data-cache-tiny-1 # more to combine
325
+ paths:
326
+ - ~/mne_data/MNE-fNIRS-motor-data # (71 M)
327
+ - ~/mne_data/MNE-refmeg-noise-data # (93 M)
328
+ - ~/mne_data/physionet-sleep-data # (95 M)
329
+ - save_cache:
330
+ key: data-cache-multimodal
331
+ paths:
332
+ - ~/mne_data/MNE-multimodal-data # (240 M)
333
+ - save_cache:
334
+ key: data-cache-limo
335
+ paths:
336
+ - ~/mne_data/MNE-limo-data # (244 M)
337
+ - save_cache:
338
+ key: data-cache-fsaverage
339
+ paths:
340
+ - ~/mne_data/MNE-fsaverage-data # (762 M)
341
+ - save_cache:
342
+ key: data-cache-bst-raw
343
+ paths:
344
+ - ~/mne_data/MNE-brainstorm-data/bst_raw # (830 M)
345
+ - save_cache:
346
+ key: data-cache-bst-phantom-ctf
347
+ paths:
348
+ - ~/mne_data/MNE-brainstorm-data/bst_phantom_ctf # (177 M)
349
+ - save_cache:
350
+ key: data-cache-bst-phantom-elekta
351
+ paths:
352
+ - ~/mne_data/MNE-brainstorm-data/bst_phantom_elekta # (1.4 G)
353
+ - save_cache:
354
+ key: data-cache-bst-phantom-kernel
355
+ paths:
356
+ - ~/mne_data/MNE-phantom-kernel-data # (362 M)
357
+ - save_cache:
358
+ key: data-cache-bst-auditory
359
+ paths:
360
+ - ~/mne_data/MNE-brainstorm-data/bst_auditory # (2.9 G)
361
+ - save_cache:
362
+ key: data-cache-bst-resting
363
+ paths:
364
+ - ~/mne_data/MNE-brainstorm-data/bst_resting # (4.5 G)
365
+ - save_cache:
366
+ key: data-cache-fieldtrip
367
+ paths:
368
+ - ~/mne_data/MNE-fieldtrip_cmc-data # (699 M)
369
+ - save_cache:
370
+ key: data-cache-somato
371
+ paths:
372
+ - ~/mne_data/MNE-somato-data # (750 M)
373
+ - save_cache:
374
+ key: data-cache-hf-sef
375
+ paths:
376
+ - ~/mne_data/HF_SEF # (1.3 G)
377
+ - save_cache:
378
+ key: data-cache-opm
379
+ paths:
380
+ - ~/mne_data/MNE-OPM-data # (1.9 G)
381
+ - save_cache:
382
+ key: data-cache-sample
383
+ paths:
384
+ - ~/mne_data/MNE-sample-data # (3.2 G)
385
+ - save_cache:
386
+ key: data-cache-spm-face
387
+ paths:
388
+ - ~/mne_data/MNE-spm-face # (1.5 G)
389
+ - save_cache:
390
+ key: data-cache-testing
391
+ paths:
392
+ - ~/mne_data/MNE-testing-data # (2.5 G)
393
+ - save_cache:
394
+ key: data-cache-visual
395
+ paths:
396
+ - ~/mne_data/MNE-visual_92_categories-data # (6 G)
397
+ - save_cache:
398
+ key: data-cache-ucl-opm-auditory
399
+ paths:
400
+ - ~/mne_data/auditory_OPM_stationary # (4 G)
401
+ - save_cache:
402
+ key: data-cache-phantom-kit
403
+ paths:
404
+ - ~/mne_data/MNE-phantom-KIT-data # (1 G)
405
+ - save_cache:
406
+ key: data-cache-ds004388
407
+ paths:
408
+ - ~/mne_data/ds004388 # (1.8 G)
409
+
410
+
411
+ linkcheck:
412
+ # there are a few files excluded from this for expediency, see Makefile
413
+ parameters:
414
+ scheduled:
415
+ type: string
416
+ default: "false"
417
+ machine:
418
+ image: ubuntu-2404:current
419
+ resource_class: large
420
+ steps:
421
+ - restore_cache:
422
+ keys:
423
+ - source-cache
424
+ - checkout
425
+ - run:
426
+ name: Check-skip
427
+ command: |
428
+ export COMMIT_MESSAGE=$(git log --format=oneline -n 1);
429
+ if [[ "$COMMIT_MESSAGE" != *"[circle linkcheck]"* ]] && [ "<< parameters.scheduled >>" != "true" ]; then
430
+ echo "Skip detected, exiting job ${CIRCLE_JOB}."
431
+ circleci-agent step halt;
432
+ fi
433
+ - run:
434
+ name: Set BASH_ENV
435
+ command: ./tools/circleci_bash_env.sh
436
+ - restore_cache:
437
+ keys:
438
+ - pip-cache-0
439
+ - run:
440
+ name: Get Python running
441
+ command: |
442
+ ./tools/circleci_dependencies.sh
443
+ - run:
444
+ name: Check installation
445
+ command: |
446
+ mne sys_info -pd
447
+ - run:
448
+ name: make linkcheck
449
+ no_output_timeout: 40m
450
+ command: |
451
+ make -C doc linkcheck
452
+ - store_artifacts:
453
+ path: doc/_build/linkcheck
454
+ destination: linkcheck
455
+
456
+
457
+ deploy:
458
+ machine:
459
+ image: ubuntu-2404:current
460
+ steps:
461
+ - attach_workspace:
462
+ at: /tmp/build
463
+ - restore_cache:
464
+ keys:
465
+ - website-cache-1
466
+ - add_ssh_keys:
467
+ fingerprints:
468
+ # SHA256:N4qvp6MSbXcTz/27xz96VPsNuTDRT92zoRP8EW0I/8I
469
+ - "19:fe:1d:c3:c7:af:7e:16:94:4c:e1:e7:0a:56:13:bd"
470
+ - run:
471
+ name: Set BASH_ENV
472
+ command: |
473
+ set -e
474
+ echo "set -e" >> $BASH_ENV
475
+ # Don't try to deploy if nothing is there or not on the right branch
476
+ - run:
477
+ name: Check docs
478
+ command: |
479
+ if [ ! -f /tmp/build/html/index.html ] ; then
480
+ echo "No files found to upload (build: ${CIRCLE_BRANCH}).";
481
+ circleci-agent step halt;
482
+ fi;
483
+ - run:
484
+ name: Fetch docs
485
+ command: |
486
+ mkdir -p ~/.ssh
487
+ echo -e "Host *\nStrictHostKeyChecking no" > ~/.ssh/config
488
+ chmod og= ~/.ssh/config
489
+ if [ ! -d ~/mne-tools.github.io ]; then
490
+ git clone git@github.com:/mne-tools/mne-tools.github.io.git ~/mne-tools.github.io --depth=1
491
+ fi
492
+ - run:
493
+ name: Deploy docs
494
+ command: |
495
+ git config --global user.email "circle@mne.tools";
496
+ git config --global user.name "Circle CI";
497
+ ssh-add -D && ssh-add ~/.ssh/id_rsa_19fe1dc3c7af7e16944ce1e70a5613bd
498
+ cd ~/mne-tools.github.io;
499
+ git checkout main
500
+ git remote -v
501
+ git fetch origin
502
+ git reset --hard origin/main
503
+ git clean -xdf
504
+ if [ "${CIRCLE_BRANCH}" == "main" ]; then
505
+ echo "Deploying dev docs for ${CIRCLE_BRANCH}.";
506
+ rm -Rf dev;
507
+ cp -a /tmp/build/html dev;
508
+ git add -A;
509
+ git commit -m "CircleCI update of dev docs (${CIRCLE_BUILD_NUM}).";
510
+ else
511
+ echo "Deploying stable docs for ${CIRCLE_BRANCH}.";
512
+ rm -Rf stable;
513
+ cp -a /tmp/build/html stable;
514
+ git add -A;
515
+ git commit -m "CircleCI update of stable docs (${CIRCLE_BUILD_NUM}).";
516
+ fi;
517
+ git push origin main;
518
+ - save_cache:
519
+ key: website-cache-1
520
+ paths:
521
+ - ~/mne-tools.github.io
522
+
523
+ workflows:
524
+ default:
525
+ jobs:
526
+ - build_docs:
527
+ name: build_docs
528
+ - linkcheck:
529
+ name: linkcheck
530
+ - deploy:
531
+ name: deploy
532
+ requires:
533
+ - build_docs
534
+ filters:
535
+ branches:
536
+ only:
537
+ - main
538
+ - /maint\/.*/
539
+
540
+ main:
541
+ jobs:
542
+ - build_docs:
543
+ scheduled: "true"
544
+ name: build_docs_main
545
+ - deploy:
546
+ name: deploy_main
547
+ requires:
548
+ - build_docs_main
549
+ triggers:
550
+ - schedule:
551
+ # "At 6:00 AM GMT every day"
552
+ cron: "0 6 * * *"
553
+ filters:
554
+ branches:
555
+ only:
556
+ - main
557
+
558
+ monthly:
559
+ jobs:
560
+ - linkcheck:
561
+ name: linkcheck_monthly
562
+ scheduled: "true"
563
+ triggers:
564
+ - schedule:
565
+ # "At 6:00 AM GMT on the first day of each month"
566
+ cron: "0 6 1 * *"
567
+ filters:
568
+ branches:
569
+ only:
570
+ - main
mne-python/source/.coveragerc ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [run]
2
+ branch = True
3
+ source = mne
4
+ omit =
5
+ */bin/*
6
+ */setup.py
7
+ */mne/fixes*
8
+ */mne/utils/linalg.py
9
+ */mne/conftest.py
10
+
11
+ [report]
12
+ exclude_lines =
13
+ pragma: no cover
14
+ if __name__ == .__main__.:
15
+ @abstractmethod
16
+ @abstractclassmethod
mne-python/source/.mailmap ADDED
@@ -0,0 +1,379 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Adam Li <adam2392@gmail.com> Adam Li <adam2392@Adams-MBP-2.home>
2
+ Adam Li <adam2392@gmail.com> Adam Li <adam2392@new-host-2.home>
3
+ Alan Leggitt <leggitta3@gmail.com> leggitta <leggitta3@gmail.com>
4
+ Alessandro Tonin <alessandro.tonin@wysscenter.ch> Lychfindel <58313635+Lychfindel@users.noreply.github.com>
5
+ Alex Lepauvre <alex.lepauvre@ae.mpg.de> Alex lepauvre <alex.lepauvre@ae.mpg.de>
6
+ Alex Rockhill <aprockhill206@gmail.com> Alex <aprockhill206@gmail.com>
7
+ Alex Rockhill <aprockhill206@gmail.com> Alex <aprockhill@mailbox.org>
8
+ Alex Rockhill <aprockhill206@gmail.com> Alex Rockhill <aprock@uw.edu>
9
+ Alex Rockhill <aprockhill206@gmail.com> Alex Rockhill <aprockhill@mailbox.org>
10
+ Alexander Rudiuk <alxanderr@gmail.com> Alexander Rudiuk <al629748@dal.ca>
11
+ Alexandre Barachant <alexandre.barachant@gmail.com> alexandre barachant <alexandre.barachant@gmail.com>
12
+ Alexandre Gramfort <alexandre.gramfort@inria.fr> Alexandre Gramfort <alexandre.gramfort@gmail.com>
13
+ Alexandre Gramfort <alexandre.gramfort@inria.fr> Alexandre Gramfort <alexandre.gramfort@inria.fr>
14
+ Alexandre Gramfort <alexandre.gramfort@inria.fr> Alexandre Gramfort <alexandre.gramfort@m4x.org>
15
+ Alexandre Gramfort <alexandre.gramfort@inria.fr> Alexandre Gramfort <alexandre.gramfort@telecom-paristech.fr>
16
+ Alexandre Gramfort <alexandre.gramfort@inria.fr> Alexandre Gramfort <gramfort@localhost.(none)>
17
+ Ana Radanovic <anaradanovica@gmail.com> anaradanovic <79697247+anaradanovic@users.noreply.github.com>
18
+ Andres Rodriguez <rodriguezandr@gmail.com>
19
+ Andrew Dykstra <andrew.r.dykstra@gmail.com>
20
+ Andrew Quinn <AJQuinn@users.noreply.github.com> AJQuinn <AJQuinn@users.noreply.github.com>
21
+ Andy Gilbert <7andy121@gmail.com> Andrew Gilbert <adgilbert21@icloud.com>
22
+ Andy Gilbert <7andy121@gmail.com> Andrew Gilbert <andrew.gilbert@irhythmtech.com>
23
+ Aniket Singh Yadav <148300120+Aniketsy@users.noreply.github.com> Aniket <148300120+Aniketsy@users.noreply.github.com>
24
+ Anna Padee <anna.padee@gmail.com> apadee <44297909+apadee@users.noreply.github.com>
25
+ Anne-Sophie Dubarry <as_dub@hotmail.com> annesodub <as_dub@hotmail.com>
26
+ Archit Singhal <43236121+architsinghal-mriirs@users.noreply.github.com> archit singhal <zyphergiest@pop-os.localdomain>
27
+ Arne Pelzer <arne.pelzer@idmt.fraunhofer.de> aplzr <7202498+aplzr@users.noreply.github.com>
28
+ Arne Pelzer <arne.pelzer@idmt.fraunhofer.de> pzr <arne.pelzer@idmt.fraunhofer.de>
29
+ Ashley Drew <ashdrew@uw.edu> ashdrew <33734402+ashdrew@users.noreply.github.com>
30
+ Asish Panda <asishrocks95@gmail.com> kaichogami <asishrocks95@gmail.com>
31
+ Basile Pinsard <basile.pinsard@umontreal.ca>
32
+ Brad Buran <bburan@galenea.com> Brad Buran <bburan@alum.mit.edu>
33
+ Britta Westner <britta.wstnr@gmail.com> britta-wstnr <britta.wstnr@gmail.com>
34
+ Bruno Aristimunha <b.aristimunha@gmail.com>
35
+ btkcodedev <btk.codedev@gmail.com>
36
+ buildqa <s1152yb68@contbay.com>
37
+ Burkhard Maess <burkhard.maess@arcor.de> Burkhard Maess <bmaess@users.noreply.github.com>
38
+ Carina Forster <carinaforster0611@gmail.com> Carina <carinaforster0611@gmail.com>
39
+ Carlos de la Torre <ctorre@mailbox.org> carlos <ctorre@mailbox.org>
40
+ Catalina María Galván <79813952+catalinamagalvan@users.noreply.github.com> Catalina Magalvan <79813952+catalinamagalvan@users.noreply.github.com>
41
+ Catalina María Galván <79813952+catalinamagalvan@users.noreply.github.com> catalinamagalvan <79813952+catalinamagalvan@users.noreply.github.com>
42
+ Cathy Nangini <cnangini@gmail.com> CN <cnangini@gmail.com>
43
+ Chetan Gohil <53237863+cgohil8@users.noreply.github.com> cgohil8 <53237863+cgohil8@users.noreply.github.com>
44
+ Chris Holdgraf <choldgraf@gmail.com> Chris Holdgraf <choldgraf@berkeley.edu>
45
+ Chris Holdgraf <choldgraf@gmail.com> Christopher Holdgraf <choldgraf@gmail.com>
46
+ Christian Brodbeck <christianmbrodbeck@gmail.com> Christian Brodbeck <christianbrodbeck@nyu.edu>
47
+ Christian Brodbeck <christianmbrodbeck@gmail.com> christianmbrodbeck <christianmbrodbeck@gmail.com>
48
+ Christian Mista <cmista@ingenieria.uner.edu.ar> cmista <79416030+cmista@users.noreply.github.com>
49
+ Christina Zhao <zhaotc@uw.edu> ChristinaZhao <zhaotc@uw.edu>
50
+ Christoph Dinh <chdinh@nmr.mgh.harvard.edu> Christoph Dinh <christoph.dinh@tu-ilmenau.de>
51
+ Christopher J. Bailey <bailey.cj@gmail.com> Chris Bailey <bailey.cj@gmail.com>
52
+ Claire Braboszcz <claire@guakamole.org> claire-braboszcz <claire@guakamole.org>
53
+ Clemens Brunner <clemens.brunner@gmail.com>
54
+ Clément Moutard <clement.moutard@gmail.com>
55
+ Cora Kim <kimjico@gmail.com> kimcoco <41998428+kimcoco@users.noreply.github.com>
56
+ Cristóbal Moënne-Loccoz <cmmoenne@gmail.com> Cristóbal <cmmoenne@gmail.com>
57
+ Dan G. Wakeman <dgwakeman@gmail.com> Daniel G. Wakeman <dgwakeman@gmail.com>
58
+ Dan G. Wakeman <dgwakeman@gmail.com> Daniel Wakeman <dwakeman@marcie.nmr.mgh.harvard.edu>
59
+ Dan G. Wakeman <dgwakeman@gmail.com> dgwakeman <dgwakeman@gmail.com>
60
+ Dan G. Wakeman <dgwakeman@gmail.com> dgwakeman <dgwakeman@users.noreply.github.com>
61
+ Daniel C Schad <daniel.c.schad@protonmail.com> Daniel C Schad <daniel@schad.se>
62
+ Daniel C Schad <daniel.c.schad@protonmail.com> Daniel Carlström Schad <daniel.c.schad@protonmail.com>
63
+ Daniel McCloy <dan@mccloy.info> Daniel McCloy <dan.mccloy@gmail.com>
64
+ Daniel McCloy <dan@mccloy.info> Daniel McCloy <drammock@users.noreply.github.com>
65
+ Daniel McCloy <dan@mccloy.info> drammock <dan.mccloy@gmail.com>
66
+ Daniel Strohmeier <daniel.strohmeier@googlemail.com> Daniel Strohmeier <daniel.strohmeier@googlemail.com>
67
+ Daniel Strohmeier <daniel.strohmeier@googlemail.com> joewalter <daniel.strohmeier@googlemail.com>
68
+ David Julien <david.julien@ifsttar.fr> David JULIEN <david.julien@ifsttar.fr>
69
+ David Sabbagh <dav.sabbagh@gmail.com> DavidSabbagh <33925146+DavidSabbagh@users.noreply.github.com>
70
+ Demetres Kostas <40433000+kostasde@users.noreply.github.com> kostasde <40433000+kostasde@users.noreply.github.com>
71
+ Denis A. Engemann <denis.engemann@gmail.com> dengemann <d.engemann@fz-juelich.de>
72
+ Denis A. Engemann <denis.engemann@gmail.com> dengemann <denis.engemann@gmail.com>
73
+ Denis A. Engemann <denis.engemann@gmail.com> denis <denis.engemann@gmail.com>
74
+ Denis A. Engemann <denis.engemann@gmail.com> Denis A. Engemann <d.engemann@fz-juelich.de>
75
+ Denis A. Engemann <denis.engemann@gmail.com> Denis A. Engemann <denis-alexander.engemann@inria.fr>
76
+ Denis A. Engemann <denis.engemann@gmail.com> Denis A. Engemann <denisaengemann@Denis-A-Engemanns-MacBook-Air.local>
77
+ Denis A. Engemann <denis.engemann@gmail.com> Denis Engemann <dengemann@Deniss-MacBook-Pro.local>
78
+ Denis A. Engemann <denis.engemann@gmail.com> Denis Engemann <dengemann@pool-186-21-zam037.wlan.kfa-juelich.de>
79
+ Dmitrii Altukhov <dm.altukhov@ya.ru> dmalt <dm.altukhov@ya.ru>
80
+ Dominik Krzemiński <raymon92@gmail.com> dokato <raymon92@gmail.com>
81
+ Dominik Welke <dominik.welke@ae.mpg.de> dominikwelke <33089761+dominikwelke@users.noreply.github.com>
82
+ Dominik Welke <dominik.welke@ae.mpg.de> dominikwelke <dominik.welke@web.de>
83
+ Dominik Wetzel <dimonok@web.de> Dominik Wetzel <dominik.wetzel@fh-zwickau.de>
84
+ Eberhard Eich <e.eich@fz-juelich.de> ebeich <ebeich@users.noreply.github.com>
85
+ Eduard Ort <eduardxort@gmail.com> Eduard Ort <edaurdxort@gmail.com>
86
+ Eduard Ort <eduardxort@gmail.com> eort <eduardxort@gmail.com>
87
+ Eduard Ort <eduardxort@gmail.com> examplename <e.ort@vu.nl>
88
+ Ellen Lau <ellenlau@umd.edu> ellenlau <ellenlau@umd.edu>
89
+ Emily Stephen <emilyps14@gmail.com> Emily P. Stephen <emilyps14@gmail.com>
90
+ Emily Stephen <emilyps14@gmail.com> emilyps14 <emilyps14@gmail.com>
91
+ Emma Bailey <93327939+emma-bailey@users.noreply.github.com> emma-bailey <93327939+emma-bailey@users.noreply.github.com>
92
+ Emma Zhang <150376834+zhijingz@users.noreply.github.com> Emma <150376834+zhijingz@users.noreply.github.com>
93
+ Enrico Varano <enricovarano@gmail.com> enricovara <69973551+enricovara@users.noreply.github.com>
94
+ Enzo Altamiranda <enzo.alt@gmail.com> enzo <enzo.alt@gmail.com>
95
+ Eric Larson <larson.eric.d@gmail.com> Eric Larson <larson.eric.d@gmail.com>
96
+ Eric Larson <larson.eric.d@gmail.com> Eric Larson <larsoner@monolith.local>
97
+ Eric Larson <larson.eric.d@gmail.com> Eric Larson <larsoner@uw.edu>
98
+ Eric Larson <larson.eric.d@gmail.com> Eric89GXL <larson.eric.d@gmail.com>
99
+ Eric Larson <larson.eric.d@gmail.com> Eric89GXL <larsoner@uw.edu>
100
+ Erica Peterson <nordme@uw.edu> nordme <38704848+nordme@users.noreply.github.com>
101
+ Erica Peterson <nordme@uw.edu> nordme <nordme@uw.edu>
102
+ Erik Hornberger <erik.hornberger@shi-g.com> er06645810 <erik.hornberger@shi-g.com>
103
+ Erik Hornberger <erik.hornberger@shi-g.com> Erik Hornberger <hornbergererik@gmail.com>
104
+ Erkka Heinila <erkkahe@gmail.com> Teekuningas <erkka.heinila@jyu.fi>
105
+ Erkka Heinila <erkkahe@gmail.com> Teekuningas <erkkahe@gmail.com>
106
+ Etienne de Montalivet <etiennedemontalivet@users.noreply.github.com>
107
+ Evgenii Kalenkovich <e.kalenkovich@gmail.com> kalenkovich <e.kalenkovich@gmail.com>
108
+ Evgeny Goldstein <84768107+evgenygoldstein@users.noreply.github.com> evgenygoldstein <84768107+evgenygoldstein@users.noreply.github.com>
109
+ Ezequiel Mikulan <e.mikulan@gmail.com> ezemikulan <39155887+ezemikulan@users.noreply.github.com>
110
+ Fahimeh Mamashli <33672431+fmamashli@users.noreply.github.com> fmamashli <33672431+fmamashli@users.noreply.github.com>
111
+ Fede Raimondo <federaimondo@gmail.com> Fede <slashack@gmail.com>
112
+ Fede Raimondo <federaimondo@gmail.com> Fede Raimondo <federaimondo@gmail.com>
113
+ Fede Raimondo <federaimondo@gmail.com> Fede Raimondo <fraimondo@dc.uba.ar>
114
+ Fede Raimondo <federaimondo@gmail.com> Fede Raimondo <slashack@gmail.com>
115
+ Fede Raimondo <federaimondo@gmail.com> Federico Raimondo <fraimondo@dc.uba.ar>
116
+ Fede Raimondo <federaimondo@gmail.com> Federico Raimondo <slashack@gmail.com>
117
+ Federico Zamberlan <44038765+fzamberlan@users.noreply.github.com>
118
+ Felix Klotzsche <klotzsche@cbs.mpg.de> eioe <felix_klotzsche@web.de>
119
+ Felix Klotzsche <klotzsche@cbs.mpg.de> eioe <klotzsche@cbs.mpg.de>
120
+ Frederik D. Weber <Frederik-D-Weber@users.noreply.github.com> Frederik-D-Weber <Frederik-D-Weber@users.noreply.github.com>
121
+ Fu-Te Wong <zuxfoucault@gmail.com> foucault <zuxfoucault@gmail.com>
122
+ Fu-Te Wong <zuxfoucault@gmail.com> zuxfoucault <zuxfoucault@yahoo.com.tw>
123
+ Félix Raimundo <gamaz3ps@gmail.com> Felix Raimundo <gamaz3ps@gmail.com>
124
+ Gansheng Tan <49130176+GanshengT@users.noreply.github.com> Gansheng TAN <49130176+GanshengT@users.noreply.github.com>
125
+ Gennadiy Belonosov <7503709+Genuster@users.noreply.github.com> Gennadiy <7503709+Genuster@users.noreply.github.com>
126
+ Gennadiy Belonosov <7503709+Genuster@users.noreply.github.com> Genuster <7503709+Genuster@users.noreply.github.com>
127
+ Giorgio Marinato <giorgio.marinato@unitn.it> neurogima <76406896+neurogima@users.noreply.github.com>
128
+ Giulio Gabrieli <giulio.gabrieli@iit.it>
129
+ Guillaume Dumas <deep@introspection.eu> deep-introspection <deep@introspection.eu>
130
+ Guillaume Dumas <deep@introspection.eu> Guillaume Dumas <deep-introspection@users.noreply.github.com>
131
+ Hakimeh Aslsardroud <hakimeh.aslsardroud@localhost>
132
+ Hamid Maymandi <46011104+HamidMandi@users.noreply.github.com> Hamid <46011104+HamidMandi@users.noreply.github.com>
133
+ Hasrat Ali Arzoo <hasrat407@gmail.com> hasrat17 <56307533+hasrat17@users.noreply.github.com>
134
+ Hongjiang Ye <rubyyhj@gmail.com> YE Hongjiang <hongjiang.ye@outlook.com>
135
+ Hongjiang Ye <rubyyhj@gmail.com> YE Hongjiang <rubyyhj@gmail.com>
136
+ Hubert Banville <hubert.jbanville@gmail.com> hubertjb <hubert.jbanville@gmail.com>
137
+ Hyonyoung Shin <55095699+mcvain@users.noreply.github.com> mcvain <55095699+mcvain@users.noreply.github.com>
138
+ Hüseyin Orkun Elmas <huseyinorkunelmas@gmail.com> Hüseyin <huseyinorkunelmas@gmail.com>
139
+ Ingoo Lee <dlsrnsladlek@naver.com> dlsrnsi <dlsrnsladlek@naver.com>
140
+ Ivo de Jong <ivopascal@gmail.com> ivopascal <ivopascal@gmail.com>
141
+ Jaakko Leppakangas <jaeilepp@gmail.com> Jaakko Leppakangas <jaeilepp@student.jyu.fi>
142
+ Jaakko Leppakangas <jaeilepp@gmail.com> jaeilepp <jaeilepp@gmail.com>
143
+ Jaakko Leppakangas <jaeilepp@gmail.com> jaeilepp <jaeilepp@student.jyu.fi>
144
+ Jacob Phelan <jacob.phelan.jp@gmail.com>
145
+ Jair Montoya <montoya.jair.m@gmail.com> jmontoyam <montoya.jair.m@gmail.com>
146
+ Jan Ebert <janpublicebert@posteo.net> janEbert <janpublicebert@posteo.net>
147
+ Jan Sedivy <sedivy@rtsoft.cz>
148
+ Jan Sosulski <mail@jan-sosulski.de> jsosulski <mail@jan-sosulski.de>
149
+ Jean-Baptiste Schiratti <jean.baptiste.schiratti@gmail.com> Jean-Baptiste SCHIRATTI <jean.baptiste.schiratti@gmail.com>
150
+ Jean-Rémi King <jeanremi.king+github@gmail.com> Jean-Rémi KING <jeanremi.king@gmail.com>
151
+ Jean-Rémi King <jeanremi.king+github@gmail.com> kingjr <jeanremi.kibng+github@gmail.com>
152
+ Jean-Rémi King <jeanremi.king+github@gmail.com> kingjr <jeanremi.king+github@gmail.com>
153
+ Jean-Rémi King <jeanremi.king+github@gmail.com> kingjr <jeanremi.king@gmail.com>
154
+ Jean-Rémi King <jeanremi.king+github@gmail.com> UMR9752 <jeanremi.king+github@gmail.com>
155
+ Jean-Rémi King <jeanremi.king+github@gmail.com> UMR9752 <umr9752@umr9752-desktop.(none)>
156
+ Jeff Stout <stoutjd@nih.gov> jstout211 <jstout211@yahoo.com>
157
+ Jennifer Behnke <jennifer.behnke@localhost>
158
+ Jesper Duemose Nielsen <jdue@dtu.dk> jdue <jdue@dtu.dk>
159
+ Jevri Hanna <jevri.hanna@gmail.com> Jeff Hanna <jeff.hanna@gmail.com>
160
+ Jevri Hanna <jevri.hanna@gmail.com> Jevri Hanna <jeff.hanna@gmail.com>
161
+ Joan Massich <mailsik@gmail.com> Joan Massich <sik@visor.udg.edu>
162
+ Joan Massich <mailsik@gmail.com> massich <sik@visor.udg.edu>
163
+ Johannes Kasper <jeythekey@tutanota.com> jeythekey <44215387+jeythekey@users.noreply.github.com>
164
+ John Samuelsson <johnsam@mit.edu> johnsam7 <johnsam@mit.edu>
165
+ John Veillette <johnv@uchicago.edu>
166
+ Jon Houck <jon.houck@gmail.com> Jon Houck <jhouck@users.noreply.github.com>
167
+ Jona Sassenhagen <jona.sassenhagen@gmail.com> jona <jona.sassenhagen@gmail.com>
168
+ Jona Sassenhagen <jona.sassenhagen@gmail.com> Jona Sassenhagen <jona.sassenhagen@staff.uni-marburg.de>
169
+ Jona Sassenhagen <jona.sassenhagen@gmail.com> jona-sassenhagen <jona.sassenhagen@gmail.com>
170
+ Jona Sassenhagen <jona.sassenhagen@gmail.com> jona-sassenhagen <jona.sassenhagen@staff.uni-marburg.de>
171
+ Jona Sassenhagen <jona.sassenhagen@gmail.com> jona-sassenhagen@ <jona.sassenhagen@gmail.com>
172
+ Jona Sassenhagen <jona.sassenhagen@gmail.com> jona.sassenhagen@gmail.com <jona.sassenhagen@gmail.com>
173
+ Jona Sassenhagen <jona.sassenhagen@gmail.com> sassenha <sassenha@fiebach1.rz.uni-frankfurt.de>
174
+ Jonathan Kuziek <kuziek@ualberta.ca>
175
+ Jordan Drew <39603454+jadrew43@users.noreply.github.com> jadrew43 <39603454+jadrew43@users.noreply.github.com>
176
+ Joris Van den Bossche <jorisvandenbossche@gmail.com> Joris Van den Bossche <jorisvandenbossche@gmail.com>
177
+ Joshua Calder-Travis <38797399+jCalderTravis@users.noreply.github.com> jCalderTravis <38797399+jCalderTravis@users.noreply.github.com>
178
+ Joshua J Bear <joshbear@users.noreply.github.com>
179
+ Joshua Teves <jbtevespro@gmail.com> Joshua Teves <joshua.teves@nih.gov>
180
+ José C. García Alanis <joialanisson@gmail.com> Jose Alanis <joialanisson@gmail.com>
181
+ José C. García Alanis <joialanisson@gmail.com> Jose C. G. Alanis <12409129+JoseAlanis@users.noreply.github.com>
182
+ José C. García Alanis <joialanisson@gmail.com> José C. G. Alanis <12409129+JoseAlanis@users.noreply.github.com>
183
+ José C. García Alanis <joialanisson@gmail.com> José C. García Alanis <12409129+JoseAlanis@users.noreply.github.com>
184
+ Julius Welzel <52565341+JuliusWelzel@users.noreply.github.com> jwelzel <52565341+JuliusWelzel@users.noreply.github.com>
185
+ Justus Schwabedal <jschwabedal@gmail.com>
186
+ Kaisu Lankinen <41806798+klankinen@users.noreply.github.com> klankinen <41806798+klankinen@users.noreply.github.com>
187
+ Kambiz Tabavi <ktavabi@gmail.com> Kambiz Tavabi <ktavabi@uw.edu>
188
+ Kambiz Tabavi <ktavabi@gmail.com> kambysese <ktavabi@gmail.com>
189
+ Katarina Slama <slama@berkeley.edu> katarinaslama <slama@berkeley.edu>
190
+ Katia Al-Amir <129207373+katia-sentry@users.noreply.github.com> Katia <129207373+katia-sentry@users.noreply.github.com>
191
+ Kostiantyn Maksymenko <makkostya@ukr.net> kostiantyn maksymenko <kostiantyn.maksymenko@inria.fr>
192
+ Kostiantyn Maksymenko <makkostya@ukr.net> Maksymenko Kostiantyn <kostiantyn.maksymenko@inria.fr>
193
+ Kostiantyn Maksymenko <makkostya@ukr.net> Maksymenko Kostiantyn <makkostya@ukr.net>
194
+ Laetitia Grabot <laetitia.grabot@gmail.com> LaetitiaG <laetitia.grabot@gmail.com>
195
+ Larry Eisenman <leisenman@wustl.edu> lneisenman <lneisenman@hotmail.com>
196
+ Laurent Lementec <laurent.lementec@gmail.com>
197
+ Lenny Varghese <lennyvarghese@users.noreply.github.com> lennyvarghese <lennyvarghese@users.noreply.github.com>
198
+ Liberty Hamilton <libertyhamilton@gmail.com>
199
+ Lorenz Esch <Lorenz.Esch@tu-ilmenau.de> Lorenz Esch <lorenzesch@hotmail.com>
200
+ Lorenzo Alfine <lorenzo.alfine@gmail.com> lorrandal <lorenzo.alfine@gmail.com>
201
+ Louis Thibault <louist87@gmail.com> = <louist87@gmail.com>
202
+ Louis Thibault <louist87@gmail.com> Louis Thibault <louist@ltpc.(none)>
203
+ Lukas Gemein <lukas.gemein@gmx.de> gemeinl <gemeinl@users.noreply.github.com>
204
+ Lukáš Hejtmánek <hejtmy@gmail.com> hejtmy <hejtmy@gmail.com>
205
+ Mads Jensen <mje.mads@gmail.com> mads jensen <mje.mads@gmail.com>
206
+ Mainak Jas <mainakjas@gmail.com> Mainak <mainakjas@gmail.com>
207
+ Mainak Jas <mainakjas@gmail.com> Mainak Jas <jasmainak@users.noreply.github.com>
208
+ Mainak Jas <mainakjas@gmail.com> Mainak Jas <mainak.jas@telecom-paristech.fr>
209
+ Mainak Jas <mainakjas@gmail.com> Mainak Jas <mainak@neuro.hut.fi> <mainakjas@users.noreply.github.com>
210
+ Mainak Jas <mainakjas@gmail.com> mainakjas <mainakjas@users.noreply.github.com>
211
+ Manoj Kumar <manojkumarsivaraj334@gmail.com> MechCoder <manojkumarsivaraj334@gmail.com>
212
+ Manu Sutela <manu.sutela@gmail.com> MJAS1 <manu.sutela@gmail.com>
213
+ Marian Dovgialo <marian.dowgialo@gmail.com> Marian Dovgialo <mdovgialo@fabrizzio.zfb.fuw.edu.pl>
214
+ Marian Dovgialo <marian.dowgialo@gmail.com> Marian Dovgialo <mdovgialo@users.noreply.github.com>
215
+ Marian Dovgialo <marian.dowgialo@gmail.com> mdovgialo <mdovgialo@users.noreply.github.com>
216
+ Marijn van Vliet <w.m.vanvliet@gmail.com> Marijn van Vliet <w.m.vanvliet@student.utwente.nl>
217
+ Mark Henney <mah@optoceutics.com> Mark <mah@optoceutics.com>
218
+ Mark Henney <mah@optoceutics.com> Mark Alexander Henney <mah@optoceutics.com>
219
+ Mark Henney <mah@optoceutics.com> Mark Henney <120719655+henneysq@users.noreply.github.com>
220
+ Mark Wronkiewicz <wronk.mark@gmail.com> wronk <wronk.mark@gmail.com>
221
+ Marmaduke Woodman <mmwoodman@gmail.com> maedoc <maedoc@mm.st>
222
+ Martin BaBer <Martinb.nmb@gmail.com>
223
+ Martin Billinger <flKazemakase@gmail.com> kazemakase <kazemakase@users.noreply.github.com>
224
+ Martin Billinger <flKazemakase@gmail.com> kazemakase <kazemakase@users.noreply.github.com>
225
+ Martin Billinger <flKazemakase@gmail.com> Martin Billinger <martin.billinger@tugraz.at>
226
+ Martin Billinger <flKazemakase@gmail.com> mbillingr <mbillingr@users.noreply.github.com>
227
+ Martin Luessi <mluessi@nmr.mgh.harvard.edu> martin <martin@think.(none)>
228
+ Martin Luessi <mluessi@nmr.mgh.harvard.edu> martin <martin@think.hsd1.ma.comcast.net>
229
+ Martin Luessi <mluessi@nmr.mgh.harvard.edu> mluessi@nmr.mgh.harvard.edu <mluessi@nmr.mgh.harvard.edu>
230
+ Martin Perez-Guevara <mperezguevara@gmail.com>
231
+ Martin Schulz <dev@mgschulz.de> Martin Schulz <46245704+marsipu@users.noreply.github.com>
232
+ Martin Schulz <dev@mgschulz.de> Martin Schulz <dev@earthman-music.de>
233
+ Martin van Harmelen <1544429+MPvHarmelen@users.noreply.github.com> Martin <1544429+MPvHarmelen@users.noreply.github.com>
234
+ Mathieu Scheltienne <mathieu.scheltienne@gmail.com> Mathieu Scheltienne <73893616+mscheltienne@users.noreply.github.com>
235
+ Mathieu Scheltienne <mathieu.scheltienne@gmail.com> Mathieu Scheltienne <mathieu.scheltienne@fcbg.ch>
236
+ Mathurin Massias <mathurin.massias@gmail.com> mathurinm <mathurin.massias@gmail.com>
237
+ Mathurin Massias <mathurin.massias@gmail.com> mathurinm <mathurinm@users.noreply.github.com>
238
+ Mats van Es <mats.vanes@psych.ox.ac.uk> Mats <mats.vanes@psych.ox.ac.uk>
239
+ Matt Sanderson <monkey_man_192@yahoo.com.au> monkeyman192 <monkey_man_192@yahoo.com.au>
240
+ Matteo Anelli <matteo.anelli@aalto.fi> Matteo Anelli <matteanelli.96.11@gmail.com>
241
+ Matteo Visconti di Oleggio Castello <matteo.visconti.gr@dartmouth.edu> Matteo Visconti dOC <matteo.visconti.gr@dartmouth.edu>
242
+ Matthias Dold <matthias.dold@gmx.net> matthiasdold <62005770+matthiasdold@users.noreply.github.com>
243
+ Matthias Eberlein <41163089+MatthiasEb@users.noreply.github.com> MatthiasEb <41163089+MatthiasEb@users.noreply.github.com>
244
+ Matti Hämäläinen <msh@nmr.mgh.harvard.edu> Matti Hamalainen <msh@nmr.mgh.harvard.edu>
245
+ Matti Hämäläinen <msh@nmr.mgh.harvard.edu> Matti Hamalainen <msh@parsley.nmr.mgh.harvard.edu>
246
+ Matti Hämäl��inen <msh@nmr.mgh.harvard.edu> Matti Hämäläinen <msh@parsley.nmr.mgh.harvard.edu>
247
+ Matti Hämäläinen <msh@nmr.mgh.harvard.edu> mshamalainen <msh@nmr.mgh.harvard.edu>
248
+ Matti Toivonen <105695400+mattitoi@users.noreply.github.com> mattitoi <105695400+mattitoi@users.noreply.github.com>
249
+ Maureen Shader <55732126+mshader@users.noreply.github.com> mshader <55732126+mshader@users.noreply.github.com>
250
+ Melih Yayli <melihyayli@hotmail.com>
251
+ Michiru Kaneda <rcmdnk@gmail.com> rcmdnk <rcmdnk@gmail.com>
252
+ Mikołaj Magnuski <mmagnuski@swps.edu.pl> Mikolaj Magnuski <mmagnuski@swps.edu.pl>
253
+ Mikołaj Magnuski <mmagnuski@swps.edu.pl> mmagnuski <mmagnuski@swps.edu.pl>
254
+ Mohamed Sherif <molpsychistb@gmail.com> mohdsherif <molpsychistb@gmail.com>
255
+ Mohammad Daneshzand <55800429+mdaneshzand@users.noreply.github.com> mdaneshzand <55800429+mdaneshzand@users.noreply.github.com>
256
+ Mojackhak <23111220065@m.fudan.edu.cn> Ankang Hu <23111220065@m.fudan.edu.cn>
257
+ Motofumi Fushimi <30593537+motofumi-fushimi@users.noreply.github.com> motofumi-fushimi <30593537+motofumi-fushimi@users.noreply.github.com>
258
+ Natalie Klein <neklein@andrew.cmu.edu> natalieklein <neklein@andrew.cmu.edu>
259
+ Nathalie Gayraud <nathalie.gayraud@inria.fr> Nathalie <nat.gayraud@gmail.com>
260
+ Nathalie Gayraud <nathalie.gayraud@inria.fr> Nathalie <nathalie.gayraud@inria.fr>
261
+ Natneal B <nati.new77@gmail.com>
262
+ Naveen Srinivasan <172697+naveensrinivasan@users.noreply.github.com> Naveen <172697+naveensrinivasan@users.noreply.github.com>
263
+ Nicolas Barascud <nbara@users.noreply.github.com> nbara <nbara@users.noreply.github.com>
264
+ Nicolas Barascud <nbara@users.noreply.github.com> Nicolas Barascud <10333715+nbara@users.noreply.github.com>
265
+ Nicolas Fourcaud-Trocmé <celicolimmo@free.fr> Fourcaud-Trocmé <nicolas.fourcaud-trocme@cnrs.fr>
266
+ Nicolas Gensollen <nicolas.gensollen@gmail.com> Gensollen <nicolas.gensollen@gmail.com>
267
+ Nicolas Legrand <legrand@cyceron.fr> Legrand Nicolas <legrand@cyceron.fr>
268
+ Nicolas Legrand <legrand@cyceron.fr> LegrandNico <legrand@cyceron.fr>
269
+ Nicolas Legrand <legrand@cyceron.fr> Nicolas Legrand <nicolas.legrand@cfin.au.dk>
270
+ Niels Focke <nfocke@uni-goettingen.de> nmri-nfocke <114056301+nmri-nfocke@users.noreply.github.com>
271
+ Niklas Wilming <niklas.wilming@gmail.com> Niklas Wilming <niklaswilming@fastmail.fm>
272
+ Nikolai Chapochnikov <23103092+chapochn@users.noreply.github.com> chapochn <23103092+chapochn@users.noreply.github.com>
273
+ Nikolai Chapochnikov <23103092+chapochn@users.noreply.github.com> Nikolai M Chapochnikov <23103092+chapochn@users.noreply.github.com>
274
+ Nikolas Chalas <nikos.ch01@gmail.com> Nichalas <nikos.ch01@gmail.com>
275
+ Noah Markowitz <34498671+nmarkowitz@users.noreply.github.com> NoahMarkowitz <34498671+nmarkowitz@users.noreply.github.com>
276
+ Olaf Hauk <olaf.hauk@mrc-cbu.cam.ac.uk> Olaf Hauk <olaf@mac0086.local>
277
+ Olaf Hauk <olaf.hauk@mrc-cbu.cam.ac.uk> olafhauk <olaf.hauk@mrc-cbu.cam.ac.uk>
278
+ Omer Shubi <omer.shubi@gmail.com> Omer S <omer.shubi@gmail.com>
279
+ Pablo Arias <pablo12co@hotmail.com>
280
+ Paul Pasler <paul@ppasler.de> ppasler <paul@ppasler.de>
281
+ Paul Roujansky <paul@roujansky.eu> Paul ROUJANSKY <paul.roujansky@bioserenity.com>
282
+ Paul Roujansky <paul@roujansky.eu> paulroujansky <paul@roujansky.eu>
283
+ Pavel Navratil <pavel.navratil@localhost>
284
+ Pedro Silva <pedrobnsilva@gmail.com> pbnsilva <pedrobnsilva@gmail.com>
285
+ Phillip Alday <phillip.alday@mpi.nl> Phillip Alday <palday@users.noreply.github.com>
286
+ Phillip Alday <phillip.alday@mpi.nl> Phillip Alday <phillip.alday@unisa.edu.au>
287
+ Pierre Ablin <pierreablin@gmail.com> pierreablin <pierreablin@gmail.com>
288
+ Pierre-Antoine Bannier <pierreantoine.bannier@gmail.com> PAB <pierreantoine.bannier@gmail.com>
289
+ Pierre-Antoine Bannier <pierreantoine.bannier@gmail.com> Pierre-Antoine Bannier <pierre-antoine@222-194.wifi-inria-saclay.saclay.inria.fr>
290
+ Pierre-Antoine Bannier <pierreantoine.bannier@gmail.com> Pierre-Antoine Bannier <pierre-antoine@macbook-pro-de-pierre-antoine.home>
291
+ Pierre-Antoine Bannier <pierreantoine.bannier@gmail.com> Pierre-Antoine Bannier <pierre-antoine@MacBook-Pro-de-Pierre-Antoine.local>
292
+ Pierre-Antoine Bannier <pierreantoine.bannier@gmail.com> Pierre-Antoine Bannier <pierre-antoine@mbpdepieantoine.home>
293
+ Ping-Keng Jao <ping-keng.jao@alumni.epfl.ch> nafraw <ping-keng.jao@alumni.epfl.ch>
294
+ Pragnya Khandelwal <prag1704@gmail.com> Pragnya <prag1704@gmail.com>
295
+ Pragnya Khandelwal <prag1704@gmail.com> PragnyaKhandelwal <prag1704@gmail.com>
296
+ Praveen Sripad <pravsripad@gmail.com> prav <prav@prav-dell.(none)>
297
+ Praveen Sripad <pravsripad@gmail.com> prav <pravsripad@gmail.com>
298
+ Proloy Das <pdas6@mgh.harvard.edu> pdas6 <pdas6@mgh.harvard.edu>
299
+ Ram Pari <ramsbam@gmail.com> Ram <ramsbam@gmail.com>
300
+ Ramonapariciog Apariciogarcia <moncho_apa@hotmail.com> ramonapariciog <moncho_apa@hotmail.com>
301
+ Rasmus Aagaard <roraa@dtu.dk> roraa <roraa@dtu.dk>
302
+ Reza Nasri <reza@ddpo.ir> Reza <qablameh13@gmail.com>
303
+ Reza Nasri <reza@ddpo.ir> RezaNasri <rezanasri@outlook.com>
304
+ Riessarius Stargardsky <rie.acad@gmail.com>
305
+ Roan LaPlante <aestrivex@gmail.com> aestrivex <aestrivex@gmail.com>
306
+ Robert Luke <code@robertluke.net> Robert Luke <748691+rob-luke@users.noreply.github.com>
307
+ Robert Luke <code@robertluke.net> Robert Luke <mail@robertluke.net>
308
+ Robert Seymour <robbyseymour@gmail.com>
309
+ Robin Tibor Schirrmeister <robintibor@gmail.com> robintibor <robintibor@gmail.com>
310
+ Roeland Hancock <rhancock@gmail.com>
311
+ Romain Derollepot <romain.derollepot@univ-eiffel.fr>
312
+ Romain Trachel <romain.trachel@inria.fr> Romain Trachel <romain.trachel@ens.fr>
313
+ Romain Trachel <romain.trachel@inria.fr> Romain Trachel <trachelr@gmail.com>
314
+ Romain Trachel <romain.trachel@inria.fr> trachelr <romain.trachel@inria.fr>
315
+ Roman Goj <roman.goj@gmail.com>
316
+ Rongfei Jin <131315c@gmail.com> GreasyCat <131315c@gmail.com>
317
+ Ross Maddox <ross.maddox@rochester.edu> rkmaddox <ross.maddox@gmail.com>
318
+ Ross Maddox <ross.maddox@rochester.edu> Ross Maddox <rkmaddox@uw.edu>
319
+ Ross Maddox <ross.maddox@rochester.edu> unknown <rkmaddox@uw.edu>
320
+ Rotem Falach <falachrotem@gmail.com> Falach <rotemfa0@gmail.com>
321
+ Roy Eric Wieske <139973278+Randomidous@users.noreply.github.com> Roy Eric <139973278+Randomidous@users.noreply.github.com>
322
+ Ryan Law <ryan.law@mpi.nl> Ryan Law <ryalaw@dccn.nl>
323
+ Ryan Law <ryan.law@mpi.nl> Ryan M.C. Law <ryan.law@mrc-cbu.cam.ac.uk>
324
+ Sammi Chekroud <sammi.chekroud@psy.ox.ac.uk>
325
+ Samuel Deslauriers-Gauthier <sam.deslauriers@gmail.com> Samuel Deslauriers-Gauthier <sdeslauriers@users.noreply.github.com>
326
+ Santeri Ruuskanen <santeri.ruuskanen@aalto.fi> Santeri Ruuskanen <66060772+ruuskas@users.noreply.github.com>
327
+ Santi Martínez <santiaguzz@gmail.com> szz-dvl <santiaguzz@gmail.com>
328
+ Sara Sommariva <sommariva@dima.unige.it> sarasommariva <sommariva@dima.unige.it>
329
+ Sebastien Treguer <sfox@riseup.net> DataFox <sfox@riseup.net>
330
+ Sena Er <2799280+sena-neuro@users.noreply.github.com> Sena <2799280+sena-neuro@users.noreply.github.com>
331
+ Senwen Deng <36327760+snwnde@users.noreply.github.com> Senwen DENG <36327760+snwnde@users.noreply.github.com>
332
+ Shristi Baral <shristi.baral@aalto.fi> shristi <shristi.baral@aalto.fi>
333
+ Silvia Cotroneo <78911192+sfc-neuro@users.noreply.github.com> sfc-neuro <78911192+sfc-neuro@users.noreply.github.com>
334
+ Simon Kern <simon.kern@online.de> Simon Kern <14980558+skjerns@users.noreply.github.com>
335
+ Simon Kern <simon.kern@online.de> skjerns <14980558+skjerns@users.noreply.github.com>
336
+ Simon Kern <simon.kern@online.de> skjerns <simon.kern@online.de>
337
+ Sondre Foslien <sondre.foslien@gmail.com> sondrfos <sondre.foslien@gmail.com>
338
+ Sophie Herbst <ksherbst@gmail.com>
339
+ Steinn Hauser Magnússon <hausersteinn@gmail.com> Steinn Magnusson <s.magnusson@senec.com>
340
+ Steve Matindi <stevematindi@gmail.com> stevemats <stevematindi@gmail.com>
341
+ Steven Bierer <neurolaunch@gmail.copm> Steven Bierer <40672003+NeuroLaunch@users.noreply.github.com>
342
+ Steven M. Gutstein <s.m.gutstein@gmail.com> S. M. Gutstein <s.m.gutstein@gmail.com>
343
+ Steven M. Gutstein <s.m.gutstein@gmail.com> smgutstein <s.m.gutstein@gmail.com>
344
+ sviter <sviter33@gmail.com>
345
+ T. Wang <twang5@swarthmore.edu> twang5 <81429617+twang5@users.noreply.github.com>
346
+ Tanay Gahlot <tanaygahlot@gmail.com> Tanay <tanaygahlot@gmail.com>
347
+ Teon L Brooks <teon.brooks@gmail.com>
348
+ Teon L Brooks <teon.brooks@gmail.com> <teon@nyu.edu>
349
+ Teon L Brooks <teon.brooks@gmail.com> Teon <teon@nyu.edu>
350
+ Teon L Brooks <teon.brooks@gmail.com> Teon Brooks <teon@nyu.edu>
351
+ Thomas Donoghue <tdonoghue.research@gmail.com> Tom <tdonoghue.research@gmail.com>
352
+ Thomas Radman <radman.thomas@gmail.com>
353
+ Timon Merk <timon.merk@charite.de>
354
+ Timon Merk <timon.merk@charite.de> Timon Merk <38216460+timonmerk@users.noreply.github.com>
355
+ Timon Merk <timon.merk@charite.de> timonmerk <38216460+timonmerk@users.noreply.github.com>
356
+ Timothy Gates <tim.gates@iress.com> Tim Gates <tim.gates@iress.com>
357
+ Timur Sokhin <qwinpin@gmail.com>
358
+ Tod Flak <45362686+todflak@users.noreply.github.com> todflak <45362686+todflak@users.noreply.github.com>
359
+ Tom Ma <myd7349@gmail.com> myd7349 <myd7349@gmail.com>
360
+ Tom Stone <TASTONE@mgh.harvard.edu> Stone <TASTONE@mgh.harvard.edu>
361
+ Tom Stone <TASTONE@mgh.harvard.edu> tomdstone <77251489+tomdstone@users.noreply.github.com>
362
+ Tristan Stenner <ttstenner@gmail.com> Tristan Stenner <derstenner@gmail.com>
363
+ Tziona NessAiver <tzionan@mail.tau.ac.il> TzionaN <tzionan@mail.tau.ac.il>
364
+ user27182 <89109579+user27182@users.noreply.github.com>
365
+ Valerii Chirkov <vagechirkov@gmail.com> Valerii <42982039+vagechirkov@users.noreply.github.com>
366
+ Valerii Chirkov <vagechirkov@gmail.com> Valerii <vagechirkov@gmail.com>
367
+ varshaa-1616 <varshaa.1616@gmail.com>
368
+ Velu Prabhakar Kumaravel <veluprabhakarkumaravel@Velus-MBP.lan> Velu Prabhakar Kumaravel <veluprabhakarkumaravel@Velus-MBP.lan>
369
+ Victoria Peterson <victoriapeterson09@gmail.com> vpeterson <victoriapeterson09@gmail.com>
370
+ Wei Xu <weixu@mail.bnu.edu.cn> Wei <weixu@mail.bnu.edu.cn>
371
+ Will Turner <wturner@student.unimelb.edu.au> Will Turner <wturner@student.unimelb.edu.au>
372
+ Yiping Zuo <frostime@foxmail.com> Frostime <frostime@foxmail.com>
373
+ Yousra Bekhti <yousra.bekhti@gmail.com> Yoursa BEKHTI <ybekhti@is222485.intra.cea.fr>
374
+ Yousra Bekhti <yousra.bekhti@gmail.com> Yoursa BEKHTI <yousra.bekhti@gmail.com>
375
+ Yousra Bekhti <yousra.bekhti@gmail.com> Yousra BEKHTI <yousra.bekhti@gmail.com>
376
+ Yousra Bekhti <yousra.bekhti@gmail.com> yousrabk <yousra.bekhti@gmail.com>
377
+ Zhi Zhang <850734033@qq.com> ZHANG Zhi <850734033@qq.com>
378
+ Zhi Zhang <850734033@qq.com> ZHANG Zhi <zhi271.zhang@connect.polyu.hk>
379
+ Ziyi ZENG <ziyizeng@link.cuhk.edu.cn> ZIYI ZENG <CME1909120@XMU.EDU.MY>
mne-python/source/.pre-commit-config.yaml ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ repos:
2
+ # Ruff mne
3
+ - repo: https://github.com/astral-sh/ruff-pre-commit
4
+ rev: v0.15.5
5
+ hooks:
6
+ - id: ruff-check
7
+ name: ruff lint mne
8
+ args: ["--fix"]
9
+ files: ^mne/|^tools/
10
+ exclude: vulture_allowlist.py
11
+ - id: ruff-check
12
+ name: ruff lint mne preview
13
+ args: ["--fix", "--preview", "--select=NPY201"]
14
+ files: ^mne/|^tools/
15
+ - id: ruff-check
16
+ name: ruff lint doc, tutorials, and examples
17
+ # D103: missing docstring in public function
18
+ # D400: docstring first line must end with period
19
+ args: ["--ignore=D103,D400", "--fix"]
20
+ files: ^doc/|^tutorials/|^examples/
21
+ - id: ruff-format
22
+ files: ^mne/|^doc/|^tutorials/|^examples/|^tools/
23
+
24
+ # Codespell
25
+ - repo: https://github.com/codespell-project/codespell
26
+ rev: v2.4.2
27
+ hooks:
28
+ - id: codespell
29
+ additional_dependencies:
30
+ - tomli
31
+ files: ^mne/|^doc/|^examples/|^tutorials/|^tools/
32
+ types_or: [python, bib, rst, inc]
33
+
34
+ # yamllint
35
+ - repo: https://github.com/adrienverge/yamllint.git
36
+ rev: v1.38.0
37
+ hooks:
38
+ - id: yamllint
39
+ args: [--strict, -c, .yamllint.yml]
40
+
41
+ # rstcheck
42
+ - repo: https://github.com/rstcheck/rstcheck.git
43
+ rev: v6.2.5
44
+ hooks:
45
+ - id: rstcheck
46
+ additional_dependencies:
47
+ - tomli
48
+ files: ^doc/.*\.(rst|inc)$
49
+ # Credit is problematic because we generate an include on the fly
50
+ exclude: ^doc/credit.rst$
51
+
52
+ # sorting
53
+ - repo: https://github.com/pre-commit/pre-commit-hooks
54
+ rev: v6.0.0
55
+ hooks:
56
+ - id: file-contents-sorter
57
+ files: ^doc/changes/names.inc|^.mailmap|^doc/sphinxext/related_software.txt
58
+ args: ["--ignore-case"]
59
+
60
+ - repo: https://github.com/pappasam/toml-sort
61
+ rev: v0.24.3
62
+ hooks:
63
+ - id: toml-sort-fix
64
+ files: pyproject.toml
65
+
66
+ # dependencies
67
+ - repo: local
68
+ hooks:
69
+ - id: update-env-file
70
+ name: Copy dependency changes from pyproject.toml to environment.yml
71
+ language: python
72
+ entry: ./tools/hooks/update_environment_file.py
73
+ files: '^(pyproject.toml|tools/hooks/update_environment_file.py)$'
74
+ - repo: local
75
+ hooks:
76
+ - id: dependency-sync
77
+ name: Copy core dependencies from pyproject.toml to README.rst
78
+ language: python
79
+ entry: ./tools/hooks/sync_dependencies.py
80
+ files: '^(pyproject.toml|tools/hooks/sync_dependencies.py)$'
81
+ additional_dependencies: ["mne==1.11.0"]
82
+
83
+ # zizmor
84
+ - repo: https://github.com/woodruffw/zizmor-pre-commit
85
+ rev: v1.23.1
86
+ hooks:
87
+ - id: zizmor
88
+ args: [--fix]
89
+ # We correctly use pull_request_trigger, and need Zizmor 2.0+ to configure the ignore
90
+ exclude: ^.github/workflows/automerge.yml
91
+
92
+ # these should *not* be run on CIs:
93
+ ci:
94
+ skip: [dependency-sync] # needs MNE to work, which exceeds the free tier space alloc.
95
+
96
+ # The following are too slow to run on local commits, so let's only run on CIs:
97
+ #
98
+ # - repo: https://github.com/pre-commit/mirrors-mypy
99
+ # rev: v1.9.0
100
+ # hooks:
101
+ # - id: mypy
102
+ #
103
+ # - repo: https://github.com/jendrikseipp/vulture
104
+ # rev: 'v2.11' # or any later Vulture version
105
+ # hooks:
106
+ # - id: vulture
mne-python/source/.yamllint.yml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ extends: default
2
+
3
+ ignore: |
4
+ .github/workflows/codeql-analysis.yml
5
+
6
+ rules:
7
+ line-length: disable
8
+ document-start: disable
9
+ new-lines:
10
+ type: platform
mne-python/source/CITATION.cff ADDED
@@ -0,0 +1,877 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ cff-version: 1.2.0
2
+ title: "MNE-Python"
3
+ message: "If you use this software, please cite both the software itself, and the paper listed in the preferred-citation field."
4
+ version: 1.11.0
5
+ date-released: "2025-11-21"
6
+ commit: 07328a6a7fa974b24455e1ac333d7607b154f87c
7
+ doi: 10.5281/zenodo.592483
8
+ keywords:
9
+ - MEG
10
+ - magnetoencephalography
11
+ - EEG
12
+ - electroencephalography
13
+ - fNIRS
14
+ - "functional near-infrared spectroscopy"
15
+ - iEEG
16
+ - "intracranial EEG"
17
+ - eCoG
18
+ - electrocorticography
19
+ - DBS
20
+ - "deep brain stimulation"
21
+ authors:
22
+ - family-names: Larson
23
+ given-names: Eric
24
+ - family-names: Gramfort
25
+ given-names: Alexandre
26
+ - family-names: Engemann
27
+ given-names: Denis A
28
+ - family-names: Leppakangas
29
+ given-names: Jaakko
30
+ - family-names: Brodbeck
31
+ given-names: Christian
32
+ - family-names: Jas
33
+ given-names: Mainak
34
+ - family-names: Brooks
35
+ given-names: Teon L
36
+ - family-names: Sassenhagen
37
+ given-names: Jona
38
+ - family-names: McCloy
39
+ given-names: Daniel
40
+ - family-names: Luessi
41
+ given-names: Martin
42
+ - family-names: King
43
+ given-names: Jean-Rémi
44
+ - family-names: Höchenberger
45
+ given-names: Richard
46
+ - family-names: Brunner
47
+ given-names: Clemens
48
+ - family-names: Goj
49
+ given-names: Roman
50
+ - family-names: Favelier
51
+ given-names: Guillaume
52
+ - family-names: van Vliet
53
+ given-names: Marijn
54
+ - family-names: Wronkiewicz
55
+ given-names: Mark
56
+ - family-names: Appelhoff
57
+ given-names: Stefan
58
+ - family-names: Rockhill
59
+ given-names: Alex
60
+ - family-names: Holdgraf
61
+ given-names: Chris
62
+ - family-names: Scheltienne
63
+ given-names: Mathieu
64
+ - family-names: Massich
65
+ given-names: Joan
66
+ - family-names: Bekhti
67
+ given-names: Yousra
68
+ - family-names: Leggitt
69
+ given-names: Alan
70
+ - family-names: Dykstra
71
+ given-names: Andrew
72
+ - family-names: Trachel
73
+ given-names: Romain
74
+ - family-names: Luke
75
+ given-names: Robert
76
+ - family-names: De Santis
77
+ given-names: Lorenzo
78
+ - family-names: Panda
79
+ given-names: Asish
80
+ - family-names: Magnuski
81
+ given-names: Mikołaj
82
+ - family-names: Westner
83
+ given-names: Britta
84
+ - family-names: Wakeman
85
+ given-names: Dan G
86
+ - family-names: Strohmeier
87
+ given-names: Daniel
88
+ - family-names: Bharadwaj
89
+ given-names: Hari
90
+ - family-names: Linzen
91
+ given-names: Tal
92
+ - family-names: Barachant
93
+ given-names: Alexandre
94
+ - family-names: Ruzich
95
+ given-names: Emily
96
+ - family-names: Huberty
97
+ given-names: Scott
98
+ - family-names: Bailey
99
+ given-names: Christopher J
100
+ - family-names: Li
101
+ given-names: Adam
102
+ - family-names: Moutard
103
+ given-names: Clément
104
+ - family-names: Bloy
105
+ given-names: Luke
106
+ - family-names: Raimondo
107
+ given-names: Fede
108
+ - family-names: Nurminen
109
+ given-names: Jussi
110
+ - family-names: Billinger
111
+ given-names: Martin
112
+ - family-names: Montoya
113
+ given-names: Jair
114
+ - family-names: Woodman
115
+ given-names: Marmaduke
116
+ - family-names: Lee
117
+ given-names: Ingoo
118
+ - family-names: Schulz
119
+ given-names: Martin
120
+ - family-names: Foti
121
+ given-names: Nick
122
+ - family-names: Nangini
123
+ given-names: Cathy
124
+ - family-names: García Alanis
125
+ given-names: José C
126
+ - family-names: Binns
127
+ given-names: Thomas S
128
+ - family-names: Orfanos
129
+ given-names: Dimitri Papadopoulos
130
+ - family-names: Hauk
131
+ given-names: Olaf
132
+ - family-names: Maddox
133
+ given-names: Ross
134
+ - family-names: LaPlante
135
+ given-names: Roan
136
+ - family-names: Drew
137
+ given-names: Ashley
138
+ - family-names: Dinh
139
+ given-names: Christoph
140
+ - family-names: Dumas
141
+ given-names: Guillaume
142
+ - name: Martin
143
+ - family-names: Benerradi
144
+ given-names: Johann
145
+ - family-names: Hartmann
146
+ given-names: Thomas
147
+ - family-names: Ort
148
+ given-names: Eduard
149
+ - family-names: Billinger
150
+ given-names: Martin
151
+ - family-names: Pasler
152
+ given-names: Paul
153
+ - family-names: Repplinger
154
+ given-names: Stefan
155
+ - family-names: Rudiuk
156
+ given-names: Alexander
157
+ - family-names: Radanovic
158
+ given-names: Ana
159
+ - family-names: Buran
160
+ given-names: Brad
161
+ - family-names: Woessner
162
+ given-names: Jacob
163
+ - family-names: Massias
164
+ given-names: Mathurin
165
+ - family-names: Hämäläinen
166
+ given-names: Matti
167
+ - family-names: Sripad
168
+ given-names: Praveen
169
+ - family-names: Chirkov
170
+ given-names: Valerii
171
+ - family-names: Mullins
172
+ given-names: Christopher
173
+ - family-names: Raimundo
174
+ given-names: Félix
175
+ - family-names: Belonosov
176
+ given-names: Gennadiy
177
+ - family-names: Kaneda
178
+ given-names: Michiru
179
+ - family-names: Alday
180
+ given-names: Phillip
181
+ - family-names: Pari
182
+ given-names: Ram
183
+ - family-names: Kornblith
184
+ given-names: Simon
185
+ - family-names: Halchenko
186
+ given-names: Yaroslav
187
+ - family-names: Luo
188
+ given-names: Yu-Han
189
+ - family-names: Gramfort
190
+ given-names: Alexandre
191
+ - family-names: Kasper
192
+ given-names: Johannes
193
+ - family-names: Doelling
194
+ given-names: Keith
195
+ - family-names: Jensen
196
+ given-names: Mads
197
+ - family-names: Ruuskanen
198
+ given-names: Santeri
199
+ - family-names: Kern
200
+ given-names: Simon
201
+ - family-names: Gahlot
202
+ given-names: Tanay
203
+ - family-names: Nunes
204
+ given-names: Adonay
205
+ - family-names: Gütlin
206
+ given-names: Dirk
207
+ - family-names: Heinila
208
+ given-names: Erkka
209
+ - family-names: Armeni
210
+ given-names: Kristijan
211
+ - name: kjs
212
+ - family-names: Weinstein
213
+ given-names: Alejandro
214
+ - family-names: Lamus
215
+ given-names: Camilo
216
+ - family-names: Galván
217
+ given-names: Catalina María
218
+ - family-names: Moënne-Loccoz
219
+ given-names: Cristóbal
220
+ - family-names: Altukhov
221
+ given-names: Dmitrii
222
+ - family-names: Peterson
223
+ given-names: Erica
224
+ - family-names: Hanna
225
+ given-names: Jevri
226
+ - family-names: Houck
227
+ given-names: Jon
228
+ - family-names: Klein
229
+ given-names: Natalie
230
+ - family-names: Roujansky
231
+ given-names: Paul
232
+ - family-names: Luke
233
+ given-names: Rob
234
+ - family-names: Rantala
235
+ given-names: Antti
236
+ - family-names: Maess
237
+ given-names: Burkhard
238
+ - family-names: Forster
239
+ given-names: Carina
240
+ - family-names: O'Reilly
241
+ given-names: Christian
242
+ - family-names: Welke
243
+ given-names: Dominik
244
+ - family-names: Welke
245
+ given-names: Dominik
246
+ - family-names: Kolkhorst
247
+ given-names: Henrich
248
+ - family-names: Banville
249
+ given-names: Hubert
250
+ - family-names: Zhang
251
+ given-names: Jack
252
+ - family-names: Maksymenko
253
+ given-names: Kostiantyn
254
+ - family-names: Clarke
255
+ given-names: Maggie
256
+ - family-names: Anelli
257
+ given-names: Matteo
258
+ - family-names: Straube
259
+ given-names: Michael
260
+ - family-names: Chapochnikov
261
+ given-names: Nikolai
262
+ - family-names: Bannier
263
+ given-names: Pierre-Antoine
264
+ - family-names: Choudhary
265
+ given-names: Saket
266
+ - family-names: Férat
267
+ given-names: Victor
268
+ - family-names: Kim
269
+ given-names: Cora
270
+ - family-names: Klotzsche
271
+ given-names: Felix
272
+ - family-names: Wong
273
+ given-names: Fu-Te
274
+ - family-names: Kojcic
275
+ given-names: Ivana
276
+ - family-names: Nielsen
277
+ given-names: Jesper Duemose
278
+ - family-names: Lankinen
279
+ given-names: Kaisu
280
+ - family-names: Tabavi
281
+ given-names: Kambiz
282
+ - family-names: Thibault
283
+ given-names: Louis
284
+ - family-names: Gerster
285
+ given-names: Moritz
286
+ - family-names: Alibou
287
+ given-names: Nabil
288
+ - family-names: Gayraud
289
+ given-names: Nathalie
290
+ - family-names: Ward
291
+ given-names: Nick
292
+ - family-names: Chu
293
+ given-names: Qian
294
+ - family-names: Herbst
295
+ given-names: Sophie
296
+ - family-names: Ma
297
+ given-names: Tom
298
+ - family-names: Radanovic
299
+ given-names: Ana
300
+ - family-names: Quinn
301
+ given-names: Andrew
302
+ - family-names: Gauthier
303
+ given-names: Antoine
304
+ - family-names: Pinsard
305
+ given-names: Basile
306
+ - family-names: Stephen
307
+ given-names: Emily
308
+ - family-names: Hornberger
309
+ given-names: Erik
310
+ - family-names: Hathaway
311
+ given-names: Evan
312
+ - family-names: Kalenkovich
313
+ given-names: Evgenii
314
+ - family-names: Mamashli
315
+ given-names: Fahimeh
316
+ - family-names: O'Neill
317
+ given-names: George
318
+ - family-names: Marinato
319
+ given-names: Giorgio
320
+ - family-names: Anevar
321
+ given-names: Hafeza
322
+ - family-names: Abdelhedi
323
+ given-names: Hamza
324
+ - family-names: Sosulski
325
+ given-names: Jan
326
+ - family-names: Stout
327
+ given-names: Jeff
328
+ - family-names: Calder-Travis
329
+ given-names: Joshua
330
+ - family-names: Zhu
331
+ given-names: Judy D
332
+ - family-names: Eisenman
333
+ given-names: Larry
334
+ - family-names: Esch
335
+ given-names: Lorenz
336
+ - family-names: Dovgialo
337
+ given-names: Marian
338
+ - family-names: Barascud
339
+ given-names: Nicolas
340
+ - family-names: Legrand
341
+ given-names: Nicolas
342
+ - family-names: Kapralov
343
+ given-names: Nikolai
344
+ - family-names: Molfese
345
+ given-names: Peter J
346
+ - family-names: Falach
347
+ given-names: Rotem
348
+ - family-names: Deslauriers-Gauthier
349
+ given-names: Samuel
350
+ - family-names: Cotroneo
351
+ given-names: Silvia
352
+ - family-names: Matindi
353
+ given-names: Steve
354
+ - family-names: Bierer
355
+ given-names: Steven
356
+ - family-names: Papadopoulo
357
+ given-names: Theodore
358
+ - family-names: Binns
359
+ given-names: Thomas Samuel
360
+ - family-names: Stenner
361
+ given-names: Tristan
362
+ - family-names: Peterson
363
+ given-names: Victoria
364
+ - family-names: Baratz
365
+ given-names: Zvi
366
+ - family-names: Tonin
367
+ given-names: Alessandro
368
+ - family-names: Kovrig
369
+ given-names: Alexander
370
+ - family-names: Pascarella
371
+ given-names: Annalisa
372
+ - family-names: Karekal
373
+ given-names: Apoorva
374
+ - family-names: Aristimunha
375
+ given-names: Bruno
376
+ - family-names: de la Torre
377
+ given-names: Carlos
378
+ - family-names: Gohil
379
+ given-names: Chetan
380
+ - family-names: Zhao
381
+ given-names: Christina
382
+ - family-names: Krzemiński
383
+ given-names: Dominik
384
+ - family-names: Makowski
385
+ given-names: Dominique
386
+ - family-names: Mikulan
387
+ given-names: Ezequiel
388
+ - family-names: Hofer
389
+ given-names: Florian
390
+ - family-names: Ritz
391
+ given-names: Harrison
392
+ - family-names: Schiratti
393
+ given-names: Jean-Baptiste
394
+ - family-names: Evans
395
+ given-names: Jen
396
+ - family-names: Herforth
397
+ given-names: Johannes
398
+ - family-names: Veillette
399
+ given-names: John
400
+ - family-names: Drew
401
+ given-names: Jordan
402
+ - family-names: Teves
403
+ given-names: Joshua
404
+ - family-names: Mathewson
405
+ given-names: Kyle
406
+ - family-names: Gwilliams
407
+ given-names: Laura
408
+ - family-names: Lementec
409
+ given-names: Laurent
410
+ - family-names: Varghese
411
+ given-names: Lenny
412
+ - family-names: Hamilton
413
+ given-names: Liberty
414
+ - family-names: Gemein
415
+ given-names: Lukas
416
+ - family-names: Hecker
417
+ given-names: Lukas
418
+ - name: Lx37
419
+ - family-names: van Es
420
+ given-names: Mats
421
+ - family-names: Boggess
422
+ given-names: Matt
423
+ - family-names: Eberlein
424
+ given-names: Matthias
425
+ - family-names: Žák
426
+ given-names: Michal
427
+ - family-names: Sherif
428
+ given-names: Mohamed
429
+ - family-names: Kozhemiako
430
+ given-names: Nataliia
431
+ - family-names: Srinivasan
432
+ given-names: Naveen
433
+ - family-names: Wilming
434
+ given-names: Niklas
435
+ - family-names: Kozynets
436
+ given-names: Oleh
437
+ - family-names: Ablin
438
+ given-names: Pierre
439
+ - family-names: Das
440
+ given-names: Proloy
441
+ - family-names: Bertrand
442
+ given-names: Quentin
443
+ - family-names: Shoorangiz
444
+ given-names: Reza
445
+ - family-names: Scholz
446
+ given-names: Richard
447
+ - family-names: Hübner
448
+ given-names: Rodrigo
449
+ - family-names: Sommariva
450
+ given-names: Sara
451
+ - family-names: Er
452
+ given-names: Sena
453
+ - family-names: Khan
454
+ given-names: Sheraz
455
+ - family-names: Datta
456
+ given-names: Sumalyo
457
+ - family-names: Donoghue
458
+ given-names: Thomas
459
+ - family-names: Jochmann
460
+ given-names: Thomas
461
+ - family-names: Merk
462
+ given-names: Timon
463
+ - family-names: Flak
464
+ given-names: Tod
465
+ - family-names: Dupré la Tour
466
+ given-names: Tom
467
+ - family-names: NessAiver
468
+ given-names: Tziona
469
+ - name: akshay0724
470
+ - name: sviter
471
+ - family-names: Earle-Richardson
472
+ given-names: Aaron
473
+ - family-names: Hindle
474
+ given-names: Abram
475
+ - family-names: Koutsou
476
+ given-names: Achilleas
477
+ - family-names: Fecker
478
+ given-names: Adeline
479
+ - family-names: Wagner
480
+ given-names: Adina
481
+ - family-names: Ciok
482
+ given-names: Alex
483
+ - family-names: Lepauvre
484
+ given-names: Alex
485
+ - family-names: Kiefer
486
+ given-names: Alexander
487
+ - family-names: Gilbert
488
+ given-names: Andy
489
+ - family-names: Pradhan
490
+ given-names: Aniket
491
+ - family-names: Padee
492
+ given-names: Anna
493
+ - family-names: Dubarry
494
+ given-names: Anne-Sophie
495
+ - family-names: Collas
496
+ given-names: Antoine
497
+ - family-names: Waniek
498
+ given-names: Anton Nikolas
499
+ - family-names: Singhal
500
+ given-names: Archit
501
+ - family-names: Rokem
502
+ given-names: Ariel
503
+ - family-names: Pelzer
504
+ given-names: Arne
505
+ - family-names: Hurst
506
+ given-names: Austin
507
+ - family-names: Jin
508
+ given-names: Beige Jerry
509
+ - family-names: Beasley
510
+ given-names: Ben
511
+ - family-names: Nicenboim
512
+ given-names: Bruno
513
+ - family-names: de la Torre
514
+ given-names: Carlos
515
+ - family-names: Clauss
516
+ given-names: Christian
517
+ - family-names: Mista
518
+ given-names: Christian
519
+ - family-names: Kechris
520
+ given-names: Christodoulos
521
+ - family-names: Li
522
+ given-names: Chun-Hui
523
+ - family-names: Braboszcz
524
+ given-names: Claire
525
+ - family-names: Schad
526
+ given-names: Daniel C
527
+ - family-names: Hasegan
528
+ given-names: Daniel
529
+ - family-names: Tse
530
+ given-names: Daniel
531
+ - family-names: Sleiter
532
+ given-names: Darin Erat
533
+ - family-names: Haslacher
534
+ given-names: David
535
+ - family-names: Sabbagh
536
+ given-names: David
537
+ - family-names: Kostas
538
+ given-names: Demetres
539
+ - family-names: Petkova
540
+ given-names: Desislava
541
+ - family-names: Issagaliyeva
542
+ given-names: Dinara
543
+ - family-names: Das
544
+ given-names: Diptyajit
545
+ - family-names: Wetzel
546
+ given-names: Dominik
547
+ - family-names: Eich
548
+ given-names: Eberhard
549
+ - family-names: DuPre
550
+ given-names: Elizabeth
551
+ - family-names: Lau
552
+ given-names: Ellen
553
+ - family-names: Olivetti
554
+ given-names: Emanuele
555
+ - family-names: Zhang
556
+ given-names: Emma
557
+ - family-names: Ferdman
558
+ given-names: Emmanuel
559
+ - family-names: Çelik
560
+ given-names: Emrecan
561
+ - family-names: Varano
562
+ given-names: Enrico
563
+ - family-names: Altamiranda
564
+ given-names: Enzo
565
+ - family-names: Brayet
566
+ given-names: Eric
567
+ - family-names: de Montalivet
568
+ given-names: Etienne
569
+ - family-names: Goldstein
570
+ given-names: Evgeny
571
+ - family-names: Mamashli
572
+ given-names: Fahimeh
573
+ - family-names: Negahbani
574
+ given-names: Farzin
575
+ - family-names: Zamberlan
576
+ given-names: Federico
577
+ - family-names: Pop
578
+ given-names: Florin
579
+ - family-names: Weber
580
+ given-names: Frederik D
581
+ - family-names: Tan
582
+ given-names: Gansheng
583
+ - family-names: Brookshire
584
+ given-names: Geoff
585
+ - family-names: O'Neill
586
+ given-names: George
587
+ - name: Giulio
588
+ - family-names: Reina
589
+ given-names: Gonzalo
590
+ - family-names: Maymandi
591
+ given-names: Hamid
592
+ - family-names: Arzoo
593
+ given-names: Hasrat Ali
594
+ - family-names: Sonntag
595
+ given-names: Hermann
596
+ - family-names: Ye
597
+ given-names: Hongjiang
598
+ - family-names: Shin
599
+ given-names: Hyonyoung
600
+ - family-names: Elmas
601
+ given-names: Hüseyin Orkun
602
+ - family-names: AZZ
603
+ given-names: Ilian
604
+ - family-names: Machairas
605
+ given-names: Ilias
606
+ - family-names: Zubarev
607
+ given-names: Ivan
608
+ - family-names: de Jong
609
+ given-names: Ivo
610
+ - family-names: Phelan
611
+ given-names: Jacob
612
+ - family-names: Kaczmarzyk
613
+ given-names: Jakub
614
+ - family-names: Zerfowski
615
+ given-names: Jan
616
+ - family-names: van den Bosch
617
+ given-names: Jasper J F
618
+ - family-names: Van Der Donckt
619
+ given-names: Jeroen
620
+ - family-names: van der Meer
621
+ given-names: Johan
622
+ - family-names: Niediek
623
+ given-names: Johannes
624
+ - family-names: Koen
625
+ given-names: Josh
626
+ - family-names: Bear
627
+ given-names: Joshua J
628
+ - family-names: Dammers
629
+ given-names: Juergen
630
+ - family-names: Galán
631
+ given-names: Julia Guiomar Niso
632
+ - family-names: Welzel
633
+ given-names: Julius
634
+ - family-names: Slama
635
+ given-names: Katarina
636
+ - family-names: Al-Amir
637
+ given-names: Katia
638
+ - family-names: Leinweber
639
+ given-names: Katrin
640
+ - family-names: Grabot
641
+ given-names: Laetitia
642
+ - family-names: Andersen
643
+ given-names: Lau Møller
644
+ - family-names: Almeida
645
+ given-names: Leonardo Rochael
646
+ - family-names: Barbosa
647
+ given-names: Leonardo S
648
+ - family-names: Alfine
649
+ given-names: Lorenzo
650
+ - family-names: Hejtmánek
651
+ given-names: Lukáš
652
+ - family-names: Balatsko
653
+ given-names: Maksym
654
+ - family-names: Kitzbichler
655
+ given-names: Manfred
656
+ - family-names: Kumar
657
+ given-names: Manoj
658
+ - family-names: Kadwani
659
+ given-names: Manorama
660
+ - family-names: Sutela
661
+ given-names: Manu
662
+ - family-names: Koculak
663
+ given-names: Marcin
664
+ - family-names: Henney
665
+ given-names: Mark
666
+ - family-names: BaBer
667
+ given-names: Martin
668
+ - family-names: Oberg
669
+ given-names: Martin
670
+ - family-names: van Harmelen
671
+ given-names: Martin
672
+ - family-names: Scheltienne
673
+ given-names: Mathieu
674
+ - family-names: Courtemanche
675
+ given-names: Matt
676
+ - family-names: Tucker
677
+ given-names: Matt
678
+ - family-names: Visconti di Oleggio Castello
679
+ given-names: Matteo
680
+ - family-names: Dold
681
+ given-names: Matthias
682
+ - family-names: Toivonen
683
+ given-names: Matti
684
+ - family-names: Shader
685
+ given-names: Maureen
686
+ - family-names: Cespedes
687
+ given-names: Mauricio
688
+ - family-names: Krause
689
+ given-names: Michael
690
+ - family-names: Rybář
691
+ given-names: Milan
692
+ - family-names: He
693
+ given-names: Mingjian
694
+ - family-names: Daneshzand
695
+ given-names: Mohammad
696
+ - name: Mojackhak
697
+ - family-names: Fourcaud-Trocmé
698
+ given-names: Nicolas
699
+ - family-names: Gensollen
700
+ given-names: Nicolas
701
+ - family-names: Proulx
702
+ given-names: Nicole
703
+ - family-names: Focke
704
+ given-names: Niels
705
+ - family-names: Chalas
706
+ given-names: Nikolas
707
+ - family-names: Markowitz
708
+ given-names: Noah
709
+ - family-names: Shubi
710
+ given-names: Omer
711
+ - family-names: Mainar
712
+ given-names: Pablo
713
+ - family-names: Sundaram
714
+ given-names: Padma
715
+ - family-names: Anders
716
+ given-names: Paul
717
+ - family-names: Silva
718
+ given-names: Pedro
719
+ - family-names: Guetschel
720
+ given-names: Pierre
721
+ - family-names: Li
722
+ given-names: Quanliang
723
+ - family-names: Barthélemy
724
+ given-names: Quentin
725
+ - family-names: Nadkarni
726
+ given-names: Rahul
727
+ - family-names: Gatti
728
+ given-names: Ramiro
729
+ - family-names: Apariciogarcia
730
+ given-names: Ramonapariciog
731
+ - family-names: Aagaard
732
+ given-names: Rasmus
733
+ - family-names: Nasri
734
+ given-names: Reza
735
+ - family-names: Koehler
736
+ given-names: Richard
737
+ - family-names: Stargardsky
738
+ given-names: Riessarius
739
+ - family-names: Oostenveld
740
+ given-names: Robert
741
+ - family-names: Seymour
742
+ given-names: Robert
743
+ - family-names: Schirrmeister
744
+ given-names: Robin Tibor
745
+ - family-names: Jin
746
+ given-names: Rongfei
747
+ - family-names: Wieske
748
+ given-names: Roy Eric
749
+ - family-names: Law
750
+ given-names: Ryan
751
+ - family-names: Pai
752
+ given-names: Sagun
753
+ - family-names: Perry
754
+ given-names: Sam
755
+ - family-names: Louviot
756
+ given-names: Samuel
757
+ - family-names: Martínez
758
+ given-names: Santi
759
+ - family-names: Saha
760
+ given-names: Sawradip
761
+ - family-names: Mathot
762
+ given-names: Sebastiaan
763
+ - family-names: Jentschke
764
+ given-names: Sebastian
765
+ - family-names: Major
766
+ given-names: Sebastian
767
+ - family-names: Treguer
768
+ given-names: Sebastien
769
+ - family-names: Castaño
770
+ given-names: Sebastián
771
+ - family-names: Deng
772
+ given-names: Senwen
773
+ - family-names: Antopolskiy
774
+ given-names: Sergey
775
+ - family-names: Shirazi
776
+ given-names: Seyed (Yahya)
777
+ - family-names: Keshari
778
+ given-names: Shresth
779
+ - family-names: Baral
780
+ given-names: Shristi
781
+ - family-names: Baral
782
+ given-names: Shristi
783
+ - family-names: Wong
784
+ given-names: Simeon
785
+ - family-names: Wong
786
+ given-names: Simeon
787
+ - family-names: Hofmann
788
+ given-names: Simon M
789
+ - family-names: Poil
790
+ given-names: Simon-Shlomo
791
+ - family-names: Foslien
792
+ given-names: Sondre
793
+ - family-names: Singh
794
+ given-names: Sourav
795
+ - family-names: Chambon
796
+ given-names: Stanislas
797
+ - family-names: Magnússon
798
+ given-names: Steinn Hauser
799
+ - family-names: Bethard
800
+ given-names: Steven
801
+ - family-names: Gutstein
802
+ given-names: Steven M
803
+ - family-names: Meyer
804
+ given-names: Svea Marie
805
+ - family-names: Wang
806
+ given-names: T
807
+ - family-names: Jayawardana
808
+ given-names: Tharupahan
809
+ - family-names: Moreau
810
+ given-names: Thomas
811
+ - family-names: Radman
812
+ given-names: Thomas
813
+ - family-names: Gates
814
+ given-names: Timothy
815
+ - family-names: Stone
816
+ given-names: Tom
817
+ - family-names: Clausner
818
+ given-names: Tommy
819
+ - family-names: Anijärv
820
+ given-names: Toomas Erik
821
+ - family-names: Kumaravel
822
+ given-names: Velu Prabhakar
823
+ - family-names: Xu
824
+ given-names: Wei
825
+ - family-names: Turner
826
+ given-names: Will
827
+ - family-names: Zuazo
828
+ given-names: Xabier de
829
+ - family-names: Xia
830
+ given-names: Xiaokai
831
+ - family-names: Zuo
832
+ given-names: Yiping
833
+ - family-names: Shen
834
+ given-names: Yixiao
835
+ - family-names: Truong
836
+ given-names: Young
837
+ - family-names: Zhang
838
+ given-names: Zhi
839
+ - family-names: ZENG
840
+ given-names: Ziyi
841
+ - name: btkcodedev
842
+ - name: buildqa
843
+ - name: luzpaz
844
+ - name: user27182
845
+ preferred-citation:
846
+ title: "MEG and EEG Data Analysis with MNE-Python"
847
+ journal: "Frontiers in Neuroscience"
848
+ type: article
849
+ year: 2013
850
+ volume: 7
851
+ issue: 267
852
+ start: 1
853
+ end: 13
854
+ doi: 10.3389/fnins.2013.00267
855
+ authors:
856
+ - family-names: Gramfort
857
+ given-names: Alexandre
858
+ - family-names: Luessi
859
+ given-names: Martin
860
+ - family-names: Larson
861
+ given-names: Eric
862
+ - family-names: Engemann
863
+ given-names: Denis A.
864
+ - family-names: Strohmeier
865
+ given-names: Daniel
866
+ - family-names: Brodbeck
867
+ given-names: Christian
868
+ - family-names: Goj
869
+ given-names: Roman
870
+ - family-names: Jas
871
+ given-names: Mainak
872
+ - family-names: Brooks
873
+ given-names: Teon
874
+ - family-names: Parkkonen
875
+ given-names: Lauri
876
+ - family-names: Hämäläinen
877
+ given-names: Matti S.
mne-python/source/CONTRIBUTING.md ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ Contributing to MNE-Python
2
+ ==========================
3
+
4
+ MNE-Python is maintained by a community of scientists and research labs. The project accepts contributions in the form of bug reports, fixes, feature additions, and documentation improvements (including typo corrections). The best way to start contributing is by [opening an issue](https://github.com/mne-tools/mne-python/issues/new/choose) on our GitHub page to discuss ideas for changes or enhancements, or to tell us about behavior that you think might be a bug. For *general troubleshooting* or *usage questions*, please consider posting your questions on our [MNE Forum](https://mne.discourse.group).
5
+
6
+ Users and contributors to MNE-Python are expected to follow our [code of conduct](https://github.com/mne-tools/.github/blob/main/CODE_OF_CONDUCT.md).
7
+
8
+ The [contributing guide](https://mne.tools/dev/development/contributing.html) has details on the preferred contribution workflow
9
+ and the recommended system configuration for a smooth contribution/development experience.
mne-python/source/LICENSE.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright 2011-2025 MNE-Python authors
2
+
3
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4
+
5
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6
+
7
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8
+
9
+ 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10
+
11
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
mne-python/source/Makefile ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # simple makefile to simplify repetitive build env management tasks under posix
2
+
3
+ PYTHON ?= python
4
+ PYTESTS ?= py.test
5
+ CODESPELL_SKIPS ?= "doc/_build,doc/auto_*,*.fif,*.eve,*.gz,*.tgz,*.zip,*.mat,*.stc,*.label,*.w,*.bz2,*.annot,*.sulc,*.log,*.local-copy,*.orig_avg,*.inflated_avg,*.gii,*.pyc,*.doctree,*.pickle,*.inv,*.png,*.edf,*.touch,*.thickness,*.nofix,*.volume,*.defect_borders,*.mgh,lh.*,rh.*,COR-*,FreeSurferColorLUT.txt,*.examples,.xdebug_mris_calc,bad.segments,BadChannels,*.hist,empty_file,*.orig,*.js,*.map,*.ipynb,searchindex.dat,install_mne_c.rst,plot_*.rst,*.rst.txt,c_EULA.rst*,*.html,gdf_encodes.txt,*.svg,references.bib,*.css,*.edf,*.bdf,*.vhdr"
6
+ CODESPELL_DIRS ?= mne/ doc/ tutorials/ examples/
7
+ all: clean test-doc
8
+
9
+ clean-pyc:
10
+ find . -name "*.pyc" | xargs rm -f
11
+
12
+ clean-so:
13
+ find . -name "*.so" | xargs rm -f
14
+ find . -name "*.pyd" | xargs rm -f
15
+
16
+ clean-build:
17
+ rm -rf build dist
18
+
19
+ clean-ctags:
20
+ rm -f tags
21
+
22
+ clean-cache:
23
+ find . -name "__pycache__" | xargs rm -rf
24
+
25
+ clean: clean-build clean-pyc clean-so clean-ctags clean-cache
26
+
27
+ wheel:
28
+ $(PYTHON) -m build -w
29
+
30
+ sample_data:
31
+ @python -c "import mne; mne.datasets.sample.data_path(verbose=True);"
32
+
33
+ testing_data:
34
+ @python -c "import mne; mne.datasets.testing.data_path(verbose=True);"
35
+
36
+ test-no-network: in
37
+ sudo unshare -n -- sh -c 'MNE_SKIP_NETWORK_TESTS=1 py.test mne'
38
+
39
+ test-no-testing-data: in
40
+ @MNE_SKIP_TESTING_DATASET_TESTS=true \
41
+ $(PYTESTS) mne
42
+
43
+ test-doc: sample_data testing_data
44
+ $(PYTESTS) --tb=short --cov=mne --cov-report=xml --cov-branch --doctest-modules --doctest-ignore-import-errors --doctest-glob='*.rst' ./doc/ --ignore=./doc/auto_examples --ignore=./doc/auto_tutorials --ignore=./doc/_build --ignore=./doc/conf.py --ignore=doc/sphinxext --fulltrace
45
+
46
+ pre-commit:
47
+ @pre-commit run -a --show-diff-on-failure
48
+
49
+ # Aliases for stuff we used to support or users might think of
50
+ ruff: pre-commit
51
+ flake: pre-commit
52
+ pep: pre-commit
53
+
54
+ codespell: # running manually
55
+ @codespell --builtin clear,rare,informal,names,usage -w -i 3 -q 3 -S $(CODESPELL_SKIPS) --ignore-words=ignore_words.txt --uri-ignore-words-list=bu $(CODESPELL_DIRS)
56
+
57
+ check-readme: clean wheel
58
+ twine check dist/*
59
+
60
+ nesting:
61
+ @echo "Running import nesting tests"
62
+ @$(PYTESTS) mne/tests/test_import_nesting.py
mne-python/source/README.rst ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .. -*- mode: rst -*-
2
+
3
+ |MNE|
4
+
5
+ MNE-Python
6
+ ==========
7
+
8
+ MNE-Python is an open-source Python package for exploring,
9
+ visualizing, and analyzing human neurophysiological data such as MEG, EEG, sEEG,
10
+ ECoG, and more. It includes modules for data input/output, preprocessing,
11
+ visualization, source estimation, time-frequency analysis, connectivity analysis,
12
+ machine learning, statistics, and more.
13
+
14
+
15
+ Documentation
16
+ ^^^^^^^^^^^^^
17
+
18
+ `Documentation`_ for MNE-Python encompasses installation instructions, tutorials,
19
+ and examples for a wide variety of topics, contributing guidelines, and an API
20
+ reference.
21
+
22
+
23
+ Forum
24
+ ^^^^^^
25
+
26
+ The `user forum`_ is the best place to ask questions about MNE-Python usage or
27
+ the contribution process. The forum also features job opportunities and other
28
+ announcements.
29
+
30
+ If you find a bug or have an idea for a new feature that should be added to
31
+ MNE-Python, please use the
32
+ `issue tracker <https://github.com/mne-tools/mne-python/issues/new/choose>`__ of
33
+ our GitHub repository.
34
+
35
+
36
+ Installation
37
+ ^^^^^^^^^^^^
38
+
39
+ To install the latest stable version of MNE-Python with minimal dependencies
40
+ only, use pip_ in a terminal:
41
+
42
+ .. code-block:: console
43
+
44
+ $ pip install --upgrade mne
45
+
46
+ For more complete instructions, including our standalone installers and more
47
+ advanced installation methods, please refer to the `installation guide`_.
48
+
49
+
50
+ Get the development version
51
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
52
+
53
+ To install the latest development version of MNE-Python using pip_, open a
54
+ terminal and type:
55
+
56
+ .. code-block:: console
57
+
58
+ $ pip install --upgrade https://github.com/mne-tools/mne-python/archive/refs/heads/main.zip
59
+
60
+ To clone the repository with `git <https://git-scm.com/>`__, open a terminal
61
+ and type:
62
+
63
+ .. code-block:: console
64
+
65
+ $ git clone https://github.com/mne-tools/mne-python.git
66
+
67
+
68
+ Dependencies
69
+ ^^^^^^^^^^^^
70
+
71
+ The minimum required dependencies to run MNE-Python are:
72
+
73
+ .. ↓↓↓ BEGIN CORE DEPS LIST. DO NOT EDIT! HANDLED BY PRE-COMMIT HOOK ↓↓↓
74
+
75
+ - `Python <https://www.python.org>`__ ≥ 3.10
76
+ - `NumPy <https://numpy.org>`__ ≥ 1.26
77
+ - `SciPy <https://scipy.org>`__ ≥ 1.11
78
+ - `Matplotlib <https://matplotlib.org>`__ ≥ 3.8
79
+ - `Pooch <https://www.fatiando.org/pooch/latest/>`__ ≥ 1.5
80
+ - `tqdm <https://tqdm.github.io>`__
81
+ - `Jinja2 <https://palletsprojects.com/p/jinja/>`__
82
+ - `decorator <https://github.com/micheles/decorator>`__
83
+ - `lazy-loader <https://pypi.org/project/lazy_loader>`__ ≥ 0.3
84
+ - `packaging <https://packaging.pypa.io/en/stable/>`__
85
+
86
+ .. ↑↑↑ END CORE DEPS LIST. DO NOT EDIT! HANDLED BY PRE-COMMIT HOOK ↑↑↑
87
+
88
+ Contributing
89
+ ^^^^^^^^^^^^
90
+
91
+ Please see the `contributing guidelines <https://mne.tools/dev/development/contributing.html>`__ on our documentation website.
92
+
93
+
94
+ About
95
+ ^^^^^
96
+
97
+ +---------+------------+----------------+
98
+ | CI | |Codecov| | |Bandit| |
99
+ +---------+------------+----------------+
100
+ | Package | |PyPI| | |conda-forge| |
101
+ +---------+------------+----------------+
102
+ | Docs | |Docs| | |Discourse| |
103
+ +---------+------------+----------------+
104
+ | Meta | |Zenodo| | |OpenSSF| |
105
+ +---------+------------+----------------+
106
+
107
+
108
+ License
109
+ ^^^^^^^
110
+
111
+ MNE-Python is licensed under the BSD-3-Clause license.
112
+
113
+
114
+ .. _Documentation: https://mne.tools/dev/
115
+ .. _user forum: https://mne.discourse.group
116
+ .. _installation guide: https://mne.tools/dev/install/index.html
117
+ .. _pip: https://pip.pypa.io/en/stable/
118
+
119
+ .. |PyPI| image:: https://img.shields.io/pypi/dm/mne.svg?label=PyPI
120
+ :target: https://pypi.org/project/mne/
121
+
122
+ .. |conda-forge| image:: https://img.shields.io/conda/dn/conda-forge/mne.svg?label=Conda
123
+ :target: https://anaconda.org/conda-forge/mne
124
+
125
+ .. |Docs| image:: https://img.shields.io/badge/Docs-online-green?label=Documentation
126
+ :target: https://mne.tools/dev/
127
+
128
+ .. |Zenodo| image:: https://zenodo.org/badge/DOI/10.5281/zenodo.592483.svg
129
+ :target: https://doi.org/10.5281/zenodo.592483
130
+
131
+ .. |Discourse| image:: https://img.shields.io/discourse/status?label=Forum&server=https%3A%2F%2Fmne.discourse.group%2F
132
+ :target: https://mne.discourse.group/
133
+
134
+ .. |Codecov| image:: https://img.shields.io/codecov/c/github/mne-tools/mne-python?label=Coverage
135
+ :target: https://codecov.io/gh/mne-tools/mne-python
136
+
137
+ .. |Bandit| image:: https://img.shields.io/badge/Security-Bandit-yellow.svg
138
+ :target: https://github.com/PyCQA/bandit
139
+
140
+ .. |OpenSSF| image:: https://www.bestpractices.dev/projects/7783/badge
141
+ :target: https://www.bestpractices.dev/projects/7783
142
+
143
+ .. |MNE| image:: https://mne.tools/dev/_static/mne_logo_gray.svg
144
+ :target: https://mne.tools/dev/
mne-python/source/SECURITY.md ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ New minor versions of MNE-Python are typically released twice per year.
6
+ Only the most current stable release is officially supported.
7
+ The unreleased, unstable "dev version" is also supported, though users
8
+ should beware that the API of the dev version is subject to change
9
+ without a proper 6-month deprecation cycle.
10
+
11
+ | Version | Supported |
12
+ | ------- | ------------------------ |
13
+ | 1.12.x | :heavy_check_mark: (dev) |
14
+ | 1.11.x | :heavy_check_mark: |
15
+ | < 1.11 | :x: |
16
+
17
+ ## Reporting a Vulnerability
18
+
19
+ MNE-Python is software for analysis and visualization of brain activity
20
+ recorded with a variety of devices/modalities (EEG, MEG, ECoG, fNIRS, etc).
21
+ It is not expected that using MNE-Python will lead to security
22
+ vulnerabilities under normal use cases (i.e., running without administrator
23
+ privileges). However, if you think you have found a security vulnerability
24
+ in MNE-Python, **please do not report it as a GitHub issue**, in order to
25
+ keep the vulnerability confidential. Instead, please report it to
26
+ mne-core-dev-team@groups.io and include a description and proof-of-concept
27
+ that is [short and self-contained](http://www.sscce.org/).
28
+
29
+ Generally you will receive a response within one week. MNE-Python does not
30
+ award bounties for security vulnerabilities.
mne-python/source/__init__.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ mne-python Project Package Initialization File
4
+ """
mne-python/source/azure-pipelines.yml ADDED
@@ -0,0 +1,303 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ trigger:
2
+ # start a new build for every push
3
+ batch: false
4
+ branches:
5
+ include:
6
+ - 'main'
7
+ - 'maint/*'
8
+ pr:
9
+ branches:
10
+ include:
11
+ - '*' # must quote since "*" is a YAML reserved character; we want a string
12
+
13
+
14
+ stages:
15
+
16
+ - stage: Check
17
+ jobs:
18
+ - job: Skip
19
+ pool:
20
+ vmImage: 'ubuntu-latest'
21
+ variables:
22
+ DECODE_PERCENTS: 'false'
23
+ RET: 'true'
24
+ BUILD_REASON: $(Build.Reason)
25
+ steps:
26
+ - bash: |
27
+ git_log=`git log --format=oneline -n 1 --skip=1`
28
+ echo "##vso[task.setvariable variable=log]$git_log"
29
+ - bash: echo "##vso[task.setvariable variable=RET]false"
30
+ condition: and(eq(variables.BUILD_REASON, 'PullRequest'), or(contains(variables.log, '[skip azp]'), contains(variables.log, '[azp skip]'), contains(variables.log, '[skip ci]'), contains(variables.log, '[ci skip]')))
31
+ - bash: echo "##vso[task.setvariable variable=start_main;isOutput=true]$RET"
32
+ name: result
33
+
34
+ - stage: Style
35
+ variables:
36
+ AZURE_CI: 'true'
37
+ jobs:
38
+ - job: All
39
+ pool:
40
+ vmImage: 'ubuntu-latest'
41
+ variables:
42
+ PYTHON_VERSION: '3.11'
43
+ PYTHON_ARCH: 'x64'
44
+ steps:
45
+ - bash: echo $(COMMIT_MSG)
46
+ - task: UsePythonVersion@0
47
+ inputs:
48
+ versionSpec: $(PYTHON_VERSION)
49
+ architecture: $(PYTHON_ARCH)
50
+ addToPath: true
51
+ displayName: 'Get Python'
52
+ - bash: |
53
+ set -eo pipefail
54
+ python -m pip install --progress-bar off --upgrade pip build
55
+ python -m pip install --progress-bar off -ve .[hdf5] --group=test
56
+ python -m pip uninstall -yq pytest-qt # don't want to set up display, etc. for this
57
+ pre-commit install --install-hooks
58
+ displayName: Install dependencies
59
+ - bash: |
60
+ make pre-commit
61
+ displayName: make pre-commit
62
+ condition: always()
63
+ - bash: |
64
+ make nesting
65
+ displayName: make nesting
66
+ condition: always()
67
+ - bash: |
68
+ make check-readme
69
+ displayName: make check-readme
70
+ condition: always()
71
+ - bash: mypy
72
+ displayName: mypy
73
+ condition: always()
74
+ - bash: vulture
75
+ displayName: vulture
76
+ condition: always()
77
+
78
+
79
+ - stage: Test
80
+ condition: and(succeeded(), eq(dependencies.Check.outputs['Skip.result.start_main'], 'true'))
81
+ dependsOn: ['Style', 'Check']
82
+ variables:
83
+ AZURE_CI: 'true'
84
+ jobs:
85
+ - job: Ultraslow_PG
86
+ pool:
87
+ vmImage: 'ubuntu-22.04'
88
+ variables:
89
+ DISPLAY: ':99'
90
+ OPENBLAS_NUM_THREADS: '1'
91
+ OMP_NUM_THREADS: '1'
92
+ MNE_TEST_ALLOW_SKIP: '^.*(PySide6 causes segfaults).*$'
93
+ MNE_BROWSER_PRECOMPUTE: 'false'
94
+ steps:
95
+ - bash: |
96
+ set -e
97
+ ./tools/setup_xvfb.sh
98
+ sudo apt install -yq tcsh
99
+ displayName: 'Install Ubuntu dependencies'
100
+ - bash: |
101
+ source tools/get_minimal_commands.sh
102
+ displayName: 'Install minimal commands'
103
+ - bash: |
104
+ echo $PATH
105
+ mne_surf2bem --version
106
+ fsl_rigid_register --version
107
+ displayName: 'Test minimal commands'
108
+ - task: UsePythonVersion@0
109
+ inputs:
110
+ versionSpec: '3.12'
111
+ architecture: 'x64'
112
+ addToPath: true
113
+ displayName: 'Get Python'
114
+ - bash: |
115
+ set -e
116
+ python -m pip install --progress-bar off --upgrade pip
117
+ python -m pip install --progress-bar off "mne-qt-browser[opengl] @ git+https://github.com/mne-tools/mne-qt-browser.git" pyvista scikit-learn python-picard qtpy nibabel sphinx-gallery "PySide6!=6.8.0,!=6.8.0.1,!=6.8.1.1,!=6.9.1" pandas neo pymatreader antio defusedxml curryreader pymef
118
+ python -m pip uninstall -yq mne
119
+ python -m pip install --progress-bar off --upgrade -e . --group=test
120
+ displayName: 'Install dependencies with pip'
121
+ - bash: |
122
+ set -e
123
+ mne sys_info -pd
124
+ mne sys_info -pd | grep "qtpy .*(PySide6=.*)$"
125
+ displayName: Print config
126
+ - bash: |
127
+ set -e
128
+ LD_DEBUG=libs python -c "from PySide6.QtWidgets import QApplication, QWidget; app = QApplication([]); import matplotlib; matplotlib.use('QtAgg'); import matplotlib.pyplot as plt; plt.figure()"
129
+ - bash: source tools/get_testing_version.sh
130
+ displayName: 'Get testing version'
131
+ - task: Cache@2
132
+ inputs:
133
+ key: $(testing_version)
134
+ path: /home/vsts/mne_data
135
+ displayName: 'Cache testing data'
136
+ - script: python -c "import mne; mne.datasets.testing.data_path(verbose=True)"
137
+ displayName: 'Get test data'
138
+ - script: pytest -m "ultraslowtest or pgtest" --tb=short --cov=mne --cov-report=xml -vv mne
139
+ displayName: 'slow and mne-qt-browser tests'
140
+ # Coverage
141
+ - bash: bash <(curl -s https://codecov.io/bash)
142
+ displayName: 'Codecov'
143
+ condition: succeededOrFailed()
144
+ - task: PublishTestResults@2
145
+ inputs:
146
+ testResultsFiles: '**/junit-*.xml'
147
+ testRunTitle: 'Publish test results for $(Agent.JobName)'
148
+ failTaskOnFailedTests: true
149
+ condition: succeededOrFailed()
150
+ - task: PublishCodeCoverageResults@2
151
+ inputs:
152
+ summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml'
153
+
154
+ - job: Qt
155
+ pool:
156
+ vmImage: 'ubuntu-22.04'
157
+ variables:
158
+ DISPLAY: ':99'
159
+ OPENBLAS_NUM_THREADS: '1'
160
+ TEST_OPTIONS: "--tb=short --cov=mne --cov-report=xml --cov-append -vv mne/viz/_brain mne/viz/backends mne/viz/tests/test_evoked.py mne/gui mne/report"
161
+ MNE_TEST_ALLOW_SKIP: '^.*(PySide6 causes segfaults).*$'
162
+ steps:
163
+ - bash: ./tools/setup_xvfb.sh
164
+ displayName: 'Install Ubuntu dependencies'
165
+ - task: UsePythonVersion@0
166
+ inputs:
167
+ versionSpec: '3.10'
168
+ architecture: 'x64'
169
+ addToPath: true
170
+ displayName: 'Get Python'
171
+ - bash: |
172
+ set -e
173
+ python -m pip install --progress-bar off --upgrade pip
174
+ python -m pip install --progress-bar off --upgrade --pre --only-binary=\"numpy,scipy,matplotlib,vtk\" numpy scipy matplotlib vtk
175
+ python -c "import vtk"
176
+ python -m pip install --progress-bar off --upgrade -ve .[full] --group=test_extra
177
+ displayName: 'Install dependencies with pip'
178
+ - bash: |
179
+ set -e
180
+ which mne
181
+ mne sys_info -pd
182
+ python ./tools/check_mne_location.py
183
+ displayName: Print config
184
+ - bash: source tools/get_testing_version.sh
185
+ displayName: 'Get testing version'
186
+ - task: Cache@2
187
+ inputs:
188
+ key: $(testing_version)
189
+ path: /home/vsts/mne_data
190
+ displayName: 'Cache testing data'
191
+ - script: python -c "import mne; mne.datasets.testing.data_path(verbose=True)"
192
+ displayName: 'Get test data'
193
+ - bash: |
194
+ set -eo pipefail
195
+ python -m pip install PyQt6
196
+ LD_DEBUG=libs python -c "from PyQt6.QtWidgets import QApplication, QWidget; app = QApplication([]); import matplotlib; matplotlib.use('QtAgg'); import matplotlib.pyplot as plt; plt.figure()"
197
+ displayName: 'Check Qt import'
198
+ - bash: |
199
+ set -eo pipefail
200
+ mne sys_info -pd
201
+ mne sys_info -pd | grep "qtpy .* (PyQt6=.*)$"
202
+ PYTEST_QT_API=PyQt6 pytest -m "not ultraslowtest" ${TEST_OPTIONS}
203
+ python -m pip uninstall -yq PyQt6 PyQt6-sip PyQt6-Qt6
204
+ displayName: 'PyQt6'
205
+ - bash: |
206
+ set -eo pipefail
207
+ python -m pip install "PySide6!=6.8.0,!=6.8.0.1,!=6.9.1"
208
+ mne sys_info -pd
209
+ mne sys_info -pd | grep "qtpy .* (PySide6=.*)$"
210
+ PYTEST_QT_API=PySide6 pytest -m "not ultraslowtest" ${TEST_OPTIONS}
211
+ python -m pip uninstall -yq PySide6
212
+ displayName: 'PySide6'
213
+ # PyQt5 leaves cruft behind, so run it last
214
+ - bash: |
215
+ set -eo pipefail
216
+ python -m pip install PyQt5
217
+ mne sys_info -pd
218
+ mne sys_info -pd | grep "qtpy .* (PyQt5=.*)$"
219
+ PYTEST_QT_API=PyQt5 pytest -m "not ultraslowtest" ${TEST_OPTIONS}
220
+ python -m pip uninstall -yq PyQt5 PyQt5-sip PyQt5-Qt5
221
+ displayName: 'PyQt5'
222
+ # Coverage
223
+ - bash: bash <(curl -s https://codecov.io/bash)
224
+ displayName: 'Codecov'
225
+ condition: succeededOrFailed()
226
+ - task: PublishTestResults@2
227
+ inputs:
228
+ testResultsFiles: '**/junit-*.xml'
229
+ testRunTitle: 'Publish test results for $(Agent.JobName)'
230
+ failTaskOnFailedTests: true
231
+ condition: succeededOrFailed()
232
+ - task: PublishCodeCoverageResults@2
233
+ inputs:
234
+ summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml'
235
+
236
+ - job: Windows
237
+ pool:
238
+ vmImage: 'windows-latest'
239
+ variables:
240
+ MNE_LOGGING_LEVEL: 'warning'
241
+ MNE_FORCE_SERIAL: 'true'
242
+ OPENBLAS_NUM_THREADS: '2'
243
+ OMP_DYNAMIC: 'false'
244
+ PYTHONUNBUFFERED: 1
245
+ PYTHONIOENCODING: 'utf-8'
246
+ AZURE_CI_WINDOWS: 'true'
247
+ PYTHON_ARCH: 'x64'
248
+ MNE_CI_KIND: $(TEST_MODE)
249
+ timeoutInMinutes: 95
250
+ strategy:
251
+ maxParallel: 4
252
+ matrix:
253
+ 3.10 pip:
254
+ TEST_MODE: 'pip'
255
+ PYTHON_VERSION: '3.10'
256
+ 3.13 pip pre:
257
+ TEST_MODE: 'pip-pre'
258
+ PYTHON_VERSION: '3.13'
259
+ steps:
260
+ - task: UsePythonVersion@0
261
+ inputs:
262
+ versionSpec: $(PYTHON_VERSION)
263
+ architecture: $(PYTHON_ARCH)
264
+ addToPath: true
265
+ displayName: 'Get Python'
266
+ - bash: |
267
+ set -eo pipefail
268
+ git clone --depth 1 https://github.com/pyvista/setup-headless-display-action.git
269
+ MESA3D_VERSION=24.3.0 bash setup-headless-display-action/windows/install_opengl.sh
270
+ displayName: Install OpenGL
271
+ - bash: ./tools/azure_dependencies.sh
272
+ displayName: Install dependencies with pip
273
+ - script: pip install -e .
274
+ displayName: 'Install MNE-Python dev'
275
+ - script: mne sys_info -pd
276
+ displayName: 'Print config'
277
+ - script: python -c "import numpy; numpy.show_config()"
278
+ displayName: Print NumPy config
279
+ - script: python -c "import numpy; import scipy.linalg; import sklearn.neighbors; from threadpoolctl import threadpool_info; from pprint import pprint; pprint(threadpool_info())"
280
+ displayName: Print threadpoolctl info
281
+ - bash: source tools/get_testing_version.sh
282
+ displayName: 'Get testing version'
283
+ - task: Cache@2
284
+ inputs:
285
+ key: $(testing_version)
286
+ path: C:\Users\VssAdministrator\mne_data
287
+ displayName: 'Cache testing data'
288
+ - script: python -c "import mne; mne.datasets.testing.data_path(verbose=True)"
289
+ displayName: 'Get test data'
290
+ - script: pytest -m "not (slowtest or pgtest)" --tb=short --cov=mne --cov-report=xml -vv mne
291
+ displayName: 'Run tests'
292
+ - bash: bash <(curl -s https://codecov.io/bash)
293
+ displayName: 'Codecov'
294
+ condition: succeededOrFailed()
295
+ - task: PublishTestResults@2
296
+ inputs:
297
+ testResultsFiles: '**/junit-*.xml'
298
+ testRunTitle: 'Publish test results for $(Agent.JobName) $(TEST_MODE) $(PYTHON_VERSION)'
299
+ failTaskOnFailedTests: true
300
+ condition: succeededOrFailed()
301
+ - task: PublishCodeCoverageResults@2
302
+ inputs:
303
+ summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml'
mne-python/source/codecov.yml ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ comment: false
2
+ github_checks: # too noisy, even though "a" interactively disables them
3
+ annotations: false
4
+
5
+ codecov:
6
+ notify:
7
+ require_ci_to_pass: false
8
+
9
+ coverage:
10
+ status:
11
+ patch:
12
+ default:
13
+ informational: true
14
+ target: 95%
15
+ if_no_uploads: error
16
+ if_not_found: success
17
+ if_ci_failed: failure
18
+ project:
19
+ default: false
20
+ library:
21
+ informational: true
22
+ target: 90%
23
+ if_no_uploads: error
24
+ if_not_found: success
25
+ if_ci_failed: failure
mne-python/source/codemeta.json ADDED
@@ -0,0 +1,2555 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "@context": "https://doi.org/10.5063/schema/codemeta-2.0",
3
+ "@type": "SoftwareSourceCode",
4
+ "license": "https://spdx.org/licenses/BSD-3-Clause",
5
+ "codeRepository": "git+https://github.com/mne-tools/mne-python.git",
6
+ "dateCreated": "2010-12-26",
7
+ "datePublished": "2014-08-04",
8
+ "dateModified": "2025-11-21",
9
+ "downloadUrl": "https://github.com/mne-tools/mne-python/archive/v1.11.0.zip",
10
+ "issueTracker": "https://github.com/mne-tools/mne-python/issues",
11
+ "name": "MNE-Python",
12
+ "version": "1.11.0",
13
+ "description": "MNE-Python is an open-source Python package for exploring, visualizing, and analyzing human neurophysiological data. It provides methods for data input/output, preprocessing, visualization, source estimation, time-frequency analysis, connectivity analysis, machine learning, and statistics.",
14
+ "applicationCategory": "Neuroscience",
15
+ "developmentStatus": "active",
16
+ "referencePublication": "https://doi.org/10.3389/fnins.2013.00267",
17
+ "keywords": [
18
+ "MEG",
19
+ "magnetoencephalography",
20
+ "EEG",
21
+ "electroencephalography",
22
+ "fNIRS",
23
+ "functional near-infrared spectroscopy",
24
+ "iEEG",
25
+ "intracranial EEG",
26
+ "eCoG",
27
+ "electrocorticography",
28
+ "DBS",
29
+ "deep brain stimulation"
30
+ ],
31
+ "programmingLanguage": [
32
+ "Python"
33
+ ],
34
+ "operatingSystem": [
35
+ "Linux",
36
+ "Windows",
37
+ "macOS"
38
+ ],
39
+ "softwareRequirements": [
40
+ "python>= 3.10",
41
+ "decorator",
42
+ "jinja2",
43
+ "lazy_loader >= 0.3",
44
+ "matplotlib >= 3.8",
45
+ "numpy >= 1.26, < 3",
46
+ "packaging",
47
+ "pooch >= 1.5",
48
+ "scipy >= 1.11",
49
+ "tqdm"
50
+ ],
51
+ "author": [
52
+ {
53
+ "@type":"Person",
54
+ "email":"larson.eric.d@gmail.com",
55
+ "givenName":"Eric",
56
+ "familyName": "Larson"
57
+ },
58
+ {
59
+ "@type":"Person",
60
+ "email":"alexandre.gramfort@inria.fr",
61
+ "givenName":"Alexandre",
62
+ "familyName": "Gramfort"
63
+ },
64
+ {
65
+ "@type":"Person",
66
+ "email":"denis.engemann@gmail.com",
67
+ "givenName":"Denis A",
68
+ "familyName": "Engemann"
69
+ },
70
+ {
71
+ "@type":"Person",
72
+ "email":"jaeilepp@gmail.com",
73
+ "givenName":"Jaakko",
74
+ "familyName": "Leppakangas"
75
+ },
76
+ {
77
+ "@type":"Person",
78
+ "email":"christianmbrodbeck@gmail.com",
79
+ "givenName":"Christian",
80
+ "familyName": "Brodbeck"
81
+ },
82
+ {
83
+ "@type":"Person",
84
+ "email":"mainakjas@gmail.com",
85
+ "givenName":"Mainak",
86
+ "familyName": "Jas"
87
+ },
88
+ {
89
+ "@type":"Person",
90
+ "email":"teon.brooks@gmail.com",
91
+ "givenName":"Teon L",
92
+ "familyName": "Brooks"
93
+ },
94
+ {
95
+ "@type":"Person",
96
+ "email":"jona.sassenhagen@gmail.com",
97
+ "givenName":"Jona",
98
+ "familyName": "Sassenhagen"
99
+ },
100
+ {
101
+ "@type":"Person",
102
+ "email":"dan@mccloy.info",
103
+ "givenName":"Daniel",
104
+ "familyName": "McCloy"
105
+ },
106
+ {
107
+ "@type":"Person",
108
+ "email":"mluessi@nmr.mgh.harvard.edu",
109
+ "givenName":"Martin",
110
+ "familyName": "Luessi"
111
+ },
112
+ {
113
+ "@type":"Person",
114
+ "email":"jeanremi.king+github@gmail.com",
115
+ "givenName":"Jean-Rémi",
116
+ "familyName": "King"
117
+ },
118
+ {
119
+ "@type":"Person",
120
+ "email":"richard.hoechenberger@gmail.com",
121
+ "givenName":"Richard",
122
+ "familyName": "Höchenberger"
123
+ },
124
+ {
125
+ "@type":"Person",
126
+ "email":"clemens.brunner@gmail.com",
127
+ "givenName":"Clemens",
128
+ "familyName": "Brunner"
129
+ },
130
+ {
131
+ "@type":"Person",
132
+ "email":"roman.goj@gmail.com",
133
+ "givenName":"Roman",
134
+ "familyName": "Goj"
135
+ },
136
+ {
137
+ "@type":"Person",
138
+ "email":"guillaume.favelier@gmail.com",
139
+ "givenName":"Guillaume",
140
+ "familyName": "Favelier"
141
+ },
142
+ {
143
+ "@type":"Person",
144
+ "email":"w.m.vanvliet@gmail.com",
145
+ "givenName":"Marijn",
146
+ "familyName": "van Vliet"
147
+ },
148
+ {
149
+ "@type":"Person",
150
+ "email":"wronk.mark@gmail.com",
151
+ "givenName":"Mark",
152
+ "familyName": "Wronkiewicz"
153
+ },
154
+ {
155
+ "@type":"Person",
156
+ "email":"stefan.appelhoff@mailbox.org",
157
+ "givenName":"Stefan",
158
+ "familyName": "Appelhoff"
159
+ },
160
+ {
161
+ "@type":"Person",
162
+ "email":"aprockhill206@gmail.com",
163
+ "givenName":"Alex",
164
+ "familyName": "Rockhill"
165
+ },
166
+ {
167
+ "@type":"Person",
168
+ "email":"choldgraf@gmail.com",
169
+ "givenName":"Chris",
170
+ "familyName": "Holdgraf"
171
+ },
172
+ {
173
+ "@type":"Person",
174
+ "email":"mathieu.scheltienne@gmail.com",
175
+ "givenName":"Mathieu",
176
+ "familyName": "Scheltienne"
177
+ },
178
+ {
179
+ "@type":"Person",
180
+ "email":"mailsik@gmail.com",
181
+ "givenName":"Joan",
182
+ "familyName": "Massich"
183
+ },
184
+ {
185
+ "@type":"Person",
186
+ "email":"yousra.bekhti@gmail.com",
187
+ "givenName":"Yousra",
188
+ "familyName": "Bekhti"
189
+ },
190
+ {
191
+ "@type":"Person",
192
+ "email":"leggitta3@gmail.com",
193
+ "givenName":"Alan",
194
+ "familyName": "Leggitt"
195
+ },
196
+ {
197
+ "@type":"Person",
198
+ "email":"andrew.r.dykstra@gmail.com",
199
+ "givenName":"Andrew",
200
+ "familyName": "Dykstra"
201
+ },
202
+ {
203
+ "@type":"Person",
204
+ "email":"romain.trachel@inria.fr",
205
+ "givenName":"Romain",
206
+ "familyName": "Trachel"
207
+ },
208
+ {
209
+ "@type":"Person",
210
+ "email":"code@robertluke.net",
211
+ "givenName":"Robert",
212
+ "familyName": "Luke"
213
+ },
214
+ {
215
+ "@type":"Person",
216
+ "email":"desantis.lnz@gmail.com",
217
+ "givenName":"Lorenzo",
218
+ "familyName": "De Santis"
219
+ },
220
+ {
221
+ "@type":"Person",
222
+ "email":"asishrocks95@gmail.com",
223
+ "givenName":"Asish",
224
+ "familyName": "Panda"
225
+ },
226
+ {
227
+ "@type":"Person",
228
+ "email":"mmagnuski@swps.edu.pl",
229
+ "givenName":"Mikołaj",
230
+ "familyName": "Magnuski"
231
+ },
232
+ {
233
+ "@type":"Person",
234
+ "email":"britta.wstnr@gmail.com",
235
+ "givenName":"Britta",
236
+ "familyName": "Westner"
237
+ },
238
+ {
239
+ "@type":"Person",
240
+ "email":"dgwakeman@gmail.com",
241
+ "givenName":"Dan G",
242
+ "familyName": "Wakeman"
243
+ },
244
+ {
245
+ "@type":"Person",
246
+ "email":"daniel.strohmeier@googlemail.com",
247
+ "givenName":"Daniel",
248
+ "familyName": "Strohmeier"
249
+ },
250
+ {
251
+ "@type":"Person",
252
+ "email":"hari@nmr.mgh.harvard.edu",
253
+ "givenName":"Hari",
254
+ "familyName": "Bharadwaj"
255
+ },
256
+ {
257
+ "@type":"Person",
258
+ "email":"tal.linzen@gmail.com",
259
+ "givenName":"Tal",
260
+ "familyName": "Linzen"
261
+ },
262
+ {
263
+ "@type":"Person",
264
+ "email":"alexandre.barachant@gmail.com",
265
+ "givenName":"Alexandre",
266
+ "familyName": "Barachant"
267
+ },
268
+ {
269
+ "@type":"Person",
270
+ "email":"emilyr@nmr.mgh.harvard.edu",
271
+ "givenName":"Emily",
272
+ "familyName": "Ruzich"
273
+ },
274
+ {
275
+ "@type":"Person",
276
+ "email":"",
277
+ "givenName":"Scott",
278
+ "familyName": "Huberty"
279
+ },
280
+ {
281
+ "@type":"Person",
282
+ "email":"bailey.cj@gmail.com",
283
+ "givenName":"Christopher J",
284
+ "familyName": "Bailey"
285
+ },
286
+ {
287
+ "@type":"Person",
288
+ "email":"adam2392@gmail.com",
289
+ "givenName":"Adam",
290
+ "familyName": "Li"
291
+ },
292
+ {
293
+ "@type":"Person",
294
+ "email":"clement.moutard@gmail.com",
295
+ "givenName":"Clément",
296
+ "familyName": "Moutard"
297
+ },
298
+ {
299
+ "@type":"Person",
300
+ "email":"luke.bloy@gmail.com",
301
+ "givenName":"Luke",
302
+ "familyName": "Bloy"
303
+ },
304
+ {
305
+ "@type":"Person",
306
+ "email":"federaimondo@gmail.com",
307
+ "givenName":"Fede",
308
+ "familyName": "Raimondo"
309
+ },
310
+ {
311
+ "@type":"Person",
312
+ "email":"jnu@iki.fi",
313
+ "givenName":"Jussi",
314
+ "familyName": "Nurminen"
315
+ },
316
+ {
317
+ "@type":"Person",
318
+ "email":"flKazemakase@gmail.com",
319
+ "givenName":"Martin",
320
+ "familyName": "Billinger"
321
+ },
322
+ {
323
+ "@type":"Person",
324
+ "email":"montoya.jair.m@gmail.com",
325
+ "givenName":"Jair",
326
+ "familyName": "Montoya"
327
+ },
328
+ {
329
+ "@type":"Person",
330
+ "email":"mmwoodman@gmail.com",
331
+ "givenName":"Marmaduke",
332
+ "familyName": "Woodman"
333
+ },
334
+ {
335
+ "@type":"Person",
336
+ "email":"dlsrnsladlek@naver.com",
337
+ "givenName":"Ingoo",
338
+ "familyName": "Lee"
339
+ },
340
+ {
341
+ "@type":"Person",
342
+ "email":"dev@mgschulz.de",
343
+ "givenName":"Martin",
344
+ "familyName": "Schulz"
345
+ },
346
+ {
347
+ "@type":"Person",
348
+ "email":"nfoti01@gmail.com",
349
+ "givenName":"Nick",
350
+ "familyName": "Foti"
351
+ },
352
+ {
353
+ "@type":"Person",
354
+ "email":"cnangini@gmail.com",
355
+ "givenName":"Cathy",
356
+ "familyName": "Nangini"
357
+ },
358
+ {
359
+ "@type":"Person",
360
+ "email":"joialanisson@gmail.com",
361
+ "givenName":"José C",
362
+ "familyName": "García Alanis"
363
+ },
364
+ {
365
+ "@type":"Person",
366
+ "email":"t.s.binns@outlook.com",
367
+ "givenName":"Thomas S",
368
+ "familyName": "Binns"
369
+ },
370
+ {
371
+ "@type":"Person",
372
+ "email":"",
373
+ "givenName":"Dimitri Papadopoulos",
374
+ "familyName": "Orfanos"
375
+ },
376
+ {
377
+ "@type":"Person",
378
+ "email":"olaf.hauk@mrc-cbu.cam.ac.uk",
379
+ "givenName":"Olaf",
380
+ "familyName": "Hauk"
381
+ },
382
+ {
383
+ "@type":"Person",
384
+ "email":"ross.maddox@rochester.edu",
385
+ "givenName":"Ross",
386
+ "familyName": "Maddox"
387
+ },
388
+ {
389
+ "@type":"Person",
390
+ "email":"aestrivex@gmail.com",
391
+ "givenName":"Roan",
392
+ "familyName": "LaPlante"
393
+ },
394
+ {
395
+ "@type":"Person",
396
+ "email":"ashdrew@uw.edu",
397
+ "givenName":"Ashley",
398
+ "familyName": "Drew"
399
+ },
400
+ {
401
+ "@type":"Person",
402
+ "email":"chdinh@nmr.mgh.harvard.edu",
403
+ "givenName":"Christoph",
404
+ "familyName": "Dinh"
405
+ },
406
+ {
407
+ "@type":"Person",
408
+ "email":"deep@introspection.eu",
409
+ "givenName":"Guillaume",
410
+ "familyName": "Dumas"
411
+ },
412
+ {
413
+ "@type":"Person",
414
+ "email":"martin.billinger@tugraz.at",
415
+ "givenName":"",
416
+ "familyName": "Martin"
417
+ },
418
+ {
419
+ "@type":"Person",
420
+ "email":"johann.benerradi@gmail.com",
421
+ "givenName":"Johann",
422
+ "familyName": "Benerradi"
423
+ },
424
+ {
425
+ "@type":"Person",
426
+ "email":"thomas.hartmann@th-ht.de",
427
+ "givenName":"Thomas",
428
+ "familyName": "Hartmann"
429
+ },
430
+ {
431
+ "@type":"Person",
432
+ "email":"eduardxort@gmail.com",
433
+ "givenName":"Eduard",
434
+ "familyName": "Ort"
435
+ },
436
+ {
437
+ "@type":"Person",
438
+ "email":"flkazemakase@gmail.com",
439
+ "givenName":"Martin",
440
+ "familyName": "Billinger"
441
+ },
442
+ {
443
+ "@type":"Person",
444
+ "email":"paul@ppasler.de",
445
+ "givenName":"Paul",
446
+ "familyName": "Pasler"
447
+ },
448
+ {
449
+ "@type":"Person",
450
+ "email":"stefan.repplinger@posteo.net",
451
+ "givenName":"Stefan",
452
+ "familyName": "Repplinger"
453
+ },
454
+ {
455
+ "@type":"Person",
456
+ "email":"alxanderr@gmail.com",
457
+ "givenName":"Alexander",
458
+ "familyName": "Rudiuk"
459
+ },
460
+ {
461
+ "@type":"Person",
462
+ "email":"anaradanovica@gmail.com",
463
+ "givenName":"Ana",
464
+ "familyName": "Radanovic"
465
+ },
466
+ {
467
+ "@type":"Person",
468
+ "email":"bburan@galenea.com",
469
+ "givenName":"Brad",
470
+ "familyName": "Buran"
471
+ },
472
+ {
473
+ "@type":"Person",
474
+ "email":"Woessner.jacob@gmail.com",
475
+ "givenName":"Jacob",
476
+ "familyName": "Woessner"
477
+ },
478
+ {
479
+ "@type":"Person",
480
+ "email":"mathurin.massias@gmail.com",
481
+ "givenName":"Mathurin",
482
+ "familyName": "Massias"
483
+ },
484
+ {
485
+ "@type":"Person",
486
+ "email":"msh@nmr.mgh.harvard.edu",
487
+ "givenName":"Matti",
488
+ "familyName": "Hämäläinen"
489
+ },
490
+ {
491
+ "@type":"Person",
492
+ "email":"pravsripad@gmail.com",
493
+ "givenName":"Praveen",
494
+ "familyName": "Sripad"
495
+ },
496
+ {
497
+ "@type":"Person",
498
+ "email":"vagechirkov@gmail.com",
499
+ "givenName":"Valerii",
500
+ "familyName": "Chirkov"
501
+ },
502
+ {
503
+ "@type":"Person",
504
+ "email":"christopherrmullins@gmail.com",
505
+ "givenName":"Christopher",
506
+ "familyName": "Mullins"
507
+ },
508
+ {
509
+ "@type":"Person",
510
+ "email":"gamaz3ps@gmail.com",
511
+ "givenName":"Félix",
512
+ "familyName": "Raimundo"
513
+ },
514
+ {
515
+ "@type":"Person",
516
+ "email":"",
517
+ "givenName":"Gennadiy",
518
+ "familyName": "Belonosov"
519
+ },
520
+ {
521
+ "@type":"Person",
522
+ "email":"rcmdnk@gmail.com",
523
+ "givenName":"Michiru",
524
+ "familyName": "Kaneda"
525
+ },
526
+ {
527
+ "@type":"Person",
528
+ "email":"phillip.alday@mpi.nl",
529
+ "givenName":"Phillip",
530
+ "familyName": "Alday"
531
+ },
532
+ {
533
+ "@type":"Person",
534
+ "email":"ramsbam@gmail.com",
535
+ "givenName":"Ram",
536
+ "familyName": "Pari"
537
+ },
538
+ {
539
+ "@type":"Person",
540
+ "email":"simon@simonster.com",
541
+ "givenName":"Simon",
542
+ "familyName": "Kornblith"
543
+ },
544
+ {
545
+ "@type":"Person",
546
+ "email":"debian@onerussian.com",
547
+ "givenName":"Yaroslav",
548
+ "familyName": "Halchenko"
549
+ },
550
+ {
551
+ "@type":"Person",
552
+ "email":"yuhanluo1994@gmail.com",
553
+ "givenName":"Yu-Han",
554
+ "familyName": "Luo"
555
+ },
556
+ {
557
+ "@type":"Person",
558
+ "email":"agramfort@fb.com",
559
+ "givenName":"Alexandre",
560
+ "familyName": "Gramfort"
561
+ },
562
+ {
563
+ "@type":"Person",
564
+ "email":"jeythekey@tutanota.com",
565
+ "givenName":"Johannes",
566
+ "familyName": "Kasper"
567
+ },
568
+ {
569
+ "@type":"Person",
570
+ "email":"kd889@nyu.edu",
571
+ "givenName":"Keith",
572
+ "familyName": "Doelling"
573
+ },
574
+ {
575
+ "@type":"Person",
576
+ "email":"mje.mads@gmail.com",
577
+ "givenName":"Mads",
578
+ "familyName": "Jensen"
579
+ },
580
+ {
581
+ "@type":"Person",
582
+ "email":"santeri.ruuskanen@aalto.fi",
583
+ "givenName":"Santeri",
584
+ "familyName": "Ruuskanen"
585
+ },
586
+ {
587
+ "@type":"Person",
588
+ "email":"simon.kern@online.de",
589
+ "givenName":"Simon",
590
+ "familyName": "Kern"
591
+ },
592
+ {
593
+ "@type":"Person",
594
+ "email":"tanaygahlot@gmail.com",
595
+ "givenName":"Tanay",
596
+ "familyName": "Gahlot"
597
+ },
598
+ {
599
+ "@type":"Person",
600
+ "email":"adonay.s.nunes@gmail.com",
601
+ "givenName":"Adonay",
602
+ "familyName": "Nunes"
603
+ },
604
+ {
605
+ "@type":"Person",
606
+ "email":"",
607
+ "givenName":"Dirk",
608
+ "familyName": "Gütlin"
609
+ },
610
+ {
611
+ "@type":"Person",
612
+ "email":"erkkahe@gmail.com",
613
+ "givenName":"Erkka",
614
+ "familyName": "Heinila"
615
+ },
616
+ {
617
+ "@type":"Person",
618
+ "email":"kristijan.armeni@gmail.com",
619
+ "givenName":"Kristijan",
620
+ "familyName": "Armeni"
621
+ },
622
+ {
623
+ "@type":"Person",
624
+ "email":"kjs@llama",
625
+ "givenName":"",
626
+ "familyName": "kjs"
627
+ },
628
+ {
629
+ "@type":"Person",
630
+ "email":"alejandro.weinstein@gmail.com",
631
+ "givenName":"Alejandro",
632
+ "familyName": "Weinstein"
633
+ },
634
+ {
635
+ "@type":"Person",
636
+ "email":"camilo@neurostat.mit.edu",
637
+ "givenName":"Camilo",
638
+ "familyName": "Lamus"
639
+ },
640
+ {
641
+ "@type":"Person",
642
+ "email":"",
643
+ "givenName":"Catalina María",
644
+ "familyName": "Galván"
645
+ },
646
+ {
647
+ "@type":"Person",
648
+ "email":"cmmoenne@gmail.com",
649
+ "givenName":"Cristóbal",
650
+ "familyName": "Moënne-Loccoz"
651
+ },
652
+ {
653
+ "@type":"Person",
654
+ "email":"dm.altukhov@ya.ru",
655
+ "givenName":"Dmitrii",
656
+ "familyName": "Altukhov"
657
+ },
658
+ {
659
+ "@type":"Person",
660
+ "email":"nordme@uw.edu",
661
+ "givenName":"Erica",
662
+ "familyName": "Peterson"
663
+ },
664
+ {
665
+ "@type":"Person",
666
+ "email":"jevri.hanna@gmail.com",
667
+ "givenName":"Jevri",
668
+ "familyName": "Hanna"
669
+ },
670
+ {
671
+ "@type":"Person",
672
+ "email":"jon.houck@gmail.com",
673
+ "givenName":"Jon",
674
+ "familyName": "Houck"
675
+ },
676
+ {
677
+ "@type":"Person",
678
+ "email":"neklein@andrew.cmu.edu",
679
+ "givenName":"Natalie",
680
+ "familyName": "Klein"
681
+ },
682
+ {
683
+ "@type":"Person",
684
+ "email":"paul@roujansky.eu",
685
+ "givenName":"Paul",
686
+ "familyName": "Roujansky"
687
+ },
688
+ {
689
+ "@type":"Person",
690
+ "email":"code@robertluke.net",
691
+ "givenName":"Rob",
692
+ "familyName": "Luke"
693
+ },
694
+ {
695
+ "@type":"Person",
696
+ "email":"antti.rantala90@gmail.com",
697
+ "givenName":"Antti",
698
+ "familyName": "Rantala"
699
+ },
700
+ {
701
+ "@type":"Person",
702
+ "email":"burkhard.maess@arcor.de",
703
+ "givenName":"Burkhard",
704
+ "familyName": "Maess"
705
+ },
706
+ {
707
+ "@type":"Person",
708
+ "email":"carinaforster0611@gmail.com",
709
+ "givenName":"Carina",
710
+ "familyName": "Forster"
711
+ },
712
+ {
713
+ "@type":"Person",
714
+ "email":"christian.oreilly@gmail.com",
715
+ "givenName":"Christian",
716
+ "familyName": "O'Reilly"
717
+ },
718
+ {
719
+ "@type":"Person",
720
+ "email":"dominik.welke@ae.mpg.de",
721
+ "givenName":"Dominik",
722
+ "familyName": "Welke"
723
+ },
724
+ {
725
+ "@type":"Person",
726
+ "email":"dominik.welke@web.de",
727
+ "givenName":"Dominik",
728
+ "familyName": "Welke"
729
+ },
730
+ {
731
+ "@type":"Person",
732
+ "email":"",
733
+ "givenName":"Henrich",
734
+ "familyName": "Kolkhorst"
735
+ },
736
+ {
737
+ "@type":"Person",
738
+ "email":"hubert.jbanville@gmail.com",
739
+ "givenName":"Hubert",
740
+ "familyName": "Banville"
741
+ },
742
+ {
743
+ "@type":"Person",
744
+ "email":"zhangmengyu10@gmail.com",
745
+ "givenName":"Jack",
746
+ "familyName": "Zhang"
747
+ },
748
+ {
749
+ "@type":"Person",
750
+ "email":"makkostya@ukr.net",
751
+ "givenName":"Kostiantyn",
752
+ "familyName": "Maksymenko"
753
+ },
754
+ {
755
+ "@type":"Person",
756
+ "email":"mdclarke@uw.edu",
757
+ "givenName":"Maggie",
758
+ "familyName": "Clarke"
759
+ },
760
+ {
761
+ "@type":"Person",
762
+ "email":"matteo.anelli@aalto.fi",
763
+ "givenName":"Matteo",
764
+ "familyName": "Anelli"
765
+ },
766
+ {
767
+ "@type":"Person",
768
+ "email":"michael.straube.d@gmail.com",
769
+ "givenName":"Michael",
770
+ "familyName": "Straube"
771
+ },
772
+ {
773
+ "@type":"Person",
774
+ "email":"",
775
+ "givenName":"Nikolai",
776
+ "familyName": "Chapochnikov"
777
+ },
778
+ {
779
+ "@type":"Person",
780
+ "email":"pierreantoine.bannier@gmail.com",
781
+ "givenName":"Pierre-Antoine",
782
+ "familyName": "Bannier"
783
+ },
784
+ {
785
+ "@type":"Person",
786
+ "email":"saketkc@gmail.com",
787
+ "givenName":"Saket",
788
+ "familyName": "Choudhary"
789
+ },
790
+ {
791
+ "@type":"Person",
792
+ "email":"victor.ferat@live.Fr",
793
+ "givenName":"Victor",
794
+ "familyName": "Férat"
795
+ },
796
+ {
797
+ "@type":"Person",
798
+ "email":"kimjico@gmail.com",
799
+ "givenName":"Cora",
800
+ "familyName": "Kim"
801
+ },
802
+ {
803
+ "@type":"Person",
804
+ "email":"klotzsche@cbs.mpg.de",
805
+ "givenName":"Felix",
806
+ "familyName": "Klotzsche"
807
+ },
808
+ {
809
+ "@type":"Person",
810
+ "email":"zuxfoucault@gmail.com",
811
+ "givenName":"Fu-Te",
812
+ "familyName": "Wong"
813
+ },
814
+ {
815
+ "@type":"Person",
816
+ "email":"",
817
+ "givenName":"Ivana",
818
+ "familyName": "Kojcic"
819
+ },
820
+ {
821
+ "@type":"Person",
822
+ "email":"jdue@dtu.dk",
823
+ "givenName":"Jesper Duemose",
824
+ "familyName": "Nielsen"
825
+ },
826
+ {
827
+ "@type":"Person",
828
+ "email":"",
829
+ "givenName":"Kaisu",
830
+ "familyName": "Lankinen"
831
+ },
832
+ {
833
+ "@type":"Person",
834
+ "email":"ktavabi@gmail.com",
835
+ "givenName":"Kambiz",
836
+ "familyName": "Tabavi"
837
+ },
838
+ {
839
+ "@type":"Person",
840
+ "email":"louist87@gmail.com",
841
+ "givenName":"Louis",
842
+ "familyName": "Thibault"
843
+ },
844
+ {
845
+ "@type":"Person",
846
+ "email":"",
847
+ "givenName":"Moritz",
848
+ "familyName": "Gerster"
849
+ },
850
+ {
851
+ "@type":"Person",
852
+ "email":"",
853
+ "givenName":"Nabil",
854
+ "familyName": "Alibou"
855
+ },
856
+ {
857
+ "@type":"Person",
858
+ "email":"nathalie.gayraud@inria.fr",
859
+ "givenName":"Nathalie",
860
+ "familyName": "Gayraud"
861
+ },
862
+ {
863
+ "@type":"Person",
864
+ "email":"ward.nickjames@gmail.com",
865
+ "givenName":"Nick",
866
+ "familyName": "Ward"
867
+ },
868
+ {
869
+ "@type":"Person",
870
+ "email":"",
871
+ "givenName":"Qian",
872
+ "familyName": "Chu"
873
+ },
874
+ {
875
+ "@type":"Person",
876
+ "email":"ksherbst@gmail.com",
877
+ "givenName":"Sophie",
878
+ "familyName": "Herbst"
879
+ },
880
+ {
881
+ "@type":"Person",
882
+ "email":"myd7349@gmail.com",
883
+ "givenName":"Tom",
884
+ "familyName": "Ma"
885
+ },
886
+ {
887
+ "@type":"Person",
888
+ "email":"",
889
+ "givenName":"Ana",
890
+ "familyName": "Radanovic"
891
+ },
892
+ {
893
+ "@type":"Person",
894
+ "email":"",
895
+ "givenName":"Andrew",
896
+ "familyName": "Quinn"
897
+ },
898
+ {
899
+ "@type":"Person",
900
+ "email":"antoine.gauthier@ensta.fr",
901
+ "givenName":"Antoine",
902
+ "familyName": "Gauthier"
903
+ },
904
+ {
905
+ "@type":"Person",
906
+ "email":"basile.pinsard@umontreal.ca",
907
+ "givenName":"Basile",
908
+ "familyName": "Pinsard"
909
+ },
910
+ {
911
+ "@type":"Person",
912
+ "email":"emilyps14@gmail.com",
913
+ "givenName":"Emily",
914
+ "familyName": "Stephen"
915
+ },
916
+ {
917
+ "@type":"Person",
918
+ "email":"erik.hornberger@shi-g.com",
919
+ "givenName":"Erik",
920
+ "familyName": "Hornberger"
921
+ },
922
+ {
923
+ "@type":"Person",
924
+ "email":"",
925
+ "givenName":"Evan",
926
+ "familyName": "Hathaway"
927
+ },
928
+ {
929
+ "@type":"Person",
930
+ "email":"e.kalenkovich@gmail.com",
931
+ "givenName":"Evgenii",
932
+ "familyName": "Kalenkovich"
933
+ },
934
+ {
935
+ "@type":"Person",
936
+ "email":"",
937
+ "givenName":"Fahimeh",
938
+ "familyName": "Mamashli"
939
+ },
940
+ {
941
+ "@type":"Person",
942
+ "email":"g.o'neill@ucl.ac.uk",
943
+ "givenName":"George",
944
+ "familyName": "O'Neill"
945
+ },
946
+ {
947
+ "@type":"Person",
948
+ "email":"giorgio.marinato@unitn.it",
949
+ "givenName":"Giorgio",
950
+ "familyName": "Marinato"
951
+ },
952
+ {
953
+ "@type":"Person",
954
+ "email":"hafiza.taj@gmail.com",
955
+ "givenName":"Hafeza",
956
+ "familyName": "Anevar"
957
+ },
958
+ {
959
+ "@type":"Person",
960
+ "email":"hamza.abdelhedii@gmail.com",
961
+ "givenName":"Hamza",
962
+ "familyName": "Abdelhedi"
963
+ },
964
+ {
965
+ "@type":"Person",
966
+ "email":"mail@jan-sosulski.de",
967
+ "givenName":"Jan",
968
+ "familyName": "Sosulski"
969
+ },
970
+ {
971
+ "@type":"Person",
972
+ "email":"stoutjd@nih.gov",
973
+ "givenName":"Jeff",
974
+ "familyName": "Stout"
975
+ },
976
+ {
977
+ "@type":"Person",
978
+ "email":"",
979
+ "givenName":"Joshua",
980
+ "familyName": "Calder-Travis"
981
+ },
982
+ {
983
+ "@type":"Person",
984
+ "email":"",
985
+ "givenName":"Judy D",
986
+ "familyName": "Zhu"
987
+ },
988
+ {
989
+ "@type":"Person",
990
+ "email":"leisenman@wustl.edu",
991
+ "givenName":"Larry",
992
+ "familyName": "Eisenman"
993
+ },
994
+ {
995
+ "@type":"Person",
996
+ "email":"Lorenz.Esch@tu-ilmenau.de",
997
+ "givenName":"Lorenz",
998
+ "familyName": "Esch"
999
+ },
1000
+ {
1001
+ "@type":"Person",
1002
+ "email":"marian.dowgialo@gmail.com",
1003
+ "givenName":"Marian",
1004
+ "familyName": "Dovgialo"
1005
+ },
1006
+ {
1007
+ "@type":"Person",
1008
+ "email":"",
1009
+ "givenName":"Nicolas",
1010
+ "familyName": "Barascud"
1011
+ },
1012
+ {
1013
+ "@type":"Person",
1014
+ "email":"legrand@cyceron.fr",
1015
+ "givenName":"Nicolas",
1016
+ "familyName": "Legrand"
1017
+ },
1018
+ {
1019
+ "@type":"Person",
1020
+ "email":"4dvlup@gmail.com",
1021
+ "givenName":"Nikolai",
1022
+ "familyName": "Kapralov"
1023
+ },
1024
+ {
1025
+ "@type":"Person",
1026
+ "email":"pmolfese@gmail.com",
1027
+ "givenName":"Peter J",
1028
+ "familyName": "Molfese"
1029
+ },
1030
+ {
1031
+ "@type":"Person",
1032
+ "email":"falachrotem@gmail.com",
1033
+ "givenName":"Rotem",
1034
+ "familyName": "Falach"
1035
+ },
1036
+ {
1037
+ "@type":"Person",
1038
+ "email":"sam.deslauriers@gmail.com",
1039
+ "givenName":"Samuel",
1040
+ "familyName": "Deslauriers-Gauthier"
1041
+ },
1042
+ {
1043
+ "@type":"Person",
1044
+ "email":"",
1045
+ "givenName":"Silvia",
1046
+ "familyName": "Cotroneo"
1047
+ },
1048
+ {
1049
+ "@type":"Person",
1050
+ "email":"stevematindi@gmail.com",
1051
+ "givenName":"Steve",
1052
+ "familyName": "Matindi"
1053
+ },
1054
+ {
1055
+ "@type":"Person",
1056
+ "email":"neurolaunch@gmail.copm",
1057
+ "givenName":"Steven",
1058
+ "familyName": "Bierer"
1059
+ },
1060
+ {
1061
+ "@type":"Person",
1062
+ "email":"Theodore.Papadopoulo@inria.fr",
1063
+ "givenName":"Theodore",
1064
+ "familyName": "Papadopoulo"
1065
+ },
1066
+ {
1067
+ "@type":"Person",
1068
+ "email":"t.s.binns@outlook.com",
1069
+ "givenName":"Thomas Samuel",
1070
+ "familyName": "Binns"
1071
+ },
1072
+ {
1073
+ "@type":"Person",
1074
+ "email":"ttstenner@gmail.com",
1075
+ "givenName":"Tristan",
1076
+ "familyName": "Stenner"
1077
+ },
1078
+ {
1079
+ "@type":"Person",
1080
+ "email":"victoriapeterson09@gmail.com",
1081
+ "givenName":"Victoria",
1082
+ "familyName": "Peterson"
1083
+ },
1084
+ {
1085
+ "@type":"Person",
1086
+ "email":"z.baratz@gmail.com",
1087
+ "givenName":"Zvi",
1088
+ "familyName": "Baratz"
1089
+ },
1090
+ {
1091
+ "@type":"Person",
1092
+ "email":"alessandro.tonin@wysscenter.ch",
1093
+ "givenName":"Alessandro",
1094
+ "familyName": "Tonin"
1095
+ },
1096
+ {
1097
+ "@type":"Person",
1098
+ "email":"alexander.kovrig@gmail.com",
1099
+ "givenName":"Alexander",
1100
+ "familyName": "Kovrig"
1101
+ },
1102
+ {
1103
+ "@type":"Person",
1104
+ "email":"a.pascarella@iac.cnr.it",
1105
+ "givenName":"Annalisa",
1106
+ "familyName": "Pascarella"
1107
+ },
1108
+ {
1109
+ "@type":"Person",
1110
+ "email":"",
1111
+ "givenName":"Apoorva",
1112
+ "familyName": "Karekal"
1113
+ },
1114
+ {
1115
+ "@type":"Person",
1116
+ "email":"b.aristimunha@gmail.com",
1117
+ "givenName":"Bruno",
1118
+ "familyName": "Aristimunha"
1119
+ },
1120
+ {
1121
+ "@type":"Person",
1122
+ "email":"",
1123
+ "givenName":"Carlos",
1124
+ "familyName": "de la Torre"
1125
+ },
1126
+ {
1127
+ "@type":"Person",
1128
+ "email":"",
1129
+ "givenName":"Chetan",
1130
+ "familyName": "Gohil"
1131
+ },
1132
+ {
1133
+ "@type":"Person",
1134
+ "email":"zhaotc@uw.edu",
1135
+ "givenName":"Christina",
1136
+ "familyName": "Zhao"
1137
+ },
1138
+ {
1139
+ "@type":"Person",
1140
+ "email":"raymon92@gmail.com",
1141
+ "givenName":"Dominik",
1142
+ "familyName": "Krzemiński"
1143
+ },
1144
+ {
1145
+ "@type":"Person",
1146
+ "email":"dom.mak19@gmail.com",
1147
+ "givenName":"Dominique",
1148
+ "familyName": "Makowski"
1149
+ },
1150
+ {
1151
+ "@type":"Person",
1152
+ "email":"e.mikulan@gmail.com",
1153
+ "givenName":"Ezequiel",
1154
+ "familyName": "Mikulan"
1155
+ },
1156
+ {
1157
+ "@type":"Person",
1158
+ "email":"hofaflo@gmail.com",
1159
+ "givenName":"Florian",
1160
+ "familyName": "Hofer"
1161
+ },
1162
+ {
1163
+ "@type":"Person",
1164
+ "email":"harrison.ritz@gmail.com",
1165
+ "givenName":"Harrison",
1166
+ "familyName": "Ritz"
1167
+ },
1168
+ {
1169
+ "@type":"Person",
1170
+ "email":"jean.baptiste.schiratti@gmail.com",
1171
+ "givenName":"Jean-Baptiste",
1172
+ "familyName": "Schiratti"
1173
+ },
1174
+ {
1175
+ "@type":"Person",
1176
+ "email":"",
1177
+ "givenName":"Jen",
1178
+ "familyName": "Evans"
1179
+ },
1180
+ {
1181
+ "@type":"Person",
1182
+ "email":"johannes@herforth.net",
1183
+ "givenName":"Johannes",
1184
+ "familyName": "Herforth"
1185
+ },
1186
+ {
1187
+ "@type":"Person",
1188
+ "email":"johnv@uchicago.edu",
1189
+ "givenName":"John",
1190
+ "familyName": "Veillette"
1191
+ },
1192
+ {
1193
+ "@type":"Person",
1194
+ "email":"",
1195
+ "givenName":"Jordan",
1196
+ "familyName": "Drew"
1197
+ },
1198
+ {
1199
+ "@type":"Person",
1200
+ "email":"jbtevespro@gmail.com",
1201
+ "givenName":"Joshua",
1202
+ "familyName": "Teves"
1203
+ },
1204
+ {
1205
+ "@type":"Person",
1206
+ "email":"kylemath@gmail.com",
1207
+ "givenName":"Kyle",
1208
+ "familyName": "Mathewson"
1209
+ },
1210
+ {
1211
+ "@type":"Person",
1212
+ "email":"lgwilliams90@gmail.com",
1213
+ "givenName":"Laura",
1214
+ "familyName": "Gwilliams"
1215
+ },
1216
+ {
1217
+ "@type":"Person",
1218
+ "email":"laurent.lementec@gmail.com",
1219
+ "givenName":"Laurent",
1220
+ "familyName": "Lementec"
1221
+ },
1222
+ {
1223
+ "@type":"Person",
1224
+ "email":"",
1225
+ "givenName":"Lenny",
1226
+ "familyName": "Varghese"
1227
+ },
1228
+ {
1229
+ "@type":"Person",
1230
+ "email":"",
1231
+ "givenName":"Liberty",
1232
+ "familyName": "Hamilton"
1233
+ },
1234
+ {
1235
+ "@type":"Person",
1236
+ "email":"lukas.gemein@gmx.de",
1237
+ "givenName":"Lukas",
1238
+ "familyName": "Gemein"
1239
+ },
1240
+ {
1241
+ "@type":"Person",
1242
+ "email":"",
1243
+ "givenName":"Lukas",
1244
+ "familyName": "Hecker"
1245
+ },
1246
+ {
1247
+ "@type":"Person",
1248
+ "email":"capmanip@DESKTOP-TLIFEG1.localdomain",
1249
+ "givenName":"",
1250
+ "familyName": "Lx37"
1251
+ },
1252
+ {
1253
+ "@type":"Person",
1254
+ "email":"mats.vanes@psych.ox.ac.uk",
1255
+ "givenName":"Mats",
1256
+ "familyName": "van Es"
1257
+ },
1258
+ {
1259
+ "@type":"Person",
1260
+ "email":"",
1261
+ "givenName":"Matt",
1262
+ "familyName": "Boggess"
1263
+ },
1264
+ {
1265
+ "@type":"Person",
1266
+ "email":"",
1267
+ "givenName":"Matthias",
1268
+ "familyName": "Eberlein"
1269
+ },
1270
+ {
1271
+ "@type":"Person",
1272
+ "email":"",
1273
+ "givenName":"Michal",
1274
+ "familyName": "Žák"
1275
+ },
1276
+ {
1277
+ "@type":"Person",
1278
+ "email":"molpsychistb@gmail.com",
1279
+ "givenName":"Mohamed",
1280
+ "familyName": "Sherif"
1281
+ },
1282
+ {
1283
+ "@type":"Person",
1284
+ "email":"natakozh22@gmail.com",
1285
+ "givenName":"Nataliia",
1286
+ "familyName": "Kozhemiako"
1287
+ },
1288
+ {
1289
+ "@type":"Person",
1290
+ "email":"",
1291
+ "givenName":"Naveen",
1292
+ "familyName": "Srinivasan"
1293
+ },
1294
+ {
1295
+ "@type":"Person",
1296
+ "email":"niklas.wilming@gmail.com",
1297
+ "givenName":"Niklas",
1298
+ "familyName": "Wilming"
1299
+ },
1300
+ {
1301
+ "@type":"Person",
1302
+ "email":"",
1303
+ "givenName":"Oleh",
1304
+ "familyName": "Kozynets"
1305
+ },
1306
+ {
1307
+ "@type":"Person",
1308
+ "email":"pierreablin@gmail.com",
1309
+ "givenName":"Pierre",
1310
+ "familyName": "Ablin"
1311
+ },
1312
+ {
1313
+ "@type":"Person",
1314
+ "email":"proloy@umd.edu",
1315
+ "givenName":"Proloy",
1316
+ "familyName": "Das"
1317
+ },
1318
+ {
1319
+ "@type":"Person",
1320
+ "email":"quentinbertrand54@gmail.com",
1321
+ "givenName":"Quentin",
1322
+ "familyName": "Bertrand"
1323
+ },
1324
+ {
1325
+ "@type":"Person",
1326
+ "email":"r.shoorangiz@live.com",
1327
+ "givenName":"Reza",
1328
+ "familyName": "Shoorangiz"
1329
+ },
1330
+ {
1331
+ "@type":"Person",
1332
+ "email":"",
1333
+ "givenName":"Richard",
1334
+ "familyName": "Scholz"
1335
+ },
1336
+ {
1337
+ "@type":"Person",
1338
+ "email":"rhubner@gmail.com",
1339
+ "givenName":"Rodrigo",
1340
+ "familyName": "Hübner"
1341
+ },
1342
+ {
1343
+ "@type":"Person",
1344
+ "email":"sommariva@dima.unige.it",
1345
+ "givenName":"Sara",
1346
+ "familyName": "Sommariva"
1347
+ },
1348
+ {
1349
+ "@type":"Person",
1350
+ "email":"",
1351
+ "givenName":"Sena",
1352
+ "familyName": "Er"
1353
+ },
1354
+ {
1355
+ "@type":"Person",
1356
+ "email":"sheraz@nmr.mgh.harvard.edu",
1357
+ "givenName":"Sheraz",
1358
+ "familyName": "Khan"
1359
+ },
1360
+ {
1361
+ "@type":"Person",
1362
+ "email":"",
1363
+ "givenName":"Sumalyo",
1364
+ "familyName": "Datta"
1365
+ },
1366
+ {
1367
+ "@type":"Person",
1368
+ "email":"tdonoghue.research@gmail.com",
1369
+ "givenName":"Thomas",
1370
+ "familyName": "Donoghue"
1371
+ },
1372
+ {
1373
+ "@type":"Person",
1374
+ "email":"",
1375
+ "givenName":"Thomas",
1376
+ "familyName": "Jochmann"
1377
+ },
1378
+ {
1379
+ "@type":"Person",
1380
+ "email":"timon.merk@charite.de",
1381
+ "givenName":"Timon",
1382
+ "familyName": "Merk"
1383
+ },
1384
+ {
1385
+ "@type":"Person",
1386
+ "email":"",
1387
+ "givenName":"Tod",
1388
+ "familyName": "Flak"
1389
+ },
1390
+ {
1391
+ "@type":"Person",
1392
+ "email":"tom.dupre-la-tour@m4x.org",
1393
+ "givenName":"Tom",
1394
+ "familyName": "Dupré la Tour"
1395
+ },
1396
+ {
1397
+ "@type":"Person",
1398
+ "email":"tzionan@mail.tau.ac.il",
1399
+ "givenName":"Tziona",
1400
+ "familyName": "NessAiver"
1401
+ },
1402
+ {
1403
+ "@type":"Person",
1404
+ "email":"akshay0724@gmail.com",
1405
+ "givenName":"",
1406
+ "familyName": "akshay0724"
1407
+ },
1408
+ {
1409
+ "@type":"Person",
1410
+ "email":"sviter33@gmail.com",
1411
+ "givenName":"",
1412
+ "familyName": "sviter"
1413
+ },
1414
+ {
1415
+ "@type":"Person",
1416
+ "email":"Jakdaxter31@gmail.com",
1417
+ "givenName":"Aaron",
1418
+ "familyName": "Earle-Richardson"
1419
+ },
1420
+ {
1421
+ "@type":"Person",
1422
+ "email":"abram.hindle@softwareprocess.es",
1423
+ "givenName":"Abram",
1424
+ "familyName": "Hindle"
1425
+ },
1426
+ {
1427
+ "@type":"Person",
1428
+ "email":"achilleas.k@gmail.com",
1429
+ "givenName":"Achilleas",
1430
+ "familyName": "Koutsou"
1431
+ },
1432
+ {
1433
+ "@type":"Person",
1434
+ "email":"",
1435
+ "givenName":"Adeline",
1436
+ "familyName": "Fecker"
1437
+ },
1438
+ {
1439
+ "@type":"Person",
1440
+ "email":"adina.wagner@t-online.de",
1441
+ "givenName":"Adina",
1442
+ "familyName": "Wagner"
1443
+ },
1444
+ {
1445
+ "@type":"Person",
1446
+ "email":"",
1447
+ "givenName":"Alex",
1448
+ "familyName": "Ciok"
1449
+ },
1450
+ {
1451
+ "@type":"Person",
1452
+ "email":"alex.lepauvre@ae.mpg.de",
1453
+ "givenName":"Alex",
1454
+ "familyName": "Lepauvre"
1455
+ },
1456
+ {
1457
+ "@type":"Person",
1458
+ "email":"",
1459
+ "givenName":"Alexander",
1460
+ "familyName": "Kiefer"
1461
+ },
1462
+ {
1463
+ "@type":"Person",
1464
+ "email":"7andy121@gmail.com",
1465
+ "givenName":"Andy",
1466
+ "familyName": "Gilbert"
1467
+ },
1468
+ {
1469
+ "@type":"Person",
1470
+ "email":"aniket17133@iiitd.ac.in",
1471
+ "givenName":"Aniket",
1472
+ "familyName": "Pradhan"
1473
+ },
1474
+ {
1475
+ "@type":"Person",
1476
+ "email":"anna.padee@gmail.com",
1477
+ "givenName":"Anna",
1478
+ "familyName": "Padee"
1479
+ },
1480
+ {
1481
+ "@type":"Person",
1482
+ "email":"as_dub@hotmail.com",
1483
+ "givenName":"Anne-Sophie",
1484
+ "familyName": "Dubarry"
1485
+ },
1486
+ {
1487
+ "@type":"Person",
1488
+ "email":"contact@antoinecollas.fr",
1489
+ "givenName":"Antoine",
1490
+ "familyName": "Collas"
1491
+ },
1492
+ {
1493
+ "@type":"Person",
1494
+ "email":"",
1495
+ "givenName":"Anton Nikolas",
1496
+ "familyName": "Waniek"
1497
+ },
1498
+ {
1499
+ "@type":"Person",
1500
+ "email":"",
1501
+ "givenName":"Archit",
1502
+ "familyName": "Singhal"
1503
+ },
1504
+ {
1505
+ "@type":"Person",
1506
+ "email":"arokem@gmail.com",
1507
+ "givenName":"Ariel",
1508
+ "familyName": "Rokem"
1509
+ },
1510
+ {
1511
+ "@type":"Person",
1512
+ "email":"arne.pelzer@idmt.fraunhofer.de",
1513
+ "givenName":"Arne",
1514
+ "familyName": "Pelzer"
1515
+ },
1516
+ {
1517
+ "@type":"Person",
1518
+ "email":"mynameisaustinhurst@gmail.com",
1519
+ "givenName":"Austin",
1520
+ "familyName": "Hurst"
1521
+ },
1522
+ {
1523
+ "@type":"Person",
1524
+ "email":"",
1525
+ "givenName":"Beige Jerry",
1526
+ "familyName": "Jin"
1527
+ },
1528
+ {
1529
+ "@type":"Person",
1530
+ "email":"code@musicinmybrain.net",
1531
+ "givenName":"Ben",
1532
+ "familyName": "Beasley"
1533
+ },
1534
+ {
1535
+ "@type":"Person",
1536
+ "email":"bruno.nicenboim@gmail.com",
1537
+ "givenName":"Bruno",
1538
+ "familyName": "Nicenboim"
1539
+ },
1540
+ {
1541
+ "@type":"Person",
1542
+ "email":"ctorre@mailbox.org",
1543
+ "givenName":"Carlos",
1544
+ "familyName": "de la Torre"
1545
+ },
1546
+ {
1547
+ "@type":"Person",
1548
+ "email":"cclauss@me.com",
1549
+ "givenName":"Christian",
1550
+ "familyName": "Clauss"
1551
+ },
1552
+ {
1553
+ "@type":"Person",
1554
+ "email":"cmista@ingenieria.uner.edu.ar",
1555
+ "givenName":"Christian",
1556
+ "familyName": "Mista"
1557
+ },
1558
+ {
1559
+ "@type":"Person",
1560
+ "email":"kechrisc@gmail.com",
1561
+ "givenName":"Christodoulos",
1562
+ "familyName": "Kechris"
1563
+ },
1564
+ {
1565
+ "@type":"Person",
1566
+ "email":"",
1567
+ "givenName":"Chun-Hui",
1568
+ "familyName": "Li"
1569
+ },
1570
+ {
1571
+ "@type":"Person",
1572
+ "email":"claire@guakamole.org",
1573
+ "givenName":"Claire",
1574
+ "familyName": "Braboszcz"
1575
+ },
1576
+ {
1577
+ "@type":"Person",
1578
+ "email":"daniel.c.schad@protonmail.com",
1579
+ "givenName":"Daniel C",
1580
+ "familyName": "Schad"
1581
+ },
1582
+ {
1583
+ "@type":"Person",
1584
+ "email":"danielhasegan@gmail.com",
1585
+ "givenName":"Daniel",
1586
+ "familyName": "Hasegan"
1587
+ },
1588
+ {
1589
+ "@type":"Person",
1590
+ "email":"xiezhibin.0.0.superman@gmail.com",
1591
+ "givenName":"Daniel",
1592
+ "familyName": "Tse"
1593
+ },
1594
+ {
1595
+ "@type":"Person",
1596
+ "email":"darin.sleiter@gmail.com",
1597
+ "givenName":"Darin Erat",
1598
+ "familyName": "Sleiter"
1599
+ },
1600
+ {
1601
+ "@type":"Person",
1602
+ "email":"haslacherdavid@gmail.com",
1603
+ "givenName":"David",
1604
+ "familyName": "Haslacher"
1605
+ },
1606
+ {
1607
+ "@type":"Person",
1608
+ "email":"dav.sabbagh@gmail.com",
1609
+ "givenName":"David",
1610
+ "familyName": "Sabbagh"
1611
+ },
1612
+ {
1613
+ "@type":"Person",
1614
+ "email":"",
1615
+ "givenName":"Demetres",
1616
+ "familyName": "Kostas"
1617
+ },
1618
+ {
1619
+ "@type":"Person",
1620
+ "email":"desislavka@gmail.com",
1621
+ "givenName":"Desislava",
1622
+ "familyName": "Petkova"
1623
+ },
1624
+ {
1625
+ "@type":"Person",
1626
+ "email":"",
1627
+ "givenName":"Dinara",
1628
+ "familyName": "Issagaliyeva"
1629
+ },
1630
+ {
1631
+ "@type":"Person",
1632
+ "email":"",
1633
+ "givenName":"Diptyajit",
1634
+ "familyName": "Das"
1635
+ },
1636
+ {
1637
+ "@type":"Person",
1638
+ "email":"dimonok@web.de",
1639
+ "givenName":"Dominik",
1640
+ "familyName": "Wetzel"
1641
+ },
1642
+ {
1643
+ "@type":"Person",
1644
+ "email":"e.eich@fz-juelich.de",
1645
+ "givenName":"Eberhard",
1646
+ "familyName": "Eich"
1647
+ },
1648
+ {
1649
+ "@type":"Person",
1650
+ "email":"emd222@cornell.edu",
1651
+ "givenName":"Elizabeth",
1652
+ "familyName": "DuPre"
1653
+ },
1654
+ {
1655
+ "@type":"Person",
1656
+ "email":"ellenlau@umd.edu",
1657
+ "givenName":"Ellen",
1658
+ "familyName": "Lau"
1659
+ },
1660
+ {
1661
+ "@type":"Person",
1662
+ "email":"emanuele@relativita.com",
1663
+ "givenName":"Emanuele",
1664
+ "familyName": "Olivetti"
1665
+ },
1666
+ {
1667
+ "@type":"Person",
1668
+ "email":"",
1669
+ "givenName":"Emma",
1670
+ "familyName": "Zhang"
1671
+ },
1672
+ {
1673
+ "@type":"Person",
1674
+ "email":"emmanuelferdman@gmail.com",
1675
+ "givenName":"Emmanuel",
1676
+ "familyName": "Ferdman"
1677
+ },
1678
+ {
1679
+ "@type":"Person",
1680
+ "email":"emrecncelik@gmail.com",
1681
+ "givenName":"Emrecan",
1682
+ "familyName": "Çelik"
1683
+ },
1684
+ {
1685
+ "@type":"Person",
1686
+ "email":"enricovarano@gmail.com",
1687
+ "givenName":"Enrico",
1688
+ "familyName": "Varano"
1689
+ },
1690
+ {
1691
+ "@type":"Person",
1692
+ "email":"enzo.alt@gmail.com",
1693
+ "givenName":"Enzo",
1694
+ "familyName": "Altamiranda"
1695
+ },
1696
+ {
1697
+ "@type":"Person",
1698
+ "email":"eric.brayet@mybraintech.com",
1699
+ "givenName":"Eric",
1700
+ "familyName": "Brayet"
1701
+ },
1702
+ {
1703
+ "@type":"Person",
1704
+ "email":"",
1705
+ "givenName":"Etienne",
1706
+ "familyName": "de Montalivet"
1707
+ },
1708
+ {
1709
+ "@type":"Person",
1710
+ "email":"",
1711
+ "givenName":"Evgeny",
1712
+ "familyName": "Goldstein"
1713
+ },
1714
+ {
1715
+ "@type":"Person",
1716
+ "email":"fmamashli@gmail.com",
1717
+ "givenName":"Fahimeh",
1718
+ "familyName": "Mamashli"
1719
+ },
1720
+ {
1721
+ "@type":"Person",
1722
+ "email":"farzin.negahbani@gmail.com",
1723
+ "givenName":"Farzin",
1724
+ "familyName": "Negahbani"
1725
+ },
1726
+ {
1727
+ "@type":"Person",
1728
+ "email":"",
1729
+ "givenName":"Federico",
1730
+ "familyName": "Zamberlan"
1731
+ },
1732
+ {
1733
+ "@type":"Person",
1734
+ "email":"florinpop@me.com",
1735
+ "givenName":"Florin",
1736
+ "familyName": "Pop"
1737
+ },
1738
+ {
1739
+ "@type":"Person",
1740
+ "email":"",
1741
+ "givenName":"Frederik D",
1742
+ "familyName": "Weber"
1743
+ },
1744
+ {
1745
+ "@type":"Person",
1746
+ "email":"",
1747
+ "givenName":"Gansheng",
1748
+ "familyName": "Tan"
1749
+ },
1750
+ {
1751
+ "@type":"Person",
1752
+ "email":"Geoff.Brookshire@gmail.com",
1753
+ "givenName":"Geoff",
1754
+ "familyName": "Brookshire"
1755
+ },
1756
+ {
1757
+ "@type":"Person",
1758
+ "email":"george.oneill.90@gmail.com",
1759
+ "givenName":"George",
1760
+ "familyName": "O'Neill"
1761
+ },
1762
+ {
1763
+ "@type":"Person",
1764
+ "email":"gack94@gmail.com",
1765
+ "givenName":"",
1766
+ "familyName": "Giulio"
1767
+ },
1768
+ {
1769
+ "@type":"Person",
1770
+ "email":"",
1771
+ "givenName":"Gonzalo",
1772
+ "familyName": "Reina"
1773
+ },
1774
+ {
1775
+ "@type":"Person",
1776
+ "email":"",
1777
+ "givenName":"Hamid",
1778
+ "familyName": "Maymandi"
1779
+ },
1780
+ {
1781
+ "@type":"Person",
1782
+ "email":"hasrat407@gmail.com",
1783
+ "givenName":"Hasrat Ali",
1784
+ "familyName": "Arzoo"
1785
+ },
1786
+ {
1787
+ "@type":"Person",
1788
+ "email":"hermann.sonntag@gmail.com",
1789
+ "givenName":"Hermann",
1790
+ "familyName": "Sonntag"
1791
+ },
1792
+ {
1793
+ "@type":"Person",
1794
+ "email":"rubyyhj@gmail.com",
1795
+ "givenName":"Hongjiang",
1796
+ "familyName": "Ye"
1797
+ },
1798
+ {
1799
+ "@type":"Person",
1800
+ "email":"",
1801
+ "givenName":"Hyonyoung",
1802
+ "familyName": "Shin"
1803
+ },
1804
+ {
1805
+ "@type":"Person",
1806
+ "email":"huseyinorkunelmas@gmail.com",
1807
+ "givenName":"Hüseyin Orkun",
1808
+ "familyName": "Elmas"
1809
+ },
1810
+ {
1811
+ "@type":"Person",
1812
+ "email":"",
1813
+ "givenName":"Ilian",
1814
+ "familyName": "AZZ"
1815
+ },
1816
+ {
1817
+ "@type":"Person",
1818
+ "email":"",
1819
+ "givenName":"Ilias",
1820
+ "familyName": "Machairas"
1821
+ },
1822
+ {
1823
+ "@type":"Person",
1824
+ "email":"ivan.zubarev@aalto.fi",
1825
+ "givenName":"Ivan",
1826
+ "familyName": "Zubarev"
1827
+ },
1828
+ {
1829
+ "@type":"Person",
1830
+ "email":"ivopascal@gmail.com",
1831
+ "givenName":"Ivo",
1832
+ "familyName": "de Jong"
1833
+ },
1834
+ {
1835
+ "@type":"Person",
1836
+ "email":"jacob.phelan.jp@gmail.com",
1837
+ "givenName":"Jacob",
1838
+ "familyName": "Phelan"
1839
+ },
1840
+ {
1841
+ "@type":"Person",
1842
+ "email":"",
1843
+ "givenName":"Jakub",
1844
+ "familyName": "Kaczmarzyk"
1845
+ },
1846
+ {
1847
+ "@type":"Person",
1848
+ "email":"",
1849
+ "givenName":"Jan",
1850
+ "familyName": "Zerfowski"
1851
+ },
1852
+ {
1853
+ "@type":"Person",
1854
+ "email":"japsai@gmail.com",
1855
+ "givenName":"Jasper J F",
1856
+ "familyName": "van den Bosch"
1857
+ },
1858
+ {
1859
+ "@type":"Person",
1860
+ "email":"",
1861
+ "givenName":"Jeroen",
1862
+ "familyName": "Van Der Donckt"
1863
+ },
1864
+ {
1865
+ "@type":"Person",
1866
+ "email":"johanvandermeer@gmail.com",
1867
+ "givenName":"Johan",
1868
+ "familyName": "van der Meer"
1869
+ },
1870
+ {
1871
+ "@type":"Person",
1872
+ "email":"",
1873
+ "givenName":"Johannes",
1874
+ "familyName": "Niediek"
1875
+ },
1876
+ {
1877
+ "@type":"Person",
1878
+ "email":"koen.joshua@gmail.com",
1879
+ "givenName":"Josh",
1880
+ "familyName": "Koen"
1881
+ },
1882
+ {
1883
+ "@type":"Person",
1884
+ "email":"",
1885
+ "givenName":"Joshua J",
1886
+ "familyName": "Bear"
1887
+ },
1888
+ {
1889
+ "@type":"Person",
1890
+ "email":"j.dammers@fz-juelich.de",
1891
+ "givenName":"Juergen",
1892
+ "familyName": "Dammers"
1893
+ },
1894
+ {
1895
+ "@type":"Person",
1896
+ "email":"guiomar.niso@ctb.upm.es",
1897
+ "givenName":"Julia Guiomar Niso",
1898
+ "familyName": "Galán"
1899
+ },
1900
+ {
1901
+ "@type":"Person",
1902
+ "email":"",
1903
+ "givenName":"Julius",
1904
+ "familyName": "Welzel"
1905
+ },
1906
+ {
1907
+ "@type":"Person",
1908
+ "email":"slama@berkeley.edu",
1909
+ "givenName":"Katarina",
1910
+ "familyName": "Slama"
1911
+ },
1912
+ {
1913
+ "@type":"Person",
1914
+ "email":"",
1915
+ "givenName":"Katia",
1916
+ "familyName": "Al-Amir"
1917
+ },
1918
+ {
1919
+ "@type":"Person",
1920
+ "email":"",
1921
+ "givenName":"Katrin",
1922
+ "familyName": "Leinweber"
1923
+ },
1924
+ {
1925
+ "@type":"Person",
1926
+ "email":"laetitia.grabot@gmail.com",
1927
+ "givenName":"Laetitia",
1928
+ "familyName": "Grabot"
1929
+ },
1930
+ {
1931
+ "@type":"Person",
1932
+ "email":"ualsbombe@protonmail.com",
1933
+ "givenName":"Lau Møller",
1934
+ "familyName": "Andersen"
1935
+ },
1936
+ {
1937
+ "@type":"Person",
1938
+ "email":"leorochael@gmail.com",
1939
+ "givenName":"Leonardo Rochael",
1940
+ "familyName": "Almeida"
1941
+ },
1942
+ {
1943
+ "@type":"Person",
1944
+ "email":"lsbarbosa@gmail.com",
1945
+ "givenName":"Leonardo S",
1946
+ "familyName": "Barbosa"
1947
+ },
1948
+ {
1949
+ "@type":"Person",
1950
+ "email":"lorenzo.alfine@gmail.com",
1951
+ "givenName":"Lorenzo",
1952
+ "familyName": "Alfine"
1953
+ },
1954
+ {
1955
+ "@type":"Person",
1956
+ "email":"hejtmy@gmail.com",
1957
+ "givenName":"Lukáš",
1958
+ "familyName": "Hejtmánek"
1959
+ },
1960
+ {
1961
+ "@type":"Person",
1962
+ "email":"mbalatsko@gmail.com",
1963
+ "givenName":"Maksym",
1964
+ "familyName": "Balatsko"
1965
+ },
1966
+ {
1967
+ "@type":"Person",
1968
+ "email":"manfredg@nmr.mgh.harvard.edu",
1969
+ "givenName":"Manfred",
1970
+ "familyName": "Kitzbichler"
1971
+ },
1972
+ {
1973
+ "@type":"Person",
1974
+ "email":"manojkumarsivaraj334@gmail.com",
1975
+ "givenName":"Manoj",
1976
+ "familyName": "Kumar"
1977
+ },
1978
+ {
1979
+ "@type":"Person",
1980
+ "email":"",
1981
+ "givenName":"Manorama",
1982
+ "familyName": "Kadwani"
1983
+ },
1984
+ {
1985
+ "@type":"Person",
1986
+ "email":"manu.sutela@gmail.com",
1987
+ "givenName":"Manu",
1988
+ "familyName": "Sutela"
1989
+ },
1990
+ {
1991
+ "@type":"Person",
1992
+ "email":"koculak.marcin@gmail.com",
1993
+ "givenName":"Marcin",
1994
+ "familyName": "Koculak"
1995
+ },
1996
+ {
1997
+ "@type":"Person",
1998
+ "email":"mah@optoceutics.com",
1999
+ "givenName":"Mark",
2000
+ "familyName": "Henney"
2001
+ },
2002
+ {
2003
+ "@type":"Person",
2004
+ "email":"Martinb.nmb@gmail.com",
2005
+ "givenName":"Martin",
2006
+ "familyName": "BaBer"
2007
+ },
2008
+ {
2009
+ "@type":"Person",
2010
+ "email":"",
2011
+ "givenName":"Martin",
2012
+ "familyName": "Oberg"
2013
+ },
2014
+ {
2015
+ "@type":"Person",
2016
+ "email":"",
2017
+ "givenName":"Martin",
2018
+ "familyName": "van Harmelen"
2019
+ },
2020
+ {
2021
+ "@type":"Person",
2022
+ "email":"mathieu.scheltienne@dandelion.science",
2023
+ "givenName":"Mathieu",
2024
+ "familyName": "Scheltienne"
2025
+ },
2026
+ {
2027
+ "@type":"Person",
2028
+ "email":"",
2029
+ "givenName":"Matt",
2030
+ "familyName": "Courtemanche"
2031
+ },
2032
+ {
2033
+ "@type":"Person",
2034
+ "email":"matt.tucker@nyu.edu",
2035
+ "givenName":"Matt",
2036
+ "familyName": "Tucker"
2037
+ },
2038
+ {
2039
+ "@type":"Person",
2040
+ "email":"matteo.visconti.gr@dartmouth.edu",
2041
+ "givenName":"Matteo",
2042
+ "familyName": "Visconti di Oleggio Castello"
2043
+ },
2044
+ {
2045
+ "@type":"Person",
2046
+ "email":"matthias.dold@gmx.net",
2047
+ "givenName":"Matthias",
2048
+ "familyName": "Dold"
2049
+ },
2050
+ {
2051
+ "@type":"Person",
2052
+ "email":"",
2053
+ "givenName":"Matti",
2054
+ "familyName": "Toivonen"
2055
+ },
2056
+ {
2057
+ "@type":"Person",
2058
+ "email":"",
2059
+ "givenName":"Maureen",
2060
+ "familyName": "Shader"
2061
+ },
2062
+ {
2063
+ "@type":"Person",
2064
+ "email":"",
2065
+ "givenName":"Mauricio",
2066
+ "familyName": "Cespedes"
2067
+ },
2068
+ {
2069
+ "@type":"Person",
2070
+ "email":"krause@mpib-berlin.mpg.de",
2071
+ "givenName":"Michael",
2072
+ "familyName": "Krause"
2073
+ },
2074
+ {
2075
+ "@type":"Person",
2076
+ "email":"kontakt@milanrybar.cz",
2077
+ "givenName":"Milan",
2078
+ "familyName": "Rybář"
2079
+ },
2080
+ {
2081
+ "@type":"Person",
2082
+ "email":"",
2083
+ "givenName":"Mingjian",
2084
+ "familyName": "He"
2085
+ },
2086
+ {
2087
+ "@type":"Person",
2088
+ "email":"",
2089
+ "givenName":"Mohammad",
2090
+ "familyName": "Daneshzand"
2091
+ },
2092
+ {
2093
+ "@type":"Person",
2094
+ "email":"23111220065@m.fudan.edu.cn",
2095
+ "givenName":"",
2096
+ "familyName": "Mojackhak"
2097
+ },
2098
+ {
2099
+ "@type":"Person",
2100
+ "email":"celicolimmo@free.fr",
2101
+ "givenName":"Nicolas",
2102
+ "familyName": "Fourcaud-Trocmé"
2103
+ },
2104
+ {
2105
+ "@type":"Person",
2106
+ "email":"nicolas.gensollen@gmail.com",
2107
+ "givenName":"Nicolas",
2108
+ "familyName": "Gensollen"
2109
+ },
2110
+ {
2111
+ "@type":"Person",
2112
+ "email":"nh.proulx@gmail.com",
2113
+ "givenName":"Nicole",
2114
+ "familyName": "Proulx"
2115
+ },
2116
+ {
2117
+ "@type":"Person",
2118
+ "email":"nfocke@uni-goettingen.de",
2119
+ "givenName":"Niels",
2120
+ "familyName": "Focke"
2121
+ },
2122
+ {
2123
+ "@type":"Person",
2124
+ "email":"nikos.ch01@gmail.com",
2125
+ "givenName":"Nikolas",
2126
+ "familyName": "Chalas"
2127
+ },
2128
+ {
2129
+ "@type":"Person",
2130
+ "email":"",
2131
+ "givenName":"Noah",
2132
+ "familyName": "Markowitz"
2133
+ },
2134
+ {
2135
+ "@type":"Person",
2136
+ "email":"omer.shubi@gmail.com",
2137
+ "givenName":"Omer",
2138
+ "familyName": "Shubi"
2139
+ },
2140
+ {
2141
+ "@type":"Person",
2142
+ "email":"pablomainar.pm@gmail.com",
2143
+ "givenName":"Pablo",
2144
+ "familyName": "Mainar"
2145
+ },
2146
+ {
2147
+ "@type":"Person",
2148
+ "email":"tottochan@gmail.com",
2149
+ "givenName":"Padma",
2150
+ "familyName": "Sundaram"
2151
+ },
2152
+ {
2153
+ "@type":"Person",
2154
+ "email":"",
2155
+ "givenName":"Paul",
2156
+ "familyName": "Anders"
2157
+ },
2158
+ {
2159
+ "@type":"Person",
2160
+ "email":"pedrobnsilva@gmail.com",
2161
+ "givenName":"Pedro",
2162
+ "familyName": "Silva"
2163
+ },
2164
+ {
2165
+ "@type":"Person",
2166
+ "email":"",
2167
+ "givenName":"Pierre",
2168
+ "familyName": "Guetschel"
2169
+ },
2170
+ {
2171
+ "@type":"Person",
2172
+ "email":"glia@dtu.dk",
2173
+ "givenName":"Quanliang",
2174
+ "familyName": "Li"
2175
+ },
2176
+ {
2177
+ "@type":"Person",
2178
+ "email":"q.barthelemy@gmail.com",
2179
+ "givenName":"Quentin",
2180
+ "familyName": "Barthélemy"
2181
+ },
2182
+ {
2183
+ "@type":"Person",
2184
+ "email":"rahuln@cs.washington.edu",
2185
+ "givenName":"Rahul",
2186
+ "familyName": "Nadkarni"
2187
+ },
2188
+ {
2189
+ "@type":"Person",
2190
+ "email":"rmrgatti@gmail.com",
2191
+ "givenName":"Ramiro",
2192
+ "familyName": "Gatti"
2193
+ },
2194
+ {
2195
+ "@type":"Person",
2196
+ "email":"moncho_apa@hotmail.com",
2197
+ "givenName":"Ramonapariciog",
2198
+ "familyName": "Apariciogarcia"
2199
+ },
2200
+ {
2201
+ "@type":"Person",
2202
+ "email":"raagaard97@gmail.com",
2203
+ "givenName":"Rasmus",
2204
+ "familyName": "Aagaard"
2205
+ },
2206
+ {
2207
+ "@type":"Person",
2208
+ "email":"reza@ddpo.ir",
2209
+ "givenName":"Reza",
2210
+ "familyName": "Nasri"
2211
+ },
2212
+ {
2213
+ "@type":"Person",
2214
+ "email":"richard.koehler@outlook.de",
2215
+ "givenName":"Richard",
2216
+ "familyName": "Koehler"
2217
+ },
2218
+ {
2219
+ "@type":"Person",
2220
+ "email":"rie.acad@gmail.com",
2221
+ "givenName":"Riessarius",
2222
+ "familyName": "Stargardsky"
2223
+ },
2224
+ {
2225
+ "@type":"Person",
2226
+ "email":"r.oostenveld@gmail.com",
2227
+ "givenName":"Robert",
2228
+ "familyName": "Oostenveld"
2229
+ },
2230
+ {
2231
+ "@type":"Person",
2232
+ "email":"robbyseymour@gmail.com",
2233
+ "givenName":"Robert",
2234
+ "familyName": "Seymour"
2235
+ },
2236
+ {
2237
+ "@type":"Person",
2238
+ "email":"robintibor@gmail.com",
2239
+ "givenName":"Robin Tibor",
2240
+ "familyName": "Schirrmeister"
2241
+ },
2242
+ {
2243
+ "@type":"Person",
2244
+ "email":"131315c@gmail.com",
2245
+ "givenName":"Rongfei",
2246
+ "familyName": "Jin"
2247
+ },
2248
+ {
2249
+ "@type":"Person",
2250
+ "email":"",
2251
+ "givenName":"Roy Eric",
2252
+ "familyName": "Wieske"
2253
+ },
2254
+ {
2255
+ "@type":"Person",
2256
+ "email":"ryan.law@mpi.nl",
2257
+ "givenName":"Ryan",
2258
+ "familyName": "Law"
2259
+ },
2260
+ {
2261
+ "@type":"Person",
2262
+ "email":"sagung.pai@gmail.com",
2263
+ "givenName":"Sagun",
2264
+ "familyName": "Pai"
2265
+ },
2266
+ {
2267
+ "@type":"Person",
2268
+ "email":"u1265119@unimail.hud.ac.uk",
2269
+ "givenName":"Sam",
2270
+ "familyName": "Perry"
2271
+ },
2272
+ {
2273
+ "@type":"Person",
2274
+ "email":"",
2275
+ "givenName":"Samuel",
2276
+ "familyName": "Louviot"
2277
+ },
2278
+ {
2279
+ "@type":"Person",
2280
+ "email":"santiaguzz@gmail.com",
2281
+ "givenName":"Santi",
2282
+ "familyName": "Martínez"
2283
+ },
2284
+ {
2285
+ "@type":"Person",
2286
+ "email":"",
2287
+ "givenName":"Sawradip",
2288
+ "familyName": "Saha"
2289
+ },
2290
+ {
2291
+ "@type":"Person",
2292
+ "email":"s.mathot@cogsci.nl",
2293
+ "givenName":"Sebastiaan",
2294
+ "familyName": "Mathot"
2295
+ },
2296
+ {
2297
+ "@type":"Person",
2298
+ "email":"",
2299
+ "givenName":"Sebastian",
2300
+ "familyName": "Jentschke"
2301
+ },
2302
+ {
2303
+ "@type":"Person",
2304
+ "email":"",
2305
+ "givenName":"Sebastian",
2306
+ "familyName": "Major"
2307
+ },
2308
+ {
2309
+ "@type":"Person",
2310
+ "email":"sfox@riseup.net",
2311
+ "givenName":"Sebastien",
2312
+ "familyName": "Treguer"
2313
+ },
2314
+ {
2315
+ "@type":"Person",
2316
+ "email":"sebastian.castano@blbt.uni-freiburg.de",
2317
+ "givenName":"Sebastián",
2318
+ "familyName": "Castaño"
2319
+ },
2320
+ {
2321
+ "@type":"Person",
2322
+ "email":"",
2323
+ "givenName":"Senwen",
2324
+ "familyName": "Deng"
2325
+ },
2326
+ {
2327
+ "@type":"Person",
2328
+ "email":"s.antopolsky@gmail.com",
2329
+ "givenName":"Sergey",
2330
+ "familyName": "Antopolskiy"
2331
+ },
2332
+ {
2333
+ "@type":"Person",
2334
+ "email":"shirazi@ieee.org",
2335
+ "givenName":"Seyed (Yahya)",
2336
+ "familyName": "Shirazi"
2337
+ },
2338
+ {
2339
+ "@type":"Person",
2340
+ "email":"kesharishresth5@gmail.com",
2341
+ "givenName":"Shresth",
2342
+ "familyName": "Keshari"
2343
+ },
2344
+ {
2345
+ "@type":"Person",
2346
+ "email":"baral.shristi@gmail.com",
2347
+ "givenName":"Shristi",
2348
+ "familyName": "Baral"
2349
+ },
2350
+ {
2351
+ "@type":"Person",
2352
+ "email":"baralshristi@gmail.com",
2353
+ "givenName":"Shristi",
2354
+ "familyName": "Baral"
2355
+ },
2356
+ {
2357
+ "@type":"Person",
2358
+ "email":"",
2359
+ "givenName":"Simeon",
2360
+ "familyName": "Wong"
2361
+ },
2362
+ {
2363
+ "@type":"Person",
2364
+ "email":"",
2365
+ "givenName":"Simeon",
2366
+ "familyName": "Wong"
2367
+ },
2368
+ {
2369
+ "@type":"Person",
2370
+ "email":"",
2371
+ "givenName":"Simon M",
2372
+ "familyName": "Hofmann"
2373
+ },
2374
+ {
2375
+ "@type":"Person",
2376
+ "email":"",
2377
+ "givenName":"Simon-Shlomo",
2378
+ "familyName": "Poil"
2379
+ },
2380
+ {
2381
+ "@type":"Person",
2382
+ "email":"sondre.foslien@gmail.com",
2383
+ "givenName":"Sondre",
2384
+ "familyName": "Foslien"
2385
+ },
2386
+ {
2387
+ "@type":"Person",
2388
+ "email":"",
2389
+ "givenName":"Sourav",
2390
+ "familyName": "Singh"
2391
+ },
2392
+ {
2393
+ "@type":"Person",
2394
+ "email":"stan.chambon@gmail.com",
2395
+ "givenName":"Stanislas",
2396
+ "familyName": "Chambon"
2397
+ },
2398
+ {
2399
+ "@type":"Person",
2400
+ "email":"",
2401
+ "givenName":"Steinn Hauser",
2402
+ "familyName": "Magnússon"
2403
+ },
2404
+ {
2405
+ "@type":"Person",
2406
+ "email":"bethard@email.arizona.edu",
2407
+ "givenName":"Steven",
2408
+ "familyName": "Bethard"
2409
+ },
2410
+ {
2411
+ "@type":"Person",
2412
+ "email":"s.m.gutstein@gmail.com",
2413
+ "givenName":"Steven M",
2414
+ "familyName": "Gutstein"
2415
+ },
2416
+ {
2417
+ "@type":"Person",
2418
+ "email":"",
2419
+ "givenName":"Svea Marie",
2420
+ "familyName": "Meyer"
2421
+ },
2422
+ {
2423
+ "@type":"Person",
2424
+ "email":"twang5@swarthmore.edu",
2425
+ "givenName":"T",
2426
+ "familyName": "Wang"
2427
+ },
2428
+ {
2429
+ "@type":"Person",
2430
+ "email":"tharupahanjayawardana@gmail.com",
2431
+ "givenName":"Tharupahan",
2432
+ "familyName": "Jayawardana"
2433
+ },
2434
+ {
2435
+ "@type":"Person",
2436
+ "email":"thomas.moreau.2010@gmail.com",
2437
+ "givenName":"Thomas",
2438
+ "familyName": "Moreau"
2439
+ },
2440
+ {
2441
+ "@type":"Person",
2442
+ "email":"radman.thomas@gmail.com",
2443
+ "givenName":"Thomas",
2444
+ "familyName": "Radman"
2445
+ },
2446
+ {
2447
+ "@type":"Person",
2448
+ "email":"tim.gates@iress.com",
2449
+ "givenName":"Timothy",
2450
+ "familyName": "Gates"
2451
+ },
2452
+ {
2453
+ "@type":"Person",
2454
+ "email":"TASTONE@mgh.harvard.edu",
2455
+ "givenName":"Tom",
2456
+ "familyName": "Stone"
2457
+ },
2458
+ {
2459
+ "@type":"Person",
2460
+ "email":"",
2461
+ "givenName":"Tommy",
2462
+ "familyName": "Clausner"
2463
+ },
2464
+ {
2465
+ "@type":"Person",
2466
+ "email":"toomaserikanijarv@gmail.com",
2467
+ "givenName":"Toomas Erik",
2468
+ "familyName": "Anijärv"
2469
+ },
2470
+ {
2471
+ "@type":"Person",
2472
+ "email":"",
2473
+ "givenName":"Velu Prabhakar",
2474
+ "familyName": "Kumaravel"
2475
+ },
2476
+ {
2477
+ "@type":"Person",
2478
+ "email":"weixu@mail.bnu.edu.cn",
2479
+ "givenName":"Wei",
2480
+ "familyName": "Xu"
2481
+ },
2482
+ {
2483
+ "@type":"Person",
2484
+ "email":"williamfrancisturner@gmail.com",
2485
+ "givenName":"Will",
2486
+ "familyName": "Turner"
2487
+ },
2488
+ {
2489
+ "@type":"Person",
2490
+ "email":"xabier@zuazo.org",
2491
+ "givenName":"Xabier de",
2492
+ "familyName": "Zuazo"
2493
+ },
2494
+ {
2495
+ "@type":"Person",
2496
+ "email":"xia@xiaokai.me",
2497
+ "givenName":"Xiaokai",
2498
+ "familyName": "Xia"
2499
+ },
2500
+ {
2501
+ "@type":"Person",
2502
+ "email":"frostime@foxmail.com",
2503
+ "givenName":"Yiping",
2504
+ "familyName": "Zuo"
2505
+ },
2506
+ {
2507
+ "@type":"Person",
2508
+ "email":"",
2509
+ "givenName":"Yixiao",
2510
+ "familyName": "Shen"
2511
+ },
2512
+ {
2513
+ "@type":"Person",
2514
+ "email":"",
2515
+ "givenName":"Young",
2516
+ "familyName": "Truong"
2517
+ },
2518
+ {
2519
+ "@type":"Person",
2520
+ "email":"850734033@qq.com",
2521
+ "givenName":"Zhi",
2522
+ "familyName": "Zhang"
2523
+ },
2524
+ {
2525
+ "@type":"Person",
2526
+ "email":"ziyizeng@link.cuhk.edu.cn",
2527
+ "givenName":"Ziyi",
2528
+ "familyName": "ZENG"
2529
+ },
2530
+ {
2531
+ "@type":"Person",
2532
+ "email":"btk.codedev@gmail.com",
2533
+ "givenName":"",
2534
+ "familyName": "btkcodedev"
2535
+ },
2536
+ {
2537
+ "@type":"Person",
2538
+ "email":"",
2539
+ "givenName":"",
2540
+ "familyName": "buildqa"
2541
+ },
2542
+ {
2543
+ "@type":"Person",
2544
+ "email":"",
2545
+ "givenName":"",
2546
+ "familyName": "luzpaz"
2547
+ },
2548
+ {
2549
+ "@type":"Person",
2550
+ "email":"",
2551
+ "givenName":"",
2552
+ "familyName": "user27182"
2553
+ }
2554
+ ]
2555
+ }
mne-python/source/doc/Makefile ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Makefile for Sphinx documentation
2
+ #
3
+
4
+ # You can set these variables from the command line.
5
+ SPHINXOPTS = -nWT --keep-going
6
+ SPHINXBUILD = sphinx-build
7
+ MPROF = SG_STAMP_STARTS=true mprof run -E --python sphinx
8
+
9
+ # Internal variables.
10
+ ALLSPHINXOPTS = -d _build/doctrees $(SPHINXOPTS) .
11
+
12
+ .PHONY: help clean html html-noplot html-pattern linkcheck linkcheck-grep doctest
13
+
14
+ # make with no arguments will build the first target by default, i.e., build standalone HTML files
15
+ first_target: html-noplot
16
+
17
+ help:
18
+ @echo "Please use \`make <target>' where <target> is one of"
19
+ @echo " html to make standalone HTML files"
20
+ @echo " html-memory to make standalone HTML files while monitoring memory usage"
21
+ @echo " html-pattern to make standalone HTML files for a specific filename pattern"
22
+ @echo " html-front to make standalone HTML files with only the frontpage examples"
23
+ @echo " html-noplot to make standalone HTML files without plotting"
24
+ @echo " clean to clean HTML files"
25
+ @echo " linkcheck to check all external links for integrity"
26
+ @echo " linkcheck-grep to grep the linkcheck result"
27
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
28
+ @echo " view to view the built HTML"
29
+
30
+ clean:
31
+ -rm -rf _build sg_execution_times.rst auto_examples auto_tutorials generated *.stc *.fif *.nii.gz
32
+
33
+ html:
34
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html
35
+ @echo
36
+ @echo "Build finished. The HTML pages are in _build/html."
37
+
38
+ html-memory:
39
+ $(MPROF) -b html $(ALLSPHINXOPTS) _build/html
40
+ @echo
41
+ @echo "Build finished. The HTML pages are in _build/html."
42
+
43
+ html-pattern:
44
+ $(SPHINXBUILD) -D sphinx_gallery_conf.filename_pattern=$(PATTERN) -D sphinx_gallery_conf.run_stale_examples=True -b html $(ALLSPHINXOPTS) _build/html
45
+ @echo
46
+ @echo "Build finished. The HTML pages are in _build/html"
47
+
48
+ html-pattern-memory:
49
+ $(MPROF) -D sphinx_gallery_conf.filename_pattern=$(PATTERN) -D sphinx_gallery_conf.run_stale_examples=True -b html $(ALLSPHINXOPTS) _build/html
50
+ @echo
51
+ @echo "Build finished. The HTML pages are in _build/html"
52
+
53
+ html-noplot:
54
+ $(SPHINXBUILD) -D plot_gallery=0 -b html $(ALLSPHINXOPTS) _build/html
55
+ @echo
56
+ @echo "Build finished. The HTML pages are in _build/html."
57
+
58
+ html-front:
59
+ @PATTERN="\(30_mne_dspm_loreta.py\|50_decoding.py\|30_strf.py\|20_cluster_1samp_spatiotemporal.py\|20_visualize_evoked.py\)" make html-pattern
60
+
61
+ # Aliases for old methods
62
+ html_dev-pattern-memory: html-pattern-memory
63
+ html_dev-pattern: html-pattern
64
+ html_dev-noplot: html-noplot
65
+ html_dev-front: html-front
66
+
67
+ linkcheck:
68
+ @$(SPHINXBUILD) -b linkcheck -D nitpicky=0 -q -D plot_gallery=0 -D exclude_patterns="cited.rst,whats_new.rst,configure_git.rst,_includes,changes/dev" -d _build/doctrees . _build/linkcheck
69
+
70
+ doctest:
71
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) _build/doctest
72
+ @echo "Testing of doctests in the sources finished, look at the " \
73
+ "results in _build/doctest/output.txt."
74
+
75
+ view:
76
+ @python -c "import webbrowser; webbrowser.open_new_tab('file://$(PWD)/_build/html/sg_execution_times.html')"
77
+
78
+ show: view
79
+
80
+ serve:
81
+ python -m http.server -d _build/html
mne-python/source/doc/_includes/bem_model.rst ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :orphan:
2
+
3
+ Creating the BEM meshes
4
+ =======================
5
+
6
+ .. NOTE: part of this file is included in doc/overview/implementation.rst.
7
+ Changes here are reflected there. If you want to link to this content, link
8
+ to :ref:`bem-model` to link to that section of the implementation.rst page.
9
+ The next line is a target for :start-after: so we can omit the title from
10
+ the include:
11
+ bem-begin-content
12
+
13
+ .. _bem_watershed_algorithm:
14
+
15
+ Using the watershed algorithm
16
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17
+
18
+ The watershed algorithm [Segonne *et al.*,
19
+ 2004] is part of the FreeSurfer software.
20
+ The name of the program is mri_watershed_.
21
+ Its use in the MNE environment is facilitated by the script
22
+ :ref:`mne watershed_bem`.
23
+
24
+ After ``mne watershed_bem`` has completed, the following files appear in the
25
+ subject's :file:`bem/watershed` directory:
26
+
27
+ - :file:`{<subject>}_brain_surface` contains the brain surface triangulation.
28
+
29
+ - :file:`{<subject>}_inner_skull_surface` contains the inner skull
30
+ triangulation.
31
+
32
+ - :file:`{<subject>}_outer_skull_surface` contains the outer skull
33
+ triangulation.
34
+
35
+ - :file:`{<subject>}_outer_skin_surface` contains the scalp triangulation.
36
+
37
+ All of these surfaces are in the FreeSurfer format. In addition, there will be
38
+ a file called :file:`bem/watershed/ws.mgz` which contains the brain MRI
39
+ volume. Furthermore, ``mne watershed_bem`` script converts the scalp surface to
40
+ fif format and saves the result to :file:`bem/{<subject>}-head.fif`.
41
+
42
+ .. _bem_flash_algorithm:
43
+
44
+ Using FLASH images
45
+ ~~~~~~~~~~~~~~~~~~
46
+
47
+ This method depends on the availablily of MRI data acquired with a multi-echo
48
+ FLASH sequence at two flip angles (5 and 30 degrees). These data can be
49
+ acquired separately from the MPRAGE data employed in FreeSurfer cortical
50
+ reconstructions but it is strongly recommended that they are collected at the
51
+ same time with the MPRAGEs or at least with the same scanner. For easy
52
+ co-registration, the images should have FOV, matrix, slice thickness, gap, and
53
+ slice orientation as the MPRAGE data. For information on suitable pulse
54
+ sequences, see :footcite:t:`FischlEtAl2004`.
55
+
56
+ Creation of the BEM meshes using this method involves the following steps:
57
+
58
+ - Creating a synthetic 5-degree flip angle FLASH volume, register
59
+ it with the MPRAGE data, and run the segmentation and meshing program.
60
+ This step is accomplished by running the script :ref:`mne flash_bem`.
61
+
62
+ - Inspecting the meshes with tkmedit, see :ref:`inspecting-meshes`.
63
+
64
+ .. note:: Different methods can be employed for the creation of the
65
+ individual surfaces. For example, it may turn out that the
66
+ watershed algorithm produces are better quality skin surface than
67
+ the segmentation approach based on the FLASH images. If this is
68
+ the case, ``outer_skin.surf`` can set to point to the corresponding
69
+ watershed output file while the other surfaces can be picked from
70
+ the FLASH segmentation data.
71
+
72
+
73
+ Organizing MRI data into directories
74
+ ------------------------------------
75
+
76
+ Since all images comprising the multi-echo FLASH data are contained in a single
77
+ series, it is necessary to organize the images according to the echoes before
78
+ proceeding to the BEM surface reconstruction. This can be accomplished by using
79
+ `dcm2niix <https://www.nitrc.org/plugins/mwiki/index.php/dcm2nii:MainPage>`__
80
+ or the MNE-C tool ``mne_organize_dicom`` if necessary, then use
81
+ :func:`mne.bem.convert_flash_mris`.
82
+
83
+ Creating the surface tessellations
84
+ ----------------------------------
85
+
86
+ The BEM surface segmentation and tessellation is automated with the script
87
+ :ref:`mne flash_bem`. It assumes that a FreeSurfer reconstruction for this
88
+ subject is already in place.
89
+
90
+ Before running :ref:`mne flash_bem` do the following:
91
+
92
+ - Create symbolic links from the directories containing the 5-degree and
93
+ 30-degree flip angle FLASH series to ``flash05`` and ``flash30``,
94
+ respectively:
95
+
96
+ - :samp:`ln -s {<FLASH 5 series dir>} flash05`
97
+
98
+ - :samp:`ln -s {<FLASH 30 series dir>} flash30`
99
+
100
+ - Some partition formats (e.g. FAT32) do not support symbolic links. In this
101
+ case, copy the file to the appropriate series:
102
+
103
+ - :samp:`cp {<FLASH 5 series dir>} flash05`
104
+
105
+ - :samp:`cp {<FLASH 30 series dir>} flash30`
106
+
107
+ - Set the ``SUBJECTS_DIR`` and ``SUBJECT`` environment variables or pass
108
+ the ``--subjects-dir`` and ``--subject`` options to ``mne flash_bem``
109
+
110
+ .. note:: If ``mne flash_bem`` is run with the ``--noflash30`` option, the
111
+ :file:`flash30` directory is not needed, *i.e.*, only the 5-degree flip
112
+ angle flash data are employed.
113
+
114
+ It may take a while for ``mne flash_bem`` to complete. It uses the FreeSurfer
115
+ directory structure under ``$SUBJECTS_DIR/$SUBJECT``. The script encapsulates
116
+ the following processing steps:
117
+
118
+ - It creates an mgz file corresponding to each of the eight echoes in each of
119
+ the FLASH directories in ``mri/flash``. The files will be called
120
+ :file:`mef {<flip-angle>}_{<echo-number>}.mgz`.
121
+
122
+ - If the ``unwarp=True`` option is specified, run grad_unwarp and produce
123
+ files :file:`mef {<flip-angle>}_{<echo-number>}u.mgz`. These files will be
124
+ then used in the following steps.
125
+
126
+ - It creates parameter maps in :file:`mri/flash/parameter_maps` using
127
+ ``mri_ms_fitparms``.
128
+
129
+ - It creates a synthetic 5-degree flip angle volume in
130
+ :file:`mri/flash/parameter_maps/flash5.mgz` using ``mri_synthesize``.
131
+
132
+ - Using ``fsl_rigid_register``, it creates a registered 5-degree flip angle
133
+ volume ``mri/flash/parameter_maps/flash5_reg.mgz`` by registering
134
+ :file:`mri/flash/parameter_maps/flash5.mgz` to the *T1* volume under ``mri``.
135
+
136
+ - Using ``mri_convert``, it converts the flash5_reg volume to COR format under
137
+ ``mri/flash5``. If necessary, the T1 and brain volumes are also converted
138
+ into the COR format.
139
+
140
+ - It runs ``mri_make_bem_surfaces`` to create the BEM surface tessellations.
141
+
142
+ - It creates the directory :file:`bem/flash`, moves the tri-format
143
+ tringulations there and creates the corresponding FreeSurfer surface files
144
+ in the same directory.
145
+
146
+ - The COR format volumes created by ``mne flash_bem`` are removed.
147
+
148
+ If the ``--noflash30`` option is specified to ``mne flash_bem``,
149
+ steps 3 and 4 in the above are replaced by averaging over the different
150
+ echo times in 5-degree flip angle data.
151
+
152
+ .. _inspecting-meshes:
153
+
154
+ Inspecting the meshes
155
+ ---------------------
156
+
157
+ It is advisable to check the validity of the BEM meshes before
158
+ using them. This can be done with:
159
+
160
+ - the ``--view`` option of :ref:`mne flash_bem`
161
+ - calling :func:`mne.viz.plot_bem` directly
162
+ - Using FreeSurfer tools ``tkmedit`` or ``freeview``
mne-python/source/doc/_includes/channel_interpolation.rst ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :orphan:
2
+
3
+ Bad channel repair via interpolation
4
+ ====================================
5
+
6
+ Spherical spline interpolation (EEG)
7
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8
+
9
+ .. NOTE: part of this file is included in doc/overview/implementation.rst.
10
+ Changes here are reflected there. If you want to link to this content, link
11
+ to :ref:`channel-interpolation` to link to that section of the
12
+ implementation.rst page. The next line is a target for :start-after: so we
13
+ can omit the title from the include:
14
+ channel-interpolation-begin-content
15
+
16
+ In short, data repair using spherical spline interpolation :footcite:`PerrinEtAl1989` consists of the following steps:
17
+
18
+ * Project the good and bad electrodes onto a unit sphere
19
+ * Compute a mapping matrix that maps :math:`N` good channels to :math:`M` bad channels
20
+ * Use this mapping matrix to compute interpolated data in the bad channels
21
+
22
+ Spherical splines assume that the potential :math:`V(\boldsymbol{r_i})` at any point :math:`\boldsymbol{r_i}` on the surface of the sphere can be represented by:
23
+
24
+ .. math:: V(\boldsymbol{r_i}) = c_0 + \sum_{j=1}^{N}c_{i}g_{m}(cos(\boldsymbol{r_i}, \boldsymbol{r_{j}}))
25
+ :name: model
26
+
27
+ where the :math:`C = (c_{1}, ..., c_{N})^{T}` are constants which must be estimated. The function :math:`g_{m}(\cdot)` of order :math:`m` is given by:
28
+
29
+ .. math:: g_{m}(x) = \frac{1}{4 \pi}\sum_{n=1}^{\infty} \frac{2n + 1}{(n(n + 1))^m}P_{n}(x)
30
+
31
+ where :math:`P_{n}(x)` are `Legendre polynomials`_ of order :math:`n`.
32
+
33
+ .. _Legendre polynomials: https://en.wikipedia.org/wiki/Legendre_polynomials
34
+
35
+ To estimate the constants :math:`C`, we must solve the following two equations simultaneously:
36
+
37
+ .. math:: G_{ss}C + T_{s}c_0 = X
38
+ :name: matrix_form
39
+
40
+ .. math:: {T_s}^{T}C = 0
41
+ :name: constraint
42
+
43
+ where :math:`G_{ss} \in R^{N \times N}` is a matrix whose entries are :math:`G_{ss}[i, j] = g_{m}(cos(\boldsymbol{r_i}, \boldsymbol{r_j}))` and :math:`X \in R^{N \times 1}` are the potentials :math:`V(\boldsymbol{r_i})` measured at the good channels. :math:`T_{s} = (1, 1, ..., 1)^\top` is a column vector of dimension :math:`N`. Equation :eq:`matrix_form` is the matrix formulation of Equation :eq:`model` and equation :eq:`constraint` is like applying an average reference to the data. From equation :eq:`matrix_form` and :eq:`constraint`, we get:
44
+
45
+ .. math:: \begin{bmatrix} c_0 \\ C \end{bmatrix} = {\begin{bmatrix} {T_s}^{T} && 0 \\ T_s && G_{ss} \end{bmatrix}}^{-1} \begin{bmatrix} 0 \\ X \end{bmatrix} = C_{i}X
46
+ :name: estimate_constant
47
+
48
+ :math:`C_{i}` is the same as matrix :math:`{\begin{bmatrix} {T_s}^{T} && 0 \\ T_s && G_{ss} \end{bmatrix}}^{-1}` but with its first column deleted, therefore giving a matrix of dimension :math:`(N + 1) \times N`.
49
+
50
+ Now, to estimate the potentials :math:`\hat{X} \in R^{M \times 1}` at the bad channels, we have to do:
51
+
52
+ .. math:: \hat{X} = G_{ds}C + T_{d}c_0
53
+ :name: estimate_data
54
+
55
+ where :math:`G_{ds} \in R^{M \times N}` computes :math:`g_{m}(\boldsymbol{r_i}, \boldsymbol{r_j})` between the bad and good channels. :math:`T_{d} = (1, 1, ..., 1)^\top` is a column vector of dimension :math:`M`. Plugging in equation :eq:`estimate_constant` in :eq:`estimate_data`, we get
56
+
57
+ .. math:: \hat{X} = \begin{bmatrix} T_d && G_{ds} \end{bmatrix} \begin{bmatrix} c_0 \\ C \end{bmatrix} = \underbrace{\begin{bmatrix} T_d && G_{ds} \end{bmatrix} C_{i}}_\text{mapping matrix}X
58
+
59
+
60
+ To interpolate bad channels, one can simply do:
61
+
62
+ >>> evoked.interpolate_bads(reset_bads=False) # doctest: +SKIP
63
+
64
+ and the bad channel will be fixed.
65
+
66
+ .. target for :end-before: channel-interpolation-end-content
67
+
68
+ .. topic:: Examples:
69
+
70
+ * :ref:`ex-interpolate-bad-channels`
mne-python/source/doc/_includes/channel_types.rst ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :orphan:
2
+
3
+ Supported channel types
4
+ =======================
5
+
6
+ .. NOTE: part of this file is included in doc/overview/implementation.rst.
7
+ Changes here are reflected there. If you want to link to this content, link
8
+ to :ref:`channel-types` to link to that section of the implementation.rst
9
+ page. The next line is a target for :start-after: so we can omit the title
10
+ from the include:
11
+ channel-types-begin-content
12
+
13
+ .. NOTE: In the future, this table should be automatically synchronized with
14
+ the sensor types listed in the glossary. Perhaps a table showing data type
15
+ channels as well as non-data type channels should be added to the glossary
16
+ and displayed here too.
17
+
18
+ Channel types are represented in MNE-Python with shortened or abbreviated
19
+ names. This page lists all supported channel types, their abbreviated names,
20
+ and the measurement unit used to represent data of that type. Where channel
21
+ types occur in two or more sub-types, the sub-type abbreviations are given in
22
+ parentheses. More information about measurement units is given in the
23
+ :ref:`units` section.
24
+
25
+ .. NOTE: To include only the table, here's a different target for :start-after:
26
+ channel-types-begin-table
27
+
28
+ .. cssclass:: table-bordered
29
+ .. rst-class:: midvalign
30
+
31
+ ================= ========================================= =================
32
+ Channel type Description Measurement unit
33
+ ================= ========================================= =================
34
+ eeg scalp electroencephalography (EEG) Volts
35
+
36
+ meg (mag) Magnetoencephalography (magnetometers) Teslas
37
+
38
+ meg (grad) Magnetoencephalography (gradiometers) Teslas/meter
39
+
40
+ ecg Electrocardiography (ECG) Volts
41
+
42
+ seeg Stereotactic EEG channels Volts
43
+
44
+ dbs Deep brain stimulation (DBS) Volts
45
+
46
+ ecog Electrocorticography (ECoG) Volts
47
+
48
+ fnirs (hbo) Functional near-infrared spectroscopy Moles/liter
49
+ (oxyhemoglobin)
50
+
51
+ fnirs (hbr) Functional near-infrared spectroscopy Moles/liter
52
+ (deoxyhemoglobin)
53
+
54
+ emg Electromyography (EMG) Volts
55
+
56
+ eog Electrooculography (EOG) Volts
57
+
58
+ bio Miscellaneous biological channels (e.g., Arbitrary units
59
+ skin conductance)
60
+
61
+ stim stimulus (a.k.a. trigger) channels Arbitrary units
62
+
63
+ resp respiration monitoring channel Volts
64
+
65
+ chpi continuous head position indicator Teslas
66
+ (HPI) coil channels
67
+
68
+ exci Flux excitation channel
69
+
70
+ ias Internal Active Shielding data
71
+ (Triux systems only?)
72
+
73
+ syst System status channel information
74
+ (Triux systems only)
75
+
76
+ temperature Temperature Degrees Celsius
77
+
78
+ gsr Galvanic skin response Siemens
79
+
80
+ ref_meg Reference Magnetometers Teslas
81
+
82
+ dipole Dipole amplitude Amperes
83
+
84
+ gof Goodness of fit (GOF) Goodness-of-fit
85
+
86
+ cw-nirs (amp) Continuous-wave functional near-infrared Volts
87
+ spectroscopy (CW-fNIRS) (CW amplitude)
88
+
89
+ fd-nirs (ac amp) Frequency-domain near-infrared Volts
90
+ spectroscopy (FD-NIRS AC amplitude)
91
+
92
+ fd-nirs (phase) Frequency-domain near-infrared Radians
93
+ spectroscopy (FD-NIRS phase)
94
+
95
+ fnirs (od) Functional near-infrared spectroscopy Volts
96
+ (optical density)
97
+
98
+ csd Current source density Volts per square
99
+ meter
100
+
101
+ eyegaze Eye-tracking (gaze position) Arbitrary units
102
+
103
+ pupil Eye-tracking (pupil size) Arbitrary units
104
+ ================= ========================================= =================
mne-python/source/doc/_includes/data_formats.rst ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :orphan:
2
+
3
+ Supported data formats
4
+ ======================
5
+
6
+ .. NOTE: part of this file is included in doc/overview/implementation.rst.
7
+ Changes here are reflected there. If you want to link to this content,
8
+ link to :ref:`data-formats`. The next line is
9
+ a target for :start-after: so we can omit the title above:
10
+ data-formats-begin-content
11
+
12
+ When MNE-Python loads sensor data, the data are stored in a Python object of
13
+ type :class:`mne.io.Raw`. Specialized loading functions are provided for the
14
+ raw data file formats from a variety of equipment manufacturers. All raw data
15
+ input/output functions in MNE-Python are found in :mod:`mne.io` and start
16
+ with :samp:`read_raw_{*}`; see the documentation for each reader function for
17
+ more info on reading specific file types.
18
+
19
+ As seen in the table below, there are also a few formats defined by other
20
+ neuroimaging analysis software packages that are supported (EEGLAB,
21
+ FieldTrip). Like the equipment-specific loading functions, these will also
22
+ return an object of class :class:`~mne.io.Raw`; additional functions are
23
+ available for reading data that has already been epoched or averaged (see
24
+ table).
25
+
26
+ .. NOTE: To include only the table, here's a different target for :start-after:
27
+ data-formats-begin-table
28
+
29
+ .. cssclass:: table-bordered
30
+ .. rst-class:: midvalign
31
+
32
+ ============ ============================================ ========= ===================================
33
+ Data type File format Extension MNE-Python function
34
+ ============ ============================================ ========= ===================================
35
+ MEG :ref:`Artemis123 <import-artemis>` .bin :func:`mne.io.read_raw_artemis123`
36
+
37
+ MEG :ref:`4-D Neuroimaging / BTi <import-bti>` <dir> :func:`mne.io.read_raw_bti`
38
+
39
+ MEG :ref:`CTF <import-ctf>` <dir> :func:`mne.io.read_raw_ctf`
40
+
41
+ MEG and EEG :ref:`Elekta Neuromag <import-neuromag>` .fif :func:`mne.io.read_raw_fif`
42
+
43
+ MEG :ref:`FIL OPM MEG <import-fil>` .bin :func:`mne.io.read_raw_fil`
44
+
45
+ MEG :ref:`KIT <import-kit>` .sqd :func:`mne.io.read_raw_kit`,
46
+ :func:`mne.read_epochs_kit`
47
+
48
+ MEG and EEG :ref:`FieldTrip <import-fieldtrip>` .mat :func:`mne.io.read_raw_fieldtrip`,
49
+ :func:`mne.read_epochs_fieldtrip`,
50
+ :func:`mne.read_evoked_fieldtrip`
51
+
52
+ EEG :ref:`Brainvision <import-bv>` .vhdr :func:`mne.io.read_raw_brainvision`
53
+
54
+ EEG :ref:`Biosemi data format <import-biosemi>` .bdf :func:`mne.io.read_raw_bdf`
55
+
56
+ EEG :ref:`Neuroscan CNT <import-cnt>` .cnt :func:`mne.io.read_raw_cnt`
57
+
58
+ EEG :ref:`European data format <import-edf>` .edf :func:`mne.io.read_raw_edf`
59
+
60
+ EEG :ref:`EEGLAB <import-set>` .set :func:`mne.io.read_raw_eeglab`,
61
+ :func:`mne.read_epochs_eeglab`
62
+
63
+ EEG :ref:`EGI simple binary <import-egi>` .egi :func:`mne.io.read_raw_egi`
64
+
65
+ EEG :ref:`EGI MFF format <import-mff>` .mff :func:`mne.io.read_raw_egi`
66
+
67
+ EEG :ref:`eXimia <import-nxe>` .nxe :func:`mne.io.read_raw_eximia`
68
+
69
+ EEG :ref:`General data format <import-gdf>` .gdf :func:`mne.io.read_raw_gdf`
70
+
71
+ EEG :ref:`Nicolet <import-nicolet>` .data :func:`mne.io.read_raw_nicolet`
72
+
73
+ EEG :ref:`Persyst <import-persyst>` .lay :func:`mne.io.read_raw_persyst`
74
+
75
+ NIRS :ref:`NIRx <import-nirx>` directory :func:`mne.io.read_raw_nirx`
76
+
77
+ NIRS :ref:`BOXY <import-boxy>` directory :func:`mne.io.read_raw_boxy`
78
+
79
+ EYETRACK SR eyelink ASCII files .asc :func:`mne.io.read_raw_eyelink`
80
+
81
+ iEEG MEF3 .mefd :func:`mne.io.read_raw_mef`
82
+
83
+ ============ ============================================ ========= ===================================
84
+
85
+ More details are provided in the tutorials in the :ref:`tut-data-formats`
86
+ section.
mne-python/source/doc/_includes/dig_formats.rst ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :orphan:
2
+
3
+ .. _dig-formats:
4
+
5
+ Supported formats for digitized 3D locations
6
+ ============================================
7
+
8
+ .. NOTE: If you want to link to this content, link to :ref:`dig-formats`
9
+ for the implementation page. The next line is
10
+ a target for :start-after: so we can omit the title above:
11
+ dig-formats-begin-content
12
+
13
+ MNE-Python can load 3D point locations obtained by digitization systems.
14
+ Such files allow to obtain a :class:`montage <mne.channels.DigMontage>`
15
+ that can then be added to :class:`~mne.io.Raw` objects with the
16
+ :meth:`~mne.io.Raw.set_montage`. See the documentation for each reader
17
+ function for more info on reading specific file types.
18
+
19
+ .. NOTE: To include only the table, here's a different target for :start-after:
20
+ dig-formats-begin-table
21
+
22
+ .. cssclass:: table-bordered
23
+ .. rst-class:: midvalign
24
+
25
+ ===================== ================ ==============================================
26
+ Vendor Extension(s) MNE-Python function
27
+ ===================== ================ ==============================================
28
+ Neuromag .fif :func:`mne.channels.read_dig_fif`
29
+
30
+ Polhemus ISOTRAK .hsp, .elp, .eeg :func:`mne.channels.read_dig_polhemus_isotrak`
31
+
32
+ EGI .xml :func:`mne.channels.read_dig_egi`
33
+
34
+ MNE-C .hpts :func:`mne.channels.read_dig_hpts`
35
+
36
+ Brain Products .bvct :func:`mne.channels.read_dig_captrak`
37
+
38
+ Compumedics .dat, .cdt :func:`mne.channels.read_dig_curry`
39
+
40
+ Compumedics (legacy) .dat :func:`mne.channels.read_dig_dat`
41
+ ===================== ================ ==============================================
42
+
43
+ To load Polhemus FastSCAN files you can use
44
+ :func:`montage <mne.channels.read_polhemus_fastscan>`.
45
+
46
+ It is also possible to make a :class:`montage <mne.channels.DigMontage>`
47
+ from arrays with :func:`mne.channels.make_dig_montage`.
mne-python/source/doc/_includes/forward.rst ADDED
@@ -0,0 +1,726 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :orphan:
2
+
3
+ The forward solution
4
+ ====================
5
+
6
+ This page covers the definitions of different coordinate systems employed in
7
+ MNE software and FreeSurfer, the details of the computation of the forward
8
+ solutions, and the associated low-level utilities.
9
+
10
+ .. NOTE: part of this file is included in doc/overview/implementation.rst.
11
+ Changes here are reflected there. If you want to link to this content, link
12
+ to :ref:`ch_forward` to link to that section of the implementation.rst page.
13
+ The next line is a target for :start-after: so we can omit the title from
14
+ the include:
15
+ forward-begin-content
16
+
17
+
18
+ .. _coordinate_systems:
19
+
20
+ MEG/EEG and MRI coordinate systems
21
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22
+
23
+ .. note:: Coordinate systems in MNE-Python
24
+ :class: sidebar
25
+
26
+ In some MNE-Python objects (e.g., :class:`~mne.Forward`,
27
+ :class:`~mne.SourceSpaces`, etc), information about the coordinate frame is
28
+ encoded as a constant integer value. The meaning of those integers is
29
+ determined `in the source code
30
+ <https://github.com/mne-tools/mne-python/blob/079c868240a898204bf82b2f1bf0e04cdee75da1/mne/_fiff/constants.py#L263-L275>`__.
31
+
32
+ The coordinate systems used in MNE software (and FreeSurfer) and their
33
+ relationships are depicted in :ref:`coordinate_system_figure`. Except for the
34
+ *sensor coordinates*, all of the coordinate systems are Cartesian and have the
35
+ "RAS" (Right-Anterior-Superior) orientation, *i.e.*, the :math:`x` axis points
36
+ to the right, the :math:`y` axis to the front, and the :math:`z` axis up.
37
+
38
+ .. _coordinate_system_figure:
39
+
40
+ .. figure:: ../_static/CoordinateSystems.png
41
+ :alt: MEG/EEG and MRI coordinate systems
42
+
43
+ MEG/EEG and MRI coordinate systems
44
+
45
+ The coordinate transforms present in the fif files in MNE and the
46
+ FreeSurfer files as well as those set to fixed values are indicated with
47
+ :math:`T_x`, where :math:`x` identifies the transformation.
48
+
49
+ The coordinate systems related to MEG/EEG data are:
50
+
51
+ **Head coordinates**
52
+
53
+ This is a coordinate system defined with help of the fiducial landmarks
54
+ (nasion and the two auricular points). In fif files, EEG electrode
55
+ locations are given in this coordinate system. In addition, the head
56
+ digitization data acquired in the beginning of an MEG, MEG/EEG, or EEG
57
+ acquisition are expressed in head coordinates. For details, see
58
+ :ref:`coordinate_systems`.
59
+
60
+ **Device coordinates**
61
+
62
+ This is a coordinate system tied to the MEG device. The relationship of the
63
+ Device and Head coordinates is determined during an MEG measurement by
64
+ feeding current to three to five head-position indicator (HPI) coils and by
65
+ determining their locations with respect to the MEG sensor array from the
66
+ magnetic fields they generate.
67
+
68
+ **Sensor coordinates**
69
+
70
+ Each MEG sensor has a local coordinate system defining the orientation and
71
+ location of the sensor. With help of this coordinate system, the numerical
72
+ integration data needed for the computation of the magnetic field can be
73
+ expressed conveniently as discussed in :ref:`coil_geometry_information`.
74
+ The channel information data in the fif files contain the information to
75
+ specify the coordinate transformation between the coordinates of each
76
+ sensor and the MEG device coordinates.
77
+
78
+ The coordinate systems related to MRI data are:
79
+
80
+ **Surface RAS coordinates**
81
+
82
+ The FreeSurfer surface data are expressed in this coordinate system. The
83
+ origin of this coordinate system is at the center of the conformed
84
+ FreeSurfer MRI volumes (usually 256 x 256 x 256 isotropic 1-mm3 voxels)
85
+ and the axes are oriented along the axes of this volume. The BEM surface
86
+ and the locations of the sources in the source space are usually expressed
87
+ in this coordinate system in the fif files. In this manual, the *Surface
88
+ RAS coordinates* are usually referred to as *MRI coordinates* unless there
89
+ is need to specifically discuss the different MRI-related coordinate
90
+ systems.
91
+
92
+ **RAS coordinates**
93
+
94
+ This coordinate system has axes identical to the Surface RAS coordinates
95
+ but the location of the origin is different and defined by the original MRI
96
+ data, i.e. , the origin is in a scanner-dependent location. There is hardly
97
+ any need to refer to this coordinate system explicitly in the analysis with
98
+ the MNE software. However, since the Talairach coordinates, discussed
99
+ below, are defined with respect to *RAS coordinates* rather than the
100
+ *Surface RAS coordinates*, the RAS coordinate system is implicitly involved
101
+ in the transformation between Surface RAS coordinates and the two
102
+ *Talairach* coordinate systems.
103
+
104
+ **MNI Talairach coordinates**
105
+
106
+ The definition of this coordinate system is discussed, e.g., in
107
+ https://imaging.mrc-cbu.cam.ac.uk/imaging/MniTalairach. This transformation
108
+ is determined during the FreeSurfer reconstruction process. These
109
+ coordinates are in MNI305 space.
110
+
111
+ **FreeSurfer Talairach coordinates**
112
+
113
+ The problem with the MNI Talairach coordinates is that the linear MNI
114
+ Talairach transform does not match the brains completely to the Talairach
115
+ brain. This is probably because the Talairach atlas brain is a rather odd
116
+ shape, and as a result, it is difficult to match a standard brain to the
117
+ atlas brain using an affine transform. As a result, the MNI brains are
118
+ slightly larger (in particular higher, deeper and longer) than the
119
+ Talairach brain. The differences are larger as you get further from the
120
+ middle of the brain, towards the outside. The FreeSurfer Talairach
121
+ coordinates mitigate this problem by additing a an additional
122
+ transformation, defined separately for negative and positive MNI Talairach
123
+ :math:`z` coordinates. These two transformations, denoted by :math:`T_-`
124
+ and :math:`T_+` in :ref:`coordinate_system_figure`, are fixed as discussed in
125
+ https://imaging.mrc-cbu.cam.ac.uk/imaging/MniTalairach (*Approach 2*).
126
+
127
+ The different coordinate systems are related by coordinate transformations
128
+ depicted in :ref:`coordinate_system_figure`. The arrows and coordinate
129
+ transformation symbols (:math:`T_x`) indicate the transformations actually
130
+ present in the FreeSurfer files. Generally,
131
+
132
+ .. math:: \begin{bmatrix}
133
+ x_2 \\
134
+ y_2 \\
135
+ z_2 \\
136
+ 1
137
+ \end{bmatrix} = T_{12} \begin{bmatrix}
138
+ x_1 \\
139
+ y_1 \\
140
+ z_1 \\
141
+ 1
142
+ \end{bmatrix} = \begin{bmatrix}
143
+ R_{11} & R_{12} & R_{13} & x_0 \\
144
+ R_{21} & R_{22} & R_{23} & y_0 \\
145
+ R_{31} & R_{32} & R_{33} & z_0 \\
146
+ 0 & 0 & 0 & 1
147
+ \end{bmatrix} \begin{bmatrix}
148
+ x_1 \\
149
+ y_1 \\
150
+ z_1 \\
151
+ 1
152
+ \end{bmatrix}\ ,
153
+
154
+ where :math:`x_k`, :math:`y_k`,and :math:`z_k` are the location coordinates in
155
+ two coordinate systems, :math:`T_{12}` is the coordinate transformation from
156
+ coordinate system "1" to "2", :math:`x_0`, :math:`y_0`, and :math:`z_0` is the
157
+ location of the origin of coordinate system "1" in coordinate system "2", and
158
+ :math:`R_{jk}` are the elements of the rotation matrix relating the two
159
+ coordinate systems. The coordinate transformations are present in different
160
+ files produced by FreeSurfer and MNE.
161
+ The fixed transformations :math:`T_-` and :math:`T_+` are:
162
+
163
+ .. math:: T_{-} = \begin{bmatrix}
164
+ 0.99 & 0 & 0 & 0 \\
165
+ 0 & 0.9688 & 0.042 & 0 \\
166
+ 0 & -0.0485 & 0.839 & 0 \\
167
+ 0 & 0 & 0 & 1
168
+ \end{bmatrix}
169
+
170
+ and
171
+
172
+ .. math:: T_{+} = \begin{bmatrix}
173
+ 0.99 & 0 & 0 & 0 \\
174
+ 0 & 0.9688 & 0.046 & 0 \\
175
+ 0 & -0.0485 & 0.9189 & 0 \\
176
+ 0 & 0 & 0 & 1
177
+ \end{bmatrix}
178
+
179
+ .. note::
180
+ This section does not discuss the transformation between the MRI voxel
181
+ indices and the different MRI coordinates. However, it is important to note
182
+ that in FreeSurfer, MNE, as well as in Neuromag software an integer voxel
183
+ coordinate corresponds to the location of the center of a voxel. Detailed
184
+ information on the FreeSurfer MRI systems can be found at
185
+ https://surfer.nmr.mgh.harvard.edu/fswiki/CoordinateSystems.
186
+ The symbols :math:`T_x` are defined in :ref:`coordinate_system_figure`.
187
+
188
+ .. tabularcolumns:: |p{0.2\linewidth}|p{0.3\linewidth}|p{0.5\linewidth}|
189
+ .. table:: Coordinate transformations in FreeSurfer and MNE software packages
190
+
191
+ +------------------------------+-------------------------------+-------------------------------------------------+
192
+ | Transformation | FreeSurfer | MNE |
193
+ +------------------------------+-------------------------------+-------------------------------------------------+
194
+ | :math:`T_1` | Not present | | Measurement data files |
195
+ | | | | Forward solution files (``*fwd.fif``) |
196
+ | | | | Inverse operator files (``*inv.fif``) |
197
+ +------------------------------+-------------------------------+-------------------------------------------------+
198
+ | :math:`T_{s_1}\dots T_{s_n}` | Not present | Channel information in files |
199
+ | | | containing :math:`T_1`. |
200
+ +------------------------------+-------------------------------+-------------------------------------------------+
201
+ | :math:`T_2` | Not present | | MRI description filesSeparate |
202
+ | | | | Separate ``-trans.fif`` files |
203
+ | | | | from :ref:`mne coreg` |
204
+ | | | | Forward solution files |
205
+ | | | | Inverse operator files |
206
+ +------------------------------+-------------------------------+-------------------------------------------------+
207
+ | :math:`T_3` | ``mri/*mgz`` files | :class:`nibabel.freesurfer.mghformat.MGHImage` |
208
+ +------------------------------+-------------------------------+-------------------------------------------------+
209
+ | :math:`T_4` | mri/transforms/talairach.xfm | Internal reading |
210
+ +------------------------------+-------------------------------+-------------------------------------------------+
211
+ | :math:`T_-` | Hardcoded in software | Hardcoded in software. |
212
+ +------------------------------+-------------------------------+-------------------------------------------------+
213
+ | :math:`T_+` | Hardcoded in software | Hardcoded in software. |
214
+ +------------------------------+-------------------------------+-------------------------------------------------+
215
+
216
+ .. _head_device_coords:
217
+
218
+ The head and device coordinate systems
219
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
220
+
221
+ .. figure:: ../_static/HeadCS.png
222
+ :alt: Head coordinate system
223
+
224
+ The head coordinate system
225
+
226
+ The MEG/EEG head coordinate system employed in the MNE software is a
227
+ right-handed Cartesian coordinate system. The direction of :math:`x` axis is
228
+ from left to right, that of :math:`y` axis to the front, and the :math:`z` axis
229
+ thus points up.
230
+
231
+ The :math:`x` axis of the head coordinate system passes through the two
232
+ periauricular or preauricular points digitized before acquiring the data with
233
+ positive direction to the right. The :math:`y` axis passes through the nasion
234
+ and is normal to the :math:`x` axis. The :math:`z` axis points up according to
235
+ the right-hand rule and is normal to the :math:`xy` plane.
236
+
237
+ The origin of the MEG device coordinate system is device dependent. Its origin
238
+ is located approximately at the center of a sphere which fits the occipital
239
+ section of the MEG helmet best with :math:`x` axis axis going from left to
240
+ right and :math:`y` axis pointing front. The :math:`z` axis is, again, normal
241
+ to the :math:`xy` plane with positive direction up.
242
+
243
+ .. note::
244
+ The above definition is identical to that of the Neuromag MEG/EEG (head)
245
+ coordinate system. However, in 4-D Neuroimaging and CTF MEG systems the head
246
+ coordinate frame definition is different. The origin of the coordinate
247
+ system is at the midpoint of the left and right auricular points. The
248
+ :math:`x` axis passes through the nasion and the origin with positive
249
+ direction to the front. The :math:`y` axis is perpendicular to the :math:`x`
250
+ axis on the and lies in the plane defined by the three fiducial landmarks,
251
+ positive direction from right to left. The :math:`z` axis is normal to the
252
+ plane of the landmarks, pointing up. Note that in this convention the
253
+ auricular points are not necessarily located on :math:`y` coordinate axis.
254
+ The file conversion utilities take care of these idiosyncrasies and convert
255
+ all coordinate information to the MNE software head coordinate frame.
256
+
257
+ Creating a surface-based source space
258
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
259
+
260
+ The fif format source space files containing the dipole locations and
261
+ orientations are created with :func:`mne.setup_source_space`.
262
+
263
+ Creating a volumetric or discrete source space
264
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
265
+
266
+ In addition to source spaces confined to a surface, the MNE software provides
267
+ some support for three-dimensional source spaces bounded by a surface as well
268
+ as source spaces comprised of discrete, arbitrarily located source points. The
269
+ :func:`mne.setup_volume_source_space` utility assists in generating such source
270
+ spaces.
271
+
272
+ Creating the BEM meshes
273
+ ~~~~~~~~~~~~~~~~~~~~~~~
274
+
275
+ See :ref:`bem-model`.
276
+
277
+ Topology checks
278
+ ---------------
279
+
280
+ The following topology checks are performed during the creation of BEM models:
281
+
282
+ - The completeness of each surface is confirmed by calculating the total solid
283
+ angle subtended by all triangles from a point inside the triangulation. The
284
+ result should be very close to :math:`4 \pi`. If the result is :math:`-4 \pi`
285
+ instead, it is conceivable that the ordering of the triangle vertices is
286
+ incorrect and the ``--swap`` option should be specified.
287
+
288
+ - The correct ordering of the surfaces is verified by checking that the
289
+ surfaces are inside each other as expected. This is accomplished by checking
290
+ that the sum solid angles subtended by triangles of a surface :math:`S_k` at
291
+ all vertices of another surface :math:`S_p` which is supposed to be inside it
292
+ equals :math:`4 \pi`. Naturally, this check is applied only if the model has
293
+ more than one surface. Since the surface relations are transitive, it is
294
+ enough to check that the outer skull surface is inside the skin surface and
295
+ that the inner skull surface is inside the outer skull one.
296
+
297
+ - The extent of each of the triangulated volumes is checked. If the extent is
298
+ smaller than 50mm, an error is reported. This may indicate that the vertex
299
+ coordinates have been specified in meters instead of millimeters.
300
+
301
+
302
+ Computing the BEM geometry data
303
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
304
+
305
+ The utility :func:`mne.make_bem_solution` computes the geometry information for
306
+ BEM.
307
+
308
+ .. _coil_geometry_information:
309
+
310
+ Coil geometry information
311
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
312
+
313
+ This Section explains the presentation of MEG detection coil geometry
314
+ information the approximations used for different detection coils in MNE
315
+ software. Two pieces of information are needed to characterize the detectors:
316
+
317
+ - The location and orientation a local coordinate system for each detector.
318
+
319
+ - A unique identifier, which has an one-to-one correspondence to the
320
+ geometrical description of the coil.
321
+
322
+ .. note:: MNE ships with several coil geometry configurations. They can be
323
+ found in ``mne/data``. See :ref:`ex-plot-meg-sensors` for a
324
+ comparison between different coil geometries, and
325
+ :ref:`implemented_coil_geometries` for detailed information regarding
326
+ the files describing Neuromag coil geometries.
327
+
328
+
329
+ The sensor coordinate system
330
+ ----------------------------
331
+
332
+ The sensor coordinate system is completely characterized by the location of its
333
+ origin and the direction cosines of three orthogonal unit vectors pointing to
334
+ the directions of the x, y, and z axis. In fact, the unit vectors contain
335
+ redundant information because the orientation can be uniquely defined with
336
+ three angles. The measurement fif files list these data in MEG device
337
+ coordinates. Transformation to the MEG head coordinate frame can be easily
338
+ accomplished by applying the device-to-head coordinate transformation matrix
339
+ available in the data files provided that the head-position indicator was used.
340
+ Optionally, the MNE software forward calculation applies another coordinate
341
+ transformation to the head-coordinate data to bring the coil locations and
342
+ orientations to the MRI coordinate system.
343
+
344
+ If :math:`r_0` is a row vector for the origin of the local sensor coordinate
345
+ system and :math:`e_x`, :math:`e_y`, and :math:`e_z` are the row vectors for
346
+ the three orthogonal unit vectors, all given in device coordinates, a location
347
+ of a point :math:`r_C` in sensor coordinates is transformed to device
348
+ coordinates (:math:`r_D`) by
349
+
350
+ .. math:: [r_D 1] = [r_C 1] T_{CD}\ ,
351
+
352
+ where
353
+
354
+ .. math:: T = \begin{bmatrix}
355
+ e_x & 0 \\
356
+ e_y & 0 \\
357
+ e_z & 0 \\
358
+ r_{0D} & 1
359
+ \end{bmatrix}\ .
360
+
361
+ Calculation of the magnetic field
362
+ ---------------------------------
363
+
364
+ The forward calculation in the MNE software computes the signals detected by
365
+ each MEG sensor for three orthogonal dipoles at each source space location.
366
+ This requires specification of the conductor model, the location and
367
+ orientation of the dipoles, and the location and orientation of each MEG sensor
368
+ as well as its coil geometry.
369
+
370
+ The output of each SQUID sensor is a weighted sum of the magnetic fluxes
371
+ threading the loops comprising the detection coil. Since the flux threading a
372
+ coil loop is an integral of the magnetic field component normal to the coil
373
+ plane, the output of the k :sup:`th` MEG channel, :math:`b_k` can be
374
+ approximated by:
375
+
376
+ .. math:: b_k = \sum_{p = 1}^{N_k} {w_{kp} B(r_{kp}) \cdot n_{kp}}
377
+
378
+ where :math:`r_{kp}` are a set of :math:`N_k` integration points covering the
379
+ pickup coil loops of the sensor, :math:`B(r_{kp})` is the magnetic field due to
380
+ the current sources calculated at :math:`r_{kp}`, :math:`n_{kp}` are the coil
381
+ normal directions at these points, and :math:`w_{kp}` are the weights
382
+ associated to the integration points. This formula essentially presents
383
+ numerical integration of the magnetic field over the pickup loops of sensor
384
+ :math:`k`.
385
+
386
+ There are three accuracy levels for the numerical integration expressed above.
387
+ The *simple* accuracy means the simplest description of the coil. This accuracy
388
+ is not used in the MNE forward calculations. The *normal* or *recommended*
389
+ accuracy typically uses two integration points for planar gradiometers, one in
390
+ each half of the pickup coil and four evenly distributed integration points for
391
+ magnetometers. This is the default accuracy used by MNE. If the ``--accurate``
392
+ option is specified, the forward calculation typically employs a total of eight
393
+ integration points for planar gradiometers and sixteen for magnetometers.
394
+ Detailed information about the integration points is given in the next section.
395
+
396
+
397
+ .. _implemented_coil_geometries:
398
+
399
+ Implemented coil geometries
400
+ ---------------------------
401
+
402
+ This section describes the coil geometries currently implemented
403
+ in MNE. The coil types fall in two general categories:
404
+
405
+ - Axial gradiometers and planar gradiometers
406
+ and
407
+
408
+ - Planar magnetometers.
409
+
410
+ For axial sensors, the *z* axis of the local coordinate system is parallel to
411
+ the field component detected, *i.e.*, normal to the coil plane.For circular
412
+ coils, the orientation of the *x* and *y* axes on the plane normal to the z
413
+ axis is irrelevant. In the square coils employed in the Vectorview (TM) system
414
+ the *x* axis is chosen to be parallel to one of the sides of the magnetometer
415
+ coil. For planar sensors, the *z* axis is likewise normal to the coil plane and
416
+ the x axis passes through the centerpoints of the two coil loops so that the
417
+ detector gives a positive signal when the normal field component increases
418
+ along the *x* axis.
419
+
420
+ :ref:`normal_coil_descriptions` lists the parameters of the *normal* coil
421
+ geometry descriptions :ref:`accurate_coil_descriptions` lists the *accurate*
422
+ descriptions. For simple accuracy, please consult the coil definition file, see
423
+ :ref:`coil_definition_file`. The columns of the tables contain the following
424
+ data:
425
+
426
+ - The number identifying the coil id.
427
+ This number is used in the coil descriptions found in the FIF files.
428
+
429
+ - Description of the coil.
430
+
431
+ - Number of integration points used
432
+
433
+ - The locations of the integration points in sensor coordinates.
434
+
435
+ - Weights assigned to the field values at the integration points.
436
+ Some formulas are listed instead of the numerical values to demonstrate
437
+ the principle of the calculation. For example, in the normal coil
438
+ descriptions of the planar gradiometers the weights are inverses
439
+ of the baseline of the gradiometer to show that the output is in
440
+ T/m.
441
+
442
+ .. note:: The coil geometry information is stored in the file
443
+ :file:`mne/data/coil_def.dat`, which is
444
+ automatically created by the MNE-C utility ``mne_list_coil_def``.
445
+
446
+ .. tabularcolumns:: |p{0.1\linewidth}|p{0.3\linewidth}|p{0.1\linewidth}|p{0.25\linewidth}|p{0.2\linewidth}|
447
+ .. table:: Normal coil descriptions
448
+ :name: normal_coil_descriptions
449
+
450
+ +------+-------------------------+----+----------------------------------+----------------------+
451
+ | Id | Description | n | r/mm | w |
452
+ +======+=========================+====+==================================+======================+
453
+ | 2 | Neuromag-122 | 2 | (+/-8.1, 0, 0) mm | +/-1 ⁄ 16.2mm |
454
+ | | planar gradiometer | | | |
455
+ +------+-------------------------+----+----------------------------------+----------------------+
456
+ | 2000 | A point magnetometer | 1 | (0, 0, 0)mm | 1 |
457
+ +------+-------------------------+----+----------------------------------+----------------------+
458
+ | 3012 | Vectorview type 1 | 2 | (+/-8.4, 0, 0.3) mm | +/-1 ⁄ 16.8mm |
459
+ | | planar gradiometer | | | |
460
+ +------+-------------------------+----+----------------------------------+----------------------+
461
+ | 3013 | Vectorview type 2 | 2 | (+/-8.4, 0, 0.3) mm | +/-1 ⁄ 16.8mm |
462
+ | | planar gradiometer | | | |
463
+ +------+-------------------------+----+----------------------------------+----------------------+
464
+ | 3022 | Vectorview type 1 | 4 | (+/-6.45, +/-6.45, 0.3)mm | 1/4 |
465
+ | | magnetometer | | | |
466
+ +------+-------------------------+----+----------------------------------+----------------------+
467
+ | 3023 | Vectorview type 2 | 4 | (+/-6.45, +/-6.45, 0.3)mm | 1/4 |
468
+ | | magnetometer | | | |
469
+ +------+-------------------------+----+----------------------------------+----------------------+
470
+ | 3024 | Vectorview type 3 | 4 | (+/-5.25, +/-5.25, 0.3)mm | 1/4 |
471
+ | | magnetometer | | | |
472
+ +------+-------------------------+----+----------------------------------+----------------------+
473
+ | 2000 | An ideal point | 1 | (0.0, 0.0, 0.0)mm | 1 |
474
+ | | magnetometer | | | |
475
+ +------+-------------------------+----+----------------------------------+----------------------+
476
+ | 4001 | Magnes WH | 4 | (+/-5.75, +/-5.75, 0.0)mm | 1/4 |
477
+ | | magnetometer | | | |
478
+ +------+-------------------------+----+----------------------------------+----------------------+
479
+ | 4002 | Magnes WH 3600 | 8 | (+/-4.5, +/-4.5, 0.0)mm | 1/4 |
480
+ | | axial gradiometer | | (+/-4.5, +/-4.5, 50.0)mm | -1/4 |
481
+ +------+-------------------------+----+----------------------------------+----------------------+
482
+ | 4003 | Magnes reference | 4 | (+/-7.5, +/-7.5, 0.0)mm | 1/4 |
483
+ | | magnetometer | | | |
484
+ +------+-------------------------+----+----------------------------------+----------------------+
485
+ | 4004 | Magnes reference | 8 | (+/-20, +/-20, 0.0)mm | 1/4 |
486
+ | | gradiometer measuring | | (+/-20, +/-20, 135)mm | -1/4 |
487
+ | | diagonal gradients | | | |
488
+ +------+-------------------------+----+----------------------------------+----------------------+
489
+ | 4005 | Magnes reference | 8 | (87.5, +/-20, 0.0)mm | 1/4 |
490
+ | | gradiometer measuring | | (47.5, +/-20, 0.0)mm | -1/4 |
491
+ | | off-diagonal gradients | | (-87.5, +/-20, 0.0)mm | 1/4 |
492
+ | | | | (-47.5, +/-20, 0.0)mm | -1/4 |
493
+ +------+-------------------------+----+----------------------------------+----------------------+
494
+ | 5001 | CTF 275 axial | 8 | (+/-4.5, +/-4.5, 0.0)mm | 1/4 |
495
+ | | gradiometer | | (+/-4.5, +/-4.5, 50.0)mm | -1/4 |
496
+ +------+-------------------------+----+----------------------------------+----------------------+
497
+ | 5002 | CTF reference | 4 | (+/-4, +/-4, 0.0)mm | 1/4 |
498
+ | | magnetometer | | | |
499
+ +------+-------------------------+----+----------------------------------+----------------------+
500
+ | 5003 | CTF reference | 8 | (+/-8.6, +/-8.6, 0.0)mm | 1/4 |
501
+ | | gradiometer measuring | | (+/-8.6, +/-8.6, 78.6)mm | -1/4 |
502
+ | | diagonal gradients | | | |
503
+ +------+-------------------------+----+----------------------------------+----------------------+
504
+
505
+ .. note:: If a plus-minus sign occurs in several coordinates, all possible
506
+ combinations have to be included.
507
+
508
+ .. tabularcolumns:: |p{0.1\linewidth}|p{0.3\linewidth}|p{0.05\linewidth}|p{0.25\linewidth}|p{0.15\linewidth}|
509
+ .. table:: Accurate coil descriptions
510
+ :name: accurate_coil_descriptions
511
+
512
+ +------+-------------------------+----+----------------------------------+----------------------+
513
+ | Id | Description | n | r/mm | w |
514
+ +======+=========================+====+==================================+======================+
515
+ | 2 | Neuromag-122 planar | 8 | +/-(8.1, 0, 0) mm | +/-1 ⁄ 16.2mm |
516
+ | | gradiometer | | | |
517
+ +------+-------------------------+----+----------------------------------+----------------------+
518
+ | 2000 | A point magnetometer | 1 | (0, 0, 0) mm | 1 |
519
+ +------+-------------------------+----+----------------------------------+----------------------+
520
+ | 3012 | Vectorview type 1 | 2 | (+/-8.4, 0, 0.3) mm | +/-1 ⁄ 16.8mm |
521
+ | | planar gradiometer | | | |
522
+ +------+-------------------------+----+----------------------------------+----------------------+
523
+ | 3013 | Vectorview type 2 | 2 | (+/-8.4, 0, 0.3) mm | +/-1 ⁄ 16.8mm |
524
+ | | planar gradiometer | | | |
525
+ +------+-------------------------+----+----------------------------------+----------------------+
526
+ | 3022 | Vectorview type 1 | 4 | (+/-6.45, +/-6.45, 0.3)mm | 1/4 |
527
+ | | magnetometer | | | |
528
+ +------+-------------------------+----+----------------------------------+----------------------+
529
+ | 3023 | Vectorview type 2 | 4 | (+/-6.45, +/-6.45, 0.3)mm | 1/4 |
530
+ | | magnetometer | | | |
531
+ +------+-------------------------+----+----------------------------------+----------------------+
532
+ | 3024 | Vectorview type 3 | 4 | (+/-5.25, +/-5.25, 0.3)mm | 1/4 |
533
+ | | magnetometer | | | |
534
+ +------+-------------------------+----+----------------------------------+----------------------+
535
+ | 4001 | Magnes WH magnetometer | 4 | (+/-5.75, +/-5.75, 0.0)mm | 1/4 |
536
+ +------+-------------------------+----+----------------------------------+----------------------+
537
+ | 4002 | Magnes WH 3600 | 4 | (+/-4.5, +/-4.5, 0.0)mm | 1/4 |
538
+ | | axial gradiometer | | (+/-4.5, +/-4.5, 0.0)mm | -1/4 |
539
+ +------+-------------------------+----+----------------------------------+----------------------+
540
+ | 4004 | Magnes reference | 8 | (+/-20, +/-20, 0.0)mm | 1/4 |
541
+ | | gradiometer measuring | | (+/-20, +/-20, 135)mm | -1/4 |
542
+ | | diagonal gradients | | | |
543
+ +------+-------------------------+----+----------------------------------+----------------------+
544
+ | 4005 | Magnes reference | 8 | (87.5, +/-20, 0.0)mm | 1/4 |
545
+ | | gradiometer measuring | | (47.5, +/-20, 0.0)mm | -1/4 |
546
+ | | off-diagonal gradients | | (-87.5, +/-20, 0.0)mm | 1/4 |
547
+ | | | | (-47.5, +/-20, 0.0)mm | -1/4 |
548
+ +------+-------------------------+----+----------------------------------+----------------------+
549
+ | 5001 | CTF 275 axial | 8 | (+/-4.5, +/-4.5, 0.0)mm | 1/4 |
550
+ | | gradiometer | | (+/-4.5, +/-4.5, 50.0)mm | -1/4 |
551
+ +------+-------------------------+----+----------------------------------+----------------------+
552
+ | 5002 | CTF reference | 4 | (+/-4, +/-4, 0.0)mm | 1/4 |
553
+ | | magnetometer | | | |
554
+ +------+-------------------------+----+----------------------------------+----------------------+
555
+ | 5003 | CTF 275 reference | 8 | (+/-8.6, +/-8.6, 0.0)mm | 1/4 |
556
+ | | gradiometer measuring | | (+/-8.6, +/-8.6, 78.6)mm | -1/4 |
557
+ | | diagonal gradients | | | |
558
+ +------+-------------------------+----+----------------------------------+----------------------+
559
+ | 5004 | CTF 275 reference | 8 | (47.8, +/-8.5, 0.0)mm | 1/4 |
560
+ | | gradiometer measuring | | (30.8, +/-8.5, 0.0)mm | -1/4 |
561
+ | | off-diagonal gradients | | (-47.8, +/-8.5, 0.0)mm | 1/4 |
562
+ | | | | (-30.8, +/-8.5, 0.0)mm | -1/4 |
563
+ +------+-------------------------+----+----------------------------------+----------------------+
564
+ | 6001 | MIT KIT system axial | 8 | (+/-3.875, +/-3.875, 0.0)mm | 1/4 |
565
+ | | gradiometer | | (+/-3.875, +/-3.875, 0.0)mm | -1/4 |
566
+ +------+-------------------------+----+----------------------------------+----------------------+
567
+
568
+
569
+ .. _coil_definition_file:
570
+
571
+ The coil definition file
572
+ ------------------------
573
+
574
+ The coil geometry information is stored in the text file
575
+ :file:`{$MNE_ROOT}/share/mne/coil_def.dat`. In this file, any lines starting
576
+ with the pound sign (#) are comments. A coil definition starts with a
577
+ description line containing the following fields:
578
+
579
+ - :samp:`{<class>}`: A number indicating class of this coil.
580
+
581
+ - :samp:`{<id>}`: Coil ID value. This value is listed in the first column of
582
+ Tables :ref:`normal_coil_descriptions` and :ref:`accurate_coil_descriptions`.
583
+
584
+ - :samp:`{<accuracy>}`: The coil representation accuracy. Possible values and
585
+ their meanings are listed in :ref:`coil_accuracies`.
586
+
587
+ - :samp:`{<np>}`: Number of integration points in this representation.
588
+
589
+ - :samp:`{<size/m>}`: The size of the coil. For circular coils this is the
590
+ diameter of the coil and for square ones the side length of the square. This
591
+ information is mainly included to facilitate drawing of the coil geometry. It
592
+ should not be employed to infer a coil approximation for the forward
593
+ calculations.
594
+
595
+ - :samp:`{<baseline/m>}`: The baseline of a this kind of a coil. This will be
596
+ zero for magnetometer coils. This information is mainly included to
597
+ facilitate drawing of the coil geometry. It should not be employed to infer
598
+ a coil approximation for the forward calculations.
599
+
600
+ - :samp:`{<description>}`: Short description of this kind of a coil. If the
601
+ description contains several words, it is enclosed in quotes.
602
+
603
+
604
+ .. tabularcolumns:: |p{0.1\linewidth}|p{0.5\linewidth}|
605
+ .. table:: Coil representation accuracies
606
+ :name: coil_accuracies
607
+
608
+ ======= ====================================================================================
609
+ Value Meaning
610
+ ======= ====================================================================================
611
+ 1 The simplest representation available
612
+ 2 The standard or *normal* representation (see :ref:`normal_coil_descriptions`)
613
+ 3 The most *accurate* representation available (see :ref:`accurate_coil_descriptions`)
614
+ ======= ====================================================================================
615
+
616
+ Each coil description line is followed by one or more integration point lines,
617
+ consisting of seven numbers:
618
+
619
+ - :samp:`{<weight>}`: Gives the weight for this integration point (last column
620
+ in Tables :ref:`normal_coil_descriptions` and
621
+ :ref:`accurate_coil_descriptions`).
622
+
623
+ - :samp:`{<x/m>} {<y/m>} {<z/m>}`: Indicates the location of the integration
624
+ point (fourth column in Tables :ref:`normal_coil_descriptions` and
625
+ :ref:`accurate_coil_descriptions`).
626
+
627
+ - :samp:`{<nx>} {<ny>} {<nz>}`: Components of a unit vector indicating the
628
+ field component to be selected. Note that listing a separate unit vector for
629
+ each integration points allows the implementation of curved coils and coils
630
+ with the gradiometer loops tilted with respect to each other.
631
+
632
+
633
+ Computing the forward solution
634
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
635
+
636
+ Purpose
637
+ -------
638
+
639
+ Examples on how to compute the forward solution in MNE-Python using
640
+ :func:`mne.make_forward_solution` can be found
641
+ :ref:`plot_forward_compute_forward_solution` and
642
+ :ref:`computing_the_forward_solution`.
643
+
644
+ Implementation of software gradient compensation
645
+ ------------------------------------------------
646
+
647
+ Accounting for noise cancellation in MNE-Python is accomplished in
648
+ :meth:`mne.io.Raw.apply_gradient_compensation`. See
649
+ :ref:`plot_brainstorm_phantom_ctf` for an example.
650
+
651
+ CTF and 4D Neuroimaging data may have been subjected to noise cancellation
652
+ employing the data from the reference sensor array. Even though these sensor
653
+ are rather far away from the brain sources, :func:`mne.make_forward_solution`
654
+ takes them into account in the computations. If the data file has software
655
+ gradient compensation activated, it computes the field of at the reference
656
+ sensors in addition to the main MEG sensor array and computes a compensated
657
+ forward solution.
658
+
659
+ The EEG sphere model definition file
660
+ ------------------------------------
661
+
662
+ In MNE-Python, different sphere models can be specified through
663
+ :func:`mne.make_sphere_model`. The default model has the following structure:
664
+
665
+ .. tabularcolumns:: |p{0.1\linewidth}|p{0.25\linewidth}|p{0.2\linewidth}|
666
+ .. table:: Structure of the default EEG model
667
+
668
+ ======== ======================= =======================
669
+ Layer Relative outer radius :math:`\sigma` (S/m)
670
+ ======== ======================= =======================
671
+ Head 1.0 0.33
672
+ Skull 0.97 0.04
673
+ CSF 0.92 1.0
674
+ Brain 0.90 0.33
675
+ ======== ======================= =======================
676
+
677
+ Although it is not BEM model per se the ``sphere`` structure describes the head
678
+ geometry so it can be passed as ``bem`` parameter in MNE-Python functions such
679
+ as :func:`mne.fit_dipole`, :func:`mne.viz.plot_alignment` or
680
+ :func:`mne.make_forward_solution`.
681
+
682
+ .. _eeg_sphere_model:
683
+
684
+ EEG forward solution in the sphere model
685
+ ----------------------------------------
686
+
687
+ .. note:: Sphere-model examples in MNE-Python
688
+ :class: sidebar
689
+
690
+ For examples of using the sphere model when computing the forward model
691
+ (using :func:`mne.make_forward_solution`), see :ref:`Brainstorm CTF phantom
692
+ dataset tutorial <plt_brainstorm_phantom_ctf_eeg_sphere_geometry>`,
693
+ :ref:`Brainstorm Elekta phantom dataset tutorial
694
+ <plt_brainstorm_phantom_elekta_eeg_sphere_geometry>`, and
695
+ :ref:`tut-source-alignment-without-mri`.
696
+
697
+ When the sphere model is employed, the computation of the EEG solution can be
698
+ substantially accelerated by using approximation methods described by Mosher
699
+ :footcite:`MosherEtAl1999`, Zhang :footcite:`Zhang1995`, and Berg
700
+ :footcite:`BergScherg1994`.
701
+ :func:`mne.make_forward_solution` approximates the solution with three dipoles
702
+ in a homogeneous sphere whose locations and amplitudes are determined by
703
+ minimizing the cost function:
704
+
705
+ .. math::
706
+ S(r_1,\dotsc,r_m\ ,\ \mu_1,\dotsc,\mu_m) = \int_{scalp} {(V_{true} - V_{approx})}\,dS
707
+
708
+ where :math:`r_1,\dotsc,r_m` and :math:`\mu_1,\dotsc,\mu_m` are the locations
709
+ and amplitudes of the approximating dipoles and :math:`V_{true}` and
710
+ :math:`V_{approx}` are the potential distributions given by the true and
711
+ approximative formulas, respectively. It can be shown that this integral can be
712
+ expressed in closed form using an expansion of the potentials in spherical
713
+ harmonics. The formula is evaluated for the most superficial dipoles, *i.e.*,
714
+ those lying just inside the inner skull surface.
715
+
716
+ Averaging forward solutions
717
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
718
+
719
+ One possibility to make a grand average over several runs of a experiment is to
720
+ average the data across runs and average the forward solutions accordingly. For
721
+ this purpose, :func:`mne.average_forward_solutions` computes a weighted average
722
+ of several forward solutions. The function averages both MEG and EEG forward
723
+ solutions. Usually the EEG forward solution is identical across runs because
724
+ the electrode locations do not change.
725
+
726
+ .. target for :end-before: forward-end-content
mne-python/source/doc/_includes/ged.rst ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :orphan:
2
+
3
+ Generalized eigendecomposition in decoding
4
+ ==========================================
5
+
6
+ .. NOTE: part of this file is included in doc/overview/implementation.rst.
7
+ Changes here are reflected there. If you want to link to this content, link
8
+ to :ref:`ged` to link to that section of the implementation.rst page.
9
+ The next line is a target for :start-after: so we can omit the title from
10
+ the include:
11
+ ged-begin-content
12
+
13
+ This section describes the mathematical formulation and application of
14
+ Generalized Eigendecomposition (GED), often used in spatial filtering
15
+ and source separation algorithms, such as :class:`mne.decoding.CSP`,
16
+ :class:`mne.decoding.SPoC`, :class:`mne.decoding.SSD` and
17
+ :class:`mne.decoding.XdawnTransformer`.
18
+
19
+ The core principle of GED is to find a set of channel weights (spatial filter)
20
+ that maximizes the ratio of signal power between two data features.
21
+ These features are defined by the researcher and are represented by two covariance matrices:
22
+ a "signal" matrix :math:`S` and a "reference" matrix :math:`R`.
23
+ For example, :math:`S` could be the covariance of data from a task time interval,
24
+ and :math:`S` could be the covariance from a baseline time interval. For more details see :footcite:`Cohen2022`.
25
+
26
+ Algebraic formulation of GED
27
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
28
+
29
+ A few definitions first:
30
+ Let :math:`n \in \mathbb{N}^+` be a number of channels.
31
+ Let :math:`\text{Symm}_n(\mathbb{R}) \subset M_n(\mathbb{R})` be a vector space of real symmetric matrices.
32
+ Let :math:`S^n_+, S^n_{++} \subset \text{Symm}_n(\mathbb{R})` be sets of real positive semidefinite and positive definite matrices, respectively.
33
+ Let :math:`S, R \in S^n_+` be covariance matrices estimated from electrophysiological data :math:`X_S \in M_{n \times t_S}(\mathbb{R})` and :math:`X_R \in M_{n \times t_R}(\mathbb{R})`.
34
+
35
+ GED (or simultaneous diagonalization by congruence) of :math:`S` and :math:`R`
36
+ is possible when :math:`R` is full rank (and thus :math:`R \in S^n_{++}`):
37
+
38
+ .. math::
39
+
40
+ SW = RWD,
41
+
42
+ where :math:`W \in M_n(\mathbb{R})` is an invertible matrix of eigenvectors
43
+ of :math:`(S, R)` and :math:`D` is a diagonal matrix of eigenvalues :math:`\lambda_i`.
44
+
45
+ Each eigenvector :math:`\mathbf{w} \in W` is a spatial filter that solves
46
+ an optimization problem of the form:
47
+
48
+ .. math::
49
+
50
+ \operatorname{argmax}_{\mathbf{w}} \frac{\mathbf{w}^t S \mathbf{w}}{\mathbf{w}^t R \mathbf{w}}
51
+
52
+ That is, using spatial filters :math:`W` on time-series :math:`X \in M_{n \times t}(\mathbb{R})`:
53
+
54
+ .. math::
55
+
56
+ \mathbf{A} = W^t X,
57
+
58
+ results in "activation" time-series :math:`A` of the estimated "sources",
59
+ such that the ratio of their variances,
60
+ :math:`\frac{\text{Var}(\mathbf{w}^T X_S)}{\text{Var}(\mathbf{w}^T X_R)} = \frac{\mathbf{w}^T S \mathbf{w}}{\mathbf{w}^T R \mathbf{w}}`,
61
+ is sequentially maximized spatial filters :math:`\mathbf{w}_i`, sorted according to :math:`\lambda_i`.
62
+
63
+ GED in the principal subspace
64
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
65
+ Unfortunately, :math:`R` might not be full rank depending on the data :math:`X_R` (for example due to average reference, removed PCA/ICA components, etc.).
66
+ In such cases, GED can be performed on :math:`S` and :math:`R` in the principal subspace :math:`Q = \operatorname{Im}(C_{ref}) \subset \mathbb{R}^n` of some reference
67
+ covariance :math:`C_{ref}` (in Common Spatial Pattern (CSP) algorithm, for example, :math:`C_{ref}=\frac{1}{2}(S+R)` and GED is performed on S and R'=S+R).
68
+
69
+ More formally:
70
+ Let :math:`r \leq n` be a rank of :math:`C \in S^n_+`.
71
+ Let :math:`Q=\operatorname{Im}(C_{ref})` be a principal subspace of :math:`C_{ref}`.
72
+ Let :math:`P \in M_{n \times r}(\mathbb{R})` be an isometry formed by orthonormal basis of :math:`Q`.
73
+ Let :math:`f:S^n_+ \to S^r_+`, :math:`A \mapsto P^t A P` be a "restricting" map, that restricts quadratic form
74
+ :math:`q_A:\mathbb{R}^n \to \mathbb{R}` to :math:`q_{A|_Q}:\mathbb{R}^n \to \mathbb{R}` (in practical terms, :math:`q_A` maps
75
+ spatial filters to variance of the spatially filtered data :math:`X_A`).
76
+
77
+ Then, the GED of :math:`S` and :math:`R` in the principal subspace :math:`Q` of :math:`C_{ref}` is performed as follows:
78
+
79
+ 1. :math:`S` and :math:`R` are transformed to :math:`S_Q = f(S) = P^t S P` and :math:`R_Q = f(R) = P^t R P`,
80
+ such that :math:`S_Q` and :math:`R_Q` are matrix representations of restricted :math:`q_{S|_Q}` and :math:`q_{R|_Q}`.
81
+ 2. GED is performed on :math:`S_Q` and :math:`R_Q`: :math:`S_Q W_Q = R_Q W_Q D`.
82
+ 3. Eigenvectors :math:`W_Q` of :math:`(S_Q, R_Q)` are transformed back to :math:`\mathbb{R}^n`
83
+ by :math:`W = P W_Q \in \mathbb{R}^{n \times r}` to obtain :math:`r` spatial filters.
84
+
85
+ Note that the solution to the original optimization problem is preserved:
86
+
87
+ .. math::
88
+
89
+ \frac{\mathbf{w_Q}^t S_Q \mathbf{w_Q}}{\mathbf{w_Q}^t R_Q \mathbf{w_Q}}= \frac{\mathbf{w_Q}^t (P^t S P) \mathbf{w_Q}}{\mathbf{w_Q}^t (P^t R P)
90
+ \mathbf{w_Q}} = \frac{\mathbf{w}^t S \mathbf{w}}{\mathbf{w}^t R \mathbf{w}} = \lambda
91
+
92
+
93
+ In addition to restriction, :math:`q_S` and :math:`q_R` can be rescaled based on the whitened :math:`C_{ref}`.
94
+ In this case the whitening map :math:`f_{wh}:S^n_+ \to S^r_+`,
95
+ :math:`A \mapsto P_{wh}^t A P_{wh}` transforms :math:`A` into matrix representation of :math:`q_{A|Q}` rescaled according to :math:`\Lambda^{-1/2}`,
96
+ where :math:`\Lambda` is a diagonal matrix of eigenvalues of :math:`C_{ref}` and so :math:`P_{wh} = P \Lambda^{-1/2}`.
97
+
98
+ In MNE-Python, the matrix :math:`P` of the restricting map can be obtained using
99
+ ::
100
+
101
+ _, ref_evecs, mask = mne.cov._smart_eigh(C_ref, ..., proj_subspace=True, ...)
102
+ restr_mat = ref_evecs[mask]
103
+
104
+ while :math:`P_{wh}` using:
105
+ ::
106
+
107
+ restr_mat = compute_whitener(C_ref, ..., pca=True, ...)
mne-python/source/doc/_includes/institutional-partners.rst ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :orphan:
2
+
3
+ Institutional partners
4
+ ----------------------
5
+
6
+ .. NOTE: this file is included in doc/funding.rst and doc/overview/people.rst.
7
+ Changes here are reflected there. If you want to link to this content, link
8
+ to :ref:`supporting-institutions` to link to that section of the funding.rst
9
+ page. The next line is a target for :start-after: so we can omit the title
10
+ from the include:
11
+ institutional-partners-begin-content
12
+
13
+ Current partners
14
+ ~~~~~~~~~~~~~~~~
15
+
16
+ - `Aalto-yliopiston perustieteiden korkeakoulu <https://sci.aalto.fi/>`_
17
+ - `Donders Institute for Brain, Cognition and Behaviour at Radboud University <https://www.ru.nl/donders/>`_
18
+ - `Karl-Franzens-Universität Graz <https://www.uni-graz.at/>`_
19
+ - `University of Washington <https://www.washington.edu/>`_
20
+
21
+ Former partners
22
+ ~~~~~~~~~~~~~~~
23
+
24
+ - `Aarhus Universitet <https://www.au.dk/>`_
25
+ - `AE Studio <https://ae.studio/>`_
26
+ - `Athinoula A. Martinos Center for Biomedical Imaging <https://martinos.org/>`_
27
+ - `Berkeley Institute for Data Science <https://bids.berkeley.edu/>`_
28
+ - `Boston University <https://www.bu.edu/>`_
29
+ - `Children’s Hospital of Philadelphia Research Institute <https://www.research.chop.edu/imaging/>`_
30
+ - `Commissariat à l’énergie atomique et aux énergies alternatives <https://www.cea.fr/>`_
31
+ - `Fondation Campus Biotech Geneva <https://fcbg.ch/>`_
32
+ - `Forschungszentrum Jülich <https://www.fz-juelich.de/>`_
33
+ - `Harvard Medical School <https://hms.harvard.edu/>`_
34
+ - `Institut du Cerveau et de la Moelle épinière <https://icm-institute.org/>`_
35
+ - `Institut national de la santé et de la recherche médicale <https://www.inserm.fr/>`_
36
+ - `Institut national de recherche en informatique et en automatique <https://www.inria.fr/>`_
37
+ - `Massachusetts General Hospital <https://www.massgeneral.org/>`_
38
+ - `Massachusetts Institute of Technology <https://web.mit.edu/>`_
39
+ - `Max-Planck-Institut für Bildungsforschung <https://www.mpib-berlin.mpg.de/>`_
40
+ - `Macquarie University <https://www.mq.edu.au/>`_
41
+ - `New York University <https://www.nyu.edu/>`_
42
+ - `SWPS Uniwersytet Humanistycznospołeczny <https://www.swps.pl/>`_
43
+ - `Technische Universität Ilmenau <https://www.tu-ilmenau.de/>`_
44
+ - `Télécom ParisTech <https://www.telecom-paris.fr/>`_
mne-python/source/doc/_includes/inverse.rst ADDED
@@ -0,0 +1,607 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .. _ch_mne:
2
+
3
+ The minimum-norm current estimates
4
+ ==================================
5
+
6
+ .. NOTE: part of this file is included in doc/overview/implementation.rst.
7
+ Changes here are reflected there. If you want to link to this content, link
8
+ to :ref:`ch_mne` to link to that section of the implementation.rst page.
9
+ The next line is a target for :start-after: so we can omit the title from
10
+ the include:
11
+ inverse-begin-content
12
+
13
+
14
+ This section describes the mathematical details of the calculation of
15
+ minimum-norm estimates. In Bayesian sense, the ensuing current distribution is
16
+ the maximum a posteriori (MAP) estimate under the following assumptions:
17
+
18
+ - The viable locations of the currents are constrained to the cortex.
19
+ Optionally, the current orientations can be fixed to be normal to the
20
+ cortical mantle.
21
+
22
+ - The amplitudes of the currents have a Gaussian prior distribution with a
23
+ known source covariance matrix.
24
+
25
+ - The measured data contain additive noise with a Gaussian distribution with a
26
+ known covariance matrix. The noise is not correlated over time.
27
+
28
+ Computing the inverse operator is accomplished using
29
+ :func:`mne.minimum_norm.make_inverse_operator` and
30
+ :func:`mne.minimum_norm.apply_inverse`. The use of these functions is presented
31
+ in the tutorial :ref:`tut-inverse-methods`.
32
+
33
+ The linear inverse operator
34
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
35
+
36
+ The measured data in the source estimation procedure consists of MEG and EEG
37
+ data, recorded on a total of N channels. The task is to estimate a total of
38
+ :math:`Q`
39
+ strengths of sources located on the cortical mantle. If the number of source
40
+ locations is :math:`P`, :math:`Q = P` for fixed-orientation sources and
41
+ :math:`Q = 3P` if the source
42
+ orientations are unconstrained. The regularized linear inverse operator
43
+ following from regularized maximal likelihood of the above probabilistic model
44
+ is given by the :math:`Q \times N` matrix
45
+
46
+ .. math:: M = R' G^\top (G R' G^\top + C)^{-1}\ ,
47
+
48
+ where :math:`G` is the gain matrix relating the source strengths to the measured
49
+ MEG/EEG data, :math:`C` is the data noise-covariance matrix and :math:`R'` is
50
+ the source covariance matrix. The dimensions of these matrices are :math:`N
51
+ \times Q`, :math:`N \times N`, and :math:`Q \times Q`, respectively. The
52
+ :math:`Q \times 1` source-strength vector is obtained by multiplying the
53
+ :math:`Q \times 1` data vector by :math:`Q`.
54
+
55
+ The expected value of the current amplitudes at time *t* is then given by
56
+ :math:`\hat{j}(t) = Mx(t)`, where :math:`x(t)` is a vector containing the
57
+ measured MEG and EEG data values at time *t*.
58
+
59
+ For computational convenience, the linear inverse operator is
60
+ not computed explicitly. See :ref:`mne_solution` for mathematical
61
+ details, and :ref:`CIHCFJEI` for a detailed example.
62
+
63
+ .. _mne_regularization:
64
+
65
+ Regularization
66
+ ~~~~~~~~~~~~~~
67
+
68
+ The a priori variance of the currents is, in practice, unknown. We can express
69
+ this by writing :math:`R' = R/ \lambda^2 = R \lambda^{-2}`, which yields the
70
+ inverse operator
71
+
72
+ .. math::
73
+ :name: inv_m
74
+
75
+ M &= R' G^\top (G R' G^\top + C)^{-1} \\
76
+ &= R \lambda^{-2} G^\top (G R \lambda^{-2} G^\top + C)^{-1} \\
77
+ &= R \lambda^{-2} G^\top \lambda^2 (G R G^\top + \lambda^2 C)^{-1} \\
78
+ &= R G^\top (G R G^\top + \lambda^2 C)^{-1}\ ,
79
+
80
+ where the unknown current amplitude is now interpreted in terms of the
81
+ regularization parameter :math:`\lambda^2`. Larger :math:`\lambda^2` values
82
+ correspond to spatially smoother and weaker current amplitudes, whereas smaller
83
+ :math:`\lambda^2` values lead to the opposite.
84
+
85
+ We can arrive at the regularized linear inverse operator also by minimizing a
86
+ cost function :math:`S` with respect to the estimated current :math:`\hat{j}`
87
+ (given the measurement vector :math:`x` at any given time :math:`t`) as
88
+
89
+ .. math::
90
+
91
+ \min_\hat{j} \Bigl\{ S \Bigr\} &= \min_\hat{j} \Bigl\{ \tilde{e}^\top \tilde{e} + \lambda^2 \hat{j}^\top R^{-1} \hat{j} \Bigr\} \\
92
+ &= \min_\hat{j} \Bigl\{ (x - G\hat{j})^\top C^{-1} (x - G\hat{j}) + \lambda^2 \hat{j}^\top R^{-1} \hat{j} \Bigr\} \,
93
+
94
+ where the first term consists of the difference between the whitened measured
95
+ data (see :ref:`whitening_and_scaling`) and those predicted by the model while the
96
+ second term is a weighted-norm of the current estimate. It is seen that, with
97
+ increasing :math:`\lambda^2`, the source term receive more weight and larger
98
+ discrepancy between the measured and predicted data is tolerable.
99
+
100
+ .. _whitening_and_scaling:
101
+
102
+ Whitening and scaling
103
+ ~~~~~~~~~~~~~~~~~~~~~
104
+
105
+ The MNE software employs data whitening so that a 'whitened' inverse operator
106
+ assumes the form
107
+
108
+ .. math:: \tilde{M} = M C^{^1/_2} = R \tilde{G}^\top (\tilde{G} R \tilde{G}^\top + \lambda^2 I)^{-1}\ ,
109
+ :name: inv_m_tilde
110
+
111
+ where
112
+
113
+ .. math:: \tilde{G} = C^{-^1/_2}G
114
+ :name: inv_g_tilde
115
+
116
+ is the spatially whitened gain matrix. We arrive at the whitened inverse
117
+ operator equation :eq:`inv_m_tilde` by making the substitution for
118
+ :math:`G` from :eq:`inv_g_tilde` in :eq:`inv_m` as
119
+
120
+ .. math::
121
+
122
+ \tilde{M} = M C^{^1/_2} &= R G^\top (G R G^\top + \lambda^2 C)^{-1} C^{^1/_2} \\
123
+ &= R \tilde{G}^\top C^{^1/_2} (C^{^1/_2} \tilde{G} R \tilde{G}^\top C^{^1/_2} + \lambda^2 C)^{-1} C^{^1/_2} \\
124
+ &= R \tilde{G}^\top C^{^1/_2} (C^{^1/_2} (\tilde{G} R \tilde{G}^\top + \lambda^2 I) C^{^1/_2})^{-1} C^{^1/_2} \\
125
+ &= R \tilde{G}^\top C^{^1/_2} C^{-^1/_2} (\tilde{G} R \tilde{G}^\top + \lambda^2 I)^{-1} C^{-^1/_2} C^{^1/_2} \\
126
+ &= R \tilde{G}^\top (\tilde{G} R \tilde{G}^\top + \lambda^2 I)^{-1}\ .
127
+
128
+ The expected current values are
129
+
130
+ .. math::
131
+ :name: inv_j_hat_t
132
+
133
+ \hat{j}(t) &= Mx(t) \\
134
+ &= M C^{^1/_2} C^{-^1/_2} x(t) \\
135
+ &= \tilde{M} \tilde{x}(t)
136
+
137
+ knowing :eq:`inv_m_tilde` and taking
138
+
139
+ .. math::
140
+ :name: inv_tilde_x_t
141
+
142
+ \tilde{x}(t) = C^{-^1/_2}x(t)
143
+
144
+ as the whitened measurement vector at time *t*. The spatial
145
+ whitening operator :math:`C^{-^1/_2}` is obtained with the help of the
146
+ eigenvalue decomposition
147
+ :math:`C = U_C \Lambda_C^2 U_C^\top` as :math:`C^{-^1/_2} = \Lambda_C^{-1} U_C^\top`.
148
+ In the MNE software the noise-covariance matrix is stored as the one applying
149
+ to raw data. To reflect the decrease of noise due to averaging, this matrix,
150
+ :math:`C_0`, is scaled by the number of averages, :math:`L`, *i.e.*, :math:`C =
151
+ C_0 / L`.
152
+
153
+ .. note::
154
+ When EEG data are included, the gain matrix :math:`G` needs to be average referenced when computing the linear inverse operator :math:`M`. This is incorporated during creating the spatial whitening operator :math:`C^{-^1/_2}`, which includes any projectors on the data. EEG data average reference (using a projector) is mandatory for source modeling and is checked when calculating the inverse operator.
155
+
156
+ As shown above, regularization of the inverse solution is equivalent to a
157
+ change in the variance of the current amplitudes in the Bayesian *a priori*
158
+ distribution.
159
+
160
+ A convenient choice for the source-covariance matrix :math:`R` is such that
161
+ :math:`\text{trace}(\tilde{G} R \tilde{G}^\top) / \text{trace}(I) = 1`. With this
162
+ choice we can approximate :math:`\lambda^2 \sim 1/\rm{SNR}^2`, where SNR is the
163
+ (amplitude) signal-to-noise ratio of the whitened data.
164
+
165
+ .. note::
166
+ The definition of the signal to noise-ratio/ :math:`\lambda^2` relationship
167
+ given above works nicely for the whitened forward solution. In the
168
+ un-whitened case scaling with the trace ratio :math:`\text{trace}(GRG^\top) /
169
+ \text{trace}(C)` does not make sense, since the diagonal elements summed
170
+ have, in general, different units of measure. For example, the MEG data are
171
+ expressed in T or T/m whereas the unit of EEG is Volts.
172
+
173
+ See :ref:`tut-compute-covariance` for example of noise covariance computation
174
+ and whitening.
175
+
176
+ .. _cov_regularization_math:
177
+
178
+ Regularization of the noise-covariance matrix
179
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
180
+
181
+ Since finite amount of data is usually available to compute an estimate of the
182
+ noise-covariance matrix :math:`C`, the smallest eigenvalues of its estimate are
183
+ usually inaccurate and smaller than the true eigenvalues. Depending on the
184
+ seriousness of this problem, the following quantities can be affected:
185
+
186
+ - The model data predicted by the current estimate,
187
+
188
+ - Estimates of signal-to-noise ratios, which lead to estimates of the required
189
+ regularization, see :ref:`mne_regularization`,
190
+
191
+ - The estimated current values, and
192
+
193
+ - The noise-normalized estimates, see :ref:`noise_normalization`.
194
+
195
+ Fortunately, the latter two are least likely to be affected due to
196
+ regularization of the estimates. However, in some cases especially the EEG part
197
+ of the noise-covariance matrix estimate can be deficient, *i.e.*, it may
198
+ possess very small eigenvalues and thus regularization of the noise-covariance
199
+ matrix is advisable.
200
+
201
+ Historically, the MNE software accomplishes the regularization by replacing a
202
+ noise-covariance matrix estimate :math:`C` with
203
+
204
+ .. math:: C' = C + \sum_k {\varepsilon_k \bar{\sigma_k}^2 I^{(k)}}\ ,
205
+
206
+ where the index :math:`k` goes across the different channel groups (MEG planar
207
+ gradiometers, MEG axial gradiometers and magnetometers, and EEG),
208
+ :math:`\varepsilon_k` are the corresponding regularization factors,
209
+ :math:`\bar{\sigma_k}` are the average variances across the channel groups, and
210
+ :math:`I^{(k)}` are diagonal matrices containing ones at the positions
211
+ corresponding to the channels contained in each channel group.
212
+
213
+ See :ref:`plot_compute_covariance_howto` for details on computing and
214
+ regularizing the channel covariance matrix.
215
+
216
+ .. _mne_solution:
217
+
218
+ Computation of the solution
219
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
220
+
221
+ The most straightforward approach to calculate the MNE is to employ the
222
+ expression of the original or whitened inverse operator directly. However, for
223
+ computational convenience we prefer to take another route, which employs the
224
+ singular-value decomposition (SVD) of the matrix
225
+
226
+ .. math::
227
+ :name: inv_a
228
+
229
+ A &= \tilde{G} R^{^1/_2} \\
230
+ &= U \Lambda V^\top
231
+
232
+ where the superscript :math:`^1/_2` indicates a square root of :math:`R`. For a
233
+ diagonal matrix, one simply takes the square root of :math:`R` while in the
234
+ more general case one can use the Cholesky factorization :math:`R = R_C R_C^\top`
235
+ and thus :math:`R^{^1/_2} = R_C`.
236
+
237
+ Combining the SVD from :eq:`inv_a` with the inverse equation :eq:`inv_m` it is
238
+ easy to show that
239
+
240
+ .. math::
241
+ :name: inv_m_tilde_svd
242
+
243
+ \tilde{M} &= R \tilde{G}^\top (\tilde{G} R \tilde{G}^\top + \lambda^2 I)^{-1} \\
244
+ &= R^{^1/_2} A^\top (A A^\top + \lambda^2 I)^{-1} \\
245
+ &= R^{^1/_2} V \Lambda U^\top (U \Lambda V^\top V \Lambda U^\top + \lambda^2 I)^{-1} \\
246
+ &= R^{^1/_2} V \Lambda U^\top (U (\Lambda^2 + \lambda^2 I) U^\top)^{-1} \\
247
+ &= R^{^1/_2} V \Lambda U^\top U (\Lambda^2 + \lambda^2 I)^{-1} U^\top \\
248
+ &= R^{^1/_2} V \Lambda (\Lambda^2 + \lambda^2 I)^{-1} U^\top \\
249
+ &= R^{^1/_2} V \Gamma U^\top
250
+
251
+ where the elements of the diagonal matrix :math:`\Gamma` are simply
252
+
253
+ .. `reginv` in our code:
254
+
255
+ .. math::
256
+ :name: inv_gamma_k
257
+
258
+ \gamma_k = \frac{\lambda_k}{\lambda_k^2 + \lambda^2}\ .
259
+
260
+ From our expected current equation :eq:`inv_j_hat_t` and our whitened
261
+ measurement equation :eq:`inv_tilde_x_t`, if we take
262
+
263
+ .. math::
264
+ :name: inv_w_t
265
+
266
+ w(t) &= U^\top \tilde{x}(t) \\
267
+ &= U^\top C^{-^1/_2} x(t)\ ,
268
+
269
+ we can see that the expression for the expected current is just
270
+
271
+ .. math::
272
+ :name: inv_j_hat_t_svd
273
+
274
+ \hat{j}(t) &= R^{^1/_2} V \Gamma w(t) \\
275
+ &= \sum_k {\bar{v_k} \gamma_k w_k(t)}\ ,
276
+
277
+ where :math:`\bar{v_k} = R^{^1/_2} v_k`, with :math:`v_k` being the
278
+ :math:`k` th column of :math:`V`. It is thus seen that the current estimate is
279
+ a weighted sum of the "weighted" eigenleads :math:`v_k`.
280
+
281
+ It is easy to see that :math:`w(t) \propto \sqrt{L}`. To maintain the relation
282
+ :math:`(\tilde{G} R \tilde{G}^\top) / \text{trace}(I) = 1` when :math:`L` changes
283
+ we must have :math:`R \propto 1/L`. With this approach, :math:`\lambda_k` is
284
+ independent of :math:`L` and, for fixed :math:`\lambda`, we see directly that
285
+ :math:`j(t)` is independent of :math:`L`.
286
+
287
+ The minimum-norm estimate is computed using this procedure in
288
+ :func:`mne.minimum_norm.make_inverse_operator`, and its usage is illustrated
289
+ in :ref:`CIHCFJEI`.
290
+
291
+
292
+ .. _noise_normalization:
293
+
294
+ Noise normalization
295
+ ~~~~~~~~~~~~~~~~~~~
296
+
297
+ Noise normalization serves three purposes:
298
+
299
+ - It converts the expected current value into a dimensionless statistical test
300
+ variable. Thus the resulting time and location dependent values are often
301
+ referred to as dynamic statistical parameter maps (dSPM).
302
+
303
+ - It reduces the location bias of the estimates. In particular, the tendency of
304
+ the MNE to prefer superficial currents is eliminated.
305
+
306
+ - The width of the point-spread function becomes less dependent on the source
307
+ location on the cortical mantle. The point-spread is defined as the MNE
308
+ resulting from the signals coming from a point current source (a current
309
+ dipole) located at a certain point on the cortex.
310
+
311
+ In practice, noise normalization is implemented as a division by the square
312
+ root of the estimated variance of each voxel. In computing these noise
313
+ normalization factors, it's convenient to reuse our "weighted eigenleads"
314
+ definition from equation :eq:`inv_j_hat_t` in matrix form as
315
+
316
+ .. math::
317
+ :name: inv_eigenleads_weighted
318
+
319
+ \bar{V} = R^{^1/_2} V\ .
320
+
321
+ dSPM
322
+ ----
323
+
324
+ Noise-normalized linear estimates introduced by Dale et al.
325
+ :footcite:`DaleEtAl1999` require division of the expected current amplitude by
326
+ its variance. In practice, this requires the computation of the diagonal
327
+ elements of the following matrix, using SVD equation :eq:`inv_m_tilde` and
328
+ :eq:`inv_eigenleads_weighted`:
329
+
330
+ .. math::
331
+
332
+ M C M^\top &= M C^{^1/_2} C^{^1/_2} M^\top \\
333
+ &= \tilde{M} \tilde{M}^\top \\
334
+ &= R^{^1/_2} V \Gamma U^\top U \Gamma V^\top R^{^1/_2} \\
335
+ &= \bar{V} \Gamma^2 \bar{V}^\top\ .
336
+
337
+ Because we only care about the diagonal entries here, we can find the
338
+ variances for each source as
339
+
340
+ .. math::
341
+
342
+ \sigma_k^2 = \gamma_k^2
343
+
344
+ Under the conditions expressed at the end of :ref:`mne_solution`, it
345
+ follows that the *t*-statistic values associated with fixed-orientation
346
+ sources) are thus proportional to :math:`\sqrt{L}` while the *F*-statistic
347
+ employed with free-orientation sources is proportional to :math:`L`,
348
+ correspondingly.
349
+
350
+ .. note::
351
+ The MNE software usually computes the *square roots* of the F-statistic to
352
+ be displayed on the inflated cortical surfaces. These are also proportional
353
+ to :math:`\sqrt{L}`.
354
+
355
+ sLORETA
356
+ -------
357
+ sLORETA :footcite:`Pascual-Marqui2002` estimates the current variances as the
358
+ diagonal entries of the
359
+ resolution matrix, which is the product of the inverse and forward operators.
360
+ In other words, the diagonal entries of (using :eq:`inv_m_tilde_svd`,
361
+ :eq:`inv_g_tilde`, and :eq:`inv_a`)
362
+
363
+ .. math::
364
+
365
+ M G &= M C^{^1/_2} C^{-^1/_2} G \\
366
+ &= \tilde{M} \tilde{G} \\
367
+ &= R^{^1/_2} V \Gamma U^\top \tilde{G} R^{^1/_2} R^{-^1/_2} \\
368
+ &= R^{^1/_2} V \Gamma U^\top U \Lambda V^\top R^{-^1/_2} \\
369
+ &= R^{^1/_2} V \Gamma U^\top U \Lambda V^\top R^{^1/_2} R^{-1} \\
370
+ &= \bar{V} \Gamma U^\top U \Lambda \bar{V}^\top R^{-1} \\
371
+ &= \bar{V} \Gamma \Lambda \bar{V}^\top R^{-1}\ .
372
+
373
+ Because :math:`R` is diagonal and we only care about the diagonal entries,
374
+ we can find our variance estimates as
375
+
376
+ .. math::
377
+
378
+ \sigma_k^2 &= \gamma_k \lambda_k R_{k,k}^{-1} \\
379
+ &= \left(\frac{\lambda_k}{(\lambda_k^2 + \lambda^2)}\right) \left(\frac{\lambda_k}{1}\right) \left(\frac{1}{\lambda^2}\right) \\
380
+ &= \frac{\lambda_k^2}{(\lambda_k^2 + \lambda^2) \lambda^2} \\
381
+ &= \left(\frac{\lambda_k^2}{(\lambda_k^2 + \lambda^2)^2}\right) \left(\frac{\lambda^2 + \lambda_k^2}{\lambda^2}\right) \\
382
+ &= \left(\frac{\lambda_k}{\lambda_k^2 + \lambda^2}\right)^2 \left(1 + \frac{\lambda_k^2}{\lambda^2}\right) \\
383
+ &= \gamma_k^2 \left(1 + \frac{\lambda_k^2}{\lambda^2}\right)\ .
384
+
385
+ eLORETA
386
+ ~~~~~~~
387
+ While dSPM and sLORETA solve for noise normalization weights
388
+ :math:`\sigma^2_k` that are applied to standard minimum-norm estimates
389
+ :math:`\hat{j}(t)`, eLORETA :footcite:`Pascual-Marqui2011` instead solves for
390
+ a source covariance
391
+ matrix :math:`R` that achieves zero localization bias. For fixed-orientation
392
+ solutions the resulting matrix :math:`R` will be a diagonal matrix, and for
393
+ free-orientation solutions it will be a block-diagonal matrix with
394
+ :math:`3 \times 3` blocks.
395
+
396
+ .. In https://royalsocietypublishing.org/doi/full/10.1098/rsta.2011.0081
397
+ .. eq. 2.10 (classical min norm), their values map onto our values as:
398
+ ..
399
+ .. - α=λ²
400
+ .. - W=R⁻¹ (pos semidef weight matrix)
401
+ .. - K=G
402
+ .. - ϕ=x
403
+ .. - C=H
404
+ ..
405
+
406
+ In :footcite:`Pascual-Marqui2011` eq. 2.13 states that the following system
407
+ of equations can be used to find the weights, :math:`\forall i \in {1, ..., P}`
408
+ (note that here we represent the equations from that paper using our notation):
409
+
410
+ .. math:: r_i = \left[ G_i^\top \left( GRG^\top + \lambda^2C \right)^{-1} G_i \right] ^{-^1/_2}
411
+
412
+ And an iterative algorithm can be used to find the values for the weights
413
+ :math:`r_i` that satisfy these equations as:
414
+
415
+ 1. Initialize identity weights.
416
+ 2. Compute :math:`N= \left( GRG^\top + \lambda^2C \right)^{-1}`.
417
+ 3. Holding :math:`N` fixed, compute new weights :math:`r_i = \left[ G_i^\top N G_i \right]^{-^1/_2}`.
418
+ 4. Using new weights, go to step (2) until convergence.
419
+
420
+ In particular, for step (2) we can use our substitution from :eq:`inv_g_tilde`
421
+ as:
422
+
423
+ .. math::
424
+
425
+ N &= (G R G^\top + \lambda^2 C)^{-1} \\
426
+ &= (C^{^1/_2} \tilde{G} R \tilde{G}^\top C^{^1/_2} + \lambda^2 C)^{-1} \\
427
+ &= (C^{^1/_2} (\tilde{G} R \tilde{G}^\top + \lambda^2 I) C^{^1/_2})^{-1} \\
428
+ &= C^{-^1/_2} (\tilde{G} R \tilde{G}^\top + \lambda^2 I)^{-1} C^{-^1/_2} \\
429
+ &= C^{-^1/_2} (\tilde{G} R \tilde{G}^\top + \lambda^2 I)^{-1} C^{-^1/_2}\ .
430
+
431
+ Then defining :math:`\tilde{N}` as the whitened version of :math:`N`, i.e.,
432
+ the regularized pseudoinverse of :math:`\tilde{G}R\tilde{G}^\top`, we can
433
+ compute :math:`N` as:
434
+
435
+ .. math::
436
+
437
+ N &= C^{-^1/_2} (U_{\tilde{G}R\tilde{G}^\top} \Lambda_{\tilde{G}R\tilde{G}^\top} V_{\tilde{G}R\tilde{G}^\top}^\top + \lambda^2 I)^{-1} C^{-^1/_2} \\
438
+ &= C^{-^1/_2} (U_{\tilde{G}R\tilde{G}^\top} (\Lambda_{\tilde{G}R\tilde{G}^\top} + \lambda^2 I) V_{\tilde{G}R\tilde{G}^\top}^\top)^{-1} C^{-^1/_2} \\
439
+ &= C^{-^1/_2} V_{\tilde{G}R\tilde{G}^\top} (\Lambda_{\tilde{G}R\tilde{G}^\top} + \lambda^2 I)^{-1} U_{\tilde{G}R\tilde{G}^\top}^\top C^{-^1/_2} \\
440
+ &= C^{-^1/_2} \tilde{N} C^{-^1/_2}\ .
441
+
442
+ In step (3) we left and right multiply with subsets of :math:`G`, but making
443
+ the substitution :eq:`inv_g_tilde` we see that we equivalently compute:
444
+
445
+ .. math::
446
+
447
+ r_i &= \left[ G_i^\top N G_i \right]^{-^1/_2} \\
448
+ &= \left[ (C^{^1/_2} \tilde{G}_i)^\top N C^{^1/_2} \tilde{G}_i \right]^{-^1/_2} \\
449
+ &= \left[ \tilde{G}_i^\top C^{^1/_2} N C^{^1/_2} \tilde{G}_i \right]^{-^1/_2} \\
450
+ &= \left[ \tilde{G}_i^\top C^{^1/_2} C^{-^1/_2} \tilde{N} C^{-^1/_2} C^{^1/_2} \tilde{G}_i \right]^{-^1/_2} \\
451
+ &= \left[ \tilde{G}_i^\top \tilde{N} \tilde{G}_i \right]^{-^1/_2}\ .
452
+
453
+ For convenience, we thus never need to compute :math:`N` itself but can instead
454
+ compute the whitened version :math:`\tilde{N}`.
455
+
456
+ Predicted data
457
+ ~~~~~~~~~~~~~~
458
+
459
+ Under noiseless conditions the SNR is infinite and thus leads to
460
+ :math:`\lambda^2 = 0` and the minimum-norm estimate explains the measured data
461
+ perfectly. Under realistic conditions, however, :math:`\lambda^2 > 0` and there
462
+ is a misfit between measured data and those predicted by the MNE. Comparison of
463
+ the predicted data, here denoted by :math:`x(t)`, and measured one can give
464
+ valuable insight on the correctness of the regularization applied.
465
+
466
+ In the SVD approach we easily find
467
+
468
+ .. math:: \hat{x}(t) = G \hat{j}(t) = C^{^1/_2} U \Pi w(t)\ ,
469
+
470
+ where the diagonal matrix :math:`\Pi` has elements :math:`\pi_k = \lambda_k
471
+ \gamma_k` The predicted data is thus expressed as the weighted sum of the
472
+ 'recolored eigenfields' in :math:`C^{^1/_2} U`.
473
+
474
+ Cortical patch statistics
475
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
476
+
477
+ If the ``add_dists=True`` option was used in source space creation,
478
+ the source space file will contain
479
+ Cortical Patch Statistics (CPS) for each vertex of the cortical surface. The
480
+ CPS provide information about the source space point closest to it as well as
481
+ the distance from the vertex to this source space point. The vertices for which
482
+ a given source space point is the nearest one define the cortical patch
483
+ associated with with the source space point. Once these data are available, it
484
+ is straightforward to compute the following cortical patch statistics for each
485
+ source location :math:`d`:
486
+
487
+ - The average over the normals of at the vertices in a patch,
488
+ :math:`\bar{n_d}`,
489
+
490
+ - The areas of the patches, :math:`A_d`, and
491
+
492
+ - The average deviation of the vertex normals in a patch from their average,
493
+ :math:`\sigma_d`, given in degrees.
494
+
495
+ ``use_cps`` parameter in :func:`mne.convert_forward_solution`, and
496
+ :func:`mne.minimum_norm.make_inverse_operator` controls whether to use
497
+ cortical patch statistics (CPS) to define normal orientations or not (see
498
+ :ref:`CHDBBCEJ`).
499
+
500
+ .. _inverse_orientation_constraints:
501
+
502
+ Orientation constraints
503
+ ~~~~~~~~~~~~~~~~~~~~~~~
504
+
505
+ The principal sources of MEG and EEG signals are generally believed to be
506
+ postsynaptic currents in the cortical pyramidal neurons. Since the net primary
507
+ current associated with these microscopic events is oriented normal to the
508
+ cortical mantle, it is reasonable to use the cortical normal orientation as a
509
+ constraint in source estimation. In addition to allowing completely free source
510
+ orientations, the MNE software implements three orientation constraints based
511
+ of the surface normal data:
512
+
513
+ - Source orientation can be rigidly fixed to the surface normal direction by
514
+ specifying ``fixed=True`` in :func:`mne.minimum_norm.make_inverse_operator`.
515
+ If cortical patch statistics are available the average
516
+ normal over each patch, :math:`\bar{n_d}`, are used to define the source
517
+ orientation. Otherwise, the vertex normal at the source space location is
518
+ employed.
519
+
520
+ - A *location independent or fixed loose orientation constraint* (fLOC) can be
521
+ employed by specifying ``fixed=False`` and ``loose=1.0`` when
522
+ calling :func:`mne.minimum_norm.make_inverse_operator` (see
523
+ :ref:`plot_dipole_orientations_fLOC_orientations`).
524
+ In this approach, a source coordinate
525
+ system based on the local surface orientation at the source location is
526
+ employed. By default, the three columns of the gain matrix G, associated with
527
+ a given source location, are the fields of unit dipoles pointing to the
528
+ directions of the :math:`x`, :math:`y`, and :math:`z` axis of the coordinate
529
+ system employed in the forward calculation (usually the :ref:`MEG head
530
+ coordinate frame <head_device_coords>`). For LOC the orientation is changed so
531
+ that the first two source components lie in the plane normal to the surface
532
+ normal at the source location and the third component is aligned with it.
533
+ Thereafter, the variance of the source components tangential to the cortical
534
+ surface are reduced by a factor defined by the ``--loose`` option.
535
+
536
+ - A *variable loose orientation constraint* (vLOC) can be employed by
537
+ specifying ``fixed=False`` and ``loose`` parameters when calling
538
+ :func:`mne.minimum_norm.make_inverse_operator` (see
539
+ :ref:`plot_dipole_orientations_vLOC_orientations`). This
540
+ is similar to *fLOC* except that the value given with the ``loose``
541
+ parameter will be multiplied by :math:`\sigma_d`, defined above.
542
+
543
+ Depth weighting
544
+ ~~~~~~~~~~~~~~~
545
+
546
+ The minimum-norm estimates have a bias towards superficial currents. This
547
+ tendency can be alleviated by adjusting the source covariance matrix :math:`R`
548
+ to favor deeper source locations. In the depth weighting scheme employed in MNE
549
+ analyze, the elements of :math:`R` corresponding to the :math:`p` th source
550
+ location are be scaled by a factor
551
+
552
+ .. math:: f_p = (g_{1p}^\top g_{1p} + g_{2p}^\top g_{2p} + g_{3p}^\top g_{3p})^{-\gamma}\ ,
553
+
554
+ where :math:`g_{1p}`, :math:`g_{2p}`, and :math:`g_{3p}` are the three columns
555
+ of :math:`G` corresponding to source location :math:`p` and :math:`\gamma` is
556
+ the order of the depth weighting, which is specified via the ``depth`` option
557
+ in :func:`mne.minimum_norm.make_inverse_operator`.
558
+
559
+ Effective number of averages
560
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
561
+
562
+ It is often the case that the epoch to be analyzed is a linear combination over
563
+ conditions rather than one of the original averages computed. As stated above,
564
+ the noise-covariance matrix computed is originally one corresponding to raw
565
+ data. Therefore, it has to be scaled correctly to correspond to the actual or
566
+ effective number of epochs in the condition to be analyzed. In general, we have
567
+
568
+ .. math:: C = C_0 / L_{eff}
569
+
570
+ where :math:`L_{eff}` is the effective number of averages. To calculate
571
+ :math:`L_{eff}` for an arbitrary linear combination of conditions
572
+
573
+ .. math:: y(t) = \sum_{i = 1}^n {w_i x_i(t)}
574
+
575
+ we make use of the the fact that the noise-covariance matrix
576
+
577
+ .. math:: C_y = \sum_{i = 1}^n {w_i^2 C_{x_i}} = C_0 \sum_{i = 1}^n {w_i^2 / L_i}
578
+
579
+ which leads to
580
+
581
+ .. math:: 1 / L_{eff} = \sum_{i = 1}^n {w_i^2 / L_i}
582
+
583
+ An important special case of the above is a weighted average, where
584
+
585
+ .. math:: w_i = L_i / \sum_{i = 1}^n {L_i}
586
+
587
+ and, therefore
588
+
589
+ .. math:: L_{eff} = \sum_{i = 1}^n {L_i}
590
+
591
+ Instead of a weighted average, one often computes a weighted sum, a simplest
592
+ case being a difference or sum of two categories. For a difference :math:`w_1 =
593
+ 1` and :math:`w_2 = -1` and thus
594
+
595
+ .. math:: 1 / L_{eff} = 1 / L_1 + 1 / L_2
596
+
597
+ or
598
+
599
+ .. math:: L_{eff} = \frac{L_1 L_2}{L_1 + L_2}
600
+
601
+ Interestingly, the same holds for a sum, where :math:`w_1 = w_2 = 1`.
602
+ Generalizing, for any combination of sums and differences, where :math:`w_i =
603
+ 1` or :math:`w_i = -1`, :math:`i = 1 \dotso n`, we have
604
+
605
+ .. math:: 1 / L_{eff} = \sum_{i = 1}^n {1/{L_i}}
606
+
607
+ .. target for :end-before: inverse-end-content
mne-python/source/doc/_includes/memory.rst ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :orphan:
2
+
3
+ Memory-efficient I/O
4
+ ====================
5
+
6
+ .. NOTE: part of this file is included in doc/overview/implementation.rst.
7
+ Changes here are reflected there. If you want to link to this content, link
8
+ to :ref:`memory` to link to that section of the implementation.rst
9
+ page. The next line is a target for :start-after: so we can omit the title
10
+ from the include:
11
+ memory-begin-content
12
+
13
+
14
+ Preloading continuous (raw) data
15
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16
+
17
+ MNE-Python can read data on-demand using the ``preload`` option provided in
18
+ raw reading functions. For example::
19
+
20
+ from mne import io
21
+ from mne.datasets import sample
22
+ data_path = sample.data_path()
23
+ raw_fname = data_path / 'MEG' / 'sample' / 'sample_audvis_filt-0-40_raw.fif'
24
+ raw = io.read_raw_fif(raw_fname, preload=False)
25
+
26
+ .. note:: Filtering, resampling and dropping or selecting channels does not
27
+ work with ``preload=False``.
28
+
29
+
30
+ Preloading epoched data
31
+ ~~~~~~~~~~~~~~~~~~~~~~~
32
+
33
+ Similarly, epochs can also be be read from disk on-demand. For example::
34
+
35
+ import mne
36
+ events = mne.find_events(raw)
37
+ event_id, tmin, tmax = 1, -0.2, 0.5
38
+ picks = mne.pick_types(raw.info, meg=True, eeg=True, stim=False, eog=True)
39
+ epochs = mne.Epochs(raw, events, event_id, tmin, tmax, picks=picks,
40
+ baseline=(None, 0), reject=dict(eeg=80e-6, eog=150e-6),
41
+ preload=False)
42
+
43
+ When ``preload=False``, the epochs data is loaded from the disk on-demand. Note
44
+ that ``preload=False`` for epochs will work even if the ``raw`` object has been
45
+ loaded with ``preload=True``. Preloading is also supported for
46
+ :func:`mne.read_epochs`.
47
+
48
+ .. warning:: This comes with a caveat. When ``preload=False``, data rejection
49
+ based on peak-to-peak thresholds is executed when the data is
50
+ loaded from disk, *not* when the ``Epochs`` object is created.
51
+
52
+ To explicitly reject artifacts with ``preload=False``, use the function :func:`mne.Epochs.drop_bad`.
53
+
54
+
55
+ Loading data explicitly
56
+ ~~~~~~~~~~~~~~~~~~~~~~~
57
+
58
+ To load the data if ``preload=False`` was initially selected, use the functions :func:`mne.io.Raw.load_data` and :func:`mne.Epochs.load_data`.
59
+
60
+
61
+ Accessing data as NumPy arrays
62
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
63
+
64
+ If you just want your raw data as a :class:`Numpy array <numpy.ndarray>` to
65
+ work with it in a different framework you can use slicing syntax::
66
+
67
+ first_channel_data, times = raw[0, :]
68
+ channels_3_and_4, times = raw[3:5, :]
mne-python/source/doc/_includes/morph.rst ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :orphan:
2
+
3
+ Morphing and averaging source estimates
4
+ =======================================
5
+
6
+ The spherical morphing of BEM surfaces accomplished by FreeSurfer can be
7
+ employed to bring data from different subjects into a common anatomical frame.
8
+ This page describes utilities which make use of the spherical :term:`morphing`
9
+ procedure. :func:`mne.morph_labels` morphs label files between subjects
10
+ allowing the definition of labels in a one brain and transforming them to
11
+ anatomically analogous labels in another. :meth:`mne.SourceMorph.apply` offers
12
+ the capability to transform all subject data to the same space and,
13
+ e.g., compute averages of data across subjects.
14
+
15
+ .. NOTE: part of this file is included in doc/overview/implementation.rst.
16
+ Changes here are reflected there. If you want to link to this content, link
17
+ to :ref:`ch_morph` to link to that section of the implementation.rst page.
18
+ The next line is a target for :start-after: so we can omit the title from
19
+ the include:
20
+ morph-begin-content
21
+
22
+
23
+ Why morphing?
24
+ ~~~~~~~~~~~~~
25
+
26
+ .. note:: Morphing examples in MNE-Python
27
+ :class: sidebar
28
+
29
+ Examples of morphing in MNE-Python include :ref:`this tutorial
30
+ <tut-mne-fixed-free>` on surface source estimation or these examples on
31
+ :ref:`surface <ex-morph-surface>` and :ref:`volumetric <ex-morph-volume>`
32
+ source estimation.
33
+
34
+ Modern neuroimaging techniques, such as source reconstruction or fMRI analyses,
35
+ make use of advanced mathematical models and hardware to map brain activity
36
+ patterns into a subject-specific anatomical brain space. This enables the study
37
+ of spatio-temporal brain activity. The representation of spatio-temporal brain
38
+ data is often mapped onto the anatomical brain structure to relate functional
39
+ and anatomical maps. Thereby activity patterns are overlaid with anatomical
40
+ locations that supposedly produced the activity. Anatomical MR images are often
41
+ used as such or are transformed into an inflated surface representations to
42
+ serve as "canvas" for the visualization.
43
+
44
+ In order to compute group-level statistics, data representations across
45
+ subjects must be morphed to a common frame, such that anatomically and
46
+ functional similar structures are represented at the same spatial location for
47
+ *all subjects equally*. Since brains vary, :term:`morphing` comes into play to
48
+ tell us how the data produced by subject A would be represented on the brain of
49
+ subject B (and vice-versa).
50
+
51
+
52
+ The morphing maps
53
+ ~~~~~~~~~~~~~~~~~
54
+
55
+ The MNE software accomplishes morphing with help of morphing maps.
56
+ The morphing is performed with help of the registered
57
+ spherical surfaces (``lh.sphere.reg`` and ``rh.sphere.reg`` ) which must be
58
+ produced in FreeSurfer. A morphing map is a linear mapping from cortical
59
+ surface values in subject A (:math:`x^{(A)}`) to those in another subject B
60
+ (:math:`x^{(B)}`)
61
+
62
+ .. math:: x^{(B)} = M^{(AB)} x^{(A)}\ ,
63
+
64
+ where :math:`M^{(AB)}` is a sparse matrix with at most three nonzero elements
65
+ on each row. These elements are determined as follows. First, using the aligned
66
+ spherical surfaces, for each vertex :math:`x_j^{(B)}`, find the triangle
67
+ :math:`T_j^{(A)}` on the spherical surface of subject A which contains the
68
+ location :math:`x_j^{(B)}`. Next, find the numbers of the vertices of this
69
+ triangle and set the corresponding elements on the *j* th row of
70
+ :math:`M^{(AB)}` so that :math:`x_j^{(B)}` will be a linear interpolation
71
+ between the triangle vertex values reflecting the location :math:`x_j^{(B)}`
72
+ within the triangle :math:`T_j^{(A)}`.
73
+
74
+ It follows from the above definition that in general
75
+
76
+ .. math:: M^{(AB)} \neq (M^{(BA)})^{-1}\ ,
77
+
78
+ *i.e.*,
79
+
80
+ .. math:: x_{(A)} \neq M^{(BA)} M^{(AB)} x^{(A)}\ ,
81
+
82
+ even if
83
+
84
+ .. math:: x^{(A)} \approx M^{(BA)} M^{(AB)} x^{(A)}\ ,
85
+
86
+ *i.e.*, the mapping is *almost* a bijection.
87
+
88
+
89
+ About smoothing
90
+ ~~~~~~~~~~~~~~~
91
+
92
+ The current estimates are normally defined only in a decimated grid which is a
93
+ sparse subset of the vertices in the triangular tessellation of the cortical
94
+ surface. Therefore, any sparse set of values is distributed to neighboring
95
+ vertices to make the visualized results easily understandable. This procedure
96
+ has been traditionally called smoothing but a more appropriate name might be
97
+ smudging or blurring in accordance with similar operations in image processing
98
+ programs.
99
+
100
+ In MNE software terms, smoothing of the vertex data is an iterative procedure,
101
+ which produces a blurred image :math:`x^{(N)}` from the original sparse image
102
+ :math:`x^{(0)}` by applying in each iteration step a sparse blurring matrix:
103
+
104
+ .. math:: x^{(p)} = S^{(p)} x^{(p - 1)}\ .
105
+
106
+ On each row :math:`j` of the matrix :math:`S^{(p)}` there are :math:`N_j^{(p -
107
+ 1)}` nonzero entries whose values equal :math:`1/N_j^{(p - 1)}`. Here
108
+ :math:`N_j^{(p - 1)}` is the number of immediate neighbors of vertex :math:`j`
109
+ which had non-zero values at iteration step :math:`p - 1`. Matrix
110
+ :math:`S^{(p)}` thus assigns the average of the non-zero neighbors as the new
111
+ value for vertex :math:`j`. One important feature of this procedure is that it
112
+ tends to preserve the amplitudes while blurring the surface image.
113
+
114
+ Once the indices non-zero vertices in :math:`x^{(0)}` and the topology of the
115
+ triangulation are fixed the matrices :math:`S^{(p)}` are fixed and independent
116
+ of the data. Therefore, it would be in principle possible to construct a
117
+ composite blurring matrix
118
+
119
+ .. math:: S^{(N)} = \prod_{p = 1}^N {S^{(p)}}\ .
120
+
121
+ However, it turns out to be computationally more effective to do blurring with
122
+ an iteration. The above formula for :math:`S^{(N)}` also shows that the
123
+ smudging (smoothing) operation is linear.
mne-python/source/doc/_includes/precision.rst ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :orphan:
2
+
3
+ Floating-point precision
4
+ ========================
5
+
6
+ .. NOTE: part of this file is included in doc/manual/io.rst and
7
+ doc/overview/implementation.rst. Changes here are reflected there. If you
8
+ want to link to this content, link to :ref:`manual-precision` for the manual
9
+ or :ref:`precision` for the implementation page. The next line is a target
10
+ for :start-after: so we can omit the title above:
11
+ precision-begin-content
12
+
13
+ MNE-Python performs all computation in memory using the double-precision 64-bit
14
+ floating point format. This means that the data is typecast into float64 format
15
+ as soon as it is read into memory. The reason for this is that operations such
16
+ as filtering and preprocessing are more accurate when using the 64-bit format.
17
+ However, for backward compatibility, MNE-Python writes :file:`.fif` files in a
18
+ 32-bit format by default. This reduces file size when saving data to disk, but
19
+ beware that *saving intermediate results to disk and re-loading them from disk
20
+ later may lead to loss in precision*. If you would like to ensure 64-bit
21
+ precision, there are two possibilities:
22
+
23
+ - Chain the operations in memory and avoid saving intermediate results.
24
+
25
+ - Save intermediate results but change the :class:`~numpy.dtype` used for
26
+ saving, by using the ``fmt`` parameter of :meth:`mne.io.Raw.save` (or
27
+ :meth:`mne.Epochs.save`, etc). However, note that this may render the
28
+ :file:`.fif` files unreadable in software packages other than MNE-Python.
mne-python/source/doc/_includes/ssp.rst ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :orphan:
2
+
3
+ The Signal-Space Projection (SSP) method
4
+ ========================================
5
+
6
+ .. NOTE: part of this file is included in doc/overview/implementation.rst.
7
+ Changes here are reflected there. If you want to link to this content, link
8
+ to :ref:`ssp-method` to link to that section of the implementation.rst
9
+ page. The next line is a target for :start-after: so we can omit the title
10
+ from the include:
11
+ ssp-begin-content
12
+
13
+ The Signal-Space Projection (SSP) is one approach to rejection of external
14
+ disturbances in software. The section presents some relevant details of this
15
+ method. For practical examples of how to use SSP for artifact rejection, see
16
+ :ref:`tut-artifact-ssp`.
17
+
18
+ General concepts
19
+ ~~~~~~~~~~~~~~~~
20
+
21
+ Unlike many other noise-cancellation approaches, SSP does not require
22
+ additional reference sensors to record the disturbance fields. Instead, SSP
23
+ relies on the fact that the magnetic field distributions generated by the
24
+ sources in the brain have spatial distributions sufficiently different from
25
+ those generated by external noise sources. Furthermore, it is implicitly
26
+ assumed that the linear space spanned by the significant external noise patterns
27
+ has a low dimension.
28
+
29
+ Without loss of generality we can always decompose any :math:`n`-channel
30
+ measurement :math:`b(t)` into its signal and noise components as
31
+
32
+ .. math:: b(t) = b_s(t) + b_n(t)
33
+ :name: additive_model
34
+
35
+ Further, if we know that :math:`b_n(t)` is well characterized by a few field
36
+ patterns :math:`b_1 \dotso b_m`, we can express the disturbance as
37
+
38
+ .. math:: b_n(t) = Uc_n(t) + e(t)\ ,
39
+ :name: pca
40
+
41
+ where the columns of :math:`U` constitute an orthonormal basis for :math:`b_1
42
+ \dotso b_m`, :math:`c_n(t)` is an :math:`m`-component column vector, and the
43
+ error term :math:`e(t)` is small and does not exhibit any consistent spatial
44
+ distributions over time, *i.e.*, :math:`C_e = E \{e e^\top\} = I`. Subsequently,
45
+ we will call the column space of :math:`U` the noise subspace. The basic idea
46
+ of SSP is that we can actually find a small basis set :math:`b_1 \dotso b_m`
47
+ such that the conditions described above are satisfied. We can now construct
48
+ the orthogonal complement operator
49
+
50
+ .. math:: P_{\perp} = I - UU^\top
51
+ :name: projector
52
+
53
+ and apply it to :math:`b(t)` in Equation :eq:`additive_model` yielding
54
+
55
+ .. math:: b_{s}(t) \approx P_{\perp}b(t)\ ,
56
+ :name: result
57
+
58
+ since :math:`P_{\perp}b_n(t) = P_{\perp}(Uc_n(t) + e(t)) \approx 0` and
59
+ :math:`P_{\perp}b_{s}(t) \approx b_{s}(t)`. The projection operator
60
+ :math:`P_{\perp}` is called the **signal-space projection operator** and
61
+ generally provides considerable rejection of noise, suppressing external
62
+ disturbances by a factor of 10 or more. The effectiveness of SSP depends on two
63
+ factors:
64
+
65
+ - The basis set :math:`b_1 \dotso b_m` should be able to characterize the
66
+ disturbance field patterns completely and
67
+
68
+ - The angles between the noise subspace space spanned by :math:`b_1 \dotso b_m`
69
+ and the signal vectors :math:`b_s(t)` should be as close to :math:`\pi / 2`
70
+ as possible.
71
+
72
+ If the first requirement is not satisfied, some noise will leak through because
73
+ :math:`P_{\perp}b_n(t) \neq 0`. If the any of the brain signal vectors
74
+ :math:`b_s(t)` is close to the noise subspace not only the noise but also the
75
+ signal will be attenuated by the application of :math:`P_{\perp}` and,
76
+ consequently, there might by little gain in signal-to-noise ratio.
77
+
78
+ Since the signal-space projection modifies the signal vectors originating in
79
+ the brain, it is necessary to apply the projection to the forward solution in
80
+ the course of inverse computations.
81
+
82
+ For more information on SSP, please consult the references listed in
83
+ :footcite:t:`TescheEtAl1995,UusitaloIlmoniemi1997`.
84
+
85
+ Estimation of the noise subspace
86
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
87
+
88
+ As described above, application of SSP requires the estimation of the signal
89
+ vectors :math:`b_1 \dotso b_m` constituting the noise subspace. The most common
90
+ approach, also implemented in :func:`mne.compute_proj_raw`
91
+ is to compute a covariance matrix
92
+ of empty room data, compute its eigenvalue decomposition, and employ the
93
+ eigenvectors corresponding to the highest eigenvalues as basis for the noise
94
+ subspace. It is also customary to use a separate set of vectors for
95
+ magnetometers and gradiometers in the Vectorview system.
96
+
97
+ EEG average electrode reference
98
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
99
+
100
+ The EEG average reference is the mean signal over all the sensors. It is
101
+ typical in EEG analysis to subtract the average reference from all the sensor
102
+ signals :math:`b^{1}(t), ..., b^{n}(t)`. That is:
103
+
104
+ .. math:: {b}^{j}_{s}(t) = b^{j}(t) - \frac{1}{n}\sum_{k}{b^k(t)}
105
+ :name: eeg_proj
106
+
107
+ where the noise term :math:`b_{n}^{j}(t)` is given by
108
+
109
+ .. math:: b_{n}^{j}(t) = \frac{1}{n}\sum_{k}{b^k(t)}
110
+ :name: noise_term
111
+
112
+ Thus, the projector vector :math:`P_{\perp}` will be given by
113
+ :math:`P_{\perp}=\frac{1}{n}[1, 1, ..., 1]`
114
+
115
+ .. warning::
116
+ When applying SSP, the signal of interest can also be sometimes removed.
117
+ Therefore, it's always a good idea to check how much the effect of interest
118
+ is reduced by applying SSP. SSP might remove *both* the artifact and signal
119
+ of interest.
mne-python/source/doc/_includes/units.rst ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :orphan:
2
+
3
+ Internal representation (units)
4
+ ===============================
5
+
6
+ .. NOTE: part of this file is included in doc/manual/io.rst and
7
+ doc/overview/implementation.rst. Changes here are reflected there. If you
8
+ want to link to this content, link to :ref:`manual-units` for the manual or
9
+ :ref:`units` for the implementation page. The next line is a target for
10
+ :start-after: so we can omit what's above:
11
+ units-begin-content
12
+
13
+ Irrespective of the units used in your manufacturer's format, when importing
14
+ data, MNE-Python will always convert measurements to the same standard units.
15
+ Thus the in-memory representation of data are always in:
16
+
17
+ - Volts (eeg, eog, seeg, emg, ecg, bio, ecog, dbs)
18
+ - Teslas (magnetometers)
19
+ - Teslas/meter (gradiometers)
20
+ - Amperes*meter (dipole fits, minimum-norm estimates, etc.)
21
+ - Moles/liter ("molar"; fNIRS data: oxyhemoglobin (hbo), deoxyhemoglobin (hbr))
22
+ - Arbitrary units (various derived unitless quantities)
23
+
24
+ .. NOTE: this is a target for :end-before: units-end-of-list
25
+
26
+ Note, however, that most MNE-Python plotting functions will scale the data when
27
+ plotted to yield nice-looking axis annotations in a sensible range; for
28
+ example, :meth:`mne.io.Raw.plot_psd` will convert teslas to femtoteslas (fT)
29
+ and volts to microvolts (µV) when plotting MEG and EEG data.
30
+
31
+ The units used in internal data representation are particularly important to
32
+ remember when extracting data from MNE-Python objects and manipulating it
33
+ outside MNE-Python (e.g., when using methods like :meth:`~mne.io.Raw.get_data`
34
+ or :meth:`~mne.Epochs.to_data_frame` to convert data to :class:`NumPy arrays
35
+ <numpy.ndarray>` or :class:`Pandas DataFrames <pandas.DataFrame>` for analysis
36
+ or plotting with other Python modules).
mne-python/source/doc/_static/CoordinateSystems.png ADDED
mne-python/source/doc/_static/HeadCS.png ADDED
mne-python/source/doc/_static/blender_import_obj/blender_import_obj1.jpg ADDED

Git LFS Details

  • SHA256: 043b90cd6267ebffe84933b1995fda4caa44a5d3f0e55df8dd1f676d1ba92e2e
  • Pointer size: 131 Bytes
  • Size of remote file: 104 kB
mne-python/source/doc/_static/blender_import_obj/blender_import_obj2.jpg ADDED