예제 #1
0
파일: functional.py 프로젝트: xwolfs/mriqc
def compute_iqms(settings, name='ComputeIQMs'):
    """Workflow that actually computes the IQMs"""
    workflow = pe.Workflow(name=name)
    inputnode = pe.Node(niu.IdentityInterface(fields=[
        'subject_id', 'session_id', 'task_id', 'run_id', 'orig', 'epi_mean',
        'brainmask', 'hmc_epi', 'hmc_fd', 'in_tsnr', 'metadata']), name='inputnode')
    outputnode = pe.Node(niu.IdentityInterface(
        fields=['out_file', 'out_dvars', 'outliers', 'out_spikes', 'out_fft']),
                         name='outputnode')

    deriv_dir = check_folder(op.abspath(op.join(settings['output_dir'], 'derivatives')))

    # Compute DVARS
    dvnode = pe.Node(nac.ComputeDVARS(save_plot=False, save_all=True), name='ComputeDVARS')

    # AFNI quality measures
    fwhm = pe.Node(afni.FWHMx(combine=True, detrend=True), name='smoothness')
    # fwhm.inputs.acf = True  # add when AFNI >= 16
    outliers = pe.Node(afni.OutlierCount(fraction=True, out_file='ouliers.out'),
                       name='outliers')
    quality = pe.Node(afni.QualityIndex(automask=True), out_file='quality.out',
                      name='quality')

    # FFT spikes finder
    spikes_fft = pe.Node(niu.Function(
        input_names=['in_file'], output_names=['n_spikes', 'out_spikes', 'out_fft'],
        function=slice_wise_fft), name='SpikesFinderFFT')

    measures = pe.Node(FunctionalQC(), name='measures')

    workflow.connect([
        (inputnode, dvnode, [('orig', 'in_file'),
                             ('brainmask', 'in_mask')]),
        (inputnode, measures, [('epi_mean', 'in_epi'),
                               ('brainmask', 'in_mask'),
                               ('hmc_epi', 'in_hmc'),
                               ('hmc_fd', 'in_fd'),
                               ('in_tsnr', 'in_tsnr')]),
        (inputnode, fwhm, [('epi_mean', 'in_file'),
                           ('brainmask', 'mask')]),
        (inputnode, spikes_fft, [('orig', 'in_file')]),
        (inputnode, quality, [('hmc_epi', 'in_file')]),
        (inputnode, outliers, [('hmc_epi', 'in_file'),
                               ('brainmask', 'mask')]),
        (dvnode, measures, [('out_all', 'in_dvars')]),
        (dvnode, outputnode, [('out_all', 'out_dvars')]),
        (outliers, outputnode, [('out_file', 'outliers')]),
        (spikes_fft, outputnode, [('out_spikes', 'out_spikes'),
                                  ('out_fft', 'out_fft')])
    ])

    # Save to JSON file
    datasink = pe.Node(IQMFileSink(
        modality='bold', out_dir=deriv_dir), name='datasink')

    workflow.connect([
        (inputnode, datasink, [('subject_id', 'subject_id'),
                               ('session_id', 'session_id'),
                               ('task_id', 'task_id'),
                               ('run_id', 'run_id'),
                               ('metadata', 'metadata')]),
        (outliers, datasink, [(('out_file', _parse_tout), 'aor')]),
        (quality, datasink, [(('out_file', _parse_tqual), 'aqi')]),
        (measures, datasink, [('out_qc', 'root')]),
        (spikes_fft, datasink, [('n_spikes', 'spikes_num')]),
        (fwhm, datasink, [(('fwhm', fwhm_dict), 'root0')]),
        (datasink, outputnode, [('out_file', 'out_file')])
    ])
    return workflow
예제 #2
0
# and expects an output (what the function returns) called subs.  The actual function
# which was created above is called get_subs.
# I can assign the input either through a workflow connect syntax or by simplying hardcoding it.
# in this case I hard coded it by saying that .inputs.func_files = func_files
getsubs = pe.Node(Function(input_names=['func_files'],
                           output_names=['subs'],
                           function=get_subs),
                  name='getsubs')
getsubs.inputs.func_files = func_files

