[ENH]: Introduce junfer.typing module #392

Merged
synchon merged 7 commits from style/typing into main 2024-11-13 08:51:58 +00:00
41 changed files with 240 additions and 171 deletions

View file

@ -39,6 +39,7 @@ The documentation is available at [https://juaml.github.io/junifer](https://juam
* `preprocess`: Preprocessing module. * `preprocess`: Preprocessing module.
* `storage`: Storage module. * `storage`: Storage module.
* `testing`: Testing components module. * `testing`: Testing components module.
* `typing`: Type hints module.
* `utils`: Utilities module (e.g. logging). * `utils`: Utilities module (e.g. logging).
## Installation ## Installation

View file

@ -0,0 +1 @@
Introduce ``junifer.typing`` sub-module to organise internal and external type hints by `Synchon Mandal`_

View file

@ -28,7 +28,7 @@ component depends on. For example, for :class:`.RSSETSMarker`, we have:
.. code-block:: python .. code-block:: python
_DEPENDENCIES: ClassVar[Set[str]] = {"nilearn"} _DEPENDENCIES: ClassVar[Dependencies] = {"nilearn"}
The type annotation is for documentation and static type checking purposes. The type annotation is for documentation and static type checking purposes.
Although not required, we highly recommend you use them, your future self Although not required, we highly recommend you use them, your future self
@ -44,7 +44,7 @@ by having a class attribute like so:
.. code-block:: python .. code-block:: python
_EXT_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, List[str]]]]] = [ _EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
{ {
"name": "afni", "name": "afni",
"commands": ["3dReHo", "3dAFNItoNIFTI"], "commands": ["3dReHo", "3dAFNItoNIFTI"],
@ -78,7 +78,7 @@ that it shows the problem a bit better and how we solve it:
class SpaceWarper(BasePreprocessor): class SpaceWarper(BasePreprocessor):
# docstring # docstring
_CONDITIONAL_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, Type]]]] = [ _CONDITIONAL_DEPENDENCIES: ClassVar[ConditionalDependencies] = [
{ {
"using": "fsl", "using": "fsl",
"depends_on": FSLWarper, "depends_on": FSLWarper,
@ -115,14 +115,14 @@ similar. ``FSLWarper`` looks like this (only the relevant part is shown here):
class FSLWarper: class FSLWarper:
# docstring # docstring
_EXT_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, List[str]]]]] = [ _EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
{ {
"name": "fsl", "name": "fsl",
"commands": ["flirt", "applywarp"], "commands": ["flirt", "applywarp"],
}, },
] ]
_DEPENDENCIES: ClassVar[Set[str]] = {"numpy", "nibabel"} _DEPENDENCIES: ClassVar[Dependencies] = {"numpy", "nibabel"}
def preprocess( def preprocess(
self, self,

View file

@ -196,15 +196,16 @@ Finally, we need to register the Marker using the ``@register_marker`` decorator
from junifer.api.decorators import register_marker from junifer.api.decorators import register_marker
from junifer.data import get_parcellation from junifer.data import get_parcellation
from junifer.markers import BaseMarker from junifer.markers import BaseMarker
from junifer.typing import Dependencies, MarkerInOutMappings
from nilearn.maskers import NiftiLabelsMasker from nilearn.maskers import NiftiLabelsMasker
@register_marker @register_marker
class ParcelMean(BaseMarker): class ParcelMean(BaseMarker):
_DEPENDENCIES = {"nilearn", "numpy"} _DEPENDENCIES: ClassVar[Dependencies] = {"nilearn", "numpy"}
_MARKER_INOUT_MAPPINGS: ClassVar[dict[str, dict[str, str]]] = { _MARKER_INOUT_MAPPINGS: ClassVar[MarkerInOutMappings] = {
"BOLD": { "BOLD": {
"parcel_mean": "timeseries", "parcel_mean": "timeseries",
}, },

View file

@ -13,6 +13,7 @@ __all__ = [
"external", "external",
"onthefly", "onthefly",
"testing", "testing",
"typing",
"__version__", "__version__",
] ]
@ -30,6 +31,7 @@ from . import (
utils, utils,
external, external,
testing, testing,
typing,
onthefly, onthefly,
) )
from ._version import __version__ from ._version import __version__

View file

@ -8,6 +8,7 @@
from typing import Type from typing import Type
from ..pipeline import PipelineComponentRegistry from ..pipeline import PipelineComponentRegistry
from ..typing import DataGrabberLike, MarkerLike, PreprocessorLike, StorageLike
__all__ = [ __all__ = [
@ -19,7 +20,7 @@ __all__ = [
] ]
def register_datagrabber(klass: Type) -> Type: def register_datagrabber(klass: DataGrabberLike) -> DataGrabberLike:
"""Register DataGrabber. """Register DataGrabber.
Registers the DataGrabber so it can be used by name. Registers the DataGrabber so it can be used by name.
@ -73,7 +74,7 @@ def register_datareader(klass: Type) -> Type:
return klass return klass
def register_preprocessor(klass: Type) -> Type: def register_preprocessor(klass: PreprocessorLike) -> PreprocessorLike:
"""Preprocessor registration decorator. """Preprocessor registration decorator.
Registers the preprocessor so it can be used by name. Registers the preprocessor so it can be used by name.
@ -96,7 +97,7 @@ def register_preprocessor(klass: Type) -> Type:
return klass return klass
def register_marker(klass: Type) -> Type: def register_marker(klass: MarkerLike) -> MarkerLike:
"""Marker registration decorator. """Marker registration decorator.
Registers the marker so it can be used by name. Registers the marker so it can be used by name.
@ -119,7 +120,7 @@ def register_marker(klass: Type) -> Type:
return klass return klass
def register_storage(klass: Type) -> Type: def register_storage(klass: StorageLike) -> StorageLike:
"""Storage registration decorator. """Storage registration decorator.
Registers the storage so it can be used by name. Registers the storage so it can be used by name.

View file

@ -11,22 +11,23 @@ from pathlib import Path
from typing import Dict, List, Optional, Tuple, Union from typing import Dict, List, Optional, Tuple, Union
from ..api.queue_context import GnuParallelLocalAdapter, HTCondorAdapter from ..api.queue_context import GnuParallelLocalAdapter, HTCondorAdapter
from ..datagrabber.base import BaseDataGrabber from ..datagrabber import BaseDataGrabber
from ..markers.base import BaseMarker from ..markers import BaseMarker
from ..pipeline import ( from ..pipeline import (
MarkerCollection, MarkerCollection,
PipelineComponentRegistry, PipelineComponentRegistry,
WorkDirManager, WorkDirManager,
) )
from ..preprocess.base import BasePreprocessor from ..preprocess import BasePreprocessor
from ..storage.base import BaseFeatureStorage from ..storage import BaseFeatureStorage
from ..typing import DataGrabberLike, MarkerLike, PreprocessorLike, StorageLike
from ..utils import logger, raise_error, yaml from ..utils import logger, raise_error, yaml
__all__ = ["run", "collect", "queue", "reset", "list_elements"] __all__ = ["run", "collect", "queue", "reset", "list_elements"]
def _get_datagrabber(datagrabber_config: Dict) -> BaseDataGrabber: def _get_datagrabber(datagrabber_config: Dict) -> DataGrabberLike:
"""Get DataGrabber. """Get DataGrabber.
Parameters Parameters
@ -48,7 +49,7 @@ def _get_datagrabber(datagrabber_config: Dict) -> BaseDataGrabber:
) )
def _get_preprocessor(preprocessing_config: Dict) -> BasePreprocessor: def _get_preprocessor(preprocessing_config: Dict) -> PreprocessorLike:
"""Get Preprocessor. """Get Preprocessor.
Parameters Parameters
@ -70,7 +71,7 @@ def _get_preprocessor(preprocessing_config: Dict) -> BasePreprocessor:
) )
def _get_marker(marker_config: Dict) -> BaseMarker: def _get_marker(marker_config: Dict) -> MarkerLike:
"""Get Marker. """Get Marker.
Parameters Parameters
@ -92,7 +93,7 @@ def _get_marker(marker_config: Dict) -> BaseMarker:
) )
def _get_storage(storage_config: Dict) -> BaseFeatureStorage: def _get_storage(storage_config: Dict) -> StorageLike:
"""Get Storage. """Get Storage.
Parameters Parameters

