junifer 0.0.3.dev186__py3-none-any.whl → 0.0.4__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.
Files changed (178) hide show
  1. junifer/_version.py +14 -2
  2. junifer/api/cli.py +162 -17
  3. junifer/api/functions.py +87 -419
  4. junifer/api/parser.py +24 -0
  5. junifer/api/queue_context/__init__.py +8 -0
  6. junifer/api/queue_context/gnu_parallel_local_adapter.py +258 -0
  7. junifer/api/queue_context/htcondor_adapter.py +365 -0
  8. junifer/api/queue_context/queue_context_adapter.py +60 -0
  9. junifer/api/queue_context/tests/test_gnu_parallel_local_adapter.py +192 -0
  10. junifer/api/queue_context/tests/test_htcondor_adapter.py +257 -0
  11. junifer/api/res/afni/run_afni_docker.sh +6 -6
  12. junifer/api/res/ants/ResampleImage +3 -0
  13. junifer/api/res/ants/antsApplyTransforms +3 -0
  14. junifer/api/res/ants/antsApplyTransformsToPoints +3 -0
  15. junifer/api/res/ants/run_ants_docker.sh +39 -0
  16. junifer/api/res/fsl/applywarp +3 -0
  17. junifer/api/res/fsl/flirt +3 -0
  18. junifer/api/res/fsl/img2imgcoord +3 -0
  19. junifer/api/res/fsl/run_fsl_docker.sh +39 -0
  20. junifer/api/res/fsl/std2imgcoord +3 -0
  21. junifer/api/res/run_conda.sh +4 -4
  22. junifer/api/res/run_venv.sh +22 -0
  23. junifer/api/tests/data/partly_cloudy_agg_mean_tian.yml +16 -0
  24. junifer/api/tests/test_api_utils.py +21 -3
  25. junifer/api/tests/test_cli.py +232 -9
  26. junifer/api/tests/test_functions.py +211 -439
  27. junifer/api/tests/test_parser.py +1 -1
  28. junifer/configs/juseless/datagrabbers/aomic_id1000_vbm.py +6 -1
  29. junifer/configs/juseless/datagrabbers/camcan_vbm.py +6 -1
  30. junifer/configs/juseless/datagrabbers/ixi_vbm.py +6 -1
  31. junifer/configs/juseless/datagrabbers/tests/test_ucla.py +8 -8
  32. junifer/configs/juseless/datagrabbers/ucla.py +44 -26
  33. junifer/configs/juseless/datagrabbers/ukb_vbm.py +6 -1
  34. junifer/data/VOIs/meta/AutobiographicalMemory_VOIs.txt +23 -0
  35. junifer/data/VOIs/meta/Power2013_MNI_VOIs.tsv +264 -0
  36. junifer/data/__init__.py +4 -0
  37. junifer/data/coordinates.py +298 -31
  38. junifer/data/masks.py +360 -28
  39. junifer/data/parcellations.py +621 -188
  40. junifer/data/template_spaces.py +190 -0
  41. junifer/data/tests/test_coordinates.py +34 -3
  42. junifer/data/tests/test_data_utils.py +1 -0
  43. junifer/data/tests/test_masks.py +202 -86
  44. junifer/data/tests/test_parcellations.py +266 -55
  45. junifer/data/tests/test_template_spaces.py +104 -0
  46. junifer/data/utils.py +4 -2
  47. junifer/datagrabber/__init__.py +1 -0
  48. junifer/datagrabber/aomic/id1000.py +111 -70
  49. junifer/datagrabber/aomic/piop1.py +116 -53
  50. junifer/datagrabber/aomic/piop2.py +116 -53
  51. junifer/datagrabber/aomic/tests/test_id1000.py +27 -27
  52. junifer/datagrabber/aomic/tests/test_piop1.py +27 -27
  53. junifer/datagrabber/aomic/tests/test_piop2.py +27 -27
  54. junifer/datagrabber/base.py +62 -10
  55. junifer/datagrabber/datalad_base.py +0 -2
  56. junifer/datagrabber/dmcc13_benchmark.py +372 -0
  57. junifer/datagrabber/hcp1200/datalad_hcp1200.py +5 -0
  58. junifer/datagrabber/hcp1200/hcp1200.py +30 -13
  59. junifer/datagrabber/pattern.py +133 -27
  60. junifer/datagrabber/pattern_datalad.py +111 -13
  61. junifer/datagrabber/tests/test_base.py +57 -6
  62. junifer/datagrabber/tests/test_datagrabber_utils.py +204 -76
  63. junifer/datagrabber/tests/test_datalad_base.py +0 -6
  64. junifer/datagrabber/tests/test_dmcc13_benchmark.py +256 -0
  65. junifer/datagrabber/tests/test_multiple.py +43 -10
  66. junifer/datagrabber/tests/test_pattern.py +125 -178
  67. junifer/datagrabber/tests/test_pattern_datalad.py +44 -25
  68. junifer/datagrabber/utils.py +151 -16
  69. junifer/datareader/default.py +36 -10
  70. junifer/external/nilearn/junifer_nifti_spheres_masker.py +6 -0
  71. junifer/markers/base.py +25 -16
  72. junifer/markers/collection.py +35 -16
  73. junifer/markers/complexity/__init__.py +27 -0
  74. junifer/markers/complexity/complexity_base.py +149 -0
  75. junifer/markers/complexity/hurst_exponent.py +136 -0
  76. junifer/markers/complexity/multiscale_entropy_auc.py +140 -0
  77. junifer/markers/complexity/perm_entropy.py +132 -0
  78. junifer/markers/complexity/range_entropy.py +136 -0
  79. junifer/markers/complexity/range_entropy_auc.py +145 -0
  80. junifer/markers/complexity/sample_entropy.py +134 -0
  81. junifer/markers/complexity/tests/test_complexity_base.py +19 -0
  82. junifer/markers/complexity/tests/test_hurst_exponent.py +69 -0
  83. junifer/markers/complexity/tests/test_multiscale_entropy_auc.py +68 -0
  84. junifer/markers/complexity/tests/test_perm_entropy.py +68 -0
  85. junifer/markers/complexity/tests/test_range_entropy.py +69 -0
  86. junifer/markers/complexity/tests/test_range_entropy_auc.py +69 -0
  87. junifer/markers/complexity/tests/test_sample_entropy.py +68 -0
  88. junifer/markers/complexity/tests/test_weighted_perm_entropy.py +68 -0
  89. junifer/markers/complexity/weighted_perm_entropy.py +133 -0
  90. junifer/markers/falff/_afni_falff.py +153 -0
  91. junifer/markers/falff/_junifer_falff.py +142 -0
  92. junifer/markers/falff/falff_base.py +91 -84
  93. junifer/markers/falff/falff_parcels.py +61 -45
  94. junifer/markers/falff/falff_spheres.py +64 -48
  95. junifer/markers/falff/tests/test_falff_parcels.py +89 -121
  96. junifer/markers/falff/tests/test_falff_spheres.py +92 -127
  97. junifer/markers/functional_connectivity/crossparcellation_functional_connectivity.py +1 -0
  98. junifer/markers/functional_connectivity/edge_functional_connectivity_parcels.py +1 -0
  99. junifer/markers/functional_connectivity/functional_connectivity_base.py +1 -0
  100. junifer/markers/functional_connectivity/tests/test_crossparcellation_functional_connectivity.py +46 -44
  101. junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_parcels.py +34 -39
  102. junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_spheres.py +40 -52
  103. junifer/markers/functional_connectivity/tests/test_functional_connectivity_parcels.py +62 -70
  104. junifer/markers/functional_connectivity/tests/test_functional_connectivity_spheres.py +99 -85
  105. junifer/markers/parcel_aggregation.py +60 -38
  106. junifer/markers/reho/_afni_reho.py +192 -0
  107. junifer/markers/reho/_junifer_reho.py +281 -0
  108. junifer/markers/reho/reho_base.py +69 -34
  109. junifer/markers/reho/reho_parcels.py +26 -16
  110. junifer/markers/reho/reho_spheres.py +23 -9
  111. junifer/markers/reho/tests/test_reho_parcels.py +93 -92
  112. junifer/markers/reho/tests/test_reho_spheres.py +88 -86
  113. junifer/markers/sphere_aggregation.py +54 -9
  114. junifer/markers/temporal_snr/temporal_snr_base.py +1 -0
  115. junifer/markers/temporal_snr/tests/test_temporal_snr_parcels.py +38 -37
  116. junifer/markers/temporal_snr/tests/test_temporal_snr_spheres.py +34 -38
  117. junifer/markers/tests/test_collection.py +43 -42
  118. junifer/markers/tests/test_ets_rss.py +29 -37
  119. junifer/markers/tests/test_parcel_aggregation.py +587 -468
  120. junifer/markers/tests/test_sphere_aggregation.py +209 -157
  121. junifer/markers/utils.py +2 -40
  122. junifer/onthefly/read_transform.py +13 -6
  123. junifer/pipeline/__init__.py +1 -0
  124. junifer/pipeline/pipeline_step_mixin.py +105 -41
  125. junifer/pipeline/registry.py +17 -0
  126. junifer/pipeline/singleton.py +45 -0
  127. junifer/pipeline/tests/test_pipeline_step_mixin.py +139 -51
  128. junifer/pipeline/tests/test_update_meta_mixin.py +1 -0
  129. junifer/pipeline/tests/test_workdir_manager.py +104 -0
  130. junifer/pipeline/update_meta_mixin.py +8 -2
  131. junifer/pipeline/utils.py +154 -15
  132. junifer/pipeline/workdir_manager.py +246 -0
  133. junifer/preprocess/__init__.py +3 -0
  134. junifer/preprocess/ants/__init__.py +4 -0
  135. junifer/preprocess/ants/ants_apply_transforms_warper.py +185 -0
  136. junifer/preprocess/ants/tests/test_ants_apply_transforms_warper.py +56 -0
  137. junifer/preprocess/base.py +96 -69
  138. junifer/preprocess/bold_warper.py +265 -0
  139. junifer/preprocess/confounds/fmriprep_confound_remover.py +91 -134
  140. junifer/preprocess/confounds/tests/test_fmriprep_confound_remover.py +106 -111
  141. junifer/preprocess/fsl/__init__.py +4 -0
  142. junifer/preprocess/fsl/apply_warper.py +179 -0
  143. junifer/preprocess/fsl/tests/test_apply_warper.py +45 -0
  144. junifer/preprocess/tests/test_bold_warper.py +159 -0
  145. junifer/preprocess/tests/test_preprocess_base.py +6 -6
  146. junifer/preprocess/warping/__init__.py +6 -0
  147. junifer/preprocess/warping/_ants_warper.py +167 -0
  148. junifer/preprocess/warping/_fsl_warper.py +109 -0
  149. junifer/preprocess/warping/space_warper.py +213 -0
  150. junifer/preprocess/warping/tests/test_space_warper.py +198 -0
  151. junifer/stats.py +18 -4
  152. junifer/storage/base.py +9 -1
  153. junifer/storage/hdf5.py +8 -3
  154. junifer/storage/pandas_base.py +2 -1
  155. junifer/storage/sqlite.py +1 -0
  156. junifer/storage/tests/test_hdf5.py +2 -1
  157. junifer/storage/tests/test_sqlite.py +8 -8
  158. junifer/storage/tests/test_utils.py +6 -6
  159. junifer/storage/utils.py +1 -0
  160. junifer/testing/datagrabbers.py +11 -7
  161. junifer/testing/utils.py +1 -0
  162. junifer/tests/test_stats.py +2 -0
  163. junifer/utils/__init__.py +1 -0
  164. junifer/utils/helpers.py +53 -0
  165. junifer/utils/logging.py +14 -3
  166. junifer/utils/tests/test_helpers.py +35 -0
  167. {junifer-0.0.3.dev186.dist-info → junifer-0.0.4.dist-info}/METADATA +59 -28
  168. junifer-0.0.4.dist-info/RECORD +257 -0
  169. {junifer-0.0.3.dev186.dist-info → junifer-0.0.4.dist-info}/WHEEL +1 -1
  170. junifer/markers/falff/falff_estimator.py +0 -334
  171. junifer/markers/falff/tests/test_falff_estimator.py +0 -238
  172. junifer/markers/reho/reho_estimator.py +0 -515
  173. junifer/markers/reho/tests/test_reho_estimator.py +0 -260
  174. junifer-0.0.3.dev186.dist-info/RECORD +0 -199
  175. {junifer-0.0.3.dev186.dist-info → junifer-0.0.4.dist-info}/AUTHORS.rst +0 -0
  176. {junifer-0.0.3.dev186.dist-info → junifer-0.0.4.dist-info}/LICENSE.md +0 -0
  177. {junifer-0.0.3.dev186.dist-info → junifer-0.0.4.dist-info}/entry_points.txt +0 -0
  178. {junifer-0.0.3.dev186.dist-info → junifer-0.0.4.dist-info}/top_level.txt +0 -0
