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
@@ -14,6 +14,9 @@ from ..parcel_aggregation import ParcelAggregation
|
|
14
14
|
from .falff_base import ALFFBase
|
15
15
|
|
16
16
|
|
17
|
+
__all__ = ["ALFFParcels"]
|
18
|
+
|
19
|
+
|
17
20
|
@register_marker
|
18
21
|
class ALFFParcels(ALFFBase):
|
19
22
|
"""Class for ALFF / fALFF on parcels.
|
@@ -23,8 +26,6 @@ class ALFFParcels(ALFFBase):
|
|
23
26
|
parcellation : str or list of str
|
24
27
|
The name(s) of the parcellation(s). Check valid options by calling
|
25
28
|
:func:`.list_parcellations`.
|
26
|
-
fractional : bool
|
27
|
-
Whether to compute fractional ALFF.
|
28
29
|
using : {"junifer", "afni"}
|
29
30
|
Implementation to use for computing ALFF:
|
30
31
|
|
@@ -70,7 +71,6 @@ class ALFFParcels(ALFFBase):
|
|
70
71
|
def __init__(
|
71
72
|
self,
|
72
73
|
parcellation: Union[str, List[str]],
|
73
|
-
fractional: bool,
|
74
74
|
using: str,
|
75
75
|
highpass: float = 0.01,
|
76
76
|
lowpass: float = 0.1,
|
@@ -82,7 +82,6 @@ class ALFFParcels(ALFFBase):
|
|
82
82
|
) -> None:
|
83
83
|
# Superclass init first to validate `using` parameter
|
84
84
|
super().__init__(
|
85
|
-
fractional=fractional,
|
86
85
|
highpass=highpass,
|
87
86
|
lowpass=lowpass,
|
88
87
|
using=using,
|
@@ -111,33 +110,63 @@ class ALFFParcels(ALFFBase):
|
|
111
110
|
Returns
|
112
111
|
-------
|
113
112
|
dict
|
114
|
-
The computed result as dictionary.
|
115
|
-
|
113
|
+
The computed result as dictionary. This will be either returned
|
114
|
+
to the user or stored in the storage by calling the store method
|
115
|
+
with this as a parameter. The dictionary has the following keys:
|
116
|
+
|
117
|
+
* ``alff`` : dictionary with the following keys:
|
118
|
+
|
119
|
+
- ``data`` : ROI values as ``numpy.ndarray``
|
120
|
+
- ``col_names`` : ROI labels as list of str
|
116
121
|
|
117
|
-
* ``
|
118
|
-
|
122
|
+
* ``falff`` : dictionary with the following keys:
|
123
|
+
|
124
|
+
- ``data`` : ROI values as ``numpy.ndarray``
|
125
|
+
- ``col_names`` : ROI labels as list of str
|
119
126
|
|
120
127
|
"""
|
121
128
|
logger.info("Calculating ALFF / fALFF for parcels")
|
122
129
|
|
123
|
-
# Compute ALFF
|
124
|
-
|
125
|
-
|
126
|
-
# Initialize parcel aggregation
|
127
|
-
parcel_aggregation = ParcelAggregation(
|
128
|
-
parcellation=self.parcellation,
|
129
|
-
method=self.agg_method,
|
130
|
-
method_params=self.agg_method_params,
|
131
|
-
masks=self.masks,
|
132
|
-
on="BOLD",
|
133
|
-
)
|
134
|
-
# Perform aggregation on ALFF / fALFF
|
135
|
-
parcel_aggregation_input = dict(input.items())
|
136
|
-
parcel_aggregation_input["data"] = output_data
|
137
|
-
parcel_aggregation_input["path"] = output_file_path
|
138
|
-
output = parcel_aggregation.compute(
|
139
|
-
input=parcel_aggregation_input,
|
140
|
-
extra_input=extra_input,
|
130
|
+
# Compute ALFF + fALFF
|
131
|
+
alff_output, falff_output, alff_output_path, falff_output_path = (
|
132
|
+
self._compute(input_data=input)
|
141
133
|
)
|
142
134
|
|
143
|
-
|
135
|
+
# Perform aggregation on ALFF + fALFF
|
136
|
+
aggregation_alff_input = dict(input.items())
|
137
|
+
aggregation_falff_input = dict(input.items())
|
138
|
+
aggregation_alff_input["data"] = alff_output
|
139
|
+
aggregation_falff_input["data"] = falff_output
|
140
|
+
aggregation_alff_input["path"] = alff_output_path
|
141
|
+
aggregation_falff_input["path"] = falff_output_path
|
142
|
+
|
143
|
+
return {
|
144
|
+
"alff": {
|
145
|
+
**ParcelAggregation(
|
146
|
+
parcellation=self.parcellation,
|
147
|
+
method=self.agg_method,
|
148
|
+
method_params=self.agg_method_params,
|
149
|
+
masks=self.masks,
|
150
|
+
on="BOLD",
|
151
|
+
).compute(
|
152
|
+
input=aggregation_alff_input,
|
153
|
+
extra_input=extra_input,
|
154
|
+
)[
|
155
|
+
"aggregation"
|
156
|
+
],
|
157
|
+
},
|
158
|
+
"falff": {
|
159
|
+
**ParcelAggregation(
|
160
|
+
parcellation=self.parcellation,
|
161
|
+
method=self.agg_method,
|
162
|
+
method_params=self.agg_method_params,
|
163
|
+
masks=self.masks,
|
164
|
+
on="BOLD",
|
165
|
+
).compute(
|
166
|
+
input=aggregation_falff_input,
|
167
|
+
extra_input=extra_input,
|
168
|
+
)[
|
169
|
+
"aggregation"
|
170
|
+
],
|
171
|
+
},
|
172
|
+
}
|
@@ -14,6 +14,9 @@ from ..sphere_aggregation import SphereAggregation
|
|
14
14
|
from .falff_base import ALFFBase
|
15
15
|
|
16
16
|
|
17
|
+
__all__ = ["ALFFSpheres"]
|
18
|
+
|
19
|
+
|
17
20
|
@register_marker
|
18
21
|
class ALFFSpheres(ALFFBase):
|
19
22
|
"""Class for computing ALFF / fALFF on spheres.
|
@@ -23,8 +26,6 @@ class ALFFSpheres(ALFFBase):
|
|
23
26
|
coords : str
|
24
27
|
The name of the coordinates list to use. See
|
25
28
|
:func:`.list_coordinates` for options.
|
26
|
-
fractional : bool
|
27
|
-
Whether to compute fractional ALFF.
|
28
29
|
using : {"junifer", "afni"}
|
29
30
|
Implementation to use for computing ALFF:
|
30
31
|
|
@@ -77,7 +78,6 @@ class ALFFSpheres(ALFFBase):
|
|
77
78
|
def __init__(
|
78
79
|
self,
|
79
80
|
coords: str,
|
80
|
-
fractional: bool,
|
81
81
|
using: str,
|
82
82
|
radius: Optional[float] = None,
|
83
83
|
allow_overlap: bool = False,
|
@@ -91,7 +91,6 @@ class ALFFSpheres(ALFFBase):
|
|
91
91
|
) -> None:
|
92
92
|
# Superclass init first to validate `using` parameter
|
93
93
|
super().__init__(
|
94
|
-
fractional=fractional,
|
95
94
|
highpass=highpass,
|
96
95
|
lowpass=lowpass,
|
97
96
|
using=using,
|
@@ -122,35 +121,67 @@ class ALFFSpheres(ALFFBase):
|
|
122
121
|
Returns
|
123
122
|
-------
|
124
123
|
dict
|
125
|
-
The computed result as dictionary.
|
126
|
-
|
124
|
+
The computed result as dictionary. This will be either returned
|
125
|
+
to the user or stored in the storage by calling the store method
|
126
|
+
with this as a parameter. The dictionary has the following keys:
|
127
|
+
|
128
|
+
* ``alff`` : dictionary with the following keys:
|
129
|
+
|
130
|
+
- ``data`` : ROI values as ``numpy.ndarray``
|
131
|
+
- ``col_names`` : ROI labels as list of str
|
127
132
|
|
128
|
-
* ``
|
129
|
-
|
133
|
+
* ``falff`` : dictionary with the following keys:
|
134
|
+
|
135
|
+
- ``data`` : ROI values as ``numpy.ndarray``
|
136
|
+
- ``col_names`` : ROI labels as list of str
|
130
137
|
|
131
138
|
"""
|
132
139
|
logger.info("Calculating ALFF / fALFF for spheres")
|
133
140
|
|
134
|
-
# Compute ALFF
|
135
|
-
|
136
|
-
|
137
|
-
# Initialize sphere aggregation
|
138
|
-
sphere_aggregation = SphereAggregation(
|
139
|
-
coords=self.coords,
|
140
|
-
radius=self.radius,
|
141
|
-
allow_overlap=self.allow_overlap,
|
142
|
-
method=self.agg_method,
|
143
|
-
method_params=self.agg_method_params,
|
144
|
-
masks=self.masks,
|
145
|
-
on="BOLD",
|
146
|
-
)
|
147
|
-
# Perform aggregation on ALFF / fALFF
|
148
|
-
sphere_aggregation_input = dict(input.items())
|
149
|
-
sphere_aggregation_input["data"] = output_data
|
150
|
-
sphere_aggregation_input["path"] = output_file_path
|
151
|
-
output = sphere_aggregation.compute(
|
152
|
-
input=sphere_aggregation_input,
|
153
|
-
extra_input=extra_input,
|
141
|
+
# Compute ALFF + fALFF
|
142
|
+
alff_output, falff_output, alff_output_path, falff_output_path = (
|
143
|
+
self._compute(input_data=input)
|
154
144
|
)
|
155
145
|
|
156
|
-
|
146
|
+
# Perform aggregation on ALFF / fALFF
|
147
|
+
aggregation_alff_input = dict(input.items())
|
148
|
+
aggregation_falff_input = dict(input.items())
|
149
|
+
aggregation_alff_input["data"] = alff_output
|
150
|
+
aggregation_falff_input["data"] = falff_output
|
151
|
+
aggregation_alff_input["path"] = alff_output_path
|
152
|
+
aggregation_falff_input["path"] = falff_output_path
|
153
|
+
|
154
|
+
return {
|
155
|
+
"alff": {
|
156
|
+
**SphereAggregation(
|
157
|
+
coords=self.coords,
|
158
|
+
radius=self.radius,
|
159
|
+
allow_overlap=self.allow_overlap,
|
160
|
+
method=self.agg_method,
|
161
|
+
method_params=self.agg_method_params,
|
162
|
+
masks=self.masks,
|
163
|
+
on="BOLD",
|
164
|
+
).compute(
|
165
|
+
input=aggregation_alff_input,
|
166
|
+
extra_input=extra_input,
|
167
|
+
)[
|
168
|
+
"aggregation"
|
169
|
+
],
|
170
|
+
},
|
171
|
+
"falff": {
|
172
|
+
**SphereAggregation(
|
173
|
+
coords=self.coords,
|
174
|
+
radius=self.radius,
|
175
|
+
allow_overlap=self.allow_overlap,
|
176
|
+
method=self.agg_method,
|
177
|
+
method_params=self.agg_method_params,
|
178
|
+
masks=self.masks,
|
179
|
+
on="BOLD",
|
180
|
+
).compute(
|
181
|
+
input=aggregation_falff_input,
|
182
|
+
extra_input=extra_input,
|
183
|
+
)[
|
184
|
+
"aggregation"
|
185
|
+
],
|
186
|
+
},
|
187
|
+
}
|
@@ -21,6 +21,28 @@ from junifer.testing.datagrabbers import PartlyCloudyTestingDataGrabber
|
|
21
21
|
PARCELLATION = "TianxS1x3TxMNInonlinear2009cAsym"
|
22
22
|
|
23
23
|
|
24
|
+
@pytest.mark.parametrize(
|
25
|
+
"feature",
|
26
|
+
[
|
27
|
+
"alff",
|
28
|
+
"falff",
|
29
|
+
],
|
30
|
+
)
|
31
|
+
def test_ALFFParcels_get_output_type(feature: str) -> None:
|
32
|
+
"""Test ALFFParcels get_output_type().
|
33
|
+
|
34
|
+
Parameters
|
35
|
+
----------
|
36
|
+
feature : str
|
37
|
+
The parametrized feature name.
|
38
|
+
|
39
|
+
"""
|
40
|
+
assert "vector" == ALFFParcels(
|
41
|
+
parcellation=PARCELLATION,
|
42
|
+
using="junifer",
|
43
|
+
).get_output_type(input_type="BOLD", output_feature=feature)
|
44
|
+
|
45
|
+
|
24
46
|
def test_ALFFParcels(caplog: pytest.LogCaptureFixture, tmp_path: Path) -> None:
|
25
47
|
"""Test ALFFParcels.
|
26
48
|
|
@@ -41,7 +63,6 @@ def test_ALFFParcels(caplog: pytest.LogCaptureFixture, tmp_path: Path) -> None:
|
|
41
63
|
# Initialize marker
|
42
64
|
marker = ALFFParcels(
|
43
65
|
parcellation=PARCELLATION,
|
44
|
-
fractional=False,
|
45
66
|
using="junifer",
|
46
67
|
)
|
47
68
|
# Fit transform marker on data
|
@@ -51,15 +72,16 @@ def test_ALFFParcels(caplog: pytest.LogCaptureFixture, tmp_path: Path) -> None:
|
|
51
72
|
|
52
73
|
# Get BOLD output
|
53
74
|
assert "BOLD" in output
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
75
|
+
for feature in output["BOLD"].keys():
|
76
|
+
output_bold = output["BOLD"][feature]
|
77
|
+
# Assert BOLD output keys
|
78
|
+
assert "data" in output_bold
|
79
|
+
assert "col_names" in output_bold
|
58
80
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
81
|
+
output_bold_data = output_bold["data"]
|
82
|
+
# Assert BOLD output data dimension
|
83
|
+
assert output_bold_data.ndim == 2
|
84
|
+
assert output_bold_data.shape == (1, 16)
|
63
85
|
|
64
86
|
# Reset log capture
|
65
87
|
caplog.clear()
|
@@ -77,18 +99,13 @@ def test_ALFFParcels(caplog: pytest.LogCaptureFixture, tmp_path: Path) -> None:
|
|
77
99
|
@pytest.mark.skipif(
|
78
100
|
_check_afni() is False, reason="requires AFNI to be in PATH"
|
79
101
|
)
|
80
|
-
|
81
|
-
"fractional", [True, False], ids=["fractional", "non-fractional"]
|
82
|
-
)
|
83
|
-
def test_ALFFParcels_comparison(tmp_path: Path, fractional: bool) -> None:
|
102
|
+
def test_ALFFParcels_comparison(tmp_path: Path) -> None:
|
84
103
|
"""Test ALFFParcels implementation comparison.
|
85
104
|
|
86
105
|
Parameters
|
87
106
|
----------
|
88
107
|
tmp_path : pathlib.Path
|
89
108
|
The path to the test directory.
|
90
|
-
fractional : bool
|
91
|
-
Whether to compute fractional ALFF or not.
|
92
109
|
|
93
110
|
"""
|
94
111
|
with PartlyCloudyTestingDataGrabber() as dg:
|
@@ -99,7 +116,6 @@ def test_ALFFParcels_comparison(tmp_path: Path, fractional: bool) -> None:
|
|
99
116
|
# Initialize marker
|
100
117
|
junifer_marker = ALFFParcels(
|
101
118
|
parcellation=PARCELLATION,
|
102
|
-
fractional=fractional,
|
103
119
|
using="junifer",
|
104
120
|
)
|
105
121
|
# Fit transform marker on data
|
@@ -110,7 +126,6 @@ def test_ALFFParcels_comparison(tmp_path: Path, fractional: bool) -> None:
|
|
110
126
|
# Initialize marker
|
111
127
|
afni_marker = ALFFParcels(
|
112
128
|
parcellation=PARCELLATION,
|
113
|
-
fractional=fractional,
|
114
129
|
using="afni",
|
115
130
|
)
|
116
131
|
# Fit transform marker on data
|
@@ -118,9 +133,10 @@ def test_ALFFParcels_comparison(tmp_path: Path, fractional: bool) -> None:
|
|
118
133
|
# Get BOLD output
|
119
134
|
afni_output_bold = afni_output["BOLD"]
|
120
135
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
136
|
+
for feature in afni_output_bold.keys():
|
137
|
+
# Check for Pearson correlation coefficient
|
138
|
+
r, _ = sp.stats.pearsonr(
|
139
|
+
junifer_output_bold[feature]["data"][0],
|
140
|
+
afni_output_bold[feature]["data"][0],
|
141
|
+
)
|
142
|
+
assert r > 0.97
|
@@ -21,6 +21,28 @@ from junifer.testing.datagrabbers import PartlyCloudyTestingDataGrabber
|
|
21
21
|
COORDINATES = "DMNBuckner"
|
22
22
|
|
23
23
|
|
24
|
+
@pytest.mark.parametrize(
|
25
|
+
"feature",
|
26
|
+
[
|
27
|
+
"alff",
|
28
|
+
"falff",
|
29
|
+
],
|
30
|
+
)
|
31
|
+
def test_ALFFSpheres_get_output_type(feature: str) -> None:
|
32
|
+
"""Test ALFFSpheres get_output_type().
|
33
|
+
|
34
|
+
Parameters
|
35
|
+
----------
|
36
|
+
feature : str
|
37
|
+
The parametrized feature name.
|
38
|
+
|
39
|
+
"""
|
40
|
+
assert "vector" == ALFFSpheres(
|
41
|
+
coords=COORDINATES,
|
42
|
+
using="junifer",
|
43
|
+
).get_output_type(input_type="BOLD", output_feature=feature)
|
44
|
+
|
45
|
+
|
24
46
|
def test_ALFFSpheres(caplog: pytest.LogCaptureFixture, tmp_path: Path) -> None:
|
25
47
|
"""Test ALFFSpheres.
|
26
48
|
|
@@ -41,7 +63,6 @@ def test_ALFFSpheres(caplog: pytest.LogCaptureFixture, tmp_path: Path) -> None:
|
|
41
63
|
# Initialize marker
|
42
64
|
marker = ALFFSpheres(
|
43
65
|
coords=COORDINATES,
|
44
|
-
fractional=False,
|
45
66
|
using="junifer",
|
46
67
|
radius=5.0,
|
47
68
|
)
|
@@ -52,15 +73,16 @@ def test_ALFFSpheres(caplog: pytest.LogCaptureFixture, tmp_path: Path) -> None:
|
|
52
73
|
|
53
74
|
# Get BOLD output
|
54
75
|
assert "BOLD" in output
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
76
|
+
for feature in output["BOLD"].keys():
|
77
|
+
output_bold = output["BOLD"][feature]
|
78
|
+
# Assert BOLD output keys
|
79
|
+
assert "data" in output_bold
|
80
|
+
assert "col_names" in output_bold
|
59
81
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
82
|
+
output_bold_data = output_bold["data"]
|
83
|
+
# Assert BOLD output data dimension
|
84
|
+
assert output_bold_data.ndim == 2
|
85
|
+
assert output_bold_data.shape == (1, 6)
|
64
86
|
|
65
87
|
# Reset log capture
|
66
88
|
caplog.clear()
|
@@ -78,18 +100,13 @@ def test_ALFFSpheres(caplog: pytest.LogCaptureFixture, tmp_path: Path) -> None:
|
|
78
100
|
@pytest.mark.skipif(
|
79
101
|
_check_afni() is False, reason="requires AFNI to be in PATH"
|
80
102
|
)
|
81
|
-
|
82
|
-
"fractional", [True, False], ids=["fractional", "non-fractional"]
|
83
|
-
)
|
84
|
-
def test_ALFFSpheres_comparison(tmp_path: Path, fractional: bool) -> None:
|
103
|
+
def test_ALFFSpheres_comparison(tmp_path: Path) -> None:
|
85
104
|
"""Test ALFFSpheres implementation comparison.
|
86
105
|
|
87
106
|
Parameters
|
88
107
|
----------
|
89
108
|
tmp_path : pathlib.Path
|
90
109
|
The path to the test directory.
|
91
|
-
fractional : bool
|
92
|
-
Whether to compute fractional ALFF or not.
|
93
110
|
|
94
111
|
"""
|
95
112
|
with PartlyCloudyTestingDataGrabber() as dg:
|
@@ -100,7 +117,6 @@ def test_ALFFSpheres_comparison(tmp_path: Path, fractional: bool) -> None:
|
|
100
117
|
# Initialize marker
|
101
118
|
junifer_marker = ALFFSpheres(
|
102
119
|
coords=COORDINATES,
|
103
|
-
fractional=fractional,
|
104
120
|
using="junifer",
|
105
121
|
radius=5.0,
|
106
122
|
)
|
@@ -112,7 +128,6 @@ def test_ALFFSpheres_comparison(tmp_path: Path, fractional: bool) -> None:
|
|
112
128
|
# Initialize marker
|
113
129
|
afni_marker = ALFFSpheres(
|
114
130
|
coords=COORDINATES,
|
115
|
-
fractional=fractional,
|
116
131
|
using="afni",
|
117
132
|
radius=5.0,
|
118
133
|
)
|
@@ -121,9 +136,10 @@ def test_ALFFSpheres_comparison(tmp_path: Path, fractional: bool) -> None:
|
|
121
136
|
# Get BOLD output
|
122
137
|
afni_output_bold = afni_output["BOLD"]
|
123
138
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
139
|
+
for feature in afni_output_bold.keys():
|
140
|
+
# Check for Pearson correlation coefficient
|
141
|
+
r, _ = sp.stats.pearsonr(
|
142
|
+
junifer_output_bold[feature]["data"][0],
|
143
|
+
afni_output_bold[feature]["data"][0],
|
144
|
+
)
|
145
|
+
assert r > 0.99
|
@@ -8,3 +8,12 @@ from .functional_connectivity_spheres import FunctionalConnectivitySpheres
|
|
8
8
|
from .crossparcellation_functional_connectivity import CrossParcellationFC
|
9
9
|
from .edge_functional_connectivity_parcels import EdgeCentricFCParcels
|
10
10
|
from .edge_functional_connectivity_spheres import EdgeCentricFCSpheres
|
11
|
+
|
12
|
+
|
13
|
+
__all__ = [
|
14
|
+
"FunctionalConnectivityParcels",
|
15
|
+
"FunctionalConnectivitySpheres",
|
16
|
+
"CrossParcellationFC",
|
17
|
+
"EdgeCentricFCParcels",
|
18
|
+
"EdgeCentricFCSpheres",
|
19
|
+
]
|
@@ -15,6 +15,9 @@ from ..parcel_aggregation import ParcelAggregation
|
|
15
15
|
from ..utils import _correlate_dataframes
|
16
16
|
|
17
17
|
|
18
|
+
__all__ = ["CrossParcellationFC"]
|
19
|
+
|
20
|
+
|
18
21
|
@register_marker
|
19
22
|
class CrossParcellationFC(BaseMarker):
|
20
23
|
"""Class for calculating parcel-wise correlations with 2 parcellations.
|
@@ -25,29 +28,42 @@ class CrossParcellationFC(BaseMarker):
|
|
25
28
|
The name of the first parcellation.
|
26
29
|
parcellation_two : str
|
27
30
|
The name of the second parcellation.
|
28
|
-
|
29
|
-
The
|
30
|
-
|
31
|
+
agg_method : str, optional
|
32
|
+
The method to perform aggregation using.
|
33
|
+
See :func:`.get_aggfunc_by_name` for options
|
34
|
+
(default "mean").
|
35
|
+
agg_method_params : dict, optional
|
36
|
+
Parameters to pass to the aggregation function.
|
37
|
+
See :func:`.get_aggfunc_by_name` for options
|
38
|
+
(default None).
|
39
|
+
corr_method : str, optional
|
31
40
|
Any method that can be passed to
|
32
|
-
:
|
41
|
+
:meth:`pandas.DataFrame.corr` (default "pearson").
|
33
42
|
masks : str, dict or list of dict or str, optional
|
34
43
|
The specification of the masks to apply to regions before extracting
|
35
44
|
signals. Check :ref:`Using Masks <using_masks>` for more details.
|
36
45
|
If None, will not apply any mask (default None).
|
37
46
|
name : str, optional
|
38
|
-
The name of the marker. If None, will use
|
39
|
-
(default None).
|
47
|
+
The name of the marker. If None, will use
|
48
|
+
``BOLD_CrossParcellationFC`` (default None).
|
40
49
|
|
41
50
|
"""
|
42
51
|
|
43
52
|
_DEPENDENCIES: ClassVar[Set[str]] = {"nilearn"}
|
44
53
|
|
54
|
+
_MARKER_INOUT_MAPPINGS: ClassVar[Dict[str, Dict[str, str]]] = {
|
55
|
+
"BOLD": {
|
56
|
+
"functional_connectivity": "matrix",
|
57
|
+
},
|
58
|
+
}
|
59
|
+
|
45
60
|
def __init__(
|
46
61
|
self,
|
47
62
|
parcellation_one: str,
|
48
63
|
parcellation_two: str,
|
49
|
-
|
50
|
-
|
64
|
+
agg_method: str = "mean",
|
65
|
+
agg_method_params: Optional[Dict] = None,
|
66
|
+
corr_method: str = "pearson",
|
51
67
|
masks: Union[str, Dict, List[Union[Dict, str]], None] = None,
|
52
68
|
name: Optional[str] = None,
|
53
69
|
) -> None:
|
@@ -57,38 +73,12 @@ class CrossParcellationFC(BaseMarker):
|
|
57
73
|
)
|
58
74
|
self.parcellation_one = parcellation_one
|
59
75
|
self.parcellation_two = parcellation_two
|
60
|
-
self.
|
61
|
-
self.
|
76
|
+
self.agg_method = agg_method
|
77
|
+
self.agg_method_params = agg_method_params
|
78
|
+
self.corr_method = corr_method
|
62
79
|
self.masks = masks
|
63
80
|
super().__init__(on=["BOLD"], name=name)
|
64
81
|
|
65
|
-
def get_valid_inputs(self) -> List[str]:
|
66
|
-
"""Get valid data types for input.
|
67
|
-
|
68
|
-
Returns
|
69
|
-
-------
|
70
|
-
list of str
|
71
|
-
The list of data types that can be used as input for this marker
|
72
|
-
|
73
|
-
"""
|
74
|
-
return ["BOLD"]
|
75
|
-
|
76
|
-
def get_output_type(self, input_type: str) -> str:
|
77
|
-
"""Get output type.
|
78
|
-
|
79
|
-
Parameters
|
80
|
-
----------
|
81
|
-
input_type : str
|
82
|
-
The data type input to the marker.
|
83
|
-
|
84
|
-
Returns
|
85
|
-
-------
|
86
|
-
str
|
87
|
-
The storage type output by the marker.
|
88
|
-
|
89
|
-
"""
|
90
|
-
return "matrix"
|
91
|
-
|
92
82
|
def compute(
|
93
83
|
self,
|
94
84
|
input: Dict[str, Any],
|
@@ -115,10 +105,14 @@ class CrossParcellationFC(BaseMarker):
|
|
115
105
|
to the user or stored in the storage by calling the store method
|
116
106
|
with this as a parameter. The dictionary has the following keys:
|
117
107
|
|
118
|
-
* ``
|
119
|
-
|
120
|
-
|
121
|
-
|
108
|
+
* ``functional_connectivity`` : dictionary with the following keys:
|
109
|
+
|
110
|
+
- ``data`` : correlation between the two parcellations as
|
111
|
+
``numpy.ndarray``
|
112
|
+
- ``col_names`` : ROI labels for first parcellation as list of
|
113
|
+
str
|
114
|
+
- ``row_names`` : ROI labels for second parcellation as list of
|
115
|
+
str
|
122
116
|
|
123
117
|
"""
|
124
118
|
logger.debug(
|
@@ -126,31 +120,40 @@ class CrossParcellationFC(BaseMarker):
|
|
126
120
|
f" {self.parcellation_one} and "
|
127
121
|
f"{self.parcellation_two} parcellations."
|
128
122
|
)
|
129
|
-
#
|
130
|
-
|
123
|
+
# Perform aggregation using two parcellations
|
124
|
+
aggregation_parcellation_one = ParcelAggregation(
|
131
125
|
parcellation=self.parcellation_one,
|
132
|
-
method=self.
|
126
|
+
method=self.agg_method,
|
127
|
+
method_params=self.agg_method_params,
|
133
128
|
masks=self.masks,
|
129
|
+
on="BOLD",
|
134
130
|
).compute(input, extra_input=extra_input)
|
135
|
-
|
131
|
+
aggregation_parcellation_two = ParcelAggregation(
|
136
132
|
parcellation=self.parcellation_two,
|
137
|
-
method=self.
|
133
|
+
method=self.agg_method,
|
134
|
+
method_params=self.agg_method_params,
|
138
135
|
masks=self.masks,
|
136
|
+
on="BOLD",
|
139
137
|
).compute(input, extra_input=extra_input)
|
140
138
|
|
141
|
-
parcellated_ts_one = parcellation_one_dict["data"]
|
142
|
-
parcellated_ts_two = parcellation_two_dict["data"]
|
143
|
-
# columns should be named after parcellation 1
|
144
|
-
# rows should be named after parcellation 2
|
145
|
-
|
146
|
-
result = _correlate_dataframes(
|
147
|
-
pd.DataFrame(parcellated_ts_one),
|
148
|
-
pd.DataFrame(parcellated_ts_two),
|
149
|
-
method=self.correlation_method,
|
150
|
-
).values
|
151
|
-
|
152
139
|
return {
|
153
|
-
"
|
154
|
-
|
155
|
-
|
140
|
+
"functional_connectivity": {
|
141
|
+
"data": _correlate_dataframes(
|
142
|
+
pd.DataFrame(
|
143
|
+
aggregation_parcellation_one["aggregation"]["data"]
|
144
|
+
),
|
145
|
+
pd.DataFrame(
|
146
|
+
aggregation_parcellation_two["aggregation"]["data"]
|
147
|
+
),
|
148
|
+
method=self.corr_method,
|
149
|
+
).values,
|
150
|
+
# Columns should be named after parcellation 1
|
151
|
+
"col_names": aggregation_parcellation_one["aggregation"][
|
152
|
+
"col_names"
|
153
|
+
],
|
154
|
+
# Rows should be named after parcellation 2
|
155
|
+
"row_names": aggregation_parcellation_two["aggregation"][
|
156
|
+
"col_names"
|
157
|
+
],
|
158
|
+
},
|
156
159
|
}
|