junifer 0.0.7.dev132__py3-none-any.whl → 0.0.7.dev153__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/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-0.0.7.dev132.dist-info → junifer-0.0.7.dev153.dist-info}/METADATA +2 -2
- {junifer-0.0.7.dev132.dist-info → junifer-0.0.7.dev153.dist-info}/RECORD +18 -12
- {junifer-0.0.7.dev132.dist-info → junifer-0.0.7.dev153.dist-info}/WHEEL +0 -0
- {junifer-0.0.7.dev132.dist-info → junifer-0.0.7.dev153.dist-info}/entry_points.txt +0 -0
- {junifer-0.0.7.dev132.dist-info → junifer-0.0.7.dev153.dist-info}/licenses/AUTHORS.rst +0 -0
- {junifer-0.0.7.dev132.dist-info → junifer-0.0.7.dev153.dist-info}/licenses/LICENSE.md +0 -0
- {junifer-0.0.7.dev132.dist-info → junifer-0.0.7.dev153.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.dev153'
|
32
|
+
__version_tuple__ = version_tuple = (0, 0, 7, 'dev153')
|
33
33
|
|
34
34
|
__commit_id__ = commit_id = None
|
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)
|
@@ -0,0 +1,446 @@
|
|
1
|
+
"""Provide a class for centralized maps data registry."""
|
2
|
+
|
3
|
+
# Authors: Synchon Mandal <s.mandal@fz-juelich.de>
|
4
|
+
# License: AGPL
|
5
|
+
|
6
|
+
from pathlib import Path
|
7
|
+
from typing import TYPE_CHECKING, Any, Optional, Union
|
8
|
+
|
9
|
+
import nibabel as nib
|
10
|
+
import nilearn.image as nimg
|
11
|
+
import numpy as np
|
12
|
+
from junifer_data import get
|
13
|
+
|
14
|
+
from ...utils import logger, raise_error
|
15
|
+
from ..pipeline_data_registry_base import BasePipelineDataRegistry
|
16
|
+
from ..utils import (
|
17
|
+
JUNIFER_DATA_PARAMS,
|
18
|
+
closest_resolution,
|
19
|
+
get_dataset_path,
|
20
|
+
get_native_warper,
|
21
|
+
)
|
22
|
+
from ._ants_maps_warper import ANTsMapsWarper
|
23
|
+
from ._fsl_maps_warper import FSLMapsWarper
|
24
|
+
|
25
|
+
|
26
|
+
if TYPE_CHECKING:
|
27
|
+
from nibabel.nifti1 import Nifti1Image
|
28
|
+
|
29
|
+
|
30
|
+
__all__ = ["MapsRegistry"]
|
31
|
+
|
32
|
+
|
33
|
+
class MapsRegistry(BasePipelineDataRegistry):
|
34
|
+
"""Class for maps data registry.
|
35
|
+
|
36
|
+
This class is a singleton and is used for managing available maps
|
37
|
+
data in a centralized manner.
|
38
|
+
|
39
|
+
"""
|
40
|
+
|
41
|
+
def __init__(self) -> None:
|
42
|
+
"""Initialize the class."""
|
43
|
+
super().__init__()
|
44
|
+
# Each entry in registry is a dictionary that must contain at least
|
45
|
+
# the following keys:
|
46
|
+
# * 'family': the maps' family name (e.g., 'Smith')
|
47
|
+
# * 'space': the maps' space (e.g., 'MNI')
|
48
|
+
# and can also have optional key(s):
|
49
|
+
# * 'valid_resolutions': a list of valid resolutions for the
|
50
|
+
# maps (e.g., [1, 2])
|
51
|
+
# The built-in maps are files that are shipped with the
|
52
|
+
# junifer-data dataset.
|
53
|
+
# Make built-in and external dictionaries for validation later
|
54
|
+
self._builtin = {}
|
55
|
+
self._external = {}
|
56
|
+
|
57
|
+
# Add Smith
|
58
|
+
for comp in ["rsn", "bm"]:
|
59
|
+
for dim in [10, 20, 70]:
|
60
|
+
self._builtin.update(
|
61
|
+
{
|
62
|
+
f"Smith_{comp}_{dim}": {
|
63
|
+
"family": "Smith2009",
|
64
|
+
"components": comp,
|
65
|
+
"dimension": dim,
|
66
|
+
"space": "MNI152NLin6Asym",
|
67
|
+
}
|
68
|
+
}
|
69
|
+
)
|
70
|
+
|
71
|
+
# Update registry with built-in ones
|
72
|
+
self._registry.update(self._builtin)
|
73
|
+
|
74
|
+
def register(
|
75
|
+
self,
|
76
|
+
name: str,
|
77
|
+
maps_path: Union[str, Path],
|
78
|
+
maps_labels: list[str],
|
79
|
+
space: str,
|
80
|
+
overwrite: bool = False,
|
81
|
+
) -> None:
|
82
|
+
"""Register a custom user map(s).
|
83
|
+
|
84
|
+
Parameters
|
85
|
+
----------
|
86
|
+
name : str
|
87
|
+
The name of the map(s).
|
88
|
+
maps_path : str or pathlib.Path
|
89
|
+
The path to the map(s) file.
|
90
|
+
maps_labels : list of str
|
91
|
+
The list of labels for the map(s).
|
92
|
+
space : str
|
93
|
+
The template space of the map(s), e.g., "MNI152NLin6Asym".
|
94
|
+
overwrite : bool, optional
|
95
|
+
If True, overwrite an existing maps with the same name.
|
96
|
+
Does not apply to built-in maps (default False).
|
97
|
+
|
98
|
+
Raises
|
99
|
+
------
|
100
|
+
ValueError
|
101
|
+
If the map(s) ``name`` is a built-in map(s) or
|
102
|
+
if the map(s) ``name`` is already registered and
|
103
|
+
``overwrite=False``.
|
104
|
+
|
105
|
+
"""
|
106
|
+
# Check for attempt of overwriting built-in maps
|
107
|
+
if name in self._builtin:
|
108
|
+
raise_error(
|
109
|
+
f"Map(s): {name} already registered as built-in map(s)."
|
110
|
+
)
|
111
|
+
# Check for attempt of overwriting external maps
|
112
|
+
if name in self._external:
|
113
|
+
if overwrite:
|
114
|
+
logger.info(f"Overwriting map(s): {name}")
|
115
|
+
else:
|
116
|
+
raise_error(
|
117
|
+
f"Map(s): {name} already registered. Set "
|
118
|
+
"`overwrite=True` to update its value."
|
119
|
+
)
|
120
|
+
# Convert str to Path
|
121
|
+
if not isinstance(maps_path, Path):
|
122
|
+
maps_path = Path(maps_path)
|
123
|
+
# Registration
|
124
|
+
logger.info(f"Registering map(s): {name}")
|
125
|
+
# Add user maps info
|
126
|
+
self._external[name] = {
|
127
|
+
"path": maps_path,
|
128
|
+
"labels": maps_labels,
|
129
|
+
"family": "CustomUserMaps",
|
130
|
+
"space": space,
|
131
|
+
}
|
132
|
+
# Update registry
|
133
|
+
self._registry[name] = {
|
134
|
+
"path": maps_path,
|
135
|
+
"labels": maps_labels,
|
136
|
+
"family": "CustomUserMaps",
|
137
|
+
"space": space,
|
138
|
+
}
|
139
|
+
|
140
|
+
def deregister(self, name: str) -> None:
|
141
|
+
"""De-register a custom user map(s).
|
142
|
+
|
143
|
+
Parameters
|
144
|
+
----------
|
145
|
+
name : str
|
146
|
+
The name of the map(s).
|
147
|
+
|
148
|
+
"""
|
149
|
+
logger.info(f"De-registering map(s): {name}")
|
150
|
+
# Remove maps info
|
151
|
+
_ = self._external.pop(name)
|
152
|
+
# Update registry
|
153
|
+
_ = self._registry.pop(name)
|
154
|
+
|
155
|
+
def load(
|
156
|
+
self,
|
157
|
+
name: str,
|
158
|
+
target_space: str,
|
159
|
+
resolution: Optional[float] = None,
|
160
|
+
path_only: bool = False,
|
161
|
+
) -> tuple[Optional["Nifti1Image"], list[str], Path, str]:
|
162
|
+
"""Load map(s) and labels.
|
163
|
+
|
164
|
+
Parameters
|
165
|
+
----------
|
166
|
+
name : str
|
167
|
+
The name of the map(s).
|
168
|
+
target_space : str
|
169
|
+
The desired space of the map(s).
|
170
|
+
resolution : float, optional
|
171
|
+
The desired resolution of the map(s) to load. If it is not
|
172
|
+
available, the closest resolution will be loaded. Preferably, use a
|
173
|
+
resolution higher than the desired one. By default, will load the
|
174
|
+
highest one (default None).
|
175
|
+
path_only : bool, optional
|
176
|
+
If True, the map(s) image will not be loaded (default False).
|
177
|
+
|
178
|
+
Returns
|
179
|
+
-------
|
180
|
+
Nifti1Image or None
|
181
|
+
Loaded map(s) image.
|
182
|
+
list of str
|
183
|
+
Map(s) labels.
|
184
|
+
pathlib.Path
|
185
|
+
File path to the map(s) image.
|
186
|
+
str
|
187
|
+
The space of the map(s).
|
188
|
+
|
189
|
+
Raises
|
190
|
+
------
|
191
|
+
ValueError
|
192
|
+
If ``name`` is invalid or
|
193
|
+
if the map(s) family is invalid or
|
194
|
+
if the map(s) values and labels
|
195
|
+
don't have equal dimension or if the value range is invalid.
|
196
|
+
|
197
|
+
"""
|
198
|
+
# Check for valid maps name
|
199
|
+
if name not in self._registry:
|
200
|
+
raise_error(
|
201
|
+
f"Map(s): {name} not found. Valid options are: {self.list}"
|
202
|
+
)
|
203
|
+
|
204
|
+
# Copy maps definition to avoid edits in original object
|
205
|
+
maps_def = self._registry[name].copy()
|
206
|
+
t_family = maps_def.pop("family")
|
207
|
+
space = maps_def.pop("space")
|
208
|
+
|
209
|
+
# Check and get highest resolution
|
210
|
+
if space != target_space:
|
211
|
+
logger.info(
|
212
|
+
f"Map(s) will be warped from {space} to {target_space} "
|
213
|
+
"using highest resolution"
|
214
|
+
)
|
215
|
+
resolution = None
|
216
|
+
|
217
|
+
# Check if the maps family is custom or built-in
|
218
|
+
if t_family == "CustomUserMaps":
|
219
|
+
maps_fname = maps_def["path"]
|
220
|
+
maps_labels = maps_def["labels"]
|
221
|
+
elif t_family in [
|
222
|
+
"Smith2009",
|
223
|
+
]:
|
224
|
+
# Load maps and labels
|
225
|
+
if t_family == "Smith2009":
|
226
|
+
maps_fname, maps_labels = _retrieve_smith(
|
227
|
+
resolution=resolution,
|
228
|
+
**maps_def,
|
229
|
+
)
|
230
|
+
else: # pragma: no cover
|
231
|
+
raise_error(f"Unknown map(s) family: {t_family}")
|
232
|
+
|
233
|
+
# Load maps image and values
|
234
|
+
logger.info(f"Loading map(s): {maps_fname.absolute()!s}")
|
235
|
+
maps_img = None
|
236
|
+
if not path_only:
|
237
|
+
# Load image via nibabel
|
238
|
+
maps_img = nib.load(maps_fname)
|
239
|
+
# Get regions
|
240
|
+
maps_regions = maps_img.get_fdata().shape[-1]
|
241
|
+
# Check for dimension
|
242
|
+
if maps_regions != len(maps_labels):
|
243
|
+
raise_error(
|
244
|
+
f"Map(s) {name} has {maps_regions} "
|
245
|
+
f"regions but {len(maps_labels)} labels."
|
246
|
+
)
|
247
|
+
|
248
|
+
return maps_img, maps_labels, maps_fname, space
|
249
|
+
|
250
|
+
def get(
|
251
|
+
self,
|
252
|
+
maps: str,
|
253
|
+
target_data: dict[str, Any],
|
254
|
+
extra_input: Optional[dict[str, Any]] = None,
|
255
|
+
) -> tuple["Nifti1Image", list[str]]:
|
256
|
+
"""Get map(s), tailored for the target image.
|
257
|
+
|
258
|
+
Parameters
|
259
|
+
----------
|
260
|
+
maps : str
|
261
|
+
The name of the map(s).
|
262
|
+
target_data : dict
|
263
|
+
The corresponding item of the data object to which the map(s)
|
264
|
+
will be applied.
|
265
|
+
extra_input : dict, optional
|
266
|
+
The other fields in the data object. Useful for accessing other
|
267
|
+
data kinds that needs to be used in the computation of
|
268
|
+
map(s) (default None).
|
269
|
+
|
270
|
+
Returns
|
271
|
+
-------
|
272
|
+
Nifti1Image
|
273
|
+
The map(s) image.
|
274
|
+
list of str
|
275
|
+
Map(s) labels.
|
276
|
+
|
277
|
+
Raises
|
278
|
+
------
|
279
|
+
ValueError
|
280
|
+
If ``extra_input`` is None when ``target_data``'s space is native.
|
281
|
+
|
282
|
+
"""
|
283
|
+
# Check pre-requirements for space manipulation
|
284
|
+
target_space = target_data["space"]
|
285
|
+
logger.debug(f"Getting {maps} in {target_space} space.")
|
286
|
+
# Extra data type requirement check if target space is native
|
287
|
+
if target_space == "native": # pragma: no cover
|
288
|
+
# Check for extra inputs
|
289
|
+
if extra_input is None:
|
290
|
+
raise_error(
|
291
|
+
"No extra input provided, requires `Warp` and `T1w` "
|
292
|
+
"data types in particular for transformation to "
|
293
|
+
f"{target_data['space']} space for further computation."
|
294
|
+
)
|
295
|
+
# Get native space warper spec
|
296
|
+
warper_spec = get_native_warper(
|
297
|
+
target_data=target_data,
|
298
|
+
other_data=extra_input,
|
299
|
+
)
|
300
|
+
# Set target standard space to warp file space source
|
301
|
+
target_std_space = warper_spec["src"]
|
302
|
+
logger.debug(
|
303
|
+
f"Target space is native. Will warp from {target_std_space}"
|
304
|
+
)
|
305
|
+
else:
|
306
|
+
# Set target standard space to target space
|
307
|
+
target_std_space = target_space
|
308
|
+
|
309
|
+
# Get the min of the voxels sizes and use it as the resolution
|
310
|
+
target_img = target_data["data"]
|
311
|
+
resolution = np.min(target_img.header.get_zooms()[:3])
|
312
|
+
|
313
|
+
# Load maps
|
314
|
+
logger.debug(f"Loading map(s) {maps}")
|
315
|
+
img, labels, _, space = self.load(
|
316
|
+
name=maps,
|
317
|
+
resolution=resolution,
|
318
|
+
target_space=target_space,
|
319
|
+
)
|
320
|
+
|
321
|
+
# Convert maps spaces if required;
|
322
|
+
# cannot be "native" due to earlier check
|
323
|
+
if space != target_std_space:
|
324
|
+
logger.debug(
|
325
|
+
f"Warping {maps} to {target_std_space} space using ANTs."
|
326
|
+
)
|
327
|
+
raw_img = ANTsMapsWarper().warp(
|
328
|
+
maps_name=maps,
|
329
|
+
maps_img=img,
|
330
|
+
src=space,
|
331
|
+
dst=target_std_space,
|
332
|
+
target_data=target_data,
|
333
|
+
warp_data=None,
|
334
|
+
)
|
335
|
+
# Remove extra dimension added by ANTs
|
336
|
+
img = nimg.math_img("np.squeeze(img)", img=raw_img)
|
337
|
+
|
338
|
+
if target_space != "native":
|
339
|
+
# No warping is going to happen, just resampling, because
|
340
|
+
# we are in the correct space
|
341
|
+
logger.debug(f"Resampling {maps} to target image.")
|
342
|
+
# Resample maps to target image
|
343
|
+
img = nimg.resample_to_img(
|
344
|
+
source_img=img,
|
345
|
+
target_img=target_img,
|
346
|
+
interpolation="continuous",
|
347
|
+
copy=True,
|
348
|
+
)
|
349
|
+
else: # pragma: no cover
|
350
|
+
# Warp maps if target space is native as either
|
351
|
+
# the image is in the right non-native space or it's
|
352
|
+
# warped from one non-native space to another non-native space
|
353
|
+
logger.debug(
|
354
|
+
"Warping map(s) to native space using "
|
355
|
+
f"{warper_spec['warper']}."
|
356
|
+
)
|
357
|
+
# extra_input check done earlier and warper_spec exists
|
358
|
+
if warper_spec["warper"] == "fsl":
|
359
|
+
img = FSLMapsWarper().warp(
|
360
|
+
maps_name="native",
|
361
|
+
maps_img=img,
|
362
|
+
target_data=target_data,
|
363
|
+
warp_data=warper_spec,
|
364
|
+
)
|
365
|
+
elif warper_spec["warper"] == "ants":
|
366
|
+
img = ANTsMapsWarper().warp(
|
367
|
+
maps_name="native",
|
368
|
+
maps_img=img,
|
369
|
+
src="",
|
370
|
+
dst="native",
|
371
|
+
target_data=target_data,
|
372
|
+
warp_data=warper_spec,
|
373
|
+
)
|
374
|
+
|
375
|
+
return img, labels
|
376
|
+
|
377
|
+
|
378
|
+
def _retrieve_smith(
|
379
|
+
resolution: Optional[float] = None,
|
380
|
+
components: Optional[str] = None,
|
381
|
+
dimension: Optional[int] = None,
|
382
|
+
) -> tuple[Path, list[str]]:
|
383
|
+
"""Retrieve Smith maps.
|
384
|
+
|
385
|
+
Parameters
|
386
|
+
----------
|
387
|
+
resolution : 2.0, optional
|
388
|
+
The desired resolution of the maps to load. If it is not
|
389
|
+
available, the closest resolution will be loaded. Preferably, use a
|
390
|
+
resolution higher than the desired one. By default, will load the
|
391
|
+
highest one (default None). Available resolution for these
|
392
|
+
maps are 2mm.
|
393
|
+
components : {"rsn", "bm"}, optional
|
394
|
+
The components to load. "rsn" loads the resting-fMRI components and
|
395
|
+
"bm" loads the BrainMap components (default None).
|
396
|
+
dimension : {10, 20, 70}, optional
|
397
|
+
The number of dimensions to load (default None).
|
398
|
+
|
399
|
+
Returns
|
400
|
+
-------
|
401
|
+
pathlib.Path
|
402
|
+
File path to the maps image.
|
403
|
+
list of str
|
404
|
+
Maps labels.
|
405
|
+
|
406
|
+
Raises
|
407
|
+
------
|
408
|
+
ValueError
|
409
|
+
If invalid value is provided for ``components`` or ``dimension``.
|
410
|
+
|
411
|
+
"""
|
412
|
+
logger.info("Maps parameters:")
|
413
|
+
logger.info(f"\tresolution: {resolution}")
|
414
|
+
logger.info(f"\tcomponents: {components}")
|
415
|
+
logger.info(f"\tdimension: {dimension}")
|
416
|
+
|
417
|
+
# Check resolution
|
418
|
+
_valid_resolutions = [2.0]
|
419
|
+
resolution = closest_resolution(resolution, _valid_resolutions)
|
420
|
+
|
421
|
+
# Check components value
|
422
|
+
_valid_components = ["rsn", "bm"]
|
423
|
+
if components not in _valid_components:
|
424
|
+
raise_error(
|
425
|
+
f"The parameter `components` ({components}) needs to be one of "
|
426
|
+
f"the following: {_valid_components}"
|
427
|
+
)
|
428
|
+
|
429
|
+
# Check dimension value
|
430
|
+
_valid_dimension = [10, 20, 70]
|
431
|
+
if dimension not in _valid_dimension:
|
432
|
+
raise_error(
|
433
|
+
f"The parameter `dimension` ({dimension}) needs to be one of the "
|
434
|
+
f"following: {_valid_dimension}"
|
435
|
+
)
|
436
|
+
|
437
|
+
# Fetch file path
|
438
|
+
maps_img_path = get(
|
439
|
+
file_path=Path(
|
440
|
+
f"parcellations/Smith2009/{components}{dimension}.nii.gz"
|
441
|
+
),
|
442
|
+
dataset_path=get_dataset_path(),
|
443
|
+
**JUNIFER_DATA_PARAMS,
|
444
|
+
)
|
445
|
+
|
446
|
+
return maps_img_path, [f"Map_{i}" for i in range(dimension)]
|
@@ -0,0 +1,255 @@
|
|
1
|
+
"""Provide tests for maps."""
|
2
|
+
|
3
|
+
# Authors: Synchon Mandal <s.mandal@fz-juelich.de>
|
4
|
+
# License: AGPL
|
5
|
+
|
6
|
+
import pytest
|
7
|
+
from numpy.testing import assert_array_equal
|
8
|
+
|
9
|
+
from junifer.data import (
|
10
|
+
deregister_data,
|
11
|
+
get_data,
|
12
|
+
list_data,
|
13
|
+
load_data,
|
14
|
+
register_data,
|
15
|
+
)
|
16
|
+
from junifer.data.maps._maps import _retrieve_smith
|
17
|
+
from junifer.datagrabber import PatternDataladDataGrabber
|
18
|
+
from junifer.datareader import DefaultDataReader
|
19
|
+
from junifer.pipeline.utils import _check_ants
|
20
|
+
from junifer.testing.datagrabbers import PartlyCloudyTestingDataGrabber
|
21
|
+
|
22
|
+
|
23
|
+
def test_register_built_in_check() -> None:
|
24
|
+
"""Test maps registration check for built-in maps."""
|
25
|
+
with pytest.raises(ValueError, match=r"built-in"):
|
26
|
+
register_data(
|
27
|
+
kind="maps",
|
28
|
+
name="Smith_rsn_10",
|
29
|
+
maps_path="testmaps.nii.gz",
|
30
|
+
maps_labels=["1", "2"],
|
31
|
+
space="MNI",
|
32
|
+
)
|
33
|
+
|
34
|
+
|
35
|
+
def test_list_incorrect() -> None:
|
36
|
+
"""Test incorrect information check for list mapss."""
|
37
|
+
assert "testmaps" not in list_data(kind="maps")
|
38
|
+
|
39
|
+
|
40
|
+
def test_register_overwrite() -> None:
|
41
|
+
"""Test maps registration check for overwriting."""
|
42
|
+
register_data(
|
43
|
+
kind="maps",
|
44
|
+
name="testmaps",
|
45
|
+
maps_path="testmaps.nii.gz",
|
46
|
+
maps_labels=["1", "2"],
|
47
|
+
space="MNI152NLin6Sym",
|
48
|
+
)
|
49
|
+
with pytest.raises(ValueError, match=r"already registered"):
|
50
|
+
register_data(
|
51
|
+
kind="maps",
|
52
|
+
name="testmaps",
|
53
|
+
maps_path="testmaps.nii.gz",
|
54
|
+
maps_labels=["1", "2"],
|
55
|
+
space="MNI152NLin6Sym",
|
56
|
+
overwrite=False,
|
57
|
+
)
|
58
|
+
|
59
|
+
register_data(
|
60
|
+
kind="maps",
|
61
|
+
name="testmaps",
|
62
|
+
maps_path="testmaps.nii.gz",
|
63
|
+
maps_labels=["1", "2"],
|
64
|
+
space="MNI152NLin6Sym",
|
65
|
+
overwrite=True,
|
66
|
+
)
|
67
|
+
|
68
|
+
assert (
|
69
|
+
load_data(
|
70
|
+
kind="maps",
|
71
|
+
name="testmaps",
|
72
|
+
target_space="MNI152NLin6Sym",
|
73
|
+
path_only=True,
|
74
|
+
)[2].name
|
75
|
+
== "testmaps.nii.gz"
|
76
|
+
)
|
77
|
+
|
78
|
+
|
79
|
+
def test_register_valid_input() -> None:
|
80
|
+
"""Test maps registration check for valid input."""
|
81
|
+
maps, labels, maps_path, _ = load_data(
|
82
|
+
kind="maps",
|
83
|
+
name="Smith_rsn_10",
|
84
|
+
target_space="MNI152NLin6Asym",
|
85
|
+
)
|
86
|
+
assert maps is not None
|
87
|
+
|
88
|
+
# Test wrong number of labels
|
89
|
+
register_data(
|
90
|
+
kind="maps",
|
91
|
+
name="WrongLabels",
|
92
|
+
maps_path=maps_path,
|
93
|
+
maps_labels=labels[:5],
|
94
|
+
space="MNI152NLin6Asym",
|
95
|
+
)
|
96
|
+
with pytest.raises(ValueError, match=r"has 10 regions but 5"):
|
97
|
+
load_data(
|
98
|
+
kind="maps",
|
99
|
+
name="WrongLabels",
|
100
|
+
target_space="MNI152NLin6Asym",
|
101
|
+
)
|
102
|
+
|
103
|
+
|
104
|
+
def test_list() -> None:
|
105
|
+
"""Test listing of available coordinates."""
|
106
|
+
assert {"Smith_rsn_10", "Smith_bm_70"}.issubset(
|
107
|
+
set(list_data(kind="maps"))
|
108
|
+
)
|
109
|
+
|
110
|
+
|
111
|
+
def test_load_nonexisting() -> None:
|
112
|
+
"""Test loading maps that not exist."""
|
113
|
+
with pytest.raises(ValueError, match=r"not found"):
|
114
|
+
load_data(kind="maps", name="nomaps", target_space="MNI152NLin6Sym")
|
115
|
+
|
116
|
+
|
117
|
+
def test_get() -> None:
|
118
|
+
"""Test tailored maps fetch."""
|
119
|
+
with PatternDataladDataGrabber(
|
120
|
+
uri="https://github.com/OpenNeuroDatasets/ds005226.git",
|
121
|
+
types=["BOLD"],
|
122
|
+
patterns={
|
123
|
+
"BOLD": {
|
124
|
+
"pattern": (
|
125
|
+
"derivatives/pre-processed_data/space-MNI/{subject}/"
|
126
|
+
"{subject-padded}_task-{task}_run-{run}_space-MNI152NLin6Asym"
|
127
|
+
"_res-2_desc-preproc_bold.nii.gz"
|
128
|
+
),
|
129
|
+
"space": "MNI152NLin6Asym",
|
130
|
+
},
|
131
|
+
},
|
132
|
+
replacements=["subject", "subject-padded", "task", "run"],
|
133
|
+
) as dg:
|
134
|
+
element = dg[("sub-01", "sub-001", "rest", "1")]
|
135
|
+
element_data = DefaultDataReader().fit_transform(element)
|
136
|
+
bold = element_data["BOLD"]
|
137
|
+
bold_img = bold["data"]
|
138
|
+
# Get tailored coordinates
|
139
|
+
tailored_maps, tailored_labels = get_data(
|
140
|
+
kind="maps", names="Smith_rsn_10", target_data=bold
|
141
|
+
)
|
142
|
+
|
143
|
+
# Check shape with original element data
|
144
|
+
assert tailored_maps.shape[:3] == bold_img.shape[:3]
|
145
|
+
|
146
|
+
# Get raw maps
|
147
|
+
raw_maps, raw_labels, _, _ = load_data(
|
148
|
+
kind="maps", name="Smith_rsn_10", target_space="MNI152NLin6Asym"
|
149
|
+
)
|
150
|
+
# Tailored and raw shape should be same
|
151
|
+
assert tailored_maps.shape[:3] == raw_maps.shape[:3]
|
152
|
+
assert tailored_labels == raw_labels
|
153
|
+
|
154
|
+
|
155
|
+
@pytest.mark.skipif(
|
156
|
+
_check_ants() is False, reason="requires ANTs to be in PATH"
|
157
|
+
)
|
158
|
+
def test_get_different_space() -> None:
|
159
|
+
"""Test tailored maps fetch in different space."""
|
160
|
+
with PartlyCloudyTestingDataGrabber() as dg:
|
161
|
+
element = dg["sub-01"]
|
162
|
+
element_data = DefaultDataReader().fit_transform(element)
|
163
|
+
bold = element_data["BOLD"]
|
164
|
+
bold_img = bold["data"]
|
165
|
+
# Get tailored coordinates
|
166
|
+
tailored_maps, tailored_labels = get_data(
|
167
|
+
kind="maps", names="Smith_rsn_10", target_data=bold
|
168
|
+
)
|
169
|
+
|
170
|
+
# Check shape with original element data
|
171
|
+
assert tailored_maps.shape[:3] == bold_img.shape[:3]
|
172
|
+
|
173
|
+
# Get raw maps
|
174
|
+
raw_maps, raw_labels, _, _ = load_data(
|
175
|
+
kind="maps",
|
176
|
+
name="Smith_rsn_10",
|
177
|
+
target_space="MNI152NLin2009cAsym",
|
178
|
+
)
|
179
|
+
# Tailored and raw should not be same
|
180
|
+
assert tailored_maps.shape[:3] != raw_maps.shape[:3]
|
181
|
+
assert tailored_labels == raw_labels
|
182
|
+
|
183
|
+
|
184
|
+
def test_deregister() -> None:
|
185
|
+
"""Test maps deregistration."""
|
186
|
+
deregister_data(kind="maps", name="testmaps")
|
187
|
+
assert "testmaps" not in list_data(kind="maps")
|
188
|
+
|
189
|
+
|
190
|
+
@pytest.mark.parametrize(
|
191
|
+
"resolution, components, dimension",
|
192
|
+
[
|
193
|
+
(2.0, "rsn", 10),
|
194
|
+
(2.0, "rsn", 20),
|
195
|
+
(2.0, "rsn", 70),
|
196
|
+
(2.0, "bm", 10),
|
197
|
+
(2.0, "bm", 20),
|
198
|
+
(2.0, "bm", 70),
|
199
|
+
],
|
200
|
+
)
|
201
|
+
def test_smith(
|
202
|
+
resolution: float,
|
203
|
+
components: str,
|
204
|
+
dimension: int,
|
205
|
+
) -> None:
|
206
|
+
"""Test Smith maps.
|
207
|
+
|
208
|
+
Parameters
|
209
|
+
----------
|
210
|
+
resolution : float
|
211
|
+
The parametrized resolution values.
|
212
|
+
components : str
|
213
|
+
The parametrized components values.
|
214
|
+
dimension : int
|
215
|
+
The parametrized dimension values.
|
216
|
+
|
217
|
+
"""
|
218
|
+
maps = list_data(kind="maps")
|
219
|
+
maps_name = f"Smith_{components}_{dimension}"
|
220
|
+
assert maps_name in maps
|
221
|
+
|
222
|
+
maps_file = f"{components}{dimension}.nii.gz"
|
223
|
+
# Load maps
|
224
|
+
img, label, img_path, space = load_data(
|
225
|
+
kind="maps",
|
226
|
+
name=maps_name,
|
227
|
+
target_space="MNI152NLin6Asym",
|
228
|
+
resolution=resolution,
|
229
|
+
)
|
230
|
+
assert img is not None
|
231
|
+
assert img_path.name == maps_file
|
232
|
+
assert space == "MNI152NLin6Asym"
|
233
|
+
assert len(label) == dimension
|
234
|
+
assert_array_equal(
|
235
|
+
img.header["pixdim"][1:4],
|
236
|
+
3 * [2.0],
|
237
|
+
)
|
238
|
+
|
239
|
+
|
240
|
+
def test_retrieve_smith_incorrect_components() -> None:
|
241
|
+
"""Test retrieve Smith with incorrect components."""
|
242
|
+
with pytest.raises(ValueError, match="The parameter `components`"):
|
243
|
+
_retrieve_smith(
|
244
|
+
components="abc",
|
245
|
+
dimension=10,
|
246
|
+
)
|
247
|
+
|
248
|
+
|
249
|
+
def test_retrieve_smith_incorrect_dimension() -> None:
|
250
|
+
"""Test retrieve Smith with incorrect dimension."""
|
251
|
+
with pytest.raises(ValueError, match="The parameter `dimension`"):
|
252
|
+
_retrieve_smith(
|
253
|
+
components="rsn",
|
254
|
+
dimension=100,
|
255
|
+
)
|
junifer/data/masks/_masks.py
CHANGED
@@ -231,8 +231,9 @@ class MaskRegistry(BasePipelineDataRegistry):
|
|
231
231
|
# * 'family': the mask's family name
|
232
232
|
# (e.g., 'Vickery-Patil', 'Callable')
|
233
233
|
# * 'space': the mask's space (e.g., 'MNI', 'inherit')
|
234
|
-
# The built-in masks are files that are shipped with the
|
235
|
-
# data
|
234
|
+
# The built-in masks are files that are shipped either with the
|
235
|
+
# junifer-data dataset or computed on-demand. The user can also
|
236
|
+
# register their own masks.
|
236
237
|
# Callable masks should be functions that take at least one parameter:
|
237
238
|
# * `target_img`: the image to which the mask will be applied.
|
238
239
|
# and should be included in the registry as a value to a key: `func`.
|
@@ -55,7 +55,7 @@ class ParcellationRegistry(BasePipelineDataRegistry):
|
|
55
55
|
# and can also have optional key(s):
|
56
56
|
# * 'valid_resolutions': a list of valid resolutions for the
|
57
57
|
# parcellation (e.g., [1, 2])
|
58
|
-
# The built-in
|
58
|
+
# The built-in parcellations are files that are shipped with the
|
59
59
|
# junifer-data dataset.
|
60
60
|
# Make built-in and external dictionaries for validation later
|
61
61
|
self._builtin = {}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: junifer
|
3
|
-
Version: 0.0.7.
|
3
|
+
Version: 0.0.7.dev153
|
4
4
|
Summary: JUelich NeuroImaging FEature extractoR
|
5
5
|
Author-email: Fede Raimondo <f.raimondo@fz-juelich.de>, Synchon Mandal <s.mandal@fz-juelich.de>
|
6
6
|
Maintainer-email: Fede Raimondo <f.raimondo@fz-juelich.de>, Synchon Mandal <s.mandal@fz-juelich.de>
|
@@ -39,7 +39,7 @@ Requires-Dist: sqlalchemy<=2.1.0,>=2.0.25
|
|
39
39
|
Requires-Dist: ruamel.yaml<0.19,>=0.17
|
40
40
|
Requires-Dist: h5py>=3.10
|
41
41
|
Requires-Dist: tqdm<4.67.0,>=4.66.1
|
42
|
-
Requires-Dist: templateflow
|
42
|
+
Requires-Dist: templateflow<25.0.0,>=23.0.0
|
43
43
|
Requires-Dist: lapy<2.0.0,>=1.0.0
|
44
44
|
Requires-Dist: lazy_loader==0.4
|
45
45
|
Requires-Dist: importlib_metadata; python_version < "3.9"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
junifer/__init__.py,sha256=2McgH1yNue6Z1V26-uN_mfMjbTcx4CLhym-DMBl5xA4,266
|
2
2
|
junifer/__init__.pyi,sha256=SsTvgq2Dod6UqJN96GH1lCphH6hJQQurEJHGNhHjGUI,508
|
3
|
-
junifer/_version.py,sha256=
|
3
|
+
junifer/_version.py,sha256=nGBDjmgSsVIBdNcUeVNDrvwixSrlmh0dkwRYtw7_Yeg,721
|
4
4
|
junifer/conftest.py,sha256=PWYkkRDU8ly2lYwv7VBKMHje4et6HX7Yey3Md_I2KbA,613
|
5
5
|
junifer/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
6
|
junifer/stats.py,sha256=e9aaagMGtgpRfW3Wdpz9ocpnYld1IWylCDcjFUgX9Mk,6225
|
@@ -72,8 +72,8 @@ junifer/configs/juseless/datagrabbers/tests/test_ixi_vbm.py,sha256=8jxpNZelXwpJG
|
|
72
72
|
junifer/configs/juseless/datagrabbers/tests/test_ucla.py,sha256=l-1y_m6NJo7JExhyIzp-vajUfiqiofX69YUOrRHIFKw,3246
|
73
73
|
junifer/configs/juseless/datagrabbers/tests/test_ukb_vbm.py,sha256=b9hjc1mgO--PSRC3id2EzzfE2yWNsuZ2UI47a6sfGZU,1025
|
74
74
|
junifer/data/__init__.py,sha256=xJDI2QKtdjcNzpd1oVFM3guh1SFHM6jKstl7pFmzOuk,267
|
75
|
-
junifer/data/__init__.pyi,sha256=
|
76
|
-
junifer/data/_dispatch.py,sha256=
|
75
|
+
junifer/data/__init__.pyi,sha256=3zKWlcp0JXFrZ4Pzfehha8QzG8sNSwvEKObdCfiNYuc,733
|
76
|
+
junifer/data/_dispatch.py,sha256=4T5cf6Ph6CgPFtDioM-eIMidh-IYVTKTWWJ6d2YI5UE,7660
|
77
77
|
junifer/data/pipeline_data_registry_base.py,sha256=G8bE3WTj4D_rKC4ZKZe6E48Sd96CGea1PS3SxmTgGK4,2010
|
78
78
|
junifer/data/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
79
79
|
junifer/data/template_spaces.py,sha256=7LcQbUV_SWCic-TtETCejgat-BxxFDxZFm5z80rRZ-M,4661
|
@@ -84,17 +84,23 @@ junifer/data/coordinates/_ants_coordinates_warper.py,sha256=9nIdg4B5EMje8s30n_8D
|
|
84
84
|
junifer/data/coordinates/_coordinates.py,sha256=l-nu-eGdW2Cp4eDmnrSsuWE-zcj55apPab5pTt07SwU,13303
|
85
85
|
junifer/data/coordinates/_fsl_coordinates_warper.py,sha256=fxxvsiq-hSeP_PDokMHJSxlyffMugzSDUHhKzuU7Vg4,2429
|
86
86
|
junifer/data/coordinates/tests/test_coordinates.py,sha256=JG045I7l5zcxGRQMbZZTrJY0TI5ZKaJ_szGMB6j1ZRI,4623
|
87
|
+
junifer/data/maps/__init__.py,sha256=t0J3N7RemjbCFaZfRmec0-af5lzH9Tsml5UBB9-e99M,179
|
88
|
+
junifer/data/maps/__init__.pyi,sha256=ev1ZNCXMzpw83BpWQZT-UXvR80YCuhdrKpb2VF5cmuE,67
|
89
|
+
junifer/data/maps/_ants_maps_warper.py,sha256=1gyVG89TcLYnaVyKfp4ZQYb3niV4P7U_ev1HjEVV3WQ,5340
|
90
|
+
junifer/data/maps/_fsl_maps_warper.py,sha256=OhLk3aLd6BOHBEQp88Hx-b2GwPR3ubfThgUXEJQxFEk,2439
|
91
|
+
junifer/data/maps/_maps.py,sha256=2rFixyEoKSQPW7Ztcu8hRmzlbXCuPkKQTwRTxyDIrAY,14700
|
92
|
+
junifer/data/maps/tests/test_maps.py,sha256=ZktNGd8coAbOGn95sYHAPEAhJodr6pUqVKbuGtBRenU,7378
|
87
93
|
junifer/data/masks/__init__.py,sha256=eEEhHglyVEx1LrqwXjq3cOmjf4sTsgBstRx5-k7zIQU,180
|
88
94
|
junifer/data/masks/__init__.pyi,sha256=lcgr8gmWDPibC4RxnWBXb8DDpIkO73Aax09u6VXiJJI,114
|
89
95
|
junifer/data/masks/_ants_mask_warper.py,sha256=YJYVuD4QkgFwUSs1edt2rrqfHYHaIR1u85HSeQE4GUk,5825
|
90
96
|
junifer/data/masks/_fsl_mask_warper.py,sha256=7-Aw4m9GA7ZLqB26jjuKYJUJSv9V11DfPFNBbb5caSE,2877
|
91
|
-
junifer/data/masks/_masks.py,sha256=
|
97
|
+
junifer/data/masks/_masks.py,sha256=oWArr4cgM5nvi8uzBrpEFmnxgnxqMYv-e4QiqBEp5ug,28626
|
92
98
|
junifer/data/masks/tests/test_masks.py,sha256=VK3IenIwhaYpbESe0pOjb40OKE6rcRlw8ddsBxSRfyU,16688
|
93
99
|
junifer/data/parcellations/__init__.py,sha256=6-Ysil3NyZ69V6rWx4RO15_d-iDKizfbHuxSjsHNt24,188
|
94
100
|
junifer/data/parcellations/__init__.pyi,sha256=lhBHTbMDizzqUqVHrx2eyfPFodrTBgMFeTgxfESSkQ8,140
|
95
101
|
junifer/data/parcellations/_ants_parcellation_warper.py,sha256=LIfeIAv3bFQbIrl6Cr7RU2RdkA-c2G6qURIBUe5MJCQ,5826
|
96
102
|
junifer/data/parcellations/_fsl_parcellation_warper.py,sha256=lmZDPv2fMjOnbJ0z2d3K9S7QH2bgYd5bXbzxNDUR5NY,2699
|
97
|
-
junifer/data/parcellations/_parcellations.py,sha256=
|
103
|
+
junifer/data/parcellations/_parcellations.py,sha256=eG6i_UgvhR0XwIdVhRqhiwunn7fO_-3AFlKAk8ayXHc,48430
|
98
104
|
junifer/data/parcellations/tests/test_parcellations.py,sha256=s3TtsXTw7wEb-FvW0pFX2QcIXjp9IwlgjtM8X95rz_8,37544
|
99
105
|
junifer/data/tests/test_data_utils.py,sha256=6-UQ7HDZ7_zA7iQalzk29KJBdftQMVyqKsQ0tx1URkE,1062
|
100
106
|
junifer/data/tests/test_dispatch.py,sha256=bm4R0E8gs_XpJ6B5lfWFXjle7PmDjaX7Wu0L6mEU33w,2315
|
@@ -326,10 +332,10 @@ junifer/utils/tests/test_config.py,sha256=7ltIXuwb_W4Mv_1dxQWyiyM10XgUAfsWKV6D_i
|
|
326
332
|
junifer/utils/tests/test_fs.py,sha256=WQS7cKlKEZ742CIuiOYYpueeAhY9PqlastfDVpVVtvE,923
|
327
333
|
junifer/utils/tests/test_helpers.py,sha256=k5qqfxK8dFyuewTJyR1Qn6-nFaYNuVr0ysc18bfPjyU,929
|
328
334
|
junifer/utils/tests/test_logging.py,sha256=W4tFKmaf8_CxnWZ-o_-XxM7DQbhGG18RsLZJk8bZelI,8163
|
329
|
-
junifer-0.0.7.
|
330
|
-
junifer-0.0.7.
|
331
|
-
junifer-0.0.7.
|
332
|
-
junifer-0.0.7.
|
333
|
-
junifer-0.0.7.
|
334
|
-
junifer-0.0.7.
|
335
|
-
junifer-0.0.7.
|
335
|
+
junifer-0.0.7.dev153.dist-info/licenses/AUTHORS.rst,sha256=rmULKpchpSol4ExWFdm-qu4fkpSZPYqIESVJBZtGb6E,163
|
336
|
+
junifer-0.0.7.dev153.dist-info/licenses/LICENSE.md,sha256=MqCnOBu8uXsEOzRZWh9EBVfVz-kE9NkXcLCrtGXo2yU,34354
|
337
|
+
junifer-0.0.7.dev153.dist-info/METADATA,sha256=re2C1YH9-idiVNi-SmZ4C3dzzfNqaqLiqU0uJPATGv4,8396
|
338
|
+
junifer-0.0.7.dev153.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
339
|
+
junifer-0.0.7.dev153.dist-info/entry_points.txt,sha256=6O8ru0BP-SP7YMUZiizFNoaZ2HvJpadO2G7nKk4PwjI,48
|
340
|
+
junifer-0.0.7.dev153.dist-info/top_level.txt,sha256=4bAq1R2QFQ4b3hohjys2JBvxrl0GKk5LNFzYvz9VGcA,8
|
341
|
+
junifer-0.0.7.dev153.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|