Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENH]: Add test for JuniferNiftiSpheresMasker against nilearn's version #136

Merged
merged 8 commits into from
Jun 18, 2024
1 change: 1 addition & 0 deletions docs/changes/newsfragments/136.enh
Original file line number Diff line number Diff line change
@@ -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 changes: 3 additions & 0 deletions junifer/external/nilearn/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
# License: AGPL

from .junifer_nifti_spheres_masker import JuniferNiftiSpheresMasker


__all__ = ["JuniferNiftiSpheresMasker"]
18 changes: 16 additions & 2 deletions junifer/external/nilearn/junifer_nifti_spheres_masker.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.


Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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]


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,22 @@
# 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


# New BSD License

# Copyright (c) 2007 - 2022 The nilearn developers.
# Copyright (c) The nilearn developers.
# All rights reserved.


Expand Down Expand Up @@ -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)
Loading