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.
Files changed (279) hide show
  1. junifer/__init__.py +2 -31
  2. junifer/__init__.pyi +37 -0
  3. junifer/_version.py +9 -4
  4. junifer/api/__init__.py +3 -5
  5. junifer/api/__init__.pyi +4 -0
  6. junifer/api/decorators.py +14 -19
  7. junifer/api/functions.py +165 -109
  8. junifer/api/py.typed +0 -0
  9. junifer/api/queue_context/__init__.py +2 -4
  10. junifer/api/queue_context/__init__.pyi +5 -0
  11. junifer/api/queue_context/gnu_parallel_local_adapter.py +22 -6
  12. junifer/api/queue_context/htcondor_adapter.py +23 -6
  13. junifer/api/queue_context/py.typed +0 -0
  14. junifer/api/queue_context/tests/test_gnu_parallel_local_adapter.py +3 -3
  15. junifer/api/queue_context/tests/test_htcondor_adapter.py +3 -3
  16. junifer/api/tests/test_functions.py +168 -74
  17. junifer/cli/__init__.py +24 -0
  18. junifer/cli/__init__.pyi +3 -0
  19. junifer/{api → cli}/cli.py +141 -125
  20. junifer/cli/parser.py +235 -0
  21. junifer/cli/py.typed +0 -0
  22. junifer/{api → cli}/tests/test_cli.py +8 -8
  23. junifer/{api/tests/test_api_utils.py → cli/tests/test_cli_utils.py} +5 -4
  24. junifer/{api → cli}/tests/test_parser.py +2 -2
  25. junifer/{api → cli}/utils.py +6 -16
  26. junifer/configs/juseless/__init__.py +2 -2
  27. junifer/configs/juseless/__init__.pyi +3 -0
  28. junifer/configs/juseless/datagrabbers/__init__.py +2 -12
  29. junifer/configs/juseless/datagrabbers/__init__.pyi +13 -0
  30. junifer/configs/juseless/datagrabbers/ixi_vbm.py +2 -2
  31. junifer/configs/juseless/datagrabbers/py.typed +0 -0
  32. junifer/configs/juseless/datagrabbers/tests/test_ucla.py +2 -2
  33. junifer/configs/juseless/datagrabbers/ucla.py +4 -4
  34. junifer/configs/juseless/py.typed +0 -0
  35. junifer/conftest.py +25 -0
  36. junifer/data/__init__.py +2 -42
  37. junifer/data/__init__.pyi +29 -0
  38. junifer/data/_dispatch.py +248 -0
  39. junifer/data/coordinates/__init__.py +9 -0
  40. junifer/data/coordinates/__init__.pyi +5 -0
  41. junifer/data/coordinates/_ants_coordinates_warper.py +104 -0
  42. junifer/data/coordinates/_coordinates.py +385 -0
  43. junifer/data/coordinates/_fsl_coordinates_warper.py +81 -0
  44. junifer/data/{tests → coordinates/tests}/test_coordinates.py +26 -33
  45. junifer/data/masks/__init__.py +9 -0
  46. junifer/data/masks/__init__.pyi +6 -0
  47. junifer/data/masks/_ants_mask_warper.py +177 -0
  48. junifer/data/masks/_fsl_mask_warper.py +106 -0
  49. junifer/data/masks/_masks.py +802 -0
  50. junifer/data/{tests → masks/tests}/test_masks.py +67 -63
  51. junifer/data/parcellations/__init__.py +9 -0
  52. junifer/data/parcellations/__init__.pyi +6 -0
  53. junifer/data/parcellations/_ants_parcellation_warper.py +166 -0
  54. junifer/data/parcellations/_fsl_parcellation_warper.py +89 -0
  55. junifer/data/parcellations/_parcellations.py +1388 -0
  56. junifer/data/{tests → parcellations/tests}/test_parcellations.py +165 -295
  57. junifer/data/pipeline_data_registry_base.py +76 -0
  58. junifer/data/py.typed +0 -0
  59. junifer/data/template_spaces.py +44 -79
  60. junifer/data/tests/test_data_utils.py +1 -2
  61. junifer/data/tests/test_template_spaces.py +8 -4
  62. junifer/data/utils.py +109 -4
  63. junifer/datagrabber/__init__.py +2 -26
  64. junifer/datagrabber/__init__.pyi +27 -0
  65. junifer/datagrabber/aomic/__init__.py +2 -4
  66. junifer/datagrabber/aomic/__init__.pyi +5 -0
  67. junifer/datagrabber/aomic/id1000.py +81 -52
  68. junifer/datagrabber/aomic/piop1.py +83 -55
  69. junifer/datagrabber/aomic/piop2.py +85 -56
  70. junifer/datagrabber/aomic/py.typed +0 -0
  71. junifer/datagrabber/aomic/tests/test_id1000.py +19 -12
  72. junifer/datagrabber/aomic/tests/test_piop1.py +52 -18
  73. junifer/datagrabber/aomic/tests/test_piop2.py +50 -17
  74. junifer/datagrabber/base.py +22 -18
  75. junifer/datagrabber/datalad_base.py +71 -34
  76. junifer/datagrabber/dmcc13_benchmark.py +31 -18
  77. junifer/datagrabber/hcp1200/__init__.py +2 -3
  78. junifer/datagrabber/hcp1200/__init__.pyi +4 -0
  79. junifer/datagrabber/hcp1200/datalad_hcp1200.py +3 -3
  80. junifer/datagrabber/hcp1200/hcp1200.py +26 -15
  81. junifer/datagrabber/hcp1200/py.typed +0 -0
  82. junifer/datagrabber/hcp1200/tests/test_hcp1200.py +8 -2
  83. junifer/datagrabber/multiple.py +14 -9
  84. junifer/datagrabber/pattern.py +132 -96
  85. junifer/datagrabber/pattern_validation_mixin.py +206 -94
  86. junifer/datagrabber/py.typed +0 -0
  87. junifer/datagrabber/tests/test_datalad_base.py +27 -12
  88. junifer/datagrabber/tests/test_dmcc13_benchmark.py +28 -11
  89. junifer/datagrabber/tests/test_multiple.py +48 -2
  90. junifer/datagrabber/tests/test_pattern_datalad.py +1 -1
  91. junifer/datagrabber/tests/test_pattern_validation_mixin.py +6 -6
  92. junifer/datareader/__init__.py +2 -2
  93. junifer/datareader/__init__.pyi +3 -0
  94. junifer/datareader/default.py +6 -6
  95. junifer/datareader/py.typed +0 -0
  96. junifer/external/nilearn/__init__.py +2 -3
  97. junifer/external/nilearn/__init__.pyi +4 -0
  98. junifer/external/nilearn/junifer_connectivity_measure.py +25 -17
  99. junifer/external/nilearn/junifer_nifti_spheres_masker.py +4 -4
  100. junifer/external/nilearn/py.typed +0 -0
  101. junifer/external/nilearn/tests/test_junifer_connectivity_measure.py +17 -16
  102. junifer/external/nilearn/tests/test_junifer_nifti_spheres_masker.py +2 -3
  103. junifer/markers/__init__.py +2 -38
  104. junifer/markers/__init__.pyi +37 -0
  105. junifer/markers/base.py +11 -14
  106. junifer/markers/brainprint.py +12 -14
  107. junifer/markers/complexity/__init__.py +2 -18
  108. junifer/markers/complexity/__init__.pyi +17 -0
  109. junifer/markers/complexity/complexity_base.py +9 -11
  110. junifer/markers/complexity/hurst_exponent.py +7 -7
  111. junifer/markers/complexity/multiscale_entropy_auc.py +7 -7
  112. junifer/markers/complexity/perm_entropy.py +7 -7
  113. junifer/markers/complexity/py.typed +0 -0
  114. junifer/markers/complexity/range_entropy.py +7 -7
  115. junifer/markers/complexity/range_entropy_auc.py +7 -7
  116. junifer/markers/complexity/sample_entropy.py +7 -7
  117. junifer/markers/complexity/tests/test_complexity_base.py +1 -1
  118. junifer/markers/complexity/tests/test_hurst_exponent.py +5 -5
  119. junifer/markers/complexity/tests/test_multiscale_entropy_auc.py +5 -5
  120. junifer/markers/complexity/tests/test_perm_entropy.py +5 -5
  121. junifer/markers/complexity/tests/test_range_entropy.py +5 -5
  122. junifer/markers/complexity/tests/test_range_entropy_auc.py +5 -5
  123. junifer/markers/complexity/tests/test_sample_entropy.py +5 -5
  124. junifer/markers/complexity/tests/test_weighted_perm_entropy.py +5 -5
  125. junifer/markers/complexity/weighted_perm_entropy.py +7 -7
  126. junifer/markers/ets_rss.py +12 -11
  127. junifer/markers/falff/__init__.py +2 -3
  128. junifer/markers/falff/__init__.pyi +4 -0
  129. junifer/markers/falff/_afni_falff.py +38 -45
  130. junifer/markers/falff/_junifer_falff.py +16 -19
  131. junifer/markers/falff/falff_base.py +7 -11
  132. junifer/markers/falff/falff_parcels.py +9 -9
  133. junifer/markers/falff/falff_spheres.py +8 -8
  134. junifer/markers/falff/py.typed +0 -0
  135. junifer/markers/falff/tests/test_falff_spheres.py +3 -1
  136. junifer/markers/functional_connectivity/__init__.py +2 -12
  137. junifer/markers/functional_connectivity/__init__.pyi +13 -0
  138. junifer/markers/functional_connectivity/crossparcellation_functional_connectivity.py +9 -8
  139. junifer/markers/functional_connectivity/edge_functional_connectivity_parcels.py +8 -8
  140. junifer/markers/functional_connectivity/edge_functional_connectivity_spheres.py +7 -7
  141. junifer/markers/functional_connectivity/functional_connectivity_base.py +13 -12
  142. junifer/markers/functional_connectivity/functional_connectivity_parcels.py +8 -8
  143. junifer/markers/functional_connectivity/functional_connectivity_spheres.py +7 -7
  144. junifer/markers/functional_connectivity/py.typed +0 -0
  145. junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_parcels.py +1 -2
  146. junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_spheres.py +1 -2
  147. junifer/markers/functional_connectivity/tests/test_functional_connectivity_parcels.py +6 -6
  148. junifer/markers/functional_connectivity/tests/test_functional_connectivity_spheres.py +5 -5
  149. junifer/markers/parcel_aggregation.py +22 -17
  150. junifer/markers/py.typed +0 -0
  151. junifer/markers/reho/__init__.py +2 -3
  152. junifer/markers/reho/__init__.pyi +4 -0
  153. junifer/markers/reho/_afni_reho.py +29 -35
  154. junifer/markers/reho/_junifer_reho.py +13 -14
  155. junifer/markers/reho/py.typed +0 -0
  156. junifer/markers/reho/reho_base.py +7 -11
  157. junifer/markers/reho/reho_parcels.py +10 -10
  158. junifer/markers/reho/reho_spheres.py +9 -9
  159. junifer/markers/sphere_aggregation.py +22 -17
  160. junifer/markers/temporal_snr/__init__.py +2 -3
  161. junifer/markers/temporal_snr/__init__.pyi +4 -0
  162. junifer/markers/temporal_snr/py.typed +0 -0
  163. junifer/markers/temporal_snr/temporal_snr_base.py +11 -10
  164. junifer/markers/temporal_snr/temporal_snr_parcels.py +8 -8
  165. junifer/markers/temporal_snr/temporal_snr_spheres.py +7 -7
  166. junifer/markers/tests/test_ets_rss.py +3 -3
  167. junifer/markers/tests/test_parcel_aggregation.py +24 -24
  168. junifer/markers/tests/test_sphere_aggregation.py +6 -6
  169. junifer/markers/utils.py +3 -3
  170. junifer/onthefly/__init__.py +2 -1
  171. junifer/onthefly/_brainprint.py +138 -0
  172. junifer/onthefly/read_transform.py +5 -8
  173. junifer/pipeline/__init__.py +2 -10
  174. junifer/pipeline/__init__.pyi +13 -0
  175. junifer/{markers/collection.py → pipeline/marker_collection.py} +8 -14
  176. junifer/pipeline/pipeline_component_registry.py +294 -0
  177. junifer/pipeline/pipeline_step_mixin.py +15 -11
  178. junifer/pipeline/py.typed +0 -0
  179. junifer/{markers/tests/test_collection.py → pipeline/tests/test_marker_collection.py} +2 -3
  180. junifer/pipeline/tests/test_pipeline_component_registry.py +200 -0
  181. junifer/pipeline/tests/test_pipeline_step_mixin.py +36 -37
  182. junifer/pipeline/tests/test_update_meta_mixin.py +4 -4
  183. junifer/pipeline/tests/test_workdir_manager.py +43 -0
  184. junifer/pipeline/update_meta_mixin.py +21 -17
  185. junifer/pipeline/utils.py +6 -6
  186. junifer/pipeline/workdir_manager.py +19 -5
  187. junifer/preprocess/__init__.py +2 -10
  188. junifer/preprocess/__init__.pyi +11 -0
  189. junifer/preprocess/base.py +10 -10
  190. junifer/preprocess/confounds/__init__.py +2 -2
  191. junifer/preprocess/confounds/__init__.pyi +3 -0
  192. junifer/preprocess/confounds/fmriprep_confound_remover.py +243 -64
  193. junifer/preprocess/confounds/py.typed +0 -0
  194. junifer/preprocess/confounds/tests/test_fmriprep_confound_remover.py +121 -14
  195. junifer/preprocess/py.typed +0 -0
  196. junifer/preprocess/smoothing/__init__.py +2 -2
  197. junifer/preprocess/smoothing/__init__.pyi +3 -0
  198. junifer/preprocess/smoothing/_afni_smoothing.py +40 -40
  199. junifer/preprocess/smoothing/_fsl_smoothing.py +22 -32
  200. junifer/preprocess/smoothing/_nilearn_smoothing.py +35 -14
  201. junifer/preprocess/smoothing/py.typed +0 -0
  202. junifer/preprocess/smoothing/smoothing.py +11 -13
  203. junifer/preprocess/warping/__init__.py +2 -2
  204. junifer/preprocess/warping/__init__.pyi +3 -0
  205. junifer/preprocess/warping/_ants_warper.py +136 -32
  206. junifer/preprocess/warping/_fsl_warper.py +73 -22
  207. junifer/preprocess/warping/py.typed +0 -0
  208. junifer/preprocess/warping/space_warper.py +39 -11
  209. junifer/preprocess/warping/tests/test_space_warper.py +5 -9
  210. junifer/py.typed +0 -0
  211. junifer/stats.py +5 -5
  212. junifer/storage/__init__.py +2 -10
  213. junifer/storage/__init__.pyi +11 -0
  214. junifer/storage/base.py +47 -13
  215. junifer/storage/hdf5.py +95 -33
  216. junifer/storage/pandas_base.py +12 -11
  217. junifer/storage/py.typed +0 -0
  218. junifer/storage/sqlite.py +11 -11
  219. junifer/storage/tests/test_hdf5.py +86 -4
  220. junifer/storage/tests/test_sqlite.py +2 -2
  221. junifer/storage/tests/test_storage_base.py +5 -2
  222. junifer/storage/tests/test_utils.py +33 -7
  223. junifer/storage/utils.py +95 -9
  224. junifer/testing/__init__.py +2 -3
  225. junifer/testing/__init__.pyi +4 -0
  226. junifer/testing/datagrabbers.py +10 -11
  227. junifer/testing/py.typed +0 -0
  228. junifer/testing/registry.py +4 -7
  229. junifer/testing/tests/test_testing_registry.py +9 -17
  230. junifer/tests/test_stats.py +2 -2
  231. junifer/typing/__init__.py +9 -0
  232. junifer/typing/__init__.pyi +31 -0
  233. junifer/typing/_typing.py +68 -0
  234. junifer/utils/__init__.py +2 -12
  235. junifer/utils/__init__.pyi +18 -0
  236. junifer/utils/_config.py +110 -0
  237. junifer/utils/_yaml.py +16 -0
  238. junifer/utils/helpers.py +6 -6
  239. junifer/utils/logging.py +117 -8
  240. junifer/utils/py.typed +0 -0
  241. junifer/{pipeline → utils}/singleton.py +19 -14
  242. junifer/utils/tests/test_config.py +59 -0
  243. {junifer-0.0.5.dev242.dist-info → junifer-0.0.6.dist-info}/METADATA +43 -38
  244. junifer-0.0.6.dist-info/RECORD +350 -0
  245. {junifer-0.0.5.dev242.dist-info → junifer-0.0.6.dist-info}/WHEEL +1 -1
  246. junifer-0.0.6.dist-info/entry_points.txt +2 -0
  247. junifer/api/parser.py +0 -118
  248. junifer/data/coordinates.py +0 -408
  249. junifer/data/masks.py +0 -670
  250. junifer/data/parcellations.py +0 -1828
  251. junifer/pipeline/registry.py +0 -177
  252. junifer/pipeline/tests/test_registry.py +0 -150
  253. junifer-0.0.5.dev242.dist-info/RECORD +0 -275
  254. junifer-0.0.5.dev242.dist-info/entry_points.txt +0 -2
  255. /junifer/{api → cli}/tests/data/gmd_mean.yaml +0 -0
  256. /junifer/{api → cli}/tests/data/gmd_mean_htcondor.yaml +0 -0
  257. /junifer/{api → cli}/tests/data/partly_cloudy_agg_mean_tian.yml +0 -0
  258. /junifer/data/{VOIs → coordinates/VOIs}/meta/AutobiographicalMemory_VOIs.txt +0 -0
  259. /junifer/data/{VOIs → coordinates/VOIs}/meta/CogAC_VOIs.txt +0 -0
  260. /junifer/data/{VOIs → coordinates/VOIs}/meta/CogAR_VOIs.txt +0 -0
  261. /junifer/data/{VOIs → coordinates/VOIs}/meta/DMNBuckner_VOIs.txt +0 -0
  262. /junifer/data/{VOIs → coordinates/VOIs}/meta/Dosenbach2010_MNI_VOIs.txt +0 -0
  263. /junifer/data/{VOIs → coordinates/VOIs}/meta/Empathy_VOIs.txt +0 -0
  264. /junifer/data/{VOIs → coordinates/VOIs}/meta/Motor_VOIs.txt +0 -0
  265. /junifer/data/{VOIs → coordinates/VOIs}/meta/MultiTask_VOIs.txt +0 -0
  266. /junifer/data/{VOIs → coordinates/VOIs}/meta/PhysioStress_VOIs.txt +0 -0
  267. /junifer/data/{VOIs → coordinates/VOIs}/meta/Power2011_MNI_VOIs.txt +0 -0
  268. /junifer/data/{VOIs → coordinates/VOIs}/meta/Power2013_MNI_VOIs.tsv +0 -0
  269. /junifer/data/{VOIs → coordinates/VOIs}/meta/Rew_VOIs.txt +0 -0
  270. /junifer/data/{VOIs → coordinates/VOIs}/meta/Somatosensory_VOIs.txt +0 -0
  271. /junifer/data/{VOIs → coordinates/VOIs}/meta/ToM_VOIs.txt +0 -0
  272. /junifer/data/{VOIs → coordinates/VOIs}/meta/VigAtt_VOIs.txt +0 -0
  273. /junifer/data/{VOIs → coordinates/VOIs}/meta/WM_VOIs.txt +0 -0
  274. /junifer/data/{VOIs → coordinates/VOIs}/meta/eMDN_VOIs.txt +0 -0
  275. /junifer/data/{VOIs → coordinates/VOIs}/meta/eSAD_VOIs.txt +0 -0
  276. /junifer/data/{VOIs → coordinates/VOIs}/meta/extDMN_VOIs.txt +0 -0
  277. {junifer-0.0.5.dev242.dist-info → junifer-0.0.6.dist-info/licenses}/AUTHORS.rst +0 -0
  278. {junifer-0.0.5.dev242.dist-info → junifer-0.0.6.dist-info/licenses}/LICENSE.md +0 -0
  279. {junifer-0.0.5.dev242.dist-info → junifer-0.0.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,4 @@
1
+ __all__ = ["ALFFParcels", "ALFFSpheres"]
2
+
3
+ from .falff_parcels import ALFFParcels
4
+ from .falff_spheres import ALFFSpheres
@@ -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 ...pipeline.singleton import singleton
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
- @singleton
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[List[Dict[str, Union[str, List[str]]]]] = [
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
- data: "Nifti1Image",
53
+ input_path: Path,
58
54
  highpass: float,
59
55
  lowpass: float,
60
56
  tr: Optional[float],
61
- ) -> Tuple["Nifti1Image", "Nifti1Image", Path, Path]:
57
+ ) -> tuple["Nifti1Image", "Nifti1Image", Path, Path]:
62
58
  """Compute ALFF + fALFF map.
63
59
 
64
60
  Parameters
65
61
  ----------
66
- data : 4D Niimg-like object
67
- Images to process.
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 component-scoped tempdir
90
- tempdir = WorkDirManager().get_tempdir(prefix="afni_alff+falff")
91
-
92
- # Save target data to a component-scoped tempfile
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
- alff_falff_out_path_prefix = tempdir / "alff_falff"
91
+ lff_out_path_prefix = element_tempdir / "output"
98
92
  bp_cmd = [
99
93
  "3dRSFC",
100
- f"-prefix {alff_falff_out_path_prefix.resolve()}",
101
- f"-input {nifti_in_file_path.resolve()}",
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
- # Create element-scoped tempdir so that the ALFF and fALFF maps are
112
- # available later as nibabel stores file path reference for
113
- # loading on computation
114
- element_tempdir = WorkDirManager().get_element_tempdir(
115
- prefix="afni_alff_falff"
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
- alff_afni_to_nifti_out_path = (
122
- element_tempdir / f"alff{params_suffix}_output.nii"
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 {alff_afni_to_nifti_out_path.resolve()}",
127
- f"{alff_falff_out_path_prefix}_ALFF+orig.BRIK",
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
- falff_afni_to_nifti_out_path = (
134
- element_tempdir / f"falff{params_suffix}_output.nii"
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 {falff_afni_to_nifti_out_path.resolve()}",
139
- f"{alff_falff_out_path_prefix}_fALFF+orig.BRIK",
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(alff_afni_to_nifti_out_path)
146
- falff_data = nib.load(falff_afni_to_nifti_out_path)
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
- alff_afni_to_nifti_out_path,
155
- falff_afni_to_nifti_out_path,
156
- ) # type: ignore
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 ...pipeline.singleton import singleton
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
- @singleton
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[Set[str]] = {"numpy", "nilearn", "scipy"}
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
- data: "Nifti1Image",
50
+ input_path: Path,
53
51
  highpass: float,
54
52
  lowpass: float,
55
53
  tr: Optional[float],
56
- ) -> Tuple["Nifti1Image", "Nifti1Image", Path, Path]:
54
+ ) -> tuple["Nifti1Image", "Nifti1Image", Path, Path]:
57
55
  """Compute ALFF + fALFF map.