# Here I am inputing just the first run functional data
# I want to use afni's 3dToutcount to find the number of
# outliers at each volume.  I will use this information to
# later select the earliest volume with the least number of outliers
# to serve as the base for the motion correction
id_outliers = pe.Node(afni.OutlierCount(), name='id_outliers')
id_outliers.inputs.in_file = func_files[0]
id_outliers.inputs.automask = True
id_outliers.inputs.legendre = True
id_outliers.inputs.polort = 4
id_outliers.inputs.out_file = 'outlier_file'
'''
CURRENTLY CRASHING COMMENTING OUT TO WORK ON LATER
#ATM ONLY: Add an unwarping mapnode here using the field maps
calc_distor_corr = pe.Node(afni.Qwarp(),
                           name = 'calc_distor_corr')
calc_distor_corr.inputs.plusminus = True
calc_distor_corr.inputs.pblur = [0.05, 0.05]
calc_distor_corr.inputs.minpatch = 9
calc_distor_corr.inputs.noweight = True
calc_distor_corr.inputs.outputtype = 'NIFTI_GZ'
예제 #3
0
# and expects an output (what the function returns) called subs.  The actual function
# which was created above is called get_subs.
# I can assign the input either through a workflow connect syntax or by simplying hardcoding it.
# in this case I hard coded it by saying that .inputs.func_files = func_files
getsubs = pe.Node(Function(input_names=['func_files'],
                           output_names=['subs'],
                           function=get_subs),
                  name='getsubs')
getsubs.inputs.func_files = func_files

# Here I am inputing just the first run functional data
# I want to use afni's 3dToutcount to find the number of
# outliers at each volume.  I will use this information to
# later select the earliest volume with the least number of outliers
# to serve as the base for the motion correction
id_outliers = pe.Node(afni.OutlierCount(),
                      name = 'id_outliers')
id_outliers.inputs.in_file = func_files[0]
id_outliers.inputs.automask = True
id_outliers.inputs.legendre = True
id_outliers.inputs.polort = 4
id_outliers.inputs.out_file = 'outlier_file'

'''
CURRENTLY CRASHING COMMENTING OUT TO WORK ON LATER
#ATM ONLY: Add an unwarping mapnode here using the field maps
calc_distor_corr = pe.Node(afni.Qwarp(),
                           name = 'calc_distor_corr')
