junifer 0.0.5.dev242__py3-none-any.whl → 0.0.6__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 (279) hide show
  1. junifer/__init__.py +2 -31
  2. junifer/__init__.pyi +37 -0
  3. junifer/_version.py +9 -4
  4. junifer/api/__init__.py +3 -5
  5. junifer/api/__init__.pyi +4 -0
  6. junifer/api/decorators.py +14 -19
  7. junifer/api/functions.py +165 -109
  8. junifer/api/py.typed +0 -0
  9. junifer/api/queue_context/__init__.py +2 -4
  10. junifer/api/queue_context/__init__.pyi +5 -0
  11. junifer/api/queue_context/gnu_parallel_local_adapter.py +22 -6
  12. junifer/api/queue_context/htcondor_adapter.py +23 -6
  13. junifer/api/queue_context/py.typed +0 -0
  14. junifer/api/queue_context/tests/test_gnu_parallel_local_adapter.py +3 -3
  15. junifer/api/queue_context/tests/test_htcondor_adapter.py +3 -3
  16. junifer/api/tests/test_functions.py +168 -74
  17. junifer/cli/__init__.py +24 -0
  18. junifer/cli/__init__.pyi +3 -0
  19. junifer/{api → cli}/cli.py +141 -125
  20. junifer/cli/parser.py +235 -0
  21. junifer/cli/py.typed +0 -0
  22. junifer/{api → cli}/tests/test_cli.py +8 -8
  23. junifer/{api/tests/test_api_utils.py → cli/tests/test_cli_utils.py} +5 -4
  24. junifer/{api → cli}/tests/test_parser.py +2 -2
  25. junifer/{api → cli}/utils.py +6 -16
  26. junifer/configs/juseless/__init__.py +2 -2
  27. junifer/configs/juseless/__init__.pyi +3 -0
  28. junifer/configs/juseless/datagrabbers/__init__.py +2 -12
  29. junifer/configs/juseless/datagrabbers/__init__.pyi +13 -0
  30. junifer/configs/juseless/datagrabbers/ixi_vbm.py +2 -2
  31. junifer/configs/juseless/datagrabbers/py.typed +0 -0
  32. junifer/configs/juseless/datagrabbers/tests/test_ucla.py +2 -2
  33. junifer/configs/juseless/datagrabbers/ucla.py +4 -4
  34. junifer/configs/juseless/py.typed +0 -0
  35. junifer/conftest.py +25 -0
  36. junifer/data/__init__.py +2 -42
  37. junifer/data/__init__.pyi +29 -0
  38. junifer/data/_dispatch.py +248 -0
  39. junifer/data/coordinates/__init__.py +9 -0
  40. junifer/data/coordinates/__init__.pyi +5 -0
  41. junifer/data/coordinates/_ants_coordinates_warper.py +104 -0
  42. junifer/data/coordinates/_coordinates.py +385 -0
  43. junifer/data/coordinates/_fsl_coordinates_warper.py +81 -0
  44. junifer/data/{tests → coordinates/tests}/test_coordinates.py +26 -33
  45. junifer/data/masks/__init__.py +9 -0
  46. junifer/data/masks/__init__.pyi +6 -0
  47. junifer/data/masks/_ants_mask_warper.py +177 -0
  48. junifer/data/masks/_fsl_mask_warper.py +106 -0
  49. junifer/data/masks/_masks.py +802 -0
  50. junifer/data/{tests → masks/tests}/test_masks.py +67 -63
  51. junifer/data/parcellations/__init__.py +9 -0
  52. junifer/data/parcellations/__init__.pyi +6 -0
  53. junifer/data/parcellations/_ants_parcellation_warper.py +166 -0
  54. junifer/data/parcellations/_fsl_parcellation_warper.py +89 -0
  55. junifer/data/parcellations/_parcellations.py +1388 -0
  56. junifer/data/{tests → parcellations/tests}/test_parcellations.py +165 -295
  57. junifer/data/pipeline_data_registry_base.py +76 -0
  58. junifer/data/py.typed +0 -0
  59. junifer/data/template_spaces.py +44 -79
  60. junifer/data/tests/test_data_utils.py +1 -2
  61. junifer/data/tests/test_template_spaces.py +8 -4
  62. junifer/data/utils.py +109 -4
  63. junifer/datagrabber/__init__.py +2 -26
  64. junifer/datagrabber/__init__.pyi +27 -0
  65. junifer/datagrabber/aomic/__init__.py +2 -4
  66. junifer/datagrabber/aomic/__init__.pyi +5 -0
  67. junifer/datagrabber/aomic/id1000.py +81 -52
  68. junifer/datagrabber/aomic/piop1.py +83 -55
  69. junifer/datagrabber/aomic/piop2.py +85 -56
  70. junifer/datagrabber/aomic/py.typed +0 -0
  71. junifer/datagrabber/aomic/tests/test_id1000.py +19 -12
  72. junifer/datagrabber/aomic/tests/test_piop1.py +52 -18
  73. junifer/datagrabber/aomic/tests/test_piop2.py +50 -17
  74. junifer/datagrabber/base.py +22 -18
  75. junifer/datagrabber/datalad_base.py +71 -34
  76. junifer/datagrabber/dmcc13_benchmark.py +31 -18
  77. junifer/datagrabber/hcp1200/__init__.py +2 -3
  78. junifer/datagrabber/hcp1200/__init__.pyi +4 -0
  79. junifer/datagrabber/hcp1200/datalad_hcp1200.py +3 -3
  80. junifer/datagrabber/hcp1200/hcp1200.py +26 -15
  81. junifer/datagrabber/hcp1200/py.typed +0 -0
  82. junifer/datagrabber/hcp1200/tests/test_hcp1200.py +8 -2
  83. junifer/datagrabber/multiple.py +14 -9
  84. junifer/datagrabber/pattern.py +132 -96
  85. junifer/datagrabber/pattern_validation_mixin.py +206 -94
  86. junifer/datagrabber/py.typed +0 -0
  87. junifer/datagrabber/tests/test_datalad_base.py +27 -12
  88. junifer/datagrabber/tests/test_dmcc13_benchmark.py +28 -11
  89. junifer/datagrabber/tests/test_multiple.py +48 -2
  90. junifer/datagrabber/tests/test_pattern_datalad.py +1 -1
  91. junifer/datagrabber/tests/test_pattern_validation_mixin.py +6 -6
  92. junifer/datareader/__init__.py +2 -2
  93. junifer/datareader/__init__.pyi +3 -0
  94. junifer/datareader/default.py +6 -6
  95. junifer/datareader/py.typed +0 -0
  96. junifer/external/nilearn/__init__.py +2 -3
  97. junifer/external/nilearn/__init__.pyi +4 -0
  98. junifer/external/nilearn/junifer_connectivity_measure.py +25 -17
  99. junifer/external/nilearn/junifer_nifti_spheres_masker.py +4 -4
  100. junifer/external/nilearn/py.typed +0 -0
  101. junifer/external/nilearn/tests/test_junifer_connectivity_measure.py +17 -16
  102. junifer/external/nilearn/tests/test_junifer_nifti_spheres_masker.py +2 -3
  103. junifer/markers/__init__.py +2 -38
  104. junifer/markers/__init__.pyi +37 -0
  105. junifer/markers/base.py +11 -14
  106. junifer/markers/brainprint.py +12 -14
  107. junifer/markers/complexity/__init__.py +2 -18
  108. junifer/markers/complexity/__init__.pyi +17 -0
  109. junifer/markers/complexity/complexity_base.py +9 -11
  110. junifer/markers/complexity/hurst_exponent.py +7 -7
  111. junifer/markers/complexity/multiscale_entropy_auc.py +7 -7
  112. junifer/markers/complexity/perm_entropy.py +7 -7
  113. junifer/markers/complexity/py.typed +0 -0
  114. junifer/markers/complexity/range_entropy.py +7 -7
  115. junifer/markers/complexity/range_entropy_auc.py +7 -7
  116. junifer/markers/complexity/sample_entropy.py +7 -7
  117. junifer/markers/complexity/tests/test_complexity_base.py +1 -1
  118. junifer/markers/complexity/tests/test_hurst_exponent.py +5 -5
  119. junifer/markers/complexity/tests/test_multiscale_entropy_auc.py +5 -5
  120. junifer/markers/complexity/tests/test_perm_entropy.py +5 -5
  121. junifer/markers/complexity/tests/test_range_entropy.py +5 -5
  122. junifer/markers/complexity/tests/test_range_entropy_auc.py +5 -5
  123. junifer/markers/complexity/tests/test_sample_entropy.py +5 -5
  124. junifer/markers/complexity/tests/test_weighted_perm_entropy.py +5 -5
  125. junifer/markers/complexity/weighted_perm_entropy.py +7 -7
  126. junifer/markers/ets_rss.py +12 -11
  127. junifer/markers/falff/__init__.py +2 -3
  128. junifer/markers/falff/__init__.pyi +4 -0
  129. junifer/markers/falff/_afni_falff.py +38 -45
  130. junifer/markers/falff/_junifer_falff.py +16 -19
  131. junifer/markers/falff/falff_base.py +7 -11
  132. junifer/markers/falff/falff_parcels.py +9 -9
  133. junifer/markers/falff/falff_spheres.py +8 -8
  134. junifer/markers/falff/py.typed +0 -0
  135. junifer/markers/falff/tests/test_falff_spheres.py +3 -1
  136. junifer/markers/functional_connectivity/__init__.py +2 -12
  137. junifer/markers/functional_connectivity/__init__.pyi +13 -0
  138. junifer/markers/functional_connectivity/crossparcellation_functional_connectivity.py +9 -8
  139. junifer/markers/functional_connectivity/edge_functional_connectivity_parcels.py +8 -8
  140. junifer/markers/functional_connectivity/edge_functional_connectivity_spheres.py +7 -7
  141. junifer/markers/functional_connectivity/functional_connectivity_base.py +13 -12
  142. junifer/markers/functional_connectivity/functional_connectivity_parcels.py +8 -8
  143. junifer/markers/functional_connectivity/functional_connectivity_spheres.py +7 -7
  144. junifer/markers/functional_connectivity/py.typed +0 -0
  145. junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_parcels.py +1 -2
  146. junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_spheres.py +1 -2
  147. junifer/markers/functional_connectivity/tests/test_functional_connectivity_parcels.py +6 -6
  148. junifer/markers/functional_connectivity/tests/test_functional_connectivity_spheres.py +5 -5
  149. junifer/markers/parcel_aggregation.py +22 -17
  150. junifer/markers/py.typed +0 -0
  151. junifer/markers/reho/__init__.py +2 -3
  152. junifer/markers/reho/__init__.pyi +4 -0
  153. junifer/markers/reho/_afni_reho.py +29 -35
  154. junifer/markers/reho/_junifer_reho.py +13 -14
  155. junifer/markers/reho/py.typed +0 -0
  156. junifer/markers/reho/reho_base.py +7 -11
  157. junifer/markers/reho/reho_parcels.py +10 -10
  158. junifer/markers/reho/reho_spheres.py +9 -9
  159. junifer/markers/sphere_aggregation.py +22 -17
  160. junifer/markers/temporal_snr/__init__.py +2 -3
  161. junifer/markers/temporal_snr/__init__.pyi +4 -0
  162. junifer/markers/temporal_snr/py.typed +0 -0
  163. junifer/markers/temporal_snr/temporal_snr_base.py +11 -10
  164. junifer/markers/temporal_snr/temporal_snr_parcels.py +8 -8
  165. junifer/markers/temporal_snr/temporal_snr_spheres.py +7 -7
  166. junifer/markers/tests/test_ets_rss.py +3 -3
  167. junifer/markers/tests/test_parcel_aggregation.py +24 -24
  168. junifer/markers/tests/test_sphere_aggregation.py +6 -6
  169. junifer/markers/utils.py +3 -3
  170. junifer/onthefly/__init__.py +2 -1
  171. junifer/onthefly/_brainprint.py +138 -0
  172. junifer/onthefly/read_transform.py +5 -8
  173. junifer/pipeline/__init__.py +2 -10
  174. junifer/pipeline/__init__.pyi +13 -0
  175. junifer/{markers/collection.py → pipeline/marker_collection.py} +8 -14
  176. junifer/pipeline/pipeline_component_registry.py +294 -0
  177. junifer/pipeline/pipeline_step_mixin.py +15 -11
  178. junifer/pipeline/py.typed +0 -0
  179. junifer/{markers/tests/test_collection.py → pipeline/tests/test_marker_collection.py} +2 -3
  180. junifer/pipeline/tests/test_pipeline_component_registry.py +200 -0
  181. junifer/pipeline/tests/test_pipeline_step_mixin.py +36 -37
  182. junifer/pipeline/tests/test_update_meta_mixin.py +4 -4
  183. junifer/pipeline/tests/test_workdir_manager.py +43 -0
  184. junifer/pipeline/update_meta_mixin.py +21 -17
  185. junifer/pipeline/utils.py +6 -6
  186. junifer/pipeline/workdir_manager.py +19 -5
  187. junifer/preprocess/__init__.py +2 -10
  188. junifer/preprocess/__init__.pyi +11 -0
  189. junifer/preprocess/base.py +10 -10
  190. junifer/preprocess/confounds/__init__.py +2 -2
  191. junifer/preprocess/confounds/__init__.pyi +3 -0
  192. junifer/preprocess/confounds/fmriprep_confound_remover.py +243 -64
  193. junifer/preprocess/confounds/py.typed +0 -0
  194. junifer/preprocess/confounds/tests/test_fmriprep_confound_remover.py +121 -14
  195. junifer/preprocess/py.typed +0 -0
  196. junifer/preprocess/smoothing/__init__.py +2 -2
  197. junifer/preprocess/smoothing/__init__.pyi +3 -0
  198. junifer/preprocess/smoothing/_afni_smoothing.py +40 -40
  199. junifer/preprocess/smoothing/_fsl_smoothing.py +22 -32
  200. junifer/preprocess/smoothing/_nilearn_smoothing.py +35 -14
  201. junifer/preprocess/smoothing/py.typed +0 -0
  202. junifer/preprocess/smoothing/smoothing.py +11 -13
  203. junifer/preprocess/warping/__init__.py +2 -2
  204. junifer/preprocess/warping/__init__.pyi +3 -0
  205. junifer/preprocess/warping/_ants_warper.py +136 -32
  206. junifer/preprocess/warping/_fsl_warper.py +73 -22
  207. junifer/preprocess/warping/py.typed +0 -0
  208. junifer/preprocess/warping/space_warper.py +39 -11
  209. junifer/preprocess/warping/tests/test_space_warper.py +5 -9
  210. junifer/py.typed +0 -0
  211. junifer/stats.py +5 -5
  212. junifer/storage/__init__.py +2 -10
  213. junifer/storage/__init__.pyi +11 -0
  214. junifer/storage/base.py +47 -13
  215. junifer/storage/hdf5.py +95 -33
  216. junifer/storage/pandas_base.py +12 -11
  217. junifer/storage/py.typed +0 -0
  218. junifer/storage/sqlite.py +11 -11
  219. junifer/storage/tests/test_hdf5.py +86 -4
  220. junifer/storage/tests/test_sqlite.py +2 -2
  221. junifer/storage/tests/test_storage_base.py +5 -2
  222. junifer/storage/tests/test_utils.py +33 -7
  223. junifer/storage/utils.py +95 -9
  224. junifer/testing/__init__.py +2 -3
  225. junifer/testing/__init__.pyi +4 -0
  226. junifer/testing/datagrabbers.py +10 -11
  227. junifer/testing/py.typed +0 -0
  228. junifer/testing/registry.py +4 -7
  229. junifer/testing/tests/test_testing_registry.py +9 -17
  230. junifer/tests/test_stats.py +2 -2
  231. junifer/typing/__init__.py +9 -0
  232. junifer/typing/__init__.pyi +31 -0
  233. junifer/typing/_typing.py +68 -0
  234. junifer/utils/__init__.py +2 -12
  235. junifer/utils/__init__.pyi +18 -0
  236. junifer/utils/_config.py +110 -0
  237. junifer/utils/_yaml.py +16 -0
  238. junifer/utils/helpers.py +6 -6
  239. junifer/utils/logging.py +117 -8
  240. junifer/utils/py.typed +0 -0
  241. junifer/{pipeline → utils}/singleton.py +19 -14
  242. junifer/utils/tests/test_config.py +59 -0
  243. {junifer-0.0.5.dev242.dist-info → junifer-0.0.6.dist-info}/METADATA +43 -38
  244. junifer-0.0.6.dist-info/RECORD +350 -0
  245. {junifer-0.0.5.dev242.dist-info → junifer-0.0.6.dist-info}/WHEEL +1 -1
  246. junifer-0.0.6.dist-info/entry_points.txt +2 -0
  247. junifer/api/parser.py +0 -118
  248. junifer/data/coordinates.py +0 -408
  249. junifer/data/masks.py +0 -670
  250. junifer/data/parcellations.py +0 -1828
  251. junifer/pipeline/registry.py +0 -177
  252. junifer/pipeline/tests/test_registry.py +0 -150
  253. junifer-0.0.5.dev242.dist-info/RECORD +0 -275
  254. junifer-0.0.5.dev242.dist-info/entry_points.txt +0 -2
  255. /junifer/{api → cli}/tests/data/gmd_mean.yaml +0 -0
  256. /junifer/{api → cli}/tests/data/gmd_mean_htcondor.yaml +0 -0
  257. /junifer/{api → cli}/tests/data/partly_cloudy_agg_mean_tian.yml +0 -0
  258. /junifer/data/{VOIs → coordinates/VOIs}/meta/AutobiographicalMemory_VOIs.txt +0 -0
  259. /junifer/data/{VOIs → coordinates/VOIs}/meta/CogAC_VOIs.txt +0 -0
  260. /junifer/data/{VOIs → coordinates/VOIs}/meta/CogAR_VOIs.txt +0 -0
  261. /junifer/data/{VOIs → coordinates/VOIs}/meta/DMNBuckner_VOIs.txt +0 -0
  262. /junifer/data/{VOIs → coordinates/VOIs}/meta/Dosenbach2010_MNI_VOIs.txt +0 -0
  263. /junifer/data/{VOIs → coordinates/VOIs}/meta/Empathy_VOIs.txt +0 -0
  264. /junifer/data/{VOIs → coordinates/VOIs}/meta/Motor_VOIs.txt +0 -0
  265. /junifer/data/{VOIs → coordinates/VOIs}/meta/MultiTask_VOIs.txt +0 -0
  266. /junifer/data/{VOIs → coordinates/VOIs}/meta/PhysioStress_VOIs.txt +0 -0
  267. /junifer/data/{VOIs → coordinates/VOIs}/meta/Power2011_MNI_VOIs.txt +0 -0
  268. /junifer/data/{VOIs → coordinates/VOIs}/meta/Power2013_MNI_VOIs.tsv +0 -0
  269. /junifer/data/{VOIs → coordinates/VOIs}/meta/Rew_VOIs.txt +0 -0
  270. /junifer/data/{VOIs → coordinates/VOIs}/meta/Somatosensory_VOIs.txt +0 -0
  271. /junifer/data/{VOIs → coordinates/VOIs}/meta/ToM_VOIs.txt +0 -0
  272. /junifer/data/{VOIs → coordinates/VOIs}/meta/VigAtt_VOIs.txt +0 -0
  273. /junifer/data/{VOIs → coordinates/VOIs}/meta/WM_VOIs.txt +0 -0
  274. /junifer/data/{VOIs → coordinates/VOIs}/meta/eMDN_VOIs.txt +0 -0
  275. /junifer/data/{VOIs → coordinates/VOIs}/meta/eSAD_VOIs.txt +0 -0
  276. /junifer/data/{VOIs → coordinates/VOIs}/meta/extDMN_VOIs.txt +0 -0
  277. {junifer-0.0.5.dev242.dist-info → junifer-0.0.6.dist-info/licenses}/AUTHORS.rst +0 -0
  278. {junifer-0.0.5.dev242.dist-info → junifer-0.0.6.dist-info/licenses}/LICENSE.md +0 -0
  279. {junifer-0.0.5.dev242.dist-info → junifer-0.0.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,248 @@
1
+ """Provide dispatch functions for pipeline data registries."""
2
+
3
+ # Authors: Synchon Mandal <s.mandal@fz-juelich.de>
4
+ # License: AGPL
5
+
6
+ from pathlib import Path
7
+ from typing import (
8
+ TYPE_CHECKING,
9
+ Any,
10
+ Callable,
11
+ Optional,
12
+ Union,
13
+ )
14
+
15
+ from numpy.typing import ArrayLike
16
+
17
+ from ..utils import raise_error
18
+ from .coordinates import CoordinatesRegistry
19
+ from .masks import MaskRegistry
20
+ from .parcellations import ParcellationRegistry
21
+
22
+
23
+ if TYPE_CHECKING:
24
+ from nibabel.nifti1 import Nifti1Image
25
+
26
+
27
+ __all__ = [
28
+ "deregister_data",
29
+ "get_data",
30
+ "list_data",
31
+ "load_data",
32
+ "register_data",
33
+ ]
34
+
35
+
36
+ def get_data(
37
+ kind: str,
38
+ names: Union[
39
+ str, # coordinates, parcellation, mask
40
+ list[str], # parcellation, mask
41
+ dict, # mask
42
+ list[dict], # mask
43
+ ],
44
+ target_data: dict[str, Any],
45
+ extra_input: Optional[dict[str, Any]] = None,
46
+ ) -> Union[
47
+ tuple[ArrayLike, list[str]], # coordinates
48
+ tuple["Nifti1Image", list[str]], # parcellation
49
+ "Nifti1Image", # mask
50
+ ]:
51
+ """Get tailored ``kind`` for ``target_data``.
52
+
53
+ Parameters
54
+ ----------
55
+ kind : {"coordinates", "parcellation", "mask"}
56
+ Kind of data to fetch and apply.
57
+ names : str or dict or list of str / dict
58
+ The registered name(s) of the data.
59
+ target_data : dict
60
+ The corresponding item of the data object to which the data
61
+ will be applied.
62
+ extra_input : dict, optional
63
+ The other fields in the data object. Useful for accessing other
64
+ data types that need to be used in the computation of data
65
+ (default None).
66
+
67
+ Returns
68
+ -------
69
+ tuple of numpy.ndarray, list of str; \
70
+ tuple of nibabel.nifti1.Nifti1Image, list of str; \
71
+ nibabel.nifti1.Nifti1Image
72
+
73
+ Raises
74
+ ------
75
+ ValueError
76
+ If ``kind`` is invalid value.
77
+
78
+ """
79
+
80
+ if kind == "coordinates":
81
+ return CoordinatesRegistry().get(
82
+ coords=names,
83
+ target_data=target_data,
84
+ extra_input=extra_input,
85
+ )
86
+ elif kind == "parcellation":
87
+ return ParcellationRegistry().get(
88
+ parcellations=names,
89
+ target_data=target_data,
90
+ extra_input=extra_input,
91
+ )
92
+ elif kind == "mask":
93
+ return MaskRegistry().get(
94
+ masks=names,
95
+ target_data=target_data,
96
+ extra_input=extra_input,
97
+ )
98
+ else:
99
+ raise_error(f"Unknown data kind: {kind}")
100
+
101
+
102
+ def list_data(kind: str) -> list[str]:
103
+ """List available data for ``kind``.
104
+
105
+ Parameters
106
+ ----------
107
+ kind : {"coordinates", "parcellation", "mask"}
108
+ Kind of data registry to list.
109
+
110
+ Returns
111
+ -------
112
+ list of str
113
+ Available data for the registry.
114
+
115
+ Raises
116
+ ------
117
+ ValueError
118
+ If ``kind`` is invalid value.
119
+
120
+ """
121
+
122
+ if kind == "coordinates":
123
+ return CoordinatesRegistry().list
124
+ elif kind == "parcellation":
125
+ return ParcellationRegistry().list
126
+ elif kind == "mask":
127
+ return MaskRegistry().list
128
+ else:
129
+ raise_error(f"Unknown data kind: {kind}")
130
+
131
+
132
+ def load_data(
133
+ kind: str,
134
+ name: str,
135
+ **kwargs,
136
+ ) -> Union[
137
+ tuple[ArrayLike, list[str], str], # coordinates
138
+ tuple[Optional["Nifti1Image"], list[str], Path, str], # parcellation
139
+ tuple[
140
+ Optional[Union["Nifti1Image", Callable]], Optional[Path], str
141
+ ], # mask
142
+ ]:
143
+ """Load ``kind`` named ``name``.
144
+
145
+ Parameters
146
+ ----------
147
+ kind : {"coordinates", "parcellation", "mask"}
148
+ Kind of data to load.
149
+ name : str
150
+ The registered name of the data.
151
+ **kwargs
152
+ Keyword arguments are passed to respective registry class method.
153
+
154
+ Returns
155
+ -------
156
+ tuple of numpy.ndarray, list of str, str; \
157
+ tuple of nibabel.nifti1.Nifti1Image or None, \
158
+ list of str, pathlib.Path, str; \
159
+ tuple of nibabel.nifti1.Nifti1Image or callable or None, \
160
+ pathlib.Path or None, str
161
+
162
+ Raises
163
+ ------
164
+ ValueError
165
+ If ``kind`` is invalid value.
166
+
167
+ """
168
+
169
+ if kind == "coordinates":
170
+ return CoordinatesRegistry().load(name=name)
171
+ elif kind == "parcellation":
172
+ return ParcellationRegistry().load(name=name, **kwargs)
173
+ elif kind == "mask":
174
+ return MaskRegistry().load(name=name, **kwargs)
175
+ else:
176
+ raise_error(f"Unknown data kind: {kind}")
177
+
178
+
179
+ def register_data(
180
+ kind: str,
181
+ name: str,
182
+ space: str,
183
+ overwrite: bool = False,
184
+ **kwargs,
185
+ ) -> None:
186
+ """Register ``name`` under ``kind``.
187
+
188
+ Parameters
189
+ ----------
190
+ kind : {"coordinates", "parcellation", "mask"}
191
+ Kind of data to register.
192
+ name : str
193
+ The name to register.
194
+ space : str
195
+ The template space of the data.
196
+ overwrite : bool, optional
197
+ If True, overwrite an existing data with the same name.
198
+ **kwargs
199
+ Keyword arguments are passed to respective registry class method.
200
+
201
+ Raises
202
+ ------
203
+ ValueError
204
+ If ``kind`` is invalid value.
205
+
206
+ """
207
+
208
+ if kind == "coordinates":
209
+ return CoordinatesRegistry().register(
210
+ name=name, space=space, overwrite=overwrite, **kwargs
211
+ )
212
+ elif kind == "parcellation":
213
+ return ParcellationRegistry().register(
214
+ name=name, space=space, overwrite=overwrite, **kwargs
215
+ )
216
+ elif kind == "mask":
217
+ return MaskRegistry().register(
218
+ name=name, space=space, overwrite=overwrite, **kwargs
219
+ )
220
+ else:
221
+ raise_error(f"Unknown data kind: {kind}")
222
+
223
+
224
+ def deregister_data(kind: str, name: str) -> None:
225
+ """De-register ``name`` from ``kind``.
226
+
227
+ Parameters
228
+ ----------
229
+ kind : {"coordinates", "parcellation", "mask"}
230
+ Kind of data to register.
231
+ name : str
232
+ The name to de-register.
233
+
234
+ Raises
235
+ ------
236
+ ValueError
237
+ If ``kind`` is invalid value.
238
+
239
+ """
240
+
241
+ if kind == "coordinates":
242
+ return CoordinatesRegistry().deregister(name=name)
243
+ elif kind == "parcellation":
244
+ return ParcellationRegistry().deregister(name=name)
245
+ elif kind == "mask":
246
+ return MaskRegistry().deregister(name=name)
247
+ else:
248
+ raise_error(f"Unknown data kind: {kind}")
@@ -0,0 +1,9 @@
1
+ """Coordinates."""
2
+
3
+ # Authors: Synchon Mandal <s.mandal@fz-juelich.de>
4
+ # License: AGPL
5
+
6
+ import lazy_loader as lazy
7
+
8
+
9
+ __getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
@@ -0,0 +1,5 @@
1
+ __all__ = [
2
+ "CoordinatesRegistry",
3
+ ]
4
+
5
+ from ._coordinates import CoordinatesRegistry
@@ -0,0 +1,104 @@
1
+ """Provide class for coordinates space warping via ANTs."""
2
+
3
+ # Authors: Synchon Mandal <s.mandal@fz-juelich.de>
4
+ # License: AGPL
5
+
6
+ from typing import Any
7
+
8
+ import numpy as np
9
+ from numpy.typing import ArrayLike
10
+
11
+ from ...pipeline import WorkDirManager
12
+ from ...utils import logger, run_ext_cmd
13
+
14
+
15
+ __all__ = ["ANTsCoordinatesWarper"]
16
+
17
+
18
+ class ANTsCoordinatesWarper:
19
+ """Class for coordinates space warping via ANTs.
20
+
21
+ This class uses ANTs ``antsApplyTransformsToPoints`` for transformation.
22
+
23
+ """
24
+
25
+ def warp(
26
+ self,
27
+ seeds: ArrayLike,
28
+ target_data: dict[str, Any],
29
+ warp_data: dict[str, Any],
30
+ ) -> ArrayLike:
31
+ """Warp ``seeds`` to correct space.
32
+
33
+ Parameters
34
+ ----------
35
+ seeds : array-like
36
+ The coordinates to transform.
37
+ target_data : dict
38
+ The corresponding item of the data object to which the coordinates
39
+ will be applied.
40
+ warp_data : dict or None
41
+ The warp data item of the data object.
42
+
43
+ Returns
44
+ -------
45
+ numpy.ndarray
46
+ The transformed coordinates.
47
+
48
+ """
49
+ logger.debug("Using ANTs for coordinates transformation")
50
+
51
+ # Create element-specific tempdir for storing post-warping assets
52
+ element_tempdir = WorkDirManager().get_element_tempdir(
53
+ prefix="ants_coordinates_warper"
54
+ )
55
+
56
+ # Save existing coordinates to a tempfile
57
+ pretransform_coordinates_path = (
58
+ element_tempdir / "pretransform_coordinates.csv"
59
+ )
60
+ # Convert LPS to RAS
61
+ seeds[:, 0] *= -1
62
+ seeds[:, 1] *= -1
63
+ np.savetxt(
64
+ pretransform_coordinates_path,
65
+ seeds,
66
+ delimiter=",",
67
+ # Add header while saving to make ANTs work
68
+ header="x,y,z",
69
+ # Remove comment tag for header
70
+ comments="",
71
+ )
72
+
73
+ # Create a tempfile for transformed coordinates output
74
+ transformed_coords_path = (
75
+ element_tempdir / "coordinates_transformed.csv"
76
+ )
77
+ # Set antsApplyTransformsToPoints command
78
+ apply_transforms_to_points_cmd = [
79
+ "antsApplyTransformsToPoints",
80
+ "-d 3",
81
+ "-p 1",
82
+ "-f 0",
83
+ f"-i {pretransform_coordinates_path.resolve()}",
84
+ f"-o {transformed_coords_path.resolve()}",
85
+ f"-t {warp_data['path'].resolve()}",
86
+ ]
87
+ # Call antsApplyTransformsToPoints
88
+ run_ext_cmd(
89
+ name="antsApplyTransformsToPoints",
90
+ cmd=apply_transforms_to_points_cmd,
91
+ )
92
+
93
+ # Load coordinates
94
+ transformed_seeds = np.loadtxt(
95
+ # Skip header when reading
96
+ transformed_coords_path,
97
+ delimiter=",",
98
+ skiprows=1,
99
+ )
100
+ # Convert RAS to LPS
101
+ transformed_seeds[:, 0] *= -1
102
+ transformed_seeds[:, 1] *= -1
103
+
104
+ return transformed_seeds