[ENH]: Add test for JuniferNiftiSpheresMasker against nilearn's version #136
4 changed files with 96 additions and 3 deletions
1
docs/changes/newsfragments/136.enh
Normal file
1
docs/changes/newsfragments/136.enh
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Add test to be sure that :class:`.JuniferNiftiSpheresMasker` with mean aggregation function behaves exactly as :class:`nilearn.maskers.NiftiSpheresMasker` by `Synchon Mandal`_
|
||||||
3
junifer/external/nilearn/__init__.py
vendored
3
junifer/external/nilearn/__init__.py
vendored
|
|
@ -4,3 +4,6 @@
|
||||||
# License: AGPL
|
# License: AGPL
|
||||||
|
|
||||||
from .junifer_nifti_spheres_masker import JuniferNiftiSpheresMasker
|
from .junifer_nifti_spheres_masker import JuniferNiftiSpheresMasker
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = ["JuniferNiftiSpheresMasker"]
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,12 @@ if TYPE_CHECKING:
|
||||||
from pandas import DataFrame
|
from pandas import DataFrame
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = ["JuniferNiftiSpheresMasker"]
|
||||||
|
|
||||||
|
|
||||||
# New BSD License
|
# New BSD License
|
||||||
|
|
||||||
# Copyright (c) 2007 - 2022 The nilearn developers.
|
# Copyright (c) The nilearn developers.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -99,6 +102,17 @@ def _apply_mask_and_get_affinity(
|
||||||
Contains the boolean indices for each sphere.
|
Contains the boolean indices for each sphere.
|
||||||
shape: (number of seeds, number of voxels)
|
shape: (number of seeds, number of voxels)
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
ValueError
|
||||||
|
If ``niimg`` and ``mask_img`` are both provided or
|
||||||
|
if overlap is detected between spheres.
|
||||||
|
|
||||||
|
Warns
|
||||||
|
-----
|
||||||
|
RuntimeWarning
|
||||||
|
If the provided images contain NaN, they will be converted to zeroes.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
seeds = list(seeds)
|
seeds = list(seeds)
|
||||||
|
|
||||||
|
|
@ -210,7 +224,7 @@ def _iter_signals_from_spheres(
|
||||||
X, A = _apply_mask_and_get_affinity(
|
X, A = _apply_mask_and_get_affinity(
|
||||||
seeds, niimg, radius, allow_overlap, mask_img=mask_img
|
seeds, niimg, radius, allow_overlap, mask_img=mask_img
|
||||||
)
|
)
|
||||||
for _, row in enumerate(A.rows):
|
for row in A.rows:
|
||||||
yield X[:, row]
|
yield X[:, row]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,14 @@
|
||||||
# License: AGPL
|
# License: AGPL
|
||||||
|
|
||||||
import warnings
|
import warnings
|
||||||
|
from typing import List, Tuple
|
||||||
|
|
||||||
import nibabel
|
import nibabel
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pytest
|
import pytest
|
||||||
from nilearn._utils import data_gen
|
from nilearn._utils import data_gen
|
||||||
from nilearn.image import get_data
|
from nilearn.image import get_data
|
||||||
|
from nilearn.maskers import NiftiSpheresMasker
|
||||||
from numpy.testing import assert_array_equal
|
from numpy.testing import assert_array_equal
|
||||||
|
|
||||||
from junifer.external.nilearn import JuniferNiftiSpheresMasker
|
from junifer.external.nilearn import JuniferNiftiSpheresMasker
|
||||||
|
|
@ -17,7 +19,7 @@ from junifer.external.nilearn import JuniferNiftiSpheresMasker
|
||||||
|
|
||||||
# New BSD License
|
# New BSD License
|
||||||
|
|
||||||
# Copyright (c) 2007 - 2022 The nilearn developers.
|
# Copyright (c) The nilearn developers.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -331,3 +333,76 @@ def test_nifti_spheres_masker_io_shapes() -> None:
|
||||||
)
|
)
|
||||||
test_data = masker.transform(img_4d)
|
test_data = masker.transform(img_4d)
|
||||||
assert test_data.shape == (n_volumes, n_regions)
|
assert test_data.shape == (n_volumes, n_regions)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"shape",
|
||||||
|
[
|
||||||
|
(10, 11, 12),
|
||||||
|
(10, 11, 12, 5),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"radius, allow_overlap",
|
||||||
|
[
|
||||||
|
(2.0, True),
|
||||||
|
(2.0, False),
|
||||||
|
(3.0, True),
|
||||||
|
(4.0, True),
|
||||||
|
(5.0, True),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"coords",
|
||||||
|
[
|
||||||
|
[(1, 1, 1)],
|
||||||
|
[(1, 1, 1), (4, 4, 4)],
|
||||||
|
[(1, 1, 1), (4, 4, 4), (10, 10, 10)],
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_junifer_and_nilearn_mean_agg_are_equal(
|
||||||
|
shape: Tuple[int, ...],
|
||||||
|
radius: float,
|
||||||
|
allow_overlap: bool,
|
||||||
|
coords: List[Tuple[int, int, int]],
|
||||||
|
) -> None:
|
||||||
|
"""Test junifer's masker behaves same as nilearn's when agg is mean.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
shape : tuple of int
|
||||||
|
The parametrized shape of the input image.
|
||||||
|
radius : float
|
||||||
|
The parametrized radius of the spheres.
|
||||||
|
allow_overlap : bool
|
||||||
|
The parametrized option to overlap spheres or not.
|
||||||
|
coords : list of tuple of int, int and int
|
||||||
|
The parametrized seeds.
|
||||||
|
|
||||||
|
"""
|
||||||
|
# Set affine
|
||||||
|
affine = np.eye(4)
|
||||||
|
# Generate random image
|
||||||
|
input_img, mask_img = data_gen.generate_random_img(
|
||||||
|
shape=shape,
|
||||||
|
affine=affine,
|
||||||
|
)
|
||||||
|
# Compute junifer's version
|
||||||
|
junifer_masker = JuniferNiftiSpheresMasker(
|
||||||
|
seeds=coords,
|
||||||
|
radius=radius,
|
||||||
|
allow_overlap=allow_overlap,
|
||||||
|
mask_img=mask_img,
|
||||||
|
)
|
||||||
|
junifer_output = junifer_masker.fit_transform(input_img)
|
||||||
|
# Compute nilearn's version
|
||||||
|
nilearn_masker = NiftiSpheresMasker(
|
||||||
|
seeds=coords,
|
||||||
|
radius=radius,
|
||||||
|
allow_overlap=allow_overlap,
|
||||||
|
mask_img=mask_img,
|
||||||
|
)
|
||||||
|
nilearn_output = nilearn_masker.fit_transform(input_img)
|
||||||
|
# Checks
|
||||||
|
assert junifer_output.shape == nilearn_output.shape
|
||||||
|
np.testing.assert_almost_equal(junifer_output, nilearn_output)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue