junifer 0.0.4.dev829__py3-none-any.whl → 0.0.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. junifer/__init__.py +17 -0
  2. junifer/_version.py +2 -2
  3. junifer/api/__init__.py +4 -1
  4. junifer/api/cli.py +91 -1
  5. junifer/api/decorators.py +9 -0
  6. junifer/api/functions.py +56 -10
  7. junifer/api/parser.py +3 -0
  8. junifer/api/queue_context/__init__.py +4 -1
  9. junifer/api/queue_context/gnu_parallel_local_adapter.py +16 -6
  10. junifer/api/queue_context/htcondor_adapter.py +16 -5
  11. junifer/api/queue_context/tests/test_gnu_parallel_local_adapter.py +41 -12
  12. junifer/api/queue_context/tests/test_htcondor_adapter.py +48 -15
  13. junifer/api/res/afni/run_afni_docker.sh +1 -1
  14. junifer/api/res/ants/run_ants_docker.sh +1 -1
  15. junifer/api/res/freesurfer/mri_binarize +3 -0
  16. junifer/api/res/freesurfer/mri_mc +3 -0
  17. junifer/api/res/freesurfer/mri_pretess +3 -0
  18. junifer/api/res/freesurfer/mris_convert +3 -0
  19. junifer/api/res/freesurfer/run_freesurfer_docker.sh +61 -0
  20. junifer/api/res/fsl/run_fsl_docker.sh +1 -1
  21. junifer/api/res/{run_conda.sh → run_conda.bash} +1 -1
  22. junifer/api/res/run_conda.zsh +23 -0
  23. junifer/api/res/run_venv.bash +22 -0
  24. junifer/api/res/{run_venv.sh → run_venv.zsh} +1 -1
  25. junifer/api/tests/test_api_utils.py +4 -2
  26. junifer/api/tests/test_cli.py +83 -0
  27. junifer/api/tests/test_functions.py +27 -2
  28. junifer/configs/__init__.py +1 -1
  29. junifer/configs/juseless/__init__.py +4 -1
  30. junifer/configs/juseless/datagrabbers/__init__.py +10 -1
  31. junifer/configs/juseless/datagrabbers/aomic_id1000_vbm.py +4 -3
  32. junifer/configs/juseless/datagrabbers/camcan_vbm.py +3 -0
  33. junifer/configs/juseless/datagrabbers/ixi_vbm.py +4 -3
  34. junifer/configs/juseless/datagrabbers/tests/test_ucla.py +1 -3
  35. junifer/configs/juseless/datagrabbers/ucla.py +12 -9
  36. junifer/configs/juseless/datagrabbers/ukb_vbm.py +3 -0
  37. junifer/data/__init__.py +21 -1
  38. junifer/data/coordinates.py +10 -19
  39. junifer/data/masks/ukb/UKB_15K_GM_template.nii.gz +0 -0
  40. junifer/data/masks.py +58 -87
  41. junifer/data/parcellations.py +14 -3
  42. junifer/data/template_spaces.py +4 -1
  43. junifer/data/tests/test_masks.py +26 -37
  44. junifer/data/utils.py +3 -0
  45. junifer/datagrabber/__init__.py +18 -1
  46. junifer/datagrabber/aomic/__init__.py +3 -0
  47. junifer/datagrabber/aomic/id1000.py +70 -37
  48. junifer/datagrabber/aomic/piop1.py +69 -36
  49. junifer/datagrabber/aomic/piop2.py +71 -38
  50. junifer/datagrabber/aomic/tests/test_id1000.py +44 -100
  51. junifer/datagrabber/aomic/tests/test_piop1.py +65 -108
  52. junifer/datagrabber/aomic/tests/test_piop2.py +45 -102
  53. junifer/datagrabber/base.py +13 -6
  54. junifer/datagrabber/datalad_base.py +13 -1
  55. junifer/datagrabber/dmcc13_benchmark.py +36 -53
  56. junifer/datagrabber/hcp1200/__init__.py +3 -0
  57. junifer/datagrabber/hcp1200/datalad_hcp1200.py +3 -0
  58. junifer/datagrabber/hcp1200/hcp1200.py +4 -1
  59. junifer/datagrabber/multiple.py +45 -6
  60. junifer/datagrabber/pattern.py +170 -62
  61. junifer/datagrabber/pattern_datalad.py +25 -12
  62. junifer/datagrabber/pattern_validation_mixin.py +388 -0
  63. junifer/datagrabber/tests/test_datalad_base.py +4 -4
  64. junifer/datagrabber/tests/test_dmcc13_benchmark.py +46 -19
  65. junifer/datagrabber/tests/test_multiple.py +161 -84
  66. junifer/datagrabber/tests/test_pattern.py +45 -0
  67. junifer/datagrabber/tests/test_pattern_datalad.py +4 -4
  68. junifer/datagrabber/tests/test_pattern_validation_mixin.py +249 -0
  69. junifer/datareader/__init__.py +4 -1
  70. junifer/datareader/default.py +95 -43
  71. junifer/external/BrainPrint/brainprint/__init__.py +4 -0
  72. junifer/external/BrainPrint/brainprint/_version.py +3 -0
  73. junifer/external/BrainPrint/brainprint/asymmetry.py +91 -0
  74. junifer/external/BrainPrint/brainprint/brainprint.py +441 -0
  75. junifer/external/BrainPrint/brainprint/surfaces.py +258 -0
  76. junifer/external/BrainPrint/brainprint/utils/__init__.py +1 -0
  77. junifer/external/BrainPrint/brainprint/utils/_config.py +112 -0
  78. junifer/external/BrainPrint/brainprint/utils/utils.py +188 -0
  79. junifer/external/__init__.py +1 -1
  80. junifer/external/nilearn/__init__.py +5 -1
  81. junifer/external/nilearn/junifer_connectivity_measure.py +483 -0
  82. junifer/external/nilearn/junifer_nifti_spheres_masker.py +23 -9
  83. junifer/external/nilearn/tests/test_junifer_connectivity_measure.py +1089 -0
  84. junifer/external/nilearn/tests/test_junifer_nifti_spheres_masker.py +76 -1
  85. junifer/markers/__init__.py +23 -1
  86. junifer/markers/base.py +68 -28
  87. junifer/markers/brainprint.py +459 -0
  88. junifer/markers/collection.py +10 -2
  89. junifer/markers/complexity/__init__.py +10 -0
  90. junifer/markers/complexity/complexity_base.py +26 -43
  91. junifer/markers/complexity/hurst_exponent.py +3 -0
  92. junifer/markers/complexity/multiscale_entropy_auc.py +3 -0
  93. junifer/markers/complexity/perm_entropy.py +3 -0
  94. junifer/markers/complexity/range_entropy.py +3 -0
  95. junifer/markers/complexity/range_entropy_auc.py +3 -0
  96. junifer/markers/complexity/sample_entropy.py +3 -0
  97. junifer/markers/complexity/tests/test_hurst_exponent.py +11 -3
  98. junifer/markers/complexity/tests/test_multiscale_entropy_auc.py +11 -3
  99. junifer/markers/complexity/tests/test_perm_entropy.py +11 -3
  100. junifer/markers/complexity/tests/test_range_entropy.py +11 -3
  101. junifer/markers/complexity/tests/test_range_entropy_auc.py +11 -3
  102. junifer/markers/complexity/tests/test_sample_entropy.py +11 -3
  103. junifer/markers/complexity/tests/test_weighted_perm_entropy.py +11 -3
  104. junifer/markers/complexity/weighted_perm_entropy.py +3 -0
  105. junifer/markers/ets_rss.py +27 -42
  106. junifer/markers/falff/__init__.py +3 -0
  107. junifer/markers/falff/_afni_falff.py +5 -2
  108. junifer/markers/falff/_junifer_falff.py +3 -0
  109. junifer/markers/falff/falff_base.py +20 -46
  110. junifer/markers/falff/falff_parcels.py +56 -27
  111. junifer/markers/falff/falff_spheres.py +60 -29
  112. junifer/markers/falff/tests/test_falff_parcels.py +39 -23
  113. junifer/markers/falff/tests/test_falff_spheres.py +39 -23
  114. junifer/markers/functional_connectivity/__init__.py +9 -0
  115. junifer/markers/functional_connectivity/crossparcellation_functional_connectivity.py +63 -60
  116. junifer/markers/functional_connectivity/edge_functional_connectivity_parcels.py +45 -32
  117. junifer/markers/functional_connectivity/edge_functional_connectivity_spheres.py +49 -36
  118. junifer/markers/functional_connectivity/functional_connectivity_base.py +71 -70
  119. junifer/markers/functional_connectivity/functional_connectivity_parcels.py +34 -25
  120. junifer/markers/functional_connectivity/functional_connectivity_spheres.py +40 -30
  121. junifer/markers/functional_connectivity/tests/test_crossparcellation_functional_connectivity.py +11 -7
  122. junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_parcels.py +27 -7
  123. junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_spheres.py +28 -12
  124. junifer/markers/functional_connectivity/tests/test_functional_connectivity_parcels.py +35 -11
  125. junifer/markers/functional_connectivity/tests/test_functional_connectivity_spheres.py +36 -62
  126. junifer/markers/parcel_aggregation.py +47 -61
  127. junifer/markers/reho/__init__.py +3 -0
  128. junifer/markers/reho/_afni_reho.py +5 -2
  129. junifer/markers/reho/_junifer_reho.py +4 -1
  130. junifer/markers/reho/reho_base.py +8 -27
  131. junifer/markers/reho/reho_parcels.py +28 -17
  132. junifer/markers/reho/reho_spheres.py +27 -18
  133. junifer/markers/reho/tests/test_reho_parcels.py +8 -3
  134. junifer/markers/reho/tests/test_reho_spheres.py +8 -3
  135. junifer/markers/sphere_aggregation.py +43 -59
  136. junifer/markers/temporal_snr/__init__.py +3 -0
  137. junifer/markers/temporal_snr/temporal_snr_base.py +23 -32
  138. junifer/markers/temporal_snr/temporal_snr_parcels.py +9 -6
  139. junifer/markers/temporal_snr/temporal_snr_spheres.py +9 -6
  140. junifer/markers/temporal_snr/tests/test_temporal_snr_parcels.py +6 -3
  141. junifer/markers/temporal_snr/tests/test_temporal_snr_spheres.py +6 -3
  142. junifer/markers/tests/test_brainprint.py +58 -0
  143. junifer/markers/tests/test_collection.py +9 -8
  144. junifer/markers/tests/test_ets_rss.py +15 -9
  145. junifer/markers/tests/test_markers_base.py +17 -18
  146. junifer/markers/tests/test_parcel_aggregation.py +93 -32
  147. junifer/markers/tests/test_sphere_aggregation.py +72 -19
  148. junifer/onthefly/__init__.py +4 -1
  149. junifer/onthefly/read_transform.py +3 -0
  150. junifer/pipeline/__init__.py +9 -1
  151. junifer/pipeline/pipeline_step_mixin.py +21 -4
  152. junifer/pipeline/registry.py +3 -0
  153. junifer/pipeline/singleton.py +3 -0
  154. junifer/pipeline/tests/test_registry.py +1 -1
  155. junifer/pipeline/update_meta_mixin.py +3 -0
  156. junifer/pipeline/utils.py +67 -1
  157. junifer/pipeline/workdir_manager.py +3 -0
  158. junifer/preprocess/__init__.py +10 -2
  159. junifer/preprocess/base.py +6 -3
  160. junifer/preprocess/confounds/__init__.py +3 -0
  161. junifer/preprocess/confounds/fmriprep_confound_remover.py +47 -60
  162. junifer/preprocess/confounds/tests/test_fmriprep_confound_remover.py +72 -113
  163. junifer/preprocess/smoothing/__init__.py +9 -0
  164. junifer/preprocess/smoothing/_afni_smoothing.py +119 -0
  165. junifer/preprocess/smoothing/_fsl_smoothing.py +116 -0
  166. junifer/preprocess/smoothing/_nilearn_smoothing.py +69 -0
  167. junifer/preprocess/smoothing/smoothing.py +174 -0
  168. junifer/preprocess/smoothing/tests/test_smoothing.py +94 -0
  169. junifer/preprocess/warping/__init__.py +3 -0
  170. junifer/preprocess/warping/_ants_warper.py +3 -0
  171. junifer/preprocess/warping/_fsl_warper.py +3 -0
  172. junifer/stats.py +4 -1
  173. junifer/storage/__init__.py +9 -1
  174. junifer/storage/base.py +40 -1
  175. junifer/storage/hdf5.py +71 -9
  176. junifer/storage/pandas_base.py +3 -0
  177. junifer/storage/sqlite.py +3 -0
  178. junifer/storage/tests/test_hdf5.py +82 -10
  179. junifer/storage/utils.py +9 -0
  180. junifer/testing/__init__.py +4 -1
  181. junifer/testing/datagrabbers.py +13 -6
  182. junifer/testing/tests/test_partlycloudytesting_datagrabber.py +7 -7
  183. junifer/testing/utils.py +3 -0
  184. junifer/utils/__init__.py +13 -2
  185. junifer/utils/fs.py +3 -0
  186. junifer/utils/helpers.py +32 -1
  187. junifer/utils/logging.py +33 -4
  188. junifer/utils/tests/test_logging.py +8 -0
  189. {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/METADATA +17 -16
  190. junifer-0.0.5.dist-info/RECORD +275 -0
  191. {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/WHEEL +1 -1
  192. junifer/datagrabber/tests/test_datagrabber_utils.py +0 -218
  193. junifer/datagrabber/utils.py +0 -230
  194. junifer/preprocess/ants/__init__.py +0 -4
  195. junifer/preprocess/ants/ants_apply_transforms_warper.py +0 -185
  196. junifer/preprocess/ants/tests/test_ants_apply_transforms_warper.py +0 -56
  197. junifer/preprocess/bold_warper.py +0 -265
  198. junifer/preprocess/fsl/__init__.py +0 -4
  199. junifer/preprocess/fsl/apply_warper.py +0 -179
  200. junifer/preprocess/fsl/tests/test_apply_warper.py +0 -45
  201. junifer/preprocess/tests/test_bold_warper.py +0 -159
  202. junifer-0.0.4.dev829.dist-info/RECORD +0 -257
  203. {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/AUTHORS.rst +0 -0
  204. {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/LICENSE.md +0 -0
  205. {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/entry_points.txt +0 -0
  206. {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/top_level.txt +0 -0
@@ -12,11 +12,11 @@ import pytest
12
12
  from junifer.api.queue_context import HTCondorAdapter
13
13
 
14
14
 
15
- def test_HTCondorAdapter_env_error() -> None:
15
+ def test_HTCondorAdapter_env_kind_error() -> None:
16
16
  """Test error for invalid env kind."""
17
17
  with pytest.raises(ValueError, match="Invalid value for `env.kind`"):
18
18
  HTCondorAdapter(
19
- job_name="check_env",
19
+ job_name="check_env_kind",
20
20
  job_dir=Path("."),
21
21
  yaml_config_path=Path("."),
22
22
  elements=["sub01"],
@@ -24,6 +24,18 @@ def test_HTCondorAdapter_env_error() -> None:
24
24
  )
25
25
 
26
26
 
27
+ def test_HTCondorAdapter_env_shell_error() -> None:
28
+ """Test error for invalid env shell."""
29
+ with pytest.raises(ValueError, match="Invalid value for `env.shell`"):
30
+ HTCondorAdapter(
31
+ job_name="check_env_shell",
32
+ job_dir=Path("."),
33
+ yaml_config_path=Path("."),
34
+ elements=["sub01"],
35
+ env={"kind": "conda", "shell": "fish"},
36
+ )
37
+
38
+
27
39
  def test_HTCondorAdapter_collect_error() -> None:
28
40
  """Test error for invalid collect option."""
29
41
  with pytest.raises(ValueError, match="Invalid value for `collect`"):
@@ -37,14 +49,18 @@ def test_HTCondorAdapter_collect_error() -> None:
37
49
 
38
50
 
39
51
  @pytest.mark.parametrize(
40
- "pre_run, expected_text",
52
+ "pre_run, expected_text, shell",
41
53
  [
42
- (None, "# Force datalad"),
43
- ("# Check this out\n", "# Check this out"),
54
+ (None, "# Force datalad", "bash"),
55
+ (None, "# Force datalad", "zsh"),
56
+ ("# Check this out\n", "# Check this out", "bash"),
57
+ ("# Check this out\n", "# Check this out", "zsh"),
44
58
  ],
45
59
  )
46
60
  def test_HTCondorAdapter_pre_run(
47
- pre_run: Optional[str], expected_text: str
61
+ pre_run: Optional[str],
62
+ expected_text: str,
63
+ shell: str,
48
64
  ) -> None:
49
65
  """Test HTCondorAdapter pre_run().
50
66
 
@@ -54,6 +70,8 @@ def test_HTCondorAdapter_pre_run(
54
70
  The parametrized pre run text.
55
71
  expected_text : str
56
72
  The parametrized expected text.
73
+ shell : str
74
+ The parametrized expected shell.
57
75
 
58
76
  """
59
77
  adapter = HTCondorAdapter(
@@ -61,22 +79,31 @@ def test_HTCondorAdapter_pre_run(
61
79
  job_dir=Path("."),
62
80
  yaml_config_path=Path("."),
63
81
  elements=["sub01"],
82
+ env={"kind": "conda", "name": "junifer", "shell": shell},
64
83
  pre_run=pre_run,
65
84
  )
85
+ assert shell in adapter.pre_run()
66
86
  assert expected_text in adapter.pre_run()
67
87
 
68
88
 
69
89
  @pytest.mark.parametrize(
70
- "pre_collect, expected_text, collect",
90
+ "pre_collect, expected_text, collect, shell",
71
91
  [
72
- (None, "exit 1", "yes"),
73
- (None, "# This script", "on_success_only"),
74
- ("# Check this out\n", "# Check this out", "yes"),
75
- ("# Check this out\n", "# Check this out", "on_success_only"),
92
+ (None, "exit 1", "yes", "bash"),
93
+ (None, "exit 1", "yes", "zsh"),
94
+ (None, "# This script", "on_success_only", "bash"),
95
+ (None, "# This script", "on_success_only", "zsh"),
96
+ ("# Check this out\n", "# Check this out", "yes", "bash"),
97
+ ("# Check this out\n", "# Check this out", "yes", "zsh"),
98
+ ("# Check this out\n", "# Check this out", "on_success_only", "bash"),
99
+ ("# Check this out\n", "# Check this out", "on_success_only", "zsh"),
76
100
  ],
77
101
  )
78
102
  def test_HTCondorAdapter_pre_collect(
79
- pre_collect: Optional[str], expected_text: str, collect: str
103
+ pre_collect: Optional[str],
104
+ expected_text: str,
105
+ collect: str,
106
+ shell: str,
80
107
  ) -> None:
81
108
  """Test HTCondorAdapter pre_collect().
82
109
 
@@ -88,6 +115,8 @@ def test_HTCondorAdapter_pre_collect(
88
115
  The parametrized expected text.
89
116
  collect : str
90
117
  The parametrized collect parameter.
118
+ shell : str
119
+ The parametrized expected shell.
91
120
 
92
121
  """
93
122
  adapter = HTCondorAdapter(
@@ -95,9 +124,11 @@ def test_HTCondorAdapter_pre_collect(
95
124
  job_dir=Path("."),
96
125
  yaml_config_path=Path("."),
97
126
  elements=["sub01"],
127
+ env={"kind": "venv", "name": "junifer", "shell": shell},
98
128
  pre_collect=pre_collect,
99
129
  collect=collect,
100
130
  )
131
+ assert shell in adapter.pre_collect()
101
132
  assert expected_text in adapter.pre_collect()
102
133
 
103
134
 
@@ -177,8 +208,10 @@ def test_HTCondor_dag(
177
208
  @pytest.mark.parametrize(
178
209
  "env",
179
210
  [
180
- {"kind": "conda", "name": "junifer"},
181
- {"kind": "venv", "name": "./junifer"},
211
+ {"kind": "conda", "name": "junifer", "shell": "bash"},
212
+ {"kind": "conda", "name": "junifer", "shell": "zsh"},
213
+ {"kind": "venv", "name": "./junifer", "shell": "bash"},
214
+ {"kind": "venv", "name": "./junifer", "shell": "zsh"},
182
215
  ],
183
216
  )
184
217
  def test_HTCondorAdapter_prepare(
@@ -215,7 +248,7 @@ def test_HTCondorAdapter_prepare(
215
248
 
216
249
  assert "Creating HTCondor job" in caplog.text
217
250
  assert "Creating logs directory" in caplog.text
218
- assert f"Copying run_{env['kind']}" in caplog.text
251
+ assert f"Copying run_{env['kind']}.{env['shell']}" in caplog.text
219
252
  assert "Writing pre_run.sh" in caplog.text
220
253
  assert "Writing run_test_prepare.submit" in caplog.text
221
254
  assert "Writing pre_collect.sh" in caplog.text
@@ -31,7 +31,7 @@ if [ -d "${var}" ]; then
31
31
  done
32
32
 
33
33
  echo "Docker args: ${docker_args[*]}" >&2
34
- echo "Corrected args for afni: ${corrected_args[*]}" >&2
34
+ echo "Corrected args for AFNI: ${corrected_args[*]}" >&2
35
35
 
36
36
  cwd=$(pwd)
37
37
  cmd="docker run --rm ${docker_args[*]} -v ${cwd}:${cwd} -w ${cwd} afni/afni_make_build ${corrected_args[*]}"
@@ -31,7 +31,7 @@ if [ -d "${var}" ]; then
31
31
  done
32
32
 
33
33
  echo "Docker args: ${docker_args[*]}" >&2
34
- echo "Corrected args for fsl: ${corrected_args[*]}" >&2
34
+ echo "Corrected args for ANTs: ${corrected_args[*]}" >&2
35
35
 
36
36
  cwd=$(pwd)
37
37
  cmd="docker run --rm ${docker_args[*]} -v ${cwd}:${cwd} -w ${cwd} antsx/ants ${corrected_args[*]}"
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+
3
+ run_freesurfer_docker.sh mri_binarize "$@"
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+
3
+ run_freesurfer_docker.sh mri_mc "$@"
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+
3
+ run_freesurfer_docker.sh mri_pretess "$@"
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+
3
+ run_freesurfer_docker.sh mris_convert "$@"
@@ -0,0 +1,61 @@
1
+ #!/bin/bash
2
+
3
+ corrected_args=()
4
+ docker_args=()
5
+ mounts=0
6
+
7
+ FS_LICENSE="${FS_LICENSE:=$HOME/freesurfer_license.txt}"
8
+
9
+ if [ -f "${FS_LICENSE}" ]; then
10
+ >&2 echo "Using freesurfer license from ${FS_LICENSE}"
11
+ else
12
+ >&2 echo "Freesurfer license not found at ${FS_LICENSE}. You can either set FS_LICENSE to the path of the license file or place the license file at
13
+ ${FS_LICENSE}"
14
+ exit 1
15
+ fi
16
+
17
+ # Map the license path to the container by binding
18
+ license_path=$(realpath "${FS_LICENSE}")
19
+ license_path_fname=$(basename "${FS_LICENSE}")
20
+ host_dir=$(dirname "${license_path}")
21
+ ((mounts+=1))
22
+ container_dir="/data/mount_${mounts}"
23
+ docker_args+=("-v ${host_dir}:${container_dir}")
24
+ export DOCKERENV_FS_LICENSE=${container_dir}/${license_path_fname}
25
+
26
+ for var in "$@"
27
+ do
28
+ if [ -d "${var}" ]; then
29
+ echo "$var is a directory" >&2
30
+ var=$(realpath "${var}")
31
+ host_dir=$(dirname "${var}")
32
+ ((mounts+=1))
33
+ container_dir="/data/mount_${mounts}"
34
+ docker_args+=("-v ${host_dir}:${container_dir}")
35
+ var=${container_dir}
36
+ elif [ -f "${var}" ] || [[ "${var}" == /* ]]; then
37
+ if [ -f "${var}" ]; then
38
+ echo "$var is a file" >&2
39
+ var=$(realpath "${var}")
40
+ else
41
+ echo "$var is a prefix" >&2
42
+ fi
43
+ fname=$(basename "${var}")
44
+ host_dir=$(dirname "${var}")
45
+ ((mounts+=1))
46
+ container_dir="/data/mount_${mounts}"
47
+ docker_args+=("-v ${host_dir}:${container_dir}")
48
+ var=${container_dir}/${fname}
49
+ fi
50
+ corrected_args+=("${var}")
51
+ done
52
+
53
+ echo "Docker args: ${docker_args[*]}" >&2
54
+ echo "Corrected args for FreeSurfer: ${corrected_args[*]}" >&2
55
+
56
+ cwd=$(pwd)
57
+ cmd="docker run --rm ${docker_args[*]} -v ${cwd}:${cwd} -w ${cwd} freesurfer/freesurfer ${corrected_args[*]}"
58
+ echo "Running command: ${cmd}" >&2
59
+ ${cmd}
60
+
61
+ unset DOCKERENV_FS_LICENSE
@@ -31,7 +31,7 @@ if [ -d "${var}" ]; then
31
31
  done
32
32
 
33
33
  echo "Docker args: ${docker_args[*]}" >&2
34
- echo "Corrected args for fsl: ${corrected_args[*]}" >&2
34
+ echo "Corrected args for FSL: ${corrected_args[*]}" >&2
35
35
 
36
36
  cwd=$(pwd)
37
37
  cmd="docker run --rm ${docker_args[*]} -v ${cwd}:${cwd} -w ${cwd} brainlife/fsl ${corrected_args[*]}"
@@ -1,4 +1,4 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env bash
2
2
 
3
3
  if [ $# -lt 2 ]; then
4
4
  echo "This script is meant to run a command within a conda environment."
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env zsh
2
+
3
+ if [ $# -lt 2 ]; then
4
+ echo "This script is meant to run a command within a conda environment."
5
+ echo "It needs at least 2 parameters."
6
+ echo "The first one must be the environment name."
7
+ echo "The rest will be the command."
8
+ exit 255
9
+ fi
10
+
11
+ eval "$(conda shell.zsh hook)"
12
+ env_name=$1
13
+ echo "Activating ${env_name}"
14
+ conda activate "${env_name}"
15
+ shift 1
16
+
17
+ if [ -f "pre_run.sh" ]; then
18
+ echo "Sourcing pre_run.sh"
19
+ . ./pre_run.sh
20
+ fi
21
+
22
+ echo "Running ${*} in conda environment"
23
+ "$@"
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env bash
2
+
3
+ if [ $# -lt 2 ]; then
4
+ echo "This script is meant to run a command within a Python virtual environment."
5
+ echo "It needs at least 2 parameters."
6
+ echo "The first one must be the virtualenv path."
7
+ echo "The rest will be the command."
8
+ exit 255
9
+ fi
10
+
11
+ env_path=$1
12
+ echo "Activating ${env_path}"
13
+ source "${env_path}"/bin/activate
14
+ shift 1
15
+
16
+ if [ -f "pre_run.sh" ]; then
17
+ echo "Sourcing pre_run.sh"
18
+ . ./pre_run.sh
19
+ fi
20
+
21
+ echo "Running ${*} in Python virtual environment"
22
+ "$@"
@@ -1,4 +1,4 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env zsh
2
2
 
3
3
  if [ $# -lt 2 ]; then
4
4
  echo "This script is meant to run a command within a Python virtual environment."
@@ -4,6 +4,7 @@
4
4
  # License: AGPL
5
5
 
6
6
  import platform as pl
7
+ import sys
7
8
 
8
9
  import pytest
9
10
 
@@ -45,11 +46,11 @@ def test_get_dependency_information_short() -> None:
45
46
  "httpx",
46
47
  "tqdm",
47
48
  "templateflow",
49
+ "lapy",
48
50
  "looseversion",
49
51
  ]
50
52
 
51
- python_minor_version = int(pl.python_version_tuple()[1])
52
- if python_minor_version < 10:
53
+ if sys.version_info < (3, 11):
53
54
  dependency_list.append("importlib_metadata")
54
55
 
55
56
  assert frozenset(dependency_information.keys()) == frozenset(
@@ -74,6 +75,7 @@ def test_get_dependency_information_long() -> None:
74
75
  "httpx",
75
76
  "tqdm",
76
77
  "templateflow",
78
+ "lapy",
77
79
  ]
78
80
  for key in dependency_list:
79
81
  assert key in dependency_information_keys
@@ -14,6 +14,7 @@ from ruamel.yaml import YAML
14
14
  from junifer.api.cli import (
15
15
  _parse_elements_file,
16
16
  collect,
17
+ list_elements,
17
18
  queue,
18
19
  reset,
19
20
  run,
@@ -297,6 +298,88 @@ def test_reset(
297
298
  assert reset_result.exit_code == 0
298
299
 
299
300
 
301
+ @pytest.mark.parametrize(
302
+ "elements",
303
+ [
304
+ ("sub-01", "sub-02"),
305
+ ("sub-03", "sub-04"),
306
+ ],
307
+ )
308
+ def test_list_elements_stdout(
309
+ elements: Tuple[str, ...],
310
+ ) -> None:
311
+ """Test elements listing to stdout.
312
+
313
+ Parameters
314
+ ----------
315
+ elements : tuple of str
316
+ The parametrized elements for filtering.
317
+
318
+ """
319
+ # Get test config
320
+ infile = Path(__file__).parent / "data" / "partly_cloudy_agg_mean_tian.yml"
321
+ # List elements command arguments
322
+ list_elements_args = [
323
+ str(infile.absolute()),
324
+ "--verbose",
325
+ "debug",
326
+ "--element",
327
+ elements[0],
328
+ "--element",
329
+ elements[1],
330
+ ]
331
+ # Invoke list elements command
332
+ list_elements_result = runner.invoke(list_elements, list_elements_args)
333
+ # Check
334
+ assert list_elements_result.exit_code == 0
335
+ assert f"{elements[0]}\n{elements[1]}" in list_elements_result.stdout
336
+
337
+
338
+ @pytest.mark.parametrize(
339
+ "elements",
340
+ [
341
+ ("sub-01", "sub-02"),
342
+ ("sub-03", "sub-04"),
343
+ ],
344
+ )
345
+ def test_list_elements_output_file(
346
+ tmp_path: Path,
347
+ elements: Tuple[str, ...],
348
+ ) -> None:
349
+ """Test elements listing to output file.
350
+
351
+ Parameters
352
+ ----------
353
+ tmp_path : pathlib.Path
354
+ The path to the test directory.
355
+ elements : tuple of str
356
+ The parametrized elements for filtering.
357
+
358
+ """
359
+ # Get test config
360
+ infile = Path(__file__).parent / "data" / "partly_cloudy_agg_mean_tian.yml"
361
+ # Output file
362
+ output_file = tmp_path / "elements.txt"
363
+ # List elements command arguments
364
+ list_elements_args = [
365
+ str(infile.absolute()),
366
+ "--verbose",
367
+ "debug",
368
+ "--element",
369
+ elements[0],
370
+ "--element",
371
+ elements[1],
372
+ "--output-file",
373
+ str(output_file.resolve()),
374
+ ]
375
+ # Invoke list elements command
376
+ list_elements_result = runner.invoke(list_elements, list_elements_args)
377
+ # Check
378
+ assert list_elements_result.exit_code == 0
379
+ with open(output_file) as f:
380
+ assert f"{elements[0]}\n{elements[1]}" == f.read()
381
+
382
+
300
383
  def test_wtf_short() -> None:
301
384
  """Test short version of wtf command."""
302
385
  # Invoke wtf command
@@ -7,13 +7,13 @@
7
7
 
8
8
  import logging
9
9
  from pathlib import Path
10
- from typing import Dict, List, Tuple, Union
10
+ from typing import Dict, List, Optional, Tuple, Union
11
11
 
12
12
  import pytest
13
13
  from ruamel.yaml import YAML
14
14
 
15
15
  import junifer.testing.registry # noqa: F401
16
- from junifer.api.functions import collect, queue, reset, run
16
+ from junifer.api.functions import collect, list_elements, queue, reset, run
17
17
  from junifer.datagrabber.base import BaseDataGrabber
18
18
  from junifer.pipeline.registry import build
19
19
 
@@ -637,3 +637,28 @@ def test_reset_queue(
637
637
 
638
638
  assert not Path(storage["uri"]).exists()
639
639
  assert not (tmp_path / "junifer_jobs" / job_name).exists()
640
+
641
+
642
+ @pytest.mark.parametrize(
643
+ "elements",
644
+ [
645
+ ["sub-01"],
646
+ None,
647
+ ],
648
+ )
649
+ def test_list_elements(
650
+ datagrabber: Dict[str, str],
651
+ elements: Optional[List[str]],
652
+ ) -> None:
653
+ """Test elements listing.
654
+
655
+ Parameters
656
+ ----------
657
+ datagrabber : dict
658
+ Testing datagrabber as dictionary.
659
+ elements : str of list of str
660
+ The parametrized elements for filtering.
661
+
662
+ """
663
+ listed_elements = list_elements(datagrabber, elements)
664
+ assert "sub-01" in listed_elements
@@ -1,4 +1,4 @@
1
- """Provide imports for configs sub-package."""
1
+ """Custom components for specific platforms."""
2
2
 
3
3
  # Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
4
4
  # License: AGPL
@@ -1,6 +1,9 @@
1
- """Provide imports for juseless sub-package."""
1
+ """Custom components for FZJ INM-7's beloved juseless."""
2
2
 
3
3
  # Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
4
4
  # License: AGPL
5
5
 
6
6
  from . import datagrabbers
7
+
8
+
9
+ __all__ = ["datagrabbers"]
@@ -1,4 +1,4 @@
1
- """Provide imports for datagrabbers sub-package."""
1
+ """Custom DataGrabbers for FZJ INM-7's beloved juseless."""
2
2
 
3
3
  # Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
4
4
  # Leonard Sasse <l.sasse@fz-juelich.de>
@@ -10,3 +10,12 @@ from .camcan_vbm import JuselessDataladCamCANVBM
10
10
  from .ixi_vbm import JuselessDataladIXIVBM
11
11
  from .ucla import JuselessUCLA
12
12
  from .ukb_vbm import JuselessDataladUKBVBM
13
+
14
+
15
+ __all__ = [
16
+ "JuselessDataladAOMICID1000VBM",
17
+ "JuselessDataladCamCANVBM",
18
+ "JuselessDataladIXIVBM",
19
+ "JuselessUCLA",
20
+ "JuselessDataladUKBVBM",
21
+ ]
@@ -11,6 +11,9 @@ from ....api.decorators import register_datagrabber
11
11
  from ....datagrabber import PatternDataladDataGrabber
12
12
 
13
13
 
14
+ __all__ = ["JuselessDataladAOMICID1000VBM"]
15
+
16
+
14
17
  @register_datagrabber
15
18
  class JuselessDataladAOMICID1000VBM(PatternDataladDataGrabber):
16
19
  """Concrete implementation for Juseless AOMIC ID1000 VBM data fetching.
@@ -32,9 +35,7 @@ class JuselessDataladAOMICID1000VBM(PatternDataladDataGrabber):
32
35
  replacements = ["subject"]
33
36
  patterns = {
34
37
  "VBM_GM": {
35
- "pattern": (
36
- "{subject}/mri/mwp1{subject}_run-2_T1w.nii.gz"
37
- ),
38
+ "pattern": ("{subject}/mri/mwp1{subject}_run-2_T1w.nii.gz"),
38
39
  "space": "IXI549Space",
39
40
  },
40
41
  }
@@ -12,6 +12,9 @@ from ....api.decorators import register_datagrabber
12
12
  from ....datagrabber import PatternDataladDataGrabber
13
13
 
14
14
 
15
+ __all__ = ["JuselessDataladCamCANVBM"]
16
+
17
+
15
18
  @register_datagrabber
16
19
  class JuselessDataladCamCANVBM(PatternDataladDataGrabber):
17
20
  """Concrete implementation for Juseless CamCAN VBM data fetching.
@@ -13,6 +13,9 @@ from ....datagrabber import PatternDataladDataGrabber
13
13
  from ....utils import raise_error
14
14
 
15
15
 
16
+ __all__ = ["JuselessDataladIXIVBM"]
17
+
18
+
16
19
  @register_datagrabber
17
20
  class JuselessDataladIXIVBM(PatternDataladDataGrabber):
18
21
  """Concrete implementation for Juseless IXI VBM data fetching.
@@ -44,9 +47,7 @@ class JuselessDataladIXIVBM(PatternDataladDataGrabber):
44
47
  replacements = ["site", "subject"]
45
48
  patterns = {
46
49
  "VBM_GM": {
47
- "pattern": (
48
- "{site}/{subject}/mri/m0wp1{subject}.nii.gz"
49
- ),
50
+ "pattern": ("{site}/{subject}/mri/m0wp1{subject}.nii.gz"),
50
51
  "space": "IXI549Space",
51
52
  },
52
53
  }
@@ -27,7 +27,6 @@ def test_JuselessUCLA() -> None:
27
27
 
28
28
  types = [
29
29
  "BOLD",
30
- "BOLD_confounds",
31
30
  "T1w",
32
31
  "VBM_CSF",
33
32
  "VBM_GM",
@@ -43,12 +42,11 @@ def test_JuselessUCLA() -> None:
43
42
  "types",
44
43
  [
45
44
  "BOLD",
46
- "BOLD_confounds",
47
45
  "T1w",
48
46
  "VBM_CSF",
49
47
  "VBM_GM",
50
48
  "VBM_WM",
51
- ["BOLD", "BOLD_confounds"],
49
+ ["BOLD", "VBM_CSF"],
52
50
  ["T1w", "VBM_CSF"],
53
51
  ["VBM_GM", "VBM_WM"],
54
52
  ["BOLD", "T1w"],
@@ -12,6 +12,9 @@ from ....datagrabber import PatternDataGrabber
12
12
  from ....utils import raise_error
13
13
 
14
14
 
15
+ __all__ = ["JuselessUCLA"]
16
+
17
+
15
18
  @register_datagrabber
16
19
  class JuselessUCLA(PatternDataGrabber):
17
20
  """Concrete implementation for Juseless UCLA data fetching.
@@ -23,8 +26,8 @@ class JuselessUCLA(PatternDataGrabber):
23
26
  datadir : str or Path, optional
24
27
  The directory where the dataset is stored.
25
28
  (default "/data/project/psychosis_thalamus/data/fmriprep").
26
- types: {"BOLD", "BOLD_confounds", "T1w", "VBM_CSF", "VBM_GM", \
27
- "VBM_WM"} or a list of the options, optional
29
+ types: {"BOLD", "T1w", "VBM_CSF", "VBM_GM", "VBM_WM"} or \
30
+ list of the options, optional
28
31
  UCLA data types. If None, all available data types are selected.
29
32
  (default None).
30
33
  tasks : {"rest", "bart", "bht", "pamenc", "pamret", \
@@ -76,13 +79,13 @@ class JuselessUCLA(PatternDataGrabber):
76
79
  "MNI152NLin2009cAsym_preproc.nii.gz"
77
80
  ),
78
81
  "space": "MNI152NLin2009cAsym",
79
- },
80
- "BOLD_confounds": {
81
- "pattern": (
82
- "{subject}/func/{subject}_"
83
- "task-{task}_bold_confounds.tsv"
84
- ),
85
- "space": "fmriprep",
82
+ "confounds": {
83
+ "pattern": (
84
+ "{subject}/func/{subject}_"
85
+ "task-{task}_bold_confounds.tsv"
86
+ ),
87
+ "space": "fmriprep",
88
+ },
86
89
  },
87
90
  "T1w": {
88
91
  "pattern": (
@@ -12,6 +12,9 @@ from ....api.decorators import register_datagrabber
12
12
  from ....datagrabber import PatternDataladDataGrabber
13
13
 
14
14
 
15
+ __all__ = ["JuselessDataladUKBVBM"]
16
+
17
+
15
18
  @register_datagrabber
16
19
  class JuselessDataladUKBVBM(PatternDataladDataGrabber):
17
20
  """Concrete implementation for Juseless UKB VBM data fetching.