Exemple #1
0
def init_phdiff_wf(omp_nthreads, phasetype='phasediff', name='phdiff_wf'):
    """
    Estimates the fieldmap using a phase-difference image and one or more
    magnitude images corresponding to two or more :abbr:`GRE (Gradient Echo sequence)`
    acquisitions. The `original code was taken from nipype
    <https://github.com/nipy/nipype/blob/master/nipype/workflows/dmri/fsl/artifacts.py#L514>`_.

    .. workflow ::
        :graph2use: orig
        :simple_form: yes

        from qsiprep.workflows.fieldmap.phdiff import init_phdiff_wf
        wf = init_phdiff_wf(omp_nthreads=1)


    Outputs::

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


    """

    workflow = Workflow(name=name)
    workflow.__desc__ = """\
A deformation field to correct for susceptibility distortions was estimated
based on a field map that was co-registered to the BOLD reference,
using a custom workflow of *fMRIPrep* derived from D. Greve's `epidewarp.fsl`
[script](http://www.nmr.mgh.harvard.edu/~greve/fbirn/b0/epidewarp.fsl) and
further improvements of HCP Pipelines [@hcppipelines].
"""

    inputnode = pe.Node(
        niu.IdentityInterface(fields=['magnitude', 'phasediff']),
        name='inputnode')

    outputnode = pe.Node(
        niu.IdentityInterface(fields=['fmap', 'fmap_ref', 'fmap_mask']),
        name='outputnode')

    # Merge input magnitude images
    magmrg = pe.Node(IntraModalMerge(), name='magmrg')

    # de-gradient the fields ("bias/illumination artifact")
    n4 = pe.Node(ants.N4BiasFieldCorrection(dimension=3, copy_header=True),
                 name='n4',
                 n_procs=omp_nthreads)
    bet = pe.Node(BETRPT(generate_report=True, frac=0.6, mask=True),
                  name='bet')
    ds_report_fmap_mask = pe.Node(DerivativesDataSink(desc='brain',
                                                      suffix='mask'),
                                  name='ds_report_fmap_mask',
                                  mem_gb=0.01,
                                  run_without_submitting=True)
    # uses mask from bet; outputs a mask
    # dilate = pe.Node(fsl.maths.MathsCommand(
    #     nan2zeros=True, args='-kernel sphere 5 -dilM'), name='MskDilate')

    # FSL PRELUDE will perform phase-unwrapping
    prelude = pe.Node(fsl.PRELUDE(), name='prelude')

    denoise = pe.Node(fsl.SpatialFilter(operation='median',
                                        kernel_shape='sphere',
                                        kernel_size=5),
                      name='denoise')

    demean = pe.Node(niu.Function(function=demean_image), name='demean')

    cleanup_wf = cleanup_edge_pipeline(name="cleanup_wf")

    compfmap = pe.Node(Phasediff2Fieldmap(), name='compfmap')

    # The phdiff2fmap interface is equivalent to:
    # rad2rsec (using rads2radsec from nipype.workflows.dmri.fsl.utils)
    # pre_fugue = pe.Node(fsl.FUGUE(save_fmap=True), name='ComputeFieldmapFUGUE')
    # rsec2hz (divide by 2pi)

    if phasetype == "phasediff":
        # Read phasediff echo times
        meta = pe.Node(ReadSidecarJSON(), name='meta', mem_gb=0.01)

        # phase diff -> radians
        pha2rads = pe.Node(niu.Function(function=siemens2rads),
                           name='pha2rads')
        # Read phasediff echo times
        meta = pe.Node(ReadSidecarJSON(),
                       name='meta',
                       mem_gb=0.01,
                       run_without_submitting=True)
        workflow.connect([
            (meta, compfmap, [('out_dict', 'metadata')]),
            (inputnode, pha2rads, [('phasediff', 'in_file')]),
            (pha2rads, prelude, [('out', 'phase_file')]),
            (inputnode, ds_report_fmap_mask, [('phasediff', 'source_file')]),
        ])

    elif phasetype == "phase":
        workflow.__desc__ += """\
The phase difference used for unwarping was calculated using two separate phase measurements
 [@pncprocessing].
    """
        # Special case for phase1, phase2 images
        meta = pe.MapNode(ReadSidecarJSON(),
                          name='meta',
                          mem_gb=0.01,
                          run_without_submitting=True,
                          iterfield=['in_file'])
        phases2fmap = pe.Node(Phases2Fieldmap(), name='phases2fmap')
        workflow.connect([
            (meta, phases2fmap, [('out_dict', 'metadatas')]),
            (inputnode, phases2fmap, [('phasediff', 'phase_files')]),
            (phases2fmap, prelude, [('out_file', 'phase_file')]),
            (phases2fmap, compfmap, [('phasediff_metadata', 'metadata')]),
            (phases2fmap, ds_report_fmap_mask, [('out_file', 'source_file')])
        ])

    workflow.connect([
        (inputnode, meta, [('phasediff', 'in_file')]),
        (inputnode, magmrg, [('magnitude', 'in_files')]),
        (magmrg, n4, [('out_avg', 'input_image')]),
        (n4, prelude, [('output_image', 'magnitude_file')]),
        (n4, bet, [('output_image', 'in_file')]),
        (bet, prelude, [('mask_file', 'mask_file')]),
        (prelude, denoise, [('unwrapped_phase_file', 'in_file')]),
        (denoise, demean, [('out_file', 'in_file')]),
        (demean, cleanup_wf, [('out', 'inputnode.in_file')]),
        (bet, cleanup_wf, [('mask_file', 'inputnode.in_mask')]),
        (cleanup_wf, compfmap, [('outputnode.out_file', 'in_file')]),
        (compfmap, outputnode, [('out_file', 'fmap')]),
        (bet, outputnode, [('mask_file', 'fmap_mask'),
                           ('out_file', 'fmap_ref')]),
        (bet, ds_report_fmap_mask, [('out_report', 'in_file')]),
    ])

    return workflow
def init_fmap_wf(omp_nthreads, fmap_bspline, name='fmap_wf'):
    """
    Fieldmap workflow - when we have a sequence that directly measures the fieldmap
    we just need to mask it (using the corresponding magnitude image) to remove the
    noise in the surrounding air region, and ensure that units are Hz.

    .. workflow ::
        :graph2use: orig
        :simple_form: yes

        from fmriprep.workflows.fieldmap.fmap import init_fmap_wf
        wf = init_fmap_wf(omp_nthreads=6, fmap_bspline=False)

    """

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

    # Merge input magnitude images
    magmrg = pe.Node(IntraModalMerge(), name='magmrg')
    # Merge input fieldmap images
    fmapmrg = pe.Node(IntraModalMerge(zero_based_avg=False, hmc=False),
                      name='fmapmrg')

    # de-gradient the fields ("bias/illumination artifact")
    n4_correct = pe.Node(ants.N4BiasFieldCorrection(dimension=3, copy_header=True),
                         name='n4_correct', n_procs=omp_nthreads)
    bet = pe.Node(BETRPT(generate_report=True, frac=0.6, mask=True),
                  name='bet')
    ds_fmap_mask = pe.Node(DerivativesDataSink(suffix='fmap_mask'),
                           name='ds_report_fmap_mask', run_without_submitting=True)

    workflow.connect([
        (inputnode, magmrg, [('magnitude', 'in_files')]),
        (inputnode, fmapmrg, [('fieldmap', 'in_files')]),
        (magmrg, n4_correct, [('out_file', 'input_image')]),
        (n4_correct, bet, [('output_image', 'in_file')]),
        (bet, outputnode, [('mask_file', 'fmap_mask'),
                           ('out_file', 'fmap_ref')]),
        (inputnode, ds_fmap_mask, [('fieldmap', 'source_file')]),
        (bet, ds_fmap_mask, [('out_report', 'in_file')]),
    ])

    if fmap_bspline:
        # despike_threshold=1.0, mask_erode=1),
        fmapenh = pe.Node(FieldEnhance(unwrap=False, despike=False),
                          name='fmapenh', mem_gb=4, n_procs=omp_nthreads)

        workflow.connect([
            (bet, fmapenh, [('mask_file', 'in_mask'),
                            ('out_file', 'in_magnitude')]),
            (fmapmrg, fmapenh, [('out_file', 'in_file')]),
            (fmapenh, outputnode, [('out_file', 'fmap')]),
        ])

    else:
        torads = pe.Node(FieldToRadS(), name='torads')
        prelude = pe.Node(fsl.PRELUDE(), name='prelude')
        tohz = pe.Node(FieldToHz(), name='tohz')

        denoise = pe.Node(fsl.SpatialFilter(operation='median', kernel_shape='sphere',
                                            kernel_size=3), name='denoise')
        demean = pe.Node(niu.Function(function=demean_image), name='demean')
        cleanup_wf = cleanup_edge_pipeline(name='cleanup_wf')

        applymsk = pe.Node(fsl.ApplyMask(), name='applymsk')

        workflow.connect([
            (bet, prelude, [('mask_file', 'mask_file'),
                            ('out_file', 'magnitude_file')]),
            (fmapmrg, torads, [('out_file', 'in_file')]),
            (torads, tohz, [('fmap_range', 'range_hz')]),
            (torads, prelude, [('out_file', 'phase_file')]),
            (prelude, tohz, [('unwrapped_phase_file', 'in_file')]),
            (tohz, denoise, [('out_file', 'in_file')]),
            (denoise, demean, [('out_file', 'in_file')]),
            (demean, cleanup_wf, [('out', 'inputnode.in_file')]),
            (bet, cleanup_wf, [('mask_file', 'inputnode.in_mask')]),
            (cleanup_wf, applymsk, [('outputnode.out_file', 'in_file')]),
            (bet, applymsk, [('mask_file', 'mask_file')]),
            (applymsk, outputnode, [('out_file', 'fmap')]),
        ])

    return workflow
