def remove_bias(name='bias_correct'): """ This workflow estimates a single multiplicative bias field from the averaged *b0* image, as suggested in [Jeurissen2014]_. .. admonition:: References .. [Jeurissen2014] Jeurissen B. et al., `Multi-tissue constrained spherical deconvolution for improved analysis of multi-shell diffusion MRI data <https://doi.org/10.1016/j.neuroimage.2014.07.061>`_. NeuroImage (2014). doi: 10.1016/j.neuroimage.2014.07.061 Example ------- >>> from nipype.workflows.dmri.fsl.artifacts import remove_bias >>> bias = remove_bias() >>> bias.inputs.inputnode.in_file = 'epi.nii' >>> bias.inputs.inputnode.in_bval = 'diffusion.bval' >>> bias.inputs.inputnode.in_mask = 'mask.nii' >>> bias.run() # doctest: +SKIP """ inputnode = pe.Node( niu.IdentityInterface(fields=['in_file', 'in_bval', 'in_mask']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface(fields=['out_file']), name='outputnode') avg_b0 = pe.Node(niu.Function(input_names=['in_dwi', 'in_bval'], output_names=['out_file'], function=b0_average), name='b0_avg') n4 = pe.Node(ants.N4BiasFieldCorrection(dimension=3, save_bias=True, bspline_fitting_distance=600), name='Bias_b0') split = pe.Node(fsl.Split(dimension='t'), name='SplitDWIs') mult = pe.MapNode(fsl.MultiImageMaths(op_string='-div %s'), iterfield=['in_file'], name='RemoveBiasOfDWIs') thres = pe.MapNode(fsl.Threshold(thresh=0.0), iterfield=['in_file'], name='RemoveNegative') merge = pe.Node(fsl.utils.Merge(dimension='t'), name='MergeDWIs') wf = pe.Workflow(name=name) wf.connect([(inputnode, avg_b0, [('in_file', 'in_dwi'), ('in_bval', 'in_bval')]), (avg_b0, n4, [('out_file', 'input_image')]), (inputnode, n4, [('in_mask', 'mask_image')]), (inputnode, split, [('in_file', 'in_file')]), (n4, mult, [('bias_image', 'operand_files')]), (split, mult, [('out_files', 'in_file')]), (mult, thres, [('out_file', 'in_file')]), (thres, merge, [('out_file', 'in_files')]), (merge, outputnode, [('merged_file', 'out_file')])]) return wf
def get_wm_seg_from_nighres(dseg_l, dseg_r): from nipype.interfaces import fsl import nipype.interfaces.utility as util import nipype.pipeline.engine as pe wf = pe.Workflow(name='get_wm_seg') inputspec = pe.Node(util.IdentityInterface(fields=['dseg_l', 'dseg_r']), name='inputspec') inputspec.inputs.dseg_l = dseg_l inputspec.inputs.dseg_r = dseg_r add = pe.Node(fsl.BinaryMaths(operation='add'), name='add') wf.connect(inputspec, 'dseg_l', add, 'in_file') wf.connect(inputspec, 'dseg_r', add, 'operand_file') get_wm = pe.Node(fsl.Threshold(thresh=2, args='-bin'), name='get_wm') outputspec = pe.Node(util.IdentityInterface(fields=['wm_seg']), name='outputspec') wf.connect(add, 'out_file', get_wm, 'in_file') wf.connect(get_wm, 'out_file', outputspec, 'wm_seg') return wf
def build_nodes(self): # BET - Skullstrip anatomical Image self.bet_anat = Node(fsl.BET(frac=0.5, robust=True, output_type='NIFTI_GZ'), name="bet_anat") # image segmentation self.segmentation = Node(fsl.FAST(output_type='NIFTI_GZ'), name='segmentation') # threshold WM probability image self.threshold = Node(fsl.Threshold(thresh=0.5, args='-bin', output_type='NIFTI_GZ'), name='threshold') # flirt - pre-alignment of images self.coreg_pre = Node(fsl.FLIRT(dof=6, output_type='NIFTI_GZ'), name='coreg_pre') # co-reg self.coreg_mi = Node(fsl.FLIRT(bins=640, cost_func='bbr', interp='spline', searchr_x=[-180, 180], searchr_y=[-180, 180], searchr_z=[-180, 180], dof=6, output_type='NIFTI_GZ'), name='coreg_mi') # apply warp map to images self.applywarp = Node(fsl.preprocess.ApplyXFM(apply_xfm=True, output_type='NIFTI_GZ'), name='applywarp') # Apply coregistration warp to mean file self.applywarp_mean = Node(fsl.FLIRT(interp='spline',output_type='NIFTI_GZ'), name="applywarp_mean")
def getMask(input_file,threshold): threshold = threshold/10 output_file = os.path.join(os.path.dirname(input_file), 'mask.nii.gz') thres = fsl.Threshold(in_file=input_file,thresh=threshold,out_file=output_file,output_datatype='char',args='-Tmin -bin') print(thres.cmdline) thres.run() return output_file
def thresh(input_file,outputPath): #output_file = os.path.join(os.path.dirname(input_file),os.path.basename(input_file).split('.')[0]+ 'Thres.nii.gz') output_file = os.path.join(outputPath, os.path.basename(input_file).split('.')[0] + 'Thres.nii.gz') myThres = fsl.Threshold(in_file=input_file,out_file=output_file,thresh=20)#,direction='above') myThres.run() print('Thresholding DONE!') return output_file
def filterFSL(input_file, highpass, tempMean): outputSFRGR = os.path.join( os.path.dirname(input_file), os.path.basename(input_file).split('SRGR')[0]) + 'SFRGR.nii.gz' myHP = fsl.TemporalFilter(in_file=input_file, highpass_sigma=highpass, args='-add ' + tempMean, out_file=outputSFRGR) print(myHP.cmdline) myHP.run() input_file = outputSFRGR output_file = os.path.join( os.path.dirname(input_file), os.path.basename(input_file).split('.')[0]) + '_thres_mask.nii.gz' #input_file = getMean(input_file,'HPmean') thres = fsl.Threshold(in_file=input_file, thresh=17, out_file=output_file, output_datatype='float', use_robust_range=True, args='-Tmean -bin') print(thres.cmdline) thres.run() return outputSFRGR
def skullstrip_wf(name='SkullStripWorkflow'): """ Skull-stripping workflow """ workflow = pe.Workflow(name=name) inputnode = pe.Node(niu.IdentityInterface(fields=['in_file']), name='inputnode') outputnode = pe.Node( niu.IdentityInterface(fields=['out_file', 'out_mask', 'head_mask']), name='outputnode') sstrip = pe.Node(afp.SkullStrip(outputtype='NIFTI_GZ'), name='skullstrip') sstrip_orig_vol = pe.Node(afp.Calc(expr='a*step(b)', outputtype='NIFTI_GZ'), name='sstrip_orig_vol') binarize = pe.Node(fsl.Threshold(args='-bin', thresh=1.e-3), name='binarize') workflow.connect([(inputnode, sstrip, [('in_file', 'in_file')]), (inputnode, sstrip_orig_vol, [('in_file', 'in_file_a')]), (sstrip, sstrip_orig_vol, [('out_file', 'in_file_b')]), (sstrip_orig_vol, binarize, [('out_file', 'in_file')]), (sstrip_orig_vol, outputnode, [('out_file', 'out_file') ]), (binarize, outputnode, [('out_file', 'out_mask')])]) return workflow
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 dwi_flirt(name='DWICoregistration', excl_nodiff=False, flirt_param={}): """ Generates a workflow for linear registration of dwi volumes """ inputnode = pe.Node(niu.IdentityInterface(fields=['reference', 'in_file', 'ref_mask', 'in_xfms', 'in_bval']), name='inputnode') initmat = pe.Node(niu.Function(input_names=['in_bval', 'in_xfms', 'excl_nodiff'], output_names=['init_xfms'], function=_checkinitxfm), name='InitXforms') initmat.inputs.excl_nodiff = excl_nodiff dilate = pe.Node(fsl.maths.MathsCommand(nan2zeros=True, args='-kernel sphere 5 -dilM'), name='MskDilate') split = pe.Node(fsl.Split(dimension='t'), name='SplitDWIs') pick_ref = pe.Node(niu.Select(), name='Pick_b0') n4 = pe.Node(ants.N4BiasFieldCorrection(dimension=3), name='Bias') enhb0 = pe.Node(niu.Function(input_names=['in_file', 'in_mask', 'clip_limit'], output_names=['out_file'], function=enhance), name='B0Equalize') enhb0.inputs.clip_limit = 0.015 enhdw = pe.MapNode(niu.Function(input_names=['in_file', 'in_mask'], output_names=['out_file'], function=enhance), name='DWEqualize', iterfield=['in_file']) flirt = pe.MapNode(fsl.FLIRT(**flirt_param), name='CoRegistration', iterfield=['in_file', 'in_matrix_file']) 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=['out_file', 'out_xfms']), name='outputnode') wf = pe.Workflow(name=name) wf.connect([ (inputnode, split, [('in_file', 'in_file')]), (inputnode, dilate, [('ref_mask', 'in_file')]), (inputnode, enhb0, [('ref_mask', 'in_mask')]), (inputnode, initmat, [('in_xfms', 'in_xfms'), ('in_bval', 'in_bval')]), (inputnode, n4, [('reference', 'input_image'), ('ref_mask', 'mask_image')]), (dilate, flirt, [('out_file', 'ref_weight'), ('out_file', 'in_weight')]), (n4, enhb0, [('output_image', 'in_file')]), (split, enhdw, [('out_files', 'in_file')]), (dilate, enhdw, [('out_file', 'in_mask')]), (enhb0, flirt, [('out_file', 'reference')]), (enhdw, flirt, [('out_file', 'in_file')]), (initmat, flirt, [('init_xfms', 'in_matrix_file')]), (flirt, thres, [('out_file', 'in_file')]), (thres, merge, [('out_file', 'in_files')]), (merge, outputnode, [('merged_file', 'out_file')]), (flirt, outputnode, [('out_matrix_file', 'out_xfms')]) ]) return wf
def __init__(self, name, base_dir=None): super(BrainExtractionWorkflow, self).__init__(name, base_dir) # Segmentation # ============ seg_node = npe.MapNode(name="Segmentation", iterfield="data", interface=spm.Segment()) seg_node.inputs.gm_output_type = [False, False, True] seg_node.inputs.wm_output_type = [False, False, True] seg_node.inputs.csf_output_type = [False, False, True] add1_node = npe.MapNode(name="AddGMWM", iterfield=["in_file", "operand_file"], interface=fsl.BinaryMaths()) add1_node.inputs.operation = 'add' add2_node = npe.MapNode(name="AddGMWMCSF", iterfield=["in_file", "operand_file"], interface=fsl.BinaryMaths()) add2_node.inputs.operation = 'add' dil_node = npe.MapNode(name="Dilate", iterfield="in_file", interface=fsl.DilateImage()) dil_node.inputs.operation = 'mean' ero_node = npe.MapNode(name="Erode", iterfield="in_file", interface=fsl.ErodeImage()) thre_node = npe.MapNode(name="Threshold", iterfield="in_file", interface=fsl.Threshold()) thre_node.inputs.thresh = 0.5 fill_node = npe.MapNode(name="Fill", iterfield="in_file", interface=fsl.UnaryMaths()) fill_node.inputs.operation = 'fillh' mask_node = npe.MapNode(name="ApplyMask", iterfield=["in_file", "mask_file"], interface=fsl.ApplyMask()) mask_node.inputs.output_type = str("NIFTI") self.connect([ (seg_node, add1_node, [('native_gm_image', 'in_file')]), (seg_node, add1_node, [('native_wm_image', 'operand_file')]), (seg_node, add2_node, [('native_csf_image', 'in_file')]), (add1_node, add2_node, [('out_file', 'operand_file')]), (add2_node, dil_node, [('out_file', 'in_file')]), (dil_node, ero_node, [('out_file', 'in_file')]), (ero_node, thre_node, [('out_file', 'in_file')]), (thre_node, fill_node, [('out_file', 'in_file')]), (fill_node, mask_node, [('out_file', 'mask_file')]), ])
def compcorr(name='compcorr'): from nipype.workflows.rsfmri.fsl.resting import extract_noise_components from nipype.algorithms.misc import TSNR wkfl = pe.Workflow(name=name) inputnode = pe.Node(utility.IdentityInterface( fields=['in_file', 'mask', 'num_components']), name='inputspec') outputnode = pe.Node(utility.IdentityInterface(fields=['corrected_file']), name='outputspec') tsnr = pe.Node(TSNR(), name='tsnr') getthresh = pe.Node(interface=fsl.ImageStats(op_string='-k %s -p 98'), name='getthreshold') threshold_stddev = pe.Node(fsl.Threshold(), name='threshold') compcor = pe.Node( utility.Function(input_names=[ 'realigned_file', 'noise_mask_file', 'num_components' ], output_names=['noise_components'], function=extract_noise_components), name='compcorr', ) remove_noise = pe.Node( fsl.FilterRegressor(filter_all=True), name='remove_noise', ) wkfl.connect([ (inputnode, tsnr, [('in_file', 'in_file')]), (inputnode, compcor, [('in_file', 'realigned_file'), ('num_components', 'num_components')]), (tsnr, threshold_stddev, [('stddev_file', 'in_file')]), (tsnr, getthresh, [('stddev_file', 'in_file')]), (inputnode, getthresh, [('mask', 'mask_file')]), (inputnode, remove_noise, [('in_file', 'in_file')]), (getthresh, threshold_stddev, [('out_stat', 'thresh')]), (threshold_stddev, compcor, [('out_file', 'noise_mask_file')]), (compcor, remove_noise, [('noise_components', 'design_file')]), (inputnode, remove_noise, [('mask', 'mask')]), (remove_noise, outputnode, [('out_file', 'corrected_file')]), ]) return wkfl
def t_compcor(wf_name="t_compcor"): cc = pe.Workflow(name=wf_name) # Define nodes inputnode = pe.Node(interface=util.IdentityInterface( fields=['func', 'num_noise_components']), name='inputspec') outputnode = pe.Node(interface=util.IdentityInterface( fields=['noise_mask_file', 'noise_components', 'residual_file']), name='outputspec') tsnr = pe.MapNode(TSNR(regress_poly=2), name='tsnr', iterfield=['in_file']) getthresh = pe.MapNode(interface=fsl.ImageStats(op_string='-p 98'), name='getthreshold', iterfield=['in_file']) threshold_stddev = pe.MapNode(fsl.Threshold(), name='threshold', iterfield=['in_file', 'thresh']) compcor = pe.MapNode(util.Function( input_names=['realigned_file', 'noise_mask_file', 'num_components'], output_names=['noise_components'], function=extract_noise_components), name='compcorr', iterfield=['realigned_file', 'noise_mask_file']) remove_noise = pe.MapNode(fsl.FilterRegressor(filter_all=True), name='remove_noise', iterfield=['in_file', 'design_file']) cc.connect(inputnode, 'func', tsnr, 'in_file') cc.connect(tsnr, 'stddev_file', threshold_stddev, 'in_file') cc.connect(tsnr, 'stddev_file', getthresh, 'in_file') cc.connect(getthresh, 'out_stat', threshold_stddev, 'thresh') cc.connect(inputnode, 'func', compcor, 'realigned_file') cc.connect(threshold_stddev, 'out_file', compcor, 'noise_mask_file') cc.connect(inputnode, 'num_noise_components', compcor, 'num_components') cc.connect(tsnr, 'detrended_file', remove_noise, 'in_file') cc.connect(compcor, 'noise_components', remove_noise, 'design_file') cc.connect(compcor, 'noise_components', outputnode, 'noise_components') cc.connect(remove_noise, 'out_file', outputnode, 'residual_file') cc.connect(threshold_stddev, 'out_file', outputnode, 'noise_mask_file') return cc
def get_wm_seg_from_fmriprep_wf(dtissue): from nipype.interfaces import fsl import nipype.interfaces.utility as util import nipype.pipeline.engine as pe wf = pe.Workflow(name='get_wm_seg') inputspec = pe.Node(util.IdentityInterface(fields=['fmriprep_dtissue']), name='inputspec') inputspec.inputs.fmriprep_dtissue = dtissue get_wm = pe.Node(fsl.Threshold(thresh=3, args='-bin'), name='get_wm') outputspec = pe.Node(util.IdentityInterface(fields=['wm_seg']), name='outputspec') wf.connect(inputspec, 'fmriprep_dtissue', get_wm, 'in_file') wf.connect(get_wm, 'out_file', outputspec, 'wm_seg') return wf
def afni_wf(name='AFNISkullStripWorkflow'): """ Skull-stripping workflow Derived from the codebase of the QAP: https://github.com/preprocessed-connectomes-project/\ quality-assessment-protocol/blob/master/qap/anatomical_preproc.py#L105 """ workflow = pe.Workflow(name=name) inputnode = pe.Node(niu.IdentityInterface(fields=['in_file']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface( fields=['bias_corrected', 'out_file', 'out_mask', 'bias_image']), name='outputnode') inu_n4 = pe.Node(ants.N4BiasFieldCorrection(dimension=3, save_bias=True), name='CorrectINU') sstrip = pe.Node(afni.SkullStrip(outputtype='NIFTI_GZ'), name='skullstrip') sstrip_orig_vol = pe.Node(afni.Calc(expr='a*step(b)', outputtype='NIFTI_GZ'), name='sstrip_orig_vol') binarize = pe.Node(fsl.Threshold(args='-bin', thresh=1.e-3), name='binarize') workflow.connect([(inputnode, sstrip_orig_vol, [('in_file', 'in_file_a')]), (inputnode, inu_n4, [('in_file', 'input_image')]), (inu_n4, sstrip, [('output_image', 'in_file')]), (sstrip, sstrip_orig_vol, [('out_file', 'in_file_b')]), (sstrip_orig_vol, binarize, [('out_file', 'in_file')]), (sstrip_orig_vol, outputnode, [('out_file', 'out_file') ]), (binarize, outputnode, [('out_file', 'out_mask')]), (inu_n4, outputnode, [('output_image', 'bias_corrected'), ('bias_image', 'bias_image')])]) return workflow
def legacy( bids_base, template, debug=False, functional_blur_xy=False, functional_match={}, keep_work=False, n_jobs=False, n_jobs_percentage=0.8, out_base=None, realign="time", registration_mask=False, sessions=[], structural_match={}, subjects=[], tr=1, workflow_name='legacy', enforce_dummy_scans=DUMMY_SCANS, exclude={}, ): ''' Legacy realignment and registration workflow representative of the tweaks and workarounds commonly used in the pre-SAMRI period. Parameters ---------- bids_base : str Path to the BIDS data set root. template : str Path to the template to register the data to. debug : bool, optional Whether to enable nipype debug mode. This increases logging. exclude : dict A dictionary with any combination of "sessions", "subjects", "tasks" as keys and corresponding identifiers as values. If this is specified matching entries will be excluded in the analysis. functional_blur_xy : float, optional Factor by which to smooth data in the xy-plane; if parameter evaluates to false, no smoothing will be applied. Ideally this value should correspond to the resolution or smoothness in the z-direction (assuing z represents the lower-resolution slice-encoding direction). functional_match : dict, optional Dictionary specifying a whitelist to use for functional data inclusion into the workflow; if dictionary is empty no whitelist is present and all data will be considered. The dictionary should have keys which are 'acquisition', 'task', or 'modality', and values which are lists of acceptable strings for the respective BIDS field. keep_work : bool, str Whether to keep the work directory after workflow conclusion (this directory contains all the intermediary processing commands, inputs, and outputs --- it is invaluable for debugging but many times larger in size than the actual output). n_jobs : int, optional Number of processors to maximally use for the workflow; if unspecified a best guess will be estimate based on `n_jobs_percentage` and hardware (but not on current load). n_jobs_percentage : float, optional Percentage of available processors (as in available hardware, not available free load) to maximally use for the workflow (this is overriden by `n_jobs`). out_base : str, optional Output base directory - inside which a directory named `workflow_name` (as well as associated directories) will be created. realign : {"space","time","spacetime",""}, optional Parameter that dictates slictiming correction and realignment of slices. "time" (FSL.SliceTimer) is default, since it works safely. Use others only with caution! registration_mask : str, optional Mask to use for the registration process. This mask will constrain the area for similarity metric evaluation, but the data will not be cropped. sessions : list, optional A whitelist of sessions to include in the workflow, if the list is empty there is no whitelist and all sessions will be considered. structural_match : dict, optional Dictionary specifying a whitelist to use for structural data inclusion into the workflow; if dictionary is empty no whitelist is present and all data will be considered. The dictionary should have keys which are 'acquisition', or 'modality', and values which are lists of acceptable strings for the respective BIDS field. subjects : list, optional A whitelist of subjects to include in the workflow, if the list is empty there is no whitelist and all sessions will be considered. tr : float, optional Repetition time, explicitly. WARNING! This is a parameter waiting for deprecation. workflow_name : str, optional Top level name for the output directory. ''' try: import nipype.interfaces.ants.legacy as antslegacy except ModuleNotFoundError: print(''' The `nipype.interfaces.ants.legacy` was not found on this system. You may want to downgrade nipype to e.g. 1.1.1, as this module has been removed in more recent versions: https://github.com/nipy/nipype/issues/3197 ''') bids_base, out_base, out_dir, template, registration_mask, data_selection, functional_scan_types, structural_scan_types, subjects_sessions, func_ind, struct_ind = common_select( bids_base, out_base, workflow_name, template, registration_mask, functional_match, structural_match, subjects, sessions, exclude, ) if not n_jobs: n_jobs = max(int(round(mp.cpu_count() * n_jobs_percentage)), 2) get_f_scan = pe.Node(name='get_f_scan', interface=util.Function( function=get_bids_scan, input_names=inspect.getargspec(get_bids_scan)[0], output_names=[ 'scan_path', 'scan_type', 'task', 'nii_path', 'nii_name', 'events_name', 'subject_session', 'metadata_filename', 'dict_slice', 'ind_type' ])) get_f_scan.inputs.ignore_exception = True get_f_scan.inputs.data_selection = data_selection get_f_scan.inputs.bids_base = bids_base get_f_scan.iterables = ("ind_type", func_ind) dummy_scans = pe.Node( name='dummy_scans', interface=util.Function( function=force_dummy_scans, input_names=inspect.getargspec(force_dummy_scans)[0], output_names=['out_file', 'deleted_scans'])) dummy_scans.inputs.desired_dummy_scans = enforce_dummy_scans events_file = pe.Node( name='events_file', interface=util.Function( function=write_bids_events_file, input_names=inspect.getargspec(write_bids_events_file)[0], output_names=['out_file'])) temporal_mean = pe.Node(interface=fsl.MeanImage(), name="temporal_mean") f_resize = pe.Node(interface=VoxelResize(), name="f_resize") f_resize.inputs.resize_factors = [10, 10, 10] f_percentile = pe.Node(interface=fsl.ImageStats(), name="f_percentile") f_percentile.inputs.op_string = '-p 98' f_threshold = pe.Node(interface=fsl.Threshold(), name="f_threshold") f_fast = pe.Node(interface=fsl.FAST(), name="f_fast") f_fast.inputs.no_pve = True f_fast.inputs.output_biascorrected = True f_bet = pe.Node(interface=fsl.BET(), name="f_BET") f_swapdim = pe.Node(interface=fsl.SwapDimensions(), name="f_swapdim") f_swapdim.inputs.new_dims = ('x', '-z', '-y') f_deleteorient = pe.Node(interface=FSLOrient(), name="f_deleteorient") f_deleteorient.inputs.main_option = 'deleteorient' datasink = pe.Node(nio.DataSink(), name='datasink') datasink.inputs.base_directory = out_dir datasink.inputs.parameterization = False workflow_connections = [ (get_f_scan, dummy_scans, [('nii_path', 'in_file')]), (dummy_scans, events_file, [('deleted_scans', 'forced_dummy_scans')]), (dummy_scans, f_resize, [('out_file', 'in_file')]), (get_f_scan, events_file, [('nii_path', 'timecourse_file'), ('task', 'task'), ('scan_path', 'scan_dir')]), (events_file, datasink, [('out_file', 'func.@events')]), (get_f_scan, events_file, [('events_name', 'out_file')]), (get_f_scan, datasink, [(('subject_session', ss_to_path), 'container') ]), (temporal_mean, f_percentile, [('out_file', 'in_file')]), # here we divide by 10 assuming 10 percent noise (f_percentile, f_threshold, [(('out_stat', divideby_10), 'thresh')]), (temporal_mean, f_threshold, [('out_file', 'in_file')]), (f_threshold, f_fast, [('out_file', 'in_files')]), (f_fast, f_bet, [('restored_image', 'in_file')]), (f_resize, f_deleteorient, [('out_file', 'in_file')]), (f_deleteorient, f_swapdim, [('out_file', 'in_file')]), ] if realign == "space": realigner = pe.Node(interface=spm.Realign(), name="realigner") realigner.inputs.register_to_mean = True workflow_connections.extend([ (f_swapdim, realigner, [('out_file', 'in_file')]), ]) elif realign == "spacetime": realigner = pe.Node(interface=nipy.SpaceTimeRealigner(), name="realigner") realigner.inputs.slice_times = "asc_alt_2" realigner.inputs.tr = tr realigner.inputs.slice_info = 3 #3 for coronal slices (2 for horizontal, 1 for sagittal) workflow_connections.extend([ (f_swapdim, realigner, [('out_file', 'in_file')]), ]) elif realign == "time": realigner = pe.Node(interface=fsl.SliceTimer(), name="slicetimer") realigner.inputs.time_repetition = tr workflow_connections.extend([ (f_swapdim, realigner, [('out_file', 'in_file')]), ]) f_antsintroduction = pe.Node(interface=antslegacy.antsIntroduction(), name='ants_introduction') f_antsintroduction.inputs.dimension = 3 f_antsintroduction.inputs.reference_image = template #will need updating to `1` f_antsintroduction.inputs.bias_field_correction = True f_antsintroduction.inputs.transformation_model = 'GR' f_antsintroduction.inputs.max_iterations = [8, 15, 8] f_warp = pe.Node(interface=ants.WarpTimeSeriesImageMultiTransform(), name='f_warp') f_warp.inputs.reference_image = template f_warp.inputs.dimension = 4 f_copysform2qform = pe.Node(interface=FSLOrient(), name='f_copysform2qform') f_copysform2qform.inputs.main_option = 'copysform2qform' warp_merge = pe.Node(util.Merge(2), name='warp_merge') workflow_connections.extend([ (f_bet, f_antsintroduction, [('out_file', 'input_image')]), (f_antsintroduction, warp_merge, [('warp_field', 'in1')]), (f_antsintroduction, warp_merge, [('affine_transformation', 'in2')]), (warp_merge, f_warp, [('out', 'transformation_series')]), (f_warp, f_copysform2qform, [('output_image', 'in_file')]), ]) if realign == "space": workflow_connections.extend([ (realigner, temporal_mean, [('realigned_files', 'in_file')]), (realigner, f_warp, [('realigned_files', 'input_image')]), ]) elif realign == "spacetime": workflow_connections.extend([ (realigner, temporal_mean, [('out_file', 'in_file')]), (realigner, f_warp, [('out_file', 'input_image')]), ]) elif realign == "time": workflow_connections.extend([ (realigner, temporal_mean, [('slice_time_corrected_file', 'in_file')]), (realigner, f_warp, [('slice_time_corrected_file', 'input_image') ]), ]) else: workflow_connections.extend([ (f_resize, temporal_mean, [('out_file', 'in_file')]), (f_swapdim, f_warp, [('out_file', 'input_image')]), ]) if functional_blur_xy: blur = pe.Node(interface=afni.preprocess.BlurToFWHM(), name="blur") blur.inputs.fwhmxy = functional_blur_xy workflow_connections.extend([ (get_f_scan, blur, [('nii_name', 'out_file')]), (f_copysform2qform, blur, [('out_file', 'in_file')]), (blur, datasink, [('out_file', 'func')]), ]) else: f_rename = pe.Node(util.Rename(), name='f_rename') workflow_connections.extend([ (get_f_scan, f_rename, [('nii_name', 'format_string')]), (f_copysform2qform, f_rename, [('out_file', 'in_file')]), (f_rename, datasink, [('out_file', 'func')]), ]) workflow_config = { 'execution': { 'crashdump_dir': path.join(out_base, 'crashdump'), } } if debug: workflow_config['logging'] = { 'workflow_level': 'DEBUG', 'utils_level': 'DEBUG', 'interface_level': 'DEBUG', 'filemanip_level': 'DEBUG', 'log_to_file': 'true', } workdir_name = workflow_name + "_work" #this gives the name of the workdir, the output name is passed to the datasink workflow = pe.Workflow(name=workdir_name) workflow.connect(workflow_connections) workflow.base_dir = out_base workflow.config = workflow_config try: workflow.write_graph(dotfilename=path.join(workflow.base_dir, workdir_name, "graph.dot"), graph2use="hierarchical", format="png") except OSError: print( 'We could not write the DOT file for visualization (`dot` function from the graphviz package). This is non-critical to the processing, but you should get this fixed.' ) workflow.run(plugin="MultiProc", plugin_args={'n_procs': n_jobs}) copy_bids_files(bids_base, os.path.join(out_base, workflow_name)) if not keep_work: workdir = path.join(workflow.base_dir, workdir_name) try: shutil.rmtree(workdir) except OSError as e: if str(e) == 'Cannot call rmtree on a symbolic link': print( 'Not deleting top level workdir (`{}`), as it is a symlink. Deleting only contents instead' .format(workdir)) for file_object in os.listdir(workdir): file_object_path = os.path.join(workdir, file_object) if os.path.isfile(file_object_path): os.unlink(file_object_path) else: shutil.rmtree(file_object_path) else: raise OSError(str(e))
def ecc_pipeline(name='eddy_correct'): """ ECC stands for Eddy currents correction. Creates a pipeline that corrects for artifacts induced by Eddy currents in dMRI sequences. It takes a series of diffusion weighted images and linearly co-registers them to one reference image (the average of all b0s in the dataset). DWIs are also modulated by the determinant of the Jacobian as indicated by [Jones10]_ and [Rohde04]_. A list of rigid transformation matrices can be provided, sourcing from a :func:`.hmc_pipeline` workflow, to initialize registrations in a *motion free* framework. A list of affine transformation matrices is available as output, so that transforms can be chained (discussion `here <https://github.com/nipy/nipype/pull/530#issuecomment-14505042>`_). .. admonition:: References .. [Jones10] Jones DK, `The signal intensity must be modulated by the determinant of the Jacobian when correcting for eddy currents in diffusion MRI <http://cds.ismrm.org/protected/10MProceedings/files/1644_129.pdf>`_, Proc. ISMRM 18th Annual Meeting, (2010). .. [Rohde04] Rohde et al., `Comprehensive Approach for Correction of Motion and Distortion in Diffusion-Weighted MRI <http://stbb.nichd.nih.gov/pdf/com_app_cor_mri04.pdf>`_, MRM 51:103-114 (2004). Example ------- >>> from nipype.workflows.dmri.fsl.artifacts import ecc_pipeline >>> ecc = ecc_pipeline() >>> ecc.inputs.inputnode.in_file = 'diffusion.nii' >>> ecc.inputs.inputnode.in_bval = 'diffusion.bval' >>> ecc.inputs.inputnode.in_mask = 'mask.nii' >>> ecc.run() # doctest: +SKIP Inputs:: inputnode.in_file - input dwi file inputnode.in_mask - weights mask of reference image (a file with data \ range sin [0.0, 1.0], indicating the weight of each voxel when computing the \ metric. inputnode.in_bval - b-values table inputnode.in_xfms - list of matrices to initialize registration (from \ head-motion correction) Outputs:: outputnode.out_file - corrected dwi file outputnode.out_xfms - list of transformation matrices """ from nipype.workflows.data import get_flirt_schedule params = dict(dof=12, no_search=True, interp='spline', bgvalue=0, schedule=get_flirt_schedule('ecc')) # cost='normmi', cost_func='normmi', bins=64, inputnode = pe.Node(niu.IdentityInterface( fields=['in_file', 'in_bval', 'in_mask', 'in_xfms']), name='inputnode') avg_b0 = pe.Node(niu.Function(input_names=['in_dwi', 'in_bval'], output_names=['out_file'], function=b0_average), name='b0_avg') pick_dws = pe.Node(niu.Function(input_names=['in_dwi', 'in_bval', 'b'], output_names=['out_file'], function=extract_bval), name='ExtractDWI') pick_dws.inputs.b = 'diff' flirt = dwi_flirt(flirt_param=params, excl_nodiff=True) mult = pe.MapNode(fsl.BinaryMaths(operation='mul'), name='ModulateDWIs', iterfield=['in_file', 'operand_value']) thres = pe.MapNode(fsl.Threshold(thresh=0.0), iterfield=['in_file'], name='RemoveNegative') split = pe.Node(fsl.Split(dimension='t'), name='SplitDWIs') get_mat = pe.Node(niu.Function(input_names=['in_bval', 'in_xfms'], output_names=['out_files'], function=recompose_xfm), name='GatherMatrices') merge = pe.Node(niu.Function( input_names=['in_dwi', 'in_bval', 'in_corrected'], output_names=['out_file'], function=recompose_dwi), name='MergeDWIs') outputnode = pe.Node( niu.IdentityInterface(fields=['out_file', 'out_xfms']), name='outputnode') wf = pe.Workflow(name=name) wf.connect([(inputnode, avg_b0, [('in_file', 'in_dwi'), ('in_bval', 'in_bval')]), (inputnode, pick_dws, [('in_file', 'in_dwi'), ('in_bval', 'in_bval')]), (inputnode, merge, [('in_file', 'in_dwi'), ('in_bval', 'in_bval')]), (inputnode, flirt, [('in_mask', 'inputnode.ref_mask'), ('in_xfms', 'inputnode.in_xfms'), ('in_bval', 'inputnode.in_bval')]), (inputnode, get_mat, [('in_bval', 'in_bval')]), (avg_b0, flirt, [('out_file', 'inputnode.reference')]), (pick_dws, flirt, [('out_file', 'inputnode.in_file')]), (flirt, get_mat, [('outputnode.out_xfms', 'in_xfms')]), (flirt, mult, [(('outputnode.out_xfms', _xfm_jacobian), 'operand_value')]), (flirt, split, [('outputnode.out_file', 'in_file')]), (split, mult, [('out_files', 'in_file')]), (mult, thres, [('out_file', 'in_file')]), (thres, merge, [('out_file', 'in_corrected')]), (get_mat, outputnode, [('out_files', 'out_xfms')]), (merge, outputnode, [('out_file', 'out_file')])]) return wf
'TumorValue2', 'NormalValue2' ], function=getScans)) ScanSource.inputs.tmln = tmln outstring = '-add %s ' * (len(Tumor) - 1) outstring = outstring[:-1] CreateTumorMask = pe.Node(interface=fsl.MultiImageMaths(), name='CreateTumorMask') CreateTumorMask.inputs.in_file = Tumor[0] CreateTumorMask.inputs.operand_files = Tumor[1:] CreateTumorMask.inputs.op_string = outstring ThresholdTumor = pe.Node(interface=fsl.Threshold(), name='ThresholdTumor') ThresholdTumor.inputs.thresh = 1 CreateNormalMask = pe.Node(interface=fsl.MultiImageMaths(), name='CreateNormalMask') CreateNormalMask.inputs.in_file = Normal[0] CreateNormalMask.inputs.operand_files = Normal[1:] CreateNormalMask.inputs.op_string = outstring ThresholdNormal = pe.Node(interface=fsl.Threshold(), name='ThresholdNormal') ThresholdNormal.inputs.thresh = 1 MaskTumorADC = pe.MapNode(interface=fsl.ApplyMask(), name='MaskTumorADC', iterfield=['in_file'])
def build_core_nodes(self): """Build and connect the core nodes of the pipeline.""" import os import nipype.interfaces.fsl as fsl import nipype.interfaces.mrtrix as mrtrix import nipype.interfaces.utility as nutil import nipype.pipeline.engine as npe from nipype.interfaces.ants import ApplyTransforms, RegistrationSynQuick from nipype.interfaces.mrtrix.preprocess import DWI2Tensor from clinica.lib.nipype.interfaces.mrtrix3.utils import TensorMetrics from clinica.utils.check_dependency import check_environment_variable from .dwi_dti_utils import ( extract_bids_identifier_from_caps_filename, get_ants_transforms, get_caps_filenames, print_begin_pipeline, print_end_pipeline, statistics_on_atlases, ) # Nodes creation # ============== get_bids_identifier = npe.Node( interface=nutil.Function( input_names=["caps_dwi_filename"], output_names=["bids_identifier"], function=extract_bids_identifier_from_caps_filename, ), name="0-Get_BIDS_Identifier", ) get_caps_filenames = npe.Node( interface=nutil.Function( input_names=["caps_dwi_filename"], output_names=[ "bids_source", "out_dti", "out_fa", "out_md", "out_ad", "out_rd", "out_evec", ], function=get_caps_filenames, ), name="0-CAPS_Filenames", ) convert_gradients = npe.Node(interface=mrtrix.FSL2MRTrix(), name="0-Convert_FSL_Gradient") dwi_to_dti = npe.Node(interface=DWI2Tensor(), name="1-Compute_DTI") dti_to_metrics = npe.Node(interface=TensorMetrics(), name="2-DTI-based_Metrics") register_fa = npe.Node(interface=RegistrationSynQuick(), name="3a-Register_FA") fsl_dir = check_environment_variable("FSLDIR", "FSL") fa_map = os.path.join(fsl_dir, "data", "atlases", "JHU", "JHU-ICBM-FA-1mm.nii.gz") register_fa.inputs.fixed_image = fa_map ants_transforms = npe.Node( interface=nutil.Function( input_names=[ "in_affine_transformation", "in_bspline_transformation" ], output_names=["transforms"], function=get_ants_transforms, ), name="combine_ants_transforms", ) apply_ants_registration = npe.Node(interface=ApplyTransforms(), name="apply_ants_registration") apply_ants_registration.inputs.dimension = 3 apply_ants_registration.inputs.input_image_type = 0 apply_ants_registration.inputs.interpolation = "Linear" apply_ants_registration.inputs.reference_image = fa_map apply_ants_registration_for_md = apply_ants_registration.clone( "3b-Apply_ANTs_Registration_MD") apply_ants_registration_for_ad = apply_ants_registration.clone( "3b-Apply_ANTs_Registration_AD") apply_ants_registration_for_rd = apply_ants_registration.clone( "3b-Apply_ANTs_Registration_RD") thres_map = npe.Node(fsl.Threshold(thresh=0.0), iterfield=["in_file"], name="RemoveNegative") thres_norm_fa = thres_map.clone("3c-RemoveNegative_FA") thres_norm_md = thres_map.clone("3c-RemoveNegative_MD") thres_norm_ad = thres_map.clone("3c-RemoveNegative_AD") thres_norm_rd = thres_map.clone("3c-RemoveNegative_RD") scalar_analysis = npe.Node( interface=nutil.Function( input_names=["in_registered_map", "name_map", "prefix_file"], output_names=["atlas_statistics_list"], function=statistics_on_atlases, ), name="4-Scalar_Analysis", ) scalar_analysis_fa = scalar_analysis.clone("4-Scalar_Analysis_FA") scalar_analysis_fa.inputs.name_map = "FA" scalar_analysis_md = scalar_analysis.clone("4-Scalar_Analysis_MD") scalar_analysis_md.inputs.name_map = "MD" scalar_analysis_ad = scalar_analysis.clone("4-Scalar_Analysis_AD") scalar_analysis_ad.inputs.name_map = "AD" scalar_analysis_rd = scalar_analysis.clone("4-Scalar_Analysis_RD") scalar_analysis_rd.inputs.name_map = "RD" thres_map = npe.Node(fsl.Threshold(thresh=0.0), iterfield=["in_file"], name="5-Remove_Negative") thres_fa = thres_map.clone("5-Remove_Negative_FA") thres_md = thres_map.clone("5-Remove_Negative_MD") thres_ad = thres_map.clone("5-Remove_Negative_AD") thres_rd = thres_map.clone("5-Remove_Negative_RD") thres_decfa = thres_map.clone("5-Remove_Negative_DECFA") print_begin_message = npe.Node( interface=nutil.Function(input_names=["in_bids_or_caps_file"], function=print_begin_pipeline), name="Write-Begin_Message", ) print_end_message = npe.Node( interface=nutil.Function( input_names=[ "in_bids_or_caps_file", "final_file_1", "final_file_2" ], function=print_end_pipeline, ), name="Write-End_Message", ) # Connection # ========== # fmt: off self.connect([ (self.input_node, get_caps_filenames, [("preproc_dwi", "caps_dwi_filename")]), # Print begin message (self.input_node, print_begin_message, [("preproc_dwi", "in_bids_or_caps_file")]), # Get BIDS/CAPS identifier from filename (self.input_node, get_bids_identifier, [("preproc_dwi", "caps_dwi_filename")]), # Convert FSL gradient files (bval/bvec) to MRtrix format (self.input_node, convert_gradients, [("preproc_bval", "bval_file"), ("preproc_bvec", "bvec_file")]), # Computation of the DTI model (self.input_node, dwi_to_dti, [("b0_mask", "mask"), ("preproc_dwi", "in_file")]), (convert_gradients, dwi_to_dti, [("encoding_file", "encoding_file") ]), (get_caps_filenames, dwi_to_dti, [("out_dti", "out_filename")]), # Computation of the different metrics from the DTI (get_caps_filenames, dti_to_metrics, [("out_fa", "out_fa")]), (get_caps_filenames, dti_to_metrics, [("out_md", "out_adc")]), (get_caps_filenames, dti_to_metrics, [("out_ad", "out_ad")]), (get_caps_filenames, dti_to_metrics, [("out_rd", "out_rd")]), (get_caps_filenames, dti_to_metrics, [("out_evec", "out_evec")]), (self.input_node, dti_to_metrics, [("b0_mask", "in_mask")]), (dwi_to_dti, dti_to_metrics, [("tensor", "in_file")]), # Registration of FA-map onto the atlas: (dti_to_metrics, register_fa, [("out_fa", "moving_image")]), # Apply deformation field on MD, AD & RD: (register_fa, ants_transforms, [("out_matrix", "in_affine_transformation")]), (register_fa, ants_transforms, [("forward_warp_field", "in_bspline_transformation")]), (dti_to_metrics, apply_ants_registration_for_md, [("out_adc", "input_image")]), (ants_transforms, apply_ants_registration_for_md, [("transforms", "transforms")]), (dti_to_metrics, apply_ants_registration_for_ad, [("out_ad", "input_image")]), (ants_transforms, apply_ants_registration_for_ad, [("transforms", "transforms")]), (dti_to_metrics, apply_ants_registration_for_rd, [("out_rd", "input_image")]), (ants_transforms, apply_ants_registration_for_rd, [("transforms", "transforms")]), # Remove negative values from the DTI maps: (register_fa, thres_norm_fa, [("warped_image", "in_file")]), (apply_ants_registration_for_md, thres_norm_md, [("output_image", "in_file")]), (apply_ants_registration_for_rd, thres_norm_rd, [("output_image", "in_file")]), (apply_ants_registration_for_ad, thres_norm_ad, [("output_image", "in_file")]), # Generate regional TSV files (get_bids_identifier, scalar_analysis_fa, [("bids_identifier", "prefix_file")]), (thres_norm_fa, scalar_analysis_fa, [("out_file", "in_registered_map")]), (get_bids_identifier, scalar_analysis_md, [("bids_identifier", "prefix_file")]), (thres_norm_md, scalar_analysis_md, [("out_file", "in_registered_map")]), (get_bids_identifier, scalar_analysis_ad, [("bids_identifier", "prefix_file")]), (thres_norm_ad, scalar_analysis_ad, [("out_file", "in_registered_map")]), (get_bids_identifier, scalar_analysis_rd, [("bids_identifier", "prefix_file")]), (thres_norm_rd, scalar_analysis_rd, [("out_file", "in_registered_map")]), # Remove negative values from the DTI maps: (get_caps_filenames, thres_fa, [("out_fa", "out_file")]), (dti_to_metrics, thres_fa, [("out_fa", "in_file")]), (get_caps_filenames, thres_md, [("out_md", "out_file")]), (dti_to_metrics, thres_md, [("out_adc", "in_file")]), (get_caps_filenames, thres_ad, [("out_ad", "out_file")]), (dti_to_metrics, thres_ad, [("out_ad", "in_file")]), (get_caps_filenames, thres_rd, [("out_rd", "out_file")]), (dti_to_metrics, thres_rd, [("out_rd", "in_file")]), (get_caps_filenames, thres_decfa, [("out_evec", "out_file")]), (dti_to_metrics, thres_decfa, [("out_evec", "in_file")]), # Outputnode (dwi_to_dti, self.output_node, [("tensor", "dti")]), (thres_fa, self.output_node, [("out_file", "fa")]), (thres_md, self.output_node, [("out_file", "md")]), (thres_ad, self.output_node, [("out_file", "ad")]), (thres_rd, self.output_node, [("out_file", "rd")]), (thres_decfa, self.output_node, [("out_file", "decfa")]), (register_fa, self.output_node, [("out_matrix", "affine_matrix")]), (register_fa, self.output_node, [("forward_warp_field", "b_spline_transform")]), (thres_norm_fa, self.output_node, [("out_file", "registered_fa")]), (thres_norm_md, self.output_node, [("out_file", "registered_md")]), (thres_norm_ad, self.output_node, [("out_file", "registered_ad")]), (thres_norm_rd, self.output_node, [("out_file", "registered_rd")]), (scalar_analysis_fa, self.output_node, [("atlas_statistics_list", "statistics_fa")]), (scalar_analysis_md, self.output_node, [("atlas_statistics_list", "statistics_md")]), (scalar_analysis_ad, self.output_node, [("atlas_statistics_list", "statistics_ad")]), (scalar_analysis_rd, self.output_node, [("atlas_statistics_list", "statistics_rd")]), # Print end message (self.input_node, print_end_message, [("preproc_dwi", "in_bids_or_caps_file")]), (thres_rd, print_end_message, [("out_file", "final_file_1")]), (scalar_analysis_rd, print_end_message, [("atlas_statistics_list", "final_file_2")]), ])
#Wraps command **slicetimer** NodeHash_1d000c0 = pe.Node(interface=fsl.SliceTimer(), name='NodeName_1d000c0') #Wraps command **mcflirt** NodeHash_22f2e80 = pe.Node(interface=fsl.MCFLIRT(), name='NodeName_22f2e80') #Computes the time-course SNR for a time series NodeHash_50c02c0 = pe.Node(interface=confounds.TSNR(), name='NodeName_50c02c0') NodeHash_50c02c0.inputs.regress_poly = 3 #Wraps command **fslstats** NodeHash_3ac27f0 = pe.Node(interface=fsl.ImageStats(), name='NodeName_3ac27f0') NodeHash_3ac27f0.inputs.op_string = '-p 98' #Wraps command **fslmaths** NodeHash_30f6760 = pe.Node(interface=fsl.Threshold(), name='NodeName_30f6760') NodeHash_30f6760.inputs.args = '-bin' #Anatomical compcor: for inputs and outputs, see CompCor. NodeHash_325da10 = pe.Node(interface=confounds.ACompCor(), name='NodeName_325da10') NodeHash_325da10.inputs.num_components = 2 #Wraps command **fsl_regfilt** NodeHash_430d1e0 = pe.Node(interface=fsl.FilterRegressor(), name='NodeName_430d1e0') NodeHash_430d1e0.inputs.filter_columns = [1, 2] #Wraps command **fslmaths** NodeHash_77e3220 = pe.Node(interface=fsl.TemporalFilter(), name='NodeName_77e3220')
def remove_bias(name="bias_correct"): """ This workflow estimates a single multiplicative bias field from the averaged *b0* image, as suggested in [Jeurissen2014]_. .. admonition:: References .. [Jeurissen2014] Jeurissen B. et al., `Multi-tissue constrained spherical deconvolution for improved analysis of multi-shell diffusion MRI data <http://dx.doi.org/10.1016/j.neuroimage.2014.07.061>`_.squeue NeuroImage (2014). doi: 10.1016/j.neuroimage.2014.07.061 Example ------- >>> from nipype.workflows.dmri.fsl.artifacts import remove_bias >>> bias = remove_bias() >>> bias.inputs.inputnode.in_file = 'epi.nii' >>> bias.inputs.inputnode.in_bval = 'diffusion.bval' >>> bias.inputs.inputnode.in_mask = 'mask.nii' >>> bias.run() # doctest: +SKIP """ import nipype.interfaces.ants as ants 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_file"]), name="inputnode") outputnode = pe.Node(niu.IdentityInterface(fields=["out_file", "b0_mask"]), name="outputnode") get_b0 = pe.Node(fsl.ExtractROI(t_min=0, t_size=1), name="get_b0") mask_b0 = pe.Node(fsl.BET(frac=0.3, mask=True, robust=True), name="mask_b0") n4 = pe.Node( ants.N4BiasFieldCorrection(dimension=3, save_bias=True, bspline_fitting_distance=600), name="Bias_b0", ) split = pe.Node(fsl.Split(dimension="t"), name="SplitDWIs") mult = pe.MapNode( fsl.MultiImageMaths(op_string="-div %s"), iterfield=["in_file"], name="RemoveBiasOfDWIs", ) thres = pe.MapNode(fsl.Threshold(thresh=0.0), iterfield=["in_file"], name="RemoveNegative") merge = pe.Node(fsl.utils.Merge(dimension="t"), name="MergeDWIs") wf = pe.Workflow(name=name) wf.connect([ (inputnode, get_b0, [("in_file", "in_file")]), (get_b0, n4, [("roi_file", "input_image")]), (get_b0, mask_b0, [("roi_file", "in_file")]), (mask_b0, n4, [("mask_file", "mask_image")]), (inputnode, split, [("in_file", "in_file")]), (n4, mult, [("bias_image", "operand_files")]), (split, mult, [("out_files", "in_file")]), (mult, thres, [("out_file", "in_file")]), (thres, merge, [("out_file", "in_files")]), (merge, outputnode, [("merged_file", "out_file")]), (mask_b0, outputnode, [("mask_file", "b0_mask")]), ]) return wf
def ecc_pipeline(name="eddy_correct"): """ ECC stands for Eddy currents correction. Creates a pipelines that corrects for artifacts induced by Eddy currents in dMRI sequences. It takes a series of diffusion weighted images and linearly co-registers them to one reference image (the average of all b0s in the dataset). DWIs are also modulated by the determinant of the Jacobian as indicated by [Jones10]_ and [Rohde04]_. A list of rigid transformation matrices can be provided, sourcing from a :func:`.hmc_pipeline` workflow, to initialize registrations in a *motion free* framework. A list of affine transformation matrices is available as output, so that transforms can be chained (discussion `here <https://github.com/nipy/nipype/pull/530#issuecomment-14505042>`_). .. admonition:: References .. [Jones10] Jones DK, `The signal intensity must be modulated by the determinant of the Jacobian when correcting for eddy currents in diffusion MRI <http://cds.ismrm.org/protected/10MProceedings/files/1644_129.pdf>`_, Proc. ISMRM 18th Annual Meeting, (2010). .. [Rohde04] Rohde et al., `Comprehensive Approach for Correction of Motion and Distortion in Diffusion-Weighted MRI <http://stbb.nichd.nih.gov/pdf/com_app_cor_mri04.pdf>`_, MRM 51:103-114 (2004). Example ------- from nipype.workflows.dmri.fsl.artifacts import ecc_pipeline ecc = ecc_pipeline() ecc.inputs.inputnode.in_file = 'diffusion.nii' ecc.inputs.inputnode.in_bval = 'diffusion.bval' ecc.inputs.inputnode.in_mask = 'mask.nii' ecc.run() # doctest: +SKIP Inputs:: inputnode.in_file - input dwi file inputnode.in_mask - weights mask of reference image (a file with data \ range sin [0.0, 1.0], indicating the weight of each voxel when computing the \ metric. inputnode.in_bval - b-values table inputnode.in_xfms - list of matrices to initialize registration (from \ head-motion correction) Outputs:: outputnode.out_file - corrected dwi file outputnode.out_xfms - list of transformation matrices """ import nipype.interfaces.fsl as fsl import nipype.interfaces.utility as niu import nipype.pipeline.engine as pe from nipype.workflows.data import get_flirt_schedule from nipype.workflows.dmri.fsl.artifacts import _xfm_jacobian from nipype.workflows.dmri.fsl.utils import ( extract_bval, recompose_dwi, recompose_xfm, ) from clinica.utils.dwi import merge_volumes_tdim from clinica.workflows.dwi_preprocessing import dwi_flirt params = dict( dof=12, no_search=True, interp="spline", bgvalue=0, schedule=get_flirt_schedule("ecc"), ) inputnode = pe.Node( niu.IdentityInterface( fields=["in_file", "in_bval", "in_mask", "in_xfms"]), name="inputnode", ) getb0 = pe.Node(fsl.ExtractROI(t_min=0, t_size=1), name="get_b0") pick_dws = pe.Node( niu.Function( input_names=["in_dwi", "in_bval", "b"], output_names=["out_file"], function=extract_bval, ), name="extract_dwi", ) pick_dws.inputs.b = "diff" flirt = dwi_flirt(flirt_param=params, excl_nodiff=True) mult = pe.MapNode( fsl.BinaryMaths(operation="mul"), name="ModulateDWIs", iterfield=["in_file", "operand_value"], ) thres = pe.MapNode(fsl.Threshold(thresh=0.0), iterfield=["in_file"], name="RemoveNegative") split = pe.Node(fsl.Split(dimension="t"), name="SplitDWIs") get_mat = pe.Node( niu.Function( input_names=["in_bval", "in_xfms"], output_names=["out_files"], function=recompose_xfm, ), name="GatherMatrices", ) merge = pe.Node( niu.Function( input_names=["in_dwi", "in_bval", "in_corrected"], output_names=["out_file"], function=recompose_dwi, ), name="MergeDWIs", ) merged_volumes = pe.Node( niu.Function( input_names=["in_file1", "in_file2"], output_names=["out_file"], function=merge_volumes_tdim, ), name="merge_enhanced_ref_dwis", ) outputnode = pe.Node( niu.IdentityInterface(fields=["out_file", "out_xfms"]), name="outputnode") wf = pe.Workflow(name=name) wf.connect([ (inputnode, getb0, [("in_file", "in_file")]), (inputnode, pick_dws, [("in_file", "in_dwi"), ("in_bval", "in_bval")]), ( flirt, merged_volumes, [ ("outputnode.out_ref", "in_file1"), ("outputnode.out_file", "in_file2"), ], ), (merged_volumes, merge, [("out_file", "in_dwi")]), (inputnode, merge, [("in_bval", "in_bval")]), ( inputnode, flirt, [ ("in_mask", "inputnode.ref_mask"), ("in_xfms", "inputnode.in_xfms"), ("in_bval", "inputnode.in_bval"), ], ), (inputnode, get_mat, [("in_bval", "in_bval")]), (getb0, flirt, [("roi_file", "inputnode.reference")]), (pick_dws, flirt, [("out_file", "inputnode.in_file")]), (flirt, get_mat, [("outputnode.out_xfms", "in_xfms")]), (flirt, mult, [(("outputnode.out_xfms", _xfm_jacobian), "operand_value")]), (flirt, split, [("outputnode.out_file", "in_file")]), (split, mult, [("out_files", "in_file")]), (mult, thres, [("out_file", "in_file")]), (thres, merge, [("out_file", "in_corrected")]), (get_mat, outputnode, [("out_files", "out_xfms")]), (merge, outputnode, [("out_file", "out_file")]), ]) return wf
def dwi_flirt(name="DWICoregistration", excl_nodiff=False, flirt_param={}): """ Generates a workflow for linear registration of dwi volumes using flirt. Inputnode --------- reference : FILE Mandatory input. Reference data set. in_file : FILE Mandatory input. Moving data set. ref_mask : FILE Mandatory input. Binary mask of the reference volume. in_xfms : FILE Mandatory input. Intialisation matrices for flirt. in_bval : FILE Mandatory input. B values file. """ import nipype.interfaces.ants as ants import nipype.interfaces.fsl as fsl import nipype.interfaces.utility as niu import nipype.pipeline.engine as pe from nipype.workflows.dmri.fsl.utils import _checkinitxfm, enhance inputnode = pe.Node( niu.IdentityInterface( fields=["reference", "in_file", "ref_mask", "in_xfms", "in_bval"]), name="inputnode", ) initmat = pe.Node( niu.Function( input_names=["in_bval", "in_xfms", "excl_nodiff"], output_names=["init_xfms"], function=_checkinitxfm, ), name="InitXforms", ) initmat.inputs.excl_nodiff = excl_nodiff dilate = pe.Node( fsl.maths.MathsCommand(nan2zeros=True, args="-kernel sphere 5 -dilM"), name="MskDilate", ) split = pe.Node(fsl.Split(dimension="t"), name="SplitDWIs") n4 = pe.Node(ants.N4BiasFieldCorrection(dimension=3), name="Bias") flirt = pe.MapNode( fsl.FLIRT(**flirt_param), name="CoRegistration", iterfield=["in_file", "in_matrix_file"], ) 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=["out_file", "out_xfms", "out_ref"]), name="outputnode", ) enhb0 = pe.Node( niu.Function( input_names=["in_file", "in_mask", "clip_limit"], output_names=["out_file"], function=enhance, ), name="B0Equalize", ) enhb0.inputs.clip_limit = 0.015 enhdw = pe.MapNode( niu.Function( input_names=["in_file", "in_mask"], output_names=["out_file"], function=enhance, ), name="DWEqualize", iterfield=["in_file"], ) # enhb0.inputs.clip_limit = clip_limit wf = pe.Workflow(name=name) wf.connect([ (inputnode, split, [("in_file", "in_file")]), (inputnode, dilate, [("ref_mask", "in_file")]), (inputnode, n4, [("reference", "input_image"), ("ref_mask", "mask_image")]), # (inputnode, flirt, [('ref_mask', 'reference')]), (n4, enhb0, [("output_image", "in_file")]), (enhb0, flirt, [("out_file", "reference")]), (inputnode, initmat, [("in_xfms", "in_xfms"), ("in_bval", "in_bval")]), (split, enhdw, [("out_files", "in_file")]), (dilate, enhdw, [("out_file", "in_mask")]), (dilate, flirt, [("out_file", "ref_weight"), ("out_file", "in_weight")]), (enhdw, flirt, [("out_file", "in_file")]), (initmat, flirt, [("init_xfms", "in_matrix_file")]), (flirt, thres, [("out_file", "in_file")]), (thres, merge, [("out_file", "in_files")]), (merge, outputnode, [("merged_file", "out_file")]), (enhb0, outputnode, [("out_file", "out_ref")]), (flirt, outputnode, [("out_matrix_file", "out_xfms")]), ]) return wf
def register_dti_maps_on_atlas(working_directory=None, name="register_dti_maps_on_atlas"): """ Register FA-map on a subject towards a FA atlas and apply the estimated deformation to MD, AD & RD. This pipelines performs the analysis of tracts using a white matter atlas and computes mean value of the scalar on each tracts of this atlas. The pipelines registers the FA-map of a subject onto the FA-map of the atlas thanks to antsRegistrationSyNQuick. Then, the estimated deformation is applied to the MD-map, AD-map and RD-map. Finally, the labelled atlas is used to compute the statistics of each scalar on each tract of the white matter atlas. Args: working_directory (Optional[str]): Directory where the temporary results are stored. If not specified, it is automatically generated (generally in /tmp/). name (Optional[str]): Name of the pipelines. Inputnode: in_fa (str): FA-map of the subject in native space. in_md (str): MD-map of the subject in native space. in_ad (str): AD-map of the subject in native space. in_rd (str): RD-map of the subject in native space. Outputnode: out_affine_transform (str): Affine transformation matrix obtained by antsRegistrationSyNQuick after registration towards <atlas_name>. out_b_spline_transform (str): BSpline transformation obtained by antsRegistrationSyNQuick after registration towards <atlas_name>. out_norm_fa (str): FA-map registered on <atlas_name>. out_norm_md (str): MD-map registered on <atlas_name>. out_norm_ad (str): AD-map registered on <atlas_name>. out_norm_rd (str): RD-map registered on <atlas_name>. """ import tempfile import nipype.interfaces.fsl as fsl import nipype.interfaces.utility as niu import nipype.pipeline.engine as pe from nipype.interfaces.ants import RegistrationSynQuick from clinica.utils.atlas import AtlasAbstract from clinica.utils.mri_registration import apply_ants_registration_syn_quick_transformation from clinica.utils.atlas import JHUDTI811mm atlas = JHUDTI811mm() if not isinstance(atlas, AtlasAbstract): raise Exception("Atlas element must be an AtlasAbstract type") if working_directory is None: working_directory = tempfile.mkdtemp() inputnode = pe.Node(niu.IdentityInterface( fields=['in_fa', 'in_md', 'in_ad', 'in_rd', 'in_atlas_scalar_image']), name='inputnode') inputnode.inputs.in_atlas_scalar_image = atlas.get_atlas_map() register_fa = pe.Node(interface=RegistrationSynQuick(), name='register_fa') apply_ants_registration_for_md = pe.Node( interface=niu.Function( input_names=[ 'in_image', 'in_reference_image', 'in_affine_transformation', 'in_bspline_transformation', 'name_output_image' ], output_names=['out_deformed_image'], function=apply_ants_registration_syn_quick_transformation), name='apply_ants_registration_for_md') apply_ants_registration_for_md.inputs.name_output_image = \ 'space-' + atlas.get_name_atlas() + '_res-' + atlas.get_spatial_resolution() + '_MD.nii.gz' apply_ants_registration_for_ad = pe.Node( interface=niu.Function( input_names=[ 'in_image', 'in_reference_image', 'in_affine_transformation', 'in_bspline_transformation', 'name_output_image' ], output_names=['out_deformed_image'], function=apply_ants_registration_syn_quick_transformation), name='apply_ants_registration_for_ad') apply_ants_registration_for_ad.inputs.name_output_image = \ 'space-' + atlas.get_name_atlas() + '_res-' + atlas.get_spatial_resolution() + '_AD.nii.gz' apply_ants_registration_for_rd = pe.Node( interface=niu.Function( input_names=[ 'in_image', 'in_reference_image', 'in_affine_transformation', 'in_bspline_transformation', 'name_output_image' ], output_names=['out_deformed_image'], function=apply_ants_registration_syn_quick_transformation), name='apply_ants_registration_for_rd') apply_ants_registration_for_rd.inputs.name_output_image = \ 'space-' + atlas.get_name_atlas() + '_res-' + atlas.get_spatial_resolution() + '_RD.nii.gz' thres_map = pe.Node(fsl.Threshold(thresh=0.0), iterfield=['in_file'], name='RemoveNegative') thres_fa = thres_map.clone('RemoveNegative_FA') thres_md = thres_map.clone('RemoveNegative_MD') thres_ad = thres_map.clone('RemoveNegative_AD') thres_rd = thres_map.clone('RemoveNegative_RD') outputnode = pe.Node(niu.IdentityInterface(fields=[ 'out_norm_fa', 'out_norm_md', 'out_norm_ad', 'out_norm_rd', 'out_affine_matrix', 'out_b_spline_transform' ]), name='outputnode') wf = pe.Workflow(name=name, base_dir=working_directory) wf.connect([ # Registration of FA-map onto the atlas: ( inputnode, register_fa, [ ('in_fa', 'moving_image'), # noqa ('in_atlas_scalar_image', 'fixed_image') ]), # noqa # Apply deformation field on MD, AD & RD: (inputnode, apply_ants_registration_for_md, [('in_md', 'in_image')] ), # noqa (inputnode, apply_ants_registration_for_md, [('in_atlas_scalar_image', 'in_reference_image')]), # noqa (register_fa, apply_ants_registration_for_md, [('out_matrix', 'in_affine_transformation')]), # noqa (register_fa, apply_ants_registration_for_md, [('forward_warp_field', 'in_bspline_transformation')]), # noqa (inputnode, apply_ants_registration_for_ad, [('in_ad', 'in_image') ]), # noqa (inputnode, apply_ants_registration_for_ad, [('in_atlas_scalar_image', 'in_reference_image')]), # noqa (register_fa, apply_ants_registration_for_ad, [('out_matrix', 'in_affine_transformation')]), # noqa (register_fa, apply_ants_registration_for_ad, [('forward_warp_field', 'in_bspline_transformation')]), # noqa (inputnode, apply_ants_registration_for_rd, [('in_rd', 'in_image') ]), # noqa (inputnode, apply_ants_registration_for_rd, [('in_atlas_scalar_image', 'in_reference_image')]), # noqa (register_fa, apply_ants_registration_for_rd, [('out_matrix', 'in_affine_transformation')]), # noqa (register_fa, apply_ants_registration_for_rd, [('forward_warp_field', 'in_bspline_transformation')]), # noqa # Remove negative values from the DTI maps: (register_fa, thres_fa, [('warped_image', 'in_file')]), # noqa (apply_ants_registration_for_md, thres_md, [('out_deformed_image', 'in_file')]), # noqa (apply_ants_registration_for_rd, thres_rd, [('out_deformed_image', 'in_file')]), # noqa (apply_ants_registration_for_ad, thres_ad, [('out_deformed_image', 'in_file')]), # noqa # Outputnode: (thres_fa, outputnode, [('out_file', 'out_norm_fa')]), # noqa ( register_fa, outputnode, [ ('out_matrix', 'out_affine_matrix'), # noqa ('forward_warp_field', 'out_b_spline_transform'), # noqa ('inverse_warp_field', 'out_inverse_warp') ]), # noqa (thres_md, outputnode, [('out_file', 'out_norm_md')]), # noqa (thres_ad, outputnode, [('out_file', 'out_norm_ad')]), # noqa (thres_rd, outputnode, [('out_file', 'out_norm_rd')]) # noqa ]) return wf
def sdc_fmb(name='fmb_correction', interp='Linear', fugue_params=dict(smooth3d=2.0)): """ SDC stands for susceptibility distortion correction. FMB stands for fieldmap-based. The fieldmap based (FMB) method implements SDC by using a mapping of the B0 field as proposed by [Jezzard95]_. This workflow uses the implementation of FSL (`FUGUE <http://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FUGUE>`_). Phase unwrapping is performed using `PRELUDE <http://fsl.fmrib.ox.ac.uk/fsl/fsl-4.1.9/fugue/prelude.html>`_ [Jenkinson03]_. Preparation of the fieldmap is performed reproducing the script in FSL `fsl_prepare_fieldmap <http://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FUGUE/Guide#SIEMENS_data>`_. Example ------- >>> from nipype.workflows.dmri.fsl.artifacts import sdc_fmb >>> fmb = sdc_fmb() >>> fmb.inputs.inputnode.in_file = 'diffusion.nii' >>> fmb.inputs.inputnode.in_ref = list(range(0, 30, 6)) >>> fmb.inputs.inputnode.in_mask = 'mask.nii' >>> fmb.inputs.inputnode.bmap_mag = 'magnitude.nii' >>> fmb.inputs.inputnode.bmap_pha = 'phase.nii' >>> fmb.inputs.inputnode.settings = 'epi_param.txt' >>> fmb.run() # doctest: +SKIP .. warning:: Only SIEMENS format fieldmaps are supported. .. admonition:: References .. [Jezzard95] Jezzard P, and Balaban RS, `Correction for geometric distortion in echo planar images from B0 field variations <https://doi.org/10.1002/mrm.1910340111>`_, MRM 34(1):65-73. (1995). doi: 10.1002/mrm.1910340111. .. [Jenkinson03] Jenkinson M., `Fast, automated, N-dimensional phase-unwrapping algorithm <https://doi.org/10.1002/mrm.10354>`_, MRM 49(1):193-197, 2003, doi: 10.1002/mrm.10354. """ epi_defaults = { 'delta_te': 2.46e-3, 'echospacing': 0.77e-3, 'acc_factor': 2, 'enc_dir': u'AP' } inputnode = pe.Node(niu.IdentityInterface(fields=[ 'in_file', 'in_ref', 'in_mask', 'bmap_pha', 'bmap_mag', 'settings' ]), name='inputnode') outputnode = pe.Node( niu.IdentityInterface(fields=['out_file', 'out_vsm', 'out_warp']), name='outputnode') r_params = pe.Node(JSONFileGrabber(defaults=epi_defaults), name='SettingsGrabber') eff_echo = pe.Node(niu.Function(function=_eff_t_echo, input_names=['echospacing', 'acc_factor'], output_names=['eff_echo']), name='EffEcho') firstmag = pe.Node(fsl.ExtractROI(t_min=0, t_size=1), name='GetFirst') n4 = pe.Node(ants.N4BiasFieldCorrection(dimension=3), name='Bias') bet = pe.Node(fsl.BET(frac=0.4, mask=True), name='BrainExtraction') dilate = pe.Node(fsl.maths.MathsCommand(nan2zeros=True, args='-kernel sphere 5 -dilM'), name='MskDilate') pha2rads = pe.Node(niu.Function(input_names=['in_file'], output_names=['out_file'], function=siemens2rads), name='PreparePhase') prelude = pe.Node(fsl.PRELUDE(process3d=True), name='PhaseUnwrap') rad2rsec = pe.Node(niu.Function(input_names=['in_file', 'delta_te'], output_names=['out_file'], function=rads2radsec), name='ToRadSec') baseline = pe.Node(niu.Function(input_names=['in_file', 'index'], output_names=['out_file'], function=time_avg), name='Baseline') fmm2b0 = pe.Node(ants.Registration(output_warped_image=True), name="FMm_to_B0") fmm2b0.inputs.transforms = ['Rigid'] * 2 fmm2b0.inputs.transform_parameters = [(1.0, )] * 2 fmm2b0.inputs.number_of_iterations = [[50], [20]] fmm2b0.inputs.dimension = 3 fmm2b0.inputs.metric = ['Mattes', 'Mattes'] fmm2b0.inputs.metric_weight = [1.0] * 2 fmm2b0.inputs.radius_or_number_of_bins = [64, 64] fmm2b0.inputs.sampling_strategy = ['Regular', 'Random'] fmm2b0.inputs.sampling_percentage = [None, 0.2] fmm2b0.inputs.convergence_threshold = [1.e-5, 1.e-8] fmm2b0.inputs.convergence_window_size = [20, 10] fmm2b0.inputs.smoothing_sigmas = [[6.0], [2.0]] fmm2b0.inputs.sigma_units = ['vox'] * 2 fmm2b0.inputs.shrink_factors = [[6], [1]] # ,[1] ] fmm2b0.inputs.use_estimate_learning_rate_once = [True] * 2 fmm2b0.inputs.use_histogram_matching = [True] * 2 fmm2b0.inputs.initial_moving_transform_com = 0 fmm2b0.inputs.collapse_output_transforms = True fmm2b0.inputs.winsorize_upper_quantile = 0.995 applyxfm = pe.Node(ants.ApplyTransforms(dimension=3, interpolation=interp), name='FMp_to_B0') pre_fugue = pe.Node(fsl.FUGUE(save_fmap=True), name='PreliminaryFugue') demean = pe.Node(niu.Function(input_names=['in_file', 'in_mask'], output_names=['out_file'], function=demean_image), name='DemeanFmap') cleanup = cleanup_edge_pipeline() addvol = pe.Node(niu.Function(input_names=['in_file'], output_names=['out_file'], function=add_empty_vol), name='AddEmptyVol') vsm = pe.Node(fsl.FUGUE(save_shift=True, **fugue_params), name="ComputeVSM") split = pe.Node(fsl.Split(dimension='t'), name='SplitDWIs') merge = pe.Node(fsl.Merge(dimension='t'), name='MergeDWIs') unwarp = pe.MapNode(fsl.FUGUE(icorr=True, forward_warping=False), iterfield=['in_file'], name='UnwarpDWIs') thres = pe.MapNode(fsl.Threshold(thresh=0.0), iterfield=['in_file'], name='RemoveNegative') vsm2dfm = vsm2warp() vsm2dfm.inputs.inputnode.scaling = 1.0 wf = pe.Workflow(name=name) wf.connect([(inputnode, r_params, [('settings', 'in_file')]), (r_params, eff_echo, [('echospacing', 'echospacing'), ('acc_factor', 'acc_factor')]), (inputnode, pha2rads, [('bmap_pha', 'in_file')]), (inputnode, firstmag, [('bmap_mag', 'in_file')]), (inputnode, baseline, [('in_file', 'in_file'), ('in_ref', 'index')]), (firstmag, n4, [('roi_file', 'input_image')]), (n4, bet, [('output_image', 'in_file')]), (bet, dilate, [('mask_file', 'in_file')]), (pha2rads, prelude, [('out_file', 'phase_file')]), (n4, prelude, [('output_image', 'magnitude_file')]), (dilate, prelude, [('out_file', 'mask_file')]), (r_params, rad2rsec, [('delta_te', 'delta_te')]), (prelude, rad2rsec, [('unwrapped_phase_file', 'in_file')]), (baseline, fmm2b0, [('out_file', 'fixed_image')]), (n4, fmm2b0, [('output_image', 'moving_image')]), (inputnode, fmm2b0, [('in_mask', 'fixed_image_mask')]), (dilate, fmm2b0, [('out_file', 'moving_image_mask')]), (baseline, applyxfm, [('out_file', 'reference_image')]), (rad2rsec, applyxfm, [('out_file', 'input_image')]), (fmm2b0, applyxfm, [('forward_transforms', 'transforms'), ('forward_invert_flags', 'invert_transform_flags')]), (applyxfm, pre_fugue, [('output_image', 'fmap_in_file')]), (inputnode, pre_fugue, [('in_mask', 'mask_file')]), (pre_fugue, demean, [('fmap_out_file', 'in_file')]), (inputnode, demean, [('in_mask', 'in_mask')]), (demean, cleanup, [('out_file', 'inputnode.in_file')]), (inputnode, cleanup, [('in_mask', 'inputnode.in_mask')]), (cleanup, addvol, [('outputnode.out_file', 'in_file')]), (inputnode, vsm, [('in_mask', 'mask_file')]), (addvol, vsm, [('out_file', 'fmap_in_file')]), (r_params, vsm, [('delta_te', 'asym_se_time')]), (eff_echo, vsm, [('eff_echo', 'dwell_time')]), (inputnode, split, [('in_file', 'in_file')]), (split, unwarp, [('out_files', 'in_file')]), (vsm, unwarp, [('shift_out_file', 'shift_in_file')]), (r_params, unwarp, [(('enc_dir', _fix_enc_dir), 'unwarp_direction')]), (unwarp, thres, [('unwarped_file', 'in_file')]), (thres, merge, [('out_file', 'in_files')]), (r_params, vsm2dfm, [(('enc_dir', _fix_enc_dir), 'inputnode.enc_dir')]), (merge, vsm2dfm, [('merged_file', 'inputnode.in_ref')]), (vsm, vsm2dfm, [('shift_out_file', 'inputnode.in_vsm')]), (merge, outputnode, [('merged_file', 'out_file')]), (vsm, outputnode, [('shift_out_file', 'out_vsm')]), (vsm2dfm, outputnode, [('outputnode.out_warp', 'out_warp')])]) return wf
# Merge registration (epi2anat) and normalisation (anat2std) merge = pe.Node(util.Merge(3), infields=['in1', 'in2', 'in3'], name='merge') # Split funcitonal by volumes before applying transformations funcSplit = pe.Node(fsl.Split(dimension='t', output_type='NIFTI_GZ'), name='funcSplit') # Resample the final reference image to the resolution of the functional resampleRef = pe.Node(ants.ApplyTransforms(args='--float', dimension=3, interpolation='BSpline', transforms='identity'), name='resampleRef') # Threshold and mask the resample reference image threshRef = pe.Node(fsl.Threshold(thresh=10, output_type='NIFTI_GZ'), name='threshRef') maskRef = pe.Node(fsl.UnaryMaths(operation='bin', output_type='NIFTI_GZ'), name='maskRef') # Transform and mask signal loss map applyTransFunc_sigloss = pe.Node(ants.ApplyTransforms( args='--float', dimension=3, interpolation='BSpline', invert_transform_flags=inv_xfm_flag), iterfield=['input_image'], name='applyTransFunc_sigloss') # Mask signal loss image with extracted brain mask
smoothed_img = smooth_img(image, kernel) smoothed_img.to_filename('smoothed_all.nii.gz') smoothed_output = os.path.abspath('smoothed_all.nii.gz') return smoothed_output nilearn_smoothing = Node(name='nilearn_smoothing', interface=Function(input_names=['image'], output_names=['smoothed_output'], function=nilearn_smoothing)) #----------------------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------------------- #mask only FA values > 0.2 to gurantee it is WM thresh_FA = Node(fsl.Threshold(), name='thresh_FA') thresh_FA.inputs.thresh = 0.2 #----------------------------------------------------------------------------------------------------- #binarize this mask binarize_FA = Node(fsl.UnaryMaths(), name='binarize_FA') binarize_FA.inputs.operation = 'bin' binarize_FA.inputs.output_datatype = 'char' #----------------------------------------------------------------------------------------------------- #randomise on the smoothed all images randomise_VBA = Node(fsl.Randomise(), name='randomise_vba') randomise_VBA.inputs.design_mat = design randomise_VBA.inputs.tcon = contrast randomise_VBA.inputs.num_perm = 10000 randomise_VBA.inputs.tfce = True
def epi_pipeline(name="susceptibility_distortion_correction_using_t1"): """ This workflow allows to correct for echo-planareinduced 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). This workflow allows also a coregistration of DWIs with their respective baseline T1-weighted structural scans in order to latter combine tracks and cortex parcelation. .. warning:: This workflow rotates the `b`-vectors' .. 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 Example ------- >>> epi = epi_pipeline() >>> epi.inputs.inputnode.DWI = 'DWI.nii' >>> epi.inputs.inputnode.bvec = 'bvec.txt' >>> epi.inputs.inputnode.T1 = 'T1.nii' >>> epi.run() # doctest: +SKIP """ import nipype.interfaces.c3 as c3 import nipype.interfaces.fsl as fsl import nipype.interfaces.utility as niu import nipype.pipeline.engine as pe from clinica.pipelines.dwi_preprocessing_using_t1.dwi_preprocessing_using_t1_utils import ( ants_combin_transform, ants_registration_syn_quick, ants_warp_image_multi_transform, change_itk_transform_type, create_jacobian_determinant_image, expend_matrix_list, rotate_bvecs, ) inputnode = pe.Node(niu.IdentityInterface(fields=["T1", "DWI", "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_2_T1 = pe.Node(interface=fsl.FLIRT(dof=6), name="flirt_B0_2_T1") flirt_b0_2_T1.inputs.interp = "spline" flirt_b0_2_T1.inputs.cost = "normmi" flirt_b0_2_T1.inputs.cost_func = "normmi" apply_xfm = pe.Node(interface=fsl.preprocess.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", ) antsRegistrationSyNQuick = pe.Node( interface=niu.Function( input_names=["fix_image", "moving_image"], output_names=[ "image_warped", "affine_matrix", "warp", "inverse_warped", "inverse_warp", ], function=ants_registration_syn_quick, ), name="antsRegistrationSyNQuick", ) c3d_flirt2ants = pe.Node(c3.C3dAffineTool(), name="fsl_reg_2_itk") c3d_flirt2ants.inputs.itk_transform = True c3d_flirt2ants.inputs.fsl2ras = True change_transform = pe.Node( niu.Function( input_names=["input_affine_file"], output_names=["updated_affine_file"], function=change_itk_transform_type, ), name="change_transform_type", ) merge_transform = pe.Node(niu.Merge(3), name="MergeTransforms") apply_transform = pe.MapNode( interface=niu.Function( input_names=["fix_image", "moving_image", "ants_warp_affine"], output_names=["out_warp_field", "out_warped"], function=ants_combin_transform, ), iterfield=["moving_image"], name="warp_filed", ) jacobian = pe.MapNode( interface=niu.Function( input_names=["imageDimension", "deformationField", "outputImage"], output_names=["outputImage"], function=create_jacobian_determinant_image, ), iterfield=["deformationField"], name="jacobian", ) jacobian.inputs.imageDimension = 3 jacobian.inputs.outputImage = "Jacobian_image.nii.gz" 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") outputnode = pe.Node( niu.IdentityInterface(fields=[ "DWI_2_T1_Coregistration_matrix", "epi_correction_deformation_field", "epi_correction_affine_transform", "epi_correction_image_warped", "DWIs_epicorrected", "warp_epi", "out_bvec", ]), name="outputnode", ) wf = pe.Workflow(name="epi_pipeline") wf.connect([(inputnode, split, [("DWI", "in_file")])]) wf.connect([(split, pick_ref, [("out_files", "inlist")])]) wf.connect([(pick_ref, flirt_b0_2_T1, [("out", "in_file")])]) wf.connect([(inputnode, flirt_b0_2_T1, [("T1", "reference")])]) wf.connect([(inputnode, rot_bvec, [("bvec", "in_bvec")])]) wf.connect([(flirt_b0_2_T1, expend_matrix, [("out_matrix_file", "in_matrix")])]) wf.connect([(inputnode, expend_matrix, [("bvec", "in_bvec")])]) wf.connect([(expend_matrix, rot_bvec, [("out_matrix_list", "in_matrix")])]) wf.connect([(inputnode, antsRegistrationSyNQuick, [("T1", "fix_image")])]) wf.connect([(flirt_b0_2_T1, antsRegistrationSyNQuick, [("out_file", "moving_image")])]) wf.connect([(inputnode, c3d_flirt2ants, [("T1", "reference_file")])]) wf.connect([(pick_ref, c3d_flirt2ants, [("out", "source_file")])]) wf.connect([(flirt_b0_2_T1, c3d_flirt2ants, [("out_matrix_file", "transform_file")])]) wf.connect([(c3d_flirt2ants, change_transform, [("itk_transform", "input_affine_file")])]) wf.connect([(antsRegistrationSyNQuick, merge_transform, [("warp", "in1")]) ]) wf.connect([(antsRegistrationSyNQuick, merge_transform, [("affine_matrix", "in2")])]) wf.connect([(change_transform, merge_transform, [("updated_affine_file", "in3")])]) wf.connect([(inputnode, apply_transform, [("T1", "fix_image")])]) wf.connect([(split, apply_transform, [("out_files", "moving_image")])]) wf.connect([(merge_transform, apply_transform, [("out", "ants_warp_affine") ])]) wf.connect([(apply_transform, jacobian, [("out_warp_field", "deformationField")])]) wf.connect([(apply_transform, jacmult, [("out_warped", "operand_files")])]) wf.connect([(jacobian, jacmult, [("outputImage", "in_file")])]) wf.connect([(jacmult, thres, [("out_file", "in_file")])]) wf.connect([(thres, merge, [("out_file", "in_files")])]) wf.connect([(merge, outputnode, [("merged_file", "DWIs_epicorrected")])]) wf.connect([( flirt_b0_2_T1, outputnode, [("out_matrix_file", "DWI_2_T1_Coregistration_matrix")], )]) wf.connect([( antsRegistrationSyNQuick, outputnode, [ ("warp", "epi_correction_deformation_field"), ("affine_matrix", "epi_correction_affine_transform"), ("image_warped", "epi_correction_image_warped"), ], )]) wf.connect([(merge_transform, outputnode, [("out", "warp_epi")])]) wf.connect([(rot_bvec, outputnode, [("out_file", "out_bvec")])]) return wf
# # data_dir + '/ROIs/lAG.nii.gz', # '/home/rcf-proj/ib2/fmri/ROIs/lIPS.nii.gz', # '/home/rcf-proj/ib2/fmri/ROIs/rIPS.nii.gz', # '/home/rcf-proj/ib2/fmri/ROIs/rLingual.nii.gz', # '/home/rcf-proj/ib2/fmri/ROIs/ACC.nii.gz', # # ] #%% #estimate a Random-FX level model flameo = pe.MapNode(interface=fsl.FLAMEO(run_mode='flame1', mask_file = mask), name="flameo", iterfield=['cope_file','var_cope_file']) ## z=1.645 was changed to z=3.1 thresholdPositive = pe.MapNode(interface=fsl.Threshold(thresh = 3.1, direction = 'below'), name = 'thresholdPositive', iterfield=['in_file']) ## z=1.645 was changed to z=3.1 thresholdNegative = pe.MapNode(interface=fsl.Threshold(thresh = 3.1, direction = 'above'), name = 'thresholdNegative', iterfield=['in_file']) thresholdCombined = pe.MapNode(interface=fsl.BinaryMaths(operation = 'add'), name = 'thresholdCombined', iterfield=['in_file', 'operand_file']) #ROIs = pe.MapNode(interface = fsl.ApplyMask(), # name ='ROIs',
def create_resting_preproc(name='restpreproc'): """Create a "resting" time series preprocessing workflow The noise removal is based on Behzadi et al. (2007) Parameters ---------- name : name of workflow (default: restpreproc) Inputs:: inputspec.func : functional run (filename or list of filenames) Outputs:: outputspec.noise_mask_file : voxels used for PCA to derive noise components outputspec.filtered_file : bandpass filtered and noise-reduced time series Example ------- >>> TR = 3.0 >>> wf = create_resting_preproc() >>> wf.inputs.inputspec.func = 'f3.nii' >>> wf.inputs.inputspec.num_noise_components = 6 >>> wf.inputs.inputspec.highpass_sigma = 100/(2*TR) >>> wf.inputs.inputspec.lowpass_sigma = 12.5/(2*TR) >>> wf.run() # doctest: +SKIP """ restpreproc = pe.Workflow(name=name) # Define nodes inputnode = pe.Node(interface=util.IdentityInterface(fields=[ 'func', 'num_noise_components', 'highpass_sigma', 'lowpass_sigma' ]), name='inputspec') outputnode = pe.Node(interface=util.IdentityInterface(fields=[ 'noise_mask_file', 'filtered_file', ]), name='outputspec') slicetimer = pe.Node(fsl.SliceTimer(), name='slicetimer') realigner = create_realign_flow() tsnr = pe.Node(TSNR(regress_poly=2), name='tsnr') getthresh = pe.Node(interface=fsl.ImageStats(op_string='-p 98'), name='getthreshold') threshold_stddev = pe.Node(fsl.Threshold(), name='threshold') compcor = pe.Node(util.Function( input_names=['realigned_file', 'noise_mask_file', 'num_components'], output_names=['noise_components'], function=extract_noise_components), name='compcorr') remove_noise = pe.Node(fsl.FilterRegressor(filter_all=True), name='remove_noise') bandpass_filter = pe.Node(fsl.TemporalFilter(), name='bandpass_filter') # Define connections restpreproc.connect(inputnode, 'func', slicetimer, 'in_file') restpreproc.connect(slicetimer, 'slice_time_corrected_file', realigner, 'inputspec.func') restpreproc.connect(realigner, 'outputspec.realigned_file', tsnr, 'in_file') restpreproc.connect(tsnr, 'stddev_file', threshold_stddev, 'in_file') restpreproc.connect(tsnr, 'stddev_file', getthresh, 'in_file') restpreproc.connect(getthresh, 'out_stat', threshold_stddev, 'thresh') restpreproc.connect(realigner, 'outputspec.realigned_file', compcor, 'realigned_file') restpreproc.connect(threshold_stddev, 'out_file', compcor, 'noise_mask_file') restpreproc.connect(inputnode, 'num_noise_components', compcor, 'num_components') restpreproc.connect(tsnr, 'detrended_file', remove_noise, 'in_file') restpreproc.connect(compcor, 'noise_components', remove_noise, 'design_file') restpreproc.connect(inputnode, 'highpass_sigma', bandpass_filter, 'highpass_sigma') restpreproc.connect(inputnode, 'lowpass_sigma', bandpass_filter, 'lowpass_sigma') restpreproc.connect(remove_noise, 'out_file', bandpass_filter, 'in_file') restpreproc.connect(threshold_stddev, 'out_file', outputnode, 'noise_mask_file') restpreproc.connect(bandpass_filter, 'out_file', outputnode, 'filtered_file') return restpreproc
def b0_flirt_pipeline(num_b0s, name="b0_coregistration"): """ Rigid registration of the B0 dataset onto the first volume. Rigid registration is achieved using FLIRT and the normalized correlation. Args: num_b0s (int): Number of the B0 volumes in the dataset. name (str): Name of the workflow. Inputnode: in_file(str): B0 dataset. Outputnode out_b0_reg(str): The set of B0 volumes registered to the first volume. Returns: The workflow """ import nipype.interfaces.utility as niu import nipype.pipeline.engine as pe from nipype.interfaces import fsl from clinica.utils.dwi import merge_volumes_tdim inputnode = pe.Node(niu.IdentityInterface(fields=["in_file"]), name="inputnode") fslroi_ref = pe.Node(fsl.ExtractROI(args="0 1"), name="b0_reference") tsize = num_b0s - 1 fslroi_moving = pe.Node(fsl.ExtractROI(args="1 " + str(tsize)), name="b0_moving") split_moving = pe.Node(fsl.Split(dimension="t"), name="split_b0_moving") bet_ref = pe.Node(fsl.BET(frac=0.3, mask=True, robust=True), name="bet_ref") dilate = pe.Node( fsl.maths.MathsCommand(nan2zeros=True, args="-kernel sphere 5 -dilM"), name="mask_dilate", ) flirt = pe.MapNode( fsl.FLIRT( interp="spline", dof=6, bins=50, save_log=True, cost="corratio", cost_func="corratio", padding_size=10, searchr_x=[-4, 4], searchr_y=[-4, 4], searchr_z=[-4, 4], fine_search=1, coarse_search=10, ), name="b0_co_registration", iterfield=["in_file"], ) merge = pe.Node(fsl.Merge(dimension="t"), name="merge_registered_b0s") thres = pe.MapNode(fsl.Threshold(thresh=0.0), iterfield=["in_file"], name="remove_negative") insert_ref = pe.Node( niu.Function( input_names=["in_file1", "in_file2"], output_names=["out_file"], function=merge_volumes_tdim, ), name="concat_ref_moving", ) outputnode = pe.Node( niu.IdentityInterface(fields=["out_file", "out_xfms"]), name="outputnode") wf = pe.Workflow(name=name) wf.connect([ (inputnode, fslroi_ref, [("in_file", "in_file")]), (inputnode, fslroi_moving, [("in_file", "in_file")]), (fslroi_moving, split_moving, [("roi_file", "in_file")]), (fslroi_ref, bet_ref, [("roi_file", "in_file")]), (bet_ref, dilate, [("mask_file", "in_file")]), (dilate, flirt, [("out_file", "ref_weight"), ("out_file", "in_weight")]), (fslroi_ref, flirt, [("roi_file", "reference")]), (split_moving, flirt, [("out_files", "in_file")]), (flirt, thres, [("out_file", "in_file")]), (thres, merge, [("out_file", "in_files")]), (merge, insert_ref, [("merged_file", "in_file2")]), (fslroi_ref, insert_ref, [("roi_file", "in_file1")]), (insert_ref, outputnode, [("out_file", "out_file")]), (flirt, outputnode, [("out_matrix_file", "out_xfms")]), ]) return wf