View file

@ -8,6 +8,7 @@
from typing import Dict, List, Tuple, Union from typing import Dict, List, Tuple, Union
from ..api.decorators import register_datagrabber from ..api.decorators import register_datagrabber
from ..typing import DataGrabberLike
from ..utils import deep_update, raise_error from ..utils import deep_update, raise_error
from .base import BaseDataGrabber from .base import BaseDataGrabber
@ -37,7 +38,7 @@ class MultipleDataGrabber(BaseDataGrabber):
""" """
def __init__(self, datagrabbers: List[BaseDataGrabber], **kwargs) -> None: def __init__(self, datagrabbers: List[DataGrabberLike], **kwargs) -> None:
# Check datagrabbers consistency # Check datagrabbers consistency
# Check for same element keys # Check for same element keys
first_keys = datagrabbers[0].get_element_keys() first_keys = datagrabbers[0].get_element_keys()

View file

@ -6,16 +6,13 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from copy import deepcopy from copy import deepcopy
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union from typing import Any, Dict, List, Optional, Union
from ..pipeline import PipelineStepMixin, UpdateMetaMixin from ..pipeline import PipelineStepMixin, UpdateMetaMixin
from ..typing import StorageLike
from ..utils import logger, raise_error from ..utils import logger, raise_error
if TYPE_CHECKING:
from junifer.storage import BaseFeatureStorage
__all__ = ["BaseMarker"] __all__ = ["BaseMarker"]
@ -159,7 +156,7 @@ class BaseMarker(ABC, PipelineStepMixin, UpdateMetaMixin):
type_: str, type_: str,
feature: str, feature: str,
out: Dict[str, Any], out: Dict[str, Any],
storage: "BaseFeatureStorage", storage: StorageLike,
) -> None: ) -> None:
"""Store. """Store.
@ -182,7 +179,7 @@ class BaseMarker(ABC, PipelineStepMixin, UpdateMetaMixin):
def _fit_transform( def _fit_transform(
self, self,
input: Dict[str, Dict], input: Dict[str, Dict],
storage: Optional["BaseFeatureStorage"] = None, storage: Optional[StorageLike] = None,
) -> Dict: ) -> Dict:
"""Fit and transform. """Fit and transform.

View file

