<commit_before># emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
"""
Resampling workflows
++++++++++++++++++++

.. autofunction:: init_bold_surf_wf
.. autofunction:: init_bold_std_trans_wf
.. autofunction:: init_bold_preproc_trans_wf

"""
from nipype.pipeline import engine as pe
from nipype.interfaces import utility as niu, freesurfer as fs
from nipype.interfaces.fsl import Split as FSLSplit
import nipype.interfaces.workbench as wb

from niworkflows.engine.workflows import LiterateWorkflow as Workflow
from niworkflows.interfaces.fixes import FixHeaderApplyTransforms as ApplyTransforms
from niworkflows.interfaces.freesurfer import (
    MedialNaNs,
    # See https://github.com/poldracklab/fmriprep/issues/768
    PatchedConcatenateLTA as ConcatenateLTA,
    PatchedLTAConvert as LTAConvert
)
from niworkflows.interfaces.itk import MultiApplyTransforms
from niworkflows.interfaces.utils import GenerateSamplingReference
from niworkflows.interfaces.utility import KeySelect
from niworkflows.interfaces.surf import GiftiSetAnatomicalStructure
from niworkflows.interfaces.nilearn import Merge

from ...config import DEFAULT_MEMORY_MIN_GB
from ...interfaces import DerivativesDataSink

from .util import init_bold_reference_wf


