junifer 0.0.6.dev219__py3-none-any.whl → 0.0.6.dev248__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 (67) hide show
  1. junifer/__init__.pyi +2 -0
  2. junifer/_version.py +2 -2
  3. junifer/api/decorators.py +5 -4
  4. junifer/api/functions.py +9 -8
  5. junifer/data/coordinates/_ants_coordinates_warper.py +4 -6
  6. junifer/data/coordinates/_coordinates.py +28 -15
  7. junifer/data/coordinates/_fsl_coordinates_warper.py +4 -6
  8. junifer/data/masks/_ants_mask_warper.py +16 -9
  9. junifer/data/masks/_fsl_mask_warper.py +4 -6
  10. junifer/data/masks/_masks.py +21 -25
  11. junifer/data/parcellations/_ants_parcellation_warper.py +16 -9
  12. junifer/data/parcellations/_fsl_parcellation_warper.py +4 -6
  13. junifer/data/parcellations/_parcellations.py +20 -24
  14. junifer/data/utils.py +67 -3
  15. junifer/datagrabber/aomic/id1000.py +22 -9
  16. junifer/datagrabber/aomic/piop1.py +22 -9
  17. junifer/datagrabber/aomic/piop2.py +22 -9
  18. junifer/datagrabber/base.py +6 -1
  19. junifer/datagrabber/datalad_base.py +15 -8
  20. junifer/datagrabber/dmcc13_benchmark.py +23 -10
  21. junifer/datagrabber/hcp1200/hcp1200.py +18 -7
  22. junifer/datagrabber/multiple.py +2 -1
  23. junifer/datagrabber/pattern.py +65 -35
  24. junifer/datagrabber/pattern_validation_mixin.py +197 -87
  25. junifer/datagrabber/tests/test_dmcc13_benchmark.py +26 -9
  26. junifer/markers/base.py +4 -7
  27. junifer/markers/brainprint.py +4 -4
  28. junifer/markers/complexity/complexity_base.py +3 -3
  29. junifer/markers/ets_rss.py +4 -3
  30. junifer/markers/falff/_afni_falff.py +3 -5
  31. junifer/markers/falff/_junifer_falff.py +3 -3
  32. junifer/markers/falff/falff_base.py +4 -6
  33. junifer/markers/functional_connectivity/crossparcellation_functional_connectivity.py +4 -3
  34. junifer/markers/functional_connectivity/functional_connectivity_base.py +4 -3
  35. junifer/markers/parcel_aggregation.py +4 -3
  36. junifer/markers/reho/_afni_reho.py +3 -5
  37. junifer/markers/reho/_junifer_reho.py +3 -3
  38. junifer/markers/reho/reho_base.py +4 -6
  39. junifer/markers/sphere_aggregation.py +4 -3
  40. junifer/markers/temporal_snr/temporal_snr_base.py +4 -3
  41. junifer/onthefly/_brainprint.py +4 -7
  42. junifer/onthefly/read_transform.py +3 -6
  43. junifer/pipeline/marker_collection.py +6 -12
  44. junifer/pipeline/pipeline_component_registry.py +3 -8
  45. junifer/pipeline/pipeline_step_mixin.py +8 -4
  46. junifer/pipeline/tests/test_pipeline_step_mixin.py +18 -19
  47. junifer/pipeline/tests/test_workdir_manager.py +1 -0
  48. junifer/pipeline/update_meta_mixin.py +21 -17
  49. junifer/preprocess/confounds/fmriprep_confound_remover.py +2 -2
  50. junifer/preprocess/smoothing/_afni_smoothing.py +4 -6
  51. junifer/preprocess/smoothing/_fsl_smoothing.py +4 -7
  52. junifer/preprocess/smoothing/_nilearn_smoothing.py +3 -3
  53. junifer/preprocess/smoothing/smoothing.py +3 -2
  54. junifer/preprocess/warping/_ants_warper.py +26 -7
  55. junifer/preprocess/warping/_fsl_warper.py +22 -8
  56. junifer/preprocess/warping/space_warper.py +34 -6
  57. junifer/preprocess/warping/tests/test_space_warper.py +4 -7
  58. junifer/typing/__init__.py +9 -0
  59. junifer/typing/__init__.pyi +23 -0
  60. junifer/typing/_typing.py +61 -0
  61. {junifer-0.0.6.dev219.dist-info → junifer-0.0.6.dev248.dist-info}/METADATA +2 -1
  62. {junifer-0.0.6.dev219.dist-info → junifer-0.0.6.dev248.dist-info}/RECORD +67 -64
  63. {junifer-0.0.6.dev219.dist-info → junifer-0.0.6.dev248.dist-info}/WHEEL +1 -1
  64. {junifer-0.0.6.dev219.dist-info → junifer-0.0.6.dev248.dist-info}/AUTHORS.rst +0 -0
  65. {junifer-0.0.6.dev219.dist-info → junifer-0.0.6.dev248.dist-info}/LICENSE.md +0 -0
  66. {junifer-0.0.6.dev219.dist-info → junifer-0.0.6.dev248.dist-info}/entry_points.txt +0 -0
  67. {junifer-0.0.6.dev219.dist-info → junifer-0.0.6.dev248.dist-info}/top_level.txt +0 -0
