Skip to content

Commit

Permalink
Merge pull request #392 from juaml/style/typing
Browse files Browse the repository at this point in the history
[ENH]: Introduce `junfer.typing` module
  • Loading branch information
synchon authored Nov 13, 2024
2 parents 8c2de75 + c4e2c59 commit 96f693e
Show file tree
Hide file tree
Showing 41 changed files with 240 additions and 171 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ The documentation is available at [https://juaml.github.io/junifer](https://juam
* `preprocess`: Preprocessing module.
* `storage`: Storage module.
* `testing`: Testing components module.
* `typing`: Type hints module.
* `utils`: Utilities module (e.g. logging).

## Installation
Expand Down
1 change: 1 addition & 0 deletions docs/changes/newsfragments/392.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Introduce ``junifer.typing`` sub-module to organise internal and external type hints by `Synchon Mandal`_
10 changes: 5 additions & 5 deletions docs/extending/dependencies.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ component depends on. For example, for :class:`.RSSETSMarker`, we have:

.. code-block:: python
_DEPENDENCIES: ClassVar[Set[str]] = {"nilearn"}
_DEPENDENCIES: ClassVar[Dependencies] = {"nilearn"}
The type annotation is for documentation and static type checking purposes.
Although not required, we highly recommend you use them, your future self
Expand All @@ -44,7 +44,7 @@ by having a class attribute like so:

.. code-block:: python
_EXT_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, List[str]]]]] = [
_EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
{
"name": "afni",
"commands": ["3dReHo", "3dAFNItoNIFTI"],
Expand Down Expand Up @@ -78,7 +78,7 @@ that it shows the problem a bit better and how we solve it:
class SpaceWarper(BasePreprocessor):
# docstring
_CONDITIONAL_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, Type]]]] = [
_CONDITIONAL_DEPENDENCIES: ClassVar[ConditionalDependencies] = [
{
"using": "fsl",
"depends_on": FSLWarper,
Expand Down Expand Up @@ -115,14 +115,14 @@ similar. ``FSLWarper`` looks like this (only the relevant part is shown here):
class FSLWarper:
# docstring
_EXT_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, List[str]]]]] = [
_EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
{
"name": "fsl",
"commands": ["flirt", "applywarp"],
},
]
_DEPENDENCIES: ClassVar[Set[str]] = {"numpy", "nibabel"}
_DEPENDENCIES: ClassVar[Dependencies] = {"numpy", "nibabel"}
def preprocess(
self,
Expand Down
5 changes: 3 additions & 2 deletions docs/extending/marker.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.data import get_parcellation
from junifer.markers import BaseMarker
from junifer.typing import Dependencies, MarkerInOutMappings
from nilearn.maskers import NiftiLabelsMasker
@register_marker
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": {
"parcel_mean": "timeseries",
},
Expand Down
2 changes: 2 additions & 0 deletions junifer/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ __all__ = [
"external",
"onthefly",
"testing",
"typing",
"__version__",
]

Expand All @@ -30,6 +31,7 @@ from . import (
utils,
external,
testing,
typing,
onthefly,
)
from ._version import __version__
9 changes: 5 additions & 4 deletions junifer/api/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from typing import Type

from ..pipeline import PipelineComponentRegistry
from ..typing import DataGrabberLike, MarkerLike, PreprocessorLike, StorageLike


__all__ = [
Expand All @@ -19,7 +20,7 @@
]


def register_datagrabber(klass: Type) -> Type:
def register_datagrabber(klass: DataGrabberLike) -> DataGrabberLike:
"""Register DataGrabber.
Registers the DataGrabber so it can be used by name.
Expand Down Expand Up @@ -73,7 +74,7 @@ def register_datareader(klass: Type) -> Type:
return klass


def register_preprocessor(klass: Type) -> Type:
def register_preprocessor(klass: PreprocessorLike) -> PreprocessorLike:
"""Preprocessor registration decorator.
Registers the preprocessor so it can be used by name.
Expand All @@ -96,7 +97,7 @@ def register_preprocessor(klass: Type) -> Type:
return klass


def register_marker(klass: Type) -> Type:
def register_marker(klass: MarkerLike) -> MarkerLike:
"""Marker registration decorator.
Registers the marker so it can be used by name.
Expand All @@ -119,7 +120,7 @@ def register_marker(klass: Type) -> Type:
return klass


def register_storage(klass: Type) -> Type:
def register_storage(klass: StorageLike) -> StorageLike:
"""Storage registration decorator.
Registers the storage so it can be used by name.
Expand Down
17 changes: 9 additions & 8 deletions junifer/api/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,23 @@
from typing import Dict, List, Optional, Tuple, Union

from ..api.queue_context import GnuParallelLocalAdapter, HTCondorAdapter
from ..datagrabber.base import BaseDataGrabber
from ..markers.base import BaseMarker
from ..datagrabber import BaseDataGrabber
from ..markers import BaseMarker
from ..pipeline import (
MarkerCollection,
PipelineComponentRegistry,
WorkDirManager,
)
from ..preprocess.base import BasePreprocessor
from ..storage.base import BaseFeatureStorage
from ..preprocess import BasePreprocessor
from ..storage import BaseFeatureStorage
from ..typing import DataGrabberLike, MarkerLike, PreprocessorLike, StorageLike
from ..utils import logger, raise_error, yaml