calc_distor_corr.inputs.plusminus = True
calc_distor_corr.inputs.pblur = [0.05, 0.05]
calc_distor_corr.inputs.minpatch = 9
예제 #4
0
def compute_iqms(settings, name='ComputeIQMs'):
    """
    Workflow that actually computes the IQMs

    .. workflow::

      from mriqc.workflows.functional import compute_iqms
      wf = compute_iqms(settings={'output_dir': 'out'})


    """
    from .utils import _tofloat
    from ..interfaces.transitional import GCOR

    biggest_file_gb = settings.get("biggest_file_size_gb", 1)

    workflow = pe.Workflow(name=name)
    inputnode = pe.Node(niu.IdentityInterface(fields=[
        'in_file', 'in_ras',
        'epi_mean', 'brainmask', 'hmc_epi', 'hmc_fd', 'fd_thres', 'in_tsnr', 'metadata',
        'exclude_index']), name='inputnode')
    outputnode = pe.Node(niu.IdentityInterface(
        fields=['out_file', 'out_dvars', 'outliers', 'out_spikes', 'out_fft']),
        name='outputnode')

    # Set FD threshold
    inputnode.inputs.fd_thres = settings.get('fd_thres', 0.2)

    # Compute DVARS
    dvnode = pe.Node(nac.ComputeDVARS(save_plot=False, save_all=True), name='ComputeDVARS',
                     mem_gb=biggest_file_gb * 3)

    # AFNI quality measures
    fwhm_interface = get_fwhmx()
    fwhm = pe.Node(fwhm_interface, name='smoothness')
    # fwhm.inputs.acf = True  # add when AFNI >= 16
    outliers = pe.Node(afni.OutlierCount(fraction=True, out_file='outliers.out'),
                       name='outliers', mem_gb=biggest_file_gb * 2.5)

    quality = pe.Node(afni.QualityIndex(automask=True), out_file='quality.out',
                      name='quality', mem_gb=biggest_file_gb * 3)

    gcor = pe.Node(GCOR(), name='gcor', mem_gb=biggest_file_gb * 2)

    measures = pe.Node(FunctionalQC(), name='measures', mem_gb=biggest_file_gb * 3)

    workflow.connect([
        (inputnode, dvnode, [('hmc_epi', 'in_file'),
                             ('brainmask', 'in_mask')]),
        (inputnode, measures, [('epi_mean', 'in_epi'),
                               ('brainmask', 'in_mask'),
                               ('hmc_epi', 'in_hmc'),
                               ('hmc_fd', 'in_fd'),
                               ('fd_thres', 'fd_thres'),
                               ('in_tsnr', 'in_tsnr')]),
        (inputnode, fwhm, [('epi_mean', 'in_file'),
                           ('brainmask', 'mask')]),
        (inputnode, quality, [('hmc_epi', 'in_file')]),
        (inputnode, outliers, [('hmc_epi', 'in_file'),
                               ('brainmask', 'mask')]),
        (inputnode, gcor, [('hmc_epi', 'in_file'),
                           ('brainmask', 'mask')]),
        (dvnode, measures, [('out_all', 'in_dvars')]),
        (fwhm, measures, [(('fwhm', _tofloat), 'in_fwhm')]),
        (dvnode, outputnode, [('out_all', 'out_dvars')]),
        (outliers, outputnode, [('out_file', 'outliers')])
    ])

    # Add metadata
    meta = pe.Node(ReadSidecarJSON(), name='metadata',
                   run_without_submitting=True)
    addprov = pe.Node(niu.Function(function=_add_provenance), name='provenance',
                      run_without_submitting=True)
    addprov.inputs.settings = {
        'fd_thres': settings.get('fd_thres', 0.2),
        'hmc_fsl': settings.get('hmc_fsl', True),
        'webapi_url': settings.get('webapi_url'),
        'webapi_port': settings.get('webapi_port'),
    }

    # Save to JSON file
    datasink = pe.Node(IQMFileSink(
        modality='bold', out_dir=str(settings['output_dir']),
        dataset=settings.get('dataset_name', 'unknown')),
        name='datasink', run_without_submitting=True)

    workflow.connect([
        (inputnode, datasink, [('in_file', 'in_file'),
                               ('exclude_index', 'dummy_trs')]),
        (inputnode, meta, [('in_file', 'in_file')]),
        (inputnode, addprov, [('in_file', 'in_file')]),
        (meta, datasink, [('subject', 'subject_id'),
                          ('session', 'session_id'),
                          ('task', 'task_id'),
                          ('acquisition', 'acq_id'),
                          ('reconstruction', 'rec_id'),
                          ('run', 'run_id'),
                          ('out_dict', 'metadata')]),
        (addprov, datasink, [('out', 'provenance')]),
        (outliers, datasink, [(('out_file', _parse_tout), 'aor')]),
        (gcor, datasink, [(('out', _tofloat), 'gcor')]),
        (quality, datasink, [(('out_file', _parse_tqual), 'aqi')]),
        (measures, datasink, [('out_qc', 'root')]),
        (datasink, outputnode, [('out_file', 'out_file')])
    ])

    # FFT spikes finder
    if settings.get('fft_spikes_detector', False):
        from .utils import slice_wise_fft
        spikes_fft = pe.Node(niu.Function(
            input_names=['in_file'],
            output_names=['n_spikes', 'out_spikes', 'out_fft'],
            function=slice_wise_fft), name='SpikesFinderFFT')

        workflow.connect([
            (inputnode, spikes_fft, [('in_ras', 'in_file')]),
            (spikes_fft, outputnode, [('out_spikes', 'out_spikes'),
                                      ('out_fft', 'out_fft')]),
            (spikes_fft, datasink, [('n_spikes', 'spikes_num')])
        ])
    return workflow