@@ -4,11 +4,12 @@
4
4
  # Kaustubh R. Patil <k.patil@fz-juelich.de>
5
5
  # License: AGPL
6
6
 
7
- from typing import Any, ClassVar, Dict, List, Optional, Set, Union
7
+ from typing import Any, ClassVar, Dict, List, Optional, Union
8
8
 
9
9
  import pandas as pd
10
10
 
11
11
  from ...api.decorators import register_marker
12
+ from ...typing import Dependencies, MarkerInOutMappings
12
13
  from ...utils import logger, raise_error
13
14
  from ..base import BaseMarker
14
15
  from ..parcel_aggregation import ParcelAggregation
@@ -49,9 +50,9 @@ class CrossParcellationFC(BaseMarker):
49
50
 
50
51
  """
51
52
 
52
- _DEPENDENCIES: ClassVar[Set[str]] = {"nilearn"}
53
+ _DEPENDENCIES: ClassVar[Dependencies] = {"nilearn"}
53
54
 
54
- _MARKER_INOUT_MAPPINGS: ClassVar[Dict[str, Dict[str, str]]] = {
55
+ _MARKER_INOUT_MAPPINGS: ClassVar[MarkerInOutMappings] = {
55
56
  "BOLD": {
56
57
  "functional_connectivity": "matrix",
57
58
  },
@@ -5,11 +5,12 @@
5
5
 
6
6
 
7
7
  from abc import abstractmethod
8
- from typing import Any, ClassVar, Dict, List, Optional, Set, Union
8
+ from typing import Any, ClassVar, Dict, List, Optional, Union
9
9
 
10
10
  from sklearn.covariance import EmpiricalCovariance, LedoitWolf
11
11
 
12
12
  from ...external.nilearn import JuniferConnectivityMeasure
13
+ from ...typing import Dependencies, MarkerInOutMappings
13
14
  from ...utils import raise_error
14
15
  from ..base import BaseMarker
15
16
 
@@ -51,9 +52,9 @@ class FunctionalConnectivityBase(BaseMarker):
51
52
 
52
53
  """
53
54
 
54
- _DEPENDENCIES: ClassVar[Set[str]] = {"nilearn", "scikit-learn"}
55
+ _DEPENDENCIES: ClassVar[Dependencies] = {"nilearn", "scikit-learn"}
55
56
 
