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.
- junifer/__init__.py +17 -0
- junifer/_version.py +2 -2
- junifer/api/__init__.py +4 -1
- junifer/api/cli.py +91 -1
- junifer/api/decorators.py +9 -0
- junifer/api/functions.py +56 -10
- junifer/api/parser.py +3 -0
- junifer/api/queue_context/__init__.py +4 -1
- junifer/api/queue_context/gnu_parallel_local_adapter.py +16 -6
- junifer/api/queue_context/htcondor_adapter.py +16 -5
- junifer/api/queue_context/tests/test_gnu_parallel_local_adapter.py +41 -12
- junifer/api/queue_context/tests/test_htcondor_adapter.py +48 -15
- junifer/api/res/afni/run_afni_docker.sh +1 -1
- junifer/api/res/ants/run_ants_docker.sh +1 -1
- junifer/api/res/freesurfer/mri_binarize +3 -0
- junifer/api/res/freesurfer/mri_mc +3 -0
- junifer/api/res/freesurfer/mri_pretess +3 -0
- junifer/api/res/freesurfer/mris_convert +3 -0
- junifer/api/res/freesurfer/run_freesurfer_docker.sh +61 -0
- junifer/api/res/fsl/run_fsl_docker.sh +1 -1
- junifer/api/res/{run_conda.sh → run_conda.bash} +1 -1
- junifer/api/res/run_conda.zsh +23 -0
- junifer/api/res/run_venv.bash +22 -0
- junifer/api/res/{run_venv.sh → run_venv.zsh} +1 -1
- junifer/api/tests/test_api_utils.py +4 -2
- junifer/api/tests/test_cli.py +83 -0
- junifer/api/tests/test_functions.py +27 -2
- junifer/configs/__init__.py +1 -1
- junifer/configs/juseless/__init__.py +4 -1
- junifer/configs/juseless/datagrabbers/__init__.py +10 -1
- junifer/configs/juseless/datagrabbers/aomic_id1000_vbm.py +4 -3
- junifer/configs/juseless/datagrabbers/camcan_vbm.py +3 -0
- junifer/configs/juseless/datagrabbers/ixi_vbm.py +4 -3
- junifer/configs/juseless/datagrabbers/tests/test_ucla.py +1 -3
- junifer/configs/juseless/datagrabbers/ucla.py +12 -9
- junifer/configs/juseless/datagrabbers/ukb_vbm.py +3 -0
- junifer/data/__init__.py +21 -1
- junifer/data/coordinates.py +10 -19
- junifer/data/masks/ukb/UKB_15K_GM_template.nii.gz +0 -0
- junifer/data/masks.py +58 -87
- junifer/data/parcellations.py +14 -3
- junifer/data/template_spaces.py +4 -1
- junifer/data/tests/test_masks.py +26 -37
- junifer/data/utils.py +3 -0
- junifer/datagrabber/__init__.py +18 -1
- junifer/datagrabber/aomic/__init__.py +3 -0
- junifer/datagrabber/aomic/id1000.py +70 -37
- junifer/datagrabber/aomic/piop1.py +69 -36
- junifer/datagrabber/aomic/piop2.py +71 -38
- junifer/datagrabber/aomic/tests/test_id1000.py +44 -100
- junifer/datagrabber/aomic/tests/test_piop1.py +65 -108
- junifer/datagrabber/aomic/tests/test_piop2.py +45 -102
- junifer/datagrabber/base.py +13 -6
- junifer/datagrabber/datalad_base.py +13 -1
- junifer/datagrabber/dmcc13_benchmark.py +36 -53
- junifer/datagrabber/hcp1200/__init__.py +3 -0
- junifer/datagrabber/hcp1200/datalad_hcp1200.py +3 -0
- junifer/datagrabber/hcp1200/hcp1200.py +4 -1
- junifer/datagrabber/multiple.py +45 -6
- junifer/datagrabber/pattern.py +170 -62
- junifer/datagrabber/pattern_datalad.py +25 -12
- junifer/datagrabber/pattern_validation_mixin.py +388 -0
- junifer/datagrabber/tests/test_datalad_base.py +4 -4
- junifer/datagrabber/tests/test_dmcc13_benchmark.py +46 -19
- junifer/datagrabber/tests/test_multiple.py +161 -84
- junifer/datagrabber/tests/test_pattern.py +45 -0
- junifer/datagrabber/tests/test_pattern_datalad.py +4 -4
- junifer/datagrabber/tests/test_pattern_validation_mixin.py +249 -0
- junifer/datareader/__init__.py +4 -1
- junifer/datareader/default.py +95 -43
- junifer/external/BrainPrint/brainprint/__init__.py +4 -0
- junifer/external/BrainPrint/brainprint/_version.py +3 -0
- junifer/external/BrainPrint/brainprint/asymmetry.py +91 -0
- junifer/external/BrainPrint/brainprint/brainprint.py +441 -0
- junifer/external/BrainPrint/brainprint/surfaces.py +258 -0
- junifer/external/BrainPrint/brainprint/utils/__init__.py +1 -0
- junifer/external/BrainPrint/brainprint/utils/_config.py +112 -0
- junifer/external/BrainPrint/brainprint/utils/utils.py +188 -0
- junifer/external/__init__.py +1 -1
- junifer/external/nilearn/__init__.py +5 -1
- junifer/external/nilearn/junifer_connectivity_measure.py +483 -0
- junifer/external/nilearn/junifer_nifti_spheres_masker.py +23 -9
- junifer/external/nilearn/tests/test_junifer_connectivity_measure.py +1089 -0
- junifer/external/nilearn/tests/test_junifer_nifti_spheres_masker.py +76 -1
- junifer/markers/__init__.py +23 -1
- junifer/markers/base.py +68 -28
- junifer/markers/brainprint.py +459 -0
- junifer/markers/collection.py +10 -2
- junifer/markers/complexity/__init__.py +10 -0
- junifer/markers/complexity/complexity_base.py +26 -43
- junifer/markers/complexity/hurst_exponent.py +3 -0
- junifer/markers/complexity/multiscale_entropy_auc.py +3 -0
- junifer/markers/complexity/perm_entropy.py +3 -0
- junifer/markers/complexity/range_entropy.py +3 -0
- junifer/markers/complexity/range_entropy_auc.py +3 -0
- junifer/markers/complexity/sample_entropy.py +3 -0
- junifer/markers/complexity/tests/test_hurst_exponent.py +11 -3
- junifer/markers/complexity/tests/test_multiscale_entropy_auc.py +11 -3
- junifer/markers/complexity/tests/test_perm_entropy.py +11 -3
- junifer/markers/complexity/tests/test_range_entropy.py +11 -3
- junifer/markers/complexity/tests/test_range_entropy_auc.py +11 -3
- junifer/markers/complexity/tests/test_sample_entropy.py +11 -3
- junifer/markers/complexity/tests/test_weighted_perm_entropy.py +11 -3
- junifer/markers/complexity/weighted_perm_entropy.py +3 -0
- junifer/markers/ets_rss.py +27 -42
- junifer/markers/falff/__init__.py +3 -0
- junifer/markers/falff/_afni_falff.py +5 -2
- junifer/markers/falff/_junifer_falff.py +3 -0
- junifer/markers/falff/falff_base.py +20 -46
- junifer/markers/falff/falff_parcels.py +56 -27
- junifer/markers/falff/falff_spheres.py +60 -29
- junifer/markers/falff/tests/test_falff_parcels.py +39 -23
- junifer/markers/falff/tests/test_falff_spheres.py +39 -23
- junifer/markers/functional_connectivity/__init__.py +9 -0
- junifer/markers/functional_connectivity/crossparcellation_functional_connectivity.py +63 -60
- junifer/markers/functional_connectivity/edge_functional_connectivity_parcels.py +45 -32
- junifer/markers/functional_connectivity/edge_functional_connectivity_spheres.py +49 -36
- junifer/markers/functional_connectivity/functional_connectivity_base.py +71 -70
- junifer/markers/functional_connectivity/functional_connectivity_parcels.py +34 -25
- junifer/markers/functional_connectivity/functional_connectivity_spheres.py +40 -30
- junifer/markers/functional_connectivity/tests/test_crossparcellation_functional_connectivity.py +11 -7
- junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_parcels.py +27 -7
- junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_spheres.py +28 -12
- junifer/markers/functional_connectivity/tests/test_functional_connectivity_parcels.py +35 -11
- junifer/markers/functional_connectivity/tests/test_functional_connectivity_spheres.py +36 -62
- junifer/markers/parcel_aggregation.py +47 -61
- junifer/markers/reho/__init__.py +3 -0
- junifer/markers/reho/_afni_reho.py +5 -2
- junifer/markers/reho/_junifer_reho.py +4 -1
- junifer/markers/reho/reho_base.py +8 -27
- junifer/markers/reho/reho_parcels.py +28 -17
- junifer/markers/reho/reho_spheres.py +27 -18
- junifer/markers/reho/tests/test_reho_parcels.py +8 -3
- junifer/markers/reho/tests/test_reho_spheres.py +8 -3
- junifer/markers/sphere_aggregation.py +43 -59
- junifer/markers/temporal_snr/__init__.py +3 -0
- junifer/markers/temporal_snr/temporal_snr_base.py +23 -32
- junifer/markers/temporal_snr/temporal_snr_parcels.py +9 -6
- junifer/markers/temporal_snr/temporal_snr_spheres.py +9 -6
- junifer/markers/temporal_snr/tests/test_temporal_snr_parcels.py +6 -3
- junifer/markers/temporal_snr/tests/test_temporal_snr_spheres.py +6 -3
- junifer/markers/tests/test_brainprint.py +58 -0
- junifer/markers/tests/test_collection.py +9 -8
- junifer/markers/tests/test_ets_rss.py +15 -9
- junifer/markers/tests/test_markers_base.py +17 -18
- junifer/markers/tests/test_parcel_aggregation.py +93 -32
- junifer/markers/tests/test_sphere_aggregation.py +72 -19
- junifer/onthefly/__init__.py +4 -1
- junifer/onthefly/read_transform.py +3 -0
- junifer/pipeline/__init__.py +9 -1
- junifer/pipeline/pipeline_step_mixin.py +21 -4
- junifer/pipeline/registry.py +3 -0
- junifer/pipeline/singleton.py +3 -0
- junifer/pipeline/tests/test_registry.py +1 -1
- junifer/pipeline/update_meta_mixin.py +3 -0
- junifer/pipeline/utils.py +67 -1
- junifer/pipeline/workdir_manager.py +3 -0
- junifer/preprocess/__init__.py +10 -2
- junifer/preprocess/base.py +6 -3
- junifer/preprocess/confounds/__init__.py +3 -0
- junifer/preprocess/confounds/fmriprep_confound_remover.py +47 -60
- junifer/preprocess/confounds/tests/test_fmriprep_confound_remover.py +72 -113
- junifer/preprocess/smoothing/__init__.py +9 -0
- junifer/preprocess/smoothing/_afni_smoothing.py +119 -0
- junifer/preprocess/smoothing/_fsl_smoothing.py +116 -0
- junifer/preprocess/smoothing/_nilearn_smoothing.py +69 -0
- junifer/preprocess/smoothing/smoothing.py +174 -0
- junifer/preprocess/smoothing/tests/test_smoothing.py +94 -0
- junifer/preprocess/warping/__init__.py +3 -0
- junifer/preprocess/warping/_ants_warper.py +3 -0
- junifer/preprocess/warping/_fsl_warper.py +3 -0
- junifer/stats.py +4 -1
- junifer/storage/__init__.py +9 -1
- junifer/storage/base.py +40 -1
- junifer/storage/hdf5.py +71 -9
- junifer/storage/pandas_base.py +3 -0
- junifer/storage/sqlite.py +3 -0
- junifer/storage/tests/test_hdf5.py +82 -10
- junifer/storage/utils.py +9 -0
- junifer/testing/__init__.py +4 -1
- junifer/testing/datagrabbers.py +13 -6
- junifer/testing/tests/test_partlycloudytesting_datagrabber.py +7 -7
- junifer/testing/utils.py +3 -0
- junifer/utils/__init__.py +13 -2
- junifer/utils/fs.py +3 -0
- junifer/utils/helpers.py +32 -1
- junifer/utils/logging.py +33 -4
- junifer/utils/tests/test_logging.py +8 -0
- {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/METADATA +17 -16
- junifer-0.0.5.dist-info/RECORD +275 -0
- {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/WHEEL +1 -1
- junifer/datagrabber/tests/test_datagrabber_utils.py +0 -218
- junifer/datagrabber/utils.py +0 -230
- junifer/preprocess/ants/__init__.py +0 -4
- junifer/preprocess/ants/ants_apply_transforms_warper.py +0 -185
- junifer/preprocess/ants/tests/test_ants_apply_transforms_warper.py +0 -56
- junifer/preprocess/bold_warper.py +0 -265
- junifer/preprocess/fsl/__init__.py +0 -4
- junifer/preprocess/fsl/apply_warper.py +0 -179
- junifer/preprocess/fsl/tests/test_apply_warper.py +0 -45
- junifer/preprocess/tests/test_bold_warper.py +0 -159
- junifer-0.0.4.dev829.dist-info/RECORD +0 -257
- {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/AUTHORS.rst +0 -0
- {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/LICENSE.md +0 -0
- {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/entry_points.txt +0 -0
- {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/top_level.txt +0 -0
junifer/data/__init__.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
"""
|
1
|
+
"""Parcellations, coordinates and masks."""
|
2
2
|
|
3
3
|
# Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
|
4
4
|
# Synchon Mandal <s.mandal@fz-juelich.de>
|
@@ -28,3 +28,23 @@ from .masks import (
|
|
28
28
|
from .template_spaces import get_template, get_xfm
|
29
29
|
|
30
30
|
from . import utils
|
31
|
+
|
32
|
+
|
33
|
+
__all__ = [
|
34
|
+
"list_coordinates",
|
35
|
+
"load_coordinates",
|
36
|
+
"register_coordinates",
|
37
|
+
"get_coordinates",
|
38
|
+
"list_parcellations",
|
39
|
+
"load_parcellation",
|
40
|
+
"register_parcellation",
|
41
|
+
"merge_parcellations",
|
42
|
+
"get_parcellation",
|
43
|
+
"list_masks",
|
44
|
+
"load_mask",
|
45
|
+
"register_mask",
|
46
|
+
"get_mask",
|
47
|
+
"get_template",
|
48
|
+
"get_xfm",
|
49
|
+
"utils",
|
50
|
+
]
|
junifer/data/coordinates.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
"""
|
1
|
+
"""Functions for coordinates manipulation."""
|
2
2
|
|
3
3
|
# Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
|
4
4
|
# Synchon Mandal <s.mandal@fz-juelich.de>
|
@@ -13,7 +13,15 @@ import pandas as pd
|
|
13
13
|
from numpy.typing import ArrayLike
|
14
14
|
|
15
15
|
from ..pipeline import WorkDirManager
|
16
|
-
from ..utils import logger, raise_error, run_ext_cmd
|
16
|
+
from ..utils import logger, raise_error, run_ext_cmd
|
17
|
+
|
18
|
+
|
19
|
+
__all__ = [
|
20
|
+
"register_coordinates",
|
21
|
+
"list_coordinates",
|
22
|
+
"get_coordinates",
|
23
|
+
"load_coordinates",
|
24
|
+
]
|
17
25
|
|
18
26
|
|
19
27
|
# Path to the VOIs
|
@@ -377,11 +385,6 @@ def load_coordinates(name: str) -> Tuple[ArrayLike, List[str], str]:
|
|
377
385
|
ValueError
|
378
386
|
If ``name`` is invalid.
|
379
387
|
|
380
|
-
Warns
|
381
|
-
-----
|
382
|
-
DeprecationWarning
|
383
|
-
If ``Power`` is provided as the ``name``.
|
384
|
-
|
385
388
|
"""
|
386
389
|
# Check for valid coordinates name
|
387
390
|
if name not in _available_coordinates:
|
@@ -389,18 +392,6 @@ def load_coordinates(name: str) -> Tuple[ArrayLike, List[str], str]:
|
|
389
392
|
f"Coordinates {name} not found. "
|
390
393
|
f"Valid options are: {list_coordinates()}"
|
391
394
|
)
|
392
|
-
|
393
|
-
# Put up deprecation notice
|
394
|
-
if name == "Power":
|
395
|
-
warn_with_log(
|
396
|
-
msg=(
|
397
|
-
"`Power` has been replaced with `Power2011` and will be "
|
398
|
-
"removed in the next release. For now, it's available for "
|
399
|
-
"backward compatibility."
|
400
|
-
),
|
401
|
-
category=DeprecationWarning,
|
402
|
-
)
|
403
|
-
|
404
395
|
# Load coordinates
|
405
396
|
t_coord = _available_coordinates[name]
|
406
397
|
if isinstance(t_coord.get("path"), Path):
|
Binary file
|
junifer/data/masks.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
"""
|
1
|
+
"""Functions for mask manipulation."""
|
2
2
|
|
3
3
|
# Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
|
4
4
|
# Synchon Mandal <s.mandal@fz-juelich.de>
|
@@ -19,7 +19,6 @@ from typing import (
|
|
19
19
|
|
20
20
|
import nibabel as nib
|
21
21
|
import numpy as np
|
22
|
-
from nilearn.datasets import fetch_icbm152_brain_gm_mask
|
23
22
|
from nilearn.image import get_data, new_img_like, resample_to_img
|
24
23
|
from nilearn.masking import (
|
25
24
|
compute_background_mask,
|
@@ -28,7 +27,7 @@ from nilearn.masking import (
|
|
28
27
|
)
|
29
28
|
|
30
29
|
from ..pipeline import WorkDirManager
|
31
|
-
from ..utils import logger, raise_error, run_ext_cmd
|
30
|
+
from ..utils import logger, raise_error, run_ext_cmd
|
32
31
|
from .template_spaces import get_template, get_xfm
|
33
32
|
from .utils import closest_resolution
|
34
33
|
|
@@ -36,6 +35,16 @@ from .utils import closest_resolution
|
|
36
35
|
if TYPE_CHECKING:
|
37
36
|
from nibabel import Nifti1Image
|
38
37
|
|
38
|
+
|
39
|
+
__all__ = [
|
40
|
+
"compute_brain_mask",
|
41
|
+
"register_mask",
|
42
|
+
"list_masks",
|
43
|
+
"get_mask",
|
44
|
+
"load_mask",
|
45
|
+
]
|
46
|
+
|
47
|
+
|
39
48
|
# Path to the masks
|
40
49
|
_masks_path = Path(__file__).parent / "masks"
|
41
50
|
|
@@ -121,46 +130,6 @@ def compute_brain_mask(
|
|
121
130
|
return new_img_like(target_img, mask) # type: ignore
|
122
131
|
|
123
132
|
|
124
|
-
def _fetch_icbm152_brain_gm_mask(
|
125
|
-
target_img: "Nifti1Image",
|
126
|
-
**kwargs,
|
127
|
-
) -> "Nifti1Image":
|
128
|
-
"""Fetch ICBM152 brain mask and resample.
|
129
|
-
|
130
|
-
Parameters
|
131
|
-
----------
|
132
|
-
target_img : nibabel.Nifti1Image
|
133
|
-
The image to which the mask will be resampled.
|
134
|
-
**kwargs : dict
|
135
|
-
Keyword arguments to be passed to
|
136
|
-
:func:`nilearn.datasets.fetch_icbm152_brain_gm_mask`.
|
137
|
-
|
138
|
-
Returns
|
139
|
-
-------
|
140
|
-
nibabel.Nifti1Image
|
141
|
-
The resampled mask.
|
142
|
-
|
143
|
-
Warns
|
144
|
-
-----
|
145
|
-
DeprecationWarning
|
146
|
-
If this function is used.
|
147
|
-
|
148
|
-
"""
|
149
|
-
warn_with_log(
|
150
|
-
msg=(
|
151
|
-
"It is recommended to use ``compute_brain_mask`` with "
|
152
|
-
"``mask_type='gm'``. This function will be removed in the next "
|
153
|
-
"release. For now, it's available for backward compatibility."
|
154
|
-
),
|
155
|
-
category=DeprecationWarning,
|
156
|
-
)
|
157
|
-
mask = fetch_icbm152_brain_gm_mask(**kwargs)
|
158
|
-
mask = resample_to_img(
|
159
|
-
mask, target_img, interpolation="nearest", copy=True
|
160
|
-
)
|
161
|
-
return mask
|
162
|
-
|
163
|
-
|
164
133
|
# A dictionary containing all supported masks and their respective file or
|
165
134
|
# data.
|
166
135
|
|
@@ -194,10 +163,9 @@ _available_masks: Dict[str, Dict[str, Any]] = {
|
|
194
163
|
"func": compute_epi_mask,
|
195
164
|
"space": "inherit",
|
196
165
|
},
|
197
|
-
"
|
198
|
-
"family": "
|
199
|
-
"
|
200
|
-
"space": "MNI152NLin2009aAsym",
|
166
|
+
"UKB_15K_GM": {
|
167
|
+
"family": "UKB",
|
168
|
+
"space": "MNI152NLin6Asym",
|
201
169
|
},
|
202
170
|
}
|
203
171
|
|
@@ -292,14 +260,12 @@ def get_mask( # noqa: C901
|
|
292
260
|
Raises
|
293
261
|
------
|
294
262
|
RuntimeError
|
295
|
-
If warp / transformation file extension is not ".mat" or ".h5"
|
296
|
-
if fetch_icbm152_brain_gm_mask is used and requires warping to
|
297
|
-
other template space.
|
263
|
+
If warp / transformation file extension is not ".mat" or ".h5".
|
298
264
|
ValueError
|
299
265
|
If extra key is provided in addition to mask name in ``masks`` or
|
300
266
|
if no mask is provided or
|
301
|
-
if ``masks = "inherit"``
|
302
|
-
|
267
|
+
if ``masks = "inherit"`` and ``mask`` key for the ``target_data`` is
|
268
|
+
not found or
|
303
269
|
if callable parameters are passed to non-callable mask or
|
304
270
|
if parameters are passed to :func:`nilearn.masking.intersect_masks`
|
305
271
|
when there is only one mask or
|
@@ -358,8 +324,8 @@ def get_mask( # noqa: C901
|
|
358
324
|
if len(true_masks) == 0:
|
359
325
|
raise_error("No mask was passed. At least one mask is required.")
|
360
326
|
|
361
|
-
# Get the data type for the input data type
|
362
|
-
inherited_mask_item = target_data.get("
|
327
|
+
# Get the nested mask data type for the input data type
|
328
|
+
inherited_mask_item = target_data.get("mask", None)
|
363
329
|
|
364
330
|
# Create component-scoped tempdir
|
365
331
|
tempdir = WorkDirManager().get_tempdir(prefix="masks")
|
@@ -378,45 +344,18 @@ def get_mask( # noqa: C901
|
|
378
344
|
mask_name = t_mask
|
379
345
|
mask_params = None
|
380
346
|
|
381
|
-
# If mask is being inherited from
|
347
|
+
# If mask is being inherited from the datagrabber or a preprocessor,
|
348
|
+
# check that it's accessible
|
382
349
|
if mask_name == "inherit":
|
383
|
-
# Requires extra input to be passed
|
384
|
-
if extra_input is None:
|
385
|
-
raise_error(
|
386
|
-
"Cannot inherit mask from another data item "
|
387
|
-
"because no extra data was passed."
|
388
|
-
)
|
389
|
-
# Missing inherited mask item
|
390
350
|
if inherited_mask_item is None:
|
391
351
|
raise_error(
|
392
|
-
"Cannot inherit mask from
|
393
|
-
"
|
394
|
-
"
|
352
|
+
"Cannot inherit mask from the target data. Either the "
|
353
|
+
"DataGrabber or a Preprocessor does not provide `mask` "
|
354
|
+
"for the target data type."
|
395
355
|
)
|
396
|
-
|
397
|
-
if inherited_mask_item not in extra_input:
|
398
|
-
raise_error(
|
399
|
-
"Cannot inherit mask from another data item "
|
400
|
-
f"because the item ({inherited_mask_item}) does not exist."
|
401
|
-
)
|
402
|
-
mask_img = extra_input[inherited_mask_item]["data"]
|
356
|
+
mask_img = inherited_mask_item["data"]
|
403
357
|
# Starting with new mask
|
404
358
|
else:
|
405
|
-
# Restrict fetch_icbm152_brain_gm_mask if target std space doesn't
|
406
|
-
# match
|
407
|
-
if (
|
408
|
-
mask_name == "fetch_icbm152_brain_gm_mask"
|
409
|
-
and target_std_space != "MNI152NLin2009aAsym"
|
410
|
-
):
|
411
|
-
raise_error(
|
412
|
-
(
|
413
|
-
"``fetch_icbm152_brain_gm_mask`` is deprecated and "
|
414
|
-
"space transformation to any other template space is "
|
415
|
-
"prohibited as it will lead to unforeseen errors. "
|
416
|
-
"``compute_brain_mask`` is a better alternative."
|
417
|
-
),
|
418
|
-
klass=RuntimeError,
|
419
|
-
)
|
420
359
|
# Load mask
|
421
360
|
mask_object, _, mask_space = load_mask(
|
422
361
|
mask_name, path_only=False, resolution=resolution
|
@@ -632,6 +571,8 @@ def load_mask(
|
|
632
571
|
elif t_family == "Callable":
|
633
572
|
mask_img = mask_definition["func"]
|
634
573
|
mask_fname = None
|
574
|
+
elif t_family == "UKB":
|
575
|
+
mask_fname = _load_ukb_mask(name)
|
635
576
|
else:
|
636
577
|
raise_error(f"I don't know about the {t_family} mask family.")
|
637
578
|
|
@@ -697,3 +638,33 @@ def _load_vickery_patil_mask(
|
|
697
638
|
mask_fname = _masks_path / "vickery-patil" / mask_fname
|
698
639
|
|
699
640
|
return mask_fname
|
641
|
+
|
642
|
+
|
643
|
+
def _load_ukb_mask(name: str) -> Path:
|
644
|
+
"""Load UKB mask.
|
645
|
+
|
646
|
+
Parameters
|
647
|
+
----------
|
648
|
+
name : {"UKB_15K_GM"}
|
649
|
+
The name of the mask.
|
650
|
+
|
651
|
+
Returns
|
652
|
+
-------
|
653
|
+
pathlib.Path
|
654
|
+
File path to the mask image.
|
655
|
+
|
656
|
+
Raises
|
657
|
+
------
|
658
|
+
ValueError
|
659
|
+
If ``name`` is invalid.
|
660
|
+
|
661
|
+
"""
|
662
|
+
if name == "UKB_15K_GM":
|
663
|
+
mask_fname = "UKB_15K_GM_template.nii.gz"
|
664
|
+
else:
|
665
|
+
raise_error(f"Cannot find a UKB mask called {name}")
|
666
|
+
|
667
|
+
# Set path for masks
|
668
|
+
mask_fname = _masks_path / "ukb" / mask_fname
|
669
|
+
|
670
|
+
return mask_fname
|
junifer/data/parcellations.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
"""
|
1
|
+
"""Functions for parcellation manipulation."""
|
2
2
|
|
3
3
|
# Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
|
4
4
|
# Vera Komeyer <v.komeyer@fz-juelich.de>
|
@@ -30,6 +30,15 @@ if TYPE_CHECKING:
|
|
30
30
|
from nibabel import Nifti1Image
|
31
31
|
|
32
32
|
|
33
|
+
__all__ = [
|
34
|
+
"register_parcellation",
|
35
|
+
"list_parcellations",
|
36
|
+
"get_parcellation",
|
37
|
+
"load_parcellation",
|
38
|
+
"merge_parcellations",
|
39
|
+
]
|
40
|
+
|
41
|
+
|
33
42
|
# A dictionary containing all supported parcellations and their respective
|
34
43
|
# valid parameters.
|
35
44
|
|
@@ -326,7 +335,9 @@ def get_parcellation(
|
|
326
335
|
# Call antsApplyTransforms
|
327
336
|
run_ext_cmd(name="antsApplyTransforms", cmd=apply_transforms_cmd)
|
328
337
|
|
329
|
-
|
338
|
+
raw_img = nib.load(warped_parcellation_path)
|
339
|
+
# Remove extra dimension added by ANTs
|
340
|
+
img = image.math_img("np.squeeze(img)", img=raw_img)
|
330
341
|
|
331
342
|
# Resample parcellation to target image
|
332
343
|
img_to_merge = image.resample_to_img(
|
@@ -887,7 +898,7 @@ def _retrieve_tian(
|
|
887
898
|
)
|
888
899
|
with open(parcellation_lname, "w") as filehandle:
|
889
900
|
for listitem in labels:
|
890
|
-
filehandle.write("
|
901
|
+
filehandle.write(f"{listitem}\n")
|
891
902
|
logger.info(
|
892
903
|
"Currently there are no labels provided for the 7T Tian "
|
893
904
|
"parcellation. A simple numbering scheme for distinction was "
|
junifer/data/template_spaces.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
"""
|
1
|
+
"""Functions for template space manipulation."""
|
2
2
|
|
3
3
|
# Authors: Synchon Mandal <s.mandal@fz-juelich.de>
|
4
4
|
# License: AGPL
|
@@ -15,6 +15,9 @@ from ..utils import logger, raise_error
|
|
15
15
|
from .utils import closest_resolution
|
16
16
|
|
17
17
|
|
18
|
+
__all__ = ["get_xfm", "get_template"]
|
19
|
+
|
20
|
+
|
18
21
|
def get_xfm(
|
19
22
|
src: str, dst: str, xfms_dir: Union[str, Path, None] = None
|
20
23
|
) -> Path: # pragma: no cover
|
junifer/data/tests/test_masks.py
CHANGED
@@ -22,6 +22,7 @@ from numpy.testing import assert_array_almost_equal, assert_array_equal
|
|
22
22
|
|
23
23
|
from junifer.data.masks import (
|
24
24
|
_available_masks,
|
25
|
+
_load_ukb_mask,
|
25
26
|
_load_vickery_patil_mask,
|
26
27
|
compute_brain_mask,
|
27
28
|
get_mask,
|
@@ -212,6 +213,7 @@ def test_register_mask(
|
|
212
213
|
[
|
213
214
|
"GM_prob0.2",
|
214
215
|
"GM_prob0.2_cortex",
|
216
|
+
"UKB_15K_GM",
|
215
217
|
],
|
216
218
|
)
|
217
219
|
def test_list_masks_correct(mask_name: str) -> None:
|
@@ -291,6 +293,21 @@ def test_vickery_patil_error() -> None:
|
|
291
293
|
_load_vickery_patil_mask(name="wrong", resolution=2.0)
|
292
294
|
|
293
295
|
|
296
|
+
def test_ukb() -> None:
|
297
|
+
"""Test UKB mask."""
|
298
|
+
mask, mask_fname, space = load_mask("UKB_15K_GM", resolution=2.0)
|
299
|
+
assert_array_almost_equal(mask.header["pixdim"][1:4], 2.0) # type: ignore
|
300
|
+
assert space == "MNI152NLin6Asym"
|
301
|
+
assert mask_fname is not None
|
302
|
+
assert mask_fname.name == "UKB_15K_GM_template.nii.gz"
|
303
|
+
|
304
|
+
|
305
|
+
def test_ukb_error() -> None:
|
306
|
+
"""Test error for UKB mask."""
|
307
|
+
with pytest.raises(ValueError, match=r"find a UKB mask "):
|
308
|
+
_load_ukb_mask(name="wrong")
|
309
|
+
|
310
|
+
|
294
311
|
def test_get_mask() -> None:
|
295
312
|
"""Test the get_mask function."""
|
296
313
|
with OasisVBMTestingDataGrabber() as dg:
|
@@ -350,7 +367,7 @@ def test_get_mask_errors() -> None:
|
|
350
367
|
with pytest.raises(ValueError, match=r"callable params"):
|
351
368
|
get_mask(masks={"GM_prob0.2": {"param": 1}}, target_data=vbm_gm)
|
352
369
|
|
353
|
-
# Pass only
|
370
|
+
# Pass only parameters to the intersection function
|
354
371
|
with pytest.raises(
|
355
372
|
ValueError, match=r" At least one mask is required."
|
356
373
|
):
|
@@ -365,35 +382,10 @@ def test_get_mask_errors() -> None:
|
|
365
382
|
target_data=vbm_gm,
|
366
383
|
)
|
367
384
|
|
368
|
-
# Test "inherited" masks
|
369
|
-
|
370
|
-
# 1) No extra_data parameter
|
371
|
-
with pytest.raises(ValueError, match=r"no extra data was passed"):
|
385
|
+
# Test "inherited" masks error
|
386
|
+
with pytest.raises(ValueError, match=r"provide `mask`"):
|
372
387
|
get_mask(masks="inherit", target_data=vbm_gm)
|
373
388
|
|
374
|
-
extra_input = {"VBM_MASK": {}}
|
375
|
-
|
376
|
-
# 2) No mask_item key in target_data
|
377
|
-
with pytest.raises(ValueError, match=r"no mask item was specified"):
|
378
|
-
get_mask(
|
379
|
-
masks="inherit", target_data=vbm_gm, extra_input=extra_input
|
380
|
-
)
|
381
|
-
|
382
|
-
# 3) mask_item not in extra data
|
383
|
-
with pytest.raises(ValueError, match=r"does not exist"):
|
384
|
-
vbm_gm["mask_item"] = "wrong"
|
385
|
-
get_mask(
|
386
|
-
masks="inherit", target_data=vbm_gm, extra_input=extra_input
|
387
|
-
)
|
388
|
-
|
389
|
-
# Block fetch_icbm152_brain_gm_mask space transformation
|
390
|
-
with pytest.raises(RuntimeError, match="prohibited"):
|
391
|
-
get_mask(
|
392
|
-
masks="fetch_icbm152_brain_gm_mask",
|
393
|
-
target_data=vbm_gm,
|
394
|
-
extra_input=extra_input,
|
395
|
-
)
|
396
|
-
|
397
389
|
|
398
390
|
@pytest.mark.parametrize(
|
399
391
|
"mask_name,function,params,resample",
|
@@ -465,18 +457,15 @@ def test_get_mask_inherit() -> None:
|
|
465
457
|
)
|
466
458
|
|
467
459
|
# Now get the mask using the inherit functionality, passing the
|
468
|
-
# computed mask as
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
}
|
460
|
+
# computed mask as the data
|
461
|
+
bold_dict = element_data["BOLD"]
|
462
|
+
bold_dict["mask"] = {
|
463
|
+
"data": gm_mask,
|
464
|
+
"space": element_data["BOLD"]["space"],
|
474
465
|
}
|
475
|
-
element_data["BOLD"]["mask_item"] = "BOLD_MASK"
|
476
466
|
mask2 = get_mask(
|
477
467
|
masks="inherit",
|
478
|
-
target_data=
|
479
|
-
extra_input=extra_input,
|
468
|
+
target_data=bold_dict,
|
480
469
|
)
|
481
470
|
|
482
471
|
# Both masks should be equal
|
junifer/data/utils.py
CHANGED
junifer/datagrabber/__init__.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
"""
|
1
|
+
"""DataGrabbers for datasets' data description."""
|
2
2
|
|
3
3
|
# Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
|
4
4
|
# Leonard Sasse <l.sasse@fz-juelich.de>
|
@@ -16,3 +16,20 @@ from .aomic import DataladAOMICID1000, DataladAOMICPIOP1, DataladAOMICPIOP2
|
|
16
16
|
from .hcp1200 import HCP1200, DataladHCP1200
|
17
17
|
from .multiple import MultipleDataGrabber
|
18
18
|
from .dmcc13_benchmark import DMCC13Benchmark
|
19
|
+
|
20
|
+
from .pattern_validation_mixin import PatternValidationMixin
|
21
|
+
|
22
|
+
__all__ = [
|
23
|
+
"BaseDataGrabber",
|
24
|
+
"DataladDataGrabber",
|
25
|
+
"PatternDataGrabber",
|
26
|
+
"PatternDataladDataGrabber",
|
27
|
+
"DataladAOMICID1000",
|
28
|
+
"DataladAOMICPIOP1",
|
29
|
+
"DataladAOMICPIOP2",
|
30
|
+
"HCP1200",
|
31
|
+
"DataladHCP1200",
|
32
|
+
"MultipleDataGrabber",
|
33
|
+
"DMCC13Benchmark",
|
34
|
+
"PatternValidationMixin",
|
35
|
+
]
|
@@ -14,6 +14,9 @@ from ...api.decorators import register_datagrabber
|
|
14
14
|
from ..pattern_datalad import PatternDataladDataGrabber
|
15
15
|
|
16
16
|
|
17
|
+
__all__ = ["DataladAOMICID1000"]
|
18
|
+
|
19
|
+
|
17
20
|
@register_datagrabber
|
18
21
|
class DataladAOMICID1000(PatternDataladDataGrabber):
|
19
22
|
"""Concrete implementation for datalad-based data fetching of AOMIC ID1000.
|
@@ -24,8 +27,8 @@ class DataladAOMICID1000(PatternDataladDataGrabber):
|
|
24
27
|
The directory where the datalad dataset will be cloned. If None,
|
25
28
|
the datalad dataset will be cloned into a temporary directory
|
26
29
|
(default None).
|
27
|
-
types: {"BOLD", "
|
28
|
-
"
|
30
|
+
types: {"BOLD", "T1w", "VBM_CSF", "VBM_GM", "VBM_WM", "DWI", \
|
31
|
+
"FreeSurfer"} or list of the options, optional
|
29
32
|
AOMIC data types. If None, all available data types are selected.
|
30
33
|
(default None).
|
31
34
|
native_t1w : bool, optional
|
@@ -48,24 +51,23 @@ class DataladAOMICID1000(PatternDataladDataGrabber):
|
|
48
51
|
"space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz"
|
49
52
|
),
|
50
53
|
"space": "MNI152NLin2009cAsym",
|
51
|
-
"
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
"
|
67
|
-
|
68
|
-
"space": "MNI152NLin2009cAsym",
|
54
|
+
"mask": {
|
55
|
+
"pattern": (
|
56
|
+
"derivatives/fmriprep/{subject}/func/"
|
57
|
+
"{subject}_task-moviewatching_"
|
58
|
+
"space-MNI152NLin2009cAsym_"
|
59
|
+
"desc-brain_mask.nii.gz"
|
60
|
+
),
|
61
|
+
"space": "MNI152NLin2009cAsym",
|
62
|
+
},
|
63
|
+
"confounds": {
|
64
|
+
"pattern": (
|
65
|
+
"derivatives/fmriprep/{subject}/func/"
|
66
|
+
"{subject}_task-moviewatching_"
|
67
|
+
"desc-confounds_regressors.tsv"
|
68
|
+
),
|
69
|
+
"format": "fmriprep",
|
70
|
+
},
|
69
71
|
},
|
70
72
|
"T1w": {
|
71
73
|
"pattern": (
|
@@ -74,15 +76,14 @@ class DataladAOMICID1000(PatternDataladDataGrabber):
|
|
74
76
|
"desc-preproc_T1w.nii.gz"
|
75
77
|
),
|
76
78
|
"space": "MNI152NLin2009cAsym",
|
77
|
-
"
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
"
|
84
|
-
|
85
|
-
"space": "MNI152NLin2009cAsym",
|
79
|
+
"mask": {
|
80
|
+
"pattern": (
|
81
|
+
"derivatives/fmriprep/{subject}/anat/"
|
82
|
+
"{subject}_space-MNI152NLin2009cAsym_"
|
83
|
+
"desc-brain_mask.nii.gz"
|
84
|
+
),
|
85
|
+
"space": "MNI152NLin2009cAsym",
|
86
|
+
},
|
86
87
|
},
|
87
88
|
"VBM_CSF": {
|
88
89
|
"pattern": (
|
@@ -114,6 +115,39 @@ class DataladAOMICID1000(PatternDataladDataGrabber):
|
|
114
115
|
"{subject}_desc-preproc_dwi.nii.gz"
|
115
116
|
),
|
116
117
|
},
|
118
|
+
"FreeSurfer": {
|
119
|
+
"pattern": "derivatives/freesurfer/[!f]{subject}/mri/T1.mg[z]",
|
120
|
+
"aseg": {
|
121
|
+
"pattern": (
|
122
|
+
"derivatives/freesurfer/[!f]{subject}/mri/aseg.mg[z]"
|
123
|
+
)
|
124
|
+
},
|
125
|
+
"norm": {
|
126
|
+
"pattern": (
|
127
|
+
"derivatives/freesurfer/[!f]{subject}/mri/norm.mg[z]"
|
128
|
+
)
|
129
|
+
},
|
130
|
+
"lh_white": {
|
131
|
+
"pattern": (
|
132
|
+
"derivatives/freesurfer/[!f]{subject}/surf/lh.whit[e]"
|
133
|
+
)
|
134
|
+
},
|
135
|
+
"rh_white": {
|
136
|
+
"pattern": (
|
137
|
+
"derivatives/freesurfer/[!f]{subject}/surf/rh.whit[e]"
|
138
|
+
)
|
139
|
+
},
|
140
|
+
"lh_pial": {
|
141
|
+
"pattern": (
|
142
|
+
"derivatives/freesurfer/[!f]{subject}/surf/lh.pia[l]"
|
143
|
+
)
|
144
|
+
},
|
145
|
+
"rh_pial": {
|
146
|
+
"pattern": (
|
147
|
+
"derivatives/freesurfer/[!f]{subject}/surf/rh.pia[l]"
|
148
|
+
)
|
149
|
+
},
|
150
|
+
},
|
117
151
|
}
|
118
152
|
# Use native T1w assets
|
119
153
|
self.native_t1w = False
|
@@ -127,14 +161,13 @@ class DataladAOMICID1000(PatternDataladDataGrabber):
|
|
127
161
|
"{subject}_desc-preproc_T1w.nii.gz"
|
128
162
|
),
|
129
163
|
"space": "native",
|
130
|
-
"
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
"
|
136
|
-
|
137
|
-
"space": "native",
|
164
|
+
"mask": {
|
165
|
+
"pattern": (
|
166
|
+
"derivatives/fmriprep/{subject}/anat/"
|
167
|
+
"{subject}_desc-brain_mask.nii.gz"
|
168
|
+
),
|
169
|
+
"space": "native",
|
170
|
+
},
|
138
171
|
},
|
139
172
|
"Warp": {
|
140
173
|
"pattern": (
|