From aa5b2d847661fa31099afc63d3f0925936b25108 Mon Sep 17 00:00:00 2001 From: John Salvatore Date: Thu, 1 Mar 2012 17:45:31 -0500 Subject: [PATCH 1/6] Added ANTS functions antsIntroduction.sh, WarpImageMultiTransform, buildtemplateparallel.sh --- nipype/interfaces/ants/__init__.py | 8 + nipype/interfaces/ants/base.py | 39 ++++ nipype/interfaces/ants/normalize.py | 322 ++++++++++++++++++++++++++++ nipype/interfaces/ants/setup.py | 14 ++ 4 files changed, 383 insertions(+) create mode 100644 nipype/interfaces/ants/__init__.py create mode 100644 nipype/interfaces/ants/base.py create mode 100644 nipype/interfaces/ants/normalize.py create mode 100644 nipype/interfaces/ants/setup.py diff --git a/nipype/interfaces/ants/__init__.py b/nipype/interfaces/ants/__init__.py new file mode 100644 index 0000000000..304d0541bd --- /dev/null +++ b/nipype/interfaces/ants/__init__.py @@ -0,0 +1,8 @@ +# 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, logger) +from nipype.interfaces.ants.normalize import (BuildTemplate, + WarpImageMultiTransform, GenWarpFields) + diff --git a/nipype/interfaces/ants/base.py b/nipype/interfaces/ants/base.py new file mode 100644 index 0000000000..05dece22dd --- /dev/null +++ b/nipype/interfaces/ants/base.py @@ -0,0 +1,39 @@ +# 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 ANTSCommandInputSpec(CommandLineInputSpec): + + def _test(): + return True + +class ANTSCommand(CommandLine): + + def _run_interface(self,runtime): + if (not os.environ.has_key('LD_LIBRARY_PATH')) or (os.environ.get('LD_LIBRARY_PATH').find(':/software/ANTS/versions/120222/lib') == -1): + os.environ['LD_LIBRARY_PATH']=os.environ['LD_LIBRARY_PATH']+':/software/ANTS/versions/120222/lib' + if (not os.environ.has_key('PATH')) or (os.environ.get('PATH').find('/software/ANTS/versions/120222/bin') == -1): + os.environ['PATH']=os.environ['PATH']+':/software/ANTS/versions/120222/bin' + if (not os.environ.has_key('ANTSPATH') )or (os.environ.get('ANTSPATH').find('/software/ANTS/versions/120222/bin/') == -1): + os.environ['ANTSPATH']='/software/ANTS/versions/120222/bin/' + self.inputs.environ=dict(os.environ) + return super(ANTSCommand, self)._run_interface(runtime) + diff --git a/nipype/interfaces/ants/normalize.py b/nipype/interfaces/ants/normalize.py new file mode 100644 index 0000000000..b8b8698e8b --- /dev/null +++ b/nipype/interfaces/ants/normalize.py @@ -0,0 +1,322 @@ +# 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.interfaces.ants.base import (ANTSCommand, ANTSCommandInputSpec) +from nipype.utils.filemanip import (filename_to_list,copyfiles, list_to_filename, + split_filename, fname_presuffix) + +class BuildTemplateInputSpec(CommandLineInputSpec): + dimension = traits.Enum(3, 2, argstr='%d', usedefault=True, + desc='image dimension (2 or 3)') + out_prefix = traits.Str('antsTMPL_',argstr='%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, + copyfile=True) + parallelization = traits.Enum(0,1,2,argstr='%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',desc='Requires parallelization = 2 (PEXEC). \ + Sets number of cpu cores to use (default 2)') + max_iterations = traits.Str('30x90x20',argstr='-m %s', + desc='maximum number of iterations (must be string \ + in the form JxKxL: J = coarsest resolution iterations, \ + K = middle resolution interations, L = fine resolution \ + iterations') + bias_field_correction = traits.Bool( + 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 + >>> BTP = BuildTemplate() + >>> BTP.inputs.out_prefix = 'antsTMPL_' + >>> BTP.inputs.in_files={'sub01':'foo.nii','sub02':'bar.nii'} + >>> BTP.cmdline + 'buildtemplateparallel.sh -d 3 -o antsTMPL_ foo.nii bar.nii' + + """ + + _cmd = 'buildtemplateparallel.sh' + input_spec = BuildTemplateInputSpec + output_spec = BuildTemplateOutputSpec + + + + def _format_arg(self, opt, spec, val): + + + if opt == 'transformation_model': + return '-t %s'%val + if opt == 'parallelization': + return '-c %d'%val + if opt == 'out_prefix': + return '-o %s'%val + if opt == 'dimension': + return '-d %d'%val + if opt == 'num_cores': + if self.inputs.parallelization == 2: + return val + else: + return '' + if opt == 'rigid_body_registration': + if self.inputs.rigid_body_registration: + return '-r 1' + if opt == 'in_files': + series = '' + if self.inputs.use_first_as_target: + series=series+'-z ' + for image_path in val: + pth, base, ext = split_filename(image_path) + series=series+base+ext+' ' + return series + return 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)') + 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='%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(traits.Either(traits.List(File(exists=True)), + File(exists=True)),argstr='%s', + desc='transformation file(s) to be applied', + mandatory=True, copyfile=False) + invert_affine = traits.Bool(desc='apply inverse of given affine') + + + + + +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.dimension = 3 + >>> WIMT.inputs.moving_image = 'con_0001.nii' + >>> WIMT.inputs.out_postfix = '_wimt' + >>> WIMT.inputs.reference_image = 'ants_deformed.nii.gz' + >>> WIMT.inputs.transformation_series = ['ants_Warp.nii.gz','ants_Affine.txt'] + >>> WIMT.cmdline + 'WarpImageMultiTransform 3 con_0001.nii con_0001_wimt -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 == 'reference_image': + return '-R %s'%val + if opt == 'dimension': + return '%d'%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 = '' + val=filename_to_list(val) + for transformation in val: + if transformation.find('Affine')!=-1 and self.inputs.invert_affine: + series=series+'-i '+transformation+' ' + else: + series=series+transformation+' ' + return series + return 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',usedefault=True, + desc='image dimension (2 or 3)') + 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.Str('30x90x20',argstr='-m %s', + desc='maximum number of iterations (must be string \ + in the form JxKxL: 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='%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 the ANTS command antsIntroduction to generate warp and inverse warp fields that transform structural data + from anatomical images of a subject to the input template space. + + Examples + -------- + + >>> from nipype.interfaces.ANTS import GenWarpFields + >>> warp = GenWarpFields() + >>> warp.inputs.reference_image = 'template.nii' + >>> warp.inputs.input_image = 'brain.nii' + >>> warp.inputs.output_prefix = 'ants_' + >>> warp.cmdline + 'antsIntroduction -d 3 -r template.nii -i brain.nii -o ants_' + + """ + + _cmd = 'antsIntroduction.sh' + input_spec = AntsIntroductionInputSpec + output_spec = AntsIntroductionOutputSpec + + + def _format_arg(self, opt, spec, val): + print val + print opt + if opt == 'out_prefix': + return '-o %s'%val + if opt == 'dimension': + return '-d %d'%val + + 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 + + diff --git a/nipype/interfaces/ants/setup.py b/nipype/interfaces/ants/setup.py new file mode 100644 index 0000000000..c9ce8f56d6 --- /dev/null +++ b/nipype/interfaces/ants/setup.py @@ -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()) From 2cd86dfe1ef7da85de06c7573da975971d4ada38 Mon Sep 17 00:00:00 2001 From: John Salvatore Date: Thu, 1 Mar 2012 18:54:48 -0500 Subject: [PATCH 2/6] made recommended changes to ANTS scripts --- nipype/interfaces/ants/__init__.py | 2 +- nipype/interfaces/ants/base.py | 17 --------- nipype/interfaces/ants/normalize.py | 59 ++++++++--------------------- 3 files changed, 17 insertions(+), 61 deletions(-) diff --git a/nipype/interfaces/ants/__init__.py b/nipype/interfaces/ants/__init__.py index 304d0541bd..e353c373bd 100644 --- a/nipype/interfaces/ants/__init__.py +++ b/nipype/interfaces/ants/__init__.py @@ -2,7 +2,7 @@ # vi: set ft=python sts=4 ts=4 sw=4 et: """Top-level namespace for ants.""" -from nipype.interfaces.ants.base import (ANTSCommand, logger) +from nipype.interfaces.ants.base import (logger) from nipype.interfaces.ants.normalize import (BuildTemplate, WarpImageMultiTransform, GenWarpFields) diff --git a/nipype/interfaces/ants/base.py b/nipype/interfaces/ants/base.py index 05dece22dd..148bcb1176 100644 --- a/nipype/interfaces/ants/base.py +++ b/nipype/interfaces/ants/base.py @@ -20,20 +20,3 @@ logger = logging.getLogger('iflogger') -class ANTSCommandInputSpec(CommandLineInputSpec): - - def _test(): - return True - -class ANTSCommand(CommandLine): - - def _run_interface(self,runtime): - if (not os.environ.has_key('LD_LIBRARY_PATH')) or (os.environ.get('LD_LIBRARY_PATH').find(':/software/ANTS/versions/120222/lib') == -1): - os.environ['LD_LIBRARY_PATH']=os.environ['LD_LIBRARY_PATH']+':/software/ANTS/versions/120222/lib' - if (not os.environ.has_key('PATH')) or (os.environ.get('PATH').find('/software/ANTS/versions/120222/bin') == -1): - os.environ['PATH']=os.environ['PATH']+':/software/ANTS/versions/120222/bin' - if (not os.environ.has_key('ANTSPATH') )or (os.environ.get('ANTSPATH').find('/software/ANTS/versions/120222/bin/') == -1): - os.environ['ANTSPATH']='/software/ANTS/versions/120222/bin/' - self.inputs.environ=dict(os.environ) - return super(ANTSCommand, self)._run_interface(runtime) - diff --git a/nipype/interfaces/ants/normalize.py b/nipype/interfaces/ants/normalize.py index b8b8698e8b..40cf3b6624 100644 --- a/nipype/interfaces/ants/normalize.py +++ b/nipype/interfaces/ants/normalize.py @@ -26,20 +26,19 @@ Directory, InputMultiPath, OutputMultiPath, CommandLine, CommandLineInputSpec, isdefined) -from nipype.interfaces.ants.base import (ANTSCommand, ANTSCommandInputSpec) from nipype.utils.filemanip import (filename_to_list,copyfiles, list_to_filename, split_filename, fname_presuffix) class BuildTemplateInputSpec(CommandLineInputSpec): - dimension = traits.Enum(3, 2, argstr='%d', usedefault=True, - desc='image dimension (2 or 3)') - out_prefix = traits.Str('antsTMPL_',argstr='%s',usedefault=True, + 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, copyfile=True) - parallelization = traits.Enum(0,1,2,argstr='%d',usedefault=True, + 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 \ @@ -82,7 +81,7 @@ class BuildTemplateOutputSpec(TraitedSpec): and warped image (deformed)') -class BuildTemplate(ANTSCommand): +class BuildTemplate(CommandLine): """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 @@ -104,24 +103,11 @@ class BuildTemplate(ANTSCommand): def _format_arg(self, opt, spec, val): - - - if opt == 'transformation_model': - return '-t %s'%val - if opt == 'parallelization': - return '-c %d'%val - if opt == 'out_prefix': - return '-o %s'%val - if opt == 'dimension': - return '-d %d'%val if opt == 'num_cores': if self.inputs.parallelization == 2: - return val + return '-j '+val else: return '' - if opt == 'rigid_body_registration': - if self.inputs.rigid_body_registration: - return '-r 1' if opt == 'in_files': series = '' if self.inputs.use_first_as_target: @@ -130,7 +116,7 @@ def _format_arg(self, opt, spec, val): pth, base, ext = split_filename(image_path) series=series+base+ext+' ' return series - return val + return super(BuildTemplate,self)._format_arg(opt,spec,val) def _list_outputs(self): outputs = self._outputs().get() @@ -152,15 +138,15 @@ def _list_outputs(self): class WarpImageMultiTransformInputSpec(CommandLineInputSpec): - dimension = traits.Enum(3, 2, argstr='%d', usedefault=True, - desc='image dimension (2 or 3)') + 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='%s',desc='reference image space that you \ + 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 \ @@ -186,7 +172,7 @@ class WarpImageMultiTransformOutputSpec(TraitedSpec): output_images = traits.Either(traits.List(File(exists=True)), File(exists=True)) -class WarpImageMultiTransform(ANTSCommand): +class WarpImageMultiTransform(CommandLine): """Uses the ANTS command WarpImageMultiTransform to warp an image (moving image) from one space to another (fixed/template space) Examples @@ -209,10 +195,6 @@ class WarpImageMultiTransform(ANTSCommand): output_spec = WarpImageMultiTransformOutputSpec def _format_arg(self, opt, spec, val): - if opt == 'reference_image': - return '-R %s'%val - if opt == 'dimension': - return '%d'%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': @@ -224,7 +206,7 @@ def _format_arg(self, opt, spec, val): else: series=series+transformation+' ' return series - return val + return super(WarpImageMultiTransform,self)._format_arg(opt,spec,val) def _list_outputs(self): outputs = self._outputs().get() @@ -234,8 +216,8 @@ def _list_outputs(self): class AntsIntroductionInputSpec(CommandLineInputSpec): - dimension = traits.Enum(3, 2, argstr='%d',usedefault=True, - desc='image dimension (2 or 3)') + 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', @@ -254,7 +236,7 @@ class AntsIntroductionInputSpec(CommandLineInputSpec): iterations') bias_field_correction = traits.Bool(argstr='-n 1', desc='Applies bias field correction to moving image') - out_prefix = traits.Str('ants_',argstr='%s', usedefault=True, + 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', @@ -278,7 +260,7 @@ class AntsIntroductionOutputSpec(TraitedSpec): 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): +class GenWarpFields(CommandLine): """Uses the ANTS command antsIntroduction to generate warp and inverse warp fields that transform structural data from anatomical images of a subject to the input template space. @@ -299,15 +281,6 @@ class GenWarpFields(ANTSCommand): input_spec = AntsIntroductionInputSpec output_spec = AntsIntroductionOutputSpec - - def _format_arg(self, opt, spec, val): - print val - print opt - if opt == 'out_prefix': - return '-o %s'%val - if opt == 'dimension': - return '-d %d'%val - def _list_outputs(self): outputs = self._outputs().get() From b4a4d580aa3a95f39d29ca1ac6b665f69a88294e Mon Sep 17 00:00:00 2001 From: John Salvatore Date: Fri, 2 Mar 2012 13:41:57 -0500 Subject: [PATCH 3/6] updated ants changes --- nipype/interfaces/ants/__init__.py | 2 - nipype/interfaces/ants/normalize.py | 203 ++++++++++++++-------------- 2 files changed, 102 insertions(+), 103 deletions(-) diff --git a/nipype/interfaces/ants/__init__.py b/nipype/interfaces/ants/__init__.py index e353c373bd..99eae52bb1 100644 --- a/nipype/interfaces/ants/__init__.py +++ b/nipype/interfaces/ants/__init__.py @@ -1,8 +1,6 @@ # 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 (logger) from nipype.interfaces.ants.normalize import (BuildTemplate, WarpImageMultiTransform, GenWarpFields) diff --git a/nipype/interfaces/ants/normalize.py b/nipype/interfaces/ants/normalize.py index 40cf3b6624..31be0a8c12 100644 --- a/nipype/interfaces/ants/normalize.py +++ b/nipype/interfaces/ants/normalize.py @@ -33,52 +33,51 @@ 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_)') + 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, - copyfile=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',desc='Requires parallelization = 2 (PEXEC). \ - Sets number of cpu cores to use (default 2)') - max_iterations = traits.Str('30x90x20',argstr='-m %s', - desc='maximum number of iterations (must be string \ - in the form JxKxL: J = coarsest resolution iterations, \ - K = middle resolution interations, L = fine resolution \ - iterations') - bias_field_correction = traits.Bool( + 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)') + 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)') + 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.') + 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)), + 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)') + 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(CommandLine): @@ -87,12 +86,12 @@ class BuildTemplate(CommandLine): Examples -------- - >>> from nipype.interfaces.ANTS import BuildTemplate - >>> BTP = BuildTemplate() - >>> BTP.inputs.out_prefix = 'antsTMPL_' - >>> BTP.inputs.in_files={'sub01':'foo.nii','sub02':'bar.nii'} - >>> BTP.cmdline - 'buildtemplateparallel.sh -d 3 -o antsTMPL_ foo.nii bar.nii' + >>> 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' """ @@ -109,13 +108,11 @@ def _format_arg(self, opt, spec, val): else: return '' if opt == 'in_files': - series = '' if self.inputs.use_first_as_target: - series=series+'-z ' - for image_path in val: - pth, base, ext = split_filename(image_path) - series=series+base+ext+' ' - return series + 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): @@ -140,29 +137,30 @@ def _list_outputs(self): 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)', + 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']) + 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']) + 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') + 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(traits.Either(traits.List(File(exists=True)), - File(exists=True)),argstr='%s', + 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.Bool(desc='apply inverse of given affine') + 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 ' + 'found in transformation_series') @@ -178,15 +176,13 @@ class WarpImageMultiTransform(CommandLine): Examples -------- - >>> from nipype.interfaces.ANTS import WarpImageMultiTransform - >>> WIMT = WarpImageMultiTransform() - >>> WIMT.inputs.dimension = 3 - >>> WIMT.inputs.moving_image = 'con_0001.nii' - >>> WIMT.inputs.out_postfix = '_wimt' - >>> WIMT.inputs.reference_image = 'ants_deformed.nii.gz' - >>> WIMT.inputs.transformation_series = ['ants_Warp.nii.gz','ants_Affine.txt'] - >>> WIMT.cmdline - 'WarpImageMultiTransform 3 con_0001.nii con_0001_wimt -R ants_deformed.nii.gz ants_Warp.nii.gz ants_Affine.txt' + >>> 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' """ @@ -199,12 +195,17 @@ def _format_arg(self, opt, spec, val): 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 = '' - val=filename_to_list(val) - for transformation in val: - if transformation.find('Affine')!=-1 and self.inputs.invert_affine: - series=series+'-i '+transformation+' ' + 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) @@ -223,35 +224,35 @@ class AntsIntroductionInputSpec(CommandLineInputSpec): 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') + 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.Str('30x90x20',argstr='-m %s', - desc='maximum number of iterations (must be string \ - in the form JxKxL: J = coarsest resolution iterations, \ - K = middle resolution interations, L = fine resolution \ - iterations') + 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_)') + 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)') + 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') + 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)') @@ -267,13 +268,13 @@ class GenWarpFields(CommandLine): Examples -------- - >>> from nipype.interfaces.ANTS import GenWarpFields + >>> from nipype.interfaces.ants import GenWarpFields >>> warp = GenWarpFields() >>> warp.inputs.reference_image = 'template.nii' >>> warp.inputs.input_image = 'brain.nii' - >>> warp.inputs.output_prefix = 'ants_' + >>> warp.inputs.max_iterations = [30,90,20] >>> warp.cmdline - 'antsIntroduction -d 3 -r template.nii -i brain.nii -o ants_' + 'antsIntroduction -d 3 -i brain.nii -m 30x90x20 -o ants_ -r template.nii' """ From de545601203036a6ff6a5ada217c7fc3758ef8df Mon Sep 17 00:00:00 2001 From: John Salvatore Date: Sat, 3 Mar 2012 12:21:46 -0500 Subject: [PATCH 4/6] included single threading env variable and made recommended changes --- nipype/interfaces/ants/__init__.py | 1 + nipype/interfaces/ants/base.py | 5 ++++- nipype/interfaces/ants/normalize.py | 15 +++++++++------ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/nipype/interfaces/ants/__init__.py b/nipype/interfaces/ants/__init__.py index 99eae52bb1..e22fc91edf 100644 --- a/nipype/interfaces/ants/__init__.py +++ b/nipype/interfaces/ants/__init__.py @@ -1,6 +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) diff --git a/nipype/interfaces/ants/base.py b/nipype/interfaces/ants/base.py index 148bcb1176..5d2c90c529 100644 --- a/nipype/interfaces/ants/base.py +++ b/nipype/interfaces/ants/base.py @@ -19,4 +19,7 @@ import logging logger = logging.getLogger('iflogger') - +class ANTSCommand(CommandLine): + def _run_interface(self, runtime): + self.inputs.environ['ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS']='1' + return super(ANTSCommand,self)._run_interface(runtime) diff --git a/nipype/interfaces/ants/normalize.py b/nipype/interfaces/ants/normalize.py index 31be0a8c12..ae23d0a244 100644 --- a/nipype/interfaces/ants/normalize.py +++ b/nipype/interfaces/ants/normalize.py @@ -28,6 +28,7 @@ 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, @@ -80,9 +81,12 @@ class BuildTemplateOutputSpec(TraitedSpec): 'and warped image (deformed)') -class BuildTemplate(CommandLine): +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 + + Note:: + This can take a VERY long time to complete + Examples -------- @@ -170,7 +174,7 @@ class WarpImageMultiTransformOutputSpec(TraitedSpec): output_images = traits.Either(traits.List(File(exists=True)), File(exists=True)) -class WarpImageMultiTransform(CommandLine): +class WarpImageMultiTransform(ANTSCommand): """Uses the ANTS command WarpImageMultiTransform to warp an image (moving image) from one space to another (fixed/template space) Examples @@ -261,9 +265,8 @@ class AntsIntroductionOutputSpec(TraitedSpec): input_file = File(exists=True, desc='input image (prefix_repaired.nii)') output_file = File(exists=True, desc='output image (prefix_deformed.nii)') -class GenWarpFields(CommandLine): - """Uses the ANTS command antsIntroduction to generate warp and inverse warp fields that transform structural data - from anatomical images of a subject to the input template space. +class GenWarpFields(ANTSCommand): + """Uses ANTS to generate matrices to warp data from one space to another. Examples -------- From 019c767d1e5e13de0a9c0af262e256511f49e54a Mon Sep 17 00:00:00 2001 From: John Salvatore Date: Sat, 3 Mar 2012 12:31:01 -0500 Subject: [PATCH 5/6] changed env update to __init__() --- nipype/interfaces/ants/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nipype/interfaces/ants/base.py b/nipype/interfaces/ants/base.py index 5d2c90c529..c55ab4f59a 100644 --- a/nipype/interfaces/ants/base.py +++ b/nipype/interfaces/ants/base.py @@ -20,6 +20,6 @@ logger = logging.getLogger('iflogger') class ANTSCommand(CommandLine): - def _run_interface(self, runtime): + def __init__(self, **inputs): self.inputs.environ['ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS']='1' - return super(ANTSCommand,self)._run_interface(runtime) + return super(ANTSCommand, self).__init__(**inputs) From 854d8ae14795f17bcdd5129604c0b7eaa072f8df Mon Sep 17 00:00:00 2001 From: John Salvatore Date: Sat, 3 Mar 2012 12:47:53 -0500 Subject: [PATCH 6/6] reformatted note --- nipype/interfaces/ants/normalize.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nipype/interfaces/ants/normalize.py b/nipype/interfaces/ants/normalize.py index ae23d0a244..3dc9b59831 100644 --- a/nipype/interfaces/ants/normalize.py +++ b/nipype/interfaces/ants/normalize.py @@ -84,8 +84,8 @@ class BuildTemplateOutputSpec(TraitedSpec): 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 + .. note:: + This can take a VERY long time to complete Examples --------