simcortexpp 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 (49) hide show
  1. simcortexpp-0.1.0/PKG-INFO +334 -0
  2. simcortexpp-0.1.0/README.md +309 -0
  3. simcortexpp-0.1.0/pyproject.toml +66 -0
  4. simcortexpp-0.1.0/setup.cfg +4 -0
  5. simcortexpp-0.1.0/src/simcortexpp/__init__.py +0 -0
  6. simcortexpp-0.1.0/src/simcortexpp/cli/__init__.py +0 -0
  7. simcortexpp-0.1.0/src/simcortexpp/cli/main.py +81 -0
  8. simcortexpp-0.1.0/src/simcortexpp/configs/__init__.py +0 -0
  9. simcortexpp-0.1.0/src/simcortexpp/configs/deform/__init__.py +0 -0
  10. simcortexpp-0.1.0/src/simcortexpp/configs/deform/eval.yaml +34 -0
  11. simcortexpp-0.1.0/src/simcortexpp/configs/deform/inference.yaml +60 -0
  12. simcortexpp-0.1.0/src/simcortexpp/configs/deform/train.yaml +98 -0
  13. simcortexpp-0.1.0/src/simcortexpp/configs/initsurf/__init__.py +0 -0
  14. simcortexpp-0.1.0/src/simcortexpp/configs/initsurf/generate.yaml +50 -0
  15. simcortexpp-0.1.0/src/simcortexpp/configs/seg/__init__.py +0 -0
  16. simcortexpp-0.1.0/src/simcortexpp/configs/seg/eval.yaml +31 -0
  17. simcortexpp-0.1.0/src/simcortexpp/configs/seg/inference.yaml +35 -0
  18. simcortexpp-0.1.0/src/simcortexpp/configs/seg/train.yaml +42 -0
  19. simcortexpp-0.1.0/src/simcortexpp/deform/__init__.py +0 -0
  20. simcortexpp-0.1.0/src/simcortexpp/deform/data/__init__.py +0 -0
  21. simcortexpp-0.1.0/src/simcortexpp/deform/data/dataloader.py +268 -0
  22. simcortexpp-0.1.0/src/simcortexpp/deform/eval.py +347 -0
  23. simcortexpp-0.1.0/src/simcortexpp/deform/inference.py +244 -0
  24. simcortexpp-0.1.0/src/simcortexpp/deform/models/__init__.py +0 -0
  25. simcortexpp-0.1.0/src/simcortexpp/deform/models/surfdeform.py +356 -0
  26. simcortexpp-0.1.0/src/simcortexpp/deform/train.py +1173 -0
  27. simcortexpp-0.1.0/src/simcortexpp/deform/utils/__init__.py +0 -0
  28. simcortexpp-0.1.0/src/simcortexpp/deform/utils/coords.py +90 -0
  29. simcortexpp-0.1.0/src/simcortexpp/initsurf/__init__.py +0 -0
  30. simcortexpp-0.1.0/src/simcortexpp/initsurf/generate.py +354 -0
  31. simcortexpp-0.1.0/src/simcortexpp/initsurf/paths.py +19 -0
  32. simcortexpp-0.1.0/src/simcortexpp/preproc/__init__.py +0 -0
  33. simcortexpp-0.1.0/src/simcortexpp/preproc/fs_to_mni.py +696 -0
  34. simcortexpp-0.1.0/src/simcortexpp/seg/__init__.py +0 -0
  35. simcortexpp-0.1.0/src/simcortexpp/seg/data/__init__.py +0 -0
  36. simcortexpp-0.1.0/src/simcortexpp/seg/data/dataloader.py +328 -0
  37. simcortexpp-0.1.0/src/simcortexpp/seg/eval.py +248 -0
  38. simcortexpp-0.1.0/src/simcortexpp/seg/inference.py +291 -0
  39. simcortexpp-0.1.0/src/simcortexpp/seg/models/__init__.py +0 -0
  40. simcortexpp-0.1.0/src/simcortexpp/seg/models/unet.py +63 -0
  41. simcortexpp-0.1.0/src/simcortexpp/seg/train.py +432 -0
  42. simcortexpp-0.1.0/src/simcortexpp/utils/__init__.py +0 -0
  43. simcortexpp-0.1.0/src/simcortexpp/utils/tca.py +298 -0
  44. simcortexpp-0.1.0/src/simcortexpp.egg-info/PKG-INFO +334 -0
  45. simcortexpp-0.1.0/src/simcortexpp.egg-info/SOURCES.txt +47 -0
  46. simcortexpp-0.1.0/src/simcortexpp.egg-info/dependency_links.txt +1 -0
  47. simcortexpp-0.1.0/src/simcortexpp.egg-info/entry_points.txt +2 -0
  48. simcortexpp-0.1.0/src/simcortexpp.egg-info/requires.txt +20 -0
  49. simcortexpp-0.1.0/src/simcortexpp.egg-info/top_level.txt +1 -0
@@ -0,0 +1,334 @@
1
+ Metadata-Version: 2.4
2
+ Name: simcortexpp
3
+ Version: 0.1.0
4
+ Summary: SimCortexPP (SCPP) — CLI-first pipeline for cortical surface reconstruction (preproc, seg, initsurf, deform)
5
+ Author: Kaveh Moradkhani
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: typer>=0.12
9
+ Requires-Dist: numpy>=1.24
10
+ Requires-Dist: pandas>=2.0
11
+ Requires-Dist: nibabel>=5.2
12
+ Requires-Dist: hydra-core>=1.3
13
+ Requires-Dist: omegaconf>=2.3
14
+ Requires-Dist: tqdm>=4.66
15
+ Requires-Dist: tensorboard>=2.14
16
+ Requires-Dist: trimesh>=4.0
17
+ Requires-Dist: openpyxl>=3.1
18
+ Provides-Extra: seg
19
+ Requires-Dist: monai>=1.3; extra == "seg"
20
+ Provides-Extra: deform-metrics
21
+ Requires-Dist: python-fcl; extra == "deform-metrics"
22
+ Requires-Dist: pymeshlab; extra == "deform-metrics"
23
+ Provides-Extra: torch
24
+ Requires-Dist: torch>=2.0; extra == "torch"
25
+
26
+ # SimCortexPP (SCPP)
27
+
28
+ SimCortexPP (SCPP) is a **CLI-first** Python package for cortical surface reconstruction in MNI space. It provides four stages:
29
+
30
+ 1. **Preprocessing (FreeSurfer → MNI152)**
31
+ Export key FreeSurfer volumes/surfaces, register them to MNI152, and write outputs in a **BIDS-derivatives-style** layout.
32
+
33
+ 2. **Segmentation (3D U-Net in MNI space)**
34
+ Train and apply a 3D U-Net to predict a **9-class segmentation** in **MNI152 space**, with inference and evaluation utilities.
35
+
36
+ 3. **Initial Surfaces (InitSurf)**
37
+ Generate initial White Matter and Pial surfaces from segmentation predictions (plus ribbon SDF/probability outputs).
38
+
39
+ 4. **Deformation (Deform)**
40
+ Deform the initial surfaces toward MNI-aligned FreeSurfer surfaces using geometric losses and optional collision metrics, and write **deformed surfaces** as BIDS-derivatives.
41
+
42
+ This README focuses on **how to run the pipeline correctly** (inputs, outputs, folder/file naming, and commands).
43
+
44
+ ---
45
+
46
+ ## Table of Contents
47
+
48
+ - [Installation](#installation)
49
+ - [Configuration](#configuration)
50
+ - [Data and Folder Conventions](#data-and-folder-conventions)
51
+ - [Split File Format](#split-file-format)
52
+ - [Stage 1 — Preprocessing: FreeSurfer → MNI152](#stage-1--preprocessing-freesurfer--mni152)
53
+ - [Stage 2 — Segmentation: 3D U-Net (MNI space)](#stage-2--segmentation-3d-u-net-mni-space)
54
+ - [Stage 3 — Initial Surfaces (InitSurf)](#stage-3--initial-surfaces-initsurf)
55
+ - [Stage 4 — Deformation (Deform)](#stage-4--deformation-deform)
56
+ - [License](#license)
57
+
58
+ ---
59
+
60
+ ## Installation
61
+
62
+ From the repository root:
63
+
64
+ ```bash
65
+ pip install -e .
66
+ scpp --help
67
+ scpp seg --help
68
+ scpp initsurf --help
69
+ scpp deform --help
70
+ ```
71
+
72
+ ### Recommended environment
73
+ - Python 3.10+
74
+ - PyTorch + MONAI
75
+ - `nibabel`, `numpy`, `pandas`, `openpyxl`
76
+ - `trimesh`, `scipy`, `tqdm`
77
+ - External tools for Stage 1: **NiftyReg** (`reg_aladin`, `reg_resample`)
78
+ - Optional (Deform metrics):
79
+ - `python-fcl` for collision metrics
80
+ - `pymeshlab` for SIF (self-intersection fraction) in Deform evaluation
81
+
82
+ ---
83
+
84
+ ## Configuration
85
+
86
+ All stages use Hydra YAML configs shipped with the package (see `src/simcortexpp/configs/<stage>/*.yaml`).
87
+
88
+ You have **two** ways to configure a run:
89
+
90
+ 1) **Edit the stage YAML** (recommended for longer runs / stable experiments), then run commands with no extra arguments, e.g.:
91
+ - `scpp deform eval`
92
+
93
+ 2) **Use Hydra overrides on the CLI** (recommended for quick tests), e.g.:
94
+ - `scpp deform eval dataset.split_name=test outputs.out_dir=/tmp/deform_eval`
95
+
96
+ ---
97
+
98
+ ## Data and Folder Conventions
99
+
100
+ You will typically work with **two roots**:
101
+
102
+ 1) **Code repository (this repository)**
103
+ Contains code, configs, and scripts (no data).
104
+
105
+ 2) **Dataset root (BIDS + derivatives)**
106
+ Each dataset has its own root directory. Recommended structure:
107
+
108
+ ```text
109
+ datasets/<dataset-name>/
110
+ bids/ # raw BIDS dataset
111
+ derivatives/ # processed outputs (BIDS derivatives)
112
+ freesurfer-7.4.1/
113
+ scpp-preproc-0.1/
114
+ scpp-seg-0.1/
115
+ scpp-initsurf-0.1/
116
+ scpp-deform-0.1/
117
+ splits/
118
+ <dataset>_split.csv
119
+ ```
120
+
121
+ SCPP reads inputs from `derivatives/` and writes outputs back to `derivatives/` using BIDS-derivatives-style naming.
122
+
123
+ > Important: keep the dataset root naming consistent (e.g., use `datasets/...` everywhere).
124
+
125
+ ---
126
+
127
+ ## Split File Format
128
+
129
+ A split CSV is required for Segmentation, InitSurf, and Deform.
130
+
131
+ ### Single-dataset split
132
+ Minimal columns:
133
+ - `subject` (e.g., `sub-0001`)
134
+ - `split` in `{train, val, test}`
135
+
136
+ ### Multi-dataset split
137
+ Include an additional column:
138
+ - `dataset` (string key that matches config keys, e.g., `HCP_YA`, `OASIS1`)
139
+
140
+ Example:
141
+ ```csv
142
+ subject,split,dataset
143
+ sub-100307,test,HCP_YA
144
+ sub-101915,test,HCP_YA
145
+ sub-0001,test,OASIS1
146
+ ```
147
+
148
+ ---
149
+
150
+ ## Stage 1 — Preprocessing: FreeSurfer → MNI152
151
+
152
+ This stage exports key FreeSurfer outputs (volumes + surfaces), registers them to **MNI152**, and writes results to a **BIDS-derivatives-style** folder.
153
+
154
+ ### Inputs
155
+ - FreeSurfer derivatives root (contains `sub-*` folders)
156
+ - MNI template (e.g., `src/MNI152_T1_1mm.nii.gz`)
157
+
158
+ ### Dependencies (system tools)
159
+ - **NiftyReg**: `reg_aladin`, `reg_resample` must be in `PATH`
160
+ - **FreeSurfer** tools are recommended (e.g., `mri_convert`, `mris_convert`) for consistent conversions
161
+
162
+ ### Run (all subjects discovered automatically)
163
+ ```bash
164
+ scpp fs-to-mni --freesurfer-root /path/to/datasets/<dataset>/derivatives/freesurfer-7.4.1 --out-deriv-root /path/to/datasets/<dataset>/derivatives/scpp-preproc-0.1 --mni-template /path/to/SimCortexPP/src/MNI152_T1_1mm.nii.gz --decimate 0.3 -v
165
+ ```
166
+
167
+ ### Run (selected subjects)
168
+ ```bash
169
+ scpp fs-to-mni --freesurfer-root /path/to/datasets/<dataset>/derivatives/freesurfer-7.4.1 --out-deriv-root /path/to/datasets/<dataset>/derivatives/scpp-preproc-0.1 --mni-template /path/to/SimCortexPP/src/MNI152_T1_1mm.nii.gz -p sub-0001 -p sub-0019 -v
170
+ ```
171
+
172
+ ### Output layout (example)
173
+ ```text
174
+ scpp-preproc-0.1/
175
+ dataset_description.json
176
+ sub-XXXX/
177
+ ses-01/
178
+ anat/
179
+ sub-XXXX_ses-01_space-MNI152_desc-preproc_T1w.nii.gz
180
+ sub-XXXX_ses-01_space-MNI152_desc-aparc+aseg_dseg.nii.gz
181
+ sub-XXXX_ses-01_space-MNI152_desc-filled_T1w.nii.gz
182
+ sub-XXXX_ses-01_from-T1w_to-MNI152_mode-image_xfm.txt
183
+ surfaces/
184
+ sub-XXXX_ses-01_space-MNI152_hemi-L_white.surf.ply
185
+ sub-XXXX_ses-01_space-MNI152_hemi-L_pial.surf.ply
186
+ sub-XXXX_ses-01_space-MNI152_hemi-R_white.surf.ply
187
+ sub-XXXX_ses-01_space-MNI152_hemi-R_pial.surf.ply
188
+ ```
189
+
190
+ ---
191
+
192
+ ## Stage 2 — Segmentation: 3D U-Net (MNI space)
193
+
194
+ This stage trains and applies a 3D U-Net to predict a **9-class segmentation** in **MNI152 space** using Stage 1 outputs.
195
+
196
+ ### Expected inputs (from Stage 1)
197
+ Under `scpp-preproc-*`, for each subject:
198
+ - `..._desc-preproc_T1w.nii.gz`
199
+ - `..._desc-aparc+aseg_dseg.nii.gz`
200
+ - `..._desc-filled_T1w.nii.gz`
201
+
202
+ ### Output naming (predictions)
203
+ Predictions are written under `scpp-seg-*`:
204
+ - `sub-XXXX/ses-01/anat/sub-XXXX_ses-01_space-MNI152_desc-seg9_dseg.nii.gz`
205
+
206
+ ### Train (single GPU)
207
+ ```bash
208
+ scpp seg train dataset.path=/path/to/datasets/<dataset>/derivatives/scpp-preproc-0.1 dataset.split_file=/path/to/datasets/<dataset>/splits/<dataset>_split.csv outputs.root=/path/to/scpp-runs/seg/exp01 trainer.use_ddp=false
209
+ ```
210
+
211
+ ### Train (multi-GPU, torchrun)
212
+ ```bash
213
+ scpp seg train --torchrun --nproc-per-node 2 dataset.path=/path/to/datasets/<dataset>/derivatives/scpp-preproc-0.1 dataset.split_file=/path/to/datasets/<dataset>/splits/<dataset>_split.csv outputs.root=/path/to/scpp-runs/seg/exp01 trainer.use_ddp=true
214
+ ```
215
+
216
+ ### Inference
217
+ ```bash
218
+ scpp seg infer dataset.path=/path/to/datasets/<dataset>/derivatives/scpp-preproc-0.1 dataset.split_file=/path/to/datasets/<dataset>/splits/<dataset>_split.csv dataset.split_name=test model.ckpt_path=/path/to/seg_best_dice.pt outputs.out_root=/path/to/datasets/<dataset>/derivatives/scpp-seg-0.1
219
+ ```
220
+
221
+ ### Evaluation (multi-dataset example)
222
+ ```bash
223
+ scpp seg eval dataset.split_file=/path/to/datasets/splits/dataset_split.csv dataset.split_name=test dataset.roots.HCP_YA=/path/to/datasets/hcpya-u100/derivatives/scpp-preproc-0.1 dataset.roots.OASIS1=/path/to/datasets/oasis-1/derivatives/scpp-preproc-0.1 outputs.pred_roots.HCP_YA=/path/to/datasets/hcpya-u100/derivatives/scpp-seg-0.1 outputs.pred_roots.OASIS1=/path/to/datasets/oasis-1/derivatives/scpp-seg-0.1 outputs.eval_csv=/path/to/scpp-runs/seg/exp01/evals/seg_eval_test.csv outputs.eval_xlsx=/path/to/scpp-runs/seg/exp01/evals/seg_eval_test.xlsx
224
+ ```
225
+
226
+ ---
227
+
228
+ ## Stage 3 — Initial Surfaces (InitSurf)
229
+
230
+ This stage generates initial cortical surfaces from saved segmentation predictions (not end-to-end).
231
+
232
+ ### Inputs
233
+ - Preproc roots (`scpp-preproc-*`) for MNI T1
234
+ - Seg roots (`scpp-seg-*`) for `..._desc-seg9_dseg.nii.gz`
235
+ - Split CSV (same format as Stage 2)
236
+
237
+ ### Outputs
238
+ BIDS-derivatives-style outputs under `scpp-initsurf-*` (meshes + SDF volumes + ribbon prob):
239
+ ```text
240
+ scpp-initsurf-0.1/
241
+ dataset_description.json
242
+ sub-XXXX/
243
+ ses-01/
244
+ anat/
245
+ sub-XXXX_ses-01_space-MNI152_desc-lh_white_sdf.nii.gz
246
+ sub-XXXX_ses-01_space-MNI152_desc-rh_white_sdf.nii.gz
247
+ sub-XXXX_ses-01_space-MNI152_desc-lh_pial_sdf.nii.gz
248
+ sub-XXXX_ses-01_space-MNI152_desc-rh_pial_sdf.nii.gz
249
+ sub-XXXX_ses-01_space-MNI152_desc-ribbon_sdf.nii.gz
250
+ sub-XXXX_ses-01_space-MNI152_desc-ribbon_prob.nii.gz
251
+ surfaces/
252
+ sub-XXXX_ses-01_space-MNI152_hemi-L_white.surf.ply
253
+ sub-XXXX_ses-01_space-MNI152_hemi-L_pial.surf.ply
254
+ sub-XXXX_ses-01_space-MNI152_hemi-R_white.surf.ply
255
+ sub-XXXX_ses-01_space-MNI152_hemi-R_pial.surf.ply
256
+ ```
257
+
258
+ ### Run (multi-dataset example)
259
+ ```bash
260
+ scpp initsurf generate dataset.split_file=/path/to/datasets/splits/dataset_split.csv dataset.split_name=all dataset.roots.HCP_YA=/path/to/datasets/hcpya-u100/derivatives/scpp-preproc-0.1 dataset.roots.OASIS1=/path/to/datasets/oasis-1/derivatives/scpp-preproc-0.1 dataset.seg_roots.HCP_YA=/path/to/datasets/hcpya-u100/derivatives/scpp-seg-0.1 dataset.seg_roots.OASIS1=/path/to/datasets/oasis-1/derivatives/scpp-seg-0.1 outputs.out_roots.HCP_YA=/path/to/datasets/hcpya-u100/derivatives/scpp-initsurf-0.1 outputs.out_roots.OASIS1=/path/to/datasets/oasis-1/derivatives/scpp-initsurf-0.1 outputs.log_dir=/path/to/scpp-runs/initsurf/exp01/logs_generate
261
+ ```
262
+
263
+ Typical runtime: ~31 s/subject (hardware-dependent).
264
+
265
+ ---
266
+
267
+ ## Stage 4 — Deformation (Deform)
268
+
269
+ This stage deforms InitSurf meshes using input volumes and geometric losses, and writes **deformed** surfaces to a BIDS-derivatives folder.
270
+
271
+ ### Inputs
272
+ - Preproc root (`scpp-preproc-*`): MNI T1 + GT FreeSurfer surfaces in MNI space
273
+ - InitSurf root (`scpp-initsurf-*`): ribbon probability + initial surfaces
274
+ - Split CSV (same format as Stage 2)
275
+
276
+ ### Outputs
277
+ Deformed surfaces under `scpp-deform-*`:
278
+ ```text
279
+ scpp-deform-0.1/
280
+ dataset_description.json
281
+ sub-XXXX/
282
+ ses-01/
283
+ surfaces/
284
+ sub-XXXX_ses-01_space-MNI152_desc-deform_hemi-L_white.surf.ply
285
+ sub-XXXX_ses-01_space-MNI152_desc-deform_hemi-L_pial.surf.ply
286
+ sub-XXXX_ses-01_space-MNI152_desc-deform_hemi-R_white.surf.ply
287
+ sub-XXXX_ses-01_space-MNI152_desc-deform_hemi-R_pial.surf.ply
288
+ ```
289
+
290
+ ### Train (multi-GPU example)
291
+ ```bash
292
+ scpp deform train --torchrun --nproc-per-node 2 outputs.root=/path/to/scpp-runs/deform/exp01
293
+ ```
294
+
295
+ ### Inference
296
+ ```bash
297
+ scpp deform infer
298
+ ```
299
+
300
+ ### Evaluation
301
+ ```bash
302
+ scpp deform eval
303
+ ```
304
+
305
+ Evaluation writes four Excel files:
306
+ - `surface_metrics.xlsx`
307
+ - `collision_metrics.xlsx`
308
+ - `collision_metrics_enhanced.xlsx`
309
+ - `collision_summary.xlsx`
310
+
311
+ ---
312
+
313
+ ## Outputs Summary
314
+
315
+ For each dataset root:
316
+
317
+ - `derivatives/scpp-preproc-0.1/`
318
+ MNI T1, aparc+aseg, filled, transforms, and MNI-aligned FreeSurfer surfaces.
319
+
320
+ - `derivatives/scpp-seg-0.1/`
321
+ 9-class segmentation predictions (`*_desc-seg9_dseg.nii.gz`).
322
+
323
+ - `derivatives/scpp-initsurf-0.1/`
324
+ Initial surfaces (`*.surf.ply`) + SDF volumes + ribbon SDF/probability.
325
+
326
+ - `derivatives/scpp-deform-0.1/`
327
+ Deformed surfaces (`*_desc-deform_*.surf.ply`).
328
+
329
+ ---
330
+
331
+
332
+ ## License
333
+
334
+ Add your license and citation details here if needed.
@@ -0,0 +1,309 @@
1
+ # SimCortexPP (SCPP)
2
+
3
+ SimCortexPP (SCPP) is a **CLI-first** Python package for cortical surface reconstruction in MNI space. It provides four stages:
4
+
5
+ 1. **Preprocessing (FreeSurfer → MNI152)**
6
+ Export key FreeSurfer volumes/surfaces, register them to MNI152, and write outputs in a **BIDS-derivatives-style** layout.
7
+
8
+ 2. **Segmentation (3D U-Net in MNI space)**
9
+ Train and apply a 3D U-Net to predict a **9-class segmentation** in **MNI152 space**, with inference and evaluation utilities.
10
+
11
+ 3. **Initial Surfaces (InitSurf)**
12
+ Generate initial White Matter and Pial surfaces from segmentation predictions (plus ribbon SDF/probability outputs).
13
+
14
+ 4. **Deformation (Deform)**
15
+ Deform the initial surfaces toward MNI-aligned FreeSurfer surfaces using geometric losses and optional collision metrics, and write **deformed surfaces** as BIDS-derivatives.
16
+
17
+ This README focuses on **how to run the pipeline correctly** (inputs, outputs, folder/file naming, and commands).
18
+
19
+ ---
20
+
21
+ ## Table of Contents
22
+
23
+ - [Installation](#installation)
24
+ - [Configuration](#configuration)
25
+ - [Data and Folder Conventions](#data-and-folder-conventions)
26
+ - [Split File Format](#split-file-format)
27
+ - [Stage 1 — Preprocessing: FreeSurfer → MNI152](#stage-1--preprocessing-freesurfer--mni152)
28
+ - [Stage 2 — Segmentation: 3D U-Net (MNI space)](#stage-2--segmentation-3d-u-net-mni-space)
29
+ - [Stage 3 — Initial Surfaces (InitSurf)](#stage-3--initial-surfaces-initsurf)
30
+ - [Stage 4 — Deformation (Deform)](#stage-4--deformation-deform)
31
+ - [License](#license)
32
+
33
+ ---
34
+
35
+ ## Installation
36
+
37
+ From the repository root:
38
+
39
+ ```bash
40
+ pip install -e .
41
+ scpp --help
42
+ scpp seg --help
43
+ scpp initsurf --help
44
+ scpp deform --help
45
+ ```
46
+
47
+ ### Recommended environment
48
+ - Python 3.10+
49
+ - PyTorch + MONAI
50
+ - `nibabel`, `numpy`, `pandas`, `openpyxl`
51
+ - `trimesh`, `scipy`, `tqdm`
52
+ - External tools for Stage 1: **NiftyReg** (`reg_aladin`, `reg_resample`)
53
+ - Optional (Deform metrics):
54
+ - `python-fcl` for collision metrics
55
+ - `pymeshlab` for SIF (self-intersection fraction) in Deform evaluation
56
+
57
+ ---
58
+
59
+ ## Configuration
60
+
61
+ All stages use Hydra YAML configs shipped with the package (see `src/simcortexpp/configs/<stage>/*.yaml`).
62
+
63
+ You have **two** ways to configure a run:
64
+
65
+ 1) **Edit the stage YAML** (recommended for longer runs / stable experiments), then run commands with no extra arguments, e.g.:
66
+ - `scpp deform eval`
67
+
68
+ 2) **Use Hydra overrides on the CLI** (recommended for quick tests), e.g.:
69
+ - `scpp deform eval dataset.split_name=test outputs.out_dir=/tmp/deform_eval`
70
+
71
+ ---
72
+
73
+ ## Data and Folder Conventions
74
+
75
+ You will typically work with **two roots**:
76
+
77
+ 1) **Code repository (this repository)**
78
+ Contains code, configs, and scripts (no data).
79
+
80
+ 2) **Dataset root (BIDS + derivatives)**
81
+ Each dataset has its own root directory. Recommended structure:
82
+
83
+ ```text
84
+ datasets/<dataset-name>/
85
+ bids/ # raw BIDS dataset
86
+ derivatives/ # processed outputs (BIDS derivatives)
87
+ freesurfer-7.4.1/
88
+ scpp-preproc-0.1/
89
+ scpp-seg-0.1/
90
+ scpp-initsurf-0.1/
91
+ scpp-deform-0.1/
92
+ splits/
93
+ <dataset>_split.csv
94
+ ```
95
+
96
+ SCPP reads inputs from `derivatives/` and writes outputs back to `derivatives/` using BIDS-derivatives-style naming.
97
+
98
+ > Important: keep the dataset root naming consistent (e.g., use `datasets/...` everywhere).
99
+
100
+ ---
101
+
102
+ ## Split File Format
103
+
104
+ A split CSV is required for Segmentation, InitSurf, and Deform.
105
+
106
+ ### Single-dataset split
107
+ Minimal columns:
108
+ - `subject` (e.g., `sub-0001`)
109
+ - `split` in `{train, val, test}`
110
+
111
+ ### Multi-dataset split
112
+ Include an additional column:
113
+ - `dataset` (string key that matches config keys, e.g., `HCP_YA`, `OASIS1`)
114
+
115
+ Example:
116
+ ```csv
117
+ subject,split,dataset
118
+ sub-100307,test,HCP_YA
119
+ sub-101915,test,HCP_YA
120
+ sub-0001,test,OASIS1
121
+ ```
122
+
123
+ ---
124
+
125
+ ## Stage 1 — Preprocessing: FreeSurfer → MNI152
126
+
127
+ This stage exports key FreeSurfer outputs (volumes + surfaces), registers them to **MNI152**, and writes results to a **BIDS-derivatives-style** folder.
128
+
129
+ ### Inputs
130
+ - FreeSurfer derivatives root (contains `sub-*` folders)
131
+ - MNI template (e.g., `src/MNI152_T1_1mm.nii.gz`)
132
+
133
+ ### Dependencies (system tools)
134
+ - **NiftyReg**: `reg_aladin`, `reg_resample` must be in `PATH`
135
+ - **FreeSurfer** tools are recommended (e.g., `mri_convert`, `mris_convert`) for consistent conversions
136
+
137
+ ### Run (all subjects discovered automatically)
138
+ ```bash
139
+ scpp fs-to-mni --freesurfer-root /path/to/datasets/<dataset>/derivatives/freesurfer-7.4.1 --out-deriv-root /path/to/datasets/<dataset>/derivatives/scpp-preproc-0.1 --mni-template /path/to/SimCortexPP/src/MNI152_T1_1mm.nii.gz --decimate 0.3 -v
140
+ ```
141
+
142
+ ### Run (selected subjects)
143
+ ```bash
144
+ scpp fs-to-mni --freesurfer-root /path/to/datasets/<dataset>/derivatives/freesurfer-7.4.1 --out-deriv-root /path/to/datasets/<dataset>/derivatives/scpp-preproc-0.1 --mni-template /path/to/SimCortexPP/src/MNI152_T1_1mm.nii.gz -p sub-0001 -p sub-0019 -v
145
+ ```
146
+
147
+ ### Output layout (example)
148
+ ```text
149
+ scpp-preproc-0.1/
150
+ dataset_description.json
151
+ sub-XXXX/
152
+ ses-01/
153
+ anat/
154
+ sub-XXXX_ses-01_space-MNI152_desc-preproc_T1w.nii.gz
155
+ sub-XXXX_ses-01_space-MNI152_desc-aparc+aseg_dseg.nii.gz
156
+ sub-XXXX_ses-01_space-MNI152_desc-filled_T1w.nii.gz
157
+ sub-XXXX_ses-01_from-T1w_to-MNI152_mode-image_xfm.txt
158
+ surfaces/
159
+ sub-XXXX_ses-01_space-MNI152_hemi-L_white.surf.ply
160
+ sub-XXXX_ses-01_space-MNI152_hemi-L_pial.surf.ply
161
+ sub-XXXX_ses-01_space-MNI152_hemi-R_white.surf.ply
162
+ sub-XXXX_ses-01_space-MNI152_hemi-R_pial.surf.ply
163
+ ```
164
+
165
+ ---
166
+
167
+ ## Stage 2 — Segmentation: 3D U-Net (MNI space)
168
+
169
+ This stage trains and applies a 3D U-Net to predict a **9-class segmentation** in **MNI152 space** using Stage 1 outputs.
170
+
171
+ ### Expected inputs (from Stage 1)
172
+ Under `scpp-preproc-*`, for each subject:
173
+ - `..._desc-preproc_T1w.nii.gz`
174
+ - `..._desc-aparc+aseg_dseg.nii.gz`
175
+ - `..._desc-filled_T1w.nii.gz`
176
+
177
+ ### Output naming (predictions)
178
+ Predictions are written under `scpp-seg-*`:
179
+ - `sub-XXXX/ses-01/anat/sub-XXXX_ses-01_space-MNI152_desc-seg9_dseg.nii.gz`
180
+
181
+ ### Train (single GPU)
182
+ ```bash
183
+ scpp seg train dataset.path=/path/to/datasets/<dataset>/derivatives/scpp-preproc-0.1 dataset.split_file=/path/to/datasets/<dataset>/splits/<dataset>_split.csv outputs.root=/path/to/scpp-runs/seg/exp01 trainer.use_ddp=false
184
+ ```
185
+
186
+ ### Train (multi-GPU, torchrun)
187
+ ```bash
188
+ scpp seg train --torchrun --nproc-per-node 2 dataset.path=/path/to/datasets/<dataset>/derivatives/scpp-preproc-0.1 dataset.split_file=/path/to/datasets/<dataset>/splits/<dataset>_split.csv outputs.root=/path/to/scpp-runs/seg/exp01 trainer.use_ddp=true
189
+ ```
190
+
191
+ ### Inference
192
+ ```bash
193
+ scpp seg infer dataset.path=/path/to/datasets/<dataset>/derivatives/scpp-preproc-0.1 dataset.split_file=/path/to/datasets/<dataset>/splits/<dataset>_split.csv dataset.split_name=test model.ckpt_path=/path/to/seg_best_dice.pt outputs.out_root=/path/to/datasets/<dataset>/derivatives/scpp-seg-0.1
194
+ ```
195
+
196
+ ### Evaluation (multi-dataset example)
197
+ ```bash
198
+ scpp seg eval dataset.split_file=/path/to/datasets/splits/dataset_split.csv dataset.split_name=test dataset.roots.HCP_YA=/path/to/datasets/hcpya-u100/derivatives/scpp-preproc-0.1 dataset.roots.OASIS1=/path/to/datasets/oasis-1/derivatives/scpp-preproc-0.1 outputs.pred_roots.HCP_YA=/path/to/datasets/hcpya-u100/derivatives/scpp-seg-0.1 outputs.pred_roots.OASIS1=/path/to/datasets/oasis-1/derivatives/scpp-seg-0.1 outputs.eval_csv=/path/to/scpp-runs/seg/exp01/evals/seg_eval_test.csv outputs.eval_xlsx=/path/to/scpp-runs/seg/exp01/evals/seg_eval_test.xlsx
199
+ ```
200
+
201
+ ---
202
+
203
+ ## Stage 3 — Initial Surfaces (InitSurf)
204
+
205
+ This stage generates initial cortical surfaces from saved segmentation predictions (not end-to-end).
206
+
207
+ ### Inputs
208
+ - Preproc roots (`scpp-preproc-*`) for MNI T1
209
+ - Seg roots (`scpp-seg-*`) for `..._desc-seg9_dseg.nii.gz`
210
+ - Split CSV (same format as Stage 2)
211
+
212
+ ### Outputs
213
+ BIDS-derivatives-style outputs under `scpp-initsurf-*` (meshes + SDF volumes + ribbon prob):
214
+ ```text
215
+ scpp-initsurf-0.1/
216
+ dataset_description.json
217
+ sub-XXXX/
218
+ ses-01/
219
+ anat/
220
+ sub-XXXX_ses-01_space-MNI152_desc-lh_white_sdf.nii.gz
221
+ sub-XXXX_ses-01_space-MNI152_desc-rh_white_sdf.nii.gz
222
+ sub-XXXX_ses-01_space-MNI152_desc-lh_pial_sdf.nii.gz
223
+ sub-XXXX_ses-01_space-MNI152_desc-rh_pial_sdf.nii.gz
224
+ sub-XXXX_ses-01_space-MNI152_desc-ribbon_sdf.nii.gz
225
+ sub-XXXX_ses-01_space-MNI152_desc-ribbon_prob.nii.gz
226
+ surfaces/
227
+ sub-XXXX_ses-01_space-MNI152_hemi-L_white.surf.ply
228
+ sub-XXXX_ses-01_space-MNI152_hemi-L_pial.surf.ply
229
+ sub-XXXX_ses-01_space-MNI152_hemi-R_white.surf.ply
230
+ sub-XXXX_ses-01_space-MNI152_hemi-R_pial.surf.ply
231
+ ```
232
+
233
+ ### Run (multi-dataset example)
234
+ ```bash
235
+ scpp initsurf generate dataset.split_file=/path/to/datasets/splits/dataset_split.csv dataset.split_name=all dataset.roots.HCP_YA=/path/to/datasets/hcpya-u100/derivatives/scpp-preproc-0.1 dataset.roots.OASIS1=/path/to/datasets/oasis-1/derivatives/scpp-preproc-0.1 dataset.seg_roots.HCP_YA=/path/to/datasets/hcpya-u100/derivatives/scpp-seg-0.1 dataset.seg_roots.OASIS1=/path/to/datasets/oasis-1/derivatives/scpp-seg-0.1 outputs.out_roots.HCP_YA=/path/to/datasets/hcpya-u100/derivatives/scpp-initsurf-0.1 outputs.out_roots.OASIS1=/path/to/datasets/oasis-1/derivatives/scpp-initsurf-0.1 outputs.log_dir=/path/to/scpp-runs/initsurf/exp01/logs_generate
236
+ ```
237
+
238
+ Typical runtime: ~31 s/subject (hardware-dependent).
239
+
240
+ ---
241
+
242
+ ## Stage 4 — Deformation (Deform)
243
+
244
+ This stage deforms InitSurf meshes using input volumes and geometric losses, and writes **deformed** surfaces to a BIDS-derivatives folder.
245
+
246
+ ### Inputs
247
+ - Preproc root (`scpp-preproc-*`): MNI T1 + GT FreeSurfer surfaces in MNI space
248
+ - InitSurf root (`scpp-initsurf-*`): ribbon probability + initial surfaces
249
+ - Split CSV (same format as Stage 2)
250
+
251
+ ### Outputs
252
+ Deformed surfaces under `scpp-deform-*`:
253
+ ```text
254
+ scpp-deform-0.1/
255
+ dataset_description.json
256
+ sub-XXXX/
257
+ ses-01/
258
+ surfaces/
259
+ sub-XXXX_ses-01_space-MNI152_desc-deform_hemi-L_white.surf.ply
260
+ sub-XXXX_ses-01_space-MNI152_desc-deform_hemi-L_pial.surf.ply
261
+ sub-XXXX_ses-01_space-MNI152_desc-deform_hemi-R_white.surf.ply
262
+ sub-XXXX_ses-01_space-MNI152_desc-deform_hemi-R_pial.surf.ply
263
+ ```
264
+
265
+ ### Train (multi-GPU example)
266
+ ```bash
267
+ scpp deform train --torchrun --nproc-per-node 2 outputs.root=/path/to/scpp-runs/deform/exp01
268
+ ```
269
+
270
+ ### Inference
271
+ ```bash
272
+ scpp deform infer
273
+ ```
274
+
275
+ ### Evaluation
276
+ ```bash
277
+ scpp deform eval
278
+ ```
279
+
280
+ Evaluation writes four Excel files:
281
+ - `surface_metrics.xlsx`
282
+ - `collision_metrics.xlsx`
283
+ - `collision_metrics_enhanced.xlsx`
284
+ - `collision_summary.xlsx`
285
+
286
+ ---
287
+
288
+ ## Outputs Summary
289
+
290
+ For each dataset root:
291
+
292
+ - `derivatives/scpp-preproc-0.1/`
293
+ MNI T1, aparc+aseg, filled, transforms, and MNI-aligned FreeSurfer surfaces.
294
+
295
+ - `derivatives/scpp-seg-0.1/`
296
+ 9-class segmentation predictions (`*_desc-seg9_dseg.nii.gz`).
297
+
298
+ - `derivatives/scpp-initsurf-0.1/`
299
+ Initial surfaces (`*.surf.ply`) + SDF volumes + ribbon SDF/probability.
300
+
301
+ - `derivatives/scpp-deform-0.1/`
302
+ Deformed surfaces (`*_desc-deform_*.surf.ply`).
303
+
304
+ ---
305
+
306
+
307
+ ## License
308
+
309
+ Add your license and citation details here if needed.