junifer 0.0.7.dev332__py3-none-any.whl → 0.0.8__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 (293) hide show
  1. junifer/_version.py +9 -19
  2. junifer/api/__init__.pyi +17 -2
  3. junifer/api/functions.py +222 -39
  4. junifer/api/queue_context/__init__.pyi +11 -3
  5. junifer/api/queue_context/gnu_parallel_local_adapter.py +81 -120
  6. junifer/api/queue_context/htcondor_adapter.py +118 -181
  7. junifer/api/queue_context/queue_context_adapter.py +51 -7
  8. junifer/api/queue_context/tests/test_gnu_parallel_local_adapter.py +10 -35
  9. junifer/api/queue_context/tests/test_htcondor_adapter.py +13 -50
  10. junifer/api/res/fsl/run_fsl_docker.sh +4 -0
  11. junifer/api/tests/test_functions.py +863 -36
  12. junifer/cli/__init__.py +1 -7
  13. junifer/cli/cli.py +41 -22
  14. junifer/cli/parser.py +23 -147
  15. junifer/cli/tests/data/gmd_mean.yaml +6 -6
  16. junifer/cli/tests/data/gmd_mean_htcondor.yaml +6 -5
  17. junifer/cli/tests/data/partly_cloudy_agg_mean_tian.yml +1 -0
  18. junifer/cli/tests/test_cli.py +120 -4
  19. junifer/cli/tests/test_cli_utils.py +23 -6
  20. junifer/cli/utils.py +14 -9
  21. junifer/configs/__init__.py +5 -0
  22. junifer/configs/__init__.pyi +0 -0
  23. junifer/configs/juseless/datagrabbers/__init__.pyi +4 -2
  24. junifer/configs/juseless/datagrabbers/aomic_id1000_vbm.py +18 -24
  25. junifer/configs/juseless/datagrabbers/camcan_vbm.py +20 -27
  26. junifer/configs/juseless/datagrabbers/ixi_vbm.py +44 -52
  27. junifer/configs/juseless/datagrabbers/tests/test_ixi_vbm.py +0 -7
  28. junifer/configs/juseless/datagrabbers/tests/test_ucla.py +2 -19
  29. junifer/configs/juseless/datagrabbers/ucla.py +111 -104
  30. junifer/configs/juseless/datagrabbers/ukb_vbm.py +19 -25
  31. junifer/configs/py.typed +0 -0
  32. junifer/conftest.py +63 -24
  33. junifer/data/_dispatch.py +9 -19
  34. junifer/data/coordinates/_ants_coordinates_warper.py +4 -1
  35. junifer/data/coordinates/_coordinates.py +51 -6
  36. junifer/data/coordinates/_fsl_coordinates_warper.py +4 -1
  37. junifer/data/coordinates/tests/test_coordinates.py +15 -3
  38. junifer/data/coordinates/tests/test_coordinates_names.py +37 -0
  39. junifer/data/maps/_ants_maps_warper.py +18 -12
  40. junifer/data/maps/_fsl_maps_warper.py +7 -3
  41. junifer/data/maps/_maps.py +12 -8
  42. junifer/data/maps/tests/test_maps.py +13 -21
  43. junifer/data/masks/_ants_mask_warper.py +18 -12
  44. junifer/data/masks/_fsl_mask_warper.py +7 -3
  45. junifer/data/masks/_masks.py +15 -12
  46. junifer/data/masks/tests/test_masks.py +20 -17
  47. junifer/data/parcellations/_ants_parcellation_warper.py +18 -12
  48. junifer/data/parcellations/_fsl_parcellation_warper.py +7 -5
  49. junifer/data/parcellations/_parcellations.py +125 -91
  50. junifer/data/parcellations/tests/test_parcellations.py +122 -1
  51. junifer/data/template_spaces.py +117 -50
  52. junifer/data/tests/test_template_spaces.py +10 -7
  53. junifer/data/utils.py +10 -8
  54. junifer/datagrabber/__init__.pyi +38 -5
  55. junifer/datagrabber/aomic/__init__.pyi +8 -1
  56. junifer/datagrabber/aomic/_types.py +22 -0
  57. junifer/datagrabber/aomic/id1000.py +193 -183
  58. junifer/datagrabber/aomic/piop1.py +215 -259
  59. junifer/datagrabber/aomic/piop2.py +211 -244
  60. junifer/datagrabber/aomic/tests/test_id1000.py +70 -53
  61. junifer/datagrabber/aomic/tests/test_piop1.py +98 -102
  62. junifer/datagrabber/aomic/tests/test_piop2.py +88 -85
  63. junifer/datagrabber/base.py +253 -79
  64. junifer/datagrabber/datalad_base.py +127 -76
  65. junifer/datagrabber/dmcc13_benchmark.py +204 -289
  66. junifer/datagrabber/hcp1200/__init__.pyi +7 -2
  67. junifer/datagrabber/hcp1200/datalad_hcp1200.py +61 -40
  68. junifer/datagrabber/hcp1200/hcp1200.py +151 -164
  69. junifer/datagrabber/hcp1200/tests/test_hcp1200.py +116 -128
  70. junifer/datagrabber/multiple.py +183 -63
  71. junifer/datagrabber/pattern.py +358 -227
  72. junifer/datagrabber/pattern_datalad.py +84 -124
  73. junifer/datagrabber/pattern_validation_mixin.py +22 -50
  74. junifer/datagrabber/tests/test_base.py +17 -4
  75. junifer/datagrabber/tests/test_datalad_base.py +20 -27
  76. junifer/datagrabber/tests/test_dmcc13_benchmark.py +110 -122
  77. junifer/datagrabber/tests/test_multiple.py +293 -31
  78. junifer/datagrabber/tests/test_pattern.py +577 -18
  79. junifer/datagrabber/tests/test_pattern_datalad.py +177 -107
  80. junifer/datagrabber/tests/test_pattern_validation_mixin.py +9 -51
  81. junifer/datareader/default.py +8 -5
  82. junifer/datareader/tests/test_default_reader.py +1 -1
  83. junifer/external/BrainPrint/.codecov.yml +2 -0
  84. junifer/external/BrainPrint/.codespellignore +2 -0
  85. junifer/external/BrainPrint/.github/ISSUE_TEMPLATE/bug-report.md +45 -0
  86. junifer/external/BrainPrint/.github/ISSUE_TEMPLATE/documentation.md +12 -0
  87. junifer/external/BrainPrint/.github/ISSUE_TEMPLATE/feature-request.md +24 -0
  88. junifer/external/BrainPrint/.github/ISSUE_TEMPLATE/questions-help-support.md +28 -0
  89. junifer/external/BrainPrint/.github/dependabot.yml +6 -0
  90. junifer/external/BrainPrint/.github/workflows/build.yml +53 -0
  91. junifer/external/BrainPrint/.github/workflows/code-style.yml +44 -0
  92. junifer/external/BrainPrint/.github/workflows/doc.yml +65 -0
  93. junifer/external/BrainPrint/.github/workflows/publish.yml +31 -0
  94. junifer/external/BrainPrint/.github/workflows/pytest.yml +54 -0
  95. junifer/external/BrainPrint/.gitignore +123 -0
  96. junifer/external/BrainPrint/LICENSE +21 -0
  97. junifer/external/BrainPrint/README.md +108 -0
  98. junifer/external/BrainPrint/brainprint/cli/__init__.py +11 -0
  99. junifer/external/BrainPrint/brainprint/cli/help_text.py +169 -0
  100. junifer/external/BrainPrint/brainprint/cli/parser.py +150 -0
  101. junifer/external/BrainPrint/brainprint/cli/utils.py +14 -0
  102. junifer/external/BrainPrint/brainprint/commands/__init__.py +0 -0
  103. junifer/external/BrainPrint/brainprint/commands/sys_info.py +18 -0
  104. junifer/external/BrainPrint/brainprint/utils/tests/__init__.py +0 -0
  105. junifer/external/BrainPrint/brainprint/utils/tests/test_config.py +33 -0
  106. junifer/external/BrainPrint/doc/Makefile +20 -0
  107. junifer/external/BrainPrint/doc/_static/.gitkeep +0 -0
  108. junifer/external/BrainPrint/doc/_templates/autosummary/class.rst +10 -0
  109. junifer/external/BrainPrint/doc/_templates/autosummary/function.rst +8 -0
  110. junifer/external/BrainPrint/doc/_templates/autosummary/module.rst +6 -0
  111. junifer/external/BrainPrint/doc/api/index.rst +11 -0
  112. junifer/external/BrainPrint/doc/conf.py +272 -0
  113. junifer/external/BrainPrint/doc/index.rst +140 -0
  114. junifer/external/BrainPrint/doc/links.inc +36 -0
  115. junifer/external/BrainPrint/doc/make.bat +35 -0
  116. junifer/external/BrainPrint/doc/references.bib +23 -0
  117. junifer/external/BrainPrint/pyproject.toml +170 -0
  118. junifer/external/BrainPrint/setup.py +3 -0
  119. junifer/external/__init__.py +5 -0
  120. junifer/external/__init__.pyi +0 -0
  121. junifer/external/nilearn/junifer_connectivity_measure.py +95 -39
  122. junifer/external/nilearn/junifer_nifti_spheres_masker.py +226 -67
  123. junifer/external/nilearn/tests/test_junifer_connectivity_measure.py +39 -27
  124. junifer/external/nilearn/tests/test_junifer_nifti_spheres_masker.py +231 -21
  125. junifer/external/py.typed +0 -0
  126. junifer/markers/__init__.pyi +6 -3
  127. junifer/markers/base.py +126 -76
  128. junifer/markers/brainprint.py +30 -39
  129. junifer/markers/complexity/__init__.py +20 -3
  130. junifer/markers/complexity/complexity_base.py +40 -41
  131. junifer/markers/complexity/hurst_exponent.py +22 -35
  132. junifer/markers/complexity/multiscale_entropy_auc.py +53 -41
  133. junifer/markers/complexity/perm_entropy.py +22 -36
  134. junifer/markers/complexity/range_entropy.py +22 -35
  135. junifer/markers/complexity/range_entropy_auc.py +27 -36
  136. junifer/markers/complexity/sample_entropy.py +22 -36
  137. junifer/markers/complexity/tests/test_complexity_registry.py +48 -0
  138. junifer/markers/complexity/tests/test_hurst_exponent.py +47 -36
  139. junifer/markers/complexity/tests/test_multiscale_entropy_auc.py +50 -36
  140. junifer/markers/complexity/tests/test_perm_entropy.py +48 -36
  141. junifer/markers/complexity/tests/test_range_entropy.py +47 -36
  142. junifer/markers/complexity/tests/test_range_entropy_auc.py +47 -36
  143. junifer/markers/complexity/tests/test_sample_entropy.py +48 -36
  144. junifer/markers/complexity/tests/test_weighted_perm_entropy.py +50 -36
  145. junifer/markers/complexity/weighted_perm_entropy.py +22 -36
  146. junifer/markers/ets_rss.py +35 -31
  147. junifer/markers/falff/__init__.pyi +7 -1
  148. junifer/markers/falff/_afni_falff.py +22 -9
  149. junifer/markers/falff/_junifer_falff.py +47 -31
  150. junifer/markers/falff/falff_base.py +80 -60
  151. junifer/markers/falff/falff_maps.py +17 -41
  152. junifer/markers/falff/falff_parcels.py +26 -51
  153. junifer/markers/falff/falff_spheres.py +34 -61
  154. junifer/markers/falff/tests/test_falff_maps.py +20 -23
  155. junifer/markers/falff/tests/test_falff_mask.py +99 -0
  156. junifer/markers/falff/tests/test_falff_parcels.py +14 -10
  157. junifer/markers/falff/tests/test_falff_spheres.py +14 -10
  158. junifer/markers/functional_connectivity/crossparcellation_functional_connectivity.py +32 -34
  159. junifer/markers/functional_connectivity/edge_functional_connectivity_maps.py +12 -25
  160. junifer/markers/functional_connectivity/edge_functional_connectivity_parcels.py +19 -34
  161. junifer/markers/functional_connectivity/edge_functional_connectivity_spheres.py +24 -44
  162. junifer/markers/functional_connectivity/functional_connectivity_base.py +50 -40
  163. junifer/markers/functional_connectivity/functional_connectivity_maps.py +12 -25
  164. junifer/markers/functional_connectivity/functional_connectivity_parcels.py +19 -34
  165. junifer/markers/functional_connectivity/functional_connectivity_spheres.py +24 -45
  166. junifer/markers/functional_connectivity/tests/test_crossparcellation_functional_connectivity.py +21 -22
  167. junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_maps.py +8 -7
  168. junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_parcels.py +8 -4
  169. junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_spheres.py +8 -4
  170. junifer/markers/functional_connectivity/tests/test_functional_connectivity_maps.py +8 -7
  171. junifer/markers/functional_connectivity/tests/test_functional_connectivity_parcels.py +9 -5
  172. junifer/markers/functional_connectivity/tests/test_functional_connectivity_spheres.py +8 -12
  173. junifer/markers/maps_aggregation.py +77 -55
  174. junifer/markers/parcel_aggregation.py +91 -70
  175. junifer/markers/reho/__init__.pyi +7 -1
  176. junifer/markers/reho/_afni_reho.py +23 -14
  177. junifer/markers/reho/_junifer_reho.py +112 -123
  178. junifer/markers/reho/reho_base.py +115 -37
  179. junifer/markers/reho/reho_maps.py +18 -32
  180. junifer/markers/reho/reho_parcels.py +26 -41
  181. junifer/markers/reho/reho_spheres.py +33 -54
  182. junifer/markers/reho/tests/test_junifer_reho.py +178 -0
  183. junifer/markers/reho/tests/test_reho_maps.py +27 -25
  184. junifer/markers/reho/tests/test_reho_parcels.py +28 -22
  185. junifer/markers/reho/tests/test_reho_spheres.py +16 -12
  186. junifer/markers/sphere_aggregation.py +88 -72
  187. junifer/markers/temporal_snr/temporal_snr_base.py +32 -30
  188. junifer/markers/temporal_snr/temporal_snr_maps.py +9 -18
  189. junifer/markers/temporal_snr/temporal_snr_parcels.py +19 -27
  190. junifer/markers/temporal_snr/temporal_snr_spheres.py +27 -41
  191. junifer/markers/temporal_snr/tests/test_temporal_snr_base.py +2 -2
  192. junifer/markers/temporal_snr/tests/test_temporal_snr_maps.py +17 -22
  193. junifer/markers/temporal_snr/tests/test_temporal_snr_parcels.py +11 -3
  194. junifer/markers/temporal_snr/tests/test_temporal_snr_spheres.py +9 -9
  195. junifer/markers/tests/test_brainprint.py +10 -9
  196. junifer/markers/tests/test_ets_rss.py +7 -3
  197. junifer/markers/tests/test_lost_regions.py +279 -0
  198. junifer/markers/tests/test_maps_aggregation.py +67 -114
  199. junifer/markers/tests/test_marker_utils.py +40 -1
  200. junifer/markers/tests/test_markers_base.py +275 -6
  201. junifer/markers/tests/test_parcel_aggregation.py +91 -53
  202. junifer/markers/tests/test_sphere_aggregation.py +53 -47
  203. junifer/markers/utils.py +267 -5
  204. junifer/onthefly/__init__.py +2 -3
  205. junifer/onthefly/__init__.pyi +4 -0
  206. junifer/onthefly/_brainprint.py +3 -5
  207. junifer/onthefly/py.typed +0 -0
  208. junifer/onthefly/read_transform.py +11 -9
  209. junifer/onthefly/tests/test_read_transform.py +7 -7
  210. junifer/pipeline/__init__.pyi +4 -2
  211. junifer/pipeline/marker_collection.py +14 -10
  212. junifer/pipeline/pipeline_component_registry.py +25 -6
  213. junifer/pipeline/pipeline_step_mixin.py +5 -12
  214. junifer/pipeline/tests/test_data_object_dumper.py +10 -10
  215. junifer/pipeline/tests/test_marker_collection.py +145 -168
  216. junifer/pipeline/tests/test_pipeline_component_registry.py +52 -8
  217. junifer/pipeline/tests/test_pipeline_step_mixin.py +12 -26
  218. junifer/pipeline/tests/test_update_meta_mixin.py +4 -5
  219. junifer/pipeline/tests/test_workdir_manager.py +39 -0
  220. junifer/pipeline/update_meta_mixin.py +13 -10
  221. junifer/pipeline/utils.py +22 -17
  222. junifer/pipeline/workdir_manager.py +41 -32
  223. junifer/preprocess/__init__.pyi +9 -4
  224. junifer/preprocess/_temporal_filter.py +34 -33
  225. junifer/preprocess/_temporal_slicer.py +17 -30
  226. junifer/preprocess/base.py +99 -55
  227. junifer/preprocess/confounds/__init__.pyi +10 -2
  228. junifer/preprocess/confounds/fmriprep_confound_remover.py +87 -109
  229. junifer/preprocess/confounds/tests/test_fmriprep_confound_remover.py +64 -45
  230. junifer/preprocess/smoothing/__init__.pyi +2 -2
  231. junifer/preprocess/smoothing/_afni_smoothing.py +8 -7
  232. junifer/preprocess/smoothing/_fsl_smoothing.py +6 -4
  233. junifer/preprocess/smoothing/_nilearn_smoothing.py +7 -5
  234. junifer/preprocess/smoothing/smoothing.py +59 -40
  235. junifer/preprocess/smoothing/tests/test_smoothing.py +28 -8
  236. junifer/preprocess/tests/test_preprocess_base.py +17 -9
  237. junifer/preprocess/tests/test_temporal_filter.py +37 -16
  238. junifer/preprocess/tests/test_temporal_slicer.py +12 -12
  239. junifer/preprocess/warping/__init__.pyi +2 -2
  240. junifer/preprocess/warping/_ants_warper.py +56 -40
  241. junifer/preprocess/warping/_fsl_warper.py +49 -36
  242. junifer/preprocess/warping/_utils.py +106 -0
  243. junifer/preprocess/warping/space_warper.py +99 -98
  244. junifer/preprocess/warping/tests/test_space_warper.py +46 -41
  245. junifer/preprocess/warping/tests/test_warping_utils.py +163 -0
  246. junifer/stats.py +46 -34
  247. junifer/storage/__init__.pyi +8 -4
  248. junifer/storage/base.py +129 -64
  249. junifer/storage/hdf5.py +307 -199
  250. junifer/storage/pandas_base.py +46 -24
  251. junifer/storage/sqlite.py +99 -62
  252. junifer/storage/tests/data/collected_h5io_fork.hdf5 +0 -0
  253. junifer/storage/tests/test_hdf5.py +147 -12
  254. junifer/storage/tests/test_repeated_storage.py +293 -0
  255. junifer/storage/tests/test_sqlite.py +9 -20
  256. junifer/storage/tests/test_storage_base.py +18 -21
  257. junifer/storage/tests/test_utils.py +83 -22
  258. junifer/storage/utils.py +58 -38
  259. junifer/testing/__init__.pyi +2 -2
  260. junifer/testing/datagrabbers.py +480 -44
  261. junifer/testing/registry.py +12 -0
  262. junifer/testing/tests/test_adhdtesting_datagrabber.py +24 -0
  263. junifer/testing/tests/test_oasisvmbtesting_datagrabber.py +5 -0
  264. junifer/testing/tests/test_partlycloudytesting_datagrabber.py +52 -0
  265. junifer/testing/tests/test_spmauditory_datagrabber.py +16 -0
  266. junifer/testing/tests/test_testing_registry.py +31 -0
  267. junifer/testing/tests/test_testing_utils.py +35 -0
  268. junifer/testing/tests/test_uclacnpvbmtesting_datagrabber.py +81 -0
  269. junifer/testing/utils.py +33 -1
  270. junifer/tests/test_stats.py +1 -5
  271. junifer/typing/__init__.pyi +2 -0
  272. junifer/typing/_typing.py +34 -19
  273. junifer/typing/py.typed +0 -0
  274. junifer/utils/__init__.pyi +10 -1
  275. junifer/utils/_config.py +1 -2
  276. junifer/utils/helpers.py +68 -2
  277. junifer/utils/logging.py +31 -7
  278. junifer/utils/tests/test_helpers.py +36 -1
  279. {junifer-0.0.7.dev332.dist-info → junifer-0.0.8.dist-info}/METADATA +43 -35
  280. junifer-0.0.8.dist-info/RECORD +402 -0
  281. {junifer-0.0.7.dev332.dist-info → junifer-0.0.8.dist-info}/WHEEL +1 -1
  282. junifer/cli/tests/test_parser.py +0 -280
  283. junifer/external/h5io/h5io/__init__.py +0 -15
  284. junifer/external/h5io/h5io/_h5io.py +0 -767
  285. junifer/external/h5io/h5io/_version.py +0 -1
  286. junifer/external/h5io/h5io/chunked_array.py +0 -94
  287. junifer/external/h5io/h5io/chunked_list.py +0 -65
  288. junifer/markers/complexity/__init__.pyi +0 -17
  289. junifer-0.0.7.dev332.dist-info/RECORD +0 -353
  290. {junifer-0.0.7.dev332.dist-info → junifer-0.0.8.dist-info}/entry_points.txt +0 -0
  291. {junifer-0.0.7.dev332.dist-info → junifer-0.0.8.dist-info}/licenses/AUTHORS.rst +0 -0
  292. {junifer-0.0.7.dev332.dist-info → junifer-0.0.8.dist-info}/licenses/LICENSE.md +0 -0
  293. {junifer-0.0.7.dev332.dist-info → junifer-0.0.8.dist-info}/top_level.txt +0 -0
