def create_templates_2func_workflow(threshold=0.5, name='templates_2func_workflow'): templates_2func_workflow = Workflow(name=name) # Input Node inputspec = Node(utility.IdentityInterface(fields=[ 'func_file', 'premat', 'warp', 'templates', ]), name='inputspec') # Get the overal EPI to MNI warp func_2mni_warp = Node(fsl.ConvertWarp(), name='func_2mni_warp') func_2mni_warp.inputs.reference = fsl.Info.standard_image( 'MNI152_T1_2mm.nii.gz') # Calculate the inverse warp mni_2func_warp = Node(fsl.InvWarp(), name='mni_2func_warp') # Transform MNI templates to EPI space templates_2func_apply = MapNode(fsl.ApplyWarp(), iterfield=['in_file'], name='templates_2func_apply') # Threshold templates templates_threshold = MapNode( fsl.ImageMaths(op_string='-thr {0} -bin'.format(threshold)), iterfield=['in_file'], name='templates_threshold') # Output Node outputspec = Node(utility.IdentityInterface( fields=['templates_2func_files', 'func_2mni_warp']), name='outputspec') # Connect the workflow nodes templates_2func_workflow.connect(inputspec, 'premat', func_2mni_warp, 'premat') templates_2func_workflow.connect(inputspec, 'warp', func_2mni_warp, 'warp1') templates_2func_workflow.connect(inputspec, 'func_file', mni_2func_warp, 'reference') templates_2func_workflow.connect(func_2mni_warp, 'out_file', mni_2func_warp, 'warp') templates_2func_workflow.connect(inputspec, 'templates', templates_2func_apply, 'in_file') templates_2func_workflow.connect(inputspec, 'func_file', templates_2func_apply, 'ref_file') templates_2func_workflow.connect(mni_2func_warp, 'inverse_warp', templates_2func_apply, 'field_file') templates_2func_workflow.connect(templates_2func_apply, 'out_file', templates_threshold, 'in_file') templates_2func_workflow.connect(func_2mni_warp, 'out_file', outputspec, 'func_2mni_warp') templates_2func_workflow.connect(templates_threshold, 'out_file', outputspec, 'templates_2func_files') return templates_2func_workflow
def vsm2warp(name='Shiftmap2Warping'): """ Converts a voxel shift map (vsm) to a displacements field (warp). """ inputnode = pe.Node(niu.IdentityInterface( fields=['in_vsm', 'in_ref', 'scaling', 'enc_dir']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface(fields=['out_warp']), name='outputnode') fixhdr = pe.Node(niu.Function(input_names=['in_file', 'in_file_hdr'], output_names=['out_file'], function=copy_hdr), name='Fix_hdr') vsm = pe.Node(fsl.maths.BinaryMaths(operation='mul'), name='ScaleField') vsm2dfm = pe.Node(fsl.ConvertWarp(relwarp=True, out_relwarp=True), name='vsm2dfm') wf = pe.Workflow(name=name) wf.connect([(inputnode, fixhdr, [('in_vsm', 'in_file'), ('in_ref', 'in_file_hdr')]), (inputnode, vsm, [('scaling', 'operand_value')]), (fixhdr, vsm, [('out_file', 'in_file')]), (vsm, vsm2dfm, [('out_file', 'shift_in_file')]), (inputnode, vsm2dfm, [('in_ref', 'reference'), ('enc_dir', 'shift_direction')]), (vsm2dfm, outputnode, [('out_file', 'out_warp')])]) return wf
def apply_all_corrections(name='UnwarpArtifacts'): """ Combines two lists of linear transforms with the deformation field map obtained typically after the SDC process. Additionally, computes the corresponding bspline coefficients and the map of determinants of the jacobian. """ inputnode = pe.Node(niu.IdentityInterface(fields=['in_sdc', 'in_hmc', 'in_ecc', 'in_dwi']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface(fields=['out_file', 'out_warp', 'out_coeff', 'out_jacobian']), name='outputnode') warps = pe.MapNode(fsl.ConvertWarp(relwarp=True), iterfield=['premat', 'postmat'], name='ConvertWarp') selref = pe.Node(niu.Select(index=[0]), name='Reference') split = pe.Node(fsl.Split(dimension='t'), name='SplitDWIs') unwarp = pe.MapNode(fsl.ApplyWarp(), iterfield=['in_file', 'field_file'], name='UnwarpDWIs') coeffs = pe.MapNode(fsl.WarpUtils(out_format='spline'), iterfield=['in_file'], name='CoeffComp') jacobian = pe.MapNode(fsl.WarpUtils(write_jacobian=True), iterfield=['in_file'], name='JacobianComp') jacmult = pe.MapNode(fsl.MultiImageMaths(op_string='-mul %s'), iterfield=['in_file', 'operand_files'], name='ModulateDWIs') thres = pe.MapNode(fsl.Threshold(thresh=0.0), iterfield=['in_file'], name='RemoveNegative') merge = pe.Node(fsl.Merge(dimension='t'), name='MergeDWIs') wf = pe.Workflow(name=name) wf.connect([ (inputnode, warps, [('in_sdc', 'warp1'), ('in_hmc', 'premat'), ('in_ecc', 'postmat'), ('in_dwi', 'reference')]), (inputnode, split, [('in_dwi', 'in_file')]), (split, selref, [('out_files', 'inlist')]), (warps, unwarp, [('out_file', 'field_file')]), (split, unwarp, [('out_files', 'in_file')]), (selref, unwarp, [('out', 'ref_file')]), (selref, coeffs, [('out', 'reference')]), (warps, coeffs, [('out_file', 'in_file')]), (selref, jacobian, [('out', 'reference')]), (coeffs, jacobian, [('out_file', 'in_file')]), (unwarp, jacmult, [('out_file', 'in_file')]), (jacobian, jacmult, [('out_jacobian', 'operand_files')]), (jacmult, thres, [('out_file', 'in_file')]), (thres, merge, [('out_file', 'in_files')]), (warps, outputnode, [('out_file', 'out_warp')]), (coeffs, outputnode, [('out_file', 'out_coeff')]), (jacobian, outputnode, [('out_jacobian', 'out_jacobian')]), (merge, outputnode, [('merged_file', 'out_file')]) ]) return wf
def apply_all_corrections_using_ants(name='UnwarpArtifacts'): """ Combines two lists of linear transforms with the deformation field map obtained epi_correction by Ants. Additionally, computes the corresponding bspline coefficients and the map of determinants of the jacobian. """ import nipype.interfaces.fsl as fsl import nipype.interfaces.utility as niu import nipype.pipeline.engine as pe inputnode = pe.Node(niu.IdentityInterface( fields=['in_sdc_syb', 'in_hmc', 'in_ecc', 'in_dwi', 'in_t1']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface( fields=['out_file', 'out_warp', 'out_coeff', 'out_jacobian']), name='outputnode') split = pe.Node(fsl.Split(dimension='t'), name='SplitDWIs') concat_hmc_ecc = pe.MapNode(fsl.ConvertXFM(), name="concat_hmc_ecc", iterfield=['in_file', 'in_file2']) concat_hmc_ecc.inputs.concat_xfm = True warps = pe.MapNode(fsl.ConvertWarp(), iterfield=['premat'], name='ConvertWarp') unwarp = pe.MapNode(interface=fsl.ApplyWarp(), iterfield=['in_file', 'field_file'], name='unwarp_warp') unwarp.inputs.interp = 'spline' coeffs = pe.MapNode(fsl.WarpUtils(out_format='spline'), iterfield=['in_file'], name='CoeffComp') jacobian = pe.MapNode(fsl.WarpUtils(write_jacobian=True), iterfield=['in_file'], name='JacobianComp') jacmult = pe.MapNode(fsl.MultiImageMaths(op_string='-mul %s'), iterfield=['in_file', 'operand_files'], name='ModulateDWIs') thres = pe.MapNode(fsl.Threshold(thresh=0.0), iterfield=['in_file'], name='RemoveNegative') merge = pe.Node(fsl.Merge(dimension='t'), name='MergeDWIs') wf = pe.Workflow(name=name) wf.connect([ (inputnode, concat_hmc_ecc, [('in_ecc', 'in_file2')]), # noqa (inputnode, concat_hmc_ecc, [('in_hmc', 'in_file')]), # noqa (concat_hmc_ecc, warps, [('out_file', 'premat')]), # noqa (inputnode, warps, [('in_sdc_syb', 'warp1')]), # noqa (inputnode, warps, [('in_t1', 'reference')]), # noqa (inputnode, split, [('in_dwi', 'in_file')]), # noqa (warps, unwarp, [('out_file', 'field_file')]), # noqa (split, unwarp, [('out_files', 'in_file')]), # noqa (inputnode, unwarp, [('in_t1', 'ref_file')]), # noqa (inputnode, coeffs, [('in_t1', 'reference')]), # noqa (warps, coeffs, [('out_file', 'in_file')]), # noqa (inputnode, jacobian, [('in_t1', 'reference')]), # noqa (coeffs, jacobian, [('out_file', 'in_file')]), # noqa (unwarp, jacmult, [('out_file', 'in_file')]), # noqa (jacobian, jacmult, [('out_jacobian', 'operand_files')]), # noqa (jacmult, thres, [('out_file', 'in_file')]), # noqa (thres, merge, [('out_file', 'in_files')]), # noqa (warps, outputnode, [('out_file', 'out_warp')]), # noqa (coeffs, outputnode, [('out_file', 'out_coeff')]), # noqa (jacobian, outputnode, [('out_jacobian', 'out_jacobian')]), # noqa (merge, outputnode, [('merged_file', 'out_file')]) # noqa ]) return wf
# roi_datasource.inputs.template_args = {'seed_rois': [['subject_id']] } """ Setup for Tracktography ----------------------- Here we will create a generic workflow for DTI computation, this workflow assumes the .bedpostX has already been run... Here we will create a workflow to enable probabilistic tracktography and hard segmentation of the seed region """ stout_tractography = pe.Workflow(name='stout_tractography') stout_tractography.base_dir = WORKINGDATAPATH ### First connect the subject list to the workflow to build up the patient lists stout_tractography.connect(infosource, 'subject_id', dti_datasource, 'subject_id') ### GENERATE THE WARP FIELDS cvtwarp_mni_to_dti = pe.Node(interface=fsl.ConvertWarp(), name='cvtwarp_mni_to_dti') cvtwarp_mni_to_dti.inputs.reference = os.path.join( RAWDATAPATH, "MNI152_T1_1mm_brain.nii.gz") stout_tractography.connect(dti_datasource, 'nodif_to_struct_aff', cvtwarp_mni_to_dti, 'premat') stout_tractography.connect(dti_datasource, 'struct_warpto_MNI', cvtwarp_mni_to_dti, 'warp1') # $statement .= " --premat=$WORKINGDATAPATH/" . $subj[$i] . "/xfms/nodif_12dof_struc.mat "; # $statement .= " --warp1=$WORKINGDATAPATH/" . $subj[$i] . "/xfms/struc_warp_MNI_warpfield.nii.gz "; # $statement .= " --out=$WORKINGDATAPATH/" . $subj[$i] . "/xfms/nodif_12dof_struc_warp_MNI_warpfield.nii.gz "; cvtwarp_dti_to_mni = pe.Node(interface=fsl.ConvertWarp(), name='cvtwarp_dti_to_mni')
def susceptibility_distortion_correction_using_t1( name='susceptibility_distortion_correction_using_t1'): """ Susceptibility distortion correction using the T1w image. This workflow allows to correct for echo-planar induced susceptibility artifacts without fieldmap (e.g. ADNI Database) by elastically register DWIs to their respective baseline T1-weighted structural scans using an inverse consistent registration algorithm with a mutual information cost function (SyN algorithm). Args: name (Optional[str]): Name of the workflow. Inputnode: in_t1 (str): T1w image. in_dwi (str): DWI dataset Outputnode: out_dwi (str): Corrected DWI dataset out_warp (str): Out warp allowing DWI to T1 registration and susceptibilty induced artifacts correction out_b0_to_t1_rigid_body_matrix (str): B0 to T1 image FLIRT rigid body FSL coregistration matrix out_t1_to_b0_rigid_body_matrix (str): T1 to B0 image FLIRT rigid body FSL coregistration matrix out_t1_coregistered_to_b0 (str): T1 image rigid body coregistered to the B0 image out_b0_to_t1_syn_deformation_field (str): B0 to T1 image ANTs SyN ITK warp out_b0_to_t1_affine_matrix (str): B0 to T1 image ANTs affine ITK coregistration matrix References: .. Nir et al. (Neurobiology of Aging 2015): Connectivity network measures predict volumetric atrophy in mild cognitive impairment .. Leow et al. (IEEE Trans Med Imaging 2007): Statistical Properties of Jacobian Maps and the Realization of Unbiased Large Deformation Nonlinear Image Registration Returns: The workflow Example: >>> epi = susceptibility_distortion_correction_using_t1() >>> epi.inputs.inputnode.in_dwi = 'dwi.nii' >>> epi.inputs.inputnode.in_t1 = 'T1w.nii' >>> epi.run() # doctest: +SKIP """ import nipype import nipype.pipeline.engine as pe import nipype.interfaces.utility as niu import nipype.interfaces.fsl as fsl import clinica.pipelines.dwi_preprocessing_using_t1.dwi_preprocessing_using_t1_utils as utils def expend_matrix_list(in_matrix, in_bvec): import numpy as np bvecs = np.loadtxt(in_bvec).T out_matrix_list = [in_matrix] out_matrix_list = out_matrix_list * len(bvecs) return out_matrix_list def rotate_bvecs(in_bvec, in_matrix): """ Rotates the input bvec file accordingly with a list of matrices. .. note:: the input affine matrix transforms points in the destination image to their corresponding coordinates in the original image. Therefore, this matrix should be inverted first, as we want to know the target position of :math:`\\vec{r}`. """ import os import numpy as np name, fext = os.path.splitext(os.path.basename(in_bvec)) if fext == '.gz': name, _ = os.path.splitext(name) out_file = os.path.abspath('%s_rotated.bvec' % name) bvecs = np.loadtxt( in_bvec).T # Warning, bvecs.txt are not in the good configuration, need to put '.T' new_bvecs = [] if len(bvecs) != len(in_matrix): raise RuntimeError(('Number of b-vectors (%d) and rotation ' 'matrices (%d) should match.') % (len(bvecs), len(in_matrix))) for bvec, mat in zip(bvecs, in_matrix): if np.all(bvec == 0.0): new_bvecs.append(bvec) else: invrot = np.linalg.inv(np.loadtxt(mat))[:3, :3] newbvec = invrot.dot(bvec) new_bvecs.append((newbvec / np.linalg.norm(newbvec))) np.savetxt(out_file, np.array(new_bvecs).T, fmt='%0.15f') return out_file inputnode = pe.Node( niu.IdentityInterface(fields=['in_t1', 'in_dwi', 'in_bvec']), name='inputnode') split = pe.Node(fsl.Split(dimension='t'), name='SplitDWIs') pick_ref = pe.Node(niu.Select(), name='Pick_b0') pick_ref.inputs.index = [0] flirt_b0_to_t1 = pe.Node(interface=fsl.FLIRT(dof=6), name='flirt_b0_to_t1') flirt_b0_to_t1.inputs.interp = "spline" flirt_b0_to_t1.inputs.cost = 'normmi' flirt_b0_to_t1.inputs.cost_func = 'normmi' if nipype.__version__.split('.') < ['0', '13', '0']: apply_xfm = pe.Node(interface=fsl.ApplyXfm(), name='apply_xfm') else: apply_xfm = pe.Node(interface=fsl.ApplyXFM(), name='apply_xfm') apply_xfm.inputs.apply_xfm = True expend_matrix = pe.Node( interface=niu.Function(input_names=['in_matrix', 'in_bvec'], output_names=['out_matrix_list'], function=expend_matrix_list), name='expend_matrix') rot_bvec = pe.Node(niu.Function(input_names=['in_matrix', 'in_bvec'], output_names=['out_file'], function=rotate_bvecs), name='Rotate_Bvec') ants_registration_syn_quick = pe.Node(interface=niu.Function( input_names=['fix_image', 'moving_image'], output_names=['image_warped', 'affine_matrix', 'warp', 'inverse_warped', 'inverse_warp'], function=utils.ants_registration_syn_quick), name='ants_registration_syn_quick') merge_transform = pe.Node(niu.Merge(2), name='MergeTransforms') combine_warp = pe.Node(interface=niu.Function( input_names=['in_file', 'transforms_list', 'reference'], output_names=['out_warp'], function=utils.ants_combine_transform), name='combine_warp') coeffs = pe.Node(fsl.WarpUtils(out_format='spline'), name='CoeffComp') fsl_transf = pe.Node(fsl.WarpUtils(out_format='field'), name='fsl_transf') warp_epi = pe.Node(fsl.ConvertWarp(), name='warp_epi') apply_warp = pe.MapNode(interface=fsl.ApplyWarp(), iterfield=['in_file'], name='apply_warp') apply_warp.inputs.interp = 'spline' thres = pe.MapNode(fsl.Threshold(thresh=0.0), iterfield=['in_file'], name='RemoveNegative') merge = pe.Node(fsl.Merge(dimension='t'), name='MergeDWIs') outputnode = pe.Node(niu.IdentityInterface( fields=['dwi_to_t1_coregistration_matrix', 'itk_dwi_t1_coregistration_matrix', 'epi_correction_deformation_field', 'epi_correction_affine_transform', 'merge_epi_transform', 'out_dwi', 'out_warp', 'out_bvec']), name='outputnode') wf = pe.Workflow(name=name) wf.connect([ (inputnode, split, [('in_dwi', 'in_file')]), # noqa (split, pick_ref, [('out_files', 'inlist')]), # noqa (pick_ref, flirt_b0_to_t1, [('out', 'in_file')]), # noqa (inputnode, flirt_b0_to_t1, [('in_t1', 'reference')]), # noqa (flirt_b0_to_t1, expend_matrix, [('out_matrix_file', 'in_matrix')]), # noqa (inputnode, expend_matrix, [('in_bvec', 'in_bvec')]), # noqa (inputnode, rot_bvec, [('in_bvec', 'in_bvec')]), # noqa (expend_matrix, rot_bvec, [('out_matrix_list', 'in_matrix')]), # noqa (inputnode, ants_registration_syn_quick, [('in_t1', 'fix_image')]), # noqa (flirt_b0_to_t1, ants_registration_syn_quick, [('out_file', 'moving_image')]), # noqa (ants_registration_syn_quick, merge_transform, [('affine_matrix', 'in2'), # noqa ('warp', 'in1')]), # noqa (flirt_b0_to_t1, combine_warp, [('out_file', 'in_file')]), # noqa (merge_transform, combine_warp, [('out', 'transforms_list')]), # noqa (inputnode, combine_warp, [('in_t1', 'reference')]), # noqa (inputnode, coeffs, [('in_t1', 'reference')]), # noqa (combine_warp, coeffs, [('out_warp', 'in_file')]), # noqa (coeffs, fsl_transf, [('out_file', 'in_file')]), # noqa (inputnode, fsl_transf, [('in_t1', 'reference')]), # noqa (inputnode, warp_epi, [('in_t1', 'reference')]), # noqa (flirt_b0_to_t1, warp_epi, [('out_matrix_file', 'premat')]), # noqa (fsl_transf, warp_epi, [('out_file', 'warp1')]), # noqa (warp_epi, apply_warp, [('out_file', 'field_file')]), # noqa (split, apply_warp, [('out_files', 'in_file')]), # noqa (inputnode, apply_warp, [('in_t1', 'ref_file')]), # noqa (apply_warp, thres, [('out_file', 'in_file')]), # noqa (thres, merge, [('out_file', 'in_files')]), # noqa # Outputnode (merge, outputnode, [('merged_file', 'out_dwi')]), # noqa (flirt_b0_to_t1, outputnode, [('out_matrix_file', 'dwi_to_t1_coregistration_matrix')]), # noqa (ants_registration_syn_quick, outputnode, [('warp', 'epi_correction_deformation_field'), # noqa ('affine_matrix', 'epi_correction_affine_transform')]), # noqa (warp_epi, outputnode, [('out_file', 'out_warp')]), # noqa (rot_bvec, outputnode, [('out_file', 'out_bvec')]), # noqa ]) return wf
def fsl_apply_transform_func_to_mni(workflow, output_name, func_key, ref_key, num_strat, strat, interpolation_method, distcor=False, map_node=False, func_ts=False, num_cpus=1): """ Applies previously calculated FSL registration transforms to input images. This workflow employs the FSL applywarp tool: https://fsl.fmrib.ox.ac.uk/fslcourse/lectures/practicals/registration/index.html Parameters ---------- workflow : Nipype workflow object the workflow containing the resources involved output_name : str what the name of the warped functional should be when written to the resource pool func_key : string resource pool key correspoding to the node containing the 3D or 4D functional file to be written into MNI space, use 'leaf' for a leaf node ref_key : string resource pool key correspoding to the file path to the template brain used for functional-to-template registration num_strat : int the number of strategy objects strat : C-PAC Strategy object a strategy with one or more resource pools interpolation_method : str which interpolation to use when applying the warps distcor : boolean indicates whether a distortion correction transformation should be added to the transforms, this of course requires that a distortion correction map exist in the resource pool map_node : boolean indicates whether a mapnode should be used, if TRUE func_key is expected to correspond to a list of resources that should each be written into standard space with the other parameters func_ts : boolean indicates whether the input image is a 4D time series num_cpus : int the number of CPUs dedicated to each participant workflow - this is used to determine how to parallelize the warp application step Returns ------- workflow : nipype.pipeline.engine.Workflow """ strat_nodes = strat.get_nodes_names() # if the input is a string, assume that it is resource pool key, # if it is a tuple, assume that it is a node, outfile pair, # otherwise, something funky is going on if isinstance(func_key, str): if func_key == "leaf": func_node, func_file = strat.get_leaf_properties() else: func_node, func_file = strat[func_key] elif isinstance(func_key, tuple): func_node, func_file = func_key if isinstance(ref_key, str): ref_node, ref_out_file = strat[ref_key] elif isinstance(ref_key, tuple): ref_node, ref_out_file = ref_key if int(num_cpus) > 1 and func_ts: # parallelize time series warp application map_node = True if map_node == True: # func_mni_warp func_mni_warp = pe.MapNode(interface=fsl.ApplyWarp(), name='func_mni_fsl_warp_{0}_{1:d}'.format( output_name, num_strat), iterfield=['in_file'], mem_gb=1.5) else: # func_mni_warp func_mni_warp = pe.Node(interface=fsl.ApplyWarp(), name='func_mni_fsl_warp_{0}_{1:d}'.format( output_name, num_strat)) func_mni_warp.inputs.interp = interpolation_method # parallelize the apply warp, if multiple CPUs, and it's a time series! if int(num_cpus) > 1 and func_ts: node_id = '{0}_{1:d}'.format(output_name, num_strat) chunk_imports = ['import nibabel as nb'] chunk = pe.Node(Function(input_names=['func_file', 'n_cpus'], output_names=['TR_ranges'], function=chunk_ts, imports=chunk_imports), name=f'chunk_{node_id}') chunk.inputs.n_cpus = int(num_cpus) workflow.connect(func_node, func_file, chunk, 'func_file') split_imports = ['import os', 'import subprocess'] split = pe.Node(Function(input_names=['func_file', 'tr_ranges'], output_names=['split_funcs'], function=split_ts_chunks, imports=split_imports), name=f'split_{node_id}') workflow.connect(func_node, func_file, split, 'func_file') workflow.connect(chunk, 'TR_ranges', split, 'tr_ranges') workflow.connect(split, 'split_funcs', func_mni_warp, 'in_file') func_concat = pe.Node(interface=afni_utils.TCat(), name=f'func_concat{node_id}') func_concat.inputs.outputtype = 'NIFTI_GZ' workflow.connect(func_mni_warp, 'out_file', func_concat, 'in_files') strat.update_resource_pool({output_name: (func_concat, 'out_file')}) else: workflow.connect(func_node, func_file, func_mni_warp, 'in_file') strat.update_resource_pool({output_name: (func_mni_warp, 'out_file')}) workflow.connect(ref_node, ref_out_file, func_mni_warp, 'ref_file') if 'anat_mni_fnirt_register' in strat_nodes: node, out_file = strat['functional_to_anat_linear_xfm'] workflow.connect(node, out_file, func_mni_warp, 'premat') node, out_file = strat['anatomical_to_mni_nonlinear_xfm'] workflow.connect(node, out_file, func_mni_warp, 'field_file') if output_name == "functional_to_standard": write_composite_xfm = pe.Node(interface=fsl.ConvertWarp(), name='combine_fsl_warps_{0}_{1:d}'.format(output_name,\ num_strat)) workflow.connect(ref_node, ref_out_file, write_composite_xfm, 'reference') node, out_file = strat['functional_to_anat_linear_xfm'] workflow.connect(node, out_file, write_composite_xfm, 'premat') node, out_file = strat['anatomical_to_mni_nonlinear_xfm'] workflow.connect(node, out_file, write_composite_xfm, 'warp1') strat.update_resource_pool({ "functional_to_standard_xfm": (write_composite_xfm, 'out_file') }) elif 'anat_mni_flirt_register' in strat_nodes: if 'functional_to_mni_linear_xfm' not in strat: combine_transforms = pe.Node(interface=fsl.ConvertXFM(), name='combine_fsl_xforms_{0}_{1:d}'.format(output_name,\ num_strat)) combine_transforms.inputs.concat_xfm = True node, out_file = strat['anatomical_to_mni_linear_xfm'] workflow.connect(node, out_file, combine_transforms, 'in_file2') node, out_file = strat['functional_to_anat_linear_xfm'] workflow.connect(node, out_file, combine_transforms, 'in_file') strat.update_resource_pool({ 'functional_to_mni_linear_xfm': (combine_transforms, 'out_file') }) strat.append_name(combine_transforms.name) combine_transforms, outfile = strat['functional_to_mni_linear_xfm'] workflow.connect(combine_transforms, outfile, func_mni_warp, 'premat') else: raise ValueError('Could not find flirt or fnirt registration in nodes') strat.append_name(func_mni_warp.name) return workflow
def create_registration_pipeline(working_dir, freesurfer_dir, ds_dir, name='registration'): """ find transformations between struct, funct, and MNI """ # initiate workflow reg_wf = Workflow(name=name) reg_wf.base_dir = os.path.join(working_dir, 'LeiCA_resting', 'rsfMRI_preprocessing') # set fsl output fsl.FSLCommand.set_default_output_type('NIFTI_GZ') freesurfer.FSCommand.set_default_subjects_dir(freesurfer_dir) # inputnode inputnode = Node(util.IdentityInterface(fields=[ 'initial_mean_epi_moco', 't1w', 't1w_brain', 'subject_id', 'wm_mask_4_bbr', 'struct_brain_mask' ]), name='inputnode') outputnode = Node(util.IdentityInterface(fields=[ 'struct_2_MNI_warp', 'epi_2_struct_mat', 'struct_2_epi_mat', 'epi_2_MNI_warp', 'MNI_2_epi_warp', 'fs_2_struct_mat', 'mean_epi_structSpace', 'mean_epi_MNIspace', 'struct_MNIspace' ]), name='outputnode') ds = Node(nio.DataSink(base_directory=ds_dir), name='ds') ds.inputs.substitutions = [('_TR_id_', 'TR_')] ########################################## # TOC REGISTRATION MATS AND WARPS ########################################## # I. STRUCT -> MNI ## 1. STRUCT -> MNI with FLIRT ## 2. CALC. WARP STRUCT -> MNI with FNIRT # II.EPI -> STRUCT ## 3. calc EPI->STRUCT initial registration ## 4. run EPI->STRUCT via bbr ## 5. INVERT to get: STRUCT -> EPI # III. COMBINE I. & II.: EPI -> MNI ## 6. COMBINE MATS: EPI -> MNI ## 7. MNI -> EPI ########################################## # CREATE REGISTRATION MATS AND WARPS ########################################## # I. STRUCT -> MNI ########################################## # 1. REGISTER STRUCT -> MNI with FLIRT struct_2_MNI_mat = Node(fsl.FLIRT(dof=12), name='struct_2_MNI_mat') struct_2_MNI_mat.inputs.reference = fsl.Info.standard_image( 'MNI152_T1_2mm_brain.nii.gz') reg_wf.connect(inputnode, 't1w_brain', struct_2_MNI_mat, 'in_file') reg_wf.connect(struct_2_MNI_mat, 'out_matrix_file', outputnode, 'struct_2_MNI_mat_flirt') # 2. CALC. WARP STRUCT -> MNI with FNIRT # cf. wrt. 2mm # https://www.jiscmail.ac.uk/cgi-bin/webadmin?A2=ind1311&L=FSL&P=R86108&1=FSL&9=A&J=on&d=No+Match%3BMatch%3BMatches&z=4 struct_2_MNI_warp = Node(fsl.FNIRT(), name='struct_2_MNI_warp') struct_2_MNI_warp.inputs.config_file = 'T1_2_MNI152_2mm' struct_2_MNI_warp.inputs.ref_file = fsl.Info.standard_image( 'MNI152_T1_2mm.nii.gz') struct_2_MNI_warp.inputs.field_file = 'struct_2_MNI_warp.nii.gz' struct_2_MNI_warp.plugin_args = {'submit_specs': 'request_memory = 4000'} reg_wf.connect(inputnode, 't1w', struct_2_MNI_warp, 'in_file') reg_wf.connect(struct_2_MNI_mat, 'out_matrix_file', struct_2_MNI_warp, 'affine_file') reg_wf.connect(struct_2_MNI_warp, 'field_file', ds, 'registration.struct_2_MNI_warp') reg_wf.connect(struct_2_MNI_warp, 'field_file', outputnode, 'struct_2_MNI_warp') reg_wf.connect(struct_2_MNI_warp, 'warped_file', outputnode, 'struct_MNIspace') reg_wf.connect(struct_2_MNI_warp, 'warped_file', ds, 'registration.struct_MNIspace') # II.EPI -> STRUCT (via bbr) ########################################## # 3. calc EPI->STRUCT initial registration with flirt dof=6 and corratio epi_2_struct_flirt6_mat = Node(fsl.FLIRT(dof=6, cost='corratio'), name='epi_2_struct_flirt6_mat') epi_2_struct_flirt6_mat.inputs.out_file = 'epi_structSpace_flirt6.nii.gz' reg_wf.connect(inputnode, 't1w_brain', epi_2_struct_flirt6_mat, 'reference') reg_wf.connect(inputnode, 'initial_mean_epi_moco', epi_2_struct_flirt6_mat, 'in_file') # 4. run EPI->STRUCT via bbr bbr_shedule = os.path.join(os.getenv('FSLDIR'), 'etc/flirtsch/bbr.sch') epi_2_struct_bbr_mat = Node(interface=fsl.FLIRT(dof=6, cost='bbr'), name='epi_2_struct_bbr_mat') epi_2_struct_bbr_mat.inputs.schedule = bbr_shedule epi_2_struct_bbr_mat.inputs.out_file = 'epi_structSpace.nii.gz' reg_wf.connect(inputnode, 'initial_mean_epi_moco', epi_2_struct_bbr_mat, 'in_file') reg_wf.connect(inputnode, 't1w_brain', epi_2_struct_bbr_mat, 'reference') reg_wf.connect(epi_2_struct_flirt6_mat, 'out_matrix_file', epi_2_struct_bbr_mat, 'in_matrix_file') reg_wf.connect(inputnode, 'wm_mask_4_bbr', epi_2_struct_bbr_mat, 'wm_seg') reg_wf.connect(epi_2_struct_bbr_mat, 'out_matrix_file', ds, 'registration.epi_2_struct_mat') reg_wf.connect(epi_2_struct_bbr_mat, 'out_file', outputnode, 'mean_epi_structSpace') # 5. INVERT to get: STRUCT -> EPI struct_2_epi_mat = Node(fsl.ConvertXFM(invert_xfm=True), name='struct_2_epi_mat') reg_wf.connect(epi_2_struct_bbr_mat, 'out_matrix_file', struct_2_epi_mat, 'in_file') reg_wf.connect(struct_2_epi_mat, 'out_file', outputnode, 'struct_2_epi_mat') # III. COMBINE I. & II.: EPI -> MNI ########################################## # 6. COMBINE MATS: EPI -> MNI epi_2_MNI_warp = Node(fsl.ConvertWarp(), name='epi_2_MNI_warp') epi_2_MNI_warp.inputs.reference = fsl.Info.standard_image( 'MNI152_T1_2mm.nii.gz') reg_wf.connect(epi_2_struct_bbr_mat, 'out_matrix_file', epi_2_MNI_warp, 'premat') # epi2struct reg_wf.connect(struct_2_MNI_warp, 'field_file', epi_2_MNI_warp, 'warp1') # struct2mni reg_wf.connect(epi_2_MNI_warp, 'out_file', outputnode, 'epi_2_MNI_warp') reg_wf.connect(epi_2_MNI_warp, 'out_file', ds, 'registration.epi_2_MNI_warp') # output: out_file # 7. MNI -> EPI MNI_2_epi_warp = Node(fsl.InvWarp(), name='MNI_2_epi_warp') MNI_2_epi_warp.inputs.reference = fsl.Info.standard_image( 'MNI152_T1_2mm.nii.gz') reg_wf.connect(epi_2_MNI_warp, 'out_file', MNI_2_epi_warp, 'warp') reg_wf.connect(inputnode, 'initial_mean_epi_moco', MNI_2_epi_warp, 'reference') reg_wf.connect(MNI_2_epi_warp, 'inverse_warp', outputnode, 'MNI_2_epi_warp') # output: inverse_warp ########################################## # TRANSFORM VOLUMES ########################################## # CREATE STRUCT IN EPI SPACE FOR DEBUGGING struct_epiSpace = Node(fsl.ApplyXfm(), name='struct_epiSpace') struct_epiSpace.inputs.out_file = 'struct_brain_epiSpace.nii.gz' reg_wf.connect(inputnode, 't1w_brain', struct_epiSpace, 'in_file') reg_wf.connect(inputnode, 'initial_mean_epi_moco', struct_epiSpace, 'reference') reg_wf.connect(struct_2_epi_mat, 'out_file', struct_epiSpace, 'in_matrix_file') reg_wf.connect(struct_epiSpace, 'out_file', ds, 'QC.struct_brain_epiSpace') # CREATE EPI IN MNI SPACE mean_epi_MNIspace = Node(fsl.ApplyWarp(), name='mean_epi_MNIspace') mean_epi_MNIspace.inputs.ref_file = fsl.Info.standard_image( 'MNI152_T1_2mm_brain.nii.gz') mean_epi_MNIspace.inputs.out_file = 'mean_epi_MNIspace.nii.gz' reg_wf.connect(inputnode, 'initial_mean_epi_moco', mean_epi_MNIspace, 'in_file') reg_wf.connect(epi_2_MNI_warp, 'out_file', mean_epi_MNIspace, 'field_file') reg_wf.connect(mean_epi_MNIspace, 'out_file', ds, 'registration.mean_epi_MNIspace') reg_wf.connect(mean_epi_MNIspace, 'out_file', outputnode, 'mean_epi_MNIspace') # CREATE MNI IN EPI SPACE FOR DEBUGGING MNI_epiSpace = Node(fsl.ApplyWarp(), name='MNI_epiSpace') MNI_epiSpace.inputs.in_file = fsl.Info.standard_image( 'MNI152_T1_2mm_brain.nii.gz') MNI_epiSpace.inputs.out_file = 'MNI_epiSpace.nii.gz' reg_wf.connect(inputnode, 'initial_mean_epi_moco', MNI_epiSpace, 'ref_file') reg_wf.connect(MNI_2_epi_warp, 'inverse_warp', MNI_epiSpace, 'field_file') reg_wf.connect(MNI_epiSpace, 'out_file', ds, 'registration.MNI_epiSpace') reg_wf.write_graph(dotfilename=reg_wf.name, graph2use='flat', format='pdf') return reg_wf
'config_file') register_flow.connect(reg_inputnode, 'target_image', highres2standard_warp, 'ref_file') register_flow.connect(reg_inputnode, 'target_mask', highres2standard_warp, 'refmask_file') # Combine linear FLIRT transformations into one to create a transformation matrix from functional to target func2standard = Node(fsl.ConvertXFM(concat_xfm=True), name='func2standard_linear') register_flow.connect(func2highres_bbr, 'out_matrix_file', func2standard, 'in_file') register_flow.connect(highres2standard, 'out_matrix_file', func2standard, 'in_file2') # Combine non linear FNIRT transformations into one to create a transformation matrix from functional to target func2standard_warp = Node(fsl.ConvertWarp(), name='example_func2standard_nonlinear') register_flow.connect(reg_inputnode, 'target_image_brain', func2standard_warp, 'reference') register_flow.connect(func2highres_bbr, 'out_matrix_file', func2standard_warp, 'premat') register_flow.connect(highres2standard_warp, 'fieldcoeff_file', func2standard_warp, 'warp1') # Apply nonlinear transform to the reference image. warpmean = Node(fsl.ApplyWarp(interp='trilinear'), name='warpmean') register_flow.connect(extract_ref, 'roi_file', warpmean, 'in_file') register_flow.connect(reg_inputnode, 'target_image_brain', warpmean, 'ref_file') register_flow.connect(func2standard_warp, 'out_file', warpmean, 'field_file')
""" Setup for Tracktography ----------------------- Here we will create a generic workflow for DTI computation, this workflow assumes the .bedpostX has already been run... Here we will create a workflow to enable probabilistic tracktography and hard segmentation of the seed region """ stout_tractography = pe.Workflow(name='stout_tractography') stout_tractography.base_dir = WORKINGDATAPATH ### First connect the subject list to the workflow to build up the patient lists stout_tractography.connect( infosource,'subject_id',dti_datasource, 'subject_id' ) ### GENERATE THE WARP FIELDS cvtwarp_mni_to_dti = pe.Node(interface=fsl.ConvertWarp(),name='cvtwarp_mni_to_dti' ) cvtwarp_mni_to_dti.inputs.reference = os.path.join(RAWDATAPATH,"MNI152_T1_1mm_brain.nii.gz") stout_tractography.connect( dti_datasource, 'nodif_to_struct_aff', cvtwarp_mni_to_dti, 'premat') stout_tractography.connect( dti_datasource, 'struct_warpto_MNI', cvtwarp_mni_to_dti, 'warp1') # $statement .= " --premat=$WORKINGDATAPATH/" . $subj[$i] . "/xfms/nodif_12dof_struc.mat "; # $statement .= " --warp1=$WORKINGDATAPATH/" . $subj[$i] . "/xfms/struc_warp_MNI_warpfield.nii.gz "; # $statement .= " --out=$WORKINGDATAPATH/" . $subj[$i] . "/xfms/nodif_12dof_struc_warp_MNI_warpfield.nii.gz "; cvtwarp_dti_to_mni = pe.Node(interface=fsl.ConvertWarp(),name='cvtwarp_dti_to_mni' ) stout_tractography.connect( dti_datasource, 'nodif_brain_mask', cvtwarp_dti_to_mni, 'reference') stout_tractography.connect( dti_datasource, 'MNI_to_struct', cvtwarp_dti_to_mni, 'warp1') stout_tractography.connect( dti_datasource, 'struct_to_nodif_aff', cvtwarp_dti_to_mni, 'postmat') # $statement .= " --ref=$WORKINGDATAPATH/" . $subj[$i] . "/DTI/data/nodif_brain_mask.nii.gz ";
def generate_workflow(**inputs): """ generates computation graph for daic2hcp :param t1w_file: t1w mgz file in some space :param t2w_file: t2w mgz file aligned to t1w :param mask_file: mask or brain mgz file aligned to t1w :param fmri_files: list of fmri mgz files :param rs_files: list of fc-preprocessed resting state fmri mgz files :param output_dir: desired output "HCP" directory :return: nipype workflow """ # setup variables subject_id = inputs['subjectid'] reference = os.path.join(os.environ['HCPPIPEDIR_Templates'], 'MNI152_T1_1mm.nii.gz') reference2mm = os.path.join(os.environ['HCPPIPEDIR_Templates'], "MNI152_T1_2mm.nii.gz") # io spec input_spec = pe.Node(nipype.IdentityInterface( fields=['t1w_file', 't2w_file', 'mask_file']), name='input_spec' ) input_func_spec = pe.Node(nipype.IdentityInterface(fields=['fmri_file']), name='input_func_spec') hcp_spec = pe.Node(nipype.IdentityInterface( fields=['t1w', 't2w', 't1w_acpc_xfm', 't2w_acpc_xfm', 't2w_to_t1w_xfm', 't1w_distortion', 't2w_distortion', 'bias_field', 't1w_res', 't2w_res', 't2w_dc', 't1w_res_brain', 't2w_res_brain', 'wmparc', 'wmparc_1mm', 'fs2standard', 'standard2fs']), name='hcp_spec' ) # connect input DAIC files input_spec.inputs.t1w_file = inputs['t1w_file'] input_spec.inputs.t2w_file = inputs['t2w_file'] input_spec.inputs.mask_file = inputs['mask_file'] input_func_spec.iterables = ('fmri_file', inputs['fmri_files'] + inputs[ 'rs_files']) # setup HCP directory specification output_dir = os.path.abspath(inputs['output_dir']) subjects_dir = os.path.join(output_dir, 'T1w') freesurfer_dir = os.path.join(subjects_dir, subject_id) native_xfms_dir = os.path.join(subjects_dir, 'xfms') t2w_dir = os.path.join(output_dir, 'T2w') t2w_xfms_dir = os.path.join(t2w_dir, 'xfms') nonlinear_dir = os.path.join(output_dir, 'MNINonLinear') results_dir = os.path.join(nonlinear_dir, 'Results') nonlin_xfms_dir = os.path.join(nonlinear_dir, 'xfms') fs_transforms = os.path.join(freesurfer_dir, 'mri', 'transforms') # create directory tree for directory in [output_dir, subjects_dir, native_xfms_dir, t2w_dir, t2w_xfms_dir, results_dir, nonlin_xfms_dir]: os.makedirs(directory, exist_ok=True) if not os.path.isdir(freesurfer_dir): shutil.copytree(inputs['fs_source_dir'], freesurfer_dir) os.makedirs(fs_transforms, exist_ok=True) def get_name(x): boldid = re.compile(r'(BOLD[0-9]*).*') number = re.compile(r'rsBOLD_data_scan([0-9]*).*') basename = os.path.basename(x).split('.')[0] match = boldid.match(basename) if match is not None: name = match.groups()[0] else: name = 'fcproc%s' % number.match(basename).groups()[0] taskname = 'task-%s' % name return taskname fmrinames = map(get_name, inputs['fmri_files'] + inputs['rs_files']) for fmriname in fmrinames: directory = os.path.join(results_dir, fmriname) os.makedirs(directory, exist_ok=True) # HCP filename specification hcp_spec.inputs.t1w = os.path.join(subjects_dir, 'T1w.nii.gz') hcp_spec.inputs.t2w = os.path.join(t2w_dir, 'T2w.nii.gz') hcp_spec.inputs.t1w_acpc_xfm = os.path.join(native_xfms_dir, 'acpc.mat') hcp_spec.inputs.t2w_acpc_xfm = os.path.join(t2w_xfms_dir, 'acpc.mat') hcp_spec.inputs.t2w_to_t1w_xfm = os.path.join(fs_transforms, 'T2wtoT1w.mat') hcp_spec.inputs.t1w_distortion = os.path.join( native_xfms_dir, 'T1w_dc.nii.gz') hcp_spec.inputs.t2w_distortion = os.path.join( native_xfms_dir, 'T2w_reg_dc.nii.gz') hcp_spec.inputs.bias_field = os.path.join( subjects_dir, 'BiasField_acpc_dc.nii.gz') hcp_spec.inputs.t1w_res = os.path.join( subjects_dir, 'T1w_acpc_dc_restore.nii.gz') hcp_spec.inputs.t1w_res_brain = os.path.join( subjects_dir, 'T1w_acpc_dc_restore_brain.nii.gz') hcp_spec.inputs.t2w_res = os.path.join( subjects_dir, 'T2w_acpc_dc_restore.nii.gz') hcp_spec.inputs.t2w_dc = os.path.join( subjects_dir, 'T2w_acpc_dc.nii.gz') hcp_spec.inputs.t2w_res_brain = os.path.join( subjects_dir, 'T2w_acpc_dc_restore_brain.nii.gz') hcp_spec.inputs.wmparc = os.path.join(subjects_dir, 'wmparc.nii.gz') hcp_spec.inputs.wmparc_1mm = os.path.join(subjects_dir, 'wmparc_1mm.nii.gz') hcp_spec.inputs.warp = os.path.join(nonlin_xfms_dir, 'fs2standard.nii.gz') ## create workflow components # utility def rename_func(in_file, path): # conditional renaming for func, fcpreproc data handled separately import os import re import shutil func_pattern = re.compile(r'(?P<name>BOLD[0-9]*).*') fc_pattern = re.compile(r'rsBOLD_data_scan(?P<number>[0-9]*).*') basename = os.path.basename(in_file) name = func_pattern.match(basename) number = fc_pattern.match(basename) if name: taskname = 'task-%s' % name.groupdict()['name'] elif number: taskname = 'task-fcproc%s' % number.groupdict()['number'] out_file = os.path.join(path, 'MNINonLinear', 'Results', taskname, taskname + '.nii.gz') shutil.copyfile(in_file, out_file) return out_file rename = pe.Node(utility.Function(input_names=['in_file', 'path'], output_names=['out_file'], function=rename_func), name='rename') rename.inputs.path = os.path.abspath(output_dir) copy_str = 'def f(src, dest): shutil.copy(src, dest); return dest' copy = pe.Node( utility.Function( input_names=['src', 'dest'], output_names=['dest'], imports=['import shutil'], function_str=copy_str ), name='copy' ) basename_str = 'def f(path): return osp.basename(path).split(".")[0]' basename = pe.Node( utility.Function( input_names=['path'], output_names=['out_name'], imports=['import os.path as osp'], function_str=basename_str ), name='basename' ) # mri convert convert_t1 = pe.Node(freesurfer.MRIConvert(out_type='niigz'), name='convert_t1') convert_t2 = convert_t1.clone(name='convert_t2') convert_mask = convert_t1.clone(name='convert_mask') convert_func = pe.Node(freesurfer.MRIConvert(out_type='niigz'), name='convert_func') # acpc alignment calc_acpc = pe.Node( fsl.FLIRT(reference=reference, dof=6, interp='spline'), name='calc_acpc' ) copy_xfm = copy.clone(name='copy_xfm') apply_acpc = pe.Node( fsl.FLIRT(reference=reference, apply_xfm=True, interp='spline'), name='apply_acpc' ) copy_t2w_res = copy.clone(name='copy_t2w_res') apply_acpc_nn = pe.Node( fsl.FLIRT(reference=reference, apply_xfm=True, interp='nearestneighbour'), name='apply_acpc_nn' ) mask_t1w = pe.Node(fsl.ApplyMask(), name='mask_t1w') mask_t2w = pe.Node(fsl.ApplyMask(), name='mask_t2w') resample_mask = pe.Node( fsl.FLIRT(apply_isoxfm=1, interp='nearestneighbour'), name='resample_mask' ) # functional transforms select_first = pe.JoinNode( utility.Select(index=[0]), joinsource='input_func_spec', joinfield='inlist', name='select_first' ) fs_to_fmri = pe.Node(fsl.FLIRT(cost='mutualinfo', dof=6), name='fs_to_func') fmri_to_fs = pe.Node(fsl.ConvertXFM(invert_xfm=True), name='func_to_fs') concat_warps = pe.Node( fsl.ConvertWarp(relwarp=True, out_relwarp=True, reference=reference2mm), name='concat_warps' ) warp_mask = pe.Node( fsl.ApplyWarp(ref_file=reference2mm, interp='nn', relwarp=True), name='warp_mask' ) mask_func = pe.Node(fsl.ApplyMask(), name='apply_mask') apply_warpfield = pe.Node( fsl.ApplyWarp(ref_file=reference2mm, interp='spline', relwarp=True), name='apply_warpfield' ) timeseries_mean = pe.Node( fsl.MeanImage(dimension='T'), name='timeseries_mean' ) renamesb = pe.Node( utility.Rename(parse_string=r'task-(?P<name>.*)_.*', format_string='%(path)s/MNINonLinear/Results/' 'task-%(name)s/task-%(name)s_SBRef.nii.gz', path=os.path.abspath(output_dir)), name='renamesb' ) renamesb.inputs.path = os.path.abspath(output_dir) # identity transforms identity_matrix = pe.Node(fsl.preprocess.FLIRT(), name='identity_matrix') # t1 -> t1 matrix zeroes = pe.Node(fsl.BinaryMaths(operation='mul', operand_value=0), name='zeroes') repeat_zeroes = pe.Node(utility.Merge(3), name='repeat_zeroes') identity_warpfield = pe.Node(fsl.Merge(dimension='t'), name='identity_warpfield') # 3D warp in t-dim identity_biasfield = pe.Node(fsl.BinaryMaths(operation='add', operand_value=1), name='identity_biasfield') # bias 1 everywhere copy_warpfield = copy.clone(name='copy_warpfield') # hcp nodes postfreesurfer, fmrisurface = create_hcp_nodes(output_dir, subject_id) executivesummary = pe.JoinNode( ExecutiveSummary(in_unprocessed=os.path.abspath(output_dir), in_processed=os.path.abspath(output_dir), in_subjectid=subject_id, in_executivesummary='executivesummary'), joinfield='in_files', joinsource='input_func_spec', name='executivesummary' ) ## workflow DAG wf = pe.Workflow(name=inputs['workflow_name'], base_dir=inputs['base_dir']) # convert to nii.gz wf.connect( [(input_spec, convert_t1, [('t1w_file', 'in_file')]), (input_spec, convert_t2, [('t2w_file', 'in_file')]), (input_spec, convert_mask, [('mask_file', 'in_file')])] ) # rigid align to acpc/MNI, apply mask wf.connect( [(convert_t1, calc_acpc, [('out_file', 'in_file')]), (calc_acpc, copy_xfm, [('out_matrix_file', 'src')]), (copy_xfm, apply_acpc, [('dest', 'in_matrix_file')]), (calc_acpc, apply_acpc_nn, [('out_matrix_file', 'in_matrix_file')]), (convert_t2, apply_acpc, [('out_file', 'in_file')]), (apply_acpc, copy_t2w_res, [('out_file', 'src')]), (convert_mask, apply_acpc_nn, [('out_file', 'in_file')]), (calc_acpc, mask_t1w, [('out_file', 'in_file')]), (apply_acpc_nn, mask_t1w, [('out_file', 'mask_file')]), (apply_acpc, mask_t2w, [('out_file', 'in_file')]), (apply_acpc_nn, mask_t2w, [('out_file', 'mask_file')]), (apply_acpc_nn, resample_mask, [('out_file', 'in_file'), ('out_file', 'reference')])] ) # create identity transformations for data flow wf.connect( [(calc_acpc, identity_matrix, [('out_file', 'in_file'), ('out_file', 'reference')]), (calc_acpc, zeroes, [('out_file', 'in_file')]), (zeroes, repeat_zeroes, [('out_file', 'in1'), ('out_file', 'in2'), ('out_file', 'in3')]), (repeat_zeroes, identity_warpfield, [('out', 'in_files')]), (zeroes, identity_biasfield, [('out_file', 'in_file')]), (identity_warpfield, copy_warpfield, [('merged_file', 'src')])] ) # connect postfreesurfer # there are more implicit connections, but these suffice dependency graph wf.connect( [(calc_acpc, postfreesurfer, [('out_file', 'in_t1')]), (copy_t2w_res, postfreesurfer, [('dest', 'in_t1_dc')]), (identity_warpfield, postfreesurfer, [('merged_file', 'in_warpfield')]), (identity_biasfield, postfreesurfer, [('out_file', 'in_biasfield')]), (copy_warpfield, postfreesurfer, [('dest', 'in_t2warpfield')]), (resample_mask, postfreesurfer, [('out_file', 'in_wmparc')]), (mask_t1w, postfreesurfer, [('out_file', 'in_t1brain')]), (mask_t2w, postfreesurfer, [('out_file', 'in_t2brain')]), (identity_matrix, postfreesurfer, [('out_file', 'in_t2_to_t1')])] ) # transform functionals to final space # @TODO leverage SELECT and RENAME utilities with Don's information. In # the interim, functional data is simply named as task-BOLD## wf.connect( [(input_func_spec, convert_func, [('fmri_file', 'in_file')]), (convert_func, select_first, [('out_file', 'inlist')]), (convert_t1, fs_to_fmri, [('out_file', 'in_file')]), (select_first, fs_to_fmri, [('out', 'reference')]), (fs_to_fmri, fmri_to_fs, [('out_matrix_file', 'in_file')]), (postfreesurfer, concat_warps, [('out_warp', 'warp1')]), (fmri_to_fs, concat_warps, [('out_file', 'premat')]), (concat_warps, apply_warpfield, [('out_file', 'field_file')]), (convert_func, apply_warpfield, [('out_file', 'in_file')]), (convert_mask, warp_mask, [('out_file', 'in_file')]), (postfreesurfer, warp_mask, [('out_warp', 'field_file')]), (warp_mask, mask_func, [('out_file', 'mask_file')]), (apply_warpfield, mask_func, [('out_file', 'in_file')])] ) # connect fmrisurface # there are more implicit connections, but these suffice dependency graph wf.connect( [(mask_func, rename, [('out_file', 'in_file')]), (rename, timeseries_mean, [('out_file', 'in_file')]), (rename, fmrisurface, [('out_file', 'in_fmri')]), (rename, basename, [('out_file', 'path')]), (basename, fmrisurface, [('out_name', 'fmriname')]), (timeseries_mean, renamesb, [('out_file', 'in_file')]), (renamesb, fmrisurface, [('out_file', 'in_sbref')])] ) # connect executivesummary wf.connect( [(fmrisurface, executivesummary, [('out_file', 'in_files')])] ) # draw workflow: output/daic2hcp/graph.png wf.write_graph(graph2use='orig', dotfilename='graph.dot') # connect intermediates to hcp filename specifications (not shown in graph) wf.connect( [(hcp_spec, convert_t1, [('t1w', 'out_file')]), (hcp_spec, convert_t2, [('t2w', 'out_file')]), (hcp_spec, convert_mask, [('wmparc', 'out_file')]), (hcp_spec, calc_acpc, [('t1w_acpc_xfm', 'out_matrix_file')]), (hcp_spec, identity_matrix, [('t2w_to_t1w_xfm', 'out_matrix_file')]), (hcp_spec, identity_warpfield, [('t1w_distortion', 'merged_file')]), (hcp_spec, identity_biasfield, [('bias_field', 'out_file')]), (hcp_spec, copy_warpfield, [('t2w_distortion', 'dest')]), (hcp_spec, calc_acpc, [('t1w_res', 'out_file')]), (hcp_spec, apply_acpc, [('t2w_res', 'out_file')]), (hcp_spec, copy_xfm, [('t2w_acpc_xfm', 'dest')]), (hcp_spec, copy_t2w_res, [('t2w_dc', 'dest')]), (hcp_spec, mask_t1w, [('t1w_res_brain', 'out_file')]), (hcp_spec, mask_t2w, [('t2w_res_brain', 'out_file')]), (hcp_spec, resample_mask, [('wmparc_1mm', 'out_file')]), (hcp_spec, concat_warps, [('warp', 'out_file')])] ) return wf