<commit_before>'''
Workflow for discovering confounds.
Calculates frame displacement, segment regressors, global regressor, dvars, aCompCor, tCompCor
'''
from nipype.interfaces import utility, nilearn, fsl
from nipype.algorithms import confounds
from nipype.interfaces.utility import Merge
from nipype.pipeline import engine as pe
from niworkflows.interfaces.masks import ACompCorRPT

from fmriprep import interfaces
from fmriprep.interfaces.bids import DerivativesDataSink
from fmriprep.interfaces.utils import prepare_roi_from_probtissue

def discover_wf(settings, name="ConfoundDiscoverer"):
    ''' All input fields are required.

    Calculates global regressor and tCompCor
        from motion-corrected fMRI ('inputnode.fmri_file').
    Calculates DVARS from the fMRI and an EPI brain mask ('inputnode.epi_mask')
    Calculates frame displacement from MCFLIRT movement parameters ('inputnode.movpar_file')
    Calculates segment regressors and aCompCor
        from the fMRI and a white matter/gray matter/CSF segmentation ('inputnode.t1_seg'), after
        applying the transform to the images. Transforms should be fsl-formatted.

    Saves the confounds in a file ('outputnode.confounds_file')'''

    inputnode = pe.Node(utility.IdentityInterface(fields=['fmri_file', 'movpar_file', 't1_tpms',
                                                          'epi_mask', 't1_transform',
                                                          'reference_image',
                                                          'motion_confounds_file',
                                                          'source_file']),
                        name='inputnode')
    outputnode = pe.Node(utility.IdentityInterface(fields=['confounds_file']),
                         name='outputnode')

    # registration using ANTs
    t1_registration = pe.MapNode(fsl.preprocess.ApplyXFM(interp='sinc'),
                                 name='T1Registration', iterfield='in_file')
    # DVARS
    dvars = pe.Node(confounds.ComputeDVARS(save_all=True, remove_zerovariance=True),
                    name="ComputeDVARS")
    dvars.interface.estimated_memory_gb = settings[
                                              "biggest_epi_file_size_gb"] * 3
    # Frame displacement
    frame_displace = pe.Node(confounds.FramewiseDisplacement(), name="FramewiseDisplacement")
    frame_displace.interface.estimated_memory_gb = settings[
                                              "biggest_epi_file_size_gb"] * 3
    # CompCor
    tcompcor = pe.Node(confounds.TCompCor(components_file='tcompcor.tsv'), name="tCompCor")
    tcompcor.interface.estimated_memory_gb = settings[
                                              "biggest_epi_file_size_gb"] * 3

    CSF_roi = pe.Node(utility.Function(input_names=['in_file', 'epi_mask',
                                                    'erosion_mm',
                                                    'epi_mask_erosion_mm'],
                                       output_names=['roi_file'],
                                       function=prepare_roi_from_probtissue),
                      name='CSF_roi')
    CSF_roi.inputs.erosion_mm = 0
    CSF_roi.inputs.epi_mask_erosion_mm = 30

    WM_roi = pe.Node(utility.Function(input_names=['in_file', 'epi_mask',
                                                   'erosion_mm',
                                                   'epi_mask_erosion_mm'],
                                      output_names=['roi_file'],
                                      function=prepare_roi_from_probtissue),
                      name='WM_roi')
    WM_roi.inputs.erosion_mm = 0
    WM_roi.inputs.epi_mask_erosion_mm = 0

    # Global and segment regressors
    signals = pe.Node(nilearn.SignalExtraction(detrend=True,
                                               class_labels=["WhiteMatter", "GlobalSignal"]),
                      name="SignalExtraction")
    signals.interface.estimated_memory_gb = settings[
                                              "biggest_epi_file_size_gb"] * 3

    def combine_rois(in_CSF, in_WM):
        import os
        import numpy as np
        import nibabel as nb

        CSF_nii = nb.load(in_CSF)
        CSF_data = CSF_nii.get_data()

        WM_nii = nb.load(in_WM)
        WM_data = WM_nii.get_data()

        combined = np.zeros_like(WM_data)

        combined[WM_data != 0] = 1
        combined[CSF_data != 0] = 1

        new_nii = nb.Nifti1Image(combined, CSF_nii.affine,
                                 CSF_nii.header)
        new_nii.to_filename("logical_and.nii.gz")

        # we have to do this explicitly because of potential differences in
        # qform_code between the two files that prevent SignalExtraction to do
        # the concatenation
        concat_nii = nb.funcs.concat_images([CSF_nii, WM_nii], check_affines=False)
        concat_nii.to_filename("concat.nii.gz")
        return os.path.abspath("concat.nii.gz"), os.path.abspath("logical_and.nii.gz")

    combine_rois = pe.Node(utility.Function(input_names=['in_CSF', 'in_WM'],
                                            output_names=['concat_file',
                                                          'logical_and_file'],
                                            function=combine_rois),
                           name='combine_rois')

    acompcor = pe.Node(ACompCorRPT(components_file='acompcor.tsv',
                                   generate_report=True),
                       name="aCompCor")
    acompcor.interface.estimated_memory_gb = settings[
                                              "biggest_epi_file_size_gb"] * 3

    ds_report = pe.Node(
        DerivativesDataSink(base_directory=settings['output_dir'],
                            suffix='acompcor', out_path_base='reports'),
        name='ds_report'
    )

    # misc utilities
    concat = pe.Node(utility.Function(function=_gather_confounds, input_names=['signals', 'dvars',
                                                                               'frame_displace',
                                                                               'tcompcor',
                                                                               'acompcor',
                                                                               'motion'],
                                      output_names=['combined_out']),
                     name="ConcatConfounds")
    ds_confounds = pe.Node(interfaces.DerivativesDataSink(base_directory=settings['output_dir'],
                                                          suffix='confounds'),
                           name="DerivConfounds")

    def pick_csf(files):
        return files[0]

    def pick_wm(files):
        return files[2]

    workflow = pe.Workflow(name=name)
    workflow.connect([
        # connect inputnode to each non-anatomical confound node
        (inputnode, dvars, [('fmri_file', 'in_file'),
                            ('epi_mask', 'in_mask')]),
        (inputnode, frame_displace, [('movpar_file', 'in_plots')]),
        (inputnode, tcompcor, [('fmri_file', 'realigned_file')]),

        # anatomically-based confound computation requires coregistration
        (inputnode, t1_registration, [('reference_image', 'reference'),
                                      ('t1_tpms', 'in_file'),
                                      ('t1_transform', 'in_matrix_file')]),
        (t1_registration, CSF_roi, [(('out_file', pick_csf), 'in_file')]),
        (inputnode, CSF_roi, [('epi_mask',  'epi_mask')]),

        (t1_registration, WM_roi, [(('out_file', pick_wm), 'in_file')]),
        (inputnode, WM_roi, [('epi_mask', 'epi_mask')]),

        (CSF_roi, combine_rois, [('roi_file', 'in_CSF')]),
        (WM_roi, combine_rois, [('roi_file', 'in_WM')]),

        # anatomical confound: aCompCor.
        (inputnode, acompcor, [('fmri_file', 'realigned_file')]),
        (combine_rois, acompcor, [('logical_and_file', 'mask_file')]),

        # anatomical confound: signal extraction
        (combine_rois, signals, [('concat_file', 'label_files')]),
        (inputnode, signals, [('fmri_file', 'in_file')]),

        # connect the confound nodes to the concatenate node
        (signals, concat, [('out_file', 'signals')]),
        (dvars, concat, [('out_all', 'dvars')]),
        (frame_displace, concat, [('out_file', 'frame_displace')]),
        (tcompcor, concat, [('components_file', 'tcompcor')]),
        (acompcor, concat, [('components_file', 'acompcor')]),
        (inputnode, concat, [('motion_confounds_file', 'motion')]),

        (concat, outputnode, [('combined_out', 'confounds_file')]),
<commit_msg>fix global signal extraction<commit_after>'''
Workflow for discovering confounds.
Calculates frame displacement, segment regressors, global regressor, dvars, aCompCor, tCompCor
'''
from nipype.interfaces import utility, nilearn, fsl
from nipype.algorithms import confounds
from nipype.interfaces.utility import Merge
from nipype.pipeline import engine as pe
from niworkflows.interfaces.masks import ACompCorRPT

from fmriprep import interfaces
from fmriprep.interfaces.bids import DerivativesDataSink
from fmriprep.interfaces.utils import prepare_roi_from_probtissue

def discover_wf(settings, name="ConfoundDiscoverer"):
    ''' All input fields are required.

    Calculates global regressor and tCompCor
        from motion-corrected fMRI ('inputnode.fmri_file').
    Calculates DVARS from the fMRI and an EPI brain mask ('inputnode.epi_mask')
    Calculates frame displacement from MCFLIRT movement parameters ('inputnode.movpar_file')
    Calculates segment regressors and aCompCor
        from the fMRI and a white matter/gray matter/CSF segmentation ('inputnode.t1_seg'), after
        applying the transform to the images. Transforms should be fsl-formatted.

    Saves the confounds in a file ('outputnode.confounds_file')'''

    inputnode = pe.Node(utility.IdentityInterface(fields=['fmri_file', 'movpar_file', 't1_tpms',
                                                          'epi_mask', 't1_transform',
                                                          'reference_image',
                                                          'motion_confounds_file',
                                                          'source_file']),
                        name='inputnode')
    outputnode = pe.Node(utility.IdentityInterface(fields=['confounds_file']),
                         name='outputnode')

    # registration using ANTs
    t1_registration = pe.MapNode(fsl.preprocess.ApplyXFM(interp='sinc'),
                                 name='T1Registration', iterfield='in_file')
    # DVARS
    dvars = pe.Node(confounds.ComputeDVARS(save_all=True, remove_zerovariance=True),
                    name="ComputeDVARS")
    dvars.interface.estimated_memory_gb = settings[
                                              "biggest_epi_file_size_gb"] * 3
    # Frame displacement
    frame_displace = pe.Node(confounds.FramewiseDisplacement(), name="FramewiseDisplacement")
    frame_displace.interface.estimated_memory_gb = settings[
                                              "biggest_epi_file_size_gb"] * 3
    # CompCor
    tcompcor = pe.Node(confounds.TCompCor(components_file='tcompcor.tsv'), name="tCompCor")
    tcompcor.interface.estimated_memory_gb = settings[
                                              "biggest_epi_file_size_gb"] * 3

    CSF_roi = pe.Node(utility.Function(input_names=['in_file', 'epi_mask',
                                                    'erosion_mm',
                                                    'epi_mask_erosion_mm'],
                                       output_names=['roi_file'],
                                       function=prepare_roi_from_probtissue),
                      name='CSF_roi')
    CSF_roi.inputs.erosion_mm = 0
    CSF_roi.inputs.epi_mask_erosion_mm = 30

    WM_roi = pe.Node(utility.Function(input_names=['in_file', 'epi_mask',
                                                   'erosion_mm',
                                                   'epi_mask_erosion_mm'],
                                      output_names=['roi_file'],
                                      function=prepare_roi_from_probtissue),
                      name='WM_roi')
    WM_roi.inputs.erosion_mm = 0
    WM_roi.inputs.epi_mask_erosion_mm = 0

    def concat_rois_func(in_WM, in_mask):
        import os
        import nibabel as nb

        WM_nii = nb.load(in_WM)
        mask_nii = nb.load(in_mask)

        # we have to do this explicitly because of potential differences in
        # qform_code between the two files that prevent SignalExtraction to do
        # the concatenation
        concat_nii = nb.funcs.concat_images([WM_nii, mask_nii],
                                            check_affines=False)
        concat_nii.to_filename("concat.nii.gz")
        return os.path.abspath("concat.nii.gz")

    concat_rois = pe.Node(utility.Function(input_names=['in_WM', 'in_mask'],
                                           output_names=['concat_file'],
                                           function=concat_rois_func),
                          name='concat_rois')

    # Global and segment regressors
    signals = pe.Node(nilearn.SignalExtraction(detrend=True,
                                               class_labels=["WhiteMatter", "GlobalSignal"]),
                      name="SignalExtraction")
    signals.interface.estimated_memory_gb = settings[
                                              "biggest_epi_file_size_gb"] * 3

    def combine_rois(in_CSF, in_WM):
        import os
        import numpy as np
        import nibabel as nb

        CSF_nii = nb.load(in_CSF)
        CSF_data = CSF_nii.get_data()

        WM_nii = nb.load(in_WM)
        WM_data = WM_nii.get_data()

        combined = np.zeros_like(WM_data)

        combined[WM_data != 0] = 1
        combined[CSF_data != 0] = 1

        new_nii = nb.Nifti1Image(combined, CSF_nii.affine,
                                 CSF_nii.header)
        new_nii.to_filename("logical_and.nii.gz")
        return os.path.abspath("logical_and.nii.gz")

    combine_rois = pe.Node(utility.Function(input_names=['in_CSF', 'in_WM'],
                                            output_names=['logical_and_file'],
                                            function=combine_rois),
                           name='combine_rois')

    acompcor = pe.Node(ACompCorRPT(components_file='acompcor.tsv',
                                   generate_report=True),
                       name="aCompCor")
    acompcor.interface.estimated_memory_gb = settings[
                                              "biggest_epi_file_size_gb"] * 3

    ds_report = pe.Node(
        DerivativesDataSink(base_directory=settings['output_dir'],
                            suffix='acompcor', out_path_base='reports'),
        name='ds_report'
    )

    # misc utilities
    concat = pe.Node(utility.Function(function=_gather_confounds, input_names=['signals', 'dvars',
                                                                               'frame_displace',
                                                                               'tcompcor',
                                                                               'acompcor',
                                                                               'motion'],
                                      output_names=['combined_out']),
                     name="ConcatConfounds")
    ds_confounds = pe.Node(interfaces.DerivativesDataSink(base_directory=settings['output_dir'],
                                                          suffix='confounds'),
                           name="DerivConfounds")

    def pick_csf(files):
        return files[0]

    def pick_wm(files):
        return files[2]

    workflow = pe.Workflow(name=name)
    workflow.connect([
        # connect inputnode to each non-anatomical confound node
        (inputnode, dvars, [('fmri_file', 'in_file'),
                            ('epi_mask', 'in_mask')]),
        (inputnode, frame_displace, [('movpar_file', 'in_plots')]),
        (inputnode, tcompcor, [('fmri_file', 'realigned_file')]),

        # anatomically-based confound computation requires coregistration
        (inputnode, t1_registration, [('reference_image', 'reference'),
                                      ('t1_tpms', 'in_file'),
                                      ('t1_transform', 'in_matrix_file')]),
        (t1_registration, CSF_roi, [(('out_file', pick_csf), 'in_file')]),
        (inputnode, CSF_roi, [('epi_mask',  'epi_mask')]),

        (t1_registration, WM_roi, [(('out_file', pick_wm), 'in_file')]),
        (inputnode, WM_roi, [('epi_mask', 'epi_mask')]),

        (CSF_roi, combine_rois, [('roi_file', 'in_CSF')]),
        (WM_roi, combine_rois, [('roi_file', 'in_WM')]),

        # anatomical confound: aCompCor.
        (inputnode, acompcor, [('fmri_file', 'realigned_file')]),
        (combine_rois, acompcor, [('logical_and_file', 'mask_file')]),

        (WM_roi, concat_rois, [('roi_file', 'in_WM')]),
        (inputnode, concat_rois, [('epi_mask', 'in_mask')]),

        # anatomical confound: signal extraction
        (concat_rois, signals, [('concat_file', 'label_files')]),
        (inputnode, signals, [('fmri_file', 'in_file')]),

        # connect the confound nodes to the concatenate node
        (signals, concat, [('out_file', 'signals')]),
        (dvars, concat, [('out_all', 'dvars')]),
        (frame_displace, concat, [('out_file', 'frame_displace')]),
        (tcompcor, concat, [('components_file', 'tcompcor')]),
        (acompcor, concat, [('components_file', 'acompcor')]),
        (inputnode, concat, [('motion_confounds_file', 'motion')]),

        (concat, outputnode, [('combined_out', 'confounds_file')]),

{'fraction_non_alphanumeric': 0.10408151839202733, 'fraction_numerical': 0.0030233469570572756, 'mean_word_length': 1.7988091507364463, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 120, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4715646', 'n_tokens_mistral': 5168, 'n_tokens_neox': 4872, 'n_words': 900}