[MAINT]: Repository maintenance #441

Merged
synchon merged 24 commits from chore/ruff-format into main 2025-04-10 11:08:49 +00:00
87 changed files with 583 additions and 1403 deletions

View file

@ -17,24 +17,22 @@ repos:
- id: trailing-whitespace - id: trailing-whitespace
args: [--markdown-linebreak-ext=md] args: [--markdown-linebreak-ext=md]
- repo: https://github.com/abravalheri/validate-pyproject - repo: https://github.com/abravalheri/validate-pyproject
rev: v0.23 rev: v0.24.1
hooks: hooks:
- id: validate-pyproject - id: validate-pyproject
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 24.10.0
hooks:
- id: black
exclude: ^(docs/|examples/|tools/)
args: [--check]
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.3 rev: v0.11.2
hooks: hooks:
- id: ruff - id: ruff
types_or: [python, jupyter] types_or: [python, jupyter]
exclude: ^(__init__.py) exclude: ^(__init__.py)
args: [--output-format, grouped, --show-fixes] args: [--output-format, grouped, --show-fixes]
- id: ruff-format
types_or: [python, jupyter]
exclude: ^(__init__.py)
args: [--check, --diff]
- repo: https://github.com/codespell-project/codespell - repo: https://github.com/codespell-project/codespell
rev: v2.4.0 rev: v2.4.1
hooks: hooks:
- id: codespell - id: codespell
exclude: ^(.github/|docs/) exclude: ^(.github/|docs/)
@ -47,10 +45,3 @@ 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.19.1"
hooks:
- id: blacken-docs
additional_dependencies:
- black==24.4.2
args: [-l 79]

View file

@ -8,7 +8,6 @@
[![Anaconda-Server Badge](https://anaconda.org/conda-forge/junifer/badges/version.svg)](https://anaconda.org/conda-forge/junifer) [![Anaconda-Server Badge](https://anaconda.org/conda-forge/junifer/badges/version.svg)](https://anaconda.org/conda-forge/junifer)
![GitHub](https://img.shields.io/github/license/juaml/junifer?style=flat-square) ![GitHub](https://img.shields.io/github/license/juaml/junifer?style=flat-square)
![Codecov](https://img.shields.io/codecov/c/github/juaml/junifer?style=flat-square) ![Codecov](https://img.shields.io/codecov/c/github/juaml/junifer?style=flat-square)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg?style=flat-square)](https://github.com/psf/black)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json)](https://github.com/charliermarsh/ruff) [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json)](https://github.com/charliermarsh/ruff)
[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit) [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.8176570.svg)](https://doi.org/10.5281/zenodo.8176570) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.8176570.svg)](https://doi.org/10.5281/zenodo.8176570)

View file

@ -1,33 +1,45 @@
name: junifer-dev name: junifer-dev
channels: channels:
- conda-forge - conda-forge
- defaults
dependencies: dependencies:
- python>=3.10,<=3.11 - python>=3.10,<=3.13
- click=8.1.* - click>=8.1.3,<8.2
- numpy>=1.22,<1.27 - numpy>=1.26.0,<2.0.0
- pandas>=1.4.0,<2.2 - scipy>=1.10.0,<=1.15.0
- nibabel>=3.2.0,<5.2 - pandas>=2.0.0,<2.3.0
- nilearn>=0.9.0,<=0.10.1 - nibabel>=5.2.0,<5.4.0
- sqlalchemy>=1.4.27,<= 2.0.21 - nilearn>=0.10.3,<=0.10.4
- ruamel.yaml=0.17.* - sqlalchemy>=2.0.25,<=2.1.0
- h5py>=3.8,<=3.9 - ruamel.yaml>=0.17,<0.19
- seaborn>=0.11,<=0.13 - h5py>=3.10
- sphinx>=5.3,<7.3 - tqdm>=4.66.1,<4.67.0
- sphinx-gallery>=0.11.0,<0.15.0 - templateflow>=23.0.0
- furo>=2022.9.29,<2023.10.0 - lapy>=1.0.0,<2.0.0
- numpydoc>=1.5.0,<1.6 - lazy_loader==0.4
- importlib_metadata
- looseversion==1.3.0
- bctpy==0.6.0
- neurokit2>=0.1.7
- seaborn>=0.13.0,<0.14.0
- sphinx>=7.3.0,<8.1.0
- sphinx-gallery>=0.17.0,<0.18.0
- furo>=2024.4.27,<2024.9.0
- numpydoc>=1.6.0,<1.9.0
- sphinx-copybutton>=0.5.1,<0.5.3 - sphinx-copybutton>=0.5.1,<0.5.3
- towncrier>=22.12.0,<23.7 - towncrier>=23.10.0,<24.7.0
- sphinxcontrib-mermaid>=0.8.1,<0.10 - sphinxcontrib-mermaid>=0.8.1,<0.10
- sphinxcontrib-towncrier==0.4.0a0
- setuptools-scm>=8
- tox - tox
- pre-commit
- ruff>=0.1.0
- ipykernel - ipykernel
- pytest-cov - pytest-cov
- pytest - pytest
- black
- ruff
- codespell - codespell
- tomli
- pip - pip
- pip: - pip:
- datalad>=0.15.4,<0.20 - datalad>=1.0.0,<1.2.0
- julearn==0.3.0 - julearn==0.3.3
- junifer_data==1.3.0

View file

@ -0,0 +1 @@
Regular repository maintenance by updating ``.pre-commit-config.yaml``, replacing ``black`` with ``ruff-format`` and updating tool configs by `Synchon Mandal`_

View file

@ -5,7 +5,6 @@
# Synchon Mandal <s.mandal@fz-juelich.de> # Synchon Mandal <s.mandal@fz-juelich.de>
# License: AGPL # License: AGPL
from ..pipeline import PipelineComponentRegistry from ..pipeline import PipelineComponentRegistry
from ..typing import DataGrabberLike, MarkerLike, PreprocessorLike, StorageLike from ..typing import DataGrabberLike, MarkerLike, PreprocessorLike, StorageLike

View file

@ -294,8 +294,7 @@ def queue(
valid_kind = ["HTCondor", "GNUParallelLocal"] valid_kind = ["HTCondor", "GNUParallelLocal"]
if kind not in valid_kind: if kind not in valid_kind:
raise_error( raise_error(
f"Invalid value for `kind`: {kind}, " f"Invalid value for `kind`: {kind}, must be one of {valid_kind}"
f"must be one of {valid_kind}"
) )
# Create a folder within the CWD to store the job files / config # Create a folder within the CWD to store the job files / config

View file

@ -218,8 +218,7 @@ class GnuParallelLocalAdapter(QueueContextAdapter):
# Copy executable if not local # Copy executable if not local
if hasattr(self, "_exec_path"): if hasattr(self, "_exec_path"):
logger.info( logger.info(
f"Copying {self._executable} to " f"Copying {self._executable} to {self._exec_path.resolve()!s}"
f"{self._exec_path.resolve()!s}"
) )
shutil.copy( shutil.copy(
src=Path(__file__).parent.parent / "res" / self._executable, src=Path(__file__).parent.parent / "res" / self._executable,
@ -235,15 +234,14 @@ class GnuParallelLocalAdapter(QueueContextAdapter):
self._elements_file_path.write_text(textwrap.dedent(self.elements())) self._elements_file_path.write_text(textwrap.dedent(self.elements()))
# Create pre run # Create pre run
logger.info( logger.info(
f"Writing {self._pre_run_path.name} to " f"Writing {self._pre_run_path.name} to {self._job_dir.resolve()!s}"
f"{self._job_dir.resolve()!s}"
) )
self._pre_run_path.touch() self._pre_run_path.touch()
self._pre_run_path.write_text(textwrap.dedent(self.pre_run())) self._pre_run_path.write_text(textwrap.dedent(self.pre_run()))
make_executable(self._pre_run_path) make_executable(self._pre_run_path)
# Create run # Create run
logger.info( logger.info(
f"Writing {self._run_path.name} to " f"{self._job_dir.resolve()!s}" f"Writing {self._run_path.name} to {self._job_dir.resolve()!s}"
) )
self._run_path.touch() self._run_path.touch()
self._run_path.write_text(textwrap.dedent(self.run())) self._run_path.write_text(textwrap.dedent(self.run()))
@ -258,8 +256,7 @@ class GnuParallelLocalAdapter(QueueContextAdapter):
make_executable(self._pre_collect_path) make_executable(self._pre_collect_path)
# Create collect # Create collect
logger.info( logger.info(
f"Writing {self._collect_path.name} to " f"Writing {self._collect_path.name} to {self._job_dir.resolve()!s}"
f"{self._job_dir.resolve()!s}"
) )
self._collect_path.touch() self._collect_path.touch()
self._collect_path.write_text(textwrap.dedent(self.collect())) self._collect_path.write_text(textwrap.dedent(self.collect()))

View file

@ -264,9 +264,7 @@ class HTCondorAdapter(QueueContextAdapter):
) )
junifer_collect_args = ( junifer_collect_args = (
"collect " f"collect {self._yaml_config_path.resolve()!s} {verbose_args}"
f"{self._yaml_config_path.resolve()!s} "
f"{verbose_args}"
) )
log_dir_prefix = f"{self._log_dir.resolve()!s}/junifer_collect" log_dir_prefix = f"{self._log_dir.resolve()!s}/junifer_collect"
fixed = ( fixed = (
@ -316,7 +314,7 @@ class HTCondorAdapter(QueueContextAdapter):
"$DAG_STATUS\n" "$DAG_STATUS\n"
) )
elif self._collect == "on_success_only": elif self._collect == "on_success_only":
var += f"JOB collect {self._submit_collect_path}\n" "PARENT " var += f"JOB collect {self._submit_collect_path}\nPARENT "
for idx, _ in enumerate(self._elements): for idx, _ in enumerate(self._elements):
var += f"run{idx} " var += f"run{idx} "
var += "CHILD collect\n" var += "CHILD collect\n"
@ -328,14 +326,13 @@ class HTCondorAdapter(QueueContextAdapter):
logger.info("Creating HTCondor job") logger.info("Creating HTCondor job")
# Create logs # Create logs
logger.info( logger.info(
f"Creating logs directory under " f"{self._job_dir.resolve()!s}" f"Creating logs directory under {self._job_dir.resolve()!s}"
) )
self._log_dir.mkdir(exist_ok=True, parents=True) self._log_dir.mkdir(exist_ok=True, parents=True)
# Copy executable if not local # Copy executable if not local
if hasattr(self, "_exec_path"): if hasattr(self, "_exec_path"):
logger.info( logger.info(
f"Copying {self._executable} to " f"Copying {self._executable} to {self._exec_path.resolve()!s}"
f"{self._exec_path.resolve()!s}"
) )
shutil.copy( shutil.copy(
src=Path(__file__).parent.parent / "res" / self._executable, src=Path(__file__).parent.parent / "res" / self._executable,
@ -344,8 +341,7 @@ class HTCondorAdapter(QueueContextAdapter):
make_executable(self._exec_path) make_executable(self._exec_path)
# Create pre run # Create pre run
logger.info( logger.info(
f"Writing {self._pre_run_path.name} to " f"Writing {self._pre_run_path.name} to {self._job_dir.resolve()!s}"
f"{self._job_dir.resolve()!s}"
) )
self._pre_run_path.touch() self._pre_run_path.touch()
self._pre_run_path.write_text(textwrap.dedent(self.pre_run())) self._pre_run_path.write_text(textwrap.dedent(self.pre_run()))
@ -374,7 +370,7 @@ class HTCondorAdapter(QueueContextAdapter):
self._submit_collect_path.write_text(textwrap.dedent(self.collect())) self._submit_collect_path.write_text(textwrap.dedent(self.collect()))
# Create DAG # Create DAG
logger.debug( logger.debug(
f"Writing {self._dag_path.name} to " f"{self._job_dir.resolve()!s}" f"Writing {self._dag_path.name} to {self._job_dir.resolve()!s}"
) )
self._dag_path.touch() self._dag_path.touch()
self._dag_path.write_text(textwrap.dedent(self.dag())) self._dag_path.write_text(textwrap.dedent(self.dag()))

View file

@ -18,6 +18,23 @@ def test_parse_yaml_failure() -> None:
parse_yaml("foo.yaml") parse_yaml("foo.yaml")
def test_parse_yaml_empty_elements_failure(tmp_path: Path) -> None:
"""Test YAML parsing with empty elements failure.
Parameters
----------
tmp_path : pathlib.Path
The path to the test directory.
"""
# Write test file
fname = tmp_path / "test_parse_yaml_empty_elements_failure.yaml"
fname.write_text("elements:")
# Check test file
with pytest.raises(ValueError, match="elements key was defined"):
parse_yaml(fname)
def test_parse_yaml_success(tmp_path: Path) -> None: def test_parse_yaml_success(tmp_path: Path) -> None:
"""Test YAML parsing success. """Test YAML parsing success.
@ -159,6 +176,41 @@ def test_parse_yaml_absolute_path(tmp_path: Path) -> None:
parse_yaml(yaml_fname) parse_yaml(yaml_fname)
def test_parse_yaml_multi_module_deps(tmp_path: Path) -> None:
"""Test YAML parsing with multi-module import with deps.
Parameters
----------
tmp_path : pathlib.Path
The path to the test directory.
"""
t_tmp_path = tmp_path / "test_with_multi_module"
# Write .py to include
py_path = t_tmp_path / "external"
py_path.mkdir(exist_ok=True, parents=True)
py_fname_1 = py_path / "first.py"
py_fname_1.write_text(
"import numpy as np\nfrom second import hej\n"
"def junifer_module_deps(): return ['second.py']\n"
)
py_fname_2 = py_path / "second.py"
py_fname_2.write_text("def hej(): print('hej')\n")
# Write yaml
yaml_path = t_tmp_path / "yamls"
yaml_path.mkdir(exist_ok=True, parents=True)
yaml_fname = yaml_path / "test_parse_yaml_multi_module.yaml"
yaml_fname.write_text(
"foo: bar\nwith:\n - ../external/first.py\n - scipy\n"
)
# Check test file
parse_yaml(yaml_fname)
def test_parse_storage_uri_relative(tmp_path: Path) -> None: def test_parse_storage_uri_relative(tmp_path: Path) -> None:
"""Test YAML parsing with storage and relative URI. """Test YAML parsing with storage and relative URI.
@ -212,3 +264,17 @@ def test_parse_storage_uri_relative(tmp_path: Path) -> None:
assert "foo" in contents assert "foo" in contents
assert contents["foo"] == "bar" assert contents["foo"] == "bar"
assert "storage" in contents assert "storage" in contents
def test_parse_yaml_queue_venv_relative(tmp_path: Path) -> None:
"""Test YAML parsing with relative venv queue.
Parameters
----------
tmp_path : pathlib.Path
The path to the test directory.
"""
fname = tmp_path / "test_parse_yaml_queue_venv_relative.yaml"
fname.write_text("queue:\n env:\n kind: venv\n name: .venv\n")
_ = parse_yaml(fname)

View file

@ -95,7 +95,7 @@ def get_data(
target_data=target_data, target_data=target_data,
extra_input=extra_input, extra_input=extra_input,
) )
else: else: # pragma: no cover
raise_error(f"Unknown data kind: {kind}") raise_error(f"Unknown data kind: {kind}")
@ -125,7 +125,7 @@ def list_data(kind: str) -> list[str]:
return ParcellationRegistry().list return ParcellationRegistry().list
elif kind == "mask": elif kind == "mask":
return MaskRegistry().list return MaskRegistry().list
else: else: # pragma: no cover
raise_error(f"Unknown data kind: {kind}") raise_error(f"Unknown data kind: {kind}")
@ -172,7 +172,7 @@ def load_data(
return ParcellationRegistry().load(name=name, **kwargs) return ParcellationRegistry().load(name=name, **kwargs)
elif kind == "mask": elif kind == "mask":
return MaskRegistry().load(name=name, **kwargs) return MaskRegistry().load(name=name, **kwargs)
else: else: # pragma: no cover
raise_error(f"Unknown data kind: {kind}") raise_error(f"Unknown data kind: {kind}")
@ -217,7 +217,7 @@ def register_data(
return MaskRegistry().register( return MaskRegistry().register(
name=name, space=space, overwrite=overwrite, **kwargs name=name, space=space, overwrite=overwrite, **kwargs
) )
else: else: # pragma: no cover
raise_error(f"Unknown data kind: {kind}") raise_error(f"Unknown data kind: {kind}")
@ -244,5 +244,5 @@ def deregister_data(kind: str, name: str) -> None:
return ParcellationRegistry().deregister(name=name) return ParcellationRegistry().deregister(name=name)
elif kind == "mask": elif kind == "mask":
return MaskRegistry().deregister(name=name) return MaskRegistry().deregister(name=name)
else: else: # pragma: no cover
raise_error(f"Unknown data kind: {kind}") raise_error(f"Unknown data kind: {kind}")

View file

@ -1,23 +0,0 @@
-2 -53 18 PCu-PCC_LR
-25 -26 -14 HC-PHC-AMG_L
-47 -61 26 TPJ_L
-3 47 -1 Medial-prefrontal-cortex_rACC(bilateral)_L
-56 -8 -14 STS_MTG_inferior-temporal-sulcus_L
-47 25 -5 Ventrolateral-prefrontal-cortex_temporal-pole_L
23 -31 -12 HC-PHC_R
-3 12 57 Middle-frontal-gyrus_LR
49 -59 27 TPJ_R
-45 3 45 Posterior-lateral-prefrontal-cortex_L
-40 47 14 Frontal-pole(lateral)_L
23 -13 -15 HC-PHC_R
49 -5 -13 Temporal-pole_STS_MTG_R
-37 14 -32 Temporal-pole_L
-37 -81 30 Occ_L
-46 24 21 Dorsolateral-prefrontal-cortex_L
50 27 -5 Ventrolateral-prefrontal-cortex_R
-11 55 17 Frontal_pole(medial)_L
3 -9 5 Thalamus_R
-5 33 22 rACC_L
-6 -37 33 PCC_L
-28 9 51 Superior-frontal-sulcus_L
28 1 -19 AMG_R

View file

@ -1,19 +0,0 @@
36.0 22.0 -4.0 RaIns
2.0 16.0 48.0 preSMA
48.0 12.0 30.0 rIFGp
36.0 2.0 54.0 rdPMC
48.0 30.0 24.0 rIFGa
-38.0 -44.0 46.0 lIPS
-24.0 -66.0 48.0 lSPL
40.0 -46.0 46.0 rIPS
60.0 -44.0 24.0 rIPC
30.0 -62.0 52.0 rSPL
-44.0 10.0 30.0 lIFG
-34.0 20.0 -4.0 LaIns
-26.0 2.0 52.0 ldPMC
6.0 -18.0 -2.0 rThal
-40.0 -66.0 -10.0 lIOG
48.0 19.0 6.0 rIFG
8.0 29.0 30.0 aMCC
-45.0 27.0 30.0 lIFG
11.0 7.0 7.0 rNcaud

View file

@ -1,8 +0,0 @@
-40 -64 -12 Fusiform_L
36 22 -4 Insula_R
-44 10 32 Precentral_L
60 -44 24 Temporal_Sup_R
0 18 48 Supp_Motor_Area_L
-36 -46 46 Parietal_Inf_L
38 -46 44 Parietal_Inf_R
-26 0 54 Frontal_Mid_L

View file

@ -1,6 +0,0 @@
0 -53 26 PCC
0 52 -6 MPFC
-48 -62 36 lAG
46 -62 32 rAG
-24 -22 -20 lHF
24 -22 -20 rHF

View file

@ -1,160 +0,0 @@
6 64 3 vmPFC
29 57 18 aPFC
-29 57 10 aPFC
0 51 32 mPFC
-25 51 27 aPFC
9 51 16 vmPFC
-6 50 -1 vmPFC
27 49 26 aPFC
42 48 -3 vent aPFC
-43 47 2 vent aPFC
-11 45 17 vmPFC
39 42 16 vlPFC
8 42 -5 vmPFC
9 39 20 ACC
46 39 -15 vlPFC
40 36 29 dlPFC
23 33 47 sup frontal
34 32 7 vPFC
-2 30 27 ACC
-16 29 54 sup frontal
-1 28 40 ACC
46 28 31 dlPFC
-52 28 17 vPFC
-44 27 33 dlPFC
51 23 8 vFC
38 21 -1 ant insula
9 20 34 dACC
-36 18 2 ant insula
40 17 40 dFC
-6 17 34 basal ganglia
0 15 45 mFC
58 11 14 frontal
-46 10 14 vFC
44 8 34 dFC
60 8 34 dFC
-42 7 36 dFC
-55 7 23 vFC
-20 6 7 basal ganglia
14 6 7 basal ganglia
-48 6 1 vFC
10 5 51 pre-SMA
43 1 12 vFC
0 -1 52 SMA
37 -2 -3 mid insula
53 -3 32 frontal
58 -3 17 precentral gyrus
-12 -3 13 thalamus
-42 -3 11 mid insula
-44 -6 49 precentral gyrus
-26 -8 54 parietal
46 -8 24 precentral gyrus
-54 -9 23 precentral gyrus
44 -11 38 precentral gyrus
-47 -12 36 parietal
33 -12 16 mid insula
-36 -12 15 mid insula
-12 -12 6 thalamus
11 -12 6 thalamus
32 -12 2 mid insula
59 -13 8 temporal
-30 -14 1 mid insula
-38 -15 59 parietal
52 -15 -13 inf temporal
-47 -18 50 parietal
46 -20 45 parietal
-55 -22 38 parietal
-54 -22 22 precentral gyrus
-54 -22 9 temporal
41 -23 55 parietal
42 -24 17 post insula
11 -24 2 basal ganglia
-59 -25 -15 inf temporal
1 -26 31 post cingulate
18 -27 62 parietal
-38 -27 60 parietal
-30 -28 9 post insula
-24 -30 64 parietal
51 -30 5 temporal
-41 -31 48 post parietal
-4 -31 -4 post cingulate
54 -31 -18 fusiform
-41 -37 16 temporal
-53 -37 13 temporal
28 -37 -15 fusiform
-3 -38 45 precuneus
34 -39 65 sup parietal
8 -40 50 precuneus
-41 -40 42 IPL
58 -41 20 parietal
-8 -41 3 post cingulate
-61 -41 -2 inf temporal
-28 -42 -11 occipital
-5 -43 25 post cingulate
9 -43 25 precuneus
43 -43 8 temporal
54 -44 43 IPL
-55 -44 30 parietal
-28 -44 -25 lat cerebellum
-35 -46 48 post parietal
42 -46 21 sup temporal
-48 -47 49 IPL
-41 -47 29 angular gyrus
-59 -47 11 temporal
-53 -50 39 IPL
5 -50 33 precuneus
-18 -50 1 occipital
44 -52 47 IPL
-5 -52 17 post cingulate
-24 -54 -21 lat cerebellum
-37 -54 -37 inf cerebellum
10 -55 17 post cingulate
-6 -56 29 precuneus
-34 -57 -24 lat cerebellum
-32 -58 46 IPS
-11 -58 17 post cingulate
32 -59 41 IPS
51 -59 34 angular gyrus
-34 -60 -5 occipital
36 -60 -8 occipital
-6 -60 -15 med cerebellum
-25 -60 -34 inf cerebellum
32 -61 -31 inf cerebellum
46 -62 5 temporal
-48 -63 35 angular gyrus
-52 -63 15 TPJ
-44 -63 -7 occipital
-16 -64 -21 med cerebellum
21 -64 -22 lat cerebellum
19 -66 -1 occipital
1 -66 -24 med cerebellum
-34 -67 -29 inf cerebellum
11 -68 42 precuneus
17 -68 20 occipital
-36 -69 40 IPS
39 -71 13 occipital
-9 -72 41 occipital
45 -72 29 occipital
-11 -72 -14 med cerebellum
29 -73 29 occipital
33 -73 -30 inf cerebellum
-2 -75 32 occipital
-29 -75 28 occipital
5 -75 -11 med cerebellum
14 -75 -21 med cerebellum
-16 -76 33 occipital
-42 -76 26 occipital
9 -76 14 occipital
15 -77 32 occipital
20 -78 -2 occipital
-21 -79 -33 inf cerebellum
-6 -79 -33 inf cerebellum
-5 -80 9 post occipital
29 -81 14 post occipital
33 -81 -2 post occipital
18 -81 -33 inf cerebellum
-37 -83 -2 post occipital
-29 -88 8 post occipital
13 -91 2 post occipital
27 -91 2 post occipital
-4 -94 12 post occipital

View file

@ -1,22 +0,0 @@
2.0 56.0 18.0 dmPFC
-8.0 54.0 34.0 dmPFC
36.0 22.0 -8.0 raI
-30.0 20.0 4.0 laI
50.0 12.0 -8.0 rIFG
54.0 16.0 20.0 rIFG/Area44
50.0 30.0 4.0 rIFG/Area45
-44.0 24.0 -6.0 lIFG
-4.0 18.0 50.0 SMA
-2.0 28.0 20.0 aMCC
-4.0 42.0 18.0 rACC
-2.0 -32.0 28.0 PCC
52.0 -58.0 22.0 rTPJ
-56.0 -58.0 22.0 lTPJ
22.0 -2.0 -16.0 rAm
54.0 -8.0 -16.0 rMTG
52.0 -36.0 2.0 rpSTS
-12.0 -4.0 12.0 laTh
6.0 -32.0 2.0 rpTh
26.0 -26.0 -12.0 rHippo
2.0 -20.0 -12.0 Midbrain
14.0 4.0 0.0 rGP

View file

@ -1,10 +0,0 @@
-39.0 -21.0 54.0 lSMC*
41.0 -16.0 57.0 rSMC*
-3.0 -2.0 54.0 SMA
-57.0 2.0 32.0 lPMCv
-53.0 -24.0 21.0 lIPC
45.0 -38.0 48.0 rIPC
-23.0 -7.0 1.0 lBG
25.0 -8.0 3.0 rBG
-22.0 -52.0 26.0 lCba
18.0 -54.0 -22.0 rCba

View file

@ -1,9 +0,0 @@
-34 22 -4 leftInsula
34 24 0 rightInsula
-26 0 52 Frontal_Mid_L
44 38 28 Frontal_Inf_Tri_R
46 10 28 Frontal_Inf_Oper_R
-6 18 50 Supp_Motor_Area_L
-34 -52 56 Parietal_Inf_L
32 -52 50 Parietal_Inf_R
32 6 58 Frontal_Mid_R

View file

@ -1,18 +0,0 @@
38.0 18.0 0.0 rIns
52.0 12.0 -4.0 rSTG
60.0 6.0 2.0 rTP
22.0 0.0 -4.0 rPall
-38.0 14.0 4.0 lIns
-58.0 0.0 6.0 lOP4
-20.0 6.0 2.0 lPut
4.0 6.0 46.0 rSMA
0.0 14.0 36.0 lMCC
-42.0 -18.0 18.0 lOP3
-54.0 -24.0 24.0 lSMG
-36.0 -20.0 2.0 lIns
-14.0 -12.0 10.0 lTh
10.0 -18.0 4.0 rTh
56.0 -24.0 24.0 lSMG
44.0 -14.0 16.0 rOP3
38.0 50.0 12.0 rMFG
-24.0 -66.0 -26.0 lCb

View file

@ -1,264 +0,0 @@
-25 -98 -12 1
27 -97 -13 2
24 32 -18 3
-56 -45 -24 4
8 41 -24 5
-21 -22 -20 6
17 -28 -17 7
-37 -29 -26 8
65 -24 -19 9
52 -34 -27 10
55 -31 -17 11
34 38 -12 12
-7 -52 61 13
-14 -18 40 14
0 -15 47 15
10 -2 45 16
-7 -21 65 17
-7 -33 72 18
13 -33 75 19
-54 -23 43 20
29 -17 71 21
10 -46 73 22
-23 -30 72 23
-40 -19 54 24
29 -39 59 25
50 -20 42 26
-38 -27 69 27
20 -29 60 28
44 -8 57 29
-29 -43 61 30
10 -17 74 31
22 -42 69 32
-45 -32 47 33
-21 -31 61 34
-13 -17 75 35
42 -20 55 36
-38 -15 69 37
-16 -46 73 38
2 -28 60 39
3 -17 58 40
38 -17 45 41
-49 -11 35 42
36 -9 14 43
51 -6 32 44
-53 -10 24 45
66 -8 25 46
-3 2 53 47
54 -28 34 48
19 -8 64 49
-16 -5 71 50
-10 -2 42 51
37 1 -4 52
13 -1 70 53
7 8 51 54
-45 0 9 55
49 8 -1 56
-34 3 4 57
-51 8 -2 58
-5 18 34 59
36 10 1 60
32 -26 13 61
65 -33 20 62
58 -16 7 63
-38 -33 17 64
-60 -25 14 65
-49 -26 5 66
43 -23 20 67
-50 -34 26 68
-53 -22 23 69
-55 -9 12 70
56 -5 13 71
59 -17 29 72
-30 -27 12 73
-41 -75 26 74
6 67 -4 75
8 48 -15 76
-13 -40 1 77
-18 63 -9 78
-46 -61 21 79
43 -72 28 80
-44 12 -34 81
46 16 -30 82
-68 -23 -16 83
-58 -26 -15 84
27 16 -17 85
-44 -65 35 86
-39 -75 44 87
-7 -55 27 88
6 -59 35 89
-11 -56 16 90
-3 -49 13 91
8 -48 31 92
15 -63 26 93
-2 -37 44 94
11 -54 17 95
52 -59 36 96
23 33 48 97
-10 39 52 98
-16 29 53 99
-35 20 51 100
22 39 39 101
13 55 38 102
-10 55 39 103
-20 45 39 104
6 54 16 105
6 64 22 106
-7 51 -1 107
9 54 3 108
-3 44 -9 109
8 42 -5 110
-11 45 8 111
-2 38 36 112
-3 42 16 113
-20 64 19 114
-8 48 23 115
65 -12 -19 116
-56 -13 -10 117
-58 -30 -4 118
65 -31 -9 119
-68 -41 -5 120
13 30 59 121
12 36 20 122
52 -2 -16 123
-26 -40 -8 124
27 -37 -13 125
-34 -38 -16 126
28 -77 -32 127
52 7 -30 128
-53 3 -27 129
47 -50 29 130
-49 -42 1 131
-31 19 -19 132
-2 -35 31 133
-7 -71 42 134
11 -66 42 135
4 -48 51 136
-46 31 -13 137
-10 11 67 138
49 35 -12 139
8 -91 -7 140
17 -91 -14 141
-12 -95 -13 142
18 -47 -10 143
40 -72 14 144
8 -72 11 145
-8 -81 7 146
-28 -79 19 147
20 -66 2 148
-24 -91 19 149
27 -59 -9 150
-15 -72 -8 151
-18 -68 5 152
43 -78 -12 153
-47 -76 -10 154
-14 -91 31 155
15 -87 37 156
29 -77 25 157
20 -86 -2 158
15 -77 31 159
-16 -52 -1 160
42 -66 -8 161
24 -87 24 162
6 -72 24 163
-42 -74 0 164
26 -79 -16 165
-16 -77 34 166
-3 -81 21 167
-40 -88 -6 168
37 -84 13 169
6 -81 6 170
-26 -90 3 171
-33 -79 -13 172
37 -81 1 173
-44 2 46 174
48 25 27 175
-47 11 23 176
-53 -49 43 177
-23 11 64 178
58 -53 -14 179
24 45 -15 180
34 54 -13 181
-21 41 -20 182
-18 -76 -24 183
17 -80 -34 184
35 -67 -34 185
47 10 33 186
-41 6 33 187
-42 38 21 188
38 43 15 189
49 -42 45 190
-28 -58 48 191
44 -53 47 192
32 14 56 193
37 -65 40 194
-42 -55 45 195
40 18 40 196
-34 55 4 197
-42 45 -2 198
33 -53 44 199
43 49 -2 200
-42 25 30 201
-3 26 44 202
11 -39 50 203
55 -45 37 204
42 -0 47 205
31 33 26 206
48 22 10 207
-35 20 0 208
36 22 3 209
37 32 -2 210
34 16 -8 211
-11 26 25 212
-1 15 44 213
-28 52 21 214
-0 30 27 215
5 23 37 216
10 22 27 217
31 56 14 218
26 50 27 219
-39 51 17 220
2 -24 30 221
6 -24 -0 222
-2 -13 12 223
-10 -18 7 224
12 -17 8 225
-5 -28 -4 226
-22 7 -5 227
-15 4 8 228
31 -14 2 229
23 10 1 230
29 1 4 231
-31 -11 -0 232
15 5 7 233
9 -4 6 234
54 -43 22 235
-56 -50 10 236
-55 -40 14 237
52 -33 8 238
51 -29 -4 239
56 -46 11 240
53 33 1 241
-49 25 -1 242
-16 -65 -20 243
-32 -55 -25 244
22 -58 -23 245
1 -62 -18 246
33 -12 -34 247
-31 -10 -36 248
49 -3 -38 249
-50 -7 -39 250
10 -62 61 251
-52 -63 5 252
-47 -51 -21 253
46 -47 -17 254
47 -30 49 255
22 -65 48 256
46 -59 4 257
25 -58 60 258
-33 -46 47 259
-27 -71 37 260
-32 -1 54 261
-42 -60 -9 262
-17 -59 64 263
29 -5 54 264

View file

@ -1,264 +0,0 @@
22 -65 48 1
25 -58 60 2
-35 20 0 3
12 36 20 4
40 18 40 5
54 -28 34 6
36 22 3 7
59 -17 29 8
-45 0 9 9
46 -59 4 10
-32 -1 54 11
32 14 56 12
-42 -60 -9 13
-34 3 4 14
37 1 -4 15
29 -5 54 16
11 -39 50 17
37 -65 40 18
-34 -38 -16 19
-52 -63 5 20
-10 11 67 21
-44 2 46 22
-3 26 44 23
49 8 -1 24
-33 -46 47 25
-27 -71 37 26
55 -45 37 27
7 8 51 28
36 10 1 29
-39 51 17 30
10 -62 61 31
-16 -5 71 32
43 49 -2 33
37 32 -2 34
10 -2 45 35
47 -30 49 36
36 -9 14 37
-3 2 53 38
-51 8 -2 39
-1 15 44 40
31 -14 2 41
19 -8 64 42
-10 -2 42 43
65 -33 20 44
-30 -27 12 45
6 -72 24 46
-7 -52 61 47
-49 -42 1 48
-49 25 -1 49
-5 18 34 50
-23 11 64 51
31 33 26 52
-0 30 27 53
-53 -22 23 54
-42 -55 45 55
-50 -34 26 56
48 22 10 57
31 56 14 58
44 -8 57 59
49 35 -12 60
-56 -50 10 61
2 -24 30 62
29 -39 59 63
-42 -74 0 64
-34 55 4 65
13 -1 70 66
42 -0 47 67
-3 42 16 68
5 23 37 69
51 -29 -4 70
0 -15 47 71
52 -33 8 72
34 16 -8 73
-7 -71 42 74
-29 -43 61 75
33 -53 44 76
-55 -40 14 77
-17 -59 64 78
56 -5 13 79
46 -47 -17 80
-11 26 25 81
22 -42 69 82
-13 -40 1 83
43 -23 20 84
-53 -49 43 85
-47 11 23 86
54 -43 22 87
53 33 1 88
10 22 27 89
-55 -9 12 90
-58 -30 -4 91
-42 45 -2 92
56 -46 11 93
-45 -32 47 94
11 -66 42 95
-28 -79 19 96
-47 -76 -10 97
-2 38 36 98
-54 -23 43 99
-28 52 21 100
47 -50 29 101
-2 -35 31 102
50 -20 42 103
-42 38 21 104
26 50 27 105
58 -53 -14 106
47 10 33 107
32 -26 13 108
-46 31 -13 109
10 -46 73 110
27 -37 -13 111
43 -72 28 112
52 -2 -16 113
-2 -37 44 114
38 43 15 115
-60 -25 14 116
-41 6 33 117
-2 -13 12 118
42 -66 -8 119
9 -4 6 120
29 1 4 121
15 5 7 122
-42 25 30 123
-26 -40 -8 124
65 -31 -9 125
44 -53 47 126
-18 -76 -24 127
-35 20 51 128
-28 -58 48 129
-49 -26 5 130
-53 -10 24 131
-47 -51 -21 132
58 -16 7 133
49 -42 45 134
40 -72 14 135
-32 -55 -25 136
-14 -18 40 137
-41 -75 26 138
-16 -77 34 139
4 -48 51 140
-68 -41 -5 141
35 -67 -34 142
22 39 39 143
-56 -13 -10 144
15 -63 26 145
-15 4 8 146
29 -77 25 147
38 -17 45 148
23 10 1 149
66 -8 25 150
51 -6 32 151
-39 -75 44 152
-11 45 8 153
52 7 -30 154
-21 41 -20 155
-12 -95 -13 156
8 42 -5 157
34 38 -12 158
-16 -46 73 159
37 -84 13 160
18 -47 -10 161
-11 -56 16 162
48 25 27 163
-53 3 -27 164
46 16 -30 165
-31 19 -19 166
37 -81 1 167
52 -59 36 168
27 16 -17 169
24 45 -15 170
-44 12 -34 171
-46 -61 21 172
-49 -11 35 173
-25 -98 -12 174
-33 -79 -13 175
11 -54 17 176
23 33 48 177
-3 -49 13 178
12 -17 8 179
-38 -33 17 180
8 48 -15 181
-10 39 52 182
43 -78 -12 183
20 -29 60 184
-40 -19 54 185
-20 45 39 186
13 30 59 187
-24 -91 19 188
-16 29 53 189
8 -91 -7 190
-21 -31 61 191
6 67 -4 192
17 -80 -34 193
-23 -30 72 194
2 -28 60 195
15 -77 31 196
3 -17 58 197
55 -31 -17 198
-31 -10 -36 199
-40 -88 -6 200
-18 63 -9 201
27 -59 -9 202
49 -3 -38 203
-31 -11 -0 204
65 -24 -19 205
17 -28 -17 206
-7 51 -1 207
24 32 -18 208
9 54 3 209
-7 -55 27 210
-21 -22 -20 211
34 54 -13 212
-38 -15 69 213
-38 -27 69 214
65 -12 -19 215
-16 -52 -1 216
-8 48 23 217
-3 44 -9 218
-37 -29 -26 219
27 -97 -13 220
17 -91 -14 221
6 54 16 222
8 41 -24 223
8 -48 31 224
24 -87 24 225
-58 -26 -15 226
29 -17 71 227
-68 -23 -16 228
-10 -18 7 229
-13 -17 75 230
-7 -33 72 231
15 -87 37 232
-20 64 19 233
42 -20 55 234
26 -79 -16 235
-10 55 39 236
13 -33 75 237
33 -12 -34 238
-26 -90 3 239
-7 -21 65 240
10 -17 74 241
-44 -65 35 242
6 -59 35 243
6 64 22 244
-18 -68 5 245
-16 -65 -20 246
8 -72 11 247
13 55 38 248
-14 -91 31 249
-3 -81 21 250
20 -86 -2 251
-50 -7 -39 252
-56 -45 -24 253
-8 -81 7 254
20 -66 2 255
6 -81 6 256
52 -34 -27 257
-15 -72 -8 258
6 -24 -0 259
28 -77 -32 260
22 -58 -23 261
1 -62 -18 262
-22 7 -5 263
-5 -28 -4 264
1 22 -65 48 1
2 25 -58 60 2
3 -35 20 0 3
4 12 36 20 4
5 40 18 40 5
6 54 -28 34 6
7 36 22 3 7
8 59 -17 29 8
9 -45 0 9 9
10 46 -59 4 10
11 -32 -1 54 11
12 32 14 56 12
13 -42 -60 -9 13
14 -34 3 4 14
15 37 1 -4 15
16 29 -5 54 16
17 11 -39 50 17
18 37 -65 40 18
19 -34 -38 -16 19
20 -52 -63 5 20
21 -10 11 67 21
22 -44 2 46 22
23 -3 26 44 23
24 49 8 -1 24
25 -33 -46 47 25
26 -27 -71 37 26
27 55 -45 37 27
28 7 8 51 28
29 36 10 1 29
30 -39 51 17 30
31 10 -62 61 31
32 -16 -5 71 32
33 43 49 -2 33
34 37 32 -2 34
35 10 -2 45 35
36 47 -30 49 36
37 36 -9 14 37
38 -3 2 53 38
39 -51 8 -2 39
40 -1 15 44 40
41 31 -14 2 41
42 19 -8 64 42
43 -10 -2 42 43
44 65 -33 20 44
45 -30 -27 12 45
46 6 -72 24 46
47 -7 -52 61 47
48 -49 -42 1 48
49 -49 25 -1 49
50 -5 18 34 50
51 -23 11 64 51
52 31 33 26 52
53 -0 30 27 53
54 -53 -22 23 54
55 -42 -55 45 55
56 -50 -34 26 56
57 48 22 10 57
58 31 56 14 58
59 44 -8 57 59
60 49 35 -12 60
61 -56 -50 10 61
62 2 -24 30 62
63 29 -39 59 63
64 -42 -74 0 64
65 -34 55 4 65
66 13 -1 70 66
67 42 -0 47 67
68 -3 42 16 68
69 5 23 37 69
70 51 -29 -4 70
71 0 -15 47 71
72 52 -33 8 72
73 34 16 -8 73
74 -7 -71 42 74
75 -29 -43 61 75
76 33 -53 44 76
77 -55 -40 14 77
78 -17 -59 64 78
79 56 -5 13 79
80 46 -47 -17 80
81 -11 26 25 81
82 22 -42 69 82
83 -13 -40 1 83
84 43 -23 20 84
85 -53 -49 43 85
86 -47 11 23 86
87 54 -43 22 87
88 53 33 1 88
89 10 22 27 89
90 -55 -9 12 90
91 -58 -30 -4 91
92 -42 45 -2 92
93 56 -46 11 93
94 -45 -32 47 94
95 11 -66 42 95
96 -28 -79 19 96
97 -47 -76 -10 97
98 -2 38 36 98
99 -54 -23 43 99
100 -28 52 21 100
101 47 -50 29 101
102 -2 -35 31 102
103 50 -20 42 103
104 -42 38 21 104
105 26 50 27 105
106 58 -53 -14 106
107 47 10 33 107
108 32 -26 13 108
109 -46 31 -13 109
110 10 -46 73 110
111 27 -37 -13 111
112 43 -72 28 112
113 52 -2 -16 113
114 -2 -37 44 114
115 38 43 15 115
116 -60 -25 14 116
117 -41 6 33 117
118 -2 -13 12 118
119 42 -66 -8 119
120 9 -4 6 120
121 29 1 4 121
122 15 5 7 122
123 -42 25 30 123
124 -26 -40 -8 124
125 65 -31 -9 125
126 44 -53 47 126
127 -18 -76 -24 127
128 -35 20 51 128
129 -28 -58 48 129
130 -49 -26 5 130
131 -53 -10 24 131
132 -47 -51 -21 132
133 58 -16 7 133
134 49 -42 45 134
135 40 -72 14 135
136 -32 -55 -25 136
137 -14 -18 40 137
138 -41 -75 26 138
139 -16 -77 34 139
140 4 -48 51 140
141 -68 -41 -5 141
142 35 -67 -34 142
143 22 39 39 143
144 -56 -13 -10 144
145 15 -63 26 145
146 -15 4 8 146
147 29 -77 25 147
148 38 -17 45 148
149 23 10 1 149
150 66 -8 25 150
151 51 -6 32 151
152 -39 -75 44 152
153 -11 45 8 153
154 52 7 -30 154
155 -21 41 -20 155
156 -12 -95 -13 156
157 8 42 -5 157
158 34 38 -12 158
159 -16 -46 73 159
160 37 -84 13 160
161 18 -47 -10 161
162 -11 -56 16 162
163 48 25 27 163
164 -53 3 -27 164
165 46 16 -30 165
166 -31 19 -19 166
167 37 -81 1 167
168 52 -59 36 168
169 27 16 -17 169
170 24 45 -15 170
171 -44 12 -34 171
172 -46 -61 21 172
173 -49 -11 35 173
174 -25 -98 -12 174
175 -33 -79 -13 175
176 11 -54 17 176
177 23 33 48 177
178 -3 -49 13 178
179 12 -17 8 179
180 -38 -33 17 180
181 8 48 -15 181
182 -10 39 52 182
183 43 -78 -12 183
184 20 -29 60 184
185 -40 -19 54 185
186 -20 45 39 186
187 13 30 59 187
188 -24 -91 19 188
189 -16 29 53 189
190 8 -91 -7 190
191 -21 -31 61 191
192 6 67 -4 192
193 17 -80 -34 193
194 -23 -30 72 194
195 2 -28 60 195
196 15 -77 31 196
197 3 -17 58 197
198 55 -31 -17 198
199 -31 -10 -36 199
200 -40 -88 -6 200
201 -18 63 -9 201
202 27 -59 -9 202
203 49 -3 -38 203
204 -31 -11 -0 204
205 65 -24 -19 205
206 17 -28 -17 206
207 -7 51 -1 207
208 24 32 -18 208
209 9 54 3 209
210 -7 -55 27 210
211 -21 -22 -20 211
212 34 54 -13 212
213 -38 -15 69 213
214 -38 -27 69 214
215 65 -12 -19 215
216 -16 -52 -1 216
217 -8 48 23 217
218 -3 44 -9 218
219 -37 -29 -26 219
220 27 -97 -13 220
221 17 -91 -14 221
222 6 54 16 222
223 8 41 -24 223
224 8 -48 31 224
225 24 -87 24 225
226 -58 -26 -15 226
227 29 -17 71 227
228 -68 -23 -16 228
229 -10 -18 7 229
230 -13 -17 75 230
231 -7 -33 72 231
232 15 -87 37 232
233 -20 64 19 233
234 42 -20 55 234
235 26 -79 -16 235
236 -10 55 39 236
237 13 -33 75 237
238 33 -12 -34 238
239 -26 -90 3 239
240 -7 -21 65 240
241 10 -17 74 241
242 -44 -65 35 242
243 6 -59 35 243
244 6 64 22 244
245 -18 -68 5 245
246 -16 -65 -20 246
247 8 -72 11 247
248 13 55 38 248
249 -14 -91 31 249
250 -3 -81 21 250
251 20 -86 -2 251
252 -50 -7 -39 252
253 -56 -45 -24 253
254 -8 -81 7 254
255 20 -66 2 255
256 6 -81 6 256
257 52 -34 -27 257
258 -15 -72 -8 258
259 6 -24 -0 259
260 28 -77 -32 260
261 22 -58 -23 261
262 1 -62 -18 262
263 -22 7 -5 263
264 -5 -28 -4 264

View file

@ -1,25 +0,0 @@
12.0 10.0 -6.0 rNAc
-10.0 8.0 -4.0 lPall
36.0 20.0 -6.0 rIns
-32.0 20.0 -4.0 lIns
0.0 24.0 40.0 dmPFC
0.0 54.0 -8.0 medOFC
24.0 -2.0 -16.0 rAm
6.0 -14.0 8.0 rTh
-6.0 -16.0 8.0 lTh
0.0 8.0 48.0 SMA
8.0 -18.0 -10.0 rBrainStem
-6.0 -18.0 -10.0 lBrainStem
2.0 44.0 20.0 ACC
-24.0 2.0 52.0 lMFG
-38.0 -4.0 6.0 lIns(Id3)
24.0 40.0 -14.0 rMidOFC(Fo3)
-16.0 42.0 -14.0 lMidOFC(Fo3)
40.0 32.0 32.0 raMFG
-28.0 -56.0 48.0 lIPL(IPS)
28.0 -58.0 50.0 rAG
0.0 -32.0 32.0 PCC
-36.0 50.0 10.0 lFP
-46.0 42.0 -4.0 lLOFC
30.0 4.0 50.0 rpMFG
-22.0 30.0 48.0 lSFG

View file

@ -1,10 +0,0 @@
-48.0 -20.0 20.0 S1_L
-54.0 -20.0 48.0 postcentralG_S1_L
-44.0 -26.0 58.0 postcentralG_S1_L
-38.0 -12.0 4.0 Ins_claustrum_L
-40.0 4.0 10.0 pars_opercularis_Ins_L
56.0 -22.0 20.0 SMG_R
56.0 -34.0 18.0 pSTG_R
56.0 -38.0 28.0 IPL_SMG_R
60.0 -20.0 32.0 postcentralG_R
-4.0 14.0 36.0 MCC_L

View file

@ -1,15 +0,0 @@
0.0 52.0 -12.0 vmPFC
2.0 58.0 12.0 FP
-8.0 56.0 30.0 dmPFC
2.0 -56.0 30.0 Prc
56.0 -50.0 18.0 rTPJ
-48.0 -56.0 24.0 lTPJ
54.0 -2.0 -20.0 rTP
-54.0 -2.0 -24.0 lTP
52.0 -18.0 -12.0 rMTG
-54.0 -28.0 -4.0 lMTG
50.0 -34.0 0.0 rpSTS
-58.0 -44.0 4.0 lpSTS
54.0 28.0 6.0 rIFG
-48.0 30.0 -12.0 lIFG
48.0 -72.0 8.0 rV5

View file

@ -1,16 +0,0 @@
-2.0 8.0 50.0 aParacentralL
8.0 32.0 46.0 rmpSFG
0.0 26.0 34.0 dMCC
50.0 8.0 32.0 rIFJ
40.0 22.0 -4.0 raI
46.0 36.0 20.0 rIFS
-40.0 -12.0 60.0 lPrecentralG
-46.0 -68.0 -6.0 lIOG
-48.0 8.0 30.0 lIFJ
62.0 -38.0 17.0 rTPJ
8.0 -12.0 6.0 rTh
32.0 -90.0 4.0 rMOG
-42.0 12.0 -2.0 laI
-10.0 -14.0 6.0 lTh
6.0 -58.0 -18.0 Cb
44.0 -44.0 46.0 rIPL

View file

@ -1,23 +0,0 @@
-32.0 22.0 -2.0 aIns_l
-48.0 10.0 26.0 IFG_l
-46.0 26.0 24.0 lPFCc_l
-38.0 50.0 10.0 lPFCr_l
36.0 22.0 -6.0 aIns_r
50.0 14.0 24.0 IFG_r
44.0 34.0 32.0 lPFCc_r
38.0 54.0 6.0 lPFCr_l
2.0 18.0 48.0 pmFC
-28.0 0.0 56.0 psFC
30.0 2.0 56.0 psFC
-42.0 -42.0 46.0 IPS_l
-34.0 -52.0 48.0 SPL_l
-24.0 -66.0 54.0 SPLp_l
42.0 -44.0 44.0 IPSa_r
32.0 -58.0 48.0 IPSp_r
16.0 -66.0 56.0 SPLp_r
-12.0 -12.0 12.0 Thal_l
-16.0 2.0 14.0 Ncaud_l
-16.0 0.0 2.0 GP_l
12.0 -10.0 10.0 Thal_r
-34.0 -66.0 -20.0 Cb_FG_l
32.0 -64.0 -18.0 Cb_FG_r

View file

@ -1,17 +0,0 @@
-46.0 6.0 30.0 IFG_l
50.0 12.0 28.0 IFG_r
-32.0 20.0 2.0 aIns_l
36.0 22.0 0.0 aIns_r
-4.0 14.0 44.0 SMA_l
6.0 18.0 46.0 SMA_r
-32.0 -52.0 46.0 IPS_l
32.0 -58.0 48.0 IPS_r
44.0 36.0 20.0 MFG_r
-28.0 -4.0 52.0 dPMC_l
-44.0 32.0 22.0 MFG_l
32.0 0.0 52.0 dPMC_r
-20.0 6.0 4.0 Put_l
10.0 -12.0 8.0 Thal_r
-46.0 -60.0 -10.0 ITG_l
22.0 6.0 4.0 Put_r
-10.0 -16.0 6.0 Thal_l

View file

@ -1,12 +0,0 @@
0.0 38.0 10.0 ACC
-24.0 -10.0 -20.0 AmyHipp_L
24.0 -8.0 -22.0 AmyHipp_R
-2.0 -52.0 26.0 PrC
-2.0 32.0 -8.0 SGC
-46.0 -66.0 18.0 TPJ_L
50.0 -60.0 18.0 TPJ_R
-2.0 52.0 14.0 dmPFC
-6.0 10.0 -8.0 vBG_L
6.0 10.0 -8.0 vBG_R
-2.0 50.0 -10.0 vmPFC
-54.0 -10.0 -20.0 aMTS/aMTG

View file

@ -1,16 +0,0 @@
0 -53 6 PCC
0 52 -6 MPFC
-48 -62 36 lAG
46 -62 32 rAG
-24 -22 -20 lHF
24 -22 -20 rHF
10 -22 42 Middlecingulate
-48 -20 38 lIPG
0 -48 -30 cerebellum
34 -80 -34 rCerebellum
56 30 8 rdlPFC
-42 -82 10 lateraloccipital
-54 24 10 rdrPFC
22 34 54 RSFG
-50 14 -40 lTempP
-38 14 54 leftmiddlefrontalgyrus(BA6)

View file

@ -27,7 +27,7 @@ class ANTsCoordinatesWarper:
seeds: ArrayLike, seeds: ArrayLike,
target_data: dict[str, Any], target_data: dict[str, Any],
warp_data: dict[str, Any], warp_data: dict[str, Any],
) -> ArrayLike: ) -> ArrayLike: # pragma: no cover
"""Warp ``seeds`` to correct space. """Warp ``seeds`` to correct space.
Parameters Parameters

View file

@ -339,7 +339,7 @@ class CoordinatesRegistry(BasePipelineDataRegistry, metaclass=Singleton):
seeds, labels, _ = self.load(name=coords) seeds, labels, _ = self.load(name=coords)
# Transform coordinate if target data is native # Transform coordinate if target data is native
if target_data["space"] == "native": if target_data["space"] == "native": # pragma: no cover
# Check for extra inputs # Check for extra inputs
if extra_input is None: if extra_input is None:
raise_error( raise_error(

View file

@ -27,7 +27,7 @@ class FSLCoordinatesWarper:
seeds: ArrayLike, seeds: ArrayLike,
target_data: dict[str, Any], target_data: dict[str, Any],
warp_data: dict[str, Any], warp_data: dict[str, Any],
) -> ArrayLike: ) -> ArrayLike: # pragma: no cover
"""Warp ``seeds`` to correct space. """Warp ``seeds`` to correct space.
Parameters Parameters

View file

@ -8,7 +8,13 @@ import numpy as np
import pytest import pytest
from numpy.testing import assert_array_equal from numpy.testing import assert_array_equal
from junifer.data import CoordinatesRegistry from junifer.data import (
deregister_data,
get_data,
list_data,
load_data,
register_data,
)
from junifer.datareader import DefaultDataReader from junifer.datareader import DefaultDataReader
from junifer.testing.datagrabbers import OasisVBMTestingDataGrabber from junifer.testing.datagrabbers import OasisVBMTestingDataGrabber
@ -16,7 +22,8 @@ from junifer.testing.datagrabbers import OasisVBMTestingDataGrabber
def test_register_built_in_check() -> None: def test_register_built_in_check() -> None:
"""Test coordinates registration check for built-in coordinates.""" """Test coordinates registration check for built-in coordinates."""
with pytest.raises(ValueError, match=r"built-in"): with pytest.raises(ValueError, match=r"built-in"):
CoordinatesRegistry().register( register_data(
kind="coordinates",
name="DMNBuckner", name="DMNBuckner",
coordinates=np.zeros(2), coordinates=np.zeros(2),
voi_names=["1", "2"], voi_names=["1", "2"],
@ -26,14 +33,16 @@ def test_register_built_in_check() -> None:
def test_register_overwrite() -> None: def test_register_overwrite() -> None:
"""Test coordinates registration check for overwriting.""" """Test coordinates registration check for overwriting."""
CoordinatesRegistry().register( register_data(
kind="coordinates",
name="MyList", name="MyList",
coordinates=np.zeros((2, 3)), coordinates=np.zeros((2, 3)),
voi_names=["roi1", "roi2"], voi_names=["roi1", "roi2"],
space="MNI", space="MNI",
) )
with pytest.raises(ValueError, match=r"already registered"): with pytest.raises(ValueError, match=r"already registered"):
CoordinatesRegistry().register( register_data(
kind="coordinates",
name="MyList", name="MyList",
coordinates=np.ones((2, 3)), coordinates=np.ones((2, 3)),
voi_names=["roi2", "roi3"], voi_names=["roi2", "roi3"],
@ -41,7 +50,8 @@ def test_register_overwrite() -> None:
overwrite=False, overwrite=False,
) )
CoordinatesRegistry().register( register_data(
kind="coordinates",
name="MyList", name="MyList",
coordinates=np.ones((2, 3)), coordinates=np.ones((2, 3)),
voi_names=["roi2", "roi3"], voi_names=["roi2", "roi3"],
@ -49,7 +59,7 @@ def test_register_overwrite() -> None:
overwrite=True, overwrite=True,
) )
coord, names, space = CoordinatesRegistry().load("MyList") coord, names, space = load_data(kind="coordinates", name="MyList")
assert_array_equal(coord, np.ones((2, 3))) assert_array_equal(coord, np.ones((2, 3)))
assert names == ["roi2", "roi3"] assert names == ["roi2", "roi3"]
assert space == "MNI" assert space == "MNI"
@ -58,7 +68,8 @@ def test_register_overwrite() -> None:
def test_register_valid_input() -> None: def test_register_valid_input() -> None:
"""Test coordinates registration check for valid input.""" """Test coordinates registration check for valid input."""
with pytest.raises(TypeError, match=r"numpy.ndarray"): with pytest.raises(TypeError, match=r"numpy.ndarray"):
CoordinatesRegistry().register( register_data(
kind="coordinates",
name="MyList", name="MyList",
coordinates=[1, 2], coordinates=[1, 2],
voi_names=["roi1", "roi2"], voi_names=["roi1", "roi2"],
@ -66,7 +77,8 @@ def test_register_valid_input() -> None:
overwrite=True, overwrite=True,
) )
with pytest.raises(ValueError, match=r"2D array"): with pytest.raises(ValueError, match=r"2D array"):
CoordinatesRegistry().register( register_data(
kind="coordinates",
name="MyList", name="MyList",
coordinates=np.zeros((2, 3, 4)), coordinates=np.zeros((2, 3, 4)),
voi_names=["roi1", "roi2"], voi_names=["roi1", "roi2"],
@ -75,7 +87,8 @@ def test_register_valid_input() -> None:
) )
with pytest.raises(ValueError, match=r"3 values"): with pytest.raises(ValueError, match=r"3 values"):
CoordinatesRegistry().register( register_data(
kind="coordinates",
name="MyList", name="MyList",
coordinates=np.zeros((2, 4)), coordinates=np.zeros((2, 4)),
voi_names=["roi1", "roi2"], voi_names=["roi1", "roi2"],
@ -83,7 +96,8 @@ def test_register_valid_input() -> None:
overwrite=True, overwrite=True,
) )
with pytest.raises(ValueError, match=r"voi_names"): with pytest.raises(ValueError, match=r"voi_names"):
CoordinatesRegistry().register( register_data(
kind="coordinates",
name="MyList", name="MyList",
coordinates=np.zeros((2, 3)), coordinates=np.zeros((2, 3)),
voi_names=["roi1", "roi2", "roi3"], voi_names=["roi1", "roi2", "roi3"],
@ -95,13 +109,13 @@ def test_register_valid_input() -> None:
def test_list() -> None: def test_list() -> None:
"""Test listing of available coordinates.""" """Test listing of available coordinates."""
assert {"DMNBuckner", "MultiTask", "VigAtt", "WM"}.issubset( assert {"DMNBuckner", "MultiTask", "VigAtt", "WM"}.issubset(
set(CoordinatesRegistry().list) set(list_data(kind="coordinates"))
) )
def test_load() -> None: def test_load() -> None:
"""Test loading coordinates from file.""" """Test loading coordinates from file."""
coord, names, space = CoordinatesRegistry().load("DMNBuckner") coord, names, space = load_data(kind="coordinates", name="DMNBuckner")
assert coord.shape == (6, 3) # type: ignore assert coord.shape == (6, 3) # type: ignore
assert names == ["PCC", "MPFC", "lAG", "rAG", "lHF", "rHF"] assert names == ["PCC", "MPFC", "lAG", "rAG", "lHF", "rHF"]
assert space == "MNI" assert space == "MNI"
@ -110,7 +124,7 @@ def test_load() -> None:
def test_load_nonexisting() -> None: def test_load_nonexisting() -> None:
"""Test loading coordinates that not exist.""" """Test loading coordinates that not exist."""
with pytest.raises(ValueError, match=r"not found"): with pytest.raises(ValueError, match=r"not found"):
CoordinatesRegistry().load("NonExisting") load_data(kind="coordinates", name="NonExisting")
def test_get() -> None: def test_get() -> None:
@ -121,11 +135,19 @@ def test_get() -> None:
element_data = reader.fit_transform(element) element_data = reader.fit_transform(element)
vbm_gm = element_data["VBM_GM"] vbm_gm = element_data["VBM_GM"]
# Get tailored coordinates # Get tailored coordinates
tailored_coords, tailored_labels = CoordinatesRegistry().get( tailored_coords, tailored_labels = get_data(
coords="DMNBuckner", target_data=vbm_gm kind="coordinates", names="DMNBuckner", target_data=vbm_gm
) )
# Get raw coordinates # Get raw coordinates
raw_coords, raw_labels, _ = CoordinatesRegistry().load("DMNBuckner") raw_coords, raw_labels, _ = load_data(
kind="coordinates", name="DMNBuckner"
)
# Both tailored and raw should be same for now # Both tailored and raw should be same for now
assert_array_equal(tailored_coords, raw_coords) assert_array_equal(tailored_coords, raw_coords)
assert tailored_labels == raw_labels assert tailored_labels == raw_labels
def test_deregister() -> None:
"""Test coordinates deregistration."""
deregister_data(kind="coordinates", name="MyList")
assert "MyList" not in list_data(kind="coordinates")

View file

@ -56,7 +56,7 @@ class ANTsMaskWarper:
dst: str, dst: str,
target_data: dict[str, Any], target_data: dict[str, Any],
warp_data: Optional[dict[str, Any]], warp_data: Optional[dict[str, Any]],
) -> "Nifti1Image": ) -> "Nifti1Image": # pragma: no cover
"""Warp ``mask_img`` to correct space. """Warp ``mask_img`` to correct space.
Parameters Parameters

View file

@ -53,7 +53,7 @@ class FSLMaskWarper:
mask_img: "Nifti1Image", mask_img: "Nifti1Image",
target_data: dict[str, Any], target_data: dict[str, Any],
warp_data: dict[str, Any], warp_data: dict[str, Any],
) -> "Nifti1Image": ) -> "Nifti1Image": # pragma: no cover
"""Warp ``mask_img`` to correct space. """Warp ``mask_img`` to correct space.
Parameters Parameters

View file

@ -20,7 +20,14 @@ from nilearn.masking import (
) )
from numpy.testing import assert_array_almost_equal, assert_array_equal from numpy.testing import assert_array_almost_equal, assert_array_equal
from junifer.data import MaskRegistry from junifer.data import (
MaskRegistry,
deregister_data,
get_data,
list_data,
load_data,
register_data,
)
from junifer.data.masks import compute_brain_mask from junifer.data.masks import compute_brain_mask
from junifer.data.masks._masks import ( from junifer.data.masks._masks import (
_load_ukb_mask, _load_ukb_mask,
@ -112,7 +119,8 @@ def test_compute_brain_mask_for_native(mask_type: str) -> None:
def test_register_built_in_check() -> None: def test_register_built_in_check() -> None:
"""Test mask registration check for built-in masks.""" """Test mask registration check for built-in masks."""
with pytest.raises(ValueError, match=r"built-in mask"): with pytest.raises(ValueError, match=r"built-in mask"):
MaskRegistry().register( register_data(
kind="mask",
name="GM_prob0.2", name="GM_prob0.2",
mask_path="testmask.nii.gz", mask_path="testmask.nii.gz",
space="MNI", space="MNI",
@ -122,36 +130,39 @@ def test_register_built_in_check() -> None:
def test_list_incorrect() -> None: def test_list_incorrect() -> None:
"""Test incorrect information check for list masks.""" """Test incorrect information check for list masks."""
assert "testmask" not in MaskRegistry().list assert "testmask" not in list_data(kind="mask")
def test_register_already_registered() -> None: def test_register_already_registered() -> None:
"""Test mask registration check for already registered.""" """Test mask registration check for already registered."""
# Register custom mask # Register custom mask
MaskRegistry().register( register_data(
kind="mask",
name="testmask", name="testmask",
mask_path="testmask.nii.gz", mask_path="testmask.nii.gz",
space="MNI", space="MNI",
) )
out = MaskRegistry().load("testmask", path_only=True) out = load_data(kind="mask", name="testmask", path_only=True)
assert out[1] is not None assert out[1] is not None
assert out[1].name == "testmask.nii.gz" assert out[1].name == "testmask.nii.gz"
# Try registering again # Try registering again
with pytest.raises(ValueError, match=r"already registered."): with pytest.raises(ValueError, match=r"already registered."):
MaskRegistry().register( register_data(
kind="mask",
name="testmask", name="testmask",
mask_path="testmask.nii.gz", mask_path="testmask.nii.gz",
space="MNI", space="MNI",
) )
MaskRegistry().register( register_data(
kind="mask",
name="testmask", name="testmask",
mask_path="testmask2.nii.gz", mask_path="testmask2.nii.gz",
space="MNI", space="MNI",
overwrite=True, overwrite=True,
) )
out = MaskRegistry().load("testmask", path_only=True) out = load_data(kind="mask", name="testmask", path_only=True)
assert out[1] is not None assert out[1] is not None
assert out[1].name == "testmask2.nii.gz" assert out[1].name == "testmask2.nii.gz"
@ -185,16 +196,17 @@ def test_register(
""" """
# Register custom mask # Register custom mask
MaskRegistry().register( register_data(
kind="mask",
name=name, name=name,
mask_path=mask_path, mask_path=mask_path,
space=space, space=space,
overwrite=overwrite, overwrite=overwrite,
) )
# List available mask and check registration # List available mask and check registration
assert name in MaskRegistry().list assert name in list_data(kind="mask")
# Load registered mask # Load registered mask
_, fname, mask_space = MaskRegistry().load(name=name, path_only=True) _, fname, mask_space = load_data(kind="mask", name=name, path_only=True)
# Check values for registered mask # Check values for registered mask
assert fname is not None assert fname is not None
assert fname.name == f"{name}.nii.gz" assert fname.name == f"{name}.nii.gz"
@ -218,7 +230,7 @@ def test_list_correct(mask_name: str) -> None:
The parametrized mask name. The parametrized mask name.
""" """
assert mask_name in MaskRegistry().list assert mask_name in list_data(kind="mask")
def test_load_incorrect() -> None: def test_load_incorrect() -> None:
@ -270,9 +282,12 @@ def test_vickery_patil(
The parametrized name of the mask file. The parametrized name of the mask file.
""" """
mask, mask_fname, space = MaskRegistry().load(name, resolution=resolution) mask, mask_fname, space = load_data(
kind="mask", name=name, resolution=resolution
)
assert_array_almost_equal( assert_array_almost_equal(
mask.header["pixdim"][1:4], pixdim # type: ignore mask.header["pixdim"][1:4],
pixdim, # type: ignore
) )
assert space == "IXI549Space" assert space == "IXI549Space"
assert mask_fname is not None assert mask_fname is not None
@ -287,7 +302,9 @@ def test_vickery_patil_error() -> None:
def test_ukb() -> None: def test_ukb() -> None:
"""Test UKB mask.""" """Test UKB mask."""
mask, mask_fname, space = MaskRegistry().load("UKB_15K_GM", resolution=2.0) mask, mask_fname, space = load_data(
kind="mask", name="UKB_15K_GM", resolution=2.0
)
assert_array_almost_equal(mask.header["pixdim"][1:4], 2.0) # type: ignore assert_array_almost_equal(mask.header["pixdim"][1:4], 2.0) # type: ignore
assert space == "MNI152NLin6Asym" assert space == "MNI152NLin6Asym"
assert mask_fname is not None assert mask_fname is not None
@ -306,8 +323,8 @@ def test_get() -> None:
element_data = DefaultDataReader().fit_transform(dg["sub-01"]) element_data = DefaultDataReader().fit_transform(dg["sub-01"])
vbm_gm = element_data["VBM_GM"] vbm_gm = element_data["VBM_GM"]
vbm_gm_img = vbm_gm["data"] vbm_gm_img = vbm_gm["data"]
mask = MaskRegistry().get( mask = get_data(
masks="compute_brain_mask", target_data=vbm_gm kind="mask", names="compute_brain_mask", target_data=vbm_gm
) )
assert mask.shape == vbm_gm_img.shape assert mask.shape == vbm_gm_img.shape
@ -355,28 +372,33 @@ def test_get_errors() -> None:
vbm_gm = element_data["VBM_GM"] vbm_gm = element_data["VBM_GM"]
# Test wrong masks definitions (more than one key per dict) # Test wrong masks definitions (more than one key per dict)
with pytest.raises(ValueError, match=r"only one key"): with pytest.raises(ValueError, match=r"only one key"):
MaskRegistry().get( get_data(
masks={"GM_prob0.2": {}, "Other": {}}, target_data=vbm_gm kind="mask",
names={"GM_prob0.2": {}, "Other": {}},
target_data=vbm_gm,
) )
# Test wrong masks definitions (pass paramaeters to non-callable mask) # Test wrong masks definitions (pass paramaeters to non-callable mask)
with pytest.raises(ValueError, match=r"callable params"): with pytest.raises(ValueError, match=r"callable params"):
MaskRegistry().get( get_data(
masks={"GM_prob0.2": {"param": 1}}, target_data=vbm_gm kind="mask",
names={"GM_prob0.2": {"param": 1}},
target_data=vbm_gm,
) )
# Pass only parameters to the intersection function # Pass only parameters to the intersection function
with pytest.raises( with pytest.raises(
ValueError, match=r" At least one mask is required." ValueError, match=r" At least one mask is required."
): ):
MaskRegistry().get(masks={"threshold": 1}, target_data=vbm_gm) get_data(kind="mask", names={"threshold": 1}, target_data=vbm_gm)
# Pass parameters to the intersection function when only one mask # Pass parameters to the intersection function when only one mask
with pytest.raises( with pytest.raises(
ValueError, match=r"parameters to the intersection" ValueError, match=r"parameters to the intersection"
): ):
MaskRegistry().get( get_data(
masks=["compute_brain_mask", {"threshold": 1}], kind="mask",
names=["compute_brain_mask", {"threshold": 1}],
target_data=vbm_gm, target_data=vbm_gm,
) )
@ -423,7 +445,7 @@ def test_nilearn_compute_masks(
else: else:
mask_spec = {mask_name: params} mask_spec = {mask_name: params}
mask = MaskRegistry().get(masks=mask_spec, target_data=bold) mask = get_data(kind="mask", names=mask_spec, target_data=bold)
assert_array_equal(mask.affine, bold_img.affine) assert_array_equal(mask.affine, bold_img.affine)
@ -449,8 +471,9 @@ def test_get_inherit() -> None:
gm_mask = compute_brain_mask(element_data["BOLD"], threshold=0.2) gm_mask = compute_brain_mask(element_data["BOLD"], threshold=0.2)
# Get mask using the compute_brain_mask function # Get mask using the compute_brain_mask function
mask1 = MaskRegistry().get( mask1 = get_data(
masks={"compute_brain_mask": {"threshold": 0.2}}, kind="mask",
names={"compute_brain_mask": {"threshold": 0.2}},
target_data=element_data["BOLD"], target_data=element_data["BOLD"],
) )
@ -461,8 +484,9 @@ def test_get_inherit() -> None:
"data": gm_mask, "data": gm_mask,
"space": element_data["BOLD"]["space"], "space": element_data["BOLD"]["space"],
} }
mask2 = MaskRegistry().get( mask2 = get_data(
masks="inherit", kind="mask",
names="inherit",
target_data=bold_dict, target_data=bold_dict,
) )
@ -503,8 +527,8 @@ def test_get_multiple(
target_img = element_data["BOLD"]["data"] target_img = element_data["BOLD"]["data"]
resolution = np.min(target_img.header.get_zooms()[:3]) resolution = np.min(target_img.header.get_zooms()[:3])
computed = MaskRegistry().get( computed = get_data(
masks=junifer_masks, target_data=element_data["BOLD"] kind="mask", names=junifer_masks, target_data=element_data["BOLD"]
) )
masks_names = [ masks_names = [
@ -523,8 +547,11 @@ def test_get_multiple(
] ]
mask_imgs = [ mask_imgs = [
MaskRegistry().load( load_data(
t_mask, path_only=False, resolution=resolution kind="mask",
name=t_mask,
path_only=False,
resolution=resolution,
)[0] )[0]
for t_mask in mask_files for t_mask in mask_files
] ]
@ -554,3 +581,9 @@ def test_get_multiple(
expected = intersect_masks(mask_imgs, **params) expected = intersect_masks(mask_imgs, **params)
assert_array_equal(computed.get_fdata(), expected.get_fdata()) assert_array_equal(computed.get_fdata(), expected.get_fdata())
def test_deregister() -> None:
"""Test mask deregistration."""
deregister_data(kind="mask", name="testmask")
assert "testmask" not in list_data(kind="mask")

View file

@ -84,7 +84,7 @@ class ANTsParcellationWarper:
) )
# Native space warping # Native space warping
if dst == "native": if dst == "native": # pragma: no cover
# Warp data check # Warp data check
if warp_data is None: if warp_data is None:
raise_error("No `warp_data` provided") raise_error("No `warp_data` provided")

View file

@ -32,7 +32,7 @@ class FSLParcellationWarper:
parcellation_img: "Nifti1Image", parcellation_img: "Nifti1Image",
target_data: dict[str, Any], target_data: dict[str, Any],
warp_data: dict[str, Any], warp_data: dict[str, Any],
) -> "Nifti1Image": ) -> "Nifti1Image": # pragma: no cover
"""Warp ``parcellation_img`` to correct space. """Warp ``parcellation_img`` to correct space.
Parameters Parameters

View file

@ -1035,17 +1035,17 @@ def _retrieve_shen(
) )
if n_rois in (268, 368) and year == 2013: if n_rois in (268, 368) and year == 2013:
raise_error( raise_error(
f"The parameter combination `resolution = {resolution}` and " f"The parameter combination `n_rois = {n_rois}` and "
"`year = 2013` is invalid" "`year = 2013` is invalid"
) )
if n_rois in (50, 100, 150) and year in (2015, 2019): if n_rois in (50, 100, 150) and year in (2015, 2019):
raise_error( raise_error(
f"The parameter combination `resolution = {resolution}` and " f"The parameter combination `n_rois = {n_rois}` and "
f"`year = {year}` is invalid" f"`year = {year}` is invalid"
) )
if (n_rois == 268 and year == 2019) or (n_rois == 368 and year == 2015): if (n_rois == 268 and year == 2019) or (n_rois == 368 and year == 2015):
raise_error( raise_error(
f"The parameter combination `resolution = {resolution}` and " f"The parameter combination `n_rois = {n_rois}` and "
f"`year = {year}` is invalid" f"`year = {year}` is invalid"
) )
@ -1312,11 +1312,11 @@ def merge_parcellations(
parcellations_names: list[str], parcellations_names: list[str],
labels_lists: list[list[str]], labels_lists: list[list[str]],
) -> tuple["Nifti1Image", list[str]]: ) -> tuple["Nifti1Image", list[str]]:
"""Merge all parcellations from a list into one parcellation. """Merge multiple parcellations.
Parameters Parameters
---------- ----------
parcellations_list : list of niimg-like object parcellations_list : list of Niimg-like object
List of parcellations to merge. List of parcellations to merge.
parcellations_names: list of str parcellations_names: list of str
List of names for parcellations at the corresponding indices. List of names for parcellations at the corresponding indices.
@ -1326,10 +1326,10 @@ def merge_parcellations(
Returns Returns
------- -------
parcellation : niimg-like object Niimg-like object
The parcellation that results from merging the list of input The parcellation that results from merging the list of input
parcellations. parcellations.
labels : list of str list of str
List of labels for the resultant parcellation. List of labels for the resultant parcellation.
""" """

View file

@ -13,7 +13,12 @@ import pytest
from nilearn.image import new_img_like, resample_to_img from nilearn.image import new_img_like, resample_to_img
from numpy.testing import assert_array_almost_equal, assert_array_equal from numpy.testing import assert_array_almost_equal, assert_array_equal
from junifer.data import ParcellationRegistry from junifer.data import (
get_data,
list_data,
load_data,
register_data,
)
from junifer.data.parcellations import merge_parcellations from junifer.data.parcellations import merge_parcellations
from junifer.data.parcellations._parcellations import ( from junifer.data.parcellations._parcellations import (
_retrieve_aicha, _retrieve_aicha,
@ -35,7 +40,8 @@ from junifer.testing.datagrabbers import (
def test_register_built_in_check() -> None: def test_register_built_in_check() -> None:
"""Test parcellation registration check for built-in parcellations.""" """Test parcellation registration check for built-in parcellations."""
with pytest.raises(ValueError, match=r"built-in parcellation"): with pytest.raises(ValueError, match=r"built-in parcellation"):
ParcellationRegistry().register( register_data(
kind="parcellation",
name="SUITxSUIT", name="SUITxSUIT",
parcellation_path="testparc.nii.gz", parcellation_path="testparc.nii.gz",
parcels_labels=["1", "2", "3"], parcels_labels=["1", "2", "3"],
@ -46,34 +52,40 @@ def test_register_built_in_check() -> None:
def test_list_incorrect() -> None: def test_list_incorrect() -> None:
"""Test incorrect information check for list parcellations.""" """Test incorrect information check for list parcellations."""
assert "testparc" not in ParcellationRegistry().list assert "testparc" not in list_data(kind="parcellation")
def test_register_already_registered() -> None: def test_register_already_registered() -> None:
"""Test parcellation registration check for already registered.""" """Test parcellation registration check for already registered."""
# Register custom parcellation # Register custom parcellation
ParcellationRegistry().register( register_data(
kind="parcellation",
name="testparc", name="testparc",
parcellation_path="testparc.nii.gz", parcellation_path="testparc.nii.gz",
parcels_labels=["1", "2", "3"], parcels_labels=["1", "2", "3"],
space="MNI152Lin", space="MNI152Lin",
) )
assert ( assert (
ParcellationRegistry() load_data(
.load("testparc", target_space="MNI152Lin", path_only=True)[2] kind="parcellation",
.name name="testparc",
target_space="MNI152Lin",
path_only=True,
)[2].name
== "testparc.nii.gz" == "testparc.nii.gz"
) )
# Try registering again # Try registering again
with pytest.raises(ValueError, match=r"already registered."): with pytest.raises(ValueError, match=r"already registered."):
ParcellationRegistry().register( register_data(
kind="parcellation",
name="testparc", name="testparc",
parcellation_path="testparc.nii.gz", parcellation_path="testparc.nii.gz",
parcels_labels=["1", "2", "3"], parcels_labels=["1", "2", "3"],
space="MNI152Lin", space="MNI152Lin",
) )
ParcellationRegistry().register( register_data(
kind="parcellation",
name="testparc", name="testparc",
parcellation_path="testparc2.nii.gz", parcellation_path="testparc2.nii.gz",
parcels_labels=["1", "2", "3"], parcels_labels=["1", "2", "3"],
@ -82,9 +94,12 @@ def test_register_already_registered() -> None:
) )
assert ( assert (
ParcellationRegistry() load_data(
.load("testparc", target_space="MNI152Lin", path_only=True)[2] kind="parcellation",
.name name="testparc",
target_space="MNI152Lin",
path_only=True,
)[2].name
== "testparc2.nii.gz" == "testparc2.nii.gz"
) )
@ -98,27 +113,44 @@ def test_parcellation_wrong_labels_values(tmp_path: Path) -> None:
The path to the test directory. The path to the test directory.
""" """
schaefer, labels, schaefer_path, _ = ParcellationRegistry().load( schaefer, labels, schaefer_path, _ = load_data(
"Schaefer100x7", kind="parcellation",
"MNI152NLin6Asym", name="Schaefer100x7",
target_space="MNI152NLin6Asym",
) )
assert schaefer is not None assert schaefer is not None
# Test wrong number of labels # Test wrong number of labels
ParcellationRegistry().register( register_data(
"WrongLabels", schaefer_path, labels[:10], "MNI152Lin" kind="parcellation",
name="WrongLabels",
parcellation_path=schaefer_path,
parcels_labels=labels[:10],
space="MNI152Lin",
) )
with pytest.raises(ValueError, match=r"has 100 parcels but 10"): with pytest.raises(ValueError, match=r"has 100 parcels but 10"):
ParcellationRegistry().load("WrongLabels", "MNI152NLin6Asym") load_data(
kind="parcellation",
name="WrongLabels",
target_space="MNI152NLin6Asym",
)
# Test wrong number of labels # Test wrong number of labels
ParcellationRegistry().register( register_data(
"WrongLabels2", schaefer_path, [*labels, "wrong"], "MNI152Lin" kind="parcellation",
name="WrongLabels2",
parcellation_path=schaefer_path,
parcels_labels=[*labels, "wrong"],
space="MNI152Lin",
) )
with pytest.raises(ValueError, match=r"has 100 parcels but 101"): with pytest.raises(ValueError, match=r"has 100 parcels but 101"):
ParcellationRegistry().load("WrongLabels2", "MNI152NLin6Asym") load_data(
kind="parcellation",
name="WrongLabels2",
target_space="MNI152NLin6Asym",
)
schaefer_data = schaefer.get_fdata().copy() schaefer_data = schaefer.get_fdata().copy()
schaefer_data[schaefer_data == 50] = 0 schaefer_data[schaefer_data == 50] = 0
@ -126,11 +158,19 @@ def test_parcellation_wrong_labels_values(tmp_path: Path) -> None:
new_schaefer_img = new_img_like(schaefer, schaefer_data) new_schaefer_img = new_img_like(schaefer, schaefer_data)
nib.save(new_schaefer_img, new_schaefer_path) nib.save(new_schaefer_img, new_schaefer_path)
ParcellationRegistry().register( register_data(
"WrongValues", new_schaefer_path, labels[:-1], "MNI152Lin" kind="parcellation",
name="WrongValues",
parcellation_path=new_schaefer_path,
parcels_labels=labels[:-1],
space="MNI152Lin",
) )
with pytest.raises(ValueError, match=r"must have all the values in the"): with pytest.raises(ValueError, match=r"must have all the values in the"):
ParcellationRegistry().load("WrongValues", "MNI152NLin6Asym") load_data(
kind="parcellation",
name="WrongValues",
target_space="MNI152NLin6Asym",
)
schaefer_data = schaefer.get_fdata().copy() schaefer_data = schaefer.get_fdata().copy()
schaefer_data[schaefer_data == 50] = 200 schaefer_data[schaefer_data == 50] = 200
@ -138,11 +178,19 @@ def test_parcellation_wrong_labels_values(tmp_path: Path) -> None:
new_schaefer_img = new_img_like(schaefer, schaefer_data) new_schaefer_img = new_img_like(schaefer, schaefer_data)
nib.save(new_schaefer_img, new_schaefer_path) nib.save(new_schaefer_img, new_schaefer_path)
ParcellationRegistry().register( register_data(
"WrongValues2", new_schaefer_path, labels, "MNI152Lin" kind="parcellation",
name="WrongValues2",
parcellation_path=new_schaefer_path,
parcels_labels=labels,
space="MNI152Lin",
) )
with pytest.raises(ValueError, match=r"must have all the values in the"): with pytest.raises(ValueError, match=r"must have all the values in the"):
ParcellationRegistry().load("WrongValues2", "MNI152NLin6Asym") load_data(
kind="parcellation",
name="WrongValues2",
target_space="MNI152NLin6Asym",
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -195,7 +243,8 @@ def test_register(
""" """
# Register custom parcellation # Register custom parcellation
ParcellationRegistry().register( register_data(
kind="parcellation",
name=name, name=name,
parcellation_path=parcellation_path, parcellation_path=parcellation_path,
parcels_labels=parcels_labels, parcels_labels=parcels_labels,
@ -203,10 +252,13 @@ def test_register(
overwrite=overwrite, overwrite=overwrite,
) )
# List available parcellation and check registration # List available parcellation and check registration
assert name in ParcellationRegistry().list assert name in list_data(kind="parcellation")
# Load registered parcellation # Load registered parcellation
_, lbl, fname, parcellation_space = ParcellationRegistry().load( _, lbl, fname, parcellation_space = load_data(
name=name, target_space=space, path_only=True kind="parcellation",
name=name,
target_space=space,
path_only=True,
) )
# Check values for registered parcellation # Check values for registered parcellation
assert lbl == parcels_labels assert lbl == parcels_labels
@ -237,13 +289,17 @@ def test_list_correct(parcellation_name: str) -> None:
The parametrized parcellation name. The parametrized parcellation name.
""" """
assert parcellation_name in ParcellationRegistry().list assert parcellation_name in list_data(kind="parcellation")
def test_load_incorrect() -> None: def test_load_incorrect() -> None:
"""Test loading of invalid parcellations.""" """Test loading of invalid parcellations."""
with pytest.raises(ValueError, match=r"not found"): with pytest.raises(ValueError, match=r"not found"):
ParcellationRegistry().load("wrongparcellation", "MNI152NLin6Asym") load_data(
kind="parcellation",
name="wrongparcellation",
target_space="MNI152NLin6Asym",
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -309,14 +365,15 @@ def test_schaefer(
""" """
parcellation_name = f"Schaefer{n_rois}x{yeo_networks}" parcellation_name = f"Schaefer{n_rois}x{yeo_networks}"
assert parcellation_name in ParcellationRegistry().list assert parcellation_name in list_data(kind="parcellation")
parcellation_file = ( parcellation_file = (
f"Schaefer2018_{n_rois}Parcels_{yeo_networks}Networks_order_FSLMNI152_" f"Schaefer2018_{n_rois}Parcels_{yeo_networks}Networks_order_FSLMNI152_"
f"{int(resolution)}mm.nii.gz" f"{int(resolution)}mm.nii.gz"
) )
# Load parcellation # Load parcellation
img, label, img_path, space = ParcellationRegistry().load( img, label, img_path, space = load_data(
kind="parcellation",
name=parcellation_name, name=parcellation_name,
target_space="MNI152NLin6Asym", target_space="MNI152NLin6Asym",
resolution=resolution, resolution=resolution,
@ -326,7 +383,8 @@ def test_schaefer(
assert len(label) == n_rois assert len(label) == n_rois
assert space == "MNI152NLin6Asym" assert space == "MNI152NLin6Asym"
assert_array_equal( assert_array_equal(
img.header["pixdim"][1:4], 3 * [resolution] # type: ignore img.header["pixdim"][1:4],
3 * [resolution], # type: ignore
) )
@ -365,9 +423,10 @@ def test_suit(space_key: str, space: str) -> None:
The parametrized space values. The parametrized space values.
""" """
assert f"SUITx{space_key}" in ParcellationRegistry().list assert f"SUITx{space_key}" in list_data(kind="parcellation")
# Load parcellation # Load parcellation
img, label, img_path, parcellation_space = ParcellationRegistry().load( img, label, img_path, parcellation_space = load_data(
kind="parcellation",
name=f"SUITx{space_key}", name=f"SUITx{space_key}",
target_space=space, target_space=space,
) )
@ -398,13 +457,14 @@ def test_tian_3T_6thgeneration(scale: int, n_label: int) -> None:
The parametrized n_label values. The parametrized n_label values.
""" """
parcellations = ParcellationRegistry().list parcellations = list_data(kind="parcellation")
assert "TianxS1x3TxMNI6thgeneration" in parcellations assert "TianxS1x3TxMNI6thgeneration" in parcellations
assert "TianxS2x3TxMNI6thgeneration" in parcellations assert "TianxS2x3TxMNI6thgeneration" in parcellations
assert "TianxS3x3TxMNI6thgeneration" in parcellations assert "TianxS3x3TxMNI6thgeneration" in parcellations
assert "TianxS4x3TxMNI6thgeneration" in parcellations assert "TianxS4x3TxMNI6thgeneration" in parcellations
# Load parcellation # Load parcellation
img, lbl, fname, space = ParcellationRegistry().load( img, lbl, fname, space = load_data(
kind="parcellation",
name=f"TianxS{scale}x3TxMNI6thgeneration", name=f"TianxS{scale}x3TxMNI6thgeneration",
target_space="MNI152NLin2009cAsym", # force highest resolution target_space="MNI152NLin2009cAsym", # force highest resolution
) )
@ -415,7 +475,8 @@ def test_tian_3T_6thgeneration(scale: int, n_label: int) -> None:
assert len(lbl) == n_label assert len(lbl) == n_label
assert_array_equal(img.header["pixdim"][1:4], [1, 1, 1]) assert_array_equal(img.header["pixdim"][1:4], [1, 1, 1])
# Load parcellation # Load parcellation
img, lbl, fname, space = ParcellationRegistry().load( img, lbl, fname, space = load_data(
kind="parcellation",
name=f"TianxS{scale}x3TxMNI6thgeneration", name=f"TianxS{scale}x3TxMNI6thgeneration",
target_space="MNI152NLin6Asym", target_space="MNI152NLin6Asym",
resolution=2, resolution=2,
@ -442,13 +503,14 @@ def test_tian_3T_nonlinear2009cAsym(scale: int, n_label: int) -> None:
The parametrized n_label values. The parametrized n_label values.
""" """
parcellations = ParcellationRegistry().list parcellations = list_data(kind="parcellation")
assert "TianxS1x3TxMNInonlinear2009cAsym" in parcellations assert "TianxS1x3TxMNInonlinear2009cAsym" in parcellations
assert "TianxS2x3TxMNInonlinear2009cAsym" in parcellations assert "TianxS2x3TxMNInonlinear2009cAsym" in parcellations
assert "TianxS3x3TxMNInonlinear2009cAsym" in parcellations assert "TianxS3x3TxMNInonlinear2009cAsym" in parcellations
assert "TianxS4x3TxMNInonlinear2009cAsym" in parcellations assert "TianxS4x3TxMNInonlinear2009cAsym" in parcellations
# Load parcellation # Load parcellation
img, lbl, fname, space = ParcellationRegistry().load( img, lbl, fname, space = load_data(
kind="parcellation",
name=f"TianxS{scale}x3TxMNInonlinear2009cAsym", name=f"TianxS{scale}x3TxMNInonlinear2009cAsym",
target_space="MNI152NLin6Asym", # force highest resolution target_space="MNI152NLin6Asym", # force highest resolution
) )
@ -459,7 +521,8 @@ def test_tian_3T_nonlinear2009cAsym(scale: int, n_label: int) -> None:
assert len(lbl) == n_label assert len(lbl) == n_label
assert_array_equal(img.header["pixdim"][1:4], [1, 1, 1]) assert_array_equal(img.header["pixdim"][1:4], [1, 1, 1])
# Load parcellation # Load parcellation
img, lbl, fname, space = ParcellationRegistry().load( img, lbl, fname, space = load_data(
kind="parcellation",
name=f"TianxS{scale}x3TxMNInonlinear2009cAsym", name=f"TianxS{scale}x3TxMNInonlinear2009cAsym",
target_space="MNI152NLin2009cAsym", target_space="MNI152NLin2009cAsym",
resolution=2, resolution=2,
@ -486,13 +549,14 @@ def test_tian_7T_6thgeneration(scale: int, n_label: int) -> None:
The parametrized n_label values. The parametrized n_label values.
""" """
parcellations = ParcellationRegistry().list parcellations = list_data(kind="parcellation")
assert "TianxS1x7TxMNI6thgeneration" in parcellations assert "TianxS1x7TxMNI6thgeneration" in parcellations
assert "TianxS2x7TxMNI6thgeneration" in parcellations assert "TianxS2x7TxMNI6thgeneration" in parcellations
assert "TianxS3x7TxMNI6thgeneration" in parcellations assert "TianxS3x7TxMNI6thgeneration" in parcellations
assert "TianxS4x7TxMNI6thgeneration" in parcellations assert "TianxS4x7TxMNI6thgeneration" in parcellations
# Load parcellation # Load parcellation
img, lbl, fname, space = ParcellationRegistry().load( img, lbl, fname, space = load_data(
kind="parcellation",
name=f"TianxS{scale}x7TxMNI6thgeneration", name=f"TianxS{scale}x7TxMNI6thgeneration",
target_space="MNI152NLin6Asym", target_space="MNI152NLin6Asym",
) )
@ -502,7 +566,8 @@ def test_tian_7T_6thgeneration(scale: int, n_label: int) -> None:
assert space == "MNI152NLin6Asym" assert space == "MNI152NLin6Asym"
assert len(lbl) == n_label assert len(lbl) == n_label
assert_array_almost_equal( assert_array_almost_equal(
img.header["pixdim"][1:4], [1.6, 1.6, 1.6] # type: ignore img.header["pixdim"][1:4],
[1.6, 1.6, 1.6], # type: ignore
) )
@ -552,9 +617,10 @@ def test_aicha(version: int) -> None:
The parametrized version values. The parametrized version values.
""" """
assert f"AICHA_v{version}" in ParcellationRegistry().list assert f"AICHA_v{version}" in list_data(kind="parcellation")
# Load parcellation # Load parcellation
img, label, img_path, space = ParcellationRegistry().load( img, label, img_path, space = load_data(
kind="parcellation",
name=f"AICHA_v{version}", name=f"AICHA_v{version}",
target_space="IXI549Space", target_space="IXI549Space",
) )
@ -610,9 +676,10 @@ def test_shen(
The parametrized partial file names. The parametrized partial file names.
""" """
assert f"Shen_{year}_{n_rois}" in ParcellationRegistry().list assert f"Shen_{year}_{n_rois}" in list_data(kind="parcellation")
# Load parcellation # Load parcellation
img, label, img_path, space = ParcellationRegistry().load( img, label, img_path, space = load_data(
kind="parcellation",
name=f"Shen_{year}_{n_rois}", name=f"Shen_{year}_{n_rois}",
target_space="MNI152NLin2009cAsym", target_space="MNI152NLin2009cAsym",
resolution=resolution, resolution=resolution,
@ -622,7 +689,8 @@ def test_shen(
assert space == "MNI152NLin2009cAsym" assert space == "MNI152NLin2009cAsym"
assert len(label) == n_labels assert len(label) == n_labels
assert_array_equal( assert_array_equal(
img.header["pixdim"][1:4], 3 * [resolution] # type: ignore img.header["pixdim"][1:4],
3 * [resolution], # type: ignore
) )
@ -771,7 +839,7 @@ def test_yan(
The parametrized Kong networks values. The parametrized Kong networks values.
""" """
parcellations = ParcellationRegistry().list parcellations = list_data(kind="parcellation")
if yeo_networks: if yeo_networks:
parcellation_name = f"Yan{n_rois}xYeo{yeo_networks}" parcellation_name = f"Yan{n_rois}xYeo{yeo_networks}"
assert parcellation_name in parcellations assert parcellation_name in parcellations
@ -787,7 +855,8 @@ def test_yan(
f"{int(resolution)}mm.nii.gz" f"{int(resolution)}mm.nii.gz"
) )
# Load parcellation # Load parcellation
img, label, img_path, space = ParcellationRegistry().load( img, label, img_path, space = load_data(
kind="parcellation",
name=parcellation_name, name=parcellation_name,
target_space="MNI152NLin6Asym", target_space="MNI152NLin6Asym",
resolution=resolution, resolution=resolution,
@ -797,7 +866,8 @@ def test_yan(
assert space == "MNI152NLin6Asym" assert space == "MNI152NLin6Asym"
assert len(label) == n_rois assert len(label) == n_rois
assert_array_equal( assert_array_equal(
img.header["pixdim"][1:4], 3 * [resolution] # type: ignore img.header["pixdim"][1:4],
3 * [resolution], # type: ignore
) )
@ -877,7 +947,7 @@ def test_brainnetome(
The parametrized threshold values. The parametrized threshold values.
""" """
parcellations = ParcellationRegistry().list parcellations = list_data(kind="parcellation")
parcellation_name = f"Brainnetome_thr{threshold}" parcellation_name = f"Brainnetome_thr{threshold}"
assert parcellation_name in parcellations assert parcellation_name in parcellations
@ -887,7 +957,8 @@ def test_brainnetome(
parcellation_file = f"BNA-maxprob-thr{threshold}-{resolution}mm.nii.gz" parcellation_file = f"BNA-maxprob-thr{threshold}-{resolution}mm.nii.gz"
# Load parcellation # Load parcellation
img, label, img_path, space = ParcellationRegistry().load( img, label, img_path, space = load_data(
kind="parcellation",
name=parcellation_name, name=parcellation_name,
target_space="MNI152NLin6Asym", target_space="MNI152NLin6Asym",
resolution=resolution, resolution=resolution,
@ -897,7 +968,8 @@ def test_brainnetome(
assert space == "MNI152NLin6Asym" assert space == "MNI152NLin6Asym"
assert len(label) == 246 assert len(label) == 246
assert_array_equal( assert_array_equal(
img.header["pixdim"][1:4], 3 * [resolution] # type: ignore img.header["pixdim"][1:4],
3 * [resolution], # type: ignore
) )
@ -912,11 +984,14 @@ def test_retrieve_brainnetome_incorrect_threshold() -> None:
def test_merge_parcellations() -> None: def test_merge_parcellations() -> None:
"""Test merging parcellations.""" """Test merging parcellations."""
# load some parcellations for testing # load some parcellations for testing
schaefer_parcellation, schaefer_labels, _, _ = ParcellationRegistry().load( schaefer_parcellation, schaefer_labels, _, _ = load_data(
"Schaefer100x17", target_space="MNI152NLin2009cAsym" kind="parcellation",
name="Schaefer100x17",
target_space="MNI152NLin2009cAsym",
) )
tian_parcellation, tian_labels, _, _ = ParcellationRegistry().load( tian_parcellation, tian_labels, _, _ = load_data(
"TianxS2x3TxMNInonlinear2009cAsym", kind="parcellation",
name="TianxS2x3TxMNInonlinear2009cAsym",
target_space="MNI152NLin2009cAsym", target_space="MNI152NLin2009cAsym",
) )
# prepare the list of the actual parcellations # prepare the list of the actual parcellations
@ -949,8 +1024,10 @@ def test_merge_parcellations_3D_multiple_non_overlapping(
""" """
# Get the testing parcellation # Get the testing parcellation
parcellation, labels, _, _ = ParcellationRegistry().load( parcellation, labels, _, _ = load_data(
"Schaefer100x7", target_space="MNI152NLin2009cAsym" kind="parcellation",
name="Schaefer100x7",
target_space="MNI152NLin2009cAsym",
) )
assert parcellation is not None assert parcellation is not None
@ -986,8 +1063,10 @@ def test_merge_parcellations_3D_multiple_overlapping() -> None:
"""Test merge_parcellations with multiple overlapping parcellations.""" """Test merge_parcellations with multiple overlapping parcellations."""
# Get the testing parcellation # Get the testing parcellation
parcellation, labels, _, _ = ParcellationRegistry().load( parcellation, labels, _, _ = load_data(
"Schaefer100x7", target_space="MNI152NLin2009cAsym" kind="parcellation",
name="Schaefer100x7",
target_space="MNI152NLin2009cAsym",
) )
assert parcellation is not None assert parcellation is not None
@ -1023,8 +1102,10 @@ def test_merge_parcellations_3D_multiple_duplicated_labels() -> None:
"""Test merge_parcellations with duplicated labels.""" """Test merge_parcellations with duplicated labels."""
# Get the testing parcellation # Get the testing parcellation
parcellation, labels, _, _ = ParcellationRegistry().load( parcellation, labels, _, _ = load_data(
"Schaefer100x7", target_space="MNI152NLin2009cAsym" kind="parcellation",
name="Schaefer100x7",
target_space="MNI152NLin2009cAsym",
) )
assert parcellation is not None assert parcellation is not None
@ -1064,15 +1145,17 @@ def test_get_single() -> None:
bold = element_data["BOLD"] bold = element_data["BOLD"]
bold_img = bold["data"] bold_img = bold["data"]
# Get tailored parcellation # Get tailored parcellation
tailored_parcellation, tailored_labels = ParcellationRegistry().get( tailored_parcellation, tailored_labels = get_data(
parcellations=["Shen_2015_268"], kind="parcellation",
names=["Shen_2015_268"],
target_data=bold, target_data=bold,
) )
# Check shape and affine with original element data # Check shape and affine with original element data
assert tailored_parcellation.shape == bold_img.shape[:3] assert tailored_parcellation.shape == bold_img.shape[:3]
assert_array_equal(tailored_parcellation.affine, bold_img.affine) assert_array_equal(tailored_parcellation.affine, bold_img.affine)
# Get raw parcellation # Get raw parcellation
raw_parcellation, raw_labels, _, _ = ParcellationRegistry().load( raw_parcellation, raw_labels, _, _ = load_data(
kind="parcellation",
name="Shen_2015_268", name="Shen_2015_268",
target_space="MNI152NLin2009cAsym", target_space="MNI152NLin2009cAsym",
resolution=4, resolution=4,
@ -1098,8 +1181,9 @@ def test_get_multi_same_space() -> None:
bold = element_data["BOLD"] bold = element_data["BOLD"]
bold_img = bold["data"] bold_img = bold["data"]
# Get tailored parcellation # Get tailored parcellation
tailored_parcellation, tailored_labels = ParcellationRegistry().get( tailored_parcellation, tailored_labels = get_data(
parcellations=[ kind="parcellation",
names=[
"Shen_2015_268", "Shen_2015_268",
"TianxS1x3TxMNInonlinear2009cAsym", "TianxS1x3TxMNInonlinear2009cAsym",
], ],
@ -1116,7 +1200,8 @@ def test_get_multi_same_space() -> None:
"TianxS1x3TxMNInonlinear2009cAsym", "TianxS1x3TxMNInonlinear2009cAsym",
] ]
for name in parcellations_names: for name in parcellations_names:
img, labels, _, _ = ParcellationRegistry().load( img, labels, _, _ = load_data(
kind="parcellation",
name=name, name=name,
target_space="MNI152NLin2009cAsym", target_space="MNI152NLin2009cAsym",
resolution=4, resolution=4,
@ -1152,8 +1237,9 @@ def test_get_multi_different_space() -> None:
with OasisVBMTestingDataGrabber() as dg: with OasisVBMTestingDataGrabber() as dg:
element_data = DefaultDataReader().fit_transform(dg["sub-01"]) element_data = DefaultDataReader().fit_transform(dg["sub-01"])
# Get tailored parcellation # Get tailored parcellation
ParcellationRegistry().get( get_data(
parcellations=[ kind="parcellation",
names=[
"Schaefer100x7", "Schaefer100x7",
"TianxS1x3TxMNInonlinear2009cAsym", "TianxS1x3TxMNInonlinear2009cAsym",
], ],

View file

@ -3,7 +3,6 @@
# Authors: Federico Raimondo <f.raimondo@fz-juelich.de> # Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
# License: AGPL # License: AGPL
import numpy as np import numpy as np
import pytest import pytest

View file

@ -76,7 +76,7 @@ def get_native_warper(
target_data: MutableMapping, target_data: MutableMapping,
other_data: MutableMapping, other_data: MutableMapping,
inverse: bool = False, inverse: bool = False,
) -> dict: ) -> dict: # pragma: no cover
"""Get correct warping specification for native space. """Get correct warping specification for native space.
Parameters Parameters

View file

@ -35,6 +35,12 @@ class DataladAOMICID1000(PatternDataladDataGrabber):
space : {"native", "MNI152NLin2009cAsym"}, optional space : {"native", "MNI152NLin2009cAsym"}, optional
The space to use for the data (default "MNI152NLin2009cAsym"). The space to use for the data (default "MNI152NLin2009cAsym").
Raises
------
ValueError
If invalid value is passed for:
* ``space``
""" """
def __init__( def __init__(

View file

@ -43,7 +43,9 @@ class DataladAOMICPIOP1(PatternDataladDataGrabber):
Raises Raises
------ ------
ValueError ValueError
If invalid value is passed for ``tasks``. If invalid value is passed for:
* ``tasks``
* ``space``
""" """
@ -79,8 +81,7 @@ class DataladAOMICPIOP1(PatternDataladDataGrabber):
for t in tasks: for t in tasks:
if t not in all_tasks: if t not in all_tasks:
raise_error( raise_error(
f"{t} is not a valid task in the AOMIC PIOP1" f"{t} is not a valid task in the AOMIC PIOP1 dataset!"
" dataset!"
) )
self.tasks = tasks self.tasks = tasks
# Descriptor for space in `anat` # Descriptor for space in `anat`

View file

@ -43,7 +43,9 @@ class DataladAOMICPIOP2(PatternDataladDataGrabber):
Raises Raises
------ ------
ValueError ValueError
If invalid value is passed for ``tasks``. If invalid value is passed for:
* ``tasks``
* ``space``
""" """
@ -77,8 +79,7 @@ class DataladAOMICPIOP2(PatternDataladDataGrabber):
for t in tasks: for t in tasks:
if t not in all_tasks: if t not in all_tasks:
raise_error( raise_error(
f"{t} is not a valid task in the AOMIC PIOP2" f"{t} is not a valid task in the AOMIC PIOP2 dataset!"
" dataset!"
) )
self.tasks = tasks self.tasks = tasks
# Descriptor for space in `anat` # Descriptor for space in `anat`

View file

@ -5,7 +5,6 @@
# Synchon Mandal <s.mandal@fz-juelich.de> # Synchon Mandal <s.mandal@fz-juelich.de>
# License: AGPL # License: AGPL
from ..api.decorators import register_datagrabber from ..api.decorators import register_datagrabber
from ..utils import logger from ..utils import logger
from .datalad_base import DataladDataGrabber from .datalad_base import DataladDataGrabber

View file

@ -3,7 +3,6 @@
# Authors: Synchon Mandal <s.mandal@fz-juelich.de> # Authors: Synchon Mandal <s.mandal@fz-juelich.de>
# License: AGPL # License: AGPL
from ..typing import DataGrabberPatterns from ..typing import DataGrabberPatterns
from ..utils import logger, raise_error, warn_with_log from ..utils import logger, raise_error, warn_with_log

View file

@ -264,7 +264,7 @@ def test_DMCC13Benchmark_invalid_sessions():
"""Test DMCC13Benchmark DataGrabber invalid sessions.""" """Test DMCC13Benchmark DataGrabber invalid sessions."""
with pytest.raises( with pytest.raises(
ValueError, ValueError,
match=("phonyses is not a valid session in " "the DMCC dataset"), match=("phonyses is not a valid session in the DMCC dataset"),
): ):
DMCC13Benchmark(sessions="phonyses") DMCC13Benchmark(sessions="phonyses")
@ -273,9 +273,7 @@ def test_DMCC13Benchmark_invalid_tasks():
"""Test DMCC13Benchmark DataGrabber invalid tasks.""" """Test DMCC13Benchmark DataGrabber invalid tasks."""
with pytest.raises( with pytest.raises(
ValueError, ValueError,
match=( match=("thisisnotarealtask is not a valid task in the DMCC dataset"),
"thisisnotarealtask is not a valid task in " "the DMCC dataset"
),
): ):
DMCC13Benchmark(tasks="thisisnotarealtask") DMCC13Benchmark(tasks="thisisnotarealtask")
@ -284,9 +282,7 @@ def test_DMCC13Benchmark_phase_encodings():
"""Test DMCC13Benchmark DataGrabber invalid phase encodings.""" """Test DMCC13Benchmark DataGrabber invalid phase encodings."""
with pytest.raises( with pytest.raises(
ValueError, ValueError,
match=( match=("moonphase is not a valid phase encoding in the DMCC dataset"),
"moonphase is not a valid phase encoding in " "the DMCC dataset"
),
): ):
DMCC13Benchmark(phase_encodings="moonphase") DMCC13Benchmark(phase_encodings="moonphase")
@ -295,6 +291,6 @@ def test_DMCC13Benchmark_runs():
"""Test DMCC13Benchmark DataGrabber invalid runs.""" """Test DMCC13Benchmark DataGrabber invalid runs."""
with pytest.raises( with pytest.raises(
ValueError, ValueError,
match=("cerebralrun is not a valid run in " "the DMCC dataset"), match=("cerebralrun is not a valid run in the DMCC dataset"),
): ):
DMCC13Benchmark(runs="cerebralrun") DMCC13Benchmark(runs="cerebralrun")

View file

@ -229,9 +229,9 @@ class BaseMarker(ABC, PipelineStepMixin, UpdateMetaMixin):
# feature data is not manipulated, only meta # feature data is not manipulated, only meta
self.update_meta(feature_data_copy, "marker") self.update_meta(feature_data_copy, "marker")
# Update marker feature's metadata name # Update marker feature's metadata name
feature_data_copy["meta"]["marker"][ feature_data_copy["meta"]["marker"]["name"] += (
"name" f"_{feature_name}"
] += f"_{feature_name}" )
if storage is not None: if storage is not None:
logger.info(f"Storing in {storage}") logger.info(f"Storing in {storage}")

View file

@ -116,7 +116,7 @@ class BrainPrint(BaseMarker):
aseg_path: Path, aseg_path: Path,
norm_path: Path, norm_path: Path,
indices: list, indices: list,
) -> Path: ) -> Path: # pragma: no cover
"""Generate a surface from the aseg and label files. """Generate a surface from the aseg and label files.
Parameters Parameters
@ -191,7 +191,7 @@ class BrainPrint(BaseMarker):
self, self,
aseg_path: Path, aseg_path: Path,
norm_path: Path, norm_path: Path,
) -> dict[str, Path]: ) -> dict[str, Path]: # pragma: no cover
"""Create surfaces from FreeSurfer aseg labels. """Create surfaces from FreeSurfer aseg labels.
Parameters Parameters
@ -266,7 +266,7 @@ class BrainPrint(BaseMarker):
rh_white_path: Path, rh_white_path: Path,
lh_pial_path: Path, lh_pial_path: Path,
rh_pial_path: Path, rh_pial_path: Path,
) -> dict[str, Path]: ) -> dict[str, Path]: # pragma: no cover
"""Create cortical surfaces from FreeSurfer labels. """Create cortical surfaces from FreeSurfer labels.
Parameters Parameters
@ -308,7 +308,7 @@ class BrainPrint(BaseMarker):
def _fix_nan( def _fix_nan(
self, self,
input_data: list[Union[float, str, npt.ArrayLike]], input_data: list[Union[float, str, npt.ArrayLike]],
) -> np.ndarray: ) -> np.ndarray: # pragma: no cover
"""Convert BrainPrint output with string NaN to ``numpy.nan``. """Convert BrainPrint output with string NaN to ``numpy.nan``.
Parameters Parameters
@ -330,7 +330,7 @@ class BrainPrint(BaseMarker):
self, self,
input: dict[str, Any], input: dict[str, Any],
extra_input: Optional[dict] = None, extra_input: Optional[dict] = None,
) -> dict: ) -> dict: # pragma: no cover
"""Compute. """Compute.
Parameters Parameters

View file

@ -114,9 +114,9 @@ class MultiscaleEntropyAUC(ComplexityBase):
assert isinstance(emb_dim, int), "Embedding dimension must be integer." assert isinstance(emb_dim, int), "Embedding dimension must be integer."
assert isinstance(scale, int), "Scale must be integer." assert isinstance(scale, int), "Scale must be integer."
assert isinstance( assert isinstance(tol, float), (
tol, float "Tolerance must be a positive float number."
), "Tolerance must be a positive float number." )
_, n_roi = extracted_bold_values.shape _, n_roi = extracted_bold_values.shape
MSEn_auc_roi = np.zeros((n_roi, 1)) MSEn_auc_roi = np.zeros((n_roi, 1))

View file

@ -114,9 +114,9 @@ class RangeEntropy(ComplexityBase):
assert isinstance(emb_dim, int), "Embedding dimension must be integer." assert isinstance(emb_dim, int), "Embedding dimension must be integer."
assert isinstance(delay, int), "Delay must be integer." assert isinstance(delay, int), "Delay must be integer."
assert isinstance( assert isinstance(tolerance, float), (
tolerance, float "Tolerance must be a float number between 0 and 1."
), "Tolerance must be a float number between 0 and 1." )
_, n_roi = extracted_bold_values.shape _, n_roi = extracted_bold_values.shape
range_en_roi = np.zeros((n_roi, 1)) range_en_roi = np.zeros((n_roi, 1))

View file

@ -115,9 +115,9 @@ class SampleEntropy(ComplexityBase):
assert isinstance(emb_dim, int), "Embedding dimension must be integer." assert isinstance(emb_dim, int), "Embedding dimension must be integer."
assert isinstance(delay, int), "Delay must be integer." assert isinstance(delay, int), "Delay must be integer."
assert isinstance( assert isinstance(tol, float), (
tol, float "Tolerance must be a positive float number."
), "Tolerance must be a positive float number." )
_, n_roi = extracted_bold_values.shape _, n_roi = extracted_bold_values.shape
samp_en_roi = np.zeros((n_roi, 1)) samp_en_roi = np.zeros((n_roi, 1))

View file

@ -151,9 +151,7 @@ class ALFFParcels(ALFFBase):
).compute( ).compute(
input=aggregation_alff_input, input=aggregation_alff_input,
extra_input=extra_input, extra_input=extra_input,
)[ )["aggregation"],
"aggregation"
],
}, },
"falff": { "falff": {
**ParcelAggregation( **ParcelAggregation(
@ -165,8 +163,6 @@ class ALFFParcels(ALFFBase):
).compute( ).compute(
input=aggregation_falff_input, input=aggregation_falff_input,
extra_input=extra_input, extra_input=extra_input,
)[ )["aggregation"],
"aggregation"
],
}, },
} }

View file

@ -164,9 +164,7 @@ class ALFFSpheres(ALFFBase):
).compute( ).compute(
input=aggregation_alff_input, input=aggregation_alff_input,
extra_input=extra_input, extra_input=extra_input,
)[ )["aggregation"],
"aggregation"
],
}, },
"falff": { "falff": {
**SphereAggregation( **SphereAggregation(
@ -180,8 +178,6 @@ class ALFFSpheres(ALFFBase):
).compute( ).compute(
input=aggregation_falff_input, input=aggregation_falff_input,
extra_input=extra_input, extra_input=extra_input,
)[ )["aggregation"],
"aggregation"
],
}, },
} }

View file

@ -3,7 +3,6 @@
# Authors: Synchon Mandal <s.mandal@fz-juelich.de> # Authors: Synchon Mandal <s.mandal@fz-juelich.de>
# License: AGPL # License: AGPL
from abc import abstractmethod from abc import abstractmethod
from typing import Any, ClassVar, Optional, Union from typing import Any, ClassVar, Optional, Union

View file

@ -91,7 +91,8 @@ def test_FunctionalConnectivityParcels(
) )
# Compute the connectivity measure # Compute the connectivity measure
connectivity_measure = ConnectivityMeasure( connectivity_measure = ConnectivityMeasure(
cov_estimator=cov_estimator, kind="correlation" # type: ignore cov_estimator=cov_estimator,
kind="correlation", # type: ignore
).fit_transform([extracted_timeseries])[0] ).fit_transform([extracted_timeseries])[0]
# Check that FC are almost equal # Check that FC are almost equal

View file

@ -92,7 +92,8 @@ def test_FunctionalConnectivitySpheres(
) )
# Compute the connectivity measure # Compute the connectivity measure
connectivity_measure = ConnectivityMeasure( connectivity_measure = ConnectivityMeasure(
cov_estimator=cov_estimator, kind="correlation" # type: ignore cov_estimator=cov_estimator,
kind="correlation", # type: ignore
).fit_transform([extracted_timeseries])[0] ).fit_transform([extracted_timeseries])[0]
# Check that FC are almost equal # Check that FC are almost equal

View file

@ -41,7 +41,7 @@ class AFNIReHo(metaclass=Singleton):
}, },
] ]
def __del__(self) -> None: def __del__(self) -> None: # pragma: no cover
"""Terminate the class.""" """Terminate the class."""
# Clear the computation cache # Clear the computation cache
logger.debug("Clearing cache for ReHo computation via AFNI") logger.debug("Clearing cache for ReHo computation via AFNI")

View file

@ -3,7 +3,6 @@
# Authors: Synchon Mandal <s.mandal@fz-juelich.de> # Authors: Synchon Mandal <s.mandal@fz-juelich.de>
# License: AGPL # License: AGPL
from pathlib import Path from pathlib import Path
from typing import ( from typing import (
TYPE_CHECKING, TYPE_CHECKING,

View file

@ -3,7 +3,6 @@
# Authors: Synchon Mandal <s.mandal@fz-juelich.de> # Authors: Synchon Mandal <s.mandal@fz-juelich.de>
# License: AGPL # License: AGPL
from typing import Any, Optional, Union from typing import Any, Optional, Union
import numpy as np import numpy as np

View file

@ -3,7 +3,6 @@
# Authors: Synchon Mandal <s.mandal@fz-juelich.de> # Authors: Synchon Mandal <s.mandal@fz-juelich.de>
# License: AGPL # License: AGPL
from typing import Any, Optional, Union from typing import Any, Optional, Union
import numpy as np import numpy as np

View file

@ -3,7 +3,6 @@
# Authors: Leonard Sasse <l.sasse@fz-juelich.de> # Authors: Leonard Sasse <l.sasse@fz-juelich.de>
# License: AGPL # License: AGPL
from abc import abstractmethod from abc import abstractmethod
from typing import Any, ClassVar, Optional, Union from typing import Any, ClassVar, Optional, Union

View file

@ -20,7 +20,6 @@ def test_base_marker_subclassing() -> None:
# Create concrete class # Create concrete class
class MyBaseMarker(BaseMarker): class MyBaseMarker(BaseMarker):
_MARKER_INOUT_MAPPINGS = { # noqa: RUF012 _MARKER_INOUT_MAPPINGS = { # noqa: RUF012
"BOLD": { "BOLD": {
"feat_1": "timeseries", "feat_1": "timeseries",

View file

@ -19,7 +19,7 @@ def normalize(
storage: StorageLike, storage: StorageLike,
features: dict[str, dict[str, Optional[str]]], features: dict[str, dict[str, Optional[str]]],
kind: str, kind: str,
) -> pd.DataFrame: ) -> pd.DataFrame: # pragma: no cover
"""Read stored brainprint data and normalize either surfaces or volumes. """Read stored brainprint data and normalize either surfaces or volumes.
Parameters Parameters
@ -79,7 +79,7 @@ def normalize(
) )
else: else:
raise_error( raise_error(
"Invalid value for `kind`, should be one of: " f"{valid_kind}" f"Invalid value for `kind`, should be one of: {valid_kind}"
) )
return normalized_df return normalized_df
@ -89,7 +89,7 @@ def reweight(
storage: StorageLike, storage: StorageLike,
feature_name: Optional[str] = None, feature_name: Optional[str] = None,
feature_md5: Optional[str] = None, feature_md5: Optional[str] = None,
) -> pd.DataFrame: ) -> pd.DataFrame: # pragma: no cover
"""Read stored brainprint data and reweight eigenvalues. """Read stored brainprint data and reweight eigenvalues.
Parameters Parameters

View file

@ -3,7 +3,6 @@
# Authors: Synchon Mandal <s.mandal@fz-juelich.de> # Authors: Synchon Mandal <s.mandal@fz-juelich.de>
# License: AGPL # License: AGPL
from typing import Optional from typing import Optional
import pandas as pd import pandas as pd
@ -85,7 +84,7 @@ def read_transform(
# Check bctpy import # Check bctpy import
try: try:
import bct import bct
except ImportError as err: except ImportError as err: # pragma: no cover
raise_error(msg=str(err), klass=ImportError) raise_error(msg=str(err), klass=ImportError)
# Warning about function usage # Warning about function usage

View file

@ -3,7 +3,6 @@
# Authors: Synchon Mandal <s.mandal@fz-juelich.de> # Authors: Synchon Mandal <s.mandal@fz-juelich.de>
# License: AGPL # License: AGPL
import logging import logging
from pathlib import Path from pathlib import Path

View file

@ -186,7 +186,8 @@ def test_marker_collection_storage(tmp_path: Path) -> None:
assert out is None assert out is None
mc2 = MarkerCollection( mc2 = MarkerCollection(
markers=markers, datareader=DefaultDataReader() # type: ignore markers=markers,
datareader=DefaultDataReader(), # type: ignore
) )
mc2.validate(dg) mc2.validate(dg)
assert mc2._storage is None assert mc2._storage is None

View file

@ -197,8 +197,7 @@ class WorkDirManager(metaclass=Singleton):
return return
if self._elementdir is not None: if self._elementdir is not None:
logger.debug( logger.debug(
"Deleting element directory at " f"Deleting element directory at {self._elementdir.resolve()!s}"
f"{self._elementdir.resolve()!s}"
) )
shutil.rmtree(self._elementdir, ignore_errors=True) shutil.rmtree(self._elementdir, ignore_errors=True)
self._elementdir = None self._elementdir = None

View file

@ -572,7 +572,7 @@ class fMRIPrepConfoundRemover(BasePreprocessor):
if bold_img.get_fdata().shape[3] != len(confound_df): if bold_img.get_fdata().shape[3] != len(confound_df):
raise_error( raise_error(
"Image time series and confounds have different length!\n" "Image time series and confounds have different length!\n"
f"\tImage time series: { bold_img.get_fdata().shape[3]}\n" f"\tImage time series: {bold_img.get_fdata().shape[3]}\n"
f"\tConfounds: {len(confound_df)}" f"\tConfounds: {len(confound_df)}"
) )

View file

@ -5,7 +5,6 @@
# Synchon Mandal <s.mandal@fz-juelich.de> # Synchon Mandal <s.mandal@fz-juelich.de>
# License: AGPL # License: AGPL
import numpy as np import numpy as np
import pandas as pd import pandas as pd
import pytest import pytest

View file

@ -3,7 +3,6 @@
# Authors: Synchon Mandal <s.mandal@fz-juelich.de> # Authors: Synchon Mandal <s.mandal@fz-juelich.de>
# License: AGPL # License: AGPL
import pytest import pytest
from junifer.datareader import DefaultDataReader from junifer.datareader import DefaultDataReader

View file

@ -72,7 +72,7 @@ class ANTsWarper:
) )
# Native space warping # Native space warping
if reference == "T1w": if reference == "T1w": # pragma: no cover
logger.debug("Using ANTs for space warping") logger.debug("Using ANTs for space warping")
# Get the min of the voxel sizes from input and use it as the # Get the min of the voxel sizes from input and use it as the
@ -237,8 +237,7 @@ class ANTsWarper:
if input.get("mask") is not None: if input.get("mask") is not None:
# Create a tempfile for warped mask output # Create a tempfile for warped mask output
apply_transforms_mask_out_path = element_tempdir / ( apply_transforms_mask_out_path = element_tempdir / (
f"warped_mask_from_{input['space']}_to_" f"warped_mask_from_{input['space']}_to_{reference}.nii.gz"
f"{reference}.nii.gz"
) )
# Set antsApplyTransforms command # Set antsApplyTransforms command
apply_transforms_mask_cmd = [ apply_transforms_mask_cmd = [

View file

@ -40,7 +40,7 @@ class FSLWarper:
self, self,
input: dict[str, Any], input: dict[str, Any],
extra_input: dict[str, Any], extra_input: dict[str, Any],
) -> dict[str, Any]: ) -> dict[str, Any]: # pragma: no cover
"""Preprocess using FSL. """Preprocess using FSL.
Parameters Parameters

View file

@ -77,7 +77,7 @@ class SpaceWarper(BasePreprocessor):
self.reference = reference self.reference = reference
# Set required data types based on reference and # Set required data types based on reference and
# initialize superclass # initialize superclass
if self.reference == "T1w": if self.reference == "T1w": # pragma: no cover
required_data_types = [self.reference, "Warp"] required_data_types = [self.reference, "Warp"]
# Listify on # Listify on
if not isinstance(on, list): if not isinstance(on, list):
@ -170,7 +170,9 @@ class SpaceWarper(BasePreprocessor):
""" """
logger.info(f"Warping to {self.reference} space using SpaceWarper") logger.info(f"Warping to {self.reference} space using SpaceWarper")
# Transform to native space # Transform to native space
if self.using in ["fsl", "ants", "auto"] and self.reference == "T1w": if (
self.using in ["fsl", "ants", "auto"] and self.reference == "T1w"
): # pragma: no cover
# Check for extra inputs # Check for extra inputs
if extra_input is None: if extra_input is None:
raise_error( raise_error(

View file

@ -187,7 +187,9 @@ class PandasBaseFeatureStorage(BaseFeatureStorage):
) )
# Prepare new dataframe # Prepare new dataframe
df = pd.DataFrame( df = pd.DataFrame(
data=data, columns=col_names, index=idx # type: ignore data=data,
columns=col_names,
index=idx, # type: ignore
) )
# Store dataframe # Store dataframe
self.store_df(meta_md5=meta_md5, element=element, df=df) self.store_df(meta_md5=meta_md5, element=element, df=df)

View file

@ -229,9 +229,7 @@ class SQLiteFeatureStorage(PandasBaseFeatureStorage):
# Format index names for retrieved data # Format index names for retrieved data
meta_df.index = meta_df.index.str.replace(r"meta_", "") meta_df.index = meta_df.index.str.replace(r"meta_", "")
# Convert dataframe to dictionary # Convert dataframe to dictionary
out: dict[str, dict[str, str]] = meta_df.to_dict( out: dict[str, dict[str, str]] = meta_df.to_dict(orient="index") # type: ignore
orient="index"
) # type: ignore
# Format output # Format output
for md5, t_meta in out.items(): for md5, t_meta in out.items():
for k, v in t_meta.items(): for k, v in t_meta.items():
@ -536,8 +534,7 @@ class SQLiteFeatureStorage(PandasBaseFeatureStorage):
klass=IOError, klass=IOError,
) )
logger.info( logger.info(
"Collecting data from " f"Collecting data from {self.uri.parent}/*{self.uri.name}" # type: ignore
f"{self.uri.parent}/*{self.uri.name}" # type: ignore
) )
# Create new instance # Create new instance
out_storage = SQLiteFeatureStorage(uri=self.uri, upsert="ignore") out_storage = SQLiteFeatureStorage(uri=self.uri, upsert="ignore")
@ -596,9 +593,7 @@ def _generate_update_statements(table, index_col, rows_to_update):
for i, (_, keys) in enumerate(pk_indb.iterrows()): for i, (_, keys) in enumerate(pk_indb.iterrows()):
stmt = ( stmt = (
table.update() table.update()
.where( .where(and_(col == keys[j] for j, col in enumerate(pk_cols))) # type: ignore
and_(col == keys[j] for j, col in enumerate(pk_cols))
) # type: ignore
.values(new_records[i]) .values(new_records[i])
) )
stmts.append(stmt) stmts.append(stmt)

View file

@ -37,7 +37,8 @@ def test_element_to_index() -> None:
assert index.levels[1].name == "idx" # type: ignore assert index.levels[1].name == "idx" # type: ignore
# Check second index level values # Check second index level values
assert all( assert all(
x == i for i, x in enumerate(index.levels[1].values) # type: ignore x == i
for i, x in enumerate(index.levels[1].values) # type: ignore
) )
# Check second index level values shape # Check second index level values shape
assert index.levels[1].values.shape == (10,) # type: ignore assert index.levels[1].values.shape == (10,) # type: ignore
@ -69,7 +70,8 @@ def test_element_to_index() -> None:
assert index.levels[1].name == "scan" # type: ignore assert index.levels[1].name == "scan" # type: ignore
# Check second index level values # Check second index level values
assert all( assert all(
x == i for i, x in enumerate(index.levels[1].values) # type: ignore x == i
for i, x in enumerate(index.levels[1].values) # type: ignore
) )
# Check second index level values shape # Check second index level values shape
assert index.levels[1].values.shape == (7,) # type: ignore assert index.levels[1].values.shape == (7,) # type: ignore
@ -97,7 +99,8 @@ def test_element_to_index() -> None:
assert index.levels[2].name == "idx" # type: ignore assert index.levels[2].name == "idx" # type: ignore
# Check third index level values # Check third index level values
assert all( assert all(
x == i for i, x in enumerate(index.levels[2].values) # type: ignore x == i
for i, x in enumerate(index.levels[2].values) # type: ignore
) )
# Check third index level values shape # Check third index level values shape
assert index.levels[2].values.shape == (10,) # type: ignore assert index.levels[2].values.shape == (10,) # type: ignore

View file

@ -13,7 +13,8 @@ def test_BaseFeatureStorage_abstractness() -> None:
"""Test BaseFeatureStorage is abstract base class.""" """Test BaseFeatureStorage is abstract base class."""
with pytest.raises(TypeError, match=r"abstract"): with pytest.raises(TypeError, match=r"abstract"):
BaseFeatureStorage( BaseFeatureStorage(
uri="/tmp", storage_types=["matrix"] # type: ignore uri="/tmp",
storage_types=["matrix"], # type: ignore
) )

View file

@ -8,15 +8,14 @@ import os
import sys import sys
if sys.version_info < (3, 12): if sys.version_info < (3, 12): # pragma: no cover
from distutils.version import LooseVersion from distutils.version import LooseVersion
else: # pragma: no cover else:
from looseversion import LooseVersion from looseversion import LooseVersion
import logging import logging
import warnings import warnings
from pathlib import Path from pathlib import Path
from subprocess import PIPE, Popen, TimeoutExpired
from typing import ClassVar, NoReturn, Optional, Union from typing import ClassVar, NoReturn, Optional, Union
from warnings import warn from warnings import warn
@ -77,7 +76,7 @@ class WrapStdOut(logging.StreamHandler):
# just stdout) in order for this to work (tested on OSX and Linux) # just stdout) in order for this to work (tested on OSX and Linux)
if hasattr(sys.stdout, name): if hasattr(sys.stdout, name):
return getattr(sys.stdout, name) return getattr(sys.stdout, name)
else: else: # pragma: no cover
raise AttributeError(f"'file' object has not attribute '{name}'") raise AttributeError(f"'file' object has not attribute '{name}'")
@ -107,11 +106,13 @@ class ColorFormatter(logging.Formatter):
COLOR_SEQ: str = "\033[1;%dm" COLOR_SEQ: str = "\033[1;%dm"
BOLD_SEQ: str = "\033[1m" BOLD_SEQ: str = "\033[1m"
def __init__(self, fmt: str, datefmt: Optional[str] = None) -> None: def __init__(
self, fmt: str, datefmt: Optional[str] = None
) -> None: # pragma: no cover
"""Initialize the ColorFormatter.""" """Initialize the ColorFormatter."""
logging.Formatter.__init__(self, fmt, datefmt) logging.Formatter.__init__(self, fmt, datefmt)
def format(self, record: logging.LogRecord) -> str: def format(self, record: logging.LogRecord) -> str: # pragma: no cover
"""Format the log record. """Format the log record.
Parameters Parameters
@ -134,45 +135,6 @@ class ColorFormatter(logging.Formatter):
return logging.Formatter.format(self, record) return logging.Formatter.format(self, record)
def _get_git_head(path: Path) -> str:
"""Aux function to read HEAD from git.
Parameters
----------
path : pathlib.Path
The path to read git HEAD from.
Returns
-------
str
Empty string if timeout expired for subprocess command execution else
git HEAD information.
Raises
------
FileNotFoundError
If ``path`` is invalid.
"""
if not path.exists():
raise_error(
msg=f"This path does not exist: {path}", klass=FileNotFoundError
)
command = f"cd {path}; git rev-parse --verify HEAD"
process = Popen(
args=command,
stdout=PIPE,
shell=True,
)
try:
stdout, _ = process.communicate(timeout=10)
proc_stdout = stdout.strip().decode()
except TimeoutExpired:
process.kill()
proc_stdout = ""
return proc_stdout
def get_versions() -> dict: def get_versions() -> dict:
"""Import stuff and get versions if module. """Import stuff and get versions if module.
@ -182,52 +144,22 @@ def get_versions() -> dict:
The module names and corresponding versions. The module names and corresponding versions.
""" """
# Setup dictionary to track versions of modules
module_versions = {} module_versions = {}
for name, module in sys.modules.copy().items(): for name, module in sys.modules.copy().items():
# Bypassing sub-modules of packages and # Bypassing sub-modules of packages and
# allowing ruamel.yaml # allowing ruamel.yaml
if "." in name and name != "ruamel.yaml": if "." in name and name != "ruamel.yaml":
continue continue
if name in ["_curses"]: # Get version or None as string
continue
vstring = str(getattr(module, "__version__", None)) vstring = str(getattr(module, "__version__", None))
module_version = LooseVersion(vstring) # Get module version
module_version = getattr(module_version, "vstring", None) module_version = getattr(LooseVersion(vstring), "vstring", None)
if module_version is None:
module_version = None
elif "git" in module_version:
git_path = Path(module.__file__).resolve().parent # type: ignore
head = _get_git_head(git_path)
module_version += f"-HEAD:{head}"
module_versions[name] = module_version module_versions[name] = module_version
return module_versions return module_versions
# def get_ext_versions(tbox_path: Path) -> Dict: def _close_handlers(logger: logging.Logger) -> None: # pragma: no cover
# """Get versions of external tools used by junifer.
# Parameters
# ----------
# tbox_path : pathlib.Path
# The path to external toolboxes.
# Returns
# -------
# dict
# The dependency information.
# """
# versions = {}
# # spm_path = tbox_path / 'spm12'
# # if spm_path.exists():
# # head = _get_git_head(spm_path)
# # module_version = 'SPM12-HEAD:{}'.format(head)
# # versions['spm'] = module_version
# return versions
def _close_handlers(logger: logging.Logger) -> None:
"""Safely close relevant handlers for logger. """Safely close relevant handlers for logger.
Parameters Parameters
@ -243,55 +175,37 @@ def _close_handlers(logger: logging.Logger) -> None:
logger.removeHandler(handler) logger.removeHandler(handler)
def _safe_log(versions: dict, name: str) -> None: def log_versions() -> None:
"""Log with safety. """Log versions of dependencies and junifer."""
Parameters
----------
versions : dict
The dictionary with keys as dependency names and values as the
versions.
name : str
The dependency to look up in `versions`.
"""
if name in versions:
logger.info(f"{name}: {versions[name]}")
def log_versions(tbox_path: Optional[Path] = None) -> None:
"""Log versions of dependencies and junifer.
If `tbox_path` is specified, can also log versions of external toolboxes.
Parameters
----------
tbox_path : pathlib.Path, optional
The path to external toolboxes (default None).
"""
# Get versions of all found packages # Get versions of all found packages
versions = get_versions() versions = get_versions()
# Set packages to log
pkgs_to_log = [
"click",
"numpy",
"scipy",
"datalad",
"pandas",
"nibabel",
"nilearn",
"sqlalchemy",
"ruamel.yaml",
"h5py",
"tqdm",
"templateflow",
"lapy",
"junifer_data",
"junifer",
]
# Log
logger.info("===== Lib Versions =====") logger.info("===== Lib Versions =====")
_safe_log(versions, "numpy") for pkg in pkgs_to_log:
_safe_log(versions, "scipy") if pkg in versions:
_safe_log(versions, "pandas") logger.info(f"{pkg}: {versions[pkg]}")
_safe_log(versions, "nipype")
_safe_log(versions, "nitime")
_safe_log(versions, "nilearn")
_safe_log(versions, "nibabel")
_safe_log(versions, "junifer")
logger.info("========================") logger.info("========================")
if tbox_path is not None:
# ext_versions = get_ext_versions(tbox_path)
# logger.info('spm: {}'.format(ext_versions['spm']))
# logger.info('========================')
pass
def _can_use_color(handler: logging.Handler) -> bool: # pragma: no cover
def _can_use_color(handler: logging.Handler) -> bool:
"""Check if color can be used in the logging output. """Check if color can be used in the logging output.
Parameters Parameters
@ -391,11 +305,7 @@ def configure_logging(
# Set logging format # Set logging format
if output_format is None: if output_format is None:
output_format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s" output_format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
# ( if _can_use_color(lh): # pragma: no cover
# "%(asctime)s [%(levelname)s] %(message)s "
# "(%(filename)s:%(lineno)s)"
# )
if _can_use_color(lh):
formatter = ColorFormatter(fmt=output_format) formatter = ColorFormatter(fmt=output_format)
else: else:
formatter = logging.Formatter(fmt=output_format) formatter = logging.Formatter(fmt=output_format)

View file

@ -68,7 +68,9 @@ def test_log_file(tmp_path: Path) -> None:
assert any("Warn message" in line for line in lines) assert any("Warn message" in line for line in lines)
assert any("Error message" in line for line in lines) assert any("Error message" in line for line in lines)
configure_logging(fname=tmp_path / "test2.log", level="INFO") configure_logging(
fname=str((tmp_path / "test2.log").resolve()), level="INFO"
)
logger.debug("Debug message") logger.debug("Debug message")
logger.info("Info message") logger.info("Info message")
logger.warning("Warn message") logger.warning("Warn message")
@ -81,7 +83,9 @@ def test_log_file(tmp_path: Path) -> None:
assert any("Warn message" in line for line in lines) assert any("Warn message" in line for line in lines)
assert any("Error message" in line for line in lines) assert any("Error message" in line for line in lines)
configure_logging(fname=tmp_path / "test3.log", level="WARNING") configure_logging(
fname=tmp_path / "test3.log", level="WARNING", level_datalad="WARNING"
)
logger.debug("Debug message") logger.debug("Debug message")
logger.info("Info message") logger.info("Info message")
logger.warning("Warn message") logger.warning("Warn message")
@ -94,7 +98,7 @@ def test_log_file(tmp_path: Path) -> None:
assert any("Warn message" in line for line in lines) assert any("Warn message" in line for line in lines)
assert any("Error message" in line for line in lines) assert any("Error message" in line for line in lines)
configure_logging(fname=tmp_path / "test4.log", level="ERROR") configure_logging(fname=tmp_path / "test4.log", level=logging.ERROR)
logger.debug("Debug message") logger.debug("Debug message")
logger.info("Info message") logger.info("Info message")
logger.warning("Warn message") logger.warning("Warn message")
@ -107,7 +111,11 @@ def test_log_file(tmp_path: Path) -> None:
assert any("Error message" in line for line in lines) assert any("Error message" in line for line in lines)
with pytest.warns(UserWarning, match="to avoid this message"): with pytest.warns(UserWarning, match="to avoid this message"):
configure_logging(fname=tmp_path / "test4.log", level="WARNING") configure_logging(
fname=tmp_path / "test4.log",
level="WARNING",
level_datalad=logging.WARNING,
)
logger.debug("Debug2 message") logger.debug("Debug2 message")
logger.info("Info2 message") logger.info("Info2 message")
logger.warning("Warn2 message") logger.warning("Warn2 message")

View file

@ -75,7 +75,12 @@ onthefly = [
"bctpy==0.6.0" "bctpy==0.6.0"
] ]
neurokit2 = ["neurokit2>=0.1.7"] neurokit2 = ["neurokit2>=0.1.7"]
dev = ["tox", "pre-commit"] dev = [
"tox",
"pre-commit",
"ruff",
"towncrier",
]
docs = [ docs = [
"seaborn>=0.13.0,<0.14.0", "seaborn>=0.13.0,<0.14.0",
"sphinx>=7.3.0,<8.1.0", "sphinx>=7.3.0,<8.1.0",
@ -107,16 +112,6 @@ version_scheme = "guess-next-dev"
local_scheme = "no-local-version" local_scheme = "no-local-version"
write_to = "junifer/_version.py" write_to = "junifer/_version.py"
[tool.black]
line-length = 79
target-version = ["py39", "py310", "py311", "py312", "py313"]
extend-exclude = """
(
junifer/external/h5io
| junifer/external/BrainPrint
)
"""
[tool.codespell] [tool.codespell]
skip = "*/auto_examples/*,*.html,.git/,*.pyc,*/_build/*,*/h5io/*,*/BrainPrint/*" skip = "*/auto_examples/*,*.html,.git/,*.pyc,*/_build/*,*/h5io/*,*/BrainPrint/*"
count = "" count = ""
@ -136,6 +131,7 @@ extend-exclude = [
"examples", "examples",
"tools", "tools",
] ]
target-version = "py39"
[tool.ruff.lint] [tool.ruff.lint]
select = [ select = [
@ -275,3 +271,31 @@ showcontent = true
[tool.towncrier.fragment.change] [tool.towncrier.fragment.change]
name = "API Changes" name = "API Changes"
showcontent = true showcontent = true
[tool.coverage.paths]
source = [
"junifer",
"*/site-packages/junifer",
]
[tool.coverage.run]
branch = true
omit = [
"*/setup.py",
"*/_version.py",
"*/tests/*",
"*/junifer/configs/*",
"*/junifer/external/h5io/*",
"*/junifer/external/BrainPrint/*",
]
[tool.coverage.report]
exclude_lines = [
# Have to re-enable the standard pragma
"pragma: no cover",
# Type checking if statements should not be considered
"if TYPE_CHECKING:",
# Don't complain if non-runnable code isn't run:
"if __name__ == .__main__.:",
]
precision = 2

57
tox.ini
View file

@ -1,5 +1,13 @@
[tox] [tox]
envlist = ruff, black, test, coverage, codespell, py3{9,10,11,12,13} requires =
tox>=4
env_list =
ruff,
changelog,
test,
coverage,
codespell,
py3{9,10,11,12,13}
isolated_build = true isolated_build = true
[gh-actions] [gh-actions]
@ -22,20 +30,27 @@ commands =
pytest pytest
[testenv:ruff] [testenv:ruff]
description = run ruff
skip_install = true skip_install = true
deps = deps =
ruff>=0.1.0 ruff>=0.1.0
commands = commands =
ruff format {toxinidir}
ruff check {toxinidir} ruff check {toxinidir}
[testenv:black] [testenv:changelog]
description = show changelog
skip_install = true skip_install = true
# See https://github.com/sphinx-contrib/sphinxcontrib-towncrier/issues/92
# Pin also present in pyproject.toml
deps = deps =
black towncrier<24.7
lazy_loader==0.4
commands = commands =
black --check --diff {toxinidir}/junifer {toxinidir}/setup.py towncrier build --draft
[testenv:test] [testenv:test]
description = run tests
skip_install = false skip_install = false
passenv = passenv =
HOME HOME
@ -45,6 +60,7 @@ commands =
pytest pytest
[testenv:coverage] [testenv:coverage]
description = run tests with coverage
skip_install = false skip_install = false
deps = deps =
bctpy==0.6.0 bctpy==0.6.0
@ -52,42 +68,13 @@ deps =
pytest pytest
pytest-cov pytest-cov
commands = commands =
pytest --cov={envsitepackagesdir}/junifer --cov-report=xml --cov-report=term {envsitepackagesdir}/junifer pytest --cov={envsitepackagesdir}/junifer --cov-report=xml --cov-report=term --cov-config=pyproject.toml {envsitepackagesdir}/junifer
[testenv:codespell] [testenv:codespell]
description = run codespell
skip_install = true skip_install = true
deps = deps =
codespell codespell
tomli tomli
commands = commands =
codespell --toml {toxinidir}/pyproject.toml {toxinidir}/docs/ {toxinidir}/examples/ {toxinidir}/junifer/ {toxinidir}/tools/ {toxinidir}/README.md codespell --toml {toxinidir}/pyproject.toml {toxinidir}/docs/ {toxinidir}/examples/ {toxinidir}/junifer/ {toxinidir}/tools/ {toxinidir}/README.md
################
# Tool configs #
################
[coverage:paths]
source =
junifer
*/site-packages/junifer
[coverage:run]
branch = true
omit =
*/setup.py
*/_version.py
*/tests/*
*/junifer/configs/*
*/junifer/external/h5io/*
*/junifer/external/BrainPrint/*
parallel = false
[coverage:report]
exclude_lines =
# Have to re-enable the standard pragma
pragma: no cover
# Type checking if statements should not be considered
if TYPE_CHECKING:
# Don't complain if non-runnable code isn't run:
if __name__ == .__main__.:
precision = 2