junifer 0.0.6.dev422__py3-none-any.whl → 0.0.6.dev459__py3-none-any.whl
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.
- junifer/_version.py +2 -2
- junifer/cli/tests/test_cli_utils.py +1 -2
- junifer/data/coordinates/_coordinates.py +123 -104
- junifer/data/coordinates/tests/test_coordinates.py +1 -2
- junifer/data/masks/_masks.py +74 -58
- junifer/data/parcellations/_parcellations.py +238 -684
- junifer/data/parcellations/tests/test_parcellations.py +66 -213
- junifer/data/template_spaces.py +15 -89
- junifer/data/utils.py +28 -2
- junifer/typing/_typing.py +1 -1
- {junifer-0.0.6.dev422.dist-info → junifer-0.0.6.dev459.dist-info}/METADATA +2 -2
- {junifer-0.0.6.dev422.dist-info → junifer-0.0.6.dev459.dist-info}/RECORD +17 -17
- {junifer-0.0.6.dev422.dist-info → junifer-0.0.6.dev459.dist-info}/AUTHORS.rst +0 -0
- {junifer-0.0.6.dev422.dist-info → junifer-0.0.6.dev459.dist-info}/LICENSE.md +0 -0
- {junifer-0.0.6.dev422.dist-info → junifer-0.0.6.dev459.dist-info}/WHEEL +0 -0
- {junifer-0.0.6.dev422.dist-info → junifer-0.0.6.dev459.dist-info}/entry_points.txt +0 -0
- {junifer-0.0.6.dev422.dist-info → junifer-0.0.6.dev459.dist-info}/top_level.txt +0 -0
@@ -5,26 +5,25 @@
|
|
5
5
|
# Synchon Mandal <s.mandal@fz-juelich.de>
|
6
6
|
# License: AGPL
|
7
7
|
|
8
|
-
import io
|
9
|
-
import shutil
|
10
|
-
import tarfile
|
11
|
-
import tempfile
|
12
|
-
import zipfile
|
13
8
|
from itertools import product
|
14
9
|
from pathlib import Path
|
15
10
|
from typing import TYPE_CHECKING, Any, Optional, Union
|
16
11
|
|
17
|
-
import httpx
|
18
12
|
import nibabel as nib
|
19
13
|
import nilearn.image as nimg
|
20
14
|
import numpy as np
|
21
15
|
import pandas as pd
|
22
|
-
from
|
16
|
+
from junifer_data import get
|
23
17
|
|
24
18
|
from ...utils import logger, raise_error, warn_with_log
|
25
19
|
from ...utils.singleton import Singleton
|
26
20
|
from ..pipeline_data_registry_base import BasePipelineDataRegistry
|
27
|
-
from ..utils import
|
21
|
+
from ..utils import (
|
22
|
+
JUNIFER_DATA_VERSION,
|
23
|
+
closest_resolution,
|
24
|
+
get_dataset_path,
|
25
|
+
get_native_warper,
|
26
|
+
)
|
28
27
|
from ._ants_parcellation_warper import ANTsParcellationWarper
|
29
28
|
from ._fsl_parcellation_warper import FSLParcellationWarper
|
30
29
|
|
@@ -49,6 +48,7 @@ class ParcellationRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
49
48
|
|
50
49
|
def __init__(self) -> None:
|
51
50
|
"""Initialize the class."""
|
51
|
+
super().__init__()
|
52
52
|
# Each entry in registry is a dictionary that must contain at least
|
53
53
|
# the following keys:
|
54
54
|
# * 'family': the parcellation's family name (e.g., 'Schaefer', 'SUIT')
|
@@ -56,6 +56,8 @@ class ParcellationRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
56
56
|
# and can also have optional key(s):
|
57
57
|
# * 'valid_resolutions': a list of valid resolutions for the
|
58
58
|
# parcellation (e.g., [1, 2])
|
59
|
+
# The built-in coordinates are files that are shipped with the
|
60
|
+
# junifer-data dataset.
|
59
61
|
# Make built-in and external dictionaries for validation later
|
60
62
|
self._builtin = {}
|
61
63
|
self._external = {}
|
@@ -63,8 +65,14 @@ class ParcellationRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
63
65
|
# Add SUIT
|
64
66
|
self._builtin.update(
|
65
67
|
{
|
66
|
-
"SUITxSUIT": {
|
67
|
-
|
68
|
+
"SUITxSUIT": {
|
69
|
+
"family": "SUIT",
|
70
|
+
"space": "SUIT",
|
71
|
+
},
|
72
|
+
"SUITxMNI": {
|
73
|
+
"family": "SUIT",
|
74
|
+
"space": "MNI152NLin6Asym",
|
75
|
+
},
|
68
76
|
}
|
69
77
|
)
|
70
78
|
# Add Schaefer
|
@@ -72,7 +80,7 @@ class ParcellationRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
72
80
|
self._builtin.update(
|
73
81
|
{
|
74
82
|
f"Schaefer{n_rois}x{t_net}": {
|
75
|
-
"family": "
|
83
|
+
"family": "Schaefer2018",
|
76
84
|
"n_rois": n_rois,
|
77
85
|
"yeo_networks": t_net,
|
78
86
|
"space": "MNI152NLin6Asym",
|
@@ -84,19 +92,19 @@ class ParcellationRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
84
92
|
self._builtin.update(
|
85
93
|
{
|
86
94
|
f"TianxS{scale}x7TxMNI6thgeneration": {
|
87
|
-
"family": "
|
95
|
+
"family": "Melbourne",
|
88
96
|
"scale": scale,
|
89
97
|
"magneticfield": "7T",
|
90
98
|
"space": "MNI152NLin6Asym",
|
91
99
|
},
|
92
100
|
f"TianxS{scale}x3TxMNI6thgeneration": {
|
93
|
-
"family": "
|
101
|
+
"family": "Melbourne",
|
94
102
|
"scale": scale,
|
95
103
|
"magneticfield": "3T",
|
96
104
|
"space": "MNI152NLin6Asym",
|
97
105
|
},
|
98
106
|
f"TianxS{scale}x3TxMNInonlinear2009cAsym": {
|
99
|
-
"family": "
|
107
|
+
"family": "Melbourne",
|
100
108
|
"scale": scale,
|
101
109
|
"magneticfield": "3T",
|
102
110
|
"space": "MNI152NLin2009cAsym",
|
@@ -155,7 +163,7 @@ class ParcellationRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
155
163
|
self._builtin.update(
|
156
164
|
{
|
157
165
|
f"Yan{n_rois}xYeo{yeo_network}": {
|
158
|
-
"family": "
|
166
|
+
"family": "Yan2023",
|
159
167
|
"n_rois": n_rois,
|
160
168
|
"yeo_networks": yeo_network,
|
161
169
|
"space": "MNI152NLin6Asym",
|
@@ -165,7 +173,7 @@ class ParcellationRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
165
173
|
self._builtin.update(
|
166
174
|
{
|
167
175
|
f"Yan{n_rois}xKong17": {
|
168
|
-
"family": "
|
176
|
+
"family": "Yan2023",
|
169
177
|
"n_rois": n_rois,
|
170
178
|
"kong_networks": 17,
|
171
179
|
"space": "MNI152NLin6Asym",
|
@@ -184,8 +192,8 @@ class ParcellationRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
184
192
|
}
|
185
193
|
)
|
186
194
|
|
187
|
-
#
|
188
|
-
self._registry
|
195
|
+
# Update registry with built-in ones
|
196
|
+
self._registry.update(self._builtin)
|
189
197
|
|
190
198
|
def register(
|
191
199
|
self,
|
@@ -214,20 +222,21 @@ class ParcellationRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
214
222
|
Raises
|
215
223
|
------
|
216
224
|
ValueError
|
217
|
-
If the parcellation ``name`` is
|
218
|
-
``
|
219
|
-
|
225
|
+
If the parcellation ``name`` is a built-in parcellation or
|
226
|
+
if the parcellation ``name`` is already registered and
|
227
|
+
``overwrite=False``.
|
220
228
|
|
221
229
|
"""
|
222
230
|
# Check for attempt of overwriting built-in parcellations
|
223
231
|
if name in self._builtin:
|
232
|
+
raise_error(
|
233
|
+
f"Parcellation: {name} already registered as "
|
234
|
+
"built-in parcellation."
|
235
|
+
)
|
236
|
+
# Check for attempt of overwriting external parcellations
|
237
|
+
if name in self._external:
|
224
238
|
if overwrite:
|
225
239
|
logger.info(f"Overwriting parcellation: {name}")
|
226
|
-
if self._registry[name]["family"] != "CustomUserParcellation":
|
227
|
-
raise_error(
|
228
|
-
f"Parcellation: {name} already registered as "
|
229
|
-
"built-in parcellation."
|
230
|
-
)
|
231
240
|
else:
|
232
241
|
raise_error(
|
233
242
|
f"Parcellation: {name} already registered. Set "
|
@@ -236,6 +245,7 @@ class ParcellationRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
236
245
|
# Convert str to Path
|
237
246
|
if not isinstance(parcellation_path, Path):
|
238
247
|
parcellation_path = Path(parcellation_path)
|
248
|
+
# Registration
|
239
249
|
logger.info(f"Registering parcellation: {name}")
|
240
250
|
# Add user parcellation info
|
241
251
|
self._external[name] = {
|
@@ -271,24 +281,17 @@ class ParcellationRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
271
281
|
self,
|
272
282
|
name: str,
|
273
283
|
target_space: str,
|
274
|
-
parcellations_dir: Union[str, Path, None] = None,
|
275
284
|
resolution: Optional[float] = None,
|
276
285
|
path_only: bool = False,
|
277
286
|
) -> tuple[Optional["Nifti1Image"], list[str], Path, str]:
|
278
287
|
"""Load parcellation and labels.
|
279
288
|
|
280
|
-
If it is a built-in parcellation and the file is not present in the
|
281
|
-
``parcellations_dir`` directory, it will be downloaded.
|
282
|
-
|
283
289
|
Parameters
|
284
290
|
----------
|
285
291
|
name : str
|
286
292
|
The name of the parcellation.
|
287
293
|
target_space : str
|
288
294
|
The desired space of the parcellation.
|
289
|
-
parcellations_dir : str or pathlib.Path, optional
|
290
|
-
Path where the parcellations files are stored. The default location
|
291
|
-
is "$HOME/junifer/data/parcellations" (default None).
|
292
295
|
resolution : float, optional
|
293
296
|
The desired resolution of the parcellation to load. If it is not
|
294
297
|
available, the closest resolution will be loaded. Preferably, use a
|
@@ -312,6 +315,7 @@ class ParcellationRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
312
315
|
------
|
313
316
|
ValueError
|
314
317
|
If ``name`` is invalid or
|
318
|
+
if the parcellation family is invalid or
|
315
319
|
if the parcellation values and labels
|
316
320
|
don't have equal dimension or if the value range is invalid.
|
317
321
|
|
@@ -327,7 +331,7 @@ class ParcellationRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
327
331
|
parcellation_definition = self._registry[name].copy()
|
328
332
|
t_family = parcellation_definition.pop("family")
|
329
333
|
# Remove space conditionally
|
330
|
-
if t_family not in ["SUIT", "
|
334
|
+
if t_family not in ["SUIT", "Melbourne"]:
|
331
335
|
space = parcellation_definition.pop("space")
|
332
336
|
else:
|
333
337
|
space = parcellation_definition["space"]
|
@@ -342,15 +346,57 @@ class ParcellationRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
342
346
|
|
343
347
|
# Check if the parcellation family is custom or built-in
|
344
348
|
if t_family == "CustomUserParcellation":
|
345
|
-
parcellation_fname =
|
349
|
+
parcellation_fname = parcellation_definition["path"]
|
346
350
|
parcellation_labels = parcellation_definition["labels"]
|
351
|
+
elif t_family in [
|
352
|
+
"Schaefer2018",
|
353
|
+
"SUIT",
|
354
|
+
"Melbourne",
|
355
|
+
"AICHA",
|
356
|
+
"Shen",
|
357
|
+
"Yan2023",
|
358
|
+
"Brainnetome",
|
359
|
+
]:
|
360
|
+
# Load parcellation and labels
|
361
|
+
if t_family == "Schaefer2018":
|
362
|
+
parcellation_fname, parcellation_labels = _retrieve_schaefer(
|
363
|
+
resolution=resolution,
|
364
|
+
**parcellation_definition,
|
365
|
+
)
|
366
|
+
elif t_family == "SUIT":
|
367
|
+
parcellation_fname, parcellation_labels = _retrieve_suit(
|
368
|
+
resolution=resolution,
|
369
|
+
**parcellation_definition,
|
370
|
+
)
|
371
|
+
elif t_family == "Melbourne":
|
372
|
+
parcellation_fname, parcellation_labels = _retrieve_tian(
|
373
|
+
resolution=resolution,
|
374
|
+
**parcellation_definition,
|
375
|
+
)
|
376
|
+
elif t_family == "AICHA":
|
377
|
+
parcellation_fname, parcellation_labels = _retrieve_aicha(
|
378
|
+
resolution=resolution,
|
379
|
+
**parcellation_definition,
|
380
|
+
)
|
381
|
+
elif t_family == "Shen":
|
382
|
+
parcellation_fname, parcellation_labels = _retrieve_shen(
|
383
|
+
resolution=resolution,
|
384
|
+
**parcellation_definition,
|
385
|
+
)
|
386
|
+
elif t_family == "Yan2023":
|
387
|
+
parcellation_fname, parcellation_labels = _retrieve_yan(
|
388
|
+
resolution=resolution,
|
389
|
+
**parcellation_definition,
|
390
|
+
)
|
391
|
+
elif t_family == "Brainnetome":
|
392
|
+
parcellation_fname, parcellation_labels = (
|
393
|
+
_retrieve_brainnetome(
|
394
|
+
resolution=resolution,
|
395
|
+
**parcellation_definition,
|
396
|
+
)
|
397
|
+
)
|
347
398
|
else:
|
348
|
-
|
349
|
-
family=t_family,
|
350
|
-
parcellations_dir=parcellations_dir,
|
351
|
-
resolution=resolution,
|
352
|
-
**parcellation_definition,
|
353
|
-
)
|
399
|
+
raise_error(f"Unknown parcellation family: {t_family}")
|
354
400
|
|
355
401
|
# Load parcellation image and values
|
356
402
|
logger.info(f"Loading parcellation: {parcellation_fname.absolute()!s}")
|
@@ -529,152 +575,7 @@ class ParcellationRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
529
575
|
return resampled_parcellation_img, labels
|
530
576
|
|
531
577
|
|
532
|
-
def _retrieve_parcellation(
|
533
|
-
family: str,
|
534
|
-
parcellations_dir: Union[str, Path, None] = None,
|
535
|
-
resolution: Optional[float] = None,
|
536
|
-
**kwargs,
|
537
|
-
) -> tuple[Path, list[str]]:
|
538
|
-
"""Retrieve a brain parcellation object from nilearn or online source.
|
539
|
-
|
540
|
-
Only returns one parcellation per call. Call function multiple times for
|
541
|
-
different parameter specifications. Only retrieves parcellation if it is
|
542
|
-
not yet in parcellations_dir.
|
543
|
-
|
544
|
-
Parameters
|
545
|
-
----------
|
546
|
-
family : {"Schaefer", "SUIT", "Tian", "AICHA", "Shen", "Yan"}
|
547
|
-
The name of the parcellation family.
|
548
|
-
parcellations_dir : str or pathlib.Path, optional
|
549
|
-
Path where the retrieved parcellations file are stored. The default
|
550
|
-
location is "$HOME/junifer/data/parcellations" (default None).
|
551
|
-
resolution : float, optional
|
552
|
-
The desired resolution of the parcellation to load. If it is not
|
553
|
-
available, the closest resolution will be loaded. Preferably, use a
|
554
|
-
resolution higher than the desired one. By default, will load the
|
555
|
-
highest one (default None).
|
556
|
-
**kwargs
|
557
|
-
Use to specify parcellation-specific keyword arguments found in the
|
558
|
-
following section.
|
559
|
-
|
560
|
-
Other Parameters
|
561
|
-
----------------
|
562
|
-
* Schaefer :
|
563
|
-
``n_rois`` : {100, 200, 300, 400, 500, 600, 700, 800, 900, 1000}
|
564
|
-
Granularity of parcellation to be used.
|
565
|
-
``yeo_network`` : {7, 17}, optional
|
566
|
-
Number of Yeo networks to use (default 7).
|
567
|
-
* Tian :
|
568
|
-
``scale`` : {1, 2, 3, 4}
|
569
|
-
Scale of parcellation (defines granularity).
|
570
|
-
``space`` : {"MNI152NLin6Asym", "MNI152NLin2009cAsym"}, optional
|
571
|
-
Space of parcellation (default "MNI152NLin6Asym"). (For more
|
572
|
-
information see https://github.com/yetianmed/subcortex)
|
573
|
-
``magneticfield`` : {"3T", "7T"}, optional
|
574
|
-
Magnetic field (default "3T").
|
575
|
-
* SUIT :
|
576
|
-
``space`` : {"MNI152NLin6Asym", "SUIT"}, optional
|
577
|
-
Space of parcellation (default "MNI"). (For more information
|
578
|
-
see http://www.diedrichsenlab.org/imaging/suit.htm).
|
579
|
-
* AICHA :
|
580
|
-
``version`` : {1, 2}, optional
|
581
|
-
Version of parcellation (default 2).
|
582
|
-
* Shen :
|
583
|
-
``year`` : {2013, 2015, 2019}, optional
|
584
|
-
Year of the parcellation to use (default 2015).
|
585
|
-
``n_rois`` : int, optional
|
586
|
-
Number of ROIs to use. Can be ``50, 100, or 150`` for
|
587
|
-
``year = 2013`` but is fixed at ``268`` for ``year = 2015`` and at
|
588
|
-
``368`` for ``year = 2019``.
|
589
|
-
* Yan :
|
590
|
-
``n_rois`` : {100, 200, 300, 400, 500, 600, 700, 800, 900, 1000}
|
591
|
-
Granularity of the parcellation to be used.
|
592
|
-
``yeo_networks`` : {7, 17}, optional
|
593
|
-
Number of Yeo networks to use (default None).
|
594
|
-
``kong_networks`` : {17}, optional
|
595
|
-
Number of Kong networks to use (default None).
|
596
|
-
* Brainnetome :
|
597
|
-
``threshold`` : {0, 25, 50}
|
598
|
-
Threshold for the probabilistic maps of subregion.
|
599
|
-
|
600
|
-
Returns
|
601
|
-
-------
|
602
|
-
pathlib.Path
|
603
|
-
File path to the parcellation image.
|
604
|
-
list of str
|
605
|
-
Parcellation labels.
|
606
|
-
|
607
|
-
Raises
|
608
|
-
------
|
609
|
-
ValueError
|
610
|
-
If the parcellation's name is invalid.
|
611
|
-
|
612
|
-
"""
|
613
|
-
if parcellations_dir is None:
|
614
|
-
parcellations_dir = (
|
615
|
-
Path().home() / "junifer" / "data" / "parcellations"
|
616
|
-
)
|
617
|
-
# Create default junifer data directory if not present
|
618
|
-
parcellations_dir.mkdir(exist_ok=True, parents=True)
|
619
|
-
# Convert str to Path
|
620
|
-
elif not isinstance(parcellations_dir, Path):
|
621
|
-
parcellations_dir = Path(parcellations_dir)
|
622
|
-
|
623
|
-
logger.info(f"Fetching one of {family} parcellations.")
|
624
|
-
|
625
|
-
# Retrieval details per family
|
626
|
-
if family == "Schaefer":
|
627
|
-
parcellation_fname, parcellation_labels = _retrieve_schaefer(
|
628
|
-
parcellations_dir=parcellations_dir,
|
629
|
-
resolution=resolution,
|
630
|
-
**kwargs,
|
631
|
-
)
|
632
|
-
elif family == "SUIT":
|
633
|
-
parcellation_fname, parcellation_labels = _retrieve_suit(
|
634
|
-
parcellations_dir=parcellations_dir,
|
635
|
-
resolution=resolution,
|
636
|
-
**kwargs,
|
637
|
-
)
|
638
|
-
elif family == "Tian":
|
639
|
-
parcellation_fname, parcellation_labels = _retrieve_tian(
|
640
|
-
parcellations_dir=parcellations_dir,
|
641
|
-
resolution=resolution,
|
642
|
-
**kwargs,
|
643
|
-
)
|
644
|
-
elif family == "AICHA":
|
645
|
-
parcellation_fname, parcellation_labels = _retrieve_aicha(
|
646
|
-
parcellations_dir=parcellations_dir,
|
647
|
-
resolution=resolution,
|
648
|
-
**kwargs,
|
649
|
-
)
|
650
|
-
elif family == "Shen":
|
651
|
-
parcellation_fname, parcellation_labels = _retrieve_shen(
|
652
|
-
parcellations_dir=parcellations_dir,
|
653
|
-
resolution=resolution,
|
654
|
-
**kwargs,
|
655
|
-
)
|
656
|
-
elif family == "Yan":
|
657
|
-
parcellation_fname, parcellation_labels = _retrieve_yan(
|
658
|
-
parcellations_dir=parcellations_dir,
|
659
|
-
resolution=resolution,
|
660
|
-
**kwargs,
|
661
|
-
)
|
662
|
-
elif family == "Brainnetome":
|
663
|
-
parcellation_fname, parcellation_labels = _retrieve_brainnetome(
|
664
|
-
parcellations_dir=parcellations_dir,
|
665
|
-
resolution=resolution,
|
666
|
-
**kwargs,
|
667
|
-
)
|
668
|
-
else:
|
669
|
-
raise_error(
|
670
|
-
f"The provided parcellation name {family} cannot be retrieved."
|
671
|
-
)
|
672
|
-
|
673
|
-
return parcellation_fname, parcellation_labels
|
674
|
-
|
675
|
-
|
676
578
|
def _retrieve_schaefer(
|
677
|
-
parcellations_dir: Path,
|
678
579
|
resolution: Optional[float] = None,
|
679
580
|
n_rois: Optional[int] = None,
|
680
581
|
yeo_networks: int = 7,
|
@@ -683,8 +584,6 @@ def _retrieve_schaefer(
|
|
683
584
|
|
684
585
|
Parameters
|
685
586
|
----------
|
686
|
-
parcellations_dir : pathlib.Path
|
687
|
-
The path to the parcellation data directory.
|
688
587
|
resolution : float, optional
|
689
588
|
The desired resolution of the parcellation to load. If it is not
|
690
589
|
available, the closest resolution will be loaded. Preferably, use a
|
@@ -706,8 +605,7 @@ def _retrieve_schaefer(
|
|
706
605
|
Raises
|
707
606
|
------
|
708
607
|
ValueError
|
709
|
-
If invalid value is provided for ``n_rois`` or ``yeo_networks
|
710
|
-
there is a problem fetching the parcellation.
|
608
|
+
If invalid value is provided for ``n_rois`` or ``yeo_networks``.
|
711
609
|
|
712
610
|
"""
|
713
611
|
logger.info("Parcellation parameters:")
|
@@ -735,47 +633,33 @@ def _retrieve_schaefer(
|
|
735
633
|
_valid_resolutions = [1, 2]
|
736
634
|
resolution = closest_resolution(resolution, _valid_resolutions)
|
737
635
|
|
738
|
-
#
|
739
|
-
|
740
|
-
|
741
|
-
/ "
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
)
|
636
|
+
# Fetch file paths
|
637
|
+
path_prefix = Path("parcellations/Schaefer2018/Yeo2011")
|
638
|
+
parcellation_img_path = get(
|
639
|
+
file_path=path_prefix / f"Schaefer2018_{n_rois}Parcels_{yeo_networks}"
|
640
|
+
f"Networks_order_FSLMNI152_{resolution}mm.nii.gz",
|
641
|
+
dataset_path=get_dataset_path(),
|
642
|
+
tag=JUNIFER_DATA_VERSION,
|
746
643
|
)
|
747
|
-
|
748
|
-
|
749
|
-
/ "
|
750
|
-
|
644
|
+
parcellation_label_path = get(
|
645
|
+
file_path=path_prefix
|
646
|
+
/ f"Schaefer2018_{n_rois}Parcels_{yeo_networks}Networks_order.txt",
|
647
|
+
dataset_path=get_dataset_path(),
|
648
|
+
tag=JUNIFER_DATA_VERSION,
|
751
649
|
)
|
752
650
|
|
753
|
-
# Check existence of parcellation
|
754
|
-
if not (parcellation_fname.exists() and parcellation_lname.exists()):
|
755
|
-
logger.info(
|
756
|
-
"At least one of the parcellation files are missing. "
|
757
|
-
"Fetching using nilearn."
|
758
|
-
)
|
759
|
-
datasets.fetch_atlas_schaefer_2018(
|
760
|
-
n_rois=n_rois,
|
761
|
-
yeo_networks=yeo_networks,
|
762
|
-
resolution_mm=resolution, # type: ignore we know it's 1 or 2
|
763
|
-
data_dir=parcellations_dir.resolve(),
|
764
|
-
)
|
765
|
-
|
766
651
|
# Load labels
|
767
652
|
labels = [
|
768
653
|
"_".join(x.split("_")[1:])
|
769
|
-
for x in pd.read_csv(
|
654
|
+
for x in pd.read_csv(parcellation_label_path, sep="\t", header=None)
|
770
655
|
.iloc[:, 1]
|
771
656
|
.to_list()
|
772
657
|
]
|
773
658
|
|
774
|
-
return
|
659
|
+
return parcellation_img_path, labels
|
775
660
|
|
776
661
|
|
777
662
|
def _retrieve_tian(
|
778
|
-
parcellations_dir: Path,
|
779
663
|
resolution: Optional[float] = None,
|
780
664
|
scale: Optional[int] = None,
|
781
665
|
space: str = "MNI152NLin6Asym",
|
@@ -785,8 +669,6 @@ def _retrieve_tian(
|
|
785
669
|
|
786
670
|
Parameters
|
787
671
|
----------
|
788
|
-
parcellations_dir : pathlib.Path
|
789
|
-
The path to the parcellation data directory.
|
790
672
|
resolution : float, optional
|
791
673
|
The desired resolution of the parcellation to load. If it is not
|
792
674
|
available, the closest resolution will be loaded. Preferably, use a
|
@@ -810,8 +692,6 @@ def _retrieve_tian(
|
|
810
692
|
|
811
693
|
Raises
|
812
694
|
------
|
813
|
-
RuntimeError
|
814
|
-
If there is a problem fetching files.
|
815
695
|
ValueError
|
816
696
|
If invalid value is provided for ``scale`` or ``magneticfield`` or
|
817
697
|
``space``.
|
@@ -832,13 +712,10 @@ def _retrieve_tian(
|
|
832
712
|
)
|
833
713
|
|
834
714
|
# Check resolution
|
835
|
-
_valid_resolutions = [] # avoid pylance error
|
836
715
|
if magneticfield == "3T":
|
837
716
|
_valid_spaces = ["MNI152NLin6Asym", "MNI152NLin2009cAsym"]
|
838
|
-
if space
|
717
|
+
if space in _valid_spaces:
|
839
718
|
_valid_resolutions = [1, 2]
|
840
|
-
elif space == "MNI152NLin2009cAsym":
|
841
|
-
_valid_resolutions = [2]
|
842
719
|
else:
|
843
720
|
raise_error(
|
844
721
|
f"The parameter `space` ({space}) for 3T needs to be one of "
|
@@ -858,100 +735,71 @@ def _retrieve_tian(
|
|
858
735
|
)
|
859
736
|
resolution = closest_resolution(resolution, _valid_resolutions)
|
860
737
|
|
861
|
-
#
|
738
|
+
# Fetch file paths
|
862
739
|
if magneticfield == "3T":
|
863
|
-
parcellation_fname_base_3T = (
|
864
|
-
|
865
|
-
)
|
866
|
-
parcellation_lname = parcellation_fname_base_3T / (
|
867
|
-
f"Tian_Subcortex_S{scale}_3T_label.txt"
|
740
|
+
parcellation_fname_base_3T = Path(
|
741
|
+
"parcellations/Melbourne/v1.4/3T/Subcortex-Only"
|
868
742
|
)
|
869
743
|
if space == "MNI152NLin6Asym":
|
870
|
-
parcellation_fname = parcellation_fname_base_3T / (
|
871
|
-
f"Tian_Subcortex_S{scale}_{magneticfield}.nii.gz"
|
872
|
-
)
|
873
744
|
if resolution == 1:
|
874
745
|
parcellation_fname = (
|
875
746
|
parcellation_fname_base_3T
|
876
747
|
/ f"Tian_Subcortex_S{scale}_{magneticfield}_1mm.nii.gz"
|
877
748
|
)
|
749
|
+
else:
|
750
|
+
parcellation_fname = parcellation_fname_base_3T / (
|
751
|
+
f"Tian_Subcortex_S{scale}_{magneticfield}.nii.gz"
|
752
|
+
)
|
878
753
|
elif space == "MNI152NLin2009cAsym":
|
879
754
|
space = "2009cAsym"
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
755
|
+
if resolution == 1:
|
756
|
+
parcellation_fname = parcellation_fname_base_3T / (
|
757
|
+
f"Tian_Subcortex_S{scale}_{magneticfield}_{space}_1mm.nii.gz"
|
758
|
+
)
|
759
|
+
else:
|
760
|
+
parcellation_fname = parcellation_fname_base_3T / (
|
761
|
+
f"Tian_Subcortex_S{scale}_{magneticfield}_{space}.nii.gz"
|
762
|
+
)
|
763
|
+
|
764
|
+
parcellation_img_path = get(
|
765
|
+
file_path=parcellation_fname,
|
766
|
+
dataset_path=get_dataset_path(),
|
767
|
+
tag=JUNIFER_DATA_VERSION,
|
886
768
|
)
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
769
|
+
parcellation_label_path = get(
|
770
|
+
file_path=parcellation_fname_base_3T
|
771
|
+
/ f"Tian_Subcortex_S{scale}_3T_label.txt",
|
772
|
+
dataset_path=get_dataset_path(),
|
773
|
+
tag=JUNIFER_DATA_VERSION,
|
774
|
+
)
|
775
|
+
# Load labels
|
776
|
+
labels = pd.read_csv(parcellation_label_path, sep=" ", header=None)[
|
777
|
+
0
|
778
|
+
].to_list()
|
779
|
+
elif magneticfield == "7T":
|
780
|
+
parcellation_img_path = get(
|
781
|
+
file_path=Path(
|
782
|
+
"parcellations/Melbourne/v1.4/7T/"
|
783
|
+
f"Tian_Subcortex_S{scale}_{magneticfield}.nii.gz"
|
784
|
+
),
|
785
|
+
dataset_path=get_dataset_path(),
|
786
|
+
tag=JUNIFER_DATA_VERSION,
|
893
787
|
)
|
894
788
|
# define 7T labels (b/c currently no labels file available for 7T)
|
895
789
|
scale7Trois = {1: 16, 2: 34, 3: 54, 4: 62}
|
896
790
|
labels = [
|
897
791
|
("parcel_" + str(x)) for x in np.arange(1, scale7Trois[scale] + 1)
|
898
792
|
]
|
899
|
-
parcellation_lname = parcellation_fname_base_7T / (
|
900
|
-
f"Tian_Subcortex_S{scale}_7T_labelnumbering.txt"
|
901
|
-
)
|
902
|
-
with open(parcellation_lname, "w") as filehandle:
|
903
|
-
for listitem in labels:
|
904
|
-
filehandle.write(f"{listitem}\n")
|
905
793
|
logger.info(
|
906
794
|
"Currently there are no labels provided for the 7T Tian "
|
907
795
|
"parcellation. A simple numbering scheme for distinction was "
|
908
796
|
"therefore used."
|
909
797
|
)
|
910
798
|
|
911
|
-
|
912
|
-
if not (parcellation_fname.exists() and parcellation_lname.exists()):
|
913
|
-
logger.info(
|
914
|
-
"At least one of the parcellation files are missing, fetching."
|
915
|
-
)
|
916
|
-
# Set URL
|
917
|
-
url = (
|
918
|
-
"https://www.nitrc.org/frs/download.php/12012/Tian2020MSA_v1.1.zip"
|
919
|
-
)
|
920
|
-
|
921
|
-
logger.info(f"Downloading TIAN from {url}")
|
922
|
-
# Store initial download in a tempdir
|
923
|
-
with tempfile.TemporaryDirectory() as tmpdir:
|
924
|
-
# Make HTTP request
|
925
|
-
try:
|
926
|
-
resp = httpx.get(url)
|
927
|
-
resp.raise_for_status()
|
928
|
-
except httpx.HTTPError as exc:
|
929
|
-
raise_error(
|
930
|
-
f"Error response {exc.response.status_code} while "
|
931
|
-
f"requesting {exc.request.url!r}",
|
932
|
-
klass=RuntimeError,
|
933
|
-
)
|
934
|
-
else:
|
935
|
-
# Set tempfile for storing initial content and unzipping
|
936
|
-
zip_fname = Path(tmpdir) / "Tian2020MSA_v1.1.zip"
|
937
|
-
# Open tempfile and write content
|
938
|
-
with open(zip_fname, "wb") as f:
|
939
|
-
f.write(resp.content)
|
940
|
-
# Unzip tempfile
|
941
|
-
with zipfile.ZipFile(zip_fname, "r") as zip_ref:
|
942
|
-
zip_ref.extractall(parcellations_dir.as_posix())
|
943
|
-
# Clean after unzipping
|
944
|
-
if (parcellations_dir / "__MACOSX").exists():
|
945
|
-
shutil.rmtree((parcellations_dir / "__MACOSX").as_posix())
|
946
|
-
|
947
|
-
# Load labels
|
948
|
-
labels = pd.read_csv(parcellation_lname, sep=" ", header=None)[0].to_list()
|
949
|
-
|
950
|
-
return parcellation_fname, labels
|
799
|
+
return parcellation_img_path, labels
|
951
800
|
|
952
801
|
|
953
802
|
def _retrieve_suit(
|
954
|
-
parcellations_dir: Path,
|
955
803
|
resolution: Optional[float],
|
956
804
|
space: str = "MNI152NLin6Asym",
|
957
805
|
) -> tuple[Path, list[str]]:
|
@@ -959,8 +807,6 @@ def _retrieve_suit(
|
|
959
807
|
|
960
808
|
Parameters
|
961
809
|
----------
|
962
|
-
parcellations_dir : pathlib.Path
|
963
|
-
The path to the parcellation data directory.
|
964
810
|
resolution : float, optional
|
965
811
|
The desired resolution of the parcellation to load. If it is not
|
966
812
|
available, the closest resolution will be loaded. Preferably, use a
|
@@ -980,8 +826,6 @@ def _retrieve_suit(
|
|
980
826
|
|
981
827
|
Raises
|
982
828
|
------
|
983
|
-
RuntimeError
|
984
|
-
If there is a problem fetching files.
|
985
829
|
ValueError
|
986
830
|
If invalid value is provided for ``space``.
|
987
831
|
|
@@ -1006,78 +850,28 @@ def _retrieve_suit(
|
|
1006
850
|
if space == "MNI152NLin6Asym":
|
1007
851
|
space = "MNI"
|
1008
852
|
|
1009
|
-
#
|
1010
|
-
|
1011
|
-
|
853
|
+
# Fetch file paths
|
854
|
+
path_prefix = Path("parcellations/SUIT")
|
855
|
+
parcellation_img_path = get(
|
856
|
+
file_path=path_prefix / f"SUIT_{space}Space_{resolution}mm.nii",
|
857
|
+
dataset_path=get_dataset_path(),
|
858
|
+
tag=JUNIFER_DATA_VERSION,
|
1012
859
|
)
|
1013
|
-
|
1014
|
-
|
860
|
+
parcellation_label_path = get(
|
861
|
+
file_path=path_prefix / f"SUIT_{space}Space_{resolution}mm.tsv",
|
862
|
+
dataset_path=get_dataset_path(),
|
863
|
+
tag=JUNIFER_DATA_VERSION,
|
1015
864
|
)
|
1016
865
|
|
1017
|
-
# Check existence of parcellation
|
1018
|
-
if not (parcellation_fname.exists() and parcellation_lname.exists()):
|
1019
|
-
logger.info(
|
1020
|
-
"At least one of the parcellation files is missing, fetching."
|
1021
|
-
)
|
1022
|
-
# Create local directory if not present
|
1023
|
-
parcellation_fname.parent.mkdir(exist_ok=True, parents=True)
|
1024
|
-
# Set URL
|
1025
|
-
url_basis = (
|
1026
|
-
"https://github.com/DiedrichsenLab/cerebellar_atlases/raw"
|
1027
|
-
"/master/Diedrichsen_2009"
|
1028
|
-
)
|
1029
|
-
if space == "MNI":
|
1030
|
-
url = f"{url_basis}/atl-Anatom_space-MNI_dseg.nii"
|
1031
|
-
else: # if not MNI, then SUIT
|
1032
|
-
url = f"{url_basis}/atl-Anatom_space-SUIT_dseg.nii"
|
1033
|
-
url_labels = f"{url_basis}/atl-Anatom.tsv"
|
1034
|
-
|
1035
|
-
# Make HTTP requests
|
1036
|
-
with httpx.Client(follow_redirects=True) as client:
|
1037
|
-
# Download parcellation file
|
1038
|
-
logger.info(f"Downloading SUIT parcellation from {url}")
|
1039
|
-
try:
|
1040
|
-
img_resp = client.get(url)
|
1041
|
-
img_resp.raise_for_status()
|
1042
|
-
except httpx.HTTPError as exc:
|
1043
|
-
raise_error(
|
1044
|
-
f"Error response {exc.response.status_code} while "
|
1045
|
-
f"requesting {exc.request.url!r}",
|
1046
|
-
klass=RuntimeError,
|
1047
|
-
)
|
1048
|
-
else:
|
1049
|
-
with open(parcellation_fname, "wb") as f:
|
1050
|
-
f.write(img_resp.content)
|
1051
|
-
# Download label file
|
1052
|
-
logger.info(f"Downloading SUIT labels from {url_labels}")
|
1053
|
-
try:
|
1054
|
-
label_resp = client.get(url_labels)
|
1055
|
-
label_resp.raise_for_status()
|
1056
|
-
except httpx.HTTPError as exc:
|
1057
|
-
raise_error(
|
1058
|
-
f"Error response {exc.response.status_code} while "
|
1059
|
-
f"requesting {exc.request.url!r}",
|
1060
|
-
klass=RuntimeError,
|
1061
|
-
)
|
1062
|
-
else:
|
1063
|
-
# Load labels
|
1064
|
-
labels = pd.read_csv(
|
1065
|
-
io.StringIO(label_resp.content.decode("utf-8")),
|
1066
|
-
sep="\t",
|
1067
|
-
usecols=["name"],
|
1068
|
-
)
|
1069
|
-
labels.to_csv(parcellation_lname, sep="\t", index=False)
|
1070
|
-
|
1071
866
|
# Load labels
|
1072
|
-
labels = pd.read_csv(
|
867
|
+
labels = pd.read_csv(parcellation_label_path, sep="\t", usecols=["name"])[
|
1073
868
|
"name"
|
1074
869
|
].to_list()
|
1075
870
|
|
1076
|
-
return
|
871
|
+
return parcellation_img_path, labels
|
1077
872
|
|
1078
873
|
|
1079
874
|
def _retrieve_aicha(
|
1080
|
-
parcellations_dir: Path,
|
1081
875
|
resolution: Optional[float] = None,
|
1082
876
|
version: int = 2,
|
1083
877
|
) -> tuple[Path, list[str]]:
|
@@ -1085,8 +879,6 @@ def _retrieve_aicha(
|
|
1085
879
|
|
1086
880
|
Parameters
|
1087
881
|
----------
|
1088
|
-
parcellations_dir : pathlib.Path
|
1089
|
-
The path to the parcellation data directory.
|
1090
882
|
resolution : float, optional
|
1091
883
|
The desired resolution of the parcellation to load. If it is not
|
1092
884
|
available, the closest resolution will be loaded. Preferably, use a
|
@@ -1105,8 +897,6 @@ def _retrieve_aicha(
|
|
1105
897
|
|
1106
898
|
Raises
|
1107
899
|
------
|
1108
|
-
RuntimeError
|
1109
|
-
If there is a problem fetching files.
|
1110
900
|
ValueError
|
1111
901
|
If invalid value is provided for ``version``.
|
1112
902
|
|
@@ -1143,99 +933,39 @@ def _retrieve_aicha(
|
|
1143
933
|
_valid_resolutions = [1]
|
1144
934
|
resolution = closest_resolution(resolution, _valid_resolutions)
|
1145
935
|
|
1146
|
-
#
|
1147
|
-
|
1148
|
-
|
936
|
+
# Fetch file paths
|
937
|
+
path_prefix = Path(f"parcellations/AICHA/v{version}")
|
938
|
+
parcellation_img_path = get(
|
939
|
+
file_path=path_prefix / "AICHA.nii",
|
940
|
+
dataset_path=get_dataset_path(),
|
941
|
+
tag=JUNIFER_DATA_VERSION,
|
1149
942
|
)
|
1150
|
-
|
943
|
+
# Conditional label file fetch
|
1151
944
|
if version == 1:
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
/ "AICHA_vol1.txt"
|
945
|
+
parcellation_label_path = get(
|
946
|
+
file_path=path_prefix / "AICHA_vol1.txt",
|
947
|
+
dataset_path=get_dataset_path(),
|
948
|
+
tag=JUNIFER_DATA_VERSION,
|
1157
949
|
)
|
1158
950
|
elif version == 2:
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
/ "AICHA_vol3.txt"
|
951
|
+
parcellation_label_path = get(
|
952
|
+
file_path=path_prefix / "AICHA_vol3.txt",
|
953
|
+
dataset_path=get_dataset_path(),
|
954
|
+
tag=JUNIFER_DATA_VERSION,
|
1164
955
|
)
|
1165
956
|
|
1166
|
-
# Check existence of parcellation
|
1167
|
-
if not (parcellation_fname.exists() and parcellation_lname.exists()):
|
1168
|
-
logger.info(
|
1169
|
-
"At least one of the parcellation files are missing, fetching."
|
1170
|
-
)
|
1171
|
-
# Set file name on server according to version
|
1172
|
-
server_filename = ""
|
1173
|
-
if version == 1:
|
1174
|
-
server_filename = "aicha_v1.zip"
|
1175
|
-
elif version == 2:
|
1176
|
-
server_filename = "AICHA_v2.tar.zip"
|
1177
|
-
# Set URL
|
1178
|
-
url = f"http://www.gin.cnrs.fr/wp-content/uploads/{server_filename}"
|
1179
|
-
|
1180
|
-
logger.info(f"Downloading AICHA v{version} from {url}")
|
1181
|
-
# Store initial download in a tempdir
|
1182
|
-
with tempfile.TemporaryDirectory() as tmpdir:
|
1183
|
-
# Make HTTP request
|
1184
|
-
try:
|
1185
|
-
resp = httpx.get(url, follow_redirects=True)
|
1186
|
-
resp.raise_for_status()
|
1187
|
-
except httpx.HTTPError as exc:
|
1188
|
-
raise_error(
|
1189
|
-
f"Error response {exc.response.status_code} while "
|
1190
|
-
f"requesting {exc.request.url!r}",
|
1191
|
-
klass=RuntimeError,
|
1192
|
-
)
|
1193
|
-
else:
|
1194
|
-
# Set tempfile for storing initial content and unzipping
|
1195
|
-
parcellation_zip_path = Path(tmpdir) / server_filename
|
1196
|
-
# Open tempfile and write content
|
1197
|
-
with open(parcellation_zip_path, "wb") as f:
|
1198
|
-
f.write(resp.content)
|
1199
|
-
# Unzip tempfile
|
1200
|
-
with zipfile.ZipFile(parcellation_zip_path, "r") as zip_ref:
|
1201
|
-
if version == 1:
|
1202
|
-
zip_ref.extractall(
|
1203
|
-
(parcellations_dir / "AICHA_v1").as_posix()
|
1204
|
-
)
|
1205
|
-
elif version == 2:
|
1206
|
-
zip_ref.extractall(Path(tmpdir).as_posix())
|
1207
|
-
# Extract tarfile for v2
|
1208
|
-
with tarfile.TarFile(
|
1209
|
-
Path(tmpdir) / "aicha_v2.tar", "r"
|
1210
|
-
) as tar_ref:
|
1211
|
-
tar_ref.extractall(
|
1212
|
-
(parcellations_dir / "AICHA_v2").as_posix()
|
1213
|
-
)
|
1214
|
-
# Cleanup after unzipping
|
1215
|
-
if (
|
1216
|
-
parcellations_dir / f"AICHA_v{version}" / "__MACOSX"
|
1217
|
-
).exists():
|
1218
|
-
shutil.rmtree(
|
1219
|
-
(
|
1220
|
-
parcellations_dir
|
1221
|
-
/ f"AICHA_v{version}"
|
1222
|
-
/ "__MACOSX"
|
1223
|
-
).as_posix()
|
1224
|
-
)
|
1225
|
-
|
1226
957
|
# Load labels
|
1227
958
|
labels = pd.read_csv(
|
1228
|
-
|
959
|
+
parcellation_label_path,
|
1229
960
|
sep="\t",
|
1230
961
|
header=None,
|
1231
|
-
skiprows=[0],
|
962
|
+
skiprows=[0],
|
1232
963
|
)[0].to_list()
|
1233
964
|
|
1234
|
-
return
|
965
|
+
return parcellation_img_path, labels
|
1235
966
|
|
1236
967
|
|
1237
|
-
def _retrieve_shen(
|
1238
|
-
parcellations_dir: Path,
|
968
|
+
def _retrieve_shen(
|
1239
969
|
resolution: Optional[float] = None,
|
1240
970
|
year: int = 2015,
|
1241
971
|
n_rois: int = 268,
|
@@ -1244,8 +974,6 @@ def _retrieve_shen( # noqa: C901
|
|
1244
974
|
|
1245
975
|
Parameters
|
1246
976
|
----------
|
1247
|
-
parcellations_dir : pathlib.Path
|
1248
|
-
The path to the parcellation data directory.
|
1249
977
|
resolution : float, optional
|
1250
978
|
The desired resolution of the parcellation to load. If it is not
|
1251
979
|
available, the closest resolution will be loaded. Preferably, use a
|
@@ -1269,8 +997,6 @@ def _retrieve_shen( # noqa: C901
|
|
1269
997
|
|
1270
998
|
Raises
|
1271
999
|
------
|
1272
|
-
RuntimeError
|
1273
|
-
If there is a problem fetching files.
|
1274
1000
|
ValueError
|
1275
1001
|
If invalid value or combination is provided for ``year`` and
|
1276
1002
|
``n_rois``.
|
@@ -1323,123 +1049,49 @@ def _retrieve_shen( # noqa: C901
|
|
1323
1049
|
f"`year = {year}` is invalid"
|
1324
1050
|
)
|
1325
1051
|
|
1326
|
-
#
|
1052
|
+
# Fetch file paths based on year
|
1053
|
+
path_prefix = Path(f"parcellations/Shen/{year}")
|
1327
1054
|
if year == 2013:
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
/ f"fconn_atlas_{n_rois}_{resolution}mm.nii"
|
1055
|
+
parcellation_img_path = get(
|
1056
|
+
file_path=path_prefix / f"fconn_atlas_{n_rois}_{resolution}mm.nii",
|
1057
|
+
dataset_path=get_dataset_path(),
|
1058
|
+
tag=JUNIFER_DATA_VERSION,
|
1333
1059
|
)
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
/ f"Group_seg{n_rois}_BAindexing_setA.txt"
|
1339
|
-
)
|
1340
|
-
elif year == 2015:
|
1341
|
-
parcellation_fname = (
|
1342
|
-
parcellations_dir
|
1343
|
-
/ "Shen_2015"
|
1344
|
-
/ f"shen_{resolution}mm_268_parcellation.nii.gz"
|
1060
|
+
parcellation_label_path = get(
|
1061
|
+
file_path=path_prefix / f"Group_seg{n_rois}_BAindexing_setA.txt",
|
1062
|
+
dataset_path=get_dataset_path(),
|
1063
|
+
tag=JUNIFER_DATA_VERSION,
|
1345
1064
|
)
|
1346
|
-
elif year == 2019:
|
1347
|
-
parcellation_fname = (
|
1348
|
-
parcellations_dir
|
1349
|
-
/ "Shen_2019"
|
1350
|
-
/ "Shen_1mm_368_parcellation.nii.gz"
|
1351
|
-
)
|
1352
|
-
|
1353
|
-
# Check existence of parcellation
|
1354
|
-
if not parcellation_fname.exists():
|
1355
|
-
logger.info(
|
1356
|
-
"At least one of the parcellation files are missing, fetching."
|
1357
|
-
)
|
1358
|
-
|
1359
|
-
# Set URL based on year
|
1360
|
-
url = ""
|
1361
|
-
if year == 2013:
|
1362
|
-
url = "https://www.nitrc.org/frs/download.php/5785/shenetal_neuroimage2013_funcatlas.zip"
|
1363
|
-
elif year == 2015:
|
1364
|
-
# Set URL based on resolution
|
1365
|
-
if resolution == 1:
|
1366
|
-
url = "https://www.nitrc.org/frs/download.php/7976/shen_1mm_268_parcellation.nii.gz"
|
1367
|
-
elif resolution == 2:
|
1368
|
-
url = "https://www.nitrc.org/frs/download.php/7977/shen_2mm_268_parcellation.nii.gz"
|
1369
|
-
elif year == 2019:
|
1370
|
-
url = "https://www.nitrc.org/frs/download.php/11629/shen_368.zip"
|
1371
|
-
|
1372
|
-
logger.info(f"Downloading Shen {year} from {url}")
|
1373
|
-
# Store initial download in a tempdir
|
1374
|
-
with tempfile.TemporaryDirectory() as tmpdir:
|
1375
|
-
# Make HTTP request
|
1376
|
-
try:
|
1377
|
-
resp = httpx.get(url)
|
1378
|
-
resp.raise_for_status()
|
1379
|
-
except httpx.HTTPError as exc:
|
1380
|
-
raise_error(
|
1381
|
-
f"Error response {exc.response.status_code} while "
|
1382
|
-
f"requesting {exc.request.url!r}",
|
1383
|
-
klass=RuntimeError,
|
1384
|
-
)
|
1385
|
-
else:
|
1386
|
-
if year in (2013, 2019):
|
1387
|
-
parcellation_zip_path = Path(tmpdir) / f"Shen{year}.zip"
|
1388
|
-
# Open tempfile and write content
|
1389
|
-
with open(parcellation_zip_path, "wb") as f:
|
1390
|
-
f.write(resp.content)
|
1391
|
-
# Unzip tempfile
|
1392
|
-
with zipfile.ZipFile(
|
1393
|
-
parcellation_zip_path, "r"
|
1394
|
-
) as zip_ref:
|
1395
|
-
zip_ref.extractall(
|
1396
|
-
(parcellations_dir / f"Shen_{year}").as_posix()
|
1397
|
-
)
|
1398
|
-
# Cleanup after unzipping
|
1399
|
-
if (
|
1400
|
-
parcellations_dir / f"Shen_{year}" / "__MACOSX"
|
1401
|
-
).exists():
|
1402
|
-
shutil.rmtree(
|
1403
|
-
(
|
1404
|
-
parcellations_dir / f"Shen_{year}" / "__MACOSX"
|
1405
|
-
).as_posix()
|
1406
|
-
)
|
1407
|
-
elif year == 2015:
|
1408
|
-
img_dir_path = parcellations_dir / "Shen_2015"
|
1409
|
-
# Create local directory if not present
|
1410
|
-
img_dir_path.mkdir(parents=True, exist_ok=True)
|
1411
|
-
img_path = (
|
1412
|
-
img_dir_path
|
1413
|
-
/ f"shen_{resolution}mm_268_parcellation.nii.gz"
|
1414
|
-
)
|
1415
|
-
# Create local file if not present
|
1416
|
-
img_path.touch(exist_ok=True)
|
1417
|
-
# Open tempfile and write content
|
1418
|
-
with open(img_path, "wb") as f:
|
1419
|
-
f.write(resp.content)
|
1420
|
-
|
1421
|
-
# Load labels based on year
|
1422
|
-
if year == 2013:
|
1423
1065
|
labels = (
|
1424
1066
|
pd.read_csv(
|
1425
|
-
|
1426
|
-
sep=",",
|
1427
|
-
header=None,
|
1428
|
-
skiprows=[0],
|
1067
|
+
parcellation_label_path,
|
1068
|
+
sep=",",
|
1069
|
+
header=None,
|
1070
|
+
skiprows=[0],
|
1429
1071
|
)[1]
|
1430
1072
|
.map(lambda x: x.strip()) # fix formatting
|
1431
1073
|
.to_list()
|
1432
1074
|
)
|
1433
1075
|
elif year == 2015:
|
1076
|
+
parcellation_img_path = get(
|
1077
|
+
file_path=path_prefix
|
1078
|
+
/ f"shen_{resolution}mm_268_parcellation.nii.gz",
|
1079
|
+
dataset_path=get_dataset_path(),
|
1080
|
+
tag=JUNIFER_DATA_VERSION,
|
1081
|
+
)
|
1434
1082
|
labels = list(range(1, 269))
|
1435
1083
|
elif year == 2019:
|
1084
|
+
parcellation_img_path = get(
|
1085
|
+
file_path=path_prefix / "Shen_1mm_368_parcellation.nii.gz",
|
1086
|
+
dataset_path=get_dataset_path(),
|
1087
|
+
tag=JUNIFER_DATA_VERSION,
|
1088
|
+
)
|
1436
1089
|
labels = list(range(1, 369))
|
1437
1090
|
|
1438
|
-
return
|
1091
|
+
return parcellation_img_path, labels
|
1439
1092
|
|
1440
1093
|
|
1441
1094
|
def _retrieve_yan(
|
1442
|
-
parcellations_dir: Path,
|
1443
1095
|
resolution: Optional[float] = None,
|
1444
1096
|
n_rois: Optional[int] = None,
|
1445
1097
|
yeo_networks: Optional[int] = None,
|
@@ -1449,8 +1101,6 @@ def _retrieve_yan(
|
|
1449
1101
|
|
1450
1102
|
Parameters
|
1451
1103
|
----------
|
1452
|
-
parcellations_dir : pathlib.Path
|
1453
|
-
The path to the parcellation data directory.
|
1454
1104
|
resolution : float, optional
|
1455
1105
|
The desired resolution of the parcellation to load. If it is not
|
1456
1106
|
available, the closest resolution will be loaded. Preferably, use a
|
@@ -1473,8 +1123,6 @@ def _retrieve_yan(
|
|
1473
1123
|
|
1474
1124
|
Raises
|
1475
1125
|
------
|
1476
|
-
RuntimeError
|
1477
|
-
If there is a problem fetching files.
|
1478
1126
|
ValueError
|
1479
1127
|
If invalid value is provided for ``n_rois``, ``yeo_networks`` or
|
1480
1128
|
``kong_networks``.
|
@@ -1507,8 +1155,8 @@ def _retrieve_yan(
|
|
1507
1155
|
f"following: {_valid_n_rois}"
|
1508
1156
|
)
|
1509
1157
|
|
1510
|
-
|
1511
|
-
|
1158
|
+
# Fetch file paths based on networks
|
1159
|
+
pre_path_prefix = Path("parcellations/Yan2023")
|
1512
1160
|
if yeo_networks:
|
1513
1161
|
# Check yeo_networks value
|
1514
1162
|
_valid_yeo_networks = [7, 17]
|
@@ -1517,19 +1165,22 @@ def _retrieve_yan(
|
|
1517
1165
|
f"The parameter `yeo_networks` ({yeo_networks}) needs to be "
|
1518
1166
|
f"one of the following: {_valid_yeo_networks}"
|
1519
1167
|
)
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
1523
|
-
|
1168
|
+
|
1169
|
+
path_prefix = pre_path_prefix / "Yeo2011"
|
1170
|
+
parcellation_img_path = get(
|
1171
|
+
file_path=path_prefix
|
1524
1172
|
/ (
|
1525
1173
|
f"{n_rois}Parcels_Yeo2011_{yeo_networks}Networks_FSLMNI152_"
|
1526
1174
|
f"{resolution}mm.nii.gz"
|
1527
|
-
)
|
1175
|
+
),
|
1176
|
+
dataset_path=get_dataset_path(),
|
1177
|
+
tag=JUNIFER_DATA_VERSION,
|
1528
1178
|
)
|
1529
|
-
|
1530
|
-
|
1531
|
-
/ "
|
1532
|
-
|
1179
|
+
parcellation_label_path = get(
|
1180
|
+
file_path=path_prefix
|
1181
|
+
/ f"{n_rois}Parcels_Yeo2011_{yeo_networks}Networks_LUT.txt",
|
1182
|
+
dataset_path=get_dataset_path(),
|
1183
|
+
tag=JUNIFER_DATA_VERSION,
|
1533
1184
|
)
|
1534
1185
|
elif kong_networks:
|
1535
1186
|
# Check kong_networks value
|
@@ -1539,106 +1190,33 @@ def _retrieve_yan(
|
|
1539
1190
|
f"The parameter `kong_networks` ({kong_networks}) needs to be "
|
1540
1191
|
f"one of the following: {_valid_kong_networks}"
|
1541
1192
|
)
|
1542
|
-
|
1543
|
-
|
1544
|
-
|
1545
|
-
|
1193
|
+
|
1194
|
+
path_prefix = pre_path_prefix / "Kong2022"
|
1195
|
+
parcellation_img_path = get(
|
1196
|
+
file_path=path_prefix
|
1546
1197
|
/ (
|
1547
1198
|
f"{n_rois}Parcels_Kong2022_{kong_networks}Networks_FSLMNI152_"
|
1548
1199
|
f"{resolution}mm.nii.gz"
|
1549
|
-
)
|
1550
|
-
|
1551
|
-
|
1552
|
-
parcellations_dir
|
1553
|
-
/ "Yan_2023"
|
1554
|
-
/ f"{n_rois}Parcels_Kong2022_{kong_networks}Networks_LUT.txt"
|
1200
|
+
),
|
1201
|
+
dataset_path=get_dataset_path(),
|
1202
|
+
tag=JUNIFER_DATA_VERSION,
|
1555
1203
|
)
|
1556
|
-
|
1557
|
-
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1204
|
+
parcellation_label_path = get(
|
1205
|
+
file_path=path_prefix
|
1206
|
+
/ f"{n_rois}Parcels_Kong2022_{kong_networks}Networks_LUT.txt",
|
1207
|
+
dataset_path=get_dataset_path(),
|
1208
|
+
tag=JUNIFER_DATA_VERSION,
|
1561
1209
|
)
|
1562
1210
|
|
1563
|
-
# Set URL based on network
|
1564
|
-
img_url = ""
|
1565
|
-
label_url = ""
|
1566
|
-
if yeo_networks:
|
1567
|
-
img_url = (
|
1568
|
-
"https://raw.githubusercontent.com/ThomasYeoLab/CBIG/"
|
1569
|
-
"master/stable_projects/brain_parcellation/Yan2023_homotopic/"
|
1570
|
-
f"parcellations/MNI/yeo{yeo_networks}/{n_rois}Parcels_Yeo2011"
|
1571
|
-
f"_{yeo_networks}Networks_FSLMNI152_{resolution}mm.nii.gz"
|
1572
|
-
)
|
1573
|
-
label_url = (
|
1574
|
-
"https://raw.githubusercontent.com/ThomasYeoLab/CBIG/"
|
1575
|
-
"master/stable_projects/brain_parcellation/Yan2023_homotopic/"
|
1576
|
-
f"parcellations/MNI/yeo{yeo_networks}/freeview_lut/{n_rois}"
|
1577
|
-
f"Parcels_Yeo2011_{yeo_networks}Networks_LUT.txt"
|
1578
|
-
)
|
1579
|
-
elif kong_networks:
|
1580
|
-
img_url = (
|
1581
|
-
"https://raw.githubusercontent.com/ThomasYeoLab/CBIG/"
|
1582
|
-
"master/stable_projects/brain_parcellation/Yan2023_homotopic/"
|
1583
|
-
f"parcellations/MNI/kong17/{n_rois}Parcels_Kong2022"
|
1584
|
-
f"_17Networks_FSLMNI152_{resolution}mm.nii.gz"
|
1585
|
-
)
|
1586
|
-
label_url = (
|
1587
|
-
"https://raw.githubusercontent.com/ThomasYeoLab/CBIG/"
|
1588
|
-
"master/stable_projects/brain_parcellation/Yan2023_homotopic/"
|
1589
|
-
f"parcellations/MNI/kong17/freeview_lut/{n_rois}Parcels_"
|
1590
|
-
"Kong2022_17Networks_LUT.txt"
|
1591
|
-
)
|
1592
|
-
|
1593
|
-
# Make HTTP requests
|
1594
|
-
with httpx.Client() as client:
|
1595
|
-
# Download parcellation file
|
1596
|
-
logger.info(f"Downloading Yan 2023 parcellation from {img_url}")
|
1597
|
-
try:
|
1598
|
-
img_resp = client.get(img_url)
|
1599
|
-
img_resp.raise_for_status()
|
1600
|
-
except httpx.HTTPError as exc:
|
1601
|
-
raise_error(
|
1602
|
-
f"Error response {exc.response.status_code} while "
|
1603
|
-
f"requesting {exc.request.url!r}",
|
1604
|
-
klass=RuntimeError,
|
1605
|
-
)
|
1606
|
-
else:
|
1607
|
-
parcellation_img_path = Path(parcellation_fname)
|
1608
|
-
# Create local directory if not present
|
1609
|
-
parcellation_img_path.parent.mkdir(parents=True, exist_ok=True)
|
1610
|
-
# Create local file if not present
|
1611
|
-
parcellation_img_path.touch(exist_ok=True)
|
1612
|
-
# Open file and write content
|
1613
|
-
with open(parcellation_img_path, "wb") as f:
|
1614
|
-
f.write(img_resp.content)
|
1615
|
-
# Download label file
|
1616
|
-
logger.info(f"Downloading Yan 2023 labels from {label_url}")
|
1617
|
-
try:
|
1618
|
-
label_resp = client.get(label_url)
|
1619
|
-
label_resp.raise_for_status()
|
1620
|
-
except httpx.HTTPError as exc:
|
1621
|
-
raise_error(
|
1622
|
-
f"Error response {exc.response.status_code} while "
|
1623
|
-
f"requesting {exc.request.url!r}",
|
1624
|
-
klass=RuntimeError,
|
1625
|
-
)
|
1626
|
-
else:
|
1627
|
-
parcellation_labels_path = Path(parcellation_lname)
|
1628
|
-
# Create local file if not present
|
1629
|
-
parcellation_labels_path.touch(exist_ok=True)
|
1630
|
-
# Open file and write content
|
1631
|
-
with open(parcellation_labels_path, "wb") as f:
|
1632
|
-
f.write(label_resp.content)
|
1633
|
-
|
1634
1211
|
# Load label file
|
1635
|
-
labels = pd.read_csv(
|
1212
|
+
labels = pd.read_csv(parcellation_label_path, sep=" ", header=None)[
|
1213
|
+
1
|
1214
|
+
].to_list()
|
1636
1215
|
|
1637
|
-
return
|
1216
|
+
return parcellation_img_path, labels
|
1638
1217
|
|
1639
1218
|
|
1640
1219
|
def _retrieve_brainnetome(
|
1641
|
-
parcellations_dir: Path,
|
1642
1220
|
resolution: Optional[float] = None,
|
1643
1221
|
threshold: Optional[int] = None,
|
1644
1222
|
) -> tuple[Path, list[str]]:
|
@@ -1646,8 +1224,6 @@ def _retrieve_brainnetome(
|
|
1646
1224
|
|
1647
1225
|
Parameters
|
1648
1226
|
----------
|
1649
|
-
parcellations_dir : pathlib.Path
|
1650
|
-
The path to the parcellation data directory.
|
1651
1227
|
resolution : {1.0, 1.25, 2.0}, optional
|
1652
1228
|
The desired resolution of the parcellation to load. If it is not
|
1653
1229
|
available, the closest resolution will be loaded. Preferably, use a
|
@@ -1666,8 +1242,6 @@ def _retrieve_brainnetome(
|
|
1666
1242
|
|
1667
1243
|
Raises
|
1668
1244
|
------
|
1669
|
-
RuntimeError
|
1670
|
-
If there is a problem fetching files.
|
1671
1245
|
ValueError
|
1672
1246
|
If invalid value is provided for ``threshold``.
|
1673
1247
|
|
@@ -1691,36 +1265,16 @@ def _retrieve_brainnetome(
|
|
1691
1265
|
if resolution in [1.0, 2.0]:
|
1692
1266
|
resolution = int(resolution)
|
1693
1267
|
|
1694
|
-
|
1695
|
-
|
1696
|
-
|
1697
|
-
|
1268
|
+
# Fetch file path
|
1269
|
+
parcellation_img_path = get(
|
1270
|
+
file_path=Path(
|
1271
|
+
"parcellations/Brainnetome/"
|
1272
|
+
f"BNA-maxprob-thr{threshold}-{resolution}mm.nii.gz"
|
1273
|
+
),
|
1274
|
+
dataset_path=get_dataset_path(),
|
1275
|
+
tag=JUNIFER_DATA_VERSION,
|
1698
1276
|
)
|
1699
1277
|
|
1700
|
-
# Check for existence of parcellation
|
1701
|
-
if not parcellation_fname.exists():
|
1702
|
-
# Set URL
|
1703
|
-
url = f"http://neurovault.org/media/images/1625/BNA-maxprob-thr{threshold}-{resolution}mm.nii.gz"
|
1704
|
-
|
1705
|
-
logger.info(f"Downloading Brainnetome from {url}")
|
1706
|
-
# Make HTTP request
|
1707
|
-
try:
|
1708
|
-
resp = httpx.get(url, follow_redirects=True)
|
1709
|
-
resp.raise_for_status()
|
1710
|
-
except httpx.HTTPError as exc:
|
1711
|
-
raise_error(
|
1712
|
-
f"Error response {exc.response.status_code} while "
|
1713
|
-
f"requesting {exc.request.url!r}",
|
1714
|
-
klass=RuntimeError,
|
1715
|
-
)
|
1716
|
-
else:
|
1717
|
-
# Create local directory if not present
|
1718
|
-
parcellation_fname.parent.mkdir(parents=True, exist_ok=True)
|
1719
|
-
# Create file if not present
|
1720
|
-
parcellation_fname.touch(exist_ok=True)
|
1721
|
-
# Open file and write bytes
|
1722
|
-
parcellation_fname.write_bytes(resp.content)
|
1723
|
-
|
1724
1278
|
# Load labels
|
1725
1279
|
labels = (
|
1726
1280
|
sorted([f"SFG_L(R)_7_{i}" for i in range(1, 8)] * 2)
|
@@ -1750,7 +1304,7 @@ def _retrieve_brainnetome(
|
|
1750
1304
|
+ sorted([f"Tha_L(R)_8_{i}" for i in range(1, 9)] * 2)
|
1751
1305
|
)
|
1752
1306
|
|
1753
|
-
return
|
1307
|
+
return parcellation_img_path, labels
|
1754
1308
|
|
1755
1309
|
|
1756
1310
|
def merge_parcellations(
|