예제 #1
0
def do_subject_preproc(subject_id,
                       output_dir,
                       func,
                       anat,
                       do_bet=True,
                       do_mc=True,
                       do_coreg=True,
                       do_normalize=True,
                       cmd_prefix="fsl5.0-",
                       **kwargs
                       ):
    """
    Preprocesses subject data using FSL.

    Parameters
    ----------

    """

    output = {'func': func,
              'anat': anat
              }

    # output dir
    subject_output_dir = os.path.join(output_dir, subject_id)
    if not os.path.exists(subject_output_dir):
        os.makedirs(subject_output_dir)

    # prepare for smart-caching
    cache_dir = os.path.join(output_dir, "cache_dir")
    if not os.path.exists(cache_dir):
        os.makedirs(cache_dir)

    nipype_mem = NipypeMemory(base_dir=cache_dir)
    joblib_mem = JoblibMemory(cache_dir, verbose=100)

    # sanitize input files
    if not isinstance(output['func'], basestring):
        output['func'] = joblib_mem.cache(do_fsl_merge)(
            func, subject_output_dir, output_prefix='Merged',
            cmd_prefix=cmd_prefix)

    ######################
    #  Brain Extraction
    ######################
    if do_bet:
        if not fsl.BET._cmd.startswith("fsl"):
            fsl.BET._cmd = cmd_prefix + fsl.BET._cmd

        bet = nipype_mem.cache(fsl.BET)
        bet_results = bet(in_file=output['anat'],
                          )

        output['anat'] = bet_results.outputs.out_file

    #######################
    #  Motion correction
    #######################
    if do_mc:
        if not fsl.MCFLIRT._cmd.startswith("fsl"):
            fsl.MCFLIRT._cmd = cmd_prefix + fsl.MCFLIRT._cmd

        mcflirt = nipype_mem.cache(fsl.MCFLIRT)
        mcflirt_results = mcflirt(in_file=output['func'],
                                  cost='mutualinfo',
                                  save_mats=True,  # save mc matrices
                                  save_plots=True  # save mc params
                                  )

        output['motion_parameters'] = mcflirt_results.outputs.par_file
        output['motion_matrices'] = mcflirt_results.outputs.mat_file
        output['func'] = mcflirt_results.outputs.out_file

    ###################
    # Coregistration
    ###################
    if do_coreg:
        if not fsl.FLIRT._cmd.startswith("fsl"):
            fsl.FLIRT._cmd = cmd_prefix + fsl.FLIRT._cmd

        flirt1 = nipype_mem.cache(fsl.FLIRT)
        flirt1_results = flirt1(in_file=output['func'],
                                reference=output['anat']
                                )

        if not do_normalize:
            output['func'] = flirt1_results.outputs.out_file

    ##########################
    # Spatial normalization
    ##########################
    if do_normalize:
        if not fsl.FLIRT._cmd.startswith("fsl"):
            fsl.FLIRT._cmd = cmd_prefix + fsl.FLIRT._cmd

        # T1 normalization
        flirt2 = nipype_mem.cache(fsl.FLIRT)
        flirt2_results = flirt2(in_file=output['anat'],
                                reference=FSL_T1_TEMPLATE)

        output['anat'] = flirt2_results.outputs.out_file

        # concatenate 'func -> anat' and 'anat -> standard space'
        # transformation matrices to obtaun 'func -> standard space'
        # transformation matrix
        if do_coreg:
            if not fsl.ConvertXFM._cmd.startswith("fsl"):
                fsl.ConvertXFM._cmd = cmd_prefix + fsl.ConvertXFM._cmd

                convertxfm = nipype_mem.cache(fsl.ConvertXFM)
                convertxfm_results = convertxfm(
                    in_file=flirt1_results.outputs.out_matrix_file,
                    in_file2=flirt2_results.outputs.out_matrix_file,
                    concat_xfm=True
                    )

        # warp func data into standard space by applying
        # 'func -> standard space' transformation matrix
        if not fsl.ApplyXfm._cmd.startswith("fsl"):
            fsl.ApplyXfm._cmd = cmd_prefix + fsl.ApplyXfm._cmd

        applyxfm = nipype_mem.cache(fsl.ApplyXfm)
        applyxfm_results = applyxfm(
            in_file=output['func'],
            in_matrix_file=convertxfm_results.outputs.out_file,
            reference=FSL_T1_TEMPLATE
            )

        output['func'] = applyxfm_results.outputs.out_file

    return output
