junifer 0.0.3.dev186__py3-none-any.whl → 0.0.4__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 (178) hide show
  1. junifer/_version.py +14 -2
  2. junifer/api/cli.py +162 -17
  3. junifer/api/functions.py +87 -419
  4. junifer/api/parser.py +24 -0
  5. junifer/api/queue_context/__init__.py +8 -0
  6. junifer/api/queue_context/gnu_parallel_local_adapter.py +258 -0
  7. junifer/api/queue_context/htcondor_adapter.py +365 -0
  8. junifer/api/queue_context/queue_context_adapter.py +60 -0
  9. junifer/api/queue_context/tests/test_gnu_parallel_local_adapter.py +192 -0
  10. junifer/api/queue_context/tests/test_htcondor_adapter.py +257 -0
  11. junifer/api/res/afni/run_afni_docker.sh +6 -6
  12. junifer/api/res/ants/ResampleImage +3 -0
  13. junifer/api/res/ants/antsApplyTransforms +3 -0
  14. junifer/api/res/ants/antsApplyTransformsToPoints +3 -0
  15. junifer/api/res/ants/run_ants_docker.sh +39 -0
  16. junifer/api/res/fsl/applywarp +3 -0
  17. junifer/api/res/fsl/flirt +3 -0
  18. junifer/api/res/fsl/img2imgcoord +3 -0
  19. junifer/api/res/fsl/run_fsl_docker.sh +39 -0
  20. junifer/api/res/fsl/std2imgcoord +3 -0
  21. junifer/api/res/run_conda.sh +4 -4
  22. junifer/api/res/run_venv.sh +22 -0
  23. junifer/api/tests/data/partly_cloudy_agg_mean_tian.yml +16 -0
  24. junifer/api/tests/test_api_utils.py +21 -3
  25. junifer/api/tests/test_cli.py +232 -9
  26. junifer/api/tests/test_functions.py +211 -439
  27. junifer/api/tests/test_parser.py +1 -1
  28. junifer/configs/juseless/datagrabbers/aomic_id1000_vbm.py +6 -1
  29. junifer/configs/juseless/datagrabbers/camcan_vbm.py +6 -1
  30. junifer/configs/juseless/datagrabbers/ixi_vbm.py +6 -1
  31. junifer/configs/juseless/datagrabbers/tests/test_ucla.py +8 -8
  32. junifer/configs/juseless/datagrabbers/ucla.py +44 -26
  33. junifer/configs/juseless/datagrabbers/ukb_vbm.py +6 -1
  34. junifer/data/VOIs/meta/AutobiographicalMemory_VOIs.txt +23 -0
  35. junifer/data/VOIs/meta/Power2013_MNI_VOIs.tsv +264 -0
  36. junifer/data/__init__.py +4 -0
  37. junifer/data/coordinates.py +298 -31
  38. junifer/data/masks.py +360 -28
  39. junifer/data/parcellations.py +621 -188
  40. junifer/data/template_spaces.py +190 -0
  41. junifer/data/tests/test_coordinates.py +34 -3
  42. junifer/data/tests/test_data_utils.py +1 -0
  43. junifer/data/tests/test_masks.py +202 -86
  44. junifer/data/tests/test_parcellations.py +266 -55
  45. junifer/data/tests/test_template_spaces.py +104 -0
  46. junifer/data/utils.py +4 -2
  47. junifer/datagrabber/__init__.py +1 -0
  48. junifer/datagrabber/aomic/id1000.py +111 -70
  49. junifer/datagrabber/aomic/piop1.py +116 -53
  50. junifer/datagrabber/aomic/piop2.py +116 -53
  51. junifer/datagrabber/aomic/tests/test_id1000.py +27 -27
  52. junifer/datagrabber/aomic/tests/test_piop1.py +27 -27
  53. junifer/datagrabber/aomic/tests/test_piop2.py +27 -27
  54. junifer/datagrabber/base.py +62 -10
  55. junifer/datagrabber/datalad_base.py +0 -2
  56. junifer/datagrabber/dmcc13_benchmark.py +372 -0
  57. junifer/datagrabber/hcp1200/datalad_hcp1200.py +5 -0
  58. junifer/datagrabber/hcp1200/hcp1200.py +30 -13
  59. junifer/datagrabber/pattern.py +133 -27
  60. junifer/datagrabber/pattern_datalad.py +111 -13
  61. junifer/datagrabber/tests/test_base.py +57 -6
  62. junifer/datagrabber/tests/test_datagrabber_utils.py +204 -76
  63. junifer/datagrabber/tests/test_datalad_base.py +0 -6
  64. junifer/datagrabber/tests/test_dmcc13_benchmark.py +256 -0
  65. junifer/datagrabber/tests/test_multiple.py +43 -10
  66. junifer/datagrabber/tests/test_pattern.py +125 -178
  67. junifer/datagrabber/tests/test_pattern_datalad.py +44 -25
  68. junifer/datagrabber/utils.py +151 -16
  69. junifer/datareader/default.py +36 -10
  70. junifer/external/nilearn/junifer_nifti_spheres_masker.py +6 -0
  71. junifer/markers/base.py +25 -16
  72. junifer/markers/collection.py +35 -16
  73. junifer/markers/complexity/__init__.py +27 -0
  74. junifer/markers/complexity/complexity_base.py +149 -0
  75. junifer/markers/complexity/hurst_exponent.py +136 -0
  76. junifer/markers/complexity/multiscale_entropy_auc.py +140 -0
  77. junifer/markers/complexity/perm_entropy.py +132 -0
  78. junifer/markers/complexity/range_entropy.py +136 -0
  79. junifer/markers/complexity/range_entropy_auc.py +145 -0
  80. junifer/markers/complexity/sample_entropy.py +134 -0
  81. junifer/markers/complexity/tests/test_complexity_base.py +19 -0
  82. junifer/markers/complexity/tests/test_hurst_exponent.py +69 -0
  83. junifer/markers/complexity/tests/test_multiscale_entropy_auc.py +68 -0
  84. junifer/markers/complexity/tests/test_perm_entropy.py +68 -0
  85. junifer/markers/complexity/tests/test_range_entropy.py +69 -0
  86. junifer/markers/complexity/tests/test_range_entropy_auc.py +69 -0
  87. junifer/markers/complexity/tests/test_sample_entropy.py +68 -0
  88. junifer/markers/complexity/tests/test_weighted_perm_entropy.py +68 -0
  89. junifer/markers/complexity/weighted_perm_entropy.py +133 -0
  90. junifer/markers/falff/_afni_falff.py +153 -0
  91. junifer/markers/falff/_junifer_falff.py +142 -0
  92. junifer/markers/falff/falff_base.py +91 -84
  93. junifer/markers/falff/falff_parcels.py +61 -45
  94. junifer/markers/falff/falff_spheres.py +64 -48
  95. junifer/markers/falff/tests/test_falff_parcels.py +89 -121
  96. junifer/markers/falff/tests/test_falff_spheres.py +92 -127
  97. junifer/markers/functional_connectivity/crossparcellation_functional_connectivity.py +1 -0
  98. junifer/markers/functional_connectivity/edge_functional_connectivity_parcels.py +1 -0
  99. junifer/markers/functional_connectivity/functional_connectivity_base.py +1 -0
  100. junifer/markers/functional_connectivity/tests/test_crossparcellation_functional_connectivity.py +46 -44
  101. junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_parcels.py +34 -39
  102. junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_spheres.py +40 -52
  103. junifer/markers/functional_connectivity/tests/test_functional_connectivity_parcels.py +62 -70
  104. junifer/markers/functional_connectivity/tests/test_functional_connectivity_spheres.py +99 -85
  105. junifer/markers/parcel_aggregation.py +60 -38
  106. junifer/markers/reho/_afni_reho.py +192 -0
  107. junifer/markers/reho/_junifer_reho.py +281 -0
  108. junifer/markers/reho/reho_base.py +69 -34
  109. junifer/markers/reho/reho_parcels.py +26 -16
  110. junifer/markers/reho/reho_spheres.py +23 -9
  111. junifer/markers/reho/tests/test_reho_parcels.py +93 -92
  112. junifer/markers/reho/tests/test_reho_spheres.py +88 -86
  113. junifer/markers/sphere_aggregation.py +54 -9
  114. junifer/markers/temporal_snr/temporal_snr_base.py +1 -0
  115. junifer/markers/temporal_snr/tests/test_temporal_snr_parcels.py +38 -37
  116. junifer/markers/temporal_snr/tests/test_temporal_snr_spheres.py +34 -38
  117. junifer/markers/tests/test_collection.py +43 -42
  118. junifer/markers/tests/test_ets_rss.py +29 -37
  119. junifer/markers/tests/test_parcel_aggregation.py +587 -468
  120. junifer/markers/tests/test_sphere_aggregation.py +209 -157
  121. junifer/markers/utils.py +2 -40
  122. junifer/onthefly/read_transform.py +13 -6
  123. junifer/pipeline/__init__.py +1 -0
  124. junifer/pipeline/pipeline_step_mixin.py +105 -41
  125. junifer/pipeline/registry.py +17 -0
  126. junifer/pipeline/singleton.py +45 -0
  127. junifer/pipeline/tests/test_pipeline_step_mixin.py +139 -51
  128. junifer/pipeline/tests/test_update_meta_mixin.py +1 -0
  129. junifer/pipeline/tests/test_workdir_manager.py +104 -0
  130. junifer/pipeline/update_meta_mixin.py +8 -2
  131. junifer/pipeline/utils.py +154 -15
  132. junifer/pipeline/workdir_manager.py +246 -0
  133. junifer/preprocess/__init__.py +3 -0
  134. junifer/preprocess/ants/__init__.py +4 -0
  135. junifer/preprocess/ants/ants_apply_transforms_warper.py +185 -0
  136. junifer/preprocess/ants/tests/test_ants_apply_transforms_warper.py +56 -0
  137. junifer/preprocess/base.py +96 -69
  138. junifer/preprocess/bold_warper.py +265 -0
  139. junifer/preprocess/confounds/fmriprep_confound_remover.py +91 -134
  140. junifer/preprocess/confounds/tests/test_fmriprep_confound_remover.py +106 -111
  141. junifer/preprocess/fsl/__init__.py +4 -0
  142. junifer/preprocess/fsl/apply_warper.py +179 -0
  143. junifer/preprocess/fsl/tests/test_apply_warper.py +45 -0
  144. junifer/preprocess/tests/test_bold_warper.py +159 -0
  145. junifer/preprocess/tests/test_preprocess_base.py +6 -6
  146. junifer/preprocess/warping/__init__.py +6 -0
  147. junifer/preprocess/warping/_ants_warper.py +167 -0
  148. junifer/preprocess/warping/_fsl_warper.py +109 -0
  149. junifer/preprocess/warping/space_warper.py +213 -0
  150. junifer/preprocess/warping/tests/test_space_warper.py +198 -0
  151. junifer/stats.py +18 -4
  152. junifer/storage/base.py +9 -1
  153. junifer/storage/hdf5.py +8 -3
  154. junifer/storage/pandas_base.py +2 -1
  155. junifer/storage/sqlite.py +1 -0
  156. junifer/storage/tests/test_hdf5.py +2 -1
  157. junifer/storage/tests/test_sqlite.py +8 -8
  158. junifer/storage/tests/test_utils.py +6 -6
  159. junifer/storage/utils.py +1 -0
  160. junifer/testing/datagrabbers.py +11 -7
  161. junifer/testing/utils.py +1 -0
  162. junifer/tests/test_stats.py +2 -0
  163. junifer/utils/__init__.py +1 -0
  164. junifer/utils/helpers.py +53 -0
  165. junifer/utils/logging.py +14 -3
  166. junifer/utils/tests/test_helpers.py +35 -0
  167. {junifer-0.0.3.dev186.dist-info → junifer-0.0.4.dist-info}/METADATA +59 -28
  168. junifer-0.0.4.dist-info/RECORD +257 -0
  169. {junifer-0.0.3.dev186.dist-info → junifer-0.0.4.dist-info}/WHEEL +1 -1
  170. junifer/markers/falff/falff_estimator.py +0 -334
  171. junifer/markers/falff/tests/test_falff_estimator.py +0 -238
  172. junifer/markers/reho/reho_estimator.py +0 -515
  173. junifer/markers/reho/tests/test_reho_estimator.py +0 -260
  174. junifer-0.0.3.dev186.dist-info/RECORD +0 -199
  175. {junifer-0.0.3.dev186.dist-info → junifer-0.0.4.dist-info}/AUTHORS.rst +0 -0
  176. {junifer-0.0.3.dev186.dist-info → junifer-0.0.4.dist-info}/LICENSE.md +0 -0
  177. {junifer-0.0.3.dev186.dist-info → junifer-0.0.4.dist-info}/entry_points.txt +0 -0
  178. {junifer-0.0.3.dev186.dist-info → junifer-0.0.4.dist-info}/top_level.txt +0 -0
