Ejemplo n.º 1
0
 def apply_topup(self):
     applytopup = fsl.ApplyTOPUP()
     applytopup.inputs.in_files = [self.dwi_base + '.nii.gz']
     applytopup.inputs.encoding_file = self.acq_file
     applytopup.inputs.in_index = [1, 2]
     applytopup.inputs.in_topup = "my_topup_results"
     # applytopup.cmdline
     res = applytopup.run()
Ejemplo n.º 2
0
def create_unwarp_workflow(name="unwarp", fieldmap_pe=("y", "y-")):
    """Unwarp functional timeseries using reverse phase-blipped images."""
    inputnode = Node(IdentityInterface(["timeseries", "fieldmap"]), "inputs")

    # Calculate the shift field
    # Note that setting readout_times to 1 will give a fine
    # map of the field, but the units will be off
    # Since we don't write out the map of the field itself, it does
    # not seem worth it to add another parameter for the readout times.
    # (It does require that they are the same, but when wouldn't they be?)
    topup = MapNode(
        fsl.TOPUP(encoding_direction=fieldmap_pe,
                  readout_times=[1] * len(fieldmap_pe)), ["in_file"], "topup")

    # Unwarp the timeseries
    applytopup = MapNode(fsl.ApplyTOPUP(method="jac", in_index=[
        1
    ]), ["in_files", "in_topup_fieldcoef", "in_topup_movpar", "encoding_file"],
                         "applytopup")

    # Make a figure summarize the unwarping
    report = MapNode(UnwarpReport(), ["orig_file", "corrected_file"],
                     "unwarp_report")

    # Define the outputs
    outputnode = Node(IdentityInterface(["timeseries", "report"]), "outputs")

    # Define and connect the workflow
    unwarp = Workflow(name)
    unwarp.connect([
        (inputnode, topup, [("fieldmap", "in_file")]),
        (inputnode, applytopup, [("timeseries", "in_files")]),
        (topup, applytopup, [("out_fieldcoef", "in_topup_fieldcoef"),
                             ("out_movpar", "in_topup_movpar"),
                             ("out_enc_file", "encoding_file")]),
        (inputnode, report, [("fieldmap", "orig_file")]),
        (topup, report, [("out_corrected", "corrected_file")]),
        (applytopup, outputnode, [("out_corrected", "timeseries")]),
        (report, outputnode, [("out_file", "report")]),
    ])

    return unwarp
Ejemplo n.º 3
0
def topup_correction(name='topup_correction'):
    """

    .. deprecated:: 0.9.3
      Use :func:`nipype.workflows.dmri.preprocess.epi.sdc_peb` instead.


    Corrects for susceptibilty distortion of EPI images when one reverse encoding dataset has
    been acquired


    Example
    -------

    >>> nipype_epicorrect = topup_correction('nipype_topup')
    >>> nipype_epicorrect.inputs.inputnode.in_file_dir = 'epi.nii'
    >>> nipype_epicorrect.inputs.inputnode.in_file_rev = 'epi_rev.nii'
    >>> nipype_epicorrect.inputs.inputnode.encoding_direction = ['y', 'y-']
    >>> nipype_epicorrect.inputs.inputnode.ref_num = 0
    >>> nipype_epicorrect.run() # doctest: +SKIP


    Inputs::

        inputnode.in_file_dir - EPI volume acquired in 'forward' phase encoding
        inputnode.in_file_rev - EPI volume acquired in 'reversed' phase encoding
        inputnode.encoding_direction - Direction encoding of in_file_dir
        inputnode.ref_num - Identifier of the reference volumes (usually B0 volume)


    Outputs::

        outputnode.epi_corrected


    """

    warnings.warn(('This workflow is deprecated from v.1.0.0, use '
                   'nipype.workflows.dmri.preprocess.epi.sdc_peb instead'),
                  DeprecationWarning)

    pipeline = pe.Workflow(name=name)

    inputnode = pe.Node(niu.IdentityInterface(fields=[
        'in_file_dir', 'in_file_rev', 'encoding_direction', 'readout_times',
        'ref_num'
    ]),
                        name='inputnode')

    outputnode = pe.Node(niu.IdentityInterface(fields=[
        'out_fieldcoef', 'out_movpar', 'out_enc_file', 'epi_corrected'
    ]),
                         name='outputnode')

    b0_dir = pe.Node(fsl.ExtractROI(t_size=1), name='b0_1')
    b0_rev = pe.Node(fsl.ExtractROI(t_size=1), name='b0_2')
    combin = pe.Node(niu.Merge(2), name='merge')
    combin2 = pe.Node(niu.Merge(2), name='merge2')
    merged = pe.Node(fsl.Merge(dimension='t'), name='b0_comb')

    topup = pe.Node(fsl.TOPUP(), name='topup')
    applytopup = pe.Node(fsl.ApplyTOPUP(in_index=[1, 2]), name='applytopup')

    pipeline.connect([
        (inputnode, b0_dir, [('in_file_dir', 'in_file'),
                             ('ref_num', 't_min')]),
        (inputnode, b0_rev, [('in_file_rev', 'in_file'),
                             ('ref_num', 't_min')]),
        (inputnode, combin2, [('in_file_dir', 'in1'), ('in_file_rev', 'in2')]),
        (b0_dir, combin, [('roi_file', 'in1')]),
        (b0_rev, combin, [('roi_file', 'in2')]),
        (combin, merged, [('out', 'in_files')]),
        (merged, topup, [('merged_file', 'in_file')]),
        (inputnode, topup, [('encoding_direction', 'encoding_direction'),
                            ('readout_times', 'readout_times')]),
        (topup, applytopup, [('out_fieldcoef', 'in_topup_fieldcoef'),
                             ('out_movpar', 'in_topup_movpar'),
                             ('out_enc_file', 'encoding_file')]),
        (combin2, applytopup, [('out', 'in_files')]),
        (topup, outputnode, [('out_fieldcoef', 'out_fieldcoef'),
                             ('out_movpar', 'out_movpar'),
                             ('out_enc_file', 'out_enc_file')]),
        (applytopup, outputnode, [('out_corrected', 'epi_corrected')])
    ])

    return pipeline