def run_suject_level1_glm(
        subject_data,
        readout_time=.01392,  # seconds
        tr=.72,
        dc=True,
        hrf_model="Canonical with Derivative",
        drift_model="Cosine",
        hfcut=100,
        regress_motion=True,
        slicer='ortho',
        cut_coords=None,
        threshold=3.,
        cluster_th=15,
        normalize=True,
        fwhm=0.,
        protocol="MOTOR",
        func_write_voxel_sizes=None,
        anat_write_voxel_sizes=None,
        **other_preproc_kwargs):
    """
    Function to do preproc + analysis for a single HCP subject (task fMRI)

    """

    add_regs_files = None
    n_motion_regressions = 6
    subject_data.n_sessions = 2

    subject_data.tmp_output_dir = os.path.join(subject_data.output_dir, "tmp")
    if not os.path.exists(subject_data.tmp_output_dir):
        os.makedirs(subject_data.tmp_output_dir)

    if not os.path.exists(subject_data.output_dir):
        os.makedirs(subject_data.output_dir)

    mem = Memory(os.path.join(subject_data.output_dir, "cache_dir"),
                 verbose=100)

    # glob design files (.fsf)
    subject_data.design_files = [
        os.path.join(subject_data.data_dir,
                     ("MNINonLinear/Results/tfMRI_%s_%s/"
                      "tfMRI_%s_%s_hp200_s4_level1.fsf") %
                     (protocol, direction, protocol, direction))
        for direction in ['LR', 'RL']
    ]

    assert len(subject_data.design_files) == 2
    for df in subject_data.design_files:
        if not os.path.isfile(df):
            return

    if 0x0:
        subject_data = _do_fmri_distortion_correction(
            subject_data,
            dc=dc,
            fwhm=fwhm,
            readout_time=readout_time,
            **other_preproc_kwargs)

    # chronometry
    stats_start_time = pretty_time()

    # merged lists
    paradigms = []
    frametimes_list = []
    design_matrices = []
    # fmri_files = []
    n_scans = []
    # for direction, direction_index in zip(['LR', 'RL'], xrange(2)):
    for sess in xrange(subject_data.n_sessions):
        direction = ['LR', 'RL'][sess]
        # glob the design file
        # design_file = os.path.join(# _subject_data_dir, "tfMRI_%s_%s" % (
        # protocol, direction),
        design_file = subject_data.design_files[sess]
        #                    "tfMRI_%s_%s_hp200_s4_level1.fsf" % (
        # protocol, direction))
        if not os.path.isfile(design_file):
            print "Can't find design file %s; skipping subject %s" % (
                design_file, subject_data.subject_id)
            return

        # read the experimental setup
        print "Reading experimental setup from %s ..." % design_file
        fsl_condition_ids, timing_files, fsl_contrast_ids, contrast_values = \
            read_fsl_design_file(design_file)
        print "... done.\r\n"

        # fix timing filenames
        timing_files = [
            tf.replace("EVs", "tfMRI_%s_%s/EVs" % (protocol, direction))
            for tf in timing_files
        ]

        # make design matrix
        print "Constructing design matrix for direction %s ..." % direction
        _n_scans = nibabel.load(subject_data.func[sess]).shape[-1]
        n_scans.append(_n_scans)
        add_regs_file = add_regs_files[
            sess] if not add_regs_files is None else None
        design_matrix, paradigm, frametimes = make_dmtx_from_timing_files(
            timing_files,
            fsl_condition_ids,
            n_scans=_n_scans,
            tr=tr,
            hrf_model=hrf_model,
            drift_model=drift_model,
            hfcut=hfcut,
            add_regs_file=add_regs_file,
            add_reg_names=[
                'Translation along x axis', 'Translation along yaxis',
                'Translation along z axis', 'Rotation along x axis',
                'Rotation along y axis', 'Rotation along z axis',
                'Differential Translation along x axis',
                'Differential Translation along yaxis',
                'Differential Translation along z axis',
                'Differential Rotation along x axis',
                'Differential Rotation along y axis',
                'Differential Rotation along z axis'
            ][:n_motion_regressions] if not add_regs_files is None else None,
        )

        print "... done."
        paradigms.append(paradigm)
        frametimes_list.append(frametimes)
        design_matrices.append(design_matrix)

        # convert contrasts to dict
        contrasts = dict((
            contrast_id,
            # append zeros to end of contrast to match design
            np.hstack((
                contrast_value,
                np.zeros(len(design_matrix.names) - len(contrast_value)))))
                         for contrast_id, contrast_value in zip(
                             fsl_contrast_ids, contrast_values))

        # more interesting contrasts
        if protocol == 'MOTOR':
            contrasts['RH-LH'] = contrasts['RH'] - contrasts['LH']
            contrasts['LH-RH'] = -contrasts['RH-LH']
            contrasts['RF-LF'] = contrasts['RF'] - contrasts['LF']
            contrasts['LF-RF'] = -contrasts['RF-LF']
            contrasts['H'] = contrasts['RH'] + contrasts['LH']
            contrasts['F'] = contrasts['RF'] + contrasts['LF']
            contrasts['H-F'] = contrasts['RH'] + contrasts['LH'] - (
                contrasts['RF'] - contrasts['LF'])
            contrasts['F-H'] = -contrasts['H-F']

        contrasts = dict((k, v) for k, v in contrasts.iteritems() if "-" in k)

    # replicate contrasts across sessions
    contrasts = dict((cid, [cval] * 2) for cid, cval in contrasts.iteritems())

    cache_dir = cache_dir = os.path.join(subject_data.output_dir, 'cache_dir')
    if not os.path.exists(cache_dir):
        os.makedirs(cache_dir)
    nipype_mem = NipypeMemory(base_dir=cache_dir)

    if 0x0:
        if np.sum(fwhm) > 0.:
            subject_data.func = nipype_mem.cache(spm.Smooth)(
                in_files=subject_data.func,
                fwhm=fwhm,
                ignore_exception=False,
            ).outputs.smoothed_files

    # fit GLM
    def tortoise(*args):
        print args
        print(
            'Fitting a "Fixed Effect" GLM for merging LR and RL '
            'phase-encoding directions for subject %s ...' %
            (subject_data.subject_id))
        fmri_glm = FMRILinearModel(
            subject_data.func,
            [design_matrix.matrix for design_matrix in design_matrices],
            mask='compute')
        fmri_glm.fit(do_scaling=True, model='ar1')
        print "... done.\r\n"

        # save computed mask
        mask_path = os.path.join(subject_data.output_dir, "mask.nii")
        print "Saving mask image to %s ..." % mask_path
        nibabel.save(fmri_glm.mask, mask_path)
        print "... done.\r\n"

        z_maps = {}
        effects_maps = {}
        map_dirs = {}
        try:
            for contrast_id, contrast_val in contrasts.iteritems():
                print "\tcontrast id: %s" % contrast_id
                z_map, eff_map = fmri_glm.contrast(contrast_val,
                                                   con_id=contrast_id,
                                                   output_z=True,
                                                   output_effects=True)

                # store stat maps to disk
                for map_type, out_map in zip(['z', 'effects'],
                                             [z_map, eff_map]):
                    map_dir = os.path.join(subject_data.output_dir,
                                           '%s_maps' % map_type)
                    map_dirs[map_type] = map_dir
                    if not os.path.exists(map_dir):
                        os.makedirs(map_dir)
                    map_path = os.path.join(
                        map_dir, '%s_%s.nii' % (map_type, contrast_id))
                    print "\t\tWriting %s ..." % map_path

                    nibabel.save(out_map, map_path)

                    # collect zmaps for contrasts we're interested in
                    if map_type == 'z':
                        z_maps[contrast_id] = map_path

                    if map_type == 'effects':
                        effects_maps[contrast_id] = map_path

            return effects_maps, z_maps, mask_path, map_dirs
        except:
            return None

    # compute native-space maps and mask
    stuff = mem.cache(tortoise)(subject_data.func, subject_data.anat)
    if stuff is None:
        return None
    effects_maps, z_maps, mask_path, map_dirs = stuff

    # remove repeated contrasts
    contrasts = dict((cid, cval[0]) for cid, cval in contrasts.iteritems())
    import json
    json.dump(
        dict((k, list(v)) for k, v in contrasts.iteritems()),
        open(os.path.join(subject_data.tmp_output_dir, "contrasts.json"), "w"))
    subject_data.contrasts = contrasts

    if normalize:
        assert hasattr(subject_data, "parameter_file")

        subject_data.native_effects_maps = effects_maps
        subject_data.native_z_maps = z_maps
        subject_data.native_mask_path = mask_path

        # warp effects maps and mask from native to standard space (MNI)
        apply_to_files = [
            v for _, v in subject_data.native_effects_maps.iteritems()
        ] + [subject_data.native_mask_path]
        tmp = nipype_mem.cache(spm.Normalize)(
            parameter_file=getattr(subject_data, "parameter_file"),
            apply_to_files=apply_to_files,
            write_bounding_box=[[-78, -112, -50], [78, 76, 85]],
            write_voxel_sizes=func_write_voxel_sizes,
            write_wrap=[0, 0, 0],
            write_interp=1,
            jobtype='write',
            ignore_exception=False,
        ).outputs.normalized_files

        subject_data.mask = hard_link(tmp[-1], subject_data.output_dir)
        subject_data.effects_maps = dict(
            zip(effects_maps.keys(), hard_link(tmp[:-1], map_dirs["effects"])))

        # warp anat image
        subject_data.anat = hard_link(
            nipype_mem.cache(spm.Normalize)(
                parameter_file=getattr(subject_data, "parameter_file"),
                apply_to_files=subject_data.anat,
                write_bounding_box=[[-78, -112, -50], [78, 76, 85]],
                write_voxel_sizes=anat_write_voxel_sizes,
                write_wrap=[0, 0, 0],
                write_interp=1,
                jobtype='write',
                ignore_exception=False,
            ).outputs.normalized_files, subject_data.anat_output_dir)
    else:
        subject_data.mask = mask_path
        subject_data.effects_maps = effects_maps
        subject_data.z_maps = z_maps

    return subject_data