@@ -1,22 +1,23 @@
1
1
  """Provide tests for sphere aggregation."""
2
2
 
3
3
  # Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
4
+ # Synchon Mandal <s.mandal@fz-juelich.de>
4
5
  # License: AGPL
5
6
 
6
- import typing
7
7
  from pathlib import Path
8
- from typing import Dict
9
8
 
10
- import nibabel as nib
11
9
  import pytest
12
- from nilearn import datasets
13
- from nilearn.image import concat_imgs
14
10
  from nilearn.maskers import NiftiSpheresMasker
15
11
  from numpy.testing import assert_array_equal
16
12
 
17
- from junifer.data import load_coordinates, load_mask
13
+ from junifer.data import get_coordinates, get_mask
14
+ from junifer.datareader import DefaultDataReader
18
15
  from junifer.markers.sphere_aggregation import SphereAggregation
19
16
  from junifer.storage import SQLiteFeatureStorage
17
+ from junifer.testing.datagrabbers import (
18
+ OasisVBMTestingDataGrabber,
19
+ SPMAuditoryTestingDataGrabber,
20
+ )
20
21
 
21
22
 
22
23
  # Define common variables
@@ -36,51 +37,66 @@ def test_SphereAggregation_input_output() -> None:
36
37
 
37
38
  def test_SphereAggregation_3D() -> None:
