junifer 0.0.7.dev132__py3-none-any.whl → 0.0.7.dev169__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/conftest.py +32 -0
- junifer/data/__init__.pyi +2 -0
- junifer/data/_dispatch.py +11 -7
- junifer/data/maps/__init__.py +9 -0
- junifer/data/maps/__init__.pyi +5 -0
- junifer/data/maps/_ants_maps_warper.py +156 -0
- junifer/data/maps/_fsl_maps_warper.py +85 -0
- junifer/data/maps/_maps.py +446 -0
- junifer/data/maps/tests/test_maps.py +255 -0
- junifer/data/masks/_masks.py +3 -2
- junifer/data/parcellations/_parcellations.py +1 -1
- junifer/markers/__init__.pyi +12 -2
- junifer/markers/falff/__init__.pyi +2 -1
- junifer/markers/falff/falff_maps.py +151 -0
- junifer/markers/falff/tests/test_falff_maps.py +167 -0
- junifer/markers/functional_connectivity/__init__.pyi +4 -0
- junifer/markers/functional_connectivity/edge_functional_connectivity_maps.py +115 -0
- junifer/markers/functional_connectivity/functional_connectivity_maps.py +95 -0
- junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_maps.py +74 -0
- junifer/markers/functional_connectivity/tests/test_functional_connectivity_maps.py +110 -0
- junifer/markers/maps_aggregation.py +201 -0
- junifer/markers/reho/__init__.pyi +2 -1
- junifer/markers/reho/reho_maps.py +161 -0
- junifer/markers/reho/tests/test_reho_maps.py +135 -0
- junifer/markers/temporal_snr/__init__.pyi +2 -1
- junifer/markers/temporal_snr/temporal_snr_maps.py +80 -0
- junifer/markers/temporal_snr/tests/test_temporal_snr_maps.py +67 -0
- junifer/markers/tests/test_maps_aggregation.py +430 -0
- junifer/typing/_typing.py +1 -3
- {junifer-0.0.7.dev132.dist-info → junifer-0.0.7.dev169.dist-info}/METADATA +2 -2
- {junifer-0.0.7.dev132.dist-info → junifer-0.0.7.dev169.dist-info}/RECORD +37 -19
- {junifer-0.0.7.dev132.dist-info → junifer-0.0.7.dev169.dist-info}/WHEEL +0 -0
- {junifer-0.0.7.dev132.dist-info → junifer-0.0.7.dev169.dist-info}/entry_points.txt +0 -0
- {junifer-0.0.7.dev132.dist-info → junifer-0.0.7.dev169.dist-info}/licenses/AUTHORS.rst +0 -0
- {junifer-0.0.7.dev132.dist-info → junifer-0.0.7.dev169.dist-info}/licenses/LICENSE.md +0 -0
- {junifer-0.0.7.dev132.dist-info → junifer-0.0.7.dev169.dist-info}/top_level.txt +0 -0
junifer/_version.py
CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
28
28
|
commit_id: COMMIT_ID
|
29
29
|
__commit_id__: COMMIT_ID
|
30
30
|
|
31
|
-
__version__ = version = '0.0.7.
|
32
|
-
__version_tuple__ = version_tuple = (0, 0, 7, '
|
31
|
+
__version__ = version = '0.0.7.dev169'
|
32
|
+
__version_tuple__ = version_tuple = (0, 0, 7, 'dev169')
|
33
33
|
|
34
34
|
__commit_id__ = commit_id = None
|
junifer/conftest.py
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
"""Provide conftest for pytest."""
|
2
2
|
|
3
3
|
# Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
|
4
|
+
# Synchon Mandal <s.mandal@fz-juelich.de>
|
4
5
|
# License: AGPL
|
5
6
|
|
7
|
+
from pathlib import Path
|
8
|
+
|
6
9
|
import pytest
|
7
10
|
|
11
|
+
from junifer.datagrabber import PatternDataladDataGrabber
|
8
12
|
from junifer.utils.singleton import Singleton
|
9
13
|
|
10
14
|
|
@@ -23,3 +27,31 @@ def reset_singletons() -> None:
|
|
23
27
|
# Force deleting the singletons
|
24
28
|
for elem in to_remove:
|
25
29
|
del elem
|
30
|
+
|
31
|
+
|
32
|
+
@pytest.fixture
|
33
|
+
def maps_datagrabber(tmp_path: Path) -> PatternDataladDataGrabber:
|
34
|
+
"""Return a PatternDataladDataGrabber for maps testing.
|
35
|
+
|
36
|
+
Parameters
|
37
|
+
----------
|
38
|
+
tmp_path : pathlib.Path
|
39
|
+
The path to the test directory.
|
40
|
+
|
41
|
+
"""
|
42
|
+
dg = PatternDataladDataGrabber(
|
43
|
+
uri="https://github.com/OpenNeuroDatasets/ds005226.git",
|
44
|
+
types=["BOLD"],
|
45
|
+
patterns={
|
46
|
+
"BOLD": {
|
47
|
+
"pattern": (
|
48
|
+
"derivatives/pre-processed_data/space-MNI/{subject}/"
|
49
|
+
"{subject-padded}_task-{task}_run-{run}_space-MNI152NLin6Asym"
|
50
|
+
"_res-2_desc-preproc_bold.nii.gz"
|
51
|
+
),
|
52
|
+
"space": "MNI152NLin6Asym",
|
53
|
+
},
|
54
|
+
},
|
55
|
+
replacements=["subject", "subject-padded", "task", "run"],
|
56
|
+
)
|
57
|
+
return dg
|
junifer/data/__init__.pyi
CHANGED
@@ -3,6 +3,7 @@ __all__ = [
|
|
3
3
|
"CoordinatesRegistry",
|
4
4
|
"DataDispatcher",
|
5
5
|
"ParcellationRegistry",
|
6
|
+
"MapsRegistry",
|
6
7
|
"MaskRegistry",
|
7
8
|
"get_data",
|
8
9
|
"list_data",
|
@@ -17,6 +18,7 @@ __all__ = [
|
|
17
18
|
from .pipeline_data_registry_base import BasePipelineDataRegistry
|
18
19
|
from .coordinates import CoordinatesRegistry
|
19
20
|
from .parcellations import ParcellationRegistry
|
21
|
+
from .maps import MapsRegistry
|
20
22
|
from .masks import MaskRegistry
|
21
23
|
|
22
24
|
from ._dispatch import (
|
junifer/data/_dispatch.py
CHANGED
@@ -17,6 +17,7 @@ from numpy.typing import ArrayLike
|
|
17
17
|
|
18
18
|
from ..utils import raise_error
|
19
19
|
from .coordinates import CoordinatesRegistry
|
20
|
+
from .maps import MapsRegistry
|
20
21
|
from .masks import MaskRegistry
|
21
22
|
from .parcellations import ParcellationRegistry
|
22
23
|
from .pipeline_data_registry_base import BasePipelineDataRegistry
|
@@ -52,6 +53,7 @@ class DataDispatcher(MutableMapping):
|
|
52
53
|
{
|
53
54
|
"coordinates": CoordinatesRegistry,
|
54
55
|
"parcellation": ParcellationRegistry,
|
56
|
+
"maps": MapsRegistry,
|
55
57
|
"mask": MaskRegistry,
|
56
58
|
}
|
57
59
|
)
|
@@ -118,14 +120,14 @@ def get_data(
|
|
118
120
|
extra_input: Optional[dict[str, Any]] = None,
|
119
121
|
) -> Union[
|
120
122
|
tuple[ArrayLike, list[str]], # coordinates
|
121
|
-
tuple["Nifti1Image", list[str]], # parcellation
|
123
|
+
tuple["Nifti1Image", list[str]], # parcellation / maps
|
122
124
|
"Nifti1Image", # mask
|
123
125
|
]:
|
124
126
|
"""Get tailored ``kind`` for ``target_data``.
|
125
127
|
|
126
128
|
Parameters
|
127
129
|
----------
|
128
|
-
kind : {"coordinates", "parcellation", "mask"}
|
130
|
+
kind : {"coordinates", "parcellation", "mask", "maps"}
|
129
131
|
Kind of data to fetch and apply.
|
130
132
|
names : str or dict or list of str / dict
|
131
133
|
The registered name(s) of the data.
|
@@ -166,7 +168,7 @@ def list_data(kind: str) -> list[str]:
|
|
166
168
|
|
167
169
|
Parameters
|
168
170
|
----------
|
169
|
-
kind : {"coordinates", "parcellation", "mask"}
|
171
|
+
kind : {"coordinates", "parcellation", "mask", "maps"}
|
170
172
|
Kind of data registry to list.
|
171
173
|
|
172
174
|
Returns
|
@@ -195,7 +197,9 @@ def load_data(
|
|
195
197
|
**kwargs,
|
196
198
|
) -> Union[
|
197
199
|
tuple[ArrayLike, list[str], str], # coordinates
|
198
|
-
tuple[
|
200
|
+
tuple[
|
201
|
+
Optional["Nifti1Image"], list[str], Path, str
|
202
|
+
], # parcellation / maps
|
199
203
|
tuple[
|
200
204
|
Optional[Union["Nifti1Image", Callable]], Optional[Path], str
|
201
205
|
], # mask
|
@@ -204,7 +208,7 @@ def load_data(
|
|
204
208
|
|
205
209
|
Parameters
|
206
210
|
----------
|
207
|
-
kind : {"coordinates", "parcellation", "mask"}
|
211
|
+
kind : {"coordinates", "parcellation", "mask", "maps"}
|
208
212
|
Kind of data to load.
|
209
213
|
name : str
|
210
214
|
The registered name of the data.
|
@@ -244,7 +248,7 @@ def register_data(
|
|
244
248
|
|
245
249
|
Parameters
|
246
250
|
----------
|
247
|
-
kind : {"coordinates", "parcellation", "mask"}
|
251
|
+
kind : {"coordinates", "parcellation", "mask", "maps"}
|
248
252
|
Kind of data to register.
|
249
253
|
name : str
|
250
254
|
The name to register.
|
@@ -277,7 +281,7 @@ def deregister_data(kind: str, name: str) -> None:
|
|
277
281
|
|
278
282
|
Parameters
|
279
283
|
----------
|
280
|
-
kind : {"coordinates", "parcellation", "mask"}
|
284
|
+
kind : {"coordinates", "parcellation", "mask", "maps"}
|
281
285
|
Kind of data to register.
|
282
286
|
name : str
|
283
287
|
The name to de-register.
|
@@ -0,0 +1,156 @@
|
|
1
|
+
"""Provide class for maps space warping via ANTs."""
|
2
|
+
|
3
|
+
# Authors: Synchon Mandal <s.mandal@fz-juelich.de>
|
4
|
+
# License: AGPL
|
5
|
+
|
6
|
+
import uuid
|
7
|
+
from typing import TYPE_CHECKING, Any, Optional
|
8
|
+
|
9
|
+
import nibabel as nib
|
10
|
+
|
11
|
+
from ...pipeline import WorkDirManager
|
12
|
+
from ...utils import logger, raise_error, run_ext_cmd
|
13
|
+
from ..template_spaces import get_template, get_xfm
|
14
|
+
|
15
|
+
|
16
|
+
if TYPE_CHECKING:
|
17
|
+
from nibabel.nifti1 import Nifti1Image
|
18
|
+
|
19
|
+
|
20
|
+
__all__ = ["ANTsMapsWarper"]
|
21
|
+
|
22
|
+
|
23
|
+
class ANTsMapsWarper:
|
24
|
+
"""Class for maps space warping via ANTs.
|
25
|
+
|
26
|
+
This class uses ANTs ``antsApplyTransforms`` for transformation.
|
27
|
+
|
28
|
+
"""
|
29
|
+
|
30
|
+
def warp(
|
31
|
+
self,
|
32
|
+
maps_name: str,
|
33
|
+
maps_img: "Nifti1Image",
|
34
|
+
src: str,
|
35
|
+
dst: str,
|
36
|
+
target_data: dict[str, Any],
|
37
|
+
warp_data: Optional[dict[str, Any]],
|
38
|
+
) -> "Nifti1Image":
|
39
|
+
"""Warp ``maps_img`` to correct space.
|
40
|
+
|
41
|
+
Parameters
|
42
|
+
----------
|
43
|
+
maps_name : str
|
44
|
+
The name of the maps.
|
45
|
+
maps_img : nibabel.nifti1.Nifti1Image
|
46
|
+
The maps image to transform.
|
47
|
+
src : str
|
48
|
+
The data type or template space to warp from.
|
49
|
+
It should be empty string if ``dst="T1w"``.
|
50
|
+
dst : str
|
51
|
+
The data type or template space to warp to.
|
52
|
+
`"T1w"` is the only allowed data type and it uses the resampled T1w
|
53
|
+
found in ``target_data.reference``. The ``"reference"``
|
54
|
+
key is added if the :class:`.SpaceWarper` is used or if the
|
55
|
+
data is provided in native space.
|
56
|
+
target_data : dict
|
57
|
+
The corresponding item of the data object to which the maps
|
58
|
+
will be applied.
|
59
|
+
warp_data : dict or None
|
60
|
+
The warp data item of the data object. The value is unused if
|
61
|
+
``dst!="T1w"``.
|
62
|
+
|
63
|
+
Returns
|
64
|
+
-------
|
65
|
+
nibabel.nifti1.Nifti1Image
|
66
|
+
The transformed maps image.
|
67
|
+
|
68
|
+
Raises
|
69
|
+
------
|
70
|
+
ValueError
|
71
|
+
If ``warp_data`` is None when ``dst="T1w"``.
|
72
|
+
|
73
|
+
"""
|
74
|
+
# Create element-scoped tempdir so that warped maps is
|
75
|
+
# available later as nibabel stores file path reference for
|
76
|
+
# loading on computation
|
77
|
+
prefix = (
|
78
|
+
f"ants_maps_warper_{maps_name}"
|
79
|
+
f"{'' if not src else f'_from_{src}'}_to_{dst}_"
|
80
|
+
f"{uuid.uuid1()}"
|
81
|
+
)
|
82
|
+
element_tempdir = WorkDirManager().get_element_tempdir(
|
83
|
+
prefix=prefix,
|
84
|
+
)
|
85
|
+
|
86
|
+
# Native space warping
|
87
|
+
if dst == "native": # pragma: no cover
|
88
|
+
# Warp data check
|
89
|
+
if warp_data is None:
|
90
|
+
raise_error("No `warp_data` provided")
|
91
|
+
if "reference" not in target_data:
|
92
|
+
raise_error("No `reference` provided")
|
93
|
+
if "path" not in target_data["reference"]:
|
94
|
+
raise_error("No `path` provided in `reference`")
|
95
|
+
|
96
|
+
logger.debug("Using ANTs for maps transformation")
|
97
|
+
|
98
|
+
# Save existing maps image to a tempfile
|
99
|
+
prewarp_maps_path = element_tempdir / "prewarp_maps.nii.gz"
|
100
|
+
nib.save(maps_img, prewarp_maps_path)
|
101
|
+
|
102
|
+
# Create a tempfile for warped output
|
103
|
+
warped_maps_path = element_tempdir / "maps_warped.nii.gz"
|
104
|
+
# Set antsApplyTransforms command
|
105
|
+
apply_transforms_cmd = [
|
106
|
+
"antsApplyTransforms",
|
107
|
+
"-d 3",
|
108
|
+
"-e 3",
|
109
|
+
"-n LanczosWindowedSinc",
|
110
|
+
f"-i {prewarp_maps_path.resolve()}",
|
111
|
+
# use resampled reference
|
112
|
+
f"-r {target_data['reference']['path'].resolve()}",
|
113
|
+
f"-t {warp_data['path'].resolve()}",
|
114
|
+
f"-o {warped_maps_path.resolve()}",
|
115
|
+
]
|
116
|
+
# Call antsApplyTransforms
|
117
|
+
run_ext_cmd(name="antsApplyTransforms", cmd=apply_transforms_cmd)
|
118
|
+
|
119
|
+
# Template space warping
|
120
|
+
else:
|
121
|
+
logger.debug(f"Using ANTs to warp maps from {src} to {dst}")
|
122
|
+
|
123
|
+
# Get xfm file
|
124
|
+
xfm_file_path = get_xfm(src=src, dst=dst)
|
125
|
+
# Get template space image
|
126
|
+
template_space_img = get_template(
|
127
|
+
space=dst,
|
128
|
+
target_img=maps_img,
|
129
|
+
extra_input=None,
|
130
|
+
)
|
131
|
+
# Save template to a tempfile
|
132
|
+
template_space_img_path = element_tempdir / f"{dst}_T1w.nii.gz"
|
133
|
+
nib.save(template_space_img, template_space_img_path)
|
134
|
+
|
135
|
+
# Save existing maps image to a tempfile
|
136
|
+
prewarp_maps_path = element_tempdir / "prewarp_maps.nii.gz"
|
137
|
+
nib.save(maps_img, prewarp_maps_path)
|
138
|
+
|
139
|
+
# Create a tempfile for warped output
|
140
|
+
warped_maps_path = element_tempdir / "maps_warped.nii.gz"
|
141
|
+
# Set antsApplyTransforms command
|
142
|
+
apply_transforms_cmd = [
|
143
|
+
"antsApplyTransforms",
|
144
|
+
"-d 3",
|
145
|
+
"-e 3",
|
146
|
+
"-n LanczosWindowedSinc",
|
147
|
+
f"-i {prewarp_maps_path.resolve()}",
|
148
|
+
f"-r {template_space_img_path.resolve()}",
|
149
|
+
f"-t {xfm_file_path.resolve()}",
|
150
|
+
f"-o {warped_maps_path.resolve()}",
|
151
|
+
]
|
152
|
+
# Call antsApplyTransforms
|
153
|
+
run_ext_cmd(name="antsApplyTransforms", cmd=apply_transforms_cmd)
|
154
|
+
|
155
|
+
# Load nifti
|
156
|
+
return nib.load(warped_maps_path)
|
@@ -0,0 +1,85 @@
|
|
1
|
+
"""Provide class for maps space warping via FSL FLIRT."""
|
2
|
+
|
3
|
+
# Authors: Synchon Mandal <s.mandal@fz-juelich.de>
|
4
|
+
# License: AGPL
|
5
|
+
|
6
|
+
import uuid
|
7
|
+
from typing import TYPE_CHECKING, Any
|
8
|
+
|
9
|
+
import nibabel as nib
|
10
|
+
|
11
|
+
from ...pipeline import WorkDirManager
|
12
|
+
from ...utils import logger, run_ext_cmd
|
13
|
+
|
14
|
+
|
15
|
+
if TYPE_CHECKING:
|
16
|
+
from nibabel.nifti1 import Nifti1Image
|
17
|
+
|
18
|
+
|
19
|
+
__all__ = ["FSLMapsWarper"]
|
20
|
+
|
21
|
+
|
22
|
+
class FSLMapsWarper:
|
23
|
+
"""Class for maps space warping via FSL FLIRT.
|
24
|
+
|
25
|
+
This class uses FSL FLIRT's ``applywarp`` for transformation.
|
26
|
+
|
27
|
+
"""
|
28
|
+
|
29
|
+
def warp(
|
30
|
+
self,
|
31
|
+
maps_name: str,
|
32
|
+
maps_img: "Nifti1Image",
|
33
|
+
target_data: dict[str, Any],
|
34
|
+
warp_data: dict[str, Any],
|
35
|
+
) -> "Nifti1Image": # pragma: no cover
|
36
|
+
"""Warp ``maps_img`` to correct space.
|
37
|
+
|
38
|
+
Parameters
|
39
|
+
----------
|
40
|
+
maps_name : str
|
41
|
+
The name of the maps.
|
42
|
+
maps_img : nibabel.nifti1.Nifti1Image
|
43
|
+
The maps image to transform.
|
44
|
+
target_data : dict
|
45
|
+
The corresponding item of the data object to which the maps
|
46
|
+
will be applied.
|
47
|
+
warp_data : dict
|
48
|
+
The warp data item of the data object.
|
49
|
+
|
50
|
+
Returns
|
51
|
+
-------
|
52
|
+
nibabel.nifti1.Nifti1Image
|
53
|
+
The transformed maps image.
|
54
|
+
|
55
|
+
"""
|
56
|
+
logger.debug("Using FSL for maps transformation")
|
57
|
+
|
58
|
+
# Create element-scoped tempdir so that warped maps is
|
59
|
+
# available later as nibabel stores file path reference for
|
60
|
+
# loading on computation
|
61
|
+
element_tempdir = WorkDirManager().get_element_tempdir(
|
62
|
+
prefix=f"fsl_maps_warper_{maps_name}_{uuid.uuid1()}"
|
63
|
+
)
|
64
|
+
|
65
|
+
# Save existing maps image to a tempfile
|
66
|
+
prewarp_maps_path = element_tempdir / "prewarp_maps.nii.gz"
|
67
|
+
nib.save(maps_img, prewarp_maps_path)
|
68
|
+
|
69
|
+
# Create a tempfile for warped output
|
70
|
+
warped_maps_path = element_tempdir / "maps_warped.nii.gz"
|
71
|
+
# Set applywarp command
|
72
|
+
applywarp_cmd = [
|
73
|
+
"applywarp",
|
74
|
+
"--interp=spline",
|
75
|
+
f"-i {prewarp_maps_path.resolve()}",
|
76
|
+
# use resampled reference
|
77
|
+
f"-r {target_data['reference']['path'].resolve()}",
|
78
|
+
f"-w {warp_data['path'].resolve()}",
|
79
|
+
f"-o {warped_maps_path.resolve()}",
|
80
|
+
]
|
81
|
+
# Call applywarp
|
82
|
+
run_ext_cmd(name="applywarp", cmd=applywarp_cmd)
|
83
|
+
|
84
|
+
# Load nifti
|
85
|
+
return nib.load(warped_maps_path)
|