def tbss_2_reg(tbss_dir, use_fmrib58_fa_1mm=False, target_img=None, find_best_target=True, nb_cpus=None, fsl_sh=DEFAULT_FSL_PATH): """ Wraps fsl tbss_2_reg command to non-linearly register the FA images to a 1x1x1mm standard space or a template image or the best target from all FA images. For more information, refer to: https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/TBSS/UserGuide Parameters ---------- tbss_dir: str (required) path to tbss root directory. use_fmrib58_fa_1mm: bool (optional, default True) use FMRIB58_FA_1mm as target for nonlinear registrations (recommended). target_img: str (optional, default None) path to a target image to use for nonlinear registration. find_best_target: bool (default False) option to find best target from all FA images. nb_cpus: int, default None the number of cpus to use, default all - 1. fsl_sh: str path to fsl setup sh file. """ if not (os.getcwd() == tbss_dir): os.chdir(tbss_dir) cmd = ["tbss_2_reg"] if use_fmrib58_fa_1mm: # cmd.append("-T") process = FSLWrapper([], shfile=fsl_sh) shutil.copy2( os.path.join(process.environment["FSLDIR"], "data", "standard", "FMRIB58_FA_1mm.nii.gz"), os.path.join(tbss_dir, "FA", "target.nii.gz")) elif target_img is not None: # cmd.extend(["-t", target_img]) shutil.copy2(target_img, os.path.join(tbss_dir, "FA", "target.nii.gz")) elif find_best_target: cmd.append("-n") fslprocess = FSLWrapper(cmd, shfile=fsl_sh) fslprocess() return else: raise ValueError( "Please enter valid parameters for function tbss_2_reg.") if nb_cpus is None: nb_cpus = multiprocessing.cpu_count() - 1 fa_basenames = glob.glob1(os.path.join(tbss_dir, "FA"), "*_FA.nii.gz") fa_basenames = [name.split(".")[0] for name in fa_basenames] Parallel(n_jobs=nb_cpus)(delayed(fsl_reg)(name, tbss_dir, fsl_sh) for name in fa_basenames)
def fslreorient2std(input_image, output_image, save_trf=True, fslconfig=DEFAULT_FSL_PATH): """ Reorient an image to match the approximate orientation of the standard template image (MNI152). It only applies 0, 90, 180 or 270 degree rotations. It is not a registration tool. It requires NIfTI images with valid orientation information in them (seen by valid labels in FSLView). This tool assumes the labels are correct - if not, fix that before using this. If the output name is not specified the equivalent transformation matrix is written to the standard output. The basic usage is: fslreorient2std <input_image> [output_image] Parameters ---------- input_image: str (mandatory) The image to reorient. output_image: str (mandatory) The reoriented image. save_trf: bool, default True If set save the reorientation matrix. fslconfig: str (optional, default DEFAULT_FSL_PATH) The FSL configuration batch. """ # Check the input parameter if not os.path.isfile(input_image): raise ValueError( "'{0}' is not a valid input file.".format(input_image)) if not output_image.endswith(".nii.gz"): output_image += ".nii.gz" # Define the FSL commands cmd1 = ["fslreorient2std", input_image, output_image] cmd2 = ["fslreorient2std", input_image] # Call fslreorient2std fslprocess = FSLWrapper(cmd1, shfile=fslconfig) fslprocess() if save_trf: fslprocess = FSLWrapper(cmd2, shfile=fslconfig) fslprocess() fsl_trf_file = output_image.split(".")[0] + ".fsl.trf" with open(fsl_trf_file, "wt") as open_file: open_file.write(fslprocess.stdout) trf_file = output_image.split(".")[0] + ".trf" numpy.savetxt(trf_file, flirt2aff(fsl_trf_file, output_image, input_image)) return output_image
def fsl_prepare_fieldmap( manufacturer, phase_file, brain_magnitude_file, output_file, delta_te, fsl_sh=DEFAULT_FSL_PATH): """ Prepares a fieldmap suitable for FEAT from SIEMENS data. Saves output in rad/s format. Parameters ---------- manufacturer: str The manufacturer name. phase_file: str The phase image. brain_magnitude_file: str The magnitude brain image: should only contains brain tissues. output_file: str The generated fieldmap image. delta_te: float The echo time difference of the fieldmap. fsl_sh: str, default DEFAULT_FSL_PATH The FSL configuration batch. Returns ------- output_file: str The generated fieldmap image in rad/s. output_hz_file: str The generated fieldmap image in Hz. """ # Check the input parameter for path in (phase_file, brain_magnitude_file): if not os.path.isfile(path): raise ValueError("'{0}' is not a valid input file.".format(path)) if not output_file.endswith(".nii.gz"): output_file += ".nii.gz" # Define the FSL command cmd = ["fsl_prepare_fieldmap", manufacturer, phase_file, brain_magnitude_file, output_file, delta_te] # Call fsl_prepare_fieldmap fslprocess = FSLWrapper(cmd, shfile=fsl_sh) fslprocess() # Convert the fieldmap in rad/s to Hz output_hz_file = output_file.replace(".nii.gz", "_hz.nii.gz") cmd = ["fslmaths", output_file, "-div", "6.28", output_hz_file] fslprocess = FSLWrapper(cmd, shfile=fsl_sh) fslprocess() return output_file, output_hz_file
def surf2surf(input_surf, output_surf, fslconfig=DEFAULT_FSL_PATH): """ Convert an input surface in ASCI mode. Parameters ---------- input_surf: str (mandatory) The input surface to convert. output_surf: str (mandatory) The converted surface. fslconfig: str (optional, default DEFAULT_FSL_PATH) The FSL configuration batch. """ # check the input parameter if not os.path.isfile(input_surf): raise ValueError("'{0}' is not a valid input file.".format(input_surf)) # Define the FSL command cmd = [ "surf2surf", "-i", input_surf, "-o", output_surf, "--outputtype=ASCII", "--values=1" ] # Call fslreorient2std fslprocess = FSLWrapper(cmd, shfile=fslconfig) fslprocess()
def bedpostx_datacheck(data_dir, fslconfig=DEFAULT_FSL_PATH): """ Wraps bedpostx_datacheck. Usage: bedpostx_datacheck data_dir Parameters ---------- data_dir: str (mandatory) The folder to check. fslconfig: str (optional) The FSL configuration batch. Returns ------- is_valid: bool True if all the data are present in the data directory """ # check data directory if not os.path.isdir(data_dir): raise ValueError("'{0}' is not a valid data directory.".format( data_dir)) # Define the FSL command cmd = ["bedpostx_datacheck", data_dir] # Execute the FSL command fslprocess = FSLWrapper(cmd, shfile=fslconfig) fslprocess() # Parse outputs is_valid = ( fslprocess.stderr == "" and "does not exist" not in fslprocess.stdout) return is_valid
def smooth_fieldmap(fieldmap, dwell_time, output_file, sigma=2, fsl_sh=DEFAULT_FSL_PATH): """ Smooth a field map using FSL using a Gaussian 3D kernel. Parameters ---------- fieldmap_file: str the FSL fieldmap. dwell_time: float the dwell time in s. output_file: str The generated smoothed fieldmap image. sigma: float, default 2 The Gaussian smoothing kernel sigma. fsl_sh: str, optional default 'DEFAULT_FSL_PATH' path to fsl setup sh file. """ cmd = [ "fugue", "--dwell={0}".format(dwell_time), "--loadfmap={0}".format(fieldmap), "--savefmap={0}".format(output_file), "-s", str(sigma)] fslprocess = FSLWrapper(cmd, shfile=fsl_sh) fslprocess()
def robustfov(input_file, output_file, brain_size=170, matrix_file=None, fsl_sh=DEFAULT_FSL_PATH): """ Reduce FOV of image to remove lower head and neck. It is based on FSL robustfov command. Parameters ---------- input_file: str the file to be cropped. output_file: str the cropped file name. brain_size: float (default 170) the size of brain in z-dimension (in mm). matrix_file: str (default None) if set, write the transformation matrix. fsl_sh: str, default DEFAULT_FSL_PATH The FSL configuration script. """ # Check input parameters if not os.path.isfile(input_file): raise ValueError("'{0}' is not a valid input file.".format(input_file)) # Define the FSL command cmd = ["robustfov", "-b", str(brain_size)] if matrix_file is not None: cmd += ["-m", matrix_file] cmd += ["-i", input_file, "-r", output_file] # Call FSL robustfov fslprocess = FSLWrapper(cmd, shfile=fsl_sh) fslprocess()
def erode(input_file, output_file, radius, fslconfig=DEFAULT_FSL_PATH): """ Erode an image using a spherical kernel. Parameters ---------- input_file: str (mandatory) The image to erode (binary or gray level). output_file: str (mandatory) The eroded image. radius: float (optional, default 2) The sphere kernel in mm. fslconfig: str (optional, default DEFAULT_FSL_PATH) The FSL configuration batch. Returns ------- output_file: str The eroded image. """ # Check the input parameter if not os.path.isfile(input_file): raise ValueError("'{0}' is not a valid input file.".format(input_file)) # Define the FSL command cmd = [ "fslmaths", input_file, "-kernel", "sphere", str(radius), "-ero", output_file ] # Call fslmaths fslprocess = FSLWrapper(cmd, shfile=fslconfig) fslprocess() return output_file
def deface(input_files, outdir, reference_file=None, fsl_sh=DEFAULT_FSL_PATH): """ Deface MRI head images using Poldrack, R. 'pydeface' Python module. Parameters ---------- input_files: list of str Input MRI head images to be defaced. outdir: str The output folder. reference_file: str (optional, default None) The image that must be used as reference if more than one image have been supplied as input. fsl_sh: str (optional, default DEFAULT_FSL_PATH) The FSL configuration file. Returns ------- deface_files: list of str The defaced input MRI head images. snap_files: list of str The corresponding snaps that can be used to check the defacing result. """ # Check input parameters outdir = os.path.abspath(outdir) if len(input_files) == 0: raise ValueError("You must specify at least one image.") elif len(input_files) > 1: raise ValueError("Mutliple input files not yet supported.") # if reference_file is None or reference_file not in input_files: # raise ValueError("If more than one image is specified, you must " # "also specify one of them as reference. The " # "reference image will be used for spatial " # "co-registration with an atlas, and others " # "will use the reference facial mask.") # Link the input files local_input_files = [] for fp in input_files: local_input_files.append(os.path.join(outdir, os.path.basename(fp))) if not os.path.exists(local_input_files[-1]): os.symlink(fp, local_input_files[-1]) else: warnings.warn("'{0}' file already here.".format( local_input_files[-1])) # Define the command deface_file = os.path.join(outdir, "pydeface_" + os.path.basename(input_files[0])) cmd = ["pydeface.py", local_input_files[0], deface_file] # Call defacing wrapper = FSLWrapper(cmd, shfile=fsl_sh, env=os.environ) wrapper() # Remove links for fp in local_input_files: os.remove(fp) return [deface_file], None
def pixel_shift_to_fieldmap(pixel_shift_file, dwell_time, output_file, fsl_sh=DEFAULT_FSL_PATH): """ Convert a pixel shift map to a FSL field map. Parameters ---------- pixel_shift_file: str the pixel shift map. dwell_time: float the dwell time in s. output_file: str The generated fieldmap image. fsl_sh: str, optional default 'DEFAULT_FSL_PATH' path to fsl setup sh file. Returns ------- fieldmap_file: str the FSL fieldmap in rad/s. fieldmap_hz_file: str the FSL fieldmap in Hz. """ # Check the input parameter if not os.path.isfile(pixel_shift_file): raise ValueError("'{0}' is not a valid input file.".format( pixel_shift_file)) if not output_file.endswith(".nii.gz"): output_file += ".nii.gz" # Convert the fieldmap cmd = [ "fugue", "--dwell={0}".format(dwell_time), "--loadshift={0}".format(pixel_shift_file), "--savefmap={0}".format(output_file)] fslprocess = FSLWrapper(cmd, shfile=fsl_sh) fslprocess() # Convert the fieldmap in rad/s to Hz output_hz_file = output_file.replace(".nii.gz", "_hz.nii.gz") cmd = ["fslmaths", output_file, "-div", "6.28", output_hz_file] fslprocess = FSLWrapper(cmd, shfile=fsl_sh) fslprocess() return output_file, output_hz_file
def __init__(self, cmd, shfile=DEFAULT_FREESURFER_PATH, env=None, subjects_dir=None, add_fsl_env=False, fsl_sh=None): """ Initialize the FSWrapper class by setting properly the environment. Parameters ---------- cmd: list of str (mandatory) the FreeSurfer command to execute. shfile: str (optional, default NeuroSpin path) the path to the FreeSurfer 'SetUpFreeSurfer.sh' configuration file. env: dict (optional, default None) An environment to add to the FreeSurfer environment, e.g. os.environ to maintain current env in the FreeSurfer env. subjects_dir: str, default None. To set the $SUBJECTS_DIR environment variable. add_fsl_env: bool, default False To activate the FSL environment, required for commands like bbregister. fsl_sh: str, default NeuroSpin path Path to the Bash script setting the FSL environment, if needed. """ self.cmd = cmd self.shfile = shfile self.version = None self.environment = self._freesurfer_version_check() if env is not None: self.environment = concat_environment(self.environment, env) # If requested add FSL environment if add_fsl_env: # Import here so that the dependency is not mandatory for # the rest of the package from pyconnectome.wrapper import FSLWrapper if fsl_sh is None: fsl_sh = DEFAULT_FSL_PATH fsl_env = FSLWrapper([], shfile=fsl_sh).environment self.environment = concat_environment(self.environment, fsl_env) # Update the environment variables if subjects_dir is not None: self.environment["SUBJECTS_DIR"] = subjects_dir elif "SUBJECTS_DIR" in os.environ: self.environment["SUBJECTS_DIR"] = os.environ["SUBJECTS_DIR"] if (len(self.cmd) > 0 and self.cmd[0] == "tkmedit" and "DISPLAY" in os.environ): self.environment["DISPLAY"] = os.environ["DISPLAY"]
def tbss_3_postreg(tbss_dir, use_fmrib58_fa_mean_and_skel=True, fsl_sh=DEFAULT_FSL_PATH): """ Wraps fsl tbss_3_postreg command to apply the nonlinear transforms found in the previous stage to all subjects to bring them into standard space. Merge results into a single 4D image. Compute a mean FA image and skeletonize it. For more information, refer to: https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/TBSS/UserGuide Parameters ---------- tbss_dir: str (required) path to tbss root directory. use_fmrib58_fa_mean_and_skel: bool (optional, default True) use the FMRIB58_FA mean FA image and its derived skeleton, instead of the mean of the subjects. fsl_sh: str path to fsl setup sh file. Returns ------- all_FA: str path to the concatenated subjects FA files in template space. mean_FA: str path to the subjects' mean FA. mean_FA_mask: str path to the brain mask of mean_FA. mean_FA_skel: str path to the skeletonized mean FA. """ if not os.getcwd() == tbss_dir: os.chdir(tbss_dir) cmd = ["tbss_3_postreg"] if use_fmrib58_fa_mean_and_skel: cmd.append("-T") else: cmd.append("-S") fslprocess = FSLWrapper(cmd, shfile=fsl_sh) fslprocess() # Check that output files have been correctly created. all_FA = os.path.join(tbss_dir, "stats", "all_FA.nii.gz") mean_FA = os.path.join(tbss_dir, "stats", "mean_FA.nii.gz") mean_FA_mask = os.path.join(tbss_dir, "stats", "mean_FA_mask.nii.gz") mean_FA_skel = os.path.join(tbss_dir, "stats", "mean_FA_skeleton.nii.gz") output_files = [all_FA, mean_FA, mean_FA_mask, mean_FA_skel] for out_file in output_files: if not os.path.isfile(out_file): raise ValueError( "tbss_3_postreg outputs : {0} does not exist! FSL error: " "{1}".format(out_file, fslprocess.stderr)) return all_FA, mean_FA, mean_FA_mask, mean_FA_skel
def applywarp(in_file, ref_file, out_file, warp_file, pre_affine_file=None, post_affine_file=None, interp="trilinear", verbose=0, shfile=DEFAULT_FSL_PATH): """ Apply FSL deformation field. Parameters ---------- in_file: str filename of input image (to be warped). ref_file: str filename for reference image. out_file: str filename for output (warped) image. warp_file: str filename for warp/coefficient (volume). pre_affine_file: str filename for pre-transform (affine matrix). post_affine_file: str filename for post-transform (affine matrix). interp: str (optional, default "trilinear") interpolation method {nn,trilinear,sinc,spline} verbose: int, default 0 the verbosity level. shfile: str, default DEFAULT_FSL_PATH The FSL configuration batch. """ # Check the input parameters for filename in (in_file, ref_file, pre_affine_file, post_affine_file): if filename is not None and not os.path.isfile(filename): raise ValueError( "'{0}' is not a valid input file.".format(filename)) # Define the FSL command cmd = [ "applywarp", "-i", in_file, "-r", ref_file, "-o", out_file, "-w", warp_file, "--interp={0}".format(interp), "--verbose={0}".format(verbose) ] if pre_affine_file is not None: cmd.append("--premat={0}".format(pre_affine_file)) if post_affine_file is not None: cmd.append("--postmat={0}".format(post_affine_file)) # Call fnirt fslprocess = FSLWrapper(cmd, shfile=shfile) fslprocess()
def get_mean_fa(fa_4D, output, fsl_sh=DEFAULT_FSL_PATH): """ Wraps fslmaths command and create a mean FA map. Parameters ---------- fa_4D: str path to the 4D FA data. output: str path to the mean FA map. fsl_sh: str path to FSL setup sh file. """ cmd = ["fslmaths", fa_4D, "-Tmean", output] fslprocess = FSLWrapper(cmd, shfile=fsl_sh) fslprocess()
def fix_freesurfer_subcortical_parcellation(parc, t1_brain, lut, output, tempdir=None, nb_threads=None, fsl_sh=DEFAULT_FSL_PATH): """ Use the MRtrix labelsgmfix command to correct the FreeSurfer subcortical parcellation. It uses FSL First to recompute 5 subcortical structures. Parameters ---------- parc: str Path to the FreeSurfer parcellation, generally aparc+aseg or aparc.a2009s+aseg. t1_brain: str Path to the T1 brain-only image on which recompute the segmentation. lut: str Path to the Look Up Table. If you haven't change the labels it should be FreeSurfer LUT (FreeSurferColorLUT.txt in $FREESURFER_HOME dir). output: str Path to output fixed parcellation. tempdir: str, default None Directory that MRtrix will use as temporary directory. nb_threads: int, default None Number of threads that MRtrix is allowed to use. fsl_sh: str, default DEFAULT_FSL_PATH The FSL configuration script. Returns ------- output: str Path to output fixed parcellation. """ cmd = ["labelsgmfix", parc, t1_brain, lut, output, "-premasked"] if tempdir is not None: cmd += ["-tempdir", tempdir] if nb_threads is not None: cmd += ["-nthreads", "%i" % nb_threads] fsl_process = FSLWrapper(cmd, env=os.environ, shfile=fsl_sh) fsl_process() return output
def tbss_4_prestats(tbss_dir, threshold=0.2, fsl_sh=DEFAULT_FSL_PATH): """ Wraps fsl tbss_4_prestats command to thresholds the mean FA skeleton image at the chosen threshold, create a distance map, and project the FA data onto the mean FA skeleton. To be used before any voxelwise cross-subject stats. For more information, refer to: https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/TBSS/UserGuide Parameters ---------- tbss_dir: str (required) path to tbss root directory. threshold: float (required, default 0.2) fsl_sh: str path to fsl setup sh file. Returns ------- all_FA_skeletonized: str path to the concatenated subjects skeletonized FA. mean_FA_skel_mask: str binary skeleton mask. mean_FA_skel_mask_dst: str distance map created from the skeleton mask. thresh_file: str text file indicating threshold used. """ if not os.getcwd() == tbss_dir: os.chdir(tbss_dir) cmd = ["tbss_4_prestats", str(threshold)] fslprocess = FSLWrapper(cmd, shfile=fsl_sh) fslprocess() # Check that output files have been correctly created. all_FA_skeletonized = os.path.join(tbss_dir, "stats", "all_FA_skeletonised.nii.gz") mean_FA_skel_mask = os.path.join(tbss_dir, "stats", "mean_FA_skeleton_mask.nii.gz") mean_FA_skel_mask_dst = os.path.join(tbss_dir, "stats", "mean_FA_skeleton_mask_dst.nii.gz") thresh_file = os.path.join(tbss_dir, "stats", "thresh.txt") return (all_FA_skeletonized, mean_FA_skel_mask, mean_FA_skel_mask_dst, thresh_file)
def fsl_reg(fa_basename, tbss_dir, fsl_sh): """ Run the FSL registration step. Wrapping around the 'fsl_reg' command. Parameters ---------- fa_basename: str the FA file base name. tbss_dir: str path to tbss root directory. fsl_sh: str path to fsl setup sh file. """ cmd = [ "fsl_reg", fa_basename, "target", fa_basename + "_to_target", "-e", "-FA" ] print("Executing: " + " ".join(cmd)) fslprocess = FSLWrapper(cmd, shfile=fsl_sh) fslprocess(cwdir=os.path.join(tbss_dir, "FA"))
def white_matter_interface(t1_brain_file, outdir, tempdir, fsl_sh=DEFAULT_FSL_PATH): """ Generate a probabilist mask image appropriate for seeding streamlines on the grey matter-white matter interface using MRtrix. This mask deals with partial volume effects. Parameters ---------- t1_brain_file: str the anatomical file used to generate the probabilist mask using MRtrix and FSL FAST. outdir: str the destination folder. tempdir: str a temporary folder for MRtrix with sufficient space. fsl_sh: str, default DEFAULT_FSL_PATH the FSL configuration script. Returns ------- gmwmi_mask_file: str the generated probabilist seed mask. """ # 5 tissue types segmentation # Generate the 5TT image based on a FSL FAST five_tissues_file = os.path.join(outdir, "5TT.nii.gz") cmd = [ "5ttgen", "fsl", t1_brain_file, five_tissues_file, "-premasked", "-tempdir", tempdir, "-nocrop" ] FSLWrapper(cmd, env=os.environ, shfile=fsl_sh)() # Generate probabilist seed mask gmwmi_mask_file = os.path.join(outdir, "gmwmi_mask.nii.gz") cmd = ["5tt2gmwmi", five_tissues_file, gmwmi_mask_file] subprocess.check_call(cmd) return gmwmi_mask_file
def average_timeserie(input_file, output_file, fslconfig=DEFAULT_FSL_PATH): """ Average a timeserie. Parameters ---------- input_file: str the image to average. output_file: str the averaged image. fslconfig: str, default DEFAULT_FSL_PATH the FSL configuration batch. """ # Check the input parameter for path in (input_file, ): if not os.path.isfile(path): raise ValueError("'{0}' is not a valid input file.".format(path)) # Define the FSL command cmd = ["fslmaths", input_file, "-Tmean", output_file] # Call fslmaths fslprocess = FSLWrapper(shfile=fslconfig) fslprocess(cmd=cmd)
def tbss_1_preproc(tbss_dir, fsl_sh=DEFAULT_FSL_PATH): """ Wraps fsl tbss_1_preproc command to erode the FA images slightly and zero the end slices (to remove likely outliers from the diffusion tensor fitting). For more information, refer to: https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/TBSS/UserGuide Parameters ---------- tbss_dir: str (required) path to tbss root directory. fsl_sh: str path to fsl setup sh file. Returns ------- fa_dir: str path to the subjects corrected FA files. orig_dir: str path to the copied subjects original FA files. """ if not os.path.isdir(tbss_dir): os.mkdir(tbss_dir) os.chdir(tbss_dir) cmd = ["tbss_1_preproc", "*.nii.gz"] fslprocess = FSLWrapper(cmd, shfile=fsl_sh) fslprocess() fa_dir = os.path.join(tbss_dir, "FA") orig_dir = os.path.join(tbss_dir, "origdata") if not os.path.isdir(fa_dir): raise ValueError( "tbss_1_preproc did not create FA dir : {0}...".format(fa_dir)) if not os.path.isdir(orig_dir): raise ValueError( "tbss_1_preproc did not create orig dir : {0}...".format(orig_dir)) return fa_dir, orig_dir
def apply_mask(input_file, output_fileroot, mask_file, fslconfig=DEFAULT_FSL_PATH): """ Apply a mask to an image. Parameters ---------- input_file: str (mandatory) The image to mask. output_fileroot: str (mandatory) The masked image root name. mask_file: str (mandatory) The mask image. fslconfig: str (optional, default DEFAULT_FSL_PATH) The FSL configuration batch. Returns ------- mask_file: str the masked input image. """ # Check the input parameter for filename in (input_file, mask_file): if not os.path.isfile(filename): raise ValueError("'{0}' is not a valid input " "file.".format(filename)) # Define the FSL command # "-mas": use (following image>0) to mask current image. cmd = ["fslmaths", input_file, "-mas", mask_file, output_fileroot] # Call fslmaths fslprocess = FSLWrapper(cmd, shfile=fslconfig) fslprocess() return glob.glob(output_fileroot + ".*")[0]
def get_fa_stack_mask(fa_4D, output, fsl_sh=DEFAULT_FSL_PATH): """ Wraps fslmaths command and create a combined binary mask volume from a FA 4D data of multiple subjects. Parameters ---------- fa_4D: str path to the 4D FA data. output: str path to the combined binary mask volume. fsl_sh: str path to fsl setup sh file. Returns ------- output: str path to the combined binary mask volume. """ cmd = [ "fslmaths", fa_4D, "-max", "0", "-Tmin", "-bin", output, "-odt", "char" ] fslprocess = FSLWrapper(cmd, shfile=fsl_sh) fslprocess() return output
def fnirt(in_file, ref_file, affine_file, outdir, inmask_file=None, verbose=0, shfile=DEFAULT_FSL_PATH): """ Wraps command fnirt. Parameters ---------- in_file: str (mandatory) Input volume. ref_file: str (mandatory) Reference volume. affine_file: str (optional, default None) Affine matrix filename in 4x4 ascii format. outdir: str The destination folder. inmask_file: str (optional, default None) Name of file with mask in input image space. verbose: int (optional) 0 is least and default. shfile: str (optional, default DEFAULT_FSL_PATH) The FSL configuration batch. Returns ------- cout: str Name of output file with field coefficients. iout: str Name of output image. fout: str Name of output file with field. jout: str Name of file for writing out the Jacobian of the field. refout: str Name of file for writing out intensity modulated. intout: str Name of files for writing information pertaining to intensity mapping logout: str Name of log-file. """ # Check the input parameters for filename in (in_file, ref_file, affine_file, inmask_file): if filename is not None and not os.path.isfile(filename): raise ValueError( "'{0}' is not a valid input file.".format(filename)) # Define the FSL command cmd = [ "fnirt", "--ref={0}".format(ref_file), "--in={0}".format(in_file), "--aff={0}".format(affine_file), "--verbose={0}".format(verbose) ] if inmask_file is not None: cmd += ["--inmask={0}".format(inmask_file)] basename = os.path.basename(in_file).split(".")[0] outputs = [] for param in ("cout", "iout", "fout", "jout", "refout", "intout", "logout"): ext = ".nii.gz" if param in ("logout"): ext = ".txt" outputs.append( os.path.join(outdir, "{0}_{1}{2}".format(param, basename, ext))) cmd += ["--{0}={1}".format(param, outputs[-1])] # Call fnirt fslprocess = FSLWrapper(cmd, shfile=shfile) fslprocess() return outputs
def flirt(in_file, ref_file, omat=None, out=None, init=None, cost="corratio", usesqform=False, displayinit=False, anglerep="euler", bins=256, interp="trilinear", dof=12, applyxfm=False, applyisoxfm=None, nosearch=False, verbose=0, shfile=DEFAULT_FSL_PATH): """ Wraps command flirt. The basic usage is: flirt [options] -in <inputvol> -ref <refvol> -out <outputvol> flirt [options] -in <inputvol> -ref <refvol> -omat <outputmatrix> flirt [options] -in <inputvol> -ref <refvol> -applyxfm -init <matrix> -out <outputvol> Parameters ---------- in_file: str (mandatory) Input volume. ref_file: str (mandatory) Reference volume. omat: str (optional, default None) Matrix filename. Output in 4x4 ascii format. out: str (optional, default None) Output volume. init: (optional, default None) Input 4x4 affine matrix cost: str (optional, default "corratio") Choose the most appropriate option: "mutualinfo", "corratio", "normcorr", "normmi", "leastsq", "labeldiff", "bbr". usesqform: bool (optional, default False) Initialise using appropriate sform or qform. displayinit: bool Display initial matrix. anglerep: str (optional default "euler") Choose the most appropriate option: "quaternion", "euler". bins: int (optional, default 256) Number of histogram bins interp: str (optional, default "trilinear") Choose the most appropriate option: "trilinear", "nearestneighbour", "sinc", "spline". (final interpolation: def - trilinear) dof: int (optional, default 12) Number of transform dofs. applyxfm: bool Applies transform (no optimisation) - requires -init. applyisoxfm: float (optional) The integer defines the scale. As applyxfm but forces isotropic resampling. verbose: int (optional) 0 is least and default. nosearch: bool (optional, default False) if set perform no search to initializa the optimization. shfile: str (optional, default DEFAULT_FSL_PATH) The FSL configuration batch. Returns ------- out: str Output volume. omat: str Output matrix filename. Output in 4x4 ascii format. """ # Check the input parameters for filename in (in_file, ref_file): if not os.path.isfile(filename): raise ValueError( "'{0}' is not a valid input file.".format(filename)) # Define the FSL command cmd = [ "flirt", "-in", in_file, "-ref", ref_file, "-cost", cost, "-searchcost", cost, "-anglerep", anglerep, "-bins", str(bins), "-interp", interp, "-dof", str(dof), "-verbose", str(verbose) ] # Set default parameters if usesqform: cmd += ["-usesqform"] if displayinit: cmd += ["-displayinit"] if applyxfm: cmd += ["-applyxfm"] if nosearch: cmd += ["-nosearch"] if init is not None: cmd += ["-init", init] if applyisoxfm is not None: cmd += ["-applyisoxfm", str(applyisoxfm)] dirname = os.path.dirname(in_file) basename = os.path.basename(in_file).split(".")[0] if out is None: out = os.path.join(dirname, "flirt_out_{0}.nii.gz".format(basename)) cmd += ["-out", out] else: cmd += ["-out", out] if omat is None: if not applyxfm: omat = os.path.join(dirname, "flirt_omat_{0}.txt".format(basename)) cmd += ["-omat", omat] else: cmd += ["-omat", omat] # Call flirt fslprocess = FSLWrapper(cmd, shfile=shfile) fslprocess() return out, omat
def mcflirt(in_file, out_fileroot, cost="normcorr", bins=256, dof=6, refvol=None, reffile=None, reg_to_mean=True, mats=False, plots=True, verbose=0, shfile=DEFAULT_FSL_PATH): """ Wraps command mcflirt. MCFLIRT is an intra-modal motion correction tool designed for use on fMRI time series and based on optimization and registration techniques used in FLIRT, a fully automated robust and accurate tool for linear (affine) inter- and inter-modal brain image registration. Parameters ---------- in_file: str (mandatory) Input serie file path. out_fileroot: str (mandatory) Output serie file path without extension. cost: str(optional, default None) The optimization cost function. Choose the most appropriate option: "mutualinfo", "woods", "corratio", "normcorr", "normmi", "leastsquares". bins: int (optional, default 256) Number of histogram bins. dof: int (optional, default 6) Number of transform degrees of freedom. refvol: int (optional, default None) the reference volume index, default is no_vols/2. reffile: str (optional, default None) use a separate 3d image file as the target for registration. reg_to_mean: bool (optional, default True) If set, register to mean, otherwise to middle volume of the serie. mats: bool (optional, default False) If set save transformation matricies in subdirectory outfilename.mat plot: bool (optional, default True) If set save transformation parameters in file outputfilename.par verbose: int (optional) 0 is least and default. shfile: str (optional, default DEFAULT_FSL_PATH) The FSL configuration batch. Returns ------- func_file: str Output realigned serie. mean_file: str Mean serie tempalte. par_file: str The motion correction transformation parameters. """ # Check the input parameters if not os.path.isfile(in_file): raise ValueError("'{0}' is not a valid input file.".format(in_file)) if cost not in [ "mutualinfo", "woods", "corratio", "normcorr", "normmi", "leastsquares" ]: raise ValueError( "'{0}' is not a valid optimization cost function.".format(cost)) # Define the FSL command cmd = [ "mcflirt", "-in", in_file, "-out", out_fileroot, "-cost", cost, "-bins", str(bins), "-dof", str(dof), "-verbose", str(verbose) ] if refvol is not None: cmd.extend(["-refvol", str(refvol)]) if reffile is not None: cmd.extend(["-reffile", reffile]) if reg_to_mean: cmd.append("-meanvol") if mats: cmd.append("-mats") if plots: cmd.append("-plots") # Call mcflirt fslprocess = FSLWrapper(cmd, shfile=shfile) fslprocess() # Get generated outputs func_files = [ elem for elem in glob.glob(out_fileroot + ".*") if not elem.endswith(".par") and os.path.isfile(elem) ] if len(func_files) != 1: raise ValueError( "Expect only one mcflirt output file, not {0}.".format(func_files)) func_file = func_files[0] if reg_to_mean: mean_file = glob.glob(out_fileroot + "_mean_reg.*")[0] else: im = nibabel.load(func_file) mean_data = numpy.mean(im.get_data(), axis=-1) im_mean = nibabel.Nifti1Image(mean_data, im.affine) mean_file = out_fileroot + "_mean_reg.nii.gz" nibabel.save(im_mean, mean_file) par_file = None if plots: par_file = out_fileroot + ".par" return func_file, mean_file, par_file
def bet2(input_file, output_fileroot, outline=False, mask=False, skull=False, nooutput=False, f=0.5, g=0, radius=None, smooth=None, c=None, threshold=False, mesh=False, shfile=DEFAULT_FSL_PATH): """ Wraps command bet2. Deletes non-brain tissue from an image of the whole head. It can also estimate the inner and outer skull surfaces, and outer scalp surface, if you have good quality T1 and T2 input images. The basic usage is: bet2 <input_fileroot> <output_fileroot> [options] Parameters ---------- input_file: (mandatory) Input image. output_fileroot: (mandatory) Output directory. outline: bool (optional, default False) Generate brain surface outline overlaid onto original image. mask: bool (optional, default False) Generate binary brain mask. skull: bool (optional, default False) Generate approximate skull image. (not as clean as what betsurf generates). nooutput: bool (optional, default False) Don't generate segmented brain image output. f: float (optional, default 0.5) Fractional intensity threshold (0->1). Smaller values give larger brain outline estimates. g: int (optional, default 0) Vertical gradient in fractional intensity threshold (-1->1). Positive values give larger brain outline at bottom, smaller at top. radius: (optional) Head radius (mm not voxels). Initial surface sphere is set to half of this. smooth : float (optional, default 1) Smoothness factor. Values smaller than 1 produce more detailed brain surface, values larger than one produce smoother, less detailed surface. c: (optional) Centre-of-gravity (voxels not mm) of initial mesh surface (x, y, z). threshold: bool (optional, default False) Apply thresholding to segmented brain image and mask. mesh: bool (optional, default False). Generates brain surface as mesh in .vtk format. shfile: (optional, default DEFAULT_FSL_PATH) The FSL configuration batch. Returns ------- output: str the extracted brain volume. mask_file: str the binary mask of the extracted brain volume. mesh_file: str the brain surface as a vtk mesh. outline_file: str the brain surface outline overlaid onto original image. inskull_mask_file, inskull_mesh_file, outskull_mask_file, outskull_mesh_file, outskin_mask_file, outskin_mesh_file, skull_mask_file: str rough skull image. shfile: str (optional, default local path) the path to the FSL 'fsl.sh' configuration file. """ # Check the input parameter if not os.path.isfile(input_file): raise ValueError("'{0}' is not a valid input file.".format(input_file)) # Check that the output directory exists if not os.path.isdir(output_fileroot): os.mkdir(output_fileroot) output_fileroot = os.path.join( output_fileroot, os.path.basename(input_file).split(".")[0] + "_brain") # Define the FSL command cmd = [ "bet", input_file, output_fileroot, "-f", str(f), "-g", str(g), "-R" ] # Set optional arguments if outline: cmd += ["-o"] if mask: cmd += ["-m"] if skull: cmd += ["-s"] if nooutput: cmd += ["-n"] if mesh: cmd += ["-e"] if threshold: cmd += ["-t"] if c is not None: cmd += ["-c", c] if radius is not None: cmd += ["-r", radius] if smooth is not None: cmd += ["-s", smooth] # Call bet2 fslprocess = FSLWrapper(cmd, shfile=shfile) fslprocess() # Check the FSL environment variable if "FSLOUTPUTTYPE" not in fslprocess.environment: raise ValueError("'{0}' variable not declared in FSL " "environ.".format("FSLOUTPUTTYPE")) # Format outputs image_ext = fslprocess.output_ext[fslprocess.environment["FSLOUTPUTTYPE"]] # Create format outputs if outline: outline_file = output_fileroot + "_outline" + image_ext else: outline_file = None if mask: mask_file = output_fileroot + "_mask" + image_ext else: mask_file = None if skull: inskull_mask_file = output_fileroot + "_inskull_mask" + image_ext inskull_mesh_file = output_fileroot + "_inskull_mesh" + image_ext outskull_mask_file = output_fileroot + "_outskull_mask" + image_ext outskull_mesh_file = output_fileroot + "_outskull_mesh" + image_ext outskin_mask_file = output_fileroot + "_outskin_mask" + image_ext outskin_mesh_file = output_fileroot + "_outskin_mesh" + image_ext skull_mask_file = output_fileroot + "_skull_mask" + image_ext else: inskull_mask_file = None inskull_mesh_file = None outskull_mask_file = None outskull_mesh_file = None outskin_mask_file = None outskin_mesh_file = None skull_mask_file = None if nooutput: output = None else: output_fileroot += image_ext output = output_fileroot if mesh: mesh_file = output_fileroot + "_mesh.vtk" else: mesh_file = None return (output, mask_file, mesh_file, outline_file, inskull_mask_file, inskull_mesh_file, outskull_mask_file, outskull_mesh_file, outskin_mask_file, outskin_mesh_file, skull_mask_file)
def fast(input_file, out_fileroot, klass=3, im_type=1, segments=False, bias_field=True, bias_corrected_im=True, probabilities=False, shfile=DEFAULT_FSL_PATH): """ FAST (FMRIB's Automated Segmentation Tool) segments a 3D image of the brain into different tissue types (Grey Matter, White Matter, CSF, etc.), whilst also correcting for spatial intensity variations (also known as bias field or RF inhomogeneities). The underlying method is based on a hidden Markov random field model and an associated Expectation-Maximization algorithm. Usage: fast [options] file(s) Parameters ---------- input_file: str (mandatory) the image to be segmented. out: str (mandatory) output basename. klass: int (optional, default 3) number of tissue-type classes. im_type: int (optional, default 1) type of image 1=T1, 2=T2, 3=PD. segments: bool (optional, default False) outputs a separate binary image for each tissue type. bias_field: bool (optional, default True) output estimated bias field. bias_corrected_im: bool (optional, default True) output bias-corrected image. probabilities: bool (optional, default False) outputs individual probability maps. shfile: str (optional, default local path) the path to the FSL 'fsl.sh' configuration file. Returns ------- tpm: list of str the generated tissue preobaility maps. tsm: list of str the generated tissue segmentation maps. segmentation_file: str the segmented tissues. bias_file: str the bias field. biascorrected_file: str the bias corrected input image. """ # Check input parameters if not os.path.isfile(input_file): raise ValueError("'{0}' is not a valid input file.".format(input_file)) # Define the FSL command bool_params = { "-g": segments, "-b": bias_field, "-B": bias_corrected_im, "-p": probabilities } cmd = ["fast", "-o", out_fileroot, "-n", str(klass), "-t", str(im_type)] for name, value in bool_params.items(): if value: cmd.append(name) cmd.append(input_file) # Call FSL fast fslprocess = FSLWrapper(cmd, shfile=shfile) fslprocess() # Check the FSL environment variable if "FSLOUTPUTTYPE" not in fslprocess.environment: raise ValueError("'{0}' variable not declared in FSL " "environ.".format("FSLOUTPUTTYPE")) # Format outputs image_ext = fslprocess.output_ext[fslprocess.environment["FSLOUTPUTTYPE"]] segmentation_file = out_fileroot + "_seg" + image_ext bias_file = out_fileroot + "_bias" + image_ext if not os.path.isfile(bias_file): bias_file = None biascorrected_file = out_fileroot + "_restore" + image_ext if not os.path.isfile(biascorrected_file): biascorrected_file = None tpm = glob.glob(out_fileroot + "_prob_*") tsm = glob.glob(out_fileroot + "_pve_*") return tpm, tsm, segmentation_file, bias_file, biascorrected_file
def mitk_gibbs_tractogram(outdir, subject_id, dwi, bvals, bvecs, nodif_brain=None, nodif_brain_mask=None, subjects_dir=None, sh_order=4, reg_factor=0.006, nb_iterations=5e8, particle_length=0, particle_width=0, particle_weight=0, start_temperature=0.1, end_temperature=0.001, inex_energy_balance=0, min_fiber_length=20, curvature_threshold=45, tempdir=None, fs_sh=DEFAULT_FREESURFER_PATH, fsl_sh=DEFAULT_FSL_PATH): """ Wrapper to the MITK global tractography tool (Gibbs Tracking). Parameters ---------- outdir: str Directory where to output. subject_id: str Subject id used with FreeSurfer 'recon-all' command. dwi: str Path to the diffusion-weighted images (Nifti required). bvals: str Path to the bvalue list. bvecs: str Path to the list of diffusion-sensitized directions. nodif_brain: str, default None Diffusion brain-only Nifti volume with bvalue ~ 0. If not passed, it is generated automatically by averaging all the b0 volumes of the DWI. nodif_brain_mask: str, default None Path to the Nifti brain binary mask in diffusion. If not passed, it is created with MRtrix 'dwi2mask'. subjects_dir: str or None, default None Path to the FreeSurfer subjects directory. Required if the FreeSurfer environment variable (i.e. $SUBJECTS_DIR) is not set. sh_order: int, default 4 Qball reconstruction spherical harmonics order. reg_factor: float, default Qball reconstruction regularization factor.. nb_iterations: int, default 5E8 Gibbs tracking number of iterations. particle_length: float, default 0 Gibbs tracking particle length, selected automatically if 0. particle_width: float, default 0 Gibbs tracking particle width, selected automatically if 0. particle_weight: float, default 0 Gibbs tracking particle weight, selected automatically if 0. start_temperature: float, default 0.1 Gibbs tracking start temperature. end_temperature: float, default 0.001 Gibbs tracking end temperature. inex_energy_balance: float, default 0 Gibbs tracking weighting between in/ext energies. min_fiber_length: int, default 20 Minimum fiber length in mm. Fibers that are shorter are discarded. curvature_threshold: int, default 45 Maximum fiber curvature in degrees. tempdir: str Path to the directory where temporary directories should be written. It should be a partition with 5+ GB available. fs_sh: str, default NeuroSpin path Path to the Bash script setting the FreeSurfer environment fsl_sh: str, default NeuroSpin path Path to the Bash script setting the FSL environment. Returns ------- mitk_tractogram: str The computed global tractogram in VTK format. """ # ------------------------------------------------------------------------- # STEP 0 - Check arguments # FreeSurfer subjects_dir subjects_dir = get_or_check_freesurfer_subjects_dir(subjects_dir) # Check input paths paths_to_check = [dwi, bvals, bvecs, nodif_brain_mask, fs_sh, fsl_sh] for p in [nodif_brain, nodif_brain_mask]: if p is not None: paths_to_check.append(p) for p in paths_to_check: if not os.path.exists(p): raise ValueError("File or directory does not exist: %s" % p) # Create <outdir> and/or <tempdir> if not existing for directory in [outdir, tempdir]: if not os.path.isdir(directory): os.makedirs(directory) # ------------------------------------------------------------------------- # STEP 1 - Compute DWI to T1 transformation and project the T1 # to the diffusion space without resampling. # If user has not provided a 'nodif_brain_mask', compute one with # MRtrix 'dwi2mask' if nodif_brain_mask is None: nodif_brain_mask = os.path.join(outdir, "nodif_brain_mask.nii.gz") cmd_1a = ["dwi2mask", dwi, nodif_brain_mask, "-fslgrad", bvecs, bvals] subprocess.check_call(cmd_1a) # If user has not provided a 'nodif_brain', apply 'nodif_brain_mask' to # mean b=0 volume if nodif_brain is None: # Extract b=0 volumes and compute mean b=0 volume b0s = os.path.join(outdir, "b0s.nii.gz") mean_b0 = os.path.join(outdir, "mean_b0.nii.gz") mrtrix_extract_b0s_and_mean_b0(dwi=dwi, b0s=b0s, mean_b0=mean_b0, bvals=bvals, bvecs=bvecs, nb_threads=1) # Apply nodif_brain_mask to dwi nodif_brain = os.path.join(outdir, "nodif_brain.nii.gz") cmd_1b = ["mri_mask", mean_b0, nodif_brain_mask, nodif_brain] FSWrapper(cmd_1b, shfile=fs_sh)() # Register nodif_brain to FreeSurfer T1 t1_brain_to_dif, dif2anat_dat, _ = freesurfer_bbregister_t1todif( outdir=outdir, subject_id=subject_id, nodif_brain=nodif_brain, subjects_dir=subjects_dir, fs_sh=fs_sh, fsl_sh=fsl_sh) # ------------------------------------------------------------------------- # STEP 2 - Apply brain mask to DWI before Qball reconstruction dwi_brain = os.path.join(outdir, "dwi_brain.nii.gz") cmd_4 = ["fslmaths", dwi, "-mas", nodif_brain_mask, dwi_brain] FSLWrapper(cmd_4, shfile=fsl_sh)() # MITK requires the Nifti to have an .fslgz extension and the bvals/bvecs # to have the same name with .bvals/.bvecs extension dwi_brain_fslgz = os.path.join(outdir, "dwi_brain.fslgz") shutil.copyfile(dwi_brain, dwi_brain_fslgz) shutil.copyfile(bvals, "%s.bvals" % dwi_brain_fslgz) shutil.copyfile(bvecs, "%s.bvecs" % dwi_brain_fslgz) # ------------------------------------------------------------------------- # STEP 3 - Qball reconstruction qball_coefs = os.path.join(outdir, "sphericalHarmonics_CSA_Qball.qbi") cmd_5 = [ "MitkQballReconstruction.sh", "-i", dwi_brain_fslgz, "-o", qball_coefs, "-sh", "%i" % sh_order, "-r", "%f" % reg_factor, "-csa", "--mrtrix" ] # TODO: create MITK wrapper with LD_LIBRARY_PATH and QT_PLUGIN_PATH subprocess.check_call(cmd_5) # ------------------------------------------------------------------------- # STEP 4 - Create white matter probability map with FSL Fast # Create directory for temporary files fast_tempdir = tempfile.mkdtemp(prefix="FSL_fast_", dir=tempdir) base_outpath = os.path.join(fast_tempdir, "brain") cmd_6 = ["fast", "-o", base_outpath, t1_brain_to_dif] FSLWrapper(cmd_6, shfile=fsl_sh)() # Save the white matter probability map wm_prob_map = os.path.join(outdir, "wm_prob_map.nii.gz") shutil.copyfile(base_outpath + "_pve_2.nii.gz", wm_prob_map) # Clean temporary directory shutil.rmtree(fast_tempdir) # ------------------------------------------------------------------------- # STEP 5 - Gibbs tracking (global tractography) # Create XML parameter file root = ElementTree.Element("global_tracking_parameter_file") root.set("version", "1.0") attributes = { "iterations": "%i" % nb_iterations, "particle_length": "%f" % particle_length, "particle_width": "%f" % particle_width, "particle_weight": "%f" % particle_weight, "temp_start": "%f" % start_temperature, "temp_end": "%f" % end_temperature, "inexbalance": "%f" % inex_energy_balance, "fiber_length": "%i" % min_fiber_length, "curvature_threshold": "%i" % curvature_threshold } ElementTree.SubElement(root, "parameter_set", attrib=attributes) tree = ElementTree.ElementTree(element=root) path_xml = os.path.join(outdir, "parameters.gtp") tree.write(path_xml) # Run tractography mitk_tractogram = os.path.join(outdir, "fibers.fib") cmd_7 = [ "MitkGibbsTracking.sh", "-i", qball_coefs, "-p", path_xml, "-m", wm_prob_map, "-o", mitk_tractogram, "-s", "MRtrix" ] subprocess.check_call(cmd_7) return mitk_tractogram
def deface(input_files, outdir, matlab_mcr, reference_file=None, mask_ears=True, verbose=0, rm_workspace=False, fsl_sh=DEFAULT_FSL_PATH): """ Deface MRI head images using the Marcus, D. 'mask_face' command. This code is standalone and does not need matlab licence. You just need MathWorks MCR software installed on your computer. Parameters ---------- input_files: list of str Input MRI head images to be defaced. outdir: str The output folder. matlab_mcr:str The MATLAB MCR directory for standalone applications. reference_file: str (optional, default None) The image that must be used as reference if more than one image have been supplied as input. mask_ears: bool (optional, default True) If activated, masks ears. verbose: int (optional, default 0) The verbosity level. rm_workspace: bool (optional, default False) If activated, keep the defacing workspace (require more disk space). fsl_sh: str (optional, default DEFAULT_FSL_PATH) The FSL configuration file. Returns ------- deface_files: list of str The defaced input MRI head images. snap_files: list of str The corresponding snaps that can be used to check the defacing result. """ # Check input parameters outdir = os.path.abspath(outdir) if len(input_files) == 0: raise ValueError("You must specify at least one image.") elif len(input_files) > 1: if reference_file is None or reference_file not in input_files: raise ValueError("If more than one image is specified, you must " "also specify one of them as reference. The " "reference image will be used for spatial " "co-registration with an atlas, and others will " "use the reference facial mask.") # Convert in analyse format pair_files = [] basenames = [] for fp in input_files: fp = os.path.abspath(fp) basenames.append(os.path.basename(fp).split(".")[0]) pair_filepath = os.path.join(outdir, "{0}.img".format(basenames[-1])) im = nibabel.load(fp) pair_im = nibabel.Nifti1Pair(im.get_data(), im.affine) pair_im.to_filename(pair_filepath) pair_files.append(pair_filepath) # Define the command cmd = ["mask_face", ",".join([fp[:-len(".img")] for fp in pair_files])] cmd += ["-a"] cmd += ["-v", "{0}".format(verbose)] if reference_file is not None: ref_index = input_files.index(reference_file) cmd += ["-r", pair_files[ref_index]] if mask_ears: cmd += ["-e", "1"] # Call defacing deface_env = os.environ deface_env["MASKFACE_MCR"] = matlab_mcr wrapper = FSLWrapper(cmd, shfile=fsl_sh, env=deface_env) wrapper(cwdir=outdir) # Deal with outputs: nifti + move deface_files = [] snap_files = [] wdir = os.path.join(outdir, "maskface") for fp, basename in zip(pair_files, basenames): deface_pair_file = os.path.join( wdir, "{0}_full_normfilter.hdr".format(basename)) nii_file = os.path.join(outdir, "{0}_full_normfilter.nii.gz".format(basename)) im = nibabel.load(deface_pair_file) nii_im = nibabel.Nifti1Image(im.get_data(), im.affine) nibabel.save(nii_im, nii_file) del im, nii_im deface_files.append(nii_file) snap_files.append( os.path.join(outdir, "{0}_normfilter.png".format(basename))) shutil.copy2(os.path.join(wdir, "{0}_normfilter.png".format(basename)), snap_files[-1]) os.remove(fp) os.remove(fp.replace(".img", ".hdr")) if rm_workspace: shutil.rmtree(wdir) else: shutil.move(wdir, os.path.join(outdir, "workspace")) return deface_files, snap_files
def topup( b0s, phase_enc_dirs, readout_time, outroot, fsl_sh=DEFAULT_FSL_PATH): """ Wraps FSL topup tool to estimate the susceptibility induced off-resonance field. Parameters ---------- b0s: list of str path to b0 file acquired in opposite phase enc. directions. phase_enc_dirs: list of str the phase enc. directions. readout_time: float the readout time. outroot: str fileroot name for output. fsl_sh: str, optional default 'DEFAULT_FSL_PATH' path to fsl setup sh file. Returns ------- fieldmap: str path to the fieldmap in Hz. corrected_b0s: str path to the unwarped b0 images. mean_corrected_b0s: str path to the mean unwarped b0 images. """ # Write topup acqp # https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/eddy/UsersGuide if len(b0s) != len(phase_enc_dirs): raise ValueError("Please specify properly the topup input data.") acqp_file = os.path.join(outroot, "acqp.txt") data = [] affine = None with open(acqp_file, "wt") as open_file: for enc_dir, path in zip(phase_enc_dirs, b0s): im = nibabel.load(path) if affine is None: affine = im.affine else: assert numpy.allclose(affine, im.affine) arr = im.get_data() for cnt, size in enumerate(arr.shape[:3]): if size % 2 == 1: print("[warn] reducing TOPUP B0 image size.") arr = numpy.delete(arr, -1, axis=cnt) if arr.ndim == 3: arr.shape += (1, ) data.append(arr) nvol = arr.shape[-1] if enc_dir == "i": row = "1 0 0 {0}".format(readout_time) elif enc_dir == "i-": row = "-1 0 0 {0}".format(readout_time) elif enc_dir == "j": row = "0 1 0 {0}".format(readout_time) elif enc_dir == "j-": row = "0 -1 0 {0}".format(readout_time) else: raise ValueError("Unknown encode phase direction : " "{0}...".format(enc_dir)) for indx in range(nvol): open_file.write(row + "\n") concatenated_b0s_file = os.path.join(outroot, "concatenated_b0s.nii.gz") concatenated_b0s = numpy.concatenate(data, axis=-1) concatenated_b0s_im = nibabel.Nifti1Image(concatenated_b0s, affine) nibabel.save(concatenated_b0s_im, concatenated_b0s_file) # The topup command fieldmap = os.path.join(outroot, "fieldmap.nii.gz") corrected_b0s = os.path.join(outroot, "unwarped_b0s.nii.gz") cmd = [ "topup", "--imain={0}".format(concatenated_b0s_file), "--datain={0}".format(acqp_file), "--config=b02b0.cnf", "--out={0}".format(os.path.join(outroot, "topup")), "--fout={0}".format(fieldmap), "--iout={0}".format(corrected_b0s), "-v"] fslprocess = FSLWrapper(cmd, shfile=fsl_sh) fslprocess() # Average b0s mean_corrected_b0s = os.path.join(outroot, "mean_unwarped_b0s.nii.gz") cmd = [ "fslmaths", corrected_b0s, "-Tmean", mean_corrected_b0s] fslprocess = FSLWrapper(cmd, shfile=fsl_sh) fslprocess() return fieldmap, corrected_b0s, mean_corrected_b0s