junifer 0.0.7.dev72__py3-none-any.whl → 0.0.7.dev93__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.
- junifer/_version.py +2 -2
- junifer/api/decorators.py +56 -11
- junifer/api/tests/test_decorators.py +32 -0
- junifer/data/__init__.pyi +4 -0
- junifer/data/_dispatch.py +102 -53
- junifer/data/coordinates/_coordinates.py +1 -2
- junifer/data/masks/_masks.py +1 -2
- junifer/data/parcellations/_parcellations.py +1 -2
- junifer/data/parcellations/tests/test_parcellations.py +7 -0
- junifer/data/tests/test_dispatch.py +87 -0
- junifer/datagrabber/__init__.pyi +11 -1
- junifer/datagrabber/pattern_validation_mixin.py +212 -85
- junifer/datagrabber/tests/test_pattern_validation_mixin.py +104 -1
- junifer/typing/__init__.pyi +2 -0
- junifer/typing/_typing.py +4 -1
- {junifer-0.0.7.dev72.dist-info → junifer-0.0.7.dev93.dist-info}/METADATA +1 -1
- {junifer-0.0.7.dev72.dist-info → junifer-0.0.7.dev93.dist-info}/RECORD +22 -20
- {junifer-0.0.7.dev72.dist-info → junifer-0.0.7.dev93.dist-info}/WHEEL +1 -1
- {junifer-0.0.7.dev72.dist-info → junifer-0.0.7.dev93.dist-info}/entry_points.txt +0 -0
- {junifer-0.0.7.dev72.dist-info → junifer-0.0.7.dev93.dist-info}/licenses/AUTHORS.rst +0 -0
- {junifer-0.0.7.dev72.dist-info → junifer-0.0.7.dev93.dist-info}/licenses/LICENSE.md +0 -0
- {junifer-0.0.7.dev72.dist-info → junifer-0.0.7.dev93.dist-info}/top_level.txt +0 -0
junifer/_version.py
CHANGED
@@ -17,5 +17,5 @@ __version__: str
|
|
17
17
|
__version_tuple__: VERSION_TUPLE
|
18
18
|
version_tuple: VERSION_TUPLE
|
19
19
|
|
20
|
-
__version__ = version = '0.0.7.
|
21
|
-
__version_tuple__ = version_tuple = (0, 0, 7, '
|
20
|
+
__version__ = version = '0.0.7.dev93'
|
21
|
+
__version_tuple__ = version_tuple = (0, 0, 7, 'dev93')
|
junifer/api/decorators.py
CHANGED
@@ -5,11 +5,19 @@
|
|
5
5
|
# Synchon Mandal <s.mandal@fz-juelich.de>
|
6
6
|
# License: AGPL
|
7
7
|
|
8
|
+
from ..data import DataDispatcher
|
8
9
|
from ..pipeline import PipelineComponentRegistry
|
9
|
-
from ..typing import
|
10
|
+
from ..typing import (
|
11
|
+
DataGrabberLike,
|
12
|
+
DataRegistryLike,
|
13
|
+
MarkerLike,
|
14
|
+
PreprocessorLike,
|
15
|
+
StorageLike,
|
16
|
+
)
|
10
17
|
|
11
18
|
|
12
19
|
__all__ = [
|
20
|
+
"register_data_registry",
|
13
21
|
"register_datagrabber",
|
14
22
|
"register_datareader",
|
15
23
|
"register_marker",
|
@@ -25,12 +33,12 @@ def register_datagrabber(klass: DataGrabberLike) -> DataGrabberLike:
|
|
25
33
|
|
26
34
|
Parameters
|
27
35
|
----------
|
28
|
-
klass: class
|
36
|
+
klass : class
|
29
37
|
The class of the DataGrabber to register.
|
30
38
|
|
31
39
|
Returns
|
32
40
|
-------
|
33
|
-
|
41
|
+
class
|
34
42
|
The unmodified input class.
|
35
43
|
|
36
44
|
Notes
|
@@ -52,12 +60,12 @@ def register_datareader(klass: type) -> type:
|
|
52
60
|
|
53
61
|
Parameters
|
54
62
|
----------
|
55
|
-
klass: class
|
63
|
+
klass : class
|
56
64
|
The class of the DataReader to register.
|
57
65
|
|
58
66
|
Returns
|
59
67
|
-------
|
60
|
-
|
68
|
+
class
|
61
69
|
The unmodified input class.
|
62
70
|
|
63
71
|
Notes
|
@@ -79,12 +87,12 @@ def register_preprocessor(klass: PreprocessorLike) -> PreprocessorLike:
|
|
79
87
|
|
80
88
|
Parameters
|
81
89
|
----------
|
82
|
-
klass: class
|
90
|
+
klass : class
|
83
91
|
The class of the preprocessor to register.
|
84
92
|
|
85
93
|
Returns
|
86
94
|
-------
|
87
|
-
|
95
|
+
class
|
88
96
|
The unmodified input class.
|
89
97
|
|
90
98
|
"""
|
@@ -102,12 +110,12 @@ def register_marker(klass: MarkerLike) -> MarkerLike:
|
|
102
110
|
|
103
111
|
Parameters
|
104
112
|
----------
|
105
|
-
klass: class
|
113
|
+
klass : class
|
106
114
|
The class of the marker to register.
|
107
115
|
|
108
116
|
Returns
|
109
117
|
-------
|
110
|
-
|
118
|
+
class
|
111
119
|
The unmodified input class.
|
112
120
|
|
113
121
|
"""
|
@@ -125,12 +133,12 @@ def register_storage(klass: StorageLike) -> StorageLike:
|
|
125
133
|
|
126
134
|
Parameters
|
127
135
|
----------
|
128
|
-
klass: class
|
136
|
+
klass : class
|
129
137
|
The class of the storage to register.
|
130
138
|
|
131
139
|
Returns
|
132
140
|
-------
|
133
|
-
|
141
|
+
class
|
134
142
|
The unmodified input class.
|
135
143
|
|
136
144
|
"""
|
@@ -139,3 +147,40 @@ def register_storage(klass: StorageLike) -> StorageLike:
|
|
139
147
|
klass=klass,
|
140
148
|
)
|
141
149
|
return klass
|
150
|
+
|
151
|
+
|
152
|
+
def register_data_registry(name: str) -> DataRegistryLike:
|
153
|
+
"""Registry registration decorator.
|
154
|
+
|
155
|
+
Registers the data registry as ``name``.
|
156
|
+
|
157
|
+
Parameters
|
158
|
+
----------
|
159
|
+
name : str
|
160
|
+
The name of the data registry.
|
161
|
+
|
162
|
+
Returns
|
163
|
+
-------
|
164
|
+
class
|
165
|
+
The unmodified input class.
|
166
|
+
|
167
|
+
"""
|
168
|
+
|
169
|
+
def decorator(klass: DataRegistryLike) -> DataRegistryLike:
|
170
|
+
"""Actual decorator.
|
171
|
+
|
172
|
+
Parameters
|
173
|
+
----------
|
174
|
+
klass : class
|
175
|
+
The class of the data registry to register.
|
176
|
+
|
177
|
+
Returns
|
178
|
+
-------
|
179
|
+
class
|
180
|
+
The unmodified input class.
|
181
|
+
|
182
|
+
"""
|
183
|
+
DataDispatcher()[name] = klass
|
184
|
+
return klass
|
185
|
+
|
186
|
+
return decorator
|
@@ -0,0 +1,32 @@
|
|
1
|
+
"""Provide tests for public decorators."""
|
2
|
+
|
3
|
+
# Authors: Synchon Mandal <s.mandal@fz-juelich.de>
|
4
|
+
# License: AGPL
|
5
|
+
|
6
|
+
from junifer.api.decorators import register_data_registry
|
7
|
+
from junifer.data import BasePipelineDataRegistry, DataDispatcher
|
8
|
+
|
9
|
+
|
10
|
+
def test_register_data_registry() -> None:
|
11
|
+
"""Test data registry registration."""
|
12
|
+
|
13
|
+
@register_data_registry("dumb")
|
14
|
+
class DumDum(BasePipelineDataRegistry):
|
15
|
+
def __init__(self):
|
16
|
+
super().__init__()
|
17
|
+
|
18
|
+
def register(self):
|
19
|
+
pass
|
20
|
+
|
21
|
+
def deregister(self):
|
22
|
+
pass
|
23
|
+
|
24
|
+
def load(self):
|
25
|
+
pass
|
26
|
+
|
27
|
+
def get(self):
|
28
|
+
pass
|
29
|
+
|
30
|
+
assert "dumb" in DataDispatcher()
|
31
|
+
_ = DataDispatcher().pop("dumb")
|
32
|
+
assert "dumb" not in DataDispatcher()
|
junifer/data/__init__.pyi
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
__all__ = [
|
2
|
+
"BasePipelineDataRegistry",
|
2
3
|
"CoordinatesRegistry",
|
4
|
+
"DataDispatcher",
|
3
5
|
"ParcellationRegistry",
|
4
6
|
"MaskRegistry",
|
5
7
|
"get_data",
|
@@ -12,11 +14,13 @@ __all__ = [
|
|
12
14
|
"utils",
|
13
15
|
]
|
14
16
|
|
17
|
+
from .pipeline_data_registry_base import BasePipelineDataRegistry
|
15
18
|
from .coordinates import CoordinatesRegistry
|
16
19
|
from .parcellations import ParcellationRegistry
|
17
20
|
from .masks import MaskRegistry
|
18
21
|
|
19
22
|
from ._dispatch import (
|
23
|
+
DataDispatcher,
|
20
24
|
get_data,
|
21
25
|
list_data,
|
22
26
|
load_data,
|
junifer/data/_dispatch.py
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
# Authors: Synchon Mandal <s.mandal@fz-juelich.de>
|
4
4
|
# License: AGPL
|
5
5
|
|
6
|
+
from collections.abc import Iterator, MutableMapping
|
6
7
|
from pathlib import Path
|
7
8
|
from typing import (
|
8
9
|
TYPE_CHECKING,
|
@@ -18,13 +19,14 @@ from ..utils import raise_error
|
|
18
19
|
from .coordinates import CoordinatesRegistry
|
19
20
|
from .masks import MaskRegistry
|
20
21
|
from .parcellations import ParcellationRegistry
|
22
|
+
from .pipeline_data_registry_base import BasePipelineDataRegistry
|
21
23
|
|
22
24
|
|
23
25
|
if TYPE_CHECKING:
|
24
26
|
from nibabel.nifti1 import Nifti1Image
|
25
27
|
|
26
|
-
|
27
28
|
__all__ = [
|
29
|
+
"DataDispatcher",
|
28
30
|
"deregister_data",
|
29
31
|
"get_data",
|
30
32
|
"list_data",
|
@@ -33,6 +35,77 @@ __all__ = [
|
|
33
35
|
]
|
34
36
|
|
35
37
|
|
38
|
+
class DataDispatcher(MutableMapping):
|
39
|
+
"""Class for helping dynamic data dispatch."""
|
40
|
+
|
41
|
+
_instance = None
|
42
|
+
|
43
|
+
def __new__(cls):
|
44
|
+
# Make class singleton
|
45
|
+
if cls._instance is None:
|
46
|
+
cls._instance = super().__new__(cls)
|
47
|
+
# Set registries
|
48
|
+
cls._registries: dict[str, type[BasePipelineDataRegistry]] = {}
|
49
|
+
cls._builtin: dict[str, type[BasePipelineDataRegistry]] = {}
|
50
|
+
cls._external: dict[str, type[BasePipelineDataRegistry]] = {}
|
51
|
+
cls._builtin.update(
|
52
|
+
{
|
53
|
+
"coordinates": CoordinatesRegistry,
|
54
|
+
"parcellation": ParcellationRegistry,
|
55
|
+
"mask": MaskRegistry,
|
56
|
+
}
|
57
|
+
)
|
58
|
+
cls._registries.update(cls._builtin)
|
59
|
+
return cls._instance
|
60
|
+
|
61
|
+
def __getitem__(self, key: str) -> type[BasePipelineDataRegistry]:
|
62
|
+
return self._registries[key]
|
63
|
+
|
64
|
+
def __iter__(self) -> Iterator[str]:
|
65
|
+
return iter(self._registries)
|
66
|
+
|
67
|
+
def __len__(self) -> int:
|
68
|
+
return len(self._registries)
|
69
|
+
|
70
|
+
def __delitem__(self, key: str) -> None:
|
71
|
+
# Internal check
|
72
|
+
if key in self._builtin:
|
73
|
+
raise_error(f"Cannot delete in-built key: {key}")
|
74
|
+
# Non-existing key
|
75
|
+
if key not in self._external:
|
76
|
+
raise_error(klass=KeyError, msg=key)
|
77
|
+
# Update external
|
78
|
+
_ = self._external.pop(key)
|
79
|
+
# Update global
|
80
|
+
_ = self._registries.pop(key)
|
81
|
+
|
82
|
+
def __setitem__(
|
83
|
+
self, key: str, value: type[BasePipelineDataRegistry]
|
84
|
+
) -> None:
|
85
|
+
# Internal check
|
86
|
+
if key in self._builtin:
|
87
|
+
raise_error(f"Cannot set value for in-built key: {key}")
|
88
|
+
# Value type check
|
89
|
+
if not issubclass(value, BasePipelineDataRegistry):
|
90
|
+
raise_error(f"Invalid value type: {type(value)}")
|
91
|
+
# Update external
|
92
|
+
self._external[key] = value
|
93
|
+
# Update global
|
94
|
+
self._registries[key] = value
|
95
|
+
|
96
|
+
def popitem():
|
97
|
+
"""Not implemented."""
|
98
|
+
pass
|
99
|
+
|
100
|
+
def clear(self):
|
101
|
+
"""Not implemented."""
|
102
|
+
pass
|
103
|
+
|
104
|
+
def setdefault(self, key: str, value=None):
|
105
|
+
"""Not implemented."""
|
106
|
+
pass
|
107
|
+
|
108
|
+
|
36
109
|
def get_data(
|
37
110
|
kind: str,
|
38
111
|
names: Union[
|
@@ -76,27 +149,16 @@ def get_data(
|
|
76
149
|
If ``kind`` is invalid value.
|
77
150
|
|
78
151
|
"""
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
elif kind == "parcellation":
|
87
|
-
return ParcellationRegistry().get(
|
88
|
-
parcellations=names,
|
89
|
-
target_data=target_data,
|
90
|
-
extra_input=extra_input,
|
91
|
-
)
|
92
|
-
elif kind == "mask":
|
93
|
-
return MaskRegistry().get(
|
94
|
-
masks=names,
|
152
|
+
try:
|
153
|
+
registry = DataDispatcher()[kind]
|
154
|
+
except KeyError:
|
155
|
+
raise_error(f"Unknown data kind: {kind}")
|
156
|
+
else:
|
157
|
+
return registry().get(
|
158
|
+
names,
|
95
159
|
target_data=target_data,
|
96
160
|
extra_input=extra_input,
|
97
161
|
)
|
98
|
-
else: # pragma: no cover
|
99
|
-
raise_error(f"Unknown data kind: {kind}")
|
100
162
|
|
101
163
|
|
102
164
|
def list_data(kind: str) -> list[str]:
|
@@ -119,14 +181,12 @@ def list_data(kind: str) -> list[str]:
|
|
119
181
|
|
120
182
|
"""
|
121
183
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
return ParcellationRegistry().list
|
126
|
-
elif kind == "mask":
|
127
|
-
return MaskRegistry().list
|
128
|
-
else: # pragma: no cover
|
184
|
+
try:
|
185
|
+
registry = DataDispatcher()[kind]
|
186
|
+
except KeyError:
|
129
187
|
raise_error(f"Unknown data kind: {kind}")
|
188
|
+
else:
|
189
|
+
return registry().list
|
130
190
|
|
131
191
|
|
132
192
|
def load_data(
|
@@ -165,15 +225,12 @@ def load_data(
|
|
165
225
|
If ``kind`` is invalid value.
|
166
226
|
|
167
227
|
"""
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
elif kind == "parcellation":
|
172
|
-
return ParcellationRegistry().load(name=name, **kwargs)
|
173
|
-
elif kind == "mask":
|
174
|
-
return MaskRegistry().load(name=name, **kwargs)
|
175
|
-
else: # pragma: no cover
|
228
|
+
try:
|
229
|
+
registry = DataDispatcher()[kind]
|
230
|
+
except KeyError:
|
176
231
|
raise_error(f"Unknown data kind: {kind}")
|
232
|
+
else:
|
233
|
+
return registry().load(name, **kwargs)
|
177
234
|
|
178
235
|
|
179
236
|
def register_data(
|
@@ -205,20 +262,14 @@ def register_data(
|
|
205
262
|
|
206
263
|
"""
|
207
264
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
)
|
212
|
-
|
213
|
-
return
|
214
|
-
name=name, space=space, overwrite=overwrite, **kwargs
|
215
|
-
)
|
216
|
-
elif kind == "mask":
|
217
|
-
return MaskRegistry().register(
|
265
|
+
try:
|
266
|
+
registry = DataDispatcher()[kind]
|
267
|
+
except KeyError:
|
268
|
+
raise_error(f"Unknown data kind: {kind}")
|
269
|
+
else:
|
270
|
+
return registry().register(
|
218
271
|
name=name, space=space, overwrite=overwrite, **kwargs
|
219
272
|
)
|
220
|
-
else: # pragma: no cover
|
221
|
-
raise_error(f"Unknown data kind: {kind}")
|
222
273
|
|
223
274
|
|
224
275
|
def deregister_data(kind: str, name: str) -> None:
|
@@ -238,11 +289,9 @@ def deregister_data(kind: str, name: str) -> None:
|
|
238
289
|
|
239
290
|
"""
|
240
291
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
return ParcellationRegistry().deregister(name=name)
|
245
|
-
elif kind == "mask":
|
246
|
-
return MaskRegistry().deregister(name=name)
|
247
|
-
else: # pragma: no cover
|
292
|
+
try:
|
293
|
+
registry = DataDispatcher()[kind]
|
294
|
+
except KeyError:
|
248
295
|
raise_error(f"Unknown data kind: {kind}")
|
296
|
+
else:
|
297
|
+
return registry().deregister(name=name)
|
@@ -13,7 +13,6 @@ from junifer_data import get
|
|
13
13
|
from numpy.typing import ArrayLike
|
14
14
|
|
15
15
|
from ...utils import logger, raise_error
|
16
|
-
from ...utils.singleton import Singleton
|
17
16
|
from ..pipeline_data_registry_base import BasePipelineDataRegistry
|
18
17
|
from ..utils import JUNIFER_DATA_PARAMS, get_dataset_path, get_native_warper
|
19
18
|
from ._ants_coordinates_warper import ANTsCoordinatesWarper
|
@@ -23,7 +22,7 @@ from ._fsl_coordinates_warper import FSLCoordinatesWarper
|
|
23
22
|
__all__ = ["CoordinatesRegistry"]
|
24
23
|
|
25
24
|
|
26
|
-
class CoordinatesRegistry(BasePipelineDataRegistry
|
25
|
+
class CoordinatesRegistry(BasePipelineDataRegistry):
|
27
26
|
"""Class for coordinates data registry.
|
28
27
|
|
29
28
|
This class is a singleton and is used for managing available coordinates
|
junifer/data/masks/_masks.py
CHANGED
@@ -24,7 +24,6 @@ from nilearn.masking import (
|
|
24
24
|
)
|
25
25
|
|
26
26
|
from ...utils import logger, raise_error
|
27
|
-
from ...utils.singleton import Singleton
|
28
27
|
from ..pipeline_data_registry_base import BasePipelineDataRegistry
|
29
28
|
from ..template_spaces import get_template
|
30
29
|
from ..utils import (
|
@@ -216,7 +215,7 @@ def compute_brain_mask(
|
|
216
215
|
return nimg.new_img_like(target_data["data"], mask) # type: ignore
|
217
216
|
|
218
217
|
|
219
|
-
class MaskRegistry(BasePipelineDataRegistry
|
218
|
+
class MaskRegistry(BasePipelineDataRegistry):
|
220
219
|
"""Class for mask data registry.
|
221
220
|
|
222
221
|
This class is a singleton and is used for managing available mask
|
@@ -16,7 +16,6 @@ import pandas as pd
|
|
16
16
|
from junifer_data import get
|
17
17
|
|
18
18
|
from ...utils import logger, raise_error, warn_with_log
|
19
|
-
from ...utils.singleton import Singleton
|
20
19
|
from ..pipeline_data_registry_base import BasePipelineDataRegistry
|
21
20
|
from ..utils import (
|
22
21
|
JUNIFER_DATA_PARAMS,
|
@@ -38,7 +37,7 @@ __all__ = [
|
|
38
37
|
]
|
39
38
|
|
40
39
|
|
41
|
-
class ParcellationRegistry(BasePipelineDataRegistry
|
40
|
+
class ParcellationRegistry(BasePipelineDataRegistry):
|
42
41
|
"""Class for parcellation data registry.
|
43
42
|
|
44
43
|
This class is a singleton and is used for managing available parcellation
|
@@ -14,6 +14,7 @@ from nilearn.image import new_img_like, resample_to_img
|
|
14
14
|
from numpy.testing import assert_array_almost_equal, assert_array_equal
|
15
15
|
|
16
16
|
from junifer.data import (
|
17
|
+
deregister_data,
|
17
18
|
get_data,
|
18
19
|
list_data,
|
19
20
|
load_data,
|
@@ -1245,3 +1246,9 @@ def test_get_multi_different_space() -> None:
|
|
1245
1246
|
],
|
1246
1247
|
target_data=element_data["VBM_GM"],
|
1247
1248
|
)
|
1249
|
+
|
1250
|
+
|
1251
|
+
def test_deregister() -> None:
|
1252
|
+
"""Test parcellation deregistration."""
|
1253
|
+
deregister_data(kind="parcellation", name="testparc_3")
|
1254
|
+
assert "testparc_3" not in list_data(kind="parcellation")
|
@@ -0,0 +1,87 @@
|
|
1
|
+
"""Provide tests for data dispatching."""
|
2
|
+
|
3
|
+
# Authors: Synchon Mandal <s.mandal@fz-juelich.de>
|
4
|
+
# License: AGPL
|
5
|
+
|
6
|
+
import pytest
|
7
|
+
|
8
|
+
from junifer.data import (
|
9
|
+
BasePipelineDataRegistry,
|
10
|
+
deregister_data,
|
11
|
+
get_data,
|
12
|
+
list_data,
|
13
|
+
load_data,
|
14
|
+
register_data,
|
15
|
+
)
|
16
|
+
from junifer.data._dispatch import DataDispatcher
|
17
|
+
|
18
|
+
|
19
|
+
def test_dispatcher_addition_errors() -> None:
|
20
|
+
"""Test registry addition errors."""
|
21
|
+
with pytest.raises(ValueError, match="Cannot set"):
|
22
|
+
DataDispatcher()["mask"] = dict
|
23
|
+
|
24
|
+
with pytest.raises(ValueError, match="Invalid"):
|
25
|
+
DataDispatcher()["masks"] = dict
|
26
|
+
|
27
|
+
|
28
|
+
def test_dispatcher_removal_errors() -> None:
|
29
|
+
"""Test registry removal errors."""
|
30
|
+
with pytest.raises(ValueError, match="Cannot delete"):
|
31
|
+
_ = DataDispatcher().pop("mask")
|
32
|
+
|
33
|
+
with pytest.raises(KeyError, match="masks"):
|
34
|
+
del DataDispatcher()["masks"]
|
35
|
+
|
36
|
+
|
37
|
+
def test_dispatcher() -> None:
|
38
|
+
"""Test registry addition and removal."""
|
39
|
+
|
40
|
+
class DumDum(BasePipelineDataRegistry):
|
41
|
+
def register():
|
42
|
+
pass
|
43
|
+
|
44
|
+
def deregister():
|
45
|
+
pass
|
46
|
+
|
47
|
+
def load():
|
48
|
+
pass
|
49
|
+
|
50
|
+
def get():
|
51
|
+
pass
|
52
|
+
|
53
|
+
DataDispatcher().update({"masks": DumDum})
|
54
|
+
assert "masks" in DataDispatcher()
|
55
|
+
|
56
|
+
_ = DataDispatcher().pop("masks")
|
57
|
+
assert "masks" not in DataDispatcher()
|
58
|
+
|
59
|
+
|
60
|
+
def test_get_data_error() -> None:
|
61
|
+
"""Test error for get_data()."""
|
62
|
+
with pytest.raises(ValueError, match="Unknown data kind"):
|
63
|
+
get_data(kind="planet", names="neptune", target_data={})
|
64
|
+
|
65
|
+
|
66
|
+
def test_list_data_error() -> None:
|
67
|
+
"""Test error for list_data()."""
|
68
|
+
with pytest.raises(ValueError, match="Unknown data kind"):
|
69
|
+
list_data(kind="planet")
|
70
|
+
|
71
|
+
|
72
|
+
def test_load_data_error() -> None:
|
73
|
+
"""Test error for load_data()."""
|
74
|
+
with pytest.raises(ValueError, match="Unknown data kind"):
|
75
|
+
load_data(kind="planet", name="neptune")
|
76
|
+
|
77
|
+
|
78
|
+
def test_register_data_error() -> None:
|
79
|
+
"""Test error for register_data()."""
|
80
|
+
with pytest.raises(ValueError, match="Unknown data kind"):
|
81
|
+
register_data(kind="planet", name="neptune", space="milkyway")
|
82
|
+
|
83
|
+
|
84
|
+
def test_deregister_data_error() -> None:
|
85
|
+
"""Test error for deregister_data()."""
|
86
|
+
with pytest.raises(ValueError, match="Unknown data kind"):
|
87
|
+
deregister_data(kind="planet", name="neptune")
|
junifer/datagrabber/__init__.pyi
CHANGED
@@ -10,7 +10,11 @@ __all__ = [
|
|
10
10
|
"DataladHCP1200",
|
11
11
|
"MultipleDataGrabber",
|
12
12
|
"DMCC13Benchmark",
|
13
|
+
"DataTypeManager",
|
14
|
+
"DataTypeSchema",
|
15
|
+
"OptionalTypeSchema",
|
13
16
|
"PatternValidationMixin",
|
17
|
+
"register_data_type",
|
14
18
|
]
|
15
19
|
|
16
20
|
# These 4 need to be in this order, otherwise it is a circular import
|
@@ -24,4 +28,10 @@ from .hcp1200 import HCP1200, DataladHCP1200
|
|
24
28
|
from .multiple import MultipleDataGrabber
|
25
29
|
from .dmcc13_benchmark import DMCC13Benchmark
|
26
30
|
|
27
|
-
from .pattern_validation_mixin import
|
31
|
+
from .pattern_validation_mixin import (
|
32
|
+
DataTypeManager,
|
33
|
+
DataTypeSchema,
|
34
|
+
OptionalTypeSchema,
|
35
|
+
PatternValidationMixin,
|
36
|
+
register_data_type,
|
37
|
+
)
|
@@ -3,71 +3,199 @@
|
|
3
3
|
# Authors: Synchon Mandal <s.mandal@fz-juelich.de>
|
4
4
|
# License: AGPL
|
5
5
|
|
6
|
+
from collections.abc import Iterator, MutableMapping
|
7
|
+
from typing import TypedDict
|
8
|
+
|
6
9
|
from ..typing import DataGrabberPatterns
|
7
10
|
from ..utils import logger, raise_error, warn_with_log
|
8
11
|
|
9
12
|
|
10
|
-
__all__ = [
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
"
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
"
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
13
|
+
__all__ = [
|
14
|
+
"DataTypeManager",
|
15
|
+
"DataTypeSchema",
|
16
|
+
"OptionalTypeSchema",
|
17
|
+
"PatternValidationMixin",
|
18
|
+
"register_data_type",
|
19
|
+
]
|
20
|
+
|
21
|
+
|
22
|
+
class OptionalTypeSchema(TypedDict):
|
23
|
+
"""Optional type schema."""
|
24
|
+
|
25
|
+
mandatory: list[str]
|
26
|
+
optional: list[str]
|
27
|
+
|
28
|
+
|
29
|
+
class DataTypeSchema(TypedDict):
|
30
|
+
"""Data type schema."""
|
31
|
+
|
32
|
+
mandatory: list[str]
|
33
|
+
optional: dict[str, OptionalTypeSchema]
|
34
|
+
|
35
|
+
|
36
|
+
class DataTypeManager(MutableMapping):
|
37
|
+
"""Class for managing data types."""
|
38
|
+
|
39
|
+
_instance = None
|
40
|
+
|
41
|
+
def __new__(cls):
|
42
|
+
"""Overridden to make the class singleton."""
|
43
|
+
# Make class singleton
|
44
|
+
if cls._instance is None:
|
45
|
+
cls._instance = super().__new__(cls)
|
46
|
+
# Set global schema
|
47
|
+
cls._global: dict[str, DataTypeSchema] = {}
|
48
|
+
cls._builtin: dict[str, DataTypeSchema] = {}
|
49
|
+
cls._external: dict[str, DataTypeSchema] = {}
|
50
|
+
cls._builtin.update(
|
51
|
+
{
|
52
|
+
"T1w": {
|
53
|
+
"mandatory": ["pattern", "space"],
|
54
|
+
"optional": {
|
55
|
+
"mask": {
|
56
|
+
"mandatory": ["pattern", "space"],
|
57
|
+
"optional": [],
|
58
|
+
},
|
59
|
+
},
|
60
|
+
},
|
61
|
+
"T2w": {
|
62
|
+
"mandatory": ["pattern", "space"],
|
63
|
+
"optional": {
|
64
|
+
"mask": {
|
65
|
+
"mandatory": ["pattern", "space"],
|
66
|
+
"optional": [],
|
67
|
+
},
|
68
|
+
},
|
69
|
+
},
|
70
|
+
"BOLD": {
|
71
|
+
"mandatory": ["pattern", "space"],
|
72
|
+
"optional": {
|
73
|
+
"mask": {
|
74
|
+
"mandatory": ["pattern", "space"],
|
75
|
+
"optional": [],
|
76
|
+
},
|
77
|
+
"confounds": {
|
78
|
+
"mandatory": ["pattern", "format"],
|
79
|
+
"optional": ["mappings"],
|
80
|
+
},
|
81
|
+
"reference": {
|
82
|
+
"mandatory": ["pattern"],
|
83
|
+
"optional": [],
|
84
|
+
},
|
85
|
+
"prewarp_space": {"mandatory": [], "optional": []},
|
86
|
+
},
|
87
|
+
},
|
88
|
+
"Warp": {
|
89
|
+
"mandatory": ["pattern", "src", "dst", "warper"],
|
90
|
+
"optional": {},
|
91
|
+
},
|
92
|
+
"VBM_GM": {
|
93
|
+
"mandatory": ["pattern", "space"],
|
94
|
+
"optional": {},
|
95
|
+
},
|
96
|
+
"VBM_WM": {
|
97
|
+
"mandatory": ["pattern", "space"],
|
98
|
+
"optional": {},
|
99
|
+
},
|
100
|
+
"VBM_CSF": {
|
101
|
+
"mandatory": ["pattern", "space"],
|
102
|
+
"optional": {},
|
103
|
+
},
|
104
|
+
"DWI": {
|
105
|
+
"mandatory": ["pattern"],
|
106
|
+
"optional": {},
|
107
|
+
},
|
108
|
+
"FreeSurfer": {
|
109
|
+
"mandatory": ["pattern"],
|
110
|
+
"optional": {
|
111
|
+
"aseg": {"mandatory": ["pattern"], "optional": []},
|
112
|
+
"norm": {"mandatory": ["pattern"], "optional": []},
|
113
|
+
"lh_white": {
|
114
|
+
"mandatory": ["pattern"],
|
115
|
+
"optional": [],
|
116
|
+
},
|
117
|
+
"rh_white": {
|
118
|
+
"mandatory": ["pattern"],
|
119
|
+
"optional": [],
|
120
|
+
},
|
121
|
+
"lh_pial": {
|
122
|
+
"mandatory": ["pattern"],
|
123
|
+
"optional": [],
|
124
|
+
},
|
125
|
+
"rh_pial": {
|
126
|
+
"mandatory": ["pattern"],
|
127
|
+
"optional": [],
|
128
|
+
},
|
129
|
+
},
|
130
|
+
},
|
131
|
+
}
|
132
|
+
)
|
133
|
+
cls._global.update(cls._builtin)
|
134
|
+
return cls._instance
|
135
|
+
|
136
|
+
def __getitem__(self, key: str) -> DataTypeSchema:
|
137
|
+
"""Retrieve schema for ``key``."""
|
138
|
+
return self._global[key]
|
139
|
+
|
140
|
+
def __iter__(self) -> Iterator[str]:
|
141
|
+
"""Iterate over data types."""
|
142
|
+
return iter(self._global)
|
143
|
+
|
144
|
+
def __len__(self) -> int:
|
145
|
+
"""Get data type count."""
|
146
|
+
return len(self._global)
|
147
|
+
|
148
|
+
def __delitem__(self, key: str) -> None:
|
149
|
+
"""Remove schema for ``key``."""
|
150
|
+
# Internal check
|
151
|
+
if key in self._builtin:
|
152
|
+
raise_error(f"Cannot delete in-built key: {key}")
|
153
|
+
# Non-existing key
|
154
|
+
if key not in self._external:
|
155
|
+
raise_error(klass=KeyError, msg=key)
|
156
|
+
# Update external
|
157
|
+
_ = self._external.pop(key)
|
158
|
+
# Update global
|
159
|
+
_ = self._global.pop(key)
|
160
|
+
|
161
|
+
def __setitem__(self, key: str, value: DataTypeSchema) -> None:
|
162
|
+
"""Update ``key`` with ``value``."""
|
163
|
+
# Internal check
|
164
|
+
if key in self._builtin:
|
165
|
+
raise_error(f"Cannot set value for in-built key: {key}")
|
166
|
+
# Value type check
|
167
|
+
if not isinstance(value, dict):
|
168
|
+
raise_error(f"Invalid value type: {type(value)}")
|
169
|
+
# Update external
|
170
|
+
self._external[key] = value
|
171
|
+
# Update global
|
172
|
+
self._global[key] = value
|
173
|
+
|
174
|
+
def popitem():
|
175
|
+
"""Not implemented."""
|
176
|
+
pass
|
177
|
+
|
178
|
+
def clear(self):
|
179
|
+
"""Not implemented."""
|
180
|
+
pass
|
181
|
+
|
182
|
+
def setdefault(self, key: str, value=None):
|
183
|
+
"""Not implemented."""
|
184
|
+
pass
|
185
|
+
|
186
|
+
|
187
|
+
def register_data_type(name: str, schema: DataTypeSchema) -> None:
|
188
|
+
"""Register custom data type.
|
189
|
+
|
190
|
+
Parameters
|
191
|
+
----------
|
192
|
+
name : str
|
193
|
+
The data type name.
|
194
|
+
schema : DataTypeSchema
|
195
|
+
The data type schema.
|
196
|
+
|
197
|
+
"""
|
198
|
+
DataTypeManager()[name] = schema
|
71
199
|
|
72
200
|
|
73
201
|
class PatternValidationMixin:
|
@@ -311,12 +439,13 @@ class PatternValidationMixin:
|
|
311
439
|
msg="`patterns` must contain all `types`", klass=ValueError
|
312
440
|
)
|
313
441
|
# Check against schema
|
442
|
+
dtype_mgr = DataTypeManager()
|
314
443
|
for dtype_key, dtype_val in patterns.items():
|
315
444
|
# Check if valid data type is provided
|
316
|
-
if dtype_key not in
|
445
|
+
if dtype_key not in dtype_mgr:
|
317
446
|
raise_error(
|
318
447
|
f"Unknown data type: {dtype_key}, "
|
319
|
-
f"should be one of: {list(
|
448
|
+
f"should be one of: {list(dtype_mgr.keys())}"
|
320
449
|
)
|
321
450
|
# Conditional for list dtype vals like Warp
|
322
451
|
if isinstance(dtype_val, list):
|
@@ -324,14 +453,14 @@ class PatternValidationMixin:
|
|
324
453
|
# Check mandatory keys for data type
|
325
454
|
self._validate_mandatory_keys(
|
326
455
|
keys=list(entry),
|
327
|
-
schema=
|
456
|
+
schema=dtype_mgr[dtype_key]["mandatory"],
|
328
457
|
data_type=f"{dtype_key}.{idx}",
|
329
458
|
partial_pattern_ok=partial_pattern_ok,
|
330
459
|
)
|
331
460
|
# Check optional keys for data type
|
332
|
-
for optional_key, optional_val in
|
333
|
-
|
334
|
-
]
|
461
|
+
for optional_key, optional_val in dtype_mgr[dtype_key][
|
462
|
+
"optional"
|
463
|
+
].items():
|
335
464
|
if optional_key not in entry:
|
336
465
|
logger.debug(
|
337
466
|
f"Optional key: `{optional_key}` missing for "
|
@@ -344,12 +473,12 @@ class PatternValidationMixin:
|
|
344
473
|
)
|
345
474
|
# Set nested type name for easier access
|
346
475
|
nested_dtype = f"{dtype_key}.{idx}.{optional_key}"
|
347
|
-
nested_mandatory_keys_schema =
|
476
|
+
nested_mandatory_keys_schema = dtype_mgr[
|
348
477
|
dtype_key
|
349
478
|
]["optional"][optional_key]["mandatory"]
|
350
|
-
nested_optional_keys_schema =
|
351
|
-
|
352
|
-
][
|
479
|
+
nested_optional_keys_schema = dtype_mgr[dtype_key][
|
480
|
+
"optional"
|
481
|
+
][optional_key]["optional"]
|
353
482
|
# Check mandatory keys for nested type
|
354
483
|
self._validate_mandatory_keys(
|
355
484
|
keys=list(optional_val["mandatory"]),
|
@@ -392,10 +521,8 @@ class PatternValidationMixin:
|
|
392
521
|
self._identify_stray_keys(
|
393
522
|
keys=list(entry.keys()),
|
394
523
|
schema=(
|
395
|
-
|
396
|
-
+ list(
|
397
|
-
PATTERNS_SCHEMA[dtype_key]["optional"].keys()
|
398
|
-
)
|
524
|
+
dtype_mgr[dtype_key]["mandatory"]
|
525
|
+
+ list(dtype_mgr[dtype_key]["optional"].keys())
|
399
526
|
),
|
400
527
|
data_type=dtype_key,
|
401
528
|
)
|
@@ -412,12 +539,12 @@ class PatternValidationMixin:
|
|
412
539
|
# Check mandatory keys for data type
|
413
540
|
self._validate_mandatory_keys(
|
414
541
|
keys=list(dtype_val),
|
415
|
-
schema=
|
542
|
+
schema=dtype_mgr[dtype_key]["mandatory"],
|
416
543
|
data_type=dtype_key,
|
417
544
|
partial_pattern_ok=partial_pattern_ok,
|
418
545
|
)
|
419
546
|
# Check optional keys for data type
|
420
|
-
for optional_key, optional_val in
|
547
|
+
for optional_key, optional_val in dtype_mgr[dtype_key][
|
421
548
|
"optional"
|
422
549
|
].items():
|
423
550
|
if optional_key not in dtype_val:
|
@@ -432,12 +559,12 @@ class PatternValidationMixin:
|
|
432
559
|
)
|
433
560
|
# Set nested type name for easier access
|
434
561
|
nested_dtype = f"{dtype_key}.{optional_key}"
|
435
|
-
nested_mandatory_keys_schema =
|
436
|
-
|
437
|
-
][
|
438
|
-
nested_optional_keys_schema =
|
439
|
-
|
440
|
-
][
|
562
|
+
nested_mandatory_keys_schema = dtype_mgr[dtype_key][
|
563
|
+
"optional"
|
564
|
+
][optional_key]["mandatory"]
|
565
|
+
nested_optional_keys_schema = dtype_mgr[dtype_key][
|
566
|
+
"optional"
|
567
|
+
][optional_key]["optional"]
|
441
568
|
# Check mandatory keys for nested type
|
442
569
|
self._validate_mandatory_keys(
|
443
570
|
keys=list(optional_val["mandatory"]),
|
@@ -476,8 +603,8 @@ class PatternValidationMixin:
|
|
476
603
|
self._identify_stray_keys(
|
477
604
|
keys=list(dtype_val.keys()),
|
478
605
|
schema=(
|
479
|
-
|
480
|
-
+ list(
|
606
|
+
dtype_mgr[dtype_key]["mandatory"]
|
607
|
+
+ list(dtype_mgr[dtype_key]["optional"].keys())
|
481
608
|
),
|
482
609
|
data_type=dtype_key,
|
483
610
|
)
|
@@ -9,7 +9,110 @@ from typing import Union
|
|
9
9
|
|
10
10
|
import pytest
|
11
11
|
|
12
|
-
from junifer.datagrabber.pattern_validation_mixin import
|
12
|
+
from junifer.datagrabber.pattern_validation_mixin import (
|
13
|
+
DataTypeManager,
|
14
|
+
DataTypeSchema,
|
15
|
+
PatternValidationMixin,
|
16
|
+
register_data_type,
|
17
|
+
)
|
18
|
+
|
19
|
+
|
20
|
+
def test_dtype_mgr_addition_errors() -> None:
|
21
|
+
"""Test data type manager addition errors."""
|
22
|
+
with pytest.raises(ValueError, match="Cannot set"):
|
23
|
+
dtype_schema: DataTypeSchema = {
|
24
|
+
"mandatory": ["pattern"],
|
25
|
+
"optional": {},
|
26
|
+
}
|
27
|
+
DataTypeManager()["T1w"] = dtype_schema
|
28
|
+
|
29
|
+
with pytest.raises(ValueError, match="Invalid"):
|
30
|
+
DataTypeManager()["DType"] = ""
|
31
|
+
|
32
|
+
|
33
|
+
def test_dtype_mgr_removal_errors() -> None:
|
34
|
+
"""Test data type manager removal errors."""
|
35
|
+
with pytest.raises(ValueError, match="Cannot delete"):
|
36
|
+
_ = DataTypeManager().pop("T1w")
|
37
|
+
|
38
|
+
with pytest.raises(KeyError, match="DType"):
|
39
|
+
del DataTypeManager()["DType"]
|
40
|
+
|
41
|
+
|
42
|
+
@pytest.mark.parametrize(
|
43
|
+
"dtype",
|
44
|
+
[
|
45
|
+
{
|
46
|
+
"mandatory": ["pattern"],
|
47
|
+
"optional": {},
|
48
|
+
},
|
49
|
+
{
|
50
|
+
"mandatory": ["pattern"],
|
51
|
+
"optional": {
|
52
|
+
"subtype": {
|
53
|
+
"mandatory": [],
|
54
|
+
"optional": [],
|
55
|
+
}
|
56
|
+
},
|
57
|
+
},
|
58
|
+
{
|
59
|
+
"mandatory": ["pattern"],
|
60
|
+
"optional": {
|
61
|
+
"subtype": {
|
62
|
+
"mandatory": ["pattern"],
|
63
|
+
"optional": [],
|
64
|
+
}
|
65
|
+
},
|
66
|
+
},
|
67
|
+
{
|
68
|
+
"mandatory": ["pattern"],
|
69
|
+
"optional": {
|
70
|
+
"subtype": {
|
71
|
+
"mandatory": ["pattern"],
|
72
|
+
"optional": ["pattern"],
|
73
|
+
}
|
74
|
+
},
|
75
|
+
},
|
76
|
+
],
|
77
|
+
)
|
78
|
+
def test_dtype_mgr(dtype: DataTypeSchema) -> None:
|
79
|
+
"""Test data type manager addition and removal.
|
80
|
+
|
81
|
+
Parameters
|
82
|
+
----------
|
83
|
+
dtype : DataTypeSchema
|
84
|
+
The parametrized schema.
|
85
|
+
|
86
|
+
"""
|
87
|
+
|
88
|
+
DataTypeManager().update({"DType": dtype})
|
89
|
+
assert "DType" in DataTypeManager()
|
90
|
+
|
91
|
+
_ = DataTypeManager().pop("DType")
|
92
|
+
assert "DType" not in DataTypeManager()
|
93
|
+
|
94
|
+
|
95
|
+
def test_register_data_type() -> None:
|
96
|
+
"""Test data type registration."""
|
97
|
+
|
98
|
+
dtype_schema: DataTypeSchema = {
|
99
|
+
"mandatory": ["pattern"],
|
100
|
+
"optional": {
|
101
|
+
"mask": {
|
102
|
+
"mandatory": ["pattern"],
|
103
|
+
"optional": [],
|
104
|
+
},
|
105
|
+
},
|
106
|
+
}
|
107
|
+
|
108
|
+
register_data_type(
|
109
|
+
name="dtype",
|
110
|
+
schema=dtype_schema,
|
111
|
+
)
|
112
|
+
|
113
|
+
assert "dtype" in DataTypeManager()
|
114
|
+
_ = DataTypeManager().pop("dtype")
|
115
|
+
assert "dumb" not in DataTypeManager()
|
13
116
|
|
14
117
|
|
15
118
|
@pytest.mark.parametrize(
|
junifer/typing/__init__.pyi
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
__all__ = [
|
2
2
|
"DataGrabberLike",
|
3
|
+
"DataRegistryLike",
|
3
4
|
"PreprocessorLike",
|
4
5
|
"MarkerLike",
|
5
6
|
"StorageLike",
|
@@ -16,6 +17,7 @@ __all__ = [
|
|
16
17
|
|
17
18
|
from ._typing import (
|
18
19
|
DataGrabberLike,
|
20
|
+
DataRegistryLike,
|
19
21
|
PreprocessorLike,
|
20
22
|
MarkerLike,
|
21
23
|
StorageLike,
|
junifer/typing/_typing.py
CHANGED
@@ -11,6 +11,7 @@ from typing import (
|
|
11
11
|
|
12
12
|
|
13
13
|
if TYPE_CHECKING:
|
14
|
+
from ..data import BasePipelineDataRegistry
|
14
15
|
from ..datagrabber import BaseDataGrabber
|
15
16
|
from ..datareader import DefaultDataReader
|
16
17
|
from ..markers import BaseMarker
|
@@ -23,6 +24,7 @@ __all__ = [
|
|
23
24
|
"ConfigVal",
|
24
25
|
"DataGrabberLike",
|
25
26
|
"DataGrabberPatterns",
|
27
|
+
"DataRegistryLike",
|
26
28
|
"Dependencies",
|
27
29
|
"Element",
|
28
30
|
"Elements",
|
@@ -35,6 +37,7 @@ __all__ = [
|
|
35
37
|
]
|
36
38
|
|
37
39
|
|
40
|
+
DataRegistryLike = type["BasePipelineDataRegistry"]
|
38
41
|
DataGrabberLike = type["BaseDataGrabber"]
|
39
42
|
PreprocessorLike = type["BasePreprocessor"]
|
40
43
|
MarkerLike = type["BaseMarker"]
|
@@ -61,7 +64,7 @@ ConditionalDependencies = Sequence[
|
|
61
64
|
ExternalDependencies = Sequence[MutableMapping[str, Union[str, Sequence[str]]]]
|
62
65
|
MarkerInOutMappings = MutableMapping[str, MutableMapping[str, str]]
|
63
66
|
DataGrabberPatterns = dict[
|
64
|
-
str, Union[dict[str, str],
|
67
|
+
str, Union[dict[str, str], list[dict[str, str]]]
|
65
68
|
]
|
66
69
|
ConfigVal = Union[bool, int, float, str]
|
67
70
|
Element = Union[str, tuple[str, ...]]
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: junifer
|
3
|
-
Version: 0.0.7.
|
3
|
+
Version: 0.0.7.dev93
|
4
4
|
Summary: JUelich NeuroImaging FEature extractoR
|
5
5
|
Author-email: Fede Raimondo <f.raimondo@fz-juelich.de>, Synchon Mandal <s.mandal@fz-juelich.de>
|
6
6
|
Maintainer-email: Fede Raimondo <f.raimondo@fz-juelich.de>, Synchon Mandal <s.mandal@fz-juelich.de>
|
@@ -1,12 +1,12 @@
|
|
1
1
|
junifer/__init__.py,sha256=2McgH1yNue6Z1V26-uN_mfMjbTcx4CLhym-DMBl5xA4,266
|
2
2
|
junifer/__init__.pyi,sha256=SsTvgq2Dod6UqJN96GH1lCphH6hJQQurEJHGNhHjGUI,508
|
3
|
-
junifer/_version.py,sha256=
|
3
|
+
junifer/_version.py,sha256=vFYsjG-TWfjglJG7fH8rtbhQ3pjvXxlnFjXQw4toOfM,526
|
4
4
|
junifer/conftest.py,sha256=PWYkkRDU8ly2lYwv7VBKMHje4et6HX7Yey3Md_I2KbA,613
|
5
5
|
junifer/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
6
|
junifer/stats.py,sha256=e9aaagMGtgpRfW3Wdpz9ocpnYld1IWylCDcjFUgX9Mk,6225
|
7
7
|
junifer/api/__init__.py,sha256=aAXW_KAEGQ8aAP5Eni2G1R4MWBF7UgjKOgM6akLuJco,252
|
8
8
|
junifer/api/__init__.pyi,sha256=UJu55ApMFd43N0xlQyNKrYpCdzqhAxA3Jjaj0ETwCXU,169
|
9
|
-
junifer/api/decorators.py,sha256=
|
9
|
+
junifer/api/decorators.py,sha256=hBmJbJIedXvCxzvxWBQond3Nu9oSTd2e7dvJ_QZ9zF0,3635
|
10
10
|
junifer/api/functions.py,sha256=LXKPqsfWINq1iSUShdryGB8hPOyyydc1ldHfr68bP20,14226
|
11
11
|
junifer/api/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
12
|
junifer/api/queue_context/__init__.py,sha256=glr8x4aMm4EvVrHywDIlugdNlwD1RzqV2FTDNPqYQZ4,204
|
@@ -40,6 +40,7 @@ junifer/api/res/fsl/flirt,sha256=tSjiUco8ui8AbHD7mTzChEwbR0Rf_4iJTgzYTPF_WuQ,42
|
|
40
40
|
junifer/api/res/fsl/img2imgcoord,sha256=Zmaw3oJYrEltcXiPyEubXry9ppAq3SND52tdDWGgeZk,49
|
41
41
|
junifer/api/res/fsl/run_fsl_docker.sh,sha256=pq-fcNdLuvHzVIQePN4GebZGlcE2UF-xj5rBIqAMz4g,1122
|
42
42
|
junifer/api/res/fsl/std2imgcoord,sha256=-X5wRH6XMl0yqnTACJX6MFhO8DFOEWg42MHRxGvimXg,49
|
43
|
+
junifer/api/tests/test_decorators.py,sha256=GN4wSRDJncqa1Jz9krNY_Ls9e6ge9xaGyOpaiSSXibk,759
|
43
44
|
junifer/api/tests/test_functions.py,sha256=HcJIBCtcgL1xJlDwtGHrGOWBMjXgCoAFoVxQW6n2Tds,20676
|
44
45
|
junifer/cli/__init__.py,sha256=LRmpmMe0DdZKYZTV61onUiLLxYZ_ZYSfmRbH55bBJMg,500
|
45
46
|
junifer/cli/__init__.pyi,sha256=PiV4znUnzSeuSSJGz-RT8N21PiMqoSMwYcypi7nt2Js,40
|
@@ -71,8 +72,8 @@ junifer/configs/juseless/datagrabbers/tests/test_ixi_vbm.py,sha256=8jxpNZelXwpJG
|
|
71
72
|
junifer/configs/juseless/datagrabbers/tests/test_ucla.py,sha256=l-1y_m6NJo7JExhyIzp-vajUfiqiofX69YUOrRHIFKw,3246
|
72
73
|
junifer/configs/juseless/datagrabbers/tests/test_ukb_vbm.py,sha256=b9hjc1mgO--PSRC3id2EzzfE2yWNsuZ2UI47a6sfGZU,1025
|
73
74
|
junifer/data/__init__.py,sha256=xJDI2QKtdjcNzpd1oVFM3guh1SFHM6jKstl7pFmzOuk,267
|
74
|
-
junifer/data/__init__.pyi,sha256=
|
75
|
-
junifer/data/_dispatch.py,sha256=
|
75
|
+
junifer/data/__init__.pyi,sha256=yt6gNTY8fgv9O5HjUqEHdKkO7Oo3q4dVp-aeqP4q5PY,682
|
76
|
+
junifer/data/_dispatch.py,sha256=l1UbmSQyrAVzfYopaijUFIkbHntFdIxsA8RpRHjvcf0,7519
|
76
77
|
junifer/data/pipeline_data_registry_base.py,sha256=G8bE3WTj4D_rKC4ZKZe6E48Sd96CGea1PS3SxmTgGK4,2010
|
77
78
|
junifer/data/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
78
79
|
junifer/data/template_spaces.py,sha256=7LcQbUV_SWCic-TtETCejgat-BxxFDxZFm5z80rRZ-M,4661
|
@@ -80,32 +81,33 @@ junifer/data/utils.py,sha256=zVqlkc2jXFDv1jx8plXBHRL6y0h1eR_XzH7fkTJ6ric,3978
|
|
80
81
|
junifer/data/coordinates/__init__.py,sha256=ffM8rwcHLgHAWixJbKrATrbUKzX940V1UF6RAxZdUMg,186
|
81
82
|
junifer/data/coordinates/__init__.pyi,sha256=Z-Ti5XD3HigkZ8uYN6oYsLqw40-F1GvTVQ5QAy08Wng,88
|
82
83
|
junifer/data/coordinates/_ants_coordinates_warper.py,sha256=9nIdg4B5EMje8s30n_8Dl7eYko3HmVJ8jyZpXETg8Sk,2976
|
83
|
-
junifer/data/coordinates/_coordinates.py,sha256=
|
84
|
+
junifer/data/coordinates/_coordinates.py,sha256=l-nu-eGdW2Cp4eDmnrSsuWE-zcj55apPab5pTt07SwU,13303
|
84
85
|
junifer/data/coordinates/_fsl_coordinates_warper.py,sha256=fxxvsiq-hSeP_PDokMHJSxlyffMugzSDUHhKzuU7Vg4,2429
|
85
86
|
junifer/data/coordinates/tests/test_coordinates.py,sha256=JG045I7l5zcxGRQMbZZTrJY0TI5ZKaJ_szGMB6j1ZRI,4623
|
86
87
|
junifer/data/masks/__init__.py,sha256=eEEhHglyVEx1LrqwXjq3cOmjf4sTsgBstRx5-k7zIQU,180
|
87
88
|
junifer/data/masks/__init__.pyi,sha256=lcgr8gmWDPibC4RxnWBXb8DDpIkO73Aax09u6VXiJJI,114
|
88
89
|
junifer/data/masks/_ants_mask_warper.py,sha256=YJYVuD4QkgFwUSs1edt2rrqfHYHaIR1u85HSeQE4GUk,5825
|
89
90
|
junifer/data/masks/_fsl_mask_warper.py,sha256=7-Aw4m9GA7ZLqB26jjuKYJUJSv9V11DfPFNBbb5caSE,2877
|
90
|
-
junifer/data/masks/_masks.py,sha256=
|
91
|
+
junifer/data/masks/_masks.py,sha256=hOQ_VpXW8HvOfpd7-bxxvPClEn5WT3WQHro2Ofrtna8,28602
|
91
92
|
junifer/data/masks/tests/test_masks.py,sha256=VK3IenIwhaYpbESe0pOjb40OKE6rcRlw8ddsBxSRfyU,16688
|
92
93
|
junifer/data/parcellations/__init__.py,sha256=6-Ysil3NyZ69V6rWx4RO15_d-iDKizfbHuxSjsHNt24,188
|
93
94
|
junifer/data/parcellations/__init__.pyi,sha256=lhBHTbMDizzqUqVHrx2eyfPFodrTBgMFeTgxfESSkQ8,140
|
94
95
|
junifer/data/parcellations/_ants_parcellation_warper.py,sha256=LIfeIAv3bFQbIrl6Cr7RU2RdkA-c2G6qURIBUe5MJCQ,5826
|
95
96
|
junifer/data/parcellations/_fsl_parcellation_warper.py,sha256=lmZDPv2fMjOnbJ0z2d3K9S7QH2bgYd5bXbzxNDUR5NY,2699
|
96
|
-
junifer/data/parcellations/_parcellations.py,sha256=
|
97
|
-
junifer/data/parcellations/tests/test_parcellations.py,sha256=
|
97
|
+
junifer/data/parcellations/_parcellations.py,sha256=e5Cd6VptKNZaqmAnfuhfMPeb48utimAkq5h4JioaB5w,48428
|
98
|
+
junifer/data/parcellations/tests/test_parcellations.py,sha256=s3TtsXTw7wEb-FvW0pFX2QcIXjp9IwlgjtM8X95rz_8,37544
|
98
99
|
junifer/data/tests/test_data_utils.py,sha256=6-UQ7HDZ7_zA7iQalzk29KJBdftQMVyqKsQ0tx1URkE,1062
|
100
|
+
junifer/data/tests/test_dispatch.py,sha256=bm4R0E8gs_XpJ6B5lfWFXjle7PmDjaX7Wu0L6mEU33w,2315
|
99
101
|
junifer/data/tests/test_template_spaces.py,sha256=ZEicEcLqOJ-NpuBZ5SYh4yZ0xZRkhYHnYXiC_YSxjrY,3219
|
100
102
|
junifer/datagrabber/__init__.py,sha256=EHIK-lbjuvkt0V8ypFvLSt85OAAXSkaxBmVlCbNNz8M,323
|
101
|
-
junifer/datagrabber/__init__.pyi,sha256=
|
103
|
+
junifer/datagrabber/__init__.pyi,sha256=4Eydc8RO4TN8TLRDq68cdbJPQMxGEynQwU2bmmWStLg,1027
|
102
104
|
junifer/datagrabber/base.py,sha256=Llr5bHyHovkySI-bzxoQ1TklEF6WOaNRN9D_srqQvYM,6661
|
103
105
|
junifer/datagrabber/datalad_base.py,sha256=52T2DbqDGOxiKSESBESzElrVJ3WihLWrrGlQewSvYOs,12616
|
104
106
|
junifer/datagrabber/dmcc13_benchmark.py,sha256=VMyiwvkr4qSvzBICSksPPKOI2w_WVo06H89Url-hrNs,12819
|
105
107
|
junifer/datagrabber/multiple.py,sha256=4tCOzojs3hoG7daHJJ7HUsx15atWR5nTmyP0S0__aig,6666
|
106
108
|
junifer/datagrabber/pattern.py,sha256=hZxXc59qFGiH710aZkcVgt-JcvVjuR-EMmQ1_QFAoHM,18724
|
107
109
|
junifer/datagrabber/pattern_datalad.py,sha256=7jY-0Xw0G-mKG0BgXNTQPuS-KPnpFhvqfVOZtD6Yfcc,4567
|
108
|
-
junifer/datagrabber/pattern_validation_mixin.py,sha256=
|
110
|
+
junifer/datagrabber/pattern_validation_mixin.py,sha256=UpeSy9jNtJ_5OL5IqlLIFPOMg0SFTHcOTpW3DlepE9g,23696
|
109
111
|
junifer/datagrabber/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
110
112
|
junifer/datagrabber/aomic/__init__.py,sha256=ATxzXq9NBPmWowTMuL77zqrmIbbnk0Wd1iXtXCP3XDg,266
|
111
113
|
junifer/datagrabber/aomic/__init__.pyi,sha256=Rp6C075fZDdKY8VIq508_g4NhVj8bWzR6zb9yln761Q,189
|
@@ -128,7 +130,7 @@ junifer/datagrabber/tests/test_dmcc13_benchmark.py,sha256=h5zLrcP7BbSCeGLt2VfCsi
|
|
128
130
|
junifer/datagrabber/tests/test_multiple.py,sha256=tZBQhlEiSE1PeQ5E3TtuVgsHENquna9t39p54AJ-O5w,9963
|
129
131
|
junifer/datagrabber/tests/test_pattern.py,sha256=H55jYRPfT3rMsoIQOAnWJgw3nGrkU7m2xFa3-ed6NQE,9527
|
130
132
|
junifer/datagrabber/tests/test_pattern_datalad.py,sha256=HJ3dQ3XSlMZ3UT1w2b2xpdPqvfmNxRWmla9zhRejWYI,6483
|
131
|
-
junifer/datagrabber/tests/test_pattern_validation_mixin.py,sha256=
|
133
|
+
junifer/datagrabber/tests/test_pattern_validation_mixin.py,sha256=yzUBRB4it_2BCNcp8syh5n3WejRRI6YfMg5T-p4_IkM,9982
|
132
134
|
junifer/datareader/__init__.py,sha256=CDWjL4PQthskxWX5d0ASro6YIfTT1Tb7ZmyDllWWZso,318
|
133
135
|
junifer/datareader/__init__.pyi,sha256=VOqhh-C3-eqapHVR7-F9Ulc_6iyHTb35XLoGb2DCRaA,72
|
134
136
|
junifer/datareader/default.py,sha256=q8aXHlBzLtRtgM2z3JWIsB-daSZncr33mliZlV5RzdM,6733
|
@@ -305,8 +307,8 @@ junifer/testing/tests/test_testing_registry.py,sha256=MK4a_q4MHieCvYhnhuPm_dH76l
|
|
305
307
|
junifer/tests/test_main.py,sha256=GMff7jlisGM9_FsiUwWDte43j-KQJGFRYZpwRRqTkd8,373
|
306
308
|
junifer/tests/test_stats.py,sha256=NljoGFu2JOPADbi9W0WeUHwpf8nZSdOkcCgCv-Z1fY4,4149
|
307
309
|
junifer/typing/__init__.py,sha256=e0UbuxozXUIxz8h8pLokMOxZV629Q1lnA7vvgm95WF0,215
|
308
|
-
junifer/typing/__init__.pyi,sha256=
|
309
|
-
junifer/typing/_typing.py,sha256=
|
310
|
+
junifer/typing/__init__.pyi,sha256=5jzVAkras38Eou5abUvdP1AXhbpCSnPAllLx88YuPB8,640
|
311
|
+
junifer/typing/_typing.py,sha256=JogiI9wCZWHuqgTaZarjk89aA5pR0yTvFx2JfheLT_Y,1783
|
310
312
|
junifer/utils/__init__.py,sha256=I3tYaePAD_ZEU-36-TJ_OYeqW_aMmi5MZ3jmqie6RfU,260
|
311
313
|
junifer/utils/__init__.pyi,sha256=CMb4rq1VcQ00IRuiBFfAWu07Vb-vA4qtVLAoY0ll-bA,422
|
312
314
|
junifer/utils/_config.py,sha256=cfxyv1bfklID2atQseu6y3J7mZrCXPwnGEfBSImG9CM,3054
|
@@ -320,10 +322,10 @@ junifer/utils/tests/test_config.py,sha256=7ltIXuwb_W4Mv_1dxQWyiyM10XgUAfsWKV6D_i
|
|
320
322
|
junifer/utils/tests/test_fs.py,sha256=WQS7cKlKEZ742CIuiOYYpueeAhY9PqlastfDVpVVtvE,923
|
321
323
|
junifer/utils/tests/test_helpers.py,sha256=k5qqfxK8dFyuewTJyR1Qn6-nFaYNuVr0ysc18bfPjyU,929
|
322
324
|
junifer/utils/tests/test_logging.py,sha256=W4tFKmaf8_CxnWZ-o_-XxM7DQbhGG18RsLZJk8bZelI,8163
|
323
|
-
junifer-0.0.7.
|
324
|
-
junifer-0.0.7.
|
325
|
-
junifer-0.0.7.
|
326
|
-
junifer-0.0.7.
|
327
|
-
junifer-0.0.7.
|
328
|
-
junifer-0.0.7.
|
329
|
-
junifer-0.0.7.
|
325
|
+
junifer-0.0.7.dev93.dist-info/licenses/AUTHORS.rst,sha256=rmULKpchpSol4ExWFdm-qu4fkpSZPYqIESVJBZtGb6E,163
|
326
|
+
junifer-0.0.7.dev93.dist-info/licenses/LICENSE.md,sha256=MqCnOBu8uXsEOzRZWh9EBVfVz-kE9NkXcLCrtGXo2yU,34354
|
327
|
+
junifer-0.0.7.dev93.dist-info/METADATA,sha256=XJDtsS1aolWYxCr-iCbrso20QFIP8bciZm9-BxskKWk,8387
|
328
|
+
junifer-0.0.7.dev93.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
329
|
+
junifer-0.0.7.dev93.dist-info/entry_points.txt,sha256=6O8ru0BP-SP7YMUZiizFNoaZ2HvJpadO2G7nKk4PwjI,48
|
330
|
+
junifer-0.0.7.dev93.dist-info/top_level.txt,sha256=4bAq1R2QFQ4b3hohjys2JBvxrl0GKk5LNFzYvz9VGcA,8
|
331
|
+
junifer-0.0.7.dev93.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|