neurospatial 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. neurospatial-0.1.0/.claude/commands/freshstart.md +60 -0
  2. neurospatial-0.1.0/.gitattributes +2 -0
  3. neurospatial-0.1.0/.github/workflows/docs.yml +65 -0
  4. neurospatial-0.1.0/.github/workflows/publish.yml +83 -0
  5. neurospatial-0.1.0/.github/workflows/release.yml +116 -0
  6. neurospatial-0.1.0/.github/workflows/test.yml +63 -0
  7. neurospatial-0.1.0/.gitignore +182 -0
  8. neurospatial-0.1.0/.pre-commit-config.yaml +35 -0
  9. neurospatial-0.1.0/.python-version +1 -0
  10. neurospatial-0.1.0/CHANGELOG.md +40 -0
  11. neurospatial-0.1.0/CLAUDE.md +723 -0
  12. neurospatial-0.1.0/CODE_REVIEW_REPORT.md +944 -0
  13. neurospatial-0.1.0/LICENSE +21 -0
  14. neurospatial-0.1.0/PKG-INFO +402 -0
  15. neurospatial-0.1.0/README.md +347 -0
  16. neurospatial-0.1.0/coverage.json +1 -0
  17. neurospatial-0.1.0/docs/api/index.md +77 -0
  18. neurospatial-0.1.0/docs/changelog.md +40 -0
  19. neurospatial-0.1.0/docs/contributing.md +262 -0
  20. neurospatial-0.1.0/docs/dimensionality_support.md +242 -0
  21. neurospatial-0.1.0/docs/examples/.gitignore +2 -0
  22. neurospatial-0.1.0/docs/examples/index.md +130 -0
  23. neurospatial-0.1.0/docs/gen_ref_pages.py +44 -0
  24. neurospatial-0.1.0/docs/getting-started/core-concepts.md +351 -0
  25. neurospatial-0.1.0/docs/getting-started/index.md +25 -0
  26. neurospatial-0.1.0/docs/getting-started/installation.md +148 -0
  27. neurospatial-0.1.0/docs/getting-started/quickstart.md +285 -0
  28. neurospatial-0.1.0/docs/includes/abbreviations.md +14 -0
  29. neurospatial-0.1.0/docs/index.md +123 -0
  30. neurospatial-0.1.0/docs/javascripts/mathjax.js +17 -0
  31. neurospatial-0.1.0/docs/stylesheets/extra.css +53 -0
  32. neurospatial-0.1.0/docs/sync_notebooks.py +17 -0
  33. neurospatial-0.1.0/docs/user-guide/alignment.md +35 -0
  34. neurospatial-0.1.0/docs/user-guide/composite-environments.md +26 -0
  35. neurospatial-0.1.0/docs/user-guide/environments.md +255 -0
  36. neurospatial-0.1.0/docs/user-guide/index.md +51 -0
  37. neurospatial-0.1.0/docs/user-guide/layout-engines.md +241 -0
  38. neurospatial-0.1.0/docs/user-guide/regions.md +54 -0
  39. neurospatial-0.1.0/docs/user-guide/workflows.md +427 -0
  40. neurospatial-0.1.0/examples/01_introduction_basics.ipynb +922 -0
  41. neurospatial-0.1.0/examples/02_layout_engines.ipynb +798 -0
  42. neurospatial-0.1.0/examples/03_morphological_operations.ipynb +1305 -0
  43. neurospatial-0.1.0/examples/04_regions_of_interest.ipynb +1061 -0
  44. neurospatial-0.1.0/examples/05_track_linearization.ipynb +1336 -0
  45. neurospatial-0.1.0/examples/06_composite_environments.ipynb +1455 -0
  46. neurospatial-0.1.0/examples/07_advanced_operations.ipynb +1450 -0
  47. neurospatial-0.1.0/examples/08_complete_workflow.ipynb +1685 -0
  48. neurospatial-0.1.0/examples/README.md +254 -0
  49. neurospatial-0.1.0/mkdocs.yml +169 -0
  50. neurospatial-0.1.0/pyproject.toml +246 -0
  51. neurospatial-0.1.0/pytest.ini +10 -0
  52. neurospatial-0.1.0/src/neurospatial/__init__.py +35 -0
  53. neurospatial-0.1.0/src/neurospatial/_constants.py +75 -0
  54. neurospatial-0.1.0/src/neurospatial/_logging.py +202 -0
  55. neurospatial-0.1.0/src/neurospatial/alignment.py +565 -0
  56. neurospatial-0.1.0/src/neurospatial/calibration.py +68 -0
  57. neurospatial-0.1.0/src/neurospatial/composite.py +1152 -0
  58. neurospatial-0.1.0/src/neurospatial/distance.py +258 -0
  59. neurospatial-0.1.0/src/neurospatial/environment.py +2182 -0
  60. neurospatial-0.1.0/src/neurospatial/io.py +513 -0
  61. neurospatial-0.1.0/src/neurospatial/layout/__init__.py +26 -0
  62. neurospatial-0.1.0/src/neurospatial/layout/base.py +221 -0
  63. neurospatial-0.1.0/src/neurospatial/layout/engines/__init__.py +0 -0
  64. neurospatial-0.1.0/src/neurospatial/layout/engines/graph.py +402 -0
  65. neurospatial-0.1.0/src/neurospatial/layout/engines/hexagonal.py +323 -0
  66. neurospatial-0.1.0/src/neurospatial/layout/engines/image_mask.py +143 -0
  67. neurospatial-0.1.0/src/neurospatial/layout/engines/masked_grid.py +111 -0
  68. neurospatial-0.1.0/src/neurospatial/layout/engines/regular_grid.py +221 -0
  69. neurospatial-0.1.0/src/neurospatial/layout/engines/shapely_polygon.py +229 -0
  70. neurospatial-0.1.0/src/neurospatial/layout/engines/triangular_mesh.py +463 -0
  71. neurospatial-0.1.0/src/neurospatial/layout/factories.py +179 -0
  72. neurospatial-0.1.0/src/neurospatial/layout/helpers/__init__.py +0 -0
  73. neurospatial-0.1.0/src/neurospatial/layout/helpers/graph.py +510 -0
  74. neurospatial-0.1.0/src/neurospatial/layout/helpers/hexagonal.py +630 -0
  75. neurospatial-0.1.0/src/neurospatial/layout/helpers/regular_grid.py +612 -0
  76. neurospatial-0.1.0/src/neurospatial/layout/helpers/triangular_mesh.py +242 -0
  77. neurospatial-0.1.0/src/neurospatial/layout/helpers/utils.py +1036 -0
  78. neurospatial-0.1.0/src/neurospatial/layout/mixins.py +393 -0
  79. neurospatial-0.1.0/src/neurospatial/layout/validation.py +416 -0
  80. neurospatial-0.1.0/src/neurospatial/py.typed +0 -0
  81. neurospatial-0.1.0/src/neurospatial/regions/__init__.py +42 -0
  82. neurospatial-0.1.0/src/neurospatial/regions/core.py +508 -0
  83. neurospatial-0.1.0/src/neurospatial/regions/io.py +939 -0
  84. neurospatial-0.1.0/src/neurospatial/regions/ops.py +346 -0
  85. neurospatial-0.1.0/src/neurospatial/regions/plot.py +159 -0
  86. neurospatial-0.1.0/src/neurospatial/spatial.py +188 -0
  87. neurospatial-0.1.0/src/neurospatial/transforms.py +798 -0
  88. neurospatial-0.1.0/tests/conftest.py +184 -0
  89. neurospatial-0.1.0/tests/layout/test_graph_utils.py +312 -0
  90. neurospatial-0.1.0/tests/layout/test_hex_grid_utils.py +162 -0
  91. neurospatial-0.1.0/tests/layout/test_layout_engine.py +474 -0
  92. neurospatial-0.1.0/tests/layout/test_regular_grid_layout.py +309 -0
  93. neurospatial-0.1.0/tests/layout/test_regular_grid_utils.py +280 -0
  94. neurospatial-0.1.0/tests/layout/test_triangular_mesh.py +539 -0
  95. neurospatial-0.1.0/tests/layout/test_utils.py +178 -0
  96. neurospatial-0.1.0/tests/layout/test_validation.py +389 -0
  97. neurospatial-0.1.0/tests/regions/test_core.py +301 -0
  98. neurospatial-0.1.0/tests/regions/test_ops.py +492 -0
  99. neurospatial-0.1.0/tests/regions/test_plot.py +429 -0
  100. neurospatial-0.1.0/tests/regions/test_serialization.py +690 -0
  101. neurospatial-0.1.0/tests/test_alignment.py +158 -0
  102. neurospatial-0.1.0/tests/test_bin_size_required.py +237 -0
  103. neurospatial-0.1.0/tests/test_calibration.py +236 -0
  104. neurospatial-0.1.0/tests/test_check_fitted_error.py +161 -0
  105. neurospatial-0.1.0/tests/test_common_pitfalls.py +389 -0
  106. neurospatial-0.1.0/tests/test_composite.py +267 -0
  107. neurospatial-0.1.0/tests/test_composite_dimension_error.py +206 -0
  108. neurospatial-0.1.0/tests/test_composite_new_methods.py +371 -0
  109. neurospatial-0.1.0/tests/test_composite_validation.py +168 -0
  110. neurospatial-0.1.0/tests/test_distance.py +383 -0
  111. neurospatial-0.1.0/tests/test_distance_new.py +134 -0
  112. neurospatial-0.1.0/tests/test_environment.py +911 -0
  113. neurospatial-0.1.0/tests/test_environment_error_paths.py +334 -0
  114. neurospatial-0.1.0/tests/test_environment_info.py +282 -0
  115. neurospatial-0.1.0/tests/test_environment_repr.py +294 -0
  116. neurospatial-0.1.0/tests/test_error_message_standardization.py +345 -0
  117. neurospatial-0.1.0/tests/test_factory_selection_guide.py +104 -0
  118. neurospatial-0.1.0/tests/test_io.py +159 -0
  119. neurospatial-0.1.0/tests/test_spatial.py +118 -0
  120. neurospatial-0.1.0/tests/test_transforms_new.py +231 -0
  121. neurospatial-0.1.0/tests/test_type_validation.py +279 -0
  122. neurospatial-0.1.0/tests/test_validation_new.py +105 -0
  123. neurospatial-0.1.0/uv.lock +3803 -0
