junifer 0.0.6.dev227__py3-none-any.whl → 0.0.6.dev252__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/api/decorators.py +1 -2
- junifer/api/functions.py +18 -18
- junifer/api/queue_context/gnu_parallel_local_adapter.py +4 -4
- junifer/api/queue_context/htcondor_adapter.py +4 -4
- junifer/api/queue_context/tests/test_gnu_parallel_local_adapter.py +3 -3
- junifer/api/queue_context/tests/test_htcondor_adapter.py +3 -3
- junifer/api/tests/test_functions.py +32 -32
- junifer/cli/cli.py +3 -3
- junifer/cli/parser.py +4 -4
- junifer/cli/tests/test_cli.py +5 -5
- junifer/cli/utils.py +5 -6
- junifer/configs/juseless/datagrabbers/ixi_vbm.py +2 -2
- junifer/configs/juseless/datagrabbers/tests/test_ucla.py +2 -2
- junifer/configs/juseless/datagrabbers/ucla.py +4 -4
- junifer/data/_dispatch.py +11 -14
- junifer/data/coordinates/_ants_coordinates_warper.py +6 -8
- junifer/data/coordinates/_coordinates.py +34 -21
- junifer/data/coordinates/_fsl_coordinates_warper.py +6 -8
- junifer/data/masks/_ants_mask_warper.py +18 -11
- junifer/data/masks/_fsl_mask_warper.py +6 -8
- junifer/data/masks/_masks.py +27 -34
- junifer/data/masks/tests/test_masks.py +4 -4
- junifer/data/parcellations/_ants_parcellation_warper.py +18 -11
- junifer/data/parcellations/_fsl_parcellation_warper.py +6 -8
- junifer/data/parcellations/_parcellations.py +39 -43
- junifer/data/parcellations/tests/test_parcellations.py +1 -2
- junifer/data/pipeline_data_registry_base.py +3 -2
- junifer/data/template_spaces.py +3 -3
- junifer/data/tests/test_data_utils.py +1 -2
- junifer/data/utils.py +69 -4
- junifer/datagrabber/aomic/id1000.py +24 -11
- junifer/datagrabber/aomic/piop1.py +27 -14
- junifer/datagrabber/aomic/piop2.py +27 -14
- junifer/datagrabber/aomic/tests/test_id1000.py +3 -3
- junifer/datagrabber/aomic/tests/test_piop1.py +4 -4
- junifer/datagrabber/aomic/tests/test_piop2.py +4 -4
- junifer/datagrabber/base.py +18 -12
- junifer/datagrabber/datalad_base.py +18 -11
- junifer/datagrabber/dmcc13_benchmark.py +31 -18
- junifer/datagrabber/hcp1200/datalad_hcp1200.py +3 -3
- junifer/datagrabber/hcp1200/hcp1200.py +26 -15
- junifer/datagrabber/hcp1200/tests/test_hcp1200.py +2 -1
- junifer/datagrabber/multiple.py +7 -7
- junifer/datagrabber/pattern.py +75 -45
- junifer/datagrabber/pattern_validation_mixin.py +204 -94
- junifer/datagrabber/tests/test_datalad_base.py +7 -8
- junifer/datagrabber/tests/test_dmcc13_benchmark.py +28 -11
- junifer/datagrabber/tests/test_pattern_validation_mixin.py +6 -6
- junifer/datareader/default.py +6 -6
- junifer/external/nilearn/junifer_connectivity_measure.py +2 -2
- junifer/external/nilearn/junifer_nifti_spheres_masker.py +4 -4
- junifer/external/nilearn/tests/test_junifer_connectivity_measure.py +15 -15
- junifer/external/nilearn/tests/test_junifer_nifti_spheres_masker.py +2 -3
- junifer/markers/base.py +8 -8
- junifer/markers/brainprint.py +7 -9
- junifer/markers/complexity/complexity_base.py +6 -8
- junifer/markers/complexity/hurst_exponent.py +5 -5
- junifer/markers/complexity/multiscale_entropy_auc.py +5 -5
- junifer/markers/complexity/perm_entropy.py +5 -5
- junifer/markers/complexity/range_entropy.py +5 -5
- junifer/markers/complexity/range_entropy_auc.py +5 -5
- junifer/markers/complexity/sample_entropy.py +5 -5
- junifer/markers/complexity/weighted_perm_entropy.py +5 -5
- junifer/markers/ets_rss.py +7 -7
- junifer/markers/falff/_afni_falff.py +1 -2
- junifer/markers/falff/_junifer_falff.py +1 -2
- junifer/markers/falff/falff_base.py +2 -4
- junifer/markers/falff/falff_parcels.py +7 -7
- junifer/markers/falff/falff_spheres.py +6 -6
- junifer/markers/functional_connectivity/crossparcellation_functional_connectivity.py +6 -6
- junifer/markers/functional_connectivity/edge_functional_connectivity_parcels.py +7 -7
- junifer/markers/functional_connectivity/edge_functional_connectivity_spheres.py +6 -6
- junifer/markers/functional_connectivity/functional_connectivity_base.py +10 -10
- junifer/markers/functional_connectivity/functional_connectivity_parcels.py +7 -7
- junifer/markers/functional_connectivity/functional_connectivity_spheres.py +6 -6
- junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_parcels.py +1 -2
- junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_spheres.py +1 -2
- junifer/markers/functional_connectivity/tests/test_functional_connectivity_parcels.py +3 -3
- junifer/markers/functional_connectivity/tests/test_functional_connectivity_spheres.py +3 -3
- junifer/markers/parcel_aggregation.py +8 -8
- junifer/markers/reho/_afni_reho.py +1 -2
- junifer/markers/reho/_junifer_reho.py +1 -2
- junifer/markers/reho/reho_base.py +2 -4
- junifer/markers/reho/reho_parcels.py +8 -8
- junifer/markers/reho/reho_spheres.py +7 -7
- junifer/markers/sphere_aggregation.py +8 -8
- junifer/markers/temporal_snr/temporal_snr_base.py +8 -8
- junifer/markers/temporal_snr/temporal_snr_parcels.py +6 -6
- junifer/markers/temporal_snr/temporal_snr_spheres.py +5 -5
- junifer/markers/utils.py +3 -3
- junifer/onthefly/_brainprint.py +2 -2
- junifer/onthefly/read_transform.py +3 -3
- junifer/pipeline/marker_collection.py +4 -4
- junifer/pipeline/pipeline_component_registry.py +5 -4
- junifer/pipeline/pipeline_step_mixin.py +15 -11
- junifer/pipeline/tests/test_pipeline_component_registry.py +2 -3
- junifer/pipeline/tests/test_pipeline_step_mixin.py +19 -19
- junifer/pipeline/tests/test_update_meta_mixin.py +4 -4
- junifer/pipeline/update_meta_mixin.py +21 -17
- junifer/pipeline/utils.py +5 -5
- junifer/preprocess/base.py +10 -10
- junifer/preprocess/confounds/fmriprep_confound_remover.py +11 -14
- junifer/preprocess/confounds/tests/test_fmriprep_confound_remover.py +1 -2
- junifer/preprocess/smoothing/smoothing.py +7 -7
- junifer/preprocess/warping/_ants_warper.py +26 -6
- junifer/preprocess/warping/_fsl_warper.py +22 -7
- junifer/preprocess/warping/space_warper.py +37 -10
- junifer/preprocess/warping/tests/test_space_warper.py +3 -4
- junifer/stats.py +4 -4
- junifer/storage/base.py +14 -13
- junifer/storage/hdf5.py +21 -20
- junifer/storage/pandas_base.py +12 -11
- junifer/storage/sqlite.py +11 -11
- junifer/storage/tests/test_hdf5.py +1 -2
- junifer/storage/tests/test_sqlite.py +2 -2
- junifer/storage/tests/test_utils.py +8 -7
- junifer/storage/utils.py +7 -7
- junifer/testing/datagrabbers.py +9 -10
- junifer/tests/test_stats.py +2 -2
- junifer/typing/_typing.py +6 -9
- junifer/utils/helpers.py +2 -3
- junifer/utils/logging.py +5 -5
- junifer/utils/singleton.py +3 -3
- {junifer-0.0.6.dev227.dist-info → junifer-0.0.6.dev252.dist-info}/METADATA +2 -2
- {junifer-0.0.6.dev227.dist-info → junifer-0.0.6.dev252.dist-info}/RECORD +131 -131
- {junifer-0.0.6.dev227.dist-info → junifer-0.0.6.dev252.dist-info}/WHEEL +1 -1
- {junifer-0.0.6.dev227.dist-info → junifer-0.0.6.dev252.dist-info}/AUTHORS.rst +0 -0
- {junifer-0.0.6.dev227.dist-info → junifer-0.0.6.dev252.dist-info}/LICENSE.md +0 -0
- {junifer-0.0.6.dev227.dist-info → junifer-0.0.6.dev252.dist-info}/entry_points.txt +0 -0
- {junifer-0.0.6.dev227.dist-info → junifer-0.0.6.dev252.dist-info}/top_level.txt +0 -0
junifer/data/_dispatch.py
CHANGED
@@ -8,10 +8,7 @@ from typing import (
|
|
8
8
|
TYPE_CHECKING,
|
9
9
|
Any,
|
10
10
|
Callable,
|
11
|
-
Dict,
|
12
|
-
List,
|
13
11
|
Optional,
|
14
|
-
Tuple,
|
15
12
|
Union,
|
16
13
|
)
|
17
14
|
|
@@ -40,15 +37,15 @@ def get_data(
|
|
40
37
|
kind: str,
|
41
38
|
names: Union[
|
42
39
|
str, # coordinates, parcellation, mask
|
43
|
-
|
44
|
-
|
45
|
-
|
40
|
+
list[str], # parcellation, mask
|
41
|
+
dict, # mask
|
42
|
+
list[dict], # mask
|
46
43
|
],
|
47
|
-
target_data:
|
48
|
-
extra_input: Optional[
|
44
|
+
target_data: dict[str, Any],
|
45
|
+
extra_input: Optional[dict[str, Any]] = None,
|
49
46
|
) -> Union[
|
50
|
-
|
51
|
-
|
47
|
+
tuple[ArrayLike, list[str]], # coordinates
|
48
|
+
tuple["Nifti1Image", list[str]], # parcellation
|
52
49
|
"Nifti1Image", # mask
|
53
50
|
]:
|
54
51
|
"""Get tailored ``kind`` for ``target_data``.
|
@@ -102,7 +99,7 @@ def get_data(
|
|
102
99
|
raise_error(f"Unknown data kind: {kind}")
|
103
100
|
|
104
101
|
|
105
|
-
def list_data(kind: str) ->
|
102
|
+
def list_data(kind: str) -> list[str]:
|
106
103
|
"""List available data for ``kind``.
|
107
104
|
|
108
105
|
Parameters
|
@@ -137,9 +134,9 @@ def load_data(
|
|
137
134
|
name: str,
|
138
135
|
**kwargs,
|
139
136
|
) -> Union[
|
140
|
-
|
141
|
-
|
142
|
-
|
137
|
+
tuple[ArrayLike, list[str], str], # coordinates
|
138
|
+
tuple[Optional["Nifti1Image"], list[str], Path, str], # parcellation
|
139
|
+
tuple[
|
143
140
|
Optional[Union["Nifti1Image", Callable]], Optional[Path], str
|
144
141
|
], # mask
|
145
142
|
]:
|
@@ -3,7 +3,7 @@
|
|
3
3
|
# Authors: Synchon Mandal <s.mandal@fz-juelich.de>
|
4
4
|
# License: AGPL
|
5
5
|
|
6
|
-
from typing import Any
|
6
|
+
from typing import Any
|
7
7
|
|
8
8
|
import numpy as np
|
9
9
|
from numpy.typing import ArrayLike
|
@@ -25,8 +25,8 @@ class ANTsCoordinatesWarper:
|
|
25
25
|
def warp(
|
26
26
|
self,
|
27
27
|
seeds: ArrayLike,
|
28
|
-
target_data:
|
29
|
-
|
28
|
+
target_data: dict[str, Any],
|
29
|
+
warp_data: dict[str, Any],
|
30
30
|
) -> ArrayLike:
|
31
31
|
"""Warp ``seeds`` to correct space.
|
32
32
|
|
@@ -37,10 +37,8 @@ class ANTsCoordinatesWarper:
|
|
37
37
|
target_data : dict
|
38
38
|
The corresponding item of the data object to which the coordinates
|
39
39
|
will be applied.
|
40
|
-
|
41
|
-
The
|
42
|
-
data kinds that needs to be used in the computation of coordinates
|
43
|
-
(default None).
|
40
|
+
warp_data : dict or None
|
41
|
+
The warp data item of the data object.
|
44
42
|
|
45
43
|
Returns
|
46
44
|
-------
|
@@ -79,7 +77,7 @@ class ANTsCoordinatesWarper:
|
|
79
77
|
"-f 0",
|
80
78
|
f"-i {pretransform_coordinates_path.resolve()}",
|
81
79
|
f"-o {transformed_coords_path.resolve()}",
|
82
|
-
f"-t {
|
80
|
+
f"-t {warp_data['path'].resolve()}",
|
83
81
|
]
|
84
82
|
# Call antsApplyTransformsToPoints
|
85
83
|
run_ext_cmd(
|
@@ -5,7 +5,7 @@
|
|
5
5
|
# License: AGPL
|
6
6
|
|
7
7
|
from pathlib import Path
|
8
|
-
from typing import Any,
|
8
|
+
from typing import Any, Optional
|
9
9
|
|
10
10
|
import numpy as np
|
11
11
|
import pandas as pd
|
@@ -14,6 +14,7 @@ from numpy.typing import ArrayLike
|
|
14
14
|
from ...utils import logger, raise_error
|
15
15
|
from ...utils.singleton import Singleton
|
16
16
|
from ..pipeline_data_registry_base import BasePipelineDataRegistry
|
17
|
+
from ..utils import get_native_warper
|
17
18
|
from ._ants_coordinates_warper import ANTsCoordinatesWarper
|
18
19
|
from ._fsl_coordinates_warper import FSLCoordinatesWarper
|
19
20
|
|
@@ -134,7 +135,7 @@ class CoordinatesRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
134
135
|
self,
|
135
136
|
name: str,
|
136
137
|
coordinates: ArrayLike,
|
137
|
-
voi_names:
|
138
|
+
voi_names: list[str],
|
138
139
|
space: str,
|
139
140
|
overwrite: Optional[bool] = False,
|
140
141
|
) -> None:
|
@@ -235,7 +236,7 @@ class CoordinatesRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
235
236
|
# Update registry
|
236
237
|
_ = self._registry.pop(name)
|
237
238
|
|
238
|
-
def load(self, name: str) ->
|
239
|
+
def load(self, name: str) -> tuple[ArrayLike, list[str], str]:
|
239
240
|
"""Load coordinates.
|
240
241
|
|
241
242
|
Parameters
|
@@ -284,9 +285,9 @@ class CoordinatesRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
284
285
|
def get(
|
285
286
|
self,
|
286
287
|
coords: str,
|
287
|
-
target_data:
|
288
|
-
extra_input: Optional[
|
289
|
-
) ->
|
288
|
+
target_data: dict[str, Any],
|
289
|
+
extra_input: Optional[dict[str, Any]] = None,
|
290
|
+
) -> tuple[ArrayLike, list[str]]:
|
290
291
|
"""Get coordinates, tailored for the target data.
|
291
292
|
|
292
293
|
Parameters
|
@@ -311,7 +312,8 @@ class CoordinatesRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
311
312
|
Raises
|
312
313
|
------
|
313
314
|
RuntimeError
|
314
|
-
If
|
315
|
+
If warping specification required for warping using ANTs, is not
|
316
|
+
found.
|
315
317
|
ValueError
|
316
318
|
If ``extra_input`` is None when ``target_data``'s space is native.
|
317
319
|
|
@@ -329,27 +331,38 @@ class CoordinatesRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
329
331
|
f"{target_data['space']} space for further computation."
|
330
332
|
)
|
331
333
|
|
332
|
-
#
|
333
|
-
|
334
|
-
|
334
|
+
# Get native space warper spec
|
335
|
+
warper_spec = get_native_warper(
|
336
|
+
target_data=target_data,
|
337
|
+
other_data=extra_input,
|
338
|
+
)
|
339
|
+
# Conditional for warping tool implementation
|
340
|
+
if warper_spec["warper"] == "fsl":
|
335
341
|
seeds = FSLCoordinatesWarper().warp(
|
336
342
|
seeds=seeds,
|
337
343
|
target_data=target_data,
|
338
|
-
|
344
|
+
warp_data=warper_spec,
|
345
|
+
)
|
346
|
+
elif warper_spec["warper"] == "ants":
|
347
|
+
# Requires the inverse warp
|
348
|
+
inverse_warper_spec = get_native_warper(
|
349
|
+
target_data=target_data,
|
350
|
+
other_data=extra_input,
|
351
|
+
inverse=True,
|
339
352
|
)
|
340
|
-
|
353
|
+
# Check warper
|
354
|
+
if inverse_warper_spec["warper"] != "ants":
|
355
|
+
raise_error(
|
356
|
+
klass=RuntimeError,
|
357
|
+
msg=(
|
358
|
+
"Warping specification mismatch for native space "
|
359
|
+
"warping of coordinates using ANTs."
|
360
|
+
),
|
361
|
+
)
|
341
362
|
seeds = ANTsCoordinatesWarper().warp(
|
342
363
|
seeds=seeds,
|
343
364
|
target_data=target_data,
|
344
|
-
|
345
|
-
)
|
346
|
-
else:
|
347
|
-
raise_error(
|
348
|
-
msg=(
|
349
|
-
"Unknown warp / transformation file extension: "
|
350
|
-
f"{warp_file_ext}"
|
351
|
-
),
|
352
|
-
klass=RuntimeError,
|
365
|
+
warp_data=warper_spec,
|
353
366
|
)
|
354
367
|
|
355
368
|
return seeds, labels
|
@@ -3,7 +3,7 @@
|
|
3
3
|
# Authors: Synchon Mandal <s.mandal@fz-juelich.de>
|
4
4
|
# License: AGPL
|
5
5
|
|
6
|
-
from typing import Any
|
6
|
+
from typing import Any
|
7
7
|
|
8
8
|
import numpy as np
|
9
9
|
from numpy.typing import ArrayLike
|
@@ -25,8 +25,8 @@ class FSLCoordinatesWarper:
|
|
25
25
|
def warp(
|
26
26
|
self,
|
27
27
|
seeds: ArrayLike,
|
28
|
-
target_data:
|
29
|
-
|
28
|
+
target_data: dict[str, Any],
|
29
|
+
warp_data: dict[str, Any],
|
30
30
|
) -> ArrayLike:
|
31
31
|
"""Warp ``seeds`` to correct space.
|
32
32
|
|
@@ -37,10 +37,8 @@ class FSLCoordinatesWarper:
|
|
37
37
|
target_data : dict
|
38
38
|
The corresponding item of the data object to which the coordinates
|
39
39
|
will be applied.
|
40
|
-
|
41
|
-
The
|
42
|
-
data kinds that needs to be used in the computation of coordinates
|
43
|
-
(default None).
|
40
|
+
warp_data : dict
|
41
|
+
The warp data item of the data object.
|
44
42
|
|
45
43
|
Returns
|
46
44
|
-------
|
@@ -72,7 +70,7 @@ class FSLCoordinatesWarper:
|
|
72
70
|
"| img2imgcoord -mm",
|
73
71
|
f"-src {target_data['path'].resolve()}",
|
74
72
|
f"-dest {target_data['reference_path'].resolve()}",
|
75
|
-
f"-warp {
|
73
|
+
f"-warp {warp_data['path'].resolve()}",
|
76
74
|
f"> {transformed_coords_path.resolve()};",
|
77
75
|
f"sed -i 1d {transformed_coords_path.resolve()}",
|
78
76
|
]
|
@@ -4,12 +4,12 @@
|
|
4
4
|
# License: AGPL
|
5
5
|
|
6
6
|
import uuid
|
7
|
-
from typing import TYPE_CHECKING, Any,
|
7
|
+
from typing import TYPE_CHECKING, Any, Optional
|
8
8
|
|
9
9
|
import nibabel as nib
|
10
10
|
|
11
11
|
from ...pipeline import WorkDirManager
|
12
|
-
from ...utils import logger, run_ext_cmd
|
12
|
+
from ...utils import logger, raise_error, run_ext_cmd
|
13
13
|
from ..template_spaces import get_template, get_xfm
|
14
14
|
|
15
15
|
|
@@ -33,8 +33,8 @@ class ANTsMaskWarper:
|
|
33
33
|
mask_img: "Nifti1Image",
|
34
34
|
src: str,
|
35
35
|
dst: str,
|
36
|
-
target_data:
|
37
|
-
|
36
|
+
target_data: dict[str, Any],
|
37
|
+
warp_data: Optional[dict[str, Any]],
|
38
38
|
) -> "Nifti1Image":
|
39
39
|
"""Warp ``mask_img`` to correct space.
|
40
40
|
|
@@ -55,17 +55,20 @@ class ANTsMaskWarper:
|
|
55
55
|
target_data : dict
|
56
56
|
The corresponding item of the data object to which the mask
|
57
57
|
will be applied.
|
58
|
-
|
59
|
-
The
|
60
|
-
|
61
|
-
(default None).
|
62
|
-
|
58
|
+
warp_data : dict or None
|
59
|
+
The warp data item of the data object. The value is unused if
|
60
|
+
``dst!="T1w"``.
|
63
61
|
|
64
62
|
Returns
|
65
63
|
-------
|
66
64
|
nibabel.nifti1.Nifti1Image
|
67
65
|
The transformed mask image.
|
68
66
|
|
67
|
+
Raises
|
68
|
+
------
|
69
|
+
RuntimeError
|
70
|
+
If ``warp_data`` is None when ``dst="T1w"``.
|
71
|
+
|
69
72
|
"""
|
70
73
|
# Create element-scoped tempdir so that warped mask is
|
71
74
|
# available later as nibabel stores file path reference for
|
@@ -80,7 +83,11 @@ class ANTsMaskWarper:
|
|
80
83
|
)
|
81
84
|
|
82
85
|
# Native space warping
|
83
|
-
if dst == "
|
86
|
+
if dst == "native":
|
87
|
+
# Warp data check
|
88
|
+
if warp_data is None:
|
89
|
+
raise_error("No `warp_data` provided")
|
90
|
+
|
84
91
|
logger.debug("Using ANTs for mask transformation")
|
85
92
|
|
86
93
|
# Save existing mask image to a tempfile
|
@@ -98,7 +105,7 @@ class ANTsMaskWarper:
|
|
98
105
|
f"-i {prewarp_mask_path.resolve()}",
|
99
106
|
# use resampled reference
|
100
107
|
f"-r {target_data['reference_path'].resolve()}",
|
101
|
-
f"-t {
|
108
|
+
f"-t {warp_data['path'].resolve()}",
|
102
109
|
f"-o {warped_mask_path.resolve()}",
|
103
110
|
]
|
104
111
|
# Call antsApplyTransforms
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# License: AGPL
|
5
5
|
|
6
6
|
import uuid
|
7
|
-
from typing import TYPE_CHECKING, Any
|
7
|
+
from typing import TYPE_CHECKING, Any
|
8
8
|
|
9
9
|
import nibabel as nib
|
10
10
|
|
@@ -30,8 +30,8 @@ class FSLMaskWarper:
|
|
30
30
|
self,
|
31
31
|
mask_name: str,
|
32
32
|
mask_img: "Nifti1Image",
|
33
|
-
target_data:
|
34
|
-
|
33
|
+
target_data: dict[str, Any],
|
34
|
+
warp_data: dict[str, Any],
|
35
35
|
) -> "Nifti1Image":
|
36
36
|
"""Warp ``mask_img`` to correct space.
|
37
37
|
|
@@ -44,10 +44,8 @@ class FSLMaskWarper:
|
|
44
44
|
target_data : dict
|
45
45
|
The corresponding item of the data object to which the mask
|
46
46
|
will be applied.
|
47
|
-
|
48
|
-
The
|
49
|
-
data kinds that needs to be used in the computation of mask
|
50
|
-
(default None).
|
47
|
+
warp_data : dict
|
48
|
+
The warp data item of the data object.
|
51
49
|
|
52
50
|
Returns
|
53
51
|
-------
|
@@ -77,7 +75,7 @@ class FSLMaskWarper:
|
|
77
75
|
f"-i {prewarp_mask_path.resolve()}",
|
78
76
|
# use resampled reference
|
79
77
|
f"-r {target_data['reference_path'].resolve()}",
|
80
|
-
f"-w {
|
78
|
+
f"-w {warp_data['path'].resolve()}",
|
81
79
|
f"-o {warped_mask_path.resolve()}",
|
82
80
|
]
|
83
81
|
# Call applywarp
|
junifer/data/masks/_masks.py
CHANGED
@@ -9,10 +9,7 @@ from typing import (
|
|
9
9
|
TYPE_CHECKING,
|
10
10
|
Any,
|
11
11
|
Callable,
|
12
|
-
Dict,
|
13
|
-
List,
|
14
12
|
Optional,
|
15
|
-
Tuple,
|
16
13
|
Union,
|
17
14
|
)
|
18
15
|
|
@@ -29,7 +26,7 @@ from ...utils import logger, raise_error
|
|
29
26
|
from ...utils.singleton import Singleton
|
30
27
|
from ..pipeline_data_registry_base import BasePipelineDataRegistry
|
31
28
|
from ..template_spaces import get_template
|
32
|
-
from ..utils import closest_resolution
|
29
|
+
from ..utils import closest_resolution, get_native_warper
|
33
30
|
from ._ants_mask_warper import ANTsMaskWarper
|
34
31
|
from ._fsl_mask_warper import FSLMaskWarper
|
35
32
|
|
@@ -46,8 +43,8 @@ _masks_path = Path(__file__).parent
|
|
46
43
|
|
47
44
|
|
48
45
|
def compute_brain_mask(
|
49
|
-
target_data:
|
50
|
-
extra_input: Optional[
|
46
|
+
target_data: dict[str, Any],
|
47
|
+
extra_input: Optional[dict[str, Any]] = None,
|
51
48
|
mask_type: str = "brain",
|
52
49
|
threshold: float = 0.5,
|
53
50
|
) -> "Nifti1Image":
|
@@ -105,14 +102,16 @@ def compute_brain_mask(
|
|
105
102
|
"data type to infer target template space."
|
106
103
|
)
|
107
104
|
# Set target standard space to warp file space source
|
108
|
-
|
105
|
+
for entry in extra_input["Warp"]:
|
106
|
+
if entry["dst"] == "native":
|
107
|
+
target_std_space = entry["src"]
|
109
108
|
|
110
109
|
# Fetch template in closest resolution
|
111
110
|
template = get_template(
|
112
111
|
space=target_std_space,
|
113
112
|
target_data=target_data,
|
114
113
|
extra_input=extra_input,
|
115
|
-
template_type=mask_type
|
114
|
+
template_type=mask_type,
|
116
115
|
)
|
117
116
|
# Resample template to target image
|
118
117
|
target_img = target_data["data"]
|
@@ -264,7 +263,7 @@ class MaskRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
264
263
|
name: str,
|
265
264
|
resolution: Optional[float] = None,
|
266
265
|
path_only: bool = False,
|
267
|
-
) ->
|
266
|
+
) -> tuple[Optional[Union["Nifti1Image", Callable]], Optional[Path], str]:
|
268
267
|
"""Load mask.
|
269
268
|
|
270
269
|
Parameters
|
@@ -330,9 +329,9 @@ class MaskRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
330
329
|
|
331
330
|
def get( # noqa: C901
|
332
331
|
self,
|
333
|
-
masks: Union[str,
|
334
|
-
target_data:
|
335
|
-
extra_input: Optional[
|
332
|
+
masks: Union[str, dict, list[Union[dict, str]]],
|
333
|
+
target_data: dict[str, Any],
|
334
|
+
extra_input: Optional[dict[str, Any]] = None,
|
336
335
|
) -> "Nifti1Image":
|
337
336
|
"""Get mask, tailored for the target image.
|
338
337
|
|
@@ -357,8 +356,6 @@ class MaskRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
357
356
|
|
358
357
|
Raises
|
359
358
|
------
|
360
|
-
RuntimeError
|
361
|
-
If warp / transformation file extension is not ".mat" or ".h5".
|
362
359
|
ValueError
|
363
360
|
If extra key is provided in addition to mask name in ``masks`` or
|
364
361
|
if no mask is provided or
|
@@ -372,8 +369,6 @@ class MaskRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
372
369
|
"""
|
373
370
|
# Check pre-requirements for space manipulation
|
374
371
|
target_space = target_data["space"]
|
375
|
-
# Set target standard space to target space
|
376
|
-
target_std_space = target_space
|
377
372
|
# Extra data type requirement check if target space is native
|
378
373
|
if target_space == "native":
|
379
374
|
# Check for extra inputs
|
@@ -383,8 +378,16 @@ class MaskRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
383
378
|
"data types in particular for transformation to "
|
384
379
|
f"{target_data['space']} space for further computation."
|
385
380
|
)
|
381
|
+
# Get native space warper spec
|
382
|
+
warper_spec = get_native_warper(
|
383
|
+
target_data=target_data,
|
384
|
+
other_data=extra_input,
|
385
|
+
)
|
386
386
|
# Set target standard space to warp file space source
|
387
|
-
target_std_space =
|
387
|
+
target_std_space = warper_spec["src"]
|
388
|
+
else:
|
389
|
+
# Set target standard space to target space
|
390
|
+
target_std_space = target_space
|
388
391
|
|
389
392
|
# Get the min of the voxels sizes and use it as the resolution
|
390
393
|
target_img = target_data["data"]
|
@@ -489,7 +492,7 @@ class MaskRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
489
492
|
src=mask_space,
|
490
493
|
dst=target_std_space,
|
491
494
|
target_data=target_data,
|
492
|
-
|
495
|
+
warp_data=None,
|
493
496
|
)
|
494
497
|
|
495
498
|
all_masks.append(mask_img)
|
@@ -510,32 +513,22 @@ class MaskRegistry(BasePipelineDataRegistry, metaclass=Singleton):
|
|
510
513
|
|
511
514
|
# Warp mask if target data is native
|
512
515
|
if target_space == "native":
|
513
|
-
# extra_input check done earlier
|
514
|
-
|
515
|
-
warp_file_ext = extra_input["Warp"]["path"].suffix
|
516
|
-
if warp_file_ext == ".mat":
|
516
|
+
# extra_input check done earlier and warper_spec exists
|
517
|
+
if warper_spec["warper"] == "fsl":
|
517
518
|
mask_img = FSLMaskWarper().warp(
|
518
519
|
mask_name="native",
|
519
520
|
mask_img=mask_img,
|
520
521
|
target_data=target_data,
|
521
|
-
|
522
|
+
warp_data=warper_spec,
|
522
523
|
)
|
523
|
-
elif
|
524
|
+
elif warper_spec["warper"] == "ants":
|
524
525
|
mask_img = ANTsMaskWarper().warp(
|
525
526
|
mask_name="native",
|
526
527
|
mask_img=mask_img,
|
527
528
|
src="",
|
528
|
-
dst="
|
529
|
+
dst="native",
|
529
530
|
target_data=target_data,
|
530
|
-
|
531
|
-
)
|
532
|
-
else:
|
533
|
-
raise_error(
|
534
|
-
msg=(
|
535
|
-
"Unknown warp / transformation file extension: "
|
536
|
-
f"{warp_file_ext}"
|
537
|
-
),
|
538
|
-
klass=RuntimeError,
|
531
|
+
warp_data=warper_spec,
|
539
532
|
)
|
540
533
|
|
541
534
|
return mask_img
|
@@ -7,7 +7,7 @@
|
|
7
7
|
|
8
8
|
import socket
|
9
9
|
from pathlib import Path
|
10
|
-
from typing import Callable,
|
10
|
+
from typing import Callable, Optional, Union
|
11
11
|
|
12
12
|
import nibabel as nib
|
13
13
|
import numpy as np
|
@@ -254,7 +254,7 @@ def test_load_incorrect() -> None:
|
|
254
254
|
def test_vickery_patil(
|
255
255
|
name: str,
|
256
256
|
resolution: Optional[float],
|
257
|
-
pixdim:
|
257
|
+
pixdim: list[float],
|
258
258
|
fname: str,
|
259
259
|
) -> None:
|
260
260
|
"""Test Vickery-Patil mask.
|
@@ -396,7 +396,7 @@ def test_get_errors() -> None:
|
|
396
396
|
def test_nilearn_compute_masks(
|
397
397
|
mask_name: str,
|
398
398
|
function: Callable,
|
399
|
-
params: Union[
|
399
|
+
params: Union[dict, None],
|
400
400
|
resample: bool,
|
401
401
|
) -> None:
|
402
402
|
"""Test using nilearn compute mask functions.
|
@@ -479,7 +479,7 @@ def test_get_inherit() -> None:
|
|
479
479
|
],
|
480
480
|
)
|
481
481
|
def test_get_multiple(
|
482
|
-
masks: Union[str,
|
482
|
+
masks: Union[str, dict, list[Union[dict, str]]], params: dict
|
483
483
|
) -> None:
|
484
484
|
"""Test getting multiple masks.
|
485
485
|
|
@@ -4,12 +4,12 @@
|
|
4
4
|
# License: AGPL
|
5
5
|
|
6
6
|
import uuid
|
7
|
-
from typing import TYPE_CHECKING, Any,
|
7
|
+
from typing import TYPE_CHECKING, Any, Optional
|
8
8
|
|
9
9
|
import nibabel as nib
|
10
10
|
|
11
11
|
from ...pipeline import WorkDirManager
|
12
|
-
from ...utils import logger, run_ext_cmd
|
12
|
+
from ...utils import logger, raise_error, run_ext_cmd
|
13
13
|
from ..template_spaces import get_template, get_xfm
|
14
14
|
|
15
15
|
|
@@ -33,8 +33,8 @@ class ANTsParcellationWarper:
|
|
33
33
|
parcellation_img: "Nifti1Image",
|
34
34
|
src: str,
|
35
35
|
dst: str,
|
36
|
-
target_data:
|
37
|
-
|
36
|
+
target_data: dict[str, Any],
|
37
|
+
warp_data: Optional[dict[str, Any]],
|
38
38
|
) -> "Nifti1Image":
|
39
39
|
"""Warp ``parcellation_img`` to correct space.
|
40
40
|
|
@@ -55,17 +55,20 @@ class ANTsParcellationWarper:
|
|
55
55
|
target_data : dict
|
56
56
|
The corresponding item of the data object to which the parcellation
|
57
57
|
will be applied.
|
58
|
-
|
59
|
-
The
|
60
|
-
|
61
|
-
(default None).
|
62
|
-
|
58
|
+
warp_data : dict or None
|
59
|
+
The warp data item of the data object. The value is unused if
|
60
|
+
``dst!="T1w"``.
|
63
61
|
|
64
62
|
Returns
|
65
63
|
-------
|
66
64
|
nibabel.nifti1.Nifti1Image
|
67
65
|
The transformed parcellation image.
|
68
66
|
|
67
|
+
Raises
|
68
|
+
------
|
69
|
+
ValueError
|
70
|
+
If ``warp_data`` is None when ``dst="T1w"``.
|
71
|
+
|
69
72
|
"""
|
70
73
|
# Create element-scoped tempdir so that warped parcellation is
|
71
74
|
# available later as nibabel stores file path reference for
|
@@ -80,7 +83,11 @@ class ANTsParcellationWarper:
|
|
80
83
|
)
|
81
84
|
|
82
85
|
# Native space warping
|
83
|
-
if dst == "
|
86
|
+
if dst == "native":
|
87
|
+
# Warp data check
|
88
|
+
if warp_data is None:
|
89
|
+
raise_error("No `warp_data` provided")
|
90
|
+
|
84
91
|
logger.debug("Using ANTs for parcellation transformation")
|
85
92
|
|
86
93
|
# Save existing parcellation image to a tempfile
|
@@ -102,7 +109,7 @@ class ANTsParcellationWarper:
|
|
102
109
|
f"-i {prewarp_parcellation_path.resolve()}",
|
103
110
|
# use resampled reference
|
104
111
|
f"-r {target_data['reference_path'].resolve()}",
|
105
|
-
f"-t {
|
112
|
+
f"-t {warp_data['path'].resolve()}",
|
106
113
|
f"-o {warped_parcellation_path.resolve()}",
|
107
114
|
]
|
108
115
|
# Call antsApplyTransforms
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# License: AGPL
|
5
5
|
|
6
6
|
import uuid
|
7
|
-
from typing import TYPE_CHECKING, Any
|
7
|
+
from typing import TYPE_CHECKING, Any
|
8
8
|
|
9
9
|
import nibabel as nib
|
10
10
|
|
@@ -30,8 +30,8 @@ class FSLParcellationWarper:
|
|
30
30
|
self,
|
31
31
|
parcellation_name: str,
|
32
32
|
parcellation_img: "Nifti1Image",
|
33
|
-
target_data:
|
34
|
-
|
33
|
+
target_data: dict[str, Any],
|
34
|
+
warp_data: dict[str, Any],
|
35
35
|
) -> "Nifti1Image":
|
36
36
|
"""Warp ``parcellation_img`` to correct space.
|
37
37
|
|
@@ -44,10 +44,8 @@ class FSLParcellationWarper:
|
|
44
44
|
target_data : dict
|
45
45
|
The corresponding item of the data object to which the parcellation
|
46
46
|
will be applied.
|
47
|
-
|
48
|
-
The
|
49
|
-
data kinds that needs to be used in the computation of parcellation
|
50
|
-
(default None).
|
47
|
+
warp_data : dict
|
48
|
+
The warp data item of the data object.
|
51
49
|
|
52
50
|
Returns
|
53
51
|
-------
|
@@ -81,7 +79,7 @@ class FSLParcellationWarper:
|
|
81
79
|
f"-i {prewarp_parcellation_path.resolve()}",
|
82
80
|
# use resampled reference
|
83
81
|
f"-r {target_data['reference_path'].resolve()}",
|
84
|
-
f"-w {
|
82
|
+
f"-w {warp_data['path'].resolve()}",
|
85
83
|
f"-o {warped_parcellation_path.resolve()}",
|
86
84
|
]
|
87
85
|
# Call applywarp
|