Source code for omni.pipelines.anat.segmentation

import os
import shutil
import logging
from concurrent.futures import ProcessPoolExecutor
import numpy as np
import nibabel as nib
from memori.helpers import create_output_path
from memori.pathman import append_suffix, repath, replace_suffix
from omni.interfaces.common import normalize
from omni.interfaces.fsl import bet


[docs]@create_output_path def brain_extraction( output_path: str, t1_debias: str = None, t2_debias: str = None, fractional_intensity_threshold: float = 0.5, method: str = "Norm", use_eye_mask: bool = True, ): """Brain extraction Parameters ---------- output_path : str Output path to write out files to. t1_debias : str T1 image. t2_debias : str T2 image. fractional_intensity_threshold : float Fractional intensity threshold for bet. method : str Method for brain extraction (T1/Norm). use_eye_mask : bool Use eye mask for anatomical mask. Returns ------- str Eye mask. str Anatomical mask. str Brain extracted T1 debiased. str Brain extracted T2 debiased. """ # ensure a t1/t2 is defined if not (t1_debias or t2_debias): raise ValueError("A t1/t2 input is required.") with ProcessPoolExecutor(max_workers=2) as executor: # generate eye mask if enabled if use_eye_mask: # generate tmp directory for eye mask data eye_path = os.path.join(output_path, "eye") os.makedirs(eye_path, exist_ok=True) # Run bet for eye mask t1_eye_bet = append_suffix(repath(eye_path, t1_debias), "_bet") logging.info("Extracting eye mask...") anat_eye_mask_future = executor.submit( bet, t1_eye_bet, t1_debias, fractional_intensity_threshold, mask=True, eye=True ) # run bet based on method selected logging.info("Running brain extraction...") anat_bet = os.path.join(output_path, "anat_bet.nii.gz") if method == "Norm": # load debiased images t1_debias_img = nib.load(t1_debias) t2_debias_img = nib.load(t2_debias) # get L2 norm sum of T1/T2 norm_anat = os.path.join(output_path, "norm_anat.nii.gz") nib.Nifti1Image( 10000 * np.sqrt(normalize(t1_debias_img.get_fdata()) + normalize(t2_debias_img.get_fdata())), t1_debias_img.affine, t1_debias_img.header, ).to_filename(norm_anat) # run bet on norm image anat_bet_future = executor.submit( bet, anat_bet, norm_anat, fractional_intensity_threshold, mask=True, neck=True ) elif method == "T1": # run bet on T1 image anat_bet_future = executor.submit( bet, anat_bet, t1_debias, fractional_intensity_threshold, mask=True, neck=True ) else: raise ValueError("Invalid method: %s selected." % method) # get futures logging.info("Waiting for bet call(s) to finish...") if use_eye_mask: # await eye mask results _, _, anat_eye_mask = anat_eye_mask_future.result() # move eye mask to output path and delete temp eye directory if os.path.exists(repath(output_path, anat_eye_mask)): os.remove(repath(output_path, anat_eye_mask)) shutil.move(anat_eye_mask, output_path) shutil.rmtree(eye_path) anat_eye_mask = repath(output_path, anat_eye_mask) shutil.move(anat_eye_mask, replace_suffix(anat_bet, "_eye_mask")) anat_eye_mask = replace_suffix(anat_bet, "_eye_mask") else: # generate a non-mask if use_eye_mask disabled anat_eye_mask = replace_suffix(anat_bet, "_eye_mask") if t1_debias: img = nib.load(t1_debias) elif t2_debias: img = nib.load(t2_debias) # create zero array zeros_data = np.zeros(img.shape, dtype="f4") # save fake eye mask nib.Nifti1Image(zeros_data, img.affine, img.header).to_filename(anat_eye_mask) # await bet results _, anat_bet_mask = anat_bet_future.result() os.remove(anat_bet) # remove anat_bet.nii.gz logging.info("bet call(s) done!") # generate a function for applying masks def apply_mask(out_file, img, mask): return nib.Nifti1Image( nib.load(img).get_fdata() * nib.load(mask).get_fdata(), nib.load(img).affine, nib.load(img).header ).to_filename(out_file) # apply mask to anatomical data t1_debias_bet = append_suffix(repath(output_path, t1_debias), "_bet") apply_mask(t1_debias_bet, t1_debias, anat_bet_mask) t2_debias_bet = append_suffix(repath(output_path, t2_debias), "_bet") apply_mask(t2_debias_bet, t2_debias, anat_bet_mask) # return files return (anat_bet_mask, anat_eye_mask, t1_debias_bet, t2_debias_bet)