junifer 0.0.5__py3-none-any.whl → 0.0.5.dev24__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 (194) hide show
  1. junifer/__init__.py +0 -17
  2. junifer/_version.py +2 -2
  3. junifer/api/__init__.py +1 -4
  4. junifer/api/cli.py +1 -91
  5. junifer/api/decorators.py +0 -9
  6. junifer/api/functions.py +10 -56
  7. junifer/api/parser.py +0 -3
  8. junifer/api/queue_context/__init__.py +1 -4
  9. junifer/api/res/afni/run_afni_docker.sh +1 -1
  10. junifer/api/res/ants/run_ants_docker.sh +1 -1
  11. junifer/api/res/fsl/run_fsl_docker.sh +1 -1
  12. junifer/api/tests/test_api_utils.py +2 -4
  13. junifer/api/tests/test_cli.py +0 -83
  14. junifer/api/tests/test_functions.py +2 -27
  15. junifer/configs/__init__.py +1 -1
  16. junifer/configs/juseless/__init__.py +1 -4
  17. junifer/configs/juseless/datagrabbers/__init__.py +1 -10
  18. junifer/configs/juseless/datagrabbers/aomic_id1000_vbm.py +0 -3
  19. junifer/configs/juseless/datagrabbers/camcan_vbm.py +0 -3
  20. junifer/configs/juseless/datagrabbers/ixi_vbm.py +0 -3
  21. junifer/configs/juseless/datagrabbers/tests/test_ucla.py +3 -1
  22. junifer/configs/juseless/datagrabbers/ucla.py +9 -12
  23. junifer/configs/juseless/datagrabbers/ukb_vbm.py +0 -3
  24. junifer/data/__init__.py +1 -21
  25. junifer/data/coordinates.py +19 -10
  26. junifer/data/masks.py +87 -58
  27. junifer/data/parcellations.py +3 -14
  28. junifer/data/template_spaces.py +1 -4
  29. junifer/data/tests/test_masks.py +37 -26
  30. junifer/data/utils.py +0 -3
  31. junifer/datagrabber/__init__.py +1 -18
  32. junifer/datagrabber/aomic/__init__.py +0 -3
  33. junifer/datagrabber/aomic/id1000.py +37 -70
  34. junifer/datagrabber/aomic/piop1.py +36 -69
  35. junifer/datagrabber/aomic/piop2.py +38 -71
  36. junifer/datagrabber/aomic/tests/test_id1000.py +99 -44
  37. junifer/datagrabber/aomic/tests/test_piop1.py +108 -65
  38. junifer/datagrabber/aomic/tests/test_piop2.py +102 -45
  39. junifer/datagrabber/base.py +6 -13
  40. junifer/datagrabber/datalad_base.py +1 -13
  41. junifer/datagrabber/dmcc13_benchmark.py +53 -36
  42. junifer/datagrabber/hcp1200/__init__.py +0 -3
  43. junifer/datagrabber/hcp1200/datalad_hcp1200.py +0 -3
  44. junifer/datagrabber/hcp1200/hcp1200.py +1 -4
  45. junifer/datagrabber/multiple.py +6 -45
  46. junifer/datagrabber/pattern.py +62 -170
  47. junifer/datagrabber/pattern_datalad.py +12 -25
  48. junifer/datagrabber/tests/test_datagrabber_utils.py +218 -0
  49. junifer/datagrabber/tests/test_datalad_base.py +4 -4
  50. junifer/datagrabber/tests/test_dmcc13_benchmark.py +19 -46
  51. junifer/datagrabber/tests/test_multiple.py +84 -161
  52. junifer/datagrabber/tests/test_pattern.py +0 -45
  53. junifer/datagrabber/tests/test_pattern_datalad.py +4 -4
  54. junifer/datagrabber/utils.py +230 -0
  55. junifer/datareader/__init__.py +1 -4
  56. junifer/datareader/default.py +43 -95
  57. junifer/external/__init__.py +1 -1
  58. junifer/external/nilearn/__init__.py +1 -5
  59. junifer/external/nilearn/junifer_nifti_spheres_masker.py +9 -23
  60. junifer/external/nilearn/tests/test_junifer_nifti_spheres_masker.py +1 -76
  61. junifer/markers/__init__.py +1 -23
  62. junifer/markers/base.py +28 -68
  63. junifer/markers/collection.py +2 -10
  64. junifer/markers/complexity/__init__.py +0 -10
  65. junifer/markers/complexity/complexity_base.py +43 -26
  66. junifer/markers/complexity/hurst_exponent.py +0 -3
  67. junifer/markers/complexity/multiscale_entropy_auc.py +0 -3
  68. junifer/markers/complexity/perm_entropy.py +0 -3
  69. junifer/markers/complexity/range_entropy.py +0 -3
  70. junifer/markers/complexity/range_entropy_auc.py +0 -3
  71. junifer/markers/complexity/sample_entropy.py +0 -3
  72. junifer/markers/complexity/tests/test_hurst_exponent.py +3 -11
  73. junifer/markers/complexity/tests/test_multiscale_entropy_auc.py +3 -11
  74. junifer/markers/complexity/tests/test_perm_entropy.py +3 -11
  75. junifer/markers/complexity/tests/test_range_entropy.py +3 -11
  76. junifer/markers/complexity/tests/test_range_entropy_auc.py +3 -11
  77. junifer/markers/complexity/tests/test_sample_entropy.py +3 -11
  78. junifer/markers/complexity/tests/test_weighted_perm_entropy.py +3 -11
  79. junifer/markers/complexity/weighted_perm_entropy.py +0 -3
  80. junifer/markers/ets_rss.py +42 -27
  81. junifer/markers/falff/__init__.py +0 -3
  82. junifer/markers/falff/_afni_falff.py +2 -5
  83. junifer/markers/falff/_junifer_falff.py +0 -3
  84. junifer/markers/falff/falff_base.py +46 -20
  85. junifer/markers/falff/falff_parcels.py +27 -56
  86. junifer/markers/falff/falff_spheres.py +29 -60
  87. junifer/markers/falff/tests/test_falff_parcels.py +23 -39
  88. junifer/markers/falff/tests/test_falff_spheres.py +23 -39
  89. junifer/markers/functional_connectivity/__init__.py +0 -9
  90. junifer/markers/functional_connectivity/crossparcellation_functional_connectivity.py +60 -63
  91. junifer/markers/functional_connectivity/edge_functional_connectivity_parcels.py +32 -45
  92. junifer/markers/functional_connectivity/edge_functional_connectivity_spheres.py +36 -49
  93. junifer/markers/functional_connectivity/functional_connectivity_base.py +70 -71
  94. junifer/markers/functional_connectivity/functional_connectivity_parcels.py +25 -34
  95. junifer/markers/functional_connectivity/functional_connectivity_spheres.py +30 -40
  96. junifer/markers/functional_connectivity/tests/test_crossparcellation_functional_connectivity.py +7 -11
  97. junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_parcels.py +7 -27
  98. junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_spheres.py +12 -28
  99. junifer/markers/functional_connectivity/tests/test_functional_connectivity_parcels.py +11 -35
  100. junifer/markers/functional_connectivity/tests/test_functional_connectivity_spheres.py +62 -36
  101. junifer/markers/parcel_aggregation.py +61 -47
  102. junifer/markers/reho/__init__.py +0 -3
  103. junifer/markers/reho/_afni_reho.py +2 -5
  104. junifer/markers/reho/_junifer_reho.py +1 -4
  105. junifer/markers/reho/reho_base.py +27 -8
  106. junifer/markers/reho/reho_parcels.py +17 -28
  107. junifer/markers/reho/reho_spheres.py +18 -27
  108. junifer/markers/reho/tests/test_reho_parcels.py +3 -8
  109. junifer/markers/reho/tests/test_reho_spheres.py +3 -8
  110. junifer/markers/sphere_aggregation.py +59 -43
  111. junifer/markers/temporal_snr/__init__.py +0 -3
  112. junifer/markers/temporal_snr/temporal_snr_base.py +32 -23
  113. junifer/markers/temporal_snr/temporal_snr_parcels.py +6 -9
  114. junifer/markers/temporal_snr/temporal_snr_spheres.py +6 -9
  115. junifer/markers/temporal_snr/tests/test_temporal_snr_parcels.py +3 -6
  116. junifer/markers/temporal_snr/tests/test_temporal_snr_spheres.py +3 -6
  117. junifer/markers/tests/test_collection.py +8 -9
  118. junifer/markers/tests/test_ets_rss.py +9 -15
  119. junifer/markers/tests/test_markers_base.py +18 -17
  120. junifer/markers/tests/test_parcel_aggregation.py +32 -93
  121. junifer/markers/tests/test_sphere_aggregation.py +19 -72
  122. junifer/onthefly/__init__.py +1 -4
  123. junifer/onthefly/read_transform.py +0 -3
  124. junifer/pipeline/__init__.py +1 -9
  125. junifer/pipeline/pipeline_step_mixin.py +4 -21
  126. junifer/pipeline/registry.py +0 -3
  127. junifer/pipeline/singleton.py +0 -3
  128. junifer/pipeline/tests/test_registry.py +1 -1
  129. junifer/pipeline/update_meta_mixin.py +0 -3
  130. junifer/pipeline/utils.py +1 -67
  131. junifer/pipeline/workdir_manager.py +0 -3
  132. junifer/preprocess/__init__.py +2 -9
  133. junifer/preprocess/ants/__init__.py +4 -0
  134. junifer/preprocess/ants/ants_apply_transforms_warper.py +185 -0
  135. junifer/preprocess/ants/tests/test_ants_apply_transforms_warper.py +56 -0
  136. junifer/preprocess/base.py +3 -6
  137. junifer/preprocess/bold_warper.py +265 -0
  138. junifer/preprocess/confounds/__init__.py +0 -3
  139. junifer/preprocess/confounds/fmriprep_confound_remover.py +60 -47
  140. junifer/preprocess/confounds/tests/test_fmriprep_confound_remover.py +113 -72
  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/smoothing/__init__.py +0 -3
  145. junifer/preprocess/smoothing/_afni_smoothing.py +1 -1
  146. junifer/preprocess/tests/test_bold_warper.py +159 -0
  147. junifer/preprocess/warping/__init__.py +0 -3
  148. junifer/preprocess/warping/_ants_warper.py +0 -3
  149. junifer/preprocess/warping/_fsl_warper.py +0 -3
  150. junifer/stats.py +1 -4
  151. junifer/storage/__init__.py +1 -9
  152. junifer/storage/base.py +1 -40
  153. junifer/storage/hdf5.py +9 -71
  154. junifer/storage/pandas_base.py +0 -3
  155. junifer/storage/sqlite.py +0 -3
  156. junifer/storage/tests/test_hdf5.py +10 -82
  157. junifer/storage/utils.py +0 -9
  158. junifer/testing/__init__.py +1 -4
  159. junifer/testing/datagrabbers.py +6 -13
  160. junifer/testing/tests/test_partlycloudytesting_datagrabber.py +7 -7
  161. junifer/testing/utils.py +0 -3
  162. junifer/utils/__init__.py +2 -13
  163. junifer/utils/fs.py +0 -3
  164. junifer/utils/helpers.py +1 -32
  165. junifer/utils/logging.py +4 -33
  166. junifer/utils/tests/test_logging.py +0 -8
  167. {junifer-0.0.5.dist-info → junifer-0.0.5.dev24.dist-info}/METADATA +16 -17
  168. junifer-0.0.5.dev24.dist-info/RECORD +265 -0
  169. {junifer-0.0.5.dist-info → junifer-0.0.5.dev24.dist-info}/WHEEL +1 -1
  170. junifer/api/res/freesurfer/mri_binarize +0 -3
  171. junifer/api/res/freesurfer/mri_mc +0 -3
  172. junifer/api/res/freesurfer/mri_pretess +0 -3
  173. junifer/api/res/freesurfer/mris_convert +0 -3
  174. junifer/api/res/freesurfer/run_freesurfer_docker.sh +0 -61
  175. junifer/data/masks/ukb/UKB_15K_GM_template.nii.gz +0 -0
  176. junifer/datagrabber/pattern_validation_mixin.py +0 -388
  177. junifer/datagrabber/tests/test_pattern_validation_mixin.py +0 -249
  178. junifer/external/BrainPrint/brainprint/__init__.py +0 -4
  179. junifer/external/BrainPrint/brainprint/_version.py +0 -3
  180. junifer/external/BrainPrint/brainprint/asymmetry.py +0 -91
  181. junifer/external/BrainPrint/brainprint/brainprint.py +0 -441
  182. junifer/external/BrainPrint/brainprint/surfaces.py +0 -258
  183. junifer/external/BrainPrint/brainprint/utils/__init__.py +0 -1
  184. junifer/external/BrainPrint/brainprint/utils/_config.py +0 -112
  185. junifer/external/BrainPrint/brainprint/utils/utils.py +0 -188
  186. junifer/external/nilearn/junifer_connectivity_measure.py +0 -483
  187. junifer/external/nilearn/tests/test_junifer_connectivity_measure.py +0 -1089
  188. junifer/markers/brainprint.py +0 -459
  189. junifer/markers/tests/test_brainprint.py +0 -58
  190. junifer-0.0.5.dist-info/RECORD +0 -275
  191. {junifer-0.0.5.dist-info → junifer-0.0.5.dev24.dist-info}/AUTHORS.rst +0 -0
  192. {junifer-0.0.5.dist-info → junifer-0.0.5.dev24.dist-info}/LICENSE.md +0 -0
  193. {junifer-0.0.5.dist-info → junifer-0.0.5.dev24.dist-info}/entry_points.txt +0 -0
  194. {junifer-0.0.5.dist-info → junifer-0.0.5.dev24.dist-info}/top_level.txt +0 -0