@@ -0,0 +1,60 @@
1
+ I'm working on the neurospatial project.
2
+
3
+ Start now by reading the files and telling me which task you'll work on first.
4
+
5
+ Your workflow MUST be:
6
+
7
+ First, read these files IN ORDER:
8
+ CLAUDE.md (implementation guide)
9
+ docs/SCRATCHPAD.md (notes and current status)
10
+ docs/TASKS.md (current tasks)
11
+
12
+ THEN if you need more detail:
13
+ docs/UX_IMPLEMENTATION_PLAN.md (overall project plan)
14
+
15
+ Find the FIRST unchecked [ ] task in TASKS.md
16
+
17
+ For EVERY feature, follow TDD:
18
+ a. Create the TEST file first
19
+ b. Run the test and verify it FAILS
20
+ c. Only then create the implementation
21
+ d. Run test until it PASSES
22
+ e. Apply review agents (code-reviewer, other relevant agents)
23
+ f. Refactor for clarity and efficiency based on feedback
24
+ g. Add/Update docstrings and types.
25
+
26
+ Update TASKS.md checkboxes as you complete items.
27
+
28
+ Update SCRATCHPAD.md with notes
29
+
30
+ Commit frequently with messages like "feat(F24): implement error handling"
31
+
32
+ Do not change tests or skip tests to match broken code. Ask permission to change requirements if needed.
33
+
34
+ ## Remember
35
+
36
+ - **Read before you code** - Use Read tool to understand context
37
+ - **Test before you implement** - TDD is mandatory
38
+ - **Verify before you claim completion** - Use verification-before-completion skill
39
+ - **Ask when uncertain** - Better to ask than assume
40
+ - **Document as you go** - Update SCRATCHPAD.md with decisions/blockers
41
+
42
+ ---
43
+
44
+ ## When Blocked
45
+
46
+ If you encounter any of these, STOP and document in SCRATCHPAD.md:
47
+
48
+ 1. **Unclear requirements** - Ask for clarification
49
+ 2. **Unexpected test failures** - Use systematic-debugging skill
50
+ 3. **Conflicting requirements** - Ask for guidance
51
+ 4. **Need to change baselines** - Request approval
52
+ 5. **Missing dependencies** - Document and ask for help
53
+
54
+ **Never proceed with assumptions** - this is critical scientific infrastructure.
55
+
56
+ You MUST investigate any test failures using the systematic debugging skill. Flaky tests are not an acceptable reason to skip or ignore tests.
57
+
58
+ ---
59
+
60
+ Now tell me: **What task are you working on next?**
@@ -0,0 +1,2 @@
1
+ # Auto detect text files and perform LF normalization
2
+ * text=auto
@@ -0,0 +1,65 @@
1
+ name: Documentation
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+ branches:
9
+ - main
10
+
11
+ permissions:
12
+ contents: read
13
+ pages: write
14
+ id-token: write
15
+
16
+ # Allow only one concurrent deployment
17
+ concurrency:
18
+ group: "pages"
19
+ cancel-in-progress: false
20
+
21
+ jobs:
22
+ build:
23
+ runs-on: ubuntu-latest
24
+ steps:
25
+ - uses: actions/checkout@v4
26
+
27
+ - name: Set up Python
28
+ uses: actions/setup-python@v5
29
+ with:
30
+ python-version: '3.13'
31
+
32
+ - name: Install uv
33
+ uses: astral-sh/setup-uv@v3
34
+ with:
35
+ version: "latest"
36
+
37
+ - name: Install dependencies
38
+ run: |
39
+ uv sync --extra docs
40
+
41
+ - name: Sync example notebooks
42
+ run: |
43
+ uv run python docs/sync_notebooks.py
44
+
45
+ - name: Build documentation
46
+ run: |
47
+ uv run mkdocs build --strict
48
+
49
+ - name: Upload artifact
50
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
51
+ uses: actions/upload-pages-artifact@v3
52
+ with:
53
+ path: ./site
54
+
55
+ deploy:
56
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
57
+ needs: build
58
+ runs-on: ubuntu-latest
59
+ environment:
60
+ name: github-pages
61
+ url: ${{ steps.deployment.outputs.page_url }}
62
+ steps:
63
+ - name: Deploy to GitHub Pages
64
+ id: deployment
65
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,83 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ build:
12
+ name: Build distribution
13
+ runs-on: ubuntu-latest
14
+
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - name: Set up Python
19
+ uses: actions/setup-python@v5
20
+ with:
21
+ python-version: '3.13'
22
+
23
+ - name: Install uv
24
+ uses: astral-sh/setup-uv@v3
25
+ with:
26
+ version: "latest"
27
+
28
+ - name: Install dependencies
29
+ run: |
30
+ uv sync --extra dev
31
+
32
+ - name: Build package
33
+ run: |
34
+ uv build
35
+
36
+ - name: Store the distribution packages
37
+ uses: actions/upload-artifact@v4
38
+ with:
39
+ name: python-package-distributions
40
+ path: dist/
41
+
42
+ publish-to-pypi:
43
+ name: Publish to PyPI
44
+ needs: [build]
45
+ runs-on: ubuntu-latest
46
+ environment:
47
+ name: pypi
48
+ url: https://pypi.org/p/neurospatial
49
+ permissions:
50
+ id-token: write # IMPORTANT: mandatory for trusted publishing
51
+
52
+ steps:
53
+ - name: Download all the dists
54
+ uses: actions/download-artifact@v4
55
+ with:
56
+ name: python-package-distributions
57
+ path: dist/
58
+
59
+ - name: Publish distribution to PyPI
60
+ uses: pypa/gh-action-pypi-publish@release/v1
61
+
62
+ publish-to-testpypi:
63
+ name: Publish to TestPyPI (for testing)
64
+ needs: [build]
65
+ runs-on: ubuntu-latest
66
+ if: github.event.release.prerelease
67
+ environment:
68
+ name: testpypi
69
+ url: https://test.pypi.org/p/neurospatial
70
+ permissions:
71
+ id-token: write
72
+
73
+ steps:
74
+ - name: Download all the dists
75
+ uses: actions/download-artifact@v4
76
+ with:
77
+ name: python-package-distributions
78
+ path: dist/
79
+
80
+ - name: Publish distribution to TestPyPI
81
+ uses: pypa/gh-action-pypi-publish@release/v1
82
+ with:
83
+ repository-url: https://test.pypi.org/legacy/
@@ -0,0 +1,116 @@
1
+ name: Create Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*.*.*'
7
+
8
+ permissions:
9
+ contents: write
10
+
11
+ jobs:
12
+ release:
13
+ name: Create GitHub Release
14
+ runs-on: ubuntu-latest
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ with:
19
+ fetch-depth: 0 # Fetch all history for changelog generation
20
+
21
+ - name: Set up Python
22
+ uses: actions/setup-python@v5
23
+ with:
24
+ python-version: '3.13'
25
+
26
+ - name: Install uv
27
+ uses: astral-sh/setup-uv@v3
28
+ with:
29
+ version: "latest"
30
+
31
+ - name: Get version from tag
32
+ id: get_version
33
+ run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
34
+
35
+ - name: Generate changelog
36
+ id: changelog
37
+ run: |
38
+ # Get the previous tag
39
+ PREVIOUS_TAG=$(git tag --sort=-version:refname | grep -A1 "${{ github.ref_name }}" | tail -1)
40
+
41
+ # If no previous tag, use initial commit
42
+ if [ -z "$PREVIOUS_TAG" ]; then
43
+ PREVIOUS_TAG=$(git rev-list --max-parents=0 HEAD)
44
+ fi
45
+
46
+ # Generate changelog
47
+ echo "## What's Changed" > CHANGELOG.txt
48
+ echo "" >> CHANGELOG.txt
49
+
50
+ # Get commits between tags, group by type
51
+ echo "### Features" >> CHANGELOG.txt
52
+ git log $PREVIOUS_TAG..${{ github.ref_name }} --pretty=format:"- %s (%h)" --grep="^feat" >> CHANGELOG.txt || echo "No new features" >> CHANGELOG.txt
53
+ echo "" >> CHANGELOG.txt
54
+ echo "" >> CHANGELOG.txt
55
+
56
+ echo "### Bug Fixes" >> CHANGELOG.txt
57
+ git log $PREVIOUS_TAG..${{ github.ref_name }} --pretty=format:"- %s (%h)" --grep="^fix" >> CHANGELOG.txt || echo "No bug fixes" >> CHANGELOG.txt
58
+ echo "" >> CHANGELOG.txt
59
+ echo "" >> CHANGELOG.txt
60
+
61
+ echo "### Documentation" >> CHANGELOG.txt
62
+ git log $PREVIOUS_TAG..${{ github.ref_name }} --pretty=format:"- %s (%h)" --grep="^docs" >> CHANGELOG.txt || echo "No documentation changes" >> CHANGELOG.txt
63
+ echo "" >> CHANGELOG.txt
64
+ echo "" >> CHANGELOG.txt
65
+
66
+ echo "### Other Changes" >> CHANGELOG.txt
67
+ git log $PREVIOUS_TAG..${{ github.ref_name }} --pretty=format:"- %s (%h)" --grep="^chore\|^test\|^refactor" >> CHANGELOG.txt || echo "No other changes" >> CHANGELOG.txt
68
+ echo "" >> CHANGELOG.txt
69
+ echo "" >> CHANGELOG.txt
70
+
71
+ echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${PREVIOUS_TAG}...${{ github.ref_name }}" >> CHANGELOG.txt
72
+
73
+ - name: Create Release
74
+ uses: softprops/action-gh-release@v2
75
+ with:
76
+ name: Release v${{ steps.get_version.outputs.VERSION }}
77
+ body_path: CHANGELOG.txt
78
+ draft: false
79
+ prerelease: ${{ contains(github.ref_name, 'rc') || contains(github.ref_name, 'beta') || contains(github.ref_name, 'alpha') }}
80
+ env:
81
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
82
+
83
+ - name: Update CHANGELOG.md
84
+ run: |
85
+ # Prepend the new changes to CHANGELOG.md
86
+ if [ -f CHANGELOG.md ]; then
87
+ # Add new release to existing changelog
88
+ echo "# Changelog" > CHANGELOG.new.md
89
+ echo "" >> CHANGELOG.new.md
90
+ echo "## [v${{ steps.get_version.outputs.VERSION }}] - $(date +%Y-%m-%d)" >> CHANGELOG.new.md
91
+ echo "" >> CHANGELOG.new.md
92
+ cat CHANGELOG.txt >> CHANGELOG.new.md
93
+ echo "" >> CHANGELOG.new.md
94
+ tail -n +2 CHANGELOG.md >> CHANGELOG.new.md
95
+ mv CHANGELOG.new.md CHANGELOG.md
96
+ else
97
+ # Create new changelog
98
+ echo "# Changelog" > CHANGELOG.md
99
+ echo "" >> CHANGELOG.md
100
+ echo "All notable changes to this project will be documented in this file." >> CHANGELOG.md
101
+ echo "" >> CHANGELOG.md
102
+ echo "The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)," >> CHANGELOG.md
103
+ echo "and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)." >> CHANGELOG.md
104
+ echo "" >> CHANGELOG.md
105
+ echo "## [v${{ steps.get_version.outputs.VERSION }}] - $(date +%Y-%m-%d)" >> CHANGELOG.md
106
+ echo "" >> CHANGELOG.md
107
+ cat CHANGELOG.txt >> CHANGELOG.md
108
+ fi
109
+
110
+ - name: Commit updated CHANGELOG.md
111
+ run: |
112
+ git config --local user.email "github-actions[bot]@users.noreply.github.com"
113
+ git config --local user.name "github-actions[bot]"
114
+ git add CHANGELOG.md
115
+ git commit -m "docs: update CHANGELOG.md for v${{ steps.get_version.outputs.VERSION }}" || echo "No changes to commit"
116
+ git push origin HEAD:main || echo "Failed to push changelog update"
@@ -0,0 +1,63 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+ branches:
9
+ - main
10
+
11
+ jobs:
12
+ test:
13
+ runs-on: ${{ matrix.os }}
14
+ strategy:
15
+ fail-fast: false
16
+ matrix:
17
+ os: [ubuntu-latest, macos-latest, windows-latest]
18
+ python-version: ['3.10', '3.11', '3.12', '3.13']
19
+
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+
23
+ - name: Set up Python ${{ matrix.python-version }}
24
+ uses: actions/setup-python@v5
25
+ with:
26
+ python-version: ${{ matrix.python-version }}
27
+
28
+ - name: Install uv
29
+ uses: astral-sh/setup-uv@v3
30
+ with:
31
+ version: "latest"
32
+
33
+ - name: Install dependencies
34
+ run: |
35
+ uv sync --extra dev
36
+
37
+ - name: Run ruff check
38
+ run: |
39
+ uv run ruff check .
40
+
41
+ - name: Run ruff format check
42
+ run: |
43
+ uv run ruff format --check .
44
+
45
+ - name: Run mypy
46
+ run: |
47
+ uv run mypy src/neurospatial
48
+ continue-on-error: true # Don't fail build on type errors (yet)
49
+
50
+ - name: Run tests with coverage
51
+ run: |
52
+ uv run pytest --cov=src/neurospatial --cov-report=xml --cov-report=term
53
+ env:
54
+ MPLBACKEND: Agg # Use non-GUI backend for matplotlib
55
+
56
+ - name: Upload coverage to Codecov
57
+ uses: codecov/codecov-action@v4
58
+ if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13'
59
+ with:
60
+ file: ./coverage.xml
61
+ fail_ci_if_error: false
62
+ env:
63
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
@@ -0,0 +1,182 @@
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
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py,cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ #uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ #poetry.lock
109
+
110
+ # pdm
111
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
112
+ #pdm.lock
113
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
114
+ # in version control.
115
+ # https://pdm.fming.dev/latest/usage/project/#working-with-version-control
116
+ .pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
121
+ __pypackages__/
122
+
123
+ # Celery stuff
124
+ celerybeat-schedule
125
+ celerybeat.pid
126
+
127
+ # SageMath parsed files
128
+ *.sage.py
129
+
130
+ # Environments
131
+ .env
132
+ .venv
133
+ env/
134
+ venv/
135
+ ENV/
136
+ env.bak/
137
+ venv.bak/
138
+
139
+ # Spyder project settings
140
+ .spyderproject
141
+ .spyproject
142
+
143
+ # Rope project settings
144
+ .ropeproject
145
+
146
+ # mkdocs documentation
147
+ /site
148
+
149
+ # mypy
150
+ .mypy_cache/
151
+ .dmypy.json
152
+ dmypy.json
153
+
154
+ # Pyre type checker
155
+ .pyre/
156
+
157
+ # pytype static type analyzer
158
+ .pytype/
159
+
160
+ # Cython debug symbols
161
+ cython_debug/
162
+
163
+ # PyCharm
164
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
165
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
166
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
167
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
168
+ #.idea/
169
+
170
+ # Ruff stuff:
171
+ .ruff_cache/
172
+
173
+ # PyPI configuration file
174
+ .pypirc
175
+
176
+ # Cursor
177
+ # Cursor is an AI-powered code editor.`.cursorignore` specifies files/directories to
178
+ # exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
179
+ # refer to https://docs.cursor.com/context/ignore-files
180
+ .cursorignore
181
+ .cursorindexingignore
182
+ .DS_Store
@@ -0,0 +1,35 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v6.0.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ - id: check-yaml
8
+ exclude: '^mkdocs\.yml$'
9
+ - id: check-added-large-files
10
+ args: ['--maxkb=1000']
11
+ exclude: '^examples/.*\.ipynb$'
12
+ - id: check-merge-conflict
13
+ - id: debug-statements
14
+ - id: mixed-line-ending
15
+
16
+ - repo: https://github.com/astral-sh/ruff-pre-commit
17
+ rev: v0.14.3
18
+ hooks:
19
+ - id: ruff
20
+ args: [--fix]
21
+ - id: ruff-format
22
+
23
+ - repo: https://github.com/pre-commit/mirrors-mypy
24
+ rev: v1.13.0
25
+ hooks:
26
+ - id: mypy
27
+ additional_dependencies:
28
+ - numpy
29
+ - pandas
30
+ - matplotlib
31
+ - networkx
32
+ - scipy
33
+ - scikit-learn
34
+ - shapely
35
+ args: [--ignore-missing-imports, --warn-unused-ignores]
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,40 @@
1
+ # Changelog
2
+
3
+ All notable changes to the neurospatial project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] - 2025-11-03
9
+
10
+ ### Added
11
+ - **CompositeEnvironment API parity**: Added `bins_in_region()`, `mask_for_region()`, `shortest_path()`, `info()`, `save()`, and `load()` methods to CompositeEnvironment for full API compatibility with Environment class
12
+ - **KDTree-optimized spatial queries**: CompositeEnvironment.bin_at() now uses KDTree for O(M log N) performance instead of O(N×M) sequential queries (enabled by default via `use_kdtree_query=True`)
13
+ - **Structured logging infrastructure**: New `_logging.py` module with NullHandler by default, enabling optional logging for debugging and workflow tracing
14
+ - **Centralized numerical constants**: New `_constants.py` module consolidating all magic numbers (tolerances, KDTree parameters, epsilon values) for consistent behavior
15
+ - **Comprehensive type validation**: CompositeEnvironment constructor now validates input types with actionable error messages
16
+ - **Graph metadata validation**: Added `validate_connectivity_graph()` to enforce required node/edge attributes from layout engines
17
+ - **Dimensionality support documentation**: New `docs/dimensionality_support.md` clarifying 1D/2D/3D feature support with compatibility matrix
18
+
19
+ ### Changed
20
+ - **Updated alignment module**: Now uses centralized constants (`IDW_MIN_DISTANCE`, `KDTREE_LEAF_SIZE`)
21
+ - **Updated regions module**: Uses `POINT_TOLERANCE` constant for consistent geometric comparisons
22
+ - **Enhanced error messages**: CompositeEnvironment now provides detailed diagnostics for dimension mismatches and type errors
23
+ - **Clarified 2D-only transforms**: Updated `transforms.py` docstring to explicitly state 2D-only status and suggest scipy for 3D
24
+
25
+ ### Fixed
26
+ - Removed unused `type: ignore` comment in `regular_grid.py`
27
+ - Fixed potential `KeyError` in logging by renaming `name` parameter to `env_name` (avoids conflict with LogRecord reserved field)
28
+
29
+ ### Documentation
30
+ - Added comprehensive dimensionality support guide (1D/2D/3D feature matrix)
31
+ - Updated CLAUDE.md with latest patterns and requirements
32
+ - Added 18 new tests for CompositeEnvironment type validation
33
+ - Added 23 new tests for Environment error path coverage
34
+ - Added 28 new tests for graph validation
35
+
36
+ ### Internal
37
+ - Consolidated duplicate dimension inference code (already done in earlier commits, verified)
38
+ - All 614 tests passing
39
+ - Ruff and mypy checks passing
40
+ - Test coverage: 78%