[MAINT]: Regular repository maintenance #337

Merged
synchon merged 13 commits from chore/repo-maint into main 2024-06-03 13:37:46 +00:00
126 changed files with 720 additions and 186 deletions

View file

@ -4,7 +4,7 @@ ci:
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0 rev: v4.6.0
hooks: hooks:
- id: check-ast - id: check-ast
- id: check-docstring-first - id: check-docstring-first
@ -20,14 +20,14 @@ repos:
rev: v0.16 rev: v0.16
hooks: hooks:
- id: validate-pyproject - id: validate-pyproject
- repo: https://github.com/psf/black - repo: https://github.com/psf/black-pre-commit-mirror
rev: 24.1.1 rev: 24.4.2
hooks: hooks:
- id: black - id: black
exclude: ^(docs/|examples/|tools/) exclude: ^(docs/|examples/|tools/)
args: [--check] args: [--check]
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.15 rev: v0.4.2
hooks: hooks:
- id: ruff - id: ruff
types_or: [python, jupyter] types_or: [python, jupyter]
@ -38,7 +38,7 @@ repos:
hooks: hooks:
- id: codespell - id: codespell
exclude: ^(.github/|docs/) exclude: ^(.github/|docs/)
args: [--config, tox.ini] args: [--toml, pyproject.toml]
- repo: https://github.com/pre-commit/pygrep-hooks - repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.10.0 rev: v1.10.0
hooks: hooks:
@ -47,3 +47,10 @@ repos:
- id: rst-backticks - id: rst-backticks
- id: rst-directive-colons - id: rst-directive-colons
- id: rst-inline-touching-normal - 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]

View file

