diff --git a/docs/changes/newsfragments/136.enh b/docs/changes/newsfragments/136.enh new file mode 100644 index 0000000000..d0a4955636 --- /dev/null +++ b/docs/changes/newsfragments/136.enh @@ -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`_ diff --git a/junifer/external/nilearn/__init__.py b/junifer/external/nilearn/__init__.py index 7575c3212a..4fdb3c40c5 100644 --- a/junifer/external/nilearn/__init__.py +++ b/junifer/external/nilearn/__init__.py @@ -4,3 +4,6 @@ # License: AGPL from .junifer_nifti_spheres_masker import JuniferNiftiSpheresMasker + + +__all__ = ["JuniferNiftiSpheresMasker"] diff --git a/junifer/external/nilearn/junifer_nifti_spheres_masker.py b/junifer/external/nilearn/junifer_nifti_spheres_masker.py index 36fd7d9b8a..699f37e62e 100644 --- a/junifer/external/nilearn/junifer_nifti_spheres_masker.py +++ b/junifer/external/nilearn/junifer_nifti_spheres_masker.py @@ -29,9 +29,12 @@ from pandas import DataFrame +__all__ = ["JuniferNiftiSpheresMasker"] + + # New BSD License -# Copyright (c) 2007 - 2022 The nilearn developers. +# Copyright (c) The nilearn developers. # All rights reserved. @@ -99,6 +102,17 @@ def _apply_mask_and_get_affinity( Contains the boolean indices for each sphere. 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) @@ -210,7 +224,7 @@ def _iter_signals_from_spheres( X, A = _apply_mask_and_get_affinity( seeds, niimg, radius, allow_overlap, mask_img=mask_img ) - for _, row in enumerate(A.rows): + for row in A.rows: yield X[:, row] diff --git a/junifer/external/nilearn/tests/test_junifer_nifti_spheres_masker.py b/junifer/external/nilearn/tests/test_junifer_nifti_spheres_masker.py index a36c8f2ff3..fbd71cb461 100644 --- a/junifer/external/nilearn/tests/test_junifer_nifti_spheres_masker.py +++ b/junifer/external/nilearn/tests/test_junifer_nifti_spheres_masker.py @@ -4,12 +4,14 @@ # License: AGPL import warnings +from typing import List, Tuple import nibabel import numpy as np import pytest from nilearn._utils import data_gen from nilearn.image import get_data +from nilearn.maskers import NiftiSpheresMasker from numpy.testing import assert_array_equal from junifer.external.nilearn import JuniferNiftiSpheresMasker @@ -17,7 +19,7 @@ # New BSD License -# Copyright (c) 2007 - 2022 The nilearn developers. +# Copyright (c) The nilearn developers. # All rights reserved. @@ -331,3 +333,76 @@ def test_nifti_spheres_masker_io_shapes() -> None: ) test_data = masker.transform(img_4d) 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)