def init_bold_grayords_wf(grayord_density, mem_gb, repetition_time, name="bold_grayords_wf"): """ Sample Grayordinates files onto the fsLR atlas. Outputs are in CIFTI2 format. Workflow Graph .. workflow:: :graph2use: colored :simple_form: yes from fprodents.workflows.bold.resampling import init_bold_grayords_wf wf = init_bold_grayords_wf(mem_gb=0.1, grayord_density='91k') Parameters ---------- grayord_density : :obj:`str` Either `91k` or `170k`, representing the total of vertices or *grayordinates*. mem_gb : :obj:`float` Size of BOLD file in GB name : :obj:`str` Unique name for the subworkflow (default: ``'bold_grayords_wf'``) Inputs ------ bold_std : :obj:`str` List of BOLD conversions to standard spaces. spatial_reference :obj:`str` List of unique identifiers corresponding to the BOLD standard-conversions. subjects_dir : :obj:`str` FreeSurfer's subjects directory. surf_files : :obj:`str` List of BOLD files resampled on the fsaverage (ico7) surfaces. surf_refs : List of unique identifiers corresponding to the BOLD surface-conversions. Outputs ------- cifti_bold : :obj:`str` List of BOLD grayordinates files - (L)eft and (R)ight. cifti_variant : :obj:`str` Only ``'HCP Grayordinates'`` is currently supported. cifti_metadata : :obj:`str` Path of metadata files corresponding to ``cifti_bold``. cifti_density : :obj:`str` Density (i.e., either `91k` or `170k`) of ``cifti_bold``. """ import templateflow.api as tf from niworkflows.engine.workflows import LiterateWorkflow as Workflow from niworkflows.interfaces.cifti import GenerateCifti from niworkflows.interfaces.utility import KeySelect workflow = Workflow(name=name) workflow.__desc__ = """\ *Grayordinates* files [@hcppipelines] containing {density} samples were also generated using the highest-resolution ``fsaverage`` as intermediate standardized surface space. """.format(density=grayord_density) fslr_density, mni_density = (("32k", "2") if grayord_density == "91k" else ("59k", "1")) inputnode = pe.Node( niu.IdentityInterface(fields=[ "bold_std", "spatial_reference", "subjects_dir", "surf_files", "surf_refs", ]), name="inputnode", ) outputnode = pe.Node( niu.IdentityInterface(fields=[ "cifti_bold", "cifti_variant", "cifti_metadata", "cifti_density" ]), name="outputnode", ) # extract out to BOLD base select_std = pe.Node( KeySelect(fields=["bold_std"]), name="select_std", run_without_submitting=True, nohash=True, ) select_std.inputs.key = "MNI152NLin6Asym_res-%s" % mni_density select_fs_surf = pe.Node( KeySelect(fields=["surf_files"]), name="select_fs_surf", run_without_submitting=True, mem_gb=DEFAULT_MEMORY_MIN_GB, ) select_fs_surf.inputs.key = "fsaverage" # Setup Workbench command. LR ordering for hemi can be assumed, as it is imposed # by the iterfield of the MapNode in the surface sampling workflow above. resample = pe.MapNode( wb.MetricResample(method="ADAP_BARY_AREA", area_metrics=True), name="resample", iterfield=[ "in_file", "out_file", "new_sphere", "new_area", "current_sphere", "current_area", ], ) resample.inputs.current_sphere = [ str( tf.get("fsaverage", hemi=hemi, density="164k", desc="std", suffix="sphere")) for hemi in "LR" ] resample.inputs.current_area = [ str( tf.get( "fsaverage", hemi=hemi, density="164k", desc="vaavg", suffix="midthickness", )) for hemi in "LR" ] resample.inputs.new_sphere = [ str( tf.get( "fsLR", space="fsaverage", hemi=hemi, density=fslr_density, suffix="sphere", )) for hemi in "LR" ] resample.inputs.new_area = [ str( tf.get( "fsLR", hemi=hemi, density=fslr_density, desc="vaavg", suffix="midthickness", )) for hemi in "LR" ] resample.inputs.out_file = [ "space-fsLR_hemi-%s_den-%s_bold.gii" % (h, grayord_density) for h in "LR" ] gen_cifti = pe.Node( GenerateCifti( volume_target="MNI152NLin6Asym", surface_target="fsLR", TR=repetition_time, surface_density=fslr_density, ), name="gen_cifti", ) # fmt:off workflow.connect([ (inputnode, gen_cifti, [('subjects_dir', 'subjects_dir')]), (inputnode, select_std, [('bold_std', 'bold_std'), ('spatial_reference', 'keys')]), (inputnode, select_fs_surf, [('surf_files', 'surf_files'), ('surf_refs', 'keys')]), (select_fs_surf, resample, [('surf_files', 'in_file')]), (select_std, gen_cifti, [('bold_std', 'bold_file')]), (resample, gen_cifti, [('out_file', 'surface_bolds')]), (gen_cifti, outputnode, [('out_file', 'cifti_bold'), ('variant', 'cifti_variant'), ('out_metadata', 'cifti_metadata'), ('density', 'cifti_density')]), ]) # fmt:on return workflow
def init_asl_grayords_wf(grayord_density, mem_gb, repetition_time, name='asl_grayords_wf'): """ Sample Grayordinates files onto the fsLR atlas. Outputs are in CIFTI2 format. Workflow Graph .. workflow:: :graph2use: colored :simple_form: yes from aslprep.workflows.asl import init_asl_grayords_wf wf = init_asl_grayords_wf(mem_gb=0.1, grayord_density='91k') Parameters ---------- grayord_density : :obj:`str` Either `91k` or `170k`, representing the total of vertices or *grayordinates*. mem_gb : :obj:`float` Size of asl file in GB name : :obj:`str` Unique name for the subworkflow (default: ``'asl_grayords_wf'``) Inputs ------ asl_std : :obj:`str` List of asl conversions to standard spaces. spatial_reference :obj:`str` List of unique identifiers corresponding to the asl standard-conversions. subjects_dir : :obj:`str` FreeSurfer's subjects directory. surf_files : :obj:`str` List of asl files resampled on the fsaverage (ico7) surfaces. surf_refs : List of unique identifiers corresponding to the asl surface-conversions. Outputs ------- cifti_asl : :obj:`str` List of asl grayordinates files - (L)eft and (R)ight. cifti_variant : :obj:`str` Only ``'HCP Grayordinates'`` is currently supported. cifti_metadata : :obj:`str` Path of metadata files corresponding to ``cifti_asl``. cifti_density : :obj:`str` Density (i.e., either `91k` or `170k`) of ``cifti_asl``. """ import templateflow.api as tf from ...niworkflows.engine.workflows import LiterateWorkflow as Workflow from ...niworkflows.interfaces.cifti import GenerateCifti from ...niworkflows.interfaces.utility import KeySelect workflow = Workflow(name=name) workflow.__desc__ = """\ *Grayordinates* files [@hcppipelines] containing {density} samples were also generated using the highest-resolution ``fsaverage`` as intermediate standardized surface space. """.format(density=grayord_density) fslr_density, mni_density = ('32k', '2') if grayord_density == '91k' else ('59k', '1') inputnode = pe.Node(niu.IdentityInterface(fields=[ 'asl_std', 'spatial_reference', 'subjects_dir', 'surf_files', 'surf_refs', ]), name='inputnode') outputnode = pe.Node(niu.IdentityInterface(fields=[ 'cifti_asl', 'cifti_variant', 'cifti_metadata', 'cifti_density', ]), name='outputnode') # extract out to asl base select_std = pe.Node(KeySelect(fields=['asl_std']), name='select_std', run_without_submitting=True, nohash=True) select_std.inputs.key = 'MNI152NLin6Asym_res-%s' % mni_density select_fs_surf = pe.Node(KeySelect(fields=['surf_files']), name='select_fs_surf', run_without_submitting=True, mem_gb=DEFAULT_MEMORY_MIN_GB) select_fs_surf.inputs.key = 'fsaverage' # Setup Workbench command. LR ordering for hemi can be assumed, as it is imposed # by the iterfield of the MapNode in the surface sampling workflow above. resample = pe.MapNode(wb.MetricResample(method='ADAP_BARY_AREA', area_metrics=True), name='resample', iterfield=[ 'in_file', 'out_file', 'new_sphere', 'new_area', 'current_sphere', 'current_area' ]) resample.inputs.current_sphere = [ str( tf.get('fsaverage', hemi=hemi, density='164k', desc='std', suffix='sphere')) for hemi in 'LR' ] resample.inputs.current_area = [ str( tf.get('fsaverage', hemi=hemi, density='164k', desc='vaavg', suffix='midthickness')) for hemi in 'LR' ] resample.inputs.new_sphere = [ str( tf.get('fsLR', space='fsaverage', hemi=hemi, density=fslr_density, suffix='sphere')) for hemi in 'LR' ] resample.inputs.new_area = [ str( tf.get('fsLR', hemi=hemi, density=fslr_density, desc='vaavg', suffix='midthickness')) for hemi in 'LR' ] resample.inputs.out_file = [ 'space-fsLR_hemi-%s_den-%s_asl.gii' % (h, grayord_density) for h in 'LR' ] gen_cifti = pe.Node(GenerateCifti( volume_target='MNI152NLin6Asym', surface_target='fsLR', TR=repetition_time, surface_density=fslr_density, ), name="gen_cifti") workflow.connect([ (inputnode, gen_cifti, [('subjects_dir', 'subjects_dir')]), (inputnode, select_std, [('asl_std', 'asl_std'), ('spatial_reference', 'keys')]), (inputnode, select_fs_surf, [('surf_files', 'surf_files'), ('surf_refs', 'keys')]), (select_fs_surf, resample, [('surf_files', 'in_file')]), (select_std, gen_cifti, [('asl_std', 'asl_file')]), (resample, gen_cifti, [('out_file', 'surface_asls')]), (gen_cifti, outputnode, [('out_file', 'cifti_asl'), ('variant', 'cifti_variant'), ('out_metadata', 'cifti_metadata'), ('density', 'cifti_density')]), ]) return workflow
def init_bold_surf_wf(mem_gb, output_spaces, medial_surface_nan, fslr_density=None, 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 fslr_density : str, optional Density of fsLR surface (32k or 59k) 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: to_fslr = 'fsaverage' in output_spaces and fslr_density spaces.pop(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, overwrite=True) fetch_fslr_tpls.inputs.den = fslr_density 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) def _basename(in_file): import os return os.path.basename(in_file) 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', _basename), '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: medial_nans.inputs.density = fslr_density workflow.connect(merge_fslr, 'out', medial_nans, 'in_file') elif to_fslr: workflow.connect(merge_fslr, 'out', 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