def init_fmriprep_wf(): """ Build *fMRIPrep*'s pipeline. This workflow organizes the execution of FMRIPREP, with a sub-workflow for each subject. If FreeSurfer's ``recon-all`` is to be run, a corresponding folder is created and populated with any needed template subjects under the derivatives folder. Workflow Graph .. workflow:: :graph2use: orig :simple_form: yes from fmriprep.workflows.tests import mock_config from fmriprep.workflows.base import init_fmriprep_wf with mock_config(): wf = init_fmriprep_wf() """ from niworkflows.engine.workflows import LiterateWorkflow as Workflow from niworkflows.interfaces.bids import BIDSFreeSurferDir fmriprep_wf = Workflow(name='fmriprep_wf') fmriprep_wf.base_dir = config.execution.work_dir freesurfer = config.workflow.run_reconall if freesurfer: fsdir = pe.Node( BIDSFreeSurferDir(derivatives=config.execution.output_dir, freesurfer_home=os.getenv('FREESURFER_HOME'), spaces=config.workflow.spaces.get_fs_spaces()), name='fsdir_run_%s' % config.execution.run_uuid.replace('-', '_'), run_without_submitting=True) if config.execution.fs_subjects_dir is not None: fsdir.inputs.subjects_dir = str( config.execution.fs_subjects_dir.absolute()) for subject_id in config.execution.participant_label: single_subject_wf = init_single_subject_wf(subject_id) single_subject_wf.config['execution']['crashdump_dir'] = str( config.execution.output_dir / "fmriprep" / "-".join( ("sub", subject_id)) / "log" / config.execution.run_uuid) for node in single_subject_wf._get_all_nodes(): node.config = deepcopy(single_subject_wf.config) if freesurfer: fmriprep_wf.connect(fsdir, 'subjects_dir', single_subject_wf, 'inputnode.subjects_dir') else: fmriprep_wf.add_nodes([single_subject_wf]) # Dump a copy of the config file into the log directory log_dir = config.execution.output_dir / 'fmriprep' / 'sub-{}'.format(subject_id) \ / 'log' / config.execution.run_uuid log_dir.mkdir(exist_ok=True, parents=True) config.to_filename(log_dir / 'fmriprep.toml') return fmriprep_wf
def init_dmriprep_wf(): """ Create the base workflow. This workflow organizes the execution of *dMRIPrep*, with a sub-workflow for each subject. If FreeSurfer's recon-all is to be run, a FreeSurfer derivatives folder is created and populated with any needed template subjects. Workflow Graph .. workflow:: :graph2use: orig :simple_form: yes from dmriprep.config.testing import mock_config from dmriprep.workflows.base import init_dmriprep_wf with mock_config(): wf = init_dmriprep_wf() """ dmriprep_wf = Workflow(name="dmriprep_wf") dmriprep_wf.base_dir = config.execution.work_dir freesurfer = config.workflow.run_reconall if freesurfer: fsdir = pe.Node( BIDSFreeSurferDir( derivatives=config.execution.output_dir, freesurfer_home=os.getenv("FREESURFER_HOME"), spaces=config.workflow.spaces.get_fs_spaces(), ), name=f"fsdir_run_{config.execution.run_uuid.replace('-', '_')}", run_without_submitting=True, ) if config.execution.fs_subjects_dir is not None: fsdir.inputs.subjects_dir = str( config.execution.fs_subjects_dir.absolute()) for subject_id in config.execution.participant_label: single_subject_wf = init_single_subject_wf(subject_id) single_subject_wf.config["execution"]["crashdump_dir"] = str( config.execution.output_dir / "dmriprep" / f"sub-{subject_id}" / "log" / config.execution.run_uuid) for node in single_subject_wf._get_all_nodes(): node.config = deepcopy(single_subject_wf.config) if freesurfer: dmriprep_wf.connect(fsdir, "subjects_dir", single_subject_wf, "fsinputnode.subjects_dir") else: dmriprep_wf.add_nodes([single_subject_wf]) # Dump a copy of the config file into the log directory log_dir = (config.execution.output_dir / "dmriprep" / f"sub-{subject_id}" / "log" / config.execution.run_uuid) log_dir.mkdir(exist_ok=True, parents=True) config.to_filename(log_dir / "dmriprep.toml") return dmriprep_wf
def init_fmriprep_wf(): """ Build *fMRIPrep*'s pipeline. This workflow organizes the execution of FMRIPREP, with a sub-workflow for each subject. If FreeSurfer's ``recon-all`` is to be run, a corresponding folder is created and populated with any needed template subjects under the derivatives folder. Workflow Graph .. workflow:: :graph2use: orig :simple_form: yes from fprodents.workflows.tests import mock_config from fprodents.workflows.base import init_fmriprep_wf with mock_config(): wf = init_fmriprep_wf() """ from niworkflows.engine.workflows import LiterateWorkflow as Workflow fmriprep_wf = Workflow(name="fmriprep_wf") fmriprep_wf.base_dir = config.execution.work_dir for subject_id in config.execution.participant_label: single_subject_wf = init_single_subject_wf(subject_id) # Dump a copy of the config file into the log directory log_dir = (config.execution.output_dir / "fmriprep" / f"sub-{subject_id}" / "log" / config.execution.run_uuid) log_dir.mkdir(exist_ok=True, parents=True) config.to_filename(log_dir / "fmriprep.toml") single_subject_wf.config["execution"]["crashdump_dir"] = str(log_dir) for node in single_subject_wf._get_all_nodes(): node.config = deepcopy(single_subject_wf.config) fmriprep_wf.add_nodes([single_subject_wf]) return fmriprep_wf
def init_fmriprep_wf(layout, subject_list, task_id, echo_idx, run_uuid, work_dir, output_dir, ignore, debug, low_mem, anat_only, longitudinal, t2s_coreg, omp_nthreads, skull_strip_template, skull_strip_fixed_seed, freesurfer, output_spaces, template, medial_surface_nan, cifti_output, hires, use_bbr, bold2t1w_dof, fmap_bspline, fmap_demean, use_syn, force_syn, use_aroma, err_on_aroma_warn, aroma_melodic_dim, template_out_grid): """ This workflow organizes the execution of FMRIPREP, with a sub-workflow for each subject. If FreeSurfer's recon-all is to be run, a FreeSurfer derivatives folder is created and populated with any needed template subjects. .. workflow:: :graph2use: orig :simple_form: yes import os from collections import namedtuple BIDSLayout = namedtuple('BIDSLayout', ['root'], defaults='.') from fmriprep.workflows.base import init_fmriprep_wf os.environ['FREESURFER_HOME'] = os.getcwd() wf = init_fmriprep_wf(layout=BIDSLayout(), subject_list=['fmripreptest'], task_id='', echo_idx=None, run_uuid='X', work_dir='.', output_dir='.', ignore=[], debug=False, low_mem=False, anat_only=False, longitudinal=False, t2s_coreg=False, omp_nthreads=1, skull_strip_template='OASIS30ANTs', skull_strip_fixed_seed=False, freesurfer=True, output_spaces=['T1w', 'fsnative', 'template', 'fsaverage5'], template='MNI152NLin2009cAsym', medial_surface_nan=False, cifti_output=False, hires=True, use_bbr=True, bold2t1w_dof=9, fmap_bspline=False, fmap_demean=True, use_syn=True, force_syn=True, use_aroma=False, err_on_aroma_warn=False, aroma_melodic_dim=-200, template_out_grid='native') Parameters layout : BIDSLayout object BIDS dataset layout subject_list : list List of subject labels task_id : str or None Task ID of BOLD series to preprocess, or ``None`` to preprocess all echo_idx : int or None Index of echo to preprocess in multiecho BOLD series, or ``None`` to preprocess all run_uuid : str Unique identifier for execution instance work_dir : str Directory in which to store workflow execution state and temporary files output_dir : str Directory in which to save derivatives ignore : list Preprocessing steps to skip (may include "slicetiming", "fieldmaps") debug : bool Enable debugging outputs low_mem : bool Write uncompressed .nii files in some cases to reduce memory usage anat_only : bool Disable functional workflows longitudinal : bool Treat multiple sessions as longitudinal (may increase runtime) See sub-workflows for specific differences t2s_coreg : bool For multi-echo EPI, use the calculated T2*-map for T2*-driven coregistration omp_nthreads : int Maximum number of threads an individual process may use skull_strip_template : str Name of ANTs skull-stripping template ('OASIS30ANTs' or 'NKI') skull_strip_fixed_seed : bool Do not use a random seed for skull-stripping - will ensure run-to-run replicability when used with --omp-nthreads 1 freesurfer : bool Enable FreeSurfer surface reconstruction (may increase runtime) output_spaces : list List of output spaces functional images are to be resampled to. Some parts of pipeline will only be instantiated for some output spaces. Valid spaces: - T1w - template - fsnative - fsaverage (or other pre-existing FreeSurfer templates) template : str Name of template targeted by ``template`` output space medial_surface_nan : bool Replace medial wall values with NaNs on functional GIFTI files cifti_output : bool Generate bold CIFTI file in output spaces hires : bool Enable sub-millimeter preprocessing in FreeSurfer use_bbr : bool or None Enable/disable boundary-based registration refinement. If ``None``, test BBR result for distortion before accepting. bold2t1w_dof : 6, 9 or 12 Degrees-of-freedom for BOLD-T1w registration fmap_bspline : bool **Experimental**: Fit B-Spline field using least-squares fmap_demean : bool Demean voxel-shift map during unwarp use_syn : bool **Experimental**: Enable ANTs SyN-based susceptibility distortion correction (SDC). If fieldmaps are present and enabled, this is not run, by default. force_syn : bool **Temporary**: Always run SyN-based SDC use_aroma : bool Perform ICA-AROMA on MNI-resampled functional series err_on_aroma_warn : bool Do not fail on ICA-AROMA errors template_out_grid : str Keyword ('native', '1mm' or '2mm') or path of custom reference image for normalization """ fmriprep_wf = Workflow(name='fmriprep_wf') fmriprep_wf.base_dir = work_dir if freesurfer: fsdir = pe.Node(BIDSFreeSurferDir( derivatives=output_dir, freesurfer_home=os.getenv('FREESURFER_HOME'), spaces=output_spaces), name='fsdir_run_' + run_uuid.replace('-', '_'), run_without_submitting=True) reportlets_dir = os.path.join(work_dir, 'reportlets') for subject_id in subject_list: single_subject_wf = init_single_subject_wf( layout=layout, subject_id=subject_id, task_id=task_id, echo_idx=echo_idx, name="single_subject_" + subject_id + "_wf", reportlets_dir=reportlets_dir, output_dir=output_dir, ignore=ignore, debug=debug, low_mem=low_mem, anat_only=anat_only, longitudinal=longitudinal, t2s_coreg=t2s_coreg, omp_nthreads=omp_nthreads, skull_strip_template=skull_strip_template, skull_strip_fixed_seed=skull_strip_fixed_seed, freesurfer=freesurfer, output_spaces=output_spaces, template=template, medial_surface_nan=medial_surface_nan, cifti_output=cifti_output, hires=hires, use_bbr=use_bbr, bold2t1w_dof=bold2t1w_dof, fmap_bspline=fmap_bspline, fmap_demean=fmap_demean, use_syn=use_syn, force_syn=force_syn, template_out_grid=template_out_grid, use_aroma=use_aroma, aroma_melodic_dim=aroma_melodic_dim, err_on_aroma_warn=err_on_aroma_warn, ) single_subject_wf.config['execution']['crashdump_dir'] = (os.path.join( output_dir, "fmriprep", "sub-" + subject_id, 'log', run_uuid)) for node in single_subject_wf._get_all_nodes(): node.config = deepcopy(single_subject_wf.config) if freesurfer: fmriprep_wf.connect(fsdir, 'subjects_dir', single_subject_wf, 'inputnode.subjects_dir') else: fmriprep_wf.add_nodes([single_subject_wf]) return fmriprep_wf
def init_smriprep_wf( debug, fast_track, freesurfer, fs_subjects_dir, hires, layout, longitudinal, low_mem, omp_nthreads, output_dir, run_uuid, skull_strip_mode, skull_strip_fixed_seed, skull_strip_template, spaces, subject_list, work_dir, bids_filters, ): """ Create the execution graph of *sMRIPrep*, with a sub-workflow for each subject. If FreeSurfer's ``recon-all`` is to be run, a FreeSurfer derivatives folder is created and populated with any needed template subjects. Workflow Graph .. workflow:: :graph2use: orig :simple_form: yes import os from collections import namedtuple BIDSLayout = namedtuple('BIDSLayout', ['root']) os.environ['FREESURFER_HOME'] = os.getcwd() from smriprep.workflows.base import init_smriprep_wf from niworkflows.utils.spaces import SpatialReferences, Reference wf = init_smriprep_wf( debug=False, fast_track=False, freesurfer=True, fs_subjects_dir=None, hires=True, layout=BIDSLayout('.'), longitudinal=False, low_mem=False, omp_nthreads=1, output_dir='.', run_uuid='testrun', skull_strip_fixed_seed=False, skull_strip_mode='force', skull_strip_template=Reference('OASIS30ANTs'), spaces=SpatialReferences(spaces=['MNI152NLin2009cAsym', 'fsaverage5']), subject_list=['smripreptest'], work_dir='.', bids_filters=None, ) Parameters ---------- debug : :obj:`bool` Enable debugging outputs fast_track : :obj:`bool` Fast-track the workflow by searching for existing derivatives. freesurfer : :obj:`bool` Enable FreeSurfer surface reconstruction (may increase runtime) fs_subjects_dir : os.PathLike or None Use existing FreeSurfer subjects directory if provided hires : :obj:`bool` Enable sub-millimeter preprocessing in FreeSurfer layout : BIDSLayout object BIDS dataset layout longitudinal : :obj:`bool` Treat multiple sessions as longitudinal (may increase runtime) See sub-workflows for specific differences low_mem : :obj:`bool` Write uncompressed .nii files in some cases to reduce memory usage omp_nthreads : :obj:`int` Maximum number of threads an individual process may use output_dir : :obj:`str` Directory in which to save derivatives run_uuid : :obj:`str` Unique identifier for execution instance skull_strip_fixed_seed : :obj:`bool` Do not use a random seed for skull-stripping - will ensure run-to-run replicability when used with --omp-nthreads 1 skull_strip_mode : :obj:`str` Determiner for T1-weighted skull stripping (`force` ensures skull stripping, `skip` ignores skull stripping, and `auto` automatically ignores skull stripping if pre-stripped brains are detected). skull_strip_template : :py:class:`~niworkflows.utils.spaces.Reference` Spatial reference to use in atlas-based brain extraction. spaces : :py:class:`~niworkflows.utils.spaces.SpatialReferences` Object containing standard and nonstandard space specifications. subject_list : :obj:`list` List of subject labels work_dir : :obj:`str` Directory in which to store workflow execution state and temporary files bids_filters : dict Provides finer specification of the pipeline input files through pybids entities filters. A dict with the following structure {<suffix>:{<entity>:<filter>,...},...} """ smriprep_wf = Workflow(name='smriprep_wf') smriprep_wf.base_dir = work_dir if freesurfer: fsdir = pe.Node(BIDSFreeSurferDir( derivatives=output_dir, freesurfer_home=os.getenv('FREESURFER_HOME'), spaces=spaces.get_fs_spaces()), name='fsdir_run_%s' % run_uuid.replace('-', '_'), run_without_submitting=True) if fs_subjects_dir is not None: fsdir.inputs.subjects_dir = str(fs_subjects_dir.absolute()) for subject_id in subject_list: single_subject_wf = init_single_subject_wf( debug=debug, freesurfer=freesurfer, fast_track=fast_track, hires=hires, layout=layout, longitudinal=longitudinal, low_mem=low_mem, name="single_subject_%s_wf" % subject_id, omp_nthreads=omp_nthreads, output_dir=output_dir, skull_strip_fixed_seed=skull_strip_fixed_seed, skull_strip_mode=skull_strip_mode, skull_strip_template=skull_strip_template, spaces=spaces, subject_id=subject_id, bids_filters=bids_filters, ) single_subject_wf.config['execution']['crashdump_dir'] = (os.path.join( output_dir, "smriprep", "sub-" + subject_id, 'log', run_uuid)) for node in single_subject_wf._get_all_nodes(): node.config = deepcopy(single_subject_wf.config) if freesurfer: smriprep_wf.connect(fsdir, 'subjects_dir', single_subject_wf, 'inputnode.subjects_dir') else: smriprep_wf.add_nodes([single_subject_wf]) return smriprep_wf
def main(args=None): """Entry point.""" import re import json from pathlib import Path from niworkflows.engine.workflows import LiterateWorkflow as Workflow from nipype import Function from nipype.pipeline import engine as pe from nipype.interfaces import utility as niu from nipype.utils.filemanip import hash_infile from comppsychflows.workflows.util import init_qwarp_inversion_wf from comppsychflows.workflows.util import init_apply_hmc_only_wf from comppsychflows.workflows.util import init_backtransform_wf from comppsychflows.workflows.util import init_scale_wf from comppsychflows.workflows.util import init_getstats_wf from nipype.interfaces.afni.preprocess import ROIStats from nipype.interfaces.io import DataSink opts = get_parser().parse_args(args=args) fmriprep_dir = Path(opts.fmriprep_dir) fmriprep_odir = fmriprep_dir / 'out' fmriprep_wdir = fmriprep_dir / 'wrk' mnitobold_dir = opts.out_path mnitobold_wdir = (Path(mnitobold_dir) / 'wrk') mnitobold_odir = (Path(mnitobold_dir) / 'out') dseg_path = opts.dseg_path mni_image = opts.mni_image omp_nthreads = opts.omp_nthreads mem_gb = opts.mem_gb n_dummy = opts.n_dummy func_wds = sorted( (fmriprep_wdir / 'fmriprep_wf').glob('single_subject_*_wf/func*')) for func_wd in func_wds: sub_extract = re.compile('subject_([0-9]*)') subject = sub_extract.findall(func_wd.as_posix())[0] sdc_path = func_wd / 'sdc_estimate_wf/pepolar_unwarp_wf/qwarp/Qwarp_PLUS_WARP.nii.gz' use_sdc = sdc_path.exists() # get paths needed for workflow ref_path = func_wd / 'bold_reference_wf/enhance_and_skullstrip_bold_wf/n4_correct/ref_bold_corrected.nii.gz' hmc_transform = func_wd / 'bold_hmc_wf/fsl2itk/mat2itk.txt' mni_to_t1 = fmriprep_odir / f'fmriprep/sub-{subject}/anat/sub-{subject}_from-MNI152NLin2009cAsym_to-T1w_mode-image_xfm.h5' t1_to_bold = func_wd / 'bold_reg_wf/bbreg_wf/concat_xfm/out_inv.tfm' split_bolds_dir = func_wd / 'bold_split' split_bolds = sorted(split_bolds_dir.glob('vol*.nii.gz')) # We'll use the reference gen workflow to get the bids path validate_json = list( (func_wd / 'bold_reference_wf/validate').glob('*.json'))[0] bold_file = json.loads(validate_json.read_text())[0][1][0] bold_basename = Path(bold_file).parts[-1].replace('bold.nii.gz', '') # If it's a rest scan replace echo 1 with echo 2 if ('task-rest' in bold_file) and ('echo-1' in bold_file): bold_file = bold_file.replace('echo-1', 'echo-2') # define workflow workflow = Workflow(name=func_wd.parts[-1]) inputnode = pe.Node(niu.IdentityInterface(fields=[ 'sdc', 'ref', 'hmc_transform', 'mni_to_t1', 't1_to_bold', 'mni_image', 'dseg', 'bold_file' ]), name='inputnode') if use_sdc: iwf = init_qwarp_inversion_wf(omp_nthreads) workflow.connect([(inputnode, iwf, [('sdc', 'inputnode.warp'), ('ref', 'inputnode.in_reference')])]) n_transforms = 3 else: n_transforms = 2 hmc_apply_wf = init_apply_hmc_only_wf(mem_gb, omp_nthreads, split_file=True) backtransform_wf = init_backtransform_wf(mem_gb, omp_nthreads) merge_transforms = pe.Node(niu.Merge(n_transforms), name='merge_xforms', run_without_submitting=True, mem_gb=mem_gb) # Get TSNR of minimally pocessed HMC Bold gettsnr = init_getstats_wf(mem_gb, omp_nthreads, n_dummy=n_dummy, name='gettsnr') # Scale time series by voxel mean scale_wf = init_scale_wf(mem_gb, omp_nthreads, n_dummy=n_dummy) # Calculate the voxel wise standard deviation of the scaled image getstd = init_getstats_wf(mem_gb, omp_nthreads, n_dummy=n_dummy, name='getstd', stat='stdev') # Get the TR-wise sum and count of each roi roi_stats = pe.Node(ROIStats(stat=['sum', 'voxels']), name='roi_stats', mem_gb=mem_gb, n_procs=omp_nthreads) get_grand_std = pe.Node(Function( input_names=['in_file', 'dseg_file', 'out_file'], output_names=['out_file'], function=roi_grand_std), name='get_grand_std') hmcxform_copy = pe.Node(Function(input_names=['in_file'], output_names=['out_file'], function=copyfile), name='hmcxform_copy') # Use a sinker to make things pretty sinker = pe.Node(DataSink(), name='sinker') sinker.inputs.base_directory = (mnitobold_odir / func_wd.parts[-1]).as_posix() sinker.inputs.substitutions = [ ('hmcxform_copymat2itk.txt', bold_basename + 'desc-hmc_xform.txt'), ('MNItohmcbold.nii.gz', bold_basename + 'desc-MNItohmc_xform.nii.gz'), ('vol0000_xform-00000_merged_calc.nii.gz', bold_basename + 'desc-hmcscaled_bold.nii.gz'), ('vol0000_xform-00000_merged.nii.gz', bold_basename + 'desc-hmc_bold.nii.gz'), ('vol0000_xform-00000_merged_tstat.nii.gz', bold_basename + 'desc-hmc_tsnr.nii.gz'), ('vol0000_xform-00000_merged_tstat_roistat.1D', bold_basename + 'desc-hmc_roistats.1D'), ('vol0000_xform-00000_merged_calc_roistat.1D', bold_basename + 'desc-hmcscaled_roistats.1D'), ('grand_std.csv', bold_basename + 'desc-hmcscaled_grandstd.1D') ] workflow.connect([ (inputnode, hmcxform_copy, [('hmc_transform', 'in_file')]), (inputnode, hmc_apply_wf, [('bold_file', 'inputnode.name_source'), ('bold_file', 'inputnode.bold_file'), ('hmc_transform', 'inputnode.hmc_xforms')]), (inputnode, backtransform_wf, [('mni_image', 'inputnode.template_file'), ('dseg', 'inputnode.dseg_file'), ('ref', 'inputnode.reference_image')]), (hmc_apply_wf, backtransform_wf, [('outputnode.bold', 'inputnode.bold_file')]), (inputnode, merge_transforms, [('mni_to_t1', 'in1'), ('t1_to_bold', 'in2')]) ]) if use_sdc: workflow.connect([(iwf, merge_transforms, [('outputnode.out_warp', 'in3')])]) workflow.connect([(merge_transforms, backtransform_wf, [('out', 'inputnode.transforms')])]) workflow.connect([ # Wire gettsnr (hmc_apply_wf, gettsnr, [('outputnode.bold', 'inputnode.bold_file') ]), (backtransform_wf, gettsnr, [('outputnode.transformed_dseg', 'inputnode.dseg_file')]), # Wire scale_wf (hmc_apply_wf, scale_wf, [('outputnode.bold', 'inputnode.bold_file')]), # Wire getstd (scale_wf, getstd, [('outputnode.scaled', 'inputnode.bold_file')]), (backtransform_wf, getstd, [('outputnode.transformed_dseg', 'inputnode.dseg_file')]), # Wire roi_stats (backtransform_wf, roi_stats, [('outputnode.transformed_dseg', 'mask_file')]), (scale_wf, roi_stats, [('outputnode.scaled', 'in_file')]), # Wire get_grand_std (scale_wf, get_grand_std, [('outputnode.scaled', 'in_file')]), (backtransform_wf, get_grand_std, [('outputnode.transformed_dseg', 'dseg_file')]), # Wire sinker (hmcxform_copy, sinker, [('out_file', 'mnitobold.@hmc_xforms')]), (hmc_apply_wf, sinker, [('outputnode.bold', 'mnitobold.@hmc_only_bold')]), (scale_wf, sinker, [('outputnode.scaled', 'mnitobold.@hmc_scaled_bold')]), (backtransform_wf, sinker, [('outputnode.combined_transforms', 'mnitobold.@mni2bold_combined_xforms'), ('outputnode.transformed_template', 'mnitobold.@transformed_template'), ('outputnode.transformed_dseg', 'mnitobold.@transformed_dseg')]), (gettsnr, sinker, [('outputnode.stat_image', 'stats.@hmc_tsnr'), ('outputnode.roi_stats', 'stats.@hmc_tsnr_roistats')]), (roi_stats, sinker, [('out_file', 'stats.@scaled_roistats')]), (get_grand_std, sinker, [('out_file', 'stats.@scaled_grandstd')]) ]) workflow.base_dir = mnitobold_wdir.as_posix() # Connect inputs to workflow workflow.inputs.inputnode.sdc = sdc_path workflow.inputs.inputnode.ref = ref_path workflow.inputs.inputnode.hmc_transform = hmc_transform workflow.inputs.inputnode.mni_to_t1 = mni_to_t1 workflow.inputs.inputnode.t1_to_bold = t1_to_bold workflow.inputs.inputnode.mni_image = mni_image workflow.inputs.inputnode.dseg = dseg_path workflow.inputs.inputnode.bold_file = bold_file wf_res = workflow.run()
def init_fmriprep_wf( anat_only, aroma_melodic_dim, bold2t1w_dof, cifti_output, debug, dummy_scans, echo_idx, err_on_aroma_warn, fmap_bspline, fmap_demean, force_syn, freesurfer, fs_subjects_dir, hires, ignore, layout, longitudinal, low_mem, medial_surface_nan, omp_nthreads, output_dir, regressors_all_comps, regressors_dvars_th, regressors_fd_th, run_uuid, skull_strip_fixed_seed, skull_strip_template, spaces, subject_list, t2s_coreg, task_id, use_aroma, use_bbr, use_syn, work_dir, ): """ Build *fMRIPrep*'s pipeline. This workflow organizes the execution of FMRIPREP, with a sub-workflow for each subject. If FreeSurfer's ``recon-all`` is to be run, a corresponding folder is created and populated with any needed template subjects under the derivatives folder. Workflow Graph .. workflow:: :graph2use: orig :simple_form: yes import os from collections import namedtuple, OrderedDict BIDSLayout = namedtuple('BIDSLayout', ['root']) from fmriprep.workflows.base import init_fmriprep_wf from niworkflows.utils.spaces import Reference, SpatialReferences os.environ['FREESURFER_HOME'] = os.getcwd() wf = init_fmriprep_wf( anat_only=False, aroma_melodic_dim=-200, bold2t1w_dof=9, cifti_output=False, debug=False, dummy_scans=None, echo_idx=None, err_on_aroma_warn=False, fmap_bspline=False, fmap_demean=True, force_syn=True, freesurfer=True, fs_subjects_dir=None, hires=True, ignore=[], layout=BIDSLayout('.'), longitudinal=False, low_mem=False, medial_surface_nan=False, omp_nthreads=1, output_dir='.', regressors_all_comps=False, regressors_dvars_th=1.5, regressors_fd_th=0.5, run_uuid='X', skull_strip_fixed_seed=False, skull_strip_template=Reference('OASIS30ANTs'), spaces=SpatialReferences( spaces=['MNI152Lin', ('fsaverage', {'density': '10k'}), 'T1w', 'fsnative'], checkpoint=True), subject_list=['fmripreptest'], t2s_coreg=False, task_id='', use_aroma=False, use_bbr=True, use_syn=True, work_dir='.', ) Parameters ---------- anat_only : bool Disable functional workflows bold2t1w_dof : 6, 9 or 12 Degrees-of-freedom for BOLD-T1w registration cifti_output : bool Generate bold CIFTI file in output spaces debug : bool Enable debugging outputs dummy_scans : int or None Number of volumes to consider as non steady state echo_idx : int or None Index of echo to preprocess in multiecho BOLD series, or ``None`` to preprocess all err_on_aroma_warn : bool Do not fail on ICA-AROMA errors fmap_bspline : bool **Experimental**: Fit B-Spline field using least-squares fmap_demean : bool Demean voxel-shift map during unwarp force_syn : bool **Temporary**: Always run SyN-based SDC freesurfer : bool Enable FreeSurfer surface reconstruction (may increase runtime) hires : bool Enable sub-millimeter preprocessing in FreeSurfer ignore : list Preprocessing steps to skip (may include "slicetiming", "fieldmaps") layout : BIDSLayout object BIDS dataset layout longitudinal : bool Treat multiple sessions as longitudinal (may increase runtime) See sub-workflows for specific differences low_mem : bool Write uncompressed .nii files in some cases to reduce memory usage medial_surface_nan : bool Replace medial wall values with NaNs on functional GIFTI files omp_nthreads : int Maximum number of threads an individual process may use output_dir : str Directory in which to save derivatives regressors_all_comps Return all CompCor component time series instead of the top fraction regressors_dvars_th Criterion for flagging DVARS outliers regressors_fd_th Criterion for flagging framewise displacement outliers run_uuid : str Unique identifier for execution instance skull_strip_template : tuple Name of target template for brain extraction with ANTs' ``antsBrainExtraction``, and corresponding dictionary of output-space modifiers. skull_strip_fixed_seed : bool Do not use a random seed for skull-stripping - will ensure run-to-run replicability when used with --omp-nthreads 1 spaces : :py:class:`~niworkflows.utils.spaces.SpatialReferences` A container for storing, organizing, and parsing spatial normalizations. Composed of :py:class:`~niworkflows.utils.spaces.Reference` objects representing spatial references. Each ``Reference`` contains a space, which is a string of either TemplateFlow template IDs (e.g., ``MNI152Lin``, ``MNI152NLin6Asym``, ``MNIPediatricAsym``), nonstandard references (e.g., ``T1w`` or ``anat``, ``sbref``, ``run``, etc.), or a custom template located in the TemplateFlow root directory. Each ``Reference`` may also contain a spec, which is a dictionary with template specifications (e.g., a specification of ``{'resolution': 2}`` would lead to resampling on a 2mm resolution of the space). subject_list : list List of subject labels t2s_coreg : bool For multi-echo EPI, use the calculated T2*-map for T2*-driven coregistration task_id : str or None Task ID of BOLD series to preprocess, or ``None`` to preprocess all use_aroma : bool Perform ICA-AROMA on MNI-resampled functional series use_bbr : bool or None Enable/disable boundary-based registration refinement. If ``None``, test BBR result for distortion before accepting. use_syn : bool **Experimental**: Enable ANTs SyN-based susceptibility distortion correction (SDC). If fieldmaps are present and enabled, this is not run, by default. work_dir : str Directory in which to store workflow execution state and temporary files """ fmriprep_wf = Workflow(name='fmriprep_wf') fmriprep_wf.base_dir = work_dir if freesurfer: fsdir = pe.Node( BIDSFreeSurferDir( derivatives=output_dir, freesurfer_home=os.getenv('FREESURFER_HOME'), spaces=spaces.get_fs_spaces()), name='fsdir_run_' + run_uuid.replace('-', '_'), run_without_submitting=True) if fs_subjects_dir is not None: fsdir.inputs.subjects_dir = str(fs_subjects_dir.absolute()) reportlets_dir = os.path.join(work_dir, 'reportlets') for subject_id in subject_list: single_subject_wf = init_single_subject_wf( anat_only=anat_only, aroma_melodic_dim=aroma_melodic_dim, bold2t1w_dof=bold2t1w_dof, cifti_output=cifti_output, debug=debug, dummy_scans=dummy_scans, echo_idx=echo_idx, err_on_aroma_warn=err_on_aroma_warn, fmap_bspline=fmap_bspline, fmap_demean=fmap_demean, force_syn=force_syn, freesurfer=freesurfer, hires=hires, ignore=ignore, layout=layout, longitudinal=longitudinal, low_mem=low_mem, medial_surface_nan=medial_surface_nan, name="single_subject_" + subject_id + "_wf", omp_nthreads=omp_nthreads, output_dir=output_dir, regressors_all_comps=regressors_all_comps, regressors_dvars_th=regressors_dvars_th, regressors_fd_th=regressors_fd_th, reportlets_dir=reportlets_dir, skull_strip_fixed_seed=skull_strip_fixed_seed, skull_strip_template=skull_strip_template, spaces=spaces, subject_id=subject_id, t2s_coreg=t2s_coreg, task_id=task_id, use_aroma=use_aroma, use_bbr=use_bbr, use_syn=use_syn, ) single_subject_wf.config['execution']['crashdump_dir'] = ( os.path.join(output_dir, "fmriprep", "sub-" + subject_id, 'log', run_uuid) ) for node in single_subject_wf._get_all_nodes(): node.config = deepcopy(single_subject_wf.config) if freesurfer: fmriprep_wf.connect(fsdir, 'subjects_dir', single_subject_wf, 'inputnode.subjects_dir') else: fmriprep_wf.add_nodes([single_subject_wf]) return fmriprep_wf
def init_dmriprep_wf( anat_only, debug, force_syn, freesurfer, hires, ignore, layout, longitudinal, low_mem, omp_nthreads, output_dir, output_spaces, run_uuid, skull_strip_fixed_seed, skull_strip_template, subject_list, use_syn, work_dir, ): """ Create the base workflow. This workflow organizes the execution of *dMRIPrep*, with a sub-workflow for each subject. If FreeSurfer's recon-all is to be run, a FreeSurfer derivatives folder is created and populated with any needed template subjects. Workflow Graph .. workflow:: :graph2use: orig :simple_form: yes import os from collections import namedtuple, OrderedDict BIDSLayout = namedtuple('BIDSLayout', ['root']) from dmriprep.workflows.base import init_dmriprep_wf os.environ['FREESURFER_HOME'] = os.getcwd() wf = init_dmriprep_wf( anat_only=False, debug=False, force_syn=True, freesurfer=True, hires=True, ignore=[], layout=BIDSLayout('.'), longitudinal=False, low_mem=False, omp_nthreads=1, output_dir='.', output_spaces=OrderedDict([ ('MNI152Lin', {}), ('fsaverage', {'density': '10k'}), ('T1w', {}), ('fsnative', {})]), run_uuid='X', skull_strip_fixed_seed=False, skull_strip_template=('OASIS30ANTs', {}), subject_list=['dmripreptest'], use_syn=True, work_dir='.', ) Parameters ---------- anat_only : bool Disable diffusion MRI workflows debug : bool Enable debugging outputs force_syn : bool **Temporary**: Always run SyN-based SDC freesurfer : bool Enable FreeSurfer surface reconstruction (may increase runtime) hires : bool Enable sub-millimeter preprocessing in FreeSurfer ignore : list Preprocessing steps to skip (may include "slicetiming", "fieldmaps") layout : BIDSLayout object BIDS dataset layout longitudinal : bool Treat multiple sessions as longitudinal (may increase runtime) See sub-workflows for specific differences low_mem : bool Write uncompressed .nii files in some cases to reduce memory usage omp_nthreads : int Maximum number of threads an individual process may use output_dir : str Directory in which to save derivatives output_spaces : OrderedDict Ordered dictionary where keys are TemplateFlow ID strings (e.g., ``MNI152Lin``, ``MNI152NLin6Asym``, ``MNI152NLin2009cAsym``, or ``fsLR``) strings designating nonstandard references (e.g., ``T1w`` or ``anat``, ``sbref``, ``run``, etc.), or paths pointing to custom templates organized in a TemplateFlow-like structure. Values of the dictionary aggregate modifiers (e.g., the value for the key ``MNI152Lin`` could be ``{'resolution': 2}`` if one wants the resampling to be done on the 2mm resolution version of the selected template). run_uuid : str Unique identifier for execution instance skull_strip_template : tuple Name of target template for brain extraction with ANTs' ``antsBrainExtraction``, and corresponding dictionary of output-space modifiers. skull_strip_fixed_seed : bool Do not use a random seed for skull-stripping - will ensure run-to-run replicability when used with --omp-nthreads 1 subject_list : list List of subject labels use_syn : bool **Experimental**: Enable ANTs SyN-based susceptibility distortion correction (SDC). If fieldmaps are present and enabled, this is not run, by default. work_dir : str Directory in which to store workflow execution state and temporary files """ dmriprep_wf = Workflow(name='dmriprep_wf') dmriprep_wf.base_dir = work_dir if freesurfer: fsdir = pe.Node(BIDSFreeSurferDir( derivatives=output_dir, freesurfer_home=os.getenv('FREESURFER_HOME'), spaces=[ s for s in output_spaces.keys() if s.startswith('fsaverage') ] + ['fsnative'] * ('fsnative' in output_spaces)), name='fsdir_run_' + run_uuid.replace('-', '_'), run_without_submitting=True) reportlets_dir = os.path.join(work_dir, 'reportlets') for subject_id in subject_list: single_subject_wf = init_single_subject_wf( anat_only=anat_only, debug=debug, force_syn=force_syn, freesurfer=freesurfer, hires=hires, ignore=ignore, layout=layout, longitudinal=longitudinal, low_mem=low_mem, name="single_subject_" + subject_id + "_wf", omp_nthreads=omp_nthreads, output_dir=output_dir, output_spaces=output_spaces, reportlets_dir=reportlets_dir, skull_strip_fixed_seed=skull_strip_fixed_seed, skull_strip_template=skull_strip_template, subject_id=subject_id, use_syn=use_syn, ) single_subject_wf.config['execution']['crashdump_dir'] = (os.path.join( output_dir, "dmriprep", "sub-" + subject_id, 'log', run_uuid)) for node in single_subject_wf._get_all_nodes(): node.config = deepcopy(single_subject_wf.config) if freesurfer: dmriprep_wf.connect(fsdir, 'subjects_dir', single_subject_wf, 'inputnode.subjects_dir') else: dmriprep_wf.add_nodes([single_subject_wf]) return dmriprep_wf
def init_smriprep_wf( debug, freesurfer, hires, layout, longitudinal, low_mem, omp_nthreads, output_dir, output_spaces, run_uuid, skull_strip_fixed_seed, skull_strip_template, subject_list, work_dir, ): """ Create the execution graph of *sMRIPrep*, with a sub-workflow for each subject. If FreeSurfer's recon-all is to be run, a FreeSurfer derivatives folder is created and populated with any needed template subjects. .. workflow:: :graph2use: orig :simple_form: yes import os from collections import OrderedDict, namedtuple BIDSLayout = namedtuple('BIDSLayout', ['root']) os.environ['FREESURFER_HOME'] = os.getcwd() from smriprep.workflows.base import init_smriprep_wf wf = init_smriprep_wf( debug=False, freesurfer=True, hires=True, layout=BIDSLayout('.'), longitudinal=False, low_mem=False, omp_nthreads=1, output_dir='.', output_spaces=OrderedDict([('MNI152NLin2009cAsym', {}), ('fsaverage5', {})]), run_uuid='testrun', skull_strip_fixed_seed=False, skull_strip_template=('OASIS30ANTs', {}), subject_list=['smripreptest'], work_dir='.', ) **Parameters** debug : bool Enable debugging outputs freesurfer : bool Enable FreeSurfer surface reconstruction (may increase runtime) hires : bool Enable sub-millimeter preprocessing in FreeSurfer layout : BIDSLayout object BIDS dataset layout longitudinal : bool Treat multiple sessions as longitudinal (may increase runtime) See sub-workflows for specific differences low_mem : bool Write uncompressed .nii files in some cases to reduce memory usage omp_nthreads : int Maximum number of threads an individual process may use output_dir : str Directory in which to save derivatives output_spaces : OrderedDict List of spatial normalization targets. Some parts of pipeline will only be instantiated for some output spaces. Valid spaces: - Any template identifier from TemplateFlow - Path to a template folder organized following TemplateFlow's conventions run_uuid : str Unique identifier for execution instance skull_strip_fixed_seed : bool Do not use a random seed for skull-stripping - will ensure run-to-run replicability when used with --omp-nthreads 1 skull_strip_template : tuple Name of ANTs skull-stripping template ('OASIS30ANTs' or 'NKI'), and dictionary with template specifications (e.g., {'res': '2'}) subject_list : list List of subject labels work_dir : str Directory in which to store workflow execution state and temporary files """ smriprep_wf = Workflow(name='smriprep_wf') smriprep_wf.base_dir = work_dir if freesurfer: fsdir = pe.Node(BIDSFreeSurferDir( derivatives=output_dir, freesurfer_home=os.getenv('FREESURFER_HOME'), spaces=[ s for s in output_spaces.keys() if s.startswith('fsaverage') ] + ['fsnative'] * ('fsnative' in output_spaces)), name='fsdir_run_%s' % run_uuid.replace('-', '_'), run_without_submitting=True) reportlets_dir = os.path.join(work_dir, 'reportlets') for subject_id in subject_list: single_subject_wf = init_single_subject_wf( debug=debug, freesurfer=freesurfer, hires=hires, layout=layout, longitudinal=longitudinal, low_mem=low_mem, name="single_subject_%s_wf" % subject_id, omp_nthreads=omp_nthreads, output_dir=output_dir, output_spaces=output_spaces, reportlets_dir=reportlets_dir, skull_strip_fixed_seed=skull_strip_fixed_seed, skull_strip_template=skull_strip_template, subject_id=subject_id, ) single_subject_wf.config['execution']['crashdump_dir'] = (os.path.join( output_dir, "smriprep", "sub-" + subject_id, 'log', run_uuid)) for node in single_subject_wf._get_all_nodes(): node.config = deepcopy(single_subject_wf.config) if freesurfer: smriprep_wf.connect(fsdir, 'subjects_dir', single_subject_wf, 'inputnode.subjects_dir') else: smriprep_wf.add_nodes([single_subject_wf]) return smriprep_wf
def init_fmriprep_wf(subject_list, task_id, echo_idx, run_uuid, work_dir, output_dir, bids_dir, ignore, debug, low_mem, anat_only, longitudinal, t2s_coreg, omp_nthreads, skull_strip_template, skull_strip_fixed_seed, freesurfer, output_spaces, template, medial_surface_nan, cifti_output, hires, use_bbr, bold2t1w_dof, fmap_bspline, fmap_demean, use_syn, force_syn, use_aroma, ignore_aroma_err, aroma_melodic_dim, template_out_grid): """ This workflow organizes the execution of FMRIPREP, with a sub-workflow for each subject. If FreeSurfer's recon-all is to be run, a FreeSurfer derivatives folder is created and populated with any needed template subjects. .. workflow:: :graph2use: orig :simple_form: yes import os os.environ['FREESURFER_HOME'] = os.getcwd() from fmriprep.workflows.base import init_fmriprep_wf wf = init_fmriprep_wf(subject_list=['fmripreptest'], task_id='', echo_idx=None, run_uuid='X', work_dir='.', output_dir='.', bids_dir='.', ignore=[], debug=False, low_mem=False, anat_only=False, longitudinal=False, t2s_coreg=False, omp_nthreads=1, skull_strip_template='OASIS', skull_strip_fixed_seed=False, freesurfer=True, output_spaces=['T1w', 'fsnative', 'template', 'fsaverage5'], template='MNI152NLin2009cAsym', medial_surface_nan=False, cifti_output=False, hires=True, use_bbr=True, bold2t1w_dof=9, fmap_bspline=False, fmap_demean=True, use_syn=True, force_syn=True, use_aroma=False, ignore_aroma_err=False, aroma_melodic_dim=-200, template_out_grid='native') Parameters subject_list : list List of subject labels task_id : str or None Task ID of BOLD series to preprocess, or ``None`` to preprocess all echo_idx : int or None Index of echo to preprocess in multiecho BOLD series, or ``None`` to preprocess all run_uuid : str Unique identifier for execution instance work_dir : str Directory in which to store workflow execution state and temporary files output_dir : str Directory in which to save derivatives bids_dir : str Root directory of BIDS dataset ignore : list Preprocessing steps to skip (may include "slicetiming", "fieldmaps") debug : bool Enable debugging outputs low_mem : bool Write uncompressed .nii files in some cases to reduce memory usage anat_only : bool Disable functional workflows longitudinal : bool Treat multiple sessions as longitudinal (may increase runtime) See sub-workflows for specific differences t2s_coreg : bool For multi-echo EPI, use the calculated T2*-map for T2*-driven coregistration omp_nthreads : int Maximum number of threads an individual process may use skull_strip_template : str Name of ANTs skull-stripping template ('OASIS' or 'NKI') skull_strip_fixed_seed : bool Do not use a random seed for skull-stripping - will ensure run-to-run replicability when used with --omp-nthreads 1 freesurfer : bool Enable FreeSurfer surface reconstruction (may increase runtime) output_spaces : list List of output spaces functional images are to be resampled to. Some parts of pipeline will only be instantiated for some output spaces. Valid spaces: - T1w - template - fsnative - fsaverage (or other pre-existing FreeSurfer templates) template : str Name of template targeted by ``template`` output space medial_surface_nan : bool Replace medial wall values with NaNs on functional GIFTI files cifti_output : bool Generate bold CIFTI file in output spaces hires : bool Enable sub-millimeter preprocessing in FreeSurfer use_bbr : bool or None Enable/disable boundary-based registration refinement. If ``None``, test BBR result for distortion before accepting. bold2t1w_dof : 6, 9 or 12 Degrees-of-freedom for BOLD-T1w registration fmap_bspline : bool **Experimental**: Fit B-Spline field using least-squares fmap_demean : bool Demean voxel-shift map during unwarp use_syn : bool **Experimental**: Enable ANTs SyN-based susceptibility distortion correction (SDC). If fieldmaps are present and enabled, this is not run, by default. force_syn : bool **Temporary**: Always run SyN-based SDC use_aroma : bool Perform ICA-AROMA on MNI-resampled functional series ignore_aroma_err : bool Do not fail on ICA-AROMA errors template_out_grid : str Keyword ('native', '1mm' or '2mm') or path of custom reference image for normalization """ fmriprep_wf = Workflow(name='fmriprep_wf') fmriprep_wf.base_dir = work_dir if freesurfer: fsdir = pe.Node( BIDSFreeSurferDir( derivatives=output_dir, freesurfer_home=os.getenv('FREESURFER_HOME'), spaces=output_spaces), name='fsdir_run_' + run_uuid.replace('-', '_'), run_without_submitting=True) reportlets_dir = os.path.join(work_dir, 'reportlets') for subject_id in subject_list: single_subject_wf = init_single_subject_wf( subject_id=subject_id, task_id=task_id, echo_idx=echo_idx, name="single_subject_" + subject_id + "_wf", reportlets_dir=reportlets_dir, output_dir=output_dir, bids_dir=bids_dir, ignore=ignore, debug=debug, low_mem=low_mem, anat_only=anat_only, longitudinal=longitudinal, t2s_coreg=t2s_coreg, omp_nthreads=omp_nthreads, skull_strip_template=skull_strip_template, skull_strip_fixed_seed=skull_strip_fixed_seed, freesurfer=freesurfer, output_spaces=output_spaces, template=template, medial_surface_nan=medial_surface_nan, cifti_output=cifti_output, hires=hires, use_bbr=use_bbr, bold2t1w_dof=bold2t1w_dof, fmap_bspline=fmap_bspline, fmap_demean=fmap_demean, use_syn=use_syn, force_syn=force_syn, template_out_grid=template_out_grid, use_aroma=use_aroma, aroma_melodic_dim=aroma_melodic_dim, ignore_aroma_err=ignore_aroma_err, ) single_subject_wf.config['execution']['crashdump_dir'] = ( os.path.join(output_dir, "fmriprep", "sub-" + subject_id, 'log', run_uuid) ) for node in single_subject_wf._get_all_nodes(): node.config = deepcopy(single_subject_wf.config) if freesurfer: fmriprep_wf.connect(fsdir, 'subjects_dir', single_subject_wf, 'inputnode.subjects_dir') else: fmriprep_wf.add_nodes([single_subject_wf]) return fmriprep_wf
def init_nibabies_wf(): """ Build *NiBabies*'s pipeline. This workflow organizes the execution of NiBabies, with a sub-workflow for each subject. If FreeSurfer's ``infant_recon_all`` is to be run, a corresponding folder is created and populated with any needed template subjects under the derivatives folder. Workflow Graph .. workflow:: :graph2use: orig :simple_form: yes from nibabies.workflows.tests import mock_config from nibabies.workflows.base import init_nibabies_wf with mock_config(): wf = init_nibabies_wf() """ from niworkflows.engine.workflows import LiterateWorkflow as Workflow from niworkflows.interfaces.bids import BIDSFreeSurferDir nibabies_wf = Workflow(name="nibabies_wf") nibabies_wf.base_dir = config.execution.work_dir freesurfer = config.workflow.run_reconall if freesurfer: fsdir = pe.Node( BIDSFreeSurferDir( derivatives=config.execution.output_dir, freesurfer_home=os.getenv("FREESURFER_HOME"), spaces=config.workflow.spaces.get_fs_spaces(), ), name=f"fsdir_run_{config.execution.run_uuid.replace('-', '_')}", run_without_submitting=True, ) if config.execution.fs_subjects_dir is not None: fsdir.inputs.subjects_dir = str( config.execution.fs_subjects_dir.absolute()) for subject_id in config.execution.participant_label: single_subject_wf = init_single_subject_wf(subject_id) single_subject_wf.config["execution"]["crashdump_dir"] = str( config.execution.fmriprep_dir / f"sub-{subject_id}" / "log" / config.execution.run_uuid) for node in single_subject_wf._get_all_nodes(): node.config = deepcopy(single_subject_wf.config) if freesurfer: nibabies_wf.connect(fsdir, "subjects_dir", single_subject_wf, "inputnode.subjects_dir") else: nibabies_wf.add_nodes([single_subject_wf]) # Dump a copy of the config file into the log directory log_dir = (config.execution.fmriprep_dir / f"sub-{subject_id}" / "log" / config.execution.run_uuid) log_dir.mkdir(exist_ok=True, parents=True) config.to_filename(log_dir / "nibabies.toml") return nibabies_wf
def init_nibetaseries_participant_wf( estimator, atlas_img, atlas_lut, bids_dir, database_path, derivatives_pipeline_dir, exclude_description_label, fir_delays, hrf_model, high_pass, norm_betas, output_dir, return_residuals, run_label, selected_confounds, session_label, signal_scaling, smoothing_kernel, space_label, subject_list, task_label, description_label, work_dir, ): """ This workflow organizes the execution of NiBetaSeries, with a sub-workflow for each subject. Parameters ---------- atlas_img : str Path to input atlas nifti atlas_lut : str Path to input atlas lookup table (tsv) bids_dir : str Root directory of BIDS dataset database_path : str Path to a BIDS database derivatives_pipeline_dir : str Root directory of the derivatives pipeline exclude_description_label : str or None Exclude bold series containing this description label fir_delays : list or None FIR delays (in scans) hrf_model : str The model that represents the shape of the hemodynamic response function high_pass : float High pass filter to apply to bold (in Hertz). Reminder - frequencies _higher_ than this number are kept. norm_betas : Bool If True, beta estimates are divided by the square root of their variance output_dir : str Directory where derivatives are saved return_residuals : bool Output the residuals from the betaseries model into the derivatives directory run_label : str or None Include bold series containing this run label selected_confounds : list List of confounds to be included in regression signal_scaling : False or 0 Whether (0) or not (False) to scale each voxel's timeseries session_label : str or None Include bold series containing this session label smoothing_kernel : float or None The smoothing kernel to be applied to the bold series before beta estimation space_label : str or None Include bold series containing this space label subject_list : list List of subject labels task_label : str or None Include bold series containing this task label description_label : str or None Include bold series containing this description label work_dir : str Directory in which to store workflow execution state and temporary files """ # setup workflow nibetaseries_participant_wf = Workflow(name='nibetaseries_participant_wf') nibetaseries_participant_wf.base_dir = os.path.join( work_dir, 'NiBetaSeries_work') os.makedirs(nibetaseries_participant_wf.base_dir, exist_ok=True) nibetaseries_participant_wf.__desc__ = """ Results included in this manuscript come from modeling performed using *NiBetaSeries* {nibs_ver} [@Kent2018], which is based on *Nipype* {nipype_ver} [@Gorgolewski2011; @Gorgolewski2018]. """.format(nibs_ver=get_versions()['version'], nipype_ver=nipype_ver) nibetaseries_participant_wf.__postdesc__ = """ ### Software Dependencies Additional libraries used in the NiBetaSeries workflow include *Pybids* {pybids_ver} [@Yarkoni2019], *Niworkflows* {niworkflows_ver}, *Nibabel* {nibabel_ver}, *Pandas* {pandas_ver} [@McKinney2010], and *Numpy* {numpy_ver} [@VanDerWalt2011; @Oliphant2006]. ### Copyright Waiver The above boilerplate text was automatically generated by NiBetaSeries with the express intention that users should copy and paste this text into their manuscripts *unchanged*. It is released under the [CC0]\ (https://creativecommons.org/publicdomain/zero/1.0/) license. ### References """.format(pybids_ver=pybids_ver, niworkflows_ver=niworkflows_ver, nibabel_ver=nibabel_ver, pandas_ver=pandas_ver, numpy_ver=numpy_ver) # Go ahead and initialize the layout database if database_path is None: database_path = os.path.join(work_dir, 'dbcache') reset_database = True else: reset_database = False # reading in derivatives and bids inputs as queryable database like objects layout = BIDSLayout(bids_dir, derivatives=derivatives_pipeline_dir, index_metadata=False, database_file=database_path, reset_database=reset_database) # only index bold file metadata if reset_database: indexer = BIDSLayoutIndexerPatch(layout) metadata_filter = { 'extension': ['nii', 'nii.gz', 'json'], 'suffix': 'bold', } indexer.index_metadata(**metadata_filter) for subject_label in subject_list: # collect the necessary inputs for both collect data subject_data = collect_data(layout, subject_label, task=task_label, run=run_label, ses=session_label, space=space_label, description=description_label) # collect files to be associated with each preproc brainmask_list = [d['brainmask'] for d in subject_data] confound_tsv_list = [d['confounds'] for d in subject_data] events_tsv_list = [d['events'] for d in subject_data] preproc_img_list = [d['preproc'] for d in subject_data] bold_metadata_list = [d['metadata'] for d in subject_data] single_subject_wf = init_single_subject_wf( estimator=estimator, atlas_img=atlas_img, atlas_lut=atlas_lut, bold_metadata_list=bold_metadata_list, brainmask_list=brainmask_list, confound_tsv_list=confound_tsv_list, events_tsv_list=events_tsv_list, fir_delays=fir_delays, hrf_model=hrf_model, high_pass=high_pass, name='single_subject' + subject_label + '_wf', norm_betas=norm_betas, output_dir=output_dir, preproc_img_list=preproc_img_list, return_residuals=return_residuals, selected_confounds=selected_confounds, signal_scaling=signal_scaling, smoothing_kernel=smoothing_kernel, ) single_subject_wf.config['execution']['crashdump_dir'] = (os.path.join( output_dir, "sub-" + subject_label, 'log')) for node in single_subject_wf._get_all_nodes(): node.config = deepcopy(single_subject_wf.config) nibetaseries_participant_wf.add_nodes([single_subject_wf]) return nibetaseries_participant_wf
def init_funcworks_wf( model_file, bids_dir, output_dir, work_dir, database_path, participants, analysis_level, smoothing, runtime_uuid, use_rapidart, detrend_poly, align_volumes, smooth_autocorrelations, despike, ): """Initialize funcworks single subject workflow for all subjects.""" with open(model_file, "r") as read_mdl: model = json.load(read_mdl) funcworks_wf = Workflow(name="funcworks_wf") (work_dir / model["Name"]).mkdir(exist_ok=True, parents=True) funcworks_wf.base_dir = work_dir / model["Name"] if smoothing: smoothing_params = smoothing.split(":") if len(smoothing_params) == 1: smoothing_params.extend(("l1", "iso")) elif len(smoothing_params) == 2: smoothing_params.append("iso") smoothing_fwhm, smoothing_level, smoothing_type = smoothing_params smoothing_fwhm = int(smoothing_fwhm) if smoothing_level.lower().startswith("l"): if int(smoothing_level[1:]) > len(model["Steps"]): raise ValueError(f"Invalid smoothing level {smoothing_level}") else: smoothing_fwhm = None smoothing_level = None smoothing_type = None for subject_id in participants: single_subject_wf = init_funcworks_subject_wf( model=model, bids_dir=bids_dir, output_dir=(output_dir / "funcworks" / model["Name"]), work_dir=work_dir, database_path=database_path, subject_id=subject_id, analysis_level=analysis_level, smoothing_fwhm=smoothing_fwhm, smoothing_level=smoothing_level, smoothing_type=smoothing_type, use_rapidart=use_rapidart, detrend_poly=detrend_poly, align_volumes=align_volumes, smooth_autocorrelations=smooth_autocorrelations, despike=despike, name=f"single_subject_{subject_id}_wf", ) crash_dir = (Path(output_dir) / "funcworks" / model["Name"] / f"sub-{subject_id}" / "log" / runtime_uuid) crash_dir.mkdir(exist_ok=True, parents=True) single_subject_wf.config["execution"]["crashdump_dir"] = str(crash_dir) for node in single_subject_wf._get_all_nodes(): node.config = deepcopy(single_subject_wf.config) funcworks_wf.add_nodes([single_subject_wf]) return funcworks_wf