@@ -11,22 +11,30 @@ from typing import List
11
11
  import nibabel as nib
12
12
  import numpy as np
13
13
  import pytest
14
- from nilearn.image import new_img_like
14
+ from nilearn.image import new_img_like, resample_to_img
15
15
  from numpy.testing import assert_array_almost_equal, assert_array_equal
16
16
 
17
17
  from junifer.data.parcellations import (
18
18
  _retrieve_aicha,
19
+ _retrieve_brainnetome,
19
20
  _retrieve_parcellation,
20
21
  _retrieve_schaefer,
21
22
  _retrieve_shen,
22
23
  _retrieve_suit,
23
24
  _retrieve_tian,
24
25
  _retrieve_yan,
26
+ get_parcellation,
25
27
  list_parcellations,
26
28
  load_parcellation,
27
29
  merge_parcellations,
28
30
  register_parcellation,
29
31
  )
32
+ from junifer.datareader import DefaultDataReader
33
+ from junifer.pipeline.utils import _check_ants
34
+ from junifer.testing.datagrabbers import (
35
+ OasisVBMTestingDataGrabber,
36
+ PartlyCloudyTestingDataGrabber,
37
+ )
30
38
 
31
39
 
32
40
  def test_register_parcellation_built_in_check() -> None:
@@ -36,6 +44,7 @@ def test_register_parcellation_built_in_check() -> None:
36
44
  name="SUITxSUIT",
