Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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()
Ejemplo n.º 5
0
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
Ejemplo n.º 6
0
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()
Ejemplo n.º 7
0
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()
Ejemplo n.º 8
0
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
Ejemplo n.º 9
0
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
Ejemplo n.º 10
0
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
Ejemplo n.º 11
0
    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"]
Ejemplo n.º 12
0
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
Ejemplo n.º 13
0
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()
Ejemplo n.º 14
0
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()
Ejemplo n.º 15
0
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
Ejemplo n.º 16
0
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)
Ejemplo n.º 17
0
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"))
Ejemplo n.º 18
0
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
Ejemplo n.º 19
0
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)
Ejemplo n.º 20
0
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
Ejemplo n.º 21
0
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]
Ejemplo n.º 22
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
Ejemplo n.º 23
0
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
Ejemplo n.º 24
0
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
Ejemplo n.º 25
0
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
Ejemplo n.º 26
0
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)
Ejemplo n.º 27
0
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
Ejemplo n.º 28
0
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
Ejemplo n.º 29
0
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
Ejemplo n.º 30
0
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