Exemple #3
0
def vsm_fmb(name='VSM_FMB', phase_unwrap=True, fmb_params={}):
    """
    Workflow that uses `FUGUE <http://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FUGUE>`_
    to compute the voxel-shift map (VSM) from the corresponding B-fieldmap in
    EPI data.
    """
    wf = pe.Workflow(name=name)

    inputnode = pe.Node(niu.IdentityInterface(
        fields=['in_bmap', 'in_mask', 'echospacing', 'delta_te', 'acc_factor',
                'enc_dir']), name='inputnode')
    outputnode = pe.Node(niu.IdentityInterface(
        fields=['vsm', 'dfm', 'dfm_inv', 'jac', 'jac_inv']), name='outputnode')

    selmag = pe.Node(niu.Select(index=0), name='SelectMag')
    selpha = pe.Node(niu.Select(index=1), name='SelectPha')

    magmsk = pe.Node(fs.ApplyMask(), name='mask_mag')
    eff_es = pe.Node(niu.Function(
        input_names=['echospacing', 'acc_factor'], function=_eff_es_seg,
        output_names=['echospacing']), name='GetEffEcho')
    phcache = pe.Node(niu.IdentityInterface(fields=['pha_unwrapped']),
                      name='PhCache')

    rad2rsec = pe.Node(niu.Function(
        input_names=['in_file', 'delta_te'], output_names=['out_file'],
        function=nwu.rads2radsec), name='ToRadSec')
    pre_fugue = pe.Node(fsl.FUGUE(save_unmasked_fmap=True),
                        name='PreliminaryFugue')
    demean = pe.Node(niu.Function(
        function=nwu.demean_image, input_names=['in_file', 'in_mask'],
        output_names=['out_file']), name='DemeanFmap')
    cleanup = nwu.cleanup_edge_pipeline()
    addvol = pe.Node(niu.Function(
        function=nwu.add_empty_vol, input_names=['in_file'],
        output_names=['out_file']), name='AddEmptyVol')
    vsm = pe.Node(fsl.FUGUE(save_unmasked_shift=True, **fmb_params),
                  name="Compute_VSM")

    dfm = process_vsm()
    dfm.inputs.inputnode.scaling = 1.0

    wf.connect([
        (inputnode,   selmag,     [('in_bmap', 'inlist')]),
        (inputnode,   selpha,     [('in_bmap', 'inlist')]),
        (inputnode,   magmsk,     [('in_mask', 'mask_file')]),
        (inputnode,   eff_es,     [('echospacing', 'echospacing'),
                                   ('acc_factor', 'acc_factor')]),
        (selmag,      magmsk,     [('out', 'in_file')]),
        (phcache,     rad2rsec,   [('pha_unwrapped', 'in_file')]),
        (inputnode,   rad2rsec,   [('delta_te', 'delta_te')]),
        (rad2rsec,    pre_fugue,  [('out_file', 'fmap_in_file')]),
        (inputnode,   pre_fugue,  [('in_mask', 'mask_file')]),
        (pre_fugue,   demean,     [('fmap_out_file', 'in_file')]),
        (inputnode,   demean,     [('in_mask', 'in_mask')]),
        (demean,      cleanup,    [('out_file', 'inputnode.in_file')]),
        (inputnode,   cleanup,    [('in_mask', 'inputnode.in_mask')]),
        (cleanup,     addvol,     [('outputnode.out_file', 'in_file')]),
        (addvol,      vsm,        [('out_file', 'fmap_in_file')]),
        (eff_es,      vsm,        [('echospacing', 'dwell_time')]),
        (inputnode,   vsm,        [('in_mask', 'mask_file'),
                                   ('delta_te', 'asym_se_time')]),
        (vsm,         outputnode, [('shift_out_file', 'vsm')]),
        (vsm,         dfm,        [('shift_out_file', 'inputnode.vsm')]),
        (inputnode,   dfm,        [('in_mask', 'inputnode.reference'),
                                   ('enc_dir', 'inputnode.enc_dir')]),
        (dfm,         outputnode, [('outputnode.dfm', 'dfm'),
                                   ('outputnode.jacobian', 'jac'),
                                   ('outputnode.inv_dfm', 'dfm_inv'),
                                   ('outputnode.inv_jacobian', 'jac_inv')])
    ])

    if phase_unwrap:
        prelude = pe.Node(fsl.PRELUDE(process3d=True), name='PhaseUnwrap')
        wf.connect([
            (selmag,   prelude, [('out', 'magnitude_file')]),
            (selpha,   prelude, [('out', 'phase_file')]),
            (magmsk,   prelude, [('out_file', 'mask_file')]),
            (prelude,  phcache, [('unwrapped_phase_file', 'pha_unwrapped')])
        ])
    else:
        wf.connect(selpha, 'out', phcache, 'pha_unwrapped')
    return wf
