junifer 0.0.5.dev242__py3-none-any.whl → 0.0.6__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 +2 -31
- junifer/__init__.pyi +37 -0
- junifer/_version.py +9 -4
- junifer/api/__init__.py +3 -5
- junifer/api/__init__.pyi +4 -0
- junifer/api/decorators.py +14 -19
- junifer/api/functions.py +165 -109
- junifer/api/py.typed +0 -0
- junifer/api/queue_context/__init__.py +2 -4
- junifer/api/queue_context/__init__.pyi +5 -0
- junifer/api/queue_context/gnu_parallel_local_adapter.py +22 -6
- junifer/api/queue_context/htcondor_adapter.py +23 -6
- junifer/api/queue_context/py.typed +0 -0
- junifer/api/queue_context/tests/test_gnu_parallel_local_adapter.py +3 -3
- junifer/api/queue_context/tests/test_htcondor_adapter.py +3 -3
- junifer/api/tests/test_functions.py +168 -74
- junifer/cli/__init__.py +24 -0
- junifer/cli/__init__.pyi +3 -0
- junifer/{api → cli}/cli.py +141 -125
- junifer/cli/parser.py +235 -0
- junifer/cli/py.typed +0 -0
- junifer/{api → cli}/tests/test_cli.py +8 -8
- junifer/{api/tests/test_api_utils.py → cli/tests/test_cli_utils.py} +5 -4
- junifer/{api → cli}/tests/test_parser.py +2 -2
- junifer/{api → cli}/utils.py +6 -16
- junifer/configs/juseless/__init__.py +2 -2
- junifer/configs/juseless/__init__.pyi +3 -0
- junifer/configs/juseless/datagrabbers/__init__.py +2 -12
- junifer/configs/juseless/datagrabbers/__init__.pyi +13 -0
- junifer/configs/juseless/datagrabbers/ixi_vbm.py +2 -2
- junifer/configs/juseless/datagrabbers/py.typed +0 -0
- junifer/configs/juseless/datagrabbers/tests/test_ucla.py +2 -2
- junifer/configs/juseless/datagrabbers/ucla.py +4 -4
- junifer/configs/juseless/py.typed +0 -0
- junifer/conftest.py +25 -0
- junifer/data/__init__.py +2 -42
- junifer/data/__init__.pyi +29 -0
- junifer/data/_dispatch.py +248 -0
- junifer/data/coordinates/__init__.py +9 -0
- junifer/data/coordinates/__init__.pyi +5 -0
- junifer/data/coordinates/_ants_coordinates_warper.py +104 -0
- junifer/data/coordinates/_coordinates.py +385 -0
- junifer/data/coordinates/_fsl_coordinates_warper.py +81 -0
- junifer/data/{tests → coordinates/tests}/test_coordinates.py +26 -33
- junifer/data/masks/__init__.py +9 -0
- junifer/data/masks/__init__.pyi +6 -0
- junifer/data/masks/_ants_mask_warper.py +177 -0
- junifer/data/masks/_fsl_mask_warper.py +106 -0
- junifer/data/masks/_masks.py +802 -0
- junifer/data/{tests → masks/tests}/test_masks.py +67 -63
- junifer/data/parcellations/__init__.py +9 -0
- junifer/data/parcellations/__init__.pyi +6 -0
- junifer/data/parcellations/_ants_parcellation_warper.py +166 -0
- junifer/data/parcellations/_fsl_parcellation_warper.py +89 -0
- junifer/data/parcellations/_parcellations.py +1388 -0
- junifer/data/{tests → parcellations/tests}/test_parcellations.py +165 -295
- junifer/data/pipeline_data_registry_base.py +76 -0
- junifer/data/py.typed +0 -0
- junifer/data/template_spaces.py +44 -79
- junifer/data/tests/test_data_utils.py +1 -2
- junifer/data/tests/test_template_spaces.py +8 -4
- junifer/data/utils.py +109 -4
- junifer/datagrabber/__init__.py +2 -26
- junifer/datagrabber/__init__.pyi +27 -0
- junifer/datagrabber/aomic/__init__.py +2 -4
- junifer/datagrabber/aomic/__init__.pyi +5 -0
- junifer/datagrabber/aomic/id1000.py +81 -52
- junifer/datagrabber/aomic/piop1.py +83 -55
- junifer/datagrabber/aomic/piop2.py +85 -56
- junifer/datagrabber/aomic/py.typed +0 -0
- junifer/datagrabber/aomic/tests/test_id1000.py +19 -12
- junifer/datagrabber/aomic/tests/test_piop1.py +52 -18
- junifer/datagrabber/aomic/tests/test_piop2.py +50 -17
- junifer/datagrabber/base.py +22 -18
- junifer/datagrabber/datalad_base.py +71 -34
- junifer/datagrabber/dmcc13_benchmark.py +31 -18
- junifer/datagrabber/hcp1200/__init__.py +2 -3
- junifer/datagrabber/hcp1200/__init__.pyi +4 -0
- junifer/datagrabber/hcp1200/datalad_hcp1200.py +3 -3
- junifer/datagrabber/hcp1200/hcp1200.py +26 -15
- junifer/datagrabber/hcp1200/py.typed +0 -0
- junifer/datagrabber/hcp1200/tests/test_hcp1200.py +8 -2
- junifer/datagrabber/multiple.py +14 -9
- junifer/datagrabber/pattern.py +132 -96
- junifer/datagrabber/pattern_validation_mixin.py +206 -94
- junifer/datagrabber/py.typed +0 -0
- junifer/datagrabber/tests/test_datalad_base.py +27 -12
- junifer/datagrabber/tests/test_dmcc13_benchmark.py +28 -11
- junifer/datagrabber/tests/test_multiple.py +48 -2
- junifer/datagrabber/tests/test_pattern_datalad.py +1 -1
- junifer/datagrabber/tests/test_pattern_validation_mixin.py +6 -6
- junifer/datareader/__init__.py +2 -2
- junifer/datareader/__init__.pyi +3 -0
- junifer/datareader/default.py +6 -6
- junifer/datareader/py.typed +0 -0
- junifer/external/nilearn/__init__.py +2 -3
- junifer/external/nilearn/__init__.pyi +4 -0
- junifer/external/nilearn/junifer_connectivity_measure.py +25 -17
- junifer/external/nilearn/junifer_nifti_spheres_masker.py +4 -4
- junifer/external/nilearn/py.typed +0 -0
- junifer/external/nilearn/tests/test_junifer_connectivity_measure.py +17 -16
- junifer/external/nilearn/tests/test_junifer_nifti_spheres_masker.py +2 -3
- junifer/markers/__init__.py +2 -38
- junifer/markers/__init__.pyi +37 -0
- junifer/markers/base.py +11 -14
- junifer/markers/brainprint.py +12 -14
- junifer/markers/complexity/__init__.py +2 -18
- junifer/markers/complexity/__init__.pyi +17 -0
- junifer/markers/complexity/complexity_base.py +9 -11
- junifer/markers/complexity/hurst_exponent.py +7 -7
- junifer/markers/complexity/multiscale_entropy_auc.py +7 -7
- junifer/markers/complexity/perm_entropy.py +7 -7
- junifer/markers/complexity/py.typed +0 -0
- junifer/markers/complexity/range_entropy.py +7 -7
- junifer/markers/complexity/range_entropy_auc.py +7 -7
- junifer/markers/complexity/sample_entropy.py +7 -7
- junifer/markers/complexity/tests/test_complexity_base.py +1 -1
- junifer/markers/complexity/tests/test_hurst_exponent.py +5 -5
- junifer/markers/complexity/tests/test_multiscale_entropy_auc.py +5 -5
- junifer/markers/complexity/tests/test_perm_entropy.py +5 -5
- junifer/markers/complexity/tests/test_range_entropy.py +5 -5
- junifer/markers/complexity/tests/test_range_entropy_auc.py +5 -5
- junifer/markers/complexity/tests/test_sample_entropy.py +5 -5
- junifer/markers/complexity/tests/test_weighted_perm_entropy.py +5 -5
- junifer/markers/complexity/weighted_perm_entropy.py +7 -7
- junifer/markers/ets_rss.py +12 -11
- junifer/markers/falff/__init__.py +2 -3
- junifer/markers/falff/__init__.pyi +4 -0
- junifer/markers/falff/_afni_falff.py +38 -45
- junifer/markers/falff/_junifer_falff.py +16 -19
- junifer/markers/falff/falff_base.py +7 -11
- junifer/markers/falff/falff_parcels.py +9 -9
- junifer/markers/falff/falff_spheres.py +8 -8
- junifer/markers/falff/py.typed +0 -0
- junifer/markers/falff/tests/test_falff_spheres.py +3 -1
- junifer/markers/functional_connectivity/__init__.py +2 -12
- junifer/markers/functional_connectivity/__init__.pyi +13 -0
- junifer/markers/functional_connectivity/crossparcellation_functional_connectivity.py +9 -8
- junifer/markers/functional_connectivity/edge_functional_connectivity_parcels.py +8 -8
- junifer/markers/functional_connectivity/edge_functional_connectivity_spheres.py +7 -7
- junifer/markers/functional_connectivity/functional_connectivity_base.py +13 -12
- junifer/markers/functional_connectivity/functional_connectivity_parcels.py +8 -8
- junifer/markers/functional_connectivity/functional_connectivity_spheres.py +7 -7
- junifer/markers/functional_connectivity/py.typed +0 -0
- junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_parcels.py +1 -2
- junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_spheres.py +1 -2
- junifer/markers/functional_connectivity/tests/test_functional_connectivity_parcels.py +6 -6
- junifer/markers/functional_connectivity/tests/test_functional_connectivity_spheres.py +5 -5
- junifer/markers/parcel_aggregation.py +22 -17
- junifer/markers/py.typed +0 -0
- junifer/markers/reho/__init__.py +2 -3
- junifer/markers/reho/__init__.pyi +4 -0
- junifer/markers/reho/_afni_reho.py +29 -35
- junifer/markers/reho/_junifer_reho.py +13 -14
- junifer/markers/reho/py.typed +0 -0
- junifer/markers/reho/reho_base.py +7 -11
- junifer/markers/reho/reho_parcels.py +10 -10
- junifer/markers/reho/reho_spheres.py +9 -9
- junifer/markers/sphere_aggregation.py +22 -17
- junifer/markers/temporal_snr/__init__.py +2 -3
- junifer/markers/temporal_snr/__init__.pyi +4 -0
- junifer/markers/temporal_snr/py.typed +0 -0
- junifer/markers/temporal_snr/temporal_snr_base.py +11 -10
- junifer/markers/temporal_snr/temporal_snr_parcels.py +8 -8
- junifer/markers/temporal_snr/temporal_snr_spheres.py +7 -7
- junifer/markers/tests/test_ets_rss.py +3 -3
- junifer/markers/tests/test_parcel_aggregation.py +24 -24
- junifer/markers/tests/test_sphere_aggregation.py +6 -6
- junifer/markers/utils.py +3 -3
- junifer/onthefly/__init__.py +2 -1
- junifer/onthefly/_brainprint.py +138 -0
- junifer/onthefly/read_transform.py +5 -8
- junifer/pipeline/__init__.py +2 -10
- junifer/pipeline/__init__.pyi +13 -0
- junifer/{markers/collection.py → pipeline/marker_collection.py} +8 -14
- junifer/pipeline/pipeline_component_registry.py +294 -0
- junifer/pipeline/pipeline_step_mixin.py +15 -11
- junifer/pipeline/py.typed +0 -0
- junifer/{markers/tests/test_collection.py → pipeline/tests/test_marker_collection.py} +2 -3
- junifer/pipeline/tests/test_pipeline_component_registry.py +200 -0
- junifer/pipeline/tests/test_pipeline_step_mixin.py +36 -37
- junifer/pipeline/tests/test_update_meta_mixin.py +4 -4
- junifer/pipeline/tests/test_workdir_manager.py +43 -0
- junifer/pipeline/update_meta_mixin.py +21 -17
- junifer/pipeline/utils.py +6 -6
- junifer/pipeline/workdir_manager.py +19 -5
- junifer/preprocess/__init__.py +2 -10
- junifer/preprocess/__init__.pyi +11 -0
- junifer/preprocess/base.py +10 -10
- junifer/preprocess/confounds/__init__.py +2 -2
- junifer/preprocess/confounds/__init__.pyi +3 -0
- junifer/preprocess/confounds/fmriprep_confound_remover.py +243 -64
- junifer/preprocess/confounds/py.typed +0 -0
- junifer/preprocess/confounds/tests/test_fmriprep_confound_remover.py +121 -14
- junifer/preprocess/py.typed +0 -0
- junifer/preprocess/smoothing/__init__.py +2 -2
- junifer/preprocess/smoothing/__init__.pyi +3 -0
- junifer/preprocess/smoothing/_afni_smoothing.py +40 -40
- junifer/preprocess/smoothing/_fsl_smoothing.py +22 -32
- junifer/preprocess/smoothing/_nilearn_smoothing.py +35 -14
- junifer/preprocess/smoothing/py.typed +0 -0
- junifer/preprocess/smoothing/smoothing.py +11 -13
- junifer/preprocess/warping/__init__.py +2 -2
- junifer/preprocess/warping/__init__.pyi +3 -0
- junifer/preprocess/warping/_ants_warper.py +136 -32
- junifer/preprocess/warping/_fsl_warper.py +73 -22
- junifer/preprocess/warping/py.typed +0 -0
- junifer/preprocess/warping/space_warper.py +39 -11
- junifer/preprocess/warping/tests/test_space_warper.py +5 -9
- junifer/py.typed +0 -0
- junifer/stats.py +5 -5
- junifer/storage/__init__.py +2 -10
- junifer/storage/__init__.pyi +11 -0
- junifer/storage/base.py +47 -13
- junifer/storage/hdf5.py +95 -33
- junifer/storage/pandas_base.py +12 -11
- junifer/storage/py.typed +0 -0
- junifer/storage/sqlite.py +11 -11
- junifer/storage/tests/test_hdf5.py +86 -4
- junifer/storage/tests/test_sqlite.py +2 -2
- junifer/storage/tests/test_storage_base.py +5 -2
- junifer/storage/tests/test_utils.py +33 -7
- junifer/storage/utils.py +95 -9
- junifer/testing/__init__.py +2 -3
- junifer/testing/__init__.pyi +4 -0
- junifer/testing/datagrabbers.py +10 -11
- junifer/testing/py.typed +0 -0
- junifer/testing/registry.py +4 -7
- junifer/testing/tests/test_testing_registry.py +9 -17
- junifer/tests/test_stats.py +2 -2
- junifer/typing/__init__.py +9 -0
- junifer/typing/__init__.pyi +31 -0
- junifer/typing/_typing.py +68 -0
- junifer/utils/__init__.py +2 -12
- junifer/utils/__init__.pyi +18 -0
- junifer/utils/_config.py +110 -0
- junifer/utils/_yaml.py +16 -0
- junifer/utils/helpers.py +6 -6
- junifer/utils/logging.py +117 -8
- junifer/utils/py.typed +0 -0
- junifer/{pipeline → utils}/singleton.py +19 -14
- junifer/utils/tests/test_config.py +59 -0
- {junifer-0.0.5.dev242.dist-info → junifer-0.0.6.dist-info}/METADATA +43 -38
- junifer-0.0.6.dist-info/RECORD +350 -0
- {junifer-0.0.5.dev242.dist-info → junifer-0.0.6.dist-info}/WHEEL +1 -1
- junifer-0.0.6.dist-info/entry_points.txt +2 -0
- junifer/api/parser.py +0 -118
- junifer/data/coordinates.py +0 -408
- junifer/data/masks.py +0 -670
- junifer/data/parcellations.py +0 -1828
- junifer/pipeline/registry.py +0 -177
- junifer/pipeline/tests/test_registry.py +0 -150
- junifer-0.0.5.dev242.dist-info/RECORD +0 -275
- junifer-0.0.5.dev242.dist-info/entry_points.txt +0 -2
- /junifer/{api → cli}/tests/data/gmd_mean.yaml +0 -0
- /junifer/{api → cli}/tests/data/gmd_mean_htcondor.yaml +0 -0
- /junifer/{api → cli}/tests/data/partly_cloudy_agg_mean_tian.yml +0 -0
- /junifer/data/{VOIs → coordinates/VOIs}/meta/AutobiographicalMemory_VOIs.txt +0 -0
- /junifer/data/{VOIs → coordinates/VOIs}/meta/CogAC_VOIs.txt +0 -0
- /junifer/data/{VOIs → coordinates/VOIs}/meta/CogAR_VOIs.txt +0 -0
- /junifer/data/{VOIs → coordinates/VOIs}/meta/DMNBuckner_VOIs.txt +0 -0
- /junifer/data/{VOIs → coordinates/VOIs}/meta/Dosenbach2010_MNI_VOIs.txt +0 -0
- /junifer/data/{VOIs → coordinates/VOIs}/meta/Empathy_VOIs.txt +0 -0
- /junifer/data/{VOIs → coordinates/VOIs}/meta/Motor_VOIs.txt +0 -0
- /junifer/data/{VOIs → coordinates/VOIs}/meta/MultiTask_VOIs.txt +0 -0
- /junifer/data/{VOIs → coordinates/VOIs}/meta/PhysioStress_VOIs.txt +0 -0
- /junifer/data/{VOIs → coordinates/VOIs}/meta/Power2011_MNI_VOIs.txt +0 -0
- /junifer/data/{VOIs → coordinates/VOIs}/meta/Power2013_MNI_VOIs.tsv +0 -0
- /junifer/data/{VOIs → coordinates/VOIs}/meta/Rew_VOIs.txt +0 -0
- /junifer/data/{VOIs → coordinates/VOIs}/meta/Somatosensory_VOIs.txt +0 -0
- /junifer/data/{VOIs → coordinates/VOIs}/meta/ToM_VOIs.txt +0 -0
- /junifer/data/{VOIs → coordinates/VOIs}/meta/VigAtt_VOIs.txt +0 -0
- /junifer/data/{VOIs → coordinates/VOIs}/meta/WM_VOIs.txt +0 -0
- /junifer/data/{VOIs → coordinates/VOIs}/meta/eMDN_VOIs.txt +0 -0
- /junifer/data/{VOIs → coordinates/VOIs}/meta/eSAD_VOIs.txt +0 -0
- /junifer/data/{VOIs → coordinates/VOIs}/meta/extDMN_VOIs.txt +0 -0
- {junifer-0.0.5.dev242.dist-info → junifer-0.0.6.dist-info/licenses}/AUTHORS.rst +0 -0
- {junifer-0.0.5.dev242.dist-info → junifer-0.0.6.dist-info/licenses}/LICENSE.md +0 -0
- {junifer-0.0.5.dev242.dist-info → junifer-0.0.6.dist-info}/top_level.txt +0 -0
@@ -8,29 +8,25 @@ from pathlib import Path
|
|
8
8
|
from typing import (
|
9
9
|
TYPE_CHECKING,
|
10
10
|
ClassVar,
|
11
|
-
Dict,
|
12
|
-
List,
|
13
11
|
Optional,
|
14
|
-
Tuple,
|
15
|
-
Union,
|
16
12
|
)
|
17
13
|
|
18
14
|
import nibabel as nib
|
19
15
|
|
20
16
|
from ...pipeline import WorkDirManager
|
21
|
-
from ...
|
17
|
+
from ...typing import ExternalDependencies
|
22
18
|
from ...utils import logger, run_ext_cmd
|
19
|
+
from ...utils.singleton import Singleton
|
23
20
|
|
24
21
|
|
25
22
|
if TYPE_CHECKING:
|
26
|
-
from nibabel import Nifti1Image
|
23
|
+
from nibabel.nifti1 import Nifti1Image
|
27
24
|
|
28
25
|
|
29
26
|
__all__ = ["AFNIALFF"]
|
30
27
|
|
31
28
|
|
32
|
-
|
33
|
-
class AFNIALFF:
|
29
|
+
class AFNIALFF(metaclass=Singleton):
|
34
30
|
"""Class for computing ALFF using AFNI.
|
35
31
|
|
36
32
|
This class uses AFNI's 3dRSFC to compute ALFF. It's designed as a singleton
|
@@ -38,7 +34,7 @@ class AFNIALFF:
|
|
38
34
|
|
39
35
|
"""
|
40
36
|
|
41
|
-
_EXT_DEPENDENCIES: ClassVar[
|
37
|
+
_EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
|
42
38
|
{
|
43
39
|
"name": "afni",
|
44
40
|
"commands": ["3dRSFC", "3dAFNItoNIFTI"],
|
@@ -54,17 +50,17 @@ class AFNIALFF:
|
|
54
50
|
@lru_cache(maxsize=None, typed=True)
|
55
51
|
def compute(
|
56
52
|
self,
|
57
|
-
|
53
|
+
input_path: Path,
|
58
54
|
highpass: float,
|
59
55
|
lowpass: float,
|
60
56
|
tr: Optional[float],
|
61
|
-
) ->
|
57
|
+
) -> tuple["Nifti1Image", "Nifti1Image", Path, Path]:
|
62
58
|
"""Compute ALFF + fALFF map.
|
63
59
|
|
64
60
|
Parameters
|
65
61
|
----------
|
66
|
-
|
67
|
-
|
62
|
+
input_path : pathlib.Path
|
63
|
+
Path to the input data.
|
68
64
|
highpass : positive float
|
69
65
|
Highpass cutoff frequency.
|
70
66
|
lowpass : positive float
|
@@ -86,19 +82,17 @@ class AFNIALFF:
|
|
86
82
|
"""
|
87
83
|
logger.debug("Creating cache for ALFF computation via AFNI")
|
88
84
|
|
89
|
-
# Create
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
nifti_in_file_path = tempdir / "input.nii" # needs to be .nii
|
94
|
-
nib.save(data, nifti_in_file_path)
|
85
|
+
# Create element-scoped tempdir
|
86
|
+
element_tempdir = WorkDirManager().get_element_tempdir(
|
87
|
+
prefix="afni_lff"
|
88
|
+
)
|
95
89
|
|
96
90
|
# Set 3dRSFC command
|
97
|
-
|
91
|
+
lff_out_path_prefix = element_tempdir / "output"
|
98
92
|
bp_cmd = [
|
99
93
|
"3dRSFC",
|
100
|
-
f"-prefix {
|
101
|
-
f"-input {
|
94
|
+
f"-prefix {lff_out_path_prefix.resolve()}",
|
95
|
+
f"-input {input_path.resolve()}",
|
102
96
|
f"-band {highpass} {lowpass}",
|
103
97
|
"-no_rsfa -nosat -nodetrend",
|
104
98
|
]
|
@@ -108,49 +102,48 @@ class AFNIALFF:
|
|
108
102
|
# Call 3dRSFC
|
109
103
|
run_ext_cmd(name="3dRSFC", cmd=bp_cmd)
|
110
104
|
|
111
|
-
#
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
105
|
+
# Read header to get output suffix
|
106
|
+
niimg = nib.load(input_path)
|
107
|
+
header = niimg.header
|
108
|
+
sform_code = header.get_sform(coded=True)[1]
|
109
|
+
if sform_code == 4:
|
110
|
+
output_suffix = "tlrc"
|
111
|
+
else:
|
112
|
+
output_suffix = "orig"
|
113
|
+
# Set params suffix
|
118
114
|
params_suffix = f"_{highpass}_{lowpass}_{tr}"
|
119
115
|
|
120
116
|
# Convert alff afni to nifti
|
121
|
-
|
122
|
-
element_tempdir / f"
|
117
|
+
alff_nifti_out_path = (
|
118
|
+
element_tempdir / f"output_alff{params_suffix}.nii"
|
123
119
|
) # needs to be .nii
|
124
120
|
convert_alff_cmd = [
|
125
121
|
"3dAFNItoNIFTI",
|
126
|
-
f"-prefix {
|
127
|
-
f"{
|
122
|
+
f"-prefix {alff_nifti_out_path.resolve()}",
|
123
|
+
f"{lff_out_path_prefix}_ALFF+{output_suffix}.BRIK",
|
128
124
|
]
|
129
125
|
# Call 3dAFNItoNIFTI
|
130
126
|
run_ext_cmd(name="3dAFNItoNIFTI", cmd=convert_alff_cmd)
|
131
127
|
|
132
128
|
# Convert falff afni to nifti
|
133
|
-
|
134
|
-
element_tempdir / f"
|
129
|
+
falff_nifti_out_path = (
|
130
|
+
element_tempdir / f"output_falff{params_suffix}.nii"
|
135
131
|
) # needs to be .nii
|
136
132
|
convert_falff_cmd = [
|
137
133
|
"3dAFNItoNIFTI",
|
138
|
-
f"-prefix {
|
139
|
-
f"{
|
134
|
+
f"-prefix {falff_nifti_out_path.resolve()}",
|
135
|
+
f"{lff_out_path_prefix}_fALFF+{output_suffix}.BRIK",
|
140
136
|
]
|
141
137
|
# Call 3dAFNItoNIFTI
|
142
138
|
run_ext_cmd(name="3dAFNItoNIFTI", cmd=convert_falff_cmd)
|
143
139
|
|
144
140
|
# Load nifti
|
145
|
-
alff_data = nib.load(
|
146
|
-
falff_data = nib.load(
|
147
|
-
|
148
|
-
# Delete tempdir
|
149
|
-
WorkDirManager().delete_tempdir(tempdir)
|
141
|
+
alff_data = nib.load(alff_nifti_out_path)
|
142
|
+
falff_data = nib.load(falff_nifti_out_path)
|
150
143
|
|
151
144
|
return (
|
152
145
|
alff_data,
|
153
146
|
falff_data,
|
154
|
-
|
155
|
-
|
156
|
-
)
|
147
|
+
alff_nifti_out_path,
|
148
|
+
falff_nifti_out_path,
|
149
|
+
)
|
@@ -9,8 +9,6 @@ from typing import (
|
|
9
9
|
TYPE_CHECKING,
|
10
10
|
ClassVar,
|
11
11
|
Optional,
|
12
|
-
Set,
|
13
|
-
Tuple,
|
14
12
|
)
|
15
13
|
|
16
14
|
import nibabel as nib
|
@@ -19,26 +17,26 @@ import scipy as sp
|
|
19
17
|
from nilearn import image as nimg
|
20
18
|
|
21
19
|
from ...pipeline import WorkDirManager
|
22
|
-
from ...
|
20
|
+
from ...typing import Dependencies
|
23
21
|
from ...utils import logger
|
22
|
+
from ...utils.singleton import Singleton
|
24
23
|
|
25
24
|
|
26
25
|
if TYPE_CHECKING:
|
27
|
-
from nibabel import Nifti1Image
|
26
|
+
from nibabel.nifti1 import Nifti1Image
|
28
27
|
|
29
28
|
|
30
29
|
__all__ = ["JuniferALFF"]
|
31
30
|
|
32
31
|
|
33
|
-
|
34
|
-
class JuniferALFF:
|
32
|
+
class JuniferALFF(metaclass=Singleton):
|
35
33
|
"""Class for computing ALFF using junifer.
|
36
34
|
|
37
35
|
It's designed as a singleton with caching for efficient computation.
|
38
36
|
|
39
37
|
"""
|
40
38
|
|
41
|
-
_DEPENDENCIES: ClassVar[
|
39
|
+
_DEPENDENCIES: ClassVar[Dependencies] = {"numpy", "nilearn", "scipy"}
|
42
40
|
|
43
41
|
def __del__(self) -> None:
|
44
42
|
"""Terminate the class."""
|
@@ -49,17 +47,17 @@ class JuniferALFF:
|
|
49
47
|
@lru_cache(maxsize=None, typed=True)
|
50
48
|
def compute(
|
51
49
|
self,
|
52
|
-
|
50
|
+
input_path: Path,
|
53
51
|
highpass: float,
|
54
52
|
lowpass: float,
|
55
53
|
tr: Optional[float],
|
56
|
-
) ->
|
54
|
+
) -> tuple["Nifti1Image", "Nifti1Image", Path, Path]:
|
57
55
|
"""Compute ALFF + fALFF map.
|
58
56
|
|
59
57
|
Parameters
|
60
58
|
----------
|
61
|
-
|
62
|
-
|
59
|
+
input_path : pathlib.Path
|
60
|
+
Path to the input data.
|
63
61
|
highpass : positive float
|
64
62
|
Highpass cutoff frequency.
|
65
63
|
lowpass : positive float
|
@@ -82,9 +80,10 @@ class JuniferALFF:
|
|
82
80
|
logger.debug("Creating cache for ALFF computation via junifer")
|
83
81
|
|
84
82
|
# Get scan data
|
85
|
-
|
83
|
+
niimg = nib.load(input_path)
|
84
|
+
niimg_data = niimg.get_fdata().copy()
|
86
85
|
if tr is None:
|
87
|
-
tr = float(
|
86
|
+
tr = float(niimg.header["pixdim"][4]) # type: ignore
|
88
87
|
logger.info(f"`tr` not provided, using `tr` from header: {tr}")
|
89
88
|
|
90
89
|
# Bandpass the data within the lowpass and highpass cutoff freqs
|
@@ -122,19 +121,17 @@ class JuniferALFF:
|
|
122
121
|
# Calculate ALFF
|
123
122
|
alff = numerator / np.sqrt(niimg_data.shape[-1])
|
124
123
|
alff_data = nimg.new_img_like(
|
125
|
-
ref_niimg=
|
124
|
+
ref_niimg=niimg,
|
126
125
|
data=alff,
|
127
126
|
)
|
128
127
|
falff_data = nimg.new_img_like(
|
129
|
-
ref_niimg=
|
128
|
+
ref_niimg=niimg,
|
130
129
|
data=falff,
|
131
130
|
)
|
132
131
|
|
133
|
-
# Create element-scoped tempdir
|
134
|
-
# available later as nibabel stores file path reference for
|
135
|
-
# loading on computation
|
132
|
+
# Create element-scoped tempdir
|
136
133
|
element_tempdir = WorkDirManager().get_element_tempdir(
|
137
|
-
prefix="
|
134
|
+
prefix="junifer_lff"
|
138
135
|
)
|
139
136
|
output_alff_path = element_tempdir / "output_alff.nii.gz"
|
140
137
|
output_falff_path = element_tempdir / "output_falff.nii.gz"
|
@@ -11,14 +11,10 @@ from typing import (
|
|
11
11
|
TYPE_CHECKING,
|
12
12
|
Any,
|
13
13
|
ClassVar,
|
14
|
-
Dict,
|
15
|
-
List,
|
16
14
|
Optional,
|
17
|
-
Tuple,
|
18
|
-
Type,
|
19
|
-
Union,
|
20
15
|
)
|
21
16
|
|
17
|
+
from ...typing import ConditionalDependencies, MarkerInOutMappings
|
22
18
|
from ...utils.logging import logger, raise_error
|
23
19
|
from ..base import BaseMarker
|
24
20
|
from ._afni_falff import AFNIALFF
|
@@ -26,7 +22,7 @@ from ._junifer_falff import JuniferALFF
|
|
26
22
|
|
27
23
|
|
28
24
|
if TYPE_CHECKING:
|
29
|
-
from nibabel import Nifti1Image
|
25
|
+
from nibabel.nifti1 import Nifti1Image
|
30
26
|
|
31
27
|
|
32
28
|
__all__ = ["ALFFBase"]
|
@@ -72,7 +68,7 @@ class ALFFBase(BaseMarker):
|
|
72
68
|
|
73
69
|
"""
|
74
70
|
|
75
|
-
_CONDITIONAL_DEPENDENCIES: ClassVar[
|
71
|
+
_CONDITIONAL_DEPENDENCIES: ClassVar[ConditionalDependencies] = [
|
76
72
|
{
|
77
73
|
"using": "afni",
|
78
74
|
"depends_on": AFNIALFF,
|
@@ -83,7 +79,7 @@ class ALFFBase(BaseMarker):
|
|
83
79
|
},
|
84
80
|
]
|
85
81
|
|
86
|
-
_MARKER_INOUT_MAPPINGS: ClassVar[
|
82
|
+
_MARKER_INOUT_MAPPINGS: ClassVar[MarkerInOutMappings] = {
|
87
83
|
"BOLD": {
|
88
84
|
"alff": "vector",
|
89
85
|
"falff": "vector",
|
@@ -118,8 +114,8 @@ class ALFFBase(BaseMarker):
|
|
118
114
|
|
119
115
|
def _compute(
|
120
116
|
self,
|
121
|
-
input_data:
|
122
|
-
) ->
|
117
|
+
input_data: dict[str, Any],
|
118
|
+
) -> tuple["Nifti1Image", "Nifti1Image", Path, Path]:
|
123
119
|
"""Compute ALFF and fALFF.
|
124
120
|
|
125
121
|
Parameters
|
@@ -150,7 +146,7 @@ class ALFFBase(BaseMarker):
|
|
150
146
|
estimator = JuniferALFF()
|
151
147
|
# Compute ALFF + fALFF
|
152
148
|
alff, falff, alff_path, falff_path = estimator.compute( # type: ignore
|
153
|
-
|
149
|
+
input_path=input_data["path"],
|
154
150
|
highpass=self.highpass,
|
155
151
|
lowpass=self.lowpass,
|
156
152
|
tr=self.tr,
|
@@ -6,7 +6,7 @@
|
|
6
6
|
# Synchon Mandal <s.mandal@fz-juelich.de>
|
7
7
|
# License: AGPL
|
8
8
|
|
9
|
-
from typing import Any,
|
9
|
+
from typing import Any, Optional, Union
|
10
10
|
|
11
11
|
from ...api.decorators import register_marker
|
12
12
|
from ...utils import logger
|
@@ -24,8 +24,8 @@ class ALFFParcels(ALFFBase):
|
|
24
24
|
Parameters
|
25
25
|
----------
|
26
26
|
parcellation : str or list of str
|
27
|
-
The name(s) of the parcellation(s)
|
28
|
-
:func:`.
|
27
|
+
The name(s) of the parcellation(s) to use.
|
28
|
+
See :func:`.list_data` for options.
|
29
29
|
using : {"junifer", "afni"}
|
30
30
|
Implementation to use for computing ALFF:
|
31
31
|
|
@@ -70,14 +70,14 @@ class ALFFParcels(ALFFBase):
|
|
70
70
|
|
71
71
|
def __init__(
|
72
72
|
self,
|
73
|
-
parcellation: Union[str,
|
73
|
+
parcellation: Union[str, list[str]],
|
74
74
|
using: str,
|
75
75
|
highpass: float = 0.01,
|
76
76
|
lowpass: float = 0.1,
|
77
77
|
tr: Optional[float] = None,
|
78
78
|
agg_method: str = "mean",
|
79
|
-
agg_method_params: Optional[
|
80
|
-
masks: Union[str,
|
79
|
+
agg_method_params: Optional[dict] = None,
|
80
|
+
masks: Union[str, dict, list[Union[dict, str]], None] = None,
|
81
81
|
name: Optional[str] = None,
|
82
82
|
) -> None:
|
83
83
|
# Superclass init first to validate `using` parameter
|
@@ -95,9 +95,9 @@ class ALFFParcels(ALFFBase):
|
|
95
95
|
|
96
96
|
def compute(
|
97
97
|
self,
|
98
|
-
input:
|
99
|
-
extra_input: Optional[
|
100
|
-
) ->
|
98
|
+
input: dict[str, Any],
|
99
|
+
extra_input: Optional[dict[str, Any]] = None,
|
100
|
+
) -> dict[str, Any]:
|
101
101
|
"""Compute.
|
102
102
|
|
103
103
|
Parameters
|
@@ -6,7 +6,7 @@
|
|
6
6
|
# Synchon Mandal <s.mandal@fz-juelich.de>
|
7
7
|
# License: AGPL
|
8
8
|
|
9
|
-
from typing import Any,
|
9
|
+
from typing import Any, Optional, Union
|
10
10
|
|
11
11
|
from ...api.decorators import register_marker
|
12
12
|
from ...utils import logger
|
@@ -24,8 +24,8 @@ class ALFFSpheres(ALFFBase):
|
|
24
24
|
Parameters
|
25
25
|
----------
|
26
26
|
coords : str
|
27
|
-
The name of the coordinates list to use.
|
28
|
-
:func:`.
|
27
|
+
The name of the coordinates list to use.
|
28
|
+
See :func:`.list_data` for options.
|
29
29
|
using : {"junifer", "afni"}
|
30
30
|
Implementation to use for computing ALFF:
|
31
31
|
|
@@ -85,8 +85,8 @@ class ALFFSpheres(ALFFBase):
|
|
85
85
|
lowpass: float = 0.1,
|
86
86
|
tr: Optional[float] = None,
|
87
87
|
agg_method: str = "mean",
|
88
|
-
agg_method_params: Optional[
|
89
|
-
masks: Union[str,
|
88
|
+
agg_method_params: Optional[dict] = None,
|
89
|
+
masks: Union[str, dict, list[Union[dict, str]], None] = None,
|
90
90
|
name: Optional[str] = None,
|
91
91
|
) -> None:
|
92
92
|
# Superclass init first to validate `using` parameter
|
@@ -106,9 +106,9 @@ class ALFFSpheres(ALFFBase):
|
|
106
106
|
|
107
107
|
def compute(
|
108
108
|
self,
|
109
|
-
input:
|
110
|
-
extra_input: Optional[
|
111
|
-
) ->
|
109
|
+
input: dict[str, Any],
|
110
|
+
extra_input: Optional[dict[str, Any]] = None,
|
111
|
+
) -> dict[str, Any]:
|
112
112
|
"""Compute.
|
113
113
|
|
114
114
|
Parameters
|
File without changes
|
@@ -69,7 +69,9 @@ def test_ALFFSpheres(caplog: pytest.LogCaptureFixture, tmp_path: Path) -> None:
|
|
69
69
|
# Fit transform marker on data
|
70
70
|
output = marker.fit_transform(element_data)
|
71
71
|
|
72
|
-
|
72
|
+
# Tests for ALFFParcels run before this with the same data and that
|
73
|
+
# should create the cache
|
74
|
+
assert "Calculating ALFF and fALFF" in caplog.text
|
73
75
|
|
74
76
|
# Get BOLD output
|
75
77
|
assert "BOLD" in output
|
@@ -3,17 +3,7 @@
|
|
3
3
|
# Authors: Synchon Mandal <s.mandal@fz-juelich.de>
|
4
4
|
# License: AGPL
|
5
5
|
|
6
|
-
|
7
|
-
from .functional_connectivity_spheres import FunctionalConnectivitySpheres
|
8
|
-
from .crossparcellation_functional_connectivity import CrossParcellationFC
|
9
|
-
from .edge_functional_connectivity_parcels import EdgeCentricFCParcels
|
10
|
-
from .edge_functional_connectivity_spheres import EdgeCentricFCSpheres
|
6
|
+
import lazy_loader as lazy
|
11
7
|
|
12
8
|
|
13
|
-
__all__ =
|
14
|
-
"FunctionalConnectivityParcels",
|
15
|
-
"FunctionalConnectivitySpheres",
|
16
|
-
"CrossParcellationFC",
|
17
|
-
"EdgeCentricFCParcels",
|
18
|
-
"EdgeCentricFCSpheres",
|
19
|
-
]
|
9
|
+
__getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
__all__ = [
|
2
|
+
"FunctionalConnectivityParcels",
|
3
|
+
"FunctionalConnectivitySpheres",
|
4
|
+
"CrossParcellationFC",
|
5
|
+
"EdgeCentricFCParcels",
|
6
|
+
"EdgeCentricFCSpheres",
|
7
|
+
]
|
8
|
+
|
9
|
+
from .functional_connectivity_parcels import FunctionalConnectivityParcels
|
10
|
+
from .functional_connectivity_spheres import FunctionalConnectivitySpheres
|
11
|
+
from .crossparcellation_functional_connectivity import CrossParcellationFC
|
12
|
+
from .edge_functional_connectivity_parcels import EdgeCentricFCParcels
|
13
|
+
from .edge_functional_connectivity_spheres import EdgeCentricFCSpheres
|
@@ -4,11 +4,12 @@
|
|
4
4
|
# Kaustubh R. Patil <k.patil@fz-juelich.de>
|
5
5
|
# License: AGPL
|
6
6
|
|
7
|
-
from typing import Any, ClassVar,
|
7
|
+
from typing import Any, ClassVar, Optional, Union
|
8
8
|
|
9
9
|
import pandas as pd
|
10
10
|
|
11
11
|
from ...api.decorators import register_marker
|
12
|
+
from ...typing import Dependencies, MarkerInOutMappings
|
12
13
|
from ...utils import logger, raise_error
|
13
14
|
from ..base import BaseMarker
|
14
15
|
from ..parcel_aggregation import ParcelAggregation
|
@@ -49,9 +50,9 @@ class CrossParcellationFC(BaseMarker):
|
|
49
50
|
|
50
51
|
"""
|
51
52
|
|
52
|
-
_DEPENDENCIES: ClassVar[
|
53
|
+
_DEPENDENCIES: ClassVar[Dependencies] = {"nilearn"}
|
53
54
|
|
54
|
-
_MARKER_INOUT_MAPPINGS: ClassVar[
|
55
|
+
_MARKER_INOUT_MAPPINGS: ClassVar[MarkerInOutMappings] = {
|
55
56
|
"BOLD": {
|
56
57
|
"functional_connectivity": "matrix",
|
57
58
|
},
|
@@ -62,9 +63,9 @@ class CrossParcellationFC(BaseMarker):
|
|
62
63
|
parcellation_one: str,
|
63
64
|
parcellation_two: str,
|
64
65
|
agg_method: str = "mean",
|
65
|
-
agg_method_params: Optional[
|
66
|
+
agg_method_params: Optional[dict] = None,
|
66
67
|
corr_method: str = "pearson",
|
67
|
-
masks: Union[str,
|
68
|
+
masks: Union[str, dict, list[Union[dict, str]], None] = None,
|
68
69
|
name: Optional[str] = None,
|
69
70
|
) -> None:
|
70
71
|
if parcellation_one == parcellation_two:
|
@@ -81,9 +82,9 @@ class CrossParcellationFC(BaseMarker):
|
|
81
82
|
|
82
83
|
def compute(
|
83
84
|
self,
|
84
|
-
input:
|
85
|
-
extra_input: Optional[
|
86
|
-
) ->
|
85
|
+
input: dict[str, Any],
|
86
|
+
extra_input: Optional[dict] = None,
|
87
|
+
) -> dict:
|
87
88
|
"""Compute.
|
88
89
|
|
89
90
|
Take a timeseries, parcellate them with two different parcellation
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# Synchon Mandal <s.mandal@fz-juelich.de>
|
5
5
|
# License: AGPL
|
6
6
|
|
7
|
-
from typing import Any,
|
7
|
+
from typing import Any, Optional, Union
|
8
8
|
|
9
9
|
from ...api.decorators import register_marker
|
10
10
|
from ..parcel_aggregation import ParcelAggregation
|
@@ -23,7 +23,7 @@ class EdgeCentricFCParcels(FunctionalConnectivityBase):
|
|
23
23
|
----------
|
24
24
|
parcellation : str or list of str
|
25
25
|
The name(s) of the parcellation(s) to use.
|
26
|
-
See :func:`.
|
26
|
+
See :func:`.list_data` for options.
|
27
27
|
agg_method : str, optional
|
28
28
|
The method to perform aggregation using.
|
29
29
|
See :func:`.get_aggfunc_by_name` for options
|
@@ -61,12 +61,12 @@ class EdgeCentricFCParcels(FunctionalConnectivityBase):
|
|
61
61
|
|
62
62
|
def __init__(
|
63
63
|
self,
|
64
|
-
parcellation: Union[str,
|
64
|
+
parcellation: Union[str, list[str]],
|
65
65
|
agg_method: str = "mean",
|
66
|
-
agg_method_params: Optional[
|
66
|
+
agg_method_params: Optional[dict] = None,
|
67
67
|
conn_method: str = "correlation",
|
68
|
-
conn_method_params: Optional[
|
69
|
-
masks: Union[str,
|
68
|
+
conn_method_params: Optional[dict] = None,
|
69
|
+
masks: Union[str, dict, list[Union[dict, str]], None] = None,
|
70
70
|
name: Optional[str] = None,
|
71
71
|
) -> None:
|
72
72
|
self.parcellation = parcellation
|
@@ -80,8 +80,8 @@ class EdgeCentricFCParcels(FunctionalConnectivityBase):
|
|
80
80
|
)
|
81
81
|
|
82
82
|
def aggregate(
|
83
|
-
self, input:
|
84
|
-
) ->
|
83
|
+
self, input: dict[str, Any], extra_input: Optional[dict] = None
|
84
|
+
) -> dict:
|
85
85
|
"""Perform parcel aggregation and ETS computation.
|
86
86
|
|
87
87
|
Parameters
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# Synchon Mandal <s.mandal@fz-juelich.de>
|
5
5
|
# License: AGPL
|
6
6
|
|
7
|
-
from typing import Any,
|
7
|
+
from typing import Any, Optional, Union
|
8
8
|
|
9
9
|
from ...api.decorators import register_marker
|
10
10
|
from ..sphere_aggregation import SphereAggregation
|
@@ -23,7 +23,7 @@ class EdgeCentricFCSpheres(FunctionalConnectivityBase):
|
|
23
23
|
----------
|
24
24
|
coords : str
|
25
25
|
The name of the coordinates list to use.
|
26
|
-
See :func:`.
|
26
|
+
See :func:`.list_data` for options.
|
27
27
|
radius : positive float, optional
|
28
28
|
The radius of the sphere around each coordinates in millimetres.
|
29
29
|
If None, the signal will be extracted from a single voxel.
|
@@ -73,10 +73,10 @@ class EdgeCentricFCSpheres(FunctionalConnectivityBase):
|
|
73
73
|
radius: Optional[float] = None,
|
74
74
|
allow_overlap: bool = False,
|
75
75
|
agg_method: str = "mean",
|
76
|
-
agg_method_params: Optional[
|
76
|
+
agg_method_params: Optional[dict] = None,
|
77
77
|
conn_method: str = "correlation",
|
78
|
-
conn_method_params: Optional[
|
79
|
-
masks: Union[str,
|
78
|
+
conn_method_params: Optional[dict] = None,
|
79
|
+
masks: Union[str, dict, list[Union[dict, str]], None] = None,
|
80
80
|
name: Optional[str] = None,
|
81
81
|
) -> None:
|
82
82
|
self.coords = coords
|
@@ -94,8 +94,8 @@ class EdgeCentricFCSpheres(FunctionalConnectivityBase):
|
|
94
94
|
)
|
95
95
|
|
96
96
|
def aggregate(
|
97
|
-
self, input:
|
98
|
-
) ->
|
97
|
+
self, input: dict[str, Any], extra_input: Optional[dict] = None
|
98
|
+
) -> dict:
|
99
99
|
"""Perform sphere aggregation and ETS computation.
|
100
100
|
|
101
101
|
Parameters
|