37
45
  parcellation_path="testparc.nii.gz",
38
46
  parcels_labels=["1", "2", "3"],
47
+ space="SUIT",
39
48
  overwrite=True,
40
49
  )
41
50
 
@@ -53,6 +62,7 @@ def test_register_parcellation_already_registered() -> None:
53
62
  name="testparc",
54
63
  parcellation_path="testparc.nii.gz",
55
64
  parcels_labels=["1", "2", "3"],
65
+ space="MNI152Lin",
56
66
  )
57
67
  assert (
58
68
  load_parcellation("testparc", path_only=True)[2].name
@@ -65,11 +75,13 @@ def test_register_parcellation_already_registered() -> None:
65
75
  name="testparc",
66
76
  parcellation_path="testparc.nii.gz",
67
77
  parcels_labels=["1", "2", "3"],
78
+ space="MNI152Lin",
68
79
  )
69
80
  register_parcellation(
70
81
  name="testparc",
71
82
  parcellation_path="testparc2.nii.gz",
72
83
  parcels_labels=["1", "2", "3"],
84
+ space="MNI152Lin",
73
85
  overwrite=True,
74
86
  )
75
87
 
@@ -86,18 +98,23 @@ def test_parcellation_wrong_labels_values(tmp_path: Path) -> None:
86
98
  ----------
