nirspy 0.0.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.
- nirspy-0.0.1/.github/ISSUE_TEMPLATE/bug.yml +65 -0
- nirspy-0.0.1/.github/ISSUE_TEMPLATE/config.yml +8 -0
- nirspy-0.0.1/.github/ISSUE_TEMPLATE/feature.yml +49 -0
- nirspy-0.0.1/.github/PULL_REQUEST_TEMPLATE.md +33 -0
- nirspy-0.0.1/.github/dependabot.yml +24 -0
- nirspy-0.0.1/.github/workflows/ci.yml +79 -0
- nirspy-0.0.1/.gitignore +70 -0
- nirspy-0.0.1/.python-version +1 -0
- nirspy-0.0.1/CHANGELOG.md +30 -0
- nirspy-0.0.1/CLAUDE.md +179 -0
- nirspy-0.0.1/CODE_OF_CONDUCT.md +16 -0
- nirspy-0.0.1/CONTRIBUTING.md +114 -0
- nirspy-0.0.1/LICENSE +28 -0
- nirspy-0.0.1/PKG-INFO +171 -0
- nirspy-0.0.1/README.md +103 -0
- nirspy-0.0.1/SECURITY.md +36 -0
- nirspy-0.0.1/docs/architecture.md +245 -0
- nirspy-0.0.1/docs/roadmap.md +143 -0
- nirspy-0.0.1/examples/data/.gitkeep +0 -0
- nirspy-0.0.1/examples/pipelines/basic-preproc.yml +20 -0
- nirspy-0.0.1/examples/pipelines/best-practices-block-design.yml +46 -0
- nirspy-0.0.1/pyproject.toml +102 -0
- nirspy-0.0.1/requirements.txt +86 -0
- nirspy-0.0.1/scripts/smoke_e1.py +67 -0
- nirspy-0.0.1/src/nirspy/__init__.py +3 -0
- nirspy-0.0.1/src/nirspy/blocks/__init__.py +70 -0
- nirspy-0.0.1/src/nirspy/blocks/analysis.py +339 -0
- nirspy-0.0.1/src/nirspy/blocks/load.py +232 -0
- nirspy-0.0.1/src/nirspy/blocks/manual_exclude.py +100 -0
- nirspy-0.0.1/src/nirspy/blocks/preprocessing.py +277 -0
- nirspy-0.0.1/src/nirspy/blocks/quality.py +234 -0
- nirspy-0.0.1/src/nirspy/blocks/registry.py +127 -0
- nirspy-0.0.1/src/nirspy/cli/__init__.py +0 -0
- nirspy-0.0.1/src/nirspy/cli/main.py +83 -0
- nirspy-0.0.1/src/nirspy/domain/__init__.py +27 -0
- nirspy-0.0.1/src/nirspy/domain/block.py +118 -0
- nirspy-0.0.1/src/nirspy/domain/cache.py +40 -0
- nirspy-0.0.1/src/nirspy/domain/data_types.py +42 -0
- nirspy-0.0.1/src/nirspy/domain/exceptions.py +74 -0
- nirspy-0.0.1/src/nirspy/domain/execution.py +117 -0
- nirspy-0.0.1/src/nirspy/domain/pipeline.py +162 -0
- nirspy-0.0.1/src/nirspy/domain/validation.py +59 -0
- nirspy-0.0.1/src/nirspy/engine/__init__.py +24 -0
- nirspy-0.0.1/src/nirspy/engine/cache_adapter.py +236 -0
- nirspy-0.0.1/src/nirspy/engine/exceptions.py +47 -0
- nirspy-0.0.1/src/nirspy/engine/mne_adapter.py +371 -0
- nirspy-0.0.1/src/nirspy/gui/__init__.py +5 -0
- nirspy-0.0.1/src/nirspy/gui/app.py +49 -0
- nirspy-0.0.1/src/nirspy/gui/callbacks/__init__.py +0 -0
- nirspy-0.0.1/src/nirspy/gui/callbacks/converter_callbacks.py +188 -0
- nirspy-0.0.1/src/nirspy/gui/callbacks/execution_callbacks.py +326 -0
- nirspy-0.0.1/src/nirspy/gui/callbacks/io_callbacks.py +116 -0
- nirspy-0.0.1/src/nirspy/gui/callbacks/param_callbacks.py +174 -0
- nirspy-0.0.1/src/nirspy/gui/callbacks/pipeline_callbacks.py +252 -0
- nirspy-0.0.1/src/nirspy/gui/callbacks/viz_callbacks.py +174 -0
- nirspy-0.0.1/src/nirspy/gui/components/__init__.py +1 -0
- nirspy-0.0.1/src/nirspy/gui/components/block_card.py +190 -0
- nirspy-0.0.1/src/nirspy/gui/components/block_catalog.py +82 -0
- nirspy-0.0.1/src/nirspy/gui/components/condition_selector.py +57 -0
- nirspy-0.0.1/src/nirspy/gui/components/condition_windows_editor.py +238 -0
- nirspy-0.0.1/src/nirspy/gui/components/converter_view.py +119 -0
- nirspy-0.0.1/src/nirspy/gui/components/error_display.py +39 -0
- nirspy-0.0.1/src/nirspy/gui/components/hrf_plot.py +152 -0
- nirspy-0.0.1/src/nirspy/gui/components/param_editor.py +409 -0
- nirspy-0.0.1/src/nirspy/gui/components/param_metadata.py +169 -0
- nirspy-0.0.1/src/nirspy/gui/components/pipeline_view.py +80 -0
- nirspy-0.0.1/src/nirspy/gui/components/probe_viewer.py +169 -0
- nirspy-0.0.1/src/nirspy/gui/components/qc_dashboard.py +98 -0
- nirspy-0.0.1/src/nirspy/gui/components/raw_data_plot.py +96 -0
- nirspy-0.0.1/src/nirspy/gui/components/run_button.py +80 -0
- nirspy-0.0.1/src/nirspy/gui/components/tooltips.py +127 -0
- nirspy-0.0.1/src/nirspy/gui/layouts.py +225 -0
- nirspy-0.0.1/src/nirspy/gui/pages/__init__.py +0 -0
- nirspy-0.0.1/src/nirspy/io/__init__.py +44 -0
- nirspy-0.0.1/src/nirspy/io/converters.py +826 -0
- nirspy-0.0.1/src/nirspy/io/oxysoft_txt.py +358 -0
- nirspy-0.0.1/src/nirspy/io/pipeline_runner.py +195 -0
- nirspy-0.0.1/src/nirspy/io/pipeline_schema.json +80 -0
- nirspy-0.0.1/src/nirspy/io/yaml_serializer.py +247 -0
- nirspy-0.0.1/tests/__init__.py +0 -0
- nirspy-0.0.1/tests/blocks/__init__.py +0 -0
- nirspy-0.0.1/tests/blocks/conftest.py +61 -0
- nirspy-0.0.1/tests/blocks/test_analysis.py +280 -0
- nirspy-0.0.1/tests/blocks/test_manual_exclude.py +96 -0
- nirspy-0.0.1/tests/blocks/test_preprocessing.py +179 -0
- nirspy-0.0.1/tests/blocks/test_quality.py +186 -0
- nirspy-0.0.1/tests/cli/__init__.py +0 -0
- nirspy-0.0.1/tests/cli/test_run.py +145 -0
- nirspy-0.0.1/tests/conftest.py +134 -0
- nirspy-0.0.1/tests/domain/__init__.py +0 -0
- nirspy-0.0.1/tests/domain/test_block.py +163 -0
- nirspy-0.0.1/tests/domain/test_cache.py +134 -0
- nirspy-0.0.1/tests/domain/test_data_types.py +68 -0
- nirspy-0.0.1/tests/domain/test_exceptions.py +133 -0
- nirspy-0.0.1/tests/domain/test_execution.py +403 -0
- nirspy-0.0.1/tests/domain/test_pipeline.py +249 -0
- nirspy-0.0.1/tests/domain/test_validation.py +139 -0
- nirspy-0.0.1/tests/engine/__init__.py +0 -0
- nirspy-0.0.1/tests/engine/test_average_epochs_empty.py +55 -0
- nirspy-0.0.1/tests/engine/test_cache_adapter.py +263 -0
- nirspy-0.0.1/tests/engine/test_mne_adapter.py +140 -0
- nirspy-0.0.1/tests/engine/test_ui_error_messages.py +94 -0
- nirspy-0.0.1/tests/gui/__init__.py +0 -0
- nirspy-0.0.1/tests/gui/test_app_factory.py +83 -0
- nirspy-0.0.1/tests/gui/test_builder.py +345 -0
- nirspy-0.0.1/tests/gui/test_condition_windows_editor.py +106 -0
- nirspy-0.0.1/tests/gui/test_converter_view.py +236 -0
- nirspy-0.0.1/tests/gui/test_execution.py +317 -0
- nirspy-0.0.1/tests/gui/test_hrf_plot.py +109 -0
- nirspy-0.0.1/tests/gui/test_param_editor_list.py +69 -0
- nirspy-0.0.1/tests/gui/test_param_editor_metadata.py +151 -0
- nirspy-0.0.1/tests/gui/test_security_5a.py +202 -0
- nirspy-0.0.1/tests/gui/test_smoke.py +225 -0
- nirspy-0.0.1/tests/io/__init__.py +0 -0
- nirspy-0.0.1/tests/io/test_converters_condnames.py +73 -0
- nirspy-0.0.1/tests/io/test_oxysoft_txt.py +149 -0
- nirspy-0.0.1/tests/io/test_pipeline_runner.py +89 -0
- nirspy-0.0.1/tests/io/test_yaml_serializer.py +200 -0
- nirspy-0.0.1/tests/test_smoke.py +7 -0
- nirspy-0.0.1/third_party/licenses/README.md +9 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Report a defect in NIRSPY
|
|
3
|
+
title: "[bug] "
|
|
4
|
+
labels: ["bug", "triage"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Thanks for taking the time to report a bug. Please fill in the
|
|
10
|
+
details below so we can reproduce it.
|
|
11
|
+
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: what-happened
|
|
14
|
+
attributes:
|
|
15
|
+
label: What happened?
|
|
16
|
+
description: Clear description of the unexpected behaviour.
|
|
17
|
+
placeholder: When I run `nirspy run pipeline.yml ...` the output ...
|
|
18
|
+
validations:
|
|
19
|
+
required: true
|
|
20
|
+
|
|
21
|
+
- type: textarea
|
|
22
|
+
id: expected
|
|
23
|
+
attributes:
|
|
24
|
+
label: What did you expect?
|
|
25
|
+
validations:
|
|
26
|
+
required: true
|
|
27
|
+
|
|
28
|
+
- type: textarea
|
|
29
|
+
id: reproduction
|
|
30
|
+
attributes:
|
|
31
|
+
label: Reproduction steps
|
|
32
|
+
description: Minimal pipeline.yml and dataset (or sample data ref).
|
|
33
|
+
render: shell
|
|
34
|
+
validations:
|
|
35
|
+
required: true
|
|
36
|
+
|
|
37
|
+
- type: input
|
|
38
|
+
id: nirspy-version
|
|
39
|
+
attributes:
|
|
40
|
+
label: NIRSPY version / commit
|
|
41
|
+
placeholder: "0.0.1 or commit sha"
|
|
42
|
+
validations:
|
|
43
|
+
required: true
|
|
44
|
+
|
|
45
|
+
- type: input
|
|
46
|
+
id: python-version
|
|
47
|
+
attributes:
|
|
48
|
+
label: Python version
|
|
49
|
+
placeholder: "3.11.5"
|
|
50
|
+
validations:
|
|
51
|
+
required: true
|
|
52
|
+
|
|
53
|
+
- type: input
|
|
54
|
+
id: os
|
|
55
|
+
attributes:
|
|
56
|
+
label: OS
|
|
57
|
+
placeholder: "Ubuntu 22.04 / Windows 11 / macOS 14"
|
|
58
|
+
validations:
|
|
59
|
+
required: true
|
|
60
|
+
|
|
61
|
+
- type: textarea
|
|
62
|
+
id: traceback
|
|
63
|
+
attributes:
|
|
64
|
+
label: Traceback / logs
|
|
65
|
+
render: python
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
blank_issues_enabled: false
|
|
2
|
+
contact_links:
|
|
3
|
+
- name: Security vulnerability
|
|
4
|
+
url: https://github.com/BrunoFurlanetto/nirspy/security/advisories/new
|
|
5
|
+
about: Please report security issues privately via GitHub Security Advisories.
|
|
6
|
+
- name: Question / discussion
|
|
7
|
+
url: https://github.com/BrunoFurlanetto/nirspy/discussions
|
|
8
|
+
about: Open-ended questions, design discussion, "how do I…?"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Propose a new feature or enhancement
|
|
3
|
+
title: "[feat] "
|
|
4
|
+
labels: ["feature", "triage"]
|
|
5
|
+
body:
|
|
6
|
+
- type: textarea
|
|
7
|
+
id: motivation
|
|
8
|
+
attributes:
|
|
9
|
+
label: Motivation
|
|
10
|
+
description: What problem does this solve? Who benefits?
|
|
11
|
+
validations:
|
|
12
|
+
required: true
|
|
13
|
+
|
|
14
|
+
- type: textarea
|
|
15
|
+
id: proposal
|
|
16
|
+
attributes:
|
|
17
|
+
label: Proposal
|
|
18
|
+
description: High-level description of what should be added or changed.
|
|
19
|
+
validations:
|
|
20
|
+
required: true
|
|
21
|
+
|
|
22
|
+
- type: textarea
|
|
23
|
+
id: alternatives
|
|
24
|
+
attributes:
|
|
25
|
+
label: Alternatives considered
|
|
26
|
+
description: Other approaches you thought about and why this one wins.
|
|
27
|
+
|
|
28
|
+
- type: dropdown
|
|
29
|
+
id: scope
|
|
30
|
+
attributes:
|
|
31
|
+
label: Affected layer
|
|
32
|
+
multiple: true
|
|
33
|
+
options:
|
|
34
|
+
- domain
|
|
35
|
+
- engine
|
|
36
|
+
- blocks
|
|
37
|
+
- io
|
|
38
|
+
- gui
|
|
39
|
+
- cli
|
|
40
|
+
- docs
|
|
41
|
+
- ci
|
|
42
|
+
validations:
|
|
43
|
+
required: true
|
|
44
|
+
|
|
45
|
+
- type: textarea
|
|
46
|
+
id: references
|
|
47
|
+
attributes:
|
|
48
|
+
label: References
|
|
49
|
+
description: Papers, Best Practices fNIRS sections, MNE-NIRS issues, etc.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<!-- Thank you for contributing to NIRSPY. -->
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
<!-- What does this PR change and why? -->
|
|
6
|
+
|
|
7
|
+
## Type of change
|
|
8
|
+
|
|
9
|
+
- [ ] feat — new feature
|
|
10
|
+
- [ ] fix — bug fix
|
|
11
|
+
- [ ] refactor — no behaviour change
|
|
12
|
+
- [ ] test — tests only
|
|
13
|
+
- [ ] docs — documentation only
|
|
14
|
+
- [ ] chore — tooling / dependencies / CI
|
|
15
|
+
|
|
16
|
+
## Linked issues / tasks
|
|
17
|
+
|
|
18
|
+
<!-- Closes #123, refs T-00X -->
|
|
19
|
+
|
|
20
|
+
## Checklist
|
|
21
|
+
|
|
22
|
+
- [ ] `ruff check .` passes
|
|
23
|
+
- [ ] `mypy src/nirspy` passes
|
|
24
|
+
- [ ] `pytest` passes locally
|
|
25
|
+
- [ ] Tests added or updated for behavioural changes
|
|
26
|
+
- [ ] Public API changes documented in CHANGELOG.md
|
|
27
|
+
- [ ] Architecture rule (`domain → engine → gui`) respected
|
|
28
|
+
- [ ] No new GPL dependency introduced (project is BSD-3)
|
|
29
|
+
|
|
30
|
+
## Reproducibility note
|
|
31
|
+
|
|
32
|
+
<!-- If this PR changes pipeline behaviour, confirm: same SNIRF + same
|
|
33
|
+
pipeline.yml produces the same numerical output. -->
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "pip"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
day: "monday"
|
|
8
|
+
open-pull-requests-limit: 5
|
|
9
|
+
labels:
|
|
10
|
+
- "dependencies"
|
|
11
|
+
groups:
|
|
12
|
+
python-deps:
|
|
13
|
+
patterns:
|
|
14
|
+
- "*"
|
|
15
|
+
|
|
16
|
+
- package-ecosystem: "github-actions"
|
|
17
|
+
directory: "/"
|
|
18
|
+
schedule:
|
|
19
|
+
interval: "weekly"
|
|
20
|
+
day: "monday"
|
|
21
|
+
open-pull-requests-limit: 3
|
|
22
|
+
labels:
|
|
23
|
+
- "dependencies"
|
|
24
|
+
- "ci"
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
tags: ["v*"]
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: [main]
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
12
|
+
cancel-in-progress: true
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
lint-and-test:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
strategy:
|
|
18
|
+
fail-fast: false
|
|
19
|
+
matrix:
|
|
20
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v6
|
|
24
|
+
|
|
25
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
26
|
+
uses: actions/setup-python@v6
|
|
27
|
+
with:
|
|
28
|
+
python-version: ${{ matrix.python-version }}
|
|
29
|
+
cache: "pip"
|
|
30
|
+
cache-dependency-path: "pyproject.toml"
|
|
31
|
+
|
|
32
|
+
- name: Install uv
|
|
33
|
+
run: pip install uv
|
|
34
|
+
|
|
35
|
+
- name: Install project
|
|
36
|
+
run: uv pip install --system -e ".[dev]" pytest-cov
|
|
37
|
+
|
|
38
|
+
- name: Ruff
|
|
39
|
+
run: ruff check .
|
|
40
|
+
|
|
41
|
+
- name: Mypy
|
|
42
|
+
run: mypy src/nirspy
|
|
43
|
+
|
|
44
|
+
- name: Pytest
|
|
45
|
+
run: pytest --cov=nirspy --cov-report=xml --cov-report=term
|
|
46
|
+
|
|
47
|
+
- name: Upload coverage
|
|
48
|
+
if: matrix.python-version == '3.12'
|
|
49
|
+
uses: actions/upload-artifact@v7
|
|
50
|
+
with:
|
|
51
|
+
name: coverage-xml
|
|
52
|
+
path: coverage.xml
|
|
53
|
+
if-no-files-found: warn
|
|
54
|
+
|
|
55
|
+
publish:
|
|
56
|
+
name: Publish to PyPI
|
|
57
|
+
needs: lint-and-test
|
|
58
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
|
59
|
+
runs-on: ubuntu-latest
|
|
60
|
+
environment:
|
|
61
|
+
name: pypi
|
|
62
|
+
url: https://pypi.org/project/nirspy/
|
|
63
|
+
permissions:
|
|
64
|
+
id-token: write
|
|
65
|
+
steps:
|
|
66
|
+
- uses: actions/checkout@v6
|
|
67
|
+
|
|
68
|
+
- name: Set up Python
|
|
69
|
+
uses: actions/setup-python@v6
|
|
70
|
+
with:
|
|
71
|
+
python-version: "3.12"
|
|
72
|
+
|
|
73
|
+
- name: Build sdist + wheel
|
|
74
|
+
run: |
|
|
75
|
+
python -m pip install --upgrade build
|
|
76
|
+
python -m build
|
|
77
|
+
|
|
78
|
+
- name: Publish to PyPI (Trusted Publisher / OIDC)
|
|
79
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
nirspy-0.0.1/.gitignore
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
MANIFEST
|
|
23
|
+
|
|
24
|
+
# Virtual envs
|
|
25
|
+
.venv/
|
|
26
|
+
venv/
|
|
27
|
+
env/
|
|
28
|
+
ENV/
|
|
29
|
+
|
|
30
|
+
# uv
|
|
31
|
+
.uv/
|
|
32
|
+
|
|
33
|
+
# Testing / coverage
|
|
34
|
+
.pytest_cache/
|
|
35
|
+
.coverage
|
|
36
|
+
.coverage.*
|
|
37
|
+
htmlcov/
|
|
38
|
+
.tox/
|
|
39
|
+
.nox/
|
|
40
|
+
coverage.xml
|
|
41
|
+
*.cover
|
|
42
|
+
|
|
43
|
+
# Type checkers
|
|
44
|
+
.mypy_cache/
|
|
45
|
+
.ruff_cache/
|
|
46
|
+
.pyre/
|
|
47
|
+
|
|
48
|
+
# Cache
|
|
49
|
+
.cache/
|
|
50
|
+
diskcache/
|
|
51
|
+
|
|
52
|
+
# Docs build
|
|
53
|
+
site/
|
|
54
|
+
|
|
55
|
+
# IDE
|
|
56
|
+
.vscode/
|
|
57
|
+
.idea/
|
|
58
|
+
*.swp
|
|
59
|
+
*.swo
|
|
60
|
+
.DS_Store
|
|
61
|
+
|
|
62
|
+
# Env
|
|
63
|
+
.env
|
|
64
|
+
.env.local
|
|
65
|
+
.env.agents
|
|
66
|
+
|
|
67
|
+
# Project-specific
|
|
68
|
+
*.snirf.cache
|
|
69
|
+
examples/data/*.snirf
|
|
70
|
+
!examples/data/.gitkeep
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12.2
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Todas as mudanças relevantes do projeto serão documentadas aqui.
|
|
4
|
+
|
|
5
|
+
Formato baseado em [Keep a Changelog](https://keepachangelog.com/),
|
|
6
|
+
versionamento por [SemVer](https://semver.org/).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.0] - 2026-05-21
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Camada `domain/`: `Pipeline`, `Block` Protocol, `DataType`, `BlockSpec`, `BlockResult`, `Context`, `CacheProtocol`, exceções (`NirspyError`, `ValidationError`, `ExecutionError`).
|
|
14
|
+
- Camada `engine/`: `MNEAdapter` com `load_snirf`, `raw_to_od`, `beer_lambert`, `bandpass_filter`, `scalp_coupling_index`, `prune_channels`, `block_average`. `DiskCacheAdapter` com `JSONDisk` (sem pickle, S-01).
|
|
15
|
+
- Blocos: `LoadSnirf`, `OpticalDensity`, `BeerLambert`, `BandpassFilter`, `ScalpCouplingIndex`, `PruneChannels`, `BlockAverage`, `ManualChannelExclude`.
|
|
16
|
+
- IO: `yaml_serializer.dump_pipeline`/`load_pipeline`, conversor `.nirs ↔ .snirf` (`io/converters.py`), conversor Oxysoft `.txt → .snirf` (`io/oxysoft_txt.py`).
|
|
17
|
+
- CLI: `nirspy run pipeline.yml --input X --output Y`, `nirspy serve`, `nirspy --version`.
|
|
18
|
+
- GUI: Dash app factory, layout de três painéis, builder de pipeline (catalog + reorder + remove + toggle), param editor enriquecido (labels, tooltips, ranges, Optional checkbox, multiselect de canais), visualização de execução (raw, probe, QC heatmap, HRF μM), tab Convert (`.nirs↔.snirf` + Oxysoft `.txt→.snirf`).
|
|
19
|
+
- **T-012 — Janelas temporais por condição em `BlockAverage`**: novo dataclass `ConditionWindow`, parâmetro `per_condition_windows`, método `MNEAdapter.create_epochs_per_condition`, editor GUI auto-populado a partir do SNIRF, YAML round-trip retrocompatível.
|
|
20
|
+
- Segurança Etapa 5A: validação de path SNIRF (S-02), sample-count guard (S-001), bloqueio de h5py external links (S-002), `O_EXCL` em escrita (S-003), opção `strip_pii` em conversores (I-001), serialização JSON em cache (S-01).
|
|
21
|
+
- Templates de issue/PR, política de segurança, dependabot, cache pip e cobertura no CI.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
- CI: removido `pytest-dash` das dev deps (unmaintained, incompatível com selenium ≥4.10).
|
|
25
|
+
- CI: `mypy` agora bloqueia merge (era `continue-on-error`).
|
|
26
|
+
- `JSONDisk.store/fetch` delegam ao `Disk` base — corrige overwrite e persistência entre instâncias.
|
|
27
|
+
- `BlockAverageBlock.run`: keys desconhecidas em `per_condition_windows` viram `UserWarning` (em vez de raise) — pipeline robusta a troca de SNIRF com conjunto de condições diferente.
|
|
28
|
+
|
|
29
|
+
### Removed
|
|
30
|
+
- `pytest-dash` das dev dependencies.
|
nirspy-0.0.1/CLAUDE.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# CLAUDE.md — nirspy
|
|
2
|
+
|
|
3
|
+
> Configurações do projeto para o time de agentes.
|
|
4
|
+
> Complementa e sobrescreve o CLAUDE.md global quando necessário.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Projeto
|
|
9
|
+
|
|
10
|
+
**Nome:** nirspy
|
|
11
|
+
**Descrição:** GUI fNIRS-first em Python — builder modular de pipeline sobre MNE-NIRS, distribuída como open source (BSD-3).
|
|
12
|
+
**Stack:** Python 3.10+ · Dash · Plotly · MNE-NIRS · uv · hatchling · pytest · ruff · mypy
|
|
13
|
+
**Repositório:** https://github.com/BrunoFurlanetto/nirspy.git
|
|
14
|
+
**Ambiente local:** `nirspy serve` → `http://127.0.0.1:8050`
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Vault (Obsidian)
|
|
19
|
+
|
|
20
|
+
**Path do projeto:** `Dev projects/nirspy`
|
|
21
|
+
**Memory:** `Dev projects/nirspy/Memory.md`
|
|
22
|
+
**Session Log:** `Dev projects/nirspy/session-log.md`
|
|
23
|
+
**Planejamentos:** `Dev projects/nirspy/features/`
|
|
24
|
+
**Visão e arquitetura:** `Dev projects/nirspy/visao-do-produto.md`, `Dev projects/nirspy/arquitetura.md`, `Dev projects/nirspy/roadmap.md`
|
|
25
|
+
|
|
26
|
+
### Abertura de sessão
|
|
27
|
+
|
|
28
|
+
Ler em paralelo antes de qualquer task:
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
mcp_obsidian: view → Dev projects/nirspy/Memory.md
|
|
32
|
+
mcp_obsidian: view → Dev projects/nirspy/session-log.md
|
|
33
|
+
mcp_obsidian: view → Dev projects/_memory.md (ADRs globais)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Se a task envolve uma feature, ler também:
|
|
37
|
+
```
|
|
38
|
+
mcp_obsidian: view → Dev projects/nirspy/features/<nome-da-feature>.md
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Sempre consultar `Dev projects/nirspy/arquitetura.md` antes de criar arquivos novos — a regra das três camadas (`domain` → `engine` → `gui`) é estrita.
|
|
42
|
+
|
|
43
|
+
### Fechamento de sessão
|
|
44
|
+
|
|
45
|
+
Seguir protocolo condicional do CLAUDE.md global. Quando registrar:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
mcp_obsidian: str_replace → Dev projects/nirspy/session-log.md
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
ADR novo (decisão de design): adicionar **antes** de fechar log:
|
|
52
|
+
```
|
|
53
|
+
mcp_obsidian: str_replace → Dev projects/nirspy/Memory.md
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Branches protegidas
|
|
59
|
+
|
|
60
|
+
Nunca commitar diretamente nem criar branches a partir de:
|
|
61
|
+
- `main`
|
|
62
|
+
|
|
63
|
+
Orchestrator sempre confirma branch base com Lead antes de criar nova branch.
|
|
64
|
+
|
|
65
|
+
### Convenção de branches
|
|
66
|
+
```
|
|
67
|
+
feature/T-xxx-nome-curto
|
|
68
|
+
fix/T-xxx-descricao
|
|
69
|
+
chore/T-xxx-descricao
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Como rodar
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# setup
|
|
78
|
+
uv venv
|
|
79
|
+
uv pip install -e ".[dev]"
|
|
80
|
+
|
|
81
|
+
# dev server
|
|
82
|
+
nirspy serve
|
|
83
|
+
|
|
84
|
+
# testes
|
|
85
|
+
pytest
|
|
86
|
+
|
|
87
|
+
# lint + types
|
|
88
|
+
ruff check .
|
|
89
|
+
mypy src/nirspy
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Ownership dos agentes
|
|
95
|
+
|
|
96
|
+
Arquitetura em três camadas (`domain` → `engine` → `gui`) determina ownership.
|
|
97
|
+
|
|
98
|
+
| Agente | Pode criar/editar | Somente leitura |
|
|
99
|
+
|--------|-------------------|-----------------|
|
|
100
|
+
| `dev` | `src/nirspy/gui/`, `src/nirspy/cli/`, `src/nirspy/blocks/` (lógica não-engine), `src/nirspy/io/`, `examples/`, `docs/` | `domain/`, `engine/` (precisa contrato dba) |
|
|
101
|
+
| `dba` | `src/nirspy/domain/`, `src/nirspy/engine/`, `src/nirspy/blocks/` (camada de execução MNE), `examples/pipelines/*.yml` (schema de pipeline) | `gui/`, `cli/` |
|
|
102
|
+
| `qa` | `tests/` | todo o código de produção |
|
|
103
|
+
| `security` | `docs/security/` (criar se necessário) | todo o codebase |
|
|
104
|
+
| `reviewer` | — | todo o codebase |
|
|
105
|
+
|
|
106
|
+
> Note: neste projeto `dba` cobre **camada de dados/domínio + adapter MNE-NIRS**, não banco relacional. Ele detém o contrato `Pipeline`/`Block`/`DataType` (ADR-005) e o adapter `engine/mne_adapter.py`. Qualquer mudança em estrutura de domínio passa por contrato dele antes do dev tocar na GUI.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Convenções
|
|
111
|
+
|
|
112
|
+
### Commits
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
tipo(escopo): mensagem imperativa curta
|
|
116
|
+
|
|
117
|
+
Agente: <Nome> (<role>)
|
|
118
|
+
Task: T-xxx
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Tipos válidos: `feat`, `fix`, `refactor`, `test`, `docs`, `chore`, `perf`, `style`
|
|
122
|
+
|
|
123
|
+
Escopos sugeridos: `domain`, `engine`, `blocks`, `gui`, `io`, `cli`, `ci`, `docs`.
|
|
124
|
+
|
|
125
|
+
### Estilo Python
|
|
126
|
+
- `ruff` configurado em `pyproject.toml` (E, F, I, B, UP, SIM)
|
|
127
|
+
- `mypy --strict` no pacote `nirspy`
|
|
128
|
+
- Linha máx 100 caracteres
|
|
129
|
+
- Type hints obrigatórios em código novo (camada `domain` em particular)
|
|
130
|
+
|
|
131
|
+
### Regra de ouro arquitetural (ADR-005)
|
|
132
|
+
- `domain/` **não importa** Dash, Plotly, MNE, MNE-NIRS — apenas stdlib + tipagem
|
|
133
|
+
- `engine/` importa `domain` + MNE/MNE-NIRS — nunca Dash
|
|
134
|
+
- `gui/` pode importar tudo do projeto
|
|
135
|
+
- Antes de criar arquivo novo, identificar a camada e respeitar a direção dos imports
|
|
136
|
+
|
|
137
|
+
### Pipelines como contrato
|
|
138
|
+
- Pipelines salvas em YAML são **API pública** do projeto
|
|
139
|
+
- Mudança breaking no schema de pipeline requer ADR e bump de minor (v0.x → v0.x+1)
|
|
140
|
+
- Round-trip YAML → Pipeline → YAML deve ser idêntico (golden tests em `tests/io/`)
|
|
141
|
+
|
|
142
|
+
### Open source
|
|
143
|
+
Toda decisão técnica deve considerar:
|
|
144
|
+
- Reprodutibilidade (mesma pipeline + mesmo SNIRF = mesmo resultado em qualquer máquina)
|
|
145
|
+
- Compatibilidade com Best Practices fNIRS (Yücel et al., 2021)
|
|
146
|
+
- Acessibilidade para usuários que não programam
|
|
147
|
+
- Manutenibilidade por dev solo
|
|
148
|
+
|
|
149
|
+
### Dependências
|
|
150
|
+
- Não adicionar dependência sem justificativa em PR
|
|
151
|
+
- Preferir biblioteca já presente no ecossistema MNE/scipy
|
|
152
|
+
- Nunca acoplar a algo GPL — projeto é BSD-3
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Stack-específico
|
|
157
|
+
|
|
158
|
+
### Estrutura de pastas (src layout)
|
|
159
|
+
```
|
|
160
|
+
src/nirspy/
|
|
161
|
+
├── domain/ # camada 1 — pura
|
|
162
|
+
├── engine/ # camada 2 — adapter MNE-NIRS
|
|
163
|
+
├── blocks/ # blocos concretos (load, OD, mBLL, motion, QC, analysis, export)
|
|
164
|
+
├── io/ # serializadores YAML/JSON de pipelines
|
|
165
|
+
├── gui/ # Dash app (components/, pages/, callbacks/)
|
|
166
|
+
└── cli/ # entry point `nirspy`
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Testes
|
|
170
|
+
- `tests/domain/` — unit puro, <100ms
|
|
171
|
+
- `tests/engine/` — integração com fixtures MNE
|
|
172
|
+
- `tests/blocks/` — integração por bloco
|
|
173
|
+
- `tests/io/` — round-trip golden files
|
|
174
|
+
- `tests/gui/` — smoke tests via `pytest-dash`
|
|
175
|
+
|
|
176
|
+
Dataset de referência: MNE-NIRS sample dataset (BSD-3, redistribuível).
|
|
177
|
+
|
|
178
|
+
### CI
|
|
179
|
+
GitHub Actions em `.github/workflows/ci.yml` — matrix Python 3.10/3.11/3.12, ruff + mypy + pytest.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
This project adopts the **[Contributor Covenant 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct/)**
|
|
4
|
+
as its code of conduct.
|
|
5
|
+
|
|
6
|
+
Full text: https://www.contributor-covenant.org/version/2/1/code_of_conduct/
|
|
7
|
+
|
|
8
|
+
Official translations: https://www.contributor-covenant.org/translations/
|
|
9
|
+
|
|
10
|
+
## Enforcement
|
|
11
|
+
|
|
12
|
+
Conduct that violates the code may be reported to the maintainer:
|
|
13
|
+
|
|
14
|
+
- Email: bruno.furlanetto@hotmail.com
|
|
15
|
+
|
|
16
|
+
Reports are handled confidentially. Expected response within 7 days.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Contributing to NIRSPY
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in contributing. This document describes the minimal
|
|
4
|
+
flow for running the project, opening issues, and submitting pull requests.
|
|
5
|
+
|
|
6
|
+
## Local setup
|
|
7
|
+
|
|
8
|
+
Prerequisites: Python 3.10+. [`uv`](https://docs.astral.sh/uv/) is supported
|
|
9
|
+
but not required.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
git clone https://github.com/BrunoFurlanetto/nirspy.git
|
|
13
|
+
cd nirspy
|
|
14
|
+
python -m venv .venv
|
|
15
|
+
# Linux/macOS
|
|
16
|
+
source .venv/bin/activate
|
|
17
|
+
# Windows PowerShell
|
|
18
|
+
.venv\Scripts\Activate.ps1
|
|
19
|
+
|
|
20
|
+
pip install -e ".[dev]"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Run tests, lint, types
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pytest
|
|
27
|
+
ruff check .
|
|
28
|
+
mypy src/nirspy
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Run the app
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
nirspy serve
|
|
35
|
+
# open http://127.0.0.1:8050
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Issues
|
|
39
|
+
|
|
40
|
+
Before opening an issue:
|
|
41
|
+
|
|
42
|
+
1. Check that a similar issue is not already open or closed.
|
|
43
|
+
2. For bugs: describe reproduction steps, expected vs observed behaviour,
|
|
44
|
+
Python version, and `nirspy` version.
|
|
45
|
+
3. For features: review the [roadmap](docs/roadmap.md) — it may already be
|
|
46
|
+
planned. Otherwise describe the problem before the solution.
|
|
47
|
+
|
|
48
|
+
Use the [issue templates](.github/ISSUE_TEMPLATE/) — blank issues are
|
|
49
|
+
disabled.
|
|
50
|
+
|
|
51
|
+
## Branches
|
|
52
|
+
|
|
53
|
+
Always branched off `main`:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
feature/T-xxx-short-name
|
|
57
|
+
fix/T-xxx-description
|
|
58
|
+
chore/T-xxx-description
|
|
59
|
+
docs/T-xxx-description
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`main` is protected — no direct commits. All changes go through a PR.
|
|
63
|
+
|
|
64
|
+
## Commits
|
|
65
|
+
|
|
66
|
+
Short Conventional Commits style:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
type(scope): short imperative subject
|
|
70
|
+
|
|
71
|
+
Optional body explaining the why.
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Types: `feat`, `fix`, `refactor`, `test`, `docs`, `chore`, `perf`, `style`.
|
|
75
|
+
Suggested scopes: `domain`, `engine`, `blocks`, `gui`, `io`, `cli`, `ci`, `docs`.
|
|
76
|
+
|
|
77
|
+
## Pull requests
|
|
78
|
+
|
|
79
|
+
1. Branch from `main`.
|
|
80
|
+
2. Lint, types and tests pass locally.
|
|
81
|
+
3. Open a PR against `main` with a clear description: what changes, why, and
|
|
82
|
+
how to test.
|
|
83
|
+
4. CI must pass (ruff + mypy + pytest matrix on Python 3.10/3.11/3.12).
|
|
84
|
+
5. Wait for review. Squash-merge is the default.
|
|
85
|
+
|
|
86
|
+
## Architecture
|
|
87
|
+
|
|
88
|
+
Before creating new files, read [`docs/architecture.md`](docs/architecture.md).
|
|
89
|
+
The golden rule:
|
|
90
|
+
|
|
91
|
+
- `domain/` must not import Dash, Plotly, or MNE.
|
|
92
|
+
- `engine/` may import `domain` + MNE/MNE-NIRS, but not Dash.
|
|
93
|
+
- `gui/` may import everything from the project.
|
|
94
|
+
|
|
95
|
+
PRs that violate this rule will be rejected.
|
|
96
|
+
|
|
97
|
+
## Tests
|
|
98
|
+
|
|
99
|
+
- `tests/domain/` — pure unit tests, <100 ms.
|
|
100
|
+
- `tests/engine/` and `tests/blocks/` — integration with fixtures.
|
|
101
|
+
- `tests/io/` — round-trip golden files.
|
|
102
|
+
- `tests/gui/` — smoke tests via Dash test client.
|
|
103
|
+
|
|
104
|
+
Minimum coverage target for `domain/`: 80%.
|
|
105
|
+
|
|
106
|
+
## Code of conduct
|
|
107
|
+
|
|
108
|
+
By participating in this project you agree to follow the
|
|
109
|
+
[Code of Conduct](CODE_OF_CONDUCT.md).
|
|
110
|
+
|
|
111
|
+
## License
|
|
112
|
+
|
|
113
|
+
Contributions are accepted under the project's
|
|
114
|
+
[BSD-3-Clause license](LICENSE).
|