예제 #3
0
def preproc(funcfile, anatfile, sid, outdir, repetitiontime, template, jipdir,
            erase, resample, interleaved, sliceorder, realign_dof,
            realign_to_vol, warp, warp_njobs, warp_index, warp_file,
            warp_restrict, delta_te, dwell_time, manufacturer, blip_files,
            blip_enc_dirs, unwarp_direction, phase_file, magnitude_file,
            anatorient, funcorient, kernel_size, fslconfig, normalization_trf,
            coregistration_trf, recon1, recon2, auto, verbose):
    """ fMRI preprocessings using FSL, SPM, JIP, and ANTS.
    """
    # TODO: remove when all controls available in pypipe
    if not isinstance(erase, bool):
        erase = eval(erase)
        resample = eval(resample)
        interleaved = eval(interleaved)
        realign_to_vol = eval(realign_to_vol)
        warp = eval(warp)
        recon1 = eval(recon1)
        recon2 = eval(recon2)
        auto = eval(auto)
        warp_restrict = eval(warp_restrict)
        blip_files = None if blip_files == "" else eval(blip_files)
        blip_enc_dirs = eval(blip_enc_dirs)

    # Read input parameters
    funcfile = os.path.abspath(funcfile)
    anatfile = os.path.abspath(anatfile)
    template = os.path.abspath(template)
    jipdir = os.path.abspath(jipdir)
    realign_to_mean = not realign_to_vol
    subjdir = os.path.join(os.path.abspath(outdir), sid)
    cachedir = os.path.join(subjdir, "cachedir")
    outputs = {}
    if erase and os.path.isdir(subjdir):
        shutil.rmtree(subjdir)
    if not os.path.isdir(cachedir):
        os.makedirs(cachedir)
    nipype_memory = NipypeMemory(cachedir)
    joblib_memory = JoblibMemory(cachedir, verbose=verbose)

    def display_outputs(outputs, verbose, **kwargs):
        """ Simple function to display/store step outputs.
        """
        if verbose > 0:
            print("-" * 50)
            for key, val in kwargs.items():
                print("{0}: {1}".format(key, val))
            print("-" * 50)
        outputs.update(kwargs)

    # Check input parameters
    template_axes = guess_orientation(template)
    if template_axes != "RAS":
        raise ValueError("The template orientation must be 'RAS', '{0}' "
                         "found.".format(template_axes))
    check_jip_install(jipdir)
    if sliceorder not in ("ascending", "descending"):
        raise ValueError("Supported slice order are: ascending & descending.")

    # Slice timing
    fslenv = environment(fslconfig)
    if (fslenv["FSLDIR"] != os.environ.get("FSLDIR", "")):
        os.environ = concat_environment(os.environ, fslenv)
    st_dir = os.path.join(subjdir, STEPS["slice_timing"])
    if not os.path.isdir(st_dir):
        os.mkdir(st_dir)
    fsl.FSLCommand.set_default_output_type('NIFTI_GZ')
    interface = nipype_memory.cache(fsl.SliceTimer)
    returncode = interface(
        in_file=funcfile,
        interleaved=interleaved,
        slice_direction=3,
        time_repetition=repetitiontime,
        index_dir=False if sliceorder == "ascending" else True,
        out_file=os.path.join(
            st_dir,
            os.path.basename(funcfile).split(".")[0] + ".nii.gz"))
    st_outputs = returncode.outputs.get()
    slice_time_corrected_file = st_outputs["slice_time_corrected_file"]
    display_outputs(outputs,
                    verbose,
                    slice_time_corrected_file=slice_time_corrected_file)

    # B0 inhomogeneities: topup or fugue or None + motion induced
    if warp:
        warp_dir = os.path.join(subjdir, STEPS["warp"])
        if not os.path.isdir(warp_dir):
            os.mkdir(warp_dir)
        if blip_files is not None:
            interface = joblib_memory.cache(topup)
            fieldmap_hz_file, unwarped_epi_file = interface(
                blip_up_file=blip_files[0],
                blip_down_file=blip_files[1],
                blip_up_phase_enc_dir=blip_enc_dirs[0],
                blip_down_phase_enc_dir=blip_enc_dirs[1],
                apply_to=slice_time_corrected_file,
                unwarp_direction=unwarp_direction,
                dwell_time=dwell_time,
                outdir=warp_dir,
                fsl_sh=fslconfig)
        elif phase_file is not None:
            interface = joblib_memory.cache(fugue)
            magnitude_brain_mask_file, vsm_file, unwarped_epi_file = interface(
                epi_file=slice_time_corrected_file,
                phase_file=phase_file,
                magnitude_file=magnitude_file,
                delta_te=delta_te,
                dwell_time=dwell_time,
                unwarp_direction=unwarp_direction,
                manufacturer=manufacturer,
                outdir=warp_dir,
                fsl_sh=fslconfig,
                verbose=verbose)
        else:
            unwarped_epi_file = slice_time_corrected_file
        interface = joblib_memory.cache(timeserie_to_reference)
        b0_corrected_file = interface(tfile=unwarped_epi_file,
                                      rindex=warp_index,
                                      restrict_deformation=warp_restrict,
                                      rfile=warp_file,
                                      outdir=warp_dir,
                                      njobs=warp_njobs,
                                      clean_tmp=True)
    else:
        b0_corrected_file = slice_time_corrected_file
    display_outputs(outputs, verbose, b0_corrected_file=b0_corrected_file)

    # Reorient images not in RAS coordinate system and
    # reorient images to match the orientation of the standard MNI152 template.
    reorient_dir = os.path.join(subjdir, STEPS["reorient"])
    if not os.path.isdir(reorient_dir):
        os.mkdir(reorient_dir)
    reoriented_funcfile = b0_corrected_file
    reoriented_anatfile = anatfile
    interface = joblib_memory.cache(reorient_image)
    if funcorient != "RAS":
        reoriented_funcfile = interface(b0_corrected_file,
                                        axes=funcorient,
                                        prefix="o",
                                        output_directory=reorient_dir)
    if anatorient != "RAS":
        reoriented_anatfile = interface(anatfile,
                                        axes=anatorient,
                                        prefix="o",
                                        output_directory=reorient_dir)
    standard_funcfile = os.path.join(
        reorient_dir,
        "d" + os.path.basename(reoriented_funcfile).split(".")[0])
    standard_anatfile = os.path.join(
        reorient_dir,
        "d" + os.path.basename(reoriented_anatfile).split(".")[0])
    interface = joblib_memory.cache(fslreorient2std)
    standard_funcfile = interface(reoriented_funcfile,
                                  standard_funcfile,
                                  fslconfig=fslconfig)
    standard_anatfile = interface(reoriented_anatfile,
                                  standard_anatfile,
                                  fslconfig=fslconfig)
    display_outputs(outputs,
                    verbose,
                    standard_funcfile=standard_funcfile,
                    standard_anatfile=standard_anatfile)

    # Downsample template
    if resample:
        template = resample_image(source_file=template,
                                  target_file=standard_anatfile,
                                  out_file=os.path.join(
                                      subjdir, "template.nii.gz"),
                                  fslconfig=fslconfig)

    # Realign
    realign_dir = os.path.join(subjdir, STEPS["realign"])
    if not os.path.isdir(realign_dir):
        os.mkdir(realign_dir)
    realign_func_rootfile = os.path.join(
        realign_dir, "r" + os.path.basename(standard_funcfile).split(".")[0])
    interface = joblib_memory.cache(mcflirt)
    realign_funcfile, realign_func_meanfile, realign_func_parfile = interface(
        in_file=standard_funcfile,
        out_fileroot=realign_func_rootfile,
        cost="normcorr",
        bins=256,
        dof=realign_dof,
        refvol=warp_index,
        reffile=warp_file,
        reg_to_mean=realign_to_mean,
        mats=True,
        plots=True,
        verbose=verbose,
        shfile=fslconfig)
    display_outputs(outputs,
                    verbose,
                    realign_funcfile=realign_funcfile,
                    realign_func_meanfile=realign_func_meanfile)

    # Early stop detected
    if recon1:
        print(
            "[warn] User requested a processing early stop. Remove the 'recon1' "
            "option to resume.")
        return outputs

    # Normalization.
    normalization_dir = os.path.join(subjdir, STEPS["normalization"])
    if not os.path.isdir(normalization_dir):
        os.mkdir(normalization_dir)
    if normalization_trf is not None:
        shutil.copyfile(normalization_trf,
                        os.path.join(normalization_dir, "align.com"))
    interface = joblib_memory.cache(jip_align)
    (register_anatfile, register_anat_maskfile, native_anat_maskfile,
     align_normfile) = interface(source_file=standard_anatfile,
                                 target_file=template,
                                 outdir=normalization_dir,
                                 jipdir=jipdir,
                                 prefix="w",
                                 auto=auto,
                                 non_linear=True,
                                 fslconfig=fslconfig)
    display_outputs(outputs,
                    verbose,
                    register_anatfile=register_anatfile,
                    register_anat_maskfile=register_anat_maskfile,
                    native_anat_maskfile=native_anat_maskfile,
                    align_normfile=align_normfile)

    # Tissues segmentation and spatial intensity variations correction.
    inhomogeneities_dir = os.path.join(subjdir, STEPS["inhomogeneities"])
    if not os.path.isdir(inhomogeneities_dir):
        os.mkdir(inhomogeneities_dir)
    biascorrected_anatfile = os.path.join(
        inhomogeneities_dir, "n4_" + os.path.basename(native_anat_maskfile))
    bias_anatfile = os.path.join(
        inhomogeneities_dir,
        "n4field_" + os.path.basename(native_anat_maskfile))
    n4 = ants.N4BiasFieldCorrection()
    interface = nipype_memory.cache(ants.N4BiasFieldCorrection)
    returncode = interface(dimension=3,
                           input_image=native_anat_maskfile,
                           bspline_fitting_distance=200,
                           shrink_factor=2,
                           n_iterations=[50, 50, 40, 30],
                           convergence_threshold=1e-6,
                           output_image=biascorrected_anatfile,
                           bias_image=bias_anatfile)
    n4_outputs = returncode.outputs.get()
    display_outputs(outputs,
                    verbose,
                    bias_anatfile=bias_anatfile,
                    biascorrected_anatfile=biascorrected_anatfile)

    # Coregistration.
    coregistration_dir = os.path.join(subjdir, STEPS["coregistration"])
    if not os.path.isdir(coregistration_dir):
        os.mkdir(coregistration_dir)
    if coregistration_trf is not None:
        shutil.copy(coregistration_trf, coregistration_dir)
    interface = joblib_memory.cache(jip_align)
    (register_func_meanfile, register_func_mean_maskfile,
     native_func_mean_maskfile,
     align_coregfile) = interface(source_file=realign_func_meanfile,
                                  target_file=biascorrected_anatfile,
                                  outdir=coregistration_dir,
                                  jipdir=jipdir,
                                  prefix="w",
                                  auto=auto,
                                  non_linear=False,
                                  fslconfig=fslconfig)
    display_outputs(outputs,
                    verbose,
                    register_func_meanfile=register_func_meanfile,
                    register_func_mean_maskfile=register_func_mean_maskfile,
                    native_func_mean_maskfile=native_func_mean_maskfile,
                    align_coregfile=align_coregfile)

    # Early stop detected
    if recon2:
        print(
            "[warn] User requested a processing early stop. Remove the 'recon2' "
            "option to resume.")
        return outputs

    # Wrap functional: resample the functional serie and mask the registered serie.
    wrap_dir = os.path.join(subjdir, STEPS["wrap"])
    if not os.path.isdir(wrap_dir):
        os.mkdir(wrap_dir)
    interface = joblib_memory.cache(apply_jip_align)
    deformed_files = interface(apply_to_files=[realign_funcfile],
                               align_with=[align_coregfile, align_normfile],
                               outdir=wrap_dir,
                               jipdir=jipdir,
                               prefix="w",
                               apply_inv=False)
    register_funcfile = deformed_files[0]
    register_func_mask_fileroot = os.path.join(
        wrap_dir, "m" + os.path.basename(register_funcfile).split(".")[0])
    interface = joblib_memory.cache(apply_mask)
    register_func_maskfile = interface(
        input_file=register_funcfile,
        output_fileroot=register_func_mask_fileroot,
        mask_file=template,
        fslconfig=fslconfig)
    display_outputs(outputs,
                    verbose,
                    register_funcfile=register_funcfile,
                    register_func_maskfile=register_func_maskfile)

    # Smooth the functional serie.
    smooth_dir = os.path.join(subjdir, STEPS["smooth"])
    if not os.path.isdir(smooth_dir):
        os.mkdir(smooth_dir)
    interface = nipype_memory.cache(fsl.Smooth)
    returncode = interface(
        in_file=register_func_maskfile,
        fwhm=kernel_size,
        output_type="NIFTI",
        smoothed_file=os.path.join(
            smooth_dir, "smooth_" +
            os.path.basename(register_func_maskfile).split(".")[0] + ".nii"))
    smooth_outputs = returncode.outputs.get()
    smoothed_file = smooth_outputs["smoothed_file"]
    display_outputs(outputs, verbose, smoothed_file=smoothed_file)

    # Copy the results to the root directory: use Nifti format.
    nibabel.load(smoothed_file).to_filename(os.path.join(subjdir, "sMNI.nii"))
    nibabel.load(register_func_maskfile).to_filename(
        os.path.join(subjdir, "MNI.nii"))
    nibabel.load(register_anat_maskfile).to_filename(
        os.path.join(subjdir, "anat.nii"))

    # Compute some snaps assessing the different processing steps.
    snapdir = os.path.join(subjdir, STEPS["snaps"])
    if not os.path.isdir(snapdir):
        os.mkdir(snapdir)
    interface = joblib_memory.cache(triplanar)
    # > generate coregistration plot
    coregister_fileroot = os.path.join(snapdir, "coregister")
    coregister_file = interface(input_file=register_func_meanfile,
                                output_fileroot=coregister_fileroot,
                                overlays=[standard_anatfile],
                                overlays_colors=None,
                                contours=True,
                                edges=False,
                                overlay_opacities=[0.7],
                                resolution=300)
    # > generate normalization plot
    normalize_fileroot = os.path.join(snapdir, "normalization")
    normalize_file = interface(input_file=register_anatfile,
                               output_fileroot=normalize_fileroot,
                               overlays=[template],
                               overlays_colors=None,
                               contours=True,
                               edges=False,
                               overlay_opacities=[0.7],
                               resolution=300)
    # > generate a motion parameter plot
    interface = joblib_memory.cache(plot_fsl_motion_parameters)
    realign_motion_file = os.path.join(snapdir,
                                       "realign_motion_parameters.png")
    interface(realign_func_parfile, realign_motion_file)
    display_outputs(outputs,
                    verbose,
                    normalize_file=normalize_file,
                    realign_motion_file=realign_motion_file,
                    coregister_file=coregister_file)

    # Generate a QC reporting
    reportdir = os.path.join(subjdir, STEPS["report"])
    reportfile = os.path.join(reportdir, "QC_preproc_{0}.pdf".format(sid))
    if not os.path.isdir(reportdir):
        os.mkdir(reportdir)
    interface = joblib_memory.cache(generate_pdf)
    tic = datetime.now()
    date = "{0}-{1}-{2}".format(tic.year, tic.month, tic.day)
    interface(datapath=snapdir,
              struct_file=os.path.join(
                  os.path.abspath(os.path.dirname(pypreclin.__file__)),
                  "utils", "resources", "pypreclin_qcpreproc.json"),
              author="NeuroSpin",
              client="-",
              poweredby="FSL-SPM-Nipype-JIP",
              project="-",
              timepoint="-",
              subject=sid,
              date=date,
              title="fMRI Preprocessing QC Reporting",
              filename=reportfile,
              pagesize=None,
              left_margin=10,
              right_margin=10,
              top_margin=20,
              bottom_margin=20,
              show_boundary=False,
              verbose=0)
    display_outputs(outputs, verbose, reportfile=reportfile)

    return outputs