@@ -1,258 +0,0 @@
1
- """
2
- Utility module holding surface generation related functions.
3
- """
4
- import uuid
5
- from pathlib import Path
6
- from typing import Dict, List
7
-
8
- from lapy import TriaMesh
9
-
10
- from .utils.utils import run_shell_command
11
-
12
-
13
- def create_aseg_surface(
14
- subject_dir: Path, destination: Path, indices: List[int]
15
- ) -> Path:
16
- """
17
- Generate a surface from the aseg and label files.
18
-
19
- Parameters
20
- ----------
21
- subject_dir : Path
22
- Path to the subject's directory.
23
- destination : Path
24
- Path to the destination directory where the surface will be saved.
25
- indices : List[int]
26
- List of label indices to include in the surface generation.
27
-
28
- Returns
29
- -------
30
- Path
31
- Path to the generated surface in VTK format.
32
- """
33
- aseg_path = subject_dir / "mri/aseg.mgz"
34
- norm_path = subject_dir / "mri/norm.mgz"
35
- temp_name = "temp/aseg.{uid}".format(uid=uuid.uuid4())
36
- indices_mask = destination / f"{temp_name}.mgz"
37
- # binarize on selected labels (creates temp indices_mask)
38
- # always binarize first, otherwise pretess may scale aseg if labels are
39
- # larger than 255 (e.g. aseg+aparc, bug in mri_pretess?)
40
- binarize_template = "mri_binarize --i {source} --match {match} --o {destination}"
41
- binarize_command = binarize_template.format(
42
- source=aseg_path, match=" ".join(indices), destination=indices_mask
43
- )
44
- run_shell_command(binarize_command)
45
-
46
- label_value = "1"
47
- # if norm exist, fix label (pretess)
48
- if norm_path.is_file():
49
- pretess_template = (
50
- "mri_pretess {source} {label_value} {norm_path} {destination}"
51
- )
52
- pretess_command = pretess_template.format(
53
- source=indices_mask,
54
- label_value=label_value,
55
- norm_path=norm_path,
56
- destination=indices_mask,
57
- )
58
- run_shell_command(pretess_command)
59
-
60
- # runs marching cube to extract surface
61
- surface_name = "{name}.surf".format(name=temp_name)
62
- surface_path = destination / surface_name
63
- extraction_template = "mri_mc {source} {label_value} {destination}"
64
- extraction_command = extraction_template.format(
65
- source=indices_mask, label_value=label_value, destination=surface_path
66
- )
67
- run_shell_command(extraction_command)
68
-
69
- # convert to vtk
70
- relative_path = "surfaces/aseg.final.{indices}.vtk".format(
71
- indices="_".join(indices)
72
- )
73
- conversion_destination = destination / relative_path
74
- conversion_template = "mris_convert {source} {destination}"
75
- conversion_command = conversion_template.format(
76
- source=surface_path, destination=conversion_destination
77
- )
78
- run_shell_command(conversion_command)
79
-
80
- return conversion_destination
81
-
82
-
83
- def create_aseg_surfaces(subject_dir: Path, destination: Path) -> Dict[str, Path]:
84
- """
85
- Create surfaces from FreeSurfer aseg labels.
86
-
87
- Parameters
88
- ----------
89
- subject_dir : Path
90
- Path to the subject's FreeSurfer directory.
91
- destination : Path
92
- Path to the destination directory for saving surfaces.
93
-
94
- Returns
95
- -------
96
- Dict[str, Path]
97
- Dictionary of label names mapped to corresponding surface Path objects.
98
- """
99
- # Define aseg labels
100
-
101
- # combined and individual aseg labels:
102
- # - Left Striatum: left Caudate + Putamen + Accumbens
103
- # - Right Striatum: right Caudate + Putamen + Accumbens
104
- # - CorpusCallosum: 5 subregions combined
105
- # - Cerebellum: brainstem + (left+right) cerebellum WM and GM
106
- # - Ventricles: (left+right) lat.vent + inf.lat.vent + choroidplexus + 3rdVent + CSF
107
- # - Lateral-Ventricle: lat.vent + inf.lat.vent + choroidplexus
108
- # - 3rd-Ventricle: 3rd-Ventricle + CSF
109
-
110
- aseg_labels = {
111
- "CorpusCallosum": ["251", "252", "253", "254", "255"],
112
- "Cerebellum": ["7", "8", "16", "46", "47"],
113
- "Ventricles": ["4", "5", "14", "24", "31", "43", "44", "63"],
114
- "3rd-Ventricle": ["14", "24"],
115
- "4th-Ventricle": ["15"],
116
- "Brain-Stem": ["16"],
117
- "Left-Striatum": ["11", "12", "26"],
118
- "Left-Lateral-Ventricle": ["4", "5", "31"],
119
- "Left-Cerebellum-White-Matter": ["7"],
120
- "Left-Cerebellum-Cortex": ["8"],
121
- "Left-Thalamus-Proper": ["10"],
122
- "Left-Caudate": ["11"],
123
- "Left-Putamen": ["12"],
124
- "Left-Pallidum": ["13"],
125
- "Left-Hippocampus": ["17"],
126
- "Left-Amygdala": ["18"],
127
- "Left-Accumbens-area": ["26"],
128
- "Left-VentralDC": ["28"],
129
- "Right-Striatum": ["50", "51", "58"],
130
- "Right-Lateral-Ventricle": ["43", "44", "63"],
131
- "Right-Cerebellum-White-Matter": ["46"],
132
- "Right-Cerebellum-Cortex": ["47"],
133
- "Right-Thalamus-Proper": ["49"],
134
- "Right-Caudate": ["50"],
135
- "Right-Putamen": ["51"],
136
- "Right-Pallidum": ["52"],
137
- "Right-Hippocampus": ["53"],
138
- "Right-Amygdala": ["54"],
139
- "Right-Accumbens-area": ["58"],
140
- "Right-VentralDC": ["60"],
141
- }
142
- return {
143
- label: create_aseg_surface(subject_dir, destination, indices)
144
- for label, indices in aseg_labels.items()
145
- }
146
-
147
-
148
- def create_cortical_surfaces(subject_dir: Path, destination: Path) -> Dict[str, Path]:
149
- """
150
- Create cortical surfaces from FreeSurfer labels.
151
-
152
- Parameters
153
- ----------
154
- subject_dir : Path
155
- Path to the subject's FreeSurfer directory.
156
- destination : Path
157
- Path to the destination directory where the surfaces will be saved.
158
-
159
- Returns
160
- -------
161
- Dict[str, Path]
162
- Dictionary mapping label names to associated surface Paths.
163
- """
164
- cortical_labels = {
165
- "lh-white-2d": "lh.white",
166
- "rh-white-2d": "rh.white",
167
- "lh-pial-2d": "lh.pial",
168
- "rh-pial-2d": "rh.pial",
169
- }
170
- return {
171
- label: surf_to_vtk(
172
- subject_dir / "surf" / name,
173
- destination / "surfaces" / f"{name}.vtk",
174
- )
175
- for label, name in cortical_labels.items()
176
- }
177
-
178
-
179
- def create_surfaces(
180
- subject_dir: Path, destination: Path, skip_cortex: bool = False
181
- ) -> Dict[str, Path]:
182
- """
183
- Create surfaces based on FreeSurfer labels.
184
-
185
- Parameters
186
- ----------
187
- subject_dir : Path
188
- Path to the subject's FreeSurfer directory.
189
- destination : Path
190
- Path to the destination directory where the surfaces will be saved.
191
- skip_cortex : bool, optional
192
- If True, cortical surfaces will not be created (default is False).
193
-
194
- Returns
195
- -------
196
- Dict[str, Path]
197
- Dict mapping label names to the corresponding Path objects of created surfaces.
198
- """
199
- surfaces = create_aseg_surfaces(subject_dir, destination)
200
- if not skip_cortex:
201
- cortical_surfaces = create_cortical_surfaces(subject_dir, destination)
202
- surfaces.update(cortical_surfaces)
203
- return surfaces
204
-
205
-
206
- def read_vtk(path: Path):
207
- """
208
- Read a VTK file and return a triangular mesh.
209
-
210
- Parameters
211
- ----------
212
- path : Path
213
- Path to the VTK file to be read.
214
-
215
- Returns
216
- -------
217
- TriaMesh
218
- A triangular mesh object representing the contents of the VTK file.
219
-
220
- Raises
221
- ------
222
- RuntimeError
223
- If there is an issue reading the VTK file or if the file is empty.
224
- """
225
- try:
226
- triangular_mesh = TriaMesh.read_vtk(path)
227
- except Exception:
228
- message = "Failed to read VTK from the following path: {path}!".format(
229
- path=path
230
- )
231
- raise RuntimeError(message)
232
- else:
233
- if triangular_mesh is None:
234
- message = "Failed to read VTK from the following path: {path}!".format(
235
- path=path
236
- )
237
- raise RuntimeError(message)
238
- return triangular_mesh
239
-
240
-
241
- def surf_to_vtk(source: Path, destination: Path) -> Path:
242
- """
243
- Converted a FreeSurfer *.surf* file to *.vtk*.
244
-
245
- Parameters
246
- ----------
247
- source : Path
248
- FreeSurfer *.surf* file.
249
- destination : Path
250
- Equivalent *.vtk* file.
251
-
252
- Returns
253
- -------
254
- Path
255
- Resulting *.vtk* file.
256
- """
257
- TriaMesh.read_fssurf(source).write_vtk(destination)
258
- return destination
@@ -1 +0,0 @@
1
- """Utilities module."""
@@ -1,112 +0,0 @@
1
- import platform
2
- import re
3
- import sys
4
- from functools import partial
5
- from importlib.metadata import requires, version
6
- from typing import IO, Callable, List, Optional
7
-
8
- import psutil
9
-
10
-
11
- def sys_info(fid: Optional[IO] = None, developer: bool = False):
12
- """Print the system information for debugging.
13
-
14
- Parameters
15
- ----------
16
- fid : file-like, default=None
17
- The file to write to, passed to :func:`print`.
18
- Can be None to use :data:`sys.stdout`.
19
- developer : bool, default=False
20
- If True, display information about optional dependencies.
21
- """
22
-
23
- ljust = 26
24
- out = partial(print, end="", file=fid)
25
- package = __package__.split(".")[0]
26
-
27
- # OS information - requires python 3.8 or above
28
- out("Platform:".ljust(ljust) + platform.platform() + "\n")
29
- # Python information
30
- out("Python:".ljust(ljust) + sys.version.replace("\n", " ") + "\n")
31
- out("Executable:".ljust(ljust) + sys.executable + "\n")
32
- # CPU information
33
- out("CPU:".ljust(ljust) + platform.processor() + "\n")
34
- out("Physical cores:".ljust(ljust) + str(psutil.cpu_count(False)) + "\n")
35
- out("Logical cores:".ljust(ljust) + str(psutil.cpu_count(True)) + "\n")
36
- # Memory information
37
- out("RAM:".ljust(ljust))
38
- out(f"{psutil.virtual_memory().total / float(2 ** 30):0.1f} GB\n")
39
- out("SWAP:".ljust(ljust))
40
- out(f"{psutil.swap_memory().total / float(2 ** 30):0.1f} GB\n")
41
-
42
- # dependencies
43
- out("\nDependencies info\n")
44
- out(f"{package}:".ljust(ljust) + version(package) + "\n")
45
- dependencies = [
46
- elt.split(";")[0].rstrip() for elt in requires(package) if "extra" not in elt
47
- ]
48
- _list_dependencies_info(out, ljust, dependencies)
49
-
50
- # extras
51
- if developer:
52
- keys = (
53
- "build",
54
- "doc",
55
- "test",
56
- "style",
57
- )
58
- for key in keys:
59
- dependencies = [
60
- elt.split(";")[0].rstrip()
61
- for elt in requires(package)
62
- if f"extra == '{key}'" in elt or f'extra == "{key}"' in elt
63
- ]
64
- if len(dependencies) == 0:
65
- continue
66
- out(f"\nOptional '{key}' info\n")
67
- _list_dependencies_info(out, ljust, dependencies)
68
-
69
-
70
- def _list_dependencies_info(out: Callable, ljust: int, dependencies: List[str]):
71
- """List dependencies names and versions.
72
-
73
- Parameters
74
- ----------
75
- out : Callable
76
- output function
77
- ljust : int
78
- length of returned string
79
- dependencies : List[str]
80
- list of dependencies
81
-
82
- """
83
-
84
- for dep in dependencies:
85
- # handle dependencies with version specifiers
86
- specifiers_pattern = r"(~=|==|!=|<=|>=|<|>|===)"
87
- specifiers = re.findall(specifiers_pattern, dep)
88
- if len(specifiers) != 0:
89
- dep, _ = dep.split(specifiers[0])
90
- while not dep[-1].isalpha():
91
- dep = dep[:-1]
92
- # handle dependencies provided with a [key], e.g. pydocstyle[toml]
93
- if "[" in dep:
94
- dep = dep.split("[")[0]
95
- try:
96
- version_ = version(dep)
97
- except Exception:
98
- version_ = "Not found."
99
-
100
- # handle special dependencies with backends, C dep, ..
101
- if dep in ("matplotlib", "seaborn") and version_ != "Not found.":
102
- try:
103
- from matplotlib import pyplot as plt
104
-
105
- backend = plt.get_backend()
106
- except Exception:
107
- backend = "Not found"
108
-
109
- out(f"{dep}:".ljust(ljust) + version_ + f" (backend: {backend})\n")
110
-
111
- else:
112
- out(f"{dep}:".ljust(ljust) + version_ + "\n")
@@ -1,188 +0,0 @@
1
- """
2
- Utilities for the :mod:`brainprint` module.
3
- """
4
- import os
5
- import shlex
6
- import subprocess
7
- from pathlib import Path
8
- from typing import Dict
9
-
10
- import numpy as np
11
- import pandas as pd
12
-
13
-
14
- def validate_environment() -> None:
15
- """
16
- Checks whether required environment variables are set.
17
- """
18
- if not os.getenv("FREESURFER_HOME"):
19
- raise RuntimeError(
20
- "FreeSurfer root directory must be set as the $FREESURFER_HOME "
21
- "environment variable!"
22
- )
23
-
24
-
25
- def test_freesurfer() -> None:
26
- """
27
- Tests FreeSurfer binarize are accessible and executable.
28
-
29
- Raises
30
- ------
31
- RuntimeError
32
- Failed to execute test FreeSurfer command
33
- """
34
- command = "mri_binarize -version"
35
- try:
36
- run_shell_command(command)
37
- except FileNotFoundError:
38
- raise RuntimeError(
39
- "Failed to run FreeSurfer command, please check the required binaries "
40
- "are included in your $PATH."
41
- )
42
-
43
-
44
- def run_shell_command(command: str, verbose: bool = False):
45
- """
46
- Execute shell command.
47
-
48
- Parameters
49
- ----------
50
- command : str
51
- Shell command to be executed
52
-
53
- Raises
54
- ------
55
- RuntimeError
56
- Shell command execution failure
57
- """
58
- if verbose:
59
- print(f"Executing command:\t{command}", end="\n")
60
- args = shlex.split(command)
61
- try:
62
- return_code = subprocess.call(args)
63
- except Exception as e:
64
- message = (
65
- "Failed to execute the following command:\n{command}\n"
66
- "The following exception was raised:\n{exception}".format(
67
- command=command, exception=e
68
- )
69
- )
70
- print(message)
71
- raise
72
- if return_code != 0:
73
- message = (
74
- "Execution of the following command:\n{command}\n"
75
- "Returned non-zero exit code!".format(command=command)
76
- )
77
- raise RuntimeError(message)
78
-
79
-
80
- def validate_subject_dir(subjects_dir: Path, subject_id: str) -> Path:
81
- """
82
- Checks the input FreeSurfer preprocessing results directory exists.
83
-
84
- Parameters
85
- ----------
86
- subjects_dir : Path
87
- FreeSurfer's subjects directory
88
- subject_id : str
89
- The subject identifier, as defined within the FreeSurfer's subjects
90
- directory
91
-
92
- Raises
93
- ------
94
- FileNotFoundError
95
- Subject results directory does not exist
96
- """
97
- subject_dir = Path(subjects_dir) / subject_id
98
- if not subject_dir.is_dir():
99
- message = "FreeSurfer results directory at {path} does not exist!".format(
100
- path=subject_dir
101
- )
102
- raise FileNotFoundError(message)
103
- return subject_dir
104
-
105
-
106
- def resolve_destination(subject_dir: Path, destination: Path = None) -> Path:
107
- if destination is None:
108
- return Path(subject_dir) / "brainprint"
109
- return destination
110
-
111
-
112
- def create_output_paths(subject_dir: Path = None, destination: Path = None) -> None:
113
- """
114
- Creates the output directories in which the BrainPrint analysis derivatives
115
- will be created. One of *subject_dir* or *destination* must be
116
- provided.
117
-
118
- Parameters
119
- ----------
120
- subject_dir : Path, optional
121
- If provided, will simply nest results in the provided directory, by
122
- default None
123
- destination : Path, optional
124
- If provided, will use this path as the results root directory, by
125
- default None
126
-
127
- Raises
128
- ------
129
- ValueError
130
- No *subject_dir* or *destination* provided
131
- """
132
- destination = resolve_destination(subject_dir, destination)
133
- destination.mkdir(parents=True, exist_ok=True)
134
- (destination / "surfaces").mkdir(parents=True, exist_ok=True)
135
- (destination / "temp").mkdir(parents=True, exist_ok=True)
136
- return destination
137
-
138
-
139
- def export_brainprint_results(
140
- destination: Path,
141
- eigenvalues: np.ndarray,
142
- eigenvectors: np.ndarray = None,
143
- distances: np.ndarray = None,
144
- ) -> Dict[str, Path]:
145
- """
146
- Writes the BrainPrint analysis results to CSV files.
147
-
148
- Parameters
149
- ----------
150
- destination : Path
151
- Eigenvalues CSV file destination
152
- eigenvalues : np.ndarray
153
- Eigenvalues
154
- eigenvectors : np.ndarray, optional
155
- Eigenvectors, by default None
156
- distances : np.ndarray, optional
157
- Distances, by default None
158
- """
159
- files = {}
160
- df = pd.DataFrame(eigenvalues).sort_index(axis=1)
161
- ev_indices = [f"ev{i}" for i in range(len(df) - 2)]
162
- df.index = ["area", "volume"] + ev_indices
163
- df.to_csv(destination, index=True, na_rep="NaN")
164
- files["eigenvalues"] = destination
165
-
166
- if eigenvectors is not None:
167
- eigenvectors_dir = destination.parent / "eigenvectors"
168
- eigenvectors_dir.mkdir(parents=True, exist_ok=True)
169
- for key, value in eigenvectors.items():
170
- suffix = ".evecs-{key}.csv".format(key=key)
171
- name = destination.with_suffix(suffix).name
172
- vectors_destination = eigenvectors_dir / name
173
- pd.DataFrame(value).to_csv(
174
- vectors_destination,
175
- index=True,
176
- na_rep="NaN",
177
- )
178
- files["eigenvectors"] = eigenvectors_dir
179
-
180
- if distances is not None:
181
- distances_destination = destination.with_suffix(".asymmetry.csv")
182
- pd.DataFrame([distances]).to_csv(
183
- distances_destination,
184
- index=False,
185
- na_rep="NaN",
186
- )
187
- files["distances"] = distances_destination
188
- return files