Ejemplo n.º 4
0
def sdc_peb(name='peb_correction',
            epi_params={
                'read_out_times': None,
                'enc_dir': 'y-'
            },
            altepi_params={
                'read_out_times': None,
                'enc_dir': 'y'
            }):
    """
    SDC stands for susceptibility distortion correction. PEB stands for
    phase-encoding-based.

    The phase-encoding-based (PEB) method implements SDC by acquiring
    diffusion images with two different enconding directions [Andersson2003]_.
    The most typical case is acquiring with opposed phase-gradient blips
    (e.g. *A>>>P* and *P>>>A*, or equivalently, *-y* and *y*)
    as in [Chiou2000]_, but it is also possible to use orthogonal
    configurations [Cordes2000]_ (e.g. *A>>>P* and *L>>>R*,
    or equivalently *-y* and *x*).
    This workflow uses the implementation of FSL
    (`TOPUP <http://fsl.fmrib.ox.ac.uk/fsl/fslwiki/TOPUP>`_).

    Example
    -------

    >>> from nipype.workflows.dmri.fsl.artifacts import sdc_peb
    >>> peb = sdc_peb()
    >>> peb.inputs.inputnode.in_file = 'epi.nii'
    >>> peb.inputs.inputnode.alt_file = 'epi_rev.nii'
    >>> peb.inputs.inputnode.in_bval = 'diffusion.bval'
    >>> peb.inputs.inputnode.in_mask = 'mask.nii'
    >>> peb.run() # doctest: +SKIP

    .. admonition:: References

      .. [Andersson2003] Andersson JL et al., `How to correct susceptibility
        distortions in spin-echo echo-planar images: application to diffusion
        tensor imaging <http://dx.doi.org/10.1016/S1053-8119(03)00336-7>`_.
        Neuroimage. 2003 Oct;20(2):870-88. doi: 10.1016/S1053-8119(03)00336-7

      .. [Cordes2000] Cordes D et al., Geometric distortion correction in EPI
        using two images with orthogonal phase-encoding directions, in Proc.
        ISMRM (8), p.1712, Denver, US, 2000.

      .. [Chiou2000] Chiou JY, and Nalcioglu O, A simple method to correct
        off-resonance related distortion in echo planar imaging, in Proc.
        ISMRM (8), p.1712, Denver, US, 2000.

    """

    inputnode = pe.Node(niu.IdentityInterface(
        fields=['in_file', 'in_bval', 'in_mask', 'alt_file', 'ref_num']),
                        name='inputnode')
    outputnode = pe.Node(
        niu.IdentityInterface(fields=['out_file', 'out_vsm', 'out_warp']),
        name='outputnode')

    b0_ref = pe.Node(fsl.ExtractROI(t_size=1), name='b0_ref')
    b0_alt = pe.Node(fsl.ExtractROI(t_size=1), name='b0_alt')
    b0_comb = pe.Node(niu.Merge(2), name='b0_list')
    b0_merge = pe.Node(fsl.Merge(dimension='t'), name='b0_merged')

    topup = pe.Node(fsl.TOPUP(), name='topup')
    topup.inputs.encoding_direction = [
        epi_params['enc_dir'], altepi_params['enc_dir']
    ]

    readout = epi_params['read_out_time']
    topup.inputs.readout_times = [readout, altepi_params['read_out_time']]

    unwarp = pe.Node(fsl.ApplyTOPUP(in_index=[1], method='jac'), name='unwarp')

    # scaling = pe.Node(niu.Function(input_names=['in_file', 'enc_dir'],
    #                   output_names=['factor'], function=_get_zoom),
    #                   name='GetZoom')
    # scaling.inputs.enc_dir = epi_params['enc_dir']
    vsm2dfm = vsm2warp()
    vsm2dfm.inputs.inputnode.enc_dir = epi_params['enc_dir']
    vsm2dfm.inputs.inputnode.scaling = readout

    wf = pe.Workflow(name=name)
    wf.connect([
        (inputnode, b0_ref, [('in_file', 'in_file'),
                             (('ref_num', _checkrnum), 't_min')]),
        (inputnode, b0_alt, [('alt_file', 'in_file'),
                             (('ref_num', _checkrnum), 't_min')]),
        (b0_ref, b0_comb, [('roi_file', 'in1')]),
        (b0_alt, b0_comb, [('roi_file', 'in2')]),
        (b0_comb, b0_merge, [('out', 'in_files')]),
        (b0_merge, topup, [('merged_file', 'in_file')]),
        (topup, unwarp, [('out_fieldcoef', 'in_topup_fieldcoef'),
                         ('out_movpar', 'in_topup_movpar'),
                         ('out_enc_file', 'encoding_file')]),
        (inputnode, unwarp, [('in_file', 'in_files')]),
        (unwarp, outputnode, [('out_corrected', 'out_file')]),
        # (b0_ref,      scaling,    [('roi_file', 'in_file')]),
        # (scaling,     vsm2dfm,    [('factor', 'inputnode.scaling')]),
        (b0_ref, vsm2dfm, [('roi_file', 'inputnode.in_ref')]),
        (topup, vsm2dfm, [('out_field', 'inputnode.in_vsm')]),
        (topup, outputnode, [('out_field', 'out_vsm')]),
        (vsm2dfm, outputnode, [('outputnode.out_warp', 'out_warp')])
    ])
    return wf
