statespacecheck 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.
- statespacecheck-0.1.0/.gitattributes +2 -0
- statespacecheck-0.1.0/.github/workflows/ci.yml +281 -0
- statespacecheck-0.1.0/.github/workflows/docs.yml +67 -0
- statespacecheck-0.1.0/.gitignore +155 -0
- statespacecheck-0.1.0/.pre-commit-config.yaml +42 -0
- statespacecheck-0.1.0/.python-version +1 -0
- statespacecheck-0.1.0/CHANGELOG.md +58 -0
- statespacecheck-0.1.0/CLAUDE.md +119 -0
- statespacecheck-0.1.0/CONTRIBUTING.md +478 -0
- statespacecheck-0.1.0/LICENSE +21 -0
- statespacecheck-0.1.0/PKG-INFO +373 -0
- statespacecheck-0.1.0/README.md +305 -0
- statespacecheck-0.1.0/docs/contributing.md +478 -0
- statespacecheck-0.1.0/docs/gen_ref_pages.py +36 -0
- statespacecheck-0.1.0/docs/index.md +144 -0
- statespacecheck-0.1.0/docs/javascripts/mathjax.js +8 -0
- statespacecheck-0.1.0/docs/tutorials/01_introduction.ipynb +1 -0
- statespacecheck-0.1.0/docs/tutorials/02_highest_density_regions.ipynb +1 -0
- statespacecheck-0.1.0/docs/tutorials/03_time_resolved_diagnostics.ipynb +1 -0
- statespacecheck-0.1.0/docs/tutorials/04_predictive_checks.ipynb +1 -0
- statespacecheck-0.1.0/docs/tutorials/index.md +120 -0
- statespacecheck-0.1.0/examples/01_introduction.ipynb +745 -0
- statespacecheck-0.1.0/examples/01_introduction.py +450 -0
- statespacecheck-0.1.0/examples/02_highest_density_regions.ipynb +1012 -0
- statespacecheck-0.1.0/examples/02_highest_density_regions.py +583 -0
- statespacecheck-0.1.0/examples/03_time_resolved_diagnostics.ipynb +951 -0
- statespacecheck-0.1.0/examples/03_time_resolved_diagnostics.py +565 -0
- statespacecheck-0.1.0/examples/04_predictive_checks.ipynb +973 -0
- statespacecheck-0.1.0/examples/04_predictive_checks.py +598 -0
- statespacecheck-0.1.0/examples/utils.py +314 -0
- statespacecheck-0.1.0/mkdocs.yml +124 -0
- statespacecheck-0.1.0/pyproject.toml +171 -0
- statespacecheck-0.1.0/src/statespacecheck/__init__.py +53 -0
- statespacecheck-0.1.0/src/statespacecheck/_validation.py +189 -0
- statespacecheck-0.1.0/src/statespacecheck/_version.py +34 -0
- statespacecheck-0.1.0/src/statespacecheck/highest_density.py +138 -0
- statespacecheck-0.1.0/src/statespacecheck/periods.py +567 -0
- statespacecheck-0.1.0/src/statespacecheck/predictive_checks.py +426 -0
- statespacecheck-0.1.0/src/statespacecheck/state_consistency.py +296 -0
- statespacecheck-0.1.0/src/statespacecheck/viz.py +137 -0
- statespacecheck-0.1.0/tests/conftest.py +205 -0
- statespacecheck-0.1.0/tests/test_edge_cases.py +268 -0
- statespacecheck-0.1.0/tests/test_highest_density.py +328 -0
- statespacecheck-0.1.0/tests/test_kl_subnormal.py +46 -0
- statespacecheck-0.1.0/tests/test_periods.py +562 -0
- statespacecheck-0.1.0/tests/test_predictive_consistency.py +242 -0
- statespacecheck-0.1.0/tests/test_predictive_density.py +293 -0
- statespacecheck-0.1.0/tests/test_predictive_pvalue.py +227 -0
- statespacecheck-0.1.0/tests/test_properties.py +390 -0
- statespacecheck-0.1.0/tests/test_state_consistency.py +310 -0
- statespacecheck-0.1.0/tests/test_validation.py +210 -0
- statespacecheck-0.1.0/tests/test_version.py +43 -0
- statespacecheck-0.1.0/tests/test_viz.py +204 -0
- statespacecheck-0.1.0/uv.lock +2829 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
tags:
|
|
8
|
+
- "v*"
|
|
9
|
+
pull_request:
|
|
10
|
+
branches:
|
|
11
|
+
- main
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
defaults:
|
|
18
|
+
run:
|
|
19
|
+
shell: bash
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
quality:
|
|
23
|
+
name: Code Quality
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v4
|
|
27
|
+
with:
|
|
28
|
+
fetch-depth: 0
|
|
29
|
+
|
|
30
|
+
- name: Set up Python
|
|
31
|
+
uses: actions/setup-python@v5
|
|
32
|
+
with:
|
|
33
|
+
python-version: "3.12"
|
|
34
|
+
|
|
35
|
+
- name: Install uv
|
|
36
|
+
uses: astral-sh/setup-uv@v4
|
|
37
|
+
|
|
38
|
+
- name: Install dependencies
|
|
39
|
+
run: uv pip install --system -e .[dev]
|
|
40
|
+
|
|
41
|
+
- name: Run ruff format check
|
|
42
|
+
run: ruff format --check .
|
|
43
|
+
|
|
44
|
+
- name: Run ruff linting
|
|
45
|
+
run: ruff check . --output-format=github
|
|
46
|
+
|
|
47
|
+
- name: Run mypy type checking
|
|
48
|
+
run: mypy src/
|
|
49
|
+
|
|
50
|
+
test:
|
|
51
|
+
name: Test Python ${{ matrix.python-version }} on ${{ matrix.os }}
|
|
52
|
+
runs-on: ${{ matrix.os }}
|
|
53
|
+
strategy:
|
|
54
|
+
fail-fast: false
|
|
55
|
+
matrix:
|
|
56
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
57
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
58
|
+
steps:
|
|
59
|
+
- uses: actions/checkout@v4
|
|
60
|
+
with:
|
|
61
|
+
fetch-depth: 0
|
|
62
|
+
|
|
63
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
64
|
+
uses: actions/setup-python@v5
|
|
65
|
+
with:
|
|
66
|
+
python-version: ${{ matrix.python-version }}
|
|
67
|
+
allow-prereleases: true
|
|
68
|
+
|
|
69
|
+
- name: Install uv
|
|
70
|
+
uses: astral-sh/setup-uv@v4
|
|
71
|
+
|
|
72
|
+
- name: Install dependencies
|
|
73
|
+
run: uv pip install --system -e .[dev]
|
|
74
|
+
|
|
75
|
+
- name: Run tests with coverage
|
|
76
|
+
run: pytest --cov=statespacecheck --cov-report=xml --cov-report=term-missing
|
|
77
|
+
|
|
78
|
+
- name: Upload coverage to Codecov
|
|
79
|
+
if: matrix.python-version == '3.12' && matrix.os == 'ubuntu-latest'
|
|
80
|
+
uses: codecov/codecov-action@v4
|
|
81
|
+
continue-on-error: true
|
|
82
|
+
with:
|
|
83
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
84
|
+
file: ./coverage.xml
|
|
85
|
+
flags: unittests
|
|
86
|
+
name: codecov-python-${{ matrix.python-version }}
|
|
87
|
+
|
|
88
|
+
build:
|
|
89
|
+
name: Build distribution
|
|
90
|
+
runs-on: ubuntu-latest
|
|
91
|
+
needs: [quality, test]
|
|
92
|
+
steps:
|
|
93
|
+
- uses: actions/checkout@v4
|
|
94
|
+
with:
|
|
95
|
+
fetch-depth: 0 # Required for hatch-vcs to get version from git tags
|
|
96
|
+
|
|
97
|
+
- name: Set up Python
|
|
98
|
+
uses: actions/setup-python@v5
|
|
99
|
+
with:
|
|
100
|
+
python-version: "3.12"
|
|
101
|
+
|
|
102
|
+
- name: Install uv
|
|
103
|
+
uses: astral-sh/setup-uv@v4
|
|
104
|
+
|
|
105
|
+
- name: Install build dependencies
|
|
106
|
+
run: uv pip install --system build twine
|
|
107
|
+
|
|
108
|
+
- name: Build sdist and wheel
|
|
109
|
+
run: python -m build
|
|
110
|
+
|
|
111
|
+
- name: Check distribution metadata
|
|
112
|
+
run: twine check dist/*
|
|
113
|
+
|
|
114
|
+
- name: List distribution contents
|
|
115
|
+
run: |
|
|
116
|
+
echo "=== Built distributions ==="
|
|
117
|
+
ls -lh dist/
|
|
118
|
+
echo ""
|
|
119
|
+
echo "=== Wheel contents ==="
|
|
120
|
+
unzip -l dist/*.whl || true
|
|
121
|
+
echo ""
|
|
122
|
+
echo "=== SDist contents ==="
|
|
123
|
+
tar -tzf dist/*.tar.gz | head -20 || true
|
|
124
|
+
|
|
125
|
+
- name: Upload distribution artifacts
|
|
126
|
+
uses: actions/upload-artifact@v4
|
|
127
|
+
with:
|
|
128
|
+
name: dist-${{ github.sha }}
|
|
129
|
+
path: dist/
|
|
130
|
+
retention-days: 7
|
|
131
|
+
|
|
132
|
+
test-install:
|
|
133
|
+
name: Test install from ${{ matrix.package }}
|
|
134
|
+
runs-on: ubuntu-latest
|
|
135
|
+
needs: [build]
|
|
136
|
+
strategy:
|
|
137
|
+
fail-fast: false
|
|
138
|
+
matrix:
|
|
139
|
+
package: ['wheel', 'sdist']
|
|
140
|
+
python-version: ["3.10", "3.13"]
|
|
141
|
+
steps:
|
|
142
|
+
- name: Download distribution artifacts
|
|
143
|
+
uses: actions/download-artifact@v4
|
|
144
|
+
with:
|
|
145
|
+
name: dist-${{ github.sha }}
|
|
146
|
+
path: dist/
|
|
147
|
+
|
|
148
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
149
|
+
uses: actions/setup-python@v5
|
|
150
|
+
with:
|
|
151
|
+
python-version: ${{ matrix.python-version }}
|
|
152
|
+
|
|
153
|
+
- name: Install from wheel
|
|
154
|
+
if: matrix.package == 'wheel'
|
|
155
|
+
run: pip install dist/*.whl
|
|
156
|
+
|
|
157
|
+
- name: Install from sdist
|
|
158
|
+
if: matrix.package == 'sdist'
|
|
159
|
+
run: pip install dist/*.tar.gz
|
|
160
|
+
|
|
161
|
+
- name: Verify installation
|
|
162
|
+
run: |
|
|
163
|
+
python -c "import statespacecheck; print('Package:', statespacecheck.__name__)"
|
|
164
|
+
python -c "import statespacecheck; print('Version:', statespacecheck.__version__)"
|
|
165
|
+
python -c "from statespacecheck import kl_divergence, hpd_overlap, highest_density_region; print('Imports successful')"
|
|
166
|
+
|
|
167
|
+
- name: Check public API
|
|
168
|
+
run: |
|
|
169
|
+
python -c "
|
|
170
|
+
import statespacecheck as ssc
|
|
171
|
+
expected = {'kl_divergence', 'hpd_overlap', 'highest_density_region',
|
|
172
|
+
'predictive_density', 'log_predictive_density',
|
|
173
|
+
'aggregate_over_period', 'predictive_pvalue',
|
|
174
|
+
'DEFAULT_COVERAGE', 'DistributionArray'}
|
|
175
|
+
actual = set(ssc.__all__)
|
|
176
|
+
missing = expected - actual
|
|
177
|
+
extra = actual - expected
|
|
178
|
+
if missing:
|
|
179
|
+
raise ValueError(f'Missing from __all__: {missing}')
|
|
180
|
+
if extra:
|
|
181
|
+
print(f'Extra in __all__: {extra}')
|
|
182
|
+
print(f'✓ All {len(expected)} expected exports present')
|
|
183
|
+
"
|
|
184
|
+
|
|
185
|
+
publish-testpypi:
|
|
186
|
+
name: Publish to TestPyPI
|
|
187
|
+
runs-on: ubuntu-latest
|
|
188
|
+
needs: [test-install]
|
|
189
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
|
190
|
+
environment:
|
|
191
|
+
name: testpypi
|
|
192
|
+
url: https://test.pypi.org/project/statespacecheck/
|
|
193
|
+
permissions:
|
|
194
|
+
id-token: write
|
|
195
|
+
steps:
|
|
196
|
+
- name: Download distribution artifacts
|
|
197
|
+
uses: actions/download-artifact@v4
|
|
198
|
+
with:
|
|
199
|
+
name: dist-${{ github.sha }}
|
|
200
|
+
path: dist/
|
|
201
|
+
|
|
202
|
+
- name: Publish to TestPyPI
|
|
203
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
204
|
+
with:
|
|
205
|
+
repository-url: https://test.pypi.org/legacy/
|
|
206
|
+
|
|
207
|
+
publish-pypi:
|
|
208
|
+
name: Publish to PyPI
|
|
209
|
+
runs-on: ubuntu-latest
|
|
210
|
+
needs: [publish-testpypi]
|
|
211
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
|
212
|
+
environment:
|
|
213
|
+
name: pypi
|
|
214
|
+
url: https://pypi.org/project/statespacecheck/
|
|
215
|
+
permissions:
|
|
216
|
+
id-token: write
|
|
217
|
+
steps:
|
|
218
|
+
- name: Download distribution artifacts
|
|
219
|
+
uses: actions/download-artifact@v4
|
|
220
|
+
with:
|
|
221
|
+
name: dist-${{ github.sha }}
|
|
222
|
+
path: dist/
|
|
223
|
+
|
|
224
|
+
- name: Publish to PyPI
|
|
225
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
226
|
+
|
|
227
|
+
create-release:
|
|
228
|
+
name: Create GitHub Release
|
|
229
|
+
runs-on: ubuntu-latest
|
|
230
|
+
needs: [publish-pypi]
|
|
231
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
|
232
|
+
permissions:
|
|
233
|
+
contents: write
|
|
234
|
+
steps:
|
|
235
|
+
- uses: actions/checkout@v4
|
|
236
|
+
with:
|
|
237
|
+
fetch-depth: 0
|
|
238
|
+
|
|
239
|
+
- name: Download distribution artifacts
|
|
240
|
+
uses: actions/download-artifact@v4
|
|
241
|
+
with:
|
|
242
|
+
name: dist-${{ github.sha }}
|
|
243
|
+
path: dist/
|
|
244
|
+
|
|
245
|
+
- name: Extract version from tag
|
|
246
|
+
id: get_version
|
|
247
|
+
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
|
|
248
|
+
|
|
249
|
+
- name: Generate release notes
|
|
250
|
+
id: release_notes
|
|
251
|
+
run: |
|
|
252
|
+
cat > release_notes.md << 'EOF'
|
|
253
|
+
## statespacecheck v${{ steps.get_version.outputs.VERSION }}
|
|
254
|
+
|
|
255
|
+
Goodness-of-fit diagnostics for state space models in neuroscience.
|
|
256
|
+
|
|
257
|
+
### Installation
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
pip install statespacecheck==${{ steps.get_version.outputs.VERSION }}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Documentation
|
|
264
|
+
|
|
265
|
+
See [README](https://github.com/edeno/statespacecheck#readme) for usage examples.
|
|
266
|
+
|
|
267
|
+
### Changes
|
|
268
|
+
|
|
269
|
+
See [commit history](https://github.com/edeno/statespacecheck/commits/v${{ steps.get_version.outputs.VERSION }}) for detailed changes.
|
|
270
|
+
EOF
|
|
271
|
+
|
|
272
|
+
- name: Create GitHub Release
|
|
273
|
+
uses: softprops/action-gh-release@v2
|
|
274
|
+
with:
|
|
275
|
+
body_path: release_notes.md
|
|
276
|
+
files: dist/*
|
|
277
|
+
draft: false
|
|
278
|
+
prerelease: false
|
|
279
|
+
generate_release_notes: true
|
|
280
|
+
env:
|
|
281
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
name: docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
pull_request:
|
|
8
|
+
branches:
|
|
9
|
+
- main
|
|
10
|
+
paths:
|
|
11
|
+
- 'docs/**'
|
|
12
|
+
- 'mkdocs.yml'
|
|
13
|
+
- 'examples/**'
|
|
14
|
+
- '.github/workflows/docs.yml'
|
|
15
|
+
|
|
16
|
+
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
pages: write
|
|
20
|
+
id-token: write
|
|
21
|
+
|
|
22
|
+
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
|
|
23
|
+
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
|
|
24
|
+
concurrency:
|
|
25
|
+
group: "pages"
|
|
26
|
+
cancel-in-progress: false
|
|
27
|
+
|
|
28
|
+
jobs:
|
|
29
|
+
build:
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@v4
|
|
33
|
+
|
|
34
|
+
- name: Set up Python
|
|
35
|
+
uses: actions/setup-python@v5
|
|
36
|
+
with:
|
|
37
|
+
python-version: '3.12'
|
|
38
|
+
|
|
39
|
+
- name: Install uv
|
|
40
|
+
uses: astral-sh/setup-uv@v3
|
|
41
|
+
with:
|
|
42
|
+
enable-cache: true
|
|
43
|
+
|
|
44
|
+
- name: Install dependencies
|
|
45
|
+
run: |
|
|
46
|
+
uv pip install --system -e ".[docs]"
|
|
47
|
+
|
|
48
|
+
- name: Build docs
|
|
49
|
+
run: mkdocs build --strict
|
|
50
|
+
|
|
51
|
+
- name: Upload artifact
|
|
52
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
53
|
+
uses: actions/upload-pages-artifact@v3
|
|
54
|
+
with:
|
|
55
|
+
path: ./site
|
|
56
|
+
|
|
57
|
+
deploy:
|
|
58
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
59
|
+
environment:
|
|
60
|
+
name: github-pages
|
|
61
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
62
|
+
runs-on: ubuntu-latest
|
|
63
|
+
needs: build
|
|
64
|
+
steps:
|
|
65
|
+
- name: Deploy to GitHub Pages
|
|
66
|
+
id: deployment
|
|
67
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,155 @@
|
|
|
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
|
+
.pdm.toml
|
|
86
|
+
.pdm-python
|
|
87
|
+
.pdm-build/
|
|
88
|
+
|
|
89
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
90
|
+
__pypackages__/
|
|
91
|
+
|
|
92
|
+
# Celery stuff
|
|
93
|
+
celerybeat-schedule
|
|
94
|
+
celerybeat.pid
|
|
95
|
+
|
|
96
|
+
# SageMath parsed files
|
|
97
|
+
*.sage.py
|
|
98
|
+
|
|
99
|
+
# Environments
|
|
100
|
+
.env
|
|
101
|
+
.venv
|
|
102
|
+
env/
|
|
103
|
+
venv/
|
|
104
|
+
ENV/
|
|
105
|
+
env.bak/
|
|
106
|
+
venv.bak/
|
|
107
|
+
|
|
108
|
+
# Spyder project settings
|
|
109
|
+
.spyderproject
|
|
110
|
+
.spyproject
|
|
111
|
+
|
|
112
|
+
# Rope project settings
|
|
113
|
+
.ropeproject
|
|
114
|
+
|
|
115
|
+
# mkdocs documentation
|
|
116
|
+
/site
|
|
117
|
+
docs/.cache/
|
|
118
|
+
.mkdocs_cache/
|
|
119
|
+
|
|
120
|
+
# mypy
|
|
121
|
+
.mypy_cache/
|
|
122
|
+
.dmypy.json
|
|
123
|
+
dmypy.json
|
|
124
|
+
|
|
125
|
+
# Pyre type checker
|
|
126
|
+
.pyre/
|
|
127
|
+
|
|
128
|
+
# pytype static type analyzer
|
|
129
|
+
.pytype/
|
|
130
|
+
|
|
131
|
+
# Cython debug symbols
|
|
132
|
+
cython_debug/
|
|
133
|
+
|
|
134
|
+
# PyCharm
|
|
135
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
136
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
137
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
138
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
139
|
+
#.idea/
|
|
140
|
+
|
|
141
|
+
# Ruff stuff:
|
|
142
|
+
.ruff_cache/
|
|
143
|
+
|
|
144
|
+
# PyPI configuration file
|
|
145
|
+
.pypirc
|
|
146
|
+
|
|
147
|
+
# Cursor
|
|
148
|
+
# Cursor is an AI-powered code editor.`.cursorignore` specifies files/directories to
|
|
149
|
+
# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
|
|
150
|
+
# refer to https://docs.cursor.com/context/ignore-files
|
|
151
|
+
.cursorignore
|
|
152
|
+
.cursorindexingignore
|
|
153
|
+
*.DS_Store
|
|
154
|
+
# VCS version file (auto-generated by hatch-vcs)
|
|
155
|
+
src/statespacecheck/_version.py
|
|
@@ -0,0 +1,42 @@
|
|
|
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: '^(docs/examples/.*\.ipynb|scripts/.*\.(pdf|png))$'
|
|
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
|
+
exclude: '^docs/examples/.*\.(ipynb|py)$'
|
|
22
|
+
- id: ruff-format
|
|
23
|
+
exclude: '^docs/examples/.*\.(ipynb|py)$'
|
|
24
|
+
|
|
25
|
+
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
26
|
+
rev: v1.13.0
|
|
27
|
+
hooks:
|
|
28
|
+
- id: mypy
|
|
29
|
+
files: ^src/
|
|
30
|
+
additional_dependencies:
|
|
31
|
+
- numpy>=1.26.0
|
|
32
|
+
- scipy>=1.11.0
|
|
33
|
+
|
|
34
|
+
- repo: local
|
|
35
|
+
hooks:
|
|
36
|
+
- id: pytest
|
|
37
|
+
name: pytest
|
|
38
|
+
entry: uv run pytest
|
|
39
|
+
language: system
|
|
40
|
+
pass_filenames: false
|
|
41
|
+
always_run: true
|
|
42
|
+
stages: [pre-commit]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2025-11-11
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
#### Core Diagnostics
|
|
13
|
+
- `kl_divergence()`: Measure information divergence between state distributions and likelihood
|
|
14
|
+
- `hpd_overlap()`: Compute spatial overlap between highest posterior density regions
|
|
15
|
+
- `highest_density_region()`: Compute boolean masks for highest density regions
|
|
16
|
+
|
|
17
|
+
#### Predictive Checks
|
|
18
|
+
- `predictive_density()`: Compute predictive density from state distribution and likelihood
|
|
19
|
+
- `log_predictive_density()`: Numerically stable log-space computation of predictive density
|
|
20
|
+
- `predictive_pvalue()`: Monte Carlo p-values for goodness-of-fit testing
|
|
21
|
+
|
|
22
|
+
#### Period Detection
|
|
23
|
+
- `flag_low_overlap()`: Identify time periods with poor posterior-likelihood agreement
|
|
24
|
+
- `flag_extreme_kl()`: Detect anomalous KL divergence using robust z-scores
|
|
25
|
+
- `flag_extreme_pvalues()`: Flag extreme predictive p-values
|
|
26
|
+
- `combine_flags()`: Aggregate multiple diagnostic flags with majority voting
|
|
27
|
+
- `find_low_overlap_intervals()`: Extract contiguous intervals of poor model fit
|
|
28
|
+
- `aggregate_over_period()`: Summarize metrics over time periods with flexible aggregation
|
|
29
|
+
|
|
30
|
+
#### Visualization
|
|
31
|
+
- `plot_diagnostics()`: Three-panel diagnostic visualization with time-resolved metrics
|
|
32
|
+
- Support for flagging problematic time periods in plots
|
|
33
|
+
|
|
34
|
+
#### Documentation
|
|
35
|
+
- Comprehensive README with neuroscience examples
|
|
36
|
+
- Four tutorial notebooks covering core concepts and workflows
|
|
37
|
+
- API reference documentation with mkdocs-material
|
|
38
|
+
- CONTRIBUTING.md with development guidelines
|
|
39
|
+
|
|
40
|
+
#### Infrastructure
|
|
41
|
+
- Full test suite with 230 tests and 100% code coverage
|
|
42
|
+
- Property-based testing with Hypothesis
|
|
43
|
+
- Type hints with strict mypy compliance
|
|
44
|
+
- Code quality enforcement with ruff (formatting and linting)
|
|
45
|
+
- Pre-commit hooks for automated checks
|
|
46
|
+
- CI/CD with GitHub Actions
|
|
47
|
+
- Automated documentation deployment
|
|
48
|
+
|
|
49
|
+
### Features
|
|
50
|
+
|
|
51
|
+
- **Flexible Dimensionality**: Supports 1D `(n_time, n_position)` and 2D `(n_time, n_x, n_y)` spatial arrays
|
|
52
|
+
- **Robust Edge Cases**: Proper handling of NaN values, zero sums, and empty distributions
|
|
53
|
+
- **Automatic Normalization**: All functions normalize inputs automatically
|
|
54
|
+
- **Time-Resolved Analysis**: All metrics return time series for local model evaluation
|
|
55
|
+
- **Vectorized Operations**: Efficient NumPy-based implementation with no Python loops
|
|
56
|
+
- **Scientific Python Standards**: Follows SPEC 0 for version support and best practices
|
|
57
|
+
|
|
58
|
+
[0.1.0]: https://github.com/edeno/statespacecheck/releases/tag/v0.1.0
|