56
- _MARKER_INOUT_MAPPINGS: ClassVar[Dict[str, Dict[str, str]]] = {
57
+ _MARKER_INOUT_MAPPINGS: ClassVar[MarkerInOutMappings] = {
57
58
  "BOLD": {
58
59
  "functional_connectivity": "matrix",
59
60
  },
@@ -4,7 +4,7 @@
4
4
  # Synchon Mandal <s.mandal@fz-juelich.de>
5
5
  # License: AGPL
6
6
 
7
- from typing import Any, ClassVar, Dict, List, Optional, Set, Union
7
+ from typing import Any, ClassVar, Dict, List, Optional, Union
8
8
 
9
9
  import numpy as np
10
10
  from nilearn.image import math_img
@@ -13,6 +13,7 @@ from nilearn.maskers import NiftiMasker
13
13
  from ..api.decorators import register_marker
14
14
  from ..data import get_data
15
15
  from ..stats import get_aggfunc_by_name
16
+ from ..typing import Dependencies, MarkerInOutMappings
16
17
  from ..utils import logger, raise_error, warn_with_log
17
18
  from .base import BaseMarker
18
19
 
@@ -61,9 +62,9 @@ class ParcelAggregation(BaseMarker):
61
62
 
62
63
  """
63
64
 
64
- _DEPENDENCIES: ClassVar[Set[str]] = {"nilearn", "numpy"}
65
+ _DEPENDENCIES: ClassVar[Dependencies] = {"nilearn", "numpy"}
65
66
 
66
- _MARKER_INOUT_MAPPINGS: ClassVar[Dict[str, Dict[str, str]]] = {
67
+ _MARKER_INOUT_MAPPINGS: ClassVar[MarkerInOutMappings] = {
67
68
  "T1w": {
68
69
  "aggregation": "vector",
69
70
  },
@@ -8,22 +8,20 @@ from pathlib import Path
8
8
  from typing import (
9
9
  TYPE_CHECKING,
10
10
  ClassVar,
11
- Dict,
12
- List,
13
11
  Optional,
14
12
  Tuple,
15
- Union,
16
13
  )
17
14
 
18
15
  import nibabel as nib
19
16
 
20
17
  from ...pipeline import WorkDirManager
18
+ from ...typing import ExternalDependencies
21
19
  from ...utils import logger, run_ext_cmd
22
20
  from ...utils.singleton import Singleton
23
21
 
24
22
 
25
23
  if TYPE_CHECKING:
26
- from nibabel import Nifti1Image
24
+ from nibabel.nifti1 import Nifti1Image
27
25
 
28
26
 
29
27
  __all__ = ["AFNIReHo"]
@@ -37,7 +35,7 @@ class AFNIReHo(metaclass=Singleton):
37
35
 
38
36
  """
39
37
 
40
- _EXT_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, List[str]]]]] = [
38
+ _EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
41
39
  {
42
40
  "name": "afni",
43
41
  "commands": ["3dReHo", "3dAFNItoNIFTI"],
@@ -9,7 +9,6 @@ from pathlib import Path
9
9
  from typing import (
10
10
  TYPE_CHECKING,
11
11
  ClassVar,
12
- Set,
13
12
  Tuple,
14
13
  )
15
14
 
@@ -20,12 +19,13 @@ from nilearn import image as nimg
20
19
  from nilearn import masking as nmask
21
20
 
22
21
  from ...pipeline import WorkDirManager
22
+ from ...typing import Dependencies
23
23
  from ...utils import logger, raise_error
24
24
  from ...utils.singleton import Singleton
25
25
 
26
26
 
27
27
  if TYPE_CHECKING:
28
- from nibabel import Nifti1Image
28
+ from nibabel.nifti1 import Nifti1Image
29
29
 
30
30
 
31
31
  __all__ = ["JuniferReHo"]
@@ -38,7 +38,7 @@ class JuniferReHo(metaclass=Singleton):
38
38
 
39
39
  """
40
40
 
41
- _DEPENDENCIES: ClassVar[Set[str]] = {"numpy", "nilearn", "scipy"}
41
+ _DEPENDENCIES: ClassVar[Dependencies] = {"numpy", "nilearn", "scipy"}
42
42
 
43
43
  def __del__(self) -> None:
44
44
  """Terminate the class."""
@@ -10,13 +10,11 @@ from typing import (
10
10
  Any,
11
11
  ClassVar,
12
12
  Dict,
13
- List,
14
13
  Optional,
15
14
  Tuple,
16
- Type,
17
- Union,
18
15
  )
19
16
 
17
+ from ...typing import ConditionalDependencies, MarkerInOutMappings
20
18
  from ...utils import logger, raise_error
21
19
  from ..base import BaseMarker
22
20
  from ._afni_reho import AFNIReHo
@@ -24,7 +22,7 @@ from ._junifer_reho import JuniferReHo
24
22
 
25
23
 
26
24
  if TYPE_CHECKING:
27
- from nibabel import Nifti1Image
25
+ from nibabel.nifti1 import Nifti1Image
28
26
 
29
27
  __all__ = ["ReHoBase"]
30
28
 
@@ -51,7 +49,7 @@ class ReHoBase(BaseMarker):
51
49
 
52
50
  """
53
51
 
54
- _CONDITIONAL_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, Type]]]] = [
52
+ _CONDITIONAL_DEPENDENCIES: ClassVar[ConditionalDependencies] = [
55
53
  {
56
54
  "using": "afni",
57
55
  "depends_on": AFNIReHo,
@@ -62,7 +60,7 @@ class ReHoBase(BaseMarker):
62
60
  },
63
61
  ]
64
62
 
65
- _MARKER_INOUT_MAPPINGS: ClassVar[Dict[str, Dict[str, str]]] = {
63
+ _MARKER_INOUT_MAPPINGS: ClassVar[MarkerInOutMappings] = {
66
64
  "BOLD": {
67
65
  "reho": "vector",
68
66
  },
@@ -4,12 +4,13 @@
4
4
  # Synchon Mandal <s.mandal@fz-juelich.de>
5
5
  # License: AGPL
6
6
 
7
- from typing import Any, ClassVar, Dict, List, Optional, Set, Union
7
+ from typing import Any, ClassVar, Dict, List, Optional, Union
8
8
 
9
9
  from ..api.decorators import register_marker
10
10
  from ..data import get_data
11
11
  from ..external.nilearn import JuniferNiftiSpheresMasker
12
12
  from ..stats import get_aggfunc_by_name
13
+ from ..typing import Dependencies, MarkerInOutMappings
13
14
  from ..utils import logger, raise_error, warn_with_log
14
15
  from .base import BaseMarker
15
16
 
@@ -66,9 +67,9 @@ class SphereAggregation(BaseMarker):
66
67
 
67
68
  """
68
69
 
69
- _DEPENDENCIES: ClassVar[Set[str]] = {"nilearn", "numpy"}
70
+ _DEPENDENCIES: ClassVar[Dependencies] = {"nilearn", "numpy"}
70
71
 
71
- _MARKER_INOUT_MAPPINGS: ClassVar[Dict[str, Dict[str, str]]] = {
72
+ _MARKER_INOUT_MAPPINGS: ClassVar[MarkerInOutMappings] = {
72
73
  "T1w": {
73
74
  "aggregation": "vector",
74
75
  },
@@ -5,10 +5,11 @@
5
5
 
6
6
 
7
7
  from abc import abstractmethod
8
- from typing import Any, ClassVar, Dict, List, Optional, Set, Union
8
+ from typing import Any, ClassVar, Dict, List, Optional, Union
9
9
 
10
10
  from nilearn import image as nimg
11
11
 
12
+ from ...typing import Dependencies, MarkerInOutMappings
12
13
  from ...utils import raise_error
13
14
  from ..base import BaseMarker
14
15
 
@@ -37,9 +38,9 @@ class TemporalSNRBase(BaseMarker):
37
38
 
38
39
  """
39
40
 
40
- _DEPENDENCIES: ClassVar[Set[str]] = {"nilearn"}
41
+ _DEPENDENCIES: ClassVar[Dependencies] = {"nilearn"}
41
42
 
42
- _MARKER_INOUT_MAPPINGS: ClassVar[Dict[str, Dict[str, str]]] = {
43
+ _MARKER_INOUT_MAPPINGS: ClassVar[MarkerInOutMappings] = {
43
44
  "BOLD": {
44
45
  "tsnr": "vector",
45
46
  },
@@ -3,23 +3,20 @@
3
3
  # Authors: Synchon Mandal <s.mandal@fz-juelich.de>
4
4
  # License: AGPL
5
5
 
6
- from typing import TYPE_CHECKING, Dict, Optional, Type
6
+ from typing import Dict, Optional
7
7
 
8
8
  import numpy as np
9
9
  import pandas as pd
10
10
 
11
+ from ..typing import StorageLike
11
12
  from ..utils import raise_error
12
13
 
13
14
 
14
- if TYPE_CHECKING:
15
- from junifer.storage import BaseFeatureStorage
16
-
17
-
18
15
  __all__ = ["normalize", "reweight"]
19
16
 
20
17
 
21
18
  def normalize(
22
- storage: Type["BaseFeatureStorage"],
19
+ storage: StorageLike,
23
20
  features: Dict[str, Dict[str, Optional[str]]],
24
21
  kind: str,
25
22
  ) -> pd.DataFrame:
@@ -89,7 +86,7 @@ def normalize(
89
86
 
90
87
 
91
88
  def reweight(
92
- storage: Type["BaseFeatureStorage"],
89
+ storage: StorageLike,
93
90
  feature_name: Optional[str] = None,
94
91
  feature_md5: Optional[str] = None,
95
92
  ) -> pd.DataFrame:
@@ -4,22 +4,19 @@
4
4
  # License: AGPL
5
5
 
6
6
 
7
- from typing import TYPE_CHECKING, Dict, Optional, Tuple, Type
7
+ from typing import Dict, Optional, Tuple
8
8
 
9
9
  import pandas as pd
10
10
 
11
+ from ..typing import StorageLike
11
12
  from ..utils import logger, raise_error, warn_with_log
12
13
 
13
14
 
14
- if TYPE_CHECKING:
15
- from junifer.storage import BaseFeatureStorage
16
-
17
-
18
15
  __all__ = ["read_transform"]
19
16
 
20
17
 
21
18
  def read_transform(
22
- storage: Type["BaseFeatureStorage"],
19
+ storage: StorageLike,
23
20
  transform: str,
24
21
  feature_name: Optional[str] = None,
25
22
  feature_md5: Optional[str] = None,
@@ -5,20 +5,14 @@
5
5
  # License: AGPL
6
6
 
7
7
  from collections import Counter
8
- from typing import TYPE_CHECKING, Dict, List, Optional
8
+ from typing import Dict, List, Optional
9
9
 
10
10
  from ..datareader import DefaultDataReader
11
11
  from ..pipeline import PipelineStepMixin, WorkDirManager
12
+ from ..typing import DataGrabberLike, MarkerLike, PreprocessorLike, StorageLike
12
13
  from ..utils import logger, raise_error
13
14
 
14
15
 
15
- if TYPE_CHECKING:
16
- from junifer.datagrabber import BaseDataGrabber
17
- from junifer.markers import BaseMarker
18
- from junifer.preprocess import BasePreprocessor
19
- from junifer.storage import BaseFeatureStorage
20
-
21
-
22
16
  __all__ = ["MarkerCollection"]
23
17
 
24
18
 
@@ -45,10 +39,10 @@ class MarkerCollection:
45
39
 
46
40
  def __init__(
47
41
  self,
48
- markers: List["BaseMarker"],
42
+ markers: List[MarkerLike],
49
43
  datareader: Optional[PipelineStepMixin] = None,
50
- preprocessors: Optional[List["BasePreprocessor"]] = None,
51
- storage: Optional["BaseFeatureStorage"] = None,
44
+ preprocessors: Optional[List[PreprocessorLike]] = None,
45
+ storage: Optional[StorageLike] = None,
52
46
  ):
53
47
  # Check that the markers have different names
54
48
  marker_names = [m.name for m in markers]
@@ -111,7 +105,7 @@ class MarkerCollection:
111
105
 
112
106
  return None if self._storage else out
113
107
 
114
- def validate(self, datagrabber: "BaseDataGrabber") -> None:
108
+ def validate(self, datagrabber: DataGrabberLike) -> None:
115
109
  """Validate the pipeline.
116
110
 
117
111
  Without doing any computation, check if the marker collection can
@@ -6,18 +6,13 @@
6
6
  # License: AGPL
7
7
 
8
8
  import importlib
9
- from typing import TYPE_CHECKING, Dict, List, Mapping, Optional, Union
9
+ from typing import Dict, List, Mapping, Optional, Union
10
10
 
11
+ from ..typing import DataGrabberLike, MarkerLike, PreprocessorLike, StorageLike
11
12
  from ..utils import logger, raise_error
12
13
  from ..utils.singleton import Singleton
13
14
 
14
15
 
15
- if TYPE_CHECKING:
16
- from ..datagrabber import BaseDataGrabber
17
- from ..storage import BaseFeatureStorage
18
- from .pipeline_step_mixin import PipelineStepMixin
19
-
20
-
21
16
  __all__ = ["PipelineComponentRegistry"]
22
17
 
23
18
 
@@ -241,7 +236,7 @@ class PipelineComponentRegistry(metaclass=Singleton):
241
236
  name: str,
242
237
  baseclass: type,
243
238
  init_params: Optional[Dict] = None,
244
- ) -> Union["BaseDataGrabber", "PipelineStepMixin", "BaseFeatureStorage"]:
239
+ ) -> Union[DataGrabberLike, PreprocessorLike, MarkerLike, StorageLike]:
245
240
  """Build an instance of class registered as ``name``.
246
241
 
247
242
  Parameters
@@ -196,10 +196,14 @@ class PipelineStepMixin:
196
196
  for dependency in obj._CONDITIONAL_DEPENDENCIES:
197
197
  if dependency["using"] == obj.using:
198
198
  depends_on = dependency["depends_on"]
199
- # Check dependencies
200
- _check_dependencies(depends_on)
201
- # Check external dependencies
202
- _check_ext_dependencies(depends_on)
199
+ # Conditional to make `using="auto"` work
200
+ if not isinstance(depends_on, list):
201
+ depends_on = [depends_on]
202
+ for entry in depends_on:
203
+ # Check dependencies
204
+ _check_dependencies(entry)
205
+ # Check external dependencies
206
+ _check_ext_dependencies(entry)
203
207
 
204
208
  # Check dependencies
205
209
  _check_dependencies(self)
@@ -5,12 +5,17 @@
5
5
  # License: AGPL
6
6
 
7
7
  import warnings
8
- from typing import ClassVar, Dict, List, Set, Type, Union
8
+ from typing import ClassVar, Dict, List
9
9
 
10
10
  import pytest
11
11
 
12
12
  from junifer.pipeline.pipeline_step_mixin import PipelineStepMixin
13
13
  from junifer.pipeline.utils import _check_afni
14
+ from junifer.typing import (
15
+ ConditionalDependencies,
16
+ Dependencies,
17
+ ExternalDependencies,
18
+ )
14
19
 
15
20
 
16
21
  def test_PipelineStepMixin_correct_dependencies() -> None:
@@ -19,7 +24,7 @@ def test_PipelineStepMixin_correct_dependencies() -> None:
19
24
  class CorrectMixer(PipelineStepMixin):
20
25
  """Test class for validation."""
21
26
 
22
- _DEPENDENCIES: ClassVar[Set[str]] = {"math"}
27
+ _DEPENDENCIES: ClassVar[Dependencies] = {"math"}
23
28
 
24
29
  def validate_input(self, input: List[str]) -> List[str]:
25
30
  return input
@@ -40,7 +45,7 @@ def test_PipelineStepMixin_incorrect_dependencies() -> None:
40
45
  class IncorrectMixer(PipelineStepMixin):
41
46
  """Test class for validation."""
42
47
 
43
- _DEPENDENCIES: ClassVar[Set[str]] = {"foobar"}
48
+ _DEPENDENCIES: ClassVar[Dependencies] = {"foobar"}
44
49
 
45
50
  def validate_input(self, input: List[str]) -> List[str]:
46
51
  return input
@@ -65,7 +70,7 @@ def test_PipelineStepMixin_correct_ext_dependencies() -> None:
65
70
  class CorrectMixer(PipelineStepMixin):
66
71
  """Test class for validation."""
67
72
 
68
- _EXT_DEPENDENCIES: ClassVar[List[Dict[str, str]]] = [{"name": "afni"}]
73
+ _EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [{"name": "afni"}]
69
74
 
70
75
  def validate_input(self, input: List[str]) -> List[str]:
71
76
  return input
@@ -89,7 +94,7 @@ def test_PipelineStepMixin_ext_deps_correct_commands() -> None:
89
94
  class CorrectMixer(PipelineStepMixin):
90
95
  """Test class for validation."""
91
96
 
92
- _EXT_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, List[str]]]]] = [
97
+ _EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
93
98
  {"name": "afni", "commands": ["3dReHo"]}
94
99
  ]
95
100
 
@@ -117,7 +122,7 @@ def test_PipelineStepMixin_ext_deps_incorrect_commands() -> None:
117
122
  class CorrectMixer(PipelineStepMixin):
118
123
  """Test class for validation."""
119
124
 
120
- _EXT_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, List[str]]]]] = [
125
+ _EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
121
126
  {"name": "afni", "commands": ["3d"]}
122
127
  ]