def init_bold_surf_wf(mem_gb, output_spaces, medial_surface_nan, name='bold_surf_wf'):
    """
    Sample functional images to FreeSurfer surfaces.

    For each vertex, the cortical ribbon is sampled at six points (spaced 20% of thickness apart)
    and averaged.
    Outputs are in GIFTI format.

    Workflow Graph
        .. workflow::
            :graph2use: colored
            :simple_form: yes

            from fmriprep.workflows.bold import init_bold_surf_wf
            wf = init_bold_surf_wf(mem_gb=0.1,
                                   output_spaces=['T1w', 'fsnative',
                                                 'template', 'fsaverage5'],
                                   medial_surface_nan=False)

    Parameters
    ----------
    output_spaces : list
        List of output spaces functional images are to be resampled to
        Target spaces beginning with ``fs`` will be selected for resampling,
        such as ``fsaverage`` or related template spaces
        If the list contains ``fsnative``, images will be resampled to the
        individual subject's native surface
        If the list contains ``fsLR``, images will be resampled twice;
        first to ``fsaverage`` and then to ``fsLR``.
    medial_surface_nan : bool
        Replace medial wall values with NaNs on functional GIFTI files

    Inputs
    ------
    source_file
        Motion-corrected BOLD series in T1 space
    t1w_preproc
        Bias-corrected structural template image
    subjects_dir
        FreeSurfer SUBJECTS_DIR
    subject_id
        FreeSurfer subject ID
    t1w2fsnative_xfm
        LTA-style affine matrix translating from T1w to FreeSurfer-conformed subject space

    Outputs
    -------
    surfaces
        BOLD series, resampled to FreeSurfer surfaces

    """
    # Ensure volumetric spaces do not sneak into this workflow
    spaces = [space for space in output_spaces if space.startswith('fs')]

    workflow = Workflow(name=name)

    if spaces:
        workflow.__desc__ = """\
The BOLD time-series, were resampled to surfaces on the following
spaces: {out_spaces}.
""".format(out_spaces=', '.join(['*%s*' % s for s in spaces]))
    inputnode = pe.Node(
        niu.IdentityInterface(fields=['source_file', 't1w_preproc', 'subject_id', 'subjects_dir',
                                      't1w2fsnative_xfm']),
        name='inputnode')

    to_fslr = False
    if 'fsLR' in output_spaces:
        fslr_den = output_spaces.get('fsLR', {}).get('den', '32k')
        to_fslr = 'fsaverage' in output_spaces
        output_spaces.pop(output_spaces.index('fsLR'))

    outputnode = pe.Node(niu.IdentityInterface(fields=['surfaces']), name='outputnode')

    def select_target(subject_id, space):
        """Get the target subject ID, given a source subject ID and a target space."""
        return subject_id if space == 'fsnative' else space

    targets = pe.MapNode(niu.Function(function=select_target),
                         iterfield=['space'], name='targets',
                         mem_gb=DEFAULT_MEMORY_MIN_GB)
    targets.inputs.space = spaces

    # Rename the source file to the output space to simplify naming later
    rename_src = pe.MapNode(niu.Rename(format_string='%(subject)s', keep_ext=True),
                            iterfield='subject', name='rename_src', run_without_submitting=True,
                            mem_gb=DEFAULT_MEMORY_MIN_GB)
    rename_src.inputs.subject = spaces

    resampling_xfm = pe.Node(LTAConvert(in_lta='identity.nofile', out_lta=True),
                             name='resampling_xfm')
    set_xfm_source = pe.Node(ConcatenateLTA(out_type='RAS2RAS'), name='set_xfm_source')

    sampler = pe.MapNode(
        fs.SampleToSurface(sampling_method='average', sampling_range=(0, 1, 0.2),
                           sampling_units='frac', interp_method='trilinear', cortex_mask=True,
                           override_reg_subj=True, out_type='gii'),
        iterfield=['source_file', 'target_subject'],
        iterables=('hemi', ['lh', 'rh']),
        name='sampler', mem_gb=mem_gb * 3)

    if to_fslr:

        filter_fsavg = pe.Node(niu.Function(function=_select_fsaverage_hemi,
                                            output_names=['fsaverage_bold', 'hemi']),
                               name='filter_fsavg', mem_gb=DEFAULT_MEMORY_MIN_GB)

        fetch_fslr_tpls = pe.Node(niu.Function(function=_fetch_fslr_templates),
                                  output_names=['fsaverage_sphere', 'fsaverage_midthick',
                                                'fslr_sphere', 'fslr_midthick'],
                                  name='fetch_fslr_tpls')

        resample_fslr = pe.Node(wb.MetricResample(method='ADAP_BARY_AREA', area_metrics=True),
                                name='resample_fslr')

    medial_nans = pe.MapNode(MedialNaNs(), iterfield=['in_file', 'target_subject'],
                             name='medial_nans', mem_gb=DEFAULT_MEMORY_MIN_GB)

    merger = pe.JoinNode(niu.Merge(1, ravel_inputs=True), name='merger',
                         joinsource='sampler', joinfield=['in1'], run_without_submitting=True,
                         mem_gb=DEFAULT_MEMORY_MIN_GB)

    update_metadata = pe.MapNode(GiftiSetAnatomicalStructure(), iterfield='in_file',
                                 name='update_metadata', mem_gb=DEFAULT_MEMORY_MIN_GB)

    workflow.connect([
        (inputnode, targets, [('subject_id', 'subject_id')]),
        (inputnode, rename_src, [('source_file', 'in_file')]),
        (inputnode, resampling_xfm, [('source_file', 'source_file'),
                                     ('t1w_preproc', 'target_file')]),
        (inputnode, set_xfm_source, [('t1w2fsnative_xfm', 'in_lta2')]),
        (resampling_xfm, set_xfm_source, [('out_lta', 'in_lta1')]),
        (inputnode, sampler, [('subjects_dir', 'subjects_dir'),
                              ('subject_id', 'subject_id')]),
        (set_xfm_source, sampler, [('out_file', 'reg_file')]),
        (targets, sampler, [('out', 'target_subject')]),
        (rename_src, sampler, [('out_file', 'source_file')]),
        (merger, update_metadata, [('out', 'in_file')]),
        (update_metadata, outputnode, [('out_file', 'surfaces')]),
    ])

    if medial_surface_nan:
        workflow.connect([
            (inputnode, medial_nans, [('subjects_dir', 'subjects_dir')]),
            (targets, medial_nans, [('out', 'target_subject')]),
            (medial_nans, merger, [('out_file', 'in1')]),
        ])

    if to_fslr and medial_surface_nan:
        workflow.connect(resample_fslr, 'out_file', medial_nans, 'in_file')
    elif to_fslr:
        workflow.connect(resample_fslr, 'out_file', merger, 'in1')
    elif medial_surface_nan:
        workflow.connect(sampler, 'out_file', medial_nans, 'in_file')
    else:
        workflow.connect(sampler, 'out_file', merger, 'in1')

    return workflow


