junifer 0.0.6.dev175__py3-none-any.whl → 0.0.6.dev201__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 (78) hide show
  1. junifer/_version.py +2 -2
  2. junifer/data/__init__.pyi +17 -31
  3. junifer/data/_dispatch.py +251 -0
  4. junifer/data/coordinates/__init__.py +9 -0
  5. junifer/data/coordinates/__init__.pyi +5 -0
  6. junifer/data/coordinates/_ants_coordinates_warper.py +96 -0
  7. junifer/data/coordinates/_coordinates.py +356 -0
  8. junifer/data/coordinates/_fsl_coordinates_warper.py +83 -0
  9. junifer/data/{tests → coordinates/tests}/test_coordinates.py +25 -31
  10. junifer/data/masks/__init__.py +9 -0
  11. junifer/data/masks/__init__.pyi +6 -0
  12. junifer/data/masks/_ants_mask_warper.py +144 -0
  13. junifer/data/masks/_fsl_mask_warper.py +87 -0
  14. junifer/data/masks/_masks.py +624 -0
  15. junifer/data/{tests → masks/tests}/test_masks.py +63 -58
  16. junifer/data/parcellations/__init__.py +9 -0
  17. junifer/data/parcellations/__init__.pyi +6 -0
  18. junifer/data/parcellations/_ants_parcellation_warper.py +154 -0
  19. junifer/data/parcellations/_fsl_parcellation_warper.py +91 -0
  20. junifer/data/{parcellations.py → parcellations/_parcellations.py} +450 -473
  21. junifer/data/{tests → parcellations/tests}/test_parcellations.py +73 -81
  22. junifer/data/pipeline_data_registry_base.py +74 -0
  23. junifer/data/utils.py +4 -0
  24. junifer/markers/complexity/hurst_exponent.py +2 -2
  25. junifer/markers/complexity/multiscale_entropy_auc.py +2 -2
  26. junifer/markers/complexity/perm_entropy.py +2 -2
  27. junifer/markers/complexity/range_entropy.py +2 -2
  28. junifer/markers/complexity/range_entropy_auc.py +2 -2
  29. junifer/markers/complexity/sample_entropy.py +2 -2
  30. junifer/markers/complexity/weighted_perm_entropy.py +2 -2
  31. junifer/markers/ets_rss.py +2 -2
  32. junifer/markers/falff/falff_parcels.py +2 -2
  33. junifer/markers/falff/falff_spheres.py +2 -2
  34. junifer/markers/functional_connectivity/edge_functional_connectivity_parcels.py +1 -1
  35. junifer/markers/functional_connectivity/edge_functional_connectivity_spheres.py +1 -1
  36. junifer/markers/functional_connectivity/functional_connectivity_parcels.py +1 -1
  37. junifer/markers/functional_connectivity/functional_connectivity_spheres.py +1 -1
  38. junifer/markers/functional_connectivity/tests/test_functional_connectivity_parcels.py +3 -3
  39. junifer/markers/functional_connectivity/tests/test_functional_connectivity_spheres.py +2 -2
  40. junifer/markers/parcel_aggregation.py +11 -7
  41. junifer/markers/reho/reho_parcels.py +2 -2
  42. junifer/markers/reho/reho_spheres.py +2 -2
  43. junifer/markers/sphere_aggregation.py +11 -7
  44. junifer/markers/temporal_snr/temporal_snr_parcels.py +2 -2
  45. junifer/markers/temporal_snr/temporal_snr_spheres.py +2 -2
  46. junifer/markers/tests/test_ets_rss.py +3 -3
  47. junifer/markers/tests/test_parcel_aggregation.py +24 -24
  48. junifer/markers/tests/test_sphere_aggregation.py +6 -6
  49. junifer/pipeline/pipeline_component_registry.py +1 -1
  50. junifer/preprocess/confounds/fmriprep_confound_remover.py +6 -3
  51. {junifer-0.0.6.dev175.dist-info → junifer-0.0.6.dev201.dist-info}/METADATA +1 -1
  52. {junifer-0.0.6.dev175.dist-info → junifer-0.0.6.dev201.dist-info}/RECORD +76 -62
  53. {junifer-0.0.6.dev175.dist-info → junifer-0.0.6.dev201.dist-info}/WHEEL +1 -1
  54. junifer/data/coordinates.py +0 -408
  55. junifer/data/masks.py +0 -670
  56. /junifer/data/{VOIs → coordinates/VOIs}/meta/AutobiographicalMemory_VOIs.txt +0 -0
  57. /junifer/data/{VOIs → coordinates/VOIs}/meta/CogAC_VOIs.txt +0 -0
  58. /junifer/data/{VOIs → coordinates/VOIs}/meta/CogAR_VOIs.txt +0 -0
  59. /junifer/data/{VOIs → coordinates/VOIs}/meta/DMNBuckner_VOIs.txt +0 -0
  60. /junifer/data/{VOIs → coordinates/VOIs}/meta/Dosenbach2010_MNI_VOIs.txt +0 -0
  61. /junifer/data/{VOIs → coordinates/VOIs}/meta/Empathy_VOIs.txt +0 -0
  62. /junifer/data/{VOIs → coordinates/VOIs}/meta/Motor_VOIs.txt +0 -0
  63. /junifer/data/{VOIs → coordinates/VOIs}/meta/MultiTask_VOIs.txt +0 -0
  64. /junifer/data/{VOIs → coordinates/VOIs}/meta/PhysioStress_VOIs.txt +0 -0
  65. /junifer/data/{VOIs → coordinates/VOIs}/meta/Power2011_MNI_VOIs.txt +0 -0
  66. /junifer/data/{VOIs → coordinates/VOIs}/meta/Power2013_MNI_VOIs.tsv +0 -0
  67. /junifer/data/{VOIs → coordinates/VOIs}/meta/Rew_VOIs.txt +0 -0
  68. /junifer/data/{VOIs → coordinates/VOIs}/meta/Somatosensory_VOIs.txt +0 -0
  69. /junifer/data/{VOIs → coordinates/VOIs}/meta/ToM_VOIs.txt +0 -0
  70. /junifer/data/{VOIs → coordinates/VOIs}/meta/VigAtt_VOIs.txt +0 -0
  71. /junifer/data/{VOIs → coordinates/VOIs}/meta/WM_VOIs.txt +0 -0
  72. /junifer/data/{VOIs → coordinates/VOIs}/meta/eMDN_VOIs.txt +0 -0
  73. /junifer/data/{VOIs → coordinates/VOIs}/meta/eSAD_VOIs.txt +0 -0
  74. /junifer/data/{VOIs → coordinates/VOIs}/meta/extDMN_VOIs.txt +0 -0
  75. {junifer-0.0.6.dev175.dist-info → junifer-0.0.6.dev201.dist-info}/AUTHORS.rst +0 -0
  76. {junifer-0.0.6.dev175.dist-info → junifer-0.0.6.dev201.dist-info}/LICENSE.md +0 -0
  77. {junifer-0.0.6.dev175.dist-info → junifer-0.0.6.dev201.dist-info}/entry_points.txt +0 -0
  78. {junifer-0.0.6.dev175.dist-info → junifer-0.0.6.dev201.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,356 @@
1
+ """Provide a class for centralized coordinates data registry."""
2
+
3
+ # Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
4
+ # Synchon Mandal <s.mandal@fz-juelich.de>
5
+ # License: AGPL
6
+
7
+ from pathlib import Path
8
+ from typing import Any, Dict, List, Optional, Tuple
9
+
10
+ import numpy as np
11
+ import pandas as pd
12
+ from numpy.typing import ArrayLike
13
+
14
+ from ...pipeline.singleton import singleton
15
+ from ...utils import logger, raise_error
16
+ from ..pipeline_data_registry_base import BasePipelineDataRegistry
17
+ from ._ants_coordinates_warper import ANTsCoordinatesWarper
18
+ from ._fsl_coordinates_warper import FSLCoordinatesWarper
19
+
20
+
21
+ __all__ = ["CoordinatesRegistry"]
22
+
23
+
24
+ @singleton
25
+ class CoordinatesRegistry(BasePipelineDataRegistry):
26
+ """Class for coordinates data registry.
27
+
28
+ This class is a singleton and is used for managing available coordinates
29
+ data in a centralized manner.
30
+
31
+ """
32
+
33
+ def __init__(self) -> None:
34
+ """Initialize the class."""
35
+ # Each entry in registry is a dictionary that must contain at least
36
+ # the following keys:
37
+ # * 'space': the coordinates' space (e.g., 'MNI')
38
+ # The built-in coordinates are files that are shipped with the package
39
+ # in the data/VOIs directory. The user can also register their own
40
+ # coordinates, which will be stored as numpy arrays in the dictionary.
41
+ # Make built-in and external dictionaries for validation later
42
+ self._builtin = {}
43
+ self._external = {}
44
+
45
+ # Path to the metadata of the VOIs
46
+ _vois_meta_path = Path(__file__).parent / "VOIs" / "meta"
47
+
48
+ self._builtin = {
49
+ "CogAC": {
50
+ "path": _vois_meta_path / "CogAC_VOIs.txt",
51
+ "space": "MNI",
52
+ },
53
+ "CogAR": {
54
+ "path": _vois_meta_path / "CogAR_VOIs.txt",
55
+ "space": "MNI",
56
+ },
57
+ "DMNBuckner": {
58
+ "path": _vois_meta_path / "DMNBuckner_VOIs.txt",
59
+ "space": "MNI",
60
+ },
61
+ "eMDN": {
62
+ "path": _vois_meta_path / "eMDN_VOIs.txt",
63
+ "space": "MNI",
64
+ },
65
+ "Empathy": {
66
+ "path": _vois_meta_path / "Empathy_VOIs.txt",
67
+ "space": "MNI",
68
+ },
69
+ "eSAD": {
70
+ "path": _vois_meta_path / "eSAD_VOIs.txt",
71
+ "space": "MNI",
72
+ },
73
+ "extDMN": {
74
+ "path": _vois_meta_path / "extDMN_VOIs.txt",
75
+ "space": "MNI",
76
+ },
77
+ "Motor": {
78
+ "path": _vois_meta_path / "Motor_VOIs.txt",
79
+ "space": "MNI",
80
+ },
81
+ "MultiTask": {
82
+ "path": _vois_meta_path / "MultiTask_VOIs.txt",
83
+ "space": "MNI",
84
+ },
85
+ "PhysioStress": {
86
+ "path": _vois_meta_path / "PhysioStress_VOIs.txt",
87
+ "space": "MNI",
88
+ },
89
+ "Rew": {
90
+ "path": _vois_meta_path / "Rew_VOIs.txt",
91
+ "space": "MNI",
92
+ },
93
+ "Somatosensory": {
94
+ "path": _vois_meta_path / "Somatosensory_VOIs.txt",
95
+ "space": "MNI",
96
+ },
97
+ "ToM": {
98
+ "path": _vois_meta_path / "ToM_VOIs.txt",
99
+ "space": "MNI",
100
+ },
101
+ "VigAtt": {
102
+ "path": _vois_meta_path / "VigAtt_VOIs.txt",
103
+ "space": "MNI",
104
+ },
105
+ "WM": {
106
+ "path": _vois_meta_path / "WM_VOIs.txt",
107
+ "space": "MNI",
108
+ },
109
+ "Power": {
110
+ "path": _vois_meta_path / "Power2011_MNI_VOIs.txt",
111
+ "space": "MNI",
112
+ },
113
+ "Power2011": {
114
+ "path": _vois_meta_path / "Power2011_MNI_VOIs.txt",
115
+ "space": "MNI",
116
+ },
117
+ "Dosenbach": {
118
+ "path": _vois_meta_path / "Dosenbach2010_MNI_VOIs.txt",
119
+ "space": "MNI",
120
+ },
121
+ "Power2013": {
122
+ "path": _vois_meta_path / "Power2013_MNI_VOIs.tsv",
123
+ "space": "MNI",
124
+ },
125
+ "AutobiographicalMemory": {
126
+ "path": _vois_meta_path / "AutobiographicalMemory_VOIs.txt",
127
+ "space": "MNI",
128
+ },
129
+ }
130
+
131
+ # Set built-in to registry
132
+ self._registry = self._builtin
133
+
134
+ def register(
135
+ self,
136
+ name: str,
137
+ coordinates: ArrayLike,
138
+ voi_names: List[str],
139
+ space: str,
140
+ overwrite: Optional[bool] = False,
141
+ ) -> None:
142
+ """Register a custom user coordinates.
143
+
144
+ Parameters
145
+ ----------
146
+ name : str
147
+ The name of the coordinates.
148
+ coordinates : numpy.ndarray
149
+ The coordinates. This should be a 2-dimensional array with three
150
+ columns. Each row corresponds to a volume-of-interest (VOI) and
151
+ each column corresponds to a spatial dimension (i.e. x, y, and
152
+ z-coordinates).
153
+ voi_names : list of str
154
+ The names of the VOIs.
155
+ space : str
156
+ The space of the coordinates, e.g., "MNI".
157
+ overwrite : bool, optional
158
+ If True, overwrite an existing list of coordinates with the same
159
+ name. Does not apply to built-in coordinates (default False).
160
+
161
+ Raises
162
+ ------
163
+ ValueError
164
+ If the coordinates ``name`` is already registered and
165
+ ``overwrite=False`` or
166
+ if the coordinates ``name`` is a built-in coordinates or
167
+ if the ``coordinates`` is not a 2D array or
168
+ if coordinate value does not have 3 components or
169
+ if the ``voi_names`` shape does not match the
170
+ ``coordinates`` shape.
171
+ TypeError
172
+ If ``coordinates`` is not a ``numpy.ndarray``.
173
+
174
+ """
175
+ # Check for attempt of overwriting built-in coordinates
176
+ if name in self._builtin:
177
+ if isinstance(self._registry[name].get("path"), Path):
178
+ raise_error(
179
+ f"Coordinates: {name} already registered as built-in "
180
+ "coordinates."
181
+ )
182
+ if overwrite:
183
+ logger.info(f"Overwriting coordinates: {name}")
184
+ else:
185
+ raise_error(
186
+ f"Coordinates: {name} already registered. "
187
+ "Set `overwrite=True` to update its value."
188
+ )
189
+
190
+ if not isinstance(coordinates, np.ndarray):
191
+ raise_error(
192
+ "Coordinates must be a `numpy.ndarray`, "
193
+ f"not {type(coordinates)}.",
194
+ klass=TypeError,
195
+ )
196
+ if coordinates.ndim != 2:
197
+ raise_error(
198
+ f"Coordinates must be a 2D array, not {coordinates.ndim}D."
199
+ )
200
+ if coordinates.shape[1] != 3:
201
+ raise_error(
202
+ "Each coordinate must have 3 values, "
203
+ f"not {coordinates.shape[1]}"
204
+ )
205
+ if len(voi_names) != coordinates.shape[0]:
206
+ raise_error(
207
+ f"Length of `voi_names` ({len(voi_names)}) does not match the "
208
+ f"number of `coordinates` ({coordinates.shape[0]})."
209
+ )
210
+ logger.info(f"Registering coordinates: {name}")
211
+ # Add coordinates info
212
+ self._external[name] = {
213
+ "coords": coordinates,
214
+ "voi_names": voi_names,
215
+ "space": space,
216
+ }
217
+ # Update registry
218
+ self._registry[name] = {
219
+ "coords": coordinates,
220
+ "voi_names": voi_names,
221
+ "space": space,
222
+ }
223
+
224
+ def deregister(self, name: str) -> None:
225
+ """De-register a custom user coordinates.
226
+
227
+ Parameters
228
+ ----------
229
+ name : str
230
+ The name of the coordinates.
231
+
232
+ """
233
+ logger.info(f"De-registering coordinates: {name}")
234
+ # Remove coordinates info
235
+ _ = self._external.pop(name)
236
+ # Update registry
237
+ _ = self._registry.pop(name)
238
+
239
+ def load(self, name: str) -> Tuple[ArrayLike, List[str], str]:
240
+ """Load coordinates.
241
+
242
+ Parameters
243
+ ----------
244
+ name : str
245
+ The name of the coordinates.
246
+
247
+ Returns
248
+ -------
249
+ numpy.ndarray
250
+ The coordinates.
251
+ list of str
252
+ The names of the VOIs.
253
+ str
254
+ The space of the coordinates.
255
+
256
+ Raises
257
+ ------
258
+ ValueError
259
+ If ``name`` is invalid.
260
+
261
+ """
262
+ # Check for valid coordinates name
263
+ if name not in self._registry:
264
+ raise_error(
265
+ f"Coordinates: {name} not found. "
266
+ f"Valid options are: {self.list}"
267
+ )
268
+ # Load coordinates
269
+ t_coord = self._registry[name]
270
+ # Load data
271
+ if isinstance(t_coord.get("path"), Path):
272
+ logger.debug(f"Loading coordinates {t_coord['path'].absolute()!s}")
273
+ # Load via pandas
274
+ df_coords = pd.read_csv(t_coord["path"], sep="\t", header=None)
275
+ # Convert dataframe to numpy ndarray
276
+ coords = df_coords.iloc[:, [0, 1, 2]].to_numpy()
277
+ # Get label names
278
+ names = list(df_coords.iloc[:, [3]].values[:, 0])
279
+ else:
280
+ coords = t_coord["coords"]
281
+ names = t_coord["voi_names"]
282
+
283
+ return coords, names, t_coord["space"]
284
+
285
+ def get(
286
+ self,
287
+ coords: str,
288
+ target_data: Dict[str, Any],
289
+ extra_input: Optional[Dict[str, Any]] = None,
290
+ ) -> Tuple[ArrayLike, List[str]]:
291
+ """Get coordinates, tailored for the target data.
292
+
293
+ Parameters
294
+ ----------
295
+ coords : str
296
+ The name of the coordinates.
297
+ target_data : dict
298
+ The corresponding item of the data object to which the coordinates
299
+ will be applied.
300
+ extra_input : dict, optional
301
+ The other fields in the data object. Useful for accessing other
302
+ data kinds that needs to be used in the computation of coordinates
303
+ (default None).
304
+
305
+ Returns
306
+ -------
307
+ numpy.ndarray
308
+ The coordinates.
309
+ list of str
310
+ The names of the VOIs.
311
+
312
+ Raises
313
+ ------
314
+ RuntimeError
315
+ If warp / transformation file extension is not ".mat" or ".h5".
316
+ ValueError
317
+ If ``extra_input`` is None when ``target_data``'s space is native.
318
+
319
+ """
320
+ # Load the coordinates
321
+ seeds, labels, _ = self.load(name=coords)
322
+
323
+ # Transform coordinate if target data is native
324
+ if target_data["space"] == "native":
325
+ # Check for extra inputs
326
+ if extra_input is None:
327
+ raise_error(
328
+ "No extra input provided, requires `Warp` and `T1w` "
329
+ "data types in particular for transformation to "
330
+ f"{target_data['space']} space for further computation."
331
+ )
332
+
333
+ # Check for warp file type to use correct tool
334
+ warp_file_ext = extra_input["Warp"]["path"].suffix
335
+ if warp_file_ext == ".mat":
336
+ seeds = FSLCoordinatesWarper().warp(
337
+ seeds=seeds,
338
+ target_data=target_data,
339
+ extra_input=extra_input,
340
+ )
341
+ elif warp_file_ext == ".h5":
342
+ seeds = ANTsCoordinatesWarper().warp(
343
+ seeds=seeds,
344
+ target_data=target_data,
345
+ extra_input=extra_input,
346
+ )
347
+ else:
348
+ raise_error(
349
+ msg=(
350
+ "Unknown warp / transformation file extension: "
351
+ f"{warp_file_ext}"
352
+ ),
353
+ klass=RuntimeError,
354
+ )
355
+
356
+ return seeds, labels
@@ -0,0 +1,83 @@
1
+ """Provide class for coordinates space warping via FSL FLIRT."""
2
+
3
+ # Authors: Synchon Mandal <s.mandal@fz-juelich.de>
4
+ # License: AGPL
5
+
6
+ from typing import Any, Dict
7
+
8
+ import numpy as np
9
+ from numpy.typing import ArrayLike
10
+
11
+ from ...pipeline import WorkDirManager
12
+ from ...utils import logger, run_ext_cmd
13
+
14
+
15
+ __all__ = ["FSLCoordinatesWarper"]
16
+
17
+
18
+ class FSLCoordinatesWarper:
19
+ """Class for coordinates space warping via FSL FLIRT.
20
+
21
+ This class uses FSL FLIRT's ``img2imgcoord`` for transformation.
22
+
23
+ """
24
+
25
+ def warp(
26
+ self,
27
+ seeds: ArrayLike,
28
+ target_data: Dict[str, Any],
29
+ extra_input: Dict[str, Any],
30
+ ) -> ArrayLike:
31
+ """Warp ``seeds`` to correct space.
32
+
33
+ Parameters
34
+ ----------
35
+ seeds : array-like
36
+ The coordinates to transform.
37
+ target_data : dict
38
+ The corresponding item of the data object to which the coordinates
39
+ will be applied.
40
+ extra_input : dict, optional
41
+ The other fields in the data object. Useful for accessing other
42
+ data kinds that needs to be used in the computation of coordinates
43
+ (default None).
44
+
45
+ Returns
46
+ -------
47
+ numpy.ndarray
48
+ The transformed coordinates.
49
+
50
+ """
51
+ logger.debug("Using FSL for coordinates transformation")
52
+
53
+ # Create element-specific tempdir for storing post-warping assets
54
+ element_tempdir = WorkDirManager().get_element_tempdir(
55
+ prefix="fsl_coordinates_warper"
56
+ )
57
+
58
+ # Save existing coordinates to a tempfile
59
+ pretransform_coordinates_path = (
60
+ element_tempdir / "pretransform_coordinates.txt"
61
+ )
62
+ np.savetxt(pretransform_coordinates_path, seeds)
63
+
64
+ # Create a tempfile for transformed coordinates output
65
+ transformed_coords_path = (
66
+ element_tempdir / "coordinates_transformed.txt"
67
+ )
68
+ # Set img2imgcoord command
69
+ img2imgcoord_cmd = [
70
+ "cat",
71
+ f"{pretransform_coordinates_path.resolve()}",
72
+ "| img2imgcoord -mm",
73
+ f"-src {target_data['path'].resolve()}",
74
+ f"-dest {target_data['reference_path'].resolve()}",
75
+ f"-warp {extra_input['Warp']['path'].resolve()}",
76
+ f"> {transformed_coords_path.resolve()};",
77
+ f"sed -i 1d {transformed_coords_path.resolve()}",
78
+ ]
79
+ # Call img2imgcoord
80
+ run_ext_cmd(name="img2imgcoord", cmd=img2imgcoord_cmd)
81
+
82
+ # Load coordinates
83
+ return np.loadtxt(transformed_coords_path)
@@ -1,26 +1,22 @@
1
1
  """Provide tests for coordinates."""
2
2
 
3
3
  # Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
4
+ # Synchon Mandal <s.mandal@fz-juelich.de>
4
5
  # License: AGPL
5
6
 
6
7
  import numpy as np
7
8
  import pytest
8
9
  from numpy.testing import assert_array_equal
9
10
 
10
- from junifer.data.coordinates import (
11
- get_coordinates,
12
- list_coordinates,
13
- load_coordinates,
14
- register_coordinates,
15
- )
11
+ from junifer.data import CoordinatesRegistry
16
12
  from junifer.datareader import DefaultDataReader
17
13
  from junifer.testing.datagrabbers import OasisVBMTestingDataGrabber
18
14
 
19
15
 
20
- def test_register_coordinates_built_in_check() -> None:
16
+ def test_register_built_in_check() -> None:
21
17
  """Test coordinates registration check for built-in coordinates."""
22
18
  with pytest.raises(ValueError, match=r"built-in"):
23
- register_coordinates(
19
+ CoordinatesRegistry().register(
24
20
  name="DMNBuckner",
25
21
  coordinates=np.zeros(2),
26
22
  voi_names=["1", "2"],
@@ -29,9 +25,9 @@ def test_register_coordinates_built_in_check() -> None:
29
25
  )
30
26
 
31
27
 
32
- def test_register_coordinates_overwrite() -> None:
28
+ def test_register_overwrite() -> None:
33
29
  """Test coordinates registration check for overwriting."""
34
- register_coordinates(
30
+ CoordinatesRegistry().register(
35
31
  name="MyList",
36
32
  coordinates=np.zeros((2, 3)),
37
33
  voi_names=["roi1", "roi2"],
@@ -39,14 +35,14 @@ def test_register_coordinates_overwrite() -> None:
39
35
  overwrite=True,
40
36
  )
41
37
  with pytest.raises(ValueError, match=r"already registered"):
42
- register_coordinates(
38
+ CoordinatesRegistry().register(
43
39
  name="MyList",
44
40
  coordinates=np.ones((2, 3)),
45
41
  voi_names=["roi2", "roi3"],
46
42
  space="MNI",
47
43
  )
48
44
 
49
- register_coordinates(
45
+ CoordinatesRegistry().register(
50
46
  name="MyList",
51
47
  coordinates=np.ones((2, 3)),
52
48
  voi_names=["roi2", "roi3"],
@@ -54,16 +50,16 @@ def test_register_coordinates_overwrite() -> None:
54
50
  overwrite=True,
55
51
  )
56
52
 
57
- coord, names, space = load_coordinates("MyList")
53
+ coord, names, space = CoordinatesRegistry().load("MyList")
58
54
  assert_array_equal(coord, np.ones((2, 3)))
59
55
  assert names == ["roi2", "roi3"]
60
56
  assert space == "MNI"
61
57
 
62
58
 
63
- def test_register_coordinates_valid_input() -> None:
59
+ def test_register_valid_input() -> None:
64
60
  """Test coordinates registration check for valid input."""
65
61
  with pytest.raises(TypeError, match=r"numpy.ndarray"):
66
- register_coordinates(
62
+ CoordinatesRegistry().register(
67
63
  name="MyList",
68
64
  coordinates=[1, 2],
69
65
  voi_names=["roi1", "roi2"],
@@ -71,7 +67,7 @@ def test_register_coordinates_valid_input() -> None:
71
67
  overwrite=True,
72
68
  )
73
69
  with pytest.raises(ValueError, match=r"2D array"):
74
- register_coordinates(
70
+ CoordinatesRegistry().register(
75
71
  name="MyList",
76
72
  coordinates=np.zeros((2, 3, 4)),
77
73
  voi_names=["roi1", "roi2"],
@@ -80,7 +76,7 @@ def test_register_coordinates_valid_input() -> None:
80
76
  )
81
77
 
82
78
  with pytest.raises(ValueError, match=r"3 values"):
83
- register_coordinates(
79
+ CoordinatesRegistry().register(
84
80
  name="MyList",
85
81
  coordinates=np.zeros((2, 4)),
86
82
  voi_names=["roi1", "roi2"],
@@ -88,7 +84,7 @@ def test_register_coordinates_valid_input() -> None:
88
84
  overwrite=True,
89
85
  )
90
86
  with pytest.raises(ValueError, match=r"voi_names"):
91
- register_coordinates(
87
+ CoordinatesRegistry().register(
92
88
  name="MyList",
93
89
  coordinates=np.zeros((2, 3)),
94
90
  voi_names=["roi1", "roi2", "roi3"],
@@ -97,30 +93,28 @@ def test_register_coordinates_valid_input() -> None:
97
93
  )
98
94
 
99
95
 
100
- def test_list_coordinates() -> None:
96
+ def test_list() -> None:
101
97
  """Test listing of available coordinates."""
102
- available_coordinates = list_coordinates()
103
- assert "DMNBuckner" in available_coordinates
104
- assert "MultiTask" in available_coordinates
105
- assert "VigAtt" in available_coordinates
106
- assert "WM" in available_coordinates
98
+ assert {"DMNBuckner", "MultiTask", "VigAtt", "WM"}.issubset(
99
+ set(CoordinatesRegistry().list)
100
+ )
107
101
 
108
102
 
109
- def test_load_coordinates() -> None:
103
+ def test_load() -> None:
110
104
  """Test loading coordinates from file."""
111
- coord, names, space = load_coordinates("DMNBuckner")
105
+ coord, names, space = CoordinatesRegistry().load("DMNBuckner")
112
106
  assert coord.shape == (6, 3) # type: ignore
113
107
  assert names == ["PCC", "MPFC", "lAG", "rAG", "lHF", "rHF"]
114
108
  assert space == "MNI"
115
109
 
116
110
 
117
- def test_load_coordinates_nonexisting() -> None:
111
+ def test_load_nonexisting() -> None:
118
112
  """Test loading coordinates that not exist."""
119
113
  with pytest.raises(ValueError, match=r"not found"):
120
- load_coordinates("NonExisting")
114
+ CoordinatesRegistry().load("NonExisting")
121
115
 
122
116
 
123
- def test_get_coordinates() -> None:
117
+ def test_get() -> None:
124
118
  """Test tailored coordinates fetch."""
125
119
  reader = DefaultDataReader()
126
120
  with OasisVBMTestingDataGrabber() as dg:
@@ -128,11 +122,11 @@ def test_get_coordinates() -> None:
128
122
  element_data = reader.fit_transform(element)
129
123
  vbm_gm = element_data["VBM_GM"]
130
124
  # Get tailored coordinates
131
- tailored_coords, tailored_labels = get_coordinates(
125
+ tailored_coords, tailored_labels = CoordinatesRegistry().get(
132
126
  coords="DMNBuckner", target_data=vbm_gm
133
127
  )
134
128
  # Get raw coordinates
135
- raw_coords, raw_labels, _ = load_coordinates("DMNBuckner")
129
+ raw_coords, raw_labels, _ = CoordinatesRegistry().load("DMNBuckner")
136
130
  # Both tailored and raw should be same for now
137
131
  assert_array_equal(tailored_coords, raw_coords)
138
132
  assert tailored_labels == raw_labels
@@ -0,0 +1,9 @@
1
+ """Masks."""
2
+
3
+ # Authors: Synchon Mandal <s.mandal@fz-juelich.de>
4
+ # License: AGPL
5
+
6
+ import lazy_loader as lazy
7
+
8
+
9
+ __getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
@@ -0,0 +1,6 @@
1
+ __all__ = [
2
+ "MaskRegistry",
3
+ "compute_brain_mask",
4
+ ]
5
+
6
+ from ._masks import MaskRegistry, compute_brain_mask