Ejemplo n.º 5
0
def se_fmap_workflow(name=WORKFLOW_NAME, settings=None):
    """
    Estimates the fieldmap using TOPUP on series of :abbr:`SE (Spin-Echo)` images
    acquired with varying :abbr:`PE (phase encoding)` direction.

    Outputs::

      outputnode.mag_brain - The average magnitude image, skull-stripped
      outputnode.fmap_mask - The brain mask applied to the fieldmap
      outputnode.fieldmap - The estimated fieldmap in Hz

    """

    if settings is None:
        settings = {}

    workflow = pe.Workflow(name=name)
    inputnode = pe.Node(niu.IdentityInterface(fields=['input_images']),
                        name='inputnode')
    outputnode = pe.Node(
        niu.IdentityInterface(fields=['fieldmap', 'fmap_mask', 'mag_brain']),
        name='outputnode')

    # Read metadata
    meta = pe.MapNode(
        ReadSidecarJSON(fields=['TotalReadoutTime', 'PhaseEncodingDirection']),
        iterfield=['in_file'],
        name='metadata')

    encfile = pe.Node(interface=niu.Function(
        input_names=['input_images', 'in_dict'],
        output_names=['parameters_file'],
        function=create_encoding_file),
                      name='TopUp_encfile',
                      updatehash=True)

    # Head motion correction
    fslmerge = pe.Node(fsl.Merge(dimension='t'), name='SE_merge')
    hmc_se = pe.Node(fsl.MCFLIRT(cost='normcorr', mean_vol=True),
                     name='SE_head_motion_corr')
    fslsplit = pe.Node(fsl.Split(dimension='t'), name='SE_split')

    # Run topup to estimate field distortions, do not estimate movement
    # since it is done in hmc_se
    topup = pe.Node(fsl.TOPUP(estmov=0), name='TopUp')

    # Use the least-squares method to correct the dropout of the SE images
    unwarp_mag = pe.Node(fsl.ApplyTOPUP(method='lsr'), name='TopUpApply')

    # Remove bias
    inu_n4 = pe.Node(N4BiasFieldCorrection(dimension=3), name='SE_bias')

    # Skull strip corrected SE image to get reference brain and mask
    mag_bet = pe.Node(fsl.BET(mask=True, robust=True), name='SE_brain')

    workflow.connect([
        (inputnode, meta, [('input_images', 'in_file')]),
        (inputnode, encfile, [('input_images', 'input_images')]),
        (inputnode, fslmerge, [('input_images', 'in_files')]),
        (fslmerge, hmc_se, [('merged_file', 'in_file')]),
        (meta, encfile, [('out_dict', 'in_dict')]),
        (encfile, topup, [('parameters_file', 'encoding_file')]),
        (hmc_se, topup, [('out_file', 'in_file')]),
        (topup, unwarp_mag, [('out_fieldcoef', 'in_topup_fieldcoef'),
                             ('out_movpar', 'in_topup_movpar')]),
        (encfile, unwarp_mag, [('parameters_file', 'encoding_file')]),
        (hmc_se, fslsplit, [('out_file', 'in_file')]),
        (fslsplit, unwarp_mag, [('out_files', 'in_files'),
                                (('out_files', gen_list), 'in_index')]),
        (unwarp_mag, inu_n4, [('out_corrected', 'input_image')]),
        (inu_n4, mag_bet, [('output_image', 'in_file')]),
        (topup, outputnode, [('out_field', 'fieldmap')]),
        (mag_bet, outputnode, [('out_file', 'mag_brain'),
                               ('mask_file', 'fmap_mask')])
    ])

    # Reports section
    se_png = pe.Node(niu.Function(
        input_names=['in_file', 'overlay_file', 'out_file'],
        output_names=['out_file'],
        function=stripped_brain_overlay),
                     name='PNG_SE_corr')
    se_png.inputs.out_file = 'corrected_SE_and_mask.png'

    datasink = pe.Node(
        nio.DataSink(base_directory=op.join(settings['work_dir'], 'images')),
        name='datasink',
        parameterization=False)
    workflow.connect([
        (unwarp_mag, se_png, [('out_corrected', 'overlay_file')]),
        (mag_bet, se_png, [('mask_file', 'in_file')]),
        (se_png, datasink, [('out_file', '@corrected_SE_and_mask')])
    ])

    return workflow