38
39
  """Test SphereAggregation object on 3D images."""
39
- # Get the testing coordinates (for nilearn)
40
- coordinates, labels = load_coordinates(COORDS)
41
-
42
- # Get the oasis VBM data
43
- oasis_dataset = datasets.fetch_oasis_vbm(n_subjects=1)
44
- vbm = oasis_dataset.gray_matter_maps[0]
45
- img = nib.load(vbm)
46
-
47
- # Create NiftSpheresMasker
48
- nifti_masker = NiftiSpheresMasker(seeds=coordinates, radius=RADIUS)
49
- auto4d = nifti_masker.fit_transform(img)
50
-
51
- # Create SphereAggregation object
52
- marker = SphereAggregation(
53
- coords=COORDS, method="mean", radius=RADIUS, on="VBM_GM"
54
- )
55
- input = {"VBM_GM": {"data": img, "meta": {}}}
56
- jun_values4d = marker.fit_transform(input)["VBM_GM"]["data"]
40
+ with OasisVBMTestingDataGrabber() as dg:
41
+ element_data = DefaultDataReader().fit_transform(dg["sub-01"])
42
+ # Create SphereAggregation object
43
+ marker = SphereAggregation(
44
+ coords=COORDS, method="mean", radius=RADIUS, on="VBM_GM"
45
+ )
46
+ sphere_agg_vbm_gm_data = marker.fit_transform(element_data)["VBM_GM"][
47
+ "data"
48
+ ]
49
+
50
+ # Compare with nilearn
51
+ # Load testing coordinates
52
+ testing_coords, _ = get_coordinates(
53
+ coords=COORDS, target_data=element_data["VBM_GM"]
54
+ )
55
+ # Extract data
56
+ nifti_spheres_masker = NiftiSpheresMasker(
57
+ seeds=testing_coords, radius=RADIUS
58
+ )
59
+ nifti_spheres_masked_vbm_gm = nifti_spheres_masker.fit_transform(
60
+ element_data["VBM_GM"]["data"]
61
+ )
57
62
 
