corticalfields 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- corticalfields-0.1.1/LICENSE +21 -0
- corticalfields-0.1.1/PKG-INFO +194 -0
- corticalfields-0.1.1/README.md +150 -0
- corticalfields-0.1.1/pyproject.toml +70 -0
- corticalfields-0.1.1/setup.cfg +4 -0
- corticalfields-0.1.1/src/corticalfields/__init__.py +75 -0
- corticalfields-0.1.1/src/corticalfields/features.py +258 -0
- corticalfields-0.1.1/src/corticalfields/graphs.py +234 -0
- corticalfields-0.1.1/src/corticalfields/kernels.py +304 -0
- corticalfields-0.1.1/src/corticalfields/mtle_pipeline.py +856 -0
- corticalfields-0.1.1/src/corticalfields/normative.py +686 -0
- corticalfields-0.1.1/src/corticalfields/spectral.py +509 -0
- corticalfields-0.1.1/src/corticalfields/surface.py +369 -0
- corticalfields-0.1.1/src/corticalfields/surprise.py +381 -0
- corticalfields-0.1.1/src/corticalfields/utils.py +227 -0
- corticalfields-0.1.1/src/corticalfields/viz.py +357 -0
- corticalfields-0.1.1/src/corticalfields.egg-info/PKG-INFO +194 -0
- corticalfields-0.1.1/src/corticalfields.egg-info/SOURCES.txt +20 -0
- corticalfields-0.1.1/src/corticalfields.egg-info/dependency_links.txt +1 -0
- corticalfields-0.1.1/src/corticalfields.egg-info/requires.txt +27 -0
- corticalfields-0.1.1/src/corticalfields.egg-info/top_level.txt +1 -0
- corticalfields-0.1.1/tests/test_core.py +331 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 R. Debona
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: corticalfields
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Geodesic-aware Gaussian Process normative modeling on cortical surfaces with spectral shape descriptors and information-theoretic surprise maps.
|
|
5
|
+
Author-email: rdneuro <r.debona@ufrj.br>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/rdneuro/corticalfields
|
|
8
|
+
Project-URL: Documentation, https://corticalfields.readthedocs.io
|
|
9
|
+
Keywords: neuroimaging,cortical-surface,gaussian-process,normative-modeling,epilepsy,heat-kernel-signature,laplace-beltrami,surprise-maps,spectral-analysis,bayesian-inference
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
|
|
15
|
+
Requires-Python: >=3.9
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: numpy>=1.24
|
|
19
|
+
Requires-Dist: scipy>=1.10
|
|
20
|
+
Requires-Dist: nibabel>=5.0
|
|
21
|
+
Requires-Dist: torch>=2.0
|
|
22
|
+
Requires-Dist: gpytorch>=1.11
|
|
23
|
+
Requires-Dist: scikit-sparse>=0.4
|
|
24
|
+
Requires-Dist: trimesh>=4.0
|
|
25
|
+
Requires-Dist: pyvista>=0.42
|
|
26
|
+
Requires-Dist: matplotlib>=3.7
|
|
27
|
+
Requires-Dist: tqdm>=4.65
|
|
28
|
+
Requires-Dist: joblib>=1.3
|
|
29
|
+
Provides-Extra: full
|
|
30
|
+
Requires-Dist: robust-laplacian>=0.2; extra == "full"
|
|
31
|
+
Requires-Dist: potpourri3d>=0.0.8; extra == "full"
|
|
32
|
+
Requires-Dist: geometric-kernels>=0.2; extra == "full"
|
|
33
|
+
Requires-Dist: pymc>=5.10; extra == "full"
|
|
34
|
+
Requires-Dist: giotto-tda>=0.6; extra == "full"
|
|
35
|
+
Requires-Dist: torch-geometric>=2.4; extra == "full"
|
|
36
|
+
Requires-Dist: surfplot>=0.2; extra == "full"
|
|
37
|
+
Requires-Dist: brainspace>=0.1; extra == "full"
|
|
38
|
+
Requires-Dist: neuromaps>=0.0.4; extra == "full"
|
|
39
|
+
Provides-Extra: dev
|
|
40
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
41
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
42
|
+
Requires-Dist: ruff>=0.1; extra == "dev"
|
|
43
|
+
Dynamic: license-file
|
|
44
|
+
|
|
45
|
+
# CorticalFields
|
|
46
|
+
|
|
47
|
+
**Geodesic-aware Gaussian Process normative modeling on cortical surfaces with spectral shape descriptors and information-theoretic surprise maps.**
|
|
48
|
+
|
|
49
|
+
CorticalFields extracts rich geometric information from structural MRI (T1w) data — without needing fMRI or dMRI — by treating the cortical surface as a Riemannian manifold and applying principled probabilistic modeling. It was designed for epilepsy research (MTLE-HS) but is applicable to any structural neuroimaging study.
|
|
50
|
+
|
|
51
|
+
## What it does
|
|
52
|
+
|
|
53
|
+
Given FreeSurfer-processed T1w data, CorticalFields:
|
|
54
|
+
|
|
55
|
+
1. **Decomposes the cortical geometry** via the Laplace–Beltrami operator, extracting the intrinsic spectral structure of the cortical mesh.
|
|
56
|
+
2. **Computes spectral shape descriptors** (Heat Kernel Signature, Wave Kernel Signature, Global Point Signature) that capture multi-scale geometric information at every vertex — from local curvature to global lobe membership.
|
|
57
|
+
3. **Builds a spectral Matérn GP** that respects the cortical manifold's geometry (not Euclidean space), producing a proper probabilistic model of "normal" brain morphology.
|
|
58
|
+
4. **Generates vertex-wise surprise maps** — information-theoretic anomaly scores that quantify how unexpected each vertex's morphometry is, given the normative model and the surrounding cortical geometry.
|
|
59
|
+
5. **Aggregates anomalies by functional network** (Yeo-7, Schaefer-200, etc.), enabling statements like *"this patient has anomalous DMN structure"* from T1w data alone.
|
|
60
|
+
|
|
61
|
+
## Key innovations
|
|
62
|
+
|
|
63
|
+
- **Geodesic-aware GP kernel**: Uses the spectral Matérn kernel (Borovitskiy et al., NeurIPS 2020) — the only mathematically correct way to define Matérn GPs on curved manifolds. Naïve geodesic distance substitution does NOT yield a valid kernel.
|
|
64
|
+
- **Surprise maps**: Vertex-wise negative log-predictive density from a calibrated probabilistic model — theoretically optimal anomaly scoring that goes beyond z-scores.
|
|
65
|
+
- **Spectral shape descriptors for neuroimaging**: Brings HKS/WKS from computer graphics into clinical brain imaging for the first time.
|
|
66
|
+
- **Scalability to 150k vertices**: Spectral truncation (≤1000 LB eigenpairs) + variational sparse GP (≤1000 inducing points) makes the pipeline tractable on a single GPU.
|
|
67
|
+
|
|
68
|
+
## Installation
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Core installation
|
|
72
|
+
pip install corticalfields
|
|
73
|
+
|
|
74
|
+
# Full installation (includes optional dependencies)
|
|
75
|
+
pip install corticalfields[full]
|
|
76
|
+
|
|
77
|
+
# Development installation
|
|
78
|
+
git clone https://github.com/rdneuro/corticalfields.git
|
|
79
|
+
cd corticalfields
|
|
80
|
+
pip install -e ".[full,dev]"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Requirements
|
|
84
|
+
|
|
85
|
+
- Python ≥ 3.9
|
|
86
|
+
- PyTorch ≥ 2.0 (with CUDA for GPU acceleration)
|
|
87
|
+
- FreeSurfer (for surface reconstruction via `recon-all`)
|
|
88
|
+
- Core: numpy, scipy, nibabel, gpytorch, matplotlib, pyvista
|
|
89
|
+
- Optional: robust-laplacian, geometric-kernels, pymc, giotto-tda
|
|
90
|
+
|
|
91
|
+
## Quick start
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
import corticalfields as cf
|
|
95
|
+
from corticalfields.spectral import compute_eigenpairs
|
|
96
|
+
from corticalfields.utils import get_device, setup_logging
|
|
97
|
+
|
|
98
|
+
setup_logging("INFO")
|
|
99
|
+
device = get_device() # auto-detect CUDA
|
|
100
|
+
|
|
101
|
+
# 1. Load a FreeSurfer surface
|
|
102
|
+
surf = cf.load_freesurfer_surface(
|
|
103
|
+
subjects_dir="/data/freesurfer",
|
|
104
|
+
subject_id="fsaverage",
|
|
105
|
+
hemi="lh",
|
|
106
|
+
surface="pial",
|
|
107
|
+
overlays=["thickness", "curv", "sulc"],
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
# 2. Compute Laplace–Beltrami eigenpairs
|
|
111
|
+
lb = compute_eigenpairs(
|
|
112
|
+
surf.vertices, surf.faces,
|
|
113
|
+
n_eigenpairs=300, # 300 is a good default
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# 3. Compute spectral shape descriptors
|
|
117
|
+
hks = cf.heat_kernel_signature(lb, n_scales=16)
|
|
118
|
+
wks = cf.wave_kernel_signature(lb, n_energies=16)
|
|
119
|
+
gps = cf.global_point_signature(lb, n_components=10)
|
|
120
|
+
|
|
121
|
+
# 4. Train normative model on reference cohort thickness
|
|
122
|
+
model = cf.CorticalNormativeModel(lb, nu=2.5, n_inducing=512, device=device)
|
|
123
|
+
model.fit(reference_thickness_matrix, feature_name="thickness", n_epochs=100)
|
|
124
|
+
|
|
125
|
+
# 5. Score a patient
|
|
126
|
+
result = model.predict(patient_thickness)
|
|
127
|
+
print(f"Mean surprise: {result.surprise.mean():.2f}")
|
|
128
|
+
print(f"Fraction anomalous (|z| > 2): {(abs(result.z_score) > 2).mean():.1%}")
|
|
129
|
+
|
|
130
|
+
# 6. Aggregate by network
|
|
131
|
+
from corticalfields.surprise import compute_surprise
|
|
132
|
+
from corticalfields.utils import load_fsaverage_parcellation
|
|
133
|
+
|
|
134
|
+
yeo_labels, yeo_names = load_fsaverage_parcellation("yeo_7", hemi="lh")
|
|
135
|
+
surprise_map = compute_surprise(
|
|
136
|
+
patient_thickness, result.mean, result.variance,
|
|
137
|
+
)
|
|
138
|
+
network_scores = surprise_map.aggregate_by_network(yeo_labels, yeo_names)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Full pipeline example
|
|
142
|
+
|
|
143
|
+
See `examples/full_pipeline.py` for a complete walkthrough from raw FreeSurfer outputs to publication-quality surprise map figures.
|
|
144
|
+
|
|
145
|
+
## Architecture
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
corticalfields/
|
|
149
|
+
├── surface.py # Surface I/O (FreeSurfer, GIfTI, mesh utilities)
|
|
150
|
+
├── spectral.py # Laplace–Beltrami decomposition, HKS, WKS, GPS
|
|
151
|
+
├── kernels.py # Spectral Matérn kernels for GPyTorch
|
|
152
|
+
├── normative.py # GP-based normative modeling pipeline
|
|
153
|
+
├── surprise.py # Information-theoretic anomaly scoring
|
|
154
|
+
├── features.py # Morphometric feature extraction
|
|
155
|
+
├── graphs.py # Cortical similarity network construction
|
|
156
|
+
├── viz.py # Publication-quality surface visualization
|
|
157
|
+
└── utils.py # Helpers (GPU detection, parcellation, timing)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Mathematical foundations
|
|
161
|
+
|
|
162
|
+
The core of CorticalFields rests on three mathematical pillars:
|
|
163
|
+
|
|
164
|
+
**1. Laplace–Beltrami spectral decomposition.** On a compact Riemannian manifold (Σ, g), the LB operator Δ_g has a discrete spectrum 0 = λ₀ ≤ λ₁ ≤ λ₂ ≤ … with orthonormal eigenfunctions φᵢ. These encode the intrinsic geometry of the surface at all scales — low eigenvalues capture global shape, high eigenvalues capture fine-grained curvature.
|
|
165
|
+
|
|
166
|
+
**2. Spectral Matérn kernel.** The Matérn kernel on the manifold is defined via the spectral density: k(x,y) = σ² Σᵢ S_ν(λᵢ) φᵢ(x) φᵢ(y), where S_ν(λ) = (2ν/κ² + λ)^{−(ν+d/2)}. This yields a valid positive-definite kernel that respects the manifold geometry, unlike naïve geodesic-distance substitution.
|
|
167
|
+
|
|
168
|
+
**3. Information-theoretic surprise.** For a GP with posterior predictive p(y*|x,D) = N(μ(x), σ²(x)), the surprise at vertex x is S(x) = −log p(y_obs|x,D) = ½ log(2πσ²) + (y_obs − μ)²/(2σ²). This is the theoretically optimal anomaly score under the model.
|
|
169
|
+
|
|
170
|
+
## References
|
|
171
|
+
|
|
172
|
+
- Borovitskiy et al. (2020). Matérn Gaussian Processes on Riemannian Manifolds. NeurIPS.
|
|
173
|
+
- Sun, Ovsjanikov & Guibas (2009). Heat Kernel Signature. SGP.
|
|
174
|
+
- Aubry, Schlickewei & Cremers (2011). Wave Kernel Signature. ICCV.
|
|
175
|
+
- Sharp & Crane (2020). A Laplacian for Nonmanifold Triangle Meshes. SGP.
|
|
176
|
+
- Seidlitz et al. (2018). Morphometric Similarity Networks. Neuron.
|
|
177
|
+
- Marquand et al. (2019). Normative modeling in neuroimaging. Nature Protocols.
|
|
178
|
+
|
|
179
|
+
## Citation
|
|
180
|
+
|
|
181
|
+
If you use CorticalFields in your research, please cite:
|
|
182
|
+
|
|
183
|
+
```bibtex
|
|
184
|
+
@software{corticalfields2026,
|
|
185
|
+
author = {Velho Mago},
|
|
186
|
+
title = {CorticalFields: Geodesic-aware GP normative modeling on cortical surfaces},
|
|
187
|
+
year = {2026},
|
|
188
|
+
url = {https://github.com/rdneuro/corticalfields},
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## License
|
|
193
|
+
|
|
194
|
+
MIT
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# CorticalFields
|
|
2
|
+
|
|
3
|
+
**Geodesic-aware Gaussian Process normative modeling on cortical surfaces with spectral shape descriptors and information-theoretic surprise maps.**
|
|
4
|
+
|
|
5
|
+
CorticalFields extracts rich geometric information from structural MRI (T1w) data — without needing fMRI or dMRI — by treating the cortical surface as a Riemannian manifold and applying principled probabilistic modeling. It was designed for epilepsy research (MTLE-HS) but is applicable to any structural neuroimaging study.
|
|
6
|
+
|
|
7
|
+
## What it does
|
|
8
|
+
|
|
9
|
+
Given FreeSurfer-processed T1w data, CorticalFields:
|
|
10
|
+
|
|
11
|
+
1. **Decomposes the cortical geometry** via the Laplace–Beltrami operator, extracting the intrinsic spectral structure of the cortical mesh.
|
|
12
|
+
2. **Computes spectral shape descriptors** (Heat Kernel Signature, Wave Kernel Signature, Global Point Signature) that capture multi-scale geometric information at every vertex — from local curvature to global lobe membership.
|
|
13
|
+
3. **Builds a spectral Matérn GP** that respects the cortical manifold's geometry (not Euclidean space), producing a proper probabilistic model of "normal" brain morphology.
|
|
14
|
+
4. **Generates vertex-wise surprise maps** — information-theoretic anomaly scores that quantify how unexpected each vertex's morphometry is, given the normative model and the surrounding cortical geometry.
|
|
15
|
+
5. **Aggregates anomalies by functional network** (Yeo-7, Schaefer-200, etc.), enabling statements like *"this patient has anomalous DMN structure"* from T1w data alone.
|
|
16
|
+
|
|
17
|
+
## Key innovations
|
|
18
|
+
|
|
19
|
+
- **Geodesic-aware GP kernel**: Uses the spectral Matérn kernel (Borovitskiy et al., NeurIPS 2020) — the only mathematically correct way to define Matérn GPs on curved manifolds. Naïve geodesic distance substitution does NOT yield a valid kernel.
|
|
20
|
+
- **Surprise maps**: Vertex-wise negative log-predictive density from a calibrated probabilistic model — theoretically optimal anomaly scoring that goes beyond z-scores.
|
|
21
|
+
- **Spectral shape descriptors for neuroimaging**: Brings HKS/WKS from computer graphics into clinical brain imaging for the first time.
|
|
22
|
+
- **Scalability to 150k vertices**: Spectral truncation (≤1000 LB eigenpairs) + variational sparse GP (≤1000 inducing points) makes the pipeline tractable on a single GPU.
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Core installation
|
|
28
|
+
pip install corticalfields
|
|
29
|
+
|
|
30
|
+
# Full installation (includes optional dependencies)
|
|
31
|
+
pip install corticalfields[full]
|
|
32
|
+
|
|
33
|
+
# Development installation
|
|
34
|
+
git clone https://github.com/rdneuro/corticalfields.git
|
|
35
|
+
cd corticalfields
|
|
36
|
+
pip install -e ".[full,dev]"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Requirements
|
|
40
|
+
|
|
41
|
+
- Python ≥ 3.9
|
|
42
|
+
- PyTorch ≥ 2.0 (with CUDA for GPU acceleration)
|
|
43
|
+
- FreeSurfer (for surface reconstruction via `recon-all`)
|
|
44
|
+
- Core: numpy, scipy, nibabel, gpytorch, matplotlib, pyvista
|
|
45
|
+
- Optional: robust-laplacian, geometric-kernels, pymc, giotto-tda
|
|
46
|
+
|
|
47
|
+
## Quick start
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
import corticalfields as cf
|
|
51
|
+
from corticalfields.spectral import compute_eigenpairs
|
|
52
|
+
from corticalfields.utils import get_device, setup_logging
|
|
53
|
+
|
|
54
|
+
setup_logging("INFO")
|
|
55
|
+
device = get_device() # auto-detect CUDA
|
|
56
|
+
|
|
57
|
+
# 1. Load a FreeSurfer surface
|
|
58
|
+
surf = cf.load_freesurfer_surface(
|
|
59
|
+
subjects_dir="/data/freesurfer",
|
|
60
|
+
subject_id="fsaverage",
|
|
61
|
+
hemi="lh",
|
|
62
|
+
surface="pial",
|
|
63
|
+
overlays=["thickness", "curv", "sulc"],
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
# 2. Compute Laplace–Beltrami eigenpairs
|
|
67
|
+
lb = compute_eigenpairs(
|
|
68
|
+
surf.vertices, surf.faces,
|
|
69
|
+
n_eigenpairs=300, # 300 is a good default
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# 3. Compute spectral shape descriptors
|
|
73
|
+
hks = cf.heat_kernel_signature(lb, n_scales=16)
|
|
74
|
+
wks = cf.wave_kernel_signature(lb, n_energies=16)
|
|
75
|
+
gps = cf.global_point_signature(lb, n_components=10)
|
|
76
|
+
|
|
77
|
+
# 4. Train normative model on reference cohort thickness
|
|
78
|
+
model = cf.CorticalNormativeModel(lb, nu=2.5, n_inducing=512, device=device)
|
|
79
|
+
model.fit(reference_thickness_matrix, feature_name="thickness", n_epochs=100)
|
|
80
|
+
|
|
81
|
+
# 5. Score a patient
|
|
82
|
+
result = model.predict(patient_thickness)
|
|
83
|
+
print(f"Mean surprise: {result.surprise.mean():.2f}")
|
|
84
|
+
print(f"Fraction anomalous (|z| > 2): {(abs(result.z_score) > 2).mean():.1%}")
|
|
85
|
+
|
|
86
|
+
# 6. Aggregate by network
|
|
87
|
+
from corticalfields.surprise import compute_surprise
|
|
88
|
+
from corticalfields.utils import load_fsaverage_parcellation
|
|
89
|
+
|
|
90
|
+
yeo_labels, yeo_names = load_fsaverage_parcellation("yeo_7", hemi="lh")
|
|
91
|
+
surprise_map = compute_surprise(
|
|
92
|
+
patient_thickness, result.mean, result.variance,
|
|
93
|
+
)
|
|
94
|
+
network_scores = surprise_map.aggregate_by_network(yeo_labels, yeo_names)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Full pipeline example
|
|
98
|
+
|
|
99
|
+
See `examples/full_pipeline.py` for a complete walkthrough from raw FreeSurfer outputs to publication-quality surprise map figures.
|
|
100
|
+
|
|
101
|
+
## Architecture
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
corticalfields/
|
|
105
|
+
├── surface.py # Surface I/O (FreeSurfer, GIfTI, mesh utilities)
|
|
106
|
+
├── spectral.py # Laplace–Beltrami decomposition, HKS, WKS, GPS
|
|
107
|
+
├── kernels.py # Spectral Matérn kernels for GPyTorch
|
|
108
|
+
├── normative.py # GP-based normative modeling pipeline
|
|
109
|
+
├── surprise.py # Information-theoretic anomaly scoring
|
|
110
|
+
├── features.py # Morphometric feature extraction
|
|
111
|
+
├── graphs.py # Cortical similarity network construction
|
|
112
|
+
├── viz.py # Publication-quality surface visualization
|
|
113
|
+
└── utils.py # Helpers (GPU detection, parcellation, timing)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Mathematical foundations
|
|
117
|
+
|
|
118
|
+
The core of CorticalFields rests on three mathematical pillars:
|
|
119
|
+
|
|
120
|
+
**1. Laplace–Beltrami spectral decomposition.** On a compact Riemannian manifold (Σ, g), the LB operator Δ_g has a discrete spectrum 0 = λ₀ ≤ λ₁ ≤ λ₂ ≤ … with orthonormal eigenfunctions φᵢ. These encode the intrinsic geometry of the surface at all scales — low eigenvalues capture global shape, high eigenvalues capture fine-grained curvature.
|
|
121
|
+
|
|
122
|
+
**2. Spectral Matérn kernel.** The Matérn kernel on the manifold is defined via the spectral density: k(x,y) = σ² Σᵢ S_ν(λᵢ) φᵢ(x) φᵢ(y), where S_ν(λ) = (2ν/κ² + λ)^{−(ν+d/2)}. This yields a valid positive-definite kernel that respects the manifold geometry, unlike naïve geodesic-distance substitution.
|
|
123
|
+
|
|
124
|
+
**3. Information-theoretic surprise.** For a GP with posterior predictive p(y*|x,D) = N(μ(x), σ²(x)), the surprise at vertex x is S(x) = −log p(y_obs|x,D) = ½ log(2πσ²) + (y_obs − μ)²/(2σ²). This is the theoretically optimal anomaly score under the model.
|
|
125
|
+
|
|
126
|
+
## References
|
|
127
|
+
|
|
128
|
+
- Borovitskiy et al. (2020). Matérn Gaussian Processes on Riemannian Manifolds. NeurIPS.
|
|
129
|
+
- Sun, Ovsjanikov & Guibas (2009). Heat Kernel Signature. SGP.
|
|
130
|
+
- Aubry, Schlickewei & Cremers (2011). Wave Kernel Signature. ICCV.
|
|
131
|
+
- Sharp & Crane (2020). A Laplacian for Nonmanifold Triangle Meshes. SGP.
|
|
132
|
+
- Seidlitz et al. (2018). Morphometric Similarity Networks. Neuron.
|
|
133
|
+
- Marquand et al. (2019). Normative modeling in neuroimaging. Nature Protocols.
|
|
134
|
+
|
|
135
|
+
## Citation
|
|
136
|
+
|
|
137
|
+
If you use CorticalFields in your research, please cite:
|
|
138
|
+
|
|
139
|
+
```bibtex
|
|
140
|
+
@software{corticalfields2026,
|
|
141
|
+
author = {Velho Mago},
|
|
142
|
+
title = {CorticalFields: Geodesic-aware GP normative modeling on cortical surfaces},
|
|
143
|
+
year = {2026},
|
|
144
|
+
url = {https://github.com/rdneuro/corticalfields},
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## License
|
|
149
|
+
|
|
150
|
+
MIT
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "corticalfields"
|
|
7
|
+
version = "0.1.1"
|
|
8
|
+
description = "Geodesic-aware Gaussian Process normative modeling on cortical surfaces with spectral shape descriptors and information-theoretic surprise maps."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "rdneuro", email = "r.debona@ufrj.br"},
|
|
14
|
+
]
|
|
15
|
+
keywords = [
|
|
16
|
+
"neuroimaging", "cortical-surface", "gaussian-process",
|
|
17
|
+
"normative-modeling", "epilepsy", "heat-kernel-signature",
|
|
18
|
+
"laplace-beltrami", "surprise-maps", "spectral-analysis",
|
|
19
|
+
"bayesian-inference",
|
|
20
|
+
]
|
|
21
|
+
classifiers = [
|
|
22
|
+
"Development Status :: 3 - Alpha",
|
|
23
|
+
"Intended Audience :: Science/Research",
|
|
24
|
+
"License :: OSI Approved :: MIT License",
|
|
25
|
+
"Programming Language :: Python :: 3",
|
|
26
|
+
"Topic :: Scientific/Engineering :: Medical Science Apps.",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
dependencies = [
|
|
30
|
+
"numpy>=1.24",
|
|
31
|
+
"scipy>=1.10",
|
|
32
|
+
"nibabel>=5.0",
|
|
33
|
+
"torch>=2.0",
|
|
34
|
+
"gpytorch>=1.11",
|
|
35
|
+
"scikit-sparse>=0.4",
|
|
36
|
+
"trimesh>=4.0",
|
|
37
|
+
"pyvista>=0.42",
|
|
38
|
+
"matplotlib>=3.7",
|
|
39
|
+
"tqdm>=4.65",
|
|
40
|
+
"joblib>=1.3",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[project.optional-dependencies]
|
|
44
|
+
full = [
|
|
45
|
+
"robust-laplacian>=0.2",
|
|
46
|
+
"potpourri3d>=0.0.8",
|
|
47
|
+
"geometric-kernels>=0.2",
|
|
48
|
+
"pymc>=5.10",
|
|
49
|
+
"giotto-tda>=0.6",
|
|
50
|
+
"torch-geometric>=2.4",
|
|
51
|
+
"surfplot>=0.2",
|
|
52
|
+
"brainspace>=0.1",
|
|
53
|
+
"neuromaps>=0.0.4",
|
|
54
|
+
]
|
|
55
|
+
dev = [
|
|
56
|
+
"pytest>=7.0",
|
|
57
|
+
"pytest-cov>=4.0",
|
|
58
|
+
"ruff>=0.1",
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
[project.urls]
|
|
62
|
+
Homepage = "https://github.com/rdneuro/corticalfields"
|
|
63
|
+
Documentation = "https://corticalfields.readthedocs.io"
|
|
64
|
+
|
|
65
|
+
[tool.setuptools.packages.find]
|
|
66
|
+
where = ["src"]
|
|
67
|
+
|
|
68
|
+
[tool.ruff]
|
|
69
|
+
line-length = 88
|
|
70
|
+
target-version = "py39"
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CorticalFields — Geodesic-aware GP normative modeling on cortical surfaces.
|
|
3
|
+
|
|
4
|
+
A library for computing information-theoretic surprise maps on the cortical
|
|
5
|
+
manifold using spectral Matérn Gaussian Processes, Heat Kernel Signatures,
|
|
6
|
+
and Laplace–Beltrami spectral analysis. Designed for structural MRI (T1w)
|
|
7
|
+
data in clinical neuroimaging, with emphasis on epilepsy (MTLE-HS).
|
|
8
|
+
|
|
9
|
+
Core pipeline:
|
|
10
|
+
1. Load FreeSurfer surfaces and morphometric overlays
|
|
11
|
+
2. Compute Laplace–Beltrami eigenpairs on the cortical mesh
|
|
12
|
+
3. Extract spectral shape descriptors (HKS, WKS, GPS)
|
|
13
|
+
4. Build spectral Matérn GP kernels on the manifold
|
|
14
|
+
5. Fit normative models on a reference cohort
|
|
15
|
+
6. Generate vertex-wise surprise / anomaly maps for patients
|
|
16
|
+
|
|
17
|
+
Modules
|
|
18
|
+
-------
|
|
19
|
+
surface : Surface I/O — FreeSurfer, GIfTI, mesh utilities
|
|
20
|
+
spectral : Laplace–Beltrami decomposition, HKS, WKS, GPS
|
|
21
|
+
kernels : Spectral Matérn kernels for GPyTorch
|
|
22
|
+
normative : GP-based normative modeling pipeline
|
|
23
|
+
surprise : Information-theoretic anomaly scoring
|
|
24
|
+
features : Morphometric feature extraction from FreeSurfer
|
|
25
|
+
graphs : Cortical similarity network construction
|
|
26
|
+
viz : Publication-quality surface visualization
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
__version__ = "0.1.0"
|
|
30
|
+
__author__ = "Velho Mago (rdneuro)"
|
|
31
|
+
|
|
32
|
+
# ── Lazy imports ────────────────────────────────────────────────────────
|
|
33
|
+
# Heavy dependencies (torch, gpytorch) are only loaded when the modules
|
|
34
|
+
# that need them are first accessed. This keeps `import corticalfields`
|
|
35
|
+
# fast and memory-light for submodule-level usage.
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def __getattr__(name: str):
|
|
39
|
+
"""Lazy attribute loader — imports submodules on first access."""
|
|
40
|
+
_MAP = {
|
|
41
|
+
# surface.py (lightweight — numpy/nibabel only)
|
|
42
|
+
"CorticalSurface": ("corticalfields.surface", "CorticalSurface"),
|
|
43
|
+
"load_freesurfer_surface": ("corticalfields.surface", "load_freesurfer_surface"),
|
|
44
|
+
# spectral.py (lightweight — numpy/scipy only)
|
|
45
|
+
"LaplaceBeltrami": ("corticalfields.spectral", "LaplaceBeltrami"),
|
|
46
|
+
"heat_kernel_signature": ("corticalfields.spectral", "heat_kernel_signature"),
|
|
47
|
+
"wave_kernel_signature": ("corticalfields.spectral", "wave_kernel_signature"),
|
|
48
|
+
"global_point_signature": ("corticalfields.spectral", "global_point_signature"),
|
|
49
|
+
# kernels.py (heavy — torch + gpytorch)
|
|
50
|
+
"SpectralMaternKernel": ("corticalfields.kernels", "SpectralMaternKernel"),
|
|
51
|
+
# normative.py (heavy — torch + gpytorch)
|
|
52
|
+
"CorticalNormativeModel": ("corticalfields.normative", "CorticalNormativeModel"),
|
|
53
|
+
# surprise.py (lightweight — numpy/scipy only)
|
|
54
|
+
"SurpriseMap": ("corticalfields.surprise", "SurpriseMap"),
|
|
55
|
+
"compute_surprise": ("corticalfields.surprise", "compute_surprise"),
|
|
56
|
+
# features.py (lightweight)
|
|
57
|
+
"MorphometricProfile": ("corticalfields.features", "MorphometricProfile"),
|
|
58
|
+
}
|
|
59
|
+
if name in _MAP:
|
|
60
|
+
module_path, attr = _MAP[name]
|
|
61
|
+
import importlib
|
|
62
|
+
mod = importlib.import_module(module_path)
|
|
63
|
+
return getattr(mod, attr)
|
|
64
|
+
raise AttributeError(f"module 'corticalfields' has no attribute {name!r}")
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
__all__ = [
|
|
68
|
+
"CorticalSurface", "load_freesurfer_surface",
|
|
69
|
+
"LaplaceBeltrami", "heat_kernel_signature",
|
|
70
|
+
"wave_kernel_signature", "global_point_signature",
|
|
71
|
+
"SpectralMaternKernel",
|
|
72
|
+
"CorticalNormativeModel",
|
|
73
|
+
"SurpriseMap", "compute_surprise",
|
|
74
|
+
"MorphometricProfile",
|
|
75
|
+
]
|