Ejemplo n.º 6
0
def get_fmri2standard_wf(
        tvols,
        subject_id,
        ACQ_PARAMS="/home/didac/LabScripts/fMRI_preprocess/acparams_hcp.txt"):
    """Estimates transformation from Gradiend Field Distortion-warped BOLD to T1
    
    In general:
        BOLD is field-inhomogeneity corrected and corregistered into standard space (T1).  
        
    To do so, the following steps are carried out:
        1)  Corregister SBref to SEgfmAP (fsl.FLIRT)
        2)  Realign BOLD to corrected SBref (fsl.MCFLIRT)
        3)  Field inhomogeneity correction estimation of SBref from SEfm_AP and SEfm_PA (fsl.TOPUP)
        4)  Apply field inhomogeneity correction to SBref (fsl.ApplyTOPUP)
        5)  Apply field inhomogeneity correction to BOLD (fsl.ApplyTOPUP)
        6)  Transform free-surfer brain mask (brain.mgz) to T1 space (freesurfer.ApplyVolTransform ;mri_vol2vol), 
            then binarized (fsl.UnaryMaths) and the mask is extracted from T1 (fsl.BinaryMaths)
        7)  Corregister BOLD (field-inhomogeneity corrected) to Standard T1 (fsl.Epi2Reg)

    Parameters
    ----------
    tvols: [t_initial, t_final] volumes included in the preprocess
    ACQ_params: Path to txt file containing MRI acquisition parameters; needs to be specified for topup correction
    
    
    Returns
    -------
    Workflow with the transformation
 
    """
    from nipype import Workflow, Node, interfaces
    from nipype.interfaces import fsl, utility, freesurfer

    print("defining workflow...")
    wf = Workflow(name=subject_id, base_dir='')

    #Setting INPUT node...
    print("defines input node...")
    node_input = Node(utility.IdentityInterface(fields=[
        'func_sbref_img', 'func_segfm_ap_img', 'func_segfm_pa_img',
        'func_bold_ap_img', 'T1_img', 'T1_brain_freesurfer_mask'
    ]),
                      name='input_node')

    print(
        "Averages the three repeated Spin-Echo images with same Phase Encoding (AP or PA) for Susceptibility Correction (unwarping)..."
    )
    node_average_SEgfm = Node(fsl.maths.MeanImage(), name='Mean_SEgfm_AP')

    print("Corregister SB-ref to average SEgfm-AP")
    node_coregister_SBref2SEgfm = Node(
        fsl.FLIRT(dof=6  #translation and rotation only
                  ),
        name='Corregister_SBref2SEgfm')

    print("Eliminates first volumes.")
    node_eliminate_first_scans = Node(
        fsl.ExtractROI(
            t_min=tvols[0],  # first included volume
            t_size=tvols[1] -
            tvols[0],  # number of volumes from the first to the last one
        ),
        name="eliminate_first_scans")

    print("Realigns fMRI BOLD volumes to SBref in SEgfm-AP space")
    node_realign_bold = Node(
        fsl.MCFLIRT(
            save_plots=True,  # save transformation matrices
        ),
        name="realign_fmri2SBref")

    print("Concatenates AP and PA SEgfm volumes...")
    # AP AP AP PA PA PA
    node_merge_ap_pa_inputs = Node(
        utility.base.Merge(2  # number of inputs; it concatenates lists
                           ),
        name='Merge_ap_pa_inputs')
    node_merge_SEgfm = Node(
        fsl.Merge(dimension='t'  # ¿? 
                  ),
        name='Merge_SEgfm_AP_PA')

    print(
        "Estimates TopUp inhomogeneity correction from SEfm_AP and SEfm_PA...")
    node_topup_SEgfm = Node(fsl.TOPUP(encoding_file=ACQ_PARAMS, ),
                            name='Topup_SEgfm_estimation')

    print("Applies warp from TOPUP to correct SBref...")
    node_apply_topup_to_SBref = Node(
        fsl.ApplyTOPUP(
            encoding_file=ACQ_PARAMS,
            method='jac',  # jacobian modulation
            interp='spline',  # interpolation method
        ),
        name="apply_topup_to_SBref")

    print("Applies warp from TOPUP to correct realigned BOLD...")
    node_apply_topup = Node(
        fsl.ApplyTOPUP(
            encoding_file=ACQ_PARAMS,
            method='jac',  # jacobian modulation
            interp='spline',  # interpolation method
        ),
        name="apply_topup")

    ## BRAIN MASK

    #Registration to T1. Epireg without fieldmaps combined (see https://www.fmrib.ox.ac.uk/primers/intro_primer/ExBox20/IntroBox20.html)
    #    print ("Eliminates scalp from brain using T1 high res image");
    #    node_mask_T1=Node(fsl.BET(
    #            frac=0.7 # umbral
    #            ),
    #    name="mask_T1");

    print('Transform brain mask T1 from freesurfer space to T1 space')
    node_vol2vol_brain = Node(
        freesurfer.ApplyVolTransform(
            reg_header=True,  # (--regheader)
            transformed_file='brainmask_warped.nii.gz'
            #source_file --mov (INPUT; freesurfer brain.mgz)
            #transformed_file --o (OUTPUT; ...brain.nii.gz)
            #target_file --targ (REFERENCE; ...T1w.nii.gz)
        ),
        name="vol2vol")

    print('Transform brain mask T1 to binary mask')
    node_bin_mask_brain = Node(
        fsl.UnaryMaths(  # fslmaths T1_brain -bin T1_binarized mask
            operation='bin',  # (-bin)
            #in_file (T1_brain)
            #out_file (T1_binarized_mask)
        ),
        name="binarize_mask")

    print('Extract brain mask from T1 using binary mask')
    node_extract_mask = Node(
        fsl.
        BinaryMaths(  # fslmaths T1 -mul T1_binarized_mask T1_extracted_mask
            operation='mul'  # (-mul)
            #in_file (T1)
            #out_file (T1_extracted_mask)
            #operand_file (T1_binarized_mask)
        ),
        name="extract_mask")

    ##
    print("Estimate and appply transformation from SBref to T1")
    node_epireg = Node(
        fsl.EpiReg(
            #t1_head=SUBJECT_FSTRUCT_DIC['anat_T1'],
            out_base='SEgfm2T1'),
        name="epi2reg")
    '''  
    EPI2REG ALREADY APPLIED         
    print ("Apply epi2reg to SBRef..");
    node_apply_epi2reg_SBref= Node(fsl.ApplyXFM(
            ),
    name="node_apply_epi2reg_SBref");
    '''

    print("Estimates inverse transform from epi2reg...")
    # quality control
    node_invert_epi2reg = Node(fsl.ConvertXFM(invert_xfm=True),
                               name="invert_epi2reg")

    print("...")
    node_mask_fMRI = Node(fsl.BET(mask=True, ), name='mask_fMRI')
    #node_fmriMask.overwrite=True
    print("Setting OUTPUT node...")
    node_output = Node(interfaces.utility.IdentityInterface(fields=[
        'SBref2SEgfm_mat',
        'realign_movpar_txt',
        'realign_fmri_img',
        'topup_movpar_txt',
        'topup_field_coef_img',
        'epi2str_mat',
        'epi2str_img',
        'fmri_mask_img',
        'rfmri_unwarped_imgs',
        'sb_ref_unwarped_img',
    ]),
                       name='output_node')

    print("All nodes created; Starts creating connections")

    #Connects nodes
    wf.connect([
        #inputs
        (node_input, node_average_SEgfm, [("func_segfm_ap_img", "in_file")]),
        (node_input, node_coregister_SBref2SEgfm, [("func_sbref_img",
                                                    "in_file")]),
        (node_input, node_eliminate_first_scans, [("func_bold_ap_img",
                                                   "in_file")]),
        (node_input, node_merge_ap_pa_inputs, [("func_segfm_ap_img", "in1"),
                                               ("func_segfm_pa_img", "in2")]),
        (node_merge_ap_pa_inputs, node_merge_SEgfm, [("out", "in_files")]),
        (node_input, node_epireg, [("T1_img", "t1_head")]),
        (node_input, node_vol2vol_brain, [("T1_brain_freesurfer_mask",
                                           "source_file")]),
        (node_input, node_vol2vol_brain, [("T1_img", "target_file")]),
        (node_input, node_extract_mask, [("T1_img", "in_file")]),

        #connections
        (node_eliminate_first_scans, node_realign_bold, [("roi_file",
                                                          "in_file")]),
        (node_average_SEgfm, node_coregister_SBref2SEgfm, [("out_file",
                                                            "reference")]),
        (node_coregister_SBref2SEgfm, node_realign_bold, [("out_file",
                                                           "ref_file")]),

        #T1 brain mask transformations (change space / vol2vol, binarize and extract)
        (node_vol2vol_brain, node_bin_mask_brain, [("transformed_file",
                                                    "in_file")]),
        (node_bin_mask_brain, node_extract_mask, [("out_file", "operand_file")
                                                  ]),

        #(node_realign_bold, node_tsnr, [("out_file", "in_file")]),
        (node_merge_SEgfm, node_topup_SEgfm, [("merged_file", "in_file")]),
        (node_realign_bold, node_apply_topup, [("out_file", "in_files")]),
        (node_topup_SEgfm, node_apply_topup,
         [("out_fieldcoef", "in_topup_fieldcoef"),
          ("out_movpar", "in_topup_movpar")]),
        (node_topup_SEgfm, node_apply_topup_to_SBref,
         [("out_fieldcoef", "in_topup_fieldcoef"),
          ("out_movpar", "in_topup_movpar")]),
        (node_coregister_SBref2SEgfm, node_apply_topup_to_SBref,
         [("out_file", "in_files")]),

        #corregister to T1
        (node_extract_mask, node_epireg, [("out_file", "t1_brain")]),
        (node_apply_topup_to_SBref, node_epireg, [("out_corrected", "epi")]),
        (node_epireg, node_invert_epi2reg, [("epi2str_mat", "in_file")]),
        (node_coregister_SBref2SEgfm, node_mask_fMRI, [("out_file", "in_file")
                                                       ]),

        #yeld relevant data to output node
        (node_coregister_SBref2SEgfm, node_output, [("out_matrix_file",
                                                     "SBref2SEgfm_mat")]),
        (node_realign_bold, node_output, [("par_file", "realign_movpar_txt"),
                                          ("out_file", "realign_fmri_img")]),
        (node_mask_fMRI, node_output, [("mask_file", "fmri_mask_img")]),
        (node_epireg, node_output, [("epi2str_mat", "epi2str_mat")]),
        (node_epireg, node_output, [("out_file", "epi2str_img")]),
        (node_topup_SEgfm, node_output,
         [("out_fieldcoef", "topup_field_coef_img"),
          ("out_corrected", "sb_ref_unwarped_img")]),
        (node_apply_topup, node_output, [("out_corrected",
                                          "rfmri_unwarped_imgs")])
    ])
    print("All connections created")
    return (wf)