87
99
  tmp_path : pathlib.Path
88
100
  The path to the test directory.
101
+
89
102
  """
90
- schaefer, labels, schaefer_path = load_parcellation("Schaefer100x7")
103
+ schaefer, labels, schaefer_path, _ = load_parcellation("Schaefer100x7")
91
104
  assert schaefer is not None
92
105
 
93
106
  # Test wrong number of labels
94
- register_parcellation("WrongLabels", schaefer_path, labels[:10])
107
+ register_parcellation(
108
+ "WrongLabels", schaefer_path, labels[:10], "MNI152Lin"
109
+ )
95
110
 
96
111
  with pytest.raises(ValueError, match=r"has 100 parcels but 10"):
97
112
  load_parcellation("WrongLabels")
98
113
 
99
114
  # Test wrong number of labels
100
- register_parcellation("WrongLabels2", schaefer_path, [*labels, "wrong"])
115
+ register_parcellation(
116
+ "WrongLabels2", schaefer_path, [*labels, "wrong"], "MNI152Lin"
117
+ )
101
118
 
102
119
  with pytest.raises(ValueError, match=r"has 100 parcels but 101"):
103
120
  load_parcellation("WrongLabels2")
@@ -108,7 +125,9 @@ def test_parcellation_wrong_labels_values(tmp_path: Path) -> None:
108
125
  new_schaefer_img = new_img_like(schaefer, schaefer_data)
109
126
  nib.save(new_schaefer_img, new_schaefer_path)
110
127
 
111
- register_parcellation("WrongValues", new_schaefer_path, labels[:-1])
128
+ register_parcellation(
129
+ "WrongValues", new_schaefer_path, labels[:-1], "MNI152Lin"
130
+ )
112
131
  with pytest.raises(ValueError, match=r"the range [0, 99]"):
113
132
  load_parcellation("WrongValues")
114
133
 
@@ -118,23 +137,44 @@ def test_parcellation_wrong_labels_values(tmp_path: Path) -> None:
118
137
  new_schaefer_img = new_img_like(schaefer, schaefer_data)
119
138
  nib.save(new_schaefer_img, new_schaefer_path)
120
139
 
121
- register_parcellation("WrongValues2", new_schaefer_path, labels)
140
+ register_parcellation(
141
+ "WrongValues2", new_schaefer_path, labels, "MNI152Lin"
142
+ )
122
143
  with pytest.raises(ValueError, match=r"the range [0, 100]"):
123
144
  load_parcellation("WrongValues2")
124
145
 
125
146
 
126
147
  @pytest.mark.parametrize(
127
- "name, parcellation_path, parcels_labels, overwrite",
148
+ "name, parcellation_path, parcels_labels, space, overwrite",
128
149
  [
129
- ("testparc_1", "testparc_1.nii.gz", ["1", "2", "3"], True),
130
- ("testparc_2", "testparc_2.nii.gz", ["1", "2", "6"], True),
131
- ("testparc_3", Path("testparc_3.nii.gz"), ["1", "2", "6"], True),
150
+ (
151
+ "testparc_1",
152
+ "testparc_1.nii.gz",
153
+ ["1", "2", "3"],
154
+ "MNI152Lin",
155
+ True,
156
+ ),
157
+ (
158
+ "testparc_2",
159
+ "testparc_2.nii.gz",
160
+ ["1", "2", "6"],
161
+ "MNI152Lin",
162
+ True,
163
+ ),
164
+ (
165
+ "testparc_3",
166
+ Path("testparc_3.nii.gz"),
167
+ ["1", "2", "6"],
168
+ "MNI152Lin",
169
+ True,
170
+ ),
132
171
  ],
133
172
  )
134
173
  def test_register_parcellation(
135
174
  name: str,
136
175
  parcellation_path: str,
137
176
  parcels_labels: List[str],
177
+ space: str,
138
178
  overwrite: bool,
139
179
  ) -> None:
140
180
  """Test parcellation registration.