@@ -3,22 +3,19 @@
3
3
  # Authors: Synchon Mandal <s.mandal@fz-juelich.de>
4
4
  # License: AGPL
5
5
 
6
- from typing import TYPE_CHECKING, Callable, Optional, Union
6
+ from collections.abc import Callable
7
+ from typing import TYPE_CHECKING, Union
7
8
 
8
9
  import numpy as np
9
10
  from nilearn import image, masking
10
- from nilearn._utils.class_inspect import get_params
11
- from nilearn._utils.niimg import img_data_dtype
12
- from nilearn._utils.niimg_conversions import (
13
- check_niimg_3d,
14
- check_niimg_4d,
15
- safe_get_data,
16
- )
11
+ from nilearn._utils.niimg import img_data_dtype, safe_get_data
12
+ from nilearn.image import check_niimg_3d, check_niimg_4d, load_img
17
13
  from nilearn.maskers import NiftiSpheresMasker
18
- from nilearn.maskers.base_masker import _filter_and_extract
14
+ from nilearn.maskers.base_masker import filter_and_extract
19
15
  from sklearn import neighbors
16
+ from sklearn.utils.validation import check_is_fitted
20
17
 
21
- from ...utils import raise_error, warn_with_log
18
+ from ...utils import config, raise_error, warn_with_log
22
19
 