Ejemplo n.º 7
0
def epi_unwarp(name='EPIUnwarpWorkflow', settings=None):
    """ A workflow to correct EPI images """
    workflow = pe.Workflow(name=name)
    inputnode = pe.Node(niu.IdentityInterface(fields=[
        'epi', 'sbref_brain', 'fieldmap', 'fmap_movpar', 'fmap_mask',
        'epi_brain'
    ]),
                        name='inputnode')
    outputnode = pe.Node(
        niu.IdentityInterface(fields=['epi_correct', 'epi_mean']),
        name='outputnode')

    # Read metadata
    meta = pe.MapNode(
        ReadSidecarJSON(fields=['TotalReadoutTime', 'PhaseEncodingDirection']),
        iterfield=['in_file'],
        name='metadata')

    encfile = pe.Node(interface=niu.Function(
        input_names=['input_images', 'in_dict'],
        output_names=['parameters_file'],
        function=create_encoding_file),
                      name='TopUp_encfile',
                      updatehash=True)

    fslsplit = pe.Node(fsl.Split(dimension='t'), name='EPI_split')

    # Now, we cannot use the LSR method
    unwarp_epi = pe.MapNode(fsl.ApplyTOPUP(method='jac', in_index=[1]),
                            iterfield=['in_files'],
                            name='TopUpApply')

    # Merge back
    fslmerge = pe.Node(fsl.Merge(dimension='t'), name='EPI_corr_merge')

    # Compute mean
    epi_mean = pe.Node(fsl.MeanImage(dimension='T'), name='EPI_mean')

    workflow.connect([
        (inputnode, meta, [('epi', 'in_file')]),
        (inputnode, encfile, [('epi', 'input_images')]),
        (inputnode, fslsplit, [('epi_brain', 'in_file')]),
        (meta, encfile, [('out_dict', 'in_dict')]),
        (inputnode, unwarp_epi, [('fieldmap', 'in_topup_fieldcoef'),
                                 ('fmap_movpar', 'in_topup_movpar')]),
        (encfile, unwarp_epi, [('parameters_file', 'encoding_file')]),
        (fslsplit, unwarp_epi, [('out_files', 'in_files')]),
        (unwarp_epi, fslmerge, [('out_corrected', 'in_files')]),
        (fslmerge, epi_mean, [('merged_file', 'in_file')]),
        (fslmerge, outputnode, [('merged_file', 'epi_correct')]),
        (epi_mean, outputnode, [('out_file', 'epi_mean')])
    ])

    # Plot result
    png_epi_corr = pe.Node(niu.Function(
        input_names=['in_file', 'overlay_file', 'out_file'],
        output_names=['out_file'],
        function=stripped_brain_overlay),
                           name='PNG_epi_corr')
    png_epi_corr.inputs.out_file = 'corrected_EPI.png'

    ds_png = pe.Node(DerivativesDataSink(base_directory=settings['output_dir'],
                                         suffix='sdc'),
                     name='DerivativesPNG')

    workflow.connect([(epi_mean, png_epi_corr, [('out_file', 'overlay_file')]),
                      (inputnode, png_epi_corr, [('fmap_mask', 'in_file')]),
                      (inputnode, ds_png, [('epi', 'source_file')]),
                      (png_epi_corr, ds_png, [('out_file', 'in_file')])])

    return workflow
Ejemplo n.º 8
0
def func_calc_disco_warp():
    '''
    Method to calculate and apply susceptibility induced distortion warps to a fresh functional image
    used topup and applytopup

    inputs
        inputnode.func
        inputnode.se_image
        inputnode.se_invpol
        inputnode.encoding_file

    outputnode
          outputnode.out_enc_file       # encoding directions file output for applytopup
          outputnode.movpar             # movpar.txt output file
          outputnode.fieldcoef          # file containing the field coefficients

    '''
    datain = '/scr/sambesi1/workspace/Projects/GluREST/functional/datain.txt'

    #define worflow
    flow = Workflow('func_distortion_correction')
    inputnode = Node(
        util.IdentityInterface(fields=['func', 'func_se', 'func_se_inv']),
        name='inputnode')
    outputnode = Node(util.IdentityInterface(fields=[
        'enc_file ', 'topup_movpar', 'topup_fieldcoef', 'topup_field',
        'func_disco'
    ]),
                      name='outputnode')
    # define nodes
    list_blips = Node(util.Merge(2), name='blips_list')
    make_blips = Node(fsl.Merge(), name='blips_merged')
    make_blips.inputs.dimension = 't'
    make_blips.inputs.output_type = 'NIFTI_GZ'

    topup = Node(interface=fsl.TOPUP(), name='calc_topup')
    topup.inputs.encoding_file = datain
    topup.inputs.output_type = "NIFTI_GZ"

    apply = Node(interface=fsl.ApplyTOPUP(), name='apply_topup')
    apply.inputs.in_index = [1]
    apply.inputs.encoding_file = datain
    apply.inputs.method = 'jac'
    apply.inputs.output_type = "NIFTI_GZ"

    # connect nodes
    flow.connect(inputnode, 'func_se', list_blips, 'in1')
    flow.connect(inputnode, 'func_se_inv', list_blips, 'in2')
    flow.connect(list_blips, 'out', make_blips, 'in_files')
    flow.connect(make_blips, 'merged_file', topup, 'in_file')
    flow.connect(inputnode, 'func', apply, 'in_files')
    flow.connect(topup, 'out_fieldcoef', apply, 'in_topup_fieldcoef')
    flow.connect(topup, 'out_movpar', apply, 'in_topup_movpar')

    flow.connect(topup, 'out_enc_file', outputnode, 'enc_file')
    flow.connect(topup, 'out_movpar', outputnode, 'topup_movpar')
    flow.connect(topup, 'out_fieldcoef', outputnode, 'topup_fieldcoef')
    flow.connect(topup, 'out_field', outputnode, 'topup_field')
    flow.connect(apply, 'out_corrected', outputnode, 'func_disco')

    return flow
