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.
Files changed (206) hide show
  1. junifer/__init__.py +17 -0
  2. junifer/_version.py +2 -2
  3. junifer/api/__init__.py +4 -1
  4. junifer/api/cli.py +91 -1
  5. junifer/api/decorators.py +9 -0
  6. junifer/api/functions.py +56 -10
  7. junifer/api/parser.py +3 -0
  8. junifer/api/queue_context/__init__.py +4 -1
  9. junifer/api/queue_context/gnu_parallel_local_adapter.py +16 -6
  10. junifer/api/queue_context/htcondor_adapter.py +16 -5
  11. junifer/api/queue_context/tests/test_gnu_parallel_local_adapter.py +41 -12
  12. junifer/api/queue_context/tests/test_htcondor_adapter.py +48 -15
  13. junifer/api/res/afni/run_afni_docker.sh +1 -1
  14. junifer/api/res/ants/run_ants_docker.sh +1 -1
  15. junifer/api/res/freesurfer/mri_binarize +3 -0
  16. junifer/api/res/freesurfer/mri_mc +3 -0
  17. junifer/api/res/freesurfer/mri_pretess +3 -0
  18. junifer/api/res/freesurfer/mris_convert +3 -0
  19. junifer/api/res/freesurfer/run_freesurfer_docker.sh +61 -0
  20. junifer/api/res/fsl/run_fsl_docker.sh +1 -1
  21. junifer/api/res/{run_conda.sh → run_conda.bash} +1 -1
  22. junifer/api/res/run_conda.zsh +23 -0
  23. junifer/api/res/run_venv.bash +22 -0
  24. junifer/api/res/{run_venv.sh → run_venv.zsh} +1 -1
  25. junifer/api/tests/test_api_utils.py +4 -2
  26. junifer/api/tests/test_cli.py +83 -0
  27. junifer/api/tests/test_functions.py +27 -2
  28. junifer/configs/__init__.py +1 -1
  29. junifer/configs/juseless/__init__.py +4 -1
  30. junifer/configs/juseless/datagrabbers/__init__.py +10 -1
  31. junifer/configs/juseless/datagrabbers/aomic_id1000_vbm.py +4 -3
  32. junifer/configs/juseless/datagrabbers/camcan_vbm.py +3 -0
  33. junifer/configs/juseless/datagrabbers/ixi_vbm.py +4 -3
  34. junifer/configs/juseless/datagrabbers/tests/test_ucla.py +1 -3
  35. junifer/configs/juseless/datagrabbers/ucla.py +12 -9
  36. junifer/configs/juseless/datagrabbers/ukb_vbm.py +3 -0
  37. junifer/data/__init__.py +21 -1
  38. junifer/data/coordinates.py +10 -19
  39. junifer/data/masks/ukb/UKB_15K_GM_template.nii.gz +0 -0
  40. junifer/data/masks.py +58 -87
  41. junifer/data/parcellations.py +14 -3
  42. junifer/data/template_spaces.py +4 -1
  43. junifer/data/tests/test_masks.py +26 -37
  44. junifer/data/utils.py +3 -0
  45. junifer/datagrabber/__init__.py +18 -1
  46. junifer/datagrabber/aomic/__init__.py +3 -0
  47. junifer/datagrabber/aomic/id1000.py +70 -37
  48. junifer/datagrabber/aomic/piop1.py +69 -36
  49. junifer/datagrabber/aomic/piop2.py +71 -38
  50. junifer/datagrabber/aomic/tests/test_id1000.py +44 -100
  51. junifer/datagrabber/aomic/tests/test_piop1.py +65 -108
  52. junifer/datagrabber/aomic/tests/test_piop2.py +45 -102
  53. junifer/datagrabber/base.py +13 -6
  54. junifer/datagrabber/datalad_base.py +13 -1
  55. junifer/datagrabber/dmcc13_benchmark.py +36 -53
  56. junifer/datagrabber/hcp1200/__init__.py +3 -0
  57. junifer/datagrabber/hcp1200/datalad_hcp1200.py +3 -0
  58. junifer/datagrabber/hcp1200/hcp1200.py +4 -1
  59. junifer/datagrabber/multiple.py +45 -6
  60. junifer/datagrabber/pattern.py +170 -62
  61. junifer/datagrabber/pattern_datalad.py +25 -12
  62. junifer/datagrabber/pattern_validation_mixin.py +388 -0
  63. junifer/datagrabber/tests/test_datalad_base.py +4 -4
  64. junifer/datagrabber/tests/test_dmcc13_benchmark.py +46 -19
  65. junifer/datagrabber/tests/test_multiple.py +161 -84
  66. junifer/datagrabber/tests/test_pattern.py +45 -0
  67. junifer/datagrabber/tests/test_pattern_datalad.py +4 -4
  68. junifer/datagrabber/tests/test_pattern_validation_mixin.py +249 -0
  69. junifer/datareader/__init__.py +4 -1
  70. junifer/datareader/default.py +95 -43
  71. junifer/external/BrainPrint/brainprint/__init__.py +4 -0
  72. junifer/external/BrainPrint/brainprint/_version.py +3 -0
  73. junifer/external/BrainPrint/brainprint/asymmetry.py +91 -0
  74. junifer/external/BrainPrint/brainprint/brainprint.py +441 -0
  75. junifer/external/BrainPrint/brainprint/surfaces.py +258 -0
  76. junifer/external/BrainPrint/brainprint/utils/__init__.py +1 -0
  77. junifer/external/BrainPrint/brainprint/utils/_config.py +112 -0
  78. junifer/external/BrainPrint/brainprint/utils/utils.py +188 -0
  79. junifer/external/__init__.py +1 -1
  80. junifer/external/nilearn/__init__.py +5 -1
  81. junifer/external/nilearn/junifer_connectivity_measure.py +483 -0
  82. junifer/external/nilearn/junifer_nifti_spheres_masker.py +23 -9
  83. junifer/external/nilearn/tests/test_junifer_connectivity_measure.py +1089 -0
  84. junifer/external/nilearn/tests/test_junifer_nifti_spheres_masker.py +76 -1
  85. junifer/markers/__init__.py +23 -1
  86. junifer/markers/base.py +68 -28
  87. junifer/markers/brainprint.py +459 -0
  88. junifer/markers/collection.py +10 -2
  89. junifer/markers/complexity/__init__.py +10 -0
  90. junifer/markers/complexity/complexity_base.py +26 -43
  91. junifer/markers/complexity/hurst_exponent.py +3 -0
  92. junifer/markers/complexity/multiscale_entropy_auc.py +3 -0
  93. junifer/markers/complexity/perm_entropy.py +3 -0
  94. junifer/markers/complexity/range_entropy.py +3 -0
  95. junifer/markers/complexity/range_entropy_auc.py +3 -0
  96. junifer/markers/complexity/sample_entropy.py +3 -0
  97. junifer/markers/complexity/tests/test_hurst_exponent.py +11 -3
  98. junifer/markers/complexity/tests/test_multiscale_entropy_auc.py +11 -3
  99. junifer/markers/complexity/tests/test_perm_entropy.py +11 -3
  100. junifer/markers/complexity/tests/test_range_entropy.py +11 -3
  101. junifer/markers/complexity/tests/test_range_entropy_auc.py +11 -3
  102. junifer/markers/complexity/tests/test_sample_entropy.py +11 -3
  103. junifer/markers/complexity/tests/test_weighted_perm_entropy.py +11 -3
  104. junifer/markers/complexity/weighted_perm_entropy.py +3 -0
  105. junifer/markers/ets_rss.py +27 -42
  106. junifer/markers/falff/__init__.py +3 -0
  107. junifer/markers/falff/_afni_falff.py +5 -2
  108. junifer/markers/falff/_junifer_falff.py +3 -0
  109. junifer/markers/falff/falff_base.py +20 -46
  110. junifer/markers/falff/falff_parcels.py +56 -27
  111. junifer/markers/falff/falff_spheres.py +60 -29
  112. junifer/markers/falff/tests/test_falff_parcels.py +39 -23
  113. junifer/markers/falff/tests/test_falff_spheres.py +39 -23
  114. junifer/markers/functional_connectivity/__init__.py +9 -0
  115. junifer/markers/functional_connectivity/crossparcellation_functional_connectivity.py +63 -60
  116. junifer/markers/functional_connectivity/edge_functional_connectivity_parcels.py +45 -32
  117. junifer/markers/functional_connectivity/edge_functional_connectivity_spheres.py +49 -36
  118. junifer/markers/functional_connectivity/functional_connectivity_base.py +71 -70
  119. junifer/markers/functional_connectivity/functional_connectivity_parcels.py +34 -25
  120. junifer/markers/functional_connectivity/functional_connectivity_spheres.py +40 -30
  121. junifer/markers/functional_connectivity/tests/test_crossparcellation_functional_connectivity.py +11 -7
  122. junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_parcels.py +27 -7
  123. junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_spheres.py +28 -12
  124. junifer/markers/functional_connectivity/tests/test_functional_connectivity_parcels.py +35 -11
  125. junifer/markers/functional_connectivity/tests/test_functional_connectivity_spheres.py +36 -62
  126. junifer/markers/parcel_aggregation.py +47 -61
  127. junifer/markers/reho/__init__.py +3 -0
  128. junifer/markers/reho/_afni_reho.py +5 -2
  129. junifer/markers/reho/_junifer_reho.py +4 -1
  130. junifer/markers/reho/reho_base.py +8 -27
  131. junifer/markers/reho/reho_parcels.py +28 -17
  132. junifer/markers/reho/reho_spheres.py +27 -18
  133. junifer/markers/reho/tests/test_reho_parcels.py +8 -3
  134. junifer/markers/reho/tests/test_reho_spheres.py +8 -3
  135. junifer/markers/sphere_aggregation.py +43 -59
  136. junifer/markers/temporal_snr/__init__.py +3 -0
  137. junifer/markers/temporal_snr/temporal_snr_base.py +23 -32
  138. junifer/markers/temporal_snr/temporal_snr_parcels.py +9 -6
  139. junifer/markers/temporal_snr/temporal_snr_spheres.py +9 -6
  140. junifer/markers/temporal_snr/tests/test_temporal_snr_parcels.py +6 -3
  141. junifer/markers/temporal_snr/tests/test_temporal_snr_spheres.py +6 -3
  142. junifer/markers/tests/test_brainprint.py +58 -0
  143. junifer/markers/tests/test_collection.py +9 -8
  144. junifer/markers/tests/test_ets_rss.py +15 -9
  145. junifer/markers/tests/test_markers_base.py +17 -18
  146. junifer/markers/tests/test_parcel_aggregation.py +93 -32
  147. junifer/markers/tests/test_sphere_aggregation.py +72 -19
  148. junifer/onthefly/__init__.py +4 -1
  149. junifer/onthefly/read_transform.py +3 -0
  150. junifer/pipeline/__init__.py +9 -1
  151. junifer/pipeline/pipeline_step_mixin.py +21 -4
  152. junifer/pipeline/registry.py +3 -0
  153. junifer/pipeline/singleton.py +3 -0
  154. junifer/pipeline/tests/test_registry.py +1 -1
  155. junifer/pipeline/update_meta_mixin.py +3 -0
  156. junifer/pipeline/utils.py +67 -1
  157. junifer/pipeline/workdir_manager.py +3 -0
  158. junifer/preprocess/__init__.py +10 -2
  159. junifer/preprocess/base.py +6 -3
  160. junifer/preprocess/confounds/__init__.py +3 -0
  161. junifer/preprocess/confounds/fmriprep_confound_remover.py +47 -60
  162. junifer/preprocess/confounds/tests/test_fmriprep_confound_remover.py +72 -113
  163. junifer/preprocess/smoothing/__init__.py +9 -0
  164. junifer/preprocess/smoothing/_afni_smoothing.py +119 -0
  165. junifer/preprocess/smoothing/_fsl_smoothing.py +116 -0
  166. junifer/preprocess/smoothing/_nilearn_smoothing.py +69 -0
  167. junifer/preprocess/smoothing/smoothing.py +174 -0
  168. junifer/preprocess/smoothing/tests/test_smoothing.py +94 -0
  169. junifer/preprocess/warping/__init__.py +3 -0
  170. junifer/preprocess/warping/_ants_warper.py +3 -0
  171. junifer/preprocess/warping/_fsl_warper.py +3 -0
  172. junifer/stats.py +4 -1
  173. junifer/storage/__init__.py +9 -1
  174. junifer/storage/base.py +40 -1
  175. junifer/storage/hdf5.py +71 -9
  176. junifer/storage/pandas_base.py +3 -0
  177. junifer/storage/sqlite.py +3 -0
  178. junifer/storage/tests/test_hdf5.py +82 -10
  179. junifer/storage/utils.py +9 -0
  180. junifer/testing/__init__.py +4 -1
  181. junifer/testing/datagrabbers.py +13 -6
  182. junifer/testing/tests/test_partlycloudytesting_datagrabber.py +7 -7
  183. junifer/testing/utils.py +3 -0
  184. junifer/utils/__init__.py +13 -2
  185. junifer/utils/fs.py +3 -0
  186. junifer/utils/helpers.py +32 -1
  187. junifer/utils/logging.py +33 -4
  188. junifer/utils/tests/test_logging.py +8 -0
  189. {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/METADATA +17 -16
  190. junifer-0.0.5.dist-info/RECORD +275 -0
  191. {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/WHEEL +1 -1
  192. junifer/datagrabber/tests/test_datagrabber_utils.py +0 -218
  193. junifer/datagrabber/utils.py +0 -230
  194. junifer/preprocess/ants/__init__.py +0 -4
  195. junifer/preprocess/ants/ants_apply_transforms_warper.py +0 -185
  196. junifer/preprocess/ants/tests/test_ants_apply_transforms_warper.py +0 -56
  197. junifer/preprocess/bold_warper.py +0 -265
  198. junifer/preprocess/fsl/__init__.py +0 -4
  199. junifer/preprocess/fsl/apply_warper.py +0 -179
  200. junifer/preprocess/fsl/tests/test_apply_warper.py +0 -45
  201. junifer/preprocess/tests/test_bold_warper.py +0 -159
  202. junifer-0.0.4.dev829.dist-info/RECORD +0 -257
  203. {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/AUTHORS.rst +0 -0
  204. {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/LICENSE.md +0 -0
  205. {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/entry_points.txt +0 -0
  206. {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. The dictionary has the following
115
- keys:
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
- * ``data`` : the actual computed values as a numpy.ndarray
118
- * ``col_names`` : the column labels for the computed values as list
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 / fALFF
124
- output_data, output_file_path = self._compute(input_data=input)
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
- return output
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. The dictionary has the following
126
- keys:
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
- * ``data`` : the actual computed values as a numpy.ndarray
129
- * ``col_names`` : the column labels for the computed values as list
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 / fALFF
135
- output_data, output_file_path = self._compute(input_data=input)
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
- return output
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
- output_bold = output["BOLD"]
55
- # Assert BOLD output keys
56
- assert "data" in output_bold
57
- assert "col_names" in output_bold
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
- output_bold_data = output_bold["data"]
60
- # Assert BOLD output data dimension
61
- assert output_bold_data.ndim == 2
62
- assert output_bold_data.shape == (1, 16)
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
- @pytest.mark.parametrize(
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
- # Check for Pearson correlation coefficient
122
- r, _ = sp.stats.pearsonr(
123
- junifer_output_bold["data"][0],
124
- afni_output_bold["data"][0],
125
- )
126
- assert r > 0.97
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
- output_bold = output["BOLD"]
56
- # Assert BOLD output keys
57
- assert "data" in output_bold
58
- assert "col_names" in output_bold
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
- output_bold_data = output_bold["data"]
61
- # Assert BOLD output data dimension
62
- assert output_bold_data.ndim == 2
63
- assert output_bold_data.shape == (1, 6)
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
- @pytest.mark.parametrize(
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
- # Check for Pearson correlation coefficient
125
- r, _ = sp.stats.pearsonr(
126
- junifer_output_bold["data"][0],
127
- afni_output_bold["data"][0],
128
- )
129
- assert r > 0.99
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
- aggregation_method : str, optional
29
- The aggregation method (default "mean").
30
- correlation_method : str, optional
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
- :any:`pandas.DataFrame.corr` (default "pearson").
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 the class name
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
- aggregation_method: str = "mean",
50
- correlation_method: str = "pearson",
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.aggregation_method = aggregation_method
61
- self.correlation_method = correlation_method
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
- * ``data`` : the correlation values between the two parcellations
119
- as a numpy.ndarray
120
- * ``col_names`` : the ROIs for first parcellation as a list
121
- * ``row_names`` : the ROIs for second parcellation as a list
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
- # Initialize a ParcelAggregation
130
- parcellation_one_dict = ParcelAggregation(
123
+ # Perform aggregation using two parcellations
124
+ aggregation_parcellation_one = ParcelAggregation(
131
125
  parcellation=self.parcellation_one,
132
- method=self.aggregation_method,
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
- parcellation_two_dict = ParcelAggregation(
131
+ aggregation_parcellation_two = ParcelAggregation(
136
132
  parcellation=self.parcellation_two,
137
- method=self.aggregation_method,
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
- "data": result,
154
- "col_names": parcellation_one_dict["col_names"],
155
- "row_names": parcellation_two_dict["col_names"],
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
  }