__all__ = ["run", "collect", "queue", "reset", "list_elements"]


def _get_datagrabber(datagrabber_config: Dict) -> BaseDataGrabber:
def _get_datagrabber(datagrabber_config: Dict) -> DataGrabberLike:
"""Get DataGrabber.
Parameters
Expand All @@ -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.
Parameters
Expand All @@ -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.
Parameters
Expand All @@ -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.
Parameters
Expand Down
3 changes: 2 additions & 1 deletion junifer/datagrabber/multiple.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from typing import Dict, List, Tuple, Union

from ..api.decorators import register_datagrabber
from ..typing import DataGrabberLike
from ..utils import deep_update, raise_error
from .base import BaseDataGrabber

Expand Down Expand Up @@ -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 for same element keys
first_keys = datagrabbers[0].get_element_keys()
Expand Down
11 changes: 4 additions & 7 deletions junifer/markers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,13 @@

from abc import ABC, abstractmethod
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 ..typing import StorageLike
from ..utils import logger, raise_error


if TYPE_CHECKING:
from junifer.storage import BaseFeatureStorage


__all__ = ["BaseMarker"]


Expand Down Expand Up @@ -159,7 +156,7 @@ def store(
type_: str,
feature: str,
out: Dict[str, Any],
storage: "BaseFeatureStorage",
storage: StorageLike,
) -> None:
"""Store.
Expand All @@ -182,7 +179,7 @@ def store(
def _fit_transform(
self,
input: Dict[str, Dict],
storage: Optional["BaseFeatureStorage"] = None,
storage: Optional[StorageLike] = None,
) -> Dict:
"""Fit and transform.
Expand Down
8 changes: 4 additions & 4 deletions junifer/markers/brainprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
Dict,
List,
Optional,
Set,
Union,
)

Expand All @@ -25,6 +24,7 @@
)
from ..external.BrainPrint.brainprint.surfaces import surf_to_vtk
from ..pipeline import WorkDirManager
from ..typing import Dependencies, ExternalDependencies, MarkerInOutMappings
from ..utils import logger, run_ext_cmd
from .base import BaseMarker

Expand Down Expand Up @@ -68,7 +68,7 @@ class BrainPrint(BaseMarker):
"""

_EXT_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, List[str]]]]] = [
_EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
{
"name": "freesurfer",
"commands": [
Expand All @@ -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": {
"eigenvalues": "scalar_table",
"areas": "vector",
Expand Down
6 changes: 3 additions & 3 deletions junifer/markers/complexity/complexity_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
Dict,
List,
Optional,
Set,
Union,
)

from ...typing import Dependencies, MarkerInOutMappings
from ...utils import raise_error
from ..base import BaseMarker
from ..parcel_aggregation import ParcelAggregation
Expand Down Expand Up @@ -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": {
"complexity": "vector",
},
Expand Down
7 changes: 4 additions & 3 deletions junifer/markers/ets_rss.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
# Synchon Mandal <[email protected]>
# 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

from ..api.decorators import register_marker
from ..typing import Dependencies, MarkerInOutMappings
from ..utils import logger
from .base import BaseMarker
from .parcel_aggregation import ParcelAggregation
Expand Down Expand Up @@ -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": {
"rss_ets": "timeseries",
},
Expand Down
8 changes: 3 additions & 5 deletions junifer/markers/falff/_afni_falff.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,20 @@
from typing import (
TYPE_CHECKING,
ClassVar,
Dict,
List,
Optional,
Tuple,
Union,
)

import nibabel as nib

from ...pipeline import WorkDirManager
from ...typing import ExternalDependencies
from ...utils import logger, run_ext_cmd
from ...utils.singleton import Singleton


if TYPE_CHECKING:
from nibabel import Nifti1Image
from nibabel.nifti1 import Nifti1Image


__all__ = ["AFNIALFF"]
Expand All @@ -37,7 +35,7 @@ class AFNIALFF(metaclass=Singleton):
"""

_EXT_DEPENDENCIES: ClassVar[List[Dict[str, Union[str, List[str]]]]] = [
_EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
{
"name": "afni",
"commands": ["3dRSFC", "3dAFNItoNIFTI"],
Expand Down
6 changes: 3 additions & 3 deletions junifer/markers/falff/_junifer_falff.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
TYPE_CHECKING,
ClassVar,
Optional,
Set,
Tuple,
)

Expand All @@ -19,12 +18,13 @@
from nilearn import image as nimg

from ...pipeline import WorkDirManager
from ...typing import Dependencies
from ...utils import logger
from ...utils.singleton import Singleton


if TYPE_CHECKING:
from nibabel import Nifti1Image
from nibabel.nifti1 import Nifti1Image


__all__ = ["JuniferALFF"]
Expand All @@ -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:
"""Terminate the class."""
Expand Down
Loading

0 comments on commit 96f693e

Please sign in to comment.