Ejemplo n.º 9
0
def create_topup_workflow(analysis_info, name='topup'):

    ###########################################################################
    # NODES
    ###########################################################################

    input_node = pe.Node(IdentityInterface(fields=[
        'in_files', 'alt_files', 'conf_file', 'output_directory', 'echo_time',
        'phase_encoding_direction', 'epi_factor'
    ]),
                         name='inputspec')

    output_node = pe.Node(
        IdentityInterface(fields=['out_files', 'field_coefs']),
        name='outputspec')

    get_info = pe.MapNode(interface=Get_scaninfo,
                          name='get_scaninfo',
                          iterfield=['in_file'])

    dyns_min_1_node = pe.MapNode(interface=Dyns_min_1,
                                 name='dyns_min_1_node',
                                 iterfield=['dyns'])

    topup_scan_params_node = pe.Node(interface=Topup_scan_params,
                                     name='topup_scan_params')

    apply_scan_params_node = pe.MapNode(interface=Apply_scan_params,
                                        name='apply_scan_params',
                                        iterfield=['nr_trs'])

    PE_ref = pe.MapNode(fsl.ExtractROI(t_size=1),
                        name='PE_ref',
                        iterfield=['in_file', 't_min'])

    # hard-coded the timepoint for this node, no more need for alt_t.
    PE_alt = pe.MapNode(fsl.ExtractROI(t_min=0, t_size=1),
                        name='PE_alt',
                        iterfield=['in_file'])

    PE_comb = pe.MapNode(Merge(2), name='PE_list', iterfield=['in1', 'in2'])
    PE_merge = pe.MapNode(fsl.Merge(dimension='t'),
                          name='PE_merged',
                          iterfield=['in_files'])

    # implementing the contents of b02b0.cnf in the args,
    # while supplying an emtpy text file as a --config option
    # gets topup going on our server.
    topup_args = """--warpres=20,16,14,12,10,6,4,4,4
    --subsamp=1,1,1,1,1,1,1,1,1
    --fwhm=8,6,4,3,3,2,1,0,0
    --miter=5,5,5,5,5,10,10,20,20
    --lambda=0.005,0.001,0.0001,0.000015,0.000005,0.0000005,0.00000005,0.0000000005,0.00000000001
    --ssqlambda=1
    --regmod=bending_energy
    --estmov=1,1,1,1,1,0,0,0,0
    --minmet=0,0,0,0,0,1,1,1,1
    --splineorder=3
    --numprec=double
    --interp=spline
    --scale=1 -v"""

    topup_node = pe.MapNode(fsl.TOPUP(args=topup_args),
                            name='topup',
                            iterfield=['in_file'])
    unwarp = pe.MapNode(fsl.ApplyTOPUP(in_index=[1], method='jac'),
                        name='unwarp',
                        iterfield=[
                            'in_files', 'in_topup_fieldcoef',
                            'in_topup_movpar', 'encoding_file'
                        ])

    ###########################################################################
    # WORKFLOW
    ###########################################################################
    topup_workflow = pe.Workflow(name=name)

    # these are now mapnodes because they split up over files
    topup_workflow.connect(input_node, 'in_files', get_info, 'in_file')
    topup_workflow.connect(input_node, 'in_files', PE_ref, 'in_file')
    topup_workflow.connect(input_node, 'alt_files', PE_alt, 'in_file')

    # this is a simple node, connecting to the input node
    topup_workflow.connect(input_node, 'phase_encoding_direction',
                           topup_scan_params_node, 'pe_direction')
    topup_workflow.connect(input_node, 'echo_time', topup_scan_params_node,
                           'te')
    topup_workflow.connect(input_node, 'epi_factor', topup_scan_params_node,
                           'epi_factor')

    # preparing a node here, which automatically iterates over dyns output of the get_info mapnode
    topup_workflow.connect(input_node, 'echo_time', apply_scan_params_node,
                           'te')
    topup_workflow.connect(input_node, 'phase_encoding_direction',
                           apply_scan_params_node, 'pe_direction')
    topup_workflow.connect(input_node, 'epi_factor', apply_scan_params_node,
                           'epi_factor')
    topup_workflow.connect(get_info, 'dyns', apply_scan_params_node, 'nr_trs')

    # the nr_trs and in_files both propagate into the PR_ref node
    topup_workflow.connect(get_info, 'dyns', dyns_min_1_node, 'dyns')
    topup_workflow.connect(dyns_min_1_node, 'dyns_1', PE_ref, 't_min')

    topup_workflow.connect(PE_ref, 'roi_file', PE_comb, 'in1')
    topup_workflow.connect(PE_alt, 'roi_file', PE_comb, 'in2')
    topup_workflow.connect(PE_comb, 'out', PE_merge, 'in_files')

    topup_workflow.connect(topup_scan_params_node, 'fn', topup_node,
                           'encoding_file')
    topup_workflow.connect(PE_merge, 'merged_file', topup_node, 'in_file')
    topup_workflow.connect(input_node, 'conf_file', topup_node, 'config')

    topup_workflow.connect(input_node, 'in_files', unwarp, 'in_files')
    topup_workflow.connect(apply_scan_params_node, 'fn', unwarp,
                           'encoding_file')
    topup_workflow.connect(topup_node, 'out_fieldcoef', unwarp,
                           'in_topup_fieldcoef')
    topup_workflow.connect(topup_node, 'out_movpar', unwarp, 'in_topup_movpar')

    topup_workflow.connect(unwarp, 'out_corrected', output_node, 'out_files')
    topup_workflow.connect(topup_node, 'out_fieldcoef', output_node,
                           'field_coefs')

    # ToDo: automatic datasink?

    return topup_workflow
