def allineate(self, in_file, out_file=None, suffix=None, final="nearestneighbor", mat=None, base=None, args=""): in_file, out_file = self.FuncHandler(in_file, out_file, suffix) myalline = afni.Allineate(in_file=in_file, out_file=out_file) #https://nipype.readthedocs.io/en/latest/interfaces/generated/interfaces.afni/preprocess.html#allineate myalline.inputs.args = args #myalline.inputs.num_threads = cpu_count() if mat is not None: mat, _ = self.FuncHandler(mat, out_file, suffix) myalline.inputs.in_matrix = mat if base is not None: myalline.inputs.reference = base myalline.run() #remove temp files if type(in_file) == models.BIDSImageFile: in_file = os.path.join(self._output_dir, in_file.filename) if "_desc-temp" in in_file: os.remove(in_file)
def alllineate_afni_template_space(in_file, ref_img_file, transfo_file): # align_NMT align_NMT = afni.Allineate() align_NMT.inputs.final_interpolation = "nearestneighbour" align_NMT.inputs.overwrite = True align_NMT.inputs.outputtype = "NIFTI_GZ" align_NMT.inputs.in_file = in_file align_NMT.inputs.reference = ref_img_file align_NMT.inputs.in_matrix = transfo_file output_file = align_NMT.run().outputs.out_file print(output_file) return output_file
def create_reg_seg_pipe(name="reg_seg_pipe"): reg_seg_pipe = pe.Workflow(name=name) # creating inputnode inputnode = pe.Node( niu.IdentityInterface(fields=['native_segmented_file', 'transfo_file', 'ref_image']), name='inputnode') # align_seg align_seg = pe.Node( afni.Allineate(), name="align_seg", iterfield=['in_file']) align_seg.inputs.final_interpolation = "nearestneighbour" align_seg.inputs.overwrite = True align_seg.inputs.outputtype = "NIFTI_GZ" reg_seg_pipe.connect(inputnode, 'native_segmented_file', align_seg, "in_file") reg_seg_pipe.connect(inputnode, 'ref_image', align_seg, "reference") reg_seg_pipe.connect(inputnode, 'transfo_file', align_seg, "in_matrix") # align_gm split_seg_mask = pe.Node( niu.Function(input_names=['nii_file'], output_names=['list_binary_masks'], function=split_indexed_mask), name="split_seg_mask") reg_seg_pipe.connect(align_seg, 'out_file', split_seg_mask, "nii_file") outputnode = pe.Node( niu.IdentityInterface(fields=['norm_seg', 'norm_gm', 'norm_wm', 'norm_csf']), name='outputnode') reg_seg_pipe.connect(align_seg, 'out_file', outputnode, "norm_seg") reg_seg_pipe.connect(split_seg_mask, ('out_file', get_elem, 0), outputnode, "norm_gm") reg_seg_pipe.connect(split_seg_mask, ('out_file', get_elem, 1), outputnode, "norm_wm") reg_seg_pipe.connect(split_seg_mask, ('out_file', get_elem, 2), outputnode, "norm_csf") return reg_seg_pipe
def test_allineate(): input_map = dict( args=dict(argstr='%s', ), environ=dict(usedefault=True, ), ignore_exception=dict(usedefault=True, ), in_file=dict( argstr='-source %s', mandatory=True, ), in_matrix=dict(argstr='-1Dmatrix_apply %s', ), out_file=dict(argstr='-prefix %s'), outputtype=dict(), ) instance = afni.Allineate() for key, metadata in input_map.items(): for metakey, value in metadata.items(): yield assert_equal, getattr(instance.inputs.traits()[key], metakey), value
def _realign(func_filename, write_dir, caching=False, terminal_output='allatonce', environ=None): if environ is None: environ = {'AFNI_DECONFLICT': 'OVERWRITE'} if caching: memory = Memory(write_dir) clip_level = memory.cache(afni.ClipLevel) threshold = memory.cache(fsl.Threshold) volreg = memory.cache(afni.Volreg) allineate = memory.cache(afni.Allineate) copy = memory.cache(afni.Copy) copy_geom = memory.cache(fsl.CopyGeom) tstat = memory.cache(afni.TStat) for step in [threshold, volreg, allineate, tstat, copy, copy_geom]: step.interface().set_default_terminal_output(terminal_output) else: clip_level = afni.ClipLevel().run threshold = fsl.Threshold(terminal_output=terminal_output).run volreg = afni.Volreg(terminal_output=terminal_output).run allineate = afni.Allineate(terminal_output=terminal_output).run copy = afni.Copy(terminal_output=terminal_output).run copy_geom = fsl.CopyGeom(terminal_output=terminal_output).run tstat = afni.TStat(terminal_output=terminal_output).run out_clip_level = clip_level(in_file=func_filename) out_threshold = threshold(in_file=func_filename, thresh=out_clip_level.outputs.clip_val, out_file=fname_presuffix(func_filename, suffix='_thresholded', newpath=write_dir)) thresholded_filename = out_threshold.outputs.out_file out_volreg = volreg( # XXX dfile not saved in_file=thresholded_filename, out_file=fname_presuffix(thresholded_filename, suffix='_volreg', newpath=write_dir), environ=environ, oned_file=fname_presuffix(thresholded_filename, suffix='_volreg.1Dfile.1D', use_ext=False, newpath=write_dir), oned_matrix_save=fname_presuffix(thresholded_filename, suffix='_volreg.aff12.1D', use_ext=False, newpath=write_dir)) # Apply the registration to the whole head out_allineate = allineate(in_file=func_filename, master=func_filename, in_matrix=out_volreg.outputs.oned_matrix_save, out_file=fname_presuffix(func_filename, suffix='_volreg', newpath=write_dir), environ=environ) # 3dAllineate removes the obliquity. This is not a good way to readd it as # removes motion correction info in the header if it were an AFNI file...as # it happens it's NIfTI which does not store that so irrelevant! out_copy = copy(in_file=out_allineate.outputs.out_file, out_file=fname_presuffix(out_allineate.outputs.out_file, suffix='_oblique', newpath=write_dir), environ=environ) out_copy_geom = copy_geom(dest_file=out_copy.outputs.out_file, in_file=out_volreg.outputs.out_file) oblique_allineated_filename = out_copy_geom.outputs.out_file # Create a (hopefully) nice mean image for use in the registration out_tstat = tstat(in_file=oblique_allineated_filename, args='-mean', out_file=fname_presuffix(oblique_allineated_filename, suffix='_tstat', newpath=write_dir), environ=environ) # Remove intermediate outputs if not caching: for output_file in [ thresholded_filename, out_volreg.outputs.oned_matrix_save, out_volreg.outputs.out_file, out_volreg.outputs.md1d_file, out_allineate.outputs.out_file ]: os.remove(output_file) return (oblique_allineated_filename, out_tstat.outputs.out_file, out_volreg.outputs.oned_file)
def create_pipeline_graph(pipeline_name, graph_file, graph_kind='hierarchical'): """Creates pipeline graph for a given piepline. Parameters ---------- pipeline_name : one of {'anat_to_common_rigid', 'anat_to_common_affine', 'anat_to_common_nonlinear'} Pipeline name. graph_file : str. Path to save the graph image to. graph_kind : one of {'orig', 'hierarchical', 'flat', 'exec', 'colored'}, optional. The kind of the graph, passed to nipype.pipeline.workflows.Workflow().write_graph """ pipeline_names = ['anats_to_common_rigid', 'anats_to_common_affine', 'anats_to_common_nonlinear'] if pipeline_name not in pipeline_names: raise NotImplementedError( 'Pipeline name must be one of {0}, you entered {1}'.format( pipeline_names, pipeline_name)) graph_kinds = ['orig', 'hierarchical', 'flat', 'exec', 'colored'] if graph_kind not in graph_kinds: raise ValueError( 'Graph kind must be one of {0}, you entered {1}'.format( graph_kinds, graph_kind)) workflow = pe.Workflow(name=pipeline_name) ####################################################################### # Specify rigid body registration pipeline steps unifize = pe.Node(interface=afni.Unifize(), name='bias_correct') clip_level = pe.Node(interface=afni.ClipLevel(), name='compute_mask_threshold') compute_mask = pe.Node(interface=interfaces.MathMorphoMask(), name='compute_brain_mask') apply_mask = pe.Node(interface=afni.Calc(), name='apply_brain_mask') center_mass = pe.Node(interface=afni.CenterMass(), name='compute_and_set_cm_in_header') refit_copy = pe.Node(afni.Refit(), name='copy_cm_in_header') tcat1 = pe.Node(afni.TCat(), name='concatenate_across_individuals1') tstat1 = pe.Node(afni.TStat(), name='compute_average1') undump = pe.Node(afni.Undump(), name='create_empty_template') refit_set = pe.Node(afni.Refit(), name='set_cm_in_header') resample1 = pe.Node(afni.Resample(), name='resample1') resample2 = pe.Node(afni.Resample(), name='resample2') shift_rotate = pe.Node(afni.Allineate(), name='shift_rotate') apply_allineate1 = pe.Node(afni.Allineate(), name='apply_transform1') tcat2 = pe.Node(afni.TCat(), name='concatenate_across_individuals2') tstat2 = pe.Node(afni.TStat(), name='compute_average2') tcat3 = pe.Node(afni.TCat(), name='concatenate_across_individuals3') tstat3 = pe.Node(afni.TStat(), name='compute_average3') workflow.add_nodes([unifize, clip_level, compute_mask, apply_mask, center_mass, refit_copy, tcat1, tstat1, undump, refit_set, resample1, resample2, shift_rotate, apply_allineate1, tcat2, tstat2, tcat3, tstat3]) ####################################################################### # and connections workflow.connect(unifize, 'out_file', clip_level, 'in_file') workflow.connect(clip_level, 'clip_val', compute_mask, 'intensity_threshold') workflow.connect(unifize, 'out_file', compute_mask, 'in_file') workflow.connect(compute_mask, 'out_file', apply_mask, 'in_file_a') workflow.connect(unifize, 'out_file', apply_mask, 'in_file_b') workflow.connect(apply_mask, 'out_file', center_mass, 'in_file') workflow.connect(unifize, 'out_file', refit_copy, 'in_file') workflow.connect(center_mass, 'out_file', refit_copy, 'duporigin_file') workflow.connect(center_mass, 'out_file', tcat1, 'in_files') workflow.connect(tcat1, 'out_file', tstat1, 'in_file') workflow.connect(tstat1, 'out_file', undump, 'in_file') workflow.connect(undump, 'out_file', refit_set, 'in_file') workflow.connect(refit_set, 'out_file', resample1, 'master') workflow.connect(refit_copy, 'out_file', resample1, 'in_file') workflow.connect(refit_set, 'out_file', resample2, 'master') workflow.connect(center_mass, 'out_file', resample2, 'in_file') workflow.connect(resample2, 'out_file', tcat2, 'in_files') workflow.connect(tcat2, 'out_file', tstat2, 'in_file') workflow.connect(tstat2, 'out_file', shift_rotate, 'reference') workflow.connect(resample2, 'out_file', shift_rotate, 'in_file') workflow.connect(tstat2, 'out_file', apply_allineate1, 'master') workflow.connect(resample1, 'out_file', apply_allineate1, 'in_file') workflow.connect(shift_rotate, 'out_matrix', apply_allineate1, 'in_matrix') workflow.connect(apply_allineate1, 'out_file', tcat3, 'in_files') workflow.connect(tcat3, 'out_file', tstat3, 'in_file') if pipeline_name in ['anats_to_common_affine', 'anat_to_common_nonlinear']: mask = pe.Node(afni.MaskTool(), name='generate_count_mask') allineate = pe.Node(afni.Allineate(), name='allineate') catmatvec = pe.Node(afni.CatMatvec(), name='concatenate_transforms') apply_allineate2 = pe.Node(afni.Allineate(), name='apply_transform2') tcat3 = pe.Node( afni.TCat(), name='concatenate_across_individuals4') tstat3 = pe.Node(afni.TStat(), name='compute_average4') workflow.add_nodes([mask, allineate, catmatvec, apply_allineate2, tcat3, tstat3]) workflow.connect(tcat2, 'out_file', mask, 'in_file') workflow.connect(mask, 'out_file', allineate, 'weight') workflow.connect(apply_allineate1, 'out_file', allineate, 'in_file') workflow.connect(allineate, 'out_matrix', catmatvec, 'in_file') #XXX how can we enter multiple files ? workflow.connect(catmatvec, 'out_file', apply_allineate2, 'in_matrix') workflow.connect(resample1, 'out_file', apply_allineate2, 'in_file') workflow.connect(apply_allineate2, 'out_file', tcat3, 'in_files') workflow.connect(tcat3, 'out_file', tstat3, 'in_file') if pipeline_name == 'anats_to_common_nonlinear': pass graph_file_root, graph_file_ext = os.path.splitext(graph_file) if graph_file_ext: _ = workflow.write_graph(graph2use=graph_kind, format=graph_file_ext[1:], dotfilename=graph_file_root) else: _ = workflow.write_graph(graph2use=graph_kind, dotfilename=graph_file_root)
def create_register_NMT_pipe(params_template, params={}, name="register_NMT_pipe"): """ Description: Register template to anat with the script NMT_subject_align, and then apply it to tissues list_priors Inputs: inputnode: T1: T1 file name indiv_params: dict with individuals parameters for some nodes arguments: params_template: dictionary of info about template params: dictionary of node sub-parameters (from a json file) name: pipeline name (default = "register_NMT_pipe") Outputs: norm_intensity.output_image: filled mask after erode align_seg_csf.out_file: csf template tissue in subject space align_seg_gm.out_file: grey matter template tissue in subject space align_seg_wm.out_file: white matter template tissue in subject space """ register_NMT_pipe = pe.Workflow(name=name) # creating inputnode inputnode = pe.Node(niu.IdentityInterface(fields=['T1', 'indiv_params']), name='inputnode') # N4 intensity normalization over brain norm_intensity = NodeParams(ants.N4BiasFieldCorrection(), params=parse_key(params, "norm_intensity"), name='norm_intensity') register_NMT_pipe.connect(inputnode, 'T1', norm_intensity, "input_image") register_NMT_pipe.connect(inputnode, ('indiv_params', parse_key, "norm_intensity"), norm_intensity, "indiv_params") deoblique = pe.Node(afni.Refit(deoblique=True), name="deoblique") register_NMT_pipe.connect(norm_intensity, 'output_image', deoblique, "in_file") # align subj to nmt (with NMT_subject_align, wrapped version with nodes) NMT_subject_align = pe.Node(NMTSubjectAlign(), name='NMT_subject_align') register_NMT_pipe.connect(deoblique, 'out_file', NMT_subject_align, "T1_file") NMT_subject_align.inputs.NMT_SS_file = params_template["template_brain"] # align_masks # "overwrap" of NwarpApply, with specifying the outputs as wished list_priors = [ params_template["template_head"], params_template["template_csf"], params_template["template_gm"], params_template["template_wm"] ] align_masks = pe.Node(NwarpApplyPriors(), name='align_masks') align_masks.inputs.in_file = list_priors align_masks.inputs.out_file = list_priors align_masks.inputs.interp = "NN" align_masks.inputs.args = "-overwrite" register_NMT_pipe.connect(NMT_subject_align, 'shft_aff_file', align_masks, 'master') register_NMT_pipe.connect(NMT_subject_align, 'warpinv_file', align_masks, "warp") # align_NMT align_NMT = pe.Node(afni.Allineate(), name="align_NMT", iterfield=['in_file']) align_NMT.inputs.final_interpolation = "nearestneighbour" align_NMT.inputs.overwrite = True align_NMT.inputs.outputtype = "NIFTI_GZ" register_NMT_pipe.connect(align_masks, ('out_file', get_elem, 0), align_NMT, "in_file") # -source register_NMT_pipe.connect(norm_intensity, 'output_image', align_NMT, "reference") # -base register_NMT_pipe.connect(NMT_subject_align, 'inv_transfo_file', align_NMT, "in_matrix") # -1Dmatrix_apply # seg_csf align_seg_csf = pe.Node(afni.Allineate(), name="align_seg_csf", iterfield=['in_file']) align_seg_csf.inputs.final_interpolation = "nearestneighbour" align_seg_csf.inputs.overwrite = True align_seg_csf.inputs.outputtype = "NIFTI_GZ" register_NMT_pipe.connect(align_masks, ('out_file', get_elem, 1), align_seg_csf, "in_file") # -source register_NMT_pipe.connect(norm_intensity, 'output_image', align_seg_csf, "reference") # -base register_NMT_pipe.connect(NMT_subject_align, 'inv_transfo_file', align_seg_csf, "in_matrix") # -1Dmatrix_apply # seg_gm align_seg_gm = pe.Node(afni.Allineate(), name="align_seg_gm", iterfield=['in_file']) align_seg_gm.inputs.final_interpolation = "nearestneighbour" align_seg_gm.inputs.overwrite = True align_seg_gm.inputs.outputtype = "NIFTI_GZ" register_NMT_pipe.connect(align_masks, ('out_file', get_elem, 2), align_seg_gm, "in_file") # -source register_NMT_pipe.connect(norm_intensity, 'output_image', align_seg_gm, "reference") # -base register_NMT_pipe.connect(NMT_subject_align, 'inv_transfo_file', align_seg_gm, "in_matrix") # -1Dmatrix_apply # seg_wm align_seg_wm = pe.Node(afni.Allineate(), name="align_seg_wm", iterfield=['in_file']) align_seg_wm.inputs.final_interpolation = "nearestneighbour" align_seg_wm.inputs.overwrite = True align_seg_wm.inputs.outputtype = "NIFTI_GZ" register_NMT_pipe.connect(align_masks, ('out_file', get_elem, 3), align_seg_wm, "in_file") # -source register_NMT_pipe.connect(norm_intensity, 'output_image', align_seg_wm, "reference") # -base register_NMT_pipe.connect(NMT_subject_align, 'inv_transfo_file', align_seg_wm, "in_matrix") # -1Dmatrix_apply return register_NMT_pipe
def __init__(self, settings): # call base constructor super().__init__(settings) # define input/output node self.set_input(['T1', 'orig', 'brainmask']) self.set_output(['T1_skullstrip', 'allineate_freesurfer2anat']) # define datasink substitutions self.set_subs([('_maskop40', ''), ('_calc_calc_calc_calc_calc', '')]) # 3dAllineate (FSorig) self.allineate_orig = MapNode(afni.Allineate( out_matrix='FSorig2MPR.aff12.1D', overwrite=True, outputtype='NIFTI_GZ'), iterfield=['in_file', 'reference'], name='3dallineate_orig') # 3dAllineate (FSbrainmask) self.allineate_bm = MapNode( afni.Allineate(overwrite=True, no_pad=True, outputtype='NIFTI_GZ'), iterfield=['in_file', 'reference', 'in_matrix'], name='3dallineate_brainmask') # skullstrip mprage (afni) self.afni_skullstrip = MapNode(afni.SkullStrip(args="-orig_vol", outputtype="NIFTI_GZ"), iterfield=['in_file'], name='afni_skullstrip') # 3dcalc operations for achieving final mask self.maskop1 = MapNode(afni.Calc(expr='step(a)', overwrite=True, outputtype='NIFTI_GZ'), iterfield=['in_file_a'], name='maskop1') self.maskop2 = [] for n in range(3): self.maskop2.append( MapNode(afni.Calc( args='-b a+i -c a-i -d a+j -e a-j -f a+k -g a-k', expr='ispositive(a+b+c+d+e+f+g)', overwrite=True, outputtype='NIFTI_GZ'), iterfield=['in_file_a'], name='maskop2_{}'.format(n))) # Inline function for setting up to copy IJK_TO_DICOM_REAL file attribute self.refit_setup = MapNode(Function(input_names=['noskull_T1'], output_names=['refit_input'], function=lambda noskull_T1: (noskull_T1, 'IJK_TO_DICOM_REAL')), iterfield=['noskull_T1'], name='refitsetup') # 3dRefit self.refit = MapNode(afni.Refit(), iterfield=['in_file', 'atrcopy'], name='3drefit') # 3dcalc for uniform intensity self.uniform = MapNode(afni.Calc(expr='a*and(b,b)', overwrite=True, outputtype='NIFTI_GZ'), iterfield=['in_file_a', 'in_file_b'], name='uniformintensity') # skullstrip mprage (fsl) self.fsl_skullstrip = MapNode(fsl.BET(), iterfield=['in_file'], name='fsl_skullstrip') self.maskop3 = MapNode( afni.Calc(expr='or(a,b,c)', overwrite=True, outputtype='NIFTI_GZ'), iterfield=['in_file_a', 'in_file_b', 'in_file_c'], name='maskop3') self.maskop4 = MapNode( afni.Calc(expr='c*and(a,b)', overwrite=True, outputtype='NIFTI_GZ'), iterfield=['in_file_a', 'in_file_b', 'in_file_c'], name='maskop4') # Convert from list to string input self.select0T1 = Node(Function(input_names=['T1_list'], output_names=['T1_0'], function=lambda T1_list: T1_list[0]), name='select0T1') # apply bias field correction self.biasfieldcorrect = Node(ants.N4BiasFieldCorrection( num_threads=settings['num_threads'], copy_header=True), name='biasfieldcorrect')
io_S3DataGrabber.inputs.template = 'sub-01/anat/sub-01_T1w.nii.gz' io_S3DataGrabber.inputs.anon = True io_S3DataGrabber.inputs.bucket_path = 'ds000101/ds000101_R2.0.0/uncompressed/' io_S3DataGrabber.inputs.local_directory = '/tmp' #Wraps command **bet** fsl_BET = pe.Node(interface=fsl.BET(), name='fsl_BET', iterfield=['']) #Generic datasink module to store structured outputs io_DataSink = pe.Node(interface=io.DataSink(), name='io_DataSink', iterfield=['']) io_DataSink.inputs.base_directory = '/tmp' #Wraps command **3dAllineate** afni_Allineate = pe.Node(interface=afni.Allineate(), name='afni_Allineate', iterfield=['']) #Create a workflow to connect all those nodes analysisflow = nipype.Workflow('MyWorkflow') analysisflow.connect(io_S3DataGrabber, "outfiles", fsl_BET, "in_file") analysisflow.connect(fsl_BET, "out_file", afni_Allineate, "in_file") analysisflow.connect(afni_Allineate, "out_file", io_DataSink, "BET_results") #Run the workflow plugin = 'MultiProc' #adjust your desired plugin here plugin_args = {'n_procs': 1} #adjust to your number of cores analysisflow.write_graph(graph2use='flat', format='png', simple_form=False) analysisflow.run(plugin=plugin, plugin_args=plugin_args)
def _rigid_body_register(moving_head_file, reference_head_file, moving_brain_file, reference_brain_file, write_dir=None, verbose=True, caching=False, terminal_output='allatonce', environ=None): # XXX: add verbosity if write_dir is None: write_dir = os.path.dirname(moving_head_file) if environ is None: environ = {'AFNI_DECONFLICT': 'OVERWRITE'} if caching: memory = Memory(write_dir) allineate = memory.cache(afni.Allineate) allineate2 = memory.cache(afni.Allineate) catmatvec = memory.cache(afni.CatMatvec) for step in [allineate, allineate2]: step.interface().set_default_terminal_output(terminal_output) else: allineate = afni.Allineate(terminal_output=terminal_output).run allineate2 = afni.Allineate(terminal_output=terminal_output).run catmatvec = afni.CatMatvec().run output_files = [moving_brain_file, reference_brain_file] # Compute the transformation from functional to anatomical brain # XXX: why in this sense # XXX: caching does not work if out_matrix # path is absolute out_matrix = fname_presuffix(reference_brain_file, suffix='_shr.aff12.1D', use_ext=False) if caching: out_matrix = os.path.basename(out_matrix) out_allineate = allineate2(in_file=reference_brain_file, reference=moving_brain_file, out_matrix=out_matrix, center_of_mass='', warp_type='shift_rotate', out_file='%s_shr', environ=environ, verbose=verbose, outputtype='NIFTI_GZ') rigid_transform_file = out_allineate.outputs.out_matrix output_files.append(out_allineate.outputs.out_file) # apply the inverse transform to register the anatomical to the func out_catmatvec = catmatvec(in_file=[(rigid_transform_file, 'I')], oneline=True, out_file=fname_presuffix(rigid_transform_file, suffix='INV', newpath=write_dir), environ=environ) output_files.append(out_catmatvec.outputs.out_file) out_allineate_apply = allineate(in_file=moving_head_file, master=reference_head_file, in_matrix=out_catmatvec.outputs.out_file, out_file=fname_presuffix( moving_head_file, suffix='_shr', newpath=write_dir), environ=environ) # Remove intermediate output if not caching: for output_file in output_files: os.remove(output_file) return out_allineate_apply.outputs.out_file, rigid_transform_file
def _apply_transforms(to_register_filename, target_filename, write_dir, transforms, transformed_filename=None, transforms_kind='nonlinear', interpolation=None, voxel_size=None, inverse=False, caching=False, verbose=True): """ Applies successive transforms to a given image to put it in template space. Parameters ---------- to_register_filename : str Path to the source file to register. target_filename : str Reference file to register to. transforms : list List of transforms in order of 3dNWarpApply application: first must one must be in the target space and last one must be in the source space. transformed_filename : str, optional Path to the output registered file inverse : bool, optional If True, after the transforms composition is computed, invert it. If the input transforms would take a dataset from space A to B, then the inverted transform will do the reverse. interpolation : one of {'nearestneighbour', 'linear', 'cubic', 'quintic', 'wsinc5'} or None, optional Interpolation type. If None, AFNI defaults are used. voxel_size : 3-tuple of floats, optional Voxel size of the registered functional, in mm. caching : bool, optional Wether or not to use caching. verbose : bool, optional If True, all steps are verbose. Note that caching implies some verbosity in any case. """ environ = {'AFNI_DECONFLICT': 'OVERWRITE'} if verbose: terminal_output = 'allatonce' else: terminal_output = 'none' if caching: memory = Memory(write_dir) catmatvec = memory.cache(afni.CatMatvec) allineate = memory.cache(afni.Allineate) warp_apply = memory.cache(afni.NwarpApply) resample = memory.cache(afni.Resample) for step in [resample, allineate, warp_apply]: step.interface().set_default_terminal_output(terminal_output) else: resample = afni.Resample(terminal_output=terminal_output).run catmatvec = afni.CatMatvec().run allineate = afni.Allineate(terminal_output=terminal_output).run warp_apply = afni.NwarpApply(terminal_output=terminal_output).run if transformed_filename is None: target_basename = os.path.basename(target_filename) target_basename = os.path.splitext(target_basename)[0] target_basename = os.path.splitext(target_basename)[0] transformed_filename = fname_presuffix(to_register_filename, suffix='_to_' + target_basename, newpath=write_dir) if voxel_size is None: resampled_target_filename = target_filename else: out_resample = resample(in_file=target_filename, voxel_size=voxel_size, out_file=fname_presuffix(target_filename, suffix='_resampled', newpath=write_dir), environ=environ) resampled_target_filename = out_resample.outputs.out_file if transforms_kind is not 'nonlinear': affine_transform_filename = fname_presuffix(transformed_filename, suffix='.aff12.1D', use_ext=False) out_catmatvec = catmatvec(in_file=[(transform, 'ONELINE') for transform in transforms], oneline=True, out_file=affine_transform_filename, environ=environ) if inverse: affine_transform_filename = fname_presuffix(transformed_filename, suffix='_INV.aff12.1D', use_ext=False) _ = catmatvec(in_file=[(out_catmatvec.outputs.out_file, 'I')], oneline=True, out_file=affine_transform_filename, environ=environ) if interpolation is None: _ = allineate(in_file=to_register_filename, master=resampled_target_filename, in_matrix=affine_transform_filename, out_file=transformed_filename, environ=environ) else: _ = allineate(in_file=to_register_filename, master=resampled_target_filename, in_matrix=affine_transform_filename, final_interpolation=interpolation, out_file=transformed_filename, environ=environ) else: warp = "'" warp += " ".join(transforms) warp += "'" if interpolation is None: _ = warp_apply(in_file=to_register_filename, master=resampled_target_filename, warp=warp, inv_warp=inverse, out_file=transformed_filename, environ=environ) else: _ = warp_apply(in_file=to_register_filename, master=resampled_target_filename, warp=warp, inv_warp=inverse, interp=interpolation, out_file=transformed_filename, environ=environ) # XXX obliquity information is lost if resampling is done transformed_filename = fix_obliquity(transformed_filename, resampled_target_filename, verbose=verbose, caching=caching, caching_dir=write_dir, environ=environ) return transformed_filename
def init_single_subject_wf( name, output_dir, layout, bold_mag_files, bold_mag_metadata, bold_phase_files, bold_phase_metadata, sbref_mag_files, sbref_mag_metadata, sbref_phase_files, sbref_phase_metadata, t1w_files, t1w_metadata, t2w_files, t2w_metadata, ): workflow = pe.Workflow(name=name) # name the nodes inputnode = pe.Node( niu.IdentityInterface(fields=[ 'bold_mag_files', 'bold_mag_metadata', 'bold_phase_files', 'bold_phase_metadata', 'sbref_mag_files', 'sbref_mag_metadata', 'sbref_phase_files', 'sbref_phase_metadata', 't1w_files', 't1w_metadata', 't2w_files', 't2w_metadata', ]), name='inputnode', iterables=[ ('bold_mag_files', bold_mag_files), ('bold_mag_metadata', bold_mag_metadata), ('bold_phase_files', bold_phase_files), ('bold_phase_metadata', bold_phase_metadata), ('sbref_mag_files', sbref_mag_files), ('sbref_mag_metadata', sbref_mag_metadata), ('sbref_phase_files', sbref_phase_files), ('sbref_phase_metadata', sbref_phase_metadata), ], synchronize=True, ) inputnode.inputs.t1w_files = t1w_files inputnode.inputs.t1w_metadata = t1w_metadata inputnode.inputs.t2w_files = t2w_files inputnode.inputs.t2w_metadata = t2w_metadata outputnode = pe.Node( niu.IdentityInterface(fields=[ 'preproc_bold_files', 'preproc_phase_files', 'motion_parameters' ]), name='outputnode', ) # Generate single-band reference image-based field maps sbref_phdiff_wf = init_phdiff_wf(name='sbref_phdiff_wf', create_phasediff=True, omp_nthreads=1, fmap_bspline=None) workflow.connect( inputnode, ('sbref_phase_files', pick_first), sbref_phdiff_wf, 'inputnode.phase1', ) workflow.connect( inputnode, ('sbref_phase_files', pick_second), sbref_phdiff_wf, 'inputnode.phase2', ) workflow.connect( inputnode, ('sbref_mag_files', pick_first), sbref_phdiff_wf, 'inputnode.magnitude', ) workflow.connect( inputnode, ('sbref_phase_metadata', pick_first), sbref_phdiff_wf, 'inputnode.phase1_metadata', ) workflow.connect( inputnode, ('sbref_phase_metadata', pick_second), sbref_phdiff_wf, 'inputnode.phase2_metadata', ) # Generate dynamic field maps # Somehow select the first two echoes docma_wf = init_docma_wf(omp_nthreads=1, name='docma_wf') bold_mag_splitter = pe.MapNode( interface=fsl.Split(dimension='t'), name='bold_mag_splitter', iterfield=['in_file'], ) bold_phase_splitter = pe.MapNode( interface=fsl.Split(dimension='t'), name='bold_phase_splitter', iterfield=['in_file'], ) workflow.connect(inputnode, 'bold_mag_files', bold_mag_splitter, 'in_file') workflow.connect(inputnode, 'bold_phase_files', bold_phase_splitter, 'in_file') """ bold_phdiff_wf = init_phdiff_wf(name='bold_phdiff_wf', create_phasediff=True, omp_nthreads=1, fmap_bspline=None) workflow.connect(inputnode, ('bold_phase_files', pick_first), bold_phdiff_wf, 'inputnode.phase1') workflow.connect(inputnode, ('bold_phase_files', pick_second), bold_phdiff_wf, 'inputnode.phase2') workflow.connect(inputnode, ('bold_mag_files', pick_first), bold_phdiff_wf, 'inputnode.magnitude') workflow.connect(inputnode, ('bold_phase_metadata', pick_first), bold_phdiff_wf, 'inputnode.phase1_metadata') workflow.connect(inputnode, ('bold_phase_metadata', pick_second), bold_phdiff_wf, 'inputnode.phase2_metadata') """ """ # Skullstrip BOLD files on a volume-wise basis # Need to feed in 3D files from first echo bold_mag_buffer = pe.Node( interface=niu.IdentityInterface(fields=['bold_mag_files']), name='bold_mag_buffer') bold_mag_buffer.iterables = ('bold_mag_files', (bold_mag_splitter.outputs.out_files, pick_first)) bold_skullstrip_wf = init_skullstrip_bold_wf(name='bold_skullstrip_wf') workflow.connect(bold_mag_buffer, 'bold_mag_files', bold_skullstrip_wf, 'inputnode.in_file') # Apply volume-wise brain masks to corresponding volumes from all echoes bold_skullstrip_apply = pe.MapNode( fsl.ApplyMask(), name='bold_skullstrip_apply', iterfield=['in_file'], ) workflow.connect(inputnode, 'bold_mag_files', bold_skullstrip_apply, 'in_file') workflow.connect(bold_skullstrip_wf, 'outputnode.mask_file', bold_skullstrip_apply, 'mask_file') """ """ # Unwarp BOLD data # Must be applied to each volume and each echo independently # Will also need to be done to the phase data, post preproc but pre-MC bold_unwarp_wf = init_sdc_unwarp_wf(name='bold_unwarp_wf', debug=False, omp_nthreads=1, fmap_demean=True) first_echo_metadata = pe.Node(interface=Function(['input'], ['output'], pick_first), name='first_echo_metadata') workflow.connect(bold_phdiff_wf, 'outputnode.fmap', bold_unwarp_wf, 'inputnode.fmap') workflow.connect(bold_phdiff_wf, 'outputnode.fmap_mask', bold_unwarp_wf, 'inputnode.fmap_mask') workflow.connect(bold_phdiff_wf, 'outputnode.fmap_ref', bold_unwarp_wf, 'inputnode.fmap_ref') workflow.connect(inputnode, ('bold_mag_files', pick_first), bold_unwarp_wf, 'inputnode.in_reference') workflow.connect(bold_skullstrip_apply, ('out_file', pick_first), bold_unwarp_wf, 'inputnode.in_reference_brain') workflow.connect(bold_skullstrip_wf, ('outputnode.mask_file', pick_first), bold_unwarp_wf, 'inputnode.in_mask') workflow.connect(inputnode, 'bold_mag_metadata', first_echo_metadata, 'input') workflow.connect(first_echo_metadata, 'output', bold_unwarp_wf, 'inputnode.metadata') """ # Process BOLD phase data for distortion correction bold_phase_wf = init_phase_processing_wf(name='phase_processing_wf') workflow.connect(inputnode, 'bold_phase_files', bold_phase_wf, 'inputnode.phase_files') workflow.connect(inputnode, 'bold_mag_files', bold_phase_wf, 'inputnode.magnitude_files') # Phaseprep preprocessing workflow to prepare phase data for phase-denoising reference_wf = init_bold_reference_wf(name='reference_wf') workflow.connect( bold_motionCorrection_applyMag, ('out_file', pick_first), reference_wf, 'inputnode.bold_file', ) workflow.connect(inputnode, ('sbref_mag_files', pick_first), reference_wf, 'inputnode.sbref_file') # This workflow is set up for single-echo data, so we need to # split or iterate over echoes here phaseprep_wf = create_preprocess_phase_wf(name='phaseprep_wf') workflow.connect(inputnode, 'bold_phase_files', phaseprep_wf, 'inputnode.input_phase') workflow.connect(inputnode, 'bold_mag_files', phaseprep_wf, 'inputnode.input_mag') # These ones are constant across echoes workflow.connect( bold_motionCorrection_estimate, 'oned_matrix_save', phaseprep_wf, 'inputnode.motion_par', ) workflow.connect(reference_wf, 'outputnode.bold_mask', phaseprep_wf, 'inputnode.mask_file') # Perform motion correction for first echo only bold_motionCorrection_estimate = pe.Node( interface=afni.Volreg(outputtype='NIFTI_GZ'), name='bold_motionCorrection_estimate', ) get_motpar_name_node = pe.Node( interface=Function(['source_file'], ['out_file'], get_motpar_name), name='get_motpar_name', ) workflow.connect( inputnode, ('bold_mag_files', pick_first), bold_motionCorrection_estimate, 'in_file', ) workflow.connect(inputnode, ('bold_mag_files', pick_first), get_motpar_name_node, 'source_file') workflow.connect( get_motpar_name_node, 'out_file', bold_motionCorrection_estimate, 'oned_matrix_save', ) workflow.connect( inputnode, ('sbref_mag_files', pick_first), bold_motionCorrection_estimate, 'basefile', ) # Apply motion parameters to all echoes, for both magnitude and phase data bold_motionCorrection_applyMag = pe.MapNode( interface=afni.Allineate(outputtype='NIFTI_GZ'), name='bold_motionCorrection_applyMag', iterfield=['in_file'], ) workflow.connect( bold_motionCorrection_estimate, 'oned_matrix_save', bold_motionCorrection_applyMag, 'in_matrix', ) workflow.connect(inputnode, 'bold_mag_files', bold_motionCorrection_applyMag, 'in_file') workflow.connect( inputnode, ('sbref_mag_files', pick_first), bold_motionCorrection_applyMag, 'reference', ) # Perform slice timing correction on magnitude and phase data bold_stc_getParams = pe.MapNode( interface=Function(['metadata'], ['slice_timing'], get_slice_timing), name='bold_stc_getParams', iterfield=['metadata'], ) workflow.connect(inputnode, 'bold_mag_metadata', bold_stc_getParams, 'metadata') bold_magnitude_stc = pe.MapNode( interface=afni.TShift(outputtype='NIFTI_GZ'), name='bold_magnitude_stc', iterfield=['in_file', 'slice_timing'], ) workflow.connect(bold_motionCorrection_applyMag, 'out_file', bold_magnitude_stc, 'in_file') workflow.connect(bold_stc_getParams, 'slice_timing', bold_magnitude_stc, 'slice_timing') # Use SBRef from first echo as reference image. # No need to coregister functional data to SBRef because it was used for # the motion correction. # Coregister reference image to structural coreg_est = pe.Node(interface=afni.Allineate(out_matrix='sbref2anat.1D'), name='sbref2anat_estimate') workflow.connect(inputnode, ('sbref_mag_files', pick_first), coreg_est, 'in_file') workflow.connect(inputnode, ('t1w_files', pick_first), coreg_est, 'reference') # Apply xform to mag data coreg_apply_mag = pe.MapNode( interface=afni.Allineate(outputtype='NIFTI_GZ'), name='sbref2anat_apply_mag', iterfield=['in_file'], ) workflow.connect(coreg_est, 'out_matrix', coreg_apply_mag, 'in_matrix') workflow.connect(bold_magnitude_stc, 'out_file', coreg_apply_mag, 'in_file') workflow.connect(inputnode, ('sbref_mag_files', pick_first), coreg_apply_mag, 'reference') # Apply xform to phase data coreg_apply_phase = pe.MapNode( interface=afni.Allineate(outputtype='NIFTI_GZ'), name='sbref2anat_apply_phase', iterfield=['in_file'], ) workflow.connect(coreg_est, 'out_matrix', coreg_apply_phase, 'in_matrix') workflow.connect(phaseprep_wf, 'outputnode.uw_phase', coreg_apply_phase, 'in_file') workflow.connect(inputnode, ('sbref_mag_files', pick_first), coreg_apply_phase, 'reference') # Apply xform to magnitude sbref data coreg_apply_sbref = pe.MapNode( interface=afni.Allineate(outputtype='NIFTI_GZ'), name='sbref2anat_apply_sbref', iterfield=['in_file'], ) workflow.connect(coreg_est, 'out_matrix', coreg_apply_sbref, 'in_matrix') workflow.connect(inputnode, 'sbref_mag_files', coreg_apply_sbref, 'in_file') workflow.connect(inputnode, ('sbref_mag_files', pick_first), coreg_apply_sbref, 'reference') # Collect outputs workflow.connect(bold_motionCorrection_estimate, 'oned_file', outputnode, 'motion_parameters') workflow.connect(coreg_apply_mag, 'out_file', outputnode, 'preproc_bold_files') workflow.connect(coreg_apply_phase, 'out_file', outputnode, 'preproc_phase_files') # Output BOLD mag files derivativesnode1 = pe.MapNode( interface=Function(['in_file', 'output_dir'], ['out_file'], copy_files), name='derivativesnode_bold_mag', iterfield=['in_file'], ) derivativesnode1.inputs.output_dir = output_dir workflow.connect(outputnode, 'preproc_bold_files', derivativesnode1, 'in_file') # Output BOLD phase files derivativesnode2 = pe.MapNode( interface=Function(['in_file', 'output_dir'], ['out_file'], copy_files), name='derivativesnode_bold_phase', iterfield=['in_file'], ) derivativesnode2.inputs.output_dir = output_dir workflow.connect(outputnode, 'preproc_phase_files', derivativesnode2, 'in_file') # Output motion parameters derivativesnode3 = pe.Node( interface=Function(['in_file', 'output_dir'], ['out_file'], copy_files), name='derivativesnode_motpars', ) derivativesnode3.inputs.output_dir = output_dir workflow.connect(outputnode, 'motion_parameters', derivativesnode3, 'in_file') return workflow
def base_preproc(trim_realign=True,name='rsfmri_base_preproc'): inputnode = pe.Node( utility.IdentityInterface( fields=['fmri','t1','t1_mask']), name='inputspec') outputnode = pe.Node( utility.IdentityInterface( fields=['preprocessed','mask','mean','motion']), name='outputspec') # n_trim = pe.Node( # interface=nipypp.Trim(begin_index=3), # name='trim') n_realign = pe.Node( fsl.MCFLIRT(ref_vol=0, mean_vol=True, save_plots=True, save_rms=True, save_mats=True, stats_imgs=True,), name='realign') n_mean = pe.Node(fsl.MeanImage(),name='mean') n_mask = pe.Node( interface=afni.Automask( out_file='%s_mask.nii', # brain_file=Undefined, outputtype='NIFTI'), name='mask') n_mask_mean = pe.Node( interface=fsl.ImageMaths(op_string='-mul', suffix='_brain', output_type='NIFTI'), name='mask_mean') n_segment_epi = pe.Node( fsl.FAST( img_type=2, number_classes=3, probability_maps=True, segments=True), name='segment_epi') #linear with shear/scale in phase direction n_coregister_linear = pe.Node( afni.Allineate(epi=True, args='-float',cost='nmi', out_param_file='params.1D', out_matrix='coregister.mat'), name='coregister_linear') n_coregister_gray_linear = pe.Node( afni.Allineate(epi=True, args='-float',cost='nmi', out_param_file='params.1D', out_matrix='coregister.mat'), name='coregister_gray_linear') n_smooth = pe.Node( afni.BlurInMask(fwhm=5.0, out_file='%s_smooth', float_out=True), name = 'smooth') n_bandpass_smooth = pe.Node( afni.Bandpass(highpass=0.005, lowpass=999999, despike=True, blur=5.0, normalize=False, out_file='%s_filt.nii.gz'), name='bandpass_smooth') n_motion_filter = pe.Node( interface = nipypp.RegressOutMotion( motion_source='fsl', regressors_type='voxelwise_translation', global_signal = False, prefix = 'mfilt_', regressors_transform='original+bw_derivatives'), name = 'motion_filter') # spm_path = spm.Info().version()['path'] # epi_tpl = os.path.join(spm_path, 'templates/EPI.nii') """ n_normalize = pe.Node( spm.Normalize(template=epi_tpl, source_image_smoothing=8, template_image_smoothing=0, DCT_period_cutoff=25, affine_regularization_type='mni', jobtype='est'), name='normalize') """ n_motion_estimates = pe.Node( nipyutils.MotionEstimate(motion_source='fsl'), name='motion_estimates') w=pe.Workflow(name=name) if trim_realign: w.connect([ # (inputnode, n_trim, [('fmri','in_file')]), # (inputnode, n_trim, [('fmri','in_file_a'), # (('fmri',n_volumes,-1),'stop_idx')]), # (n_trim, n_realign, [('out_file','in_file')]), (inputnode, n_realign, [('fmri','in_file')]), # (inputnode, n_realign, [('fmri','in_file')]), (n_realign, n_motion_filter, [('out_file','in_file'), ('par_file','motion')]), (n_mask, n_motion_filter,[('out_file','mask')]), (n_motion_filter, n_bandpass_smooth, [('out_file','in_file')]), (n_realign, n_mask, [('out_file','in_file')]), (n_realign, n_mask_mean, [('mean_img', 'in_file')]), (n_realign, n_motion_estimates,[('par_file','motion')]), (n_mask, n_motion_estimates,[('out_file','mask')]), (n_realign, outputnode, [('par_file','motion')]), ]) else: w.connect([ (inputnode, n_bandpass_smooth, [('fmri','in_file')]), (inputnode, n_mean, [('fmri','in_file')]), (inputnode, n_mask, [('fmri','in_file')]), (n_mean, n_mask_mean, [('out_file', 'in_file')]), ]) w.connect([ (n_mask, n_mask_mean, [('out_file', 'in_file2')]), (n_mask, n_bandpass_smooth, [('out_file','mask')]), # (n_mask_mean, n_segment_epi, [('out_file','in_files')]), # (n_mask_mean, n_normalize, [('out_file','source')]), # (n_detrend, n_smooth, [('out_file','in_file')]), # (n_mask, n_smooth, [('out_file', 'mask')]), # (n_smooth, outputnode, [('out_file','preprocessed')]), (n_bandpass_smooth, outputnode, [('out_file','preprocessed')]), (n_mask, outputnode, [('out_file','mask')]), (n_mask_mean, outputnode, [('out_file','mean')]), ]) return w
def create_preprocess_mag_wf(): preprocmag = pe.Workflow(name="preprocmag") preprocmag.config['execution']['remove_unnecessary_outputs'] = False # define inputs inputspec = pe.Node(ul.IdentityInterface(fields=['input_mag', # raw phase data 'frac', # BET franction (-f parameter) 'rest', # volumes of rest in block design 'task', # volumes of task in block design ]), name='inputspec') # convert image to float img2float = pe.MapNode(interface=fsl.ImageMaths(out_data_type='float', op_string='', suffix='_dtype'), iterfield=['in_file'], name='img2float') # motion correct each run volreg = pe.MapNode(interface=afni.Volreg(), name='volreg', iterfield='in_file') volreg.inputs.outputtype = 'NIFTI_GZ' # calculate relative motions calcrel = pe.MapNode(ul.Function(['in_file'], ['out_file'], calcrelmotion), name='calcrel', iterfield=['in_file']) #generate motion plots plotmc = pe.MapNode(interface=fsl.PlotMotionParams(), name='plotmc', iterfield='in_file') plotmc.inputs.in_source = 'fsl' plotmc.iterables = ("plot_type", ['rotations', 'translations', 'displacement']) # register each run to first volume of first run # A) extract the first volume of the first run extract_ref = pe.MapNode(interface=fsl.ExtractROI(t_size=1, t_min=0), name='extract_ref', iterfield=['in_file']) # B) registration align2first = pe.MapNode(interface=afni.Allineate(), name='align2first', iterfield=['in_file']) align2first.inputs.num_threads = 2 align2first.inputs.out_matrix = 'align2first' # merge xfm from moco and first run alignment merge_xfm = pe.MapNode(interface=ul.Merge(2), name='merge_xfm', iterfield=['in1', 'in2']) # concatenate moco and alignment to run 1 cat_xfm = pe.MapNode(interface=afni.CatMatvec(oneline=True), name='cat_xfm', iterfield=['in_file']) cat_xfm.inputs.out_file = 'concated_xfm.aff12.1D' # apply first volume registration and motion correction in a single step applyalign = pe.MapNode(interface=afni.Allineate(), name='applyalign', iterfield=['in_file', 'in_matrix']) applyalign.inputs.num_threads = 2 applyalign.inputs.final_interpolation = 'nearestneighbour' applyalign.inputs.outputtype = 'NIFTI_GZ' # afni messes with the header (unobliques the data) this puts it back cpgeommoco = pe.MapNode(interface=fsl.CopyGeom(), name='cpgeommoco', iterfield=['dest_file', 'in_file']) # linear detrending prior to SNR calculation detrend = pe.MapNode(interface=pp.DetrendMag(), name='detrend', iterfield=['mag']) # get the mean functional of run 1 for brain extraction meanfunc = pe.MapNode(interface=fsl.ImageMaths(op_string='-Tmean', suffix='_mean'), name='meanfunc', iterfield=['in_file']) # calculate the phase noise (takes in volume of activation, if none provided them assumes resting state) calcSNR = pe.MapNode(interface=pp.RestAverage(), name='calcSNR', iterfield=['func', 'rest', 'task']) # extract brain with fsl and save the mask extractor = pe.Node(interface=fsl.BET(), name="extractor") extractor.inputs.mask = True # apply the mask to all runs maskfunc = pe.MapNode(interface=fsl.ImageMaths(suffix='_bet', op_string='-mas'), iterfield=['in_file'], name='maskfunc') # outputspec outputspec = pe.Node(ul.IdentityInterface(fields=['proc_mag','motion_par', 'motion_data', 'maxdisp_data' , 'motion_plot', 'run_txfm', 'mask_file','mean_file','snr']), name='outputspec') preprocmag = pe.Workflow(name='preprocmag') preprocmag.connect([(inputspec, img2float, [('input_mag', 'in_file')]), (img2float, volreg, [('out_file', 'in_file')]), (volreg, extract_ref, [('out_file', 'in_file')]), (extract_ref, align2first, [('roi_file', 'in_file')]), (extract_ref, align2first, [(('roi_file', pickfirst), 'reference')]), (extract_ref, applyalign, [(('roi_file', pickfirst), 'reference')]), (volreg, merge_xfm, [('oned_matrix_save', 'in2')]), (align2first, merge_xfm, [('out_matrix', 'in1')]), (merge_xfm, cat_xfm, [(('out', wraptuple), 'in_file')]), (volreg,applyalign, [('out_file', 'in_file')]), (volreg, calcrel, [('md1d_file', 'in_file')]), (volreg, plotmc, [('oned_file', 'in_file')]), (cat_xfm, applyalign, [('out_file', 'in_matrix')]), (img2float, cpgeommoco, [('out_file', 'in_file')]), (applyalign, cpgeommoco, [('out_file', 'dest_file')]), (cpgeommoco, detrend, [('out_file', 'mag')]), (detrend, meanfunc, [('detrended_mag', 'in_file')]), (inputspec, calcSNR, [('rest', 'rest'), ('task', 'task')]), (detrend, calcSNR, [('detrended_mag', 'func')]), (inputspec, extractor, [('frac', 'frac')]), (meanfunc, extractor, [(('out_file', pickfirst), 'in_file')]), (cpgeommoco, maskfunc, [('out_file', 'in_file')]), (extractor, maskfunc, [('mask_file', 'in_file2')]), (maskfunc, outputspec, [('out_file', 'proc_mag')]), (volreg, outputspec, [('oned_matrix_save', 'motion_par')]), (volreg, outputspec, [('oned_file', 'motion_data')]), (volreg, outputspec, [('md1d_file', 'maxdisp_data')]), (plotmc, outputspec, [('out_file', 'motion_plot')]), (cat_xfm, outputspec, [('out_file', 'run_txfm')]), (extractor, outputspec, [('mask_file', 'mask_file')]), (extractor, outputspec, [('out_file', 'mean_file')]), (calcSNR, outputspec, [('tsnr', 'snr')]), ]) return preprocmag
def coregister_fmri_session(session_data, t_r, write_dir, brain_volume, use_rats_tool=True, slice_timing=True, prior_rigid_body_registration=False, caching=False, voxel_size_x=.1, voxel_size_y=.1, verbose=True, **environ_kwargs): """ Coregistration of the subject's functional and anatomical images. The functional volume is aligned to the anatomical, first with a rigid body registration and then on a per-slice basis (only a fine correction, this is mostly for correction of EPI distortion). Parameters ---------- session_data : sammba.registration.SessionData Single animal data, giving paths to its functional and anatomical image, as well as it identifier. t_r : float Repetition time for the EPI, in seconds. write_dir : str Directory to save the output and temporary images. brain_volume : int Volume of the brain in mm3 used for brain extraction. Typically 400 for mouse and 1800 for rat. use_rats_tool : bool, optional If True, brain mask is computed using RATS Mathematical Morphology. Otherwise, a histogram-based brain segmentation is used. prior_rigid_body_registration : bool, optional If True, a rigid-body registration of the anat to the func is performed prior to the warp. Useful if the images headers have missing/wrong information. voxel_size_x : float, optional Resampling resolution for the x-axis, in mm. voxel_size_y : float, optional Resampling resolution for the y-axis, in mm. caching : bool, optional Wether or not to use caching. verbose : bool, optional If True, all steps are verbose. Note that caching implies some verbosity in any case. environ_kwargs : extra arguments keywords Extra arguments keywords, passed to interfaces environ variable. Returns ------- the same sequence with each animal_data updated: the following attributes are added - `output_dir_` : str Path to the output directory. - `coreg_func_` : str Path to paths to the coregistered functional image. - `coreg_anat_` : str Path to paths to the coregistered functional image. - `coreg_transform_` : str Path to the transform from anat to func. Notes ----- If `use_rats_tool` is turned on, RATS tool is used for brain extraction and has to be cited. For more information, see `RATS <http://www.iibi.uiowa.edu/content/rats-overview/>`_ """ func_filename = session_data.func anat_filename = session_data.anat environ = {'AFNI_DECONFLICT': 'OVERWRITE'} for (key, value) in environ_kwargs.items(): environ[key] = value if verbose: terminal_output = 'allatonce' else: terminal_output = 'none' if use_rats_tool: if segmentation.interfaces.Info().version() is None: raise ValueError('Can not locate RATS') else: ComputeMask = segmentation.MathMorphoMask else: ComputeMask = segmentation.HistogramMask if ants.base.Info().version is None: raise ValueError('Can not locate ANTS') if caching: memory = Memory(write_dir) tshift = memory.cache(afni.TShift) clip_level = memory.cache(afni.ClipLevel) volreg = memory.cache(afni.Volreg) allineate = memory.cache(afni.Allineate) tstat = memory.cache(afni.TStat) compute_mask = memory.cache(ComputeMask) calc = memory.cache(afni.Calc) allineate = memory.cache(afni.Allineate) allineate2 = memory.cache(afni.Allineate) unifize = memory.cache(afni.Unifize) bias_correct = memory.cache(ants.N4BiasFieldCorrection) catmatvec = memory.cache(afni.CatMatvec) warp = memory.cache(afni.Warp) resample = memory.cache(afni.Resample) slicer = memory.cache(afni.ZCutUp) warp_apply = memory.cache(afni.NwarpApply) qwarp = memory.cache(afni.Qwarp) merge = memory.cache(afni.Zcat) copy_geom = memory.cache(fsl.CopyGeom) overwrite = False for step in [ tshift, volreg, allineate, allineate2, tstat, compute_mask, calc, unifize, resample, slicer, warp_apply, qwarp, merge ]: step.interface().set_default_terminal_output(terminal_output) else: tshift = afni.TShift(terminal_output=terminal_output).run clip_level = afni.ClipLevel().run volreg = afni.Volreg(terminal_output=terminal_output).run allineate = afni.Allineate(terminal_output=terminal_output).run allineate2 = afni.Allineate(terminal_output=terminal_output ).run # TODO: remove after fixed bug tstat = afni.TStat(terminal_output=terminal_output).run compute_mask = ComputeMask().run calc = afni.Calc(terminal_output=terminal_output).run unifize = afni.Unifize(terminal_output=terminal_output).run bias_correct = ants.N4BiasFieldCorrection( terminal_output=terminal_output).run catmatvec = afni.CatMatvec().run warp = afni.Warp().run resample = afni.Resample(terminal_output=terminal_output).run slicer = afni.ZCutUp(terminal_output=terminal_output).run warp_apply = afni.NwarpApply(terminal_output=terminal_output).run qwarp = afni.Qwarp(terminal_output=terminal_output).run merge = afni.Zcat(terminal_output=terminal_output).run copy_geom = fsl.CopyGeom(terminal_output=terminal_output).run overwrite = True session_data._check_inputs() output_dir = os.path.join(os.path.abspath(write_dir), session_data.animal_id) session_data._set_output_dir_(output_dir) current_dir = os.getcwd() os.chdir(output_dir) output_files = [] ####################################### # Correct functional for slice timing # ####################################### if slice_timing: out_tshift = tshift(in_file=func_filename, outputtype='NIFTI_GZ', tpattern='altplus', tr=str(t_r), environ=environ) func_filename = out_tshift.outputs.out_file output_files.append(func_filename) ################################################ # Register functional volumes to the first one # ################################################ # XXX why do you need a thresholded image ? out_clip_level = clip_level(in_file=func_filename) out_calc_threshold = calc(in_file_a=func_filename, expr='ispositive(a-{0}) * a'.format( out_clip_level.outputs.clip_val), outputtype='NIFTI_GZ') thresholded_filename = out_calc_threshold.outputs.out_file out_volreg = volreg( # XXX dfile not saved in_file=thresholded_filename, outputtype='NIFTI_GZ', environ=environ, oned_file=fname_presuffix(thresholded_filename, suffix='Vr.1Dfile.1D', use_ext=False), oned_matrix_save=fname_presuffix(thresholded_filename, suffix='Vr.aff12.1D', use_ext=False)) # Apply the registration to the whole head out_allineate = allineate(in_file=func_filename, master=func_filename, in_matrix=out_volreg.outputs.oned_matrix_save, out_file=fname_presuffix(func_filename, suffix='Av'), environ=environ) # 3dAllineate removes the obliquity. This is not a good way to readd it as # removes motion correction info in the header if it were an AFNI file...as # it happens it's NIfTI which does not store that so irrelevant! out_copy_geom = copy_geom(dest_file=out_allineate.outputs.out_file, in_file=out_volreg.outputs.out_file) allineated_filename = out_copy_geom.outputs.out_file # Create a (hopefully) nice mean image for use in the registration out_tstat = tstat(in_file=allineated_filename, args='-mean', outputtype='NIFTI_GZ', environ=environ) # Update outputs output_files.extend([ thresholded_filename, out_volreg.outputs.oned_matrix_save, out_volreg.outputs.out_file, out_volreg.outputs.md1d_file, allineated_filename, out_tstat.outputs.out_file ]) ########################################### # Corret anat and func for intensity bias # ########################################### # Correct the functional average for intensities bias out_bias_correct = bias_correct(input_image=out_tstat.outputs.out_file) unbiased_func_filename = out_bias_correct.outputs.output_image # Bias correct the antomical image out_unifize = unifize(in_file=anat_filename, outputtype='NIFTI_GZ', environ=environ) unbiased_anat_filename = out_unifize.outputs.out_file # Update outputs output_files.extend([unbiased_func_filename, unbiased_anat_filename]) ############################################# # Rigid-body registration anat -> mean func # ############################################# if prior_rigid_body_registration: # Mask the mean functional volume outside the brain. out_clip_level = clip_level(in_file=unbiased_func_filename) out_compute_mask_func = compute_mask( in_file=unbiased_func_filename, volume_threshold=brain_volume, intensity_threshold=int(out_clip_level.outputs.clip_val)) out_cacl_func = calc(in_file_a=unbiased_func_filename, in_file_b=out_compute_mask_func.outputs.out_file, expr='a*b', outputtype='NIFTI_GZ', environ=environ) # Mask the anatomical volume outside the brain. out_clip_level = clip_level(in_file=unbiased_anat_filename) out_compute_mask_anat = compute_mask( in_file=unbiased_anat_filename, volume_threshold=brain_volume, intensity_threshold=int(out_clip_level.outputs.clip_val)) out_cacl_anat = calc(in_file_a=unbiased_anat_filename, in_file_b=out_compute_mask_anat.outputs.out_file, expr='a*b', outputtype='NIFTI_GZ', environ=environ) # Compute the transformation from functional to anatomical brain # XXX: why in this sense out_allineate = allineate2( in_file=out_cacl_func.outputs.out_file, reference=out_cacl_anat.outputs.out_file, out_matrix=fname_presuffix(out_cacl_func.outputs.out_file, suffix='_shr.aff12.1D', use_ext=False), center_of_mass='', warp_type='shift_rotate', out_file=fname_presuffix(out_cacl_func.outputs.out_file, suffix='_shr'), environ=environ) rigid_transform_file = out_allineate.outputs.out_matrix output_files.extend([ out_compute_mask_func.outputs.out_file, out_cacl_func.outputs.out_file, out_compute_mask_anat.outputs.out_file, out_cacl_anat.outputs.out_file, rigid_transform_file, out_allineate.outputs.out_file ]) # apply the inverse transform to register the anatomical to the func catmatvec_out_file = fname_presuffix(rigid_transform_file, suffix='INV') out_catmatvec = catmatvec(in_file=[(rigid_transform_file, 'I')], oneline=True, out_file=catmatvec_out_file) output_files.append(out_catmatvec.outputs.out_file) out_allineate = allineate(in_file=unbiased_anat_filename, master=unbiased_func_filename, in_matrix=out_catmatvec.outputs.out_file, out_file=fname_presuffix( unbiased_anat_filename, suffix='_shr_in_func_space'), environ=environ) allineated_anat_filename = out_allineate.outputs.out_file output_files.append(allineated_anat_filename) else: allineated_anat_filename = unbiased_anat_filename ############################################ # Nonlinear registration anat -> mean func # ############################################ # 3dWarp doesn't put the obliquity in the header, so do it manually # This step generates one file per slice and per time point, so we are # making sure they are removed at the end out_warp = warp(in_file=allineated_anat_filename, oblique_parent=unbiased_func_filename, interp='quintic', gridset=unbiased_func_filename, outputtype='NIFTI_GZ', verbose=True, environ=environ) registered_anat_filename = out_warp.outputs.out_file registered_anat_oblique_filename = fix_obliquity(registered_anat_filename, unbiased_func_filename, verbose=verbose) # Concatenate all the anat to func tranforms mat_filename = fname_presuffix(registered_anat_filename, suffix='_warp.mat', use_ext=False) # XXX Handle this correctly according to caching if not os.path.isfile(mat_filename): np.savetxt(mat_filename, [out_warp.runtime.stdout], fmt='%s') output_files.append(mat_filename) transform_filename = fname_presuffix(registered_anat_filename, suffix='_anat_to_func.aff12.1D', use_ext=False) if prior_rigid_body_registration: _ = catmatvec(in_file=[(mat_filename, 'ONELINE'), (rigid_transform_file, 'ONELINE')], oneline=True, out_file=transform_filename) else: _ = catmatvec(in_file=[(mat_filename, 'ONELINE')], oneline=True, out_file=transform_filename) ################################################## # Per-slice non-linear registration func -> anat # ################################################## # Slice anatomical image anat_img = nibabel.load(registered_anat_oblique_filename) anat_n_slices = anat_img.header.get_data_shape()[2] sliced_registered_anat_filenames = [] for slice_n in range(anat_n_slices): out_slicer = slicer(in_file=registered_anat_oblique_filename, keep='{0} {0}'.format(slice_n), out_file=fname_presuffix( registered_anat_oblique_filename, suffix='Sl%d' % slice_n), environ=environ) oblique_slice = fix_obliquity(out_slicer.outputs.out_file, registered_anat_oblique_filename, verbose=verbose) sliced_registered_anat_filenames.append(oblique_slice) # Slice mean functional sliced_bias_corrected_filenames = [] img = nibabel.load(func_filename) n_slices = img.header.get_data_shape()[2] for slice_n in range(n_slices): out_slicer = slicer(in_file=unbiased_func_filename, keep='{0} {0}'.format(slice_n), out_file=fname_presuffix(unbiased_func_filename, suffix='Sl%d' % slice_n), environ=environ) oblique_slice = fix_obliquity(out_slicer.outputs.out_file, unbiased_func_filename, verbose=verbose) sliced_bias_corrected_filenames.append(oblique_slice) # Below line is to deal with slices where there is no signal (for example # rostral end of some anatomicals) # The inverse warp frequently fails, Resampling can help it work better # XXX why specifically .1 in voxel_size ? voxel_size_z = anat_img.header.get_zooms()[2] resampled_registered_anat_filenames = [] for sliced_registered_anat_filename in sliced_registered_anat_filenames: out_resample = resample(in_file=sliced_registered_anat_filename, voxel_size=(voxel_size_x, voxel_size_y, voxel_size_z), outputtype='NIFTI_GZ', environ=environ) resampled_registered_anat_filenames.append( out_resample.outputs.out_file) resampled_bias_corrected_filenames = [] for sliced_bias_corrected_filename in sliced_bias_corrected_filenames: out_resample = resample(in_file=sliced_bias_corrected_filename, voxel_size=(voxel_size_x, voxel_size_y, voxel_size_z), outputtype='NIFTI_GZ', environ=environ) resampled_bias_corrected_filenames.append( out_resample.outputs.out_file) # single slice non-linear functional to anatomical registration warped_slices = [] warp_filenames = [] for (resampled_bias_corrected_filename, resampled_registered_anat_filename) in zip( resampled_bias_corrected_filenames, resampled_registered_anat_filenames): warped_slice = fname_presuffix(resampled_bias_corrected_filename, suffix='_qw') out_qwarp = qwarp( in_file=resampled_bias_corrected_filename, base_file=resampled_registered_anat_filename, iwarp=True, # XXX: is this necessary noneg=True, blur=[0], nmi=True, noXdis=True, allineate=True, allineate_opts='-parfix 1 0 -parfix 2 0 -parfix 3 0 ' '-parfix 4 0 -parfix 5 0 -parfix 6 0 ' '-parfix 7 0 -parfix 9 0 ' '-parfix 10 0 -parfix 12 0', out_file=warped_slice, environ=environ) warped_slices.append(out_qwarp.outputs.warped_source) warp_filenames.append(out_qwarp.outputs.source_warp) output_files.append(out_qwarp.outputs.base_warp) # There are files geenrated by the allineate option output_files.extend([ fname_presuffix(out_qwarp.outputs.warped_source, suffix='_Allin'), fname_presuffix(out_qwarp.outputs.warped_source, suffix='_Allin.nii', use_ext=False), fname_presuffix(out_qwarp.outputs.warped_source, suffix='_Allin.aff12.1D', use_ext=False) ]) # Resample the mean volume back to the initial resolution, voxel_size = nibabel.load(unbiased_func_filename).header.get_zooms() resampled_warped_slices = [] for warped_slice in warped_slices: out_resample = resample(in_file=warped_slice, voxel_size=voxel_size, outputtype='NIFTI_GZ', environ=environ) resampled_warped_slices.append(out_resample.outputs.out_file) # fix the obliquity resampled_warped_slices_oblique = [] for (sliced_registered_anat_filename, resampled_warped_slice) in zip(sliced_registered_anat_filenames, resampled_warped_slices): oblique_slice = fix_obliquity(resampled_warped_slice, sliced_registered_anat_filename, verbose=verbose) resampled_warped_slices_oblique.append(oblique_slice) # slice functional sliced_func_filenames = [] for slice_n in range(n_slices): out_slicer = slicer(in_file=allineated_filename, keep='{0} {0}'.format(slice_n), out_file=fname_presuffix(allineated_filename, suffix='Sl%d' % slice_n), environ=environ) oblique_slice = fix_obliquity(out_slicer.outputs.out_file, allineated_filename, verbose=verbose) sliced_func_filenames.append(oblique_slice) # Apply the precomputed warp slice by slice warped_func_slices = [] for (sliced_func_filename, warp_filename) in zip(sliced_func_filenames, warp_filenames): out_warp_apply = warp_apply(in_file=sliced_func_filename, master=sliced_func_filename, warp=warp_filename, out_file=fname_presuffix( sliced_func_filename, suffix='_qw'), environ=environ) warped_func_slices.append(out_warp_apply.outputs.out_file) # Finally, merge all slices ! out_merge_func = merge(in_files=warped_func_slices, outputtype='NIFTI_GZ', environ=environ) # Fix the obliquity merged_oblique = fix_obliquity(out_merge_func.outputs.out_file, allineated_filename, verbose=verbose) # Update the fmri data setattr(session_data, "coreg_func_", merged_oblique) setattr(session_data, "coreg_anat_", registered_anat_oblique_filename) setattr(session_data, "coreg_transform_", transform_filename) os.chdir(current_dir) # Collect the outputs output_files.extend(sliced_registered_anat_filenames + sliced_bias_corrected_filenames + resampled_registered_anat_filenames + resampled_bias_corrected_filenames + warped_slices + warp_filenames + resampled_warped_slices_oblique + sliced_func_filenames + warped_func_slices) if not caching: for out_file in output_files: if os.path.isfile(out_file): os.remove(out_file)
def __init__(self,settings): # call base constructor super().__init__(settings) # check files being processed check_query(settings['bids_query'],settings['bids_dir']) # define output node self.set_input(['subject']) self.set_output(['anat','func','subject']) # define datasink substitutions self.set_resubs([ ('_alignanattoanat\d{1,3}',''), ('bidsselector/sub-(?P<subject>\w+)_','bidsselector/sub-\g<subject>/sub-\g<subject>_') # put raw files under subject ]) # parametrize subject for multiple subject processing self.inputnode.iterables = ('subject',settings['subject']) # Get BIDs dataset and organize data for input self.bidsselection = Node( BIDSDataGrabber( base_dir=settings['bids_dir'], output_query=settings['bids_query'] ), name='bidsselection' ) # select anat to align to self.selectanat = Node( Function( input_names=['anat','refnum'], output_names=['anat_reference','anat_align'], function=lambda anat,refnum: (anat[refnum],[img for idx,img in enumerate(anat) if idx!=refnum]) ), name='selectanat' ) self.selectanat.inputs.refnum = settings['anat_reference'] # create node for aligning multiple T1 images to T1 reference self.alignanattoanat = MapNode( afni.Allineate( outputtype='NIFTI_GZ', ), iterfield=['in_file'], name='alignanattoanat' ) # merge anats into single list self.mergeanatlist = Node( Merge( numinputs=2, ravel_inputs=True ), name='mergeanatlist' ) # avg all anats self.avganat = Node( Function( input_names=['anat_list'], output_names=['avg_anat'], function=avganats ), name='avganat' )
def _func_to_template(func_coreg_filename, template_filename, write_dir, func_to_anat_oned_filename, anat_to_template_oned_filename, anat_to_template_warp_filename, voxel_size=None, caching=False, verbose=True): """ Applies successive transforms to coregistered functional to put it in template space. Parameters ---------- coreg_func_filename : str Path to functional volume, coregistered to a common space with the anatomical volume. template_filename : str Template to register the functional to. func_to_anat_oned_filename : str Path to the affine 1D transform from functional to coregistration space. anat_to_template_oned_filename : str Path to the affine 1D transform from anatomical to template space. anat_to_template_warp_filename : str Path to the warp transform from anatomical to template space. voxel_size : 3-tuple of floats, optional Voxel size of the registered functional, in mm. caching : bool, optional Wether or not to use caching. verbose : bool, optional If True, all steps are verbose. Note that caching implies some verbosity in any case. """ environ = {} if verbose: terminal_output = 'allatonce' else: terminal_output = 'none' if caching: memory = Memory(write_dir) resample = memory.cache(afni.Resample) catmatvec = memory.cache(afni.CatMatvec) allineate = memory.cache(afni.Allineate) warp_apply = memory.cache(afni.NwarpApply) for step in [resample, allineate, warp_apply]: step.interface().set_default_terminal_output(terminal_output) else: resample = afni.Resample(terminal_output=terminal_output).run catmatvec = afni.CatMatvec().run allineate = afni.Allineate(terminal_output=terminal_output).run warp_apply = afni.NwarpApply(terminal_output=terminal_output).run environ['AFNI_DECONFLICT'] = 'OVERWRITE' current_dir = os.getcwd() os.chdir(write_dir) # XXX to remove normalized_filename = fname_presuffix(func_coreg_filename, suffix='_normalized') if voxel_size is None: func_template_filename = template_filename else: out_resample = resample(in_file=template_filename, voxel_size=voxel_size, outputtype='NIFTI_GZ', environ=environ) func_template_filename = out_resample.outputs.out_file if anat_to_template_warp_filename is None: affine_transform_filename = fname_presuffix(func_to_anat_oned_filename, suffix='_to_template') _ = catmatvec(in_file=[(anat_to_template_oned_filename, 'ONELINE'), (func_to_anat_oned_filename, 'ONELINE')], oneline=True, out_file=affine_transform_filename, environ=environ) _ = allineate(in_file=func_coreg_filename, master=func_template_filename, in_matrix=affine_transform_filename, out_file=normalized_filename, environ=environ) else: warp = "'{0} {1} {2}'".format(anat_to_template_warp_filename, anat_to_template_oned_filename, func_to_anat_oned_filename) _ = warp_apply(in_file=func_coreg_filename, master=func_template_filename, warp=warp, out_file=normalized_filename, environ=environ) os.chdir(current_dir) return normalized_filename
def _create_split_hemi_pipe(params, params_template, name="split_hemi_pipe"): """Description: Split segmentated tissus according hemisheres after \ removal of cortical structure Processing steps: - TODO Params: - None so far Inputs: inputnode: warpinv_file: non-linear transformation (from NMT_subject_align) inv_transfo_file: inverse transformation aff_file: affine transformation file t1_ref_file: preprocessd T1 segmented_file: from atropos segmentation, with all the tissues segmented arguments: params: dictionary of node sub-parameters (from a json file) name: pipeline name (default = "split_hemi_pipe") Outputs: """ split_hemi_pipe = pe.Workflow(name=name) # creating inputnode inputnode = pe.Node(niu.IdentityInterface(fields=[ 'warpinv_file', 'inv_transfo_file', 'aff_file', 't1_ref_file', 'segmented_file' ]), name='inputnode') # get values if "cereb_template" in params_template.keys(): cereb_template_file = params_template["cereb_template"] # ### cereb # Binarize cerebellum bin_cereb = pe.Node(interface=fsl.UnaryMaths(), name='bin_cereb') bin_cereb.inputs.operation = "bin" bin_cereb.inputs.in_file = cereb_template_file # Warp cereb brainmask to subject space warp_cereb = pe.Node(interface=reg.NwarpApplyPriors(), name='warp_cereb') warp_cereb.inputs.in_file = cereb_template_file warp_cereb.inputs.out_file = cereb_template_file warp_cereb.inputs.interp = "NN" warp_cereb.inputs.args = "-overwrite" split_hemi_pipe.connect(bin_cereb, 'out_file', warp_cereb, 'in_file') split_hemi_pipe.connect(inputnode, 'aff_file', warp_cereb, 'master') split_hemi_pipe.connect(inputnode, 'warpinv_file', warp_cereb, "warp") # Align cereb template align_cereb = pe.Node(interface=afni.Allineate(), name='align_cereb') align_cereb.inputs.final_interpolation = "nearestneighbour" align_cereb.inputs.overwrite = True align_cereb.inputs.outputtype = "NIFTI_GZ" split_hemi_pipe.connect(warp_cereb, 'out_file', align_cereb, "in_file") # -source split_hemi_pipe.connect(inputnode, 't1_ref_file', align_cereb, "reference") # -base split_hemi_pipe.connect(inputnode, 'inv_transfo_file', align_cereb, "in_matrix") # -1Dmatrix_apply if "L_hemi_template" in params_template.keys() and \ "R_hemi_template" in params_template.keys(): L_hemi_template_file = params_template["L_hemi_template"] R_hemi_template_file = params_template["R_hemi_template"] # Warp L hemi template brainmask to subject space warp_L_hemi = pe.Node(interface=reg.NwarpApplyPriors(), name='warp_L_hemi') warp_L_hemi.inputs.in_file = L_hemi_template_file warp_L_hemi.inputs.out_file = L_hemi_template_file warp_L_hemi.inputs.interp = "NN" warp_L_hemi.inputs.args = "-overwrite" split_hemi_pipe.connect(inputnode, 'aff_file', warp_L_hemi, 'master') split_hemi_pipe.connect(inputnode, 'warpinv_file', warp_L_hemi, "warp") # Align L hemi template align_L_hemi = pe.Node(interface=afni.Allineate(), name='align_L_hemi') align_L_hemi.inputs.final_interpolation = "nearestneighbour" align_L_hemi.inputs.overwrite = True align_L_hemi.inputs.outputtype = "NIFTI_GZ" split_hemi_pipe.connect(warp_L_hemi, 'out_file', align_L_hemi, "in_file") # -source split_hemi_pipe.connect(inputnode, 't1_ref_file', align_L_hemi, "reference") # -base split_hemi_pipe.connect(inputnode, 'inv_transfo_file', align_L_hemi, "in_matrix") # -1Dmatrix_apply # Warp R hemi template brainmask to subject space warp_R_hemi = pe.Node(interface=reg.NwarpApplyPriors(), name='warp_R_hemi') warp_R_hemi.inputs.in_file = R_hemi_template_file warp_R_hemi.inputs.out_file = R_hemi_template_file warp_R_hemi.inputs.interp = "NN" warp_R_hemi.inputs.args = "-overwrite" split_hemi_pipe.connect(inputnode, 'aff_file', warp_R_hemi, 'master') split_hemi_pipe.connect(inputnode, 'warpinv_file', warp_R_hemi, "warp") # Align R hemi template align_R_hemi = pe.Node(interface=afni.Allineate(), name='align_R_hemi') align_R_hemi.inputs.final_interpolation = "nearestneighbour" align_R_hemi.inputs.overwrite = True align_R_hemi.inputs.outputtype = "NIFTI_GZ" split_hemi_pipe.connect(warp_R_hemi, 'out_file', align_R_hemi, "in_file") # -source split_hemi_pipe.connect(inputnode, 't1_ref_file', align_R_hemi, "reference") # -base split_hemi_pipe.connect(inputnode, 'inv_transfo_file', align_R_hemi, "in_matrix") # -1Dmatrix_apply elif "LR_hemi_template" in params_template.keys(): LR_hemi_template_file = params_template["LR_hemi_template"] # Warp LR hemi template brainmask to subject space warp_LR_hemi = pe.Node(interface=reg.NwarpApplyPriors(), name='warp_LR_hemi') warp_LR_hemi.inputs.in_file = LR_hemi_template_file warp_LR_hemi.inputs.out_file = LR_hemi_template_file warp_LR_hemi.inputs.interp = "NN" warp_LR_hemi.inputs.args = "-overwrite" split_hemi_pipe.connect(inputnode, 'aff_file', warp_LR_hemi, 'master') split_hemi_pipe.connect(inputnode, 'warpinv_file', warp_LR_hemi, "warp") # Align LR hemi template align_LR_hemi = pe.Node(interface=afni.Allineate(), name='align_LR_hemi') align_LR_hemi.inputs.final_interpolation = "nearestneighbour" align_LR_hemi.inputs.overwrite = True align_LR_hemi.inputs.outputtype = "NIFTI_GZ" split_hemi_pipe.connect(warp_LR_hemi, 'out_file', align_LR_hemi, "in_file") # -source split_hemi_pipe.connect(inputnode, 't1_ref_file', align_LR_hemi, "reference") # -base split_hemi_pipe.connect(inputnode, 'inv_transfo_file', align_LR_hemi, "in_matrix") # -1Dmatrix_apply split_LR = pe.Node(interface=niu.Function( input_names=["LR_mask_file"], output_names=["L_mask_file", "R_mask_file"], function=split_LR_mask), name="split_LR") split_hemi_pipe.connect(align_LR_hemi, "out_file", split_LR, 'LR_mask_file') else: print("Error, could not find LR_hemi_template or L_hemi_template and \ R_hemi_template, skipping") print(params_template.keys()) exit() # Using LH and RH masks to obtain hemisphere segmentation masks calc_L_hemi = pe.Node(interface=afni.Calc(), name='calc_L_hemi') calc_L_hemi.inputs.expr = 'a*b/b' calc_L_hemi.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(inputnode, 'segmented_file', calc_L_hemi, "in_file_a") if "LR_hemi_template" in params_template.keys(): split_hemi_pipe.connect(split_LR, 'L_mask_file', calc_L_hemi, "in_file_b") else: split_hemi_pipe.connect(align_L_hemi, 'out_file', calc_L_hemi, "in_file_b") # R_hemi calc_R_hemi = pe.Node(interface=afni.Calc(), name='calc_R_hemi') calc_R_hemi.inputs.expr = 'a*b/b' calc_R_hemi.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(inputnode, 'segmented_file', calc_R_hemi, "in_file_a") if "LR_hemi_template" in params_template.keys(): split_hemi_pipe.connect(split_LR, 'R_mask_file', calc_R_hemi, "in_file_b") else: split_hemi_pipe.connect(align_R_hemi, 'out_file', calc_R_hemi, "in_file_b") # remove cerebellum from left and right brain segmentations calc_nocb_L_hemi = pe.Node(interface=afni.Calc(), name='calc_nocb_L_hemi') calc_nocb_L_hemi.inputs.expr = '(a*(not (b)))' calc_nocb_L_hemi.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(calc_L_hemi, 'out_file', calc_nocb_L_hemi, "in_file_a") split_hemi_pipe.connect(align_cereb, 'out_file', calc_nocb_L_hemi, "in_file_b") calc_nocb_R_hemi = pe.Node(interface=afni.Calc(), name='calc_nocb_R_hemi') calc_nocb_R_hemi.inputs.expr = '(a*(not (b)))' calc_nocb_R_hemi.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(calc_R_hemi, 'out_file', calc_nocb_R_hemi, "in_file_a") split_hemi_pipe.connect(align_cereb, 'out_file', calc_nocb_R_hemi, "in_file_b") # create L/R GM and WM no-cerebellum masks from subject brain segmentation calc_GM_nocb_L_hemi = pe.Node(interface=afni.Calc(), name='calc_GM_nocb_L_hemi') calc_GM_nocb_L_hemi.inputs.expr = 'iszero(a-2)' calc_GM_nocb_L_hemi.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(calc_nocb_L_hemi, 'out_file', calc_GM_nocb_L_hemi, "in_file_a") calc_WM_nocb_L_hemi = pe.Node(interface=afni.Calc(), name='calc_WM_nocb_L_hemi') calc_WM_nocb_L_hemi.inputs.expr = 'iszero(a-3)' calc_WM_nocb_L_hemi.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(calc_nocb_L_hemi, 'out_file', calc_WM_nocb_L_hemi, "in_file_a") calc_GM_nocb_R_hemi = pe.Node(interface=afni.Calc(), name='calc_GM_nocb_R_hemi') calc_GM_nocb_R_hemi.inputs.expr = 'iszero(a-2)' calc_GM_nocb_R_hemi.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(calc_nocb_R_hemi, 'out_file', calc_GM_nocb_R_hemi, "in_file_a") calc_WM_nocb_R_hemi = pe.Node(interface=afni.Calc(), name='calc_WM_nocb_R_hemi') calc_WM_nocb_R_hemi.inputs.expr = 'iszero(a-3)' calc_WM_nocb_R_hemi.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(calc_nocb_R_hemi, 'out_file', calc_WM_nocb_R_hemi, "in_file_a") # Extract Cerebellum using template mask transformed to subject space extract_cereb = pe.Node(interface=afni.Calc(), name='extract_cereb') extract_cereb.inputs.expr = 'a*b/b' extract_cereb.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(inputnode, 't1_ref_file', extract_cereb, "in_file_a") split_hemi_pipe.connect(align_cereb, 'out_file', extract_cereb, "in_file_b") # Extract L.GM using template mask transformed to subject space extract_L_GM = pe.Node(interface=afni.Calc(), name='extract_L_GM') extract_L_GM.inputs.expr = 'a*b/b' extract_L_GM.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(inputnode, 't1_ref_file', extract_L_GM, "in_file_a") split_hemi_pipe.connect(calc_GM_nocb_L_hemi, 'out_file', extract_L_GM, "in_file_b") # Extract L.WM using template mask transformed to subject space extract_L_WM = pe.Node(interface=afni.Calc(), name='extract_L_WM') extract_L_WM.inputs.expr = 'a*b/b' extract_L_WM.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(inputnode, 't1_ref_file', extract_L_WM, "in_file_a") split_hemi_pipe.connect(calc_WM_nocb_L_hemi, 'out_file', extract_L_WM, "in_file_b") # Extract L.GM using template mask transformed to subject space extract_R_GM = pe.Node(interface=afni.Calc(), name='extract_R_GM') extract_R_GM.inputs.expr = 'a*b/b' extract_R_GM.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(inputnode, 't1_ref_file', extract_R_GM, "in_file_a") split_hemi_pipe.connect(calc_GM_nocb_R_hemi, 'out_file', extract_R_GM, "in_file_b") # Extract L.WM using template mask transformed to subject space extract_R_WM = pe.Node(interface=afni.Calc(), name='extract_R_WM') extract_R_WM.inputs.expr = 'a*b/b' extract_R_WM.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(inputnode, 't1_ref_file', extract_R_WM, "in_file_a") split_hemi_pipe.connect(calc_WM_nocb_R_hemi, 'out_file', extract_R_WM, "in_file_b") return split_hemi_pipe
def create_preprocess_phase_wf(): """Create's phase preprocessing workflow with the following steps: 1) Convert data to float 2) Determine scaling required for radians 3) Apply radian scaling 4) Convert to real and imaginary 5) Apply magnitude motion correction parameters 6) Correct geometry changes (AFNI issue) 7) Convert back to phase 8) Unwrap and detrend data 9) Mask data using magnitude mask 10) Calculate noise from data """ preprocphase = pe.Workflow(name="preprocphase") preprocphase.config['execution']['remove_unnecessary_outputs'] = False # define inputs inputspec = pe.Node( ul.IdentityInterface(fields=[ 'input_phase', # raw phase data 'input_mag', # raw mag data 'motion_par', # afni transform concatenated from magnitude data 'mask_file', # bet mask from magnitude data 'rest', # volumes of rest in block design 'task', # volumes of task in block design ]), name='inputspec') # 1) Convert data to float img2float = pe.MapNode(interface=fsl.ImageMaths(out_data_type='float', op_string='', suffix='_dtype'), iterfield=['in_file'], name='img2float') # 2) Determine radian scaling required findscaling = pe.MapNode(interface=ul.Function( input_names=['in_file'], output_names=['scaling_arg'], function=findscalingarg), name='findscaling', iterfield=['in_file']) # 3) Apply radian scaling convert2rad = pe.MapNode(interface=fsl.maths.MathsCommand(), name='convert2rad', iterfield=['in_file', 'args']) # 4) Convert to real and imaginary (2 step process) makecomplex = pe.MapNode(interface=fsl.Complex(complex_polar=True), name='makecomplex', iterfield=['magnitude_in_file', 'phase_in_file']) splitcomplex = pe.MapNode(interface=fsl.Complex(real_cartesian=True), name='splitcomplex', iterfield=['complex_in_file']) # 5) Apply magnitude motion correction parameters mocoreal = pe.MapNode(interface=afni.Allineate(), name='mocoreal', iterfield=['in_file', 'in_matrix']) mocoreal.inputs.outputtype = 'NIFTI_GZ' mocoreal.inputs.out_file = 'mocophase.nii.gz' mocoreal.inputs.num_threads = 2 mocoimag = mocoreal.clone('mocoimag') # 6) Correct geometry changes (AFNI issue) cpgeommocoreal = pe.MapNode(interface=fsl.CopyGeom(), name='cpgeommoco', iterfield=['dest_file', 'in_file']) cpgeommocoimag = cpgeommocoreal.clone('cpgeommocoimag') cpgeommocophase = cpgeommocoreal.clone('cpgeommocophase') # 7) Convert back to phase (2 step process) makecomplexmoco = pe.MapNode( interface=fsl.Complex(complex_cartesian=True), name='makecomplexmoco', iterfield=['real_in_file', 'imaginary_in_file']) splitcomplexmoco = pe.MapNode(interface=fsl.Complex(real_polar=True), name='splitcomplexmoco', iterfield=['complex_in_file']) # 8) Remove first volume, unwrap and detrend phase data prepphase = pe.MapNode(interface=pp.PreprocessPhase(), name='prepphase', iterfield=['phase']) # 9) Mask data using magnitude mask maskfunc = pe.MapNode(interface=fsl.ImageMaths(suffix='_bet', op_string='-mas'), iterfield=['in_file'], name='maskfunc') # 10) Calculate noise from data calcSNR = pe.MapNode(interface=pp.RestAverage(), name='calcSNR', iterfield=['func', 'rest', 'task']) # outputspec outputspec = pe.Node(ul.IdentityInterface( fields=['proc_phase', 'uw_phase', 'delta_phase', 'std_phase']), name='outputspec') preprocphase = pe.Workflow(name='preprocphase') preprocphase.connect([ (inputspec, img2float, [('input_phase', 'in_file')]), # 1 (inputspec, findscaling, [('input_phase', 'in_file')]), # 2 (findscaling, convert2rad, [('scaling_arg', 'args')]), (img2float, convert2rad, [('out_file', 'in_file')]), (convert2rad, makecomplex, [('out_file', 'phase_in_file')]), # 3 (inputspec, makecomplex, [('input_mag', 'magnitude_in_file')]), (makecomplex, splitcomplex, [('complex_out_file', 'complex_in_file') ]), # 4 (inputspec, mocoreal, [('motion_par', 'in_matrix')]), # 5 real (splitcomplex, mocoreal, [('real_out_file', 'in_file')]), (mocoreal, cpgeommocoreal, [('out_file', 'dest_file')]), #6 real (img2float, cpgeommocoreal, [('out_file', 'in_file')]), (inputspec, mocoimag, [('motion_par', 'in_matrix')]), # 5 imag (splitcomplex, mocoimag, [('imaginary_out_file', 'in_file')]), (mocoimag, cpgeommocoimag, [('out_file', 'dest_file')]), # 6 imag (img2float, cpgeommocoimag, [('out_file', 'in_file')]), (cpgeommocoreal, makecomplexmoco, [('out_file', 'real_in_file')]), # 7 (cpgeommocoimag, makecomplexmoco, [('out_file', 'imaginary_in_file')]), (makecomplexmoco, splitcomplexmoco, [('complex_out_file', 'complex_in_file')]), (splitcomplexmoco, cpgeommocophase, [('phase_out_file', 'dest_file')]), (img2float, cpgeommocophase, [('out_file', 'in_file')]), (cpgeommocophase, prepphase, [('out_file', 'phase')]), # 8 (prepphase, maskfunc, [('detrended_phase', 'in_file')]), # 9 (inputspec, maskfunc, [('mask_file', 'in_file2')]), (maskfunc, outputspec, [('out_file', 'proc_phase')]), (prepphase, outputspec, [('uw_phase', 'uw_phase')]), (prepphase, outputspec, [('delta_phase', 'delta_phase')]), ( inputspec, calcSNR, [ ('rest', 'rest'), # 10 ('task', 'task') ]), (prepphase, calcSNR, [('detrended_phase', 'func')]), (calcSNR, outputspec, [('noise', 'std_phase')]) ]) return preprocphase
def create_register_NMT_pipe(params_template, params={}, name="register_NMT_pipe", NMT_version="v1.3"): """Description: Register template to anat with the script NMT_subject_align Processing steps: - Bias correction (norm_intensity) - Deoblique (Refit with deoblique option) - NMT_subject_align (see :class:`NMTSubjectAlign \ <macapype.nodes.register.NMTSubjectAlign>` and :class:`NMTSubjectAlign2 \ <macapype.nodes.register.NMTSubjectAlign2>` for explanations) - apply it to tissues list_priors (NwarpApplyPriors and Allineate) Params: - norm_intensity (see `N4BiasFieldCorrection <https://\ nipype.readthedocs.io/en/0.12.1/interfaces/generated/nipype.interfaces\ .ants.segmentation.html#n4biasfieldcorrection>`_ for arguments)) - \ also available as :ref:`indiv_params <indiv_params>` - NMT_version (default = 1.2; 1.3 is also accepted) Inputs: inputnode: T1: T1 file name indiv_params: dict with individuals parameters for some nodes arguments: params_template: dictionary of info about template params: dictionary of node sub-parameters (from a json file) name: pipeline name (default = "register_NMT_pipe") NMT_version: NMT version (default = 1.2); can be overwritten in params json Outputs: norm_intensity.output_image: filled mask after erode align_seg_csf.out_file: csf template tissue in subject space align_seg_gm.out_file: grey matter template tissue in subject space align_seg_wm.out_file: white matter template tissue in subject space """ register_NMT_pipe = pe.Workflow(name=name) # creating inputnode inputnode = pe.Node( niu.IdentityInterface(fields=['T1', 'indiv_params']), name='inputnode') if "NMT_version" in params.keys(): NMT_version = params['NMT_version'] print("*** Overriding NMT_version with parmas {}".format( params['NMT_version'])) # N4 intensity normalization over brain norm_intensity = NodeParams(ants.N4BiasFieldCorrection(), params=parse_key(params, "norm_intensity"), name='norm_intensity') register_NMT_pipe.connect(inputnode, 'T1', norm_intensity, "input_image") register_NMT_pipe.connect( inputnode, ('indiv_params', parse_key, "norm_intensity"), norm_intensity, "indiv_params") deoblique = pe.Node(afni.Refit(deoblique=True), name="deoblique") register_NMT_pipe.connect(norm_intensity, 'output_image', deoblique, "in_file") print("*** Found NMT_version {}".format(NMT_version)) if NMT_version == "v1.2": # align subj to nmt NMT_subject_align = NodeParams( NMTSubjectAlign(), params=parse_key(params, "NMT_subject_align"), name='NMT_subject_align') elif NMT_version == "v1.3" or NMT_version == "v2.0": # align subj to nmt NMT_subject_align = NodeParams( NMTSubjectAlign2(), params=parse_key(params, "NMT_subject_align"), name='NMT_subject_align') else: print("NMT_version {} is not implemented".format(NMT_version)) exit() NMT_subject_align.inputs.NMT_SS_file = params_template["template_brain"] register_NMT_pipe.connect(deoblique, 'out_file', NMT_subject_align, "T1_file") if NMT_version.split(".")[0] == "v1": # align_masks # "overwrap" of NwarpApply, with specifying the outputs as wished list_priors = [params_template["template_head"], params_template["template_csf"], params_template["template_gm"], params_template["template_wm"]] elif NMT_version.split(".")[0] == "v2": # align_masks # "overwrap" of NwarpApply, with specifying the outputs as wished list_priors = [params_template["template_head"], params_template["template_seg"]] align_masks = pe.Node(NwarpApplyPriors(), name='align_masks') align_masks.inputs.in_file = list_priors align_masks.inputs.out_file = list_priors align_masks.inputs.interp = "NN" align_masks.inputs.args = "-overwrite" register_NMT_pipe.connect(NMT_subject_align, 'aff_file', align_masks, 'master') register_NMT_pipe.connect(NMT_subject_align, 'warpinv_file', align_masks, "warp") # align_NMT align_NMT = pe.Node( afni.Allineate(), name="align_NMT", iterfield=['in_file']) align_NMT.inputs.final_interpolation = "nearestneighbour" align_NMT.inputs.overwrite = True align_NMT.inputs.outputtype = "NIFTI_GZ" register_NMT_pipe.connect(align_masks, ('out_file', get_elem, 0), align_NMT, "in_file") # -source register_NMT_pipe.connect(norm_intensity, 'output_image', align_NMT, "reference") # -base register_NMT_pipe.connect(NMT_subject_align, 'inv_transfo_file', align_NMT, "in_matrix") # -1Dmatrix_apply if NMT_version.split(".")[0] == "v1": # seg_csf align_seg_csf = pe.Node( afni.Allineate(), name="align_seg_csf", iterfield=['in_file']) align_seg_csf.inputs.final_interpolation = "nearestneighbour" align_seg_csf.inputs.overwrite = True align_seg_csf.inputs.outputtype = "NIFTI_GZ" register_NMT_pipe.connect(align_masks, ('out_file', get_elem, 1), align_seg_csf, "in_file") # -source register_NMT_pipe.connect(norm_intensity, 'output_image', align_seg_csf, "reference") # -base register_NMT_pipe.connect( NMT_subject_align, 'inv_transfo_file', align_seg_csf, "in_matrix") # -1Dmatrix_apply # seg_gm align_seg_gm = pe.Node( afni.Allineate(), name="align_seg_gm", iterfield=['in_file']) align_seg_gm.inputs.final_interpolation = "nearestneighbour" align_seg_gm.inputs.overwrite = True align_seg_gm.inputs.outputtype = "NIFTI_GZ" register_NMT_pipe.connect(align_masks, ('out_file', get_elem, 2), align_seg_gm, "in_file") # -source register_NMT_pipe.connect(norm_intensity, 'output_image', align_seg_gm, "reference") # -base register_NMT_pipe.connect(NMT_subject_align, 'inv_transfo_file', align_seg_gm, "in_matrix") # -1Dmatrix_apply # seg_wm align_seg_wm = pe.Node(afni.Allineate(), name="align_seg_wm", iterfield=['in_file']) align_seg_wm.inputs.final_interpolation = "nearestneighbour" align_seg_wm.inputs.overwrite = True align_seg_wm.inputs.outputtype = "NIFTI_GZ" register_NMT_pipe.connect(align_masks, ('out_file', get_elem, 3), align_seg_wm, "in_file") # -source register_NMT_pipe.connect(norm_intensity, 'output_image', align_seg_wm, "reference") # -base register_NMT_pipe.connect(NMT_subject_align, 'inv_transfo_file', align_seg_wm, "in_matrix") # -1Dmatrix_apply elif NMT_version.split(".")[0] == "v2": # seg align_seg = pe.Node( afni.Allineate(), name="align_seg", iterfield=['in_file']) align_seg.inputs.final_interpolation = "nearestneighbour" align_seg.inputs.overwrite = True align_seg.inputs.outputtype = "NIFTI_GZ" register_NMT_pipe.connect(align_masks, ('out_file', get_elem, 1), align_seg, "in_file") # -source register_NMT_pipe.connect(norm_intensity, 'output_image', align_seg, "reference") # -base register_NMT_pipe.connect(NMT_subject_align, 'inv_transfo_file', align_seg, "in_matrix") # -1Dmatrix_apply return register_NMT_pipe
def afni_anatomical_linear_registration(workflow, resource_pool, \ config, name="_"): """Build Nipype workflow to calculate the linear registration (participant to template) of an anatomical image using AFNI's 3dAllineate. - If any resources/outputs required by this workflow are not in the resource pool, this workflow will call pre-requisite workflow builder functions to further populate the pipeline with workflows which will calculate/generate these necessary pre-requisites. Expected Settings in Configuration - skull_on_registration: (optional- default: True) Whether or not to accept anatomical_reorient or anatomical_brain as the input for registration. - template_head_for_anat: (for skull-on registration) The reference template of the whole head. - template_brain_for_anat: (for skull-off registration) The reference template of the brain without skull. Expected Resources in Resource Pool - anatomical_reorient: The deobliqued, reoriented anatomical scan. OR - anatomical_brain: The skull-stripped anatomical image (brain only). New Resources Added to Resource Pool - afni_linear_warped_image: The anatomical image transformed to the template (using linear warps). - allineate_linear_xfm: The text file containing the linear warp matrix produced by AFNI's 3dAllineate. Workflow Steps 1. AFNI's 3dAllineate to calculate the linear registration. :type workflow: Nipype workflow object :param workflow: A Nipype workflow object which can already contain other connected nodes; this function will insert the following workflow into this one provided. :type resource_pool: dict :param resource_pool: A dictionary defining input files and pointers to Nipype node outputs / workflow connections; the keys are the resource names. :type config: dict :param config: A dictionary defining the configuration settings for the workflow, such as directory paths or toggled options. :type name: str :param name: (default: "_") A string to append to the end of each node name. :rtype: Nipype workflow object :return: The Nipype workflow originally provided, but with this function's sub-workflow connected into it. :rtype: dict :return: The resource pool originally provided, but updated (if applicable) with the newest outputs and connections. """ import copy import nipype.pipeline.engine as pe import nipype.interfaces.afni as afni if "skull_on_registration" not in config.keys(): config["skull_on_registration"] = True calc_allineate_warp = pe.Node(interface=afni.Allineate(), name='calc_3dAllineate_warp%s' % name) calc_allineate_warp.inputs.outputtype = "NIFTI_GZ" if config["skull_on_registration"]: if "anatomical_reorient" not in resource_pool.keys(): from anatomical_preproc import anatomical_reorient_workflow old_rp = copy.copy(resource_pool) workflow, new_resource_pool = \ anatomical_reorient_workflow(workflow, resource_pool, config, name) if resource_pool == old_rp: return workflow, resource_pool if len(resource_pool["anatomical_reorient"]) == 2: node, out_file = resource_pool["anatomical_reorient"] workflow.connect(node, out_file, calc_allineate_warp, 'in_file') else: calc_allineate_warp.inputs.in_file = \ resource_pool["anatomical_reorient"] calc_allineate_warp.inputs.reference = \ config["template_head_for_anat"] calc_allineate_warp.inputs.out_file = "allineate_warped_head.nii.gz" else: if "anatomical_brain" not in resource_pool.keys(): from anatomical_preproc import anatomical_skullstrip_workflow old_rp = copy.copy(resource_pool) workflow, new_resource_pool = \ anatomical_skullstrip_workflow(workflow, resource_pool, \ config, name) if resource_pool == old_rp: return workflow, resource_pool if len(resource_pool["anatomical_brain"]) == 2: node, out_file = resource_pool["anatomical_brain"] workflow.connect(node, out_file, calc_allineate_warp, 'in_file') else: calc_allineate_warp.inputs.in_file = \ resource_pool["anatomical_brain"] calc_allineate_warp.inputs.reference = \ config["template_brain_for_anat"] calc_allineate_warp.inputs.out_file = \ "allineate_warped_brain.nii.gz" calc_allineate_warp.inputs.out_matrix = "3dallineate_warp" resource_pool["allineate_linear_xfm"] = \ (calc_allineate_warp, 'matrix') resource_pool["afni_linear_warped_image"] = \ (calc_allineate_warp, 'out_file') return workflow, resource_pool
tv_scale=0.5, save_data=False, overwrite=False, output_dir=False, file_name=False) phase_array2[:, :, :, i] = temp_out["result"].get_fdata() # save unwrapped time series name_phase = name_phase + "_unwrap" output = nb.Nifti1Image(phase_array2, magn_img.affine, magn_img.header) nb.save(output, os.path.join(path_phase, name_phase + ext_phase)) """ apply motion correction to unwrapped phase time series """ allineate = afni.Allineate() allineate.inputs.in_file = os.path.join(path_phase, name_phase + ext_phase) allineate.inputs.out_file = os.path.join(path_phase, "u" + name_phase + ext_phase) allineate.inputs.in_matrix = os.path.join(path_moco, 'moco_matrix.1D') allineate.inputs.outputtype = 'NIFTI' allineate.inputs.final_interpolation = 'linear' allineate.inputs.no_pad = True # do not use zero-padding on the base image allineate.run() """ set new basenames to target realigned and temporary timeseries """ name_magn = "u" + name_magn name_phase = "u" + name_phase name_magn_temp = name_magn + "_temp" name_phase_temp = name_phase + "_temp"