def init_bold_std_trans_wf(
    freesurfer,
    mem_gb,
    omp_nthreads,<commit_msg>fix: fslr and medial wall nan compatibility<commit_after># emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
"""
Resampling workflows
++++++++++++++++++++

.. autofunction:: init_bold_surf_wf
.. autofunction:: init_bold_std_trans_wf
.. autofunction:: init_bold_preproc_trans_wf

"""
from nipype.pipeline import engine as pe
from nipype.interfaces import utility as niu, freesurfer as fs
from nipype.interfaces.fsl import Split as FSLSplit
import nipype.interfaces.workbench as wb

from niworkflows.engine.workflows import LiterateWorkflow as Workflow
from niworkflows.interfaces.fixes import FixHeaderApplyTransforms as ApplyTransforms
from niworkflows.interfaces.freesurfer import (
    MedialNaNs,
    # See https://github.com/poldracklab/fmriprep/issues/768
    PatchedConcatenateLTA as ConcatenateLTA,
    PatchedLTAConvert as LTAConvert
)
from niworkflows.interfaces.itk import MultiApplyTransforms
from niworkflows.interfaces.utils import GenerateSamplingReference
from niworkflows.interfaces.utility import KeySelect
from niworkflows.interfaces.surf import GiftiSetAnatomicalStructure
from niworkflows.interfaces.nilearn import Merge

from ...config import DEFAULT_MEMORY_MIN_GB
from ...interfaces import DerivativesDataSink

from .util import init_bold_reference_wf


def init_bold_surf_wf(mem_gb, output_spaces, medial_surface_nan, name='bold_surf_wf'):
    """
    Sample functional images to FreeSurfer surfaces.

    For each vertex, the cortical ribbon is sampled at six points (spaced 20% of thickness apart)
    and averaged.
    Outputs are in GIFTI format.

    Workflow Graph
        .. workflow::
            :graph2use: colored
            :simple_form: yes

            from fmriprep.workflows.bold import init_bold_surf_wf
            wf = init_bold_surf_wf(mem_gb=0.1,
                                   output_spaces=['T1w', 'fsnative',
                                                 'template', 'fsaverage5'],
                                   medial_surface_nan=False)

    Parameters
    ----------
    output_spaces : list
        List of output spaces functional images are to be resampled to
        Target spaces beginning with ``fs`` will be selected for resampling,
        such as ``fsaverage`` or related template spaces
        If the list contains ``fsnative``, images will be resampled to the
        individual subject's native surface
        If the list contains ``fsLR``, images will be resampled twice;
        first to ``fsaverage`` and then to ``fsLR``.
    medial_surface_nan : bool
        Replace medial wall values with NaNs on functional GIFTI files

    Inputs
    ------
    source_file
        Motion-corrected BOLD series in T1 space
    t1w_preproc
        Bias-corrected structural template image
    subjects_dir
        FreeSurfer SUBJECTS_DIR
    subject_id
        FreeSurfer subject ID
    t1w2fsnative_xfm
        LTA-style affine matrix translating from T1w to FreeSurfer-conformed subject space

    Outputs
    -------
    surfaces
        BOLD series, resampled to FreeSurfer surfaces

    """
    # Ensure volumetric spaces do not sneak into this workflow
    spaces = [space for space in output_spaces if space.startswith('fs')]

    workflow = Workflow(name=name)

    if spaces:
        workflow.__desc__ = """\
The BOLD time-series, were resampled to surfaces on the following
spaces: {out_spaces}.
""".format(out_spaces=', '.join(['*%s*' % s for s in spaces]))
    inputnode = pe.Node(
        niu.IdentityInterface(fields=['source_file', 't1w_preproc', 'subject_id', 'subjects_dir',
                                      't1w2fsnative_xfm']),
        name='inputnode')

    to_fslr = False
    if 'fsLR' in output_spaces:
        fslr_den = output_spaces.get('fsLR', {}).get('den', '32')
        to_fslr = 'fsaverage' in output_spaces
        output_spaces.pop(output_spaces.index('fsLR'))

    outputnode = pe.Node(niu.IdentityInterface(fields=['surfaces']), name='outputnode')

    def select_target(subject_id, space):
        """Get the target subject ID, given a source subject ID and a target space."""
        return subject_id if space == 'fsnative' else space

    targets = pe.MapNode(niu.Function(function=select_target),
                         iterfield=['space'], name='targets',
                         mem_gb=DEFAULT_MEMORY_MIN_GB)
    targets.inputs.space = spaces

    # Rename the source file to the output space to simplify naming later
    rename_src = pe.MapNode(niu.Rename(format_string='%(subject)s', keep_ext=True),
                            iterfield='subject', name='rename_src', run_without_submitting=True,
                            mem_gb=DEFAULT_MEMORY_MIN_GB)
    rename_src.inputs.subject = spaces

    resampling_xfm = pe.Node(LTAConvert(in_lta='identity.nofile', out_lta=True),
                             name='resampling_xfm')
    set_xfm_source = pe.Node(ConcatenateLTA(out_type='RAS2RAS'), name='set_xfm_source')

    sampler = pe.MapNode(
        fs.SampleToSurface(sampling_method='average', sampling_range=(0, 1, 0.2),
                           sampling_units='frac', interp_method='trilinear', cortex_mask=True,
                           override_reg_subj=True, out_type='gii'),
        iterfield=['source_file', 'target_subject'],
        iterables=('hemi', ['lh', 'rh']),
        name='sampler', mem_gb=mem_gb * 3)

    if to_fslr:

        filter_fsavg = pe.Node(niu.Function(function=_select_fsaverage_hemi,
                                            output_names=['fsaverage_bold', 'hemi']),
                               name='filter_fsavg', mem_gb=DEFAULT_MEMORY_MIN_GB,
                               run_without_submitting=True)

        rename_fslr = pe.Node(niu.Rename(format_string="%(hemi)s.fslr", keep_ext=True,
                                         parse_string=r'^(?P<hemi>\w+)'),
                              name='rename_fslr', mem_gb=DEFAULT_MEMORY_MIN_GB,
                              run_without_submitting=True)

        fetch_fslr_tpls = pe.Node(niu.Function(function=_fetch_fslr_templates),
                                  output_names=['fsaverage_sphere', 'fslr_sphere',
                                                'fsaverage_midthick', 'fslr_midthick'],
                                  name='fetch_fslr_tpls', mem_gb=DEFAULT_MEMORY_MIN_GB)
        fetch_fslr_tpls.inputs.den = fslr_den

        resample_fslr = pe.Node(wb.MetricResample(method='ADAP_BARY_AREA', area_metrics=True),
                                name='resample_fslr')

        merge_fslr = pe.Node(niu.Merge(2), name='merge_fslr', mem_gb=DEFAULT_MEMORY_MIN_GB,
                             run_without_submitting=True)

        workflow.connect([
            (sampler, filter_fsavg, [('out_file', 'in_files')]),
            (filter_fsavg, fetch_fslr_tpls, [('hemi', 'hemi')]),
            (filter_fsavg, rename_fslr, [('fsaverage_bold', 'in_file')]),
            (rename_fslr, resample_fslr, [('out_file', 'in_file')]),
            (rename_fslr, resample_fslr, [('out_file', 'out_file')]),
            (fetch_fslr_tpls, resample_fslr, [('fsaverage_sphere', 'current_sphere'),
                                              ('fslr_sphere', 'new_sphere'),
                                              ('fsaverage_midthick', 'current_area'),
                                              ('fslr_midthick', 'new_area')]),
            (sampler, merge_fslr, [('out_file', 'in1')]),
            (resample_fslr, merge_fslr, [('out_file', 'in2')]),
        ])

    merger = pe.JoinNode(niu.Merge(1, ravel_inputs=True), name='merger',
                         joinsource='sampler', joinfield=['in1'], run_without_submitting=True,
                         mem_gb=DEFAULT_MEMORY_MIN_GB)

    if medial_surface_nan:
        medial_nans = pe.MapNode(MedialNaNs(), iterfield=['in_file'],
                                 name='medial_nans', mem_gb=DEFAULT_MEMORY_MIN_GB)

        workflow.connect([
            (inputnode, medial_nans, [('subjects_dir', 'subjects_dir')]),
            (medial_nans, merger, [('out_file', 'in1')]),
        ])

    update_metadata = pe.MapNode(GiftiSetAnatomicalStructure(), iterfield='in_file',
                                 name='update_metadata', mem_gb=DEFAULT_MEMORY_MIN_GB)

    workflow.connect([
        (inputnode, targets, [('subject_id', 'subject_id')]),
        (inputnode, rename_src, [('source_file', 'in_file')]),
        (inputnode, resampling_xfm, [('source_file', 'source_file'),
                                     ('t1w_preproc', 'target_file')]),
        (inputnode, set_xfm_source, [('t1w2fsnative_xfm', 'in_lta2')]),
        (resampling_xfm, set_xfm_source, [('out_lta', 'in_lta1')]),
        (inputnode, sampler, [('subjects_dir', 'subjects_dir'),
                              ('subject_id', 'subject_id')]),
        (set_xfm_source, sampler, [('out_file', 'reg_file')]),
        (targets, sampler, [('out', 'target_subject')]),
        (rename_src, sampler, [('out_file', 'source_file')]),
        (merger, update_metadata, [('out', 'in_file')]),
        (update_metadata, outputnode, [('out_file', 'surfaces')]),
    ])

    if to_fslr and medial_surface_nan:
        workflow.connect(merge_fslr, 'out_file', medial_nans, 'in_file')
    elif to_fslr:
        workflow.connect(merge_fslr, 'out_file', merger, 'in1')
    elif medial_surface_nan:
        workflow.connect(sampler, 'out_file', medial_nans, 'in_file')
    else:
        workflow.connect(sampler, 'out_file', merger, 'in1')

    return workflow


def init_bold_std_trans_wf(
    freesurfer,
    mem_gb,
    omp_nthreads,
{'fraction_non_alphanumeric': 0.11186270125223613, 'fraction_numerical': 0.0046399821109123435, 'mean_word_length': 2.6448655256723717, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 4, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 35, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3089005', 'n_tokens_mistral': 5772, 'n_tokens_neox': 5501, 'n_words': 1153}