58
- assert jun_values4d.ndim == 2
59
- assert_array_equal(auto4d.shape, jun_values4d.shape)
60
- assert_array_equal(auto4d, jun_values4d)
63
+ assert sphere_agg_vbm_gm_data.ndim == 2
64
+ assert_array_equal(
65
+ nifti_spheres_masked_vbm_gm.shape, sphere_agg_vbm_gm_data.shape
66
+ )
67
+ assert_array_equal(nifti_spheres_masked_vbm_gm, sphere_agg_vbm_gm_data)
61
68
 
62
69
 
63
70
  def test_SphereAggregation_4D() -> None:
64
71
  """Test SphereAggregation object on 4D images."""
65
- # Get the testing coordinates (for nilearn)
66
- coordinates, _ = load_coordinates(COORDS)
67
-
68
- # Get the SPM auditory data
69
- subject_data = datasets.fetch_spm_auditory()
70
- fmri_img = concat_imgs(subject_data.func) # type: ignore
71
-
72
- # Create NiftSpheresMasker
73
- nifti_masker = NiftiSpheresMasker(seeds=coordinates, radius=RADIUS)
74
- auto4d = nifti_masker.fit_transform(fmri_img)
75
-
76
- # Create SphereAggregation object
77
- marker = SphereAggregation(coords=COORDS, method="mean", radius=RADIUS)
78
- input = {"BOLD": {"data": fmri_img, "meta": {}}}
79
- jun_values4d = marker.fit_transform(input)["BOLD"]["data"]
72
+ with SPMAuditoryTestingDataGrabber() as dg:
73
+ element_data = DefaultDataReader().fit_transform(dg["sub001"])
74
+ # Create SphereAggregation object
75
+ marker = SphereAggregation(
76
+ coords=COORDS, method="mean", radius=RADIUS, on="BOLD"
77
+ )
78
+ sphere_agg_bold_data = marker.fit_transform(element_data)["BOLD"][
79
+ "data"
80
+ ]
81
+
82
+ # Compare with nilearn
83
+ # Load testing coordinates
84
+ testing_coords, _ = get_coordinates(
85
+ coords=COORDS, target_data=element_data["BOLD"]
86
+ )
87
+ # Extract data
88
+ nifti_spheres_masker = NiftiSpheresMasker(
89
+ seeds=testing_coords, radius=RADIUS
90
+ )
91
+ nifti_spheres_masked_bold = nifti_spheres_masker.fit_transform(
92
+ element_data["BOLD"]["data"]
93
+ )
80
94
 
