neurodags 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. neurodags-0.1.1/.gitignore +57 -0
  2. neurodags-0.1.1/LICENSE +21 -0
  3. neurodags-0.1.1/PKG-INFO +316 -0
  4. neurodags-0.1.1/README.md +255 -0
  5. neurodags-0.1.1/pyproject.toml +144 -0
  6. neurodags-0.1.1/src/neurodags/__init__.py +12 -0
  7. neurodags-0.1.1/src/neurodags/_version.py +24 -0
  8. neurodags-0.1.1/src/neurodags/dag.py +824 -0
  9. neurodags-0.1.1/src/neurodags/datasets.py +789 -0
  10. neurodags-0.1.1/src/neurodags/definitions.py +39 -0
  11. neurodags-0.1.1/src/neurodags/derivatives/__init__.py +160 -0
  12. neurodags-0.1.1/src/neurodags/derivatives/pipeline.py +48 -0
  13. neurodags-0.1.1/src/neurodags/derivatives/pipeline.yml +109 -0
  14. neurodags-0.1.1/src/neurodags/example.py +20 -0
  15. neurodags-0.1.1/src/neurodags/iterators.py +181 -0
  16. neurodags-0.1.1/src/neurodags/loaders.py +181 -0
  17. neurodags-0.1.1/src/neurodags/loggers.py +196 -0
  18. neurodags-0.1.1/src/neurodags/nodes/__init__.py +116 -0
  19. neurodags-0.1.1/src/neurodags/nodes/antropy.py +117 -0
  20. neurodags-0.1.1/src/neurodags/nodes/descriptive.py +283 -0
  21. neurodags-0.1.1/src/neurodags/nodes/dummy.py +33 -0
  22. neurodags-0.1.1/src/neurodags/nodes/factories.py +875 -0
  23. neurodags-0.1.1/src/neurodags/nodes/loader.py +62 -0
  24. neurodags-0.1.1/src/neurodags/nodes/neurokit.py +364 -0
  25. neurodags-0.1.1/src/neurodags/nodes/operations.py +277 -0
  26. neurodags-0.1.1/src/neurodags/nodes/preprocessing.py +153 -0
  27. neurodags-0.1.1/src/neurodags/nodes/spectral.py +1274 -0
  28. neurodags-0.1.1/src/neurodags/orchestrators.py +842 -0
  29. neurodags-0.1.1/src/neurodags/utils.py +391 -0
  30. neurodags-0.1.1/src/neurodags/visualization.py +221 -0
  31. neurodags-0.1.1/src/neurodags/writers.py +62 -0
