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.
- neurospatial-0.1.0/.claude/commands/freshstart.md +60 -0
- neurospatial-0.1.0/.gitattributes +2 -0
- neurospatial-0.1.0/.github/workflows/docs.yml +65 -0
- neurospatial-0.1.0/.github/workflows/publish.yml +83 -0
- neurospatial-0.1.0/.github/workflows/release.yml +116 -0
- neurospatial-0.1.0/.github/workflows/test.yml +63 -0
- neurospatial-0.1.0/.gitignore +182 -0
- neurospatial-0.1.0/.pre-commit-config.yaml +35 -0
- neurospatial-0.1.0/.python-version +1 -0
- neurospatial-0.1.0/CHANGELOG.md +40 -0
- neurospatial-0.1.0/CLAUDE.md +723 -0
- neurospatial-0.1.0/CODE_REVIEW_REPORT.md +944 -0
- neurospatial-0.1.0/LICENSE +21 -0
- neurospatial-0.1.0/PKG-INFO +402 -0
- neurospatial-0.1.0/README.md +347 -0
- neurospatial-0.1.0/coverage.json +1 -0
- neurospatial-0.1.0/docs/api/index.md +77 -0
- neurospatial-0.1.0/docs/changelog.md +40 -0
- neurospatial-0.1.0/docs/contributing.md +262 -0
- neurospatial-0.1.0/docs/dimensionality_support.md +242 -0
- neurospatial-0.1.0/docs/examples/.gitignore +2 -0
- neurospatial-0.1.0/docs/examples/index.md +130 -0
- neurospatial-0.1.0/docs/gen_ref_pages.py +44 -0
- neurospatial-0.1.0/docs/getting-started/core-concepts.md +351 -0
- neurospatial-0.1.0/docs/getting-started/index.md +25 -0
- neurospatial-0.1.0/docs/getting-started/installation.md +148 -0
- neurospatial-0.1.0/docs/getting-started/quickstart.md +285 -0
- neurospatial-0.1.0/docs/includes/abbreviations.md +14 -0
- neurospatial-0.1.0/docs/index.md +123 -0
- neurospatial-0.1.0/docs/javascripts/mathjax.js +17 -0
- neurospatial-0.1.0/docs/stylesheets/extra.css +53 -0
- neurospatial-0.1.0/docs/sync_notebooks.py +17 -0
- neurospatial-0.1.0/docs/user-guide/alignment.md +35 -0
- neurospatial-0.1.0/docs/user-guide/composite-environments.md +26 -0
- neurospatial-0.1.0/docs/user-guide/environments.md +255 -0
- neurospatial-0.1.0/docs/user-guide/index.md +51 -0
- neurospatial-0.1.0/docs/user-guide/layout-engines.md +241 -0
- neurospatial-0.1.0/docs/user-guide/regions.md +54 -0
- neurospatial-0.1.0/docs/user-guide/workflows.md +427 -0
- neurospatial-0.1.0/examples/01_introduction_basics.ipynb +922 -0
- neurospatial-0.1.0/examples/02_layout_engines.ipynb +798 -0
- neurospatial-0.1.0/examples/03_morphological_operations.ipynb +1305 -0
- neurospatial-0.1.0/examples/04_regions_of_interest.ipynb +1061 -0
- neurospatial-0.1.0/examples/05_track_linearization.ipynb +1336 -0
- neurospatial-0.1.0/examples/06_composite_environments.ipynb +1455 -0
- neurospatial-0.1.0/examples/07_advanced_operations.ipynb +1450 -0
- neurospatial-0.1.0/examples/08_complete_workflow.ipynb +1685 -0
- neurospatial-0.1.0/examples/README.md +254 -0
- neurospatial-0.1.0/mkdocs.yml +169 -0
- neurospatial-0.1.0/pyproject.toml +246 -0
- neurospatial-0.1.0/pytest.ini +10 -0
- neurospatial-0.1.0/src/neurospatial/__init__.py +35 -0
- neurospatial-0.1.0/src/neurospatial/_constants.py +75 -0
- neurospatial-0.1.0/src/neurospatial/_logging.py +202 -0
- neurospatial-0.1.0/src/neurospatial/alignment.py +565 -0
- neurospatial-0.1.0/src/neurospatial/calibration.py +68 -0
- neurospatial-0.1.0/src/neurospatial/composite.py +1152 -0
- neurospatial-0.1.0/src/neurospatial/distance.py +258 -0
- neurospatial-0.1.0/src/neurospatial/environment.py +2182 -0
- neurospatial-0.1.0/src/neurospatial/io.py +513 -0
- neurospatial-0.1.0/src/neurospatial/layout/__init__.py +26 -0
- neurospatial-0.1.0/src/neurospatial/layout/base.py +221 -0
- neurospatial-0.1.0/src/neurospatial/layout/engines/__init__.py +0 -0
- neurospatial-0.1.0/src/neurospatial/layout/engines/graph.py +402 -0
- neurospatial-0.1.0/src/neurospatial/layout/engines/hexagonal.py +323 -0
- neurospatial-0.1.0/src/neurospatial/layout/engines/image_mask.py +143 -0
- neurospatial-0.1.0/src/neurospatial/layout/engines/masked_grid.py +111 -0
- neurospatial-0.1.0/src/neurospatial/layout/engines/regular_grid.py +221 -0
- neurospatial-0.1.0/src/neurospatial/layout/engines/shapely_polygon.py +229 -0
- neurospatial-0.1.0/src/neurospatial/layout/engines/triangular_mesh.py +463 -0
- neurospatial-0.1.0/src/neurospatial/layout/factories.py +179 -0
- neurospatial-0.1.0/src/neurospatial/layout/helpers/__init__.py +0 -0
- neurospatial-0.1.0/src/neurospatial/layout/helpers/graph.py +510 -0
- neurospatial-0.1.0/src/neurospatial/layout/helpers/hexagonal.py +630 -0
- neurospatial-0.1.0/src/neurospatial/layout/helpers/regular_grid.py +612 -0
- neurospatial-0.1.0/src/neurospatial/layout/helpers/triangular_mesh.py +242 -0
- neurospatial-0.1.0/src/neurospatial/layout/helpers/utils.py +1036 -0
- neurospatial-0.1.0/src/neurospatial/layout/mixins.py +393 -0
- neurospatial-0.1.0/src/neurospatial/layout/validation.py +416 -0
- neurospatial-0.1.0/src/neurospatial/py.typed +0 -0
- neurospatial-0.1.0/src/neurospatial/regions/__init__.py +42 -0
- neurospatial-0.1.0/src/neurospatial/regions/core.py +508 -0
- neurospatial-0.1.0/src/neurospatial/regions/io.py +939 -0
- neurospatial-0.1.0/src/neurospatial/regions/ops.py +346 -0
- neurospatial-0.1.0/src/neurospatial/regions/plot.py +159 -0
- neurospatial-0.1.0/src/neurospatial/spatial.py +188 -0
- neurospatial-0.1.0/src/neurospatial/transforms.py +798 -0
- neurospatial-0.1.0/tests/conftest.py +184 -0
- neurospatial-0.1.0/tests/layout/test_graph_utils.py +312 -0
- neurospatial-0.1.0/tests/layout/test_hex_grid_utils.py +162 -0
- neurospatial-0.1.0/tests/layout/test_layout_engine.py +474 -0
- neurospatial-0.1.0/tests/layout/test_regular_grid_layout.py +309 -0
- neurospatial-0.1.0/tests/layout/test_regular_grid_utils.py +280 -0
- neurospatial-0.1.0/tests/layout/test_triangular_mesh.py +539 -0
- neurospatial-0.1.0/tests/layout/test_utils.py +178 -0
- neurospatial-0.1.0/tests/layout/test_validation.py +389 -0
- neurospatial-0.1.0/tests/regions/test_core.py +301 -0
- neurospatial-0.1.0/tests/regions/test_ops.py +492 -0
- neurospatial-0.1.0/tests/regions/test_plot.py +429 -0
- neurospatial-0.1.0/tests/regions/test_serialization.py +690 -0
- neurospatial-0.1.0/tests/test_alignment.py +158 -0
- neurospatial-0.1.0/tests/test_bin_size_required.py +237 -0
- neurospatial-0.1.0/tests/test_calibration.py +236 -0
- neurospatial-0.1.0/tests/test_check_fitted_error.py +161 -0
- neurospatial-0.1.0/tests/test_common_pitfalls.py +389 -0
- neurospatial-0.1.0/tests/test_composite.py +267 -0
- neurospatial-0.1.0/tests/test_composite_dimension_error.py +206 -0
- neurospatial-0.1.0/tests/test_composite_new_methods.py +371 -0
- neurospatial-0.1.0/tests/test_composite_validation.py +168 -0
- neurospatial-0.1.0/tests/test_distance.py +383 -0
- neurospatial-0.1.0/tests/test_distance_new.py +134 -0
- neurospatial-0.1.0/tests/test_environment.py +911 -0
- neurospatial-0.1.0/tests/test_environment_error_paths.py +334 -0
- neurospatial-0.1.0/tests/test_environment_info.py +282 -0
- neurospatial-0.1.0/tests/test_environment_repr.py +294 -0
- neurospatial-0.1.0/tests/test_error_message_standardization.py +345 -0
- neurospatial-0.1.0/tests/test_factory_selection_guide.py +104 -0
- neurospatial-0.1.0/tests/test_io.py +159 -0
- neurospatial-0.1.0/tests/test_spatial.py +118 -0
- neurospatial-0.1.0/tests/test_transforms_new.py +231 -0
- neurospatial-0.1.0/tests/test_type_validation.py +279 -0
- neurospatial-0.1.0/tests/test_validation_new.py +105 -0
- 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,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%
|