81
- assert jun_values4d.ndim == 2
82
- assert_array_equal(auto4d.shape, jun_values4d.shape)
83
- assert_array_equal(auto4d, jun_values4d)
95
+ assert sphere_agg_bold_data.ndim == 2
96
+ assert_array_equal(
97
+ nifti_spheres_masked_bold.shape, sphere_agg_bold_data.shape
98
+ )
99
+ assert_array_equal(nifti_spheres_masked_bold, sphere_agg_bold_data)
84
100
 
85
101
 
86
102
  def test_SphereAggregation_storage(tmp_path: Path) -> None:
@@ -92,124 +108,143 @@ def test_SphereAggregation_storage(tmp_path: Path) -> None:
92
108
  The path to the test directory.
93
109
 
94
110
  """
95
- # Get the oasis VBM data
96
- oasis_dataset = datasets.fetch_oasis_vbm(n_subjects=1)
97
- vbm = oasis_dataset.gray_matter_maps[0]
98
- img = nib.load(vbm)
99
- uri = tmp_path / "test_sphere_storage_3D.sqlite"
100
-
101
- storage = SQLiteFeatureStorage(uri=uri, upsert="ignore")
102
- meta = {
103
- "element": {"subject": "sub-01", "session": "ses-01"},
104
- "dependencies": {"nilearn", "nibabel"},
105
- }
106
- input = {"VBM_GM": {"data": img, "meta": meta}}
107
- marker = SphereAggregation(
108
- coords=COORDS, method="mean", radius=RADIUS, on="VBM_GM"
109
- )
110
-
111
- marker.fit_transform(input, storage=storage)
112
-
113
- features: Dict = typing.cast(Dict, storage.list_features())
114
- assert any(
115
- x["name"] == "VBM_GM_SphereAggregation" for x in features.values()
116
- )
117
-
118
- meta = {
119
- "element": {"subject": "sub-01", "session": "ses-01"},
120
- "dependencies": {"nilearn", "nibabel"},
121
- }
122
- # Get the SPM auditory data
123
- subject_data = datasets.fetch_spm_auditory()
124
- fmri_img = concat_imgs(subject_data.func) # type: ignore
125
- input = {"BOLD": {"data": fmri_img, "meta": meta}}
126
- marker = SphereAggregation(
127
- coords=COORDS, method="mean", radius=RADIUS, on="BOLD"
128
- )
129
-
130
- marker.fit_transform(input, storage=storage)
131
- features: Dict = typing.cast(Dict, storage.list_features())
132
- assert any(
133
- x["name"] == "BOLD_SphereAggregation" for x in features.values()
134
- )
111
+ # Store 3D
112
+ with OasisVBMTestingDataGrabber() as dg:
113
+ element_data = DefaultDataReader().fit_transform(dg["sub-01"])
114
+ storage = SQLiteFeatureStorage(
115
+ uri=tmp_path / "test_sphere_storage_3D.sqlite", upsert="ignore"
116
+ )
117
+ marker = SphereAggregation(
118
+ coords=COORDS, method="mean", radius=RADIUS, on="VBM_GM"
119
+ )
120
+ marker.fit_transform(input=element_data, storage=storage)
121
+ features = storage.list_features()
122
+ assert any(
123
+ x["name"] == "VBM_GM_SphereAggregation" for x in features.values()
124
+ )
125
+
126
+ # Store 4D
127
+ with SPMAuditoryTestingDataGrabber() as dg:
128
+ element_data = DefaultDataReader().fit_transform(dg["sub001"])
129
+ storage = SQLiteFeatureStorage(
130
+ uri=tmp_path / "test_sphere_storage_4D.sqlite", upsert="ignore"
131
+ )
132
+ marker = SphereAggregation(
133
+ coords=COORDS, method="mean", radius=RADIUS, on="BOLD"
134
+ )
135
+ marker.fit_transform(input=element_data, storage=storage)
136
+ features = storage.list_features()
137
+ assert any(
138
+ x["name"] == "BOLD_SphereAggregation" for x in features.values()
139
+ )
135
140
 
136
141
 
137
142
  def test_SphereAggregation_3D_mask() -> None:
138
143
  """Test SphereAggregation object on 3D images using mask."""
139
- # Get the testing coordinates (for nilearn)
140
- coordinates, _ = load_coordinates(COORDS)
141
-
142
- # Get one mask
143
- mask_img, _ = load_mask("GM_prob0.2")
144
-
145
- # Get the oasis VBM data
146
- oasis_dataset = datasets.fetch_oasis_vbm(n_subjects=1)
147
- vbm = oasis_dataset.gray_matter_maps[0]
148
- img = nib.load(vbm)
149
-
150
- # Create NiftSpheresMasker
151
- nifti_masker = NiftiSpheresMasker(
152
- seeds=coordinates, radius=RADIUS, mask_img=mask_img
153
- )
154
- auto4d = nifti_masker.fit_transform(img)
155
-
156
- # Create SphereAggregation object
157
- marker = SphereAggregation(
158
- coords=COORDS,
159
- method="mean",
160
- radius=RADIUS,
161
- on="VBM_GM",
162
- masks="GM_prob0.2",
163
- )
164
- input = {"VBM_GM": {"data": img, "meta": {}}}
165
- jun_values4d = marker.fit_transform(input)["VBM_GM"]["data"]
166
-
167
- assert jun_values4d.ndim == 2
168
- assert_array_equal(auto4d.shape, jun_values4d.shape)
169
- assert_array_equal(auto4d, jun_values4d)
144
+ with OasisVBMTestingDataGrabber() as dg:
145
+ element_data = DefaultDataReader().fit_transform(dg["sub-01"])
146
+ # Create SphereAggregation object
147
+ marker = SphereAggregation(
148
+ coords=COORDS,
149
+ method="mean",
150
+ radius=RADIUS,
151
+ on="VBM_GM",
152
+ masks="compute_brain_mask",
153
+ )
154
+ sphere_agg_vbm_gm_data = marker.fit_transform(element_data)["VBM_GM"][
155
+ "data"
156
+ ]
157
+
158
+ # Compare with nilearn
159
+ # Load testing coordinates
160
+ testing_coords, _ = get_coordinates(
161
+ coords=COORDS, target_data=element_data["VBM_GM"]
162
+ )
163
+ # Load mask
164
+ mask_img = get_mask(
165
+ "compute_brain_mask", target_data=element_data["VBM_GM"]
166
+ )
167
+ # Extract data
168
+ nifti_spheres_masker = NiftiSpheresMasker(
169
+ seeds=testing_coords, radius=RADIUS, mask_img=mask_img
170
+ )
171
+ nifti_spheres_masked_vbm_agg = nifti_spheres_masker.fit_transform(
172
+ element_data["VBM_GM"]["data"]
173
+ )
174
+
175
+ assert sphere_agg_vbm_gm_data.ndim == 2
176
+ assert_array_equal(
177
+ nifti_spheres_masked_vbm_agg.shape,
178
+ nifti_spheres_masked_vbm_agg.shape,
179
+ )
180
+ assert_array_equal(
181
+ nifti_spheres_masked_vbm_agg, nifti_spheres_masked_vbm_agg
182
+ )
170
183
 
171
184
 
172
185
  def test_SphereAggregation_4D_agg_time() -> None:
173
186
  """Test SphereAggregation object on 4D images, aggregating time."""
174
- # Get the testing coordinates (for nilearn)
175
- coordinates, _ = load_coordinates(COORDS)
176
-
177
- # Get the SPM auditory data
178
- subject_data = datasets.fetch_spm_auditory()
179
- fmri_img = concat_imgs(subject_data.func) # type: ignore
180
-
181
- # Create NiftSpheresMasker
182
- nifti_masker = NiftiSpheresMasker(seeds=coordinates, radius=RADIUS)
183
- auto4d = nifti_masker.fit_transform(fmri_img)
184
- auto_mean = auto4d.mean(axis=0)
185
-
186
- # Create SphereAggregation object
187
- marker = SphereAggregation(
188
- coords=COORDS, method="mean", radius=RADIUS, time_method="mean"
189
- )
190
- input = {"BOLD": {"data": fmri_img, "meta": {}}}
191
- jun_values4d = marker.fit_transform(input)["BOLD"]["data"]
192
-
193
- assert jun_values4d.ndim == 1
194
- assert_array_equal(auto_mean.shape, jun_values4d.shape)
195
- assert_array_equal(auto_mean, jun_values4d)
196
-
197
- auto_pick_0 = auto4d[:1, :]
198
- marker = SphereAggregation(
199
- coords=COORDS,
200
- method="mean",
201
- radius=RADIUS,
202
- time_method="select",
203
- time_method_params={"pick": [0]},
204
- )
205
-
206
- input = {"BOLD": {"data": fmri_img, "meta": {}}}
207
- jun_values4d = marker.fit_transform(input)["BOLD"]["data"]
208
-
209
- assert jun_values4d.ndim == 2
210
- assert_array_equal(auto_pick_0.shape, jun_values4d.shape)
211
- assert_array_equal(auto_pick_0, jun_values4d)
187
+ with SPMAuditoryTestingDataGrabber() as dg:
188
+ element_data = DefaultDataReader().fit_transform(dg["sub001"])
189
+ # Create SphereAggregation object
190
+ marker = SphereAggregation(
191
+ coords=COORDS,
192
+ method="mean",
193
+ radius=RADIUS,
194
+ time_method="mean",
195
+ on="BOLD",
196
+ )
197
+ sphere_agg_bold_data = marker.fit_transform(element_data)["BOLD"][
198
+ "data"
199
+ ]
200
+
201
+ # Compare with nilearn
202
+ # Load testing coordinates
203
+ testing_coords, _ = get_coordinates(
204
+ coords=COORDS, target_data=element_data["BOLD"]
205
+ )
206
+ # Extract data
207
+ nifti_spheres_masker = NiftiSpheresMasker(
208
+ seeds=testing_coords, radius=RADIUS
209
+ )
210
+ nifti_spheres_masked_bold = nifti_spheres_masker.fit_transform(
211
+ element_data["BOLD"]["data"]
212
+ )
213
+ nifti_spheres_masked_bold_mean = nifti_spheres_masked_bold.mean(axis=0)
212
214
 
215
+ assert sphere_agg_bold_data.ndim == 1
216
+ assert_array_equal(
217
+ nifti_spheres_masked_bold_mean.shape, sphere_agg_bold_data.shape
218
+ )
219
+ assert_array_equal(
220
+ nifti_spheres_masked_bold_mean, sphere_agg_bold_data
221
+ )
222
+
223
+ # Test picking first time point
224
+ nifti_spheres_masked_bold_pick_0 = nifti_spheres_masked_bold[:1, :]
225
+ marker = SphereAggregation(
226
+ coords=COORDS,
227
+ method="mean",
228
+ radius=RADIUS,
229
+ time_method="select",
230
+ time_method_params={"pick": [0]},
231
+ on="BOLD",
232
+ )
233
+ sphere_agg_bold_data = marker.fit_transform(element_data)["BOLD"][
234
+ "data"
235
+ ]
236
+
237
+ assert sphere_agg_bold_data.ndim == 2
238
+ assert_array_equal(
239
+ nifti_spheres_masked_bold_pick_0.shape, sphere_agg_bold_data.shape
240
+ )
241
+ assert_array_equal(
242
+ nifti_spheres_masked_bold_pick_0, sphere_agg_bold_data
243
+ )
244
+
245
+
246
+ def test_SphereAggregation_errors() -> None:
247
+ """Test errors for SphereAggregation."""
213
248
  with pytest.raises(ValueError, match="can only be used with BOLD data"):
214
249
  SphereAggregation(
215
250
  coords=COORDS,
@@ -231,6 +266,23 @@ def test_SphereAggregation_4D_agg_time() -> None:
231
266
  on="VBM_GM",
232
267
  )
233
268
 
234
- with pytest.warns(RuntimeWarning, match="No time dimension to aggregate"):
235
- input = {"BOLD": {"data": fmri_img.slicer[..., 0:1], "meta": {}}}
236
- marker.fit_transform(input)
269
+
270
+ def test_SphereAggregation_warning() -> None:
271
+ """Test warning for SphereAggregation."""
272
+ with SPMAuditoryTestingDataGrabber() as dg:
273
+ element_data = DefaultDataReader().fit_transform(dg["sub001"])
274
+ with pytest.warns(
275
+ RuntimeWarning, match="No time dimension to aggregate"
276
+ ):
277
+ marker = SphereAggregation(
278
+ coords=COORDS,
279
+ method="mean",
280
+ radius=RADIUS,
281
+ time_method="select",
282
+ time_method_params={"pick": [0]},
283
+ on="BOLD",
284
+ )
285
+ element_data["BOLD"]["data"] = element_data["BOLD"]["data"].slicer[
286
+ ..., 0:1
287
+ ]
288
+ marker.fit_transform(element_data)
junifer/markers/utils.py CHANGED
@@ -5,9 +5,10 @@
5
5
  # Sami Hamdan <s.hamdan@fz-juelich.de>
6
6
  # Synchon Mandal <s.mandal@fz-juelich.de>
7
7
  # Federico Raimondo <f.raimondo@fz-juelich.de>
8
+ # Amir Omidvarnia <a.omidvarnia@fz-juelich.de>
8
9
  # License: AGPL
9
10
 
10
- from typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union
11
+ from typing import Callable, List, Optional, Tuple, Union
11
12
 
12
13
  import numpy as np
13
14
  import pandas as pd
@@ -16,45 +17,6 @@ from scipy.stats import zscore
16
17
  from ..utils import raise_error
17
18
 
18
19
 
19
- def singleton(cls: Type) -> Type:
20
- """Make a class singleton.
21
-
22
- Parameters
23
- ----------
24
- cls : class
25
- The class to designate as singleton.
26
-
27
- Returns
28
- -------
29
- class
30
- The only instance of the class.
31
-
32
- """
33
- instances: Dict = {}
34
-
35
- def get_instance(*args: Any, **kwargs: Any) -> Type:
36
- """Get the only instance for a class.
37
-
38
- Parameters
39
- ----------
40
- *args : tuple
41
- The positional arguments to pass to the class.
42
- **kwargs : dict
43
- The keyword arguments to pass to the class.
44
-
45
- Returns
46
- -------
47
- class
48
- The only instance of the class.
49
-
50
- """
51
- if cls not in instances:
52
- instances[cls] = cls(*args, **kwargs)
53
- return instances[cls]
54
-
55
- return get_instance
56
-
57
-
58
20
  def _ets(
59
21
  bold_ts: np.ndarray,
60
22
  roi_names: Union[None, List[str]] = None,
@@ -17,8 +17,9 @@ if TYPE_CHECKING:
17
17
 
18
18
  def read_transform(
19
19
  storage: Type["BaseFeatureStorage"],
20
- feature_name: str,
21
20
  transform: str,
21
+ feature_name: Optional[str] = None,
22
+ feature_md5: Optional[str] = None,
22
23
  transform_args: Optional[Tuple] = None,
23
24
  transform_kw_args: Optional[Dict] = None,
24
25
  ) -> pd.DataFrame:
@@ -28,11 +29,13 @@ def read_transform(
28
29
  ----------
29
30
  storage : storage-like
30
31
  The storage class, for example, SQLiteFeatureStorage.
31
- feature_name : str
32
- Name of the feature to read.
33
32
  transform : str
34
33
  The kind of transform formatted as ``<package>_<function>``,
35
34
  for example, ``bctpy_degrees_und``.
35
+ feature_name : str, optional
36
+ Name of the feature to read (default None).
37
+ feature_md5 : str, optional
38
+ MD5 hash of the feature to read (default None).
36
39
  transform_args : tuple, optional
37
40
  The positional arguments for the callable of ``transform``
38
41
  (default None).
@@ -62,7 +65,9 @@ def read_transform(
62
65
  transform_kw_args = transform_kw_args or {}
63
66
 
64
67
  # Read storage
65
- stored_data = storage.read(feature_name=feature_name) # type: ignore
68
+ stored_data = storage.read(
69
+ feature_name=feature_name, feature_md5=feature_md5
70
+ ) # type: ignore
66
71
  # Retrieve package and function
67
72
  package, func_str = transform.split("_", 1)
68
73
  # Condition for package
@@ -105,7 +110,8 @@ def read_transform(
105
110
  # Apply function and store subject-wise
106
111
  output_list = []
107
112
  logger.debug(
108
- f"Computing '{package}.{func_str}' for feature {feature_name} ..."
113
+ f"Computing '{package}.{func_str}' for feature "
114
+ f"{feature_name or feature_md5} ..."
109
115
  )
110
116
  for subject in range(stored_data["data"].shape[2]):
111
117
  output = func(
@@ -119,7 +125,8 @@ def read_transform(
119
125
  idx_df = pd.DataFrame(data=stored_data["element"])
120
126
  # Create multiindex from dataframe
121
127
  logger.debug(
122
- f"Generating pandas.MultiIndex for feature {feature_name} ..."
128
+ "Generating pandas.MultiIndex for feature "
129
+ f"{feature_name or feature_md5} ..."
123
130
  )
124
131
  data_idx = pd.MultiIndex.from_frame(df=idx_df)
125
132
 
@@ -6,3 +6,4 @@
6
6
  from . import registry
7
7
  from .pipeline_step_mixin import PipelineStepMixin
8
8
  from .update_meta_mixin import UpdateMetaMixin
9
+ from .workdir_manager import WorkDirManager