@@ -147,6 +187,8 @@ def test_register_parcellation(
147
187
  The parametrized parcellation path.
148
188
  parcels_labels : list of str
149
189
  The parametrized parcellation labels.
190
+ space : str
191
+ The parametrized parcellation space.
150
192
  overwrite : bool
151
193
  The parametrized parcellation overwrite value.
152
194
 
@@ -156,16 +198,20 @@ def test_register_parcellation(
156
198
  name=name,
157
199
  parcellation_path=parcellation_path,
158
200
  parcels_labels=parcels_labels,
201
+ space=space,
159
202
  overwrite=overwrite,
160
203
  )
161
204
  # List available parcellation and check registration
162
205
  parcellations = list_parcellations()
163
206
  assert name in parcellations
164
207
  # Load registered parcellation
165
- _, lbl, fname = load_parcellation(name=name, path_only=True)
208
+ _, lbl, fname, parcellation_space = load_parcellation(
209
+ name=name, path_only=True
210
+ )
166
211
  # Check values for registered parcellation
167
212
  assert lbl == parcels_labels
168
213
  assert fname.name == f"{name}.nii.gz"
214
+ assert parcellation_space == space
169
215
 
170
216
 
171
217
  @pytest.mark.parametrize(
@@ -281,7 +327,7 @@ def test_schaefer(
281
327
  f"{int(resolution)}mm.nii.gz"
282
328
  )
283
329
  # Load parcellation
284
- img, label, img_path = load_parcellation(
330
+ img, label, img_path, space = load_parcellation(
285
331
  name=parcellation_name,
286
332
  parcellations_dir=tmp_path,
287
333
  resolution=resolution,
@@ -289,6 +335,7 @@ def test_schaefer(
289
335
  assert img is not None
290
336
  assert img_path.name == parcellation_file
291
337
  assert len(label) == n_rois
338
+ assert space == "MNI152NLin6Asym"
292
339
  assert_array_equal(
293
340
  img.header["pixdim"][1:4], 3 * [resolution] # type: ignore
294
341
  )
@@ -331,29 +378,32 @@ def test_retrieve_schaefer_incorrect_yeo_networks(tmp_path: Path) -> None:
331
378
 
332
379
 
333
380
  @pytest.mark.parametrize(
334
- "space",
335
- ["SUIT", "MNI"],
381
+ "space_key, space",
382
+ [("SUIT", "SUIT"), ("MNI", "MNI152NLin6Asym")],
336
383
  )
337
- def test_suit(tmp_path: Path, space: str) -> None:
384
+ def test_suit(tmp_path: Path, space_key: str, space: str) -> None:
338
385
  """Test SUIT parcellation.
339
386
 
340
387
  Parameters
341
388
  ----------
342
389
  tmp_path : pathlib.Path
343
390
  The path to the test directory.
391
+ space_key : str
392
+ The parametrized space values for the key.
344
393
  space : str
345
394
  The parametrized space values.
346
395
 
347
396
  """
348
397
  parcellations = list_parcellations()
349
- assert f"SUITx{space}" in parcellations
398
+ assert f"SUITx{space_key}" in parcellations
350
399
  # Load parcellation
351
- img, label, img_path = load_parcellation(
352
- name=f"SUITx{space}",
400
+ img, label, img_path, parcellation_space = load_parcellation(
401
+ name=f"SUITx{space_key}",
353
402
  parcellations_dir=tmp_path,
354
403
  )
355
404
  assert img is not None
356
- assert img_path.name == f"SUIT_{space}Space_1mm.nii"
405
+ assert img_path.name == f"SUIT_{space_key}Space_1mm.nii"
406
+ assert parcellation_space == space
357
407
  assert len(label) == 34
358
408
  assert_array_equal(img.header["pixdim"][1:4], [1, 1, 1]) # type: ignore
359
409
 
@@ -397,16 +447,17 @@ def test_tian_3T_6thgeneration(
397
447
  assert "TianxS3x3TxMNI6thgeneration" in parcellations
398
448
  assert "TianxS4x3TxMNI6thgeneration" in parcellations
399
449
  # Load parcellation
400
- img, lbl, fname = load_parcellation(
450
+ img, lbl, fname, parcellation_space_1 = load_parcellation(
401
451
  name=f"TianxS{scale}x3TxMNI6thgeneration", parcellations_dir=tmp_path
402
452
  )
403
453
  fname1 = f"Tian_Subcortex_S{scale}_3T_1mm.nii.gz"
404
454
  assert img is not None
405
455
  assert fname.name == fname1
456
+ assert parcellation_space_1 == "MNI152NLin6Asym"
406
457
  assert len(lbl) == n_label
407
458
  assert_array_equal(img.header["pixdim"][1:4], [1, 1, 1]) # type: ignore
408
459
  # Load parcellation
409
- img, lbl, fname = load_parcellation(
460
+ img, lbl, fname, parcellation_space_2 = load_parcellation(
410
461
  name=f"TianxS{scale}x3TxMNI6thgeneration",
411
462
  parcellations_dir=tmp_path,
412
463
  resolution=2,
@@ -414,6 +465,7 @@ def test_tian_3T_6thgeneration(
414
465
  fname1 = f"Tian_Subcortex_S{scale}_3T.nii.gz"
415
466
  assert img is not None
416
467
  assert fname.name == fname1
468
+ assert parcellation_space_2 == "MNI152NLin6Asym"
417
469
  assert len(lbl) == n_label
418
470
  assert_array_equal(img.header["pixdim"][1:4], [2, 2, 2]) # type: ignore
419
471
 
@@ -442,13 +494,14 @@ def test_tian_3T_nonlinear2009cAsym(
442
494
  assert "TianxS3x3TxMNInonlinear2009cAsym" in parcellations
443
495
  assert "TianxS4x3TxMNInonlinear2009cAsym" in parcellations
444
496
  # Load parcellation
445
- img, lbl, fname = load_parcellation(
497
+ img, lbl, fname, space = load_parcellation(
446
498
  name=f"TianxS{scale}x3TxMNInonlinear2009cAsym",
447
499
  parcellations_dir=tmp_path,
448
500
  )
449
501
  fname1 = f"Tian_Subcortex_S{scale}_3T_2009cAsym.nii.gz"
450
502
  assert img is not None
451
503
  assert fname.name == fname1
504
+ assert space == "MNI152NLin2009cAsym"
452
505
  assert len(lbl) == n_label
453
506
  assert_array_equal(img.header["pixdim"][1:4], [2, 2, 2]) # type: ignore
454
507
 
@@ -477,12 +530,13 @@ def test_tian_7T_6thgeneration(
477
530
  assert "TianxS3x7TxMNI6thgeneration" in parcellations
478
531
  assert "TianxS4x7TxMNI6thgeneration" in parcellations
479
532
  # Load parcellation
480
- img, lbl, fname = load_parcellation(
533
+ img, lbl, fname, space = load_parcellation(
481
534
  name=f"TianxS{scale}x7TxMNI6thgeneration", parcellations_dir=tmp_path
482
535
  )
483
536
  fname1 = f"Tian_Subcortex_S{scale}_7T.nii.gz"
484
537
  assert img is not None
485
538
  assert fname.name == fname1
539
+ assert space == "MNI152NLin6Asym"
486
540
  assert len(lbl) == n_label
487
541
  assert_array_almost_equal(
488
542
  img.header["pixdim"][1:4], [1.6, 1.6, 1.6] # type: ignore
@@ -503,13 +557,13 @@ def test_retrieve_tian_incorrect_space(tmp_path: Path) -> None:
503
557
  parcellations_dir=tmp_path, resolution=1, scale=1, space="wrong"
504
558
  )
505
559
 
506
- with pytest.raises(ValueError, match=r"MNI6thgeneration"):
560
+ with pytest.raises(ValueError, match=r"MNI152NLin6Asym"):
507
561
  _retrieve_tian(
508
562
  parcellations_dir=tmp_path,
509
563
  resolution=1,
510
564
  scale=1,
511
565
  magneticfield="7T",
512
- space="MNInonlinear2009cAsym",
566
+ space="MNI152NLin2009cAsym",
513
567
  )
514
568
 
515
569
 
@@ -545,7 +599,7 @@ def test_retrieve_tian_incorrect_scale(tmp_path: Path) -> None:
545
599
  parcellations_dir=tmp_path,
546
600
  resolution=1,
547
601
  scale=5,
548
- space="MNI6thgeneration",
602
+ space="MNI152NLin6Asym",
549
603
  )
550
604
 
551
605
 
@@ -564,11 +618,12 @@ def test_aicha(tmp_path: Path, version: int) -> None:
564
618
  parcellations = list_parcellations()
565
619
  assert f"AICHA_v{version}" in parcellations
566
620
  # Load parcellation
567
- img, label, img_path = load_parcellation(
621
+ img, label, img_path, space = load_parcellation(
568
622
  name=f"AICHA_v{version}", parcellations_dir=tmp_path
569
623
  )
570
624
  assert img is not None
571
625
  assert img_path.name == "AICHA.nii"
626
+ assert space == "IXI549Space"
572
627
  assert len(label) == 384
573
628
  assert_array_equal(img.header["pixdim"][1:4], [2, 2, 2]) # type: ignore
574
629
 
@@ -632,13 +687,14 @@ def test_shen(
632
687
  parcellations = list_parcellations()
633
688
  assert f"Shen_{year}_{n_rois}" in parcellations
634
689
  # Load parcellation
635
- img, label, img_path = load_parcellation(
690
+ img, label, img_path, space = load_parcellation(
636
691
  name=f"Shen_{year}_{n_rois}",
637
692
  parcellations_dir=tmp_path,
638
693
  resolution=resolution,
639
694
  )
640
695
  assert img is not None
641
696
  assert img_name in img_path.name
697
+ assert space == "MNI152NLin2009cAsym"
642
698
  assert len(label) == n_labels
643
699
  assert_array_equal(
644
700
  img.header["pixdim"][1:4], 3 * [resolution] # type: ignore
@@ -827,13 +883,14 @@ def test_yan(
827
883
  f"{int(resolution)}mm.nii.gz"
828
884
  )
829
885
  # Load parcellation
830
- img, label, img_path = load_parcellation(
886
+ img, label, img_path, space = load_parcellation(
831
887
  name=parcellation_name, # type: ignore
832
888
  parcellations_dir=tmp_path,
833
889
  resolution=resolution,
834
890
  )
835
891
  assert img is not None
836
892
  assert img_path.name == parcellation_file # type: ignore
893
+ assert space == "MNI152NLin6Asym"
837
894
  assert len(label) == n_rois
838
895
  assert_array_equal(
839
896
  img.header["pixdim"][1:4], 3 * [resolution] # type: ignore
@@ -921,13 +978,84 @@ def test_retrieve_yan_incorrect_kong_networks(tmp_path: Path) -> None:
921
978
  )
922
979
 
923
980
 
981
+ @pytest.mark.parametrize(
982
+ "resolution, threshold",
983
+ [
984
+ (1.0, 0),
985
+ (1.0, 25),
986
+ (1.0, 50),
987
+ (1.25, 0),
988
+ (1.25, 25),
989
+ (1.25, 50),
990
+ (2, 0),
991
+ (2, 25),
992
+ (2, 50),
993
+ ],
994
+ )
995
+ def test_brainnetome(
996
+ tmp_path: Path,
997
+ resolution: float,
998
+ threshold: int,
999
+ ) -> None:
1000
+ """Test Brainnetome parcellation.
1001
+
1002
+ Parameters
1003
+ ----------
1004
+ tmp_path : pathlib.Path
1005
+ The path to the test directory.
1006
+ resolution : float
1007
+ The parametrized resolution values.
1008
+ threshold : int
1009
+ The parametrized threshold values.
1010
+
1011
+ """
1012
+ parcellations = list_parcellations()
1013
+ parcellation_name = f"Brainnetome_thr{threshold}"
1014
+ assert parcellation_name in parcellations
1015
+
1016
+ # Fix resolution
1017
+ if resolution in [1.0, 2.0]:
1018
+ resolution = int(resolution)
1019
+
1020
+ parcellation_file = f"BNA-maxprob-thr{threshold}-{resolution}mm.nii.gz"
1021
+ # Load parcellation
1022
+ img, label, img_path, space = load_parcellation(
1023
+ name=parcellation_name,
1024
+ parcellations_dir=tmp_path,
1025
+ resolution=resolution,
1026
+ )
1027
+ assert img is not None
1028
+ assert img_path.name == parcellation_file
1029
+ assert space == "MNI152NLin6Asym"
1030
+ assert len(label) == 246
1031
+ assert_array_equal(
1032
+ img.header["pixdim"][1:4], 3 * [resolution] # type: ignore
1033
+ )
1034
+
1035
+
1036
+ def test_retrieve_brainnetome_incorrect_threshold(tmp_path: Path) -> None:
1037
+ """Test retrieve Brainnetome with incorrect threshold.
1038
+
1039
+ Parameters
1040
+ ----------
1041
+ tmp_path : pathlib.Path
1042
+ The path to the test directory.
1043
+
1044
+ """
1045
+ with pytest.raises(ValueError, match="The parameter `threshold`"):
1046
+ _retrieve_brainnetome(
1047
+ parcellations_dir=tmp_path,
1048
+ threshold=100,
1049
+ )
1050
+
1051
+
924
1052
  def test_merge_parcellations() -> None:
925
1053
  """Test merging parcellations."""
926
1054
  # load some parcellations for testing
927
- schaefer_parcellation, schaefer_labels, _ = load_parcellation(
1055
+ schaefer_parcellation, schaefer_labels, _, _ = load_parcellation(
928
1056
  "Schaefer100x17"
929
1057
  )
930
- tian_parcellation, tian_labels, _ = load_parcellation(
1058
+ tian_parcellation, tian_labels, _, _ = load_parcellation(
931
1059
  "TianxS2x3TxMNInonlinear2009cAsym"
932
1060
  )
933
1061
  # prepare the list of the actual parcellations
@@ -960,7 +1088,7 @@ def test_merge_parcellations_3D_multiple_non_overlapping(
960
1088
 
961
1089
  """
962
1090
  # Get the testing parcellation
963
- parcellation, labels, _ = load_parcellation("Schaefer100x7")
1091
+ parcellation, labels, _, _ = load_parcellation("Schaefer100x7")
964
1092
 
965
1093
  assert parcellation is not None
966
1094
 
@@ -981,7 +1109,7 @@ def test_merge_parcellations_3D_multiple_non_overlapping(
981
1109
  names = ["high", "low"]
982
1110
  labels_lists = [labels1, labels2]
983
1111
 
984
- merged_parc, merged_labels = merge_parcellations(
1112
+ merged_parc, _ = merge_parcellations(
985
1113
  parcellation_list, names, labels_lists
986
1114
  )
987
1115
 
@@ -991,18 +1119,11 @@ def test_merge_parcellations_3D_multiple_non_overlapping(
991
1119
  assert len(np.unique(parc_data)) == 101 # 100 + 1 because background 0
992
1120
 
993
1121
 
994
- def test_merge_parcellations_3D_multiple_overlapping(tmp_path: Path) -> None:
995
- """Test merge_parcellations with multiple overlapping parcellations.
996
-
997
- Parameters
998
- ----------
999
- tmp_path : pathlib.Path
1000
- The path to the test directory.
1001
-
1002
- """
1122
+ def test_merge_parcellations_3D_multiple_overlapping() -> None:
1123
+ """Test merge_parcellations with multiple overlapping parcellations."""
1003
1124
 
1004
1125
  # Get the testing parcellation
1005
- parcellation, labels, _ = load_parcellation("Schaefer100x7")
1126
+ parcellation, labels, _, _ = load_parcellation("Schaefer100x7")
1006
1127
 
1007
1128
  assert parcellation is not None
1008
1129
 
@@ -1035,20 +1156,11 @@ def test_merge_parcellations_3D_multiple_overlapping(tmp_path: Path) -> None:
1035
1156
  assert len(np.unique(parc_data)) == 101 # 100 + 1 because background 0
1036
1157
 
1037
1158
 
1038
- def test_merge_parcellations_3D_multiple_duplicated_labels(
1039
- tmp_path: Path,
1040
- ) -> None:
1041
- """Test merge_parcellations with two parcellations with duplicated labels.
1042
-
1043
- Parameters
1044
- ----------
1045
- tmp_path : pathlib.Path
1046
- The path to the test directory.
1047
-
1048
- """
1159
+ def test_merge_parcellations_3D_multiple_duplicated_labels() -> None:
1160
+ """Test merge_parcellations with duplicated labels."""
1049
1161
 
1050
1162
  # Get the testing parcellation
1051
- parcellation, labels, _ = load_parcellation("Schaefer100x7")
1163
+ parcellation, labels, _, _ = load_parcellation("Schaefer100x7")
1052
1164
 
1053
1165
  assert parcellation is not None
1054
1166
 
@@ -1078,3 +1190,102 @@ def test_merge_parcellations_3D_multiple_duplicated_labels(
1078
1190
  assert_array_equal(parc_data, merged_parc.get_fdata())
1079
1191
  assert len(labels) == 100
1080
1192
  assert len(np.unique(parc_data)) == 101 # 100 + 1 because background 0
1193
+
1194
+
1195
+ def test_get_parcellation_single() -> None:
1196
+ """Test tailored single parcellation fetch."""
1197
+ with PartlyCloudyTestingDataGrabber() as dg:
1198
+ element_data = DefaultDataReader().fit_transform(dg["sub-01"])
1199
+ bold = element_data["BOLD"]
1200
+ bold_img = bold["data"]
1201
+ # Get tailored parcellation
1202
+ tailored_parcellation, tailored_labels = get_parcellation(
1203
+ parcellation=["TianxS1x3TxMNInonlinear2009cAsym"],
1204
+ target_data=bold,
1205
+ )
1206
+ # Check shape and affine with original element data
1207
+ assert tailored_parcellation.shape == bold_img.shape[:3]
1208
+ assert_array_equal(tailored_parcellation.affine, bold_img.affine)
1209
+ # Get raw parcellation
1210
+ raw_parcellation, raw_labels, _, _ = load_parcellation(
1211
+ "TianxS1x3TxMNInonlinear2009cAsym",
1212
+ resolution=1.5,
1213
+ )
1214
+ resampled_raw_parcellation = resample_to_img(
1215
+ source_img=raw_parcellation,
1216
+ target_img=bold_img,
1217
+ interpolation="nearest",
1218
+ copy=True,
1219
+ )
1220
+ # Check resampled data with tailored data
1221
+ assert_array_equal(
1222
+ tailored_parcellation.get_fdata(),
1223
+ resampled_raw_parcellation.get_fdata(),
1224
+ )
1225
+ assert tailored_labels == raw_labels
1226
+
1227
+
1228
+ def test_get_parcellation_multi_same_space() -> None:
1229
+ """Test tailored multi parcellation fetch in same space."""
1230
+ with PartlyCloudyTestingDataGrabber() as dg:
1231
+ element_data = DefaultDataReader().fit_transform(dg["sub-01"])
1232
+ bold = element_data["BOLD"]
1233
+ bold_img = bold["data"]
1234
+ # Get tailored parcellation
1235
+ tailored_parcellation, tailored_labels = get_parcellation(
1236
+ parcellation=[
1237
+ "Shen_2015_268",
1238
+ "TianxS1x3TxMNInonlinear2009cAsym",
1239
+ ],
1240
+ target_data=bold,
1241
+ )
1242
+ # Check shape and affine with original element data
1243
+ assert tailored_parcellation.shape == bold_img.shape[:3]
1244
+ assert_array_equal(tailored_parcellation.affine, bold_img.affine)
1245
+ # Get raw parcellations
1246
+ raw_parcellations = []
1247
+ raw_labels = []
1248
+ parcellations_names = [
1249
+ "Shen_2015_268",
1250
+ "TianxS1x3TxMNInonlinear2009cAsym",
1251
+ ]
1252
+ for name in parcellations_names:
1253
+ img, labels, _, _ = load_parcellation(name=name, resolution=1.5)
1254
+ # Resample raw parcellations
1255
+ resampled_img = resample_to_img(
1256
+ source_img=img,
1257
+ target_img=bold_img,
1258
+ interpolation="nearest",
1259
+ copy=True,
1260
+ )
1261
+ raw_parcellations.append(resampled_img)
1262
+ raw_labels.append(labels)
1263
+ # Merge resampled parcellations
1264
+ merged_resampled_parcellations, merged_labels = merge_parcellations(
1265
+ parcellations_list=raw_parcellations,
1266
+ parcellations_names=parcellations_names,
1267
+ labels_lists=raw_labels,
1268
+ )
1269
+ # Check resampled data with tailored data
1270
+ assert_array_equal(
1271
+ tailored_parcellation.get_fdata(),
1272
+ merged_resampled_parcellations.get_fdata(),
1273
+ )
1274
+ assert tailored_labels == merged_labels
1275
+
1276
+
1277
+ @pytest.mark.skipif(
1278
+ _check_ants() is False, reason="requires ANTs to be in PATH"
1279
+ )
1280
+ def test_get_parcellation_multi_different_space() -> None:
1281
+ """Test tailored multi parcellation fetch in different space."""
1282
+ with OasisVBMTestingDataGrabber() as dg:
1283
+ element_data = DefaultDataReader().fit_transform(dg["sub-01"])
1284
+ # Get tailored parcellation
1285
+ get_parcellation(
1286
+ parcellation=[
1287
+ "Schaefer100x7",
1288
+ "TianxS1x3TxMNInonlinear2009cAsym",
1289
+ ],
1290
+ target_data=element_data["VBM_GM"],
1291
+ )