From 7084983ee23cd40c3b1e500851e4d202b14cbf7d Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 14 Dec 2023 12:49:18 +0100 Subject: [PATCH 1/6] update: add input BOLD template space to fMRIPrepConfoundRemover's output BOLD_mask --- junifer/preprocess/confounds/fmriprep_confound_remover.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/junifer/preprocess/confounds/fmriprep_confound_remover.py b/junifer/preprocess/confounds/fmriprep_confound_remover.py index 4b26035896..30fb51f41e 100644 --- a/junifer/preprocess/confounds/fmriprep_confound_remover.py +++ b/junifer/preprocess/confounds/fmriprep_confound_remover.py @@ -574,7 +574,10 @@ def _remove_confounds( # this allows to use "inherit" down the pipeline if extra_input is not None: logger.debug("Setting mask_item") - extra_input["BOLD_mask"] = {"data": mask_img} + extra_input["BOLD_mask"] = { + "data": mask_img, + "space": input["space"], + } input["mask_item"] = "BOLD_mask" logger.info("Cleaning image") From 4e707aef96351434f2d3abc4fd953ddd849545fe Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 14 Dec 2023 12:50:28 +0100 Subject: [PATCH 2/6] update: improve template space awareness for inherited mask and avoid double mask warping in get_mask() --- junifer/data/masks.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/junifer/data/masks.py b/junifer/data/masks.py index 62096bd57e..bf6f901b2e 100644 --- a/junifer/data/masks.py +++ b/junifer/data/masks.py @@ -280,6 +280,7 @@ def get_mask( # noqa: C901 f"because the item ({inherited_mask_item}) does not exist." ) mask_img = extra_input[inherited_mask_item]["data"] + mask_space = extra_input[inherited_mask_item]["space"] # Starting with new mask else: # Load mask @@ -306,7 +307,7 @@ def get_mask( # noqa: C901 interpolation="nearest", copy=True, ) - all_spaces.append(mask_space) + all_spaces.append(mask_space) all_masks.append(mask_img) # Multiple masks, need intersection / union @@ -316,6 +317,8 @@ def get_mask( # noqa: C901 # Intersect / union of masks only if all masks are in the same space if len(filtered_spaces) == 1: mask_img = intersect_masks(all_masks, **intersect_params) + # Store the mask space for further checks + mask_space = next(iter(filtered_spaces)) else: raise_error( msg=( @@ -333,9 +336,10 @@ def get_mask( # noqa: C901 "when there is only one mask." ) mask_img = all_masks[0] + mask_space = all_spaces[0] - # Warp mask if target data is native - if target_data["space"] == "native": + # Warp mask if target data is native and mask space is not native + if target_data["space"] == "native" and target_data["space"] != mask_space: # Check for extra inputs if extra_input is None: raise_error( From cbcd1232d286a96e695df17b09ed4745931a5ce1 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 14 Dec 2023 12:58:13 +0100 Subject: [PATCH 3/6] chore: add changelog 284.bugfix --- docs/changes/newsfragments/284.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/changes/newsfragments/284.bugfix diff --git a/docs/changes/newsfragments/284.bugfix b/docs/changes/newsfragments/284.bugfix new file mode 100644 index 0000000000..dd780eb329 --- /dev/null +++ b/docs/changes/newsfragments/284.bugfix @@ -0,0 +1 @@ +Avoid warping mask preprocessed with :class:`.fMRIPrepConfoundRemover` and used by markers with ``mask="inherit"`` in subject-native template space by `Fede Raimondo`_ and `Synchon Mandal`_ From 97c5d15dc6a8dec82b0e30005a742105935a90cd Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Thu, 14 Dec 2023 15:13:39 +0100 Subject: [PATCH 4/6] update: add space info to test_get_mask_inherit() --- junifer/data/tests/test_masks.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/junifer/data/tests/test_masks.py b/junifer/data/tests/test_masks.py index 1a530f7ae5..ff1966c033 100644 --- a/junifer/data/tests/test_masks.py +++ b/junifer/data/tests/test_masks.py @@ -392,7 +392,9 @@ def test_get_mask_inherit() -> None: # Now get the mask using the inherit functionality, passing the # computed mask as extra data - extra_input = {"BOLD_MASK": {"data": gm_mask}} + extra_input = { + "BOLD_MASK": {"data": gm_mask, "space": input["BOLD"]["space"]} + } input["BOLD"]["mask_item"] = "BOLD_MASK" mask2 = get_mask( masks="inherit", target_data=input["BOLD"], extra_input=extra_input From 3ec905e479e7dc0272d5267d3b556a345cd8b10b Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Fri, 12 Jan 2024 11:15:49 +0100 Subject: [PATCH 5/6] fix: update inherited masks and masks with inherit space to target space before computation in get_mask() --- junifer/data/masks.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/junifer/data/masks.py b/junifer/data/masks.py index bf6f901b2e..e3cabc6e5e 100644 --- a/junifer/data/masks.py +++ b/junifer/data/masks.py @@ -280,13 +280,16 @@ def get_mask( # noqa: C901 f"because the item ({inherited_mask_item}) does not exist." ) mask_img = extra_input[inherited_mask_item]["data"] - mask_space = extra_input[inherited_mask_item]["space"] + mask_space = target_data["space"] # Starting with new mask else: # Load mask mask_object, _, mask_space = load_mask( mask_name, path_only=False, resolution=resolution ) + # Replace mask space with target space if mask's space is inherit + if mask_space == "inherit": + mask_space = target_data["space"] # If mask is callable like from nilearn if callable(mask_object): if mask_params is None: @@ -312,17 +315,17 @@ def get_mask( # noqa: C901 # Multiple masks, need intersection / union if len(all_masks) > 1: - # Filter out "inherit" and make a set for spaces - filtered_spaces = set(filter(lambda x: x != "inherit", all_spaces)) + # Make a set of unique spaces + unique_spaces = set(all_spaces) # Intersect / union of masks only if all masks are in the same space - if len(filtered_spaces) == 1: + if len(unique_spaces) == 1: mask_img = intersect_masks(all_masks, **intersect_params) # Store the mask space for further checks - mask_space = next(iter(filtered_spaces)) + mask_space = next(iter(unique_spaces)) else: raise_error( msg=( - f"Masks are in different spaces: {filtered_spaces}, " + f"Masks are in different spaces: {unique_spaces}, " "unable to merge." ), klass=RuntimeError, From 8e27ca2b37837a144b1d28067d3486a474e6f3b5 Mon Sep 17 00:00:00 2001 From: Synchon Mandal Date: Fri, 12 Jan 2024 11:16:32 +0100 Subject: [PATCH 6/6] update: improve tests for get_mask() with multiple masks --- junifer/data/tests/test_masks.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/junifer/data/tests/test_masks.py b/junifer/data/tests/test_masks.py index ff1966c033..c908eba661 100644 --- a/junifer/data/tests/test_masks.py +++ b/junifer/data/tests/test_masks.py @@ -407,11 +407,9 @@ def test_get_mask_inherit() -> None: @pytest.mark.parametrize( "masks,params", [ - (["GM_prob0.2", "compute_brain_mask"], {}), - ( - ["GM_prob0.2", "compute_brain_mask"], - {"threshold": 0.2}, - ), + (["GM_prob0.2", "GM_prob0.2_cortex"], {}), + (["compute_brain_mask", "compute_background_mask"], {}), + (["compute_brain_mask", "compute_epi_mask"], {}), ], ) def test_get_mask_multiple(