예제 #5
0
파일: functional.py 프로젝트: jdkent/mriqc
def compute_iqms(settings, name='ComputeIQMs'):
    """
    Workflow that actually computes the IQMs

    .. workflow::

      from mriqc.workflows.functional import compute_iqms
      wf = compute_iqms(settings={'output_dir': 'out'})


    """
    from mriqc.workflows.utils import _tofloat

    biggest_file_gb = settings.get("biggest_file_size_gb", 1)

    workflow = pe.Workflow(name=name)
    inputnode = pe.Node(niu.IdentityInterface(fields=[
        'subject_id', 'session_id', 'task_id', 'acq_id', 'rec_id', 'run_id',
        'orig', 'epi_mean', 'brainmask', 'hmc_epi', 'hmc_fd', 'fd_thres',
        'in_tsnr', 'metadata'
    ]),
                        name='inputnode')
    outputnode = pe.Node(niu.IdentityInterface(
        fields=['out_file', 'out_dvars', 'outliers', 'out_spikes', 'out_fft']),
                         name='outputnode')
    #Set FD threshold
    inputnode.inputs.fd_thres = settings.get('fd_thres', 0.2)
    deriv_dir = check_folder(
        op.abspath(op.join(settings['output_dir'], 'derivatives')))

    # Compute DVARS
    dvnode = pe.Node(nac.ComputeDVARS(save_plot=False, save_all=True),
                     name='ComputeDVARS')
    dvnode.interface.estimated_memory_gb = biggest_file_gb * 3

    # AFNI quality measures
    fwhm = pe.Node(afni.FWHMx(combine=True, detrend=True), name='smoothness')
    # fwhm.inputs.acf = True  # add when AFNI >= 16
    outliers = pe.Node(afni.OutlierCount(fraction=True,
                                         out_file='ouliers.out'),
                       name='outliers')
    outliers.interface.estimated_memory_gb = biggest_file_gb * 2.5
    quality = pe.Node(afni.QualityIndex(automask=True),
                      out_file='quality.out',
                      name='quality')
    quality.interface.estimated_memory_gb = biggest_file_gb * 3

    measures = pe.Node(FunctionalQC(), name='measures')
    measures.interface.estimated_memory_gb = biggest_file_gb * 3

    workflow.connect([(inputnode, dvnode, [('hmc_epi', 'in_file'),
                                           ('brainmask', 'in_mask')]),
                      (inputnode, measures, [('epi_mean', 'in_epi'),
                                             ('brainmask', 'in_mask'),
                                             ('hmc_epi', 'in_hmc'),
                                             ('hmc_fd', 'in_fd'),
                                             ('fd_thres', 'fd_thres'),
                                             ('in_tsnr', 'in_tsnr')]),
                      (inputnode, fwhm, [('epi_mean', 'in_file'),
                                         ('brainmask', 'mask')]),
                      (inputnode, quality, [('hmc_epi', 'in_file')]),
                      (inputnode, outliers, [('hmc_epi', 'in_file'),
                                             ('brainmask', 'mask')]),
                      (dvnode, measures, [('out_all', 'in_dvars')]),
                      (fwhm, measures, [(('fwhm', _tofloat), 'in_fwhm')]),
                      (dvnode, outputnode, [('out_all', 'out_dvars')]),
                      (outliers, outputnode, [('out_file', 'outliers')])])

    # Save to JSON file
    datasink = pe.Node(IQMFileSink(modality='bold', out_dir=deriv_dir),
                       name='datasink')

    workflow.connect([
        (inputnode, datasink, [('subject_id', 'subject_id'),
                               ('session_id', 'session_id'),
                               ('task_id', 'task_id'), ('acq_id', 'acq_id'),
                               ('rec_id', 'rec_id'), ('run_id', 'run_id'),
                               ('metadata', 'metadata')]),
        (outliers, datasink, [(('out_file', _parse_tout), 'aor')]),
        (quality, datasink, [(('out_file', _parse_tqual), 'aqi')]),
        (measures, datasink, [('out_qc', 'root')]),
        (datasink, outputnode, [('out_file', 'out_file')])
    ])

    if settings.get('fft_spikes_detector', False):
        # FFT spikes finder
        spikes_fft = pe.Node(niu.Function(
            input_names=['in_file'],
            output_names=['n_spikes', 'out_spikes', 'out_fft'],
            function=slice_wise_fft),
                             name='SpikesFinderFFT')

        workflow.connect([
            (inputnode, spikes_fft, [('orig', 'in_file')]),
            (spikes_fft, outputnode, [('out_spikes', 'out_spikes'),
                                      ('out_fft', 'out_fft')]),
            (spikes_fft, datasink, [('n_spikes', 'spikes_num')])
        ])

    return workflow
