Skip to content

Commit

Permalink
removed remove background option
Browse files Browse the repository at this point in the history
  • Loading branch information
ravih18 committed Nov 22, 2024
1 parent 6f8c496 commit 0fec25e
Show file tree
Hide file tree
Showing 5 changed files with 15 additions and 227 deletions.
8 changes: 0 additions & 8 deletions clinica/pipelines/pet/linear/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,6 @@
is_flag=True,
help="Do not crop the image with template (cropped image are suggested for using with DL models)",
)
@cli_param.option.option(
"-rb",
"--remove_background",
is_flag=True,
help="Remove the background according to a dilated binary MNI mask",
)
@cli_param.option.option(
"--save_pet_in_t1w_space",
is_flag=True,
Expand All @@ -47,7 +41,6 @@ def cli(
suvr_reference_region: str,
reconstruction_method: Optional[str] = None,
uncropped_image: bool = False,
remove_background: bool = False,
save_pet_in_t1w_space: bool = False,
random_seed: Optional[int] = None,
subjects_sessions_tsv: Optional[str] = None,
Expand Down Expand Up @@ -77,7 +70,6 @@ def cli(
"suvr_reference_region": suvr_reference_region,
"reconstruction_method": reconstruction_method,
"uncropped_image": uncropped_image,
"remove_background": remove_background,
"save_PETinT1w": save_pet_in_t1w_space,
"random_seed": random_seed,
}
Expand Down
117 changes: 15 additions & 102 deletions clinica/pipelines/pet/linear/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def _build_input_node(self):
import nipype.interfaces.utility as nutil
import nipype.pipeline.engine as npe

from clinica.pipelines.pet.utils import get_mni_mask, get_suvr_mask
from clinica.pipelines.pet.utils import get_suvr_mask
from clinica.utils.exceptions import (
ClinicaBIDSError,
ClinicaCAPSError,
Expand All @@ -81,7 +81,6 @@ def _build_input_node(self):

self.ref_template = get_mni_template("t1")
self.ref_mask = get_suvr_mask(self.parameters["suvr_reference_region"])
# self.mni_mask = get_mni_mask()

# Inputs from BIDS directory
pet_files, pet_errors = clinica_file_reader(
Expand Down Expand Up @@ -227,21 +226,8 @@ def _build_output_node(self):
),
]
)
# Case 1: crop image and don't remove the background
if not (self.parameters.get("uncropped_image")) and not (
self.parameters.get("remove_background")
):
if not (self.parameters.get("uncropped_image")):
node_out_name = "outfile_crop"
# Case 2: crop image and remove the background
elif not (self.parameters.get("uncropped_image")) and (
self.parameters.get("remove_background")
):
node_out_name = "outfile_crop_no_bkgd"
# Case 3: don't crop the image and remove the background
elif (self.parameters.get("uncropped_image")) and (
self.parameters.get("remove_background")
):
node_out_name = "outfile_no_bkgd"
else:
node_out_name = "suvr_pet"
self.connect(
Expand Down Expand Up @@ -285,8 +271,6 @@ def _build_core_nodes(self):
from .tasks import (
clip_task,
perform_suvr_normalization_task,
remove_background_otsu_task,
remove_mni_background_task,
)
from .utils import concatenate_transforms, init_input_node, print_end_pipeline

Expand All @@ -309,7 +293,7 @@ def _build_core_nodes(self):

# The core (processing) nodes

# 0. Clipping node
# 1. Clipping node
clipping_node = npe.Node(
name="clipping",
interface=nutil.Function(
Expand All @@ -319,21 +303,21 @@ def _build_core_nodes(self):
),
)

# 1. `RegistrationSynQuick` by *ANTS*. It uses nipype interface.
# 2. `RegistrationSynQuick` by *ANTS*. It uses nipype interface.
ants_registration_node = npe.Node(
name="antsRegistration", interface=ants.RegistrationSynQuick()
)
ants_registration_node.inputs.dimension = 3
ants_registration_node.inputs.transform_type = "r"

# 2. `ApplyTransforms` by *ANTS*. It uses nipype interface. PET to MRI
# 3. `ApplyTransforms` by *ANTS*. It uses nipype interface. PET to MRI
ants_applytransform_node = npe.Node(
name="antsApplyTransformPET2MNI", interface=ants.ApplyTransforms()
)
ants_applytransform_node.inputs.dimension = 3
ants_applytransform_node.inputs.reference_image = self.ref_template

# 3. Normalize the image (using nifti). It uses custom interface, from utils file
# 4. Normalize the image (using nifti). It uses custom interface, from utils file
ants_registration_nonlinear_node = npe.Node(
name="antsRegistrationT1W2MNI", interface=ants.Registration()
)
Expand Down Expand Up @@ -379,7 +363,7 @@ def _build_core_nodes(self):
)
normalize_intensity_node.inputs.reference_mask_path = self.ref_mask

# 4. Crop image (using nifti). It uses custom interface, from utils file
# 5. Crop image (using nifti). It uses custom interface, from utils file
crop_nifti_node = npe.Node(
name="cropNifti",
interface=nutil.Function(
Expand All @@ -390,27 +374,6 @@ def _build_core_nodes(self):
)
crop_nifti_node.inputs.output_path = self.base_dir

# 5. Remove background using MNI mask
# remove_background_node = npe.Node(
# name="removeBackground",
# interface=nutil.Function(
# function=remove_mni_background_task,
# input_names=["input_image", "mni_mask_path"],
# output_names=["output_image"],
# ),
# )
# remove_background_node.inputs.mni_mask_path = self.mni_mask

# 5. Remove background using OTSU thresholding
remove_background_node = npe.Node(
name="removeBackground",
interface=nutil.Function(
function=remove_background_otsu_task,
input_names=["input_image"],
output_names=["output_image"],
),
)

# 6. Print end message
print_end_message = npe.Node(
interface=nutil.Function(
Expand All @@ -428,16 +391,16 @@ def _build_core_nodes(self):
self.connect(
[
(self.input_node, init_node, [("pet", "pet")]),
# STEP 0:
# STEP 1:
(init_node, clipping_node, [("pet", "input_pet")]),
# STEP 1
# STEP 2
(
clipping_node,
ants_registration_node,
[("output_image", "moving_image")],
),
(self.input_node, ants_registration_node, [("t1w", "fixed_image")]),
# STEP 2
# STEP 3
(
ants_registration_node,
concatenate_node,
Expand All @@ -458,7 +421,7 @@ def _build_core_nodes(self):
ants_applytransform_node,
[("transforms_list", "transforms")],
),
# STEP 3
# STEP 4
(
self.input_node,
ants_registration_nonlinear_node,
Expand Down Expand Up @@ -498,11 +461,9 @@ def _build_core_nodes(self):
(self.input_node, print_end_message, [("pet", "pet")]),
]
)
# STEP 4
# Case 1: crop image and don't remove the background
if not (self.parameters.get("uncropped_image")) and not (
self.parameters.get("remove_background")
):
# STEP 5
# Case 1: crop the image
if not (self.parameters.get("uncropped_image")):
self.connect(
[
(
Expand All @@ -518,57 +479,9 @@ def _build_core_nodes(self):
]
)
last_node = crop_nifti_node
# Case 2: crop image and remove the background
elif not (self.parameters.get("uncropped_image")) and (
self.parameters.get("remove_background")
):
self.connect(
[
(
normalize_intensity_node,
remove_background_node,
[("output_image", "input_image")],
),
(
remove_background_node,
crop_nifti_node,
[("output_image", "input_image")],
),
(
crop_nifti_node,
self.output_node,
[
("output_image", "outfile_crop_no_bkgd")
], # to implement in out node
),
]
)
last_node = crop_nifti_node
# Case 3: don't crop the image and remove the background
elif (self.parameters.get("uncropped_image")) and (
self.parameters.get("remove_background")
):
self.connect(
[
(
normalize_intensity_node,
remove_background_node,
[("output_image", "input_image")],
),
(
remove_background_node,
self.output_node,
[
("output_image", "outfile_no_bkgd")
], # to implement in out node
),
]
)
last_node = remove_background_node
# Case 4: don't crop the image and don't remove the background
# Case 2: don't crop the image
else:
last_node = normalize_intensity_node

self.connect(
[
(
Expand Down
26 changes: 0 additions & 26 deletions clinica/pipelines/pet/linear/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,6 @@ def perform_suvr_normalization_task(
)


def remove_mni_background_task(
input_image: str,
mni_mask_path: str,
) -> str:
from pathlib import Path

from clinica.pipelines.pet.linear.utils import remove_mni_background

return str(
remove_mni_background(
Path(input_image),
Path(mni_mask_path),
)
)


def remove_background_otsu_task(
input_image: str,
) -> str:
from pathlib import Path

from clinica.pipelines.pet.linear.utils import remove_background_otsu

return str(remove_background_otsu(Path(input_image)))


def clip_task(
input_pet: str,
) -> str:
Expand Down
72 changes: 0 additions & 72 deletions clinica/pipelines/pet/linear/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,78 +108,6 @@ def perform_suvr_normalization(
return output_image


def remove_mni_background(
pet_image_path: Path,
mni_mask_path: Path,
) -> Path:
"""Remove background according to a dilated binary mask.
Parameters
----------
pet_image_path : Path
The path to the image to be processed.
mni_mask_path : Path
The path to the dilated MNI binary mask.
Returns
-------
output_img : Path
The path to the nifti image with the background removed.
"""
import nibabel as nib

from clinica.utils.filemanip import get_filename_no_ext

pet_image = nib.load(pet_image_path)
mni_mask = nib.load(mni_mask_path)

# TODO: check if it is the best way to do the operation
data = pet_image.get_fdata(dtype="float32") * mni_mask.get_fdata(dtype="float32")

output_image = (
Path.cwd() / f"{get_filename_no_ext(pet_image_path)}_remove_background.nii.gz"
)
no_bkgd_img = nib.Nifti1Image(data, pet_image.affine, header=pet_image.header)
no_bkgd_img.to_filename(output_image)

return output_image


def remove_background_otsu(
pet_image_path: Path,
):
"""Remove background using OTSU thresholding.
Parameters
----------
pet_image_path : Path
The path to the image to be processed.
Returns
-------
output_img : Path
The path to the nifti image with the background removed.
"""
import nibabel as nib
from skimage.filters import threshold_otsu

from clinica.utils.filemanip import get_filename_no_ext

pet_image = nib.load(pet_image_path)

data = pet_image.get_fdata(dtype="float32")
threshold = threshold_otsu(data)
data[data < threshold] = 0
output_image = (
Path.cwd() / f"{get_filename_no_ext(pet_image_path)}_remove_background.nii.gz"
)
no_bkgd_img = nib.Nifti1Image(data, pet_image.affine, header=pet_image.header)
no_bkgd_img.to_filename(output_image)

return output_image


def clip_img(
pet_image_path: Path,
) -> Path:
Expand Down
19 changes: 0 additions & 19 deletions clinica/pipelines/pet/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,6 @@ def get_suvr_mask(region: Union[str, SUVRReferenceRegion]) -> Path:
)


def get_mni_mask() -> Path:
"""Returns the path to the dilated MNI binary mask.
Parameters
----------
Returns
-------
Path :
The path to the dilated MNI binary mask.
"""
return (
Path(__file__).resolve().parents[2]
/ "resources"
/ "masks"
/ "dilated_MNI_binary_mask.nii.gz"
)


def _get_suvr_reference_region_labels_filename(region: SUVRReferenceRegion) -> str:
if region == SUVRReferenceRegion.PONS:
return "region-pons_eroded-6mm_mask.nii.gz"
Expand Down

0 comments on commit 0fec25e

Please sign in to comment.