@ -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`_

View file

@ -70,10 +70,7 @@ with the DMN. Here, we use the DMN coordinates used in a
.. code-block:: python .. code-block:: python
dmn_coords = np.array( dmn_coords = np.array(
[[0, -52, 18], [[0, -52, 18], [-46, -68, 32], [46, -68, 32], [1, 50, -5]]
[-46, -68, 32],
[46, -68, 32],
[1, 50, -5]]
) )
voi_names = [ voi_names = [
"Posterior Cingulate Cortex", "Posterior Cingulate Cortex",
@ -90,10 +87,7 @@ simply use this to register our coordinates:
.. code-block:: python .. code-block:: python
register_coordinates( register_coordinates(
name="DMNCustom", name="DMNCustom", coordinates=dmn_coords, voi_names=voi_names, space="MNI"
coordinates=dmn_coords,
voi_names=voi_names,
space="MNI"
) )
Now, when we run this script, ``junifer`` registers these coordinates and we can Now, when we run this script, ``junifer`` registers these coordinates and we can

View file

@ -144,7 +144,6 @@ With the variables defined above, we can create our DataGrabber and name it
class ExampleBIDSDataGrabber(PatternDataGrabber): class ExampleBIDSDataGrabber(PatternDataGrabber):
def __init__(self, datadir: str | Path) -> None: def __init__(self, datadir: str | Path) -> None:
types = ["T1w", "BOLD"] types = ["T1w", "BOLD"]
patterns = { patterns = {
@ -180,7 +179,6 @@ use the :func:`.register_datagrabber` decorator.
@register_datagrabber @register_datagrabber
class ExampleBIDSDataGrabber(PatternDataGrabber): class ExampleBIDSDataGrabber(PatternDataGrabber):
def __init__(self, datadir: str | Path) -> None: def __init__(self, datadir: str | Path) -> None:
types = ["T1w", "BOLD"] types = ["T1w", "BOLD"]
patterns = { patterns = {
@ -267,7 +265,6 @@ And we can create our DataGrabber:
@register_datagrabber @register_datagrabber
class ExampleBIDSDataGrabber(PatternDataladDataGrabber): class ExampleBIDSDataGrabber(PatternDataladDataGrabber):
def __init__(self) -> None: def __init__(self) -> None:
types = ["T1w", "BOLD"] types = ["T1w", "BOLD"]
patterns = { patterns = {
@ -448,8 +445,9 @@ So, to summarise, our DataGrabber will look like this:
@register_datagrabber @register_datagrabber
class ExampleBIDSDataGrabber(BaseDataGrabber): class ExampleBIDSDataGrabber(BaseDataGrabber):
def get_item(
def get_item(self, subject: str, session: str) -> dict[str, dict[str, str]]: self, subject: str, session: str
) -> dict[str, dict[str, str]]:
out = { out = {
"T1w": { "T1w": {
"path": f"{subject}/{session}/anat/{subject}_{session}_T1w.nii.gz", "path": f"{subject}/{session}/anat/{subject}_{session}_T1w.nii.gz",
@ -522,9 +520,7 @@ this:
.. code-block:: python .. code-block:: python
def get_item( def get_item(self, subject: str, session: str) -> dict:
self, subject: str, session: str
) -> dict:
out = { out = {
"BOLD": { "BOLD": {
"path": f"{subject}/{session}/func/{subject}_{session}_task-rest_bold.nii.gz", "path": f"{subject}/{session}/func/{subject}_{session}_task-rest_bold.nii.gz",

View file

@ -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] self, using: str, reference: str, on: Union[List[str], str]
) -> None: ) -> None:
# validation and setting up # validation and setting up
...
Here, you see a new class attribute ``_CONDITIONAL_DEPENDENCIES`` which is a 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], extra_input: Dict[str, Any],
) -> Dict[str, Any]: ) -> Dict[str, Any]:
# implementation # implementation
...
Here you can see the familiar ``_DEPENDENCIES`` and ``_EXT_DEPENDENCIES`` class Here you can see the familiar ``_DEPENDENCIES`` and ``_EXT_DEPENDENCIES`` class
attributes. The validation process starts by looking up the ``using`` value of attributes. The validation process starts by looking up the ``using`` value of

View file

@ -269,7 +269,6 @@ Template for a custom Marker
@register_marker @register_marker
class TemplateMarker(BaseMarker): class TemplateMarker(BaseMarker):
def __init__(self, on=None, name=None): def __init__(self, on=None, name=None):
# TODO: add marker-specific parameters # TODO: add marker-specific parameters
super().__init__(on=on, name=name) super().__init__(on=on, name=name)

View file

@ -83,7 +83,7 @@ look like this:
name="my_custom_parcellation", name="my_custom_parcellation",
parcellation_path=path_to_parcellation, parcellation_path=path_to_parcellation,
parcels_labels=my_labels, parcels_labels=my_labels,
space="MNI152NLin2009cAsym" space="MNI152NLin2009cAsym",
) )
We can run this code and it seems to work, however, how can we actually We can run this code and it seems to work, however, how can we actually

View file

@ -43,9 +43,11 @@ For input we can accept ``T1w``, ``T2w`` and ``BOLD``
... ...
def get_valid_inputs(self) -> list[str]: def get_valid_inputs(self) -> list[str]:
return ["T1w", "T2w", "BOLD"] return ["T1w", "T2w", "BOLD"]
... ...
The output definition of the Preprocessor is unused now but is kept for 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: def get_output_type(self, input_type: str) -> str:
return input_type return input_type
... ...
.. _extending_preprocessors_init: .. _extending_preprocessors_init:
@ -90,6 +94,7 @@ you configure it. Our class will have the following arguments:
... ...
def __init__( def __init__(
self, self,
fwhm: int | float | ArrayLike | Literal["fast"] | None, fwhm: int | float | ArrayLike | Literal["fast"] | None,
@ -98,6 +103,7 @@ you configure it. Our class will have the following arguments:
self.fwhm = fwhm self.fwhm = fwhm
super().__init__(on=on) super().__init__(on=on)
... ...
.. caution:: .. caution::
@ -147,6 +153,7 @@ and it has two return values:
... ...
def preprocess( def preprocess(
self, self,
input: dict[str, Any], input: dict[str, Any],
@ -155,8 +162,10 @@ and it has two return values:
input["data"] = nimg.smooth_img(imgs=input["data"], fwhm=self.fwhm) input["data"] = nimg.smooth_img(imgs=input["data"], fwhm=self.fwhm)
return input, None return input, None
... ...
Step 4: Finalise the Preprocessor Step 4: Finalise the Preprocessor
--------------------------------- ---------------------------------

View file

@ -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 <data_types>` dictionary of dictionaries. The first level of keys are the :ref:`data types <data_types>`
and the values are the corresponding information as dictionaries. and the values are the corresponding information as dictionaries.
.. code-block:: python .. code-block::
{'BOLD': {...}, 'T1w': {...}} {'BOLD': {...}, 'T1w': {...}}
@ -24,7 +24,7 @@ The :ref:`Data Grabber <datagrabber>` step adds the ``path`` second-level key
which gives the path to the file containing the data. The ``meta`` key in this which gives the path to the file containing the data. The ``meta`` key in this
step only contains information about the DataGrabber used. step only contains information about the DataGrabber used.
.. code-block:: python .. code-block::
{'BOLD': {'meta': {'datagrabber': {'class': 'SPMAuditoryTestingDataGrabber', {'BOLD': {'meta': {'datagrabber': {'class': 'SPMAuditoryTestingDataGrabber',
'types': ['BOLD', 'T1w']}, 'types': ['BOLD', 'T1w']},
@ -41,7 +41,7 @@ The :ref:`Data Reader <datareader>` step adds the ``data`` second-level key
which is the actual data loaded into memory. The ``meta`` key in this step which is the actual data loaded into memory. The ``meta`` key in this step
adds information about the DataReader used to read the data. adds information about the DataReader used to read the data.
.. code-block:: python .. code-block::
{'BOLD': {'data': <nibabel.nifti1.Nifti1Image object at 0x16b5d8910>, {'BOLD': {'data': <nibabel.nifti1.Nifti1Image object at 0x16b5d8910>,
'meta': {'datagrabber': {'class': 'SPMAuditoryTestingDataGrabber', 'meta': {'datagrabber': {'class': 'SPMAuditoryTestingDataGrabber',
@ -58,6 +58,7 @@ adds information about the DataReader used to read the data.
'element': {'subject': 'sub001'}}, 'element': {'subject': 'sub001'}},
'path': PosixPath('/var/folders/dv/2lbr8f8j0q12zrx3mz3ll5m40000gp/T/tmpe49321ce/sub001_T1w.nii.gz')}} 'path': PosixPath('/var/folders/dv/2lbr8f8j0q12zrx3mz3ll5m40000gp/T/tmpe49321ce/sub001_T1w.nii.gz')}}
The :ref:`Preprocess <preprocess>` step, if used, modifies the ``data`` The :ref:`Preprocess <preprocess>` step, if used, modifies the ``data``
second-level key's value and appends the ``meta`` key with information about second-level key's value and appends the ``meta`` key with information about
the preprocessor. the preprocessor.
@ -66,7 +67,7 @@ The :ref:`Marker <marker>` step removes the ``path`` second-level key,
replaces the ``data`` second-level key's value with the marker's computed value 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``. 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'], {'BOLD': {'col_names': ['root_sum_of_squares_ets'],
'data': ..., 'data': ...,

View file

@ -69,7 +69,7 @@ Example in python format:
strategy = { strategy = {
"motion": "basic", "motion": "basic",
"wm_csf": "full", "wm_csf": "full",
"global_signal": "derivatives" "global_signal": "derivatives",
} }
or in YAML format: 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 .. code-block:: python
strategy = { strategy = {"motion": "full", "wm_csf": "full", "global_signal": "full"}
"motion": "full",
"wm_csf": "full",
"global_signal": "full"
}
Other Parameters Other Parameters
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~

View file

@ -20,3 +20,20 @@ from . import (
onthefly, onthefly,
) )
from ._version import __version__ from ._version import __version__
__all__ = [
"api",
"configs",
"data",
"datagrabber",
"datareader",
"markers",
"pipeline",
"preprocess",
"stats",
"storage",
"utils",
"external",
"onthefly",
]

View file

@ -7,3 +7,6 @@
from . import decorators from . import decorators
from .cli import cli from .cli import cli
from .functions import collect, queue, run from .functions import collect, queue, run
__all__ = ["decorators", "cli", "collect", "queue", "run"]

View file

@ -10,6 +10,15 @@ from typing import Type
from ..pipeline.registry import register from ..pipeline.registry import register
__all__ = [
"register_datagrabber",
"register_datareader",
"register_preprocessor",
"register_marker",
"register_storage",
]
def register_datagrabber(klass: Type) -> Type: def register_datagrabber(klass: Type) -> Type:
"""Register DataGrabber. """Register DataGrabber.

View file

@ -23,6 +23,9 @@ from .queue_context import GnuParallelLocalAdapter, HTCondorAdapter
from .utils import yaml from .utils import yaml
__all__ = ["run", "collect", "queue", "reset", "list_elements"]
def _get_datagrabber(datagrabber_config: Dict) -> BaseDataGrabber: def _get_datagrabber(datagrabber_config: Dict) -> BaseDataGrabber:
"""Get DataGrabber. """Get DataGrabber.
@ -92,7 +95,7 @@ def run(
datagrabber : dict datagrabber : dict
DataGrabber to use. Must have a key ``kind`` with the kind of DataGrabber to use. Must have a key ``kind`` with the kind of
DataGrabber to use. All other keys are passed to the DataGrabber DataGrabber to use. All other keys are passed to the DataGrabber
init function. constructor.
markers : list of dict markers : list of dict
List of markers to extract. Each marker is a dict with at least two 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 keys: ``name`` and ``kind``. The ``name`` key is used to name the
@ -102,11 +105,11 @@ def run(
storage : dict storage : dict
Storage to use. Must have a key ``kind`` with the kind of Storage to use. Must have a key ``kind`` with the kind of
storage to use. All other keys are passed to the storage storage to use. All other keys are passed to the storage
init function. constructor.
preprocessors : list of dict, optional preprocessors : list of dict, optional
List of preprocessors to use. Each preprocessor is a dict with at List of preprocessors to use. Each preprocessor is a dict with at
least a key ``kind`` specifying the preprocessor to use. All other keys 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 elements : str or tuple or list of str or tuple, optional
Element(s) to process. Will be used to index the DataGrabber Element(s) to process. Will be used to index the DataGrabber
(default None). (default None).
@ -188,7 +191,7 @@ def collect(storage: Dict) -> None:
storage : dict storage : dict
Storage to use. Must have a key ``kind`` with the kind of Storage to use. Must have a key ``kind`` with the kind of
storage to use. All other keys are passed to the storage storage to use. All other keys are passed to the storage
init function. constructor.
""" """
storage_params = storage.copy() storage_params = storage.copy()

View file

@ -14,6 +14,9 @@ from ..utils.logging import logger, raise_error
from .utils import yaml from .utils import yaml
__all__ = ["parse_yaml"]
def parse_yaml(filepath: Union[str, Path]) -> Dict: def parse_yaml(filepath: Union[str, Path]) -> Dict:
"""Parse YAML. """Parse YAML.

View file

@ -6,3 +6,6 @@
from .queue_context_adapter import QueueContextAdapter from .queue_context_adapter import QueueContextAdapter
from .htcondor_adapter import HTCondorAdapter from .htcondor_adapter import HTCondorAdapter
from .gnu_parallel_local_adapter import GnuParallelLocalAdapter from .gnu_parallel_local_adapter import GnuParallelLocalAdapter
__all__ = ["QueueContextAdapter", "HTCondorAdapter", "GnuParallelLocalAdapter"]

View file

@ -31,7 +31,7 @@ if [ -d "${var}" ]; then
done done
echo "Docker args: ${docker_args[*]}" >&2 echo "Docker args: ${docker_args[*]}" >&2
echo "Corrected args for afni: ${corrected_args[*]}" >&2 echo "Corrected args for AFNI: ${corrected_args[*]}" >&2
cwd=$(pwd) cwd=$(pwd)
cmd="docker run --rm ${docker_args[*]} -v ${cwd}:${cwd} -w ${cwd} afni/afni_make_build ${corrected_args[*]}" cmd="docker run --rm ${docker_args[*]} -v ${cwd}:${cwd} -w ${cwd} afni/afni_make_build ${corrected_args[*]}"

View file

@ -31,7 +31,7 @@ if [ -d "${var}" ]; then
done done
echo "Docker args: ${docker_args[*]}" >&2 echo "Docker args: ${docker_args[*]}" >&2
echo "Corrected args for fsl: ${corrected_args[*]}" >&2 echo "Corrected args for ANTs: ${corrected_args[*]}" >&2
cwd=$(pwd) cwd=$(pwd)
cmd="docker run --rm ${docker_args[*]} -v ${cwd}:${cwd} -w ${cwd} antsx/ants ${corrected_args[*]}" cmd="docker run --rm ${docker_args[*]} -v ${cwd}:${cwd} -w ${cwd} antsx/ants ${corrected_args[*]}"

View file

@ -31,7 +31,7 @@ if [ -d "${var}" ]; then
done done
echo "Docker args: ${docker_args[*]}" >&2 echo "Docker args: ${docker_args[*]}" >&2
echo "Corrected args for fsl: ${corrected_args[*]}" >&2 echo "Corrected args for FSL: ${corrected_args[*]}" >&2
cwd=$(pwd) cwd=$(pwd)
cmd="docker run --rm ${docker_args[*]} -v ${cwd}:${cwd} -w ${cwd} brainlife/fsl ${corrected_args[*]}" cmd="docker run --rm ${docker_args[*]} -v ${cwd}:${cwd} -w ${cwd} brainlife/fsl ${corrected_args[*]}"

View file

@ -4,3 +4,6 @@
# License: AGPL # License: AGPL
from . import datagrabbers from . import datagrabbers
__all__ = ["datagrabbers"]

View file

@ -10,3 +10,12 @@ from .camcan_vbm import JuselessDataladCamCANVBM
from .ixi_vbm import JuselessDataladIXIVBM from .ixi_vbm import JuselessDataladIXIVBM
from .ucla import JuselessUCLA from .ucla import JuselessUCLA
from .ukb_vbm import JuselessDataladUKBVBM from .ukb_vbm import JuselessDataladUKBVBM
__all__ = [
"JuselessDataladAOMICID1000VBM",
"JuselessDataladCamCANVBM",
"JuselessDataladIXIVBM",
"JuselessUCLA",
"JuselessDataladUKBVBM",
]

View file

@ -11,6 +11,9 @@ from ....api.decorators import register_datagrabber
from ....datagrabber import PatternDataladDataGrabber from ....datagrabber import PatternDataladDataGrabber
__all__ = ["JuselessDataladAOMICID1000VBM"]
@register_datagrabber @register_datagrabber
class JuselessDataladAOMICID1000VBM(PatternDataladDataGrabber): class JuselessDataladAOMICID1000VBM(PatternDataladDataGrabber):
"""Concrete implementation for Juseless AOMIC ID1000 VBM data fetching. """Concrete implementation for Juseless AOMIC ID1000 VBM data fetching.

View file

@ -12,6 +12,9 @@ from ....api.decorators import register_datagrabber
from ....datagrabber import PatternDataladDataGrabber from ....datagrabber import PatternDataladDataGrabber
__all__ = ["JuselessDataladCamCANVBM"]
@register_datagrabber @register_datagrabber
class JuselessDataladCamCANVBM(PatternDataladDataGrabber): class JuselessDataladCamCANVBM(PatternDataladDataGrabber):
"""Concrete implementation for Juseless CamCAN VBM data fetching. """Concrete implementation for Juseless CamCAN VBM data fetching.

View file

@ -13,6 +13,9 @@ from ....datagrabber import PatternDataladDataGrabber
from ....utils import raise_error from ....utils import raise_error
__all__ = ["JuselessDataladIXIVBM"]
@register_datagrabber @register_datagrabber
class JuselessDataladIXIVBM(PatternDataladDataGrabber): class JuselessDataladIXIVBM(PatternDataladDataGrabber):
"""Concrete implementation for Juseless IXI VBM data fetching. """Concrete implementation for Juseless IXI VBM data fetching.

View file

@ -12,6 +12,9 @@ from ....datagrabber import PatternDataGrabber
from ....utils import raise_error from ....utils import raise_error
__all__ = ["JuselessUCLA"]
@register_datagrabber @register_datagrabber
class JuselessUCLA(PatternDataGrabber): class JuselessUCLA(PatternDataGrabber):
"""Concrete implementation for Juseless UCLA data fetching. """Concrete implementation for Juseless UCLA data fetching.

View file

@ -12,6 +12,9 @@ from ....api.decorators import register_datagrabber
from ....datagrabber import PatternDataladDataGrabber from ....datagrabber import PatternDataladDataGrabber
__all__ = ["JuselessDataladUKBVBM"]
@register_datagrabber @register_datagrabber
class JuselessDataladUKBVBM(PatternDataladDataGrabber): class JuselessDataladUKBVBM(PatternDataladDataGrabber):
"""Concrete implementation for Juseless UKB VBM data fetching. """Concrete implementation for Juseless UKB VBM data fetching.

View file

@ -28,3 +28,23 @@ from .masks import (
from .template_spaces import get_template, get_xfm from .template_spaces import get_template, get_xfm
from . import utils 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",
]

View file

@ -16,6 +16,14 @@ from ..pipeline import WorkDirManager
from ..utils import logger, raise_error, run_ext_cmd from ..utils import logger, raise_error, run_ext_cmd
__all__ = [
"register_coordinates",
"list_coordinates",
"get_coordinates",
"load_coordinates",
]
# Path to the VOIs # Path to the VOIs
_vois_path = Path(__file__).parent / "VOIs" _vois_path = Path(__file__).parent / "VOIs"

View file

@ -35,6 +35,16 @@ from .utils import closest_resolution
if TYPE_CHECKING: if TYPE_CHECKING:
from nibabel import Nifti1Image from nibabel import Nifti1Image
__all__ = [
"compute_brain_mask",
"register_mask",
"list_masks",
"get_mask",
"load_mask",
]
# Path to the masks # Path to the masks
_masks_path = Path(__file__).parent / "masks" _masks_path = Path(__file__).parent / "masks"

View file

@ -30,6 +30,15 @@ if TYPE_CHECKING:
from nibabel import Nifti1Image from nibabel import Nifti1Image
__all__ = [
"register_parcellation",
"list_parcellations",
"get_parcellation",
"load_parcellation",
"merge_parcellations",
]
# A dictionary containing all supported parcellations and their respective # A dictionary containing all supported parcellations and their respective
# valid parameters. # valid parameters.

View file

@ -15,6 +15,9 @@ from ..utils import logger, raise_error
from .utils import closest_resolution from .utils import closest_resolution
__all__ = ["get_xfm", "get_template"]
def get_xfm( def get_xfm(
src: str, dst: str, xfms_dir: Union[str, Path, None] = None src: str, dst: str, xfms_dir: Union[str, Path, None] = None
) -> Path: # pragma: no cover ) -> Path: # pragma: no cover

View file

@ -7,6 +7,9 @@ import numpy as np
from ..utils.logging import logger from ..utils.logging import logger
__all__ = ["closest_resolution"]
def closest_resolution( def closest_resolution(
resolution: Optional[Union[float, int]], resolution: Optional[Union[float, int]],
valid_resolution: Union[List[float], List[int], np.ndarray], valid_resolution: Union[List[float], List[int], np.ndarray],

View file

@ -16,3 +16,18 @@ from .aomic import DataladAOMICID1000, DataladAOMICPIOP1, DataladAOMICPIOP2
from .hcp1200 import HCP1200, DataladHCP1200 from .hcp1200 import HCP1200, DataladHCP1200
from .multiple import MultipleDataGrabber from .multiple import MultipleDataGrabber
from .dmcc13_benchmark import DMCC13Benchmark from .dmcc13_benchmark import DMCC13Benchmark
__all__ = [
"BaseDataGrabber",
"DataladDataGrabber",
"PatternDataGrabber",
"PatternDataladDataGrabber",
"DataladAOMICID1000",
"DataladAOMICPIOP1",
"DataladAOMICPIOP2",
"HCP1200",
"DataladHCP1200",
"MultipleDataGrabber",
"DMCC13Benchmark",
]

View file

@ -7,3 +7,6 @@
from .id1000 import DataladAOMICID1000 from .id1000 import DataladAOMICID1000
from .piop1 import DataladAOMICPIOP1 from .piop1 import DataladAOMICPIOP1
from .piop2 import DataladAOMICPIOP2 from .piop2 import DataladAOMICPIOP2
__all__ = ["DataladAOMICID1000", "DataladAOMICPIOP1", "DataladAOMICPIOP2"]

View file

@ -14,6 +14,9 @@ from ...api.decorators import register_datagrabber
from ..pattern_datalad import PatternDataladDataGrabber from ..pattern_datalad import PatternDataladDataGrabber
__all__ = ["DataladAOMICID1000"]
@register_datagrabber @register_datagrabber
class DataladAOMICID1000(PatternDataladDataGrabber): class DataladAOMICID1000(PatternDataladDataGrabber):
"""Concrete implementation for datalad-based data fetching of AOMIC ID1000. """Concrete implementation for datalad-based data fetching of AOMIC ID1000.

View file

@ -16,6 +16,9 @@ from ...utils import raise_error
from ..pattern_datalad import PatternDataladDataGrabber from ..pattern_datalad import PatternDataladDataGrabber
__all__ = ["DataladAOMICPIOP1"]
@register_datagrabber @register_datagrabber
class DataladAOMICPIOP1(PatternDataladDataGrabber): class DataladAOMICPIOP1(PatternDataladDataGrabber):
"""Concrete implementation for pattern-based data fetching of AOMIC PIOP1. """Concrete implementation for pattern-based data fetching of AOMIC PIOP1.

View file

@ -16,6 +16,9 @@ from ...utils import raise_error
from ..pattern_datalad import PatternDataladDataGrabber from ..pattern_datalad import PatternDataladDataGrabber
__all__ = ["DataladAOMICPIOP2"]
@register_datagrabber @register_datagrabber
class DataladAOMICPIOP2(PatternDataladDataGrabber): class DataladAOMICPIOP2(PatternDataladDataGrabber):
"""Concrete implementation for pattern-based data fetching of AOMIC PIOP2. """Concrete implementation for pattern-based data fetching of AOMIC PIOP2.

View file

@ -14,6 +14,9 @@ from ..utils import logger, raise_error
from .utils import validate_types from .utils import validate_types
__all__ = ["BaseDataGrabber"]
class BaseDataGrabber(ABC, UpdateMetaMixin): class BaseDataGrabber(ABC, UpdateMetaMixin):
"""Abstract base class for DataGrabber. """Abstract base class for DataGrabber.

View file

@ -21,6 +21,9 @@ from ..utils import logger, raise_error, warn_with_log
from .base import BaseDataGrabber from .base import BaseDataGrabber
__all__ = ["DataladDataGrabber"]
class DataladDataGrabber(BaseDataGrabber): class DataladDataGrabber(BaseDataGrabber):
"""Abstract base class for datalad-based data fetching. """Abstract base class for datalad-based data fetching.

View file

@ -5,3 +5,6 @@
from .hcp1200 import HCP1200 from .hcp1200 import HCP1200
from .datalad_hcp1200 import DataladHCP1200 from .datalad_hcp1200 import DataladHCP1200
__all__ = ["HCP1200", "DataladHCP1200"]

View file

@ -14,6 +14,9 @@ from ...api.decorators import register_datagrabber
from .hcp1200 import HCP1200 from .hcp1200 import HCP1200
__all__ = ["DataladHCP1200"]
@register_datagrabber @register_datagrabber
class DataladHCP1200(DataladDataGrabber, HCP1200): class DataladHCP1200(DataladDataGrabber, HCP1200):
"""Concrete implementation for datalad-based data fetching of HCP1200. """Concrete implementation for datalad-based data fetching of HCP1200.

View file

@ -14,6 +14,9 @@ from ..pattern import PatternDataGrabber
from ..utils import raise_error from ..utils import raise_error
__all__ = ["HCP1200"]
@register_datagrabber @register_datagrabber
class HCP1200(PatternDataGrabber): class HCP1200(PatternDataGrabber):
"""Concrete implementation for pattern-based data fetching of HCP1200. """Concrete implementation for pattern-based data fetching of HCP1200.

View file

@ -11,6 +11,9 @@ from ..utils import raise_error
from .base import BaseDataGrabber from .base import BaseDataGrabber
__all__ = ["MultipleDataGrabber"]
class MultipleDataGrabber(BaseDataGrabber): class MultipleDataGrabber(BaseDataGrabber):
"""Concrete implementation for multi sourced data fetching. """Concrete implementation for multi sourced data fetching.

View file

@ -18,6 +18,9 @@ from .base import BaseDataGrabber
from .utils import validate_patterns, validate_replacements from .utils import validate_patterns, validate_replacements
__all__ = ["PatternDataGrabber"]
# Accepted formats for confounds specification # Accepted formats for confounds specification
_CONFOUNDS_FORMATS = ("fmriprep", "adhoc") _CONFOUNDS_FORMATS = ("fmriprep", "adhoc")

View file

@ -12,6 +12,9 @@ from .datalad_base import DataladDataGrabber
from .pattern import PatternDataGrabber from .pattern import PatternDataGrabber
__all__ = ["PatternDataladDataGrabber"]
@register_datagrabber @register_datagrabber
class PatternDataladDataGrabber(DataladDataGrabber, PatternDataGrabber): class PatternDataladDataGrabber(DataladDataGrabber, PatternDataGrabber):
"""Concrete implementation for pattern and datalad based data fetching. """Concrete implementation for pattern and datalad based data fetching.

View file

@ -9,6 +9,9 @@ from typing import Dict, List
from ..utils import logger, raise_error from ..utils import logger, raise_error
__all__ = ["validate_types", "validate_replacements", "validate_patterns"]
# Define schema for pattern-based datagrabber's patterns # Define schema for pattern-based datagrabber's patterns
PATTERNS_SCHEMA = { PATTERNS_SCHEMA = {
"T1w": { "T1w": {

View file

@ -6,3 +6,6 @@
# License: AGPL # License: AGPL
from .default import DefaultDataReader from .default import DefaultDataReader
__all__ = ["DefaultDataReader"]

View file

@ -15,6 +15,9 @@ from ..pipeline import PipelineStepMixin, UpdateMetaMixin
from ..utils.logging import logger, warn_with_log from ..utils.logging import logger, warn_with_log
__all__ = ["DefaultDataReader"]
# Map each file extension to a type # Map each file extension to a type
_extensions = { _extensions = {
".nii": "NIFTI", ".nii": "NIFTI",

View file

@ -24,3 +24,24 @@ from .temporal_snr import (
TemporalSNRSpheres, TemporalSNRSpheres,
) )
from .brainprint import BrainPrint from .brainprint import BrainPrint
__all__ = [
"BaseMarker",
"MarkerCollection",
"RSSETSMarker",
"ParcelAggregation",
"SphereAggregation",
"FunctionalConnectivityParcels",
"FunctionalConnectivitySpheres",
"CrossParcellationFC",
"EdgeCentricFCParcels",
"EdgeCentricFCSpheres",
"ReHoParcels",
"ReHoSpheres",
"ALFFParcels",
"ALFFSpheres",
"TemporalSNRParcels",
"TemporalSNRSpheres",
"BrainPrint",
]

View file

@ -15,16 +15,22 @@ if TYPE_CHECKING:
from junifer.storage import BaseFeatureStorage from junifer.storage import BaseFeatureStorage
__all__ = ["BaseMarker"]
class BaseMarker(ABC, PipelineStepMixin, UpdateMetaMixin): class BaseMarker(ABC, PipelineStepMixin, UpdateMetaMixin):
"""Abstract base class for all markers. """Abstract base class for all markers.
For every interface that is required, one needs to provide a concrete
implementation of this abstract class.
Parameters Parameters
---------- ----------
on : str or list of str on : str or list of str or None, optional
The kind of data to apply the marker to. By default, will work on all The data type to apply the marker on. If None,
available data. will work on all available data types (default None).
name : str, optional 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). name of the marker (default None).
Raises Raises
@ -192,17 +198,25 @@ class BaseMarker(ABC, PipelineStepMixin, UpdateMetaMixin):
for type_ in self._on: for type_ in self._on:
if type_ in input.keys(): if type_ in input.keys():
logger.info(f"Computing {type_}") logger.info(f"Computing {type_}")
# Get data dict for data type
t_input = input[type_] t_input = input[type_]
# Pass the other data types as extra input, removing
# the current type
extra_input = input.copy() extra_input = input.copy()
extra_input.pop(type_) 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 = t_input["meta"].copy()
t_meta["type"] = type_ t_meta["type"] = type_
# Compute marker
t_out = self.compute(input=t_input, extra_input=extra_input) t_out = self.compute(input=t_input, extra_input=extra_input)
t_out["meta"] = t_meta t_out["meta"] = t_meta
# Update metadata for step
self.update_meta(t_out, "marker") self.update_meta(t_out, "marker")
# Check storage
if storage is not None: if storage is not None:
logger.info(f"Storing in {storage}") logger.info(f"Storing in {storage}")
self.store(type_=type_, out=t_out, storage=storage) self.store(type_=type_, out=t_out, storage=storage)

View file

@ -43,6 +43,9 @@ if TYPE_CHECKING:
from junifer.storage import BaseFeatureStorage from junifer.storage import BaseFeatureStorage
__all__ = ["BrainPrint"]
@register_marker @register_marker
class BrainPrint(BaseMarker): class BrainPrint(BaseMarker):
"""Class for BrainPrint. """Class for BrainPrint.

View file

@ -19,6 +19,9 @@ if TYPE_CHECKING:
from junifer.datagrabber import BaseDataGrabber from junifer.datagrabber import BaseDataGrabber
__all__ = ["MarkerCollection"]
class MarkerCollection: class MarkerCollection:
"""Class for marker collection. """Class for marker collection.

View file

@ -25,3 +25,13 @@ else:
from .weighted_perm_entropy import WeightedPermEntropy from .weighted_perm_entropy import WeightedPermEntropy
from .sample_entropy import SampleEntropy from .sample_entropy import SampleEntropy
from .multiscale_entropy_auc import MultiscaleEntropyAUC from .multiscale_entropy_auc import MultiscaleEntropyAUC
__all__ = [
"HurstExponent",
"RangeEntropy",
"RangeEntropyAUC",
"PermEntropy",
"WeightedPermEntropy",
"SampleEntropy",
"MultiscaleEntropyAUC",
]

View file

@ -24,6 +24,9 @@ if TYPE_CHECKING:
import numpy as np import numpy as np
__all__ = ["ComplexityBase"]
class ComplexityBase(BaseMarker): class ComplexityBase(BaseMarker):
"""Base class for complexity computation. """Base class for complexity computation.

View file

@ -14,6 +14,9 @@ from ...utils import logger, warn_with_log
from .complexity_base import ComplexityBase from .complexity_base import ComplexityBase
__all__ = ["HurstExponent"]
@register_marker @register_marker
class HurstExponent(ComplexityBase): class HurstExponent(ComplexityBase):
"""Class for Hurst exponent of a time series. """Class for Hurst exponent of a time series.

View file

@ -14,6 +14,9 @@ from ...utils import logger, warn_with_log
from .complexity_base import ComplexityBase from .complexity_base import ComplexityBase
__all__ = ["MultiscaleEntropyAUC"]
@register_marker @register_marker
class MultiscaleEntropyAUC(ComplexityBase): class MultiscaleEntropyAUC(ComplexityBase):
"""Class for AUC of multiscale entropy of a time series. """Class for AUC of multiscale entropy of a time series.

View file

@ -14,6 +14,9 @@ from ...utils import logger, warn_with_log
from .complexity_base import ComplexityBase from .complexity_base import ComplexityBase
__all__ = ["PermEntropy"]
@register_marker @register_marker
class PermEntropy(ComplexityBase): class PermEntropy(ComplexityBase):
"""Class for permutation entropy of a time series. """Class for permutation entropy of a time series.

View file

@ -14,6 +14,9 @@ from ...utils import logger, warn_with_log
from .complexity_base import ComplexityBase from .complexity_base import ComplexityBase
__all__ = ["RangeEntropy"]
@register_marker @register_marker
class RangeEntropy(ComplexityBase): class RangeEntropy(ComplexityBase):
"""Class for range entropy of a time series. """Class for range entropy of a time series.

View file

@ -14,6 +14,9 @@ from ...utils import logger, warn_with_log
from .complexity_base import ComplexityBase from .complexity_base import ComplexityBase
__all__ = ["RangeEntropyAUC"]
@register_marker @register_marker
class RangeEntropyAUC(ComplexityBase): class RangeEntropyAUC(ComplexityBase):
"""Class for AUC of range entropy values of a time series over r = 0 to 1. """Class for AUC of range entropy values of a time series over r = 0 to 1.

View file

@ -14,6 +14,9 @@ from ...utils import logger, warn_with_log
from .complexity_base import ComplexityBase from .complexity_base import ComplexityBase
__all__ = ["SampleEntropy"]
@register_marker @register_marker
class SampleEntropy(ComplexityBase): class SampleEntropy(ComplexityBase):
"""Class for sample entropy of a time series. """Class for sample entropy of a time series.

View file

@ -14,6 +14,7 @@ pytest.importorskip("neurokit2")
from junifer.datareader import DefaultDataReader # noqa: E402 from junifer.datareader import DefaultDataReader # noqa: E402
from junifer.markers.complexity import HurstExponent # 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.storage import SQLiteFeatureStorage # noqa: E402
from junifer.testing.datagrabbers import ( # noqa: E402 from junifer.testing.datagrabbers import ( # noqa: E402
SPMAuditoryTestingDataGrabber, SPMAuditoryTestingDataGrabber,
@ -24,6 +25,9 @@ from junifer.testing.datagrabbers import ( # noqa: E402
PARCELLATION = "Schaefer100x17" PARCELLATION = "Schaefer100x17"
@pytest.mark.skipif(
_check_ants() is False, reason="requires ANTs to be in PATH"
)
def test_compute() -> None: def test_compute() -> None:
"""Test HurstExponent compute().""" """Test HurstExponent compute()."""
with SPMAuditoryTestingDataGrabber() as dg: with SPMAuditoryTestingDataGrabber() as dg:
@ -45,6 +49,9 @@ def test_get_output_type() -> None:
assert marker.get_output_type("BOLD") == "vector" 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: def test_store(tmp_path: Path) -> None:
"""Test HurstExponent store(). """Test HurstExponent store().

View file

@ -13,6 +13,7 @@ pytest.importorskip("neurokit2")
from junifer.datareader import DefaultDataReader # noqa: E402 from junifer.datareader import DefaultDataReader # noqa: E402
from junifer.markers.complexity import MultiscaleEntropyAUC # 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.storage import SQLiteFeatureStorage # noqa: E402
from junifer.testing.datagrabbers import ( # noqa: E402 from junifer.testing.datagrabbers import ( # noqa: E402
SPMAuditoryTestingDataGrabber, SPMAuditoryTestingDataGrabber,
@ -23,6 +24,9 @@ from junifer.testing.datagrabbers import ( # noqa: E402
PARCELLATION = "Schaefer100x17" PARCELLATION = "Schaefer100x17"
@pytest.mark.skipif(
_check_ants() is False, reason="requires ANTs to be in PATH"
)
def test_compute() -> None: def test_compute() -> None:
"""Test MultiscaleEntropyAUC compute().""" """Test MultiscaleEntropyAUC compute()."""
with SPMAuditoryTestingDataGrabber() as dg: with SPMAuditoryTestingDataGrabber() as dg:
@ -44,6 +48,9 @@ def test_get_output_type() -> None:
assert marker.get_output_type("BOLD") == "vector" 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: def test_store(tmp_path: Path) -> None:
"""Test MultiscaleEntropyAUC store(). """Test MultiscaleEntropyAUC store().

View file

@ -13,6 +13,7 @@ pytest.importorskip("neurokit2")
from junifer.datareader import DefaultDataReader # noqa: E402 from junifer.datareader import DefaultDataReader # noqa: E402
from junifer.markers.complexity import PermEntropy # 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.storage import SQLiteFeatureStorage # noqa: E402
from junifer.testing.datagrabbers import ( # noqa: E402 from junifer.testing.datagrabbers import ( # noqa: E402
SPMAuditoryTestingDataGrabber, SPMAuditoryTestingDataGrabber,
@ -23,6 +24,9 @@ from junifer.testing.datagrabbers import ( # noqa: E402
PARCELLATION = "Schaefer100x17" PARCELLATION = "Schaefer100x17"
@pytest.mark.skipif(
_check_ants() is False, reason="requires ANTs to be in PATH"
)
def test_compute() -> None: def test_compute() -> None:
"""Test PermEntropy compute().""" """Test PermEntropy compute()."""
with SPMAuditoryTestingDataGrabber() as dg: with SPMAuditoryTestingDataGrabber() as dg:
@ -44,6 +48,9 @@ def test_get_output_type() -> None:
assert marker.get_output_type("BOLD") == "vector" 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: def test_store(tmp_path: Path) -> None:
"""Test PermEntropy store(). """Test PermEntropy store().

View file

@ -14,6 +14,7 @@ pytest.importorskip("neurokit2")
from junifer.datareader import DefaultDataReader # noqa: E402 from junifer.datareader import DefaultDataReader # noqa: E402
from junifer.markers.complexity import RangeEntropy # 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.storage import SQLiteFeatureStorage # noqa: E402
from junifer.testing.datagrabbers import ( # noqa: E402 from junifer.testing.datagrabbers import ( # noqa: E402
SPMAuditoryTestingDataGrabber, SPMAuditoryTestingDataGrabber,
@ -24,6 +25,9 @@ from junifer.testing.datagrabbers import ( # noqa: E402
PARCELLATION = "Schaefer100x17" PARCELLATION = "Schaefer100x17"
@pytest.mark.skipif(
_check_ants() is False, reason="requires ANTs to be in PATH"
)
def test_compute() -> None: def test_compute() -> None:
"""Test RangeEntropy compute().""" """Test RangeEntropy compute()."""
with SPMAuditoryTestingDataGrabber() as dg: with SPMAuditoryTestingDataGrabber() as dg:
@ -45,6 +49,9 @@ def test_get_output_type() -> None:
assert marker.get_output_type("BOLD") == "vector" 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: def test_store(tmp_path: Path) -> None:
"""Test RangeEntropy store(). """Test RangeEntropy store().

View file

@ -14,6 +14,7 @@ pytest.importorskip("neurokit2")
from junifer.datareader import DefaultDataReader # noqa: E402 from junifer.datareader import DefaultDataReader # noqa: E402
from junifer.markers.complexity import RangeEntropyAUC # 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.storage import SQLiteFeatureStorage # noqa: E402
from junifer.testing.datagrabbers import ( # noqa: E402 from junifer.testing.datagrabbers import ( # noqa: E402
SPMAuditoryTestingDataGrabber, SPMAuditoryTestingDataGrabber,
@ -24,6 +25,9 @@ from junifer.testing.datagrabbers import ( # noqa: E402
PARCELLATION = "Schaefer100x17" PARCELLATION = "Schaefer100x17"
@pytest.mark.skipif(
_check_ants() is False, reason="requires ANTs to be in PATH"
)
def test_compute() -> None: def test_compute() -> None:
"""Test RangeEntropyAUC compute().""" """Test RangeEntropyAUC compute()."""
with SPMAuditoryTestingDataGrabber() as dg: with SPMAuditoryTestingDataGrabber() as dg:
@ -45,6 +49,9 @@ def test_get_output_type() -> None:
assert marker.get_output_type("BOLD") == "vector" 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: def test_store(tmp_path: Path) -> None:
"""Test RangeEntropyAUC store(). """Test RangeEntropyAUC store().

View file

@ -13,6 +13,7 @@ pytest.importorskip("neurokit2")
from junifer.datareader import DefaultDataReader # noqa: E402 from junifer.datareader import DefaultDataReader # noqa: E402
from junifer.markers.complexity import SampleEntropy # 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.storage import SQLiteFeatureStorage # noqa: E402
from junifer.testing.datagrabbers import ( # noqa: E402 from junifer.testing.datagrabbers import ( # noqa: E402
SPMAuditoryTestingDataGrabber, SPMAuditoryTestingDataGrabber,
@ -23,6 +24,9 @@ from junifer.testing.datagrabbers import ( # noqa: E402
PARCELLATION = "Schaefer100x17" PARCELLATION = "Schaefer100x17"
@pytest.mark.skipif(
_check_ants() is False, reason="requires ANTs to be in PATH"
)
def test_compute() -> None: def test_compute() -> None:
"""Test SampleEntropy compute().""" """Test SampleEntropy compute()."""
with SPMAuditoryTestingDataGrabber() as dg: with SPMAuditoryTestingDataGrabber() as dg:
@ -44,6 +48,9 @@ def test_get_output_type() -> None:
assert marker.get_output_type("BOLD") == "vector" 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: def test_store(tmp_path: Path) -> None:
"""Test SampleEntropy store(). """Test SampleEntropy store().

View file

@ -13,6 +13,7 @@ pytest.importorskip("neurokit2")
from junifer.datareader import DefaultDataReader # noqa: E402 from junifer.datareader import DefaultDataReader # noqa: E402
from junifer.markers.complexity import WeightedPermEntropy # 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.storage import SQLiteFeatureStorage # noqa: E402
from junifer.testing.datagrabbers import ( # noqa: E402 from junifer.testing.datagrabbers import ( # noqa: E402
SPMAuditoryTestingDataGrabber, SPMAuditoryTestingDataGrabber,
@ -23,6 +24,9 @@ from junifer.testing.datagrabbers import ( # noqa: E402
PARCELLATION = "Schaefer100x17" PARCELLATION = "Schaefer100x17"
@pytest.mark.skipif(
_check_ants() is False, reason="requires ANTs to be in PATH"
)
def test_compute() -> None: def test_compute() -> None:
"""Test WeightedPermEntropy compute().""" """Test WeightedPermEntropy compute()."""
with SPMAuditoryTestingDataGrabber() as dg: with SPMAuditoryTestingDataGrabber() as dg:
@ -44,6 +48,9 @@ def test_get_output_type() -> None:
assert marker.get_output_type("BOLD") == "vector" 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: def test_store(tmp_path: Path) -> None:
"""Test WeightedPermEntropy store(). """Test WeightedPermEntropy store().

View file

@ -14,6 +14,9 @@ from ...utils import logger, warn_with_log
from .complexity_base import ComplexityBase from .complexity_base import ComplexityBase
__all__ = ["WeightedPermEntropy"]
@register_marker @register_marker
class WeightedPermEntropy(ComplexityBase): class WeightedPermEntropy(ComplexityBase):
"""Class for weighted permutation entropy of a time series. """Class for weighted permutation entropy of a time series.

View file

@ -17,6 +17,9 @@ from .parcel_aggregation import ParcelAggregation
from .utils import _ets from .utils import _ets
__all__ = ["RSSETSMarker"]
@register_marker @register_marker
class RSSETSMarker(BaseMarker): class RSSETSMarker(BaseMarker):
"""Class for root sum of squares of edgewise timeseries. """Class for root sum of squares of edgewise timeseries.

View file

@ -5,3 +5,6 @@
from .falff_parcels import ALFFParcels from .falff_parcels import ALFFParcels
from .falff_spheres import ALFFSpheres from .falff_spheres import ALFFSpheres
__all__ = ["ALFFParcels", "ALFFSpheres"]

View file

@ -26,6 +26,9 @@ if TYPE_CHECKING:
from nibabel import Nifti1Image from nibabel import Nifti1Image
__all__ = ["AFNIALFF"]
@singleton @singleton
class AFNIALFF: class AFNIALFF:
"""Class for computing ALFF using AFNI. """Class for computing ALFF using AFNI.

View file

@ -27,6 +27,9 @@ if TYPE_CHECKING:
from nibabel import Nifti1Image from nibabel import Nifti1Image
__all__ = ["JuniferALFF"]
@singleton @singleton
class JuniferALFF: class JuniferALFF:
"""Class for computing ALFF using junifer. """Class for computing ALFF using junifer.

View file

@ -29,6 +29,9 @@ if TYPE_CHECKING:
from nibabel import Nifti1Image from nibabel import Nifti1Image
__all__ = ["ALFFBase"]
class ALFFBase(BaseMarker): class ALFFBase(BaseMarker):
"""Base class for (fractional) Amplitude Low Frequency Fluctuation. """Base class for (fractional) Amplitude Low Frequency Fluctuation.

View file

@ -14,6 +14,9 @@ from ..parcel_aggregation import ParcelAggregation
from .falff_base import ALFFBase from .falff_base import ALFFBase
__all__ = ["ALFFParcels"]
@register_marker @register_marker
class ALFFParcels(ALFFBase): class ALFFParcels(ALFFBase):
"""Class for ALFF / fALFF on parcels. """Class for ALFF / fALFF on parcels.

View file

@ -14,6 +14,9 @@ from ..sphere_aggregation import SphereAggregation
from .falff_base import ALFFBase from .falff_base import ALFFBase
__all__ = ["ALFFSpheres"]
@register_marker @register_marker
class ALFFSpheres(ALFFBase): class ALFFSpheres(ALFFBase):
"""Class for computing ALFF / fALFF on spheres. """Class for computing ALFF / fALFF on spheres.

View file

@ -8,3 +8,12 @@ from .functional_connectivity_spheres import FunctionalConnectivitySpheres
from .crossparcellation_functional_connectivity import CrossParcellationFC from .crossparcellation_functional_connectivity import CrossParcellationFC
from .edge_functional_connectivity_parcels import EdgeCentricFCParcels from .edge_functional_connectivity_parcels import EdgeCentricFCParcels
from .edge_functional_connectivity_spheres import EdgeCentricFCSpheres from .edge_functional_connectivity_spheres import EdgeCentricFCSpheres
__all__ = [
"FunctionalConnectivityParcels",
"FunctionalConnectivitySpheres",
"CrossParcellationFC",
"EdgeCentricFCParcels",
"EdgeCentricFCSpheres",
]

View file

@ -15,6 +15,9 @@ from ..parcel_aggregation import ParcelAggregation
from ..utils import _correlate_dataframes from ..utils import _correlate_dataframes
__all__ = ["CrossParcellationFC"]
@register_marker @register_marker
class CrossParcellationFC(BaseMarker): class CrossParcellationFC(BaseMarker):
"""Class for calculating parcel-wise correlations with 2 parcellations. """Class for calculating parcel-wise correlations with 2 parcellations.

View file

@ -12,6 +12,9 @@ from ..utils import _ets
from .functional_connectivity_base import FunctionalConnectivityBase from .functional_connectivity_base import FunctionalConnectivityBase
__all__ = ["EdgeCentricFCParcels"]
@register_marker @register_marker
class EdgeCentricFCParcels(FunctionalConnectivityBase): class EdgeCentricFCParcels(FunctionalConnectivityBase):
"""Class for edge-centric FC using parcellations. """Class for edge-centric FC using parcellations.

View file

@ -12,6 +12,9 @@ from ..utils import _ets, raise_error
from .functional_connectivity_base import FunctionalConnectivityBase from .functional_connectivity_base import FunctionalConnectivityBase
__all__ = ["EdgeCentricFCSpheres"]
@register_marker @register_marker
class EdgeCentricFCSpheres(FunctionalConnectivityBase): class EdgeCentricFCSpheres(FunctionalConnectivityBase):
"""Class for edge-centric FC using coordinates (spheres). """Class for edge-centric FC using coordinates (spheres).

View file

@ -14,6 +14,9 @@ from ...utils import raise_error
from ..base import BaseMarker from ..base import BaseMarker
__all__ = ["FunctionalConnectivityBase"]
class FunctionalConnectivityBase(BaseMarker): class FunctionalConnectivityBase(BaseMarker):
"""Abstract base class for functional connectivity markers. """Abstract base class for functional connectivity markers.

View file

@ -12,6 +12,9 @@ from ..parcel_aggregation import ParcelAggregation
from .functional_connectivity_base import FunctionalConnectivityBase from .functional_connectivity_base import FunctionalConnectivityBase
__all__ = ["FunctionalConnectivityParcels"]
@register_marker @register_marker
class FunctionalConnectivityParcels(FunctionalConnectivityBase): class FunctionalConnectivityParcels(FunctionalConnectivityBase):
"""Class for functional connectivity using parcellations. """Class for functional connectivity using parcellations.

View file

@ -13,6 +13,9 @@ from ..utils import raise_error
from .functional_connectivity_base import FunctionalConnectivityBase from .functional_connectivity_base import FunctionalConnectivityBase
__all__ = ["FunctionalConnectivitySpheres"]
@register_marker @register_marker
class FunctionalConnectivitySpheres(FunctionalConnectivityBase): class FunctionalConnectivitySpheres(FunctionalConnectivityBase):
"""Class for functional connectivity using coordinates (spheres). """Class for functional connectivity using coordinates (spheres).

View file

@ -17,6 +17,9 @@ from ..utils import logger, raise_error, warn_with_log
from .base import BaseMarker from .base import BaseMarker
__all__ = ["ParcelAggregation"]
@register_marker @register_marker
class ParcelAggregation(BaseMarker): class ParcelAggregation(BaseMarker):
"""Class for parcel aggregation. """Class for parcel aggregation.

View file

@ -5,3 +5,6 @@
from .reho_parcels import ReHoParcels from .reho_parcels import ReHoParcels
from .reho_spheres import ReHoSpheres from .reho_spheres import ReHoSpheres
__all__ = ["ReHoParcels", "ReHoSpheres"]

View file

@ -26,6 +26,9 @@ if TYPE_CHECKING:
from nibabel import Nifti1Image from nibabel import Nifti1Image
__all__ = ["AFNIReHo"]
@singleton @singleton
class AFNIReHo: class AFNIReHo:
"""Class for computing ReHo using AFNI. """Class for computing ReHo using AFNI.

View file

@ -28,6 +28,9 @@ if TYPE_CHECKING:
from nibabel import Nifti1Image from nibabel import Nifti1Image
__all__ = ["JuniferReHo"]
@singleton @singleton
class JuniferReHo: class JuniferReHo:
"""Class for computing ReHo using junifer. """Class for computing ReHo using junifer.

View file

@ -26,6 +26,8 @@ from ._junifer_reho import JuniferReHo
if TYPE_CHECKING: if TYPE_CHECKING:
from nibabel import Nifti1Image from nibabel import Nifti1Image
__all__ = ["ReHoBase"]
class ReHoBase(BaseMarker): class ReHoBase(BaseMarker):
"""Base class for regional homogeneity computation. """Base class for regional homogeneity computation.

View file

@ -14,6 +14,9 @@ from ..parcel_aggregation import ParcelAggregation
from .reho_base import ReHoBase from .reho_base import ReHoBase
__all__ = ["ReHoParcels"]
@register_marker @register_marker
class ReHoParcels(ReHoBase): class ReHoParcels(ReHoBase):
"""Class for regional homogeneity on parcels. """Class for regional homogeneity on parcels.

View file

@ -14,6 +14,9 @@ from ..sphere_aggregation import SphereAggregation
from .reho_base import ReHoBase from .reho_base import ReHoBase
__all__ = ["ReHoSpheres"]
@register_marker @register_marker
class ReHoSpheres(ReHoBase): class ReHoSpheres(ReHoBase):
"""Class for regional homogeneity on spheres. """Class for regional homogeneity on spheres.

View file

@ -14,6 +14,9 @@ from ..utils import logger, raise_error, warn_with_log
from .base import BaseMarker from .base import BaseMarker
__all__ = ["SphereAggregation"]
@register_marker @register_marker
class SphereAggregation(BaseMarker): class SphereAggregation(BaseMarker):
"""Class for sphere aggregation. """Class for sphere aggregation.

View file

@ -5,3 +5,6 @@
from .temporal_snr_parcels import TemporalSNRParcels from .temporal_snr_parcels import TemporalSNRParcels
from .temporal_snr_spheres import TemporalSNRSpheres from .temporal_snr_spheres import TemporalSNRSpheres
__all__ = ["TemporalSNRParcels", "TemporalSNRSpheres"]

View file

@ -13,6 +13,9 @@ from ...utils import raise_error
from ..base import BaseMarker from ..base import BaseMarker
__all__ = ["TemporalSNRBase"]
class TemporalSNRBase(BaseMarker): class TemporalSNRBase(BaseMarker):
"""Abstract base class for temporal SNR markers. """Abstract base class for temporal SNR markers.

View file

@ -10,6 +10,9 @@ from ..parcel_aggregation import ParcelAggregation
from .temporal_snr_base import TemporalSNRBase from .temporal_snr_base import TemporalSNRBase
__all__ = ["TemporalSNRParcels"]
@register_marker @register_marker
class TemporalSNRParcels(TemporalSNRBase): class TemporalSNRParcels(TemporalSNRBase):
"""Class for temporal signal-to-noise ratio using parcellations. """Class for temporal signal-to-noise ratio using parcellations.

View file

@ -11,6 +11,9 @@ from ..utils import raise_error
from .temporal_snr_base import TemporalSNRBase from .temporal_snr_base import TemporalSNRBase
__all__ = ["TemporalSNRSpheres"]
@register_marker @register_marker
class TemporalSNRSpheres(TemporalSNRBase): class TemporalSNRSpheres(TemporalSNRBase):
"""Class for temporal signal-to-noise ratio using coordinates (spheres). """Class for temporal signal-to-noise ratio using coordinates (spheres).

View file

@ -4,3 +4,6 @@
# License: AGPL # License: AGPL
from .read_transform import read_transform from .read_transform import read_transform
__all__ = ["read_transform"]

View file

@ -15,6 +15,9 @@ if TYPE_CHECKING:
from junifer.storage import BaseFeatureStorage from junifer.storage import BaseFeatureStorage
__all__ = ["read_transform"]
def read_transform( def read_transform(
storage: Type["BaseFeatureStorage"], storage: Type["BaseFeatureStorage"],
transform: str, transform: str,

View file

@ -7,3 +7,11 @@ from . import registry
from .pipeline_step_mixin import PipelineStepMixin from .pipeline_step_mixin import PipelineStepMixin
from .update_meta_mixin import UpdateMetaMixin from .update_meta_mixin import UpdateMetaMixin
from .workdir_manager import WorkDirManager from .workdir_manager import WorkDirManager
__all__ = [
"registry",
"PipelineStepMixin",
"UpdateMetaMixin",
"WorkDirManager",
]

View file

@ -17,6 +17,9 @@ from ..utils import raise_error
from .utils import check_ext_dependencies from .utils import check_ext_dependencies
__all__ = ["PipelineStepMixin"]
class PipelineStepMixin: class PipelineStepMixin:
"""Mixin class for a pipeline step.""" """Mixin class for a pipeline step."""

View file

@ -16,6 +16,9 @@ if TYPE_CHECKING:
from .pipeline_step_mixin import PipelineStepMixin from .pipeline_step_mixin import PipelineStepMixin
__all__ = ["register", "get_step_names", "get_class", "build"]
# Define valid steps for operation # Define valid steps for operation
_VALID_STEPS: List[str] = [ _VALID_STEPS: List[str] = [
"datagrabber", "datagrabber",

View file

@ -6,6 +6,9 @@
from typing import Any, Dict, Type from typing import Any, Dict, Type
__all__ = ["singleton"]
def singleton(cls: Type) -> Type: def singleton(cls: Type) -> Type:
"""Make a class singleton. """Make a class singleton.

Some files were not shown because too many files have changed in this diff Show more