예제 #6
0
def create_rs_qc(subjectlist):
    # main workflow for extended qc of diffusion/rsfmri data
    # fsl output type
    fsl.FSLCommand.set_default_output_type('NIFTI_GZ')
    # some hard coded things
    fd_thres = 0.2
    tr = 2

    # Specify the location of the preprocessed data
    data_dir = "/data/pt_life/LIFE_fu/wd_preprocessing/hcp_prep_workflow/resting/"
    working_dir = "/data/pt_life/LIFE_fu/wd_preprocessing/"  #MODIFY
    freesurfer_dir = "/data/pt_life_freesurfer/freesurfer_all"

    qc = Workflow(name="qc")
    qc.base_dir = working_dir + '/'
    qc.config['execution']['crashdump_dir'] = qc.base_dir + "/crash_files"
    qc.config['execution'] = {'hash_method': 'content'}
    #first get all data needed
    identitynode = Node(util.IdentityInterface(fields=['subject']),
                        name='identitynode')
    identitynode.iterables = ('subject', subjectlist)

    info = dict(func=[[
        'transform_timeseries/', '_subject_', 'subj', '/merge/rest2anat.nii.gz'
    ]],
                dvars=[[
                    'transform_timeseries/', '_subject_', 'subj',
                    '/dvars/rest2anat_dvars.tsv'
                ]],
                motpars=[[
                    '/motion_correction/', '_subject_', 'subj',
                    '/mcflirt/rest_realigned.nii.gz.par'
                ]],
                brainmask=[[
                    'transform_timeseries/', '_subject_', 'subj',
                    '/resample_brain/T1_brain_mask_lowres.nii.gz'
                ]])

    ds_rs = Node(interface=nio.DataGrabber(
        infields=['subj'], outfields=['func', 'dvars', 'motpars',
                                      'brainmask']),
                 name='ds_rs')
    ds_rs.inputs.base_directory = data_dir
    ds_rs.inputs.template = '%s%s%s%s'
    ds_rs.inputs.template_args = info
    ds_rs.inputs.sort_filelist = True

    def juggle_subj(input_id):
        import pandas as pd
        from datetime import datetime as dt
        import os
        import random, string

        sic_pseudo = pd.read_csv(
            "/data/gh_gr_agingandobesity_share/life_shared/Data/Preprocessed/derivatives/pseudo_mrt_20201214.csv"
        )
        tmp = sic_pseudo.loc[sic_pseudo.sic == input_id, 'pseudonym']
        pseudo = tmp.get_values()[0] + "_fu"
        return pseudo

    rename = Node(util.Function(input_names=['input_id'],
                                output_names=['output_id'],
                                function=juggle_subj),
                  name="rename")

    get_fs = Node(nio.FreeSurferSource(), name="get_fs")
    get_fs.inputs.subjects_dir = freesurfer_dir

    get_correct_aseg = Node(util.Function(input_names=['in_list'],
                                          output_names=['out_aseg'],
                                          function=get_aseg),
                            name="get_correct_aseg")

    convert = Node(fs.MRIConvert(), name="convert")
    convert.inputs.out_type = "niigz"

    downsample = Node(afni.Resample(resample_mode='NN',
                                    outputtype='NIFTI_GZ',
                                    out_file='aparcaseg_lowres.nii.gz'),
                      name='downsample')

    calc_fd_official = Node(FramewiseDisplacement(parameter_source='FSL'),
                            name='calc_fd_official')

    calc_fd = Node(util.Function(
        input_names=['realignment_parameters_file', 'parameter_source'],
        output_names=['FD_power', 'fn'],
        function=calc_frame_displacement),
                   name="calc_fd")
    calc_fd.inputs.parameter_source = 'FSL'

    outliers = Node(afni.OutlierCount(fraction=True, out_file='outliers.out'),
                    name='outliers',
                    mem_gb=1 * 2.5)

    bigplot = Node(util.Function(input_names=[
        'func', 'seg', 'tr', 'fd_thres', 'outliers', 'dvars', 'fd', 'subj',
        'outfile'
    ],
                                 output_names=['fn', 'dataframe'],
                                 function=make_the_plot),
                   name="bigplot")
    bigplot.inputs.tr = tr
    bigplot.inputs.fd_thres = fd_thres
    bigplot.inputs.outfile = "summary_fmriplot.png"

    fftplot = Node(util.Function(input_names=['fn_pd', 'tr'],
                                 output_names=['fn'],
                                 function=plot_fft),
                   name="fftplot")
    fftplot.inputs.tr = tr

    datasink = Node(name="datasink", interface=nio.DataSink())
    datasink.inputs.base_directory = "/data/pt_life_restingstate_followup/Results/QA"
    datasink.inputs.substitutions = [('_subject_', '')]

    qc.connect([
        (identitynode, rename, [('subject', 'input_id')]),
        (rename, get_fs, [('output_id', 'subject_id')]),
        (identitynode, ds_rs, [('subject', 'subj')]),
        (identitynode, bigplot, [('subject', 'subj')]),
        (get_fs, get_correct_aseg, [('aparc_aseg', 'in_list')]),
        (get_correct_aseg, convert, [('out_aseg', 'in_file')]),
        (convert, downsample, [('out_file', 'in_file')]),
        (ds_rs, downsample, [('func', 'master')]),
        (downsample, bigplot, [('out_file', 'seg')]),
        (ds_rs, calc_fd, [('motpars', 'realignment_parameters_file')]),
        (ds_rs, calc_fd_official, [('motpars', 'in_file')]),
        (ds_rs, bigplot, [('func', 'func')]),
        (ds_rs, bigplot, [('dvars', 'dvars')]),
        (calc_fd, bigplot, [('fn', 'fd')]),  #FD_power
        (ds_rs, outliers, [('func', 'in_file')]),
        (ds_rs, outliers, [('brainmask', 'mask')]),
        (outliers, bigplot, [('out_file', 'outliers')]),
        (bigplot, datasink, [('fn', 'detailedQA.@bigplot')]),
        (bigplot, fftplot, [('dataframe', 'fn_pd')]),
        (bigplot, datasink, [('dataframe', 'detailedQA.metrics.@dataframe')]),
        (fftplot, datasink, [('fn', 'detailedQA.@fftplot')]),
        (calc_fd, datasink, [('fn', 'detailedQA.metrics.@fd')]),
        (calc_fd_official, datasink, [('out_file',
                                       'detailedQA.metrics.@fd_official')])
    ])

    qc.run(plugin="MultiProc", plugin_args={"n_procs": 16, "non_daemon": True})

    return qc