@@ -0,0 +1,57 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ dist/
13
+ .eggs/
14
+ *.egg-info/
15
+ *.egg
16
+
17
+ docs/sg_execution_times.rst
18
+ src/*/_version.py
19
+ _data/
20
+ _outputs/
21
+ data/
22
+
23
+ # Virtual environments
24
+ .venv/
25
+ .venv*/
26
+ venv/
27
+ .env/
28
+
29
+ # Installer logs
30
+ pip-log.txt
31
+ pip-delete-this-directory.txt
32
+
33
+ # Unit test / coverage reports
34
+ htmlcov/
35
+ .tox/
36
+ .nox/
37
+ .coverage
38
+ .coverage.*
39
+ .cache/
40
+ .pytest_cache/
41
+
42
+ # Type checker / linters
43
+ .mypy_cache/
44
+ .ruff_cache/
45
+
46
+ # IDEs and editors
47
+ #.vscode/
48
+ .idea/
49
+
50
+ # Sphinx documentation
51
+ docs/_build/
52
+ docs/auto_examples/
53
+
54
+ # OS files
55
+ .DS_Store
56
+ Thumbs.db
57
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Your Name
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,316 @@
1
+ Metadata-Version: 2.4
2
+ Name: neurodags
3
+ Version: 0.1.1
4
+ Summary: A slurm friendly MEEG derivative extraction package leveraging bids-like data organization and DAG processing.
5
+ Project-URL: Homepage, https://github.com/yjmantilla/neurodags
6
+ Project-URL: Documentation, https://yjmantilla.github.io/neurodags/
7
+ Project-URL: Repository, https://github.com/yjmantilla/neurodags
8
+ Project-URL: Issues, https://github.com/yjmantilla/neurodags/issues
9
+ Author-email: Yorguin-Jose Mantilla-Ramos <yjmantilla@gmail.com>
10
+ License: MIT
11
+ License-File: LICENSE
12
+ Keywords: bids,derivative,eeg,extraction,meeg,meg
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: antropy
25
+ Requires-Dist: dash
26
+ Requires-Dist: fooof
27
+ Requires-Dist: h5py
28
+ Requires-Dist: imageio
29
+ Requires-Dist: joblib
30
+ Requires-Dist: mne
31
+ Requires-Dist: mne-bids
32
+ Requires-Dist: netcdf4
33
+ Requires-Dist: networkx
34
+ Requires-Dist: neurokit2
35
+ Requires-Dist: pandas
36
+ Requires-Dist: plotly
37
+ Requires-Dist: pybv>=0.7.3
38
+ Requires-Dist: pydantic
39
+ Requires-Dist: pyyaml
40
+ Requires-Dist: structlog
41
+ Requires-Dist: xarray
42
+ Requires-Dist: xpublish
43
+ Provides-Extra: dev
44
+ Requires-Dist: black>=24.3; extra == 'dev'
45
+ Requires-Dist: build>=1.2; extra == 'dev'
46
+ Requires-Dist: mypy>=1.10; extra == 'dev'
47
+ Requires-Dist: pre-commit>=3.7; extra == 'dev'
48
+ Requires-Dist: ruff>=0.5; extra == 'dev'
49
+ Provides-Extra: docs
50
+ Requires-Dist: furo>=2024.1.29; extra == 'docs'
51
+ Requires-Dist: matplotlib>=3.7; extra == 'docs'
52
+ Requires-Dist: myst-parser>=2.0; extra == 'docs'
53
+ Requires-Dist: sphinx-autoapi; extra == 'docs'
54
+ Requires-Dist: sphinx-autodoc-typehints>=2.1; extra == 'docs'
55
+ Requires-Dist: sphinx-gallery>=0.16; extra == 'docs'
56
+ Requires-Dist: sphinx>=7.3; extra == 'docs'
57
+ Provides-Extra: test
58
+ Requires-Dist: pytest-cov>=5.0; extra == 'test'
59
+ Requires-Dist: pytest>=8.2; extra == 'test'
60
+ Description-Content-Type: text/markdown
61
+
62
+ [![CI](https://img.shields.io/github/actions/workflow/status/yjmantilla/neurodags/ci.yml?branch=main&label=tests)](https://github.com/yjmantilla/neurodags/actions?query=workflow%3ACI)
63
+ [![Docs](https://img.shields.io/github/actions/workflow/status/yjmantilla/neurodags/docs.yml?branch=main&label=docs)](https://github.com/yjmantilla/neurodags/actions?query=workflow%3ADocs)
64
+ [![codecov](https://img.shields.io/codecov/c/github/yjmantilla/neurodags)](https://app.codecov.io/gh/yjmantilla/neurodags)
65
+
66
+ # NeuroDAGs
67
+
68
+ **An Extensible and Declarative DAG Framework for Reproducible Neuroscience Workflows**
69
+
70
+ M/EEG studies generate many interdependent intermediate derivatives. Recomputing full pipelines is wasteful; reusing valid intermediates is non-trivial. Large-scale studies require reproducible, extensible, and efficient workflows. NeuroDAGs addresses this with a declarative, graph-based framework for scalable and reusable derivative computation.
71
+
72
+ **[Poster BRaIN Symposium 2026 Montreal](https://canva.link/c2b2fm0mk2wotwq)**
73
+
74
+ ## Core Idea
75
+
76
+ Pipelines are defined as a **directed acyclic graph (DAG)** of computation nodes that output reusable derivatives, executed for each input file.
77
+
78
+ ## Design Principles
79
+
80
+ - **Reproducible, transparent workflows** defined declaratively in YAML — version-controllable and LLM-friendly.
81
+ - **Uniform node abstraction** — preprocessing, features, and any custom nodes are treated identically.
82
+ - **Directory-agnostic** — outputs mirror inputs' organization. Derivatives are labeled with a `@DerivativeName` suffix.
83
+ - **xarray-centered outputs** — derivatives stored as language-agnostic, metadata-rich, dimension-aware xarray → NetCDF.
84
+ - **Graph-based reuse** — if a derivative is already computed and `overwrite=False`, it is skipped automatically.
85
+
86
+ ## Features
87
+
88
+ - Agnostic to data organization / directory hierarchy
89
+ - SLURM / HPC friendly with file-level parallelism via joblib
90
+ - Graph-based caching: skip already-computed derivatives
91
+ - Extensible node system — add nodes without forking the package
92
+ - YAML-based declarative configuration
93
+ - Built-in nodes for preprocessing, spectral analysis, entropy, complexity, and data transformations
94
+ - Dataframe assembly (wide or long format) from derivative artifacts
95
+ - Dry-run mode — inspect planned computations without executing
96
+ - Built-in Dash-Plotly explorer for `.fif` and `.nc` files
97
+
98
+ ## Installation
99
+
100
+ ```bash
101
+ pip install neurodags
102
+ ```
103
+
104
+ With [uv](https://docs.astral.sh/uv/) (recommended):
105
+
106
+ ```bash
107
+ uv add neurodags
108
+ ```
109
+
110
+ ## Quickstart
111
+
112
+ See the [quickstart example](https://yjmantilla.github.io/neurodags/auto_examples/plot_quickstart_synthetic.html) — full synthetic pipeline, no real data required.
113
+
114
+ ## Development
115
+
116
+ ```bash
117
+ git clone https://github.com/yjmantilla/neurodags
118
+ cd neurodags
119
+ uv sync --all-extras --all-groups # creates .venv and installs all deps incl. dev/test/docs
120
+ uv run pre-commit install
121
+ ```
122
+
123
+ Key commands (all via `uv run`):
124
+
125
+ ```bash
126
+ uv run ruff check src/ # lint (fix: uv run ruff check src/ --fix)
127
+ uv run black --check . # format check (fix: uv run black .)
128
+ uv run pytest -q # run tests
129
+ uv run pytest -s -q --no-cov --pdb # debug a failing test
130
+
131
+ uv run sphinx-build -b html docs docs/_build/html -W --keep-going # build docs
132
+ rm -rf docs/_build # clean docs
133
+ ```
134
+
135
+ > **No uv?** Install it with `pip install uv` or `curl -Ls https://astral.sh/uv/install.sh | sh`.
136
+ > All commands above work with plain `python`/`pip` too — swap `uv run` → activate `.venv`, `uv sync` → `pip install -e .[dev,test,docs]`.
137
+
138
+ ## Project Structure
139
+
140
+ ```
141
+ my_project/
142
+ ├── datasets.yml # Dataset sources and paths
143
+ ├── pipeline.yml # Derivative definitions and execution list
144
+ └── custom_nodes.py # Optional custom node definitions
145
+ ```
146
+
147
+ ## Quick Example
148
+
149
+ **`datasets.yml`**
150
+ ```yaml
151
+ my_dataset:
152
+ name: MyDataset
153
+ file_pattern:
154
+ local: data/**/*.vhdr
155
+ hpc: /cluster/BIDS/**/*.vhdr
156
+ derivatives_path:
157
+ local: outputs/
158
+ hpc: /cluster/scratch/out
159
+ ```
160
+
161
+ **`pipeline.yml`**
162
+ ```yaml
163
+ datasets: datasets.yml
164
+ mount_point: local
165
+ new_definitions: custom_nodes.py # optional
166
+
167
+ DerivativeDefinitions:
168
+ CleanedEEG:
169
+ nodes:
170
+ - id: 0
171
+ derivative: SourceFile
172
+ - id: 1
173
+ node: basic_preprocessing
174
+ args:
175
+ mne_object: id.0
176
+ resample: 256
177
+ filter_args:
178
+ l_freq: 0.5
179
+ h_freq: 110
180
+
181
+ PowerSpectrum:
182
+ for_dataframe: True
183
+ nodes:
184
+ - id: 0
185
+ derivative: CleanedEEG.fif
186
+ - id: 1
187
+ node: mne_spectrum_array
188
+ args:
189
+ meeg: id.0
190
+ method: multitaper
191
+
192
+ DerivativeList:
193
+ - CleanedEEG
194
+ - PowerSpectrum
195
+ ```
196
+
197
+ **Python**
198
+ ```python
199
+ from neurodags.loaders import load_configuration
200
+ from neurodags.orchestrators import iterate_derivative_pipeline
201
+
202
+ config = load_configuration("pipeline.yml")
203
+ iterate_derivative_pipeline(config, "CleanedEEG")
204
+ iterate_derivative_pipeline(config, "PowerSpectrum")
205
+ ```
206
+
207
+ ## Custom Nodes
208
+
209
+ Add nodes without modifying or forking the package:
210
+
211
+ ```python
212
+ # custom_nodes.py
213
+ from neurodags.nodes import register_node
214
+ from neurodags.definitions import Artifact, NodeResult
215
+
216
+ @register_node
217
+ def my_node(data) -> NodeResult:
218
+ result = compute(data)
219
+ return NodeResult(
220
+ artifacts={
221
+ ".nc": Artifact(
222
+ item=result,
223
+ writer=lambda path: result.to_netcdf(path),
224
+ ),
225
+ },
226
+ )
227
+ ```
228
+
229
+ Key rules:
230
+ 1. A node is a function decorated with `@register_node`.
231
+ 2. It returns a `NodeResult`.
232
+ 3. A `NodeResult` contains `artifacts` — a dict mapping file extension to `Artifact(item, writer)`.
233
+
234
+ ## Dataframe Assembly
235
+
236
+ ```python
237
+ from neurodags.orchestrators import build_derivative_dataframe
238
+
239
+ df = build_derivative_dataframe("pipeline.yml", output_format="wide")
240
+ ```
241
+
242
+ Derivatives marked `for_dataframe: True` are collected automatically. Supports `"wide"` (one row per file) and `"long"` (one row per value) formats.
243
+
244
+ ## Parallel Execution
245
+
246
+ ```yaml
247
+ # pipeline.yml
248
+ n_jobs: 4 # -1 = all cores, 1 or null = serial
249
+ joblib_backend: loky
250
+ joblib_prefer: processes
251
+ ```
252
+
253
+ Or via Python:
254
+
255
+ ```python
256
+ iterate_derivative_pipeline(config, "MyDerivative", n_jobs=4)
257
+ ```
258
+
259
+ ## Visualization
260
+
261
+ ```bash
262
+ python -m neurodags.visualization path/to/file.fif
263
+ python -m neurodags.visualization path/to/file.nc
264
+ ```
265
+
266
+ Built-in Dash-Plotly explorer with dimension-aware UI — dropdown per axis, plot types: Line, Scatter, Bar, Heatmap.
267
+
268
+ ## Inspection (Dry Run)
269
+
270
+ ```python
271
+ iterate_derivative_pipeline(config, "MyDerivative", dry_run=True)
272
+ ```
273
+
274
+ Returns a dataframe describing the execution plan without running any nodes. `.error` marker files prevent silent retry of failed runs.
275
+
276
+ ## Derivative Flags
277
+
278
+ | Flag | Default | Description |
279
+ |------|---------|-------------|
280
+ | `save` | `True` | Persist artifacts to disk. `False` = compute but don't write. |
281
+ | `overwrite` | `False` | Force recompute even if output exists. |
282
+ | `for_dataframe` | `False` | Include this derivative in `build_derivative_dataframe`. |
283
+
284
+ ## Custom Node Definitions
285
+
286
+ Point `new_definitions` to one or more Python files:
287
+
288
+ ```yaml
289
+ new_definitions:
290
+ - custom_nodes/my_nodes.py
291
+ - /abs/path/to/other_nodes.py
292
+ ```
293
+
294
+ Relative paths are resolved from the pipeline YAML location.
295
+
296
+ ## Documentation
297
+
298
+ [https://yjmantilla.github.io/neurodags/](https://yjmantilla.github.io/neurodags/)
299
+
300
+ ## HDF5 / NetCDF Note
301
+
302
+ If you encounter `RuntimeError: NetCDF: HDF error`:
303
+
304
+ ```bash
305
+ uv run pip install --no-binary=h5py h5py
306
+ # or without uv:
307
+ pip install --no-binary=h5py h5py
308
+ ```
309
+
310
+ ## Contributing
311
+
312
+ See [`CONTRIBUTING.md`](CONTRIBUTING.md).
313
+
314
+ ## License
315
+
316
+ MIT. See [`LICENSE`](LICENSE).
@@ -0,0 +1,255 @@
1
+ [![CI](https://img.shields.io/github/actions/workflow/status/yjmantilla/neurodags/ci.yml?branch=main&label=tests)](https://github.com/yjmantilla/neurodags/actions?query=workflow%3ACI)
2
+ [![Docs](https://img.shields.io/github/actions/workflow/status/yjmantilla/neurodags/docs.yml?branch=main&label=docs)](https://github.com/yjmantilla/neurodags/actions?query=workflow%3ADocs)
3
+ [![codecov](https://img.shields.io/codecov/c/github/yjmantilla/neurodags)](https://app.codecov.io/gh/yjmantilla/neurodags)
4
+
5
+ # NeuroDAGs
6
+
7
+ **An Extensible and Declarative DAG Framework for Reproducible Neuroscience Workflows**
8
+
9
+ M/EEG studies generate many interdependent intermediate derivatives. Recomputing full pipelines is wasteful; reusing valid intermediates is non-trivial. Large-scale studies require reproducible, extensible, and efficient workflows. NeuroDAGs addresses this with a declarative, graph-based framework for scalable and reusable derivative computation.
10
+
11
+ **[Poster BRaIN Symposium 2026 Montreal](https://canva.link/c2b2fm0mk2wotwq)**
12
+
13
+ ## Core Idea
14
+
15
+ Pipelines are defined as a **directed acyclic graph (DAG)** of computation nodes that output reusable derivatives, executed for each input file.
16
+
17
+ ## Design Principles
18
+
19
+ - **Reproducible, transparent workflows** defined declaratively in YAML — version-controllable and LLM-friendly.
20
+ - **Uniform node abstraction** — preprocessing, features, and any custom nodes are treated identically.
21
+ - **Directory-agnostic** — outputs mirror inputs' organization. Derivatives are labeled with a `@DerivativeName` suffix.
22
+ - **xarray-centered outputs** — derivatives stored as language-agnostic, metadata-rich, dimension-aware xarray → NetCDF.
23
+ - **Graph-based reuse** — if a derivative is already computed and `overwrite=False`, it is skipped automatically.
24
+
25
+ ## Features
26
+
27
+ - Agnostic to data organization / directory hierarchy
28
+ - SLURM / HPC friendly with file-level parallelism via joblib
29
+ - Graph-based caching: skip already-computed derivatives
30
+ - Extensible node system — add nodes without forking the package
31
+ - YAML-based declarative configuration
32
+ - Built-in nodes for preprocessing, spectral analysis, entropy, complexity, and data transformations
33
+ - Dataframe assembly (wide or long format) from derivative artifacts
34
+ - Dry-run mode — inspect planned computations without executing
35
+ - Built-in Dash-Plotly explorer for `.fif` and `.nc` files
36
+
37
+ ## Installation
38
+
39
+ ```bash
40
+ pip install neurodags
41
+ ```
42
+
43
+ With [uv](https://docs.astral.sh/uv/) (recommended):
44
+
45
+ ```bash
46
+ uv add neurodags
47
+ ```
48
+
49
+ ## Quickstart
50
+
51
+ See the [quickstart example](https://yjmantilla.github.io/neurodags/auto_examples/plot_quickstart_synthetic.html) — full synthetic pipeline, no real data required.
52
+
53
+ ## Development
54
+
55
+ ```bash
56
+ git clone https://github.com/yjmantilla/neurodags
57
+ cd neurodags
58
+ uv sync --all-extras --all-groups # creates .venv and installs all deps incl. dev/test/docs
59
+ uv run pre-commit install
60
+ ```
61
+
62
+ Key commands (all via `uv run`):
63
+
64
+ ```bash
65
+ uv run ruff check src/ # lint (fix: uv run ruff check src/ --fix)
66
+ uv run black --check . # format check (fix: uv run black .)
67
+ uv run pytest -q # run tests
68
+ uv run pytest -s -q --no-cov --pdb # debug a failing test
69
+
70
+ uv run sphinx-build -b html docs docs/_build/html -W --keep-going # build docs
71
+ rm -rf docs/_build # clean docs
72
+ ```
73
+
74
+ > **No uv?** Install it with `pip install uv` or `curl -Ls https://astral.sh/uv/install.sh | sh`.
75
+ > All commands above work with plain `python`/`pip` too — swap `uv run` → activate `.venv`, `uv sync` → `pip install -e .[dev,test,docs]`.
76
+
77
+ ## Project Structure
78
+
79
+ ```
80
+ my_project/
81
+ ├── datasets.yml # Dataset sources and paths
82
+ ├── pipeline.yml # Derivative definitions and execution list
83
+ └── custom_nodes.py # Optional custom node definitions
84
+ ```
85
+
86
+ ## Quick Example
87
+
88
+ **`datasets.yml`**
89
+ ```yaml
90
+ my_dataset:
91
+ name: MyDataset
92
+ file_pattern:
93
+ local: data/**/*.vhdr
94
+ hpc: /cluster/BIDS/**/*.vhdr
95
+ derivatives_path:
96
+ local: outputs/
97
+ hpc: /cluster/scratch/out
98
+ ```
99
+
100
+ **`pipeline.yml`**
101
+ ```yaml
102
+ datasets: datasets.yml
103
+ mount_point: local
104
+ new_definitions: custom_nodes.py # optional
105
+
106
+ DerivativeDefinitions:
107
+ CleanedEEG:
108
+ nodes:
109
+ - id: 0
110
+ derivative: SourceFile
111
+ - id: 1
112
+ node: basic_preprocessing
113
+ args:
114
+ mne_object: id.0
115
+ resample: 256
116
+ filter_args:
117
+ l_freq: 0.5
118
+ h_freq: 110
119
+
120
+ PowerSpectrum:
121
+ for_dataframe: True
122
+ nodes:
123
+ - id: 0
124
+ derivative: CleanedEEG.fif
125
+ - id: 1
126
+ node: mne_spectrum_array
127
+ args:
128
+ meeg: id.0
129
+ method: multitaper
130
+
131
+ DerivativeList:
132
+ - CleanedEEG
133
+ - PowerSpectrum
134
+ ```
135
+
136
+ **Python**
137
+ ```python
138
+ from neurodags.loaders import load_configuration
139
+ from neurodags.orchestrators import iterate_derivative_pipeline
140
+
141
+ config = load_configuration("pipeline.yml")
142
+ iterate_derivative_pipeline(config, "CleanedEEG")
143
+ iterate_derivative_pipeline(config, "PowerSpectrum")
144
+ ```
145
+
146
+ ## Custom Nodes
147
+
148
+ Add nodes without modifying or forking the package:
149
+
150
+ ```python
151
+ # custom_nodes.py
152
+ from neurodags.nodes import register_node
153
+ from neurodags.definitions import Artifact, NodeResult
154
+
155
+ @register_node
156
+ def my_node(data) -> NodeResult:
157
+ result = compute(data)
158
+ return NodeResult(
159
+ artifacts={
160
+ ".nc": Artifact(
161
+ item=result,
162
+ writer=lambda path: result.to_netcdf(path),
163
+ ),
164
+ },
165
+ )
166
+ ```
167
+
168
+ Key rules:
169
+ 1. A node is a function decorated with `@register_node`.
170
+ 2. It returns a `NodeResult`.
171
+ 3. A `NodeResult` contains `artifacts` — a dict mapping file extension to `Artifact(item, writer)`.
172
+
173
+ ## Dataframe Assembly
174
+
175
+ ```python
176
+ from neurodags.orchestrators import build_derivative_dataframe
177
+
178
+ df = build_derivative_dataframe("pipeline.yml", output_format="wide")
179
+ ```
180
+
181
+ Derivatives marked `for_dataframe: True` are collected automatically. Supports `"wide"` (one row per file) and `"long"` (one row per value) formats.
182
+
183
+ ## Parallel Execution
184
+
185
+ ```yaml
186
+ # pipeline.yml
187
+ n_jobs: 4 # -1 = all cores, 1 or null = serial
188
+ joblib_backend: loky
189
+ joblib_prefer: processes
190
+ ```
191
+
192
+ Or via Python:
193
+
194
+ ```python
195
+ iterate_derivative_pipeline(config, "MyDerivative", n_jobs=4)
196
+ ```
197
+
198
+ ## Visualization
199
+
200
+ ```bash
201
+ python -m neurodags.visualization path/to/file.fif
202
+ python -m neurodags.visualization path/to/file.nc
203
+ ```
204
+
205
+ Built-in Dash-Plotly explorer with dimension-aware UI — dropdown per axis, plot types: Line, Scatter, Bar, Heatmap.
206
+
207
+ ## Inspection (Dry Run)
208
+
209
+ ```python
210
+ iterate_derivative_pipeline(config, "MyDerivative", dry_run=True)
211
+ ```
212
+
213
+ Returns a dataframe describing the execution plan without running any nodes. `.error` marker files prevent silent retry of failed runs.
214
+
215
+ ## Derivative Flags
216
+
217
+ | Flag | Default | Description |
218
+ |------|---------|-------------|
219
+ | `save` | `True` | Persist artifacts to disk. `False` = compute but don't write. |
220
+ | `overwrite` | `False` | Force recompute even if output exists. |
221
+ | `for_dataframe` | `False` | Include this derivative in `build_derivative_dataframe`. |
222
+
223
+ ## Custom Node Definitions
224
+
225
+ Point `new_definitions` to one or more Python files:
226
+
227
+ ```yaml
228
+ new_definitions:
229
+ - custom_nodes/my_nodes.py
230
+ - /abs/path/to/other_nodes.py
231
+ ```
232
+
233
+ Relative paths are resolved from the pipeline YAML location.
234
+
235
+ ## Documentation
236
+
237
+ [https://yjmantilla.github.io/neurodags/](https://yjmantilla.github.io/neurodags/)
238
+
239
+ ## HDF5 / NetCDF Note
240
+
241
+ If you encounter `RuntimeError: NetCDF: HDF error`:
242
+
243
+ ```bash
244
+ uv run pip install --no-binary=h5py h5py
245
+ # or without uv:
246
+ pip install --no-binary=h5py h5py
247
+ ```
248
+
249
+ ## Contributing
250
+
251
+ See [`CONTRIBUTING.md`](CONTRIBUTING.md).
252
+
253
+ ## License
254
+
255
+ MIT. See [`LICENSE`](LICENSE).