Exemple #4
0
def init_fmap_wf(omp_nthreads, fmap_bspline, name='fmap_wf'):
    """
    Fieldmap workflow - when we have a sequence that directly measures the fieldmap
    we just need to mask it (using the corresponding magnitude image) to remove the
    noise in the surrounding air region, and ensure that units are Hz.

    .. workflow ::
        :graph2use: orig
        :simple_form: yes

        from fmriprep.workflows.fieldmap.fmap import init_fmap_wf
        wf = init_fmap_wf(omp_nthreads=6, fmap_bspline=False)

    """

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

    # Merge input magnitude images
    magmrg = pe.Node(IntraModalMerge(), name='magmrg')
    # Merge input fieldmap images
    fmapmrg = pe.Node(IntraModalMerge(zero_based_avg=False, hmc=False),
                      name='fmapmrg')

    # de-gradient the fields ("bias/illumination artifact")
    n4_correct = pe.Node(ants.N4BiasFieldCorrection(dimension=3,
                                                    copy_header=True),
                         name='n4_correct',
                         n_procs=omp_nthreads)
    bet = pe.Node(BETRPT(generate_report=True, frac=0.6, mask=True),
                  name='bet')
    ds_fmap_mask = pe.Node(DerivativesDataSink(suffix='fmap_mask'),
                           name='ds_report_fmap_mask',
                           run_without_submitting=True)

    workflow.connect([
        (inputnode, magmrg, [('magnitude', 'in_files')]),
        (inputnode, fmapmrg, [('fieldmap', 'in_files')]),
        (magmrg, n4_correct, [('out_file', 'input_image')]),
        (n4_correct, bet, [('output_image', 'in_file')]),
        (bet, outputnode, [('mask_file', 'fmap_mask'),
                           ('out_file', 'fmap_ref')]),
        (inputnode, ds_fmap_mask, [('fieldmap', 'source_file')]),
        (bet, ds_fmap_mask, [('out_report', 'in_file')]),
    ])

    if fmap_bspline:
        # despike_threshold=1.0, mask_erode=1),
        fmapenh = pe.Node(FieldEnhance(unwrap=False, despike=False),
                          name='fmapenh',
                          mem_gb=4,
                          n_procs=omp_nthreads)

        workflow.connect([
            (bet, fmapenh, [('mask_file', 'in_mask'),
                            ('out_file', 'in_magnitude')]),
            (fmapmrg, fmapenh, [('out_file', 'in_file')]),
            (fmapenh, outputnode, [('out_file', 'fmap')]),
        ])

    else:
        torads = pe.Node(FieldToRadS(), name='torads')
        prelude = pe.Node(fsl.PRELUDE(), name='prelude')
        tohz = pe.Node(FieldToHz(), name='tohz')

        denoise = pe.Node(fsl.SpatialFilter(operation='median',
                                            kernel_shape='sphere',
                                            kernel_size=3),
                          name='denoise')
        demean = pe.Node(niu.Function(function=demean_image), name='demean')
        cleanup_wf = cleanup_edge_pipeline(name='cleanup_wf')

        applymsk = pe.Node(fsl.ApplyMask(), name='applymsk')

        workflow.connect([
            (bet, prelude, [('mask_file', 'mask_file'),
                            ('out_file', 'magnitude_file')]),
            (fmapmrg, torads, [('out_file', 'in_file')]),
            (torads, tohz, [('fmap_range', 'range_hz')]),
            (torads, prelude, [('out_file', 'phase_file')]),
            (prelude, tohz, [('unwrapped_phase_file', 'in_file')]),
            (tohz, denoise, [('out_file', 'in_file')]),
            (denoise, demean, [('out_file', 'in_file')]),
            (demean, cleanup_wf, [('out', 'inputnode.in_file')]),
            (bet, cleanup_wf, [('mask_file', 'inputnode.in_mask')]),
            (cleanup_wf, applymsk, [('outputnode.out_file', 'in_file')]),
            (bet, applymsk, [('mask_file', 'mask_file')]),
            (applymsk, outputnode, [('out_file', 'fmap')]),
        ])

    return workflow