Ejemplo n.º 10
0
def sdc_unwarp(name=SDC_UNWARP_NAME, ref_vol=None, method='jac'):
    """
    This workflow takes an estimated fieldmap and a target image and applies TOPUP,
    an :abbr:`SDC (susceptibility-derived distortion correction)` method in FSL to
    unwarp the target image.

    Input fields:
    ~~~~~~~~~~~~~

      inputnode.in_file - the image(s) to which this correction will be applied
      inputnode.in_mask - a brain mask corresponding to the in_file image
      inputnode.fmap_ref - the fieldmap reference (generally, a *magnitude* image or the
                           resulting SE image)
      inputnode.fmap_mask - a brain mask in fieldmap-space
      inputnode.fmap - a fieldmap in Hz
      inputnode.hmc_movpar - the head motion parameters (iff inputnode.in_file is only
                             one 4D file)

    Output fields:
    ~~~~~~~~~~~~~~

      outputnode.out_file - the in_file after susceptibility-distortion correction.

    """

    workflow = pe.Workflow(name=name)
    inputnode = pe.Node(niu.IdentityInterface(
        fields=['in_file', 'fmap_ref', 'fmap_mask', 'fmap',
                'hmc_movpar']), name='inputnode')
    outputnode = pe.Node(niu.IdentityInterface(fields=['out_file']), name='outputnode')

    # Compute movpar file iff we have several images with different
    # PE directions.
    align = pe.Node(niu.Function(
        input_names=['in_files', 'in_movpar'],
        output_names=['out_file', 'ref_vol', 'ref_mask', 'out_movpar'],
        function=_multiple_pe_hmc), name='AlignMultiplePE')
    align.inputs.in_ref = ref_vol

    # Read metadata
    meta = pe.MapNode(niu.Function(
        input_names=['in_file'], output_names=['out_dict'], function=_get_metadata),
        iterfield=['in_file'], name='metadata')

    encfile = pe.Node(interface=niu.Function(
        input_names=['input_images', 'in_dict'], output_names=['parameters_file'],
        function=create_encoding_file), name='TopUp_encfile', updatehash=True)

    fslsplit = pe.Node(fsl.Split(dimension='t'), name='ImageHMCSplit')

    # Register the reference of the fieldmap to the reference
    # of the target image (the one that shall be corrected)
    fmap2ref = pe.Node(ants.Registration(output_warped_image=True),
                       name='Fieldmap2ImageRegistration')

    grabber = nio.JSONFileGrabber()
    setattr(grabber, '_always_run', False)
    fmap2ref_params = pe.Node(grabber, name='Fieldmap2ImageRegistration_params')
    fmap2ref_params.inputs.in_file = (
        pkgr.resource_filename('fmriprep', 'data/fmap-any_registration.json'))

    applyxfm = pe.Node(ants.ApplyTransforms(
        dimension=3, interpolation='Linear'), name='Fieldmap2ImageApply')

    topup_adapt = pe.Node(niu.Function(
        input_names=['in_file', 'in_ref', 'in_movpar'],
        output_names=['out_fieldcoef', 'out_movpar'],
        function=_gen_coeff), name='TopUpAdapt')

    # Use the least-squares method to correct the dropout of the SBRef images
    unwarp = pe.Node(fsl.ApplyTOPUP(method=method), name='TopUpApply')


    workflow.connect([
        (inputnode, meta, [('in_file', 'in_file')]),
        (inputnode, align, [('in_file', 'in_files'),
                            ('hmc_movpar', 'in_movpar')]),
        (inputnode, applyxfm, [('fmap', 'input_image')]),
        (inputnode, encfile, [('in_file', 'input_images')]),
        (inputnode, fmap2ref, [('fmap_ref', 'moving_image'),
                               ('fmap_mask', 'moving_image_mask')]),

        (align, fmap2ref, [('ref_vol', 'fixed_image'),
                           ('ref_mask', 'fixed_image_mask')]),
        (align, applyxfm, [('ref_vol', 'reference_image')]),
        (align, topup_adapt, [('ref_vol', 'in_ref'),
                              ('out_movpar', 'in_movpar')]),

        (meta, encfile, [('out_dict', 'in_dict')]),

        (fmap2ref, applyxfm, [
            ('forward_transforms', 'transforms'),
            ('forward_invert_flags', 'invert_transform_flags')]),
        (align, fslsplit, [('out_file', 'in_file')]),
        (applyxfm, topup_adapt, [('output_image', 'in_file')]),
        (fslsplit, unwarp, [('out_files', 'in_files'),
                            (('out_files', gen_list), 'in_index')]),
        (topup_adapt, unwarp, [('out_fieldcoef', 'in_topup_fieldcoef'),
                               ('out_movpar', 'in_topup_movpar')]),
        (encfile, unwarp, [('parameters_file', 'encoding_file')]),
        (unwarp, outputnode, [('out_corrected', 'out_file')])
    ])

    # Connect registration settings in the end, not to clutter the code
    workflow.connect([
        (fmap2ref_params, fmap2ref, [
            ('transforms', 'transforms'),
            ('transform_parameters', 'transform_parameters'),
            ('number_of_iterations', 'number_of_iterations'),
            ('dimension', 'dimension'),
            ('metric', 'metric'),
            ('metric_weight', 'metric_weight'),
            ('radius_or_number_of_bins', 'radius_or_number_of_bins'),
            ('sampling_strategy', 'sampling_strategy'),
            ('sampling_percentage', 'sampling_percentage'),
            ('convergence_threshold', 'convergence_threshold'),
            ('convergence_window_size', 'convergence_window_size'),
            ('smoothing_sigmas', 'smoothing_sigmas'),
            ('sigma_units', 'sigma_units'),
            ('shrink_factors', 'shrink_factors'),
            ('use_estimate_learning_rate_once', 'use_estimate_learning_rate_once'),
            ('use_histogram_matching', 'use_histogram_matching'),
            ('initial_moving_transform_com', 'initial_moving_transform_com'),
            ('collapse_output_transforms', 'collapse_output_transforms'),
            ('winsorize_upper_quantile', 'winsorize_upper_quantile'),
            ('winsorize_lower_quantile', 'winsorize_lower_quantile')
        ])
    ])

    return workflow
