diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5f7c2bcd8..27e551b7a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ ci: repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v4.6.0 hooks: - id: check-ast - id: check-docstring-first @@ -20,14 +20,14 @@ repos: rev: v0.16 hooks: - id: validate-pyproject - - repo: https://github.com/psf/black - rev: 24.1.1 + - repo: https://github.com/psf/black-pre-commit-mirror + rev: 24.4.2 hooks: - id: black exclude: ^(docs/|examples/|tools/) args: [--check] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.1.15 + rev: v0.4.2 hooks: - id: ruff types_or: [python, jupyter] @@ -38,7 +38,7 @@ repos: hooks: - id: codespell exclude: ^(.github/|docs/) - args: [--config, tox.ini] + args: [--toml, pyproject.toml] - repo: https://github.com/pre-commit/pygrep-hooks rev: v1.10.0 hooks: @@ -47,3 +47,10 @@ repos: - id: rst-backticks - id: rst-directive-colons - id: rst-inline-touching-normal + - repo: https://github.com/adamchainz/blacken-docs + rev: "1.16.0" + hooks: + - id: blacken-docs + additional_dependencies: + - black==24.4.2 + args: [-l 79] diff --git a/docs/changes/newsfragments/337.misc b/docs/changes/newsfragments/337.misc new file mode 100644 index 000000000..9c829fc2d --- /dev/null +++ b/docs/changes/newsfragments/337.misc @@ -0,0 +1 @@ +Update ``pre-commit`` dependency versions, add ``blacken-docs`` to ``pre-commit``, add ``__all__`` for modules, sub-packages and package, update ``ruff`` and ``pytest`` configs in ``pyproject.toml`` by `Synchon Mandal`_ diff --git a/docs/extending/coordinates.rst b/docs/extending/coordinates.rst index f56c29708..89f32e066 100644 --- a/docs/extending/coordinates.rst +++ b/docs/extending/coordinates.rst @@ -70,10 +70,7 @@ with the DMN. Here, we use the DMN coordinates used in a .. code-block:: python dmn_coords = np.array( - [[0, -52, 18], - [-46, -68, 32], - [46, -68, 32], - [1, 50, -5]] + [[0, -52, 18], [-46, -68, 32], [46, -68, 32], [1, 50, -5]] ) voi_names = [ "Posterior Cingulate Cortex", @@ -90,10 +87,7 @@ simply use this to register our coordinates: .. code-block:: python register_coordinates( - name="DMNCustom", - coordinates=dmn_coords, - voi_names=voi_names, - space="MNI" + name="DMNCustom", coordinates=dmn_coords, voi_names=voi_names, space="MNI" ) Now, when we run this script, ``junifer`` registers these coordinates and we can diff --git a/docs/extending/datagrabber.rst b/docs/extending/datagrabber.rst index deaa98ba8..f76303f35 100644 --- a/docs/extending/datagrabber.rst +++ b/docs/extending/datagrabber.rst @@ -115,14 +115,14 @@ For example, in our BIDS example, the variables will be: types = ["T1w", "BOLD"] patterns = { - "T1w": { - "pattern": "{subject}/{session}/anat/{subject}_{session}_T1w.nii.gz", - "space": "native", - }, - "BOLD": { - "pattern": "{subject}/{session}/func/{subject}_{session}_task-rest_bold.nii.gz", - "space": "MNI152NLin6Asym", - }, + "T1w": { + "pattern": "{subject}/{session}/anat/{subject}_{session}_T1w.nii.gz", + "space": "native", + }, + "BOLD": { + "pattern": "{subject}/{session}/func/{subject}_{session}_task-rest_bold.nii.gz", + "space": "MNI152NLin6Asym", + }, } replacements = ["subject", "session"] @@ -144,25 +144,24 @@ With the variables defined above, we can create our DataGrabber and name it class ExampleBIDSDataGrabber(PatternDataGrabber): - def __init__(self, datadir: str | Path) -> None: types = ["T1w", "BOLD"] patterns = { - "T1w": { - "pattern": "{subject}/{session}/anat/{subject}_{session}_T1w.nii.gz", - "space": "native", - }, - "BOLD": { - "pattern": "{subject}/{session}/func/{subject}_{session}_task-rest_bold.nii.gz", - "space": "MNI152NLin6Asym", - }, + "T1w": { + "pattern": "{subject}/{session}/anat/{subject}_{session}_T1w.nii.gz", + "space": "native", + }, + "BOLD": { + "pattern": "{subject}/{session}/func/{subject}_{session}_task-rest_bold.nii.gz", + "space": "MNI152NLin6Asym", + }, } replacements = ["subject", "session"] super().__init__( - datadir=datadir, - types=types, - patterns=patterns, - replacements=replacements, + datadir=datadir, + types=types, + patterns=patterns, + replacements=replacements, ) Our DataGrabber is ready to be used by ``junifer``. However, it is still unknown @@ -180,25 +179,24 @@ use the :func:`.register_datagrabber` decorator. @register_datagrabber class ExampleBIDSDataGrabber(PatternDataGrabber): - def __init__(self, datadir: str | Path) -> None: types = ["T1w", "BOLD"] patterns = { - "T1w": { - "pattern": "{subject}/{session}/anat/{subject}_{session}_T1w.nii.gz", - "space": "native", - }, - "BOLD": { - "pattern": "{subject}/{session}/func/{subject}_{session}_task-rest_bold.nii.gz", - "space": "MNI152NLin6Asym", - }, + "T1w": { + "pattern": "{subject}/{session}/anat/{subject}_{session}_T1w.nii.gz", + "space": "native", + }, + "BOLD": { + "pattern": "{subject}/{session}/func/{subject}_{session}_task-rest_bold.nii.gz", + "space": "MNI152NLin6Asym", + }, } replacements = ["subject", "session"] super().__init__( - datadir=datadir, - types=types, - patterns=patterns, - replacements=replacements, + datadir=datadir, + types=types, + patterns=patterns, + replacements=replacements, ) @@ -267,29 +265,28 @@ And we can create our DataGrabber: @register_datagrabber class ExampleBIDSDataGrabber(PatternDataladDataGrabber): - def __init__(self) -> None: types = ["T1w", "BOLD"] patterns = { - "T1w": { - "pattern": "{subject}/{session}/anat/{subject}_{session}_T1w.nii.gz", - "space": "native", - }, - "BOLD": { - "pattern": "{subject}/{session}/func/{subject}_{session}_task-rest_bold.nii.gz", - "space": "MNI152NLin6Asym", - }, + "T1w": { + "pattern": "{subject}/{session}/anat/{subject}_{session}_T1w.nii.gz", + "space": "native", + }, + "BOLD": { + "pattern": "{subject}/{session}/func/{subject}_{session}_task-rest_bold.nii.gz", + "space": "MNI152NLin6Asym", + }, } replacements = ["subject", "session"] uri = "https://gin.g-node.org/juaml/datalad-example-bids" rootdir = "example_bids_ses" super().__init__( - datadir=None, - uri=uri, - rootdir=rootdir, - types=types, - patterns=patterns, - replacements=replacements, + datadir=None, + uri=uri, + rootdir=rootdir, + types=types, + patterns=patterns, + replacements=replacements, ) This approach can be used directly from the YAML, like so: @@ -391,17 +388,17 @@ and ``session``, we will use them as parameters of ``get_item``: .. code-block:: python def get_item(self, subject: str, session: str) -> dict[str, dict[str, str]]: - out = { - "T1w": { - "path": f"{subject}/{session}/anat/{subject}_{session}_T1w.nii.gz", - "space": "native", - }, - "BOLD": { - "path": f"{subject}/{session}/func/{subject}_{session}_task-rest_bold.nii.gz", - "space": "MNI152NLin6Asym", - }, - } - return out + out = { + "T1w": { + "path": f"{subject}/{session}/anat/{subject}_{session}_T1w.nii.gz", + "space": "native", + }, + "BOLD": { + "path": f"{subject}/{session}/func/{subject}_{session}_task-rest_bold.nii.gz", + "space": "MNI152NLin6Asym", + }, + } + return out The second method, ``get_elements``, needs to return a list of all the elements @@ -415,16 +412,16 @@ need to remember that for session *ses-03* there is no BOLD data. def get_elements(self) -> list[str]: - subjects = ["sub-01", "sub-02", "sub-03"] - sessions = ["ses-01", "ses-02"] + subjects = ["sub-01", "sub-02", "sub-03"] + sessions = ["ses-01", "ses-02"] - # If we are not working on BOLD data, we can add "ses-03" - if "BOLD" not in self.types: - sessions.append("ses-03") - elements = [] - for subject, element in product(subjects, sessions): - elements.append({"subject": subject, "session": session}) - return elements + # If we are not working on BOLD data, we can add "ses-03" + if "BOLD" not in self.types: + sessions.append("ses-03") + elements = [] + for subject, element in product(subjects, sessions): + elements.append({"subject": subject, "session": session}) + return elements And finally, we can implement the ``get_element_keys`` method. This method needs @@ -435,7 +432,7 @@ method, in the same order. .. code-block:: python def get_element_keys(self) -> list[str]: - return ["subject", "session"] + return ["subject", "session"] So, to summarise, our DataGrabber will look like this: @@ -448,35 +445,36 @@ So, to summarise, our DataGrabber will look like this: @register_datagrabber class ExampleBIDSDataGrabber(BaseDataGrabber): + def get_item( + self, subject: str, session: str + ) -> dict[str, dict[str, str]]: + out = { + "T1w": { + "path": f"{subject}/{session}/anat/{subject}_{session}_T1w.nii.gz", + "space": "native", + }, + "BOLD": { + "path": f"{subject}/{session}/func/{subject}_{session}_task-rest_bold.nii.gz", + "space": "MNI152NLin6Asym", + }, + } + return out - def get_item(self, subject: str, session: str) -> dict[str, dict[str, str]]: - out = { - "T1w": { - "path": f"{subject}/{session}/anat/{subject}_{session}_T1w.nii.gz", - "space": "native", - }, - "BOLD": { - "path": f"{subject}/{session}/func/{subject}_{session}_task-rest_bold.nii.gz", - "space": "MNI152NLin6Asym", - }, - } - return out + def get_elements(self) -> list[str]: + subjects = ["sub-01", "sub-02", "sub-03"] + sessions = ["ses-01", "ses-02"] - def get_elements(self) -> list[str]: - subjects = ["sub-01", "sub-02", "sub-03"] - sessions = ["ses-01", "ses-02"] + # If we are not working on BOLD data, we can add "ses-03" + if "BOLD" not in self.types: + sessions.append("ses-03") + elements = [] + for subject in subjects: + for session in sessions: + elements.append({"subject": subject, "session": session}) + return elements - # If we are not working on BOLD data, we can add "ses-03" - if "BOLD" not in self.types: - sessions.append("ses-03") - elements = [] - for subject in subjects: - for session in sessions: - elements.append({"subject": subject, "session": session}) - return elements - - def get_element_keys(self) -> list[str]: - return ["subject", "session"] + def get_element_keys(self) -> list[str]: + return ["subject", "session"] Optional: Using datalad ~~~~~~~~~~~~~~~~~~~~~~~ @@ -522,26 +520,24 @@ this: .. code-block:: python - def get_item( - self, subject: str, session: str - ) -> dict: - out = { - "BOLD": { - "path": f"{subject}/{session}/func/{subject}_{session}_task-rest_bold.nii.gz", - "space": "MNI152NLin6Asym", - "confounds": { - "path": f"{subject}/{session}/func/{subject}_{session}_confounds.tsv", - "format": "adhoc", - "mappings": { - "fmriprep": { - "variable1": "rot_x", - "variable2": "rot_z", - "variable3": "rot_y", - }, - }, - }, - }, - } + def get_item(self, subject: str, session: str) -> dict: + out = { + "BOLD": { + "path": f"{subject}/{session}/func/{subject}_{session}_task-rest_bold.nii.gz", + "space": "MNI152NLin6Asym", + "confounds": { + "path": f"{subject}/{session}/func/{subject}_{session}_confounds.tsv", + "format": "adhoc", + "mappings": { + "fmriprep": { + "variable1": "rot_x", + "variable2": "rot_z", + "variable3": "rot_y", + }, + }, + }, + }, + } .. note:: diff --git a/docs/extending/dependencies.rst b/docs/extending/dependencies.rst index 1e44f3535..d1b538853 100644 --- a/docs/extending/dependencies.rst +++ b/docs/extending/dependencies.rst @@ -93,6 +93,7 @@ that it shows the problem a bit better and how we solve it: self, using: str, reference: str, on: Union[List[str], str] ) -> None: # validation and setting up + ... Here, you see a new class attribute ``_CONDITIONAL_DEPENDENCIES`` which is a @@ -129,6 +130,7 @@ similar. ``FSLWarper`` looks like this (only the relevant part is shown here): extra_input: Dict[str, Any], ) -> Dict[str, Any]: # implementation + ... Here you can see the familiar ``_DEPENDENCIES`` and ``_EXT_DEPENDENCIES`` class attributes. The validation process starts by looking up the ``using`` value of diff --git a/docs/extending/marker.rst b/docs/extending/marker.rst index 744a4cc2f..426c1b1d4 100644 --- a/docs/extending/marker.rst +++ b/docs/extending/marker.rst @@ -82,10 +82,10 @@ parcellation to use. Thus, we can define the ``__init__`` method as follows: .. code-block:: python def __init__( - self, - parcellation: str, - on: str | list[str] | None = None, - name: str | None = None, + self, + parcellation: str, + on: str | list[str] | None = None, + name: str | None = None, ) -> None: self.parcellation = parcellation super().__init__(on=on, name=name) @@ -137,9 +137,9 @@ the ``store`` method. def compute( - self, - input: dict[str, Any], - extra_input: dict[str, Any] | None = None, + self, + input: dict[str, Any], + extra_input: dict[str, Any] | None = None, ) -> dict[str, Any]: # Get the data data = input["data"] @@ -207,10 +207,10 @@ Finally, we need to register the Marker using the ``@register_marker`` decorator _DEPENDENCIES = {"nilearn", "numpy"} def __init__( - self, - parcellation: str, - on: str | list[str] | None = None, - name: str | None = None, + self, + parcellation: str, + on: str | list[str] | None = None, + name: str | None = None, ) -> None: self.parcellation = parcellation super().__init__(on=on, name=name) @@ -225,9 +225,9 @@ Finally, we need to register the Marker using the ``@register_marker`` decorator return "vector" def compute( - self, - input: dict[str, Any], - extra_input: dict[str, Any] | None = None, + self, + input: dict[str, Any], + extra_input: dict[str, Any] | None = None, ) -> dict[str, Any]: # Get the data data = input["data"] @@ -269,7 +269,6 @@ Template for a custom Marker @register_marker class TemplateMarker(BaseMarker): - def __init__(self, on=None, name=None): # TODO: add marker-specific parameters super().__init__(on=on, name=name) diff --git a/docs/extending/parcellations.rst b/docs/extending/parcellations.rst index 6c1a197cd..328735cf2 100644 --- a/docs/extending/parcellations.rst +++ b/docs/extending/parcellations.rst @@ -83,7 +83,7 @@ look like this: name="my_custom_parcellation", parcellation_path=path_to_parcellation, parcels_labels=my_labels, - space="MNI152NLin2009cAsym" + space="MNI152NLin2009cAsym", ) We can run this code and it seems to work, however, how can we actually diff --git a/docs/extending/preprocessor.rst b/docs/extending/preprocessor.rst index e94c6f3df..3fb26828a 100644 --- a/docs/extending/preprocessor.rst +++ b/docs/extending/preprocessor.rst @@ -43,9 +43,11 @@ For input we can accept ``T1w``, ``T2w`` and ``BOLD`` ... + def get_valid_inputs(self) -> list[str]: return ["T1w", "T2w", "BOLD"] + ... The output definition of the Preprocessor is unused now but is kept for @@ -55,9 +57,11 @@ completeness. ... + def get_output_type(self, input_type: str) -> str: return input_type + ... .. _extending_preprocessors_init: @@ -90,6 +94,7 @@ you configure it. Our class will have the following arguments: ... + def __init__( self, fwhm: int | float | ArrayLike | Literal["fast"] | None, @@ -98,6 +103,7 @@ you configure it. Our class will have the following arguments: self.fwhm = fwhm super().__init__(on=on) + ... .. caution:: @@ -147,15 +153,18 @@ and it has two return values: ... + def preprocess( self, input: dict[str, Any], extra_input: dict[str, Any] | None = None, ) -> tuple[dict[str, Any], dict[str, Any] | None]: - input["data"] = nimg.smooth_img(imgs=input["data"], fwhm=self.fwhm) - return input, None + input["data"] = nimg.smooth_img(imgs=input["data"], fwhm=self.fwhm) + return input, None + + + ... - ... Step 4: Finalise the Preprocessor --------------------------------- diff --git a/docs/understanding/data.rst b/docs/understanding/data.rst index 294eb4cb8..631e43529 100644 --- a/docs/understanding/data.rst +++ b/docs/understanding/data.rst @@ -12,7 +12,7 @@ This is the *object* that traverses the steps of the pipeline. It is indeed a dictionary of dictionaries. The first level of keys are the :ref:`data types ` and the values are the corresponding information as dictionaries. -.. code-block:: python +.. code-block:: {'BOLD': {...}, 'T1w': {...}} @@ -24,7 +24,7 @@ The :ref:`Data Grabber ` step adds the ``path`` second-level key which gives the path to the file containing the data. The ``meta`` key in this step only contains information about the DataGrabber used. -.. code-block:: python +.. code-block:: {'BOLD': {'meta': {'datagrabber': {'class': 'SPMAuditoryTestingDataGrabber', 'types': ['BOLD', 'T1w']}, @@ -41,7 +41,7 @@ The :ref:`Data Reader ` step adds the ``data`` second-level key which is the actual data loaded into memory. The ``meta`` key in this step adds information about the DataReader used to read the data. -.. code-block:: python +.. code-block:: {'BOLD': {'data': , 'meta': {'datagrabber': {'class': 'SPMAuditoryTestingDataGrabber', @@ -58,6 +58,7 @@ adds information about the DataReader used to read the data. 'element': {'subject': 'sub001'}}, 'path': PosixPath('/var/folders/dv/2lbr8f8j0q12zrx3mz3ll5m40000gp/T/tmpe49321ce/sub001_T1w.nii.gz')}} + The :ref:`Preprocess ` step, if used, modifies the ``data`` second-level key's value and appends the ``meta`` key with information about the preprocessor. @@ -66,7 +67,7 @@ The :ref:`Marker ` step removes the ``path`` second-level key, replaces the ``data`` second-level key's value with the marker's computed value and adds further keys needed for the storage, for example, ``col_names``. -.. code-block:: python +.. code-block:: {'BOLD': {'col_names': ['root_sum_of_squares_ets'], 'data': ..., diff --git a/docs/understanding/preprocess.rst b/docs/understanding/preprocess.rst index 37b4c3a8a..c5701aa18 100644 --- a/docs/understanding/preprocess.rst +++ b/docs/understanding/preprocess.rst @@ -69,7 +69,7 @@ Example in python format: strategy = { "motion": "basic", "wm_csf": "full", - "global_signal": "derivatives" + "global_signal": "derivatives", } or in YAML format: @@ -85,11 +85,7 @@ The default value is to use all the *noise components* with the ``full`` *confou .. code-block:: python - strategy = { - "motion": "full", - "wm_csf": "full", - "global_signal": "full" - } + strategy = {"motion": "full", "wm_csf": "full", "global_signal": "full"} Other Parameters ~~~~~~~~~~~~~~~~ diff --git a/junifer/__init__.py b/junifer/__init__.py index 500fde796..177cf7567 100644 --- a/junifer/__init__.py +++ b/junifer/__init__.py @@ -20,3 +20,20 @@ from . import ( onthefly, ) from ._version import __version__ + + +__all__ = [ + "api", + "configs", + "data", + "datagrabber", + "datareader", + "markers", + "pipeline", + "preprocess", + "stats", + "storage", + "utils", + "external", + "onthefly", +] diff --git a/junifer/api/__init__.py b/junifer/api/__init__.py index 7031d20a6..7ef7bb075 100644 --- a/junifer/api/__init__.py +++ b/junifer/api/__init__.py @@ -7,3 +7,6 @@ from . import decorators from .cli import cli from .functions import collect, queue, run + + +__all__ = ["decorators", "cli", "collect", "queue", "run"] diff --git a/junifer/api/decorators.py b/junifer/api/decorators.py index 627c3a720..11cbd2f80 100644 --- a/junifer/api/decorators.py +++ b/junifer/api/decorators.py @@ -10,6 +10,15 @@ from typing import Type from ..pipeline.registry import register +__all__ = [ + "register_datagrabber", + "register_datareader", + "register_preprocessor", + "register_marker", + "register_storage", +] + + def register_datagrabber(klass: Type) -> Type: """Register DataGrabber. diff --git a/junifer/api/functions.py b/junifer/api/functions.py index 5ae749056..2d16815b0 100644 --- a/junifer/api/functions.py +++ b/junifer/api/functions.py @@ -23,6 +23,9 @@ from .queue_context import GnuParallelLocalAdapter, HTCondorAdapter from .utils import yaml +__all__ = ["run", "collect", "queue", "reset", "list_elements"] + + def _get_datagrabber(datagrabber_config: Dict) -> BaseDataGrabber: """Get DataGrabber. @@ -92,7 +95,7 @@ def run( datagrabber : dict DataGrabber to use. Must have a key ``kind`` with the kind of DataGrabber to use. All other keys are passed to the DataGrabber - init function. + constructor. markers : list of dict List of markers to extract. Each marker is a dict with at least two keys: ``name`` and ``kind``. The ``name`` key is used to name the @@ -102,11 +105,11 @@ def run( storage : dict Storage to use. Must have a key ``kind`` with the kind of storage to use. All other keys are passed to the storage - init function. + constructor. preprocessors : list of dict, optional List of preprocessors to use. Each preprocessor is a dict with at least a key ``kind`` specifying the preprocessor to use. All other keys - are passed to the preprocessor init function (default None). + are passed to the preprocessor constructor (default None). elements : str or tuple or list of str or tuple, optional Element(s) to process. Will be used to index the DataGrabber (default None). @@ -188,7 +191,7 @@ def collect(storage: Dict) -> None: storage : dict Storage to use. Must have a key ``kind`` with the kind of storage to use. All other keys are passed to the storage - init function. + constructor. """ storage_params = storage.copy() diff --git a/junifer/api/parser.py b/junifer/api/parser.py index 535520995..93bc94527 100644 --- a/junifer/api/parser.py +++ b/junifer/api/parser.py @@ -14,6 +14,9 @@ from ..utils.logging import logger, raise_error from .utils import yaml +__all__ = ["parse_yaml"] + + def parse_yaml(filepath: Union[str, Path]) -> Dict: """Parse YAML. diff --git a/junifer/api/queue_context/__init__.py b/junifer/api/queue_context/__init__.py index ca4ea2074..59bee28f7 100644 --- a/junifer/api/queue_context/__init__.py +++ b/junifer/api/queue_context/__init__.py @@ -6,3 +6,6 @@ from .queue_context_adapter import QueueContextAdapter from .htcondor_adapter import HTCondorAdapter from .gnu_parallel_local_adapter import GnuParallelLocalAdapter + + +__all__ = ["QueueContextAdapter", "HTCondorAdapter", "GnuParallelLocalAdapter"] diff --git a/junifer/api/res/afni/run_afni_docker.sh b/junifer/api/res/afni/run_afni_docker.sh index 014d50218..034c7bad7 100755 --- a/junifer/api/res/afni/run_afni_docker.sh +++ b/junifer/api/res/afni/run_afni_docker.sh @@ -31,7 +31,7 @@ if [ -d "${var}" ]; then done echo "Docker args: ${docker_args[*]}" >&2 -echo "Corrected args for afni: ${corrected_args[*]}" >&2 +echo "Corrected args for AFNI: ${corrected_args[*]}" >&2 cwd=$(pwd) cmd="docker run --rm ${docker_args[*]} -v ${cwd}:${cwd} -w ${cwd} afni/afni_make_build ${corrected_args[*]}" diff --git a/junifer/api/res/ants/run_ants_docker.sh b/junifer/api/res/ants/run_ants_docker.sh index b24560d38..237d08ab1 100755 --- a/junifer/api/res/ants/run_ants_docker.sh +++ b/junifer/api/res/ants/run_ants_docker.sh @@ -31,7 +31,7 @@ if [ -d "${var}" ]; then done echo "Docker args: ${docker_args[*]}" >&2 -echo "Corrected args for fsl: ${corrected_args[*]}" >&2 +echo "Corrected args for ANTs: ${corrected_args[*]}" >&2 cwd=$(pwd) cmd="docker run --rm ${docker_args[*]} -v ${cwd}:${cwd} -w ${cwd} antsx/ants ${corrected_args[*]}" diff --git a/junifer/api/res/fsl/run_fsl_docker.sh b/junifer/api/res/fsl/run_fsl_docker.sh index 1d935e4c8..e76d41f36 100755 --- a/junifer/api/res/fsl/run_fsl_docker.sh +++ b/junifer/api/res/fsl/run_fsl_docker.sh @@ -31,7 +31,7 @@ if [ -d "${var}" ]; then done echo "Docker args: ${docker_args[*]}" >&2 -echo "Corrected args for fsl: ${corrected_args[*]}" >&2 +echo "Corrected args for FSL: ${corrected_args[*]}" >&2 cwd=$(pwd) cmd="docker run --rm ${docker_args[*]} -v ${cwd}:${cwd} -w ${cwd} brainlife/fsl ${corrected_args[*]}" diff --git a/junifer/configs/juseless/__init__.py b/junifer/configs/juseless/__init__.py index db7014b83..c6d999243 100644 --- a/junifer/configs/juseless/__init__.py +++ b/junifer/configs/juseless/__init__.py @@ -4,3 +4,6 @@ # License: AGPL from . import datagrabbers + + +__all__ = ["datagrabbers"] diff --git a/junifer/configs/juseless/datagrabbers/__init__.py b/junifer/configs/juseless/datagrabbers/__init__.py index edd5eb9d6..8bb09991a 100644 --- a/junifer/configs/juseless/datagrabbers/__init__.py +++ b/junifer/configs/juseless/datagrabbers/__init__.py @@ -10,3 +10,12 @@ from .camcan_vbm import JuselessDataladCamCANVBM from .ixi_vbm import JuselessDataladIXIVBM from .ucla import JuselessUCLA from .ukb_vbm import JuselessDataladUKBVBM + + +__all__ = [ + "JuselessDataladAOMICID1000VBM", + "JuselessDataladCamCANVBM", + "JuselessDataladIXIVBM", + "JuselessUCLA", + "JuselessDataladUKBVBM", +] diff --git a/junifer/configs/juseless/datagrabbers/aomic_id1000_vbm.py b/junifer/configs/juseless/datagrabbers/aomic_id1000_vbm.py index d62064e72..3bf1ad098 100644 --- a/junifer/configs/juseless/datagrabbers/aomic_id1000_vbm.py +++ b/junifer/configs/juseless/datagrabbers/aomic_id1000_vbm.py @@ -11,6 +11,9 @@ from ....api.decorators import register_datagrabber from ....datagrabber import PatternDataladDataGrabber +__all__ = ["JuselessDataladAOMICID1000VBM"] + + @register_datagrabber class JuselessDataladAOMICID1000VBM(PatternDataladDataGrabber): """Concrete implementation for Juseless AOMIC ID1000 VBM data fetching. diff --git a/junifer/configs/juseless/datagrabbers/camcan_vbm.py b/junifer/configs/juseless/datagrabbers/camcan_vbm.py index 101cf02e0..782574b38 100644 --- a/junifer/configs/juseless/datagrabbers/camcan_vbm.py +++ b/junifer/configs/juseless/datagrabbers/camcan_vbm.py @@ -12,6 +12,9 @@ from ....api.decorators import register_datagrabber from ....datagrabber import PatternDataladDataGrabber +__all__ = ["JuselessDataladCamCANVBM"] + + @register_datagrabber class JuselessDataladCamCANVBM(PatternDataladDataGrabber): """Concrete implementation for Juseless CamCAN VBM data fetching. diff --git a/junifer/configs/juseless/datagrabbers/ixi_vbm.py b/junifer/configs/juseless/datagrabbers/ixi_vbm.py index 1c4bcf7f0..f131ca4ac 100644 --- a/junifer/configs/juseless/datagrabbers/ixi_vbm.py +++ b/junifer/configs/juseless/datagrabbers/ixi_vbm.py @@ -13,6 +13,9 @@ from ....datagrabber import PatternDataladDataGrabber from ....utils import raise_error +__all__ = ["JuselessDataladIXIVBM"] + + @register_datagrabber class JuselessDataladIXIVBM(PatternDataladDataGrabber): """Concrete implementation for Juseless IXI VBM data fetching. diff --git a/junifer/configs/juseless/datagrabbers/ucla.py b/junifer/configs/juseless/datagrabbers/ucla.py index c81db95da..647a79f75 100644 --- a/junifer/configs/juseless/datagrabbers/ucla.py +++ b/junifer/configs/juseless/datagrabbers/ucla.py @@ -12,6 +12,9 @@ from ....datagrabber import PatternDataGrabber from ....utils import raise_error +__all__ = ["JuselessUCLA"] + + @register_datagrabber class JuselessUCLA(PatternDataGrabber): """Concrete implementation for Juseless UCLA data fetching. diff --git a/junifer/configs/juseless/datagrabbers/ukb_vbm.py b/junifer/configs/juseless/datagrabbers/ukb_vbm.py index 981a17583..cea8ac655 100644 --- a/junifer/configs/juseless/datagrabbers/ukb_vbm.py +++ b/junifer/configs/juseless/datagrabbers/ukb_vbm.py @@ -12,6 +12,9 @@ from ....api.decorators import register_datagrabber from ....datagrabber import PatternDataladDataGrabber +__all__ = ["JuselessDataladUKBVBM"] + + @register_datagrabber class JuselessDataladUKBVBM(PatternDataladDataGrabber): """Concrete implementation for Juseless UKB VBM data fetching. diff --git a/junifer/data/__init__.py b/junifer/data/__init__.py index 8e69bf592..56e4d6d57 100644 --- a/junifer/data/__init__.py +++ b/junifer/data/__init__.py @@ -28,3 +28,23 @@ from .masks import ( from .template_spaces import get_template, get_xfm from . import utils + + +__all__ = [ + "list_coordinates", + "load_coordinates", + "register_coordinates", + "get_coordinates", + "list_parcellations", + "load_parcellation", + "register_parcellation", + "merge_parcellations", + "get_parcellation", + "list_masks", + "load_mask", + "register_mask", + "get_mask", + "get_template", + "get_xfm", + "utils", +] diff --git a/junifer/data/coordinates.py b/junifer/data/coordinates.py index 2cefb1ab7..f9ff7c5c9 100644 --- a/junifer/data/coordinates.py +++ b/junifer/data/coordinates.py @@ -16,6 +16,14 @@ from ..pipeline import WorkDirManager from ..utils import logger, raise_error, run_ext_cmd +__all__ = [ + "register_coordinates", + "list_coordinates", + "get_coordinates", + "load_coordinates", +] + + # Path to the VOIs _vois_path = Path(__file__).parent / "VOIs" diff --git a/junifer/data/masks.py b/junifer/data/masks.py index eec5dbaeb..f7b1f503d 100644 --- a/junifer/data/masks.py +++ b/junifer/data/masks.py @@ -35,6 +35,16 @@ from .utils import closest_resolution if TYPE_CHECKING: from nibabel import Nifti1Image + +__all__ = [ + "compute_brain_mask", + "register_mask", + "list_masks", + "get_mask", + "load_mask", +] + + # Path to the masks _masks_path = Path(__file__).parent / "masks" diff --git a/junifer/data/parcellations.py b/junifer/data/parcellations.py index cfd242659..0fc3d651d 100644 --- a/junifer/data/parcellations.py +++ b/junifer/data/parcellations.py @@ -30,6 +30,15 @@ if TYPE_CHECKING: from nibabel import Nifti1Image +__all__ = [ + "register_parcellation", + "list_parcellations", + "get_parcellation", + "load_parcellation", + "merge_parcellations", +] + + # A dictionary containing all supported parcellations and their respective # valid parameters. diff --git a/junifer/data/template_spaces.py b/junifer/data/template_spaces.py index 409d6550e..524eb92f5 100644 --- a/junifer/data/template_spaces.py +++ b/junifer/data/template_spaces.py @@ -15,6 +15,9 @@ from ..utils import logger, raise_error from .utils import closest_resolution +__all__ = ["get_xfm", "get_template"] + + def get_xfm( src: str, dst: str, xfms_dir: Union[str, Path, None] = None ) -> Path: # pragma: no cover diff --git a/junifer/data/utils.py b/junifer/data/utils.py index 291425c18..3e0702017 100644 --- a/junifer/data/utils.py +++ b/junifer/data/utils.py @@ -7,6 +7,9 @@ import numpy as np from ..utils.logging import logger +__all__ = ["closest_resolution"] + + def closest_resolution( resolution: Optional[Union[float, int]], valid_resolution: Union[List[float], List[int], np.ndarray], diff --git a/junifer/datagrabber/__init__.py b/junifer/datagrabber/__init__.py index be95a85f9..fb5e276ab 100644 --- a/junifer/datagrabber/__init__.py +++ b/junifer/datagrabber/__init__.py @@ -16,3 +16,18 @@ from .aomic import DataladAOMICID1000, DataladAOMICPIOP1, DataladAOMICPIOP2 from .hcp1200 import HCP1200, DataladHCP1200 from .multiple import MultipleDataGrabber from .dmcc13_benchmark import DMCC13Benchmark + + +__all__ = [ + "BaseDataGrabber", + "DataladDataGrabber", + "PatternDataGrabber", + "PatternDataladDataGrabber", + "DataladAOMICID1000", + "DataladAOMICPIOP1", + "DataladAOMICPIOP2", + "HCP1200", + "DataladHCP1200", + "MultipleDataGrabber", + "DMCC13Benchmark", +] diff --git a/junifer/datagrabber/aomic/__init__.py b/junifer/datagrabber/aomic/__init__.py index c73da27e3..cb6c58b9b 100644 --- a/junifer/datagrabber/aomic/__init__.py +++ b/junifer/datagrabber/aomic/__init__.py @@ -7,3 +7,6 @@ from .id1000 import DataladAOMICID1000 from .piop1 import DataladAOMICPIOP1 from .piop2 import DataladAOMICPIOP2 + + +__all__ = ["DataladAOMICID1000", "DataladAOMICPIOP1", "DataladAOMICPIOP2"] diff --git a/junifer/datagrabber/aomic/id1000.py b/junifer/datagrabber/aomic/id1000.py index 5c1156c5d..7d0586255 100644 --- a/junifer/datagrabber/aomic/id1000.py +++ b/junifer/datagrabber/aomic/id1000.py @@ -14,6 +14,9 @@ from ...api.decorators import register_datagrabber from ..pattern_datalad import PatternDataladDataGrabber +__all__ = ["DataladAOMICID1000"] + + @register_datagrabber class DataladAOMICID1000(PatternDataladDataGrabber): """Concrete implementation for datalad-based data fetching of AOMIC ID1000. diff --git a/junifer/datagrabber/aomic/piop1.py b/junifer/datagrabber/aomic/piop1.py index 509a0c532..d2763bb18 100644 --- a/junifer/datagrabber/aomic/piop1.py +++ b/junifer/datagrabber/aomic/piop1.py @@ -16,6 +16,9 @@ from ...utils import raise_error from ..pattern_datalad import PatternDataladDataGrabber +__all__ = ["DataladAOMICPIOP1"] + + @register_datagrabber class DataladAOMICPIOP1(PatternDataladDataGrabber): """Concrete implementation for pattern-based data fetching of AOMIC PIOP1. diff --git a/junifer/datagrabber/aomic/piop2.py b/junifer/datagrabber/aomic/piop2.py index cf6320f42..db55e3d4f 100644 --- a/junifer/datagrabber/aomic/piop2.py +++ b/junifer/datagrabber/aomic/piop2.py @@ -16,6 +16,9 @@ from ...utils import raise_error from ..pattern_datalad import PatternDataladDataGrabber +__all__ = ["DataladAOMICPIOP2"] + + @register_datagrabber class DataladAOMICPIOP2(PatternDataladDataGrabber): """Concrete implementation for pattern-based data fetching of AOMIC PIOP2. diff --git a/junifer/datagrabber/base.py b/junifer/datagrabber/base.py index 3b575bf0f..e9b4dfbc8 100644 --- a/junifer/datagrabber/base.py +++ b/junifer/datagrabber/base.py @@ -14,6 +14,9 @@ from ..utils import logger, raise_error from .utils import validate_types +__all__ = ["BaseDataGrabber"] + + class BaseDataGrabber(ABC, UpdateMetaMixin): """Abstract base class for DataGrabber. diff --git a/junifer/datagrabber/datalad_base.py b/junifer/datagrabber/datalad_base.py index 3680ec8ea..95b9c4749 100644 --- a/junifer/datagrabber/datalad_base.py +++ b/junifer/datagrabber/datalad_base.py @@ -21,6 +21,9 @@ from ..utils import logger, raise_error, warn_with_log from .base import BaseDataGrabber +__all__ = ["DataladDataGrabber"] + + class DataladDataGrabber(BaseDataGrabber): """Abstract base class for datalad-based data fetching. diff --git a/junifer/datagrabber/hcp1200/__init__.py b/junifer/datagrabber/hcp1200/__init__.py index 69a07090d..6a3c9a429 100644 --- a/junifer/datagrabber/hcp1200/__init__.py +++ b/junifer/datagrabber/hcp1200/__init__.py @@ -5,3 +5,6 @@ from .hcp1200 import HCP1200 from .datalad_hcp1200 import DataladHCP1200 + + +__all__ = ["HCP1200", "DataladHCP1200"] diff --git a/junifer/datagrabber/hcp1200/datalad_hcp1200.py b/junifer/datagrabber/hcp1200/datalad_hcp1200.py index 83193d38a..21e847fe8 100644 --- a/junifer/datagrabber/hcp1200/datalad_hcp1200.py +++ b/junifer/datagrabber/hcp1200/datalad_hcp1200.py @@ -14,6 +14,9 @@ from ...api.decorators import register_datagrabber from .hcp1200 import HCP1200 +__all__ = ["DataladHCP1200"] + + @register_datagrabber class DataladHCP1200(DataladDataGrabber, HCP1200): """Concrete implementation for datalad-based data fetching of HCP1200. diff --git a/junifer/datagrabber/hcp1200/hcp1200.py b/junifer/datagrabber/hcp1200/hcp1200.py index cdfb162ef..bee9405ce 100644 --- a/junifer/datagrabber/hcp1200/hcp1200.py +++ b/junifer/datagrabber/hcp1200/hcp1200.py @@ -14,6 +14,9 @@ from ..pattern import PatternDataGrabber from ..utils import raise_error +__all__ = ["HCP1200"] + + @register_datagrabber class HCP1200(PatternDataGrabber): """Concrete implementation for pattern-based data fetching of HCP1200. diff --git a/junifer/datagrabber/multiple.py b/junifer/datagrabber/multiple.py index a923ebb95..fef8f0da1 100644 --- a/junifer/datagrabber/multiple.py +++ b/junifer/datagrabber/multiple.py @@ -11,6 +11,9 @@ from ..utils import raise_error from .base import BaseDataGrabber +__all__ = ["MultipleDataGrabber"] + + class MultipleDataGrabber(BaseDataGrabber): """Concrete implementation for multi sourced data fetching. diff --git a/junifer/datagrabber/pattern.py b/junifer/datagrabber/pattern.py index ef46ecdb3..3947a3953 100644 --- a/junifer/datagrabber/pattern.py +++ b/junifer/datagrabber/pattern.py @@ -18,6 +18,9 @@ from .base import BaseDataGrabber from .utils import validate_patterns, validate_replacements +__all__ = ["PatternDataGrabber"] + + # Accepted formats for confounds specification _CONFOUNDS_FORMATS = ("fmriprep", "adhoc") diff --git a/junifer/datagrabber/pattern_datalad.py b/junifer/datagrabber/pattern_datalad.py index a8c4eeaa5..ccf47fe52 100644 --- a/junifer/datagrabber/pattern_datalad.py +++ b/junifer/datagrabber/pattern_datalad.py @@ -12,6 +12,9 @@ from .datalad_base import DataladDataGrabber from .pattern import PatternDataGrabber +__all__ = ["PatternDataladDataGrabber"] + + @register_datagrabber class PatternDataladDataGrabber(DataladDataGrabber, PatternDataGrabber): """Concrete implementation for pattern and datalad based data fetching. diff --git a/junifer/datagrabber/utils.py b/junifer/datagrabber/utils.py index 3004ac451..5caec4e85 100644 --- a/junifer/datagrabber/utils.py +++ b/junifer/datagrabber/utils.py @@ -9,6 +9,9 @@ from typing import Dict, List from ..utils import logger, raise_error +__all__ = ["validate_types", "validate_replacements", "validate_patterns"] + + # Define schema for pattern-based datagrabber's patterns PATTERNS_SCHEMA = { "T1w": { diff --git a/junifer/datareader/__init__.py b/junifer/datareader/__init__.py index 5ad1c5c32..d3b6a820d 100644 --- a/junifer/datareader/__init__.py +++ b/junifer/datareader/__init__.py @@ -6,3 +6,6 @@ # License: AGPL from .default import DefaultDataReader + + +__all__ = ["DefaultDataReader"] diff --git a/junifer/datareader/default.py b/junifer/datareader/default.py index 2770c833d..3246a18d4 100644 --- a/junifer/datareader/default.py +++ b/junifer/datareader/default.py @@ -15,6 +15,9 @@ from ..pipeline import PipelineStepMixin, UpdateMetaMixin from ..utils.logging import logger, warn_with_log +__all__ = ["DefaultDataReader"] + + # Map each file extension to a type _extensions = { ".nii": "NIFTI", diff --git a/junifer/markers/__init__.py b/junifer/markers/__init__.py index a829a28c6..ccbff328e 100644 --- a/junifer/markers/__init__.py +++ b/junifer/markers/__init__.py @@ -24,3 +24,24 @@ from .temporal_snr import ( TemporalSNRSpheres, ) from .brainprint import BrainPrint + + +__all__ = [ + "BaseMarker", + "MarkerCollection", + "RSSETSMarker", + "ParcelAggregation", + "SphereAggregation", + "FunctionalConnectivityParcels", + "FunctionalConnectivitySpheres", + "CrossParcellationFC", + "EdgeCentricFCParcels", + "EdgeCentricFCSpheres", + "ReHoParcels", + "ReHoSpheres", + "ALFFParcels", + "ALFFSpheres", + "TemporalSNRParcels", + "TemporalSNRSpheres", + "BrainPrint", +] diff --git a/junifer/markers/base.py b/junifer/markers/base.py index 5ec0b3e35..96098d7e0 100644 --- a/junifer/markers/base.py +++ b/junifer/markers/base.py @@ -15,16 +15,22 @@ if TYPE_CHECKING: from junifer.storage import BaseFeatureStorage +__all__ = ["BaseMarker"] + + class BaseMarker(ABC, PipelineStepMixin, UpdateMetaMixin): """Abstract base class for all markers. + For every interface that is required, one needs to provide a concrete + implementation of this abstract class. + Parameters ---------- - on : str or list of str - The kind of data to apply the marker to. By default, will work on all - available data. + on : str or list of str or None, optional + The data type to apply the marker on. If None, + will work on all available data types (default None). name : str, optional - The name of the marker. By default, it will use the class name as the + The name of the marker. If None, will use the class name as the name of the marker (default None). Raises @@ -192,17 +198,25 @@ class BaseMarker(ABC, PipelineStepMixin, UpdateMetaMixin): for type_ in self._on: if type_ in input.keys(): logger.info(f"Computing {type_}") + # Get data dict for data type t_input = input[type_] + # Pass the other data types as extra input, removing + # the current type extra_input = input.copy() extra_input.pop(type_) + logger.debug( + f"Extra data type for feature extraction: " + f"{extra_input.keys()}" + ) + # Copy metadata t_meta = t_input["meta"].copy() t_meta["type"] = type_ - + # Compute marker t_out = self.compute(input=t_input, extra_input=extra_input) t_out["meta"] = t_meta - + # Update metadata for step self.update_meta(t_out, "marker") - + # Check storage if storage is not None: logger.info(f"Storing in {storage}") self.store(type_=type_, out=t_out, storage=storage) diff --git a/junifer/markers/brainprint.py b/junifer/markers/brainprint.py index d9e16b0cd..611dde5c3 100644 --- a/junifer/markers/brainprint.py +++ b/junifer/markers/brainprint.py @@ -43,6 +43,9 @@ if TYPE_CHECKING: from junifer.storage import BaseFeatureStorage +__all__ = ["BrainPrint"] + + @register_marker class BrainPrint(BaseMarker): """Class for BrainPrint. diff --git a/junifer/markers/collection.py b/junifer/markers/collection.py index cfdf20a0e..a26c5f207 100644 --- a/junifer/markers/collection.py +++ b/junifer/markers/collection.py @@ -19,6 +19,9 @@ if TYPE_CHECKING: from junifer.datagrabber import BaseDataGrabber +__all__ = ["MarkerCollection"] + + class MarkerCollection: """Class for marker collection. diff --git a/junifer/markers/complexity/__init__.py b/junifer/markers/complexity/__init__.py index 66e620192..090b935f9 100644 --- a/junifer/markers/complexity/__init__.py +++ b/junifer/markers/complexity/__init__.py @@ -25,3 +25,13 @@ else: from .weighted_perm_entropy import WeightedPermEntropy from .sample_entropy import SampleEntropy from .multiscale_entropy_auc import MultiscaleEntropyAUC + + __all__ = [ + "HurstExponent", + "RangeEntropy", + "RangeEntropyAUC", + "PermEntropy", + "WeightedPermEntropy", + "SampleEntropy", + "MultiscaleEntropyAUC", + ] diff --git a/junifer/markers/complexity/complexity_base.py b/junifer/markers/complexity/complexity_base.py index 193cb7940..2b7239c57 100644 --- a/junifer/markers/complexity/complexity_base.py +++ b/junifer/markers/complexity/complexity_base.py @@ -24,6 +24,9 @@ if TYPE_CHECKING: import numpy as np +__all__ = ["ComplexityBase"] + + class ComplexityBase(BaseMarker): """Base class for complexity computation. diff --git a/junifer/markers/complexity/hurst_exponent.py b/junifer/markers/complexity/hurst_exponent.py index eba2632eb..f73e449ba 100644 --- a/junifer/markers/complexity/hurst_exponent.py +++ b/junifer/markers/complexity/hurst_exponent.py @@ -14,6 +14,9 @@ from ...utils import logger, warn_with_log from .complexity_base import ComplexityBase +__all__ = ["HurstExponent"] + + @register_marker class HurstExponent(ComplexityBase): """Class for Hurst exponent of a time series. diff --git a/junifer/markers/complexity/multiscale_entropy_auc.py b/junifer/markers/complexity/multiscale_entropy_auc.py index b6a3c112b..4ae8d6b8f 100644 --- a/junifer/markers/complexity/multiscale_entropy_auc.py +++ b/junifer/markers/complexity/multiscale_entropy_auc.py @@ -14,6 +14,9 @@ from ...utils import logger, warn_with_log from .complexity_base import ComplexityBase +__all__ = ["MultiscaleEntropyAUC"] + + @register_marker class MultiscaleEntropyAUC(ComplexityBase): """Class for AUC of multiscale entropy of a time series. diff --git a/junifer/markers/complexity/perm_entropy.py b/junifer/markers/complexity/perm_entropy.py index 4748e052b..5f4c76e5b 100644 --- a/junifer/markers/complexity/perm_entropy.py +++ b/junifer/markers/complexity/perm_entropy.py @@ -14,6 +14,9 @@ from ...utils import logger, warn_with_log from .complexity_base import ComplexityBase +__all__ = ["PermEntropy"] + + @register_marker class PermEntropy(ComplexityBase): """Class for permutation entropy of a time series. diff --git a/junifer/markers/complexity/range_entropy.py b/junifer/markers/complexity/range_entropy.py index b88031edc..99f6779bb 100644 --- a/junifer/markers/complexity/range_entropy.py +++ b/junifer/markers/complexity/range_entropy.py @@ -14,6 +14,9 @@ from ...utils import logger, warn_with_log from .complexity_base import ComplexityBase +__all__ = ["RangeEntropy"] + + @register_marker class RangeEntropy(ComplexityBase): """Class for range entropy of a time series. diff --git a/junifer/markers/complexity/range_entropy_auc.py b/junifer/markers/complexity/range_entropy_auc.py index 582813332..7b6544e2c 100644 --- a/junifer/markers/complexity/range_entropy_auc.py +++ b/junifer/markers/complexity/range_entropy_auc.py @@ -14,6 +14,9 @@ from ...utils import logger, warn_with_log from .complexity_base import ComplexityBase +__all__ = ["RangeEntropyAUC"] + + @register_marker class RangeEntropyAUC(ComplexityBase): """Class for AUC of range entropy values of a time series over r = 0 to 1. diff --git a/junifer/markers/complexity/sample_entropy.py b/junifer/markers/complexity/sample_entropy.py index 12503e092..954bb96b5 100644 --- a/junifer/markers/complexity/sample_entropy.py +++ b/junifer/markers/complexity/sample_entropy.py @@ -14,6 +14,9 @@ from ...utils import logger, warn_with_log from .complexity_base import ComplexityBase +__all__ = ["SampleEntropy"] + + @register_marker class SampleEntropy(ComplexityBase): """Class for sample entropy of a time series. diff --git a/junifer/markers/complexity/tests/test_hurst_exponent.py b/junifer/markers/complexity/tests/test_hurst_exponent.py index 24ebee564..4de868a1c 100644 --- a/junifer/markers/complexity/tests/test_hurst_exponent.py +++ b/junifer/markers/complexity/tests/test_hurst_exponent.py @@ -14,6 +14,7 @@ pytest.importorskip("neurokit2") from junifer.datareader import DefaultDataReader # noqa: E402 from junifer.markers.complexity import HurstExponent # noqa: E402 +from junifer.pipeline.utils import _check_ants # noqa: E402 from junifer.storage import SQLiteFeatureStorage # noqa: E402 from junifer.testing.datagrabbers import ( # noqa: E402 SPMAuditoryTestingDataGrabber, @@ -24,6 +25,9 @@ from junifer.testing.datagrabbers import ( # noqa: E402 PARCELLATION = "Schaefer100x17" +@pytest.mark.skipif( + _check_ants() is False, reason="requires ANTs to be in PATH" +) def test_compute() -> None: """Test HurstExponent compute().""" with SPMAuditoryTestingDataGrabber() as dg: @@ -45,6 +49,9 @@ def test_get_output_type() -> None: assert marker.get_output_type("BOLD") == "vector" +@pytest.mark.skipif( + _check_ants() is False, reason="requires ANTs to be in PATH" +) def test_store(tmp_path: Path) -> None: """Test HurstExponent store(). diff --git a/junifer/markers/complexity/tests/test_multiscale_entropy_auc.py b/junifer/markers/complexity/tests/test_multiscale_entropy_auc.py index 924202d23..c1ac2d273 100644 --- a/junifer/markers/complexity/tests/test_multiscale_entropy_auc.py +++ b/junifer/markers/complexity/tests/test_multiscale_entropy_auc.py @@ -13,6 +13,7 @@ pytest.importorskip("neurokit2") from junifer.datareader import DefaultDataReader # noqa: E402 from junifer.markers.complexity import MultiscaleEntropyAUC # noqa: E402 +from junifer.pipeline.utils import _check_ants # noqa: E402 from junifer.storage import SQLiteFeatureStorage # noqa: E402 from junifer.testing.datagrabbers import ( # noqa: E402 SPMAuditoryTestingDataGrabber, @@ -23,6 +24,9 @@ from junifer.testing.datagrabbers import ( # noqa: E402 PARCELLATION = "Schaefer100x17" +@pytest.mark.skipif( + _check_ants() is False, reason="requires ANTs to be in PATH" +) def test_compute() -> None: """Test MultiscaleEntropyAUC compute().""" with SPMAuditoryTestingDataGrabber() as dg: @@ -44,6 +48,9 @@ def test_get_output_type() -> None: assert marker.get_output_type("BOLD") == "vector" +@pytest.mark.skipif( + _check_ants() is False, reason="requires ANTs to be in PATH" +) def test_store(tmp_path: Path) -> None: """Test MultiscaleEntropyAUC store(). diff --git a/junifer/markers/complexity/tests/test_perm_entropy.py b/junifer/markers/complexity/tests/test_perm_entropy.py index 7f3826ddf..81731e8c2 100644 --- a/junifer/markers/complexity/tests/test_perm_entropy.py +++ b/junifer/markers/complexity/tests/test_perm_entropy.py @@ -13,6 +13,7 @@ pytest.importorskip("neurokit2") from junifer.datareader import DefaultDataReader # noqa: E402 from junifer.markers.complexity import PermEntropy # noqa: E402 +from junifer.pipeline.utils import _check_ants # noqa: E402 from junifer.storage import SQLiteFeatureStorage # noqa: E402 from junifer.testing.datagrabbers import ( # noqa: E402 SPMAuditoryTestingDataGrabber, @@ -23,6 +24,9 @@ from junifer.testing.datagrabbers import ( # noqa: E402 PARCELLATION = "Schaefer100x17" +@pytest.mark.skipif( + _check_ants() is False, reason="requires ANTs to be in PATH" +) def test_compute() -> None: """Test PermEntropy compute().""" with SPMAuditoryTestingDataGrabber() as dg: @@ -44,6 +48,9 @@ def test_get_output_type() -> None: assert marker.get_output_type("BOLD") == "vector" +@pytest.mark.skipif( + _check_ants() is False, reason="requires ANTs to be in PATH" +) def test_store(tmp_path: Path) -> None: """Test PermEntropy store(). diff --git a/junifer/markers/complexity/tests/test_range_entropy.py b/junifer/markers/complexity/tests/test_range_entropy.py index 86c83fc5c..8691246d0 100644 --- a/junifer/markers/complexity/tests/test_range_entropy.py +++ b/junifer/markers/complexity/tests/test_range_entropy.py @@ -14,6 +14,7 @@ pytest.importorskip("neurokit2") from junifer.datareader import DefaultDataReader # noqa: E402 from junifer.markers.complexity import RangeEntropy # noqa: E402 +from junifer.pipeline.utils import _check_ants # noqa: E402 from junifer.storage import SQLiteFeatureStorage # noqa: E402 from junifer.testing.datagrabbers import ( # noqa: E402 SPMAuditoryTestingDataGrabber, @@ -24,6 +25,9 @@ from junifer.testing.datagrabbers import ( # noqa: E402 PARCELLATION = "Schaefer100x17" +@pytest.mark.skipif( + _check_ants() is False, reason="requires ANTs to be in PATH" +) def test_compute() -> None: """Test RangeEntropy compute().""" with SPMAuditoryTestingDataGrabber() as dg: @@ -45,6 +49,9 @@ def test_get_output_type() -> None: assert marker.get_output_type("BOLD") == "vector" +@pytest.mark.skipif( + _check_ants() is False, reason="requires ANTs to be in PATH" +) def test_store(tmp_path: Path) -> None: """Test RangeEntropy store(). diff --git a/junifer/markers/complexity/tests/test_range_entropy_auc.py b/junifer/markers/complexity/tests/test_range_entropy_auc.py index c8a98f7c6..2ff166ac9 100644 --- a/junifer/markers/complexity/tests/test_range_entropy_auc.py +++ b/junifer/markers/complexity/tests/test_range_entropy_auc.py @@ -14,6 +14,7 @@ pytest.importorskip("neurokit2") from junifer.datareader import DefaultDataReader # noqa: E402 from junifer.markers.complexity import RangeEntropyAUC # noqa: E402 +from junifer.pipeline.utils import _check_ants # noqa: E402 from junifer.storage import SQLiteFeatureStorage # noqa: E402 from junifer.testing.datagrabbers import ( # noqa: E402 SPMAuditoryTestingDataGrabber, @@ -24,6 +25,9 @@ from junifer.testing.datagrabbers import ( # noqa: E402 PARCELLATION = "Schaefer100x17" +@pytest.mark.skipif( + _check_ants() is False, reason="requires ANTs to be in PATH" +) def test_compute() -> None: """Test RangeEntropyAUC compute().""" with SPMAuditoryTestingDataGrabber() as dg: @@ -45,6 +49,9 @@ def test_get_output_type() -> None: assert marker.get_output_type("BOLD") == "vector" +@pytest.mark.skipif( + _check_ants() is False, reason="requires ANTs to be in PATH" +) def test_store(tmp_path: Path) -> None: """Test RangeEntropyAUC store(). diff --git a/junifer/markers/complexity/tests/test_sample_entropy.py b/junifer/markers/complexity/tests/test_sample_entropy.py index cdc39d386..18f4963d1 100644 --- a/junifer/markers/complexity/tests/test_sample_entropy.py +++ b/junifer/markers/complexity/tests/test_sample_entropy.py @@ -13,6 +13,7 @@ pytest.importorskip("neurokit2") from junifer.datareader import DefaultDataReader # noqa: E402 from junifer.markers.complexity import SampleEntropy # noqa: E402 +from junifer.pipeline.utils import _check_ants # noqa: E402 from junifer.storage import SQLiteFeatureStorage # noqa: E402 from junifer.testing.datagrabbers import ( # noqa: E402 SPMAuditoryTestingDataGrabber, @@ -23,6 +24,9 @@ from junifer.testing.datagrabbers import ( # noqa: E402 PARCELLATION = "Schaefer100x17" +@pytest.mark.skipif( + _check_ants() is False, reason="requires ANTs to be in PATH" +) def test_compute() -> None: """Test SampleEntropy compute().""" with SPMAuditoryTestingDataGrabber() as dg: @@ -44,6 +48,9 @@ def test_get_output_type() -> None: assert marker.get_output_type("BOLD") == "vector" +@pytest.mark.skipif( + _check_ants() is False, reason="requires ANTs to be in PATH" +) def test_store(tmp_path: Path) -> None: """Test SampleEntropy store(). diff --git a/junifer/markers/complexity/tests/test_weighted_perm_entropy.py b/junifer/markers/complexity/tests/test_weighted_perm_entropy.py index 188e184bc..ed3e3a6fd 100644 --- a/junifer/markers/complexity/tests/test_weighted_perm_entropy.py +++ b/junifer/markers/complexity/tests/test_weighted_perm_entropy.py @@ -13,6 +13,7 @@ pytest.importorskip("neurokit2") from junifer.datareader import DefaultDataReader # noqa: E402 from junifer.markers.complexity import WeightedPermEntropy # noqa: E402 +from junifer.pipeline.utils import _check_ants # noqa: E402 from junifer.storage import SQLiteFeatureStorage # noqa: E402 from junifer.testing.datagrabbers import ( # noqa: E402 SPMAuditoryTestingDataGrabber, @@ -23,6 +24,9 @@ from junifer.testing.datagrabbers import ( # noqa: E402 PARCELLATION = "Schaefer100x17" +@pytest.mark.skipif( + _check_ants() is False, reason="requires ANTs to be in PATH" +) def test_compute() -> None: """Test WeightedPermEntropy compute().""" with SPMAuditoryTestingDataGrabber() as dg: @@ -44,6 +48,9 @@ def test_get_output_type() -> None: assert marker.get_output_type("BOLD") == "vector" +@pytest.mark.skipif( + _check_ants() is False, reason="requires ANTs to be in PATH" +) def test_store(tmp_path: Path) -> None: """Test WeightedPermEntropy store(). diff --git a/junifer/markers/complexity/weighted_perm_entropy.py b/junifer/markers/complexity/weighted_perm_entropy.py index 374e0c19f..649c7bb36 100644 --- a/junifer/markers/complexity/weighted_perm_entropy.py +++ b/junifer/markers/complexity/weighted_perm_entropy.py @@ -14,6 +14,9 @@ from ...utils import logger, warn_with_log from .complexity_base import ComplexityBase +__all__ = ["WeightedPermEntropy"] + + @register_marker class WeightedPermEntropy(ComplexityBase): """Class for weighted permutation entropy of a time series. diff --git a/junifer/markers/ets_rss.py b/junifer/markers/ets_rss.py index c573a057b..0a00ce924 100644 --- a/junifer/markers/ets_rss.py +++ b/junifer/markers/ets_rss.py @@ -17,6 +17,9 @@ from .parcel_aggregation import ParcelAggregation from .utils import _ets +__all__ = ["RSSETSMarker"] + + @register_marker class RSSETSMarker(BaseMarker): """Class for root sum of squares of edgewise timeseries. diff --git a/junifer/markers/falff/__init__.py b/junifer/markers/falff/__init__.py index c04f42aa9..a0d280921 100644 --- a/junifer/markers/falff/__init__.py +++ b/junifer/markers/falff/__init__.py @@ -5,3 +5,6 @@ from .falff_parcels import ALFFParcels from .falff_spheres import ALFFSpheres + + +__all__ = ["ALFFParcels", "ALFFSpheres"] diff --git a/junifer/markers/falff/_afni_falff.py b/junifer/markers/falff/_afni_falff.py index 81d1ec669..31e59c1d6 100644 --- a/junifer/markers/falff/_afni_falff.py +++ b/junifer/markers/falff/_afni_falff.py @@ -26,6 +26,9 @@ if TYPE_CHECKING: from nibabel import Nifti1Image +__all__ = ["AFNIALFF"] + + @singleton class AFNIALFF: """Class for computing ALFF using AFNI. diff --git a/junifer/markers/falff/_junifer_falff.py b/junifer/markers/falff/_junifer_falff.py index 3dc6fd083..390c45fee 100644 --- a/junifer/markers/falff/_junifer_falff.py +++ b/junifer/markers/falff/_junifer_falff.py @@ -27,6 +27,9 @@ if TYPE_CHECKING: from nibabel import Nifti1Image +__all__ = ["JuniferALFF"] + + @singleton class JuniferALFF: """Class for computing ALFF using junifer. diff --git a/junifer/markers/falff/falff_base.py b/junifer/markers/falff/falff_base.py index 7bdd86c0a..fd5514198 100644 --- a/junifer/markers/falff/falff_base.py +++ b/junifer/markers/falff/falff_base.py @@ -29,6 +29,9 @@ if TYPE_CHECKING: from nibabel import Nifti1Image +__all__ = ["ALFFBase"] + + class ALFFBase(BaseMarker): """Base class for (fractional) Amplitude Low Frequency Fluctuation. diff --git a/junifer/markers/falff/falff_parcels.py b/junifer/markers/falff/falff_parcels.py index 8741a219d..86d39f98f 100644 --- a/junifer/markers/falff/falff_parcels.py +++ b/junifer/markers/falff/falff_parcels.py @@ -14,6 +14,9 @@ from ..parcel_aggregation import ParcelAggregation from .falff_base import ALFFBase +__all__ = ["ALFFParcels"] + + @register_marker class ALFFParcels(ALFFBase): """Class for ALFF / fALFF on parcels. diff --git a/junifer/markers/falff/falff_spheres.py b/junifer/markers/falff/falff_spheres.py index d60d3c2a2..6d40842d6 100644 --- a/junifer/markers/falff/falff_spheres.py +++ b/junifer/markers/falff/falff_spheres.py @@ -14,6 +14,9 @@ from ..sphere_aggregation import SphereAggregation from .falff_base import ALFFBase +__all__ = ["ALFFSpheres"] + + @register_marker class ALFFSpheres(ALFFBase): """Class for computing ALFF / fALFF on spheres. diff --git a/junifer/markers/functional_connectivity/__init__.py b/junifer/markers/functional_connectivity/__init__.py index e1eb9fab5..b3833fd37 100644 --- a/junifer/markers/functional_connectivity/__init__.py +++ b/junifer/markers/functional_connectivity/__init__.py @@ -8,3 +8,12 @@ from .functional_connectivity_spheres import FunctionalConnectivitySpheres from .crossparcellation_functional_connectivity import CrossParcellationFC from .edge_functional_connectivity_parcels import EdgeCentricFCParcels from .edge_functional_connectivity_spheres import EdgeCentricFCSpheres + + +__all__ = [ + "FunctionalConnectivityParcels", + "FunctionalConnectivitySpheres", + "CrossParcellationFC", + "EdgeCentricFCParcels", + "EdgeCentricFCSpheres", +] diff --git a/junifer/markers/functional_connectivity/crossparcellation_functional_connectivity.py b/junifer/markers/functional_connectivity/crossparcellation_functional_connectivity.py index c56319180..29a3ec1ca 100644 --- a/junifer/markers/functional_connectivity/crossparcellation_functional_connectivity.py +++ b/junifer/markers/functional_connectivity/crossparcellation_functional_connectivity.py @@ -15,6 +15,9 @@ from ..parcel_aggregation import ParcelAggregation from ..utils import _correlate_dataframes +__all__ = ["CrossParcellationFC"] + + @register_marker class CrossParcellationFC(BaseMarker): """Class for calculating parcel-wise correlations with 2 parcellations. diff --git a/junifer/markers/functional_connectivity/edge_functional_connectivity_parcels.py b/junifer/markers/functional_connectivity/edge_functional_connectivity_parcels.py index ba3ea9070..0203a7a4b 100644 --- a/junifer/markers/functional_connectivity/edge_functional_connectivity_parcels.py +++ b/junifer/markers/functional_connectivity/edge_functional_connectivity_parcels.py @@ -12,6 +12,9 @@ from ..utils import _ets from .functional_connectivity_base import FunctionalConnectivityBase +__all__ = ["EdgeCentricFCParcels"] + + @register_marker class EdgeCentricFCParcels(FunctionalConnectivityBase): """Class for edge-centric FC using parcellations. diff --git a/junifer/markers/functional_connectivity/edge_functional_connectivity_spheres.py b/junifer/markers/functional_connectivity/edge_functional_connectivity_spheres.py index 60554752d..c01345a0f 100644 --- a/junifer/markers/functional_connectivity/edge_functional_connectivity_spheres.py +++ b/junifer/markers/functional_connectivity/edge_functional_connectivity_spheres.py @@ -12,6 +12,9 @@ from ..utils import _ets, raise_error from .functional_connectivity_base import FunctionalConnectivityBase +__all__ = ["EdgeCentricFCSpheres"] + + @register_marker class EdgeCentricFCSpheres(FunctionalConnectivityBase): """Class for edge-centric FC using coordinates (spheres). diff --git a/junifer/markers/functional_connectivity/functional_connectivity_base.py b/junifer/markers/functional_connectivity/functional_connectivity_base.py index 743adc976..0f70f34c6 100644 --- a/junifer/markers/functional_connectivity/functional_connectivity_base.py +++ b/junifer/markers/functional_connectivity/functional_connectivity_base.py @@ -14,6 +14,9 @@ from ...utils import raise_error from ..base import BaseMarker +__all__ = ["FunctionalConnectivityBase"] + + class FunctionalConnectivityBase(BaseMarker): """Abstract base class for functional connectivity markers. diff --git a/junifer/markers/functional_connectivity/functional_connectivity_parcels.py b/junifer/markers/functional_connectivity/functional_connectivity_parcels.py index 935af35da..17d8bd886 100644 --- a/junifer/markers/functional_connectivity/functional_connectivity_parcels.py +++ b/junifer/markers/functional_connectivity/functional_connectivity_parcels.py @@ -12,6 +12,9 @@ from ..parcel_aggregation import ParcelAggregation from .functional_connectivity_base import FunctionalConnectivityBase +__all__ = ["FunctionalConnectivityParcels"] + + @register_marker class FunctionalConnectivityParcels(FunctionalConnectivityBase): """Class for functional connectivity using parcellations. diff --git a/junifer/markers/functional_connectivity/functional_connectivity_spheres.py b/junifer/markers/functional_connectivity/functional_connectivity_spheres.py index 8ad915926..43b483f26 100644 --- a/junifer/markers/functional_connectivity/functional_connectivity_spheres.py +++ b/junifer/markers/functional_connectivity/functional_connectivity_spheres.py @@ -13,6 +13,9 @@ from ..utils import raise_error from .functional_connectivity_base import FunctionalConnectivityBase +__all__ = ["FunctionalConnectivitySpheres"] + + @register_marker class FunctionalConnectivitySpheres(FunctionalConnectivityBase): """Class for functional connectivity using coordinates (spheres). diff --git a/junifer/markers/parcel_aggregation.py b/junifer/markers/parcel_aggregation.py index 934a76bf5..f04b25bac 100644 --- a/junifer/markers/parcel_aggregation.py +++ b/junifer/markers/parcel_aggregation.py @@ -17,6 +17,9 @@ from ..utils import logger, raise_error, warn_with_log from .base import BaseMarker +__all__ = ["ParcelAggregation"] + + @register_marker class ParcelAggregation(BaseMarker): """Class for parcel aggregation. diff --git a/junifer/markers/reho/__init__.py b/junifer/markers/reho/__init__.py index e2fb886d0..99bf6e949 100644 --- a/junifer/markers/reho/__init__.py +++ b/junifer/markers/reho/__init__.py @@ -5,3 +5,6 @@ from .reho_parcels import ReHoParcels from .reho_spheres import ReHoSpheres + + +__all__ = ["ReHoParcels", "ReHoSpheres"] diff --git a/junifer/markers/reho/_afni_reho.py b/junifer/markers/reho/_afni_reho.py index c027726e4..c1eb8d88e 100644 --- a/junifer/markers/reho/_afni_reho.py +++ b/junifer/markers/reho/_afni_reho.py @@ -26,6 +26,9 @@ if TYPE_CHECKING: from nibabel import Nifti1Image +__all__ = ["AFNIReHo"] + + @singleton class AFNIReHo: """Class for computing ReHo using AFNI. diff --git a/junifer/markers/reho/_junifer_reho.py b/junifer/markers/reho/_junifer_reho.py index 47191fa64..173eb16d6 100644 --- a/junifer/markers/reho/_junifer_reho.py +++ b/junifer/markers/reho/_junifer_reho.py @@ -28,6 +28,9 @@ if TYPE_CHECKING: from nibabel import Nifti1Image +__all__ = ["JuniferReHo"] + + @singleton class JuniferReHo: """Class for computing ReHo using junifer. diff --git a/junifer/markers/reho/reho_base.py b/junifer/markers/reho/reho_base.py index 1603754d3..56c7b691f 100644 --- a/junifer/markers/reho/reho_base.py +++ b/junifer/markers/reho/reho_base.py @@ -26,6 +26,8 @@ from ._junifer_reho import JuniferReHo if TYPE_CHECKING: from nibabel import Nifti1Image +__all__ = ["ReHoBase"] + class ReHoBase(BaseMarker): """Base class for regional homogeneity computation. diff --git a/junifer/markers/reho/reho_parcels.py b/junifer/markers/reho/reho_parcels.py index e8e6327a2..806ed65bc 100644 --- a/junifer/markers/reho/reho_parcels.py +++ b/junifer/markers/reho/reho_parcels.py @@ -14,6 +14,9 @@ from ..parcel_aggregation import ParcelAggregation from .reho_base import ReHoBase +__all__ = ["ReHoParcels"] + + @register_marker class ReHoParcels(ReHoBase): """Class for regional homogeneity on parcels. diff --git a/junifer/markers/reho/reho_spheres.py b/junifer/markers/reho/reho_spheres.py index 869c4658a..88d38dcbd 100644 --- a/junifer/markers/reho/reho_spheres.py +++ b/junifer/markers/reho/reho_spheres.py @@ -14,6 +14,9 @@ from ..sphere_aggregation import SphereAggregation from .reho_base import ReHoBase +__all__ = ["ReHoSpheres"] + + @register_marker class ReHoSpheres(ReHoBase): """Class for regional homogeneity on spheres. diff --git a/junifer/markers/sphere_aggregation.py b/junifer/markers/sphere_aggregation.py index a1ccc1cb8..bb93ef7ae 100644 --- a/junifer/markers/sphere_aggregation.py +++ b/junifer/markers/sphere_aggregation.py @@ -14,6 +14,9 @@ from ..utils import logger, raise_error, warn_with_log from .base import BaseMarker +__all__ = ["SphereAggregation"] + + @register_marker class SphereAggregation(BaseMarker): """Class for sphere aggregation. diff --git a/junifer/markers/temporal_snr/__init__.py b/junifer/markers/temporal_snr/__init__.py index ca150f982..d7b460ee8 100644 --- a/junifer/markers/temporal_snr/__init__.py +++ b/junifer/markers/temporal_snr/__init__.py @@ -5,3 +5,6 @@ from .temporal_snr_parcels import TemporalSNRParcels from .temporal_snr_spheres import TemporalSNRSpheres + + +__all__ = ["TemporalSNRParcels", "TemporalSNRSpheres"] diff --git a/junifer/markers/temporal_snr/temporal_snr_base.py b/junifer/markers/temporal_snr/temporal_snr_base.py index 64e1953a5..366feb5e3 100644 --- a/junifer/markers/temporal_snr/temporal_snr_base.py +++ b/junifer/markers/temporal_snr/temporal_snr_base.py @@ -13,6 +13,9 @@ from ...utils import raise_error from ..base import BaseMarker +__all__ = ["TemporalSNRBase"] + + class TemporalSNRBase(BaseMarker): """Abstract base class for temporal SNR markers. diff --git a/junifer/markers/temporal_snr/temporal_snr_parcels.py b/junifer/markers/temporal_snr/temporal_snr_parcels.py index 3c18ceccf..084fc77ce 100644 --- a/junifer/markers/temporal_snr/temporal_snr_parcels.py +++ b/junifer/markers/temporal_snr/temporal_snr_parcels.py @@ -10,6 +10,9 @@ from ..parcel_aggregation import ParcelAggregation from .temporal_snr_base import TemporalSNRBase +__all__ = ["TemporalSNRParcels"] + + @register_marker class TemporalSNRParcels(TemporalSNRBase): """Class for temporal signal-to-noise ratio using parcellations. diff --git a/junifer/markers/temporal_snr/temporal_snr_spheres.py b/junifer/markers/temporal_snr/temporal_snr_spheres.py index 34ec1101a..383723cd9 100644 --- a/junifer/markers/temporal_snr/temporal_snr_spheres.py +++ b/junifer/markers/temporal_snr/temporal_snr_spheres.py @@ -11,6 +11,9 @@ from ..utils import raise_error from .temporal_snr_base import TemporalSNRBase +__all__ = ["TemporalSNRSpheres"] + + @register_marker class TemporalSNRSpheres(TemporalSNRBase): """Class for temporal signal-to-noise ratio using coordinates (spheres). diff --git a/junifer/onthefly/__init__.py b/junifer/onthefly/__init__.py index 183966b53..024e6825a 100644 --- a/junifer/onthefly/__init__.py +++ b/junifer/onthefly/__init__.py @@ -4,3 +4,6 @@ # License: AGPL from .read_transform import read_transform + + +__all__ = ["read_transform"] diff --git a/junifer/onthefly/read_transform.py b/junifer/onthefly/read_transform.py index c1bfa6ca5..3cc656f13 100644 --- a/junifer/onthefly/read_transform.py +++ b/junifer/onthefly/read_transform.py @@ -15,6 +15,9 @@ if TYPE_CHECKING: from junifer.storage import BaseFeatureStorage +__all__ = ["read_transform"] + + def read_transform( storage: Type["BaseFeatureStorage"], transform: str, diff --git a/junifer/pipeline/__init__.py b/junifer/pipeline/__init__.py index 44e521c52..741544228 100644 --- a/junifer/pipeline/__init__.py +++ b/junifer/pipeline/__init__.py @@ -7,3 +7,11 @@ from . import registry from .pipeline_step_mixin import PipelineStepMixin from .update_meta_mixin import UpdateMetaMixin from .workdir_manager import WorkDirManager + + +__all__ = [ + "registry", + "PipelineStepMixin", + "UpdateMetaMixin", + "WorkDirManager", +] diff --git a/junifer/pipeline/pipeline_step_mixin.py b/junifer/pipeline/pipeline_step_mixin.py index 39e701039..dfad3c795 100644 --- a/junifer/pipeline/pipeline_step_mixin.py +++ b/junifer/pipeline/pipeline_step_mixin.py @@ -17,6 +17,9 @@ from ..utils import raise_error from .utils import check_ext_dependencies +__all__ = ["PipelineStepMixin"] + + class PipelineStepMixin: """Mixin class for a pipeline step.""" diff --git a/junifer/pipeline/registry.py b/junifer/pipeline/registry.py index 0579d2b36..d4b985885 100644 --- a/junifer/pipeline/registry.py +++ b/junifer/pipeline/registry.py @@ -16,6 +16,9 @@ if TYPE_CHECKING: from .pipeline_step_mixin import PipelineStepMixin +__all__ = ["register", "get_step_names", "get_class", "build"] + + # Define valid steps for operation _VALID_STEPS: List[str] = [ "datagrabber", diff --git a/junifer/pipeline/singleton.py b/junifer/pipeline/singleton.py index b04d7507d..68325fd6a 100644 --- a/junifer/pipeline/singleton.py +++ b/junifer/pipeline/singleton.py @@ -6,6 +6,9 @@ from typing import Any, Dict, Type +__all__ = ["singleton"] + + def singleton(cls: Type) -> Type: """Make a class singleton. diff --git a/junifer/pipeline/update_meta_mixin.py b/junifer/pipeline/update_meta_mixin.py index a160b7cd4..c88978244 100644 --- a/junifer/pipeline/update_meta_mixin.py +++ b/junifer/pipeline/update_meta_mixin.py @@ -7,6 +7,9 @@ from typing import Dict +__all__ = ["UpdateMetaMixin"] + + class UpdateMetaMixin: """Mixin class for updating meta.""" diff --git a/junifer/pipeline/utils.py b/junifer/pipeline/utils.py index 712fc600f..eabf3b284 100644 --- a/junifer/pipeline/utils.py +++ b/junifer/pipeline/utils.py @@ -10,6 +10,9 @@ from typing import Any, List, Optional from junifer.utils.logging import raise_error, warn_with_log +__all__ = ["check_ext_dependencies"] + + def check_ext_dependencies( name: str, optional: bool = False, **kwargs: Any ) -> bool: diff --git a/junifer/pipeline/workdir_manager.py b/junifer/pipeline/workdir_manager.py index c1d1b5ef4..b5a43eb83 100644 --- a/junifer/pipeline/workdir_manager.py +++ b/junifer/pipeline/workdir_manager.py @@ -13,6 +13,9 @@ from ..utils import logger from .singleton import singleton +__all__ = ["WorkDirManager"] + + @singleton class WorkDirManager: """Class for working directory manager. diff --git a/junifer/preprocess/__init__.py b/junifer/preprocess/__init__.py index 32b944353..2404a909e 100644 --- a/junifer/preprocess/__init__.py +++ b/junifer/preprocess/__init__.py @@ -9,3 +9,11 @@ from .base import BasePreprocessor from .confounds import fMRIPrepConfoundRemover from .warping import SpaceWarper from .smoothing import Smoothing + + +__all__ = [ + "BasePreprocessor", + "fMRIPrepConfoundRemover", + "SpaceWarper", + "Smoothing", +] diff --git a/junifer/preprocess/base.py b/junifer/preprocess/base.py index b46fe7afe..68dda654d 100644 --- a/junifer/preprocess/base.py +++ b/junifer/preprocess/base.py @@ -11,6 +11,9 @@ from ..pipeline import PipelineStepMixin, UpdateMetaMixin from ..utils import logger, raise_error +__all__ = ["BasePreprocessor"] + + class BasePreprocessor(ABC, PipelineStepMixin, UpdateMetaMixin): """Abstract base class for all preprocessors. @@ -136,7 +139,7 @@ class BasePreprocessor(ABC, PipelineStepMixin, UpdateMetaMixin): A single input from the Junifer Data object to preprocess. extra_input : dict, optional The other fields in the Junifer Data object. Useful for accessing - other data kind that needs to be used in the computation. For + other data type that needs to be used in the computation. For example, the confound removers can make use of the confounds if available (default None). diff --git a/junifer/preprocess/confounds/__init__.py b/junifer/preprocess/confounds/__init__.py index bd0189b10..afcdbaf64 100644 --- a/junifer/preprocess/confounds/__init__.py +++ b/junifer/preprocess/confounds/__init__.py @@ -5,3 +5,6 @@ # License: AGPL from .fmriprep_confound_remover import fMRIPrepConfoundRemover + + +__all__ = ["fMRIPrepConfoundRemover"] diff --git a/junifer/preprocess/confounds/fmriprep_confound_remover.py b/junifer/preprocess/confounds/fmriprep_confound_remover.py index 4e77a8e1b..7a13abf61 100644 --- a/junifer/preprocess/confounds/fmriprep_confound_remover.py +++ b/junifer/preprocess/confounds/fmriprep_confound_remover.py @@ -27,6 +27,9 @@ from ...utils import logger, raise_error from ..base import BasePreprocessor +__all__ = ["fMRIPrepConfoundRemover"] + + FMRIPREP_BASICS = { "motion": [ "trans_x", diff --git a/junifer/preprocess/smoothing/__init__.py b/junifer/preprocess/smoothing/__init__.py index 0236a63d1..801770682 100644 --- a/junifer/preprocess/smoothing/__init__.py +++ b/junifer/preprocess/smoothing/__init__.py @@ -4,3 +4,6 @@ # License: AGPL from .smoothing import Smoothing + + +__all__ = ["Smoothing"] diff --git a/junifer/preprocess/warping/__init__.py b/junifer/preprocess/warping/__init__.py index 1b7a3bc2b..6c31c840b 100644 --- a/junifer/preprocess/warping/__init__.py +++ b/junifer/preprocess/warping/__init__.py @@ -4,3 +4,6 @@ # License: AGPL from .space_warper import SpaceWarper + + +__all__ = ["SpaceWarper"] diff --git a/junifer/preprocess/warping/_ants_warper.py b/junifer/preprocess/warping/_ants_warper.py index a78d67702..eea08f428 100644 --- a/junifer/preprocess/warping/_ants_warper.py +++ b/junifer/preprocess/warping/_ants_warper.py @@ -20,6 +20,9 @@ from ...pipeline import WorkDirManager from ...utils import logger, run_ext_cmd +__all__ = ["ANTsWarper"] + + class ANTsWarper: """Class for space warping via ANTs antsApplyTransforms. diff --git a/junifer/preprocess/warping/_fsl_warper.py b/junifer/preprocess/warping/_fsl_warper.py index 32ded0e60..3c32de64c 100644 --- a/junifer/preprocess/warping/_fsl_warper.py +++ b/junifer/preprocess/warping/_fsl_warper.py @@ -19,6 +19,9 @@ from ...pipeline import WorkDirManager from ...utils import logger, run_ext_cmd +__all__ = ["FSLWarper"] + + class FSLWarper: """Class for space warping via FSL FLIRT. diff --git a/junifer/stats.py b/junifer/stats.py index d87e31cb4..2a74b6e88 100644 --- a/junifer/stats.py +++ b/junifer/stats.py @@ -13,6 +13,9 @@ from scipy.stats.mstats import winsorize from .utils import logger, raise_error +__all__ = ["get_aggfunc_by_name", "count", "winsorized_mean", "select"] + + def get_aggfunc_by_name( name: str, func_params: Optional[Dict[str, Any]] = None ) -> Callable: diff --git a/junifer/storage/__init__.py b/junifer/storage/__init__.py index d355c3413..0282c846f 100644 --- a/junifer/storage/__init__.py +++ b/junifer/storage/__init__.py @@ -8,3 +8,11 @@ from .base import BaseFeatureStorage from .pandas_base import PandasBaseFeatureStorage from .sqlite import SQLiteFeatureStorage from .hdf5 import HDF5FeatureStorage + + +__all__ = [ + "BaseFeatureStorage", + "PandasBaseFeatureStorage", + "SQLiteFeatureStorage", + "HDF5FeatureStorage", +] diff --git a/junifer/storage/base.py b/junifer/storage/base.py index 65050b0f9..ab2cc6197 100644 --- a/junifer/storage/base.py +++ b/junifer/storage/base.py @@ -15,6 +15,9 @@ from ..utils import raise_error from .utils import process_meta +__all__ = ["BaseFeatureStorage"] + + class BaseFeatureStorage(ABC): """Abstract base class for feature storage. diff --git a/junifer/storage/hdf5.py b/junifer/storage/hdf5.py index c61c0dce8..512ec52ee 100644 --- a/junifer/storage/hdf5.py +++ b/junifer/storage/hdf5.py @@ -26,6 +26,9 @@ from .base import BaseFeatureStorage from .utils import element_to_prefix, matrix_to_vector, store_matrix_checks +__all__ = ["HDF5FeatureStorage"] + + def _create_chunk( chunk_data: List[np.ndarray], kind: str, diff --git a/junifer/storage/pandas_base.py b/junifer/storage/pandas_base.py index d0c61ce96..ce33663e8 100644 --- a/junifer/storage/pandas_base.py +++ b/junifer/storage/pandas_base.py @@ -15,6 +15,9 @@ from ..utils import raise_error from .base import BaseFeatureStorage +__all__ = ["PandasBaseFeatureStorage"] + + class PandasBaseFeatureStorage(BaseFeatureStorage): """Abstract base class for feature storage via pandas. diff --git a/junifer/storage/sqlite.py b/junifer/storage/sqlite.py index d43fbb3fc..c5c3f9fa3 100644 --- a/junifer/storage/sqlite.py +++ b/junifer/storage/sqlite.py @@ -25,6 +25,9 @@ if TYPE_CHECKING: from sqlalchemy.engine import Engine +__all__ = ["SQLiteFeatureStorage"] + + @register_storage class SQLiteFeatureStorage(PandasBaseFeatureStorage): """Concrete implementation for feature storage via SQLite. diff --git a/junifer/storage/utils.py b/junifer/storage/utils.py index f386d0033..6a41172b8 100644 --- a/junifer/storage/utils.py +++ b/junifer/storage/utils.py @@ -14,6 +14,15 @@ import numpy as np from ..utils.logging import logger, raise_error +__all__ = [ + "get_dependency_version", + "process_meta", + "element_to_prefix", + "store_matrix_checks", + "matrix_to_vector", +] + + def get_dependency_version(dependency: str) -> str: """Get dependency version. diff --git a/junifer/testing/__init__.py b/junifer/testing/__init__.py index ed232268e..40917383b 100644 --- a/junifer/testing/__init__.py +++ b/junifer/testing/__init__.py @@ -6,3 +6,6 @@ from . import datagrabbers from .utils import get_testing_data + + +__all__ = ["datagrabbers", "get_testing_data"] diff --git a/junifer/testing/datagrabbers.py b/junifer/testing/datagrabbers.py index c59fb3634..7d0b835e8 100644 --- a/junifer/testing/datagrabbers.py +++ b/junifer/testing/datagrabbers.py @@ -14,6 +14,13 @@ from nilearn import datasets, image from ..datagrabber.base import BaseDataGrabber +__all__ = [ + "OasisVBMTestingDataGrabber", + "SPMAuditoryTestingDataGrabber", + "PartlyCloudyTestingDataGrabber", +] + + class OasisVBMTestingDataGrabber(BaseDataGrabber): """DataGrabber for Oasis VBM testing data. diff --git a/junifer/testing/utils.py b/junifer/testing/utils.py index 3a5b25a0c..6b2c18c60 100644 --- a/junifer/testing/utils.py +++ b/junifer/testing/utils.py @@ -6,6 +6,9 @@ from pathlib import Path +__all__ = ["get_testing_data"] + + def get_testing_data(fname: str) -> Path: """Get the path to a testing data file. diff --git a/junifer/utils/__init__.py b/junifer/utils/__init__.py index f63888fd7..c11541231 100644 --- a/junifer/utils/__init__.py +++ b/junifer/utils/__init__.py @@ -7,3 +7,13 @@ from .fs import make_executable from .logging import configure_logging, logger, raise_error, warn_with_log from .helpers import run_ext_cmd + + +__all__ = [ + "make_executable", + "configure_logging", + "logger", + "raise_error", + "warn_with_log", + "run_ext_cmd", +] diff --git a/junifer/utils/fs.py b/junifer/utils/fs.py index 844eb95e9..4d69dab82 100644 --- a/junifer/utils/fs.py +++ b/junifer/utils/fs.py @@ -8,6 +8,9 @@ import stat from pathlib import Path +__all__ = ["make_executable"] + + def make_executable(path: Path) -> None: """Make ``path`` executable. diff --git a/junifer/utils/helpers.py b/junifer/utils/helpers.py index ec4cdc528..3946ee000 100644 --- a/junifer/utils/helpers.py +++ b/junifer/utils/helpers.py @@ -9,6 +9,9 @@ from typing import List from .logging import logger, raise_error +__all__ = ["run_ext_cmd"] + + def run_ext_cmd(name: str, cmd: List[str]) -> None: """Run external command via subprocess. diff --git a/junifer/utils/logging.py b/junifer/utils/logging.py index c60a9d68e..c2b20331a 100644 --- a/junifer/utils/logging.py +++ b/junifer/utils/logging.py @@ -19,6 +19,16 @@ from warnings import warn import datalad +__all__ = [ + "WrapStdOut", + "get_versions", + "log_versions", + "configure_logging", + "raise_error", + "warn_with_log", +] + + logger = logging.getLogger("JUNIFER") # Set up datalad logger level to warning by default diff --git a/pyproject.toml b/pyproject.toml index f8ddf7c7a..e318016b7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -124,6 +124,16 @@ builtin = "clear,rare,informal,names,usage,code" [tool.ruff] line-length = 79 +extend-exclude = [ + "__init__.py", + "junifer/external/h5io", + "junifer/external/BrainPrint", + "docs", + "examples", + "tools", +] + +[tool.ruff.lint] select = [ # flake8-bugbear "B", @@ -156,14 +166,6 @@ select = [ # flake8-2020 "YTT", ] -extend-exclude = [ - "__init__.py", - "junifer/external/h5io", - "junifer/external/BrainPrint", - "docs", - "examples", - "tools", -] ignore = [ # Use of `functools.lru_cache` or `functools.cache` on methods can lead to # memory leaks. The cache may retain instance references, preventing garbage @@ -186,7 +188,7 @@ ignore = [ "PGH003", ] -[tool.ruff.isort] +[tool.ruff.lint.isort] lines-after-imports = 2 known-first-party = ["junifer"] known-third-party =[ @@ -210,12 +212,22 @@ known-third-party =[ "pytest", ] -[tool.ruff.mccabe] +[tool.ruff.lint.mccabe] max-complexity = 20 [tool.pytest.ini_options] minversion = "7.0" -addopts = "--ignore=junifer/external/h5io --ignore=junifer/external/BrainPrint -vv" +testpaths = "junifer" +log_cli_level = "INFO" +xfail_strict = true +addopts = [ + "-ra", + "--strict-config", + "--strict-markers", + "--ignore=junifer/external/h5io", + "--ignore=junifer/external/BrainPrint", + "-vv", +] [tool.towncrier] directory = "docs/changes/newsfragments"