def susceptibility_distortion_correction_using_phasediff_fmap(
        fugue_params=dict(smooth3d=2.0),
        register_fmap_on_b0=True,
        name='susceptibility_distortion_correction_using_phasediff_fmap'):
    """
    The fieldmap based method implements susceptibility distortion correction
    by using a mapping of the B0 field as proposed by [Jezzard95]_.
    This workflow uses the implementation of FSL
    (`FUGUE <http://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FUGUE>`_). Phase
    unwrapping is performed using
    `PRELUDE <http://fsl.fmrib.ox.ac.uk/fsl/fsl-4.1.9/fugue/prelude.html>`_
    [Jenkinson03]_. Preparation of the fieldmap is performed reproducing the
    script in FSL `fsl_prepare_fieldmap
    <http://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FUGUE/Guide#SIEMENS_data>`_.

    Args:
        fugue_params: Regularisation to apply to the fieldmap with a
            3D Gaussian smoothing (default: 2.0)
        register_fmap_on_b0: Register the fmap on the b0 or not. If the fmap
            is already well aligned and
        name:

    Inputnode
        in_file (str): DWI dataset.
        in_bval (str): Bval file.
        in_mask (str): Mask file.
        in_fmap_magnitude (str): Magnitude fieldmap. Chose the fmap with the
            best contrast.
        in_fmap_phasediff (str): Phase difference fieldmap.
        delta_echo_time (float): Difference of echo time of the
        effective_echo_spacing (float):
        phase_encoding_direction (str):

    Outputnode:
        out_file (str): Output.
        out_vsm (str): The set of DWI volumes.
        out_warp (str): The bvalues corresponding to the out_dwi.


    .. warning:: Only SIEMENS format fieldmaps are supported.

    .. admonition:: References
<
      .. [Jezzard95] Jezzard P, and Balaban RS, `Correction for geometric
        distortion in echo planar images from B0 field variations
        <http://dx.doi.org/10.1002/mrm.1910340111>`_,
        MRM 34(1):65-73. (1995). doi: 10.1002/mrm.1910340111.

      .. [Jenkinson03] Jenkinson M., `Fast, automated, N-dimensional
        phase-unwrapping algorithm <http://dx.doi.org/10.1002/mrm.10354>`_,
        MRM 49(1):193-197, 2003, doi: 10.1002/mrm.10354.
    """
    import nipype.pipeline.engine as pe
    import nipype.interfaces.utility as niu
    import nipype.interfaces.fsl as fsl
    import nipype.interfaces.ants as ants

    from clinica.utils.epi import bids_dir_to_fsl_dir
    from clinica.utils.fmap import resample_fmap_to_b0

    from nipype.workflows.dmri.fsl.utils import (rads2radsec, siemens2rads,
                                                 vsm2warp, add_empty_vol,
                                                 cleanup_edge_pipeline,
                                                 demean_image)

    inputnode = pe.Node(niu.IdentityInterface(fields=[
        'in_dwi', 'in_mask', 'in_fmap_phasediff', 'in_fmap_magnitude',
        'delta_echo_time', 'effective_echo_spacing', 'phase_encoding_direction'
    ]),
                        name='inputnode')
    outputnode = pe.Node(niu.IdentityInterface(
        fields=['out_file', 'out_vsm', 'out_warp', 'out_prepared_fmap']),
                         name='outputnode')

    fsl_dir = pe.Node(niu.Function(input_names=['bids_dir'],
                                   output_names=['fsl_dir'],
                                   function=bids_dir_to_fsl_dir),
                      name='ConvertToFslDir')

    get_b0 = pe.Node(fsl.ExtractROI(t_min=0, t_size=1), name='GetB0')

    first_mag = pe.Node(fsl.ExtractROI(t_min=0, t_size=1), name='GetFirst')

    n4 = pe.Node(ants.N4BiasFieldCorrection(dimension=3),
                 name='N4MagnitudeFmap')

    bet = pe.Node(fsl.BET(frac=0.4, mask=True), name='BetN4MagnitudeFmap')

    dilate = pe.Node(fsl.maths.MathsCommand(nan2zeros=True,
                                            args='-kernel sphere 5 -dilM'),
                     name='DilateBet')

    pha2rads = pe.Node(niu.Function(input_names=['in_file'],
                                    output_names=['out_file'],
                                    function=siemens2rads),
                       name='PreparePhase')

    prelude = pe.Node(fsl.PRELUDE(process3d=True), name='PhaseUnwrap')

    rad2rsec = pe.Node(niu.Function(input_names=['in_file', 'delta_te'],
                                    output_names=['out_file'],
                                    function=rads2radsec),
                       name='ToRadSec')

    # Node when we register the fmap onto the b0
    fmm2b0 = pe.Node(ants.Registration(output_warped_image=True),
                     name="FmapMagnitudeToB0")
    fmm2b0.inputs.transforms = ['Rigid'] * 2
    fmm2b0.inputs.transform_parameters = [(1.0, )] * 2
    fmm2b0.inputs.number_of_iterations = [[50], [20]]
    fmm2b0.inputs.dimension = 3
    fmm2b0.inputs.metric = ['Mattes', 'Mattes']
    fmm2b0.inputs.metric_weight = [1.0] * 2
    fmm2b0.inputs.radius_or_number_of_bins = [64, 64]
    fmm2b0.inputs.sampling_strategy = ['Regular', 'Random']
    fmm2b0.inputs.sampling_percentage = [None, 0.2]
    fmm2b0.inputs.convergence_threshold = [1.e-5, 1.e-8]
    fmm2b0.inputs.convergence_window_size = [20, 10]
    fmm2b0.inputs.smoothing_sigmas = [[6.0], [2.0]]
    fmm2b0.inputs.sigma_units = ['vox'] * 2
    fmm2b0.inputs.shrink_factors = [[6], [1]]  # ,[1] ]
    fmm2b0.inputs.use_estimate_learning_rate_once = [True] * 2
    fmm2b0.inputs.use_histogram_matching = [True] * 2
    fmm2b0.inputs.initial_moving_transform_com = 0
    fmm2b0.inputs.collapse_output_transforms = True
    fmm2b0.inputs.winsorize_upper_quantile = 0.995

    # Node when we resample the fmap onto the b0
    res_fmap = pe.Node(niu.Function(
        input_names=['in_fmap', 'in_b0', 'out_file'],
        output_names=['out_resampled_fmap'],
        function=resample_fmap_to_b0),
                       name='ResampleFmap')

    apply_xfm = pe.Node(ants.ApplyTransforms(dimension=3,
                                             interpolation='BSpline'),
                        name='FmapPhaseToB0')

    pre_fugue = pe.Node(fsl.FUGUE(save_fmap=True), name='PreliminaryFugue')

    demean = pe.Node(niu.Function(input_names=['in_file', 'in_mask'],
                                  output_names=['out_file'],
                                  function=demean_image),
                     name='DemeanFmap')

    cleanup = cleanup_edge_pipeline()

    add_vol = pe.Node(niu.Function(input_names=['in_file'],
                                   output_names=['out_file'],
                                   function=add_empty_vol),
                      name='AddEmptyVol')

    vsm = pe.Node(fsl.FUGUE(save_shift=True, **fugue_params),
                  name="ComputeVSM")

    split = pe.Node(fsl.Split(dimension='t'), name='SplitDWIs')

    merge = pe.Node(fsl.Merge(dimension='t'), name='MergeDWIs')

    unwarp = pe.MapNode(fsl.FUGUE(icorr=True, forward_warping=False),
                        iterfield=['in_file'],
                        name='UnwarpDWIs')

    thres = pe.MapNode(fsl.Threshold(thresh=0.0),
                       iterfield=['in_file'],
                       name='RemoveNegative')

    vsm2dfm = vsm2warp()
    vsm2dfm.inputs.inputnode.scaling = 1.0

    wf = pe.Workflow(name=name)
    wf.connect([
        (inputnode, fsl_dir, [('phase_encoding_direction', 'bids_dir')
                              ]),  # noqa
        (inputnode, pha2rads, [('in_fmap_phasediff', 'in_file')]),  # noqa
        (inputnode, get_b0, [('in_dwi', 'in_file')]),  # noqa
        (inputnode, first_mag, [('in_fmap_magnitude', 'in_file')]),  # noqa
        (first_mag, n4, [('roi_file', 'input_image')]),  # noqa
        (n4, bet, [('output_image', 'in_file')]),  # noqa
        (bet, dilate, [('mask_file', 'in_file')]),  # noqa
        (pha2rads, prelude, [('out_file', 'phase_file')]),  # noqa
        (n4, prelude, [('output_image', 'magnitude_file')]),  # noqa
        (dilate, prelude, [('out_file', 'mask_file')]),  # noqa
        (prelude, rad2rsec, [('unwrapped_phase_file', 'in_file')]),  # noqa
        (inputnode, rad2rsec, [('delta_echo_time', 'delta_te')]),  # noqa
    ])
    if register_fmap_on_b0:
        wf.connect([
            (get_b0, fmm2b0, [('roi_file', 'fixed_image')]),  # noqa
            (n4, fmm2b0, [('output_image', 'moving_image')]),  # noqa
            (inputnode, fmm2b0, [('in_mask', 'fixed_image_mask')]),  # noqa
            (dilate, fmm2b0, [('out_file', 'moving_image_mask')]),  # noqa
            (get_b0, apply_xfm, [('roi_file', 'reference_image')]),  # noqa
            (rad2rsec, apply_xfm, [('out_file', 'input_image')]),  # noqa
            (
                fmm2b0,
                apply_xfm,
                [
                    ('forward_transforms', 'transforms'),  # noqa
                    ('forward_invert_flags', 'invert_transform_flags')
                ]),  # noqa
            (apply_xfm, pre_fugue, [('output_image', 'fmap_in_file')]),  # noqa
            (inputnode, pre_fugue, [('in_mask', 'mask_file')]),  # noqa
            (apply_xfm, outputnode, [('output_image', 'out_prepared_fmap')]
             )  # noqa
        ])
    else:
        wf.connect([
            (get_b0, res_fmap, [('roi_file', 'in_b0')]),  # noqa
            (rad2rsec, res_fmap, [('out_file', 'in_fmap')]),  # noqa
            (res_fmap, pre_fugue, [('out_resampled_fmap', 'fmap_in_file')
                                   ]),  # noqa
            (inputnode, pre_fugue, [('in_mask', 'mask_file')]),  # noqa
            (res_fmap, outputnode, [('out_resampled_fmap', 'out_prepared_fmap')
                                    ])  # noqa
        ])
    wf.connect([
        (pre_fugue, demean, [('fmap_out_file', 'in_file')]),  # noqa
        (inputnode, demean, [('in_mask', 'in_mask')]),  # noqa
        (demean, cleanup, [('out_file', 'inputnode.in_file')]),  # noqa
        (inputnode, cleanup, [('in_mask', 'inputnode.in_mask')]),  # noqa
        (cleanup, add_vol, [('outputnode.out_file', 'in_file')]),  # noqa
        (inputnode, vsm, [('in_mask', 'mask_file')]),  # noqa
        (add_vol, vsm, [('out_file', 'fmap_in_file')]),  # noqa
        (inputnode, vsm, [('delta_echo_time', 'asym_se_time')]),  # noqa
        (inputnode, vsm, [('effective_echo_spacing', 'dwell_time')]),  # noqa
        (inputnode, split, [('in_dwi', 'in_file')]),  # noqa
        (split, unwarp, [('out_files', 'in_file')]),  # noqa
        (vsm, unwarp, [('shift_out_file', 'shift_in_file')]),  # noqa
        (fsl_dir, unwarp, [('fsl_dir', 'unwarp_direction')]),  # noqa
        (unwarp, thres, [('unwarped_file', 'in_file')]),  # noqa
        (thres, merge, [('out_file', 'in_files')]),  # noqa
        (merge, vsm2dfm, [('merged_file', 'inputnode.in_ref')]),  # noqa
        (vsm, vsm2dfm, [('shift_out_file', 'inputnode.in_vsm')]),  # noqa
        (fsl_dir, vsm2dfm, [('fsl_dir', 'inputnode.enc_dir')]),  # noqa
        (rad2rsec, outputnode, [('out_file', 'out_native_fmap')]),  # noqa
        (merge, outputnode, [('merged_file', 'out_file')]),  # noqa
        (vsm, outputnode, [('shift_out_file', 'out_vsm')]),  # noqa
        (vsm2dfm, outputnode, [('outputnode.out_warp', 'out_warp')]),  # noqa
    ])

    return wf