58
56
 
59
57
  Parameters
60
58
  ----------
61
- data : 4D Niimg-like object
62
- Images to process.
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
- niimg_data = data.get_fdata().copy()
83
+ niimg = nib.load(input_path)
84
+ niimg_data = niimg.get_fdata().copy()
86
85
  if tr is None:
87
- tr = float(data.header["pixdim"][4]) # type: ignore
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=data,
124
+ ref_niimg=niimg,
126
125
  data=alff,
127
126
  )
128
127
  falff_data = nimg.new_img_like(
129
- ref_niimg=data,
128
+ ref_niimg=niimg,
130
129
  data=falff,
131
130
  )
132
131
 
133
- # Create element-scoped tempdir so that the ALFF and fALFF maps are
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="junifer_alff+falff"
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[List[Dict[str, Union[str, Type]]]] = [
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[Dict[str, Dict[str, str]]] = {
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: Dict[str, Any],
122
- ) -> Tuple["Nifti1Image", "Nifti1Image", Path, Path]:
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
- data=input_data["data"],
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, Dict, List, Optional, Union
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). Check valid options by calling
28
- :func:`.list_parcellations`.
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, List[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[Dict] = None,
80
- masks: Union[str, Dict, List[Union[Dict, str]], None] = None,
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: Dict[str, Any],
99
- extra_input: Optional[Dict[str, Any]] = None,
100
- ) -> Dict[str, Any]:
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, Dict, List, Optional, Union
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. See
28
- :func:`.list_coordinates` for options.
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[Dict] = None,
89
- masks: Union[str, Dict, List[Union[Dict, str]], None] = None,
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: Dict[str, Any],
110
- extra_input: Optional[Dict[str, Any]] = None,
111
- ) -> Dict[str, Any]:
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
- assert "Creating cache" in caplog.text
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
- from .functional_connectivity_parcels import FunctionalConnectivityParcels
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, Dict, List, Optional, Set, Union
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[Set[str]] = {"nilearn"}
53
+ _DEPENDENCIES: ClassVar[Dependencies] = {"nilearn"}
53
54
 