Ejemplo n.º 11
0
def create_preproc_workflow(session):
    """
    Defines simple functional preprocessing workflow, including motion
    correction, registration to distortion scans, and unwarping. Assumes
    recon-all has been performed on T1, and computes but does not apply
    registration to anatomy.
    """

    #---Create workflow---
    wf = Workflow(name='workflow', base_dir=session['working_dir'])

    #---EPI Realignment---

    # Realign every TR in each functional run to the sbref image using mcflirt
    realign = MapNode(fsl.MCFLIRT(ref_file=session['sbref'],
                                  save_mats=True,
                                  save_plots=True),
                      iterfield=['in_file'],
                      name='realign')
    realign.inputs.in_file = session['epis']
    wf.add_nodes([realign])

    #---Registration to distortion scan---

    # Register the sbref scan to the distortion scan with the same PE using flirt
    reg2dist = Node(fsl.FLIRT(in_file=session['sbref'],
                              reference=session['distort_PE'],
                              out_file='sbref_reg.nii.gz',
                              out_matrix_file='sbref2dist.mat',
                              dof=6),
                    name='reg2distort')
    wf.add_nodes([reg2dist])

    #---Distortion correction---

    # Merge the two distortion scans for unwarping
    distort_scans = [session['distort_PE'], session['distort_revPE']]
    merge_dist = Node(fsl.Merge(in_files=distort_scans,
                                dimension='t',
                                merged_file='distortion_merged.nii.gz'),
                      name='merge_distort')
    wf.add_nodes([merge_dist])

    # Run topup to estimate warpfield and create unwarped distortion scans
    if '-' not in session['PE_dim']:
        PEs = np.repeat([session['PE_dim'], session['PE_dim'] + '-'], 3)
    else:
        PEs = np.repeat(
            [session['PE_dim'], session['PE_dim'].replace('-', '')], 3)
    unwarp_dist = Node(fsl.TOPUP(encoding_direction=list(PEs),
                                 readout_times=[1, 1, 1, 1, 1, 1],
                                 config='b02b0.cnf',
                                 fwhm=0),
                       name='unwarp_distort')
    wf.connect(merge_dist, 'merged_file', unwarp_dist, 'in_file')

    # Unwarp sbref image in case it's useful
    unwarp_sbref = Node(fsl.ApplyTOPUP(in_index=[1], method='jac'),
                        name='unwarp_sbref')
    wf.connect([(reg2dist, unwarp_sbref, [('out_file', 'in_files')]),
                (unwarp_dist, unwarp_sbref,
                 [('out_enc_file', 'encoding_file'),
                  ('out_fieldcoef', 'in_topup_fieldcoef'),
                  ('out_movpar', 'in_topup_movpar')])])

    #---Registration to anatomy---

    # Create mean unwarped distortion scan
    mean_unwarped_dist = Node(fsl.MeanImage(dimension='T'),
                              name='mean_unwarped_distort')
    wf.connect(unwarp_dist, 'out_corrected', mean_unwarped_dist, 'in_file')

    # Register mean unwarped distortion scan to anatomy using bbregister
    reg2anat = Node(fs.BBRegister(
        subject_id=session['Freesurfer_subject_name'],
        contrast_type='t2',
        init='fsl',
        out_reg_file='distort2anat_tkreg.dat',
        out_fsl_file='distort2anat_flirt.mat'),
                    name='reg2anat')
    wf.connect(mean_unwarped_dist, 'out_file', reg2anat, 'source_file')

    #---Combine and apply transforms to EPIs---

    # Split EPI runs into 3D files
    split_epis = MapNode(fsl.Split(dimension='t'),
                         iterfield=['in_file'],
                         name='split_epis')
    split_epis.inputs.in_file = session['epis']
    wf.add_nodes([split_epis])

    # Combine the rigid transforms to be applied to each EPI volume
    concat_rigids = MapNode(fsl.ConvertXFM(concat_xfm=True),
                            iterfield=['in_file'],
                            nested=True,
                            name='concat_rigids')
    wf.connect([(realign, concat_rigids, [('mat_file', 'in_file')]),
                (reg2dist, concat_rigids, [('out_matrix_file', 'in_file2')])])

    # Apply rigid transforms and warpfield to each EPI volume
    correct_epis = MapNode(fsl.ApplyWarp(interp='spline', relwarp=True),
                           iterfield=['in_file', 'ref_file', 'premat'],
                           nested=True,
                           name='correct_epis')

    get_warp = lambda warpfields: warpfields[0]
    wf.connect([(split_epis, correct_epis, [('out_files', 'in_file'),
                                            ('out_files', 'ref_file')]),
                (concat_rigids, correct_epis, [('out_file', 'premat')]),
                (unwarp_dist, correct_epis, [(('out_warps', get_warp),
                                              'field_file')])])

    # Merge processed files back into 4D nifti
    merge_epis = MapNode(fsl.Merge(dimension='t',
                                   merged_file='timeseries_corrected.nii.gz'),
                         iterfield='in_files',
                         name='merge_epis')
    wf.connect([(correct_epis, merge_epis, [('out_file', 'in_files')])])

    #---Copy important files to main directory---
    substitutions = [('_merge_epis%d/timeseries_corrected.nii.gz' % i, n)
                     for i, n in enumerate(session['out_names'])]
    ds = Node(DataSink(base_directory=os.path.abspath(session['out']),
                       substitutions=substitutions),
              name='outfiles')
    wf.connect(unwarp_dist, 'out_corrected', ds, '@unwarp_dist')
    wf.connect(mean_unwarped_dist, 'out_file', ds, '@mean_unwarped_dist')
    wf.connect(unwarp_sbref, 'out_corrected', ds, '@unwarp_sbref')
    wf.connect(reg2anat, 'out_reg_file', ds, '@reg2anat')
    wf.connect(merge_epis, 'merged_file', ds, '@merge_epis')

    return wf