Exemple #6
0
def init_phdiff_wf(omp_nthreads, name='phdiff_wf'):
    """
    Distortion correction of EPI sequences using phase-difference maps.

    Estimates the fieldmap using a phase-difference image and one or more
    magnitude images corresponding to two or more :abbr:`GRE (Gradient Echo sequence)`
    acquisitions. The `original code was taken from nipype
    <https://github.com/nipy/nipype/blob/master/nipype/workflows/dmri/fsl/artifacts.py#L514>`_.

    .. workflow ::
        :graph2use: orig
        :simple_form: yes

        from sdcflows.workflows.phdiff import init_phdiff_wf
        wf = init_phdiff_wf(omp_nthreads=1)

    **Parameters**:

        omp_nthreads : int
            Maximum number of threads an individual process may use

    **Inputs**:

        magnitude : pathlike
            Path to the corresponding magnitude path(s).
        phasediff : pathlike
            Path to the corresponding phase-difference file.
        metadata : dict
            Metadata dictionary corresponding to the phasediff input

    **Outputs**:

        fmap_ref : pathlike
            The average magnitude image, skull-stripped
        fmap_mask : pathlike
            The brain mask applied to the fieldmap
        fmap : pathlike
            The estimated fieldmap in Hz

    """
    workflow = Workflow(name=name)
    workflow.__desc__ = """\
A deformation field to correct for susceptibility distortions was estimated
based on a field map that was co-registered to the BOLD reference,
using a custom workflow of *fMRIPrep* derived from D. Greve's `epidewarp.fsl`
[script](http://www.nmr.mgh.harvard.edu/~greve/fbirn/b0/epidewarp.fsl) and
further improvements of HCP Pipelines [@hcppipelines].
"""

    inputnode = pe.Node(
        niu.IdentityInterface(fields=['magnitude', 'phasediff', 'metadata']),
        name='inputnode')

    outputnode = pe.Node(
        niu.IdentityInterface(fields=['fmap', 'fmap_ref', 'fmap_mask']),
        name='outputnode')

    # Merge input magnitude images
    magmrg = pe.Node(IntraModalMerge(), name='magmrg')

    # de-gradient the fields ("bias/illumination artifact")
    n4 = pe.Node(ants.N4BiasFieldCorrection(dimension=3, copy_header=True),
                 name='n4',
                 n_procs=omp_nthreads)
    bet = pe.Node(BETRPT(generate_report=True, frac=0.6, mask=True),
                  name='bet')

    # uses mask from bet; outputs a mask
    # dilate = pe.Node(fsl.maths.MathsCommand(
    #     nan2zeros=True, args='-kernel sphere 5 -dilM'), name='MskDilate')

    # phase diff -> radians
    pha2rads = pe.Node(niu.Function(function=siemens2rads), name='pha2rads')

    # FSL PRELUDE will perform phase-unwrapping
    prelude = pe.Node(fsl.PRELUDE(), name='prelude')

    denoise = pe.Node(fsl.SpatialFilter(operation='median',
                                        kernel_shape='sphere',
                                        kernel_size=3),
                      name='denoise')

    demean = pe.Node(niu.Function(function=demean_image), name='demean')

    cleanup_wf = cleanup_edge_pipeline(name="cleanup_wf")

    compfmap = pe.Node(Phasediff2Fieldmap(), name='compfmap')

    # The phdiff2fmap interface is equivalent to:
    # rad2rsec (using rads2radsec from nipype.workflows.dmri.fsl.utils)
    # pre_fugue = pe.Node(fsl.FUGUE(save_fmap=True), name='ComputeFieldmapFUGUE')
    # rsec2hz (divide by 2pi)

    workflow.connect([
        (inputnode, compfmap, [('metadata', 'metadata')]),
        (inputnode, magmrg, [('magnitude', 'in_files')]),
        (magmrg, n4, [('out_avg', 'input_image')]),
        (n4, prelude, [('output_image', 'magnitude_file')]),
        (n4, bet, [('output_image', 'in_file')]),
        (bet, prelude, [('mask_file', 'mask_file')]),
        (inputnode, pha2rads, [('phasediff', 'in_file')]),
        (pha2rads, prelude, [('out', 'phase_file')]),
        (prelude, denoise, [('unwrapped_phase_file', 'in_file')]),
        (denoise, demean, [('out_file', 'in_file')]),
        (demean, cleanup_wf, [('out', 'inputnode.in_file')]),
        (bet, cleanup_wf, [('mask_file', 'inputnode.in_mask')]),
        (cleanup_wf, compfmap, [('outputnode.out_file', 'in_file')]),
        (compfmap, outputnode, [('out_file', 'fmap')]),
        (bet, outputnode, [('mask_file', 'fmap_mask'),
                           ('out_file', 'fmap_ref')]),
    ])

    return workflow
Exemple #7
0
def init_phdiff_wf(omp_nthreads, name='phdiff_wf'):
    """
    Estimates the fieldmap using a phase-difference image and one or more
    magnitude images corresponding to two or more :abbr:`GRE (Gradient Echo sequence)`
    acquisitions. The `original code was taken from nipype
    <https://github.com/nipy/nipype/blob/master/nipype/workflows/dmri/fsl/artifacts.py#L514>`_.

    .. workflow ::
        :graph2use: orig
        :simple_form: yes

        from fmriprep.workflows.fieldmap.phdiff import init_phdiff_wf
        wf = init_phdiff_wf(omp_nthreads=1)


    Outputs::

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


    """

    inputnode = pe.Node(
        niu.IdentityInterface(fields=['magnitude', 'phasediff']),
        name='inputnode')

    outputnode = pe.Node(
        niu.IdentityInterface(fields=['fmap', 'fmap_ref', 'fmap_mask']),
        name='outputnode')

    def _pick1st(inlist):
        return inlist[0]

    # Read phasediff echo times
    meta = pe.Node(ReadSidecarJSON(),
                   name='meta',
                   mem_gb=0.01,
                   run_without_submitting=True)

    # Merge input magnitude images
    magmrg = pe.Node(IntraModalMerge(), name='magmrg')

    # de-gradient the fields ("bias/illumination artifact")
    n4 = pe.Node(ants.N4BiasFieldCorrection(dimension=3, copy_header=True),
                 name='n4',
                 n_procs=omp_nthreads)
    bet = pe.Node(BETRPT(generate_report=True, frac=0.6, mask=True),
                  name='bet')
    ds_fmap_mask = pe.Node(DerivativesDataSink(suffix='fmap_mask'),
                           name='ds_report_fmap_mask',
                           mem_gb=0.01,
                           run_without_submitting=True)
    # uses mask from bet; outputs a mask
    # dilate = pe.Node(fsl.maths.MathsCommand(
    #     nan2zeros=True, args='-kernel sphere 5 -dilM'), name='MskDilate')

    # phase diff -> radians
    pha2rads = pe.Node(niu.Function(function=siemens2rads), name='pha2rads')

    # FSL PRELUDE will perform phase-unwrapping
    prelude = pe.Node(fsl.PRELUDE(), name='prelude')

    denoise = pe.Node(fsl.SpatialFilter(operation='median',
                                        kernel_shape='sphere',
                                        kernel_size=3),
                      name='denoise')

    demean = pe.Node(niu.Function(function=demean_image), name='demean')

    cleanup_wf = cleanup_edge_pipeline(name="cleanup_wf")

    compfmap = pe.Node(Phasediff2Fieldmap(), name='compfmap')

    # The phdiff2fmap interface is equivalent to:
    # rad2rsec (using rads2radsec from nipype.workflows.dmri.fsl.utils)
    # pre_fugue = pe.Node(fsl.FUGUE(save_fmap=True), name='ComputeFieldmapFUGUE')
    # rsec2hz (divide by 2pi)

    workflow = pe.Workflow(name=name)
    workflow.connect([
        (inputnode, meta, [('phasediff', 'in_file')]),
        (inputnode, magmrg, [('magnitude', 'in_files')]),
        (magmrg, n4, [('out_avg', 'input_image')]),
        (n4, prelude, [('output_image', 'magnitude_file')]),
        (n4, bet, [('output_image', 'in_file')]),
        (bet, prelude, [('mask_file', 'mask_file')]),
        (inputnode, pha2rads, [('phasediff', 'in_file')]),
        (pha2rads, prelude, [('out', 'phase_file')]),
        (meta, compfmap, [('out_dict', 'metadata')]),
        (prelude, denoise, [('unwrapped_phase_file', 'in_file')]),
        (denoise, demean, [('out_file', 'in_file')]),
        (demean, cleanup_wf, [('out', 'inputnode.in_file')]),
        (bet, cleanup_wf, [('mask_file', 'inputnode.in_mask')]),
        (cleanup_wf, compfmap, [('outputnode.out_file', 'in_file')]),
        (compfmap, outputnode, [('out_file', 'fmap')]),
        (bet, outputnode, [('mask_file', 'fmap_mask'),
                           ('out_file', 'fmap_ref')]),
        (inputnode, ds_fmap_mask, [('phasediff', 'source_file')]),
        (bet, ds_fmap_mask, [('out_report', 'in_file')]),
    ])

    return workflow