54
- _MARKER_INOUT_MAPPINGS: ClassVar[Dict[str, Dict[str, str]]] = {
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[Dict] = None,
66
+ agg_method_params: Optional[dict] = None,
66
67
  corr_method: str = "pearson",
67
- masks: Union[str, Dict, List[Union[Dict, str]], None] = None,
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: Dict[str, Any],
85
- extra_input: Optional[Dict] = None,
86
- ) -> Dict:
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, Dict, List, Optional, Union
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:`.list_parcellations` for options.
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, List[str]],
64
+ parcellation: Union[str, list[str]],
65
65
  agg_method: str = "mean",
66
- agg_method_params: Optional[Dict] = None,
66
+ agg_method_params: Optional[dict] = None,
67
67
  conn_method: str = "correlation",
68
- conn_method_params: Optional[Dict] = None,
69
- masks: Union[str, Dict, List[Union[Dict, str]], None] = None,
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: Dict[str, Any], extra_input: Optional[Dict] = None
84
- ) -> Dict:
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, Dict, List, Optional, Union
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:`.list_coordinates` for options.
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[Dict] = None,
76
+ agg_method_params: Optional[dict] = None,
77
77
  conn_method: str = "correlation",
78
- conn_method_params: Optional[Dict] = None,
79
- masks: Union[str, Dict, List[Union[Dict, str]], None] = None,
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: Dict[str, Any], extra_input: Optional[Dict] = None
98
- ) -> Dict:
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