23
20
 
24
21
  if TYPE_CHECKING:
@@ -27,6 +24,7 @@ if TYPE_CHECKING:
27
24
  from nibabel import Nifti1Image, Nifti2Image
28
25
  from numpy.typing import ArrayLike, DTypeLike
29
26
  from pandas import DataFrame
27
+ from scipy.sparse import lil_matrix
30
28
 
31
29
 
32
30
  __all__ = ["JuniferNiftiSpheresMasker"]
@@ -65,14 +63,40 @@ __all__ = ["JuniferNiftiSpheresMasker"]
65
63
  # DAMAGE.
66
64
 
67
65
 
68
- def _apply_mask_and_get_affinity(
66
+ def _get_chunk_size() -> int:
67
+ """Get the number of volumes to read at once.
68
+
69
+ Returns
70
+ -------
71
+ int
72
+ The value of ``markers.spheres.chunksize`` (default 100).
73
+
74
+ Raises
75
+ ------
76
+ ValueError
77
+ If ``markers.spheres.chunksize`` is not a positive integer.
78
+
79
+ """
80
+ chunk_size = config.get("markers.spheres.chunksize", 100)
81
+ if (
82
+ isinstance(chunk_size, bool)
83
+ or not isinstance(chunk_size, int)
84
+ or chunk_size < 1
85
+ ):
86
+ raise_error(
87
+ "`markers.spheres.chunksize` must be a positive integer, "
88
+ f"but is {chunk_size}"
89
+ )
90
+ return chunk_size
91
+
92
+
93
+ def _get_sphere_voxels(
69
94
  seeds, niimg, radius, allow_overlap, mask_img=None
70
- ):
71
- """Apply mask and get affinity matrix for given seeds.
95
+ ) -> tuple[np.ndarray, "lil_matrix"]:
96
+ """Get the voxels of the spheres at given seed locations.
72
97
 
73
- Utility function to get only the rows which are occupied by sphere at
74
- given seed locations and the provided radius. Rows are in target_affine and
75
- target_shape space.
98
+ The voxels only depend on the geometry (and the mask), so the data of
99
+ ``niimg`` is not read.
76
100
 
77
101
  Parameters
78
102
  ----------
@@ -82,8 +106,6 @@ def _apply_mask_and_get_affinity(
82
106
  niimg : 3D/4D Niimg-like object
83
107
  See :ref:`extracting_data`.
84
108
  Images to process.
85
- If a 3D niimg is provided, a singleton dimension will be added to
86
- the output to represent the single scan in the niimg.
87
109
  radius : float
88
110
  Indicates, in millimeters, the radius for the sphere around the seed.
89
111
  allow_overlap : boolean
@@ -95,9 +117,9 @@ def _apply_mask_and_get_affinity(
95
117
 
96
118
  Returns
97
119
  -------
98
- X : 2D numpy.ndarray
99
- Signal for each brain voxel in the (masked) niimgs.
100
- shape: (number of scans, number of voxels)
120
+ voxels : 1D numpy.ndarray
121
+ The flat (C order) index in ``niimg`` of each voxel (column of ``A``):
122
+ the voxels in the mask or all the voxels if there is no mask.
101
123
  A : scipy.sparse.lil_matrix
102
124
  Contains the boolean indices for each sphere.
103
125
  shape: (number of seeds, number of voxels)
@@ -105,54 +127,38 @@ def _apply_mask_and_get_affinity(
105
127
  Raises
106
128
  ------
107
129
  ValueError
108
- If ``niimg`` and ``mask_img`` are both provided or
130
+ If ``niimg`` and ``mask_img`` are both not provided or
109
131
  if overlap is detected between spheres.
110
132
 
111
- Warns
112
- -----
113
- RuntimeWarning
114
- If the provided images contain NaN, they will be converted to zeroes.
115
-
116
133
  """
117
134
  seeds = list(seeds)
118
-
119
135
  # Compute world coordinates of all in-mask voxels.
120
136
  if niimg is None:
137
+ if mask_img is None:
138
+ raise_error("Either a niimg or a mask_img must be provided.")
121
139
  mask, affine = masking.load_mask_img(mask_img)
140
+ shape = mask.shape
122
141
  # Get coordinate for all voxels inside of mask
123
142
  mask_coords = np.asarray(np.nonzero(mask)).T.tolist()
124
- X = None
125
-
126
143
  elif mask_img is not None:
127
144
  affine = niimg.affine
145
+ shape = niimg.shape[:3]
128
146
  mask_img = check_niimg_3d(mask_img)
129
147
  mask_img = image.resample_img(
130
148
  mask_img,
131
149
  target_affine=affine,
132
- target_shape=niimg.shape[:3],
150
+ target_shape=shape,
133
151
  interpolation="nearest",
134
152
  )
135
153
  mask, _ = masking.load_mask_img(mask_img)
136
- mask_coords = list(zip(*np.where(mask != 0)))
137
-
138
- X = masking.apply_mask_fmri(niimg, mask_img)
139
-
140
- elif niimg is not None:
141
- affine = niimg.affine
142
- if np.isnan(np.sum(safe_get_data(niimg))):
143
- warn_with_log(
144
- "The imgs you have fed into fit_transform() contains NaN "
145
- "values which will be converted to zeroes."
146
- )
147
- X = safe_get_data(niimg, True).reshape([-1, niimg.shape[3]]).T
148
- else:
149
- X = safe_get_data(niimg).reshape([-1, niimg.shape[3]]).T
150
-
151
- mask_coords = list(np.ndindex(niimg.shape[:3]))
152
-
154
+ mask_coords = list(zip(*np.where(mask != 0), strict=False))
153
155
  else:
154
- raise_error("Either a niimg or a mask_img must be provided.")
155
-
156
+ affine = niimg.affine
157
+ shape = niimg.shape[:3]
158
+ mask_coords = list(np.ndindex(shape))
159
+ voxels = np.ravel_multi_index(
160
+ tuple(np.asarray(mask_coords, dtype=int).reshape(-1, 3).T), shape
161
+ )
156
162
  # For each seed, get coordinates of nearest voxel
157
163
  nearests = []
158
164
  for sx, sy, sz in seeds:
@@ -166,7 +172,7 @@ def _apply_mask_and_get_affinity(
166
172
  except ValueError:
167
173
  nearests.append(None)
168
174
 
169
- mask_coords = np.asarray(list(zip(*mask_coords)))
175
+ mask_coords = np.asarray(list(zip(*mask_coords, strict=False)))
170
176
  mask_coords = image.resampling.coord_transform(
171
177
  mask_coords[0], mask_coords[1], mask_coords[2], affine
172
178
  )
@@ -193,6 +199,132 @@ def _apply_mask_and_get_affinity(
193
199
  if (not allow_overlap) and np.any(A.sum(axis=0) >= 2):
194
200
  raise_error("Overlap detected between spheres")
195
201
 
202
+ return voxels, A
203
+
204
+
205
+ def _read_signals(niimg, voxels, masked) -> np.ndarray:
206
+ """Read the signals of some voxels, a few volumes at a time.
207
+
208
+ The data is read in chunks of ``markers.spheres.chunksize`` volumes and
209
+ only the signals of ``voxels`` are kept, so the whole data is never in
210
+ memory. The values are the same as extracting the signals from the whole
211
+ data with :func:`nilearn.masking.apply_mask_fmri` (``masked``) or
212
+ :func:`nilearn._utils.niimg.safe_get_data` (not ``masked``).
213
+
214
+ Parameters
215
+ ----------
216
+ niimg : 4D Niimg-like object
217
+ The image to read.
218
+ voxels : 1D numpy.ndarray
219
+ The flat (C order) indices of the voxels to read.
220
+ masked : bool
221
+ Whether the voxels are the ones of a mask: as
222
+ :func:`nilearn.masking.apply_mask_fmri` does, the signals are then
223
+ float32 if the data is not floating point, and the non-finite values
224
+ are set to 0. Otherwise, the signals keep the data type of the image
225
+ and the non-finite values are set to 0 only if the image has NaN
226
+ values, with a warning.
227
+
228
+ Returns
229
+ -------
230
+ numpy.ndarray of shape (number of scans, number of voxels)
231
+ The signals of the voxels.
232
+
233
+ """
234
+ n_scans = niimg.shape[3]
235
+ chunk_size = _get_chunk_size()
236
+ signals = None
237
+ has_nan = False
238
+ for start in range(0, n_scans, chunk_size):
239
+ chunk = np.asanyarray(niimg.dataobj[..., start : start + chunk_size])
240
+ if not masked and not has_nan:
241
+ has_nan = bool(np.isnan(np.sum(chunk)))
242
+ chunk = chunk.reshape(-1, chunk.shape[-1])[voxels].T
243
+ if masked and chunk.dtype.kind != "f":
244
+ chunk = chunk.astype(np.float32)
245
+ if signals is None:
246
+ signals = np.empty((n_scans, len(voxels)), dtype=chunk.dtype)
247
+ signals[start : start + chunk.shape[0]] = chunk
248
+ if masked or has_nan:
249
+ if has_nan:
250
+ warn_with_log(
251
+ "The imgs you have fed into fit_transform() contains NaN "
252
+ "values which will be converted to zeroes."
253
+ )
254
+ signals[~np.isfinite(signals)] = 0
255
+ return signals
256
+
257
+
258
+ def _apply_mask_and_get_affinity(
259
+ seeds, niimg, radius, allow_overlap, mask_img=None
260
+ ):
261
+ """Apply mask and get affinity matrix for given seeds.
262
+
263
+ Utility function to get only the rows which are occupied by sphere at
264
+ given seed locations and the provided radius. Rows are in target_affine and
265
+ target_shape space.
266
+
267
+ Parameters
268
+ ----------
269
+ seeds : List of triplets of coordinates in native space
270
+ Seed definitions. List of coordinates of the seeds in the same space
271
+ as target_affine.
272
+ niimg : 3D/4D Niimg-like object
273
+ See :ref:`extracting_data`.
274
+ Images to process.
275
+ If a 3D niimg is provided, a singleton dimension will be added to
276
+ the output to represent the single scan in the niimg.
277
+ radius : float
278
+ Indicates, in millimeters, the radius for the sphere around the seed.
279
+ allow_overlap : boolean
280
+ If False, a ValueError is raised if VOIs overlap
281
+ mask_img : Niimg-like object, optional
282
+ Mask to apply to regions before extracting signals. If niimg is None,
283
+ mask_img is used as a reference space in which the spheres 'indices are
284
+ placed.
285
+
286
+ Returns
287
+ -------
288
+ X : 2D numpy.ndarray
289
+ Signal for each brain voxel in the (masked) niimgs.
290
+ shape: (number of scans, number of voxels)
291
+ A : scipy.sparse.lil_matrix
292
+ Contains the boolean indices for each sphere.
293
+ shape: (number of seeds, number of voxels)
294
+
295
+ Raises
296
+ ------
297
+ ValueError
298
+ If ``niimg`` and ``mask_img`` are both provided or
299
+ if overlap is detected between spheres.
300
+
301
+ Warns
302
+ -----
303
+ RuntimeWarning
304
+ If the provided images contain NaN, they will be converted to zeroes.
305
+
306
+ """
307
+ _, A = _get_sphere_voxels(
308
+ seeds, niimg, radius, allow_overlap, mask_img=mask_img
309
+ )
310
+ X = None
311
+ if niimg is not None and mask_img is not None:
312
+ mask_img = image.resample_img(
313
+ check_niimg_3d(mask_img),
314
+ target_affine=niimg.affine,
315
+ target_shape=niimg.shape[:3],
316
+ interpolation="nearest",
317
+ )
318
+ X = masking.apply_mask_fmri(niimg, mask_img)
319
+ elif niimg is not None:
320
+ if np.isnan(np.sum(safe_get_data(niimg))):
321
+ warn_with_log(
322
+ "The imgs you have fed into fit_transform() contains NaN "
323
+ "values which will be converted to zeroes."
324
+ )
325
+ X = safe_get_data(niimg, True).reshape([-1, niimg.shape[3]]).T
326
+ else:
327
+ X = safe_get_data(niimg).reshape([-1, niimg.shape[3]]).T
196
328
  return X, A
197
329
 
198
330
 
@@ -201,16 +333,17 @@ def _iter_signals_from_spheres(
201
333
  ):
202
334
  """Iterate over spheres.
203
335
 
336
+ Only the signals of the voxels of the spheres are read, a few volumes at
337
+ a time (see :func:`_read_signals`), so the whole data is never in memory.
338
+
204
339
  Parameters
205
340
  ----------
206
341
  seeds : :obj:`list` of triplets of coordinates in native space
207
342
  Seed definitions. List of coordinates of the seeds in the same space
208
343
  as the images (typically MNI or TAL).
209
- niimg : 3D/4D Niimg-like object
344
+ niimg : 4D Niimg-like object
210
345
  See :ref:`extracting_data`.
211
346
  Images to process.
212
- If a 3D niimg is provided, a singleton dimension will be added to
213
- the output to represent the single scan in the niimg.
214
347
  radius: float
215
348
  Indicates, in millimeters, the radius for the sphere around the seed.
216
349
  allow_overlap: boolean
@@ -221,11 +354,17 @@ def _iter_signals_from_spheres(
221
354
  Mask to apply to regions before extracting signals.
222
355
 
223
356
  """
224
- X, A = _apply_mask_and_get_affinity(
357
+ voxels, A = _get_sphere_voxels(
225
358
  seeds, niimg, radius, allow_overlap, mask_img=mask_img
226
359
  )
227
- for row in A.rows:
228
- yield X[:, row]
360
+ rows = [np.asarray(row, dtype=int) for row in A.rows]
361
+ # The voxels of any sphere, and their position in the signals read
362
+ used = np.unique(np.concatenate([np.zeros(0, dtype=int), *rows]))
363
+ position = np.full(len(voxels), -1, dtype=int)
364
+ position[used] = np.arange(len(used))
365
+ signals = _read_signals(niimg, voxels[used], masked=mask_img is not None)
366
+ for row in rows:
367
+ yield signals[:, position[row]]
229
368
 
230
369
 
231
370
  class _JuniferExtractionFunctor:
@@ -255,7 +394,7 @@ class _JuniferExtractionFunctor:
255
394
  def __init__(
256
395
  self,
257
396
  seeds_: "ArrayLike",
258
- radius: Optional[float],
397
+ radius: float | None,
259
398
  mask_img: Union["Nifti1Image", "Nifti2Image", None],
260
399
  agg_func: Callable,
261
400
  allow_overlap: bool,
@@ -324,6 +463,11 @@ class JuniferNiftiSpheresMasker(NiftiSpheresMasker):
324
463
  * it allows to pass any callable as the ``agg_func`` parameter.
325
464
  * empty spheres do not create an error. Instead, ``agg_func`` is applied to
326
465
  an empty array and the result is passed.
466
+ * only the signals of the voxels of the spheres are read, a few volumes at
467
+ a time (``markers.spheres.chunksize``), so the whole data is never in
468
+ memory.
469
+ * ``reports`` is False by default, as the data for the reports (e.g., the
470
+ middle volume of the resampled images) needs the whole data in memory.
327
471
 
328
472
  Parameters
329
473
  ----------
@@ -352,7 +496,7 @@ class JuniferNiftiSpheresMasker(NiftiSpheresMasker):
352
496
  def __init__(
353
497
  self,
354
498
  seeds: "ArrayLike",
355
- radius: Optional[float] = None,
499
+ radius: float | None = None,
356
500
  mask_img: Union["Nifti1Image", "Nifti2Image", None] = None,
357
501
  agg_func: Callable = np.mean,
358
502
  allow_overlap: bool = False,
@@ -360,11 +504,17 @@ class JuniferNiftiSpheresMasker(NiftiSpheresMasker):
360
504
  **kwargs, # TODO: to keep or not?
361
505
  ) -> None:
362
506
  self.agg_func = agg_func
507
+ # nilearn's default (False) is deprecated, use the new equivalent
508
+ kwargs.setdefault("standardize", None)
509
+ # The reports are not used, and computing their data at fit time
510
+ # loads (and resamples) the whole data
511
+ kwargs.setdefault("reports", False)
363
512
  super().__init__(
364
513
  seeds=seeds,
365
514
  radius=radius,
366
515
  mask_img=mask_img,
367
516
  allow_overlap=allow_overlap,
517
+ dtype=dtype,
368
518
  **kwargs,
369
519
  )
370
520
 
@@ -409,16 +559,19 @@ class JuniferNiftiSpheresMasker(NiftiSpheresMasker):
409
559
  inputs.
410
560
 
411
561
  """
412
- self._check_fitted()
562
+ check_is_fitted(self)
413
563
 
414
- params = get_params(NiftiSpheresMasker, self)
415
-
416
- # New in nilearn 0.10.1
417
- if hasattr(self, "clean_kwargs"):
418
- params["clean_kwargs"] = self.clean_kwargs
564
+ # The parameters are taken from NiftiSpheresMasker, as the ones not
565
+ # in this class' signature are passed as keyword arguments
566
+ params = {
567
+ k: getattr(self, k)
568
+ for k in NiftiSpheresMasker._get_param_names()
569
+ if k not in {"memory", "memory_level", "verbose", "copy", "n_jobs"}
570
+ }
571
+ params["clean_kwargs"] = self.clean_args_
419
572
 
420
573
  signals, _ = self._cache(
421
- _filter_and_extract, ignore=["verbose", "memory", "memory_level"]
574
+ filter_and_extract, ignore=["verbose", "memory", "memory_level"]
422
575
  )(
423
576
  imgs,
424
577
  _JuniferExtractionFunctor(
@@ -434,12 +587,18 @@ class JuniferNiftiSpheresMasker(NiftiSpheresMasker):
434
587
  confounds=confounds,
435
588
  sample_mask=sample_mask,
436
589
  dtype=self.dtype,
590
+ sklearn_output_config=getattr(
591
+ self, "_sklearn_output_config", None
592
+ ),
437
593
  # Caching
438
- memory=self.memory,
594
+ memory=self.memory_,
439
595
  memory_level=self.memory_level,
440
596
  # kwargs
441
597
  verbose=self.verbose,
442
598
  )
599
+ target_dtype = self._get_target_dtype(load_img(imgs))
600
+ if target_dtype is not None:
601
+ signals = signals.astype(target_dtype)
443
602
  return signals
444
603
 
445
604
  def inverse_transform(self, region_signals: "ArrayLike") -> "Nifti1Image":
@@ -7,11 +7,15 @@ import copy
7
7
  import sys
8
8
  import warnings
9
9
  from math import cosh, exp, log, sinh, sqrt
10
- from typing import TYPE_CHECKING, Optional, Union
10
+ from typing import TYPE_CHECKING, Optional
11
11
 
12
12
  import numpy as np
13
13
  import pytest
14
14
  from nilearn.connectome.connectivity_matrices import sym_matrix_to_vec
15
+
16
+ # Not part of nilearn's public API, so it might move in future versions.
17
+ # Importing it evaluates the markers of nilearn's test module, which need to
18
+ # be registered in the pytest markers (see pyproject.toml).
15
19
  from nilearn.tests.test_signal import generate_signals
16
20
  from numpy.testing import (
17
21
  assert_allclose,
@@ -21,6 +25,7 @@ from numpy.testing import (
21
25
  from pandas import DataFrame
22
26
  from scipy import linalg
23
27
  from sklearn.covariance import EmpiricalCovariance, LedoitWolf
28
+ from sklearn.exceptions import NotFittedError
24
29
 
25
30
  from junifer.external.nilearn import JuniferConnectivityMeasure
26
31
  from junifer.external.nilearn.junifer_connectivity_measure import (
@@ -88,7 +93,7 @@ def random_diagonal(
88
93
  p: int,
89
94
  v_min: float = 1.0,
90
95
  v_max: float = 2.0,
91
- random_state: Union[int, np.random.RandomState] = 0,
96
+ random_state: int | np.random.RandomState = 0,
92
97
  ) -> np.ndarray:
93
98
  """Generate a random diagonal matrix.
94
99
 
@@ -120,7 +125,7 @@ def random_spd(
120
125
  p: int,
121
126
  eig_min: float,
122
127
  cond: float,
123
- random_state: Union[int, np.random.RandomState] = 0,
128
+ random_state: int | np.random.RandomState = 0,
124
129
  ) -> np.ndarray:
125
130
  """Generate a random symmetric positive definite matrix.
126
131
 
@@ -190,7 +195,7 @@ def signals() -> list[np.ndarray]:
190
195
 
191
196
  @pytest.fixture
192
197
  def signals_and_covariances(
193
- cov_estimator: Union[LedoitWolf, EmpiricalCovariance],
198
+ cov_estimator: LedoitWolf | EmpiricalCovariance,
194
199
  ) -> tuple[list[np.ndarray], list[float]]:
195
200
  """Return signals and covariances for a covariance estimator.
196
201
 
@@ -343,7 +348,7 @@ def test_geometric_mean_properties() -> None:
343
348
 
344
349
  # Generic
345
350
  assert isinstance(spds, list)
346
- for spd, input_spd in zip(spds, input_spds):
351
+ for spd, input_spd in zip(spds, input_spds, strict=False):
347
352
  assert_array_equal(spd, input_spd)
348
353
  assert is_spd(gmean, decimal=7)
349
354
 
@@ -352,7 +357,7 @@ def random_non_singular(
352
357
  p: int,
353
358
  sing_min: float = 1.0,
354
359
  sing_max: float = 2.0,
355
- random_state: Union[int, np.random.RandomState] = 0,
360
+ random_state: int | np.random.RandomState = 0,
356
361
  ) -> np.ndarray:
357
362
  """Generate a random nonsingular matrix.
358
363
 
@@ -587,9 +592,7 @@ def test_connectivity_measure_errors():
587
592
  # Raising error for input subjects not iterable
588
593
  conn_measure = JuniferConnectivityMeasure()
589
594
 
590
- with pytest.raises(
591
- ValueError, match=r"'subjects' input argument must be an iterable"
592
- ):
595
+ with pytest.raises(TypeError, match=r"Input must be an iterable"):
593
596
  conn_measure.fit(1.0)
594
597
 
595
598
  # input subjects not 2D numpy.ndarrays
@@ -605,6 +608,15 @@ def test_connectivity_measure_errors():
605
608
  ):
606
609
  conn_measure.fit([np.ones((100, 40)), np.ones((100, 41))])
607
610
 
611
+ # invalid kind, listing all the allowed kinds
612
+ conn_measure = JuniferConnectivityMeasure(kind="foo")
613
+ with pytest.raises(
614
+ ValueError,
615
+ match=r"Allowed connectivity kinds .*'spearman correlation'.*"
616
+ r"'xi correlation'.* Got kind foo",
617
+ ):
618
+ conn_measure.fit([np.ones((100, 40))])
619
+
608
620
  # fit_transform with a single subject and kind=tangent
609
621
  conn_measure = JuniferConnectivityMeasure(kind="tangent")
610
622
 
@@ -669,7 +681,7 @@ def _assert_connectivity_tangent(connectivities, conn_measure, covs) -> None:
669
681
 
670
682
  """
671
683
  for true_covariance_matrix, estimated_covariance_matrix in zip(
672
- covs, connectivities
684
+ covs, connectivities, strict=False
673
685
  ):
674
686
  assert_array_almost_equal(
675
687
  estimated_covariance_matrix, estimated_covariance_matrix.T
@@ -701,7 +713,7 @@ def _assert_connectivity_precision(connectivities, covs) -> None:
701
713
 
702
714
  """
703
715
  for true_covariance_matrix, estimated_covariance_matrix in zip(
704
- covs, connectivities
716
+ covs, connectivities, strict=False
705
717
  ):
706
718
  assert is_spd(estimated_covariance_matrix, decimal=7)
707
719
  assert_array_almost_equal(
@@ -729,7 +741,7 @@ def _assert_connectivity_correlation(
729
741
 
730
742
  """
731
743
  for true_covariance_matrix, estimated_covariance_matrix in zip(
732
- covs, connectivities
744
+ covs, connectivities, strict=False
733
745
  ):
734
746
  assert is_spd(estimated_covariance_matrix, decimal=7)
735
747
 
@@ -750,7 +762,7 @@ def _assert_connectivity_correlation(
750
762
  def _assert_connectivity_partial_correlation(connectivities, covs) -> None:
751
763
  """Assert partial correlation connectivity matrix."""
752
764
  for true_covariance_matrix, estimated_covariance_matrix in zip(
753
- covs, connectivities
765
+ covs, connectivities, strict=False
754
766
  ):
755
767
  precision_matrix = linalg.inv(true_covariance_matrix)
756
768
 
@@ -874,7 +886,7 @@ def test_connectivity_measure_check_vectorization_option(
874
886
  )
875
887
 
876
888
  # Check not fitted error
877
- with pytest.raises(ValueError, match=r"has not been fitted. "):
889
+ with pytest.raises(NotFittedError):
878
890
  JuniferConnectivityMeasure().inverse_transform(
879
891
  vectorized_connectivities
880
892
  )
@@ -1053,15 +1065,15 @@ def test_confounds_connectivity_measure_errors() -> None:
1053
1065
  conn_measure = JuniferConnectivityMeasure(vectorize=True)
1054
1066
  msg = r"'confounds' input argument must be an iterable"
1055
1067
 
1056
- with pytest.raises(ValueError, match=msg):
1068
+ with pytest.raises(TypeError, match=msg):
1057
1069
  conn_measure._check_input(X=signals, confounds=1.0)
1058
1070
 
1059
- with pytest.raises(ValueError, match=msg):
1071
+ with pytest.raises(TypeError, match=msg):
1060
1072
  conn_measure._fit_transform(
1061
1073
  X=signals, do_fit=True, do_transform=True, confounds=1.0
1062
1074
  )
1063
1075
 
1064
- with pytest.raises(ValueError, match=msg):
1076
+ with pytest.raises(TypeError, match=msg):
1065
1077
  conn_measure.fit_transform(X=signals, y=None, confounds=1.0)
1066
1078
 
1067
1079
  # Raising error for input confounds are given but not vectorize=True
@@ -1075,7 +1087,7 @@ def test_confounds_connectivity_measure_errors() -> None:
1075
1087
  def test_connectivity_measure_standardize(
1076
1088
  signals: list[np.ndarray],
1077
1089
  ) -> None:
1078
- """Check warning is raised and then suppressed with setting standardize.
1090
+ """Check standardize strategies and the error for booleans.
1079
1091
 
1080
1092
  Parameters
1081
1093
  ----------
@@ -1083,17 +1095,17 @@ def test_connectivity_measure_standardize(
1083
1095
  The input signals.
1084
1096
 
1085
1097
  """
1086
- match = r"default strategy for standardize"
1087
-
1088
- with pytest.warns(DeprecationWarning, match=match):
1098
+ # No warnings about standardize with the default strategy
1099
+ with warnings.catch_warnings(record=True) as record:
1100
+ warnings.simplefilter("always")
1089
1101
  JuniferConnectivityMeasure(kind="correlation").fit_transform(signals)
1102
+ assert not [m for m in record if "standardize" in str(m.message)]
1090
1103
 
1091
- with warnings.catch_warnings(record=True) as record:
1092
- JuniferConnectivityMeasure(
1093
- kind="correlation", standardize="zscore_sample"
1094
- ).fit_transform(signals)
1095
- for m in record:
1096
- assert match not in m.message
1104
+ for standardize in (True, False):
1105
+ with pytest.raises(ValueError, match="does not accept booleans"):
1106
+ JuniferConnectivityMeasure(
1107
+ kind="correlation", standardize=standardize
1108
+ ).fit_transform(signals)
1097
1109
 
1098
1110
 
1099
1111
  @pytest.mark.skipif(