@ -11,7 +11,6 @@ from typing import (
Dict, Dict,
List, List,
Optional, Optional,
Set,
Union, Union,
) )
@ -25,6 +24,7 @@ from ..external.BrainPrint.brainprint.brainprint import (
) )
from ..external.BrainPrint.brainprint.surfaces import surf_to_vtk from ..external.BrainPrint.brainprint.surfaces import surf_to_vtk
from ..pipeline import WorkDirManager from ..pipeline import WorkDirManager
from ..typing import Dependencies, ExternalDependencies, MarkerInOutMappings
from ..utils import logger, run_ext_cmd from ..utils import logger, run_ext_cmd
from .base import BaseMarker from .base import BaseMarker
@ -68,7 +68,7 @@ class BrainPrint(BaseMarker):
""" """
_EXT_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, List[str]]]]] = [ _EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
{ {
"name": "freesurfer", "name": "freesurfer",
"commands": [ "commands": [
@ -80,9 +80,9 @@ class BrainPrint(BaseMarker):
}, },
] ]
_DEPENDENCIES: ClassVar[Set[str]] = {"lapy", "numpy"} _DEPENDENCIES: ClassVar[Dependencies] = {"lapy", "numpy"}
_MARKER_INOUT_MAPPINGS: ClassVar[Dict[str, Dict[str, str]]] = { _MARKER_INOUT_MAPPINGS: ClassVar[MarkerInOutMappings] = {
"FreeSurfer": { "FreeSurfer": {
"eigenvalues": "scalar_table", "eigenvalues": "scalar_table",
"areas": "vector", "areas": "vector",

View file

@ -11,10 +11,10 @@ from typing import (
Dict, Dict,
List, List,
Optional, Optional,
Set,
Union, Union,
) )
from ...typing import Dependencies, MarkerInOutMappings
from ...utils import raise_error from ...utils import raise_error
from ..base import BaseMarker from ..base import BaseMarker
from ..parcel_aggregation import ParcelAggregation from ..parcel_aggregation import ParcelAggregation
@ -51,9 +51,9 @@ class ComplexityBase(BaseMarker):
""" """
_DEPENDENCIES: ClassVar[Set[str]] = {"nilearn", "neurokit2"} _DEPENDENCIES: ClassVar[Dependencies] = {"nilearn", "neurokit2"}
_MARKER_INOUT_MAPPINGS: ClassVar[Dict[str, Dict[str, str]]] = { _MARKER_INOUT_MAPPINGS: ClassVar[MarkerInOutMappings] = {
"BOLD": { "BOLD": {
"complexity": "vector", "complexity": "vector",
}, },

View file

@ -6,11 +6,12 @@
# Synchon Mandal <s.mandal@fz-juelich.de> # Synchon Mandal <s.mandal@fz-juelich.de>
# License: AGPL # License: AGPL
from typing import Any, ClassVar, Dict, List, Optional, Set, Union from typing import Any, ClassVar, Dict, List, Optional, Union
import numpy as np import numpy as np
from ..api.decorators import register_marker from ..api.decorators import register_marker
from ..typing import Dependencies, MarkerInOutMappings
from ..utils import logger from ..utils import logger
from .base import BaseMarker from .base import BaseMarker
from .parcel_aggregation import ParcelAggregation from .parcel_aggregation import ParcelAggregation
@ -45,9 +46,9 @@ class RSSETSMarker(BaseMarker):
""" """
_DEPENDENCIES: ClassVar[Set[str]] = {"nilearn"} _DEPENDENCIES: ClassVar[Dependencies] = {"nilearn"}
_MARKER_INOUT_MAPPINGS: ClassVar[Dict[str, Dict[str, str]]] = { _MARKER_INOUT_MAPPINGS: ClassVar[MarkerInOutMappings] = {
"BOLD": { "BOLD": {
"rss_ets": "timeseries", "rss_ets": "timeseries",
}, },

View file

@ -8,22 +8,20 @@ from pathlib import Path
from typing import ( from typing import (
TYPE_CHECKING, TYPE_CHECKING,
ClassVar, ClassVar,
Dict,
List,
Optional, Optional,
Tuple, Tuple,
Union,
) )
import nibabel as nib import nibabel as nib
from ...pipeline import WorkDirManager from ...pipeline import WorkDirManager
from ...typing import ExternalDependencies
from ...utils import logger, run_ext_cmd from ...utils import logger, run_ext_cmd
from ...utils.singleton import Singleton from ...utils.singleton import Singleton
if TYPE_CHECKING: if TYPE_CHECKING:
from nibabel import Nifti1Image from nibabel.nifti1 import Nifti1Image
__all__ = ["AFNIALFF"] __all__ = ["AFNIALFF"]
@ -37,7 +35,7 @@ class AFNIALFF(metaclass=Singleton):
""" """
_EXT_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, List[str]]]]] = [ _EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
{ {
"name": "afni", "name": "afni",
"commands": ["3dRSFC", "3dAFNItoNIFTI"], "commands": ["3dRSFC", "3dAFNItoNIFTI"],

View file

@ -9,7 +9,6 @@ from typing import (
TYPE_CHECKING, TYPE_CHECKING,
ClassVar, ClassVar,
Optional, Optional,
Set,
Tuple, Tuple,
) )
@ -19,12 +18,13 @@ import scipy as sp
from nilearn import image as nimg from nilearn import image as nimg
from ...pipeline import WorkDirManager from ...pipeline import WorkDirManager
from ...typing import Dependencies
from ...utils import logger from ...utils import logger
from ...utils.singleton import Singleton from ...utils.singleton import Singleton
if TYPE_CHECKING: if TYPE_CHECKING:
from nibabel import Nifti1Image from nibabel.nifti1 import Nifti1Image
__all__ = ["JuniferALFF"] __all__ = ["JuniferALFF"]
@ -37,7 +37,7 @@ class JuniferALFF(metaclass=Singleton):
""" """
_DEPENDENCIES: ClassVar[Set[str]] = {"numpy", "nilearn", "scipy"} _DEPENDENCIES: ClassVar[Dependencies] = {"numpy", "nilearn", "scipy"}
def __del__(self) -> None: def __del__(self) -> None:
"""Terminate the class.""" """Terminate the class."""

View file

@ -12,13 +12,11 @@ from typing import (
Any, Any,
ClassVar, ClassVar,
Dict, Dict,
List,
Optional, Optional,
Tuple, Tuple,
Type,
Union,
) )
from ...typing import ConditionalDependencies, MarkerInOutMappings
from ...utils.logging import logger, raise_error from ...utils.logging import logger, raise_error
from ..base import BaseMarker from ..base import BaseMarker
from ._afni_falff import AFNIALFF from ._afni_falff import AFNIALFF
@ -26,7 +24,7 @@ from ._junifer_falff import JuniferALFF
if TYPE_CHECKING: if TYPE_CHECKING:
from nibabel import Nifti1Image from nibabel.nifti1 import Nifti1Image
__all__ = ["ALFFBase"] __all__ = ["ALFFBase"]
@ -72,7 +70,7 @@ class ALFFBase(BaseMarker):
""" """
_CONDITIONAL_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, Type]]]] = [ _CONDITIONAL_DEPENDENCIES: ClassVar[ConditionalDependencies] = [
{ {
"using": "afni", "using": "afni",
"depends_on": AFNIALFF, "depends_on": AFNIALFF,
@ -83,7 +81,7 @@ class ALFFBase(BaseMarker):
}, },
] ]
_MARKER_INOUT_MAPPINGS: ClassVar[Dict[str, Dict[str, str]]] = { _MARKER_INOUT_MAPPINGS: ClassVar[MarkerInOutMappings] = {
"BOLD": { "BOLD": {
"alff": "vector", "alff": "vector",
"falff": "vector", "falff": "vector",

View file

@ -4,11 +4,12 @@
# Kaustubh R. Patil <k.patil@fz-juelich.de> # Kaustubh R. Patil <k.patil@fz-juelich.de>
# License: AGPL # License: AGPL
from typing import Any, ClassVar, Dict, List, Optional, Set, Union from typing import Any, ClassVar, Dict, List, Optional, Union
import pandas as pd import pandas as pd
from ...api.decorators import register_marker from ...api.decorators import register_marker
from ...typing import Dependencies, MarkerInOutMappings
from ...utils import logger, raise_error from ...utils import logger, raise_error
from ..base import BaseMarker from ..base import BaseMarker
from ..parcel_aggregation import ParcelAggregation from ..parcel_aggregation import ParcelAggregation
@ -49,9 +50,9 @@ class CrossParcellationFC(BaseMarker):
""" """
_DEPENDENCIES: ClassVar[Set[str]] = {"nilearn"} _DEPENDENCIES: ClassVar[Dependencies] = {"nilearn"}
_MARKER_INOUT_MAPPINGS: ClassVar[Dict[str, Dict[str, str]]] = { _MARKER_INOUT_MAPPINGS: ClassVar[MarkerInOutMappings] = {
"BOLD": { "BOLD": {
"functional_connectivity": "matrix", "functional_connectivity": "matrix",
}, },

View file

@ -5,11 +5,12 @@
from abc import abstractmethod from abc import abstractmethod
from typing import Any, ClassVar, Dict, List, Optional, Set, Union from typing import Any, ClassVar, Dict, List, Optional, Union
from sklearn.covariance import EmpiricalCovariance, LedoitWolf from sklearn.covariance import EmpiricalCovariance, LedoitWolf
from ...external.nilearn import JuniferConnectivityMeasure from ...external.nilearn import JuniferConnectivityMeasure
from ...typing import Dependencies, MarkerInOutMappings
from ...utils import raise_error from ...utils import raise_error
from ..base import BaseMarker from ..base import BaseMarker
@ -51,9 +52,9 @@ class FunctionalConnectivityBase(BaseMarker):
""" """
_DEPENDENCIES: ClassVar[Set[str]] = {"nilearn", "scikit-learn"} _DEPENDENCIES: ClassVar[Dependencies] = {"nilearn", "scikit-learn"}
_MARKER_INOUT_MAPPINGS: ClassVar[Dict[str, Dict[str, str]]] = { _MARKER_INOUT_MAPPINGS: ClassVar[MarkerInOutMappings] = {
"BOLD": { "BOLD": {
"functional_connectivity": "matrix", "functional_connectivity": "matrix",
}, },

View file

@ -4,7 +4,7 @@
# Synchon Mandal <s.mandal@fz-juelich.de> # Synchon Mandal <s.mandal@fz-juelich.de>
# License: AGPL # License: AGPL
from typing import Any, ClassVar, Dict, List, Optional, Set, Union from typing import Any, ClassVar, Dict, List, Optional, Union
import numpy as np import numpy as np
from nilearn.image import math_img from nilearn.image import math_img
@ -13,6 +13,7 @@ from nilearn.maskers import NiftiMasker
from ..api.decorators import register_marker from ..api.decorators import register_marker
from ..data import get_data from ..data import get_data
from ..stats import get_aggfunc_by_name from ..stats import get_aggfunc_by_name
from ..typing import Dependencies, MarkerInOutMappings
from ..utils import logger, raise_error, warn_with_log from ..utils import logger, raise_error, warn_with_log
from .base import BaseMarker from .base import BaseMarker
@ -61,9 +62,9 @@ class ParcelAggregation(BaseMarker):
""" """
_DEPENDENCIES: ClassVar[Set[str]] = {"nilearn", "numpy"} _DEPENDENCIES: ClassVar[Dependencies] = {"nilearn", "numpy"}
_MARKER_INOUT_MAPPINGS: ClassVar[Dict[str, Dict[str, str]]] = { _MARKER_INOUT_MAPPINGS: ClassVar[MarkerInOutMappings] = {
"T1w": { "T1w": {
"aggregation": "vector", "aggregation": "vector",
}, },

View file

@ -8,22 +8,20 @@ from pathlib import Path
from typing import ( from typing import (
TYPE_CHECKING, TYPE_CHECKING,
ClassVar, ClassVar,
Dict,
List,
Optional, Optional,
Tuple, Tuple,
Union,
) )
import nibabel as nib import nibabel as nib
from ...pipeline import WorkDirManager from ...pipeline import WorkDirManager
from ...typing import ExternalDependencies
from ...utils import logger, run_ext_cmd from ...utils import logger, run_ext_cmd
from ...utils.singleton import Singleton from ...utils.singleton import Singleton
if TYPE_CHECKING: if TYPE_CHECKING:
from nibabel import Nifti1Image from nibabel.nifti1 import Nifti1Image
__all__ = ["AFNIReHo"] __all__ = ["AFNIReHo"]
@ -37,7 +35,7 @@ class AFNIReHo(metaclass=Singleton):
""" """
_EXT_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, List[str]]]]] = [ _EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
{ {
"name": "afni", "name": "afni",
"commands": ["3dReHo", "3dAFNItoNIFTI"], "commands": ["3dReHo", "3dAFNItoNIFTI"],

View file

@ -9,7 +9,6 @@ from pathlib import Path
from typing import ( from typing import (
TYPE_CHECKING, TYPE_CHECKING,
ClassVar, ClassVar,
Set,
Tuple, Tuple,
) )
@ -20,12 +19,13 @@ from nilearn import image as nimg
from nilearn import masking as nmask from nilearn import masking as nmask
from ...pipeline import WorkDirManager from ...pipeline import WorkDirManager
from ...typing import Dependencies
from ...utils import logger, raise_error from ...utils import logger, raise_error
from ...utils.singleton import Singleton from ...utils.singleton import Singleton
if TYPE_CHECKING: if TYPE_CHECKING:
from nibabel import Nifti1Image from nibabel.nifti1 import Nifti1Image
__all__ = ["JuniferReHo"] __all__ = ["JuniferReHo"]
@ -38,7 +38,7 @@ class JuniferReHo(metaclass=Singleton):
""" """
_DEPENDENCIES: ClassVar[Set[str]] = {"numpy", "nilearn", "scipy"} _DEPENDENCIES: ClassVar[Dependencies] = {"numpy", "nilearn", "scipy"}
def __del__(self) -> None: def __del__(self) -> None:
"""Terminate the class.""" """Terminate the class."""

View file

@ -10,13 +10,11 @@ from typing import (
Any, Any,
ClassVar, ClassVar,
Dict, Dict,
List,
Optional, Optional,
Tuple, Tuple,
Type,
Union,
) )
from ...typing import ConditionalDependencies, MarkerInOutMappings
from ...utils import logger, raise_error from ...utils import logger, raise_error
from ..base import BaseMarker from ..base import BaseMarker
from ._afni_reho import AFNIReHo from ._afni_reho import AFNIReHo
@ -24,7 +22,7 @@ from ._junifer_reho import JuniferReHo
if TYPE_CHECKING: if TYPE_CHECKING:
from nibabel import Nifti1Image from nibabel.nifti1 import Nifti1Image
__all__ = ["ReHoBase"] __all__ = ["ReHoBase"]
@ -51,7 +49,7 @@ class ReHoBase(BaseMarker):
""" """
_CONDITIONAL_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, Type]]]] = [ _CONDITIONAL_DEPENDENCIES: ClassVar[ConditionalDependencies] = [
{ {
"using": "afni", "using": "afni",
"depends_on": AFNIReHo, "depends_on": AFNIReHo,
@ -62,7 +60,7 @@ class ReHoBase(BaseMarker):
}, },
] ]
_MARKER_INOUT_MAPPINGS: ClassVar[Dict[str, Dict[str, str]]] = { _MARKER_INOUT_MAPPINGS: ClassVar[MarkerInOutMappings] = {
"BOLD": { "BOLD": {
"reho": "vector", "reho": "vector",
}, },

View file

@ -4,12 +4,13 @@
# Synchon Mandal <s.mandal@fz-juelich.de> # Synchon Mandal <s.mandal@fz-juelich.de>
# License: AGPL # License: AGPL
from typing import Any, ClassVar, Dict, List, Optional, Set, Union from typing import Any, ClassVar, Dict, List, Optional, Union
from ..api.decorators import register_marker from ..api.decorators import register_marker
from ..data import get_data from ..data import get_data
from ..external.nilearn import JuniferNiftiSpheresMasker from ..external.nilearn import JuniferNiftiSpheresMasker
from ..stats import get_aggfunc_by_name from ..stats import get_aggfunc_by_name
from ..typing import Dependencies, MarkerInOutMappings
from ..utils import logger, raise_error, warn_with_log from ..utils import logger, raise_error, warn_with_log
from .base import BaseMarker from .base import BaseMarker
@ -66,9 +67,9 @@ class SphereAggregation(BaseMarker):
""" """
_DEPENDENCIES: ClassVar[Set[str]] = {"nilearn", "numpy"} _DEPENDENCIES: ClassVar[Dependencies] = {"nilearn", "numpy"}
_MARKER_INOUT_MAPPINGS: ClassVar[Dict[str, Dict[str, str]]] = { _MARKER_INOUT_MAPPINGS: ClassVar[MarkerInOutMappings] = {
"T1w": { "T1w": {
"aggregation": "vector", "aggregation": "vector",
}, },

View file

@ -5,10 +5,11 @@
from abc import abstractmethod from abc import abstractmethod
from typing import Any, ClassVar, Dict, List, Optional, Set, Union from typing import Any, ClassVar, Dict, List, Optional, Union
from nilearn import image as nimg from nilearn import image as nimg
from ...typing import Dependencies, MarkerInOutMappings
from ...utils import raise_error from ...utils import raise_error
from ..base import BaseMarker from ..base import BaseMarker
@ -37,9 +38,9 @@ class TemporalSNRBase(BaseMarker):
""" """
_DEPENDENCIES: ClassVar[Set[str]] = {"nilearn"} _DEPENDENCIES: ClassVar[Dependencies] = {"nilearn"}
_MARKER_INOUT_MAPPINGS: ClassVar[Dict[str, Dict[str, str]]] = { _MARKER_INOUT_MAPPINGS: ClassVar[MarkerInOutMappings] = {
"BOLD": { "BOLD": {
"tsnr": "vector", "tsnr": "vector",
}, },

View file

@ -3,23 +3,20 @@
# Authors: Synchon Mandal <s.mandal@fz-juelich.de> # Authors: Synchon Mandal <s.mandal@fz-juelich.de>
# License: AGPL # License: AGPL
from typing import TYPE_CHECKING, Dict, Optional, Type from typing import Dict, Optional
import numpy as np import numpy as np
import pandas as pd import pandas as pd
from ..typing import StorageLike
from ..utils import raise_error from ..utils import raise_error
if TYPE_CHECKING:
from junifer.storage import BaseFeatureStorage
__all__ = ["normalize", "reweight"] __all__ = ["normalize", "reweight"]
def normalize( def normalize(
storage: Type["BaseFeatureStorage"], storage: StorageLike,
features: Dict[str, Dict[str, Optional[str]]], features: Dict[str, Dict[str, Optional[str]]],
kind: str, kind: str,
) -> pd.DataFrame: ) -> pd.DataFrame:
@ -89,7 +86,7 @@ def normalize(
def reweight( def reweight(
storage: Type["BaseFeatureStorage"], storage: StorageLike,
feature_name: Optional[str] = None, feature_name: Optional[str] = None,
feature_md5: Optional[str] = None, feature_md5: Optional[str] = None,
) -> pd.DataFrame: ) -> pd.DataFrame:

View file

@ -4,22 +4,19 @@
# License: AGPL # License: AGPL
from typing import TYPE_CHECKING, Dict, Optional, Tuple, Type from typing import Dict, Optional, Tuple
import pandas as pd import pandas as pd
from ..typing import StorageLike
from ..utils import logger, raise_error, warn_with_log from ..utils import logger, raise_error, warn_with_log
if TYPE_CHECKING:
from junifer.storage import BaseFeatureStorage
__all__ = ["read_transform"] __all__ = ["read_transform"]
def read_transform( def read_transform(
storage: Type["BaseFeatureStorage"], storage: StorageLike,
transform: str, transform: str,
feature_name: Optional[str] = None, feature_name: Optional[str] = None,
feature_md5: Optional[str] = None, feature_md5: Optional[str] = None,

View file

@ -5,20 +5,14 @@
# License: AGPL # License: AGPL
from collections import Counter from collections import Counter
from typing import TYPE_CHECKING, Dict, List, Optional from typing import Dict, List, Optional
from ..datareader import DefaultDataReader from ..datareader import DefaultDataReader
from ..pipeline import PipelineStepMixin, WorkDirManager from ..pipeline import PipelineStepMixin, WorkDirManager
from ..typing import DataGrabberLike, MarkerLike, PreprocessorLike, StorageLike
from ..utils import logger, raise_error from ..utils import logger, raise_error
if TYPE_CHECKING:
from junifer.datagrabber import BaseDataGrabber
from junifer.markers import BaseMarker
from junifer.preprocess import BasePreprocessor
from junifer.storage import BaseFeatureStorage
__all__ = ["MarkerCollection"] __all__ = ["MarkerCollection"]
@ -45,10 +39,10 @@ class MarkerCollection:
def __init__( def __init__(
self, self,
markers: List["BaseMarker"], markers: List[MarkerLike],
datareader: Optional[PipelineStepMixin] = None, datareader: Optional[PipelineStepMixin] = None,
preprocessors: Optional[List["BasePreprocessor"]] = None, preprocessors: Optional[List[PreprocessorLike]] = None,
storage: Optional["BaseFeatureStorage"] = None, storage: Optional[StorageLike] = None,
): ):
# Check that the markers have different names # Check that the markers have different names
marker_names = [m.name for m in markers] marker_names = [m.name for m in markers]
@ -111,7 +105,7 @@ class MarkerCollection:
return None if self._storage else out return None if self._storage else out
def validate(self, datagrabber: "BaseDataGrabber") -> None: def validate(self, datagrabber: DataGrabberLike) -> None:
"""Validate the pipeline. """Validate the pipeline.
Without doing any computation, check if the marker collection can Without doing any computation, check if the marker collection can

View file

@ -6,18 +6,13 @@
# License: AGPL # License: AGPL
import importlib import importlib
from typing import TYPE_CHECKING, Dict, List, Mapping, Optional, Union from typing import Dict, List, Mapping, Optional, Union
from ..typing import DataGrabberLike, MarkerLike, PreprocessorLike, StorageLike
from ..utils import logger, raise_error from ..utils import logger, raise_error
from ..utils.singleton import Singleton from ..utils.singleton import Singleton
if TYPE_CHECKING:
from ..datagrabber import BaseDataGrabber
from ..storage import BaseFeatureStorage
from .pipeline_step_mixin import PipelineStepMixin
__all__ = ["PipelineComponentRegistry"] __all__ = ["PipelineComponentRegistry"]
@ -241,7 +236,7 @@ class PipelineComponentRegistry(metaclass=Singleton):
name: str, name: str,
baseclass: type, baseclass: type,
init_params: Optional[Dict] = None, init_params: Optional[Dict] = None,
) -> Union["BaseDataGrabber", "PipelineStepMixin", "BaseFeatureStorage"]: ) -> Union[DataGrabberLike, PreprocessorLike, MarkerLike, StorageLike]:
"""Build an instance of class registered as ``name``. """Build an instance of class registered as ``name``.
Parameters Parameters

View file

@ -5,12 +5,17 @@
# License: AGPL # License: AGPL
import warnings import warnings
from typing import ClassVar, Dict, List, Set, Type, Union from typing import ClassVar, Dict, List
import pytest import pytest
from junifer.pipeline.pipeline_step_mixin import PipelineStepMixin from junifer.pipeline.pipeline_step_mixin import PipelineStepMixin
from junifer.pipeline.utils import _check_afni from junifer.pipeline.utils import _check_afni
from junifer.typing import (
ConditionalDependencies,
Dependencies,
ExternalDependencies,
)
def test_PipelineStepMixin_correct_dependencies() -> None: def test_PipelineStepMixin_correct_dependencies() -> None:
@ -19,7 +24,7 @@ def test_PipelineStepMixin_correct_dependencies() -> None:
class CorrectMixer(PipelineStepMixin): class CorrectMixer(PipelineStepMixin):
"""Test class for validation.""" """Test class for validation."""
_DEPENDENCIES: ClassVar[Set[str]] = {"math"} _DEPENDENCIES: ClassVar[Dependencies] = {"math"}
def validate_input(self, input: List[str]) -> List[str]: def validate_input(self, input: List[str]) -> List[str]:
return input return input
@ -40,7 +45,7 @@ def test_PipelineStepMixin_incorrect_dependencies() -> None:
class IncorrectMixer(PipelineStepMixin): class IncorrectMixer(PipelineStepMixin):
"""Test class for validation.""" """Test class for validation."""
_DEPENDENCIES: ClassVar[Set[str]] = {"foobar"} _DEPENDENCIES: ClassVar[Dependencies] = {"foobar"}
def validate_input(self, input: List[str]) -> List[str]: def validate_input(self, input: List[str]) -> List[str]:
return input return input
@ -65,7 +70,7 @@ def test_PipelineStepMixin_correct_ext_dependencies() -> None:
class CorrectMixer(PipelineStepMixin): class CorrectMixer(PipelineStepMixin):
"""Test class for validation.""" """Test class for validation."""
_EXT_DEPENDENCIES: ClassVar[List[Dict[str, str]]] = [{"name": "afni"}] _EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [{"name": "afni"}]
def validate_input(self, input: List[str]) -> List[str]: def validate_input(self, input: List[str]) -> List[str]:
return input return input
@ -89,7 +94,7 @@ def test_PipelineStepMixin_ext_deps_correct_commands() -> None:
class CorrectMixer(PipelineStepMixin): class CorrectMixer(PipelineStepMixin):
"""Test class for validation.""" """Test class for validation."""
_EXT_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, List[str]]]]] = [ _EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
{"name": "afni", "commands": ["3dReHo"]} {"name": "afni", "commands": ["3dReHo"]}
] ]
@ -117,7 +122,7 @@ def test_PipelineStepMixin_ext_deps_incorrect_commands() -> None:
class CorrectMixer(PipelineStepMixin): class CorrectMixer(PipelineStepMixin):
"""Test class for validation.""" """Test class for validation."""
_EXT_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, List[str]]]]] = [ _EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
{"name": "afni", "commands": ["3d"]} {"name": "afni", "commands": ["3d"]}
] ]
@ -141,7 +146,7 @@ def test_PipelineStepMixin_incorrect_ext_dependencies() -> None:
class IncorrectMixer(PipelineStepMixin): class IncorrectMixer(PipelineStepMixin):
"""Test class for validation.""" """Test class for validation."""
_EXT_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, bool]]]] = [ _EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
{"name": "foobar", "optional": True} {"name": "foobar", "optional": True}
] ]
@ -163,14 +168,12 @@ def test_PipelineStepMixin_correct_conditional_dependencies() -> None:
"""Test fit-transform with correct conditional dependencies.""" """Test fit-transform with correct conditional dependencies."""
class Dependency: class Dependency:
_DEPENDENCIES: ClassVar[Set[str]] = {"math"} _DEPENDENCIES: ClassVar[Dependencies] = {"math"}
class CorrectMixer(PipelineStepMixin): class CorrectMixer(PipelineStepMixin):
"""Test class for validation.""" """Test class for validation."""
_CONDITIONAL_DEPENDENCIES: ClassVar[ _CONDITIONAL_DEPENDENCIES: ClassVar[ConditionalDependencies] = [
List[Dict[str, Union[str, Type]]]
] = [
{ {
"using": "math", "using": "math",
"depends_on": Dependency, "depends_on": Dependency,
@ -196,14 +199,12 @@ def test_PipelineStepMixin_incorrect_conditional_dependencies() -> None:
"""Test fit-transform with incorrect conditional dependencies.""" """Test fit-transform with incorrect conditional dependencies."""
class Dependency: class Dependency:
_DEPENDENCIES: ClassVar[Set[str]] = {"math"} _DEPENDENCIES: ClassVar[Dependencies] = {"math"}
class IncorrectMixer(PipelineStepMixin): class IncorrectMixer(PipelineStepMixin):
"""Test class for validation.""" """Test class for validation."""
_CONDITIONAL_DEPENDENCIES: ClassVar[ _CONDITIONAL_DEPENDENCIES: ClassVar[ConditionalDependencies] = [
List[Dict[str, Union[str, Type]]]
] = [
{ {
"using": "math", "using": "math",
"depends_on": Dependency, "depends_on": Dependency,
@ -231,14 +232,12 @@ def test_PipelineStepMixin_correct_conditional_ext_dependencies() -> None:
"""Test fit-transform with correct conditional external dependencies.""" """Test fit-transform with correct conditional external dependencies."""
class ExternalDependency: class ExternalDependency:
_EXT_DEPENDENCIES: ClassVar[List[Dict[str, str]]] = [{"name": "afni"}] _EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [{"name": "afni"}]
class CorrectMixer(PipelineStepMixin): class CorrectMixer(PipelineStepMixin):
"""Test class for validation.""" """Test class for validation."""
_CONDITIONAL_DEPENDENCIES: ClassVar[ _CONDITIONAL_DEPENDENCIES: ClassVar[ConditionalDependencies] = [
List[Dict[str, Union[str, Type]]]
] = [
{ {
"using": "afni", "using": "afni",
"depends_on": ExternalDependency, "depends_on": ExternalDependency,

View file

@ -103,6 +103,7 @@ def test_workdir_manager_get_and_delete_tempdir(tmp_path: Path) -> None:
# Should remove temporary directory # Should remove temporary directory
assert workdir_mgr.root_tempdir is None assert workdir_mgr.root_tempdir is None
def test_workdir_manager_no_cleanup(tmp_path: Path) -> None: def test_workdir_manager_no_cleanup(tmp_path: Path) -> None:
"""Test WorkDirManager correctly bypasses cleanup. """Test WorkDirManager correctly bypasses cleanup.

View file

@ -11,7 +11,6 @@ from typing import (
Dict, Dict,
List, List,
Optional, Optional,
Set,
Tuple, Tuple,
Union, Union,
) )
@ -23,6 +22,7 @@ from nilearn._utils.niimg_conversions import check_niimg_4d
from ...api.decorators import register_preprocessor from ...api.decorators import register_preprocessor
from ...data import get_data from ...data import get_data
from ...typing import Dependencies
from ...utils import logger, raise_error from ...utils import logger, raise_error
from ..base import BasePreprocessor from ..base import BasePreprocessor
@ -152,7 +152,7 @@ class fMRIPrepConfoundRemover(BasePreprocessor):
""" """
_DEPENDENCIES: ClassVar[Set[str]] = {"numpy", "nilearn"} _DEPENDENCIES: ClassVar[Dependencies] = {"numpy", "nilearn"}
def __init__( def __init__(
self, self,

View file

@ -6,20 +6,18 @@
from typing import ( from typing import (
TYPE_CHECKING, TYPE_CHECKING,
ClassVar, ClassVar,
Dict,
List,
Set,
Union, Union,
) )
import nibabel as nib import nibabel as nib
from ...pipeline import WorkDirManager from ...pipeline import WorkDirManager
from ...typing import Dependencies, ExternalDependencies
from ...utils import logger, run_ext_cmd from ...utils import logger, run_ext_cmd
if TYPE_CHECKING: if TYPE_CHECKING:
from nibabel import Nifti1Image from nibabel.nifti1 import Nifti1Image
__all__ = ["AFNISmoothing"] __all__ = ["AFNISmoothing"]
@ -32,14 +30,14 @@ class AFNISmoothing:
""" """
_EXT_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, List[str]]]]] = [ _EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
{ {
"name": "afni", "name": "afni",
"commands": ["3dBlurToFWHM"], "commands": ["3dBlurToFWHM"],
}, },
] ]
_DEPENDENCIES: ClassVar[Set[str]] = {"nibabel"} _DEPENDENCIES: ClassVar[Dependencies] = {"nibabel"}
def preprocess( def preprocess(
self, self,

View file

@ -6,20 +6,17 @@
from typing import ( from typing import (
TYPE_CHECKING, TYPE_CHECKING,
ClassVar, ClassVar,
Dict,
List,
Set,
Union,
) )
import nibabel as nib import nibabel as nib
from ...pipeline import WorkDirManager from ...pipeline import WorkDirManager
from ...typing import Dependencies, ExternalDependencies
from ...utils import logger, run_ext_cmd from ...utils import logger, run_ext_cmd
if TYPE_CHECKING: if TYPE_CHECKING:
from nibabel import Nifti1Image from nibabel.nifti1 import Nifti1Image
__all__ = ["FSLSmoothing"] __all__ = ["FSLSmoothing"]
@ -32,14 +29,14 @@ class FSLSmoothing:
""" """
_EXT_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, List[str]]]]] = [ _EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
{ {
"name": "fsl", "name": "fsl",
"commands": ["susan"], "commands": ["susan"],
}, },
] ]
_DEPENDENCIES: ClassVar[Set[str]] = {"nibabel"} _DEPENDENCIES: ClassVar[Dependencies] = {"nibabel"}
def preprocess( def preprocess(
self, self,

View file

@ -7,18 +7,18 @@ from typing import (
TYPE_CHECKING, TYPE_CHECKING,
ClassVar, ClassVar,
Literal, Literal,
Set,
Union, Union,
) )
from nilearn import image as nimg from nilearn import image as nimg
from numpy.typing import ArrayLike from numpy.typing import ArrayLike
from ...typing import Dependencies
from ...utils import logger from ...utils import logger
if TYPE_CHECKING: if TYPE_CHECKING:
from nibabel import Nifti1Image from nibabel.nifti1 import Nifti1Image
__all__ = ["NilearnSmoothing"] __all__ = ["NilearnSmoothing"]
@ -31,7 +31,7 @@ class NilearnSmoothing:
""" """
_DEPENDENCIES: ClassVar[Set[str]] = {"nilearn"} _DEPENDENCIES: ClassVar[Dependencies] = {"nilearn"}
def preprocess( def preprocess(
self, self,

View file

@ -3,9 +3,10 @@
# Authors: Synchon Mandal <s.mandal@fz-juelich.de> # Authors: Synchon Mandal <s.mandal@fz-juelich.de>
# License: AGPL # License: AGPL
from typing import Any, ClassVar, Dict, List, Optional, Tuple, Type, Union from typing import Any, ClassVar, Dict, List, Optional, Tuple, Union
from ...api.decorators import register_preprocessor from ...api.decorators import register_preprocessor
from ...typing import ConditionalDependencies
from ...utils import logger, raise_error from ...utils import logger, raise_error
from ..base import BasePreprocessor from ..base import BasePreprocessor
from ._afni_smoothing import AFNISmoothing from ._afni_smoothing import AFNISmoothing
@ -67,7 +68,7 @@ class Smoothing(BasePreprocessor):
""" """
_CONDITIONAL_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, Type]]]] = [ _CONDITIONAL_DEPENDENCIES: ClassVar[ConditionalDependencies] = [
{ {
"using": "nilearn", "using": "nilearn",
"depends_on": NilearnSmoothing, "depends_on": NilearnSmoothing,

View file

@ -7,9 +7,6 @@ from typing import (
Any, Any,
ClassVar, ClassVar,
Dict, Dict,
List,
Set,
Union,
) )
import nibabel as nib import nibabel as nib
@ -17,6 +14,7 @@ import numpy as np
from ...data import get_template, get_xfm from ...data import get_template, get_xfm
from ...pipeline import WorkDirManager from ...pipeline import WorkDirManager
from ...typing import Dependencies, ExternalDependencies
from ...utils import logger, run_ext_cmd from ...utils import logger, run_ext_cmd
@ -31,14 +29,14 @@ class ANTsWarper:
""" """
_EXT_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, List[str]]]]] = [ _EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
{ {
"name": "ants", "name": "ants",
"commands": ["ResampleImage", "antsApplyTransforms"], "commands": ["ResampleImage", "antsApplyTransforms"],
}, },
] ]
_DEPENDENCIES: ClassVar[Set[str]] = {"numpy", "nibabel"} _DEPENDENCIES: ClassVar[Dependencies] = {"numpy", "nibabel"}
def preprocess( def preprocess(
self, self,

View file

@ -7,15 +7,13 @@ from typing import (
Any, Any,
ClassVar, ClassVar,
Dict, Dict,
List,
Set,
Union,
) )
import nibabel as nib import nibabel as nib
import numpy as np import numpy as np
from ...pipeline import WorkDirManager from ...pipeline import WorkDirManager
from ...typing import Dependencies, ExternalDependencies
from ...utils import logger, run_ext_cmd from ...utils import logger, run_ext_cmd
@ -30,14 +28,14 @@ class FSLWarper:
""" """
_EXT_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, List[str]]]]] = [ _EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
{ {
"name": "fsl", "name": "fsl",
"commands": ["flirt", "applywarp"], "commands": ["flirt", "applywarp"],
}, },
] ]
_DEPENDENCIES: ClassVar[Set[str]] = {"numpy", "nibabel"} _DEPENDENCIES: ClassVar[Dependencies] = {"numpy", "nibabel"}
def preprocess( def preprocess(
self, self,

View file

@ -3,11 +3,12 @@
# Authors: Synchon Mandal <s.mandal@fz-juelich.de> # Authors: Synchon Mandal <s.mandal@fz-juelich.de>
# License: AGPL # License: AGPL
from typing import Any, ClassVar, Dict, List, Optional, Tuple, Type, Union from typing import Any, ClassVar, Dict, List, Optional, Tuple, Union
from templateflow import api as tflow from templateflow import api as tflow
from ...api.decorators import register_preprocessor from ...api.decorators import register_preprocessor
from ...typing import ConditionalDependencies
from ...utils import logger, raise_error from ...utils import logger, raise_error
from ..base import BasePreprocessor from ..base import BasePreprocessor
from ._ants_warper import ANTsWarper from ._ants_warper import ANTsWarper
@ -46,7 +47,7 @@ class SpaceWarper(BasePreprocessor):
""" """
_CONDITIONAL_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, Type]]]] = [ _CONDITIONAL_DEPENDENCIES: ClassVar[ConditionalDependencies] = [
{ {
"using": "fsl", "using": "fsl",
"depends_on": FSLWarper, "depends_on": FSLWarper,

View file

@ -4,7 +4,7 @@
# License: AGPL # License: AGPL
import socket import socket
from typing import TYPE_CHECKING, Tuple, Type from typing import Tuple, Type
import pytest import pytest
from numpy.testing import assert_array_equal, assert_raises from numpy.testing import assert_array_equal, assert_raises
@ -14,10 +14,7 @@ from junifer.datareader import DefaultDataReader
from junifer.pipeline.utils import _check_ants, _check_fsl from junifer.pipeline.utils import _check_ants, _check_fsl
from junifer.preprocess import SpaceWarper from junifer.preprocess import SpaceWarper
from junifer.testing.datagrabbers import PartlyCloudyTestingDataGrabber from junifer.testing.datagrabbers import PartlyCloudyTestingDataGrabber
from junifer.typing import DataGrabberLike
if TYPE_CHECKING:
from junifer.datagrabber import BaseDataGrabber
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -99,7 +96,7 @@ def test_SpaceWarper_errors(
reason="only for juseless", reason="only for juseless",
) )
def test_SpaceWarper_native( def test_SpaceWarper_native(
datagrabber: "BaseDataGrabber", element: Tuple[str, ...], using: str datagrabber: DataGrabberLike, element: Tuple[str, ...], using: str
) -> None: ) -> None:
"""Test SpaceWarper for native space warping. """Test SpaceWarper for native space warping.
@ -162,7 +159,7 @@ def test_SpaceWarper_native(
_check_ants() is False, reason="requires ANTs to be in PATH" _check_ants() is False, reason="requires ANTs to be in PATH"
) )
def test_SpaceWarper_multi_mni( def test_SpaceWarper_multi_mni(
datagrabber: "BaseDataGrabber", datagrabber: DataGrabberLike,
element: Tuple[str, ...], element: Tuple[str, ...],
space: str, space: str,
) -> None: ) -> None:

View file

@ -0,0 +1,9 @@
"""Type hints for internal and external use."""
# Authors: Synchon Mandal <s.mandal@fz-juelich.de>
# License: AGPL
import lazy_loader as lazy
__getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)

View file

@ -0,0 +1,23 @@
__all__ = [
"DataGrabberLike",
"PreprocessorLike",
"MarkerLike",
"StorageLike",
"PipelineComponent",
"Dependencies",
"ConditionalDependencies",
"ExternalDependencies",
"MarkerInOutMappings",
]
from ._typing import (
DataGrabberLike,
PreprocessorLike,
MarkerLike,
StorageLike,
PipelineComponent,
Dependencies,
ConditionalDependencies,
ExternalDependencies,
MarkerInOutMappings,
)

61
junifer/typing/_typing.py Normal file
View file

@ -0,0 +1,61 @@
"""Provide type hints for internal and external use."""
# Authors: Synchon Mandal <s.mandal@fz-juelich.de>
# License: AGPL
from typing import (
TYPE_CHECKING,
AbstractSet,
MutableMapping,
Sequence,
Type,
Union,
)
if TYPE_CHECKING:
from ..datagrabber import BaseDataGrabber
from ..datareader import DefaultDataReader
from ..markers import BaseMarker
from ..preprocess import BasePreprocessor
from ..storage import BaseFeatureStorage
__all__ = [
"DataGrabberLike",
"PreprocessorLike",
"MarkerLike",
"StorageLike",
"PipelineComponent",
"Dependencies",
"ConditionalDependencies",
"ExternalDependencies",
"MarkerInOutMappings",
]
DataGrabberLike = Type["BaseDataGrabber"]
PreprocessorLike = Type["BasePreprocessor"]
MarkerLike = Type["BaseMarker"]
StorageLike = Type["BaseFeatureStorage"]
PipelineComponent = Union[
"DataGrabberLike",
"DefaultDataReader",
"PreprocessorLike",
"MarkerLike",
"StorageLike",
]
Dependencies = AbstractSet[str]
ConditionalDependencies = Sequence[
MutableMapping[
str,
Union[
str,
PipelineComponent,
Sequence[str],
Sequence[PipelineComponent],
],
]
]
ExternalDependencies = Sequence[MutableMapping[str, Union[str, Sequence[str]]]]
MarkerInOutMappings = MutableMapping[str, MutableMapping[str, str]]