junifer 0.0.6.dev154__py3-none-any.whl → 0.0.6.dev175__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/__init__.pyi +2 -0
- junifer/_version.py +2 -2
- junifer/api/decorators.py +6 -11
- junifer/api/functions.py +74 -62
- junifer/api/tests/test_functions.py +2 -2
- junifer/datagrabber/aomic/piop2.py +1 -1
- junifer/pipeline/__init__.pyi +2 -2
- junifer/pipeline/pipeline_component_registry.py +299 -0
- junifer/pipeline/tests/test_pipeline_component_registry.py +201 -0
- junifer/testing/__init__.pyi +2 -2
- junifer/testing/registry.py +4 -7
- junifer/testing/tests/test_testing_registry.py +9 -17
- {junifer-0.0.6.dev154.dist-info → junifer-0.0.6.dev175.dist-info}/METADATA +1 -1
- {junifer-0.0.6.dev154.dist-info → junifer-0.0.6.dev175.dist-info}/RECORD +19 -19
- junifer/pipeline/registry.py +0 -245
- junifer/pipeline/tests/test_registry.py +0 -150
- {junifer-0.0.6.dev154.dist-info → junifer-0.0.6.dev175.dist-info}/AUTHORS.rst +0 -0
- {junifer-0.0.6.dev154.dist-info → junifer-0.0.6.dev175.dist-info}/LICENSE.md +0 -0
- {junifer-0.0.6.dev154.dist-info → junifer-0.0.6.dev175.dist-info}/WHEEL +0 -0
- {junifer-0.0.6.dev154.dist-info → junifer-0.0.6.dev175.dist-info}/entry_points.txt +0 -0
- {junifer-0.0.6.dev154.dist-info → junifer-0.0.6.dev175.dist-info}/top_level.txt +0 -0
junifer/__init__.pyi
CHANGED
junifer/_version.py
CHANGED
@@ -12,5 +12,5 @@ __version__: str
|
|
12
12
|
__version_tuple__: VERSION_TUPLE
|
13
13
|
version_tuple: VERSION_TUPLE
|
14
14
|
|
15
|
-
__version__ = version = '0.0.6.
|
16
|
-
__version_tuple__ = version_tuple = (0, 0, 6, '
|
15
|
+
__version__ = version = '0.0.6.dev175'
|
16
|
+
__version_tuple__ = version_tuple = (0, 0, 6, 'dev175')
|
junifer/api/decorators.py
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
|
8
8
|
from typing import Type
|
9
9
|
|
10
|
-
from ..pipeline
|
10
|
+
from ..pipeline import PipelineComponentRegistry
|
11
11
|
|
12
12
|
|
13
13
|
__all__ = [
|
@@ -39,9 +39,8 @@ def register_datagrabber(klass: Type) -> Type:
|
|
39
39
|
It should only be used as a decorator.
|
40
40
|
|
41
41
|
"""
|
42
|
-
register(
|
42
|
+
PipelineComponentRegistry().register(
|
43
43
|
step="datagrabber",
|
44
|
-
name=klass.__name__,
|
45
44
|
klass=klass,
|
46
45
|
)
|
47
46
|
return klass
|
@@ -67,9 +66,8 @@ def register_datareader(klass: Type) -> Type:
|
|
67
66
|
It should only be used as a decorator.
|
68
67
|
|
69
68
|
"""
|
70
|
-
register(
|
69
|
+
PipelineComponentRegistry().register(
|
71
70
|
step="datareader",
|
72
|
-
name=klass.__name__,
|
73
71
|
klass=klass,
|
74
72
|
)
|
75
73
|
return klass
|
@@ -91,9 +89,8 @@ def register_preprocessor(klass: Type) -> Type:
|
|
91
89
|
The unmodified input class.
|
92
90
|
|
93
91
|
"""
|
94
|
-
register(
|
92
|
+
PipelineComponentRegistry().register(
|
95
93
|
step="preprocessing",
|
96
|
-
name=klass.__name__,
|
97
94
|
klass=klass,
|
98
95
|
)
|
99
96
|
return klass
|
@@ -115,9 +112,8 @@ def register_marker(klass: Type) -> Type:
|
|
115
112
|
The unmodified input class.
|
116
113
|
|
117
114
|
"""
|
118
|
-
register(
|
115
|
+
PipelineComponentRegistry().register(
|
119
116
|
step="marker",
|
120
|
-
name=klass.__name__,
|
121
117
|
klass=klass,
|
122
118
|
)
|
123
119
|
return klass
|
@@ -139,9 +135,8 @@ def register_storage(klass: Type) -> Type:
|
|
139
135
|
The unmodified input class.
|
140
136
|
|
141
137
|
"""
|
142
|
-
register(
|
138
|
+
PipelineComponentRegistry().register(
|
143
139
|
step="storage",
|
144
|
-
name=klass.__name__,
|
145
140
|
klass=klass,
|
146
141
|
)
|
147
142
|
return klass
|
junifer/api/functions.py
CHANGED
@@ -7,15 +7,17 @@
|
|
7
7
|
|
8
8
|
import os
|
9
9
|
import shutil
|
10
|
-
import typing
|
11
10
|
from pathlib import Path
|
12
11
|
from typing import Dict, List, Optional, Tuple, Union
|
13
12
|
|
14
13
|
from ..api.queue_context import GnuParallelLocalAdapter, HTCondorAdapter
|
15
14
|
from ..datagrabber.base import BaseDataGrabber
|
16
15
|
from ..markers.base import BaseMarker
|
17
|
-
from ..pipeline import
|
18
|
-
|
16
|
+
from ..pipeline import (
|
17
|
+
MarkerCollection,
|
18
|
+
PipelineComponentRegistry,
|
19
|
+
WorkDirManager,
|
20
|
+
)
|
19
21
|
from ..preprocess.base import BasePreprocessor
|
20
22
|
from ..storage.base import BaseFeatureStorage
|
21
23
|
from ..utils import logger, raise_error, yaml
|
@@ -38,42 +40,78 @@ def _get_datagrabber(datagrabber_config: Dict) -> BaseDataGrabber:
|
|
38
40
|
The DataGrabber.
|
39
41
|
|
40
42
|
"""
|
41
|
-
|
42
|
-
datagrabber_kind = datagrabber_params.pop("kind")
|
43
|
-
datagrabber = build(
|
43
|
+
return PipelineComponentRegistry().build_component_instance(
|
44
44
|
step="datagrabber",
|
45
|
-
name=
|
45
|
+
name=datagrabber_config.pop("kind"),
|
46
46
|
baseclass=BaseDataGrabber,
|
47
|
-
init_params=
|
47
|
+
init_params=datagrabber_config,
|
48
48
|
)
|
49
|
-
datagrabber = typing.cast(BaseDataGrabber, datagrabber)
|
50
|
-
return datagrabber
|
51
49
|
|
52
50
|
|
53
51
|
def _get_preprocessor(preprocessing_config: Dict) -> BasePreprocessor:
|
54
|
-
"""Get
|
52
|
+
"""Get Preprocessor.
|
55
53
|
|
56
54
|
Parameters
|
57
55
|
----------
|
58
56
|
preprocessing_config : dict
|
59
|
-
The config to get the
|
57
|
+
The config to get the Preprocessor using.
|
60
58
|
|
61
59
|
Returns
|
62
60
|
-------
|
63
61
|
dict
|
64
|
-
The
|
62
|
+
The Preprocessor.
|
65
63
|
|
66
64
|
"""
|
67
|
-
|
68
|
-
preprocessor_kind = preprocessor_params.pop("kind")
|
69
|
-
preprocessor = build(
|
65
|
+
return PipelineComponentRegistry().build_component_instance(
|
70
66
|
step="preprocessing",
|
71
|
-
name=
|
67
|
+
name=preprocessing_config.pop("kind"),
|
72
68
|
baseclass=BasePreprocessor,
|
73
|
-
init_params=
|
69
|
+
init_params=preprocessing_config,
|
70
|
+
)
|
71
|
+
|
72
|
+
|
73
|
+
def _get_marker(marker_config: Dict) -> BaseMarker:
|
74
|
+
"""Get Marker.
|
75
|
+
|
76
|
+
Parameters
|
77
|
+
----------
|
78
|
+
marker_config : dict
|
79
|
+
The config to get the Marker using.
|
80
|
+
|
81
|
+
Returns
|
82
|
+
-------
|
83
|
+
object
|
84
|
+
The Marker.
|
85
|
+
|
86
|
+
"""
|
87
|
+
return PipelineComponentRegistry().build_component_instance(
|
88
|
+
step="marker",
|
89
|
+
name=marker_config.pop("kind"),
|
90
|
+
baseclass=BaseMarker,
|
91
|
+
init_params=marker_config,
|
92
|
+
)
|
93
|
+
|
94
|
+
|
95
|
+
def _get_storage(storage_config: Dict) -> BaseFeatureStorage:
|
96
|
+
"""Get Storage.
|
97
|
+
|
98
|
+
Parameters
|
99
|
+
----------
|
100
|
+
storage_config : dict
|
101
|
+
The config to get the Storage using.
|
102
|
+
|
103
|
+
Returns
|
104
|
+
-------
|
105
|
+
dict
|
106
|
+
The Storage.
|
107
|
+
|
108
|
+
"""
|
109
|
+
return PipelineComponentRegistry().build_component_instance(
|
110
|
+
step="storage",
|
111
|
+
name=storage_config.pop("kind"),
|
112
|
+
baseclass=BaseFeatureStorage,
|
113
|
+
init_params=storage_config,
|
74
114
|
)
|
75
|
-
preprocessor = typing.cast(BasePreprocessor, preprocessor)
|
76
|
-
return preprocessor
|
77
115
|
|
78
116
|
|
79
117
|
def run(
|
@@ -123,41 +161,22 @@ def run(
|
|
123
161
|
elements = [elements]
|
124
162
|
|
125
163
|
# Get datagrabber to use
|
126
|
-
datagrabber_object = _get_datagrabber(datagrabber)
|
164
|
+
datagrabber_object = _get_datagrabber(datagrabber.copy())
|
127
165
|
|
128
|
-
#
|
129
|
-
|
130
|
-
built_markers = []
|
131
|
-
for t_marker in _markers:
|
132
|
-
kind = t_marker.pop("kind")
|
133
|
-
t_m = build(
|
134
|
-
step="marker",
|
135
|
-
name=kind,
|
136
|
-
baseclass=BaseMarker,
|
137
|
-
init_params=t_marker,
|
138
|
-
)
|
139
|
-
built_markers.append(t_m)
|
166
|
+
# Get markers to use
|
167
|
+
built_markers = [_get_marker(marker) for marker in markers.copy()]
|
140
168
|
|
141
169
|
# Get storage engine to use
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
storage_params["single_output"] = False
|
146
|
-
storage_object = build(
|
147
|
-
step="storage",
|
148
|
-
name=storage_kind,
|
149
|
-
baseclass=BaseFeatureStorage,
|
150
|
-
init_params=storage_params,
|
151
|
-
)
|
152
|
-
storage_object = typing.cast(BaseFeatureStorage, storage_object)
|
170
|
+
if "single_output" not in storage:
|
171
|
+
storage["single_output"] = False
|
172
|
+
storage_object = _get_storage(storage.copy())
|
153
173
|
|
154
174
|
# Get preprocessor to use (if provided)
|
155
175
|
if preprocessors is not None:
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
built_preprocessors.append(preprocessor_object)
|
176
|
+
built_preprocessors = [
|
177
|
+
_get_preprocessor(preprocessor)
|
178
|
+
for preprocessor in preprocessors.copy()
|
179
|
+
]
|
161
180
|
else:
|
162
181
|
built_preprocessors = None
|
163
182
|
|
@@ -167,6 +186,7 @@ def run(
|
|
167
186
|
preprocessors=built_preprocessors,
|
168
187
|
storage=storage_object,
|
169
188
|
)
|
189
|
+
# Validate the marker collection for the datagrabber
|
170
190
|
mc.validate(datagrabber_object)
|
171
191
|
|
172
192
|
# Fit elements
|
@@ -192,19 +212,11 @@ def collect(storage: Dict) -> None:
|
|
192
212
|
constructor.
|
193
213
|
|
194
214
|
"""
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
storage_params["single_output"] = False
|
201
|
-
storage_object = build(
|
202
|
-
step="storage",
|
203
|
-
name=storage_kind,
|
204
|
-
baseclass=BaseFeatureStorage,
|
205
|
-
init_params=storage_params,
|
206
|
-
)
|
207
|
-
storage_object = typing.cast(BaseFeatureStorage, storage_object)
|
215
|
+
logger.info(f"Collecting data using {storage['kind']}")
|
216
|
+
logger.debug(f"\tStorage params: {storage}")
|
217
|
+
if "single_output" not in storage:
|
218
|
+
storage["single_output"] = False
|
219
|
+
storage_object = _get_storage(storage.copy())
|
208
220
|
logger.debug("Running storage.collect()")
|
209
221
|
storage_object.collect()
|
210
222
|
logger.info("Collect done")
|
@@ -15,7 +15,7 @@ from ruamel.yaml import YAML
|
|
15
15
|
import junifer.testing.registry # noqa: F401
|
16
16
|
from junifer.api import collect, list_elements, queue, reset, run
|
17
17
|
from junifer.datagrabber.base import BaseDataGrabber
|
18
|
-
from junifer.pipeline
|
18
|
+
from junifer.pipeline import PipelineComponentRegistry
|
19
19
|
|
20
20
|
|
21
21
|
# Configure YAML class
|
@@ -240,7 +240,7 @@ def test_run_and_collect(
|
|
240
240
|
storage=storage,
|
241
241
|
)
|
242
242
|
# Get datagrabber
|
243
|
-
dg =
|
243
|
+
dg = PipelineComponentRegistry().build_component_instance(
|
244
244
|
step="datagrabber", name=datagrabber["kind"], baseclass=BaseDataGrabber
|
245
245
|
)
|
246
246
|
elements = dg.get_elements() # type: ignore
|
junifer/pipeline/__init__.pyi
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
__all__ = [
|
2
|
-
"
|
2
|
+
"PipelineComponentRegistry",
|
3
3
|
"PipelineStepMixin",
|
4
4
|
"UpdateMetaMixin",
|
5
5
|
"WorkDirManager",
|
6
6
|
"MarkerCollection",
|
7
7
|
]
|
8
8
|
|
9
|
-
from . import
|
9
|
+
from .pipeline_component_registry import PipelineComponentRegistry
|
10
10
|
from .pipeline_step_mixin import PipelineStepMixin
|
11
11
|
from .update_meta_mixin import UpdateMetaMixin
|
12
12
|
from .workdir_manager import WorkDirManager
|
@@ -0,0 +1,299 @@
|
|
1
|
+
"""Provide a class for centralized pipeline component registry."""
|
2
|
+
|
3
|
+
# Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
|
4
|
+
# Leonard Sasse <l.sasse@fz-juelich.de>
|
5
|
+
# Synchon Mandal <s.mandal@fz-juelich.de>
|
6
|
+
# License: AGPL
|
7
|
+
|
8
|
+
import importlib
|
9
|
+
from typing import TYPE_CHECKING, Dict, List, Mapping, Optional, Union
|
10
|
+
|
11
|
+
from ..utils import logger, raise_error
|
12
|
+
from .singleton import singleton
|
13
|
+
|
14
|
+
|
15
|
+
if TYPE_CHECKING:
|
16
|
+
from ..datagrabber import BaseDataGrabber
|
17
|
+
from ..storage import BaseFeatureStorage
|
18
|
+
from .pipeline_step_mixin import PipelineStepMixin
|
19
|
+
|
20
|
+
|
21
|
+
__all__ = ["PipelineComponentRegistry"]
|
22
|
+
|
23
|
+
|
24
|
+
@singleton
|
25
|
+
class PipelineComponentRegistry:
|
26
|
+
"""Class for pipeline component registry.
|
27
|
+
|
28
|
+
This class is a singleton and is used for managing pipeline components.
|
29
|
+
It serves as a centralized registry for built-in and third-party pipeline
|
30
|
+
components like datagrabbers, datareaders, preprocessors, markers and
|
31
|
+
storage.
|
32
|
+
|
33
|
+
Attributes
|
34
|
+
----------
|
35
|
+
steps : list of str
|
36
|
+
Valid pipeline steps.
|
37
|
+
components : dict
|
38
|
+
Registered components for valid pipeline steps.
|
39
|
+
|
40
|
+
"""
|
41
|
+
|
42
|
+
def __init__(self) -> None:
|
43
|
+
"""Initialize the class."""
|
44
|
+
# Valid steps for operation
|
45
|
+
self._steps = [
|
46
|
+
"datagrabber",
|
47
|
+
"datareader",
|
48
|
+
"preprocessing",
|
49
|
+
"marker",
|
50
|
+
"storage",
|
51
|
+
]
|
52
|
+
# Step to sub-package mapping
|
53
|
+
self._step_to_subpkg_mappings = {
|
54
|
+
"datagrabber": "datagrabber",
|
55
|
+
"datareader": "datareader",
|
56
|
+
"preprocessing": "preprocess",
|
57
|
+
"marker": "markers",
|
58
|
+
"storage": "storage",
|
59
|
+
}
|
60
|
+
# Component registry for valid steps
|
61
|
+
self._components = {
|
62
|
+
"datagrabber": {
|
63
|
+
"HCP1200": "HCP1200",
|
64
|
+
"BaseDataGrabber": "BaseDataGrabber",
|
65
|
+
"DataladAOMICID1000": "DataladAOMICID1000",
|
66
|
+
"DataladAOMICPIOP1": "DataladAOMICPIOP1",
|
67
|
+
"DataladAOMICPIOP2": "DataladAOMICPIOP2",
|
68
|
+
"DataladDataGrabber": "DataladDataGrabber",
|
69
|
+
"DataladHCP1200": "DataladHCP1200",
|
70
|
+
"DMCC13Benchmark": "DMCC13Benchmark",
|
71
|
+
"MultipleDataGrabber": "MultipleDataGrabber",
|
72
|
+
"PatternDataGrabber": "PatternDataGrabber",
|
73
|
+
"PatternDataladDataGrabber": "PatternDataladDataGrabber",
|
74
|
+
},
|
75
|
+
"datareader": {
|
76
|
+
"DefaultDataReader": "DefaultDataReader",
|
77
|
+
},
|
78
|
+
"preprocessing": {
|
79
|
+
"BasePreprocessor": "BasePreprocessor",
|
80
|
+
"Smoothing": "Smoothing",
|
81
|
+
"SpaceWarper": "SpaceWarper",
|
82
|
+
"fMRIPrepConfoundRemover": "fMRIPrepConfoundRemover",
|
83
|
+
},
|
84
|
+
"marker": {
|
85
|
+
"ALFFParcels": "ALFFParcels",
|
86
|
+
"ALFFSpheres": "ALFFSpheres",
|
87
|
+
"BaseMarker": "BaseMarker",
|
88
|
+
"BrainPrint": "BrainPrint",
|
89
|
+
"CrossParcellationFC": "CrossParcellationFC",
|
90
|
+
"EdgeCentricFCParcels": "EdgeCentricFCParcels",
|
91
|
+
"EdgeCentricFCSpheres": "EdgeCentricFCSpheres",
|
92
|
+
"FunctionalConnectivityParcels": (
|
93
|
+
"FunctionalConnectivityParcels"
|
94
|
+
),
|
95
|
+
"FunctionalConnectivitySpheres": (
|
96
|
+
"FunctionalConnectivitySpheres"
|
97
|
+
),
|
98
|
+
"ParcelAggregation": "ParcelAggregation",
|
99
|
+
"ReHoParcels": "ReHoParcels",
|
100
|
+
"ReHoSpheres": "ReHoSpheres",
|
101
|
+
"RSSETSMarker": "RSSETSMarker",
|
102
|
+
"SphereAggregation": "SphereAggregation",
|
103
|
+
"TemporalSNRParcels": "TemporalSNRParcels",
|
104
|
+
"TemporalSNRSpheres": "TemporalSNRSpheres",
|
105
|
+
},
|
106
|
+
"storage": {
|
107
|
+
"BaseFeatureStorage": "BaseFeatureStorage",
|
108
|
+
"HDF5FeatureStorage": "HDF5FeatureStorage",
|
109
|
+
"PandasBaseFeatureStorage": "PandasBaseFeatureStorage",
|
110
|
+
"SQLiteFeatureStorage": "SQLiteFeatureStorage",
|
111
|
+
},
|
112
|
+
}
|
113
|
+
|
114
|
+
def _check_valid_step(self, step: str) -> None:
|
115
|
+
"""Check if ``step`` is valid."""
|
116
|
+
if step not in self._steps:
|
117
|
+
raise_error(msg=f"Invalid step: {step}", klass=ValueError)
|
118
|
+
|
119
|
+
@property
|
120
|
+
def steps(self) -> List[str]:
|
121
|
+
"""Get valid pipeline steps."""
|
122
|
+
return self._steps
|
123
|
+
|
124
|
+
@property
|
125
|
+
def components(self) -> Mapping[str, Mapping[str, Union[str, type]]]:
|
126
|
+
"""Get registered components for valid pipeline steps."""
|
127
|
+
return self._components
|
128
|
+
|
129
|
+
def register(self, step: str, klass: type) -> None:
|
130
|
+
"""Register ``klass`` under ``step``.
|
131
|
+
|
132
|
+
Parameters
|
133
|
+
----------
|
134
|
+
step : str
|
135
|
+
Name of the pipeline step. For valid steps, check :meth:`.steps`.
|
136
|
+
klass : class
|
137
|
+
Class to be registered.
|
138
|
+
|
139
|
+
Raises
|
140
|
+
------
|
141
|
+
ValueError
|
142
|
+
If the ``step`` is invalid.
|
143
|
+
|
144
|
+
"""
|
145
|
+
# Verify step
|
146
|
+
self._check_valid_step(step)
|
147
|
+
# Log and register
|
148
|
+
name = klass.__name__
|
149
|
+
logger.info(f"Registering {name} in {step}")
|
150
|
+
self._components[step][name] = klass
|
151
|
+
|
152
|
+
def deregister(self, step: str, klass: type) -> None:
|
153
|
+
"""De-register ``klass`` under ``step``.
|
154
|
+
|
155
|
+
Parameters
|
156
|
+
----------
|
157
|
+
step : str
|
158
|
+
Name of the pipeline step. For valid steps, check :meth:`.steps`.
|
159
|
+
klass : class
|
160
|
+
Class to be de-registered.
|
161
|
+
|
162
|
+
Raises
|
163
|
+
------
|
164
|
+
ValueError
|
165
|
+
If the ``step`` is invalid.
|
166
|
+
|
167
|
+
"""
|
168
|
+
# Verify step
|
169
|
+
self._check_valid_step(step)
|
170
|
+
# Log and register
|
171
|
+
name = klass.__name__
|
172
|
+
logger.info(f"De-registering {name} in {step}")
|
173
|
+
_ = self._components[step].pop(name)
|
174
|
+
|
175
|
+
def step_components(self, step: str) -> List[str]:
|
176
|
+
"""Get registered components for ``step``.
|
177
|
+
|
178
|
+
Parameters
|
179
|
+
----------
|
180
|
+
step : str
|
181
|
+
Name of the pipeline step.
|
182
|
+
|
183
|
+
Returns
|
184
|
+
-------
|
185
|
+
list of str
|
186
|
+
List of registered component classes.
|
187
|
+
|
188
|
+
Raises
|
189
|
+
------
|
190
|
+
ValueError
|
191
|
+
If the ``step`` is invalid.
|
192
|
+
|
193
|
+
"""
|
194
|
+
# Verify step
|
195
|
+
self._check_valid_step(step)
|
196
|
+
|
197
|
+
return list(self._components[step].keys())
|
198
|
+
|
199
|
+
def get_class(self, step: str, name: str) -> type:
|
200
|
+
"""Get the class registered under ``name`` for ``step``.
|
201
|
+
|
202
|
+
Parameters
|
203
|
+
----------
|
204
|
+
step : str
|
205
|
+
Name of the pipeline step.
|
206
|
+
name : str
|
207
|
+
Name of the component.
|
208
|
+
|
209
|
+
Returns
|
210
|
+
-------
|
211
|
+
class
|
212
|
+
Registered class.
|
213
|
+
|
214
|
+
Raises
|
215
|
+
------
|
216
|
+
ValueError
|
217
|
+
If the ``step`` or ``name`` is invalid.
|
218
|
+
|
219
|
+
"""
|
220
|
+
# Verify step
|
221
|
+
self._check_valid_step(step)
|
222
|
+
# Verify step name
|
223
|
+
if name not in self._components[step]:
|
224
|
+
raise_error(msg=f"Invalid name: {name}", klass=ValueError)
|
225
|
+
|
226
|
+
# Check if first-time import, then import it
|
227
|
+
if isinstance(self._components[step][name], str):
|
228
|
+
klass = getattr(
|
229
|
+
importlib.import_module(
|
230
|
+
f"junifer.{self._step_to_subpkg_mappings[step]}"
|
231
|
+
),
|
232
|
+
name,
|
233
|
+
)
|
234
|
+
else:
|
235
|
+
klass = self._components[step][name]
|
236
|
+
|
237
|
+
return klass
|
238
|
+
|
239
|
+
def build_component_instance(
|
240
|
+
self,
|
241
|
+
step: str,
|
242
|
+
name: str,
|
243
|
+
baseclass: type,
|
244
|
+
init_params: Optional[Dict] = None,
|
245
|
+
) -> Union["BaseDataGrabber", "PipelineStepMixin", "BaseFeatureStorage"]:
|
246
|
+
"""Build an instance of class registered as ``name``.
|
247
|
+
|
248
|
+
Parameters
|
249
|
+
----------
|
250
|
+
step : str
|
251
|
+
Name of the pipeline step.
|
252
|
+
name : str
|
253
|
+
Name of the component.
|
254
|
+
baseclass : class
|
255
|
+
Base class to be checked against.
|
256
|
+
init_params : dict or None, optional
|
257
|
+
Parameters to pass to the class constructor (default None).
|
258
|
+
|
259
|
+
Returns
|
260
|
+
-------
|
261
|
+
object
|
262
|
+
An instance of the class registered as ``name`` under ``step``.
|
263
|
+
|
264
|
+
Raises
|
265
|
+
------
|
266
|
+
RuntimeError
|
267
|
+
If there is a problem creating the instance.
|
268
|
+
ValueError
|
269
|
+
If the created object with the given name is not a subclass of the
|
270
|
+
base class ``baseclass``.
|
271
|
+
|
272
|
+
"""
|
273
|
+
# Set default init parameters
|
274
|
+
if init_params is None:
|
275
|
+
init_params = {}
|
276
|
+
# Get registered class
|
277
|
+
logger.debug(f"Building {step}/{name}")
|
278
|
+
klass = self.get_class(step=step, name=name)
|
279
|
+
logger.debug(f"\tClass: {klass.__name__}")
|
280
|
+
logger.debug(f"\tInit params: {init_params}")
|
281
|
+
try:
|
282
|
+
# Create instance of the class
|
283
|
+
object_ = klass(**init_params)
|
284
|
+
except (ValueError, TypeError) as e:
|
285
|
+
raise_error(
|
286
|
+
msg=f"Failed to create {step} ({name}). Error: {e}",
|
287
|
+
klass=RuntimeError,
|
288
|
+
exception=e,
|
289
|
+
)
|
290
|
+
# Verify created instance belongs to the base class
|
291
|
+
if not isinstance(object_, baseclass):
|
292
|
+
raise_error(
|
293
|
+
msg=(
|
294
|
+
f"Invalid {step} ({object_.__class__.__name__}). "
|
295
|
+
f"Must inherit from {baseclass.__name__}"
|
296
|
+
),
|
297
|
+
klass=ValueError,
|
298
|
+
)
|
299
|
+
return object_
|