def phase_diff_and_magnitudes(name='phase_diff_and_magnitudes'):
    """
    Estimates the fieldmap using a phase-difference image and one or more
    magnitude images corresponding to two or more :abbr:`GRE (Gradient Echo sequence)`
    acquisitions. The `original code was taken from nipype
    <https://github.com/nipy/nipype/blob/master/nipype/workflows/dmri/fsl/artifacts.py#L514>`_.

    Outputs::

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


    """
    inputnode = pe.Node(niu.IdentityInterface(fields=['input_images']),
                        name='inputnode')

    outputnode = pe.Node(
        niu.IdentityInterface(fields=['fmap_ref', 'fmap_mask', 'fmap']),
        name='outputnode')

    sortfmaps = pe.Node(niu.Function(function=_sort_fmaps,
                                     input_names=['input_images'],
                                     output_names=['magnitude', 'phasediff']),
                        name='SortFmaps')

    def _pick1st(inlist):
        return inlist[0]

    # Read phasediff echo times
    meta = pe.Node(ReadSidecarJSON(fields=['EchoTime1', 'EchoTime2']),
                   name='metadata')
    dte = pe.Node(niu.Function(input_names=['in_values'],
                               output_names=['delta_te'],
                               function=_delta_te),
                  name='ComputeDeltaTE')

    # Merge input magnitude images
    magmrg = pe.Node(IntraModalMerge(), name='MagnitudeFuse')

    # de-gradient the fields ("bias/illumination artifact")
    n4 = pe.Node(ants.N4BiasFieldCorrection(dimension=3), name='MagnitudeBias')
    bet = pe.Node(fsl.BET(frac=0.6, mask=True), name='MagnitudeBET')
    # uses mask from bet; outputs a mask
    # dilate = pe.Node(fsl.maths.MathsCommand(
    #     nan2zeros=True, args='-kernel sphere 5 -dilM'), name='MskDilate')

    # phase diff -> radians
    pha2rads = pe.Node(niu.Function(input_names=['in_file'],
                                    output_names=['out_file'],
                                    function=siemens2rads),
                       name='PreparePhase')

    # FSL PRELUDE will perform phase-unwrapping
    prelude = pe.Node(fsl.PRELUDE(process3d=True), name='PhaseUnwrap')

    denoise = pe.Node(fsl.SpatialFilter(operation='median',
                                        kernel_shape='sphere',
                                        kernel_size=3),
                      name='PhaseDenoise')

    demean = pe.Node(niu.Function(input_names=['in_file', 'in_mask'],
                                  output_names=['out_file'],
                                  function=demean_image),
                     name='DemeanFmap')

    cleanup = cleanup_edge_pipeline()

    compfmap = pe.Node(niu.Function(input_names=['in_file', 'delta_te'],
                                    output_names=['out_file'],
                                    function=phdiff2fmap),
                       name='ComputeFieldmap')

    # The phdiff2fmap interface is equivalent to:
    # rad2rsec (using rads2radsec from nipype.workflows.dmri.fsl.utils)
    # pre_fugue = pe.Node(fsl.FUGUE(save_fmap=True), name='ComputeFieldmapFUGUE')
    # rsec2hz (divide by 2pi)

    workflow = pe.Workflow(name=name)
    workflow.connect([
        (inputnode, sortfmaps, [('input_images', 'input_images')]),
        (sortfmaps, meta, [(('phasediff', _pick1st), 'in_file')]),
        (sortfmaps, magmrg, [('magnitude', 'in_files')]),
        (magmrg, n4, [('out_avg', 'input_image')]),
        (n4, prelude, [('output_image', 'magnitude_file')]),
        (n4, bet, [('output_image', 'in_file')]),
        (bet, prelude, [('mask_file', 'mask_file')]),
        (sortfmaps, pha2rads, [(('phasediff', _pick1st), 'in_file')]),
        (pha2rads, prelude, [('out_file', 'phase_file')]),
        (meta, dte, [('out_dict', 'in_values')]),
        (dte, compfmap, [('delta_te', 'delta_te')]),
        (prelude, denoise, [('unwrapped_phase_file', 'in_file')]),
        (denoise, demean, [('out_file', 'in_file')]),
        (demean, cleanup, [('out_file', 'inputnode.in_file')]),
        (bet, cleanup, [('mask_file', 'inputnode.in_mask')]),
        (cleanup, compfmap, [('outputnode.out_file', 'in_file')]),
        (compfmap, outputnode, [('out_file', 'fmap')]),
        (bet, outputnode, [('mask_file', 'fmap_mask'),
                           ('out_file', 'fmap_ref')])
    ])

    return workflow
Exemple #9
0
def init_phdiff_wf(omp_nthreads, name='phdiff_wf'):
    """
    Estimates the fieldmap using a phase-difference image and one or more
    magnitude images corresponding to two or more :abbr:`GRE (Gradient Echo sequence)`
    acquisitions. The `original code was taken from nipype
    <https://github.com/nipy/nipype/blob/master/nipype/workflows/dmri/fsl/artifacts.py#L514>`_.

    .. workflow ::
        :graph2use: orig
        :simple_form: yes

        from fmriprep.workflows.fieldmap.phdiff import init_phdiff_wf
        wf = init_phdiff_wf(omp_nthreads=1)


    Outputs::

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


    """

    inputnode = pe.Node(niu.IdentityInterface(fields=['magnitude', 'phasediff']),
                        name='inputnode')

    outputnode = pe.Node(niu.IdentityInterface(
        fields=['fmap', 'fmap_ref', 'fmap_mask']), name='outputnode')

    def _pick1st(inlist):
        return inlist[0]

    # Read phasediff echo times
    meta = pe.Node(ReadSidecarJSON(), name='meta', mem_gb=0.01, run_without_submitting=True)

    # Merge input magnitude images
    magmrg = pe.Node(IntraModalMerge(), name='magmrg')

    # de-gradient the fields ("bias/illumination artifact")
    n4 = pe.Node(ants.N4BiasFieldCorrection(dimension=3, copy_header=True),
                 name='n4', n_procs=omp_nthreads)
    bet = pe.Node(BETRPT(generate_report=True, frac=0.6, mask=True),
                  name='bet')
    ds_fmap_mask = pe.Node(DerivativesDataSink(suffix='fmap_mask'), name='ds_report_fmap_mask',
                           mem_gb=0.01, run_without_submitting=True)
    # uses mask from bet; outputs a mask
    # dilate = pe.Node(fsl.maths.MathsCommand(
    #     nan2zeros=True, args='-kernel sphere 5 -dilM'), name='MskDilate')

    # phase diff -> radians
    pha2rads = pe.Node(niu.Function(function=siemens2rads), name='pha2rads')

    # FSL PRELUDE will perform phase-unwrapping
    prelude = pe.Node(fsl.PRELUDE(), name='prelude')

    denoise = pe.Node(fsl.SpatialFilter(operation='median', kernel_shape='sphere',
                                        kernel_size=3), name='denoise')

    demean = pe.Node(niu.Function(function=demean_image), name='demean')

    cleanup_wf = cleanup_edge_pipeline(name="cleanup_wf")

    compfmap = pe.Node(Phasediff2Fieldmap(), name='compfmap')

    # The phdiff2fmap interface is equivalent to:
    # rad2rsec (using rads2radsec from nipype.workflows.dmri.fsl.utils)
    # pre_fugue = pe.Node(fsl.FUGUE(save_fmap=True), name='ComputeFieldmapFUGUE')
    # rsec2hz (divide by 2pi)

    workflow = pe.Workflow(name=name)
    workflow.connect([
        (inputnode, meta, [('phasediff', 'in_file')]),
        (inputnode, magmrg, [('magnitude', 'in_files')]),
        (magmrg, n4, [('out_avg', 'input_image')]),
        (n4, prelude, [('output_image', 'magnitude_file')]),
        (n4, bet, [('output_image', 'in_file')]),
        (bet, prelude, [('mask_file', 'mask_file')]),
        (inputnode, pha2rads, [('phasediff', 'in_file')]),
        (pha2rads, prelude, [('out', 'phase_file')]),
        (meta, compfmap, [('out_dict', 'metadata')]),
        (prelude, denoise, [('unwrapped_phase_file', 'in_file')]),
        (denoise, demean, [('out_file', 'in_file')]),
        (demean, cleanup_wf, [('out', 'inputnode.in_file')]),
        (bet, cleanup_wf, [('mask_file', 'inputnode.in_mask')]),
        (cleanup_wf, compfmap, [('outputnode.out_file', 'in_file')]),
        (compfmap, outputnode, [('out_file', 'fmap')]),
        (bet, outputnode, [('mask_file', 'fmap_mask'),
                           ('out_file', 'fmap_ref')]),
        (inputnode, ds_fmap_mask, [('phasediff', 'source_file')]),
        (bet, ds_fmap_mask, [('out_report', 'in_file')]),
    ])

    return workflow
