pyLQT 1.0.dev1__tar.gz → 1.0.dev2__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.
- pylqt-1.0.dev2/PKG-INFO +136 -0
- pylqt-1.0.dev2/README.md +112 -0
- {pylqt-1.0.dev1 → pylqt-1.0.dev2}/pyproject.toml +4 -3
- pylqt-1.0.dev2/src/pyLQT/__init__.py +3 -0
- pylqt-1.0.dev2/src/pyLQT/cli.py +71 -0
- {pylqt-1.0.dev1/src → pylqt-1.0.dev2/src/pyLQT}/lesion_metrics/gray_matter/metrics.py +1 -1
- {pylqt-1.0.dev1/src → pylqt-1.0.dev2/src/pyLQT}/lesion_metrics/utils/downloads.py +82 -9
- {pylqt-1.0.dev1/src → pylqt-1.0.dev2/src/pyLQT}/lesion_metrics/utils/registration.py +13 -9
- pylqt-1.0.dev2/src/pyLQT/pipeline.py +183 -0
- pylqt-1.0.dev2/src/pyLQT.egg-info/PKG-INFO +136 -0
- pylqt-1.0.dev2/src/pyLQT.egg-info/SOURCES.txt +26 -0
- pylqt-1.0.dev2/src/pyLQT.egg-info/entry_points.txt +2 -0
- {pylqt-1.0.dev1 → pylqt-1.0.dev2}/src/pyLQT.egg-info/requires.txt +1 -0
- pylqt-1.0.dev2/src/pyLQT.egg-info/top_level.txt +1 -0
- pylqt-1.0.dev1/PKG-INFO +0 -62
- pylqt-1.0.dev1/README.md +0 -39
- pylqt-1.0.dev1/src/pyLQT.egg-info/PKG-INFO +0 -62
- pylqt-1.0.dev1/src/pyLQT.egg-info/SOURCES.txt +0 -24
- pylqt-1.0.dev1/src/pyLQT.egg-info/entry_points.txt +0 -2
- pylqt-1.0.dev1/src/pyLQT.egg-info/top_level.txt +0 -2
- pylqt-1.0.dev1/src/pyLQT_cli.py +0 -180
- {pylqt-1.0.dev1 → pylqt-1.0.dev2}/LICENSE +0 -0
- {pylqt-1.0.dev1 → pylqt-1.0.dev2}/setup.cfg +0 -0
- {pylqt-1.0.dev1/src → pylqt-1.0.dev2/src/pyLQT}/lesion_metrics/__init__.py +0 -0
- {pylqt-1.0.dev1/src → pylqt-1.0.dev2/src/pyLQT}/lesion_metrics/gray_matter/__init__.py +0 -0
- {pylqt-1.0.dev1/src → pylqt-1.0.dev2/src/pyLQT}/lesion_metrics/gray_matter/utils.py +0 -0
- {pylqt-1.0.dev1/src → pylqt-1.0.dev2/src/pyLQT}/lesion_metrics/network/__init__.py +0 -0
- {pylqt-1.0.dev1/src → pylqt-1.0.dev2/src/pyLQT}/lesion_metrics/network/metrics.py +0 -0
- {pylqt-1.0.dev1/src → pylqt-1.0.dev2/src/pyLQT}/lesion_metrics/network/utils.py +0 -0
- {pylqt-1.0.dev1/src → pylqt-1.0.dev2/src/pyLQT}/lesion_metrics/utils/__init__.py +0 -0
- {pylqt-1.0.dev1/src → pylqt-1.0.dev2/src/pyLQT}/lesion_metrics/utils/configs.py +0 -0
- {pylqt-1.0.dev1/src → pylqt-1.0.dev2/src/pyLQT}/lesion_metrics/white_matter/__init__.py +0 -0
- {pylqt-1.0.dev1/src → pylqt-1.0.dev2/src/pyLQT}/lesion_metrics/white_matter/metrics.py +0 -0
- {pylqt-1.0.dev1/src → pylqt-1.0.dev2/src/pyLQT}/lesion_metrics/white_matter/utils.py +0 -0
- {pylqt-1.0.dev1 → pylqt-1.0.dev2}/src/pyLQT.egg-info/dependency_links.txt +0 -0
pylqt-1.0.dev2/PKG-INFO
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyLQT
|
|
3
|
+
Version: 1.0.dev2
|
|
4
|
+
Summary: Python version of LQT from Griffis et al. 2021 (https://www.sciencedirect.com/science/article/pii/S2213158221000838)
|
|
5
|
+
Author-email: Antonin HUDRY <hudryantoninm@gmail.com>
|
|
6
|
+
License-Expression: GPL-3.0-only
|
|
7
|
+
Keywords: LQT,lqt,lesion,brain,
|
|
8
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
9
|
+
Classifier: Intended Audience :: Science/Research
|
|
10
|
+
Classifier: Intended Audience :: Healthcare Industry
|
|
11
|
+
Classifier: Programming Language :: Python
|
|
12
|
+
Requires-Python: >=3.10
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: numpy<2.0
|
|
16
|
+
Requires-Dist: nibabel>5.0
|
|
17
|
+
Requires-Dist: pandas>3.0
|
|
18
|
+
Requires-Dist: scipy>1.15
|
|
19
|
+
Requires-Dist: requests>2.0
|
|
20
|
+
Requires-Dist: dipy>1.10
|
|
21
|
+
Requires-Dist: templateflow
|
|
22
|
+
Requires-Dist: networkx>3.6.1
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# pyLQT
|
|
26
|
+
|
|
27
|
+
pyLQT, standing for “Python Lesion Quantification Toolkit”, is a toolbox designed for analysis brain-lesioned patients scans with minimal resources, regrouping several metrics for lesion quantification. It is a sucessor to LQT [[1]](#ref1) which was originally developped on MATLAB and remastered on R [[2]](#ref2).
|
|
28
|
+
|
|
29
|
+
The metrics are divided into three main domains:
|
|
30
|
+
|
|
31
|
+
* **Grey matter:** lesion effects on grey-matter regions and parcels.
|
|
32
|
+
* **White matter:** lesion effects on white-matter tracts and streamlines.
|
|
33
|
+
* **Network:** lesion effects on structural or functional brain networks.
|
|
34
|
+
|
|
35
|
+
## installation
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pip install pyLQT
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Running pyLQT
|
|
42
|
+
|
|
43
|
+
### Configuration files
|
|
44
|
+
|
|
45
|
+
pyLQT uses three JSON configuration files to define the lesion cohort, atlas, and tractography dataset. Each file specifies the relevant data paths and reference space. For the simplest usage, only the lesion cohort configuration file is required, in which case the atlas and tractogram files are automatically downloaded.
|
|
46
|
+
|
|
47
|
+
##### Lesion configuration
|
|
48
|
+
|
|
49
|
+
Defines the lesion cohort, the folder containing the lesion NIfTI files, and their reference space.
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"cohort_name": "ExampleCohort",
|
|
54
|
+
"lesion_folder": "lesions",
|
|
55
|
+
"space": "MNI152NLin6Asym"
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
##### Atlas configuration
|
|
60
|
+
|
|
61
|
+
Specifies the atlas NIfTI file, its corresponding label CSV, and its reference space. The CSV must contain a `Parcel` column with parcel indices matching the atlas NIfTI and a `Label` column with the corresponding parcel names.
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"name": "glasser360",
|
|
66
|
+
"atlas": "glasser360.nii.gz",
|
|
67
|
+
"atlas_labels": "glasser360_labels.csv",
|
|
68
|
+
"space": "MNI152NLin2009cAsym"
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
##### Tractography configuration
|
|
73
|
+
|
|
74
|
+
Specifies the tractography dataset, the folder containing its `.trk` files, the folder containing its reference NIfTI files, and its reference space.
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"name": "HCP1065",
|
|
79
|
+
"tracts": "hcp1065_avg_tracts_trk",
|
|
80
|
+
"references": "hcp1065_avg_tracts",
|
|
81
|
+
"space": "MNI152NLin2009aAsym"
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Notes:**
|
|
86
|
+
- All paths are relative to the corresponding configuration file.
|
|
87
|
+
- NIfTI files can be uncompressed (`.nii`) or gzipped (`.nii.gz`).
|
|
88
|
+
- The `space` field can specify either a standard space supported by TemplateFlow (e.g., `MNI152NLin2009cAsym`) or a relative path to a reference NIfTI file (`.nii` or `.nii.gz`).
|
|
89
|
+
- All paths and names above are examples and should be adapted to your dataset.
|
|
90
|
+
|
|
91
|
+
### basic use
|
|
92
|
+
|
|
93
|
+
Below is the simplest usage that only requires the [lesion cohort configuration file](#lesion-configuration). By default, the Glasser360 atlas and the HCP1065 tractogram are downloaded if not provided in the arguments.
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
pyLQT --lesion_cfg <path/to/lesion_config> --out_folder <path/to/outputs>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
| Argument | Default | Options / Range | Description |
|
|
101
|
+
|---|---|---|---|
|
|
102
|
+
| `--lesion_cfg` | — | Path to a `.json` file | Path to the lesion cohort configuration file. |
|
|
103
|
+
| `--atlas_cfg` | `None` | Path to a `.json` file or `None` | Path to the atlas configuration file. |
|
|
104
|
+
| `--tracts_cfg` | `None` | Path to a `.json` file or `None` | Path to the tracts configuration file. |
|
|
105
|
+
| `--out_folder` | — | Path to a directory | Path to the output folder. |
|
|
106
|
+
| `--registration_type` | `syn` | `syn`, `affine` | Registration type used to transform the lesion and atlas from their respective spaces to tract space. |
|
|
107
|
+
| `--spared_threshold` | `0.5` | Float between `0` and `1` | Threshold used to define spared parcel-to-parcel connectivity. |
|
|
108
|
+
| `--delete_tmp` | `True` | `True`, `False` | Whether to delete temporary files generated during processing. |
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
## Dependencies
|
|
112
|
+
|
|
113
|
+
pyLQT relies on the following libraries:
|
|
114
|
+
- `numpy`
|
|
115
|
+
- `nibabel`
|
|
116
|
+
- `pandas`
|
|
117
|
+
- `scipy`
|
|
118
|
+
- `requests`
|
|
119
|
+
- `dipy`
|
|
120
|
+
- `templateflow`
|
|
121
|
+
- `networkx`
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
## Links
|
|
125
|
+
|
|
126
|
+
- [Source](https://github.com/AntoninHUDRY/pyLQT)
|
|
127
|
+
- [documentation]() [TODO, deploy via github]
|
|
128
|
+
- [PyPI](https://pypi.org/project/pyLQT/)
|
|
129
|
+
|
|
130
|
+
## References
|
|
131
|
+
|
|
132
|
+
<a id="ref1"></a>
|
|
133
|
+
[1] Griffis et al. (2021). [Lesion Quantification Toolkit: A MATLAB software tool for estimating grey matter damage and white matter disconnections in patients with focal brain lesions](https://doi.org/10.1016/j.nicl.2021.102639). *NeuroImage: Clinical*.
|
|
134
|
+
|
|
135
|
+
<a id="ref2"></a>
|
|
136
|
+
[2] Dworkin Jordan (https://github.com/jdwor/LQT)
|
pylqt-1.0.dev2/README.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# pyLQT
|
|
2
|
+
|
|
3
|
+
pyLQT, standing for “Python Lesion Quantification Toolkit”, is a toolbox designed for analysis brain-lesioned patients scans with minimal resources, regrouping several metrics for lesion quantification. It is a sucessor to LQT [[1]](#ref1) which was originally developped on MATLAB and remastered on R [[2]](#ref2).
|
|
4
|
+
|
|
5
|
+
The metrics are divided into three main domains:
|
|
6
|
+
|
|
7
|
+
* **Grey matter:** lesion effects on grey-matter regions and parcels.
|
|
8
|
+
* **White matter:** lesion effects on white-matter tracts and streamlines.
|
|
9
|
+
* **Network:** lesion effects on structural or functional brain networks.
|
|
10
|
+
|
|
11
|
+
## installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install pyLQT
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Running pyLQT
|
|
18
|
+
|
|
19
|
+
### Configuration files
|
|
20
|
+
|
|
21
|
+
pyLQT uses three JSON configuration files to define the lesion cohort, atlas, and tractography dataset. Each file specifies the relevant data paths and reference space. For the simplest usage, only the lesion cohort configuration file is required, in which case the atlas and tractogram files are automatically downloaded.
|
|
22
|
+
|
|
23
|
+
##### Lesion configuration
|
|
24
|
+
|
|
25
|
+
Defines the lesion cohort, the folder containing the lesion NIfTI files, and their reference space.
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"cohort_name": "ExampleCohort",
|
|
30
|
+
"lesion_folder": "lesions",
|
|
31
|
+
"space": "MNI152NLin6Asym"
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
##### Atlas configuration
|
|
36
|
+
|
|
37
|
+
Specifies the atlas NIfTI file, its corresponding label CSV, and its reference space. The CSV must contain a `Parcel` column with parcel indices matching the atlas NIfTI and a `Label` column with the corresponding parcel names.
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"name": "glasser360",
|
|
42
|
+
"atlas": "glasser360.nii.gz",
|
|
43
|
+
"atlas_labels": "glasser360_labels.csv",
|
|
44
|
+
"space": "MNI152NLin2009cAsym"
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
##### Tractography configuration
|
|
49
|
+
|
|
50
|
+
Specifies the tractography dataset, the folder containing its `.trk` files, the folder containing its reference NIfTI files, and its reference space.
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"name": "HCP1065",
|
|
55
|
+
"tracts": "hcp1065_avg_tracts_trk",
|
|
56
|
+
"references": "hcp1065_avg_tracts",
|
|
57
|
+
"space": "MNI152NLin2009aAsym"
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Notes:**
|
|
62
|
+
- All paths are relative to the corresponding configuration file.
|
|
63
|
+
- NIfTI files can be uncompressed (`.nii`) or gzipped (`.nii.gz`).
|
|
64
|
+
- The `space` field can specify either a standard space supported by TemplateFlow (e.g., `MNI152NLin2009cAsym`) or a relative path to a reference NIfTI file (`.nii` or `.nii.gz`).
|
|
65
|
+
- All paths and names above are examples and should be adapted to your dataset.
|
|
66
|
+
|
|
67
|
+
### basic use
|
|
68
|
+
|
|
69
|
+
Below is the simplest usage that only requires the [lesion cohort configuration file](#lesion-configuration). By default, the Glasser360 atlas and the HCP1065 tractogram are downloaded if not provided in the arguments.
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pyLQT --lesion_cfg <path/to/lesion_config> --out_folder <path/to/outputs>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
| Argument | Default | Options / Range | Description |
|
|
77
|
+
|---|---|---|---|
|
|
78
|
+
| `--lesion_cfg` | — | Path to a `.json` file | Path to the lesion cohort configuration file. |
|
|
79
|
+
| `--atlas_cfg` | `None` | Path to a `.json` file or `None` | Path to the atlas configuration file. |
|
|
80
|
+
| `--tracts_cfg` | `None` | Path to a `.json` file or `None` | Path to the tracts configuration file. |
|
|
81
|
+
| `--out_folder` | — | Path to a directory | Path to the output folder. |
|
|
82
|
+
| `--registration_type` | `syn` | `syn`, `affine` | Registration type used to transform the lesion and atlas from their respective spaces to tract space. |
|
|
83
|
+
| `--spared_threshold` | `0.5` | Float between `0` and `1` | Threshold used to define spared parcel-to-parcel connectivity. |
|
|
84
|
+
| `--delete_tmp` | `True` | `True`, `False` | Whether to delete temporary files generated during processing. |
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
## Dependencies
|
|
88
|
+
|
|
89
|
+
pyLQT relies on the following libraries:
|
|
90
|
+
- `numpy`
|
|
91
|
+
- `nibabel`
|
|
92
|
+
- `pandas`
|
|
93
|
+
- `scipy`
|
|
94
|
+
- `requests`
|
|
95
|
+
- `dipy`
|
|
96
|
+
- `templateflow`
|
|
97
|
+
- `networkx`
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
## Links
|
|
101
|
+
|
|
102
|
+
- [Source](https://github.com/AntoninHUDRY/pyLQT)
|
|
103
|
+
- [documentation]() [TODO, deploy via github]
|
|
104
|
+
- [PyPI](https://pypi.org/project/pyLQT/)
|
|
105
|
+
|
|
106
|
+
## References
|
|
107
|
+
|
|
108
|
+
<a id="ref1"></a>
|
|
109
|
+
[1] Griffis et al. (2021). [Lesion Quantification Toolkit: A MATLAB software tool for estimating grey matter damage and white matter disconnections in patients with focal brain lesions](https://doi.org/10.1016/j.nicl.2021.102639). *NeuroImage: Clinical*.
|
|
110
|
+
|
|
111
|
+
<a id="ref2"></a>
|
|
112
|
+
[2] Dworkin Jordan (https://github.com/jdwor/LQT)
|
|
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pyLQT"
|
|
7
7
|
keywords = ["LQT", "lqt", "lesion", "brain", ""]
|
|
8
|
-
version = "1.0.
|
|
8
|
+
version = "1.0.dev2"
|
|
9
9
|
authors = [
|
|
10
10
|
{name="Antonin HUDRY", email="hudryantoninm@gmail.com"},
|
|
11
11
|
]
|
|
@@ -28,17 +28,18 @@ dependencies = [
|
|
|
28
28
|
"requests>2.0",
|
|
29
29
|
"dipy>1.10",
|
|
30
30
|
"templateflow",
|
|
31
|
+
"networkx>3.6.1",
|
|
31
32
|
]
|
|
32
33
|
|
|
33
34
|
license = "GPL-3.0-only"
|
|
34
35
|
license-files = ["LICEN[CS]E*"]
|
|
35
36
|
|
|
36
37
|
[project.scripts]
|
|
37
|
-
pyLQT = "
|
|
38
|
+
pyLQT = "pyLQT.cli:main"
|
|
38
39
|
|
|
39
40
|
[tool.setuptools]
|
|
40
41
|
package-dir = {"" = "src"}
|
|
41
|
-
py-modules = ["
|
|
42
|
+
py-modules = ["pyLQT"]
|
|
42
43
|
|
|
43
44
|
[tool.setuptools.packages.find]
|
|
44
45
|
where = ["src"]
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
|
|
3
|
+
from pipeline import run_pyLQT
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def main():
|
|
7
|
+
"""Run the pyLQT pipeline through the command-line interface."""
|
|
8
|
+
|
|
9
|
+
parser = argparse.ArgumentParser(
|
|
10
|
+
prog="pyLQT",
|
|
11
|
+
description="Run the pyLQT lesion quantification pipeline."
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
parser.add_argument(
|
|
15
|
+
"--lesion_cfg",
|
|
16
|
+
required=True,
|
|
17
|
+
help='[Path] Path to lesion config'
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
parser.add_argument(
|
|
21
|
+
"--atlas_cfg",
|
|
22
|
+
default=None,
|
|
23
|
+
help='[Path, optional] Path to atlas config. If none provided, a default atlas is downloaded.'
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
parser.add_argument(
|
|
27
|
+
"--tracts_cfg",
|
|
28
|
+
default=None,
|
|
29
|
+
help='[Path, optional] Path to tracts config. If none provided, default tracts are downloaded.'
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
parser.add_argument(
|
|
33
|
+
"--out_folder",
|
|
34
|
+
required=True,
|
|
35
|
+
help='[Path] Output folder path'
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
parser.add_argument(
|
|
39
|
+
"--registration_type",
|
|
40
|
+
choices=['affine', 'syn'],
|
|
41
|
+
default='syn',
|
|
42
|
+
help='[str, default=syn] Registration type, from lesion space and atlas space to tract space'
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
parser.add_argument(
|
|
46
|
+
"--spared_threshold",
|
|
47
|
+
default=0.5,
|
|
48
|
+
help='[float (0,1), default=0.5] Defines threshold for spared parcel-to-parcel connectivity'
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
parser.add_argument(
|
|
52
|
+
"--delete_tmp",
|
|
53
|
+
default=False,
|
|
54
|
+
help='[bool, default=False] Delete temporary folder'
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
args = parser.parse_args()
|
|
58
|
+
|
|
59
|
+
run_pyLQT(
|
|
60
|
+
lesion_cfg=args.lesion_cfg,
|
|
61
|
+
atlas_cfg=args.atlas_cfg,
|
|
62
|
+
tracts_cfg=args.tracts_cfg,
|
|
63
|
+
out_folder=args.out_folder,
|
|
64
|
+
registration_type=args.registration_type,
|
|
65
|
+
spared_threshold=args.spared_threshold,
|
|
66
|
+
delete_tmp=args.delete_tmp,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
if __name__ == "__main__":
|
|
71
|
+
main()
|
|
@@ -14,7 +14,7 @@ def get_parcel_damage(
|
|
|
14
14
|
):
|
|
15
15
|
"""Compute lesion damage for each parcel of an atlas.
|
|
16
16
|
|
|
17
|
-
The lesion is resampled to the atlas
|
|
17
|
+
The lesion is resampled to the atlas grid, and the proportion of
|
|
18
18
|
each parcel overlapping with the lesion is computed. A parcel damage
|
|
19
19
|
map is created, where each parcel voxel is assigned the damage proportion
|
|
20
20
|
of its parcel.
|
|
@@ -6,6 +6,7 @@ import shutil
|
|
|
6
6
|
import gzip
|
|
7
7
|
import nibabel as nib
|
|
8
8
|
import numpy as np
|
|
9
|
+
import pandas as pd
|
|
9
10
|
|
|
10
11
|
from templateflow import api as tf
|
|
11
12
|
from pathlib import Path
|
|
@@ -135,7 +136,72 @@ def uncompress_trk_gz(
|
|
|
135
136
|
|
|
136
137
|
return out_path
|
|
137
138
|
|
|
138
|
-
def
|
|
139
|
+
def default_atlas_download(out_folder: Path):
|
|
140
|
+
atlas_cfg_folder = out_folder / "glasser360_config"
|
|
141
|
+
atlas_cfg_folder.mkdir(parents=True, exist_ok=True)
|
|
142
|
+
|
|
143
|
+
atlas_path = atlas_cfg_folder / "glasser360_MNI152NLin2009cAsym.nii.gz"
|
|
144
|
+
atlas_labels_path = atlas_cfg_folder / "glasser360_labels.csv"
|
|
145
|
+
atlas_labels_path_txt = atlas_labels_path.with_suffix(".txt")
|
|
146
|
+
atlas_cfg_path = atlas_cfg_folder / "glasser360_config.json"
|
|
147
|
+
|
|
148
|
+
if atlas_path.exists():
|
|
149
|
+
warnings.warn(
|
|
150
|
+
f"atlas already exists, using it: {atlas_path}"
|
|
151
|
+
)
|
|
152
|
+
else:
|
|
153
|
+
url_atlas = "https://ndownloader.figshare.com/files/43043653"
|
|
154
|
+
|
|
155
|
+
response = requests.get(url_atlas, stream=True, timeout=60)
|
|
156
|
+
response.raise_for_status()
|
|
157
|
+
|
|
158
|
+
with atlas_path.open("wb") as f:
|
|
159
|
+
for chunk in response.iter_content(chunk_size=1024*1024):
|
|
160
|
+
if chunk:
|
|
161
|
+
f.write(chunk)
|
|
162
|
+
|
|
163
|
+
if atlas_labels_path.exists():
|
|
164
|
+
warnings.warn(
|
|
165
|
+
f"atlas labels already exist, using it: {atlas_labels_path}"
|
|
166
|
+
)
|
|
167
|
+
else:
|
|
168
|
+
url_labels = "https://ndownloader.figshare.com/files/43041079"
|
|
169
|
+
|
|
170
|
+
response = requests.get(url_labels, stream=True, timeout=60)
|
|
171
|
+
response.raise_for_status()
|
|
172
|
+
|
|
173
|
+
with atlas_labels_path_txt.open("wb") as f:
|
|
174
|
+
for chunk in response.iter_content(chunk_size=1024*1024):
|
|
175
|
+
if chunk:
|
|
176
|
+
f.write(chunk)
|
|
177
|
+
|
|
178
|
+
with open(atlas_labels_path_txt, "r") as f:
|
|
179
|
+
labels = [line.strip() for line in f if line.strip()]
|
|
180
|
+
|
|
181
|
+
atlas_labels = pd.DataFrame({
|
|
182
|
+
"Parcel": range(1, len(labels) + 1),
|
|
183
|
+
"Label": labels
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
atlas_labels.to_csv(atlas_labels_path, index=False)
|
|
187
|
+
atlas_labels_path_txt.unlink()
|
|
188
|
+
|
|
189
|
+
config = {
|
|
190
|
+
"name": "glasser360",
|
|
191
|
+
"atlas": "glasser360_MNI152NLin2009cAsym.nii.gz",
|
|
192
|
+
"atlas_labels": "glasser360_labels.csv",
|
|
193
|
+
"space": "MNI152NLin2009cAsym"
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
atlas_cfg = Path(atlas_cfg_folder / "glasser360_config.json")
|
|
197
|
+
|
|
198
|
+
with open(atlas_cfg, "w") as f:
|
|
199
|
+
json.dump(config, f, indent=4)
|
|
200
|
+
|
|
201
|
+
return atlas_cfg
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def default_tracts_download(out_folder: Path):
|
|
139
205
|
"""Download the default HCP1065 tractography dataset and create its configuration.
|
|
140
206
|
|
|
141
207
|
The function downloads the HCP1065 average tractograms and their
|
|
@@ -162,7 +228,9 @@ def default_download(out_folder: Path):
|
|
|
162
228
|
|
|
163
229
|
if tracts_folder.exists():
|
|
164
230
|
warnings.warn(
|
|
165
|
-
f"Tracts folder already exists, using it: {tracts_folder}"
|
|
231
|
+
f"Tracts folder already exists, using it: {tracts_folder}",
|
|
232
|
+
UserWarning,
|
|
233
|
+
stacklevel=2
|
|
166
234
|
)
|
|
167
235
|
else:
|
|
168
236
|
url = "https://github.com/data-others/atlas/releases/download/hcp1065/hcp1065_avg_tracts_trk.zip"
|
|
@@ -185,7 +253,9 @@ def default_download(out_folder: Path):
|
|
|
185
253
|
|
|
186
254
|
if references_folder.exists():
|
|
187
255
|
warnings.warn(
|
|
188
|
-
f"References folder already exists, using it: {references_folder}"
|
|
256
|
+
f"References folder already exists, using it: {references_folder}",
|
|
257
|
+
UserWarning,
|
|
258
|
+
stacklevel=2
|
|
189
259
|
)
|
|
190
260
|
else:
|
|
191
261
|
url = "https://github.com/data-others/atlas/releases/download/hcp1065/hcp1065_avg_tracts_nifti.zip"
|
|
@@ -200,14 +270,13 @@ def default_download(out_folder: Path):
|
|
|
200
270
|
f.write(chunk)
|
|
201
271
|
|
|
202
272
|
with zipfile.ZipFile(zip_path) as zip_file:
|
|
203
|
-
zip_file.extractall(
|
|
273
|
+
zip_file.extractall(tracts_cfg_folder)
|
|
204
274
|
|
|
205
275
|
zip_path.unlink()
|
|
206
276
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
)
|
|
277
|
+
extracted_niftis = tracts_cfg_folder / "nifti"
|
|
278
|
+
if extracted_niftis.exists():
|
|
279
|
+
extracted_niftis.rename(references_folder)
|
|
211
280
|
|
|
212
281
|
tracts_name = "HCP1065"
|
|
213
282
|
tracts_space = "MNI152NLin2009aAsym"
|
|
@@ -247,4 +316,8 @@ def get_ref_space_tf(space: str, res: int = 1):
|
|
|
247
316
|
ref_space_volume[brain_mask.get_fdata() <= 0] = 0
|
|
248
317
|
ref_space = nib.Nifti1Image(ref_space_volume, t1w_ref.affine, t1w_ref.header)
|
|
249
318
|
|
|
250
|
-
return ref_space
|
|
319
|
+
return ref_space
|
|
320
|
+
|
|
321
|
+
if __name__=="__main__":
|
|
322
|
+
|
|
323
|
+
default_atlas_download(Path("D:/internship_myspace_lab/pyLQT/test_download_atlas"))
|
|
@@ -26,14 +26,18 @@ def register_affine(
|
|
|
26
26
|
AffineMap
|
|
27
27
|
Affine mapping from the moving image space to the static image space.
|
|
28
28
|
"""
|
|
29
|
-
|
|
29
|
+
|
|
30
|
+
moving_data = moving.get_fdata()
|
|
31
|
+
static_data = static.get_fdata()
|
|
32
|
+
|
|
33
|
+
metric = MutualInformationMetric(nbins=32, sampling_proportion=0.2)
|
|
30
34
|
|
|
31
|
-
affreg = AffineRegistration(metric=metric)
|
|
35
|
+
affreg = AffineRegistration(metric=metric, level_iters=[500, 250, 100])
|
|
32
36
|
|
|
33
37
|
transform = TranslationTransform3D()
|
|
34
38
|
translation = affreg.optimize(
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
static_data,
|
|
40
|
+
moving_data,
|
|
37
41
|
transform,
|
|
38
42
|
params0=None,
|
|
39
43
|
static_grid2world=static.affine,
|
|
@@ -42,8 +46,8 @@ def register_affine(
|
|
|
42
46
|
|
|
43
47
|
transform = RigidTransform3D()
|
|
44
48
|
rigid = affreg.optimize(
|
|
45
|
-
|
|
46
|
-
|
|
49
|
+
static_data,
|
|
50
|
+
moving_data,
|
|
47
51
|
transform,
|
|
48
52
|
starting_affine=translation.affine,
|
|
49
53
|
params0=None,
|
|
@@ -53,8 +57,8 @@ def register_affine(
|
|
|
53
57
|
|
|
54
58
|
transform = AffineTransform3D()
|
|
55
59
|
mapping = affreg.optimize(
|
|
56
|
-
|
|
57
|
-
|
|
60
|
+
static_data,
|
|
61
|
+
moving_data,
|
|
58
62
|
transform,
|
|
59
63
|
starting_affine=rigid.affine,
|
|
60
64
|
params0=None,
|
|
@@ -93,7 +97,7 @@ def register_syn(
|
|
|
93
97
|
"""
|
|
94
98
|
metric = CCMetric(dim=3)
|
|
95
99
|
|
|
96
|
-
syn = SymmetricDiffeomorphicRegistration(metric)
|
|
100
|
+
syn = SymmetricDiffeomorphicRegistration(metric, level_iters=[20, 10, 5])
|
|
97
101
|
|
|
98
102
|
mapping = syn.optimize(static.get_fdata(),
|
|
99
103
|
moving.get_fdata(),
|