def anatomical_init(wf, cfg, strat_pool, pipe_num, opt=None): ''' {"name": "anatomical_init", "config": "None", "switch": "None", "option_key": "None", "option_val": "None", "inputs": ["T1w"], "outputs": ["desc-preproc_T1w", "desc-reorient_T1w"]} ''' anat_deoblique = pe.Node(interface=afni.Refit(), name=f'anat_deoblique_{pipe_num}') anat_deoblique.inputs.deoblique = True node, out = strat_pool.get_data('T1w') wf.connect(node, out, anat_deoblique, 'in_file') anat_reorient = pe.Node(interface=afni.Resample(), name=f'anat_reorient_{pipe_num}') anat_reorient.inputs.orientation = 'RPI' anat_reorient.inputs.outputtype = 'NIFTI_GZ' wf.connect(anat_deoblique, 'out_file', anat_reorient, 'in_file') outputs = { 'desc-preproc_T1w': (anat_reorient, 'out_file'), 'desc-reorient_T1w': (anat_reorient, 'out_file') } return (wf, outputs)
def create_workflow(config: AttrDict, resource_pool: ResourcePool, context: Context): for _, rp in resource_pool[['T1w']]: anat_image = rp[R('T1w')] anat_deoblique = NipypeJob(interface=afni.Refit(deoblique=True), reference='anat_deoblique') anat_deoblique.in_file = anat_image output_node = anat_deoblique.out_file if config.non_local_means_filtering: denoise = NipypeJob(interface=ants.DenoiseImage(), reference='anat_denoise') denoise.input_image = output_node output_node = denoise.output_image if config.n4_bias_field_correction: n4 = NipypeJob(interface=ants.N4BiasFieldCorrection( dimension=3, shrink_factor=2, copy_header=True), reference='anat_n4') n4.input_image = output_node output_node = n4.output_image anat_reorient = NipypeJob(interface=afni.Resample( orientation='RPI', outputtype='NIFTI_GZ'), reference='anat_reorient') anat_reorient.in_file = output_node rp[R('T1w', label='reorient')] = anat_reorient.out_file
def test_mock_nipype(self): with mock_nipype(): from radiome.core.jobs import NipypeJob job = NipypeJob(interface=afni.Refit(deoblique=True), reference='deoblique') in_file = data_path(__file__, 'mocks/sub-0050682_T1w.nii.gz') res = job(in_file=in_file) self.assertEqual(str(res['out_file']), in_file)
def _reset_affines(in_file, out_file, overwrite=False, axes_to_permute=None, axes_to_flip=None, xyzscale=None, center_mass=None, verbose=1): """Sets the qform equal to the sform in the header, with optionally rescaling, setting the image center to 0, permuting or/and flipping axes """ if not os.path.isfile(out_file) or overwrite: shutil.copy(in_file, out_file) else: raise ValueError('{} already existed'.format(out_file)) if verbose: terminal_output = 'stream' else: terminal_output = 'none' in_file = out_file if xyzscale is not None: refit = afni.Refit() refit.inputs.in_file = in_file refit.inputs.xyzscale = xyzscale refit.set_default_terminal_output(terminal_output) result = refit.run() in_file = result.outputs.out_file if center_mass is not None: set_center_mass = afni.CenterMass() set_center_mass.inputs.in_file = in_file set_center_mass.inputs.cm_file = fname_presuffix(out_file, suffix='.txt', use_ext=False) set_center_mass.inputs.set_cm = center_mass # set_center_mass.set_default_terminal_output(terminal_output) # XXX BUG result = set_center_mass.run() in_file = result.outputs.out_file img = nibabel.load(in_file) header = img.header.copy() sform, code = header.get_sform(coded=True) if axes_to_flip: for axis in axes_to_flip: sform[axis] *= -1 if axes_to_permute: for (axis1, axis2) in axes_to_permute: sform[[axis1, axis2]] = sform[[axis2, axis1]] header.set_sform(sform) header.set_qform(sform, int(code)) nibabel.Nifti1Image(img.get_data(), sform, header).to_filename(out_file)
def refit(self, in_file, out_file=None, deoblique=False, args=""): myfit = afni.Refit(in_file=in_file) #https://nipype.readthedocs.io/en/latest/interfaces/generated/interfaces.afni/utils.html#refit myfit.inputs.deoblique = deoblique myfit.inputs.args = args myfit.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 lesion_preproc(lesion_mask: str): lesion_deoblique = NipypeJob(interface=afni.Refit(deoblique=True), reference='lesion_deoblique') lesion_inverted = PythonJob(function=inverse_lesion, reference='inverse_lesion') lesion_reorient = NipypeJob(interface=afni.Resample(orientation='RPI', outputtype='NIFTI_GZ'), reference='lesion_reorient') lesion_inverted.lesion_path = S3Resource(lesion_mask) if lesion_mask.lower( ).startswith('s3://') else lesion_mask lesion_deoblique.in_file = lesion_inverted.lesion_out lesion_reorient.in_file = lesion_deoblique.out_file return lesion_reorient.out_file
def _reorient_wf(name='ReorientWorkflow'): """A workflow to reorient images to 'RPI' orientation.""" workflow = Workflow(name=name) workflow.__desc__ = "Inner workflow. " inputnode = Node(niu.IdentityInterface(fields=['in_file']), name='inputnode') outputnode = Node(niu.IdentityInterface(fields=['out_file']), name='outputnode') deoblique = Node(afni.Refit(deoblique=True), name='deoblique') reorient = Node(afni.Resample(orientation='RPI', outputtype='NIFTI_GZ'), name='reorient') workflow.connect([(inputnode, deoblique, [('in_file', 'in_file')]), (deoblique, reorient, [('out_file', 'in_file')]), (reorient, outputnode, [('out_file', 'out_file')])]) return workflow
def create_workflow(config: AttrDict, resource_pool: ResourcePool, context: Context): for _, rp in resource_pool[['T1w']]: anat_image = rp[R('T1w')] anat_deoblique = NipypeJob( interface=afni.Refit(deoblique=True), reference='deoblique' ) anat_deoblique.in_file = anat_image output_node = anat_deoblique.out_file anat_reorient = NipypeJob( interface=afni.Resample(orientation='RPI', outputtype='NIFTI_GZ'), reference='reorient' ) anat_reorient.in_file = output_node rp[R('T1w', label='reorient')] = anat_reorient.out_file
def _reorient_wf(name="ReorientWorkflow"): """A workflow to reorient images to 'RPI' orientation.""" workflow = Workflow(name=name) workflow.__desc__ = "Inner workflow. " inputnode = Node(niu.IdentityInterface(fields=["in_file"]), name="inputnode") outputnode = Node(niu.IdentityInterface(fields=["out_file"]), name="outputnode") deoblique = Node(afni.Refit(deoblique=True), name="deoblique") reorient = Node(afni.Resample(orientation="RPI", outputtype="NIFTI_GZ"), name="reorient") workflow.connect([ (inputnode, deoblique, [("in_file", "in_file")]), (deoblique, reorient, [("out_file", "in_file")]), (reorient, outputnode, [("out_file", "out_file")]), ]) return workflow
def test_refit(): input_map = dict( args=dict(argstr='%s', ), deoblique=dict(argstr='-deoblique', ), environ=dict(usedefault=True, ), ignore_exception=dict(usedefault=True, ), in_file=dict( copyfile=True, mandatory=True, argstr='%s', ), outputtype=dict(), xorigin=dict(argstr='-xorigin %s', ), yorigin=dict(argstr='-yorigin %s', ), zorigin=dict(argstr='-zorigin %s', ), ) instance = afni.Refit() for key, metadata in input_map.items(): for metakey, value in metadata.items(): yield assert_equal, getattr(instance.inputs.traits()[key], metakey), value
def _delete_orientation(in_file, write_dir=None, min_zoom=.1, caching=False, verbose=True): if write_dir is None: write_dir = os.path.dirname(in_file) if verbose: terminal_output = 'stream' else: terminal_output = 'none' if caching: memory = Memory(write_dir) copy = memory.cache(afni.Copy) refit = memory.cache(afni.Refit) center_mass = memory.cache(afni.CenterMass) for step in [copy, refit]: step.interface().set_default_terminal_output(terminal_output) else: copy = afni.Copy(terminal_output=terminal_output).run refit = afni.Refit(terminal_output=terminal_output).run center_mass = afni.CenterMass().run out_copy = copy(in_file=in_file, out_file=fname_presuffix(in_file, newpath=write_dir)) zooms = nibabel.load(in_file).header.get_zooms()[:3] out_refit = refit(in_file=out_copy.outputs.out_file, xyzscale=min_zoom / min(zooms)) out_center_mass = center_mass(in_file=out_refit.outputs.out_file, cm_file=fname_presuffix(in_file, suffix='.txt', use_ext=False, newpath=write_dir), set_cm=(0, 0, 0)) return out_center_mass.outputs.out_file
def create_anat_preproc(template_path=None, mask_path=None, regmask_path=None, method='afni', already_skullstripped=False, non_local_means_filtering=True, n4_correction=True, wf_name='anat_preproc'): """ The main purpose of this workflow is to process T1 scans. Raw mprage file is deobliqued, reoriented into RPI and skullstripped. Also, a whole brain only mask is generated from the skull stripped image for later use in registration. Returns ------- anat_preproc : workflow Anatomical Preprocessing Workflow Notes ----- `Source <https://github.com/FCP-INDI/C-PAC/blob/master/CPAC/anat_preproc/anat_preproc.py>`_ Workflow Inputs:: inputspec.anat : string User input anatomical (T1) Image, in any of the 8 orientations Workflow Outputs:: outputspec.refit : string Path to deobliqued anatomical image outputspec.reorient : string Path to RPI oriented anatomical image outputspec.skullstrip : string Path to skull stripped RPI oriented mprage file with normalized intensities. outputspec.brain : string Path to skull stripped RPI brain image with original intensity values and not normalized or scaled. Order of commands: - Deobliqing the scans. :: 3drefit -deoblique mprage.nii.gz - Re-orienting the Image into Right-to-Left Posterior-to-Anterior Inferior-to-Superior (RPI) orientation :: 3dresample -orient RPI -prefix mprage_RPI.nii.gz -inset mprage.nii.gz - Skull-Stripping the image :: Using AFNI :: 3dSkullStrip -input mprage_RPI.nii.gz -o_ply mprage_RPI_3dT.nii.gz or using BET :: bet mprage_RPI.nii.gz - The skull-stripping step modifies the intensity values. To get back the original intensity values, we do an element wise product of RPI data with step function of skull-stripped data :: 3dcalc -a mprage_RPI.nii.gz -b mprage_RPI_3dT.nii.gz -expr 'a*step(b)' -prefix mprage_RPI_3dc.nii.gz High Level Workflow Graph: .. image:: ../images/anatpreproc_graph.dot.png :width: 500 Detailed Workflow Graph: .. image:: ../images/anatpreproc_graph_detailed.dot.png :width: 500 Examples -------- >>> from CPAC.anat_preproc import create_anat_preproc >>> preproc = create_anat_preproc() >>> preproc.inputs.inputspec.anat = 'sub1/anat/mprage.nii.gz' >>> preproc.run() #doctest: +SKIP """ preproc = pe.Workflow(name=wf_name) inputnode = pe.Node(util.IdentityInterface(fields=['anat', 'brain_mask']), name='inputspec') outputnode = pe.Node(util.IdentityInterface( fields=['refit', 'reorient', 'skullstrip', 'brain', 'brain_mask']), name='outputspec') anat_deoblique = pe.Node(interface=afni.Refit(), name='anat_deoblique') anat_deoblique.inputs.deoblique = True preproc.connect(inputnode, 'anat', anat_deoblique, 'in_file') preproc.connect(anat_deoblique, 'out_file', outputnode, 'refit') # Disable non_local_means_filtering and n4_correction when run niworkflows-ants if method == 'niworkflows-ants': non_local_means_filtering = False n4_correction = False if non_local_means_filtering and n4_correction: denoise = pe.Node(interface=ants.DenoiseImage(), name='anat_denoise') preproc.connect(anat_deoblique, 'out_file', denoise, 'input_image') n4 = pe.Node(interface=ants.N4BiasFieldCorrection(dimension=3, shrink_factor=2, copy_header=True), name='anat_n4') preproc.connect(denoise, 'output_image', n4, 'input_image') elif non_local_means_filtering and not n4_correction: denoise = pe.Node(interface=ants.DenoiseImage(), name='anat_denoise') preproc.connect(anat_deoblique, 'out_file', denoise, 'input_image') elif not non_local_means_filtering and n4_correction: n4 = pe.Node(interface=ants.N4BiasFieldCorrection(dimension=3, shrink_factor=2, copy_header=True), name='anat_n4') preproc.connect(anat_deoblique, 'out_file', n4, 'input_image') # Anatomical reorientation anat_reorient = pe.Node(interface=afni.Resample(), name='anat_reorient') anat_reorient.inputs.orientation = 'RPI' anat_reorient.inputs.outputtype = 'NIFTI_GZ' if n4_correction: preproc.connect(n4, 'output_image', anat_reorient, 'in_file') elif non_local_means_filtering and not n4_correction: preproc.connect(denoise, 'output_image', anat_reorient, 'in_file') else: preproc.connect(anat_deoblique, 'out_file', anat_reorient, 'in_file') preproc.connect(anat_reorient, 'out_file', outputnode, 'reorient') if already_skullstripped: anat_skullstrip = pe.Node( interface=util.IdentityInterface(fields=['out_file']), name='anat_skullstrip') preproc.connect(anat_reorient, 'out_file', anat_skullstrip, 'out_file') preproc.connect(anat_skullstrip, 'out_file', outputnode, 'skullstrip') preproc.connect(anat_skullstrip, 'out_file', outputnode, 'brain') else: if method == 'afni': # Skull-stripping using AFNI 3dSkullStrip inputnode_afni = pe.Node(util.IdentityInterface(fields=[ 'shrink_factor', 'var_shrink_fac', 'shrink_fac_bot_lim', 'avoid_vent', 'niter', 'pushout', 'touchup', 'fill_hole', 'avoid_eyes', 'use_edge', 'exp_frac', 'smooth_final', 'push_to_edge', 'use_skull', 'perc_int', 'max_inter_iter', 'blur_fwhm', 'fac', 'monkey' ]), name='AFNI_options') skullstrip_args = pe.Node(util.Function( input_names=[ 'spat_norm', 'spat_norm_dxyz', 'shrink_fac', 'var_shrink_fac', 'shrink_fac_bot_lim', 'avoid_vent', 'niter', 'pushout', 'touchup', 'fill_hole', 'avoid_eyes', 'use_edge', 'exp_frac', 'smooth_final', 'push_to_edge', 'use_skull', 'perc_int', 'max_inter_iter', 'blur_fwhm', 'fac', 'monkey' ], output_names=['expr'], function=create_3dskullstrip_arg_string), name='anat_skullstrip_args') preproc.connect([(inputnode_afni, skullstrip_args, [('shrink_factor', 'shrink_fac'), ('var_shrink_fac', 'var_shrink_fac'), ('shrink_fac_bot_lim', 'shrink_fac_bot_lim'), ('avoid_vent', 'avoid_vent'), ('niter', 'niter'), ('pushout', 'pushout'), ('touchup', 'touchup'), ('fill_hole', 'fill_hole'), ('avoid_eyes', 'avoid_eyes'), ('use_edge', 'use_edge'), ('exp_frac', 'exp_frac'), ('smooth_final', 'smooth_final'), ('push_to_edge', 'push_to_edge'), ('use_skull', 'use_skull'), ('perc_int', 'perc_int'), ('max_inter_iter', 'max_inter_iter'), ('blur_fwhm', 'blur_fwhm'), ('fac', 'fac'), ('monkey', 'monkey')])]) anat_skullstrip = pe.Node(interface=afni.SkullStrip(), name='anat_skullstrip') anat_skullstrip.inputs.outputtype = 'NIFTI_GZ' preproc.connect(anat_reorient, 'out_file', anat_skullstrip, 'in_file') preproc.connect(skullstrip_args, 'expr', anat_skullstrip, 'args') preproc.connect(anat_skullstrip, 'out_file', outputnode, 'skullstrip') # Apply skull-stripping step mask to original volume anat_skullstrip_orig_vol = pe.Node(interface=afni.Calc(), name='anat_skullstrip_orig_vol') anat_skullstrip_orig_vol.inputs.expr = 'a*step(b)' anat_skullstrip_orig_vol.inputs.outputtype = 'NIFTI_GZ' preproc.connect(anat_reorient, 'out_file', anat_skullstrip_orig_vol, 'in_file_a') anat_brain_mask = pe.Node(interface=afni.Calc(), name='anat_brain_mask') anat_brain_mask.inputs.expr = 'step(a)' anat_brain_mask.inputs.outputtype = 'NIFTI_GZ' preproc.connect(anat_skullstrip, 'out_file', anat_brain_mask, 'in_file_a') preproc.connect(anat_skullstrip, 'out_file', anat_skullstrip_orig_vol, 'in_file_b') preproc.connect(anat_brain_mask, 'out_file', outputnode, 'brain_mask') preproc.connect(anat_skullstrip_orig_vol, 'out_file', outputnode, 'brain') elif method == 'fsl': # Skull-stripping using FSL BET inputnode_bet = pe.Node(util.IdentityInterface(fields=[ 'frac', 'mask_boolean', 'mesh_boolean', 'outline', 'padding', 'radius', 'reduce_bias', 'remove_eyes', 'robust', 'skull', 'surfaces', 'threshold', 'vertical_gradient' ]), name='BET_options') anat_skullstrip = pe.Node(interface=fsl.BET(), name='anat_skullstrip') preproc.connect(anat_reorient, 'out_file', anat_skullstrip, 'in_file') preproc.connect([(inputnode_bet, anat_skullstrip, [ ('frac', 'frac'), ('mask_boolean', 'mask'), ('mesh_boolean', 'mesh'), ('outline', 'outline'), ('padding', 'padding'), ('radius', 'radius'), ('reduce_bias', 'reduce_bias'), ('remove_eyes', 'remove_eyes'), ('robust', 'robust'), ('skull', 'skull'), ('surfaces', 'surfaces'), ('threshold', 'threshold'), ('vertical_gradient', 'vertical_gradient'), ])]) preproc.connect(anat_skullstrip, 'out_file', outputnode, 'skullstrip') # Apply skull-stripping step mask to original volume anat_skullstrip_orig_vol = pe.Node(interface=afni.Calc(), name='anat_skullstrip_orig_vol') anat_skullstrip_orig_vol.inputs.expr = 'a*step(b)' anat_skullstrip_orig_vol.inputs.outputtype = 'NIFTI_GZ' preproc.connect(anat_reorient, 'out_file', anat_skullstrip_orig_vol, 'in_file_a') preproc.connect(anat_skullstrip, 'out_file', anat_skullstrip_orig_vol, 'in_file_b') preproc.connect(anat_skullstrip, 'mask_file', outputnode, 'brain_mask') preproc.connect(anat_skullstrip_orig_vol, 'out_file', outputnode, 'brain') elif method == 'niworkflows-ants': # Skull-stripping using niworkflows-ants anat_skullstrip_ants = init_brain_extraction_wf( tpl_target_path=template_path, tpl_mask_path=mask_path, tpl_regmask_path=regmask_path, name='anat_skullstrip_ants') preproc.connect(anat_reorient, 'out_file', anat_skullstrip_ants, 'inputnode.in_files') preproc.connect(anat_skullstrip_ants, 'copy_xform.out_file', outputnode, 'skullstrip') preproc.connect(anat_skullstrip_ants, 'copy_xform.out_file', outputnode, 'brain') preproc.connect(anat_skullstrip_ants, 'atropos_wf.copy_xform.out_mask', outputnode, 'brain_mask') elif method == 'mask': anat_skullstrip_orig_vol = pe.Node(interface=afni.Calc(), name='anat_skullstrip_orig_vol') anat_skullstrip_orig_vol.inputs.expr = 'a*step(b)' anat_skullstrip_orig_vol.inputs.outputtype = 'NIFTI_GZ' preproc.connect(anat_reorient, 'out_file', anat_skullstrip_orig_vol, 'in_file_a') preproc.connect(inputnode, 'brain_mask', anat_skullstrip_orig_vol, 'in_file_b') preproc.connect(inputnode, 'brain_mask', outputnode, 'brain_mask') preproc.connect(anat_skullstrip_orig_vol, 'out_file', outputnode, 'brain') return preproc
def create_lesion_preproc(wf_name='lesion_preproc'): """ The main purpose of this workflow is to process lesions masks. Lesion mask file is deobliqued and reoriented in the same way as the T1 in the anat_preproc function. Returns ------- lesion_preproc : workflow Lesion preprocessing Workflow Workflow Inputs:: inputspec.lesion : string User input lesion mask, in any of the 8 orientations Workflow Outputs:: outputspec.refit : string Path to deobliqued anatomical image outputspec.reorient : string Path to RPI oriented anatomical image Order of commands: - Deobliqing the scans. :: 3drefit -deoblique mprage.nii.gz - Re-orienting the Image into Right-to-Left Posterior-to-Anterior Inferior-to-Superior (RPI) orientation :: 3dresample -orient RPI -prefix mprage_RPI.nii.gz -inset mprage.nii.gz Examples -------- >>> from CPAC.anat_preproc.lesion_preproc import create_lesion_preproc >>> preproc = create_lesion_preproc() >>> preproc.inputs.inputspec.lesion = 'sub1/anat/lesion-mask.nii.gz' >>> preproc.run() #doctest: +SKIP """ preproc = pe.Workflow(name=wf_name) inputnode = pe.Node(util.IdentityInterface(fields=['lesion']), name='inputspec') outputnode = pe.Node(util.IdentityInterface(fields=['refit', 'reorient']), name='outputspec') lesion_deoblique = pe.Node(interface=afni.Refit(), name='lesion_deoblique') lesion_deoblique.inputs.deoblique = True lesion_inverted = pe.Node(interface=util.Function( input_names=['lesion_path'], output_names=['lesion_out'], function=inverse_lesion), name='inverse_lesion') # We first check and invert the lesion if needed to be used by ANTs preproc.connect(inputnode, 'lesion', lesion_inverted, 'lesion_path') preproc.connect(lesion_inverted, 'lesion_out', lesion_deoblique, 'in_file') preproc.connect(lesion_deoblique, 'out_file', outputnode, 'refit') # Anatomical reorientation lesion_reorient = pe.Node(interface=afni.Resample(), name='lesion_reorient') lesion_reorient.inputs.orientation = 'RPI' lesion_reorient.inputs.outputtype = 'NIFTI_GZ' preproc.connect(lesion_deoblique, 'out_file', lesion_reorient, 'in_file') preproc.connect(lesion_reorient, 'out_file', outputnode, 'reorient') return preproc
def create_anat_preproc(method='afni', already_skullstripped=False, c=None, wf_name='anat_preproc'): """The main purpose of this workflow is to process T1 scans. Raw mprage file is deobliqued, reoriented into RPI and skullstripped. Also, a whole brain only mask is generated from the skull stripped image for later use in registration. Returns ------- anat_preproc : workflow Anatomical Preprocessing Workflow Notes ----- `Source <https://github.com/FCP-INDI/C-PAC/blob/master/CPAC/anat_preproc/anat_preproc.py>`_ Workflow Inputs:: inputspec.anat : string User input anatomical (T1) Image, in any of the 8 orientations Workflow Outputs:: outputspec.refit : string Path to deobliqued anatomical image outputspec.reorient : string Path to RPI oriented anatomical image outputspec.skullstrip : string Path to skull stripped RPI oriented mprage file with normalized intensities. outputspec.brain : string Path to skull stripped RPI brain image with original intensity values and not normalized or scaled. Order of commands: - Deobliqing the scans. :: 3drefit -deoblique mprage.nii.gz - Re-orienting the Image into Right-to-Left Posterior-to-Anterior Inferior-to-Superior (RPI) orientation :: 3dresample -orient RPI -prefix mprage_RPI.nii.gz -inset mprage.nii.gz - Skull-Stripping the image :: Using AFNI :: 3dSkullStrip -input mprage_RPI.nii.gz -o_ply mprage_RPI_3dT.nii.gz or using BET :: bet mprage_RPI.nii.gz - The skull-stripping step modifies the intensity values. To get back the original intensity values, we do an element wise product of RPI data with step function of skull-stripped data :: 3dcalc -a mprage_RPI.nii.gz -b mprage_RPI_3dT.nii.gz -expr 'a*step(b)' -prefix mprage_RPI_3dc.nii.gz High Level Workflow Graph: .. image:: ../images/anatpreproc_graph.dot.png :width: 500 Detailed Workflow Graph: .. image:: ../images/anatpreproc_graph_detailed.dot.png :width: 500 Examples -------- >>> from CPAC.anat_preproc import create_anat_preproc >>> preproc = create_anat_preproc() >>> preproc.inputs.inputspec.anat = 'sub1/anat/mprage.nii.gz' >>> preproc.run() #doctest: +SKIP """ preproc = pe.Workflow(name=wf_name) inputnode = pe.Node(util.IdentityInterface(fields=['anat', 'brain_mask']), name='inputspec') outputnode = pe.Node(util.IdentityInterface( fields=['refit', 'reorient', 'skullstrip', 'brain', 'brain_mask']), name='outputspec') anat_deoblique = pe.Node(interface=afni.Refit(), name='anat_deoblique') anat_deoblique.inputs.deoblique = True preproc.connect(inputnode, 'anat', anat_deoblique, 'in_file') preproc.connect(anat_deoblique, 'out_file', outputnode, 'refit') # Disable non_local_means_filtering and n4_bias_field_correction when run niworkflows-ants if method == 'niworkflows-ants': c.non_local_means_filtering = False c.n4_bias_field_correction = False if c.non_local_means_filtering and c.n4_bias_field_correction: denoise = pe.Node(interface=ants.DenoiseImage(), name='anat_denoise') preproc.connect(anat_deoblique, 'out_file', denoise, 'input_image') n4 = pe.Node(interface=ants.N4BiasFieldCorrection(dimension=3, shrink_factor=2, copy_header=True), name='anat_n4') preproc.connect(denoise, 'output_image', n4, 'input_image') elif c.non_local_means_filtering and not c.n4_bias_field_correction: denoise = pe.Node(interface=ants.DenoiseImage(), name='anat_denoise') preproc.connect(anat_deoblique, 'out_file', denoise, 'input_image') elif not c.non_local_means_filtering and c.n4_bias_field_correction: n4 = pe.Node(interface=ants.N4BiasFieldCorrection(dimension=3, shrink_factor=2, copy_header=True), name='anat_n4') preproc.connect(anat_deoblique, 'out_file', n4, 'input_image') # Anatomical reorientation anat_reorient = pe.Node(interface=afni.Resample(), name='anat_reorient') anat_reorient.inputs.orientation = 'RPI' anat_reorient.inputs.outputtype = 'NIFTI_GZ' if c.n4_bias_field_correction: preproc.connect(n4, 'output_image', anat_reorient, 'in_file') elif c.non_local_means_filtering and not c.n4_bias_field_correction: preproc.connect(denoise, 'output_image', anat_reorient, 'in_file') else: preproc.connect(anat_deoblique, 'out_file', anat_reorient, 'in_file') preproc.connect(anat_reorient, 'out_file', outputnode, 'reorient') if already_skullstripped: anat_skullstrip = pe.Node( interface=util.IdentityInterface(fields=['out_file']), name='anat_skullstrip') preproc.connect(anat_reorient, 'out_file', anat_skullstrip, 'out_file') preproc.connect(anat_skullstrip, 'out_file', outputnode, 'skullstrip') preproc.connect(anat_skullstrip, 'out_file', outputnode, 'brain') else: if method == 'afni': # Skull-stripping using AFNI 3dSkullStrip inputnode_afni = pe.Node(util.IdentityInterface(fields=[ 'mask_vol', 'shrink_factor', 'var_shrink_fac', 'shrink_fac_bot_lim', 'avoid_vent', 'niter', 'pushout', 'touchup', 'fill_hole', 'avoid_eyes', 'use_edge', 'exp_frac', 'smooth_final', 'push_to_edge', 'use_skull', 'perc_int', 'max_inter_iter', 'blur_fwhm', 'fac', 'monkey' ]), name='AFNI_options') skullstrip_args = pe.Node(util.Function( input_names=[ 'spat_norm', 'spat_norm_dxyz', 'mask_vol', 'shrink_fac', 'var_shrink_fac', 'shrink_fac_bot_lim', 'avoid_vent', 'niter', 'pushout', 'touchup', 'fill_hole', 'avoid_eyes', 'use_edge', 'exp_frac', 'smooth_final', 'push_to_edge', 'use_skull', 'perc_int', 'max_inter_iter', 'blur_fwhm', 'fac', 'monkey' ], output_names=['expr'], function=create_3dskullstrip_arg_string), name='anat_skullstrip_args') preproc.connect([(inputnode_afni, skullstrip_args, [('mask_vol', 'mask_vol'), ('shrink_factor', 'shrink_fac'), ('var_shrink_fac', 'var_shrink_fac'), ('shrink_fac_bot_lim', 'shrink_fac_bot_lim'), ('avoid_vent', 'avoid_vent'), ('niter', 'niter'), ('pushout', 'pushout'), ('touchup', 'touchup'), ('fill_hole', 'fill_hole'), ('avoid_eyes', 'avoid_eyes'), ('use_edge', 'use_edge'), ('exp_frac', 'exp_frac'), ('smooth_final', 'smooth_final'), ('push_to_edge', 'push_to_edge'), ('use_skull', 'use_skull'), ('perc_int', 'perc_int'), ('max_inter_iter', 'max_inter_iter'), ('blur_fwhm', 'blur_fwhm'), ('fac', 'fac'), ('monkey', 'monkey')])]) anat_skullstrip = pe.Node(interface=afni.SkullStrip(), name='anat_skullstrip') anat_skullstrip.inputs.outputtype = 'NIFTI_GZ' preproc.connect(anat_reorient, 'out_file', anat_skullstrip, 'in_file') preproc.connect(skullstrip_args, 'expr', anat_skullstrip, 'args') # Generate anatomical brain mask anat_brain_mask = pe.Node(interface=afni.Calc(), name='anat_brain_mask') anat_brain_mask.inputs.expr = 'step(a)' anat_brain_mask.inputs.outputtype = 'NIFTI_GZ' preproc.connect(anat_skullstrip, 'out_file', anat_brain_mask, 'in_file_a') # Apply skull-stripping step mask to original volume anat_skullstrip_orig_vol = pe.Node(interface=afni.Calc(), name='anat_skullstrip_orig_vol') anat_skullstrip_orig_vol.inputs.expr = 'a*step(b)' anat_skullstrip_orig_vol.inputs.outputtype = 'NIFTI_GZ' preproc.connect(anat_reorient, 'out_file', anat_skullstrip_orig_vol, 'in_file_a') preproc.connect(anat_brain_mask, 'out_file', anat_skullstrip_orig_vol, 'in_file_b') preproc.connect(anat_brain_mask, 'out_file', outputnode, 'brain_mask') preproc.connect(anat_skullstrip_orig_vol, 'out_file', outputnode, 'brain') elif method == 'fsl': # Skull-stripping using FSL BET inputnode_bet = pe.Node(util.IdentityInterface(fields=[ 'frac', 'mask_boolean', 'mesh_boolean', 'outline', 'padding', 'radius', 'reduce_bias', 'remove_eyes', 'robust', 'skull', 'surfaces', 'threshold', 'vertical_gradient' ]), name='BET_options') anat_skullstrip = pe.Node(interface=fsl.BET(), name='anat_skullstrip') anat_skullstrip.inputs.output_type = 'NIFTI_GZ' preproc.connect(anat_reorient, 'out_file', anat_skullstrip, 'in_file') preproc.connect([(inputnode_bet, anat_skullstrip, [ ('frac', 'frac'), ('mask_boolean', 'mask'), ('mesh_boolean', 'mesh'), ('outline', 'outline'), ('padding', 'padding'), ('radius', 'radius'), ('reduce_bias', 'reduce_bias'), ('remove_eyes', 'remove_eyes'), ('robust', 'robust'), ('skull', 'skull'), ('surfaces', 'surfaces'), ('threshold', 'threshold'), ('vertical_gradient', 'vertical_gradient'), ])]) preproc.connect(anat_skullstrip, 'out_file', outputnode, 'skullstrip') # Apply skull-stripping step mask to original volume anat_skullstrip_orig_vol = pe.Node(interface=afni.Calc(), name='anat_skullstrip_orig_vol') anat_skullstrip_orig_vol.inputs.expr = 'a*step(b)' anat_skullstrip_orig_vol.inputs.outputtype = 'NIFTI_GZ' preproc.connect(anat_reorient, 'out_file', anat_skullstrip_orig_vol, 'in_file_a') preproc.connect(anat_skullstrip, 'out_file', anat_skullstrip_orig_vol, 'in_file_b') preproc.connect(anat_skullstrip, 'mask_file', outputnode, 'brain_mask') preproc.connect(anat_skullstrip_orig_vol, 'out_file', outputnode, 'brain') elif method == 'niworkflows-ants': # Skull-stripping using niworkflows-ants anat_skullstrip_ants = init_brain_extraction_wf( tpl_target_path=c.niworkflows_ants_template_path, tpl_mask_path=c.niworkflows_ants_mask_path, tpl_regmask_path=c.niworkflows_ants_regmask_path, name='anat_skullstrip_ants') preproc.connect(anat_reorient, 'out_file', anat_skullstrip_ants, 'inputnode.in_files') preproc.connect(anat_skullstrip_ants, 'copy_xform.out_file', outputnode, 'skullstrip') preproc.connect(anat_skullstrip_ants, 'copy_xform.out_file', outputnode, 'brain') preproc.connect(anat_skullstrip_ants, 'atropos_wf.copy_xform.out_mask', outputnode, 'brain_mask') elif method == 'mask': brain_mask_deoblique = pe.Node(interface=afni.Refit(), name='brain_mask_deoblique') brain_mask_deoblique.inputs.deoblique = True preproc.connect(inputnode, 'brain_mask', brain_mask_deoblique, 'in_file') brain_mask_reorient = pe.Node(interface=afni.Resample(), name='brain_mask_reorient') brain_mask_reorient.inputs.orientation = 'RPI' brain_mask_reorient.inputs.outputtype = 'NIFTI_GZ' preproc.connect(brain_mask_deoblique, 'out_file', brain_mask_reorient, 'in_file') anat_skullstrip_orig_vol = pe.Node(interface=afni.Calc(), name='anat_skullstrip_orig_vol') anat_skullstrip_orig_vol.inputs.expr = 'a*step(b)' anat_skullstrip_orig_vol.inputs.outputtype = 'NIFTI_GZ' preproc.connect(anat_reorient, 'out_file', anat_skullstrip_orig_vol, 'in_file_a') preproc.connect(brain_mask_reorient, 'out_file', anat_skullstrip_orig_vol, 'in_file_b') preproc.connect(brain_mask_reorient, 'out_file', outputnode, 'brain_mask') preproc.connect(anat_skullstrip_orig_vol, 'out_file', outputnode, 'brain') elif method == 'unet': """ UNet options (following numbers are default): input_slice: 3 conv_block: 5 kernel_root: 16 rescale_dim: 256 """ # TODO: add options to pipeline_config train_model = UNet2d(dim_in=3, num_conv_block=5, kernel_root=16) unet_path = check_for_s3(c.unet_model) checkpoint = torch.load(unet_path, map_location={'cuda:0': 'cpu'}) train_model.load_state_dict(checkpoint['state_dict']) model = nn.Sequential(train_model, nn.Softmax2d()) # create a node called unet_mask unet_mask = pe.Node(util.Function(input_names=['model', 'cimg_in'], output_names=['out_path'], function=predict_volumes), name='unet_mask') unet_mask.inputs.model = model preproc.connect(anat_reorient, 'out_file', unet_mask, 'cimg_in') """ Revised mask with ANTs """ # fslmaths <whole head> -mul <mask> brain.nii.gz unet_masked_brain = pe.Node(interface=fsl.MultiImageMaths(), name='unet_masked_brain') unet_masked_brain.inputs.op_string = "-mul %s" preproc.connect(anat_reorient, 'out_file', unet_masked_brain, 'in_file') preproc.connect(unet_mask, 'out_path', unet_masked_brain, 'operand_files') # flirt -v -dof 6 -in brain.nii.gz -ref NMT_SS_0.5mm.nii.gz -o brain_rot2atl -omat brain_rot2atl.mat -interp sinc # TODO change it to ANTs linear transform native_brain_to_template_brain = pe.Node( interface=fsl.FLIRT(), name='native_brain_to_template_brain') native_brain_to_template_brain.inputs.reference = c.template_brain_only_for_anat native_brain_to_template_brain.inputs.dof = 6 native_brain_to_template_brain.inputs.interp = 'sinc' preproc.connect(unet_masked_brain, 'out_file', native_brain_to_template_brain, 'in_file') # flirt -in head.nii.gz -ref NMT_0.5mm.nii.gz -o head_rot2atl -applyxfm -init brain_rot2atl.mat # TODO change it to ANTs linear transform native_head_to_template_head = pe.Node( interface=fsl.FLIRT(), name='native_head_to_template_head') native_head_to_template_head.inputs.reference = c.template_skull_for_anat native_head_to_template_head.inputs.apply_xfm = True preproc.connect(anat_reorient, 'out_file', native_head_to_template_head, 'in_file') preproc.connect(native_brain_to_template_brain, 'out_matrix_file', native_head_to_template_head, 'in_matrix_file') # fslmaths NMT_SS_0.5mm.nii.gz -bin templateMask.nii.gz template_brain_mask = pe.Node(interface=fsl.maths.MathsCommand(), name='template_brain_mask') template_brain_mask.inputs.in_file = c.template_brain_only_for_anat template_brain_mask.inputs.args = '-bin' # ANTS 3 -m CC[head_rot2atl.nii.gz,NMT_0.5mm.nii.gz,1,5] -t SyN[0.25] -r Gauss[3,0] -o atl2T1rot -i 60x50x20 --use-Histogram-Matching --number-of-affine-iterations 10000x10000x10000x10000x10000 --MI-option 32x16000 ants_template_head_to_template = pe.Node( interface=ants.Registration(), name='template_head_to_template') ants_template_head_to_template.inputs.metric = ['CC'] ants_template_head_to_template.inputs.metric_weight = [1, 5] ants_template_head_to_template.inputs.moving_image = c.template_skull_for_anat ants_template_head_to_template.inputs.transforms = ['SyN'] ants_template_head_to_template.inputs.transform_parameters = [ (0.25, ) ] ants_template_head_to_template.inputs.interpolation = 'NearestNeighbor' ants_template_head_to_template.inputs.number_of_iterations = [[ 60, 50, 20 ]] ants_template_head_to_template.inputs.smoothing_sigmas = [[ 0.6, 0.2, 0.0 ]] ants_template_head_to_template.inputs.shrink_factors = [[4, 2, 1]] ants_template_head_to_template.inputs.convergence_threshold = [ 1.e-8 ] preproc.connect(native_head_to_template_head, 'out_file', ants_template_head_to_template, 'fixed_image') # antsApplyTransforms -d 3 -i templateMask.nii.gz -t atl2T1rotWarp.nii.gz atl2T1rotAffine.txt -r brain_rot2atl.nii.gz -o brain_rot2atl_mask.nii.gz template_head_transform_to_template = pe.Node( interface=ants.ApplyTransforms(), name='template_head_transform_to_template') template_head_transform_to_template.inputs.dimension = 3 preproc.connect(template_brain_mask, 'out_file', template_head_transform_to_template, 'input_image') preproc.connect(native_brain_to_template_brain, 'out_file', template_head_transform_to_template, 'reference_image') preproc.connect(ants_template_head_to_template, 'forward_transforms', template_head_transform_to_template, 'transforms') # convert_xfm -omat brain_rot2native.mat -inverse brain_rot2atl.mat invt = pe.Node(interface=fsl.ConvertXFM(), name='convert_xfm') invt.inputs.invert_xfm = True preproc.connect(native_brain_to_template_brain, 'out_matrix_file', invt, 'in_file') # flirt -in brain_rot2atl_mask.nii.gz -ref brain.nii.gz -o brain_mask.nii.gz -applyxfm -init brain_rot2native.mat template_brain_to_native_brain = pe.Node( interface=fsl.FLIRT(), name='template_brain_to_native_brain') template_brain_to_native_brain.inputs.apply_xfm = True preproc.connect(template_head_transform_to_template, 'output_image', template_brain_to_native_brain, 'in_file') preproc.connect(unet_masked_brain, 'out_file', template_brain_to_native_brain, 'reference') preproc.connect(invt, 'out_file', template_brain_to_native_brain, 'in_matrix_file') # fslmaths brain_mask.nii.gz -thr .5 -bin brain_mask_thr.nii.gz refined_mask = pe.Node(interface=fsl.Threshold(), name='refined_mask') refined_mask.inputs.thresh = 0.5 preproc.connect(template_brain_to_native_brain, 'out_file', refined_mask, 'in_file') # get a new brain with mask refined_brain = pe.Node(interface=fsl.MultiImageMaths(), name='refined_brain') refined_brain.inputs.op_string = "-mul %s" preproc.connect(anat_reorient, 'out_file', refined_brain, 'in_file') preproc.connect(refined_mask, 'out_file', refined_brain, 'operand_files') preproc.connect(refined_mask, 'out_file', outputnode, 'brain_mask') preproc.connect(refined_brain, 'out_file', outputnode, 'brain') return preproc
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 fix_obliquity(to_fix_filename, reference_filename, caching=False, caching_dir=None, overwrite=False, verbose=True, environ=None): if caching_dir is None: caching_dir = os.getcwd() if caching: memory = Memory(caching_dir) if verbose: terminal_output = 'allatonce' else: terminal_output = 'none' if environ is None: if caching: environ = {} else: environ = {'AFNI_DECONFLICT': 'OVERWRITE'} if caching: copy = memory.cache(afni.Copy) refit = memory.cache(afni.Refit) copy.interface().set_default_terminal_output(terminal_output) refit.interface().set_default_terminal_output(terminal_output) else: copy = afni.Copy(terminal_output=terminal_output).run refit = afni.Refit(terminal_output=terminal_output).run tmp_folder = os.path.join(caching_dir, 'tmp') if not os.path.isdir(tmp_folder): os.makedirs(tmp_folder) reference_basename = os.path.basename(reference_filename) orig_reference_filename = fname_presuffix(os.path.join( tmp_folder, reference_basename), suffix='+orig.BRIK', use_ext=False) out_copy_oblique = copy(in_file=reference_filename, out_file=orig_reference_filename, environ=environ) orig_reference_filename = out_copy_oblique.outputs.out_file to_fix_basename = os.path.basename(to_fix_filename) orig_to_fix_filename = fname_presuffix(os.path.join( tmp_folder, to_fix_basename), suffix='+orig.BRIK', use_ext=False) out_copy = copy(in_file=to_fix_filename, out_file=orig_to_fix_filename, environ=environ) orig_to_fix_filename = out_copy.outputs.out_file out_refit = refit(in_file=orig_to_fix_filename, atrcopy=(orig_reference_filename, 'IJK_TO_DICOM_REAL')) out_copy = copy(in_file=out_refit.outputs.out_file, out_file=fname_presuffix(to_fix_filename, suffix='_oblique'), environ=environ) if not caching: shutil.rmtree(tmp_folder) return out_copy.outputs.out_file
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 skullstrip_anatomical(method='afni', config=None, wf_name='skullstrip_anatomical'): method = method.lower() preproc = pe.Workflow(name=wf_name) inputnode = pe.Node(util.IdentityInterface(fields=['anat_data', 'brain_mask', 'template_brain_only_for_anat', 'template_skull_for_anat']), name='inputspec') outputnode = pe.Node(util.IdentityInterface(fields=['skullstrip', 'brain', 'brain_mask']), name='outputspec') if method == 'afni': # Skull-stripping using AFNI 3dSkullStrip inputnode_afni = pe.Node( util.IdentityInterface(fields=['mask_vol', 'shrink_factor', 'var_shrink_fac', 'shrink_fac_bot_lim', 'avoid_vent', 'niter', 'pushout', 'touchup', 'fill_hole', 'avoid_eyes', 'use_edge', 'exp_frac', 'smooth_final', 'push_to_edge', 'use_skull', 'perc_int', 'max_inter_iter', 'blur_fwhm', 'fac', 'monkey']), name='AFNI_options') skullstrip_args = pe.Node(util.Function(input_names=['spat_norm', 'spat_norm_dxyz', 'mask_vol', 'shrink_fac', 'var_shrink_fac', 'shrink_fac_bot_lim', 'avoid_vent', 'niter', 'pushout', 'touchup', 'fill_hole', 'avoid_eyes', 'use_edge', 'exp_frac', 'smooth_final', 'push_to_edge', 'use_skull', 'perc_int', 'max_inter_iter', 'blur_fwhm', 'fac', 'monkey'], output_names=['expr'], function=create_3dskullstrip_arg_string), name='anat_skullstrip_args') inputnode_afni.inputs.set( mask_vol=config.skullstrip_mask_vol, shrink_factor=config.skullstrip_shrink_factor, var_shrink_fac=config.skullstrip_var_shrink_fac, shrink_fac_bot_lim=config.skullstrip_shrink_factor_bot_lim, avoid_vent=config.skullstrip_avoid_vent, niter=config.skullstrip_n_iterations, pushout=config.skullstrip_pushout, touchup=config.skullstrip_touchup, fill_hole=config.skullstrip_fill_hole, avoid_eyes=config.skullstrip_avoid_eyes, use_edge=config.skullstrip_use_edge, exp_frac=config.skullstrip_exp_frac, smooth_final=config.skullstrip_smooth_final, push_to_edge=config.skullstrip_push_to_edge, use_skull=config.skullstrip_use_skull, perc_int=config.skullstrip_perc_int, max_inter_iter=config.skullstrip_max_inter_iter, blur_fwhm=config.skullstrip_blur_fwhm, fac=config.skullstrip_fac, monkey=config.skullstrip_monkey, ) preproc.connect([ (inputnode_afni, skullstrip_args, [ ('mask_vol', 'mask_vol'), ('shrink_factor', 'shrink_fac'), ('var_shrink_fac', 'var_shrink_fac'), ('shrink_fac_bot_lim', 'shrink_fac_bot_lim'), ('avoid_vent', 'avoid_vent'), ('niter', 'niter'), ('pushout', 'pushout'), ('touchup', 'touchup'), ('fill_hole', 'fill_hole'), ('avoid_eyes', 'avoid_eyes'), ('use_edge', 'use_edge'), ('exp_frac', 'exp_frac'), ('smooth_final', 'smooth_final'), ('push_to_edge', 'push_to_edge'), ('use_skull', 'use_skull'), ('perc_int', 'perc_int'), ('max_inter_iter', 'max_inter_iter'), ('blur_fwhm', 'blur_fwhm'), ('fac', 'fac'), ('monkey','monkey') ]) ]) anat_skullstrip = pe.Node(interface=afni.SkullStrip(), name='anat_skullstrip') anat_skullstrip.inputs.outputtype = 'NIFTI_GZ' preproc.connect(inputnode, 'anat_data', anat_skullstrip, 'in_file') preproc.connect(skullstrip_args, 'expr', anat_skullstrip, 'args') # Generate anatomical brain mask anat_brain_mask = pe.Node(interface=afni.Calc(), name='anat_brain_mask') anat_brain_mask.inputs.expr = 'step(a)' anat_brain_mask.inputs.outputtype = 'NIFTI_GZ' preproc.connect(anat_skullstrip, 'out_file', anat_brain_mask, 'in_file_a') # Apply skull-stripping step mask to original volume anat_skullstrip_orig_vol = pe.Node(interface=afni.Calc(), name='anat_skullstrip_orig_vol') anat_skullstrip_orig_vol.inputs.expr = 'a*step(b)' anat_skullstrip_orig_vol.inputs.outputtype = 'NIFTI_GZ' preproc.connect(inputnode, 'anat_data', anat_skullstrip_orig_vol, 'in_file_a') preproc.connect(anat_brain_mask, 'out_file', anat_skullstrip_orig_vol, 'in_file_b') preproc.connect(anat_brain_mask, 'out_file', outputnode, 'brain_mask') preproc.connect(anat_skullstrip_orig_vol, 'out_file', outputnode, 'brain') elif method == 'fsl': # Skull-stripping using FSL BET inputnode_bet = pe.Node( util.IdentityInterface(fields=['frac', 'mask_boolean', 'mesh_boolean', 'outline', 'padding', 'radius', 'reduce_bias', 'remove_eyes', 'robust', 'skull', 'surfaces', 'threshold', 'vertical_gradient']), name='BET_options') anat_skullstrip = pe.Node( interface=fsl.BET(), name='anat_skullstrip') anat_skullstrip.inputs.output_type = 'NIFTI_GZ' inputnode_bet.inputs.set( frac=config.bet_frac, mask_boolean=config.bet_mask_boolean, mesh_boolean=config.bet_mesh_boolean, outline=config.bet_outline, padding=config.bet_padding, radius=config.bet_radius, reduce_bias=config.bet_reduce_bias, remove_eyes=config.bet_remove_eyes, robust=config.bet_robust, skull=config.bet_skull, surfaces=config.bet_surfaces, threshold=config.bet_threshold, vertical_gradient=config.bet_vertical_gradient, ) preproc.connect(inputnode, 'anat_data', anat_skullstrip, 'in_file') preproc.connect([ (inputnode_bet, anat_skullstrip, [ ('frac', 'frac'), ('mask_boolean', 'mask'), ('mesh_boolean', 'mesh'), ('outline', 'outline'), ('padding', 'padding'), ('radius', 'radius'), ('reduce_bias', 'reduce_bias'), ('remove_eyes', 'remove_eyes'), ('robust', 'robust'), ('skull', 'skull'), ('surfaces', 'surfaces'), ('threshold', 'threshold'), ('vertical_gradient', 'vertical_gradient'), ]) ]) preproc.connect(anat_skullstrip, 'out_file', outputnode, 'skullstrip') # Apply skull-stripping step mask to original volume anat_skullstrip_orig_vol = pe.Node(interface=afni.Calc(), name='anat_skullstrip_orig_vol') anat_skullstrip_orig_vol.inputs.expr = 'a*step(b)' anat_skullstrip_orig_vol.inputs.outputtype = 'NIFTI_GZ' preproc.connect(inputnode, 'anat_data', anat_skullstrip_orig_vol, 'in_file_a') preproc.connect(anat_skullstrip, 'out_file', anat_skullstrip_orig_vol, 'in_file_b') preproc.connect(anat_skullstrip, 'mask_file', outputnode, 'brain_mask') preproc.connect(anat_skullstrip_orig_vol, 'out_file', outputnode, 'brain') elif method == 'niworkflows-ants': # Skull-stripping using niworkflows-ants anat_skullstrip_ants = init_brain_extraction_wf(tpl_target_path=config.niworkflows_ants_template_path, tpl_mask_path=config.niworkflows_ants_mask_path, tpl_regmask_path=config.niworkflows_ants_regmask_path, name='anat_skullstrip_ants') preproc.connect(inputnode, 'anat_data', anat_skullstrip_ants, 'inputnode.in_files') preproc.connect(anat_skullstrip_ants, 'copy_xform.out_file', outputnode, 'skullstrip') preproc.connect(anat_skullstrip_ants, 'copy_xform.out_file', outputnode, 'brain') preproc.connect(anat_skullstrip_ants, 'atropos_wf.copy_xform.out_mask', outputnode, 'brain_mask') elif method == 'mask': brain_mask_deoblique = pe.Node(interface=afni.Refit(), name='brain_mask_deoblique') brain_mask_deoblique.inputs.deoblique = True preproc.connect(inputnode, 'brain_mask', brain_mask_deoblique, 'in_file') brain_mask_reorient = pe.Node(interface=afni.Resample(), name='brain_mask_reorient') brain_mask_reorient.inputs.orientation = 'RPI' brain_mask_reorient.inputs.outputtype = 'NIFTI_GZ' preproc.connect(brain_mask_deoblique, 'out_file', brain_mask_reorient, 'in_file') anat_skullstrip_orig_vol = pe.Node(interface=afni.Calc(), name='anat_skullstrip_orig_vol') anat_skullstrip_orig_vol.inputs.expr = 'a*step(b)' anat_skullstrip_orig_vol.inputs.outputtype = 'NIFTI_GZ' preproc.connect(inputnode, 'anat_data', anat_skullstrip_orig_vol, 'in_file_a') preproc.connect(brain_mask_reorient, 'out_file', anat_skullstrip_orig_vol, 'in_file_b') preproc.connect(brain_mask_reorient, 'out_file', outputnode, 'brain_mask') preproc.connect(anat_skullstrip_orig_vol, 'out_file', outputnode, 'brain') elif method == 'unet': """ UNet options (following numbers are default): input_slice: 3 conv_block: 5 kernel_root: 16 rescale_dim: 256 """ # TODO: add options to pipeline_config unet_check_for_s3 = create_check_for_s3_node('unet', config.unet_model) unet_mask = pe.Node(util.Function(input_names=['model_path', 'cimg_in'], output_names=['out_path'], function=predict_volumes), name='unet_mask') preproc.connect(unet_check_for_s3, 'local_path', unet_mask, 'model_path') preproc.connect(inputnode, 'anat_data', unet_mask, 'cimg_in') """ Revised mask with ANTs """ # fslmaths <whole head> -mul <mask> brain.nii.gz unet_masked_brain = pe.Node(interface=fsl.MultiImageMaths(), name='unet_masked_brain') unet_masked_brain.inputs.op_string = "-mul %s" preproc.connect(inputnode, 'anat_data', unet_masked_brain, 'in_file') preproc.connect(unet_mask, 'out_path', unet_masked_brain, 'operand_files') # flirt -v -dof 6 -in brain.nii.gz -ref NMT_SS_0.5mm.nii.gz -o brain_rot2atl -omat brain_rot2atl.mat -interp sinc # TODO: antsRegistration -z 0 -d 3 -r [NMT_SS_0.5mm.nii.gz,brain.nii.gz,0] -o [transform,brain_rot2atl.nii.gz,brain_inv_rot2atl.nii.gz] -t Rigid[0.1] -m MI[NMT_SS_0.5mm.nii.gz,brain.nii.gz,1,32,Regular,0.25] -c [1000x500x250x100,1e-08,10] -s 3.0x2.0x1.0x0.0 -f 8x4x2x1 -u 1 -t Affine[0.1] -m MI[NMT_SS_0.5mm.nii.gz,brain.nii.gz,1,32,Regular,0.25] -c [1000x500x250x100,1e-08,10] -s 3.0x2.0x1.0x0.0 -f 8x4x2x1 -u 1 native_brain_to_template_brain = pe.Node(interface=fsl.FLIRT(), name='native_brain_to_template_brain') native_brain_to_template_brain.inputs.dof = 6 native_brain_to_template_brain.inputs.interp = 'sinc' preproc.connect(unet_masked_brain, 'out_file', native_brain_to_template_brain, 'in_file') preproc.connect(inputnode, 'template_brain_only_for_anat', native_brain_to_template_brain, 'reference') # flirt -in head.nii.gz -ref NMT_0.5mm.nii.gz -o head_rot2atl -applyxfm -init brain_rot2atl.mat # TODO: antsApplyTransforms -d 3 -i head.nii.gz -r NMT_0.5mm.nii.gz -n Linear -o head_rot2atl.nii.gz -v -t transform1Rigid.mat -t transform2Affine.mat -t transform0DerivedInitialMovingTranslation.mat native_head_to_template_head = pe.Node(interface=fsl.FLIRT(), name='native_head_to_template_head') native_head_to_template_head.inputs.apply_xfm = True preproc.connect(inputnode, 'anat_data', native_head_to_template_head, 'in_file') preproc.connect(native_brain_to_template_brain, 'out_matrix_file', native_head_to_template_head, 'in_matrix_file') preproc.connect(inputnode, 'template_skull_for_anat', native_head_to_template_head, 'reference') # fslmaths NMT_SS_0.5mm.nii.gz -bin templateMask.nii.gz template_brain_mask = pe.Node(interface=fsl.maths.MathsCommand(), name='template_brain_mask') template_brain_mask.inputs.args = '-bin' preproc.connect(inputnode, 'template_brain_only_for_anat', template_brain_mask, 'in_file') # ANTS 3 -m CC[head_rot2atl.nii.gz,NMT_0.5mm.nii.gz,1,5] -t SyN[0.25] -r Gauss[3,0] -o atl2T1rot -i 60x50x20 --use-Histogram-Matching --number-of-affine-iterations 10000x10000x10000x10000x10000 --MI-option 32x16000 ants_template_head_to_template = pe.Node(interface=ants.Registration(), name='template_head_to_template') ants_template_head_to_template.inputs.metric = ['CC'] ants_template_head_to_template.inputs.metric_weight = [1,5] ants_template_head_to_template.inputs.transforms = ['SyN'] ants_template_head_to_template.inputs.transform_parameters = [(0.25,)] ants_template_head_to_template.inputs.interpolation = 'NearestNeighbor' ants_template_head_to_template.inputs.number_of_iterations = [[60,50,20]] ants_template_head_to_template.inputs.smoothing_sigmas = [[0.6,0.2,0.0]] ants_template_head_to_template.inputs.shrink_factors = [[4,2,1]] ants_template_head_to_template.inputs.convergence_threshold = [1.e-8] preproc.connect(native_head_to_template_head, 'out_file', ants_template_head_to_template, 'fixed_image') preproc.connect(inputnode, 'template_skull_for_anat', ants_template_head_to_template, 'moving_image') # antsApplyTransforms -d 3 -i templateMask.nii.gz -t atl2T1rotWarp.nii.gz atl2T1rotAffine.txt -r brain_rot2atl.nii.gz -o brain_rot2atl_mask.nii.gz template_head_transform_to_template = pe.Node(interface=ants.ApplyTransforms(), name='template_head_transform_to_template') template_head_transform_to_template.inputs.dimension = 3 preproc.connect(template_brain_mask, 'out_file', template_head_transform_to_template, 'input_image') preproc.connect(native_brain_to_template_brain, 'out_file', template_head_transform_to_template, 'reference_image') preproc.connect(ants_template_head_to_template, 'forward_transforms', template_head_transform_to_template, 'transforms') # TODO: replace convert_xfm and flirt with: # antsApplyTransforms -d 3 -i brain_rot2atl_mask.nii.gz -r brain.nii.gz -n linear -o brain_mask.nii.gz -t [transform0DerivedInitialMovingTranslation.mat,1] -t [transform2Affine.mat,1] -t [transform1Rigid.mat,1] # convert_xfm -omat brain_rot2native.mat -inverse brain_rot2atl.mat invt = pe.Node(interface=fsl.ConvertXFM(), name='convert_xfm') invt.inputs.invert_xfm = True preproc.connect(native_brain_to_template_brain, 'out_matrix_file', invt, 'in_file') # flirt -in brain_rot2atl_mask.nii.gz -ref brain.nii.gz -o brain_mask.nii.gz -applyxfm -init brain_rot2native.mat template_brain_to_native_brain = pe.Node(interface=fsl.FLIRT(), name='template_brain_to_native_brain') template_brain_to_native_brain.inputs.apply_xfm = True preproc.connect(template_head_transform_to_template, 'output_image', template_brain_to_native_brain, 'in_file') preproc.connect(unet_masked_brain, 'out_file', template_brain_to_native_brain, 'reference') preproc.connect(invt, 'out_file', template_brain_to_native_brain, 'in_matrix_file') # fslmaths brain_mask.nii.gz -thr .5 -bin brain_mask_thr.nii.gz refined_mask = pe.Node(interface=fsl.Threshold(), name='refined_mask') refined_mask.inputs.thresh = 0.5 refined_mask.inputs.args = '-bin' preproc.connect(template_brain_to_native_brain, 'out_file', refined_mask, 'in_file') # get a new brain with mask refined_brain = pe.Node(interface=fsl.MultiImageMaths(), name='refined_brain') refined_brain.inputs.op_string = "-mul %s" preproc.connect(inputnode, 'anat_data', refined_brain, 'in_file') preproc.connect(refined_mask, 'out_file', refined_brain, 'operand_files') preproc.connect(refined_mask, 'out_file', outputnode, 'brain_mask') preproc.connect(refined_brain, 'out_file', outputnode, 'brain') return preproc
def hmc_afni(name='fMRI_HMC_afni', st_correct=False, despike=False, deoblique=False): """A head motion correction (HMC) workflow for functional scans""" workflow = pe.Workflow(name=name) inputnode = pe.Node(niu.IdentityInterface( fields=['in_file', 'fd_radius', 'start_idx', 'stop_idx']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface( fields=['out_file', 'out_fd']), name='outputnode') drop_trs = pe.Node(afni.Calc(expr='a', outputtype='NIFTI_GZ'), name='drop_trs') reorient = pe.Node(afni.Resample( orientation='RPI', outputtype='NIFTI_GZ'), name='reorient') get_mean_RPI = pe.Node(afni.TStat( options='-mean', outputtype='NIFTI_GZ'), name='get_mean_RPI') # calculate hmc parameters hmc = pe.Node( afni.Volreg(args='-Fourier -twopass', zpad=4, outputtype='NIFTI_GZ'), name='motion_correct') get_mean_motion = get_mean_RPI.clone('get_mean_motion') hmc_A = hmc.clone('motion_correct_A') hmc_A.inputs.md1d_file = 'max_displacement.1D' # Compute the frame-wise displacement calc_fd = pe.Node(niu.Function( function=fd_jenkinson, input_names=['in_file', 'rmax'], output_names=['out_fd']), name='calc_fd') workflow.connect([ (inputnode, drop_trs, [('in_file', 'in_file_a'), ('start_idx', 'start_idx'), ('stop_idx', 'stop_idx')]), (inputnode, calc_fd, [('fd_radius', 'rmax')]), (reorient, get_mean_RPI, [('out_file', 'in_file')]), (reorient, hmc, [('out_file', 'in_file')]), (get_mean_RPI, hmc, [('out_file', 'basefile')]), (hmc, get_mean_motion, [('out_file', 'in_file')]), (reorient, hmc_A, [('out_file', 'in_file')]), (get_mean_motion, hmc_A, [('out_file', 'basefile')]), (hmc_A, outputnode, [('out_file', 'out_file')]), (hmc_A, calc_fd, [('oned_matrix_save', 'in_file')]), (calc_fd, outputnode, [('out_fd', 'out_fd')]), ]) # Slice timing correction, despiking, and deoblique st_corr = pe.Node(afni.TShift(outputtype='NIFTI_GZ'), name='TimeShifts') deoblique_node = pe.Node(afni.Refit(deoblique=True), name='deoblique') despike_node = pe.Node(afni.Despike(outputtype='NIFTI_GZ'), name='despike') if st_correct and despike and deoblique: workflow.connect([ (drop_trs, st_corr, [('out_file', 'in_file')]), (st_corr, despike_node, [('out_file', 'in_file')]), (despike_node, deoblique_node, [('out_file', 'in_file')]), (deoblique_node, reorient, [('out_file', 'in_file')]) ]) elif st_correct and despike: workflow.connect([ (drop_trs, st_corr, [('out_file', 'in_file')]), (st_corr, despike_node, [('out_file', 'in_file')]), (despike_node, reorient, [('out_file', 'in_file')]), ]) elif st_correct and deoblique: workflow.connect([ (drop_trs, st_corr, [('out_file', 'in_file')]), (st_corr, deoblique_node, [('out_file', 'in_file')]), (deoblique_node, reorient, [('out_file', 'in_file')]) ]) elif st_correct: workflow.connect([ (drop_trs, st_corr, [('out_file', 'in_file')]), (st_corr, reorient, [('out_file', 'in_file')]) ]) elif despike and deoblique: workflow.connect([ (drop_trs, despike_node, [('out_file', 'in_file')]), (despike_node, deoblique_node, [('out_file', 'in_file')]), (deoblique_node, reorient, [('out_file', 'in_file')]) ]) elif despike: workflow.connect([ (drop_trs, despike_node, [('out_file', 'in_file')]), (despike_node, reorient, [('out_file', 'in_file')]), ]) elif deoblique: workflow.connect([ (drop_trs, deoblique_node, [('out_file', 'in_file')]), (deoblique_node, reorient, [('out_file', 'in_file')]) ]) else: workflow.connect([ (drop_trs, reorient, [('out_file', 'in_file')]), ]) return workflow
def create_nii_to_mesh_fs_pipe(params, name="nii_to_mesh_fs_pipe"): """ Description: surface generation using freesurfer tools Params: - fill_wm (see `MRIFill <https://nipype.readthedocs.io/en/0.12.1/\ interfaces/generated/nipype.interfaces.freesurfer.utils.html#mrifill>`_) \ - also available as :ref:`indiv_params <indiv_params>` Inputs: inputnode: wm_mask_file: segmented white matter mask (binary) in template space reg_brain_file: preprocessd T1, registered to template indiv_params (opt): dict with individuals parameters for some nodes arguments: params: dictionary of node sub-parameters (from a json file) name: pipeline name (default = "nii_to_mesh_fs_pipe") Outputs: """ # creating pipeline nii_to_mesh_fs_pipe = pe.Workflow(name=name) # creating inputnode inputnode = pe.Node(niu.IdentityInterface( fields=['wm_mask_file', 'reg_brain_file', 'indiv_params']), name='inputnode') # bin_wm bin_wm = pe.Node(interface=fsl.UnaryMaths(), name="bin_wm") bin_wm.inputs.operation = "fillh" nii_to_mesh_fs_pipe.connect(inputnode, 'wm_mask_file', bin_wm, 'in_file') # resample everything refit_wm = pe.Node(interface=afni.Refit(), name="refit_wm") refit_wm.inputs.args = "-xdel 1.0 -ydel 1.0 -zdel 1.0 -keepcen" nii_to_mesh_fs_pipe.connect(bin_wm, 'out_file', refit_wm, 'in_file') # resample everything refit_reg = pe.Node(interface=afni.Refit(), name="refit_reg") refit_reg.inputs.args = "-xdel 1.0 -ydel 1.0 -zdel 1.0 -keepcen" nii_to_mesh_fs_pipe.connect(inputnode, 'reg_brain_file', refit_reg, 'in_file') # mri_convert wm to freesurfer mgz convert_wm = pe.Node(interface=fs.MRIConvert(), name="convert_wm") convert_wm.inputs.out_type = "mgz" convert_wm.inputs.conform = True nii_to_mesh_fs_pipe.connect(refit_wm, 'out_file', convert_wm, 'in_file') # mri_convert reg to freesurfer mgz convert_reg = pe.Node(interface=fs.MRIConvert(), name="convert_reg") convert_reg.inputs.out_type = "mgz" convert_reg.inputs.conform = True nii_to_mesh_fs_pipe.connect(refit_reg, 'out_file', convert_reg, 'in_file') # mri_fill fill_wm = NodeParams(interface=fs.MRIFill(), params=parse_key(params, "fill_wm"), name="fill_wm") fill_wm.inputs.out_file = "filled.mgz" nii_to_mesh_fs_pipe.connect(convert_wm, 'out_file', fill_wm, 'in_file') nii_to_mesh_fs_pipe.connect(inputnode, ("indiv_params", parse_key, "fill_wm"), fill_wm, 'indiv_params') # pretesselate wm pretess_wm = pe.Node(interface=fs.MRIPretess(), name="pretess_wm") pretess_wm.inputs.label = 255 nii_to_mesh_fs_pipe.connect(fill_wm, 'out_file', pretess_wm, 'in_filled') nii_to_mesh_fs_pipe.connect(convert_reg, 'out_file', pretess_wm, 'in_norm') # tesselate wm lh tess_wm_lh = pe.Node(interface=fs.MRITessellate(), name="tess_wm_lh") tess_wm_lh.inputs.label_value = 255 tess_wm_lh.inputs.out_file = "lh_tess" nii_to_mesh_fs_pipe.connect(pretess_wm, 'out_file', tess_wm_lh, 'in_file') # tesselate wm rh tess_wm_rh = pe.Node(interface=fs.MRITessellate(), name="tess_wm_rh") tess_wm_rh.inputs.label_value = 127 tess_wm_rh.inputs.out_file = "rh_tess" nii_to_mesh_fs_pipe.connect(pretess_wm, 'out_file', tess_wm_rh, 'in_file') # ExtractMainComponent lh extract_mc_lh = pe.Node(interface=fs.ExtractMainComponent(), name="extract_mc_lh") nii_to_mesh_fs_pipe.connect(tess_wm_lh, 'surface', extract_mc_lh, 'in_file') extract_mc_lh.inputs.out_file = "lh.lh_tess.maincmp" # ExtractMainComponent rh extract_mc_rh = pe.Node(interface=fs.ExtractMainComponent(), name="extract_mc_rh") nii_to_mesh_fs_pipe.connect(tess_wm_rh, 'surface', extract_mc_rh, 'in_file') extract_mc_rh.inputs.out_file = "rh.rh_tess.maincmp" # SmoothTessellation lh smooth_tess_lh = pe.Node(interface=fs.SmoothTessellation(), name="smooth_tess_lh") smooth_tess_lh.inputs.disable_estimates = True nii_to_mesh_fs_pipe.connect(extract_mc_lh, 'out_file', smooth_tess_lh, 'in_file') # SmoothTessellation rh smooth_tess_rh = pe.Node(interface=fs.SmoothTessellation(), name="smooth_tess_rh") smooth_tess_rh.inputs.disable_estimates = True nii_to_mesh_fs_pipe.connect(extract_mc_rh, 'out_file', smooth_tess_rh, 'in_file') return nii_to_mesh_fs_pipe
def create_anat_preproc(method='afni', already_skullstripped=False, config=None, acpc_target='whole-head', wf_name='anat_preproc'): """The main purpose of this workflow is to process T1 scans. Raw mprage file is deobliqued, reoriented into RPI and skullstripped. Also, a whole brain only mask is generated from the skull stripped image for later use in registration. Returns ------- anat_preproc : workflow Anatomical Preprocessing Workflow Notes ----- `Source <https://github.com/FCP-INDI/C-PAC/blob/master/CPAC/anat_preproc/anat_preproc.py>`_ Workflow Inputs:: inputspec.anat : string User input anatomical (T1) Image, in any of the 8 orientations Workflow Outputs:: outputspec.refit : string Path to deobliqued anatomical image outputspec.reorient : string Path to RPI oriented anatomical image outputspec.skullstrip : string Path to skull stripped RPI oriented mprage file with normalized intensities. outputspec.brain : string Path to skull stripped RPI brain image with original intensity values and not normalized or scaled. Order of commands: - Deobliqing the scans. :: 3drefit -deoblique mprage.nii.gz - Re-orienting the Image into Right-to-Left Posterior-to-Anterior Inferior-to-Superior (RPI) orientation :: 3dresample -orient RPI -prefix mprage_RPI.nii.gz -inset mprage.nii.gz - Skull-Stripping the image :: Using AFNI :: 3dSkullStrip -input mprage_RPI.nii.gz -o_ply mprage_RPI_3dT.nii.gz or using BET :: bet mprage_RPI.nii.gz - The skull-stripping step modifies the intensity values. To get back the original intensity values, we do an element wise product of RPI data with step function of skull-stripped data :: 3dcalc -a mprage_RPI.nii.gz -b mprage_RPI_3dT.nii.gz -expr 'a*step(b)' -prefix mprage_RPI_3dc.nii.gz High Level Workflow Graph: .. image:: ../images/anatpreproc_graph.dot.png :width: 500 Detailed Workflow Graph: .. image:: ../images/anatpreproc_graph_detailed.dot.png :width: 500 Examples -------- >>> from CPAC.anat_preproc import create_anat_preproc >>> preproc = create_anat_preproc() >>> preproc.inputs.inputspec.anat = 'sub1/anat/mprage.nii.gz' >>> preproc.run() #doctest: +SKIP """ preproc = pe.Workflow(name=wf_name) inputnode = pe.Node(util.IdentityInterface(fields=['anat', 'brain_mask', 'template_brain_only_for_anat', 'template_skull_for_anat', 'template_brain_only_for_acpc', 'template_skull_for_acpc', 'template_cmass']), name='inputspec') outputnode = pe.Node(util.IdentityInterface(fields=['refit', 'reorient', 'skullstrip', 'brain', 'brain_mask', 'anat_skull_leaf', 'center_of_mass']), name='outputspec') anat_deoblique = pe.Node(interface=afni.Refit(), name='anat_deoblique') anat_deoblique.inputs.deoblique = True preproc.connect(inputnode, 'anat', anat_deoblique, 'in_file') preproc.connect(anat_deoblique, 'out_file', outputnode, 'refit') # Anatomical reorientation anat_reorient = pe.Node(interface=afni.Resample(), name='anat_reorient') anat_reorient.inputs.orientation = 'RPI' anat_reorient.inputs.outputtype = 'NIFTI_GZ' preproc.connect(anat_deoblique, 'out_file', anat_reorient, 'in_file') preproc.connect(anat_reorient, 'out_file', outputnode, 'reorient') anat_leaf = pe.Node(util.IdentityInterface(fields=['anat_data']), name='anat_leaf') if not config.acpc_align: preproc.connect(anat_reorient, 'out_file', anat_leaf, 'anat_data') # ACPC alignment if config.acpc_align: acpc_align = acpc_alignment(skullstrip_tool=method, config=config, acpc_target=acpc_target, wf_name='acpc_align') preproc.connect(anat_reorient, 'out_file', acpc_align, 'inputspec.anat_leaf') preproc.connect(inputnode, 'brain_mask', acpc_align, 'inputspec.brain_mask') preproc.connect(inputnode, 'template_brain_only_for_acpc', acpc_align, 'inputspec.template_brain_for_acpc') preproc.connect(inputnode, 'template_skull_for_acpc', acpc_align, 'inputspec.template_head_for_acpc') preproc.connect(acpc_align, 'outputspec.acpc_aligned_head', anat_leaf, 'anat_data') if method == 'unet': preproc.connect(inputnode, 'template_brain_only_for_anat', acpc_align, 'inputspec.template_brain_only_for_anat') preproc.connect(inputnode, 'template_skull_for_anat', acpc_align, 'inputspec.template_skull_for_anat') # Disable non_local_means_filtering and n4_bias_field_correction when run niworkflows-ants if method == 'niworkflows-ants': config.non_local_means_filtering = False config.n4_bias_field_correction = False if config.non_local_means_filtering and config.n4_bias_field_correction: denoise = pe.Node(interface = ants.DenoiseImage(), name = 'anat_denoise') preproc.connect(anat_leaf, 'anat_data', denoise, 'input_image') n4 = pe.Node(interface = ants.N4BiasFieldCorrection(dimension=3, shrink_factor=2, copy_header=True), name='anat_n4') preproc.connect(denoise, 'output_image', n4, 'input_image') elif config.non_local_means_filtering and not config.n4_bias_field_correction: denoise = pe.Node(interface = ants.DenoiseImage(), name = 'anat_denoise') preproc.connect(anat_leaf, 'anat_data', denoise, 'input_image') elif not config.non_local_means_filtering and config.n4_bias_field_correction: n4 = pe.Node(interface = ants.N4BiasFieldCorrection(dimension=3, shrink_factor=2, copy_header=True), name='anat_n4') preproc.connect(anat_leaf, 'anat_data', n4, 'input_image') anat_leaf2 = pe.Node(util.IdentityInterface(fields=['anat_data']), name='anat_leaf2') if config.n4_bias_field_correction: preproc.connect(n4, 'output_image', anat_leaf2, 'anat_data') elif config.non_local_means_filtering and not config.n4_bias_field_correction: preproc.connect(denoise, 'output_image', anat_leaf2, 'anat_data') else: preproc.connect(anat_leaf, 'anat_data', anat_leaf2, 'anat_data') if already_skullstripped: anat_skullstrip = pe.Node(interface=util.IdentityInterface(fields=['out_file']), name='anat_skullstrip') preproc.connect(anat_leaf2, 'anat_data', anat_skullstrip, 'out_file') preproc.connect(anat_skullstrip, 'out_file', outputnode, 'skullstrip') # binarize skullstripped brain to get brain mask brain_mask = pe.Node(interface=fsl.maths.MathsCommand(), name='brain_mask') brain_mask.inputs.args = '-bin' preproc.connect(anat_skullstrip, 'out_file', brain_mask, 'in_file') preproc.connect(brain_mask, 'out_file', outputnode, 'brain_mask') preproc.connect(anat_skullstrip, 'out_file', outputnode, 'brain') else: anat_skullstrip = skullstrip_anatomical(method=method, config=config, wf_name="{0}_skullstrip".format(wf_name)) preproc.connect(anat_leaf2, 'anat_data', anat_skullstrip, 'inputspec.anat_data') preproc.connect(inputnode, 'template_brain_only_for_anat', anat_skullstrip, 'inputspec.template_brain_only_for_anat') preproc.connect(inputnode, 'template_skull_for_anat', anat_skullstrip, 'inputspec.template_skull_for_anat') if method == 'mask' and config.acpc_align: preproc.connect(acpc_align, 'outputspec.acpc_brain_mask', anat_skullstrip, 'inputspec.brain_mask') else: preproc.connect(inputnode, 'brain_mask', anat_skullstrip, 'inputspec.brain_mask') preproc.connect(anat_skullstrip, 'outputspec.brain_mask', outputnode, 'brain_mask') preproc.connect(anat_skullstrip, 'outputspec.brain', outputnode, 'brain') preproc.connect(anat_leaf2, 'anat_data', outputnode, 'anat_skull_leaf') return preproc
def hmc_afni(name='fMRI_HMC_afni', st_correct=False, despike=False, deoblique=False, start_idx=None, stop_idx=None): """ A :abbr:`HMC (head motion correction)` workflow for functional scans .. workflow:: from mriqc.workflows.functional import hmc_afni wf = hmc_afni() """ workflow = pe.Workflow(name=name) inputnode = pe.Node(niu.IdentityInterface( fields=['in_file', 'fd_radius', 'start_idx', 'stop_idx']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface(fields=['out_file', 'out_fd']), name='outputnode') if (start_idx is not None) or (stop_idx is not None): drop_trs = pe.Node(afni.Calc(expr='a', outputtype='NIFTI_GZ'), name='drop_trs') workflow.connect([ (inputnode, drop_trs, [('in_file', 'in_file_a'), ('start_idx', 'start_idx'), ('stop_idx', 'stop_idx')]), ]) else: drop_trs = pe.Node(niu.IdentityInterface(fields=['out_file']), name='drop_trs') workflow.connect([ (inputnode, drop_trs, [('in_file', 'out_file')]), ]) get_mean_RPI = pe.Node(afni.TStat(options='-mean', outputtype='NIFTI_GZ'), name='get_mean_RPI') # calculate hmc parameters hmc = pe.Node(afni.Volreg(args='-Fourier -twopass', zpad=4, outputtype='NIFTI_GZ'), name='motion_correct') get_mean_motion = get_mean_RPI.clone('get_mean_motion') hmc_A = hmc.clone('motion_correct_A') hmc_A.inputs.md1d_file = 'max_displacement.1D' # Compute the frame-wise displacement fdnode = pe.Node(nac.FramewiseDisplacement(normalize=False, parameter_source="AFNI"), name='ComputeFD') workflow.connect([ (inputnode, fdnode, [('fd_radius', 'radius')]), (get_mean_RPI, hmc, [('out_file', 'basefile')]), (hmc, get_mean_motion, [('out_file', 'in_file')]), (get_mean_motion, hmc_A, [('out_file', 'basefile')]), (hmc_A, outputnode, [('out_file', 'out_file')]), (hmc_A, fdnode, [('oned_file', 'in_file')]), (fdnode, outputnode, [('out_file', 'out_fd')]), ]) # Slice timing correction, despiking, and deoblique st_corr = pe.Node(afni.TShift(outputtype='NIFTI_GZ'), name='TimeShifts') deoblique_node = pe.Node(afni.Refit(deoblique=True), name='deoblique') despike_node = pe.Node(afni.Despike(outputtype='NIFTI_GZ'), name='despike') if st_correct and despike and deoblique: workflow.connect([ (drop_trs, st_corr, [('out_file', 'in_file')]), (st_corr, despike_node, [('out_file', 'in_file')]), (despike_node, deoblique_node, [('out_file', 'in_file')]), (deoblique_node, get_mean_RPI, [('out_file', 'in_file')]), (deoblique_node, hmc, [('out_file', 'in_file')]), (deoblique_node, hmc_A, [('out_file', 'in_file')]), ]) elif st_correct and despike: workflow.connect([ (drop_trs, st_corr, [('out_file', 'in_file')]), (st_corr, despike_node, [('out_file', 'in_file')]), (despike_node, get_mean_RPI, [('out_file', 'in_file')]), (despike_node, hmc, [('out_file', 'in_file')]), (despike_node, hmc_A, [('out_file', 'in_file')]), ]) elif st_correct and deoblique: workflow.connect([ (drop_trs, st_corr, [('out_file', 'in_file')]), (st_corr, deoblique_node, [('out_file', 'in_file')]), (deoblique_node, get_mean_RPI, [('out_file', 'in_file')]), (deoblique_node, hmc, [('out_file', 'in_file')]), (deoblique_node, hmc_A, [('out_file', 'in_file')]), ]) elif st_correct: workflow.connect([ (drop_trs, st_corr, [('out_file', 'in_file')]), (st_corr, get_mean_RPI, [('out_file', 'in_file')]), (st_corr, hmc, [('out_file', 'in_file')]), (st_corr, hmc_A, [('out_file', 'in_file')]), ]) elif despike and deoblique: workflow.connect([ (drop_trs, despike_node, [('out_file', 'in_file')]), (despike_node, deoblique_node, [('out_file', 'in_file')]), (deoblique_node, get_mean_RPI, [('out_file', 'in_file')]), (deoblique_node, hmc, [('out_file', 'in_file')]), (deoblique_node, hmc_A, [('out_file', 'in_file')]), ]) elif despike: workflow.connect([ (drop_trs, despike_node, [('out_file', 'in_file')]), (despike_node, get_mean_RPI, [('out_file', 'in_file')]), (despike_node, hmc, [('out_file', 'in_file')]), (despike_node, hmc_A, [('out_file', 'in_file')]), ]) elif deoblique: workflow.connect([ (drop_trs, deoblique_node, [('out_file', 'in_file')]), (deoblique_node, get_mean_RPI, [('out_file', 'in_file')]), (deoblique_node, hmc, [('out_file', 'in_file')]), (deoblique_node, hmc_A, [('out_file', 'in_file')]), ]) else: workflow.connect([ (drop_trs, get_mean_RPI, [('out_file', 'in_file')]), (drop_trs, hmc, [('out_file', 'in_file')]), (drop_trs, hmc_A, [('out_file', 'in_file')]), ]) return workflow
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 __init__(self, experiment_dir, output_dir, func_source, struct_source, datasink): self.experiment_dir = experiment_dir self.output_dir = output_dir # specify input and output nodes self.func_source = func_source self.struct_source = struct_source self.datasink = datasink # specify nodes # structual process self.refit_struct = pe.Node(interface=afni.Refit(), name='de_oblique_struct') self.refit_struct.inputs.deoblique = True self.resample_struct = pe.Node(interface=afni.Resample(), name='re_orientation_struct') self.resample_struct.inputs.orientation = 'RPI' self.resample_struct.inputs.outputtype = "NIFTI" self.bet_struct = pe.Node(interface=fsl.BET(), name='non_brain_removal_BET_struct') self.bet_struct.inputs.output_type = "NIFTI" # functional process self.refit_func = pe.Node(interface=afni.Refit(), name='de_oblique_func') self.refit_func.inputs.deoblique = True self.resample_func = pe.Node(interface=afni.Resample(), name='re_orientation_func') self.resample_func.inputs.orientation = 'RPI' self.resample_func.inputs.outputtype = "NIFTI" self.slice_timer = pe.Node(interface=fsl.SliceTimer(), name='time_slice_correction') self.mcflirt = pe.Node(interface=fsl.MCFLIRT(), name='motion_correction') self.mcflirt.inputs.output_type = "NIFTI" self.mcflirt.inputs.mean_vol = True self.fslsplit = pe.Node(interface=fsl.Split(), name='fslsplit') self.fslsplit.inputs.dimension = 't' self.fslsplit.inputs.output_type = "NIFTI" self.fslmerge = pe.Node(interface=fsl.Merge(), name='fslmerge') self.fslmerge.inputs.dimension = 't' self.fslmerge.inputs.output_type = "NIFTI" self.bet_mean = pe.Node(interface=fsl.BET(), name='non_brain_removal_BET_mean') self.bet_mean.inputs.output_type = "NIFTI" # helper function(s) def bet_each(in_files): ''' @param in_files: list of image files @return out_files: list of image files after applied fsl.BET on it ''' from nipype.interfaces import fsl import nipype.pipeline.engine as pe out_files = list() step_no = 0 for file_ in in_files: bet = pe.Node(interface=fsl.BET(), name='BET_for_step_{}'.format(step_no)) bet.inputs.in_file = file_ bet.inputs.out_file = file_[:len(file_) - 4] + '_bet.nii' bet.inputs.output_type = "NIFTI" bet.run() out_files.append(bet.inputs.out_file) step_no += 1 return out_files # bet_func return a list of NIFITI files self.bet_func = pe.Node(interface=Function(input_names=['in_files'], output_names=['out_files'], function=bet_each), name='non_brain_removal_BET_func') self.coregister = pe.Node(interface=spm.Coregister(), name="coregister") self.coregister.inputs.jobtype = 'estimate' self.segment = pe.Node(interface=spm.Segment(), name="segment") self.segment.inputs.affine_regularization = 'mni' self.normalize = pe.Node(interface=spm.Normalize(), name="normalize") self.normalize.inputs.jobtype = "write" # self.fourier = pe.Node(interface=afni.Fourier(), name='temporal_filtering') # self.fourier.inputs.highpass = 0.01 # self.fourier.inputs.lowpass = 0.1 self.smooth = pe.Node(interface=spm.Smooth(), name="smooth") self.smooth.inputs.fwhm = [8, 8, 8] # specify workflow instance self.workflow = pe.Workflow(name='FuNP_workflow') # connect nodes self.workflow.connect([ (self.struct_source, self.refit_struct, [('outfiles', 'in_file')]), (self.refit_struct, self.resample_struct, [('out_file', 'in_file') ]), (self.resample_struct, self.bet_struct, [('out_file', 'in_file')]), # (self.func_source, self.refit_func, [('outfiles', 'in_file')]), # (self.refit_func, self.resample_func, [('out_file', 'in_file')]), # (self.resample_func, self.slice_timer, [('out_file', 'in_file')]), (self.func_source, self.slice_timer, [('outfiles', 'in_file')]), (self.slice_timer, self.mcflirt, [('slice_time_corrected_file', 'in_file')]), (self.mcflirt, self.bet_mean, [('mean_img', 'in_file')]), (self.mcflirt, self.fslsplit, [('out_file', 'in_file')]), (self.fslsplit, self.bet_func, [('out_files', 'in_files')]), (self.bet_func, self.fslmerge, [('out_files', 'in_files') ]), # intersect (self.bet_struct, self.coregister, [('out_file', 'source')]), (self.bet_mean, self.coregister, [('out_file', 'target')]), (self.coregister, self.segment, [('coregistered_source', 'data')]), (self.segment, self.normalize, [('transformation_mat', 'parameter_file')]), (self.fslmerge, self.normalize, [('merged_file', 'apply_to_files') ]), (self.normalize, self.smooth, [('normalized_files', 'in_files')]), (self.coregister, self.datasink, [('coregistered_source', 'registered_file')]), (self.normalize, self.datasink, [('normalized_files', 'before_smooth')]), (self.smooth, self.datasink, [('smoothed_files', 'final_out')]) ])
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')
def hmc_afni(settings, name='fMRI_HMC_afni', st_correct=False, despike=False, deoblique=False, start_idx=None, stop_idx=None): """ A :abbr:`HMC (head motion correction)` workflow for functional scans .. workflow:: from mriqc.workflows.functional import hmc_afni wf = hmc_afni({'biggest_file_size_gb': 1}) """ biggest_file_gb = settings.get("biggest_file_size_gb", 1) workflow = pe.Workflow(name=name) inputnode = pe.Node(niu.IdentityInterface( fields=['in_file', 'fd_radius', 'start_idx', 'stop_idx']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface( fields=['out_file', 'out_fd']), name='outputnode') if (start_idx is not None) or (stop_idx is not None): drop_trs = pe.Node(afni.Calc(expr='a', outputtype='NIFTI_GZ'), name='drop_trs') workflow.connect([ (inputnode, drop_trs, [('in_file', 'in_file_a'), ('start_idx', 'start_idx'), ('stop_idx', 'stop_idx')]), ]) else: drop_trs = pe.Node(niu.IdentityInterface(fields=['out_file']), name='drop_trs') workflow.connect([ (inputnode, drop_trs, [('in_file', 'out_file')]), ]) gen_ref = pe.Node(nwr.EstimateReferenceImage(mc_method="AFNI"), name="gen_ref") # calculate hmc parameters hmc = pe.Node( afni.Volreg(args='-Fourier -twopass', zpad=4, outputtype='NIFTI_GZ'), name='motion_correct', mem_gb=biggest_file_gb * 2.5) # Compute the frame-wise displacement fdnode = pe.Node(nac.FramewiseDisplacement(normalize=False, parameter_source="AFNI"), name='ComputeFD') workflow.connect([ (inputnode, fdnode, [('fd_radius', 'radius')]), (gen_ref, hmc, [('ref_image', 'basefile')]), (hmc, outputnode, [('out_file', 'out_file')]), (hmc, fdnode, [('oned_file', 'in_file')]), (fdnode, outputnode, [('out_file', 'out_fd')]), ]) # Slice timing correction, despiking, and deoblique st_corr = pe.Node(afni.TShift(outputtype='NIFTI_GZ'), name='TimeShifts') deoblique_node = pe.Node(afni.Refit(deoblique=True), name='deoblique') despike_node = pe.Node(afni.Despike(outputtype='NIFTI_GZ'), name='despike') if st_correct and despike and deoblique: workflow.connect([ (drop_trs, st_corr, [('out_file', 'in_file')]), (st_corr, despike_node, [('out_file', 'in_file')]), (despike_node, deoblique_node, [('out_file', 'in_file')]), (deoblique_node, gen_ref, [('out_file', 'in_file')]), (deoblique_node, hmc, [('out_file', 'in_file')]), ]) elif st_correct and despike: workflow.connect([ (drop_trs, st_corr, [('out_file', 'in_file')]), (st_corr, despike_node, [('out_file', 'in_file')]), (despike_node, gen_ref, [('out_file', 'in_file')]), (despike_node, hmc, [('out_file', 'in_file')]), ]) elif st_correct and deoblique: workflow.connect([ (drop_trs, st_corr, [('out_file', 'in_file')]), (st_corr, deoblique_node, [('out_file', 'in_file')]), (deoblique_node, gen_ref, [('out_file', 'in_file')]), (deoblique_node, hmc, [('out_file', 'in_file')]), ]) elif st_correct: workflow.connect([ (drop_trs, st_corr, [('out_file', 'in_file')]), (st_corr, gen_ref, [('out_file', 'in_file')]), (st_corr, hmc, [('out_file', 'in_file')]), ]) elif despike and deoblique: workflow.connect([ (drop_trs, despike_node, [('out_file', 'in_file')]), (despike_node, deoblique_node, [('out_file', 'in_file')]), (deoblique_node, gen_ref, [('out_file', 'in_file')]), (deoblique_node, hmc, [('out_file', 'in_file')]), ]) elif despike: workflow.connect([ (drop_trs, despike_node, [('out_file', 'in_file')]), (despike_node, gen_ref, [('out_file', 'in_file')]), (despike_node, hmc, [('out_file', 'in_file')]), ]) elif deoblique: workflow.connect([ (drop_trs, deoblique_node, [('out_file', 'in_file')]), (deoblique_node, gen_ref, [('out_file', 'in_file')]), (deoblique_node, hmc, [('out_file', 'in_file')]), ]) else: workflow.connect([ (drop_trs, gen_ref, [('out_file', 'in_file')]), (drop_trs, hmc, [('out_file', 'in_file')]), ]) return workflow