From c86926bbd937351e875cfa26cc2efcbd1526daa9 Mon Sep 17 00:00:00 2001 From: Fede Raimondo Date: Thu, 5 Dec 2024 14:39:13 +0100 Subject: [PATCH 1/7] Use template space with right resolution and resample later --- junifer/data/masks/_masks.py | 18 +++++++------- junifer/data/parcellations/_parcellations.py | 26 ++++++++------------ 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/junifer/data/masks/_masks.py b/junifer/data/masks/_masks.py index b37df104b..05496720d 100644 --- a/junifer/data/masks/_masks.py +++ b/junifer/data/masks/_masks.py @@ -583,17 +583,17 @@ class MaskRegistry(BasePipelineDataRegistry, metaclass=Singleton): warp_data=warper_spec, ) - else: + if target_space != "native": # Resample mask to target image; no further warping logger.debug(f"Resampling {t_mask} to target image.") - if target_space != "native": - mask_img = resample_to_img( - source_img=mask_object, - target_img=target_data["data"], - ) - # Set mask_img in case no warping happens before this - else: - mask_img = mask_object + mask_img = resample_to_img( + source_img=mask_object, + target_img=target_data["data"], + ) + # Set mask_img in case no warping happens before this + else: + mask_img = mask_object + # Resample and warp mask if target data is native if target_space == "native": logger.debug( diff --git a/junifer/data/parcellations/_parcellations.py b/junifer/data/parcellations/_parcellations.py index 64b95cf1e..b6598ef26 100644 --- a/junifer/data/parcellations/_parcellations.py +++ b/junifer/data/parcellations/_parcellations.py @@ -471,24 +471,18 @@ class ParcellationRegistry(BasePipelineDataRegistry, metaclass=Singleton): ) # Remove extra dimension added by ANTs img = image.math_img("np.squeeze(img)", img=raw_img) - # Set correct affine as resolution won't be correct - img = image.resample_img( - img=img, - target_affine=target_img.affine, + + if target_space != "native": + # No warping is going to happen, just resampling, because + # we are in the correct space + logger.debug(f"Resampling {name} to target image.") + # Resample parcellation to target image + img = image.resample_to_img( + source_img=img, + target_img=target_img, interpolation="nearest", + copy=True, ) - else: - if target_space != "native": - # No warping is going to happen, just resampling, because - # we are in the correct space - logger.debug(f"Resampling {name} to target image.") - # Resample parcellation to target image - img = image.resample_to_img( - source_img=img, - target_img=target_img, - interpolation="nearest", - copy=True, - ) # Warp parcellation if target space is native if target_space == "native": -- 2.52.0 From c0ef22cad9d070a787b9d32710c4d53b43124531 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Fri, 6 Dec 2024 13:46:22 +0100 Subject: [PATCH 2/7] chore: improve nilearn.image imports in _masks.py and _parcellations.py --- junifer/data/masks/_masks.py | 12 ++++++------ junifer/data/parcellations/_parcellations.py | 11 ++++++----- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/junifer/data/masks/_masks.py b/junifer/data/masks/_masks.py index 05496720d..11ff179e9 100644 --- a/junifer/data/masks/_masks.py +++ b/junifer/data/masks/_masks.py @@ -14,8 +14,8 @@ from typing import ( ) import nibabel as nib +import nilearn.image as nimg import numpy as np -from nilearn.image import get_data, new_img_like, resample_to_img from nilearn.masking import ( compute_background_mask, compute_epi_mask, @@ -168,14 +168,14 @@ def compute_brain_mask( ) # Resample template to target image else: - resampled_template = resample_to_img( + resampled_template = nimg.resample_to_img( source_img=template, target_img=target_data["data"] ) # Threshold resampled template and get mask - mask = (get_data(resampled_template) >= threshold).astype("int8") + mask = (nimg.get_data(resampled_template) >= threshold).astype("int8") - return new_img_like(target_data["data"], mask) # type: ignore + return nimg.new_img_like(target_data["data"], mask) # type: ignore class MaskRegistry(BasePipelineDataRegistry, metaclass=Singleton): @@ -523,7 +523,7 @@ class MaskRegistry(BasePipelineDataRegistry, metaclass=Singleton): ) logger.debug("Resampling inherited mask to target image.") # Resample inherited mask to target image - mask_img = resample_to_img( + mask_img = nimg.resample_to_img( source_img=mask_img, target_img=target_data["data"], ) @@ -586,9 +586,9 @@ class MaskRegistry(BasePipelineDataRegistry, metaclass=Singleton): if target_space != "native": # Resample mask to target image; no further warping logger.debug(f"Resampling {t_mask} to target image.") - mask_img = resample_to_img( source_img=mask_object, target_img=target_data["data"], + mask_img = nimg.resample_to_img( ) # Set mask_img in case no warping happens before this else: diff --git a/junifer/data/parcellations/_parcellations.py b/junifer/data/parcellations/_parcellations.py index b6598ef26..6c0b6fbce 100644 --- a/junifer/data/parcellations/_parcellations.py +++ b/junifer/data/parcellations/_parcellations.py @@ -16,9 +16,10 @@ from typing import TYPE_CHECKING, Any, Optional, Union import httpx import nibabel as nib +import nilearn.image as nimg import numpy as np import pandas as pd -from nilearn import datasets, image +from nilearn import datasets from ...utils import logger, raise_error, warn_with_log from ...utils.singleton import Singleton @@ -470,14 +471,14 @@ class ParcellationRegistry(BasePipelineDataRegistry, metaclass=Singleton): warp_data=None, ) # Remove extra dimension added by ANTs - img = image.math_img("np.squeeze(img)", img=raw_img) + img = nimg.math_img("np.squeeze(img)", img=raw_img) if target_space != "native": # No warping is going to happen, just resampling, because # we are in the correct space logger.debug(f"Resampling {name} to target image.") # Resample parcellation to target image - img = image.resample_to_img( + img = nimg.resample_to_img( source_img=img, target_img=target_img, interpolation="nearest", @@ -1801,7 +1802,7 @@ def merge_parcellations( "The parcellations have different resolutions!" "Resampling all parcellations to the first one in the list." ) - t_parc = image.resample_to_img( + t_parc = nimg.resample_to_img( t_parc, ref_parc, interpolation="nearest", copy=True ) @@ -1827,6 +1828,6 @@ def merge_parcellations( "parcellation that was first in the list." ) - parcellation_img_res = image.new_img_like(parcellations_list[0], parc_data) + parcellation_img_res = nimg.new_img_like(parcellations_list[0], parc_data) return parcellation_img_res, labels -- 2.52.0 From fb58f05d30d6c6c0bd94d4480324a1d5af497481 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Fri, 6 Dec 2024 13:46:56 +0100 Subject: [PATCH 3/7] chore: improve log message in _masks.py --- junifer/data/masks/_masks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junifer/data/masks/_masks.py b/junifer/data/masks/_masks.py index 11ff179e9..dd5a6660f 100644 --- a/junifer/data/masks/_masks.py +++ b/junifer/data/masks/_masks.py @@ -572,7 +572,7 @@ class MaskRegistry(BasePipelineDataRegistry, metaclass=Singleton): if mask_space != target_std_space: logger.debug( f"Warping {t_mask} to {target_std_space} space " - "using ants." + "using ANTs." ) mask_img = ANTsMaskWarper().warp( mask_name=mask_name, -- 2.52.0 From 00ac72e22dbd10fc0281a0c4db994cea70d6cd1f Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Fri, 6 Dec 2024 13:47:28 +0100 Subject: [PATCH 4/7] chore: simplify warping conditional in _parcellations.py --- junifer/data/parcellations/_parcellations.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/junifer/data/parcellations/_parcellations.py b/junifer/data/parcellations/_parcellations.py index 6c0b6fbce..354c1ca8c 100644 --- a/junifer/data/parcellations/_parcellations.py +++ b/junifer/data/parcellations/_parcellations.py @@ -484,9 +484,10 @@ class ParcellationRegistry(BasePipelineDataRegistry, metaclass=Singleton): interpolation="nearest", copy=True, ) - - # Warp parcellation if target space is native - if target_space == "native": + else: + # Warp parcellation if target space is native as either + # the image is in the right non-native space or it's + # warped from one non-native space to another non-native space logger.debug( "Warping parcellation to native space using " f"{warper_spec['warper']}." -- 2.52.0 From 95427f16cabc246aa6bf8fadbc6f48a4fcdeec9e Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Fri, 6 Dec 2024 13:48:11 +0100 Subject: [PATCH 5/7] chore: improve warping conditional in _masks.py --- junifer/data/masks/_masks.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/junifer/data/masks/_masks.py b/junifer/data/masks/_masks.py index dd5a6660f..0206f1f6d 100644 --- a/junifer/data/masks/_masks.py +++ b/junifer/data/masks/_masks.py @@ -568,6 +568,9 @@ class MaskRegistry(BasePipelineDataRegistry, metaclass=Singleton): "mask." ) + # Set here to simplify things later + mask_img: nib.nifti1.Nifti1Image = mask_object + # Resample and warp mask to standard space if mask_space != target_std_space: logger.debug( @@ -576,26 +579,30 @@ class MaskRegistry(BasePipelineDataRegistry, metaclass=Singleton): ) mask_img = ANTsMaskWarper().warp( mask_name=mask_name, - mask_img=mask_object, + mask_img=mask_img, src=mask_space, dst=target_std_space, target_data=target_data, warp_data=warper_spec, ) + # Remove extra dimension added by ANTs + mask_img = nimg.math_img( + "np.squeeze(img)", img=mask_img + ) if target_space != "native": - # Resample mask to target image; no further warping + # No warping is going to happen, just resampling, + # because we are in the correct space logger.debug(f"Resampling {t_mask} to target image.") - source_img=mask_object, - target_img=target_data["data"], mask_img = nimg.resample_to_img( + source_img=mask_img, + target_img=target_img, ) - # Set mask_img in case no warping happens before this else: - mask_img = mask_object - - # Resample and warp mask if target data is native - if target_space == "native": + # Warp mask if target space is native as + # either the image is in the right non-native space or + # it's warped from one non-native space to another + # non-native space logger.debug( "Warping mask to native space using " f"{warper_spec['warper']}." -- 2.52.0 From 0015d66ec40b26bed2b09146af12d34b62df1f7e Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Mon, 9 Dec 2024 10:36:33 +0100 Subject: [PATCH 6/7] chore: remove xfail from reho comparison test --- junifer/markers/reho/tests/test_reho_parcels.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/junifer/markers/reho/tests/test_reho_parcels.py b/junifer/markers/reho/tests/test_reho_parcels.py index d5746e3a8..d7737e335 100644 --- a/junifer/markers/reho/tests/test_reho_parcels.py +++ b/junifer/markers/reho/tests/test_reho_parcels.py @@ -86,10 +86,6 @@ def test_ReHoParcels(caplog: pytest.LogCaptureFixture, tmp_path: Path) -> None: @pytest.mark.skipif( _check_afni() is False, reason="requires AFNI to be in PATH" ) -@pytest.mark.xfail( - reason="junifer ReHo needs to use the correct mask", - raises=AssertionError, -) def test_ReHoParcels_comparison(tmp_path: Path) -> None: """Test ReHoParcels implementation comparison. -- 2.52.0 From c93d589db094d33cb855141224f60b9100bed604 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Mon, 9 Dec 2024 10:42:33 +0100 Subject: [PATCH 7/7] chore: add changelog 414.misc --- docs/changes/newsfragments/414.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/changes/newsfragments/414.misc diff --git a/docs/changes/newsfragments/414.misc b/docs/changes/newsfragments/414.misc new file mode 100644 index 000000000..f13aef72d --- /dev/null +++ b/docs/changes/newsfragments/414.misc @@ -0,0 +1 @@ +Simplify logic for parcellation and mask space warping by `Synchon Mandal`_ -- 2.52.0