-
Notifications
You must be signed in to change notification settings - Fork 536
Added ANTS functions antsIntroduction.sh, WarpImageMultiTransform, build... #310
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
aa5b2d8
2cd86df
b4a4d58
de54560
019c767
854d8ae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- | ||
| # vi: set ft=python sts=4 ts=4 sw=4 et: | ||
| """Top-level namespace for ants.""" | ||
| from nipype.interfaces.ants.base import ANTSCommand | ||
| from nipype.interfaces.ants.normalize import (BuildTemplate, | ||
| WarpImageMultiTransform, GenWarpFields) | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- | ||
| # vi: set ft=python sts=4 ts=4 sw=4 et: | ||
| """The ants module provides basic functions for interfacing with ANTS tools.""" | ||
|
|
||
| __docformat__ = 'restructuredtext' | ||
|
|
||
| # Standard library imports | ||
| import os | ||
| from copy import deepcopy | ||
|
|
||
| # Third-party imports | ||
| import numpy as np | ||
|
|
||
| # Local imports | ||
| from nipype.interfaces.base import (TraitedSpec, File, traits, | ||
| Directory, InputMultiPath, | ||
| OutputMultiPath, CommandLine, | ||
| CommandLineInputSpec, isdefined) | ||
| import logging | ||
| logger = logging.getLogger('iflogger') | ||
|
|
||
| class ANTSCommand(CommandLine): | ||
| def __init__(self, **inputs): | ||
| self.inputs.environ['ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS']='1' | ||
| return super(ANTSCommand, self).__init__(**inputs) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,299 @@ | ||
| # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- | ||
| # vi: set ft=python sts=4 ts=4 sw=4 et: | ||
| """The ants module provides basic functions for interfacing with ants functions. | ||
|
|
||
| Change directory to provide relative paths for doctests | ||
| >>> import os | ||
| >>> filepath = os.path.dirname( os.path.realpath( __file__ ) ) | ||
| >>> datadir = os.path.realpath(os.path.join(filepath, '../../testing/data')) | ||
| >>> os.chdir(datadir) | ||
|
|
||
| """ | ||
|
|
||
| __docformat__ = 'restructuredtext' | ||
|
|
||
| # Standard library imports | ||
| import logging | ||
| import os | ||
| from glob import glob | ||
|
|
||
| # Third-party imports | ||
| import numpy as np | ||
| import scipy.io as sio | ||
|
|
||
| # Local imports | ||
| from nipype.interfaces.base import (TraitedSpec, File, traits, | ||
| Directory, InputMultiPath, | ||
| OutputMultiPath, CommandLine, | ||
| CommandLineInputSpec, isdefined) | ||
| from nipype.utils.filemanip import (filename_to_list,copyfiles, list_to_filename, | ||
| split_filename, fname_presuffix) | ||
| from nipype.interfaces.ants.base import ANTSCommand | ||
|
|
||
| class BuildTemplateInputSpec(CommandLineInputSpec): | ||
| dimension = traits.Enum(3, 2, argstr='-d %d',usedefault=True, | ||
| desc='image dimension (2 or 3)', position=1) | ||
| out_prefix = traits.Str('antsTMPL_',argstr='-o %s',usedefault=True, | ||
| desc='Prefix that is prepended to all output files ' | ||
| '(default = antsTMPL_)') | ||
| in_files = traits.List(File(exists=True), mandatory=True, | ||
| desc='list of images to generate template from',argstr='%s',position=-1) | ||
| parallelization = traits.Enum(0,1,2,argstr='-c %d',usedefault=True, | ||
| desc='control for parallel processing (0 = serial, ' | ||
| '1 = use PBS, 2 = use PEXEC, 3 = use Apple XGrid') | ||
| gradient_step_size = traits.Float(argstr='-g %f',desc='smaller magnitude ' | ||
| 'results in more cautious steps (default = .25)') | ||
| iteration_limit = traits.Int(argstr='-i %d',desc='iterations of template ' | ||
| 'construction (default 4)') | ||
| num_cores = traits.Int(argstr='-j %d',requires=['parallelization'],desc='Requires parallelization = 2 (PEXEC). ' | ||
| 'Sets number of cpu cores to use (default 2)') | ||
| max_iterations = traits.List(traits.Int,argstr='-m %s',sep='x', | ||
| desc='maximum number of iterations (must be list of integers ' | ||
| 'in the form [J,K,L...]: J = coarsest resolution iterations, ' | ||
| 'K = middle resolution interations, L = fine resolution ' | ||
| 'iterations') | ||
| bias_field_correction = traits.Bool(argstr = '-n 1', | ||
| desc='Applies bias field correction to moving image') | ||
| rigid_body_registration = traits.Bool(argstr='-r 1', | ||
| desc='registers inputs before creating template (useful' | ||
| 'if no initial template available)') | ||
| similarity_metric = traits.Enum('PR','CC','MI','MSQ',argstr='-s %s', | ||
| desc='Type of similartiy metric used for registration ' | ||
| '(CC = cross correlation, MI = mutual information, ' | ||
| 'PR = probability mapping, MSQ = mean square difference)') | ||
| transformation_model = traits.Enum('GR','EL','SY','S2','EX','DD',argstr='-t %s',usedefault=True, | ||
| desc='Type of transofmration model used for registration ' | ||
| '(EL = elastic transformation model, SY = SyN with time, ' | ||
| 'arbitrary number of time points, S2 = SyN with time ' | ||
| 'optimized for 2 time points, GR = greedy SyN, EX = ' | ||
| 'exponential, DD = diffeomorphic demons style exponential ' | ||
| 'mapping') | ||
| use_first_as_target = traits.Bool(desc='uses first volume as target of all inputs. ' | ||
| 'When not used, an unbiased average image is used to start.') | ||
|
|
||
| class BuildTemplateOutputSpec(TraitedSpec): | ||
| final_template_file = File(exists=True, desc='final ANTS template') | ||
| template_files = traits.Either(traits.List(File(exists=True)), | ||
| File(exists=True), desc='Templates from different stages of iteration') | ||
| subject_outfiles = output_images = traits.Either(traits.List(File(exists=True)), | ||
| File(exists=True), desc='Outputs for each input image. ' | ||
| 'Includes warp field, inverse warp, Affine, original image (repaired) ' | ||
| 'and warped image (deformed)') | ||
|
|
||
|
|
||
| class BuildTemplate(ANTSCommand): | ||
| """Uses the ANTS command buildtemplateparallel.sh to generate a template from the files listed in in_files. | ||
|
|
||
| .. note:: | ||
| This can take a VERY long time to complete | ||
|
|
||
| Examples | ||
| -------- | ||
|
|
||
| >>> from nipype.interfaces.ants import BuildTemplate | ||
| >>> tmpl = BuildTemplate() | ||
| >>> tmpl.inputs.in_files = ['foo.nii','bar.nii'] | ||
| >>> tmpl.inputs.max_iterations = [30,90,20] | ||
| >>> tpml.cmdline | ||
| 'buildtemplateparallel.sh -d 3 -m 30x90x20 -o antsTMPL_ -c 0 -t GR foo.nii bar.nii' | ||
|
|
||
| """ | ||
|
|
||
| _cmd = 'buildtemplateparallel.sh' | ||
| input_spec = BuildTemplateInputSpec | ||
| output_spec = BuildTemplateOutputSpec | ||
|
|
||
|
|
||
|
|
||
| def _format_arg(self, opt, spec, val): | ||
| if opt == 'num_cores': | ||
| if self.inputs.parallelization == 2: | ||
| return '-j '+val | ||
| else: | ||
| return '' | ||
| if opt == 'in_files': | ||
| if self.inputs.use_first_as_target: | ||
| start='-z ' | ||
| else: | ||
| start='' | ||
| return start+' '.join([os.path.split(name)[1] for name in val]) | ||
| return super(BuildTemplate,self)._format_arg(opt,spec,val) | ||
|
|
||
| def _list_outputs(self): | ||
| outputs = self._outputs().get() | ||
| outputs['template_files'] = [] | ||
| for i in range(len(glob(os.path.realpath('*iteration*')))): | ||
| temp = os.path.realpath('%s_iteration_%d/%stemplate.nii.gz'%(self.inputs.transformation_model,i,self.inputs.out_prefix)) | ||
| os.rename(temp,os.path.realpath('%s_iteration_%d/%stemplate_i%d.nii.gz'%(self.inputs.transformation_model,i,self.inputs.out_prefix,i))) | ||
| outputs['template_files'].append(os.path.realpath('%s_iteration_%d/%stemplate_i%d.nii.gz'%(self.inputs.transformation_model,i,self.inputs.out_prefix,i))) | ||
| outputs['final_template_file'] = os.path.realpath('%stemplate.nii.gz'%self.inputs.out_prefix) | ||
| outputs['subject_outfiles'] = [] | ||
| for filename in self.inputs.in_files: | ||
| pth, base, ext = split_filename(filename) | ||
| temp = glob(os.path.realpath('%s%s*'%(self.inputs.out_prefix,base))) | ||
| for file_ in temp: | ||
| outputs['subject_outfiles'].append(file_) | ||
| return outputs | ||
|
|
||
|
|
||
|
|
||
|
|
||
| class WarpImageMultiTransformInputSpec(CommandLineInputSpec): | ||
| dimension = traits.Enum(3, 2, argstr='%d',usedefault=True, | ||
| desc='image dimension (2 or 3)',position=1) | ||
| moving_image = File(argstr='%s',desc='image to apply transformation ' | ||
| 'to (generally a coregistered functional)', | ||
| mandatory=True, copyfile=True) | ||
| out_postfix = traits.Str('_wimt',argstr='%s', | ||
| desc='Postfix that is prepended to all output files ' | ||
| '(default = _wimt)',usedefault=True) | ||
| reference_image = File(argstr='-R %s',desc='reference image space that you ' | ||
| 'wish to warp INTO',xor=['tightest_box']) | ||
| tightest_box = traits.Bool(argstr='--tightest-bounding-box', | ||
| desc='computes tightest bounding box (overrided by ' | ||
| 'reference_image if given)',xor=['reference_image']) | ||
| reslice_by_header = traits.Bool(argstr='--reslice-by-header', | ||
| desc='Uses orientation matrix and origin encoded in ' | ||
| 'reference image file header. Not typically used with ' | ||
| 'additional transforms') | ||
| use_nearest = traits.Bool(argstr='--use-NN',desc='Use nearest neighbor interpolation') | ||
| use_bspline = traits.Bool(argstr='--use-Bspline',desc='Use 3rd order' | ||
| 'B-Spline interpolation') | ||
| transformation_series = InputMultiPath(File(exists=True),argstr='%s', | ||
| desc='transformation file(s) to be applied', | ||
| mandatory=True, copyfile=False) | ||
| invert_affine = traits.List(traits.Int, desc='List of Affine transformations to invert. ' | ||
| 'E.g.: [1,4,5] inverts the 1st, 4th, and 5th Affines ' | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should be 0 based? or not?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, to make sense for the user, it's not the actual index of the Affine, but the 1st, 4th, and 5th affine that are found in the series (see _format_arg()) |
||
| 'found in transformation_series') | ||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
| class WarpImageMultiTransformOutputSpec(TraitedSpec): | ||
| output_images = traits.Either(traits.List(File(exists=True)), | ||
| File(exists=True)) | ||
|
|
||
| class WarpImageMultiTransform(ANTSCommand): | ||
| """Uses the ANTS command WarpImageMultiTransform to warp an image (moving image) from one space to another (fixed/template space) | ||
|
|
||
| Examples | ||
| -------- | ||
|
|
||
| >>> from nipype.interfaces.ants import WarpImageMultiTransform | ||
| >>> wimt = WarpImageMultiTransform() | ||
| >>> wimt.inputs.moving_image = 'foo.nii' | ||
| >>> wimt.inputs.reference_image = 'ants_deformed.nii.gz' | ||
| >>> wimt.inputs.transformation_series = ['ants_Warp.nii.gz','ants_Affine.txt'] | ||
| >>> wimt.cmdline | ||
| 'WarpImageMultiTransform 3 foo.nii foo_wimt.nii -R ants_deformed.nii.gz ants_Warp.nii.gz ants_Affine.txt' | ||
|
|
||
| """ | ||
|
|
||
| _cmd = 'WarpImageMultiTransform' | ||
| input_spec = WarpImageMultiTransformInputSpec | ||
| output_spec = WarpImageMultiTransformOutputSpec | ||
|
|
||
| def _format_arg(self, opt, spec, val): | ||
| if opt == 'out_postfix': | ||
| return os.path.split(self.inputs.moving_image)[-1].partition('.')[0]+val+'.'+os.path.split(self.inputs.moving_image)[-1].partition('.')[2] | ||
| if opt == 'transformation_series': | ||
| series = '' | ||
| affine_counter = 0 | ||
| for transformation in val: | ||
| if transformation.find('Affine')!=-1 and isdefined(self.inputs.invert_affine): | ||
| affine_counter = affine_counter + 1 | ||
| if self.inputs.invert_affine.__contains__(affine_counter): | ||
| series=series+'-i '+transformation+' ' | ||
| else: | ||
| series=series+transformation+' ' | ||
| else: | ||
| series=series+transformation+' ' | ||
|
|
||
| return series | ||
| return super(WarpImageMultiTransform,self)._format_arg(opt,spec,val) | ||
|
|
||
| def _list_outputs(self): | ||
| outputs = self._outputs().get() | ||
| outputs['output_images'] = glob(os.path.join(os.getcwd(),os.path.split(self.inputs.moving_image)[-1].partition('.')[0]+self.inputs.out_postfix+'*'))[0] | ||
| print outputs['output_images'] | ||
| return outputs | ||
|
|
||
|
|
||
| class AntsIntroductionInputSpec(CommandLineInputSpec): | ||
| dimension = traits.Enum(3, 2, argstr='-d %d',usedefault=True, | ||
| desc='image dimension (2 or 3)', position=1) | ||
| reference_image = File(argstr='-r %s',desc='template file to warp to', | ||
| mandatory=True, copyfile=True) | ||
| input_image = File(argstr='-i %s',desc='input image to warp to template', | ||
| mandatory=True, copyfile=False) | ||
| force_proceed = traits.Bool(argstr='-f 1', | ||
| desc='force script to proceed even if headers may ' | ||
| 'be incompatible') | ||
| inverse_warp_template_labels = traits.Bool(argstr='-l', | ||
| desc='Applies inverse warp to the template labels ' | ||
| 'to estimate label positions in target space (use ' | ||
| 'for template-based segmentation)') | ||
| max_iterations = traits.List(traits.Int,argstr='-m %s',sep='x', | ||
| desc='maximum number of iterations (must be list of integers ' | ||
| 'in the form [J,K,L...]: J = coarsest resolution iterations, ' | ||
| 'K = middle resolution interations, L = fine resolution ' | ||
| 'iterations') | ||
| bias_field_correction = traits.Bool(argstr='-n 1', | ||
| desc='Applies bias field correction to moving image') | ||
| out_prefix = traits.Str('ants_',argstr='-o %s', usedefault=True, | ||
| desc='Prefix that is prepended to all output files ' | ||
| '(default = ants_)') | ||
| quality_check = traits.Bool(argstr='-q 1', | ||
| desc='Perform a quality check of the result') | ||
| similarity_metric = traits.Enum('PR','CC','MI','MSQ',argstr='-s %s', | ||
| desc='Type of similartiy metric used for registration ' | ||
| '(CC = cross correlation, MI = mutual information, ' | ||
| 'PR = probability mapping, MSQ = mean square difference)') | ||
| transformation_model = traits.Enum('GR','EL','SY','S2','EX','DD','RI','RA',argstr='-t %s', | ||
| desc='Type of transofmration model used for registration ' | ||
| '(EL = elastic transformation model, SY = SyN with time, ' | ||
| 'arbitrary number of time points, S2 = SyN with time ' | ||
| 'optimized for 2 time points, GR = greedy SyN, EX = ' | ||
| 'exponential, DD = diffeomorphic demons style exponential ' | ||
| 'mapping, RI = purely rigid, RA = affine rigid') | ||
|
|
||
| class AntsIntroductionOutputSpec(TraitedSpec): | ||
| affine_transformation = File(exists=True, desc='affine (prefix_Affine.txt)') | ||
| warp_field = File(exists=True, desc='warp field (prefix_Warp.nii)') | ||
| inverse_warp_field = File(exists=True, desc='inverse warp field (prefix_InverseWarp.nii)') | ||
| input_file = File(exists=True, desc='input image (prefix_repaired.nii)') | ||
| output_file = File(exists=True, desc='output image (prefix_deformed.nii)') | ||
|
|
||
| class GenWarpFields(ANTSCommand): | ||
| """Uses ANTS to generate matrices to warp data from one space to another. | ||
|
|
||
| Examples | ||
| -------- | ||
|
|
||
| >>> from nipype.interfaces.ants import GenWarpFields | ||
| >>> warp = GenWarpFields() | ||
| >>> warp.inputs.reference_image = 'template.nii' | ||
| >>> warp.inputs.input_image = 'brain.nii' | ||
| >>> warp.inputs.max_iterations = [30,90,20] | ||
| >>> warp.cmdline | ||
| 'antsIntroduction -d 3 -i brain.nii -m 30x90x20 -o ants_ -r template.nii' | ||
|
|
||
| """ | ||
|
|
||
| _cmd = 'antsIntroduction.sh' | ||
| input_spec = AntsIntroductionInputSpec | ||
| output_spec = AntsIntroductionOutputSpec | ||
|
|
||
| def _list_outputs(self): | ||
| outputs = self._outputs().get() | ||
|
|
||
| outputs['affine_transformation'] = os.path.join(os.getcwd(),self.inputs.out_prefix+'Affine.txt') | ||
| outputs['warp_field'] = os.path.join(os.getcwd(),self.inputs.out_prefix+'Warp.nii.gz') | ||
| outputs['inverse_warp_field'] = os.path.join(os.getcwd(),self.inputs.out_prefix+'InverseWarp.nii.gz') | ||
| outputs['input_file'] = os.path.join(os.getcwd(),self.inputs.out_prefix+'repaired.nii.gz') | ||
| outputs['output_file'] = os.path.join(os.getcwd(),self.inputs.out_prefix+'deformed.nii.gz') | ||
|
|
||
| return outputs | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- | ||
| # vi: set ft=python sts=4 ts=4 sw=4 et: | ||
| def configuration(parent_package='',top_path=None): | ||
| from numpy.distutils.misc_util import Configuration | ||
|
|
||
| config = Configuration('ants', parent_package, top_path) | ||
|
|
||
| config.add_data_dir('tests') | ||
|
|
||
| return config | ||
|
|
||
| if __name__ == '__main__': | ||
| from numpy.distutils.core import setup | ||
| setup(**configuration(top_path='').todict()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you want to do this in
__init__so that people can modify it if they have to.