예제 #7
0
def create_rs_qc(subjectlist):
    # main workflow for extended qc of diffusion/rsfmri data
    # fsl output type
    fsl.FSLCommand.set_default_output_type('NIFTI_GZ')
    # some hard coded things
    fd_thres = 0.2
    tr = 1.4

    # Specify the location of the preprocessed data
    data_dir = "/data/pt_02030/wd_preprocessing/hcp_prep_workflow/resting/"
    working_dir = "/data/pt_02030/wd_preprocessing/"  #MODIFY
    freesurfer_dir = "/data/pt_02030/preprocessed/freesurfer/"

    qc = Workflow(name="qc")
    qc.base_dir = working_dir + '/'
    qc.config['execution']['crashdump_dir'] = qc.base_dir + "/crash_files"

    #first get all data needed
    identitynode = Node(util.IdentityInterface(fields=['subject']),
                        name='identitynode')
    identitynode.iterables = ('subject', subjectlist)

    info = dict(func=[[
        'transform_timeseries/', '_subject_', 'subj', '/merge/rest2anat.nii.gz'
    ]],
                dvars=[[
                    'transform_timeseries/', '_subject_', 'subj',
                    '/dvars/rest2anat_dvars.tsv'
                ]],
                motpars=[[
                    '/motion_correction/', '_subject_', 'subj',
                    '/mcflirt/rest_realigned.nii.gz.par'
                ]],
                brainmask=[[
                    'transform_timeseries/', '_subject_', 'subj',
                    '/resample_brain/T1_brain_mask_lowres.nii.gz'
                ]])

    ds_rs = Node(interface=nio.DataGrabber(
        infields=['subj'], outfields=['func', 'dvars', 'motpars',
                                      'brainmask']),
                 name='ds_rs')
    ds_rs.inputs.base_directory = data_dir
    ds_rs.inputs.template = '%s%s%s%s'
    ds_rs.inputs.template_args = info
    ds_rs.inputs.sort_filelist = True

    get_fs = Node(nio.FreeSurferSource(), name="get_fs")
    get_fs.inputs.subjects_dir = freesurfer_dir

    get_correct_aseg = Node(util.Function(input_names=['in_list'],
                                          output_names=['out_aseg'],
                                          function=get_aseg),
                            name="get_correct_aseg")

    convert = Node(fs.MRIConvert(), name="convert")
    convert.inputs.out_type = "niigz"

    downsample = Node(afni.Resample(resample_mode='NN',
                                    outputtype='NIFTI_GZ',
                                    out_file='aparcaseg_lowres.nii.gz'),
                      name='downsample')

    calc_fd = Node(util.Function(
        input_names=['realignment_parameters_file', 'parameter_source'],
        output_names=['FD_power', 'fn'],
        function=calc_frame_displacement),
                   name="calc_fd")
    calc_fd.inputs.parameter_source = 'FSL'

    outliers = Node(afni.OutlierCount(fraction=True, out_file='outliers.out'),
                    name='outliers',
                    mem_gb=1 * 2.5)

    bigplot = Node(util.Function(input_names=[
        'func', 'seg', 'tr', 'fd_thres', 'outliers', 'dvars', 'fd', 'subj',
        'outfile'
    ],
                                 output_names=['fn', 'dataframe'],
                                 function=make_the_plot),
                   name="bigplot")
    bigplot.inputs.tr = tr
    bigplot.inputs.fd_thres = fd_thres
    bigplot.inputs.outfile = "summary_fmriplot.png"

    fftplot = Node(util.Function(input_names=['fn_pd', 'tr'],
                                 output_names=['fn'],
                                 function=plot_fft),
                   name="fftplot")
    fftplot.inputs.tr = tr

    datasink = Node(name="datasink", interface=nio.DataSink())
    datasink.inputs.base_directory = "/data/pt_02030/preprocessed/reports/"
    datasink.inputs.substitutions = [('_subject_', '')]

    qc.connect([(identitynode, get_fs, [('subject', 'subject_id')]),
                (identitynode, ds_rs, [('subject', 'subj')]),
                (identitynode, bigplot, [('subject', 'subj')]),
                (get_fs, get_correct_aseg, [('aparc_aseg', 'in_list')]),
                (get_correct_aseg, convert, [('out_aseg', 'in_file')]),
                (convert, downsample, [('out_file', 'in_file')]),
                (ds_rs, downsample, [('func', 'master')]),
                (downsample, bigplot, [('out_file', 'seg')]),
                (ds_rs, calc_fd, [('motpars', 'realignment_parameters_file')]),
                (ds_rs, bigplot, [('func', 'func')]),
                (ds_rs, bigplot, [('dvars', 'dvars')]),
                (calc_fd, bigplot, [('FD_power', 'fd')]),
                (ds_rs, outliers, [('func', 'in_file')]),
                (ds_rs, outliers, [('brainmask', 'mask')]),
                (outliers, bigplot, [('out_file', 'outliers')]),
                (bigplot, datasink, [('fn', 'detailedQA.@bigplot')]),
                (bigplot, fftplot, [('dataframe', 'fn_pd')]),
                (bigplot, datasink, [('dataframe',
                                      'detailedQA.metrics.@dataframe')]),
                (fftplot, datasink, [('fn', 'detailedQA.@fftplot')]),
                (calc_fd, datasink, [('fn', 'detailedQA.metrics.@fd')])])

    qc.run(plugin="MultiProc", plugin_args={"n_procs": 16, "non_daemon": True})

    return qc