123
128
 
@@ -141,7 +146,7 @@ def test_PipelineStepMixin_incorrect_ext_dependencies() -> None:
141
146
  class IncorrectMixer(PipelineStepMixin):
142
147
  """Test class for validation."""
143
148
 
144
- _EXT_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, bool]]]] = [
149
+ _EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
145
150
  {"name": "foobar", "optional": True}
146
151
  ]
147
152
 
@@ -163,14 +168,12 @@ def test_PipelineStepMixin_correct_conditional_dependencies() -> None:
163
168
  """Test fit-transform with correct conditional dependencies."""
164
169
 
165
170
  class Dependency:
166
- _DEPENDENCIES: ClassVar[Set[str]] = {"math"}
171
+ _DEPENDENCIES: ClassVar[Dependencies] = {"math"}
167
172
 
168
173
  class CorrectMixer(PipelineStepMixin):
169
174
  """Test class for validation."""
170
175
 
171
- _CONDITIONAL_DEPENDENCIES: ClassVar[
172
- List[Dict[str, Union[str, Type]]]
173
- ] = [
176
+ _CONDITIONAL_DEPENDENCIES: ClassVar[ConditionalDependencies] = [
174
177
  {
175
178
  "using": "math",
176
179
  "depends_on": Dependency,
@@ -196,14 +199,12 @@ def test_PipelineStepMixin_incorrect_conditional_dependencies() -> None:
196
199
  """Test fit-transform with incorrect conditional dependencies."""
197
200
 
198
201
  class Dependency:
199
- _DEPENDENCIES: ClassVar[Set[str]] = {"math"}
202
+ _DEPENDENCIES: ClassVar[Dependencies] = {"math"}
200
203
 
201
204
  class IncorrectMixer(PipelineStepMixin):
202
205
  """Test class for validation."""
203
206
 
204
- _CONDITIONAL_DEPENDENCIES: ClassVar[
205
- List[Dict[str, Union[str, Type]]]
206
- ] = [
207
+ _CONDITIONAL_DEPENDENCIES: ClassVar[ConditionalDependencies] = [
207
208
  {
208
209
  "using": "math",
209
210
  "depends_on": Dependency,
@@ -231,14 +232,12 @@ def test_PipelineStepMixin_correct_conditional_ext_dependencies() -> None:
231
232
  """Test fit-transform with correct conditional external dependencies."""
232
233
 
233
234
  class ExternalDependency:
234
- _EXT_DEPENDENCIES: ClassVar[List[Dict[str, str]]] = [{"name": "afni"}]
235
+ _EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [{"name": "afni"}]
235
236
 
236
237
  class CorrectMixer(PipelineStepMixin):
237
238
  """Test class for validation."""
238
239
 
239
- _CONDITIONAL_DEPENDENCIES: ClassVar[
240
- List[Dict[str, Union[str, Type]]]
241
- ] = [
240
+ _CONDITIONAL_DEPENDENCIES: ClassVar[ConditionalDependencies] = [
242
241
  {
243
242
  "using": "afni",
244
243
  "depends_on": ExternalDependency,
@@ -103,6 +103,7 @@ def test_workdir_manager_get_and_delete_tempdir(tmp_path: Path) -> None:
103
103
  # Should remove temporary directory
104
104
  assert workdir_mgr.root_tempdir is None
105
105
 
106
+
106
107
  def test_workdir_manager_no_cleanup(tmp_path: Path) -> None:
107
108
  """Test WorkDirManager correctly bypasses cleanup.
108
109
 
@@ -4,7 +4,7 @@
4
4
  # Synchon Mandal <s.mandal@fz-juelich.de>
5
5
  # License: AGPL
6
6
 
7
- from typing import Dict
7
+ from typing import Dict, List, Union
8
8
 
9
9
 
10
10
  __all__ = ["UpdateMetaMixin"]
@@ -15,14 +15,14 @@ class UpdateMetaMixin:
15
15
 
16
16
  def update_meta(
17
17
  self,
18
- input: Dict,
18
+ input: Union[Dict, List[Dict]],
19
19
  step_name: str,
20
20
  ) -> None:
21
21
  """Update metadata.
22
22
 
23
23
  Parameters
24
24
  ----------
25
- input : dict
25
+ input : dict or list of dict
26
26
  The data object to update.
27
27
  step_name : str
28
28
  The name of the pipeline step.
@@ -36,17 +36,21 @@ class UpdateMetaMixin:
36
36
  for k, v in vars(self).items():
37
37
  if not k.startswith("_"):
38
38
  t_meta[k] = v
39
- # Add "meta" to the step's local context dict
40
- if "meta" not in input:
41
- input["meta"] = {}
42
- # Add step name
43
- input["meta"][step_name] = t_meta
44
- # Add step dependencies
45
- if "dependencies" not in input["meta"]:
46
- input["meta"]["dependencies"] = set()
47
- # Update step dependencies
48
- dependencies = getattr(self, "_DEPENDENCIES", set())
49
- if dependencies is not None:
50
- if not isinstance(dependencies, (set, list)):
51
- dependencies = {dependencies}
52
- input["meta"]["dependencies"].update(dependencies)
39
+ # Conditional for list dtype vals like Warp
40
+ if not isinstance(input, list):
41
+ input = [input]
42
+ for entry in input:
43
+ # Add "meta" to the step's entry's local context dict
44
+ if "meta" not in entry:
45
+ entry["meta"] = {}
46
+ # Add step name
47
+ entry["meta"][step_name] = t_meta
48
+ # Add step dependencies
49
+ if "dependencies" not in entry["meta"]:
50
+ entry["meta"]["dependencies"] = set()
51
+ # Update step dependencies
52
+ dependencies = getattr(self, "_DEPENDENCIES", set())
53
+ if dependencies is not None:
54
+ if not isinstance(dependencies, (set, list)):
55
+ dependencies = {dependencies}
56
+ entry["meta"]["dependencies"].update(dependencies)
@@ -11,7 +11,6 @@ from typing import (
11
11
  Dict,
12
12
  List,
13
13
  Optional,
14
- Set,
15
14
  Tuple,
16
15
  Union,
17
16
  )
@@ -23,6 +22,7 @@ from nilearn._utils.niimg_conversions import check_niimg_4d
23
22
 
24
23
  from ...api.decorators import register_preprocessor
25
24
  from ...data import get_data
25
+ from ...typing import Dependencies
26
26
  from ...utils import logger, raise_error
27
27
  from ..base import BasePreprocessor
28
28
 
@@ -152,7 +152,7 @@ class fMRIPrepConfoundRemover(BasePreprocessor):
152
152
 
153
153
  """
154
154
 
155
- _DEPENDENCIES: ClassVar[Set[str]] = {"numpy", "nilearn"}
155
+ _DEPENDENCIES: ClassVar[Dependencies] = {"numpy", "nilearn"}
156
156
 
157
157
  def __init__(
158
158
  self,
@@ -6,20 +6,18 @@
6
6
  from typing import (
7
7
  TYPE_CHECKING,
8
8
  ClassVar,
9
- Dict,
10
- List,
11
- Set,
12
9
  Union,
13
10
  )
14
11
 
15
12
  import nibabel as nib
16
13
 
17
14
  from ...pipeline import WorkDirManager
15
+ from ...typing import Dependencies, ExternalDependencies
18
16
  from ...utils import logger, run_ext_cmd
19
17
 
20
18
 
21
19
  if TYPE_CHECKING:
22
- from nibabel import Nifti1Image
20
+ from nibabel.nifti1 import Nifti1Image
23
21
 
24
22
 
25
23
  __all__ = ["AFNISmoothing"]
@@ -32,14 +30,14 @@ class AFNISmoothing:
32
30
 
33
31
  """
34
32
 
35
- _EXT_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, List[str]]]]] = [
33
+ _EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
36
34
  {
37
35
  "name": "afni",
38
36
  "commands": ["3dBlurToFWHM"],
39
37
  },
40
38
  ]
41
39
 
42
- _DEPENDENCIES: ClassVar[Set[str]] = {"nibabel"}
40
+ _DEPENDENCIES: ClassVar[Dependencies] = {"nibabel"}
43
41
 
44
42
  def preprocess(
45
43
  self,