Exemple #10
0
def vsm_fmb(name='VSM_FMB', phase_unwrap=True, fmb_params={}):
    """
    Workflow that uses `FUGUE <http://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FUGUE>`_
    to compute the voxel-shift map (VSM) from the corresponding B-fieldmap in
    EPI data.
    """
    wf = pe.Workflow(name=name)

    inputnode = pe.Node(niu.IdentityInterface(fields=[
        'in_bmap', 'in_mask', 'echospacing', 'delta_te', 'acc_factor',
        'enc_dir'
    ]),
                        name='inputnode')
    outputnode = pe.Node(niu.IdentityInterface(
        fields=['vsm', 'dfm', 'dfm_inv', 'jac', 'jac_inv']),
                         name='outputnode')

    selmag = pe.Node(niu.Select(index=0), name='SelectMag')
    selpha = pe.Node(niu.Select(index=1), name='SelectPha')

    magmsk = pe.Node(fs.ApplyMask(), name='mask_mag')
    eff_es = pe.Node(niu.Function(input_names=['echospacing', 'acc_factor'],
                                  function=_eff_es_seg,
                                  output_names=['echospacing']),
                     name='GetEffEcho')
    phcache = pe.Node(niu.IdentityInterface(fields=['pha_unwrapped']),
                      name='PhCache')

    rad2rsec = pe.Node(niu.Function(input_names=['in_file', 'delta_te'],
                                    output_names=['out_file'],
                                    function=nwu.rads2radsec),
                       name='ToRadSec')
    pre_fugue = pe.Node(fsl.FUGUE(save_unmasked_fmap=True),
                        name='PreliminaryFugue')
    demean = pe.Node(niu.Function(function=nwu.demean_image,
                                  input_names=['in_file', 'in_mask'],
                                  output_names=['out_file']),
                     name='DemeanFmap')
    cleanup = nwu.cleanup_edge_pipeline()
    addvol = pe.Node(niu.Function(function=nwu.add_empty_vol,
                                  input_names=['in_file'],
                                  output_names=['out_file']),
                     name='AddEmptyVol')
    vsm = pe.Node(fsl.FUGUE(save_unmasked_shift=True, **fmb_params),
                  name="Compute_VSM")

    dfm = process_vsm()
    dfm.inputs.inputnode.scaling = 1.0

    wf.connect([(inputnode, selmag, [('in_bmap', 'inlist')]),
                (inputnode, selpha, [('in_bmap', 'inlist')]),
                (inputnode, magmsk, [('in_mask', 'mask_file')]),
                (inputnode, eff_es, [('echospacing', 'echospacing'),
                                     ('acc_factor', 'acc_factor')]),
                (selmag, magmsk, [('out', 'in_file')]),
                (phcache, rad2rsec, [('pha_unwrapped', 'in_file')]),
                (inputnode, rad2rsec, [('delta_te', 'delta_te')]),
                (rad2rsec, pre_fugue, [('out_file', 'fmap_in_file')]),
                (inputnode, pre_fugue, [('in_mask', 'mask_file')]),
                (pre_fugue, demean, [('fmap_out_file', 'in_file')]),
                (inputnode, demean, [('in_mask', 'in_mask')]),
                (demean, cleanup, [('out_file', 'inputnode.in_file')]),
                (inputnode, cleanup, [('in_mask', 'inputnode.in_mask')]),
                (cleanup, addvol, [('outputnode.out_file', 'in_file')]),
                (addvol, vsm, [('out_file', 'fmap_in_file')]),
                (eff_es, vsm, [('echospacing', 'dwell_time')]),
                (inputnode, vsm, [('in_mask', 'mask_file'),
                                  ('delta_te', 'asym_se_time')]),
                (vsm, outputnode, [('shift_out_file', 'vsm')]),
                (vsm, dfm, [('shift_out_file', 'inputnode.vsm')]),
                (inputnode, dfm, [('in_mask', 'inputnode.reference'),
                                  ('enc_dir', 'inputnode.enc_dir')]),
                (dfm, outputnode, [('outputnode.dfm', 'dfm'),
                                   ('outputnode.jacobian', 'jac'),
                                   ('outputnode.inv_dfm', 'dfm_inv'),
                                   ('outputnode.inv_jacobian', 'jac_inv')])])

    if phase_unwrap:
        prelude = pe.Node(fsl.PRELUDE(process3d=True), name='PhaseUnwrap')
        wf.connect([(selmag, prelude, [('out', 'magnitude_file')]),
                    (selpha, prelude, [('out', 'phase_file')]),
                    (magmsk, prelude, [('out_file', 'mask_file')]),
                    (prelude, phcache, [('unwrapped_phase_file',
                                         'pha_unwrapped')])])
    else:
        wf.connect(selpha, 'out', phcache, 'pha_unwrapped')
    return wf
