junifer 0.0.4.dev829__py3-none-any.whl → 0.0.5__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 (206) hide show
  1. junifer/__init__.py +17 -0
  2. junifer/_version.py +2 -2
  3. junifer/api/__init__.py +4 -1
  4. junifer/api/cli.py +91 -1
  5. junifer/api/decorators.py +9 -0
  6. junifer/api/functions.py +56 -10
  7. junifer/api/parser.py +3 -0
  8. junifer/api/queue_context/__init__.py +4 -1
  9. junifer/api/queue_context/gnu_parallel_local_adapter.py +16 -6
  10. junifer/api/queue_context/htcondor_adapter.py +16 -5
  11. junifer/api/queue_context/tests/test_gnu_parallel_local_adapter.py +41 -12
  12. junifer/api/queue_context/tests/test_htcondor_adapter.py +48 -15
  13. junifer/api/res/afni/run_afni_docker.sh +1 -1
  14. junifer/api/res/ants/run_ants_docker.sh +1 -1
  15. junifer/api/res/freesurfer/mri_binarize +3 -0
  16. junifer/api/res/freesurfer/mri_mc +3 -0
  17. junifer/api/res/freesurfer/mri_pretess +3 -0
  18. junifer/api/res/freesurfer/mris_convert +3 -0
  19. junifer/api/res/freesurfer/run_freesurfer_docker.sh +61 -0
  20. junifer/api/res/fsl/run_fsl_docker.sh +1 -1
  21. junifer/api/res/{run_conda.sh → run_conda.bash} +1 -1
  22. junifer/api/res/run_conda.zsh +23 -0
  23. junifer/api/res/run_venv.bash +22 -0
  24. junifer/api/res/{run_venv.sh → run_venv.zsh} +1 -1
  25. junifer/api/tests/test_api_utils.py +4 -2
  26. junifer/api/tests/test_cli.py +83 -0
  27. junifer/api/tests/test_functions.py +27 -2
  28. junifer/configs/__init__.py +1 -1
  29. junifer/configs/juseless/__init__.py +4 -1
  30. junifer/configs/juseless/datagrabbers/__init__.py +10 -1
  31. junifer/configs/juseless/datagrabbers/aomic_id1000_vbm.py +4 -3
  32. junifer/configs/juseless/datagrabbers/camcan_vbm.py +3 -0
  33. junifer/configs/juseless/datagrabbers/ixi_vbm.py +4 -3
  34. junifer/configs/juseless/datagrabbers/tests/test_ucla.py +1 -3
  35. junifer/configs/juseless/datagrabbers/ucla.py +12 -9
  36. junifer/configs/juseless/datagrabbers/ukb_vbm.py +3 -0
  37. junifer/data/__init__.py +21 -1
  38. junifer/data/coordinates.py +10 -19
  39. junifer/data/masks/ukb/UKB_15K_GM_template.nii.gz +0 -0
  40. junifer/data/masks.py +58 -87
  41. junifer/data/parcellations.py +14 -3
  42. junifer/data/template_spaces.py +4 -1
  43. junifer/data/tests/test_masks.py +26 -37
  44. junifer/data/utils.py +3 -0
  45. junifer/datagrabber/__init__.py +18 -1
  46. junifer/datagrabber/aomic/__init__.py +3 -0
  47. junifer/datagrabber/aomic/id1000.py +70 -37
  48. junifer/datagrabber/aomic/piop1.py +69 -36
  49. junifer/datagrabber/aomic/piop2.py +71 -38
  50. junifer/datagrabber/aomic/tests/test_id1000.py +44 -100
  51. junifer/datagrabber/aomic/tests/test_piop1.py +65 -108
  52. junifer/datagrabber/aomic/tests/test_piop2.py +45 -102
  53. junifer/datagrabber/base.py +13 -6
  54. junifer/datagrabber/datalad_base.py +13 -1
  55. junifer/datagrabber/dmcc13_benchmark.py +36 -53
  56. junifer/datagrabber/hcp1200/__init__.py +3 -0
  57. junifer/datagrabber/hcp1200/datalad_hcp1200.py +3 -0
  58. junifer/datagrabber/hcp1200/hcp1200.py +4 -1
  59. junifer/datagrabber/multiple.py +45 -6
  60. junifer/datagrabber/pattern.py +170 -62
  61. junifer/datagrabber/pattern_datalad.py +25 -12
  62. junifer/datagrabber/pattern_validation_mixin.py +388 -0
  63. junifer/datagrabber/tests/test_datalad_base.py +4 -4
  64. junifer/datagrabber/tests/test_dmcc13_benchmark.py +46 -19
  65. junifer/datagrabber/tests/test_multiple.py +161 -84
  66. junifer/datagrabber/tests/test_pattern.py +45 -0
  67. junifer/datagrabber/tests/test_pattern_datalad.py +4 -4
  68. junifer/datagrabber/tests/test_pattern_validation_mixin.py +249 -0
  69. junifer/datareader/__init__.py +4 -1
  70. junifer/datareader/default.py +95 -43
  71. junifer/external/BrainPrint/brainprint/__init__.py +4 -0
  72. junifer/external/BrainPrint/brainprint/_version.py +3 -0
  73. junifer/external/BrainPrint/brainprint/asymmetry.py +91 -0
  74. junifer/external/BrainPrint/brainprint/brainprint.py +441 -0
  75. junifer/external/BrainPrint/brainprint/surfaces.py +258 -0
  76. junifer/external/BrainPrint/brainprint/utils/__init__.py +1 -0
  77. junifer/external/BrainPrint/brainprint/utils/_config.py +112 -0
  78. junifer/external/BrainPrint/brainprint/utils/utils.py +188 -0
  79. junifer/external/__init__.py +1 -1
  80. junifer/external/nilearn/__init__.py +5 -1
  81. junifer/external/nilearn/junifer_connectivity_measure.py +483 -0
  82. junifer/external/nilearn/junifer_nifti_spheres_masker.py +23 -9
  83. junifer/external/nilearn/tests/test_junifer_connectivity_measure.py +1089 -0
  84. junifer/external/nilearn/tests/test_junifer_nifti_spheres_masker.py +76 -1
  85. junifer/markers/__init__.py +23 -1
  86. junifer/markers/base.py +68 -28
  87. junifer/markers/brainprint.py +459 -0
  88. junifer/markers/collection.py +10 -2
  89. junifer/markers/complexity/__init__.py +10 -0
  90. junifer/markers/complexity/complexity_base.py +26 -43
  91. junifer/markers/complexity/hurst_exponent.py +3 -0
  92. junifer/markers/complexity/multiscale_entropy_auc.py +3 -0
  93. junifer/markers/complexity/perm_entropy.py +3 -0
  94. junifer/markers/complexity/range_entropy.py +3 -0
  95. junifer/markers/complexity/range_entropy_auc.py +3 -0
  96. junifer/markers/complexity/sample_entropy.py +3 -0
  97. junifer/markers/complexity/tests/test_hurst_exponent.py +11 -3
  98. junifer/markers/complexity/tests/test_multiscale_entropy_auc.py +11 -3
  99. junifer/markers/complexity/tests/test_perm_entropy.py +11 -3
  100. junifer/markers/complexity/tests/test_range_entropy.py +11 -3
  101. junifer/markers/complexity/tests/test_range_entropy_auc.py +11 -3
  102. junifer/markers/complexity/tests/test_sample_entropy.py +11 -3
  103. junifer/markers/complexity/tests/test_weighted_perm_entropy.py +11 -3
  104. junifer/markers/complexity/weighted_perm_entropy.py +3 -0
  105. junifer/markers/ets_rss.py +27 -42
  106. junifer/markers/falff/__init__.py +3 -0
  107. junifer/markers/falff/_afni_falff.py +5 -2
  108. junifer/markers/falff/_junifer_falff.py +3 -0
  109. junifer/markers/falff/falff_base.py +20 -46
  110. junifer/markers/falff/falff_parcels.py +56 -27
  111. junifer/markers/falff/falff_spheres.py +60 -29
  112. junifer/markers/falff/tests/test_falff_parcels.py +39 -23
  113. junifer/markers/falff/tests/test_falff_spheres.py +39 -23
  114. junifer/markers/functional_connectivity/__init__.py +9 -0
  115. junifer/markers/functional_connectivity/crossparcellation_functional_connectivity.py +63 -60
  116. junifer/markers/functional_connectivity/edge_functional_connectivity_parcels.py +45 -32
  117. junifer/markers/functional_connectivity/edge_functional_connectivity_spheres.py +49 -36
  118. junifer/markers/functional_connectivity/functional_connectivity_base.py +71 -70
  119. junifer/markers/functional_connectivity/functional_connectivity_parcels.py +34 -25
  120. junifer/markers/functional_connectivity/functional_connectivity_spheres.py +40 -30
  121. junifer/markers/functional_connectivity/tests/test_crossparcellation_functional_connectivity.py +11 -7
  122. junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_parcels.py +27 -7
  123. junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_spheres.py +28 -12
  124. junifer/markers/functional_connectivity/tests/test_functional_connectivity_parcels.py +35 -11
  125. junifer/markers/functional_connectivity/tests/test_functional_connectivity_spheres.py +36 -62
  126. junifer/markers/parcel_aggregation.py +47 -61
  127. junifer/markers/reho/__init__.py +3 -0
  128. junifer/markers/reho/_afni_reho.py +5 -2
  129. junifer/markers/reho/_junifer_reho.py +4 -1
  130. junifer/markers/reho/reho_base.py +8 -27
  131. junifer/markers/reho/reho_parcels.py +28 -17
  132. junifer/markers/reho/reho_spheres.py +27 -18
  133. junifer/markers/reho/tests/test_reho_parcels.py +8 -3
  134. junifer/markers/reho/tests/test_reho_spheres.py +8 -3
  135. junifer/markers/sphere_aggregation.py +43 -59
  136. junifer/markers/temporal_snr/__init__.py +3 -0
  137. junifer/markers/temporal_snr/temporal_snr_base.py +23 -32
  138. junifer/markers/temporal_snr/temporal_snr_parcels.py +9 -6
  139. junifer/markers/temporal_snr/temporal_snr_spheres.py +9 -6
  140. junifer/markers/temporal_snr/tests/test_temporal_snr_parcels.py +6 -3
  141. junifer/markers/temporal_snr/tests/test_temporal_snr_spheres.py +6 -3
  142. junifer/markers/tests/test_brainprint.py +58 -0
  143. junifer/markers/tests/test_collection.py +9 -8
  144. junifer/markers/tests/test_ets_rss.py +15 -9
  145. junifer/markers/tests/test_markers_base.py +17 -18
  146. junifer/markers/tests/test_parcel_aggregation.py +93 -32
  147. junifer/markers/tests/test_sphere_aggregation.py +72 -19
  148. junifer/onthefly/__init__.py +4 -1
  149. junifer/onthefly/read_transform.py +3 -0
  150. junifer/pipeline/__init__.py +9 -1
  151. junifer/pipeline/pipeline_step_mixin.py +21 -4
  152. junifer/pipeline/registry.py +3 -0
  153. junifer/pipeline/singleton.py +3 -0
  154. junifer/pipeline/tests/test_registry.py +1 -1
  155. junifer/pipeline/update_meta_mixin.py +3 -0
  156. junifer/pipeline/utils.py +67 -1
  157. junifer/pipeline/workdir_manager.py +3 -0
  158. junifer/preprocess/__init__.py +10 -2
  159. junifer/preprocess/base.py +6 -3
  160. junifer/preprocess/confounds/__init__.py +3 -0
  161. junifer/preprocess/confounds/fmriprep_confound_remover.py +47 -60
  162. junifer/preprocess/confounds/tests/test_fmriprep_confound_remover.py +72 -113
  163. junifer/preprocess/smoothing/__init__.py +9 -0
  164. junifer/preprocess/smoothing/_afni_smoothing.py +119 -0
  165. junifer/preprocess/smoothing/_fsl_smoothing.py +116 -0
  166. junifer/preprocess/smoothing/_nilearn_smoothing.py +69 -0
  167. junifer/preprocess/smoothing/smoothing.py +174 -0
  168. junifer/preprocess/smoothing/tests/test_smoothing.py +94 -0
  169. junifer/preprocess/warping/__init__.py +3 -0
  170. junifer/preprocess/warping/_ants_warper.py +3 -0
  171. junifer/preprocess/warping/_fsl_warper.py +3 -0
  172. junifer/stats.py +4 -1
  173. junifer/storage/__init__.py +9 -1
  174. junifer/storage/base.py +40 -1
  175. junifer/storage/hdf5.py +71 -9
  176. junifer/storage/pandas_base.py +3 -0
  177. junifer/storage/sqlite.py +3 -0
  178. junifer/storage/tests/test_hdf5.py +82 -10
  179. junifer/storage/utils.py +9 -0
  180. junifer/testing/__init__.py +4 -1
  181. junifer/testing/datagrabbers.py +13 -6
  182. junifer/testing/tests/test_partlycloudytesting_datagrabber.py +7 -7
  183. junifer/testing/utils.py +3 -0
  184. junifer/utils/__init__.py +13 -2
  185. junifer/utils/fs.py +3 -0
  186. junifer/utils/helpers.py +32 -1
  187. junifer/utils/logging.py +33 -4
  188. junifer/utils/tests/test_logging.py +8 -0
  189. {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/METADATA +17 -16
  190. junifer-0.0.5.dist-info/RECORD +275 -0
  191. {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/WHEEL +1 -1
  192. junifer/datagrabber/tests/test_datagrabber_utils.py +0 -218
  193. junifer/datagrabber/utils.py +0 -230
  194. junifer/preprocess/ants/__init__.py +0 -4
  195. junifer/preprocess/ants/ants_apply_transforms_warper.py +0 -185
  196. junifer/preprocess/ants/tests/test_ants_apply_transforms_warper.py +0 -56
  197. junifer/preprocess/bold_warper.py +0 -265
  198. junifer/preprocess/fsl/__init__.py +0 -4
  199. junifer/preprocess/fsl/apply_warper.py +0 -179
  200. junifer/preprocess/fsl/tests/test_apply_warper.py +0 -45
  201. junifer/preprocess/tests/test_bold_warper.py +0 -159
  202. junifer-0.0.4.dev829.dist-info/RECORD +0 -257
  203. {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/AUTHORS.rst +0 -0
  204. {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/LICENSE.md +0 -0
  205. {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/entry_points.txt +0 -0
  206. {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/top_level.txt +0 -0
@@ -1,230 +0,0 @@
1
- """Provide utility functions for the datagrabber sub-package."""
2
-
3
- # Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
4
- # Synchon Mandal <s.mandal@fz-juelich.de>
5
- # License: AGPL
6
-
7
- from typing import Dict, List
8
-
9
- from ..utils import logger, raise_error
10
-
11
-
12
- # Define schema for pattern-based datagrabber's patterns
13
- PATTERNS_SCHEMA = {
14
- "T1w": {
15
- "mandatory": ["pattern", "space"],
16
- "optional": ["mask_item"],
17
- },
18
- "T1w_mask": {
19
- "mandatory": ["pattern", "space"],
20
- "optional": [],
21
- },
22
- "T2w": {
23
- "mandatory": ["pattern", "space"],
24
- "optional": ["mask_item"],
25
- },
26
- "T2w_mask": {
27
- "mandatory": ["pattern", "space"],
28
- "optional": [],
29
- },
30
- "BOLD": {
31
- "mandatory": ["pattern", "space"],
32
- "optional": ["mask_item"],
33
- },
34
- "BOLD_confounds": {
35
- "mandatory": ["pattern", "format"],
36
- "optional": [],
37
- },
38
- "BOLD_mask": {
39
- "mandatory": ["pattern", "space"],
40
- "optional": [],
41
- },
42
- "Warp": {
43
- "mandatory": ["pattern", "src", "dst"],
44
- "optional": [],
45
- },
46
- "VBM_GM": {
47
- "mandatory": ["pattern", "space"],
48
- "optional": [],
49
- },
50
- "VBM_WM": {
51
- "mandatory": ["pattern", "space"],
52
- "optional": [],
53
- },
54
- "VBM_CSF": {
55
- "mandatory": ["pattern", "space"],
56
- "optional": [],
57
- },
58
- "DWI": {
59
- "mandatory": ["pattern"],
60
- "optional": [],
61
- },
62
- }
63
-
64
-
65
- def validate_types(types: List[str]) -> None:
66
- """Validate the types.
67
-
68
- Parameters
69
- ----------
70
- types : list of str
71
- The object to validate.
72
-
73
- Raises
74
- ------
75
- TypeError
76
- If ``types`` is not a list or if the values are not string.
77
-
78
- """
79
- if not isinstance(types, list):
80
- raise_error(msg="`types` must be a list", klass=TypeError)
81
- if any(not isinstance(x, str) for x in types):
82
- raise_error(msg="`types` must be a list of strings", klass=TypeError)
83
-
84
-
85
- def validate_replacements(
86
- replacements: List[str], patterns: Dict[str, Dict[str, str]]
87
- ) -> None:
88
- """Validate the replacements.
89
-
90
- Parameters
91
- ----------
92
- replacements : list of str
93
- The object to validate.
94
- patterns : dict
95
- The patterns to validate against.
96
-
97
- Raises
98
- ------
99
- TypeError
100
- If ``replacements`` is not a list or if the values are not string.
101
- ValueError
102
- If a value in ``replacements`` is not part of a data type pattern or
103
- if no data type patterns contain all values in ``replacements``.
104
-
105
- """
106
- if not isinstance(replacements, list):
107
- raise_error(msg="`replacements` must be a list.", klass=TypeError)
108
-
109
- if any(not isinstance(x, str) for x in replacements):
110
- raise_error(
111
- msg="`replacements` must be a list of strings.", klass=TypeError
112
- )
113
-
114
- for x in replacements:
115
- if all(
116
- x not in y
117
- for y in [
118
- data_type_val["pattern"] for data_type_val in patterns.values()
119
- ]
120
- ):
121
- raise_error(msg=f"Replacement: {x} is not part of any pattern.")
122
-
123
- # Check that at least one pattern has all the replacements
124
- at_least_one = False
125
- for data_type_val in patterns.values():
126
- if all(x in data_type_val["pattern"] for x in replacements):
127
- at_least_one = True
128
- if at_least_one is False:
129
- raise_error(msg="At least one pattern must contain all replacements.")
130
-
131
-
132
- def validate_patterns(
133
- types: List[str], patterns: Dict[str, Dict[str, str]]
134
- ) -> None:
135
- """Validate the patterns.
136
-
137
- Parameters
138
- ----------
139
- types : list of str
140
- The types list.
141
- patterns : dict
142
- The object to validate.
143
-
144
- Raises
145
- ------
146
- KeyError
147
- If any mandatory key is missing for a data type.
148
- RuntimeError
149
- If an unknown key is found for a data type.
150
- TypeError
151
- If ``patterns`` is not a dictionary.
152
- ValueError
153
- If length of ``types`` and ``patterns`` are different or
154
- if ``patterns`` is missing entries from ``types`` or
155
- if unknown data type is found in ``patterns`` or
156
- if data type pattern key contains '*' as value.
157
-
158
- """
159
- # Validate the types
160
- validate_types(types)
161
- if not isinstance(patterns, dict):
162
- raise_error(msg="`patterns` must be a dict.", klass=TypeError)
163
- # Unequal length of objects
164
- if len(types) > len(patterns):
165
- raise_error(
166
- msg="Length of `types` more than that of `patterns`.",
167
- klass=ValueError,
168
- )
169
- # Missing type in patterns
170
- if any(x not in patterns for x in types):
171
- raise_error(
172
- msg="`patterns` must contain all `types`", klass=ValueError
173
- )
174
- # Check against schema
175
- for data_type_key, data_type_val in patterns.items():
176
- # Check if valid data type is provided
177
- if data_type_key not in PATTERNS_SCHEMA:
178
- raise_error(
179
- f"Unknown data type: {data_type_key}, "
180
- f"should be one of: {list(PATTERNS_SCHEMA.keys())}"
181
- )
182
- # Check mandatory keys for data type
183
- for mandatory_key in PATTERNS_SCHEMA[data_type_key]["mandatory"]:
184
- if mandatory_key not in data_type_val:
185
- raise_error(
186
- msg=(
187
- f"Mandatory key: `{mandatory_key}` missing for "
188
- f"{data_type_key}"
189
- ),
190
- klass=KeyError,
191
- )
192
- else:
193
- logger.debug(
194
- f"Mandatory key: `{mandatory_key}` found for "
195
- f"{data_type_key}"
196
- )
197
- # Check optional keys for data type
198
- for optional_key in PATTERNS_SCHEMA[data_type_key]["optional"]:
199
- if optional_key not in data_type_val:
200
- logger.debug(
201
- f"Optional key: `{optional_key}` missing for "
202
- f"{data_type_key}"
203
- )
204
- else:
205
- logger.debug(
206
- f"Optional key: `{optional_key}` found for "
207
- f"{data_type_key}"
208
- )
209
- # Check stray key for data type
210
- for key in data_type_val.keys():
211
- if key not in (
212
- PATTERNS_SCHEMA[data_type_key]["mandatory"]
213
- + PATTERNS_SCHEMA[data_type_key]["optional"]
214
- ):
215
- raise_error(
216
- msg=(
217
- f"Key: {key} not accepted for {data_type_key} "
218
- "pattern, remove it to proceed"
219
- ),
220
- klass=RuntimeError,
221
- )
222
- # Wildcard check in patterns
223
- if "}*" in data_type_val["pattern"]:
224
- raise_error(
225
- msg=(
226
- f"`{data_type_key}.pattern` must not contain `*` "
227
- "following a replacement"
228
- ),
229
- klass=ValueError,
230
- )
@@ -1,4 +0,0 @@
1
- """Provide imports for ants sub-package."""
2
-
3
- # Authors: Synchon Mandal <s.mandal@fz-juelich.de>
4
- # License: AGPL
@@ -1,185 +0,0 @@
1
- """Provide class for warping via ANTs antsApplyTransforms."""
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
- ClassVar,
11
- Dict,
12
- List,
13
- Optional,
14
- Tuple,
15
- Union,
16
- )
17
-
18
- import nibabel as nib
19
- import numpy as np
20
-
21
- from ...pipeline import WorkDirManager
22
- from ...utils import logger, raise_error, run_ext_cmd
23
-
24
-
25
- if TYPE_CHECKING:
26
- from nibabel import Nifti1Image
27
-
28
-
29
- class _AntsApplyTransformsWarper:
30
- """Class for warping NIfTI images via ANTs antsApplyTransforms.
31
-
32
- Warps ANTs ``antsApplyTransforms``.
33
-
34
- Parameters
35
- ----------
36
- reference : str
37
- The data type to use as reference for warping.
38
- on : str
39
- The data type to use for warping.
40
-
41
- Raises
42
- ------
43
- ValueError
44
- If a list was passed for ``on``.
45
-
46
- """
47
-
48
- _EXT_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, List[str]]]]] = [
49
- {
50
- "name": "ants",
51
- "commands": ["ResampleImage", "antsApplyTransforms"],
52
- },
53
- ]
54
-
55
- def __init__(self, reference: str, on: str) -> None:
56
- """Initialize the class."""
57
- self.ref = reference
58
- # Check only single data type is passed
59
- if isinstance(on, list):
60
- raise_error("Can only work on single data type, list was passed.")
61
- self.on = on
62
-
63
- def _run_apply_transforms(
64
- self,
65
- input_data: Dict,
66
- ref_path: Path,
67
- warp_path: Path,
68
- ) -> Tuple["Nifti1Image", Path]:
69
- """Run ``antsApplyTransforms``.
70
-
71
- Parameters
72
- ----------
73
- input_data : dict
74
- The input data.
75
- ref_path : pathlib.Path
76
- The path to the reference file.
77
- warp_path : pathlib.Path
78
- The path to the warp file.
79
-
80
- Returns
81
- -------
82
- Niimg-like object
83
- The warped input image.
84
- pathlib.Path
85
- The path to the resampled reference image.
86
-
87
- """
88
- # Get the min of the voxel sizes from input and use it as the
89
- # resolution
90
- resolution = np.min(input_data["data"].header.get_zooms()[:3])
91
-
92
- # Create element-specific tempdir for storing post-warping assets
93
- tempdir = WorkDirManager().get_element_tempdir(
94
- prefix="applytransforms"
95
- )
96
-
97
- # Create a tempfile for resampled reference output
98
- resample_image_out_path = tempdir / "reference_resampled.nii.gz"
99
- # Set ResampleImage command
100
- resample_image_cmd = [
101
- "ResampleImage",
102
- "3", # image dimension
103
- f"{ref_path.resolve()}",
104
- f"{resample_image_out_path.resolve()}",
105
- f"{resolution}x{resolution}x{resolution}",
106
- "0", # option for spacing and not size
107
- "3 3", # Lanczos windowed sinc
108
- ]
109
- # Call ResampleImage
110
- run_ext_cmd(name="ResampleImage", cmd=resample_image_cmd)
111
-
112
- # Create a tempfile for warped output
113
- apply_transforms_out_path = tempdir / "input_warped.nii.gz"
114
- # Set antsApplyTransforms command
115
- apply_transforms_cmd = [
116
- "antsApplyTransforms",
117
- "-d 3",
118
- "-e 3",
119
- "-n LanczosWindowedSinc",
120
- f"-i {input_data['path'].resolve()}",
121
- # use resampled reference
122
- f"-r {resample_image_out_path.resolve()}",
123
- f"-t {warp_path.resolve()}",
124
- f"-o {apply_transforms_out_path.resolve()}",
125
- ]
126
- # Call antsApplyTransforms
127
- run_ext_cmd(name="antsApplyTransforms", cmd=apply_transforms_cmd)
128
-
129
- # Load nifti
130
- output_img = nib.load(apply_transforms_out_path)
131
-
132
- return output_img, resample_image_out_path # type: ignore
133
-
134
- def preprocess(
135
- self,
136
- input: Dict[str, Any],
137
- extra_input: Optional[Dict[str, Any]] = None,
138
- ) -> Tuple[str, Dict[str, Any]]:
139
- """Preprocess.
140
-
141
- Parameters
142
- ----------
143
- input : dict
144
- A single input from the Junifer Data object in which to preprocess.
145
- extra_input : dict, optional
146
- The other fields in the Junifer Data object. Must include the
147
- ``Warp`` and ``ref`` value's keys.
148
-
149
- Returns
150
- -------
151
- str
152
- The key to store the output in the Junifer Data object.
153
- dict
154
- The computed result as dictionary. This will be stored in the
155
- Junifer Data object under the key ``data`` of the data type.
156
-
157
- Raises
158
- ------
159
- ValueError
160
- If ``extra_input`` is None.
161
-
162
- """
163
- logger.debug("Warping via ANTs using antsApplyTransforms")
164
- # Check for extra inputs
165
- if extra_input is None:
166
- raise_error(
167
- f"No extra input provided, requires `Warp` and `{self.ref}` "
168
- "data types in particular."
169
- )
170
- # Retrieve data type info to warp
171
- to_warp_input = input
172
- # Retrieve data type info to use as reference
173
- ref_input = extra_input[self.ref]
174
- # Retrieve Warp data
175
- warp = extra_input["Warp"]
176
- # Replace original data with warped data and add resampled reference
177
- # path
178
- input["data"], input["reference_path"] = self._run_apply_transforms(
179
- input_data=to_warp_input,
180
- ref_path=ref_input["path"],
181
- warp_path=warp["path"],
182
- )
183
- # Use reference input's space as warped input's space
184
- input["space"] = ref_input["space"]
185
- return self.on, input
@@ -1,56 +0,0 @@
1
- """Provide tests for AntsApplyTransformsWarper."""
2
-
3
- # Authors: Synchon Mandal <s.mandal@fz-juelich.de>
4
- # License: AGPL
5
-
6
- import socket
7
-
8
- import pytest
9
-
10
- from junifer.datagrabber import DMCC13Benchmark
11
- from junifer.datareader import DefaultDataReader
12
- from junifer.pipeline.utils import _check_ants
13
- from junifer.preprocess.ants.ants_apply_transforms_warper import (
14
- _AntsApplyTransformsWarper,
15
- )
16
-
17
-
18
- def test_AntsApplyTransformsWarper_init() -> None:
19
- """Test AntsApplyTransformsWarper init."""
20
- ants_apply_transforms_warper = _AntsApplyTransformsWarper(
21
- reference="T1w", on="BOLD"
22
- )
23
- assert ants_apply_transforms_warper.ref == "T1w"
24
- assert ants_apply_transforms_warper.on == "BOLD"
25
-
26
-
27
- @pytest.mark.skipif(
28
- _check_ants() is False, reason="requires ANTs to be in PATH"
29
- )
30
- @pytest.mark.skipif(
31
- socket.gethostname() != "juseless",
32
- reason="only for juseless",
33
- )
34
- def test_AntsApplyTransformsWarper_preprocess() -> None:
35
- """Test AntsApplyTransformsWarper preprocess."""
36
- with DMCC13Benchmark(
37
- types=["BOLD", "T1w", "Warp"],
38
- sessions=["ses-wave1bas"],
39
- tasks=["Rest"],
40
- phase_encodings=["AP"],
41
- runs=["1"],
42
- native_t1w=True,
43
- ) as dg:
44
- # Read data
45
- element_data = DefaultDataReader().fit_transform(
46
- dg[("sub-f9057kp", "ses-wave1bas", "Rest", "AP", "1")]
47
- )
48
- # Preprocess data
49
- data_type, data = _AntsApplyTransformsWarper(
50
- reference="T1w", on="BOLD"
51
- ).preprocess(
52
- input=element_data["BOLD"],
53
- extra_input=element_data,
54
- )
55
- assert isinstance(data_type, str)
56
- assert isinstance(data, dict)