purple-mri 0.0.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.
- purple_mri-0.0.1/PKG-INFO +112 -0
- purple_mri-0.0.1/README.md +97 -0
- purple_mri-0.0.1/purple_mri/__init__.py +0 -0
- purple_mri-0.0.1/purple_mri/__main__.py +13 -0
- purple_mri-0.0.1/purple_mri/scripts/create_mesh.sh +25 -0
- purple_mri-0.0.1/purple_mri/scripts/decimate_mesh.py +296 -0
- purple_mri-0.0.1/purple_mri/scripts/do_mni_txs.sh +32 -0
- purple_mri-0.0.1/purple_mri/scripts/make_fs_directories.sh +43 -0
- purple_mri-0.0.1/purple_mri/scripts/parcellation.sh +236 -0
- purple_mri-0.0.1/purple_mri/scripts/prepare_segm_files.sh +37 -0
- purple_mri-0.0.1/purple_mri/scripts/run_surface_pipeline.sh +43 -0
- purple_mri-0.0.1/purple_mri/scripts/topology_correction.sh +39 -0
- purple_mri-0.0.1/purple_mri.egg-info/PKG-INFO +112 -0
- purple_mri-0.0.1/purple_mri.egg-info/SOURCES.txt +17 -0
- purple_mri-0.0.1/purple_mri.egg-info/dependency_links.txt +1 -0
- purple_mri-0.0.1/purple_mri.egg-info/requires.txt +7 -0
- purple_mri-0.0.1/purple_mri.egg-info/top_level.txt +1 -0
- purple_mri-0.0.1/pyproject.toml +33 -0
- purple_mri-0.0.1/setup.cfg +4 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: purple_mri
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: purple_mri: Penn Utilities for Registration and ParcelLation of Ex vivo MRI
|
|
5
|
+
Author-email: Pulkit Khandelwal <kpulkit95@gmail.com>
|
|
6
|
+
Project-URL: Homepage, https://github.com/Pulkit-Khandelwal/purple_mri
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: numpy
|
|
9
|
+
Requires-Dist: torch
|
|
10
|
+
Requires-Dist: pykeops
|
|
11
|
+
Requires-Dist: pymeshlab
|
|
12
|
+
Requires-Dist: vtk
|
|
13
|
+
Requires-Dist: SimpleITK
|
|
14
|
+
Requires-Dist: geomloss
|
|
15
|
+
|
|
16
|
+
# purple-mri: **P**enn **U**tilities for **R**egistration and **P**arcel**L**ation of **E**x vivo **MRI**
|
|
17
|
+
|
|
18
|
+
We provide a set of tools packaged as `purple-mri` for segmentation, parcellation and registration of ultra high-resolution (< 300 microns) postmortem human brain hemisphere at 7 tesla t2w MRI at native subject-space resolution. This pipeline leverages advances in both deep learning and classical surface-based modeling techniques to produce parcellations in any atlas used in neuroimaging. The developed method allows us to perform vertex-wise analysis in the template space and thereby link morphometry measures with pathology measurements derived from histology.
|
|
19
|
+
|
|
20
|
+
Check out the [project page](https://pulkit-khandelwal.github.io/exvivo-brain-upenn/) and our latest papers [here](https://direct.mit.edu/imag/article/doi/10.1162/imag_a_00171/120741) and [here](https://arxiv.org/abs/2403.19497).
|
|
21
|
+
|
|
22
|
+
In particular, `purple-mri` allows you to do the following:
|
|
23
|
+
+ obtain an initial 10 label segmentation: cortical GM, normal appearing WM, WMH, medial temporal lobe, corpus callosum, ventricles, caudate, putamen, globus pallidus and thalamus
|
|
24
|
+
+ obtain surface-based native subject-space parcellation based on different brain atlases such as: DKT, Economo, Schaeffer etc
|
|
25
|
+
+ create population specific volumetric and surface-based templates
|
|
26
|
+
+ perform exvivo to invivo registration in volumetric intensity space
|
|
27
|
+
+ perform surface-to-surface registration between exvivo or invivo
|
|
28
|
+
+ perform intensity-based registration between 9.4 tesla MTL to 7 tesla whole hemsiphere registration
|
|
29
|
+
+ perform vertex-wise and group-wise generalized linear modeling analysis for exvivo subject population for morphometry and histology
|
|
30
|
+
|
|
31
|
+
## Steps (for segmentation and parcellation)
|
|
32
|
+
`purple-mri` follows a series of steps making use of bash scripts and Docker.
|
|
33
|
+
|
|
34
|
+
### Pre-processing
|
|
35
|
+
Perform bias correction and image normalization/standardization. We use `N4BiasFieldCorrection` as part of the CLI tool [ANTs](https://github.com/ANTsX/ANTs) and [`c3d`](http://www.itksnap.org/pmwiki/pmwiki.php?n=Convert3D.Convert3D). We highly recommend using the option of an input mask in `N4BiasFieldCorrection` which can be obtained via corase threhsolding.
|
|
36
|
+
[Here](https://github.com/Pulkit-Khandelwal/upenn-picsl-brain-ex-vivo/tree/main/misc_scripts/perform_bias_correction.sh) is a sample script.
|
|
37
|
+
|
|
38
|
+
### Deep learning-based initial labeling and CRUISE-based post-hoc topology correction
|
|
39
|
+
Currently, we have two Docker images. The first image provides the segmentation and the second employs [Nighres/CRUISE](https://nighres.readthedocs.io/en/latest/installation.html) for post-hoc topology correction.
|
|
40
|
+
Please follow the [link]([https://github.com/Pulkit-Khandelwal/upenn-picsl-brain-ex-vivo/blob/main/exvivo-segm-demo-docker.md](https://github.com/Pulkit-Khandelwal/purple-mri/blob/main/docker/exvivo_docker.md) for detailed instructions on how to use Docker to get the segmentations. Some key commands are emphasized here:
|
|
41
|
+
|
|
42
|
+
Place the pre-processed image(s) (with a suffix _0000.nii.gz to your filenames) in a folder named `data_for_inference` within your working directory is `/your/working/directory`.
|
|
43
|
+
```
|
|
44
|
+
docker pull pulks/docker_hippogang_exvivo_segm:v${LATEST_TAG}
|
|
45
|
+
|
|
46
|
+
docker run --gpus all --privileged -v /your/working/directory/:/data/exvivo/ -it pulks/docker_hippogang_exvivo_segm:v${LATEST_TAG} /bin/bash -c "bash /src/commands_nnunet_inference.sh ${OPTION}" >> logs.txt
|
|
47
|
+
```
|
|
48
|
+
You will see the output in `/your/working/directory/data_for_inference/output_from_nnunet_inference`.
|
|
49
|
+
|
|
50
|
+
Next, correct for topology so that adjoining gyri and sulci are clearly separated. Copy the segmentations from `output_from_nnunet_inference` to a folder `data_for_topology_correction` in your wokring directory.
|
|
51
|
+
```
|
|
52
|
+
docker pull pulks/docker_nighres:v1.0.0
|
|
53
|
+
|
|
54
|
+
docker run -v /your/working/directory/:/data/cruise_files/ -it pulks/docker_nighres:v1.0.0 /bin/bash -c "bash /data/prepare_cruise_files.sh"
|
|
55
|
+
|
|
56
|
+
# Locally run the file to get the final combined label file. See instructions [here](https://github.com/Pulkit-Khandelwal/upenn-picsl-brain-ex-vivo/blob/main/exvivo-segm-demo-docker.md) and links referenced therein.
|
|
57
|
+
bash clean_labels_final.sh
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Surface-based modeling to obtain whole-hemisphere parcellations
|
|
61
|
+
Once, you have obtained an initial 10-label topology corrected volumetric segmentation, you can proceed to the surface-based pipeline to obtain parcellations based on your favorite atlas. This step will be on your local machine. No GPUs required. To do this, you should have FreeSurfer installed locally. We have used FreeSurfer version 7.4.0 on linux obtained from [here](https://surfer.nmr.mgh.harvard.edu/fswiki/DownloadAndInstall). Moreover, there are some Python dependencies which can be found in the `dependencies.txt` file and installed using `pip`.
|
|
62
|
+
|
|
63
|
+
Run the following file which calls in several bash scripts which prepares the data, computes appropriate transformations and re-orients the images, corrects surface topology, and perform the parcellation into Desikan-Killiany-Tourville (DKT), Schaefer, Glasser and the Von Economo-Koskinos atlases.
|
|
64
|
+
|
|
65
|
+
For the surface-based modeling step, we assume that all the hemishpehrs are right hemispheres. So, we suggest flipping the left t2w MRI and its corresponding segmentation to left using the following `c3d` command: `c3d image_left.nii.gz -flip y image_right_flipped.nii.gz`
|
|
66
|
+
|
|
67
|
+
Clone the current repository and the run the following script `run_surface_pipeline.sh` from within the `purple_mri` folder which takes the following mandatory arguments:
|
|
68
|
+
`freesurfer_path`: path to the FreeSurfer installtion
|
|
69
|
+
`working_dir`: directory which will have the outputs for each subject stored
|
|
70
|
+
`mri_path`: mri images path
|
|
71
|
+
`segm_path`: 10-label segmentation path
|
|
72
|
+
`external_atlases_path`: directory with files for other atlases
|
|
73
|
+
`num_threads`: number of threads
|
|
74
|
+
|
|
75
|
+
Place your t2w MRI in a folder `mri_path` and the intial deep learning-based segmentations in `segm_path`.
|
|
76
|
+
Make sure your mri images and segmentation files have the same names ending with `.nii.gz`.
|
|
77
|
+
Place the `fsaverage` in the `working_dir` folder.
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
cd purple_mri
|
|
81
|
+
|
|
82
|
+
bash run_surface_pipeline.sh freesurfer_path working_dir mri_path segm_path external_atlases_path num_threads
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Other scripts
|
|
86
|
+
### Intensity-based volumetric template building
|
|
87
|
+
We build intensity-based volumetric templates using the [greedy](https://sites.google.com/view/greedyreg/about?authuser=0) tool. The required binaries (for Linux) and the scripts are located in the the `intensity_template` within the `scripts` directory. Follow the instructions [here](https://github.com/Pulkit-Khandelwal/purple-mri/blob/main/scripts/intensity_template/README.md).
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
### Ex vivo and in vivo registration
|
|
91
|
+
Script `exvivo_invivo_greedy_registration.sh` to register in vivo (t1w) and ex vivo (t2w) MRI is located in the folder `scripts`. We use [greedy](https://sites.google.com/view/greedyreg/about?authuser=0) to register the segmentations of in vivo aseg+aparc labels derived from FreeSurfer and 10-label initial deep learning segmentation of postmortem MRI. The warps are then used to regsiter the MRIs.
|
|
92
|
+
|
|
93
|
+
### Perform GLM analyses
|
|
94
|
+
We perform vertex-wise analysis in `fsaverage` space to fit a generalized linear model (GLM) between cortical thickness (mm) and with global ratings of amyloid-β, Braak staging, CERAD, and semiquantitative ratings of the medial temporal lobe (MTL) neuronal loss and tau pathology, with age, sex and postmortem interval (PMI) as covariates. You can follow the steps detailed [here](https://github.com/Pulkit-Khandelwal/purple-mri/tree/main/glm).
|
|
95
|
+
|
|
96
|
+
## Notes
|
|
97
|
+
+ Our method has been developed to work on a single exvivo hemisphere.
|
|
98
|
+
+ The deep learning-based segmentation was primarily trained on 7T t2w MRI. We have tested the model on t2* flash as well and it works pretty well but, if need be, we recommend re-training the model with some manual labels obtained on t2* flash MRI.
|
|
99
|
+
|
|
100
|
+
## pip package
|
|
101
|
+
|
|
102
|
+
## Introductory video
|
|
103
|
+
<div align="center">
|
|
104
|
+
<a href="https://youtu.be/0BOeUtlWlYw?si=7NeNDsoePOW3_J4Y">
|
|
105
|
+
<img src="https://github.com/Pulkit-Khandelwal/purple-mri/blob/main/images/thumbnail.png" style="width:75%;">
|
|
106
|
+
</a>
|
|
107
|
+
</div>
|
|
108
|
+
|
|
109
|
+
## Citations
|
|
110
|
+
+ Khandelwal, P., Duong, M. T., Sadaghiani, S., Lim, S., Denning, A. E., Chung, E., ... & Yushkevich, P. A. (2024). Automated deep learning segmentation of high-resolution 7 tesla postmortem MRI for quantitative analysis of structure-pathology correlations in neurodegenerative diseases. Imaging Neuroscience, 2, 1-30.
|
|
111
|
+
+ Khandelwal, P., Duong, M. T., Fuentes, C., Denning, A., Trotman, W., Ittyerah, R., ... & Yushkevich, P. A. (2024). Surface-based parcellation and vertex-wise analysis of ultra high-resolution ex vivo 7 tesla MRI in neurodegenerative diseases. arXiv preprint arXiv:2403.19497.
|
|
112
|
+
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# purple-mri: **P**enn **U**tilities for **R**egistration and **P**arcel**L**ation of **E**x vivo **MRI**
|
|
2
|
+
|
|
3
|
+
We provide a set of tools packaged as `purple-mri` for segmentation, parcellation and registration of ultra high-resolution (< 300 microns) postmortem human brain hemisphere at 7 tesla t2w MRI at native subject-space resolution. This pipeline leverages advances in both deep learning and classical surface-based modeling techniques to produce parcellations in any atlas used in neuroimaging. The developed method allows us to perform vertex-wise analysis in the template space and thereby link morphometry measures with pathology measurements derived from histology.
|
|
4
|
+
|
|
5
|
+
Check out the [project page](https://pulkit-khandelwal.github.io/exvivo-brain-upenn/) and our latest papers [here](https://direct.mit.edu/imag/article/doi/10.1162/imag_a_00171/120741) and [here](https://arxiv.org/abs/2403.19497).
|
|
6
|
+
|
|
7
|
+
In particular, `purple-mri` allows you to do the following:
|
|
8
|
+
+ obtain an initial 10 label segmentation: cortical GM, normal appearing WM, WMH, medial temporal lobe, corpus callosum, ventricles, caudate, putamen, globus pallidus and thalamus
|
|
9
|
+
+ obtain surface-based native subject-space parcellation based on different brain atlases such as: DKT, Economo, Schaeffer etc
|
|
10
|
+
+ create population specific volumetric and surface-based templates
|
|
11
|
+
+ perform exvivo to invivo registration in volumetric intensity space
|
|
12
|
+
+ perform surface-to-surface registration between exvivo or invivo
|
|
13
|
+
+ perform intensity-based registration between 9.4 tesla MTL to 7 tesla whole hemsiphere registration
|
|
14
|
+
+ perform vertex-wise and group-wise generalized linear modeling analysis for exvivo subject population for morphometry and histology
|
|
15
|
+
|
|
16
|
+
## Steps (for segmentation and parcellation)
|
|
17
|
+
`purple-mri` follows a series of steps making use of bash scripts and Docker.
|
|
18
|
+
|
|
19
|
+
### Pre-processing
|
|
20
|
+
Perform bias correction and image normalization/standardization. We use `N4BiasFieldCorrection` as part of the CLI tool [ANTs](https://github.com/ANTsX/ANTs) and [`c3d`](http://www.itksnap.org/pmwiki/pmwiki.php?n=Convert3D.Convert3D). We highly recommend using the option of an input mask in `N4BiasFieldCorrection` which can be obtained via corase threhsolding.
|
|
21
|
+
[Here](https://github.com/Pulkit-Khandelwal/upenn-picsl-brain-ex-vivo/tree/main/misc_scripts/perform_bias_correction.sh) is a sample script.
|
|
22
|
+
|
|
23
|
+
### Deep learning-based initial labeling and CRUISE-based post-hoc topology correction
|
|
24
|
+
Currently, we have two Docker images. The first image provides the segmentation and the second employs [Nighres/CRUISE](https://nighres.readthedocs.io/en/latest/installation.html) for post-hoc topology correction.
|
|
25
|
+
Please follow the [link]([https://github.com/Pulkit-Khandelwal/upenn-picsl-brain-ex-vivo/blob/main/exvivo-segm-demo-docker.md](https://github.com/Pulkit-Khandelwal/purple-mri/blob/main/docker/exvivo_docker.md) for detailed instructions on how to use Docker to get the segmentations. Some key commands are emphasized here:
|
|
26
|
+
|
|
27
|
+
Place the pre-processed image(s) (with a suffix _0000.nii.gz to your filenames) in a folder named `data_for_inference` within your working directory is `/your/working/directory`.
|
|
28
|
+
```
|
|
29
|
+
docker pull pulks/docker_hippogang_exvivo_segm:v${LATEST_TAG}
|
|
30
|
+
|
|
31
|
+
docker run --gpus all --privileged -v /your/working/directory/:/data/exvivo/ -it pulks/docker_hippogang_exvivo_segm:v${LATEST_TAG} /bin/bash -c "bash /src/commands_nnunet_inference.sh ${OPTION}" >> logs.txt
|
|
32
|
+
```
|
|
33
|
+
You will see the output in `/your/working/directory/data_for_inference/output_from_nnunet_inference`.
|
|
34
|
+
|
|
35
|
+
Next, correct for topology so that adjoining gyri and sulci are clearly separated. Copy the segmentations from `output_from_nnunet_inference` to a folder `data_for_topology_correction` in your wokring directory.
|
|
36
|
+
```
|
|
37
|
+
docker pull pulks/docker_nighres:v1.0.0
|
|
38
|
+
|
|
39
|
+
docker run -v /your/working/directory/:/data/cruise_files/ -it pulks/docker_nighres:v1.0.0 /bin/bash -c "bash /data/prepare_cruise_files.sh"
|
|
40
|
+
|
|
41
|
+
# Locally run the file to get the final combined label file. See instructions [here](https://github.com/Pulkit-Khandelwal/upenn-picsl-brain-ex-vivo/blob/main/exvivo-segm-demo-docker.md) and links referenced therein.
|
|
42
|
+
bash clean_labels_final.sh
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Surface-based modeling to obtain whole-hemisphere parcellations
|
|
46
|
+
Once, you have obtained an initial 10-label topology corrected volumetric segmentation, you can proceed to the surface-based pipeline to obtain parcellations based on your favorite atlas. This step will be on your local machine. No GPUs required. To do this, you should have FreeSurfer installed locally. We have used FreeSurfer version 7.4.0 on linux obtained from [here](https://surfer.nmr.mgh.harvard.edu/fswiki/DownloadAndInstall). Moreover, there are some Python dependencies which can be found in the `dependencies.txt` file and installed using `pip`.
|
|
47
|
+
|
|
48
|
+
Run the following file which calls in several bash scripts which prepares the data, computes appropriate transformations and re-orients the images, corrects surface topology, and perform the parcellation into Desikan-Killiany-Tourville (DKT), Schaefer, Glasser and the Von Economo-Koskinos atlases.
|
|
49
|
+
|
|
50
|
+
For the surface-based modeling step, we assume that all the hemishpehrs are right hemispheres. So, we suggest flipping the left t2w MRI and its corresponding segmentation to left using the following `c3d` command: `c3d image_left.nii.gz -flip y image_right_flipped.nii.gz`
|
|
51
|
+
|
|
52
|
+
Clone the current repository and the run the following script `run_surface_pipeline.sh` from within the `purple_mri` folder which takes the following mandatory arguments:
|
|
53
|
+
`freesurfer_path`: path to the FreeSurfer installtion
|
|
54
|
+
`working_dir`: directory which will have the outputs for each subject stored
|
|
55
|
+
`mri_path`: mri images path
|
|
56
|
+
`segm_path`: 10-label segmentation path
|
|
57
|
+
`external_atlases_path`: directory with files for other atlases
|
|
58
|
+
`num_threads`: number of threads
|
|
59
|
+
|
|
60
|
+
Place your t2w MRI in a folder `mri_path` and the intial deep learning-based segmentations in `segm_path`.
|
|
61
|
+
Make sure your mri images and segmentation files have the same names ending with `.nii.gz`.
|
|
62
|
+
Place the `fsaverage` in the `working_dir` folder.
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
cd purple_mri
|
|
66
|
+
|
|
67
|
+
bash run_surface_pipeline.sh freesurfer_path working_dir mri_path segm_path external_atlases_path num_threads
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Other scripts
|
|
71
|
+
### Intensity-based volumetric template building
|
|
72
|
+
We build intensity-based volumetric templates using the [greedy](https://sites.google.com/view/greedyreg/about?authuser=0) tool. The required binaries (for Linux) and the scripts are located in the the `intensity_template` within the `scripts` directory. Follow the instructions [here](https://github.com/Pulkit-Khandelwal/purple-mri/blob/main/scripts/intensity_template/README.md).
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
### Ex vivo and in vivo registration
|
|
76
|
+
Script `exvivo_invivo_greedy_registration.sh` to register in vivo (t1w) and ex vivo (t2w) MRI is located in the folder `scripts`. We use [greedy](https://sites.google.com/view/greedyreg/about?authuser=0) to register the segmentations of in vivo aseg+aparc labels derived from FreeSurfer and 10-label initial deep learning segmentation of postmortem MRI. The warps are then used to regsiter the MRIs.
|
|
77
|
+
|
|
78
|
+
### Perform GLM analyses
|
|
79
|
+
We perform vertex-wise analysis in `fsaverage` space to fit a generalized linear model (GLM) between cortical thickness (mm) and with global ratings of amyloid-β, Braak staging, CERAD, and semiquantitative ratings of the medial temporal lobe (MTL) neuronal loss and tau pathology, with age, sex and postmortem interval (PMI) as covariates. You can follow the steps detailed [here](https://github.com/Pulkit-Khandelwal/purple-mri/tree/main/glm).
|
|
80
|
+
|
|
81
|
+
## Notes
|
|
82
|
+
+ Our method has been developed to work on a single exvivo hemisphere.
|
|
83
|
+
+ The deep learning-based segmentation was primarily trained on 7T t2w MRI. We have tested the model on t2* flash as well and it works pretty well but, if need be, we recommend re-training the model with some manual labels obtained on t2* flash MRI.
|
|
84
|
+
|
|
85
|
+
## pip package
|
|
86
|
+
|
|
87
|
+
## Introductory video
|
|
88
|
+
<div align="center">
|
|
89
|
+
<a href="https://youtu.be/0BOeUtlWlYw?si=7NeNDsoePOW3_J4Y">
|
|
90
|
+
<img src="https://github.com/Pulkit-Khandelwal/purple-mri/blob/main/images/thumbnail.png" style="width:75%;">
|
|
91
|
+
</a>
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
## Citations
|
|
95
|
+
+ Khandelwal, P., Duong, M. T., Sadaghiani, S., Lim, S., Denning, A. E., Chung, E., ... & Yushkevich, P. A. (2024). Automated deep learning segmentation of high-resolution 7 tesla postmortem MRI for quantitative analysis of structure-pathology correlations in neurodegenerative diseases. Imaging Neuroscience, 2, 1-30.
|
|
96
|
+
+ Khandelwal, P., Duong, M. T., Fuentes, C., Denning, A., Trotman, W., Ittyerah, R., ... & Yushkevich, P. A. (2024). Surface-based parcellation and vertex-wise analysis of ultra high-resolution ex vivo 7 tesla MRI in neurodegenerative diseases. arXiv preprint arXiv:2403.19497.
|
|
97
|
+
|
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import subprocess
|
|
3
|
+
|
|
4
|
+
arg1 = sys.argv[1]
|
|
5
|
+
arg2 = sys.argv[2]
|
|
6
|
+
arg3 = sys.argv[3]
|
|
7
|
+
arg4 = sys.argv[4]
|
|
8
|
+
arg5 = sys.argv[5]
|
|
9
|
+
arg6 = int(sys.argv[6])
|
|
10
|
+
arg7 = sys.argv[7]
|
|
11
|
+
|
|
12
|
+
subprocess.run("bash run_surface_pipeline.sh %s %s %s %s %s %s %s" \
|
|
13
|
+
% (arg1, arg2, arg3, arg4, arg5, arg6, arg7), shell=True)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
working_dir=$1
|
|
2
|
+
tgt_dir_FS_mesh=$2
|
|
3
|
+
tgt_dir_FS_mesh_decimated=$3
|
|
4
|
+
str_split=$4
|
|
5
|
+
for i in $str_split; do subjects+=($i) ; done
|
|
6
|
+
|
|
7
|
+
hemis=rh
|
|
8
|
+
for subj in "${subjects[@]}"
|
|
9
|
+
do
|
|
10
|
+
echo ${subj}
|
|
11
|
+
SUBJECTS_DIR=${working_dir}/${subj}
|
|
12
|
+
|
|
13
|
+
mri_pretess ${SUBJECTS_DIR}/mri/filled.mgz 1 ${SUBJECTS_DIR}/mri/mri.mgz ${tgt_dir_FS_mesh}/${subj}_pretess.mgz
|
|
14
|
+
mri_tessellate ${tgt_dir_FS_mesh}/${subj}_pretess.mgz 1 ${tgt_dir_FS_mesh}/${subj}.orig.nofix
|
|
15
|
+
mris_convert ${tgt_dir_FS_mesh}/${subj}.orig.nofix ${tgt_dir_FS_mesh}/${subj}.orig.nofix.vtk
|
|
16
|
+
|
|
17
|
+
# decimate the vtk file
|
|
18
|
+
python3 -m purple_mri.scripts.decimate_mesh ${tgt_dir_FS_mesh} ${tgt_dir_FS_mesh_decimated} ${subj}.orig.nofix.vtk ${subj}.decimated.orig.nofix.vtk
|
|
19
|
+
|
|
20
|
+
# convert back to FreeSurfer format and this will act as the input to the topology correction step
|
|
21
|
+
mris_convert ${tgt_dir_FS_mesh_decimated}/${subj}.decimated.orig.nofix.vtk ${tgt_dir_FS_mesh_decimated}/${subj}.decimated.orig.nofix
|
|
22
|
+
|
|
23
|
+
cp ${tgt_dir_FS_mesh_decimated}/${subj}.decimated.orig.nofix ${working_dir}/${subj}/surf/${hemis}.orig.nofix
|
|
24
|
+
|
|
25
|
+
done;
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import numpy as np
|
|
4
|
+
import torch
|
|
5
|
+
from torch.autograd import grad
|
|
6
|
+
import vtk
|
|
7
|
+
from vtk.util.numpy_support import vtk_to_numpy, numpy_to_vtk
|
|
8
|
+
import pymeshlab
|
|
9
|
+
import pandas as pd
|
|
10
|
+
from pykeops.torch import Vi, Vj
|
|
11
|
+
|
|
12
|
+
# torch type and device
|
|
13
|
+
use_cuda = torch.cuda.is_available()
|
|
14
|
+
torchdeviceId = torch.device("cuda:0") if use_cuda else "cpu"
|
|
15
|
+
torchdtype = torch.float32
|
|
16
|
+
|
|
17
|
+
# PyKeOps counterpart
|
|
18
|
+
KeOpsdeviceId = torchdeviceId.index # id of Gpu device (in case GPU is used)
|
|
19
|
+
KeOpsdtype = torchdtype.__str__().split(".")[1] # 'float32'
|
|
20
|
+
|
|
21
|
+
use_cuda = torch.cuda.is_available()
|
|
22
|
+
torchdeviceId = torch.device("cuda:0") if use_cuda else "cpu"
|
|
23
|
+
|
|
24
|
+
# Read VTK mesh
|
|
25
|
+
def load_vtk(filename):
|
|
26
|
+
rd = vtk.vtkPolyDataReader()
|
|
27
|
+
rd.SetFileName(filename)
|
|
28
|
+
rd.Update()
|
|
29
|
+
return rd.GetOutput()
|
|
30
|
+
|
|
31
|
+
# Read points from the polydata
|
|
32
|
+
def vtk_get_points(pd):
|
|
33
|
+
return vtk_to_numpy(pd.GetPoints().GetData())
|
|
34
|
+
|
|
35
|
+
# Read the faces from the polydata
|
|
36
|
+
def vtk_get_triangles(pd):
|
|
37
|
+
return vtk_to_numpy(pd.GetPolys().GetData()).reshape(-1,4)[:,1:]
|
|
38
|
+
|
|
39
|
+
# Map all point arrays to cell arrays
|
|
40
|
+
def vtk_all_point_arrays_to_cell_arrays(pd):
|
|
41
|
+
flt = vtk.vtkPointDataToCellData()
|
|
42
|
+
flt.SetInputData(pd)
|
|
43
|
+
flt.Update()
|
|
44
|
+
return flt.GetOutput()
|
|
45
|
+
|
|
46
|
+
# Read a point array
|
|
47
|
+
def vtk_get_point_array(pd, name):
|
|
48
|
+
a = pd.GetPointData().GetArray(name)
|
|
49
|
+
return vtk_to_numpy(a) if a is not None else None
|
|
50
|
+
|
|
51
|
+
# Add a cell array to a mesh
|
|
52
|
+
def vtk_set_point_array(pd, name, array, array_type=vtk.VTK_FLOAT):
|
|
53
|
+
a = numpy_to_vtk(array, array_type=array_type)
|
|
54
|
+
a.SetName(name)
|
|
55
|
+
pd.GetPointData().AddArray(a)
|
|
56
|
+
|
|
57
|
+
# Read a cell array
|
|
58
|
+
def vtk_get_cell_array(pd, name):
|
|
59
|
+
a = pd.GetCellData().GetArray(name)
|
|
60
|
+
return vtk_to_numpy(a) if a is not None else None
|
|
61
|
+
|
|
62
|
+
# Add a cell array to a mesh
|
|
63
|
+
def vtk_set_cell_array(pd, name, array):
|
|
64
|
+
a = numpy_to_vtk(array)
|
|
65
|
+
a.SetName(name)
|
|
66
|
+
pd.GetCellData().AddArray(a)
|
|
67
|
+
|
|
68
|
+
# Make a VTK polydata from vertices and triangles
|
|
69
|
+
def vtk_make_pd(v, f):
|
|
70
|
+
pd = vtk.vtkPolyData()
|
|
71
|
+
pts = vtk.vtkPoints()
|
|
72
|
+
pts.SetData(numpy_to_vtk(v))
|
|
73
|
+
pd.SetPoints(pts)
|
|
74
|
+
ca = vtk.vtkCellArray()
|
|
75
|
+
ca.SetCells(f.shape[0], numpy_to_vtk(np.insert(f, 0, 3, axis=1).ravel(), array_type=vtk.VTK_ID_TYPE))
|
|
76
|
+
pd.SetPolys(ca)
|
|
77
|
+
return pd
|
|
78
|
+
|
|
79
|
+
# Save VTK polydata
|
|
80
|
+
def save_vtk(pd, filename, binary = False):
|
|
81
|
+
wr=vtk.vtkPolyDataWriter()
|
|
82
|
+
wr.SetFileName(filename)
|
|
83
|
+
wr.SetInputData(pd)
|
|
84
|
+
#wr.SetFileVersion(1)
|
|
85
|
+
wr.SetFileVersion(42)
|
|
86
|
+
#wr.SetFileFormat(1,2)
|
|
87
|
+
if binary:
|
|
88
|
+
wr.SetFileTypeToBinary()
|
|
89
|
+
wr.Update()
|
|
90
|
+
|
|
91
|
+
# Reduction using pymeshlab
|
|
92
|
+
def decimate(v, f, target_faces):
|
|
93
|
+
ms = pymeshlab.MeshSet()
|
|
94
|
+
ms.add_mesh(pymeshlab.Mesh(vertex_matrix=v, face_matrix=f))
|
|
95
|
+
ms.meshing_decimation_quadric_edge_collapse(targetfacenum=target_faces,
|
|
96
|
+
preserveboundary=True,
|
|
97
|
+
preservenormal=True,
|
|
98
|
+
preservetopology=True,
|
|
99
|
+
planarquadric=True)
|
|
100
|
+
m0 = ms.mesh(0)
|
|
101
|
+
return m0.vertex_matrix(), m0.face_matrix()
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
# For LDDMM
|
|
105
|
+
def GaussKernel(sigma):
|
|
106
|
+
x, y, b = Vi(0, 3), Vj(1, 3), Vj(2, 3)
|
|
107
|
+
gamma = 1 / (sigma * sigma)
|
|
108
|
+
D2 = x.sqdist(y)
|
|
109
|
+
K = (-D2 * gamma).exp()
|
|
110
|
+
return (K * b).sum_reduction(axis=1)
|
|
111
|
+
|
|
112
|
+
# For Varifold
|
|
113
|
+
def GaussLinKernel(sigma):
|
|
114
|
+
x, y, u, v, b = Vi(0, 3), Vj(1, 3), Vi(2, 3), Vj(3, 3), Vj(4, 1)
|
|
115
|
+
gamma = 1 / (sigma * sigma)
|
|
116
|
+
D2 = x.sqdist(y)
|
|
117
|
+
K = (-D2 * gamma).exp() * (u * v).sum() ** 2
|
|
118
|
+
return (K * b).sum_reduction(axis=1)
|
|
119
|
+
|
|
120
|
+
# For Currents
|
|
121
|
+
def GaussLinCurrentsKernel(sigma):
|
|
122
|
+
x, y, u, v = Vi(0, 3), Vj(1, 3), Vi(2, 3), Vj(3, 3)
|
|
123
|
+
gamma = 1 / (sigma * sigma)
|
|
124
|
+
D2 = x.sqdist(y)
|
|
125
|
+
K = (-D2 * gamma).exp() * (u * v).sum()
|
|
126
|
+
return K.sum_reduction(axis=1)
|
|
127
|
+
|
|
128
|
+
# For Currents
|
|
129
|
+
def GaussLinCurrentsKernel(sigma):
|
|
130
|
+
x, y, u, v = Vi(0, 3), Vj(1, 3), Vi(2, 3), Vj(3, 3)
|
|
131
|
+
gamma = 1 / (sigma * sigma)
|
|
132
|
+
D2 = x.sqdist(y)
|
|
133
|
+
K = (-D2 * gamma).exp() * (u * v).sum()
|
|
134
|
+
return K.sum_reduction(axis=1)
|
|
135
|
+
|
|
136
|
+
# For Currents to match C++ code
|
|
137
|
+
def GaussLinCurrentsKernelC(sigma):
|
|
138
|
+
x, y, u, v = Vi(0, 3), Vj(1, 3), Vi(2, 3), Vj(3, 3)
|
|
139
|
+
gamma = 1 / (2 * sigma * sigma)
|
|
140
|
+
D2 = x.sqdist(y)
|
|
141
|
+
K = (-D2 * gamma).exp() * (u * v).sum() * 0.5
|
|
142
|
+
return K.sum_reduction(axis=1)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
# Forward integration
|
|
146
|
+
def RalstonIntegrator():
|
|
147
|
+
def f(ODESystem, x0, nt, deltat=1.0):
|
|
148
|
+
x = tuple(map(lambda x: x.clone(), x0))
|
|
149
|
+
dt = deltat / nt
|
|
150
|
+
l = [x]
|
|
151
|
+
for i in range(nt):
|
|
152
|
+
xdot = ODESystem(*x)
|
|
153
|
+
xi = tuple(map(lambda x, xdot: x + (2 * dt / 3) * xdot, x, xdot))
|
|
154
|
+
xdoti = ODESystem(*xi)
|
|
155
|
+
x = tuple(
|
|
156
|
+
map(
|
|
157
|
+
lambda x, xdot, xdoti: x + (0.25 * dt) * (xdot + 3 * xdoti),
|
|
158
|
+
x,
|
|
159
|
+
xdot,
|
|
160
|
+
xdoti,
|
|
161
|
+
)
|
|
162
|
+
)
|
|
163
|
+
l.append(x)
|
|
164
|
+
return l
|
|
165
|
+
|
|
166
|
+
return f
|
|
167
|
+
|
|
168
|
+
# LDDMM definitions
|
|
169
|
+
|
|
170
|
+
def Hamiltonian(K):
|
|
171
|
+
def H(p, q):
|
|
172
|
+
return 0.5 * (p * K(q, q, p)).sum()
|
|
173
|
+
|
|
174
|
+
return H
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def HamiltonianSystem(K):
|
|
178
|
+
H = Hamiltonian(K)
|
|
179
|
+
|
|
180
|
+
def HS(p, q):
|
|
181
|
+
Gp, Gq = grad(H(p, q), (p, q), create_graph=True)
|
|
182
|
+
return -Gq, Gp
|
|
183
|
+
|
|
184
|
+
return HS
|
|
185
|
+
|
|
186
|
+
def Shooting(p0, q0, K, nt=10, Integrator=RalstonIntegrator()):
|
|
187
|
+
return Integrator(HamiltonianSystem(K), (p0, q0), nt)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def Flow(x0, p0, q0, K, deltat=1.0, Integrator=RalstonIntegrator()):
|
|
191
|
+
HS = HamiltonianSystem(K)
|
|
192
|
+
|
|
193
|
+
def FlowEq(x, p, q):
|
|
194
|
+
return (K(x, q, p),) + HS(p, q)
|
|
195
|
+
|
|
196
|
+
return Integrator(FlowEq, (x0, p0, q0), deltat)[0]
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def LDDMMloss(K, dataloss, gamma=0):
|
|
200
|
+
def loss(p0, q0):
|
|
201
|
+
p, q = Shooting(p0, q0, K)[-1]
|
|
202
|
+
return gamma * Hamiltonian(K)(p0, q0) + dataloss(q)
|
|
203
|
+
|
|
204
|
+
return loss
|
|
205
|
+
|
|
206
|
+
# Basic Varifold loss
|
|
207
|
+
# VT: vertices coordinates of target surface,
|
|
208
|
+
# FS,FT : Face connectivity of source and target surfaces
|
|
209
|
+
# K kernel
|
|
210
|
+
def lossVarifoldSurf(FS, VT, FT, K):
|
|
211
|
+
def get_center_length_normal(F, V):
|
|
212
|
+
V0, V1, V2 = (
|
|
213
|
+
V.index_select(0, F[:, 0]),
|
|
214
|
+
V.index_select(0, F[:, 1]),
|
|
215
|
+
V.index_select(0, F[:, 2]),
|
|
216
|
+
)
|
|
217
|
+
centers, normals = (V0 + V1 + V2) / 3, 0.5 * torch.cross(V1 - V0, V2 - V0)
|
|
218
|
+
length = (normals**2).sum(dim=1)[:, None].sqrt()
|
|
219
|
+
return centers, length, normals / length
|
|
220
|
+
|
|
221
|
+
CT, LT, NTn = get_center_length_normal(FT, VT)
|
|
222
|
+
cst = (LT * K(CT, CT, NTn, NTn, LT)).sum()
|
|
223
|
+
|
|
224
|
+
def loss(VS):
|
|
225
|
+
CS, LS, NSn = get_center_length_normal(FS, VS)
|
|
226
|
+
return (
|
|
227
|
+
cst
|
|
228
|
+
+ (LS * K(CS, CS, NSn, NSn, LS)).sum()
|
|
229
|
+
- 2 * (LS * K(CS, CT, NSn, NTn, LT)).sum()
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
return loss
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
# Also implement a basic currents loss
|
|
236
|
+
def lossCurrentsSurf(FS, VT, FT, K):
|
|
237
|
+
def get_center_length_normal(F, V):
|
|
238
|
+
V0, V1, V2 = (
|
|
239
|
+
V.index_select(0, F[:, 0]),
|
|
240
|
+
V.index_select(0, F[:, 1]),
|
|
241
|
+
V.index_select(0, F[:, 2]),
|
|
242
|
+
)
|
|
243
|
+
centers, normals = (V0 + V1 + V2) / 3, 0.5 * torch.cross(V1 - V0, V2 - V0)
|
|
244
|
+
return centers, normals
|
|
245
|
+
|
|
246
|
+
CT, NT = get_center_length_normal(FT, VT)
|
|
247
|
+
cst = K(CT, CT, NT, NT).sum()
|
|
248
|
+
|
|
249
|
+
def loss(VS):
|
|
250
|
+
CS, NS = get_center_length_normal(FS, VS)
|
|
251
|
+
tt,ss,st = cst, K(CS, CS, NS, NS).sum(), 2 * K(CS, CT, NS, NT).sum()
|
|
252
|
+
print(f'tt: {tt}, ss: {ss}, st: {st}')
|
|
253
|
+
return (
|
|
254
|
+
cst
|
|
255
|
+
+ K(CS, CS, NS, NS).sum()
|
|
256
|
+
- 2 * K(CS, CT, NS, NT).sum()
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
return loss
|
|
260
|
+
|
|
261
|
+
# This function loads a mesh and extracts derived objects/tensors
|
|
262
|
+
def load_mesh(fn, target_faces=None):
|
|
263
|
+
pd = vtk_all_point_arrays_to_cell_arrays(load_vtk(fn))
|
|
264
|
+
v, f = vtk_get_points(pd), vtk_get_triangles(pd)
|
|
265
|
+
if target_faces:
|
|
266
|
+
v, f = decimate(v, f, target_faces)
|
|
267
|
+
#lp = mesh_label_prob_maps(pd)
|
|
268
|
+
return {
|
|
269
|
+
'fn': fn,
|
|
270
|
+
'pd': pd,
|
|
271
|
+
'v': v,
|
|
272
|
+
'f': f,
|
|
273
|
+
#'lp': lp,
|
|
274
|
+
'vt': torch.tensor(v, dtype=torchdtype, device=torchdeviceId).contiguous(),
|
|
275
|
+
'ft': torch.tensor(f, dtype=torch.long, device=torchdeviceId).contiguous()
|
|
276
|
+
#'lpt': torch.tensor(lp, dtype=torchdtype, device=torchdeviceId).contiguous()
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def closure():
|
|
281
|
+
optimizer.zero_grad()
|
|
282
|
+
L = loss(p0, q0)
|
|
283
|
+
print("loss", L.detach().cpu().numpy())
|
|
284
|
+
L.backward()
|
|
285
|
+
return L
|
|
286
|
+
|
|
287
|
+
print("decimating the mesh............")
|
|
288
|
+
src_path=str(sys.argv[1])
|
|
289
|
+
tgt_path=str(sys.argv[2])
|
|
290
|
+
|
|
291
|
+
md_src = load_mesh(os.path.join(src_path, sys.argv[3]))
|
|
292
|
+
print(md_src.keys(), len(md_src['f']), len(md_src['v']))
|
|
293
|
+
|
|
294
|
+
v_dec, f_dec = decimate(md_src['v'], md_src['f'], 300000)
|
|
295
|
+
print(len(v_dec), len(f_dec))
|
|
296
|
+
save_vtk(vtk_make_pd(v_dec, f_dec), os.path.join(tgt_path, sys.argv[4]))
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
freesurfer_path=$1
|
|
2
|
+
working_dir=$2
|
|
3
|
+
str_split=$3
|
|
4
|
+
hemis=rh
|
|
5
|
+
for i in $str_split; do subjects+=($i) ; done
|
|
6
|
+
|
|
7
|
+
for subj in "${subjects[@]}"
|
|
8
|
+
do
|
|
9
|
+
|
|
10
|
+
echo ${subj}
|
|
11
|
+
SUBJECTS_DIR=${working_dir}/${subj}
|
|
12
|
+
|
|
13
|
+
mri_convert ${SUBJECTS_DIR}/mri/rawavg.mgz ${SUBJECTS_DIR}/mri/orig_conform.mgz --conform
|
|
14
|
+
|
|
15
|
+
tkregister2 --mov ${SUBJECTS_DIR}/mri/rawavg.mgz --targ ${SUBJECTS_DIR}/mri/orig_conform.mgz \
|
|
16
|
+
--reg ${SUBJECTS_DIR}/mri/transforms/register.native.dat --regheader-center \
|
|
17
|
+
--noedit --ltaout ${SUBJECTS_DIR}/mri/transforms/init_for_mris_register.lta
|
|
18
|
+
|
|
19
|
+
mri_add_xform_to_header -c ${SUBJECTS_DIR}/mri/transforms/talairach.xfm ${SUBJECTS_DIR}/mri/orig_conform.mgz ${SUBJECTS_DIR}/mri/orig_conform.mgz
|
|
20
|
+
|
|
21
|
+
mri_info ${SUBJECTS_DIR}/mri/orig_conform.mgz
|
|
22
|
+
|
|
23
|
+
${freesurfer_path}/bin/talairach_avi --i ${SUBJECTS_DIR}/mri/orig_conform.mgz --xfm ${SUBJECTS_DIR}/mri/transforms/talairach.auto.xfm
|
|
24
|
+
|
|
25
|
+
cp ${SUBJECTS_DIR}/mri/transforms/talairach.auto.xfm ${SUBJECTS_DIR}/mri/transforms/talairach.xfm
|
|
26
|
+
|
|
27
|
+
lta_convert --src ${SUBJECTS_DIR}/mri/orig_conform.mgz --trg /data/pulkit/exvivo_reg_reconstruct/freesurfer_installation/freesurfer/average/mni305.cor.mgz \
|
|
28
|
+
--inxfm ${SUBJECTS_DIR}/mri/transforms/talairach.xfm --outlta ${SUBJECTS_DIR}/mri/transforms/talairach.xfm.lta --subject fsaverage --ltavox2vox
|
|
29
|
+
|
|
30
|
+
mri_add_xform_to_header -c ${SUBJECTS_DIR}/mri/transforms/talairach.xfm ${SUBJECTS_DIR}/mri/orig_conform.mgz ${SUBJECTS_DIR}/mri/orig_conform.mgz
|
|
31
|
+
|
|
32
|
+
done;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
working_dir=$1
|
|
2
|
+
generated_files_folder=$2
|
|
3
|
+
mri_dir=$3
|
|
4
|
+
str_split=$4
|
|
5
|
+
for i in $str_split; do subjects+=($i) ; done
|
|
6
|
+
|
|
7
|
+
hemis=rh
|
|
8
|
+
for subj in "${subjects[@]}"
|
|
9
|
+
do
|
|
10
|
+
echo ${subj}
|
|
11
|
+
|
|
12
|
+
SUBJECTS_DIR=${working_dir}/${subj}
|
|
13
|
+
mkdir -p ${SUBJECTS_DIR}
|
|
14
|
+
|
|
15
|
+
mkdir -p ${SUBJECTS_DIR}/mri \
|
|
16
|
+
${SUBJECTS_DIR}/surf \
|
|
17
|
+
${SUBJECTS_DIR}/scripts \
|
|
18
|
+
${SUBJECTS_DIR}/label \
|
|
19
|
+
${SUBJECTS_DIR}/stats \
|
|
20
|
+
${SUBJECTS_DIR}/mri/transforms
|
|
21
|
+
|
|
22
|
+
mri_convert ${mri_dir}/${subj}.nii.gz ${SUBJECTS_DIR}/mri/${subj}.mgz
|
|
23
|
+
|
|
24
|
+
cp ${SUBJECTS_DIR}/mri/${subj}.mgz ${SUBJECTS_DIR}/mri/mri.mgz
|
|
25
|
+
cp ${SUBJECTS_DIR}/mri/${subj}.mgz ${SUBJECTS_DIR}/mri/brain.mgz
|
|
26
|
+
cp ${SUBJECTS_DIR}/mri/${subj}.mgz ${SUBJECTS_DIR}/mri/brainmask.mgz
|
|
27
|
+
cp ${SUBJECTS_DIR}/mri/${subj}.mgz ${SUBJECTS_DIR}/mri/brain.finalsurfs.mgz
|
|
28
|
+
cp ${SUBJECTS_DIR}/mri/${subj}.mgz ${SUBJECTS_DIR}/mri/rawavg.mgz
|
|
29
|
+
cp ${SUBJECTS_DIR}/mri/${subj}.mgz ${SUBJECTS_DIR}/mri/norm.mgz
|
|
30
|
+
cp ${SUBJECTS_DIR}/mri/${subj}.mgz ${SUBJECTS_DIR}/mri/nu.mgz
|
|
31
|
+
cp ${SUBJECTS_DIR}/mri/${subj}.mgz ${SUBJECTS_DIR}/mri/orig.mgz
|
|
32
|
+
cp ${SUBJECTS_DIR}/mri/${subj}.mgz ${SUBJECTS_DIR}/mri/T1.mgz
|
|
33
|
+
|
|
34
|
+
cp ${generated_files_folder}/${subj}_filled.mgz ${SUBJECTS_DIR}/mri/filled.mgz
|
|
35
|
+
cp ${generated_files_folder}/${subj}_wm.mgz ${SUBJECTS_DIR}/mri/wm.mgz
|
|
36
|
+
|
|
37
|
+
cp ${generated_files_folder}/${subj}_aseg.presurf.mgz ${SUBJECTS_DIR}/mri/aseg.presurf.mgz
|
|
38
|
+
cp ${generated_files_folder}/${subj}_aseg.presurf_100.mgz ${SUBJECTS_DIR}/mri/aseg.presurf_100.mgz
|
|
39
|
+
cp ${generated_files_folder}/${subj}_aseg.mgz ${SUBJECTS_DIR}/mri/aseg.mgz
|
|
40
|
+
cp ${generated_files_folder}/${subj}_rh.ribbon.mgz ${SUBJECTS_DIR}/mri/${hemis}.ribbon.mgz
|
|
41
|
+
cp ${generated_files_folder}/${subj}.ribbon.mgz ${SUBJECTS_DIR}/mri/ribbon.mgz
|
|
42
|
+
|
|
43
|
+
done;
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
working_dir=$1
|
|
2
|
+
str_split=$2
|
|
3
|
+
freesurfer_path=$3
|
|
4
|
+
num_threads=$4
|
|
5
|
+
external_atlases_path=$5
|
|
6
|
+
autodet_stats_dat=$6
|
|
7
|
+
for i in $str_split; do subjects+=($i) ; done
|
|
8
|
+
|
|
9
|
+
hemis=rh
|
|
10
|
+
hemis_other=lh
|
|
11
|
+
for subj in "${subjects[@]}"
|
|
12
|
+
do
|
|
13
|
+
echo ${subj}
|
|
14
|
+
start=$SECONDS
|
|
15
|
+
|
|
16
|
+
SUBJECTS_DIR=${working_dir}
|
|
17
|
+
|
|
18
|
+
######### segm_parc file
|
|
19
|
+
mris_place_surface --adgws-in ${autodet_stats_dat} \
|
|
20
|
+
--wm ${SUBJECTS_DIR}/${subj}/mri/wm.mgz --threads ${num_threads} --invol ${SUBJECTS_DIR}/${subj}/mri/aseg.presurf_100.mgz --${hemis} \
|
|
21
|
+
--i ${SUBJECTS_DIR}/${subj}/surf/${hemis}.orig \
|
|
22
|
+
--o ${SUBJECTS_DIR}/${subj}/surf/${hemis}.white.preaparc --white --seg ${SUBJECTS_DIR}/${subj}/mri/aseg.presurf.mgz
|
|
23
|
+
|
|
24
|
+
mri_label2label --label-cortex ${SUBJECTS_DIR}/${subj}/surf/${hemis}.white.preaparc ${SUBJECTS_DIR}/${subj}/mri/aseg.presurf.mgz 0 ${SUBJECTS_DIR}/${subj}/label/${hemis}.cortex.label
|
|
25
|
+
|
|
26
|
+
mris_smooth -n 3 -nw ${SUBJECTS_DIR}/${subj}/surf/${hemis}.white.preaparc ${SUBJECTS_DIR}/${subj}/surf/${hemis}.smoothwm
|
|
27
|
+
mris_inflate ${SUBJECTS_DIR}/${subj}/surf/${hemis}.smoothwm ${SUBJECTS_DIR}/${subj}/surf/${hemis}.inflated
|
|
28
|
+
|
|
29
|
+
mris_curvature -w ${SUBJECTS_DIR}/${subj}/surf/${hemis}.white.preaparc
|
|
30
|
+
mris_curvature -thresh .999 -n -a 5 -w -distances 10 10 ${SUBJECTS_DIR}/${subj}/surf/${hemis}.inflated
|
|
31
|
+
|
|
32
|
+
mris_sphere ${SUBJECTS_DIR}/${subj}/surf/${hemis}.inflated ${SUBJECTS_DIR}/${subj}/surf/${hemis}.sphere
|
|
33
|
+
|
|
34
|
+
mris_register -curv -threads ${num_threads} -inflated -init \
|
|
35
|
+
-reg ${SUBJECTS_DIR}/${subj}/mri/transforms/init_for_mris_register.lta \
|
|
36
|
+
${SUBJECTS_DIR}/${subj}/surf/${hemis}.sphere ${freesurfer_path}/average/${hemis}.folding.atlas.acfb40.noaparc.i12.2016-08-02.tif ${SUBJECTS_DIR}/${subj}/surf/${hemis}.sphere.reg
|
|
37
|
+
|
|
38
|
+
ln -sf ${hemis}.sphere.reg ${hemis}.fsaverage.sphere.reg
|
|
39
|
+
|
|
40
|
+
mris_jacobian ${SUBJECTS_DIR}/${subj}/surf/${hemis}.white.preaparc ${SUBJECTS_DIR}/${subj}/surf/${hemis}.sphere.reg ${SUBJECTS_DIR}/${subj}/surf/${hemis}.jacobian_white
|
|
41
|
+
mrisp_paint -a 5 ${freesurfer_path}/average/${hemis}.folding.atlas.acfb40.noaparc.i12.2016-08-02.tif#6 ${SUBJECTS_DIR}/${subj}/surf/${hemis}.sphere.reg ${SUBJECTS_DIR}/${subj}/surf/${hemis}.avg_curv
|
|
42
|
+
|
|
43
|
+
mris_ca_label -l ${SUBJECTS_DIR}/${subj}/label/${hemis}.cortex.label -aseg ${SUBJECTS_DIR}/${subj}/mri/aseg.presurf.mgz ${subj} ${hemis} ${SUBJECTS_DIR}/${subj}/surf/${hemis}.sphere.reg ${freesurfer_path}/average/${hemis}.DKaparc.atlas.acfb40.noaparc.i12.2016-08-02.gcs ${SUBJECTS_DIR}/${subj}/label/${hemis}.aparc.annot
|
|
44
|
+
|
|
45
|
+
SUBJECTS_DIR=${working_dir}
|
|
46
|
+
|
|
47
|
+
cd ${SUBJECTS_DIR}/${subj}/mri
|
|
48
|
+
mris_place_surface --adgws-in ${autodet_stats_dat} \
|
|
49
|
+
--seg aseg.presurf.mgz --threads ${num_threads} --wm wm.mgz --invol aseg.presurf_100.mgz --${hemis} --i ../surf/${hemis}.white.preaparc --o ../surf/${hemis}.white --white --nsmooth 0 \
|
|
50
|
+
--rip-label ../label/${hemis}.cortex.label --rip-bg --rip-surf ../surf/${hemis}.white.preaparc --aparc ../label/${hemis}.aparc.annot
|
|
51
|
+
|
|
52
|
+
cd ${SUBJECTS_DIR}/${subj}/mri
|
|
53
|
+
mris_place_surface --adgws-in ${autodet_stats_dat} \
|
|
54
|
+
--seg aseg.presurf.mgz --threads ${num_threads} --wm wm.mgz \
|
|
55
|
+
--invol aseg.presurf_100.mgz --${hemis} --i ../surf/${hemis}.white --o ../surf/${hemis}.pial.T1 --pial --nsmooth 0 \
|
|
56
|
+
--pin-medial-wall ../label/${hemis}.cortex.label --aparc ../label/${hemis}.aparc.annot \
|
|
57
|
+
--repulse-surf ../surf/${hemis}.white --white-surf ../surf/${hemis}.white \
|
|
58
|
+
--no-rip --intensity 10.00 --curv 10.00
|
|
59
|
+
|
|
60
|
+
cp ${SUBJECTS_DIR}/${subj}/surf/${hemis}.pial.T1 ${SUBJECTS_DIR}/${subj}/surf/${hemis}.pial
|
|
61
|
+
|
|
62
|
+
######## white curv
|
|
63
|
+
cd ${SUBJECTS_DIR}/${subj}/mri
|
|
64
|
+
mris_place_surface --curv-map ../surf/${hemis}.white 2 10 ../surf/${hemis}.curv
|
|
65
|
+
|
|
66
|
+
######## white area
|
|
67
|
+
cd ${SUBJECTS_DIR}/${subj}/mri
|
|
68
|
+
mris_place_surface --area-map ../surf/${hemis}.white ../surf/${hemis}.area
|
|
69
|
+
|
|
70
|
+
######## pial curv
|
|
71
|
+
cd ${SUBJECTS_DIR}/${subj}/mri
|
|
72
|
+
mris_place_surface --curv-map ../surf/${hemis}.pial 2 10 ../surf/${hemis}.curv.pial
|
|
73
|
+
|
|
74
|
+
######## pial area
|
|
75
|
+
cd ${SUBJECTS_DIR}/${subj}/mri
|
|
76
|
+
mris_place_surface --area-map ../surf/${hemis}.pial ../surf/${hemis}.area.pial
|
|
77
|
+
|
|
78
|
+
######## thickness
|
|
79
|
+
cd ${SUBJECTS_DIR}/${subj}/mri
|
|
80
|
+
mris_place_surface --thickness ../surf/${hemis}.white ../surf/${hemis}.pial 20 5 ../surf/${hemis}.thickness
|
|
81
|
+
|
|
82
|
+
######## area and vertex vol
|
|
83
|
+
cd ${SUBJECTS_DIR}/${subj}/mri
|
|
84
|
+
mris_place_surface --thickness ../surf/${hemis}.white ../surf/${hemis}.pial 20 5 ../surf/${hemis}.thickness
|
|
85
|
+
|
|
86
|
+
mris_curvature_stats -m --writeCurvatureFiles -G -o ${SUBJECTS_DIR}/${subj}/stats/${hemis}.curv.stats -F smoothwm ${subj} ${hemis} curv sulc
|
|
87
|
+
|
|
88
|
+
######## Cortical Parc 2
|
|
89
|
+
cd ${SUBJECTS_DIR}/${subj}/mri
|
|
90
|
+
mris_ca_label -l ../label/${hemis}.cortex.label -aseg ../mri/aseg.presurf.mgz ${subj} ${hemis} ../surf/${hemis}.sphere.reg ${freesurfer_path}/average/${hemis}.CDaparc.atlas.acfb40.noaparc.i12.2016-08-02.gcs ../label/${hemis}.aparc.a2009s.annot
|
|
91
|
+
|
|
92
|
+
######## Cortical Parc 3
|
|
93
|
+
cd ${SUBJECTS_DIR}/${subj}/mri
|
|
94
|
+
mris_ca_label -l ../label/${hemis}.cortex.label -aseg ../mri/aseg.presurf.mgz ${subj} ${hemis} ../surf/${hemis}.sphere.reg ${freesurfer_path}/average/${hemis}.DKTaparc.atlas.acfb40.noaparc.i12.2016-08-02.gcs ../label/${hemis}.aparc.DKTatlas.annot
|
|
95
|
+
|
|
96
|
+
ln -sf ${hemis}.sphere.reg ${hemis}.fsaverage.sphere.reg
|
|
97
|
+
|
|
98
|
+
SUBJECTS_DIR=${working_dir}
|
|
99
|
+
|
|
100
|
+
##### Cortical Parc Schaefer atlas: 7 and 17 networks
|
|
101
|
+
cd ${SUBJECTS_DIR}/${subj}/mri
|
|
102
|
+
mri_surf2surf --hemi ${hemis} \
|
|
103
|
+
--srcsubject fsaverage \
|
|
104
|
+
--trgsubject ${subj} \
|
|
105
|
+
--sval-annot ${external_atlases_path}/schaefer/${hemis}.Schaefer2018_400Parcels_17Networks_order.annot \
|
|
106
|
+
--tval ${SUBJECTS_DIR}/${subj}/label/${hemis}.aparc.Schaefer2018_400Parcels_17Networks.annot
|
|
107
|
+
|
|
108
|
+
##### Economo-Koskinos atlas
|
|
109
|
+
cd ${SUBJECTS_DIR}/${subj}/mri
|
|
110
|
+
mris_ca_label -t ${external_atlases_path}/economo/${hemis}.colortable.txt ${subj} ${hemis} ../surf/${hemis}.sphere.reg ${external_atlases_path}/economo/${hemis}.economo.gcs \
|
|
111
|
+
${SUBJECTS_DIR}/${subj}/label/${hemis}.economo.annot
|
|
112
|
+
|
|
113
|
+
##### Glasser atlas
|
|
114
|
+
cd ${SUBJECTS_DIR}/${subj}/mri
|
|
115
|
+
mri_surf2surf --hemi ${hemis} \
|
|
116
|
+
--srcsubject fsaverage \
|
|
117
|
+
--trgsubject ${subj} \
|
|
118
|
+
--sval-annot ${external_atlases_path}/glasser/${hemis}.HCP-MMP1.annot \
|
|
119
|
+
--tval ${SUBJECTS_DIR}/${subj}/label/${hemis}.aparc.HCP-MMP1.glasser.annot
|
|
120
|
+
|
|
121
|
+
SUBJECTS_DIR=${working_dir}
|
|
122
|
+
|
|
123
|
+
######## dummy left hemis needed for stats computation
|
|
124
|
+
cp ${SUBJECTS_DIR}/${subj}/surf/${hemis}.white ${SUBJECTS_DIR}/${subj}/surf/${hemis_other}.white
|
|
125
|
+
cp ${SUBJECTS_DIR}/${subj}/surf/${hemis}.pial ${SUBJECTS_DIR}/${subj}/surf/${hemis_other}.pial
|
|
126
|
+
cp ${SUBJECTS_DIR}/${subj}/surf/${hemis}.orig.nofix ${SUBJECTS_DIR}/${subj}/surf/${hemis_other}.orig.nofix
|
|
127
|
+
cp ${SUBJECTS_DIR}/${subj}/label/${hemis}.cortex.label ${SUBJECTS_DIR}/${subj}/label/${hemis_other}.cortex.label
|
|
128
|
+
cp ${SUBJECTS_DIR}/${subj}/label/${hemis}.aparc.annot ${SUBJECTS_DIR}/${subj}/label/${hemis_other}.aparc.annot
|
|
129
|
+
cp ${SUBJECTS_DIR}/${subj}/label/${hemis}.aparc.DKTatlas.annot ${SUBJECTS_DIR}/${subj}/label/${hemis_other}.aparc.DKTatlas.annot
|
|
130
|
+
cp ${SUBJECTS_DIR}/${subj}/label/${hemis}.aparc.a2009s.annot ${SUBJECTS_DIR}/${subj}/label/${hemis_other}.aparc.a2009s.annot
|
|
131
|
+
|
|
132
|
+
pctsurfcon --s ${subj} --${hemis}-only
|
|
133
|
+
|
|
134
|
+
mri_brainvol_stats --subject ${subj}
|
|
135
|
+
|
|
136
|
+
######## AParc-to-ASeg aparc
|
|
137
|
+
cd ${SUBJECTS_DIR}/${subj}/mri
|
|
138
|
+
mri_surf2volseg --o aparc+aseg.mgz --label-cortex --i aseg.mgz --threads ${num_threads} \
|
|
139
|
+
--lh-annot ${SUBJECTS_DIR}/${subj}/label/lh.aparc.annot 1000 \
|
|
140
|
+
--lh-cortex-mask ${SUBJECTS_DIR}/${subj}/label/lh.cortex.label \
|
|
141
|
+
--lh-white ${SUBJECTS_DIR}/${subj}/surf/lh.white \
|
|
142
|
+
--lh-pial ${SUBJECTS_DIR}/${subj}/surf/lh.pial \
|
|
143
|
+
--rh-annot ${SUBJECTS_DIR}/${subj}/label/rh.aparc.annot 2000 \
|
|
144
|
+
--rh-cortex-mask ${SUBJECTS_DIR}/${subj}/label/rh.cortex.label \
|
|
145
|
+
--rh-white ${SUBJECTS_DIR}/${subj}/surf/rh.white \
|
|
146
|
+
--rh-pial ${SUBJECTS_DIR}/${subj}/surf/rh.pial
|
|
147
|
+
|
|
148
|
+
######## AParc-to-ASeg aparc.a2009s
|
|
149
|
+
cd ${SUBJECTS_DIR}/${subj}/mri
|
|
150
|
+
mri_surf2volseg --o aparc.a2009s+aseg.mgz \
|
|
151
|
+
--label-cortex --i aseg.mgz --threads ${num_threads} \
|
|
152
|
+
--lh-annot ${SUBJECTS_DIR}/${subj}/label/lh.aparc.a2009s.annot 11100 \
|
|
153
|
+
--lh-cortex-mask ${SUBJECTS_DIR}/${subj}/label/lh.cortex.label \
|
|
154
|
+
--lh-white ${SUBJECTS_DIR}/${subj}/surf/lh.white \
|
|
155
|
+
--lh-pial ${SUBJECTS_DIR}/${subj}/surf/lh.pial \
|
|
156
|
+
--rh-annot ${SUBJECTS_DIR}/${subj}/label/rh.aparc.a2009s.annot 12100 \
|
|
157
|
+
--rh-cortex-mask ${SUBJECTS_DIR}/${subj}/label/rh.cortex.label \
|
|
158
|
+
--rh-white ${SUBJECTS_DIR}/${subj}/surf/rh.white \
|
|
159
|
+
--rh-pial ${SUBJECTS_DIR}/${subj}/surf/rh.pial
|
|
160
|
+
|
|
161
|
+
######## AParc-to-ASeg aparc.DKTatlas
|
|
162
|
+
cd ${SUBJECTS_DIR}/${subj}/mri
|
|
163
|
+
mri_surf2volseg --o aparc.DKTatlas+aseg.mgz \
|
|
164
|
+
--label-cortex --i aseg.mgz --threads ${num_threads} \
|
|
165
|
+
--lh-annot ${SUBJECTS_DIR}/${subj}/label/lh.aparc.DKTatlas.annot 1000 \
|
|
166
|
+
--lh-cortex-mask ${SUBJECTS_DIR}/${subj}/label/lh.cortex.label \
|
|
167
|
+
--lh-white ${SUBJECTS_DIR}/${subj}/surf/lh.white \
|
|
168
|
+
--lh-pial ${SUBJECTS_DIR}/${subj}/surf/lh.pial \
|
|
169
|
+
--rh-annot ${SUBJECTS_DIR}/${subj}/label/rh.aparc.DKTatlas.annot 2000 \
|
|
170
|
+
--rh-cortex-mask ${SUBJECTS_DIR}/${subj}/label/rh.cortex.label \
|
|
171
|
+
--rh-white ${SUBJECTS_DIR}/${subj}/surf/rh.white \
|
|
172
|
+
--rh-pial ${SUBJECTS_DIR}/${subj}/surf/rh.pial
|
|
173
|
+
|
|
174
|
+
######## WMParc
|
|
175
|
+
cd ${SUBJECTS_DIR}/${subj}/mri
|
|
176
|
+
mri_surf2volseg --o wmparc.mgz \
|
|
177
|
+
--label-wm --i aparc+aseg.mgz --threads ${num_threads} \
|
|
178
|
+
--lh-annot ${SUBJECTS_DIR}/${subj}/label/lh.aparc.annot 3000 \
|
|
179
|
+
--lh-cortex-mask ${SUBJECTS_DIR}/${subj}/label/lh.cortex.label \
|
|
180
|
+
--lh-white ${SUBJECTS_DIR}/${subj}/surf/lh.white \
|
|
181
|
+
--lh-pial ${SUBJECTS_DIR}/${subj}/surf/lh.pial \
|
|
182
|
+
--rh-annot ${SUBJECTS_DIR}/${subj}/label/rh.aparc.annot 4000 \
|
|
183
|
+
--rh-cortex-mask ${SUBJECTS_DIR}/${subj}/label/rh.cortex.label \
|
|
184
|
+
--rh-white ${SUBJECTS_DIR}/${subj}/surf/rh.white \
|
|
185
|
+
--rh-pial ${SUBJECTS_DIR}/${subj}/surf/rh.pial
|
|
186
|
+
|
|
187
|
+
cd ${SUBJECTS_DIR}/${subj}
|
|
188
|
+
mri_segstats --seg mri/wmparc.mgz \
|
|
189
|
+
--sum stats/wmparc.stats --pv mri/norm.mgz \
|
|
190
|
+
--excludeid 0 --brainmask mri/brainmask.mgz --in mri/norm.mgz \
|
|
191
|
+
--in-intensity-name norm --in-intensity-units MR \
|
|
192
|
+
--subject ${subj} \
|
|
193
|
+
--surf-wm-vol --ctab ${freesurfer_path}/WMParcStatsLUT.txt --etiv
|
|
194
|
+
|
|
195
|
+
######## Parcellation Stats
|
|
196
|
+
mris_anatomical_stats -th3 -mgz \
|
|
197
|
+
-cortex ${SUBJECTS_DIR}/${subj}/label/${hemis}.cortex.label \
|
|
198
|
+
-f ${SUBJECTS_DIR}/${subj}/stats/${hemis}.aparc.stats \
|
|
199
|
+
-b -a ${SUBJECTS_DIR}/${subj}/label/${hemis}.aparc.annot \
|
|
200
|
+
-c ${SUBJECTS_DIR}/${subj}/label/aparc.annot.ctab ${subj} ${hemis} white
|
|
201
|
+
|
|
202
|
+
mri_brainvol_stats --subject ${subj}
|
|
203
|
+
|
|
204
|
+
mris_anatomical_stats -th3 -mgz \
|
|
205
|
+
-cortex ${SUBJECTS_DIR}/${subj}/label/${hemis}.cortex.label \
|
|
206
|
+
-f ${SUBJECTS_DIR}/${subj}/stats/${hemis}.aparc.pial.stats \
|
|
207
|
+
-b -a ${SUBJECTS_DIR}/${subj}/label/${hemis}.aparc.annot \
|
|
208
|
+
-c ${SUBJECTS_DIR}/${subj}/label/aparc.annot.ctab ${subj} ${hemis} pial
|
|
209
|
+
|
|
210
|
+
######## Parcellation Stats 2
|
|
211
|
+
mris_anatomical_stats -th3 -mgz \
|
|
212
|
+
-cortex ${SUBJECTS_DIR}/${subj}/label/${hemis}.cortex.label \
|
|
213
|
+
-f ${SUBJECTS_DIR}/${subj}/stats/${hemis}.aparc.a2009s.stats \
|
|
214
|
+
-b -a ${SUBJECTS_DIR}/${subj}/label/${hemis}.aparc.a2009s.annot \
|
|
215
|
+
-c ${SUBJECTS_DIR}/${subj}/label/aparc.annot.a2009s.ctab ${subj} ${hemis} white
|
|
216
|
+
|
|
217
|
+
######## Parcellation Stats 3
|
|
218
|
+
mris_anatomical_stats -th3 -mgz \
|
|
219
|
+
-cortex ${SUBJECTS_DIR}/${subj}/label/${hemis}.cortex.label \
|
|
220
|
+
-f ${SUBJECTS_DIR}/${subj}/stats/${hemis}.aparc.DKTatlas.stats \
|
|
221
|
+
-b -a ${SUBJECTS_DIR}/${subj}/label/${hemis}.aparc.DKTatlas.annot \
|
|
222
|
+
-c ${SUBJECTS_DIR}/${subj}/label/aparc.annot.DKTatlas.ctab ${subj} ${hemis} white
|
|
223
|
+
|
|
224
|
+
######## ASeg Stats
|
|
225
|
+
mri_segstats --seg ${SUBJECTS_DIR}/${subj}/mri/aseg.mgz \
|
|
226
|
+
--sum ${SUBJECTS_DIR}/${subj}/stats/aseg.stats --pv ${SUBJECTS_DIR}/${subj}/mri/norm.mgz \
|
|
227
|
+
--empty --brainmask ${SUBJECTS_DIR}/${subj}/mri/brainmask.mgz --brain-vol-from-seg \
|
|
228
|
+
--excludeid 0 --excl-ctxgmwm --supratent --subcortgray \
|
|
229
|
+
--in ${SUBJECTS_DIR}/${subj}/mri/norm.mgz --in-intensity-name norm --in-intensity-units MR \
|
|
230
|
+
--etiv --surf-wm-vol --surf-ctx-vol --totalgray --euler \
|
|
231
|
+
--ctab ${freesurfer_path}/ASegStatsLUT.txt \
|
|
232
|
+
--subject ${subj}
|
|
233
|
+
|
|
234
|
+
duration=$(( SECONDS - start ))
|
|
235
|
+
echo "total time for this subject:" $duration
|
|
236
|
+
done
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
working_dir=$1
|
|
2
|
+
str_split=$2
|
|
3
|
+
generated_files_folder=$3
|
|
4
|
+
segm_path=$4
|
|
5
|
+
for i in $str_split; do subjects+=($i) ; done
|
|
6
|
+
|
|
7
|
+
for subj in "${subjects[@]}"
|
|
8
|
+
do
|
|
9
|
+
echo ${subj}
|
|
10
|
+
|
|
11
|
+
cp ${segm_path}/${subj}.nii.gz ${generated_files_folder}/${subj}_reslice_aseg_ready_with_overlap_corrected.nii.gz
|
|
12
|
+
|
|
13
|
+
c3d ${generated_files_folder}/${subj}_reslice_aseg_ready_with_overlap_corrected.nii.gz -replace 6 7 -o ${generated_files_folder}/${subj}_reslice_aseg_ready_with_overlap_corrected.nii.gz
|
|
14
|
+
|
|
15
|
+
c3d ${generated_files_folder}/${subj}_reslice_aseg_ready_with_overlap_corrected.nii.gz -replace 1 42 2 50 3 51 4 52 5 49 7 41 8 43 9 0 10 53 -o ${generated_files_folder}/${subj}_reslice_aseg_ready_with_overlap_corrected_RH_FS_labels.nii.gz
|
|
16
|
+
|
|
17
|
+
mri_convert ${generated_files_folder}/${subj}_reslice_aseg_ready_with_overlap_corrected_RH_FS_labels.nii.gz ${generated_files_folder}/${subj}_aseg.mgz
|
|
18
|
+
cp ${generated_files_folder}/${subj}_aseg.mgz ${generated_files_folder}/${subj}_aseg.presurf.mgz
|
|
19
|
+
|
|
20
|
+
c3d ${generated_files_folder}/${subj}_reslice_aseg_ready_with_overlap_corrected_RH_FS_labels.nii.gz -replace 0 100 42 142 50 150 51 151 52 152 49 149 41 241 43 143 53 153 -o ${generated_files_folder}/${subj}_reslice_aseg_ready_with_overlap_corrected_RH_FS_labels_presurf_100.nii.gz
|
|
21
|
+
c3d ${generated_files_folder}/${subj}_reslice_aseg_ready_with_overlap_corrected_RH_FS_labels_presurf_100.nii.gz -dup -lstat
|
|
22
|
+
mri_convert ${generated_files_folder}/${subj}_reslice_aseg_ready_with_overlap_corrected_RH_FS_labels_presurf_100.nii.gz ${generated_files_folder}/${subj}_aseg.presurf_100.mgz
|
|
23
|
+
|
|
24
|
+
c3d ${generated_files_folder}/${subj}_reslice_aseg_ready_with_overlap_corrected.nii.gz -retain-labels 2 3 4 5 7 9 -o ${generated_files_folder}/${subj}_reslice_aseg_ready_with_overlap_corrected_WM_only.nii.gz
|
|
25
|
+
c3d ${generated_files_folder}/${subj}_reslice_aseg_ready_with_overlap_corrected_WM_only.nii.gz -replace 2 1 3 1 4 1 5 1 7 1 9 1 -o ${generated_files_folder}/${subj}_reslice_aseg_ready_with_overlap_corrected_WM_only.nii.gz
|
|
26
|
+
|
|
27
|
+
c3d ${generated_files_folder}/${subj}_reslice_aseg_ready_with_overlap_corrected_WM_only.nii.gz -comp -threshold 1 1 1 0 -o ${generated_files_folder}/${subj}_reslice_aseg_ready_with_overlap_corrected_WM_only_cc.nii.gz
|
|
28
|
+
|
|
29
|
+
mri_convert ${generated_files_folder}/${subj}_reslice_aseg_ready_with_overlap_corrected_WM_only_cc.nii.gz ${generated_files_folder}/${subj}_wm.mgz
|
|
30
|
+
cp ${generated_files_folder}/${subj}_wm.mgz ${generated_files_folder}/${subj}_filled.mgz
|
|
31
|
+
|
|
32
|
+
c3d ${generated_files_folder}/${subj}_reslice_aseg_ready_with_overlap_corrected.nii.gz -replace 1 42 2 41 3 41 4 41 5 41 7 41 8 41 9 41 10 0 -o ${generated_files_folder}/${subj}_ribbon.nii.gz
|
|
33
|
+
c3d ${generated_files_folder}/${subj}_reslice_aseg_ready_with_overlap_corrected.nii.gz -retain-labels 1 -o ${generated_files_folder}/${subj}_rh.ribbon.nii.gz
|
|
34
|
+
|
|
35
|
+
mri_convert ${generated_files_folder}/${subj}_rh.ribbon.nii.gz ${generated_files_folder}/${subj}_rh.ribbon.mgz
|
|
36
|
+
mri_convert ${generated_files_folder}/${subj}_ribbon.nii.gz ${generated_files_folder}/${subj}.ribbon.mgz
|
|
37
|
+
done;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# read the mri files and create a list of the subjects
|
|
2
|
+
freesurfer_path=$1
|
|
3
|
+
working_dir=$2
|
|
4
|
+
mri_path=$3
|
|
5
|
+
segm_path=$4
|
|
6
|
+
external_atlases_path=$5
|
|
7
|
+
num_threads=$6
|
|
8
|
+
autodet_stats_dat=$7
|
|
9
|
+
|
|
10
|
+
subjects=()
|
|
11
|
+
for file in ${mri_path}/*.nii.gz
|
|
12
|
+
do
|
|
13
|
+
fname=$(basename "$file" .nii.gz)
|
|
14
|
+
subjects+=(${fname})
|
|
15
|
+
done
|
|
16
|
+
|
|
17
|
+
echo "Here are the list of subjects to be processed: " ${subjects[@]}
|
|
18
|
+
|
|
19
|
+
##### STEP 1: Prepare files from the initial 10-label deep learning based-segmentation
|
|
20
|
+
generated_files_folder=${working_dir}/files_prepared_for_pipeline
|
|
21
|
+
mkdir -p ${generated_files_folder}
|
|
22
|
+
prepare_segm_files.sh ${working_dir} "${subjects[*]}" ${generated_files_folder} ${segm_path}
|
|
23
|
+
|
|
24
|
+
##### STEP 2: Create FreeSurfer-like files
|
|
25
|
+
make_fs_directories.sh ${working_dir} ${generated_files_folder} ${mri_path} "${subjects[*]}"
|
|
26
|
+
|
|
27
|
+
##### STEP 3: Create mesh and downsample the same
|
|
28
|
+
tgt_dir_FS_mesh=${working_dir}/freesurfer_high_res_mesh
|
|
29
|
+
tgt_dir_FS_mesh_decimated=${working_dir}/decimated_mesh
|
|
30
|
+
mkdir -p ${tgt_dir_FS_mesh}
|
|
31
|
+
mkdir -p ${tgt_dir_FS_mesh_decimated}
|
|
32
|
+
|
|
33
|
+
# this file calls the Python script: decimate_mesh.py
|
|
34
|
+
create_mesh.sh ${working_dir} ${tgt_dir_FS_mesh} ${tgt_dir_FS_mesh_decimated} "${subjects[*]}"
|
|
35
|
+
|
|
36
|
+
##### STEP 4: Perform some intial regsitration to get all the required orientations
|
|
37
|
+
do_mni_txs.sh ${freesurfer_path} ${working_dir} "${subjects[*]}"
|
|
38
|
+
|
|
39
|
+
##### STEP 5: Perform surface-based topology correction
|
|
40
|
+
topology_correction.sh ${working_dir} "${subjects[*]}"
|
|
41
|
+
|
|
42
|
+
##### STEP 6: Perform surface-based parcellation
|
|
43
|
+
parcellation.sh ${working_dir} "${subjects[*]}" ${freesurfer_path} ${num_threads} ${external_atlases_path} ${autodet_stats_dat}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
working_dir=$1
|
|
2
|
+
str_split=$2
|
|
3
|
+
for i in $str_split; do subjects+=($i) ; done
|
|
4
|
+
|
|
5
|
+
hemis=rh
|
|
6
|
+
for subj in "${subjects[@]}"
|
|
7
|
+
do
|
|
8
|
+
echo ${subj}
|
|
9
|
+
start=$SECONDS
|
|
10
|
+
|
|
11
|
+
SUBJECTS_DIR=${working_dir}/${subj}
|
|
12
|
+
mris_extract_main_component ${SUBJECTS_DIR}/surf/${hemis}.orig.nofix ${SUBJECTS_DIR}/surf/${hemis}.orig.nofix
|
|
13
|
+
|
|
14
|
+
mris_smooth -nw ${SUBJECTS_DIR}/surf/${hemis}.orig.nofix ${SUBJECTS_DIR}/surf/${hemis}.smoothwm.nofix
|
|
15
|
+
mris_euler_number ${SUBJECTS_DIR}/surf/${hemis}.smoothwm.nofix
|
|
16
|
+
|
|
17
|
+
mris_inflate -no-save-sulc ${SUBJECTS_DIR}/surf/${hemis}.smoothwm.nofix ${SUBJECTS_DIR}/surf/${hemis}.inflated.nofix
|
|
18
|
+
mris_euler_number ${SUBJECTS_DIR}/surf/${hemis}.inflated.nofix
|
|
19
|
+
|
|
20
|
+
mris_sphere -q -p 6 -a 128 ${SUBJECTS_DIR}/surf/${hemis}.inflated.nofix ${SUBJECTS_DIR}/surf/${hemis}.qsphere.nofix
|
|
21
|
+
|
|
22
|
+
SUBJECTS_DIR=${working_dir}
|
|
23
|
+
mris_fix_topology -mgz -sphere qsphere.nofix -inflated inflated.nofix -orig orig.nofix -out orig.premesh -defect defect -ga ${subj} ${hemis} -threads 64 -verbose -errors -warnings
|
|
24
|
+
mris_euler_number ${SUBJECTS_DIR}/${subj}/surf/${hemis}.orig.premesh
|
|
25
|
+
|
|
26
|
+
mris_inflate ${SUBJECTS_DIR}/${subj}/surf/${hemis}.orig.premesh ${SUBJECTS_DIR}/${subj}/surf/${hemis}.inflated.fixed
|
|
27
|
+
mris_euler_number ${SUBJECTS_DIR}/${subj}/surf/${hemis}.inflated.fixed
|
|
28
|
+
|
|
29
|
+
mris_remove_intersection ${SUBJECTS_DIR}/${subj}/surf/${hemis}.orig.premesh ${SUBJECTS_DIR}/${subj}/surf/${hemis}.orig.premesh
|
|
30
|
+
mris_extract_main_component ${SUBJECTS_DIR}/${subj}/surf/${hemis}.orig.premesh ${SUBJECTS_DIR}/${subj}/surf/${hemis}.orig.premesh
|
|
31
|
+
mris_euler_number ${SUBJECTS_DIR}/${subj}/surf/${hemis}.orig.premesh
|
|
32
|
+
|
|
33
|
+
cp ${SUBJECTS_DIR}/${subj}/surf/${hemis}.orig.premesh ${SUBJECTS_DIR}/${subj}/surf/${hemis}.orig
|
|
34
|
+
cp ${SUBJECTS_DIR}/${subj}/surf/${hemis}.inflated.fixed ${SUBJECTS_DIR}/${subj}/surf/${hemis}.inflated
|
|
35
|
+
mris_euler_number ${SUBJECTS_DIR}/${subj}/surf/${hemis}.orig
|
|
36
|
+
|
|
37
|
+
duration=$(( SECONDS - start ))
|
|
38
|
+
echo "total time for this subject:" $duration
|
|
39
|
+
done
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: purple_mri
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: purple_mri: Penn Utilities for Registration and ParcelLation of Ex vivo MRI
|
|
5
|
+
Author-email: Pulkit Khandelwal <kpulkit95@gmail.com>
|
|
6
|
+
Project-URL: Homepage, https://github.com/Pulkit-Khandelwal/purple_mri
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: numpy
|
|
9
|
+
Requires-Dist: torch
|
|
10
|
+
Requires-Dist: pykeops
|
|
11
|
+
Requires-Dist: pymeshlab
|
|
12
|
+
Requires-Dist: vtk
|
|
13
|
+
Requires-Dist: SimpleITK
|
|
14
|
+
Requires-Dist: geomloss
|
|
15
|
+
|
|
16
|
+
# purple-mri: **P**enn **U**tilities for **R**egistration and **P**arcel**L**ation of **E**x vivo **MRI**
|
|
17
|
+
|
|
18
|
+
We provide a set of tools packaged as `purple-mri` for segmentation, parcellation and registration of ultra high-resolution (< 300 microns) postmortem human brain hemisphere at 7 tesla t2w MRI at native subject-space resolution. This pipeline leverages advances in both deep learning and classical surface-based modeling techniques to produce parcellations in any atlas used in neuroimaging. The developed method allows us to perform vertex-wise analysis in the template space and thereby link morphometry measures with pathology measurements derived from histology.
|
|
19
|
+
|
|
20
|
+
Check out the [project page](https://pulkit-khandelwal.github.io/exvivo-brain-upenn/) and our latest papers [here](https://direct.mit.edu/imag/article/doi/10.1162/imag_a_00171/120741) and [here](https://arxiv.org/abs/2403.19497).
|
|
21
|
+
|
|
22
|
+
In particular, `purple-mri` allows you to do the following:
|
|
23
|
+
+ obtain an initial 10 label segmentation: cortical GM, normal appearing WM, WMH, medial temporal lobe, corpus callosum, ventricles, caudate, putamen, globus pallidus and thalamus
|
|
24
|
+
+ obtain surface-based native subject-space parcellation based on different brain atlases such as: DKT, Economo, Schaeffer etc
|
|
25
|
+
+ create population specific volumetric and surface-based templates
|
|
26
|
+
+ perform exvivo to invivo registration in volumetric intensity space
|
|
27
|
+
+ perform surface-to-surface registration between exvivo or invivo
|
|
28
|
+
+ perform intensity-based registration between 9.4 tesla MTL to 7 tesla whole hemsiphere registration
|
|
29
|
+
+ perform vertex-wise and group-wise generalized linear modeling analysis for exvivo subject population for morphometry and histology
|
|
30
|
+
|
|
31
|
+
## Steps (for segmentation and parcellation)
|
|
32
|
+
`purple-mri` follows a series of steps making use of bash scripts and Docker.
|
|
33
|
+
|
|
34
|
+
### Pre-processing
|
|
35
|
+
Perform bias correction and image normalization/standardization. We use `N4BiasFieldCorrection` as part of the CLI tool [ANTs](https://github.com/ANTsX/ANTs) and [`c3d`](http://www.itksnap.org/pmwiki/pmwiki.php?n=Convert3D.Convert3D). We highly recommend using the option of an input mask in `N4BiasFieldCorrection` which can be obtained via corase threhsolding.
|
|
36
|
+
[Here](https://github.com/Pulkit-Khandelwal/upenn-picsl-brain-ex-vivo/tree/main/misc_scripts/perform_bias_correction.sh) is a sample script.
|
|
37
|
+
|
|
38
|
+
### Deep learning-based initial labeling and CRUISE-based post-hoc topology correction
|
|
39
|
+
Currently, we have two Docker images. The first image provides the segmentation and the second employs [Nighres/CRUISE](https://nighres.readthedocs.io/en/latest/installation.html) for post-hoc topology correction.
|
|
40
|
+
Please follow the [link]([https://github.com/Pulkit-Khandelwal/upenn-picsl-brain-ex-vivo/blob/main/exvivo-segm-demo-docker.md](https://github.com/Pulkit-Khandelwal/purple-mri/blob/main/docker/exvivo_docker.md) for detailed instructions on how to use Docker to get the segmentations. Some key commands are emphasized here:
|
|
41
|
+
|
|
42
|
+
Place the pre-processed image(s) (with a suffix _0000.nii.gz to your filenames) in a folder named `data_for_inference` within your working directory is `/your/working/directory`.
|
|
43
|
+
```
|
|
44
|
+
docker pull pulks/docker_hippogang_exvivo_segm:v${LATEST_TAG}
|
|
45
|
+
|
|
46
|
+
docker run --gpus all --privileged -v /your/working/directory/:/data/exvivo/ -it pulks/docker_hippogang_exvivo_segm:v${LATEST_TAG} /bin/bash -c "bash /src/commands_nnunet_inference.sh ${OPTION}" >> logs.txt
|
|
47
|
+
```
|
|
48
|
+
You will see the output in `/your/working/directory/data_for_inference/output_from_nnunet_inference`.
|
|
49
|
+
|
|
50
|
+
Next, correct for topology so that adjoining gyri and sulci are clearly separated. Copy the segmentations from `output_from_nnunet_inference` to a folder `data_for_topology_correction` in your wokring directory.
|
|
51
|
+
```
|
|
52
|
+
docker pull pulks/docker_nighres:v1.0.0
|
|
53
|
+
|
|
54
|
+
docker run -v /your/working/directory/:/data/cruise_files/ -it pulks/docker_nighres:v1.0.0 /bin/bash -c "bash /data/prepare_cruise_files.sh"
|
|
55
|
+
|
|
56
|
+
# Locally run the file to get the final combined label file. See instructions [here](https://github.com/Pulkit-Khandelwal/upenn-picsl-brain-ex-vivo/blob/main/exvivo-segm-demo-docker.md) and links referenced therein.
|
|
57
|
+
bash clean_labels_final.sh
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Surface-based modeling to obtain whole-hemisphere parcellations
|
|
61
|
+
Once, you have obtained an initial 10-label topology corrected volumetric segmentation, you can proceed to the surface-based pipeline to obtain parcellations based on your favorite atlas. This step will be on your local machine. No GPUs required. To do this, you should have FreeSurfer installed locally. We have used FreeSurfer version 7.4.0 on linux obtained from [here](https://surfer.nmr.mgh.harvard.edu/fswiki/DownloadAndInstall). Moreover, there are some Python dependencies which can be found in the `dependencies.txt` file and installed using `pip`.
|
|
62
|
+
|
|
63
|
+
Run the following file which calls in several bash scripts which prepares the data, computes appropriate transformations and re-orients the images, corrects surface topology, and perform the parcellation into Desikan-Killiany-Tourville (DKT), Schaefer, Glasser and the Von Economo-Koskinos atlases.
|
|
64
|
+
|
|
65
|
+
For the surface-based modeling step, we assume that all the hemishpehrs are right hemispheres. So, we suggest flipping the left t2w MRI and its corresponding segmentation to left using the following `c3d` command: `c3d image_left.nii.gz -flip y image_right_flipped.nii.gz`
|
|
66
|
+
|
|
67
|
+
Clone the current repository and the run the following script `run_surface_pipeline.sh` from within the `purple_mri` folder which takes the following mandatory arguments:
|
|
68
|
+
`freesurfer_path`: path to the FreeSurfer installtion
|
|
69
|
+
`working_dir`: directory which will have the outputs for each subject stored
|
|
70
|
+
`mri_path`: mri images path
|
|
71
|
+
`segm_path`: 10-label segmentation path
|
|
72
|
+
`external_atlases_path`: directory with files for other atlases
|
|
73
|
+
`num_threads`: number of threads
|
|
74
|
+
|
|
75
|
+
Place your t2w MRI in a folder `mri_path` and the intial deep learning-based segmentations in `segm_path`.
|
|
76
|
+
Make sure your mri images and segmentation files have the same names ending with `.nii.gz`.
|
|
77
|
+
Place the `fsaverage` in the `working_dir` folder.
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
cd purple_mri
|
|
81
|
+
|
|
82
|
+
bash run_surface_pipeline.sh freesurfer_path working_dir mri_path segm_path external_atlases_path num_threads
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Other scripts
|
|
86
|
+
### Intensity-based volumetric template building
|
|
87
|
+
We build intensity-based volumetric templates using the [greedy](https://sites.google.com/view/greedyreg/about?authuser=0) tool. The required binaries (for Linux) and the scripts are located in the the `intensity_template` within the `scripts` directory. Follow the instructions [here](https://github.com/Pulkit-Khandelwal/purple-mri/blob/main/scripts/intensity_template/README.md).
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
### Ex vivo and in vivo registration
|
|
91
|
+
Script `exvivo_invivo_greedy_registration.sh` to register in vivo (t1w) and ex vivo (t2w) MRI is located in the folder `scripts`. We use [greedy](https://sites.google.com/view/greedyreg/about?authuser=0) to register the segmentations of in vivo aseg+aparc labels derived from FreeSurfer and 10-label initial deep learning segmentation of postmortem MRI. The warps are then used to regsiter the MRIs.
|
|
92
|
+
|
|
93
|
+
### Perform GLM analyses
|
|
94
|
+
We perform vertex-wise analysis in `fsaverage` space to fit a generalized linear model (GLM) between cortical thickness (mm) and with global ratings of amyloid-β, Braak staging, CERAD, and semiquantitative ratings of the medial temporal lobe (MTL) neuronal loss and tau pathology, with age, sex and postmortem interval (PMI) as covariates. You can follow the steps detailed [here](https://github.com/Pulkit-Khandelwal/purple-mri/tree/main/glm).
|
|
95
|
+
|
|
96
|
+
## Notes
|
|
97
|
+
+ Our method has been developed to work on a single exvivo hemisphere.
|
|
98
|
+
+ The deep learning-based segmentation was primarily trained on 7T t2w MRI. We have tested the model on t2* flash as well and it works pretty well but, if need be, we recommend re-training the model with some manual labels obtained on t2* flash MRI.
|
|
99
|
+
|
|
100
|
+
## pip package
|
|
101
|
+
|
|
102
|
+
## Introductory video
|
|
103
|
+
<div align="center">
|
|
104
|
+
<a href="https://youtu.be/0BOeUtlWlYw?si=7NeNDsoePOW3_J4Y">
|
|
105
|
+
<img src="https://github.com/Pulkit-Khandelwal/purple-mri/blob/main/images/thumbnail.png" style="width:75%;">
|
|
106
|
+
</a>
|
|
107
|
+
</div>
|
|
108
|
+
|
|
109
|
+
## Citations
|
|
110
|
+
+ Khandelwal, P., Duong, M. T., Sadaghiani, S., Lim, S., Denning, A. E., Chung, E., ... & Yushkevich, P. A. (2024). Automated deep learning segmentation of high-resolution 7 tesla postmortem MRI for quantitative analysis of structure-pathology correlations in neurodegenerative diseases. Imaging Neuroscience, 2, 1-30.
|
|
111
|
+
+ Khandelwal, P., Duong, M. T., Fuentes, C., Denning, A., Trotman, W., Ittyerah, R., ... & Yushkevich, P. A. (2024). Surface-based parcellation and vertex-wise analysis of ultra high-resolution ex vivo 7 tesla MRI in neurodegenerative diseases. arXiv preprint arXiv:2403.19497.
|
|
112
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
purple_mri/__init__.py
|
|
4
|
+
purple_mri/__main__.py
|
|
5
|
+
purple_mri.egg-info/PKG-INFO
|
|
6
|
+
purple_mri.egg-info/SOURCES.txt
|
|
7
|
+
purple_mri.egg-info/dependency_links.txt
|
|
8
|
+
purple_mri.egg-info/requires.txt
|
|
9
|
+
purple_mri.egg-info/top_level.txt
|
|
10
|
+
purple_mri/scripts/create_mesh.sh
|
|
11
|
+
purple_mri/scripts/decimate_mesh.py
|
|
12
|
+
purple_mri/scripts/do_mni_txs.sh
|
|
13
|
+
purple_mri/scripts/make_fs_directories.sh
|
|
14
|
+
purple_mri/scripts/parcellation.sh
|
|
15
|
+
purple_mri/scripts/prepare_segm_files.sh
|
|
16
|
+
purple_mri/scripts/run_surface_pipeline.sh
|
|
17
|
+
purple_mri/scripts/topology_correction.sh
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
purple_mri
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools"]
|
|
3
|
+
|
|
4
|
+
[project]
|
|
5
|
+
name = "purple_mri"
|
|
6
|
+
version = "0.0.1"
|
|
7
|
+
authors = [
|
|
8
|
+
{ name="Pulkit Khandelwal", email="kpulkit95@gmail.com" },
|
|
9
|
+
]
|
|
10
|
+
description = "purple_mri: Penn Utilities for Registration and ParcelLation of Ex vivo MRI"
|
|
11
|
+
dependencies = [
|
|
12
|
+
'numpy',
|
|
13
|
+
'torch',
|
|
14
|
+
'pykeops',
|
|
15
|
+
'pymeshlab',
|
|
16
|
+
'vtk',
|
|
17
|
+
'SimpleITK',
|
|
18
|
+
'geomloss'
|
|
19
|
+
]
|
|
20
|
+
readme = "README.md"
|
|
21
|
+
[tool.setuptools]
|
|
22
|
+
script-files = [
|
|
23
|
+
"purple_mri/scripts/run_surface_pipeline.sh",
|
|
24
|
+
"purple_mri/scripts/do_mni_txs.sh",
|
|
25
|
+
"purple_mri/scripts/prepare_segm_files.sh",
|
|
26
|
+
"purple_mri/scripts/create_mesh.sh",
|
|
27
|
+
"purple_mri/scripts/make_fs_directories.sh",
|
|
28
|
+
"purple_mri/scripts/parcellation.sh",
|
|
29
|
+
"purple_mri/scripts/topology_correction.sh",
|
|
30
|
+
"purple_mri/scripts/decimate_mesh.py"]
|
|
31
|
+
|
|
32
|
+
[project.urls]
|
|
33
|
+
Homepage = "https://github.com/Pulkit-Khandelwal/purple_mri"
|