Exemple #11
0
def sdc_fmb(name='fmb_correction',
            interp='Linear',
            fugue_params=dict(smooth3d=2.0)):
    """
    SDC stands for susceptibility distortion correction. FMB stands for
    fieldmap-based.

    The fieldmap based (FMB) method implements SDC by using a mapping of the
    B0 field as proposed by [Jezzard95]_. This workflow uses the implementation
    of FSL (`FUGUE <http://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FUGUE>`_). Phase
    unwrapping is performed using `PRELUDE
    <http://fsl.fmrib.ox.ac.uk/fsl/fsl-4.1.9/fugue/prelude.html>`_
    [Jenkinson03]_. Preparation of the fieldmap is performed reproducing the
    script in FSL `fsl_prepare_fieldmap
    <http://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FUGUE/Guide#SIEMENS_data>`_.



    Example
    -------

    >>> from nipype.workflows.dmri.fsl.artifacts import sdc_fmb
    >>> fmb = sdc_fmb()
    >>> fmb.inputs.inputnode.in_file = 'diffusion.nii'
    >>> fmb.inputs.inputnode.in_ref = list(range(0, 30, 6))
    >>> fmb.inputs.inputnode.in_mask = 'mask.nii'
    >>> fmb.inputs.inputnode.bmap_mag = 'magnitude.nii'
    >>> fmb.inputs.inputnode.bmap_pha = 'phase.nii'
    >>> fmb.inputs.inputnode.settings = 'epi_param.txt'
    >>> fmb.run() # doctest: +SKIP

    .. warning:: Only SIEMENS format fieldmaps are supported.

    .. admonition:: References

      .. [Jezzard95] Jezzard P, and Balaban RS, `Correction for geometric
        distortion in echo planar images from B0 field variations
        <http://dx.doi.org/10.1002/mrm.1910340111>`_,
        MRM 34(1):65-73. (1995). doi: 10.1002/mrm.1910340111.

      .. [Jenkinson03] Jenkinson M., `Fast, automated, N-dimensional
        phase-unwrapping algorithm <http://dx.doi.org/10.1002/mrm.10354>`_,
        MRM 49(1):193-197, 2003, doi: 10.1002/mrm.10354.

    """

    epi_defaults = {
        'delta_te': 2.46e-3,
        'echospacing': 0.77e-3,
        'acc_factor': 2,
        'enc_dir': u'AP'
    }

    inputnode = pe.Node(niu.IdentityInterface(fields=[
        'in_file', 'in_ref', 'in_mask', 'bmap_pha', 'bmap_mag', 'settings'
    ]),
                        name='inputnode')

    outputnode = pe.Node(
        niu.IdentityInterface(fields=['out_file', 'out_vsm', 'out_warp']),
        name='outputnode')

    r_params = pe.Node(JSONFileGrabber(defaults=epi_defaults),
                       name='SettingsGrabber')
    eff_echo = pe.Node(niu.Function(function=_eff_t_echo,
                                    input_names=['echospacing', 'acc_factor'],
                                    output_names=['eff_echo']),
                       name='EffEcho')

    firstmag = pe.Node(fsl.ExtractROI(t_min=0, t_size=1), name='GetFirst')
    n4 = pe.Node(ants.N4BiasFieldCorrection(dimension=3), name='Bias')
    bet = pe.Node(fsl.BET(frac=0.4, mask=True), name='BrainExtraction')
    dilate = pe.Node(fsl.maths.MathsCommand(nan2zeros=True,
                                            args='-kernel sphere 5 -dilM'),
                     name='MskDilate')
    pha2rads = pe.Node(niu.Function(input_names=['in_file'],
                                    output_names=['out_file'],
                                    function=siemens2rads),
                       name='PreparePhase')
    prelude = pe.Node(fsl.PRELUDE(process3d=True), name='PhaseUnwrap')
    rad2rsec = pe.Node(niu.Function(input_names=['in_file', 'delta_te'],
                                    output_names=['out_file'],
                                    function=rads2radsec),
                       name='ToRadSec')

    baseline = pe.Node(niu.Function(input_names=['in_file', 'index'],
                                    output_names=['out_file'],
                                    function=time_avg),
                       name='Baseline')

    fmm2b0 = pe.Node(ants.Registration(output_warped_image=True),
                     name="FMm_to_B0")
    fmm2b0.inputs.transforms = ['Rigid'] * 2
    fmm2b0.inputs.transform_parameters = [(1.0, )] * 2
    fmm2b0.inputs.number_of_iterations = [[50], [20]]
    fmm2b0.inputs.dimension = 3
    fmm2b0.inputs.metric = ['Mattes', 'Mattes']
    fmm2b0.inputs.metric_weight = [1.0] * 2
    fmm2b0.inputs.radius_or_number_of_bins = [64, 64]
    fmm2b0.inputs.sampling_strategy = ['Regular', 'Random']
    fmm2b0.inputs.sampling_percentage = [None, 0.2]
    fmm2b0.inputs.convergence_threshold = [1.e-5, 1.e-8]
    fmm2b0.inputs.convergence_window_size = [20, 10]
    fmm2b0.inputs.smoothing_sigmas = [[6.0], [2.0]]
    fmm2b0.inputs.sigma_units = ['vox'] * 2
    fmm2b0.inputs.shrink_factors = [[6], [1]]  # ,[1] ]
    fmm2b0.inputs.use_estimate_learning_rate_once = [True] * 2
    fmm2b0.inputs.use_histogram_matching = [True] * 2
    fmm2b0.inputs.initial_moving_transform_com = 0
    fmm2b0.inputs.collapse_output_transforms = True
    fmm2b0.inputs.winsorize_upper_quantile = 0.995

    applyxfm = pe.Node(ants.ApplyTransforms(dimension=3, interpolation=interp),
                       name='FMp_to_B0')

    pre_fugue = pe.Node(fsl.FUGUE(save_fmap=True), name='PreliminaryFugue')
    demean = pe.Node(niu.Function(input_names=['in_file', 'in_mask'],
                                  output_names=['out_file'],
                                  function=demean_image),
                     name='DemeanFmap')

    cleanup = cleanup_edge_pipeline()

    addvol = pe.Node(niu.Function(input_names=['in_file'],
                                  output_names=['out_file'],
                                  function=add_empty_vol),
                     name='AddEmptyVol')

    vsm = pe.Node(fsl.FUGUE(save_shift=True, **fugue_params),
                  name="ComputeVSM")

    split = pe.Node(fsl.Split(dimension='t'), name='SplitDWIs')
    merge = pe.Node(fsl.Merge(dimension='t'), name='MergeDWIs')
    unwarp = pe.MapNode(fsl.FUGUE(icorr=True, forward_warping=False),
                        iterfield=['in_file'],
                        name='UnwarpDWIs')
    thres = pe.MapNode(fsl.Threshold(thresh=0.0),
                       iterfield=['in_file'],
                       name='RemoveNegative')
    vsm2dfm = vsm2warp()
    vsm2dfm.inputs.inputnode.scaling = 1.0

    wf = pe.Workflow(name=name)
    wf.connect([(inputnode, r_params, [('settings', 'in_file')]),
                (r_params, eff_echo, [('echospacing', 'echospacing'),
                                      ('acc_factor', 'acc_factor')]),
                (inputnode, pha2rads, [('bmap_pha', 'in_file')]),
                (inputnode, firstmag, [('bmap_mag', 'in_file')]),
                (inputnode, baseline, [('in_file', 'in_file'),
                                       ('in_ref', 'index')]),
                (firstmag, n4, [('roi_file', 'input_image')]),
                (n4, bet, [('output_image', 'in_file')]),
                (bet, dilate, [('mask_file', 'in_file')]),
                (pha2rads, prelude, [('out_file', 'phase_file')]),
                (n4, prelude, [('output_image', 'magnitude_file')]),
                (dilate, prelude, [('out_file', 'mask_file')]),
                (r_params, rad2rsec, [('delta_te', 'delta_te')]),
                (prelude, rad2rsec, [('unwrapped_phase_file', 'in_file')]),
                (baseline, fmm2b0, [('out_file', 'fixed_image')]),
                (n4, fmm2b0, [('output_image', 'moving_image')]),
                (inputnode, fmm2b0, [('in_mask', 'fixed_image_mask')]),
                (dilate, fmm2b0, [('out_file', 'moving_image_mask')]),
                (baseline, applyxfm, [('out_file', 'reference_image')]),
                (rad2rsec, applyxfm, [('out_file', 'input_image')]),
                (fmm2b0, applyxfm, [('forward_transforms', 'transforms'),
                                    ('forward_invert_flags',
                                     'invert_transform_flags')]),
                (applyxfm, pre_fugue, [('output_image', 'fmap_in_file')]),
                (inputnode, pre_fugue, [('in_mask', 'mask_file')]),
                (pre_fugue, demean, [('fmap_out_file', 'in_file')]),
                (inputnode, demean, [('in_mask', 'in_mask')]),
                (demean, cleanup, [('out_file', 'inputnode.in_file')]),
                (inputnode, cleanup, [('in_mask', 'inputnode.in_mask')]),
                (cleanup, addvol, [('outputnode.out_file', 'in_file')]),
                (inputnode, vsm, [('in_mask', 'mask_file')]),
                (addvol, vsm, [('out_file', 'fmap_in_file')]),
                (r_params, vsm, [('delta_te', 'asym_se_time')]),
                (eff_echo, vsm, [('eff_echo', 'dwell_time')]),
                (inputnode, split, [('in_file', 'in_file')]),
                (split, unwarp, [('out_files', 'in_file')]),
                (vsm, unwarp, [('shift_out_file', 'shift_in_file')]),
                (r_params, unwarp, [(('enc_dir', _fix_enc_dir),
                                     'unwarp_direction')]),
                (unwarp, thres, [('unwarped_file', 'in_file')]),
                (thres, merge, [('out_file', 'in_files')]),
                (r_params, vsm2dfm, [(('enc_dir',
                                       _fix_enc_dir), 'inputnode.enc_dir')]),
                (merge, vsm2dfm, [('merged_file', 'inputnode.in_ref')]),
                (vsm, vsm2dfm, [('shift_out_file', 'inputnode.in_vsm')]),
                (merge, outputnode, [('merged_file', 'out_file')]),
                (vsm, outputnode, [('shift_out_file', 'out_vsm')]),
                (vsm2dfm, outputnode, [('outputnode.out_warp', 'out_warp')])])
    return wf