From 2b4ad4fd9e5f078e6984ab23fd98411920fee2f2 Mon Sep 17 00:00:00 2001 From: Alexandre Manhaes Savio Date: Fri, 24 Feb 2017 15:04:47 +0100 Subject: [PATCH 1/6] add ANTs' KellyKapowski interface --- nipype/interfaces/ants/segmentation.py | 165 +++++++++++++++++++++++++ 1 file changed, 165 insertions(+) diff --git a/nipype/interfaces/ants/segmentation.py b/nipype/interfaces/ants/segmentation.py index d71ec104de..6f984984a5 100644 --- a/nipype/interfaces/ants/segmentation.py +++ b/nipype/interfaces/ants/segmentation.py @@ -12,6 +12,7 @@ from builtins import range, str import os +from ...external.due import BibTeX from ...utils.filemanip import split_filename, copyfile from ..base import TraitedSpec, File, traits, InputMultiPath, OutputMultiPath, isdefined from .base import ANTSCommand, ANTSCommandInputSpec @@ -1153,3 +1154,167 @@ def _list_outputs(self): self.inputs.out_atlas_voting_weight_name_format) return outputs + + +class KellyKapowskiInputSpec(ANTSCommandInputSpec): + dimension = traits.Enum(3, 2, argstr='--image-dimensionality %d', + usedefault=True, + desc='image dimension (2 or 3)') + + segmentation_image = File(exists=True, argstr='--segmentation-image "%s"', + mandatory=True, + desc="A segmentation image must be supplied labeling the gray and white matters.\n" + "Default values = 2 and 3, respectively.",) + + gray_matter_label = traits.Int(2, usedefault=True, + desc="The label value for the gray matter label in the segmentation_image.") + + white_matter_label = traits.Int(3, usedefault=True, + desc="The label value for the white matter label in the segmentation_image.") + + gray_matter_prob_image = File(exists=True, argstr='--gray-matter-probability-image "%s"', + desc="In addition to the segmentation image, a gray matter probability image can be\n" + "used. If no such image is supplied, one is created using the segmentation image\n" + "and a variance of 1.0 mm.") + + white_matter_prob_image = File(exists=True, argstr='--white-matter-probability-image "%s"', + desc="In addition to the segmentation image, a white matter probability image can be\n" + "used. If no such image is supplied, one is created using the segmentation image\n" + "and a variance of 1.0 mm.") + + convergence = traits.Str(default="[50,0.001,10]", argstr='--convergence "%s"', usedefault=True, + desc="Convergence is determined by fitting a line to the normalized energy profile of\n" + "the last N iterations (where N is specified by the window size) and determining\n" + "the slope which is then compared with the convergence threshold.",) + + thickness_prior_estimate = traits.Float(10, usedefault=True, argstr="--thickness-prior-estimate %f", + desc="Provides a prior constraint on the final thickness measurement in mm.") + + thickness_prior_image = File(exists=True, argstr='--thickness-prior-image "%s"', + desc="An image containing spatially varying prior thickness values.") + + gradient_step = traits.Float(0.025, usedefault=True, argstr="--gradient-step %f", + desc="Gradient step size for the optimization.") + + smoothing_variance = traits.Float(1.0, argstr="--smoothing-variance %f", + desc="Defines the Gaussian smoothing of the hit and total images.") + + smoothing_velocity_field = traits.Float(1.5, argstr="--smoothing-velocity-field-parameter %f", + desc="Defines the Gaussian smoothing of the velocity field (default = 1.5).\n" + "If the b-spline smoothing option is chosen, then this defines the \n" + "isotropic mesh spacing for the smoothing spline (default = 15).") + + use_bspline_smoothing = traits.Bool(argstr="--use-bspline-smoothing 1", + desc="Sets the option for B-spline smoothing of the velocity field.") + + number_integration_points = traits.Int(10, argstr="--number-of-integration-points %d", + desc="Number of compositions of the diffeomorphism per iteration.") + + max_invert_displacement_field_iters = traits.Int(20, argstr="--maximum-number-of-invert-displacement-field-iterations %d", + desc="Maximum number of iterations for estimating the invert \n" + "displacement field.") + + cortical_thickness = File(argstr='--output "%s"', genfile=True, + desc='Filename for the cortical thickness.', hash_files=False) + + warped_white_matter = File(desc='Filename for the warped white matter file.', hash_files=False) + + +class KellyKapowskiOutputSpec(TraitedSpec): + cortical_thickness = File(desc="A thickness map defined in the segmented gray matter.") + warped_white_matter = File(desc="A warped white matter image.") + + +class KellyKapowski(ANTSCommand): + """ Nipype Interface to ANTs' KellyKapowski, also known as DiReCT. + + DiReCT is a registration based estimate of cortical thickness. It was published + in S. R. Das, B. B. Avants, M. Grossman, and J. C. Gee, Registration based + cortical thickness measurement, Neuroimage 2009, 45:867--879. + + Examples + -------- + >>> from pypes.interfaces.ants import KellyKapowski + >>> kk = KellyKapowski() + >>> kk.inputs.dimension = 3 + >>> kk.inputs.segmentation_image = "anat_hc_gm_wm.nii.gz" + >>> kk.inputs.gray_matter_prob_image = "anat_hc_gm.nii.gz" + >>> kk.inputs.white_matter_prob_image = "anat_hc_wm.nii.gz" + >>> kk.inputs.convergence = "[45,0.0,10]" + >>> kk.inputs.gradient_step = 0.025 + >>> kk.inputs.smoothing_variance = 1.0 + >>> kk.inputs.smoothing_velocity_field = 1.5 + >>> #kk.inputs.use_bspline_smoothing = False + >>> kk.inputs.number_integration_points = 10 + >>> kk.inputs.thickness_prior_estimate = 10 + >>> kk.cmdline # doctest: +ALLOW_UNICODE + 'KellyKapowski --convergence "[45,0.0,10]" + --output "[anat_hc_gm_wm_cortical_thickness.nii.gz, anat_hc_gm_wm_warped_white_matter.nii.gz]" + --image-dimensionality 3 --gradient-step 0.025000 --gray-matter-probability-image "anat_hc_gm.nii.gz" + --number-of-integration-points 10 --segmentation-image "[anat_hc_gm_wm.nii.gz,2,3]" --smoothing-variance 1.000000 + --smoothing-velocity-field-parameter 1.500000 --thickness-prior-estimate 10.000000 + --white-matter-probability-image "anat_hc_wm.nii.gz"' + """ + _cmd = "KellyKapowski" + input_spec = KellyKapowskiInputSpec + output_spec = KellyKapowskiOutputSpec + + references_ = [{'entry': BibTeX("@book{Das2009867," + "author={Sandhitsu R. Das and Brian B. Avants and Murray Grossman and James C. Gee}," + "title={Registration based cortical thickness measurement.}," + "journal={NeuroImage}," + "volume={45}," + "number={37}," + "pages={867--879}," + "year={2009}," + "issn={1053-8119}," + "url={http://www.sciencedirect.com/science/article/pii/S1053811908012780}," + "doi={http://dx.doi.org/10.1016/j.neuroimage.2008.12.016}" + "}"), + 'description': 'The details on the implementation of DiReCT.', + 'tags': ['implementation'], + }] + + def _parse_inputs(self, skip=None): + if skip is None: + skip = [] + skip += ['warped_white_matter', 'gray_matter_label', 'white_matter_label'] + return super(KellyKapowski, self)._parse_inputs(skip=skip) + + def _list_outputs(self): + outputs = self._outputs().get() + outputs['cortical_thickness'] = os.path.abspath(self._gen_filename('cortical_thickness')) + outputs['warped_white_matter'] = os.path.abspath(self._gen_filename('warped_white_matter')) + return outputs + + def _gen_filename(self, name): + if name == 'cortical_thickness': + output = self.inputs.cortical_thickness + if not isdefined(output): + _, name, ext = split_filename(self.inputs.segmentation_image) + output = name + '_cortical_thickness' + ext + return output + + if name == 'warped_white_matter': + output = self.inputs.warped_white_matter + if not isdefined(output): + _, name, ext = split_filename(self.inputs.segmentation_image) + output = name + '_warped_white_matter' + ext + return output + + return None + + def _format_arg(self, opt, spec, val): + if opt == "segmentation_image": + newval = '[{0},{1},{2}]'.format(self.inputs.segmentation_image, + self.inputs.gray_matter_label, + self.inputs.white_matter_label) + return spec.argstr % newval + + if opt == "cortical_thickness": + ct = self._gen_filename("cortical_thickness") + wm = self._gen_filename("warped_white_matter") + newval = '[{}, {}]'.format(ct, wm) + return spec.argstr % newval + + return super(KellyKapowski, self)._format_arg(opt, spec, val) From 56d89f6e53164c71466a716167fa4e28245289d7 Mon Sep 17 00:00:00 2001 From: Alexandre Manhaes Savio Date: Fri, 24 Feb 2017 15:52:07 +0100 Subject: [PATCH 2/6] fix example in KellyKapowski --- nipype/interfaces/ants/segmentation.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/nipype/interfaces/ants/segmentation.py b/nipype/interfaces/ants/segmentation.py index 6f984984a5..8741d1ddac 100644 --- a/nipype/interfaces/ants/segmentation.py +++ b/nipype/interfaces/ants/segmentation.py @@ -1157,12 +1157,10 @@ def _list_outputs(self): class KellyKapowskiInputSpec(ANTSCommandInputSpec): - dimension = traits.Enum(3, 2, argstr='--image-dimensionality %d', - usedefault=True, + dimension = traits.Enum(3, 2, argstr='--image-dimensionality %d', usedefault=True, desc='image dimension (2 or 3)') - segmentation_image = File(exists=True, argstr='--segmentation-image "%s"', - mandatory=True, + segmentation_image = File(exists=True, argstr='--segmentation-image "%s"', mandatory=True, desc="A segmentation image must be supplied labeling the gray and white matters.\n" "Default values = 2 and 3, respectively.",) @@ -1234,7 +1232,7 @@ class KellyKapowski(ANTSCommand): Examples -------- - >>> from pypes.interfaces.ants import KellyKapowski + >>> from nipype.interfaces.ants.segmentation import KellyKapowski >>> kk = KellyKapowski() >>> kk.inputs.dimension = 3 >>> kk.inputs.segmentation_image = "anat_hc_gm_wm.nii.gz" From 786b209bf9c0fc981142b743506e2dc3fda036ee Mon Sep 17 00:00:00 2001 From: Alexandre Manhaes Savio Date: Fri, 24 Feb 2017 16:33:43 +0100 Subject: [PATCH 3/6] fix example in KellyKapowski --- nipype/interfaces/ants/segmentation.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/nipype/interfaces/ants/segmentation.py b/nipype/interfaces/ants/segmentation.py index 8741d1ddac..fbb8fdd5d4 100644 --- a/nipype/interfaces/ants/segmentation.py +++ b/nipype/interfaces/ants/segmentation.py @@ -1235,9 +1235,7 @@ class KellyKapowski(ANTSCommand): >>> from nipype.interfaces.ants.segmentation import KellyKapowski >>> kk = KellyKapowski() >>> kk.inputs.dimension = 3 - >>> kk.inputs.segmentation_image = "anat_hc_gm_wm.nii.gz" - >>> kk.inputs.gray_matter_prob_image = "anat_hc_gm.nii.gz" - >>> kk.inputs.white_matter_prob_image = "anat_hc_wm.nii.gz" + >>> kk.inputs.segmentation_image = "segmentation0.nii.gz" >>> kk.inputs.convergence = "[45,0.0,10]" >>> kk.inputs.gradient_step = 0.025 >>> kk.inputs.smoothing_variance = 1.0 @@ -1246,12 +1244,15 @@ class KellyKapowski(ANTSCommand): >>> kk.inputs.number_integration_points = 10 >>> kk.inputs.thickness_prior_estimate = 10 >>> kk.cmdline # doctest: +ALLOW_UNICODE - 'KellyKapowski --convergence "[45,0.0,10]" - --output "[anat_hc_gm_wm_cortical_thickness.nii.gz, anat_hc_gm_wm_warped_white_matter.nii.gz]" - --image-dimensionality 3 --gradient-step 0.025000 --gray-matter-probability-image "anat_hc_gm.nii.gz" - --number-of-integration-points 10 --segmentation-image "[anat_hc_gm_wm.nii.gz,2,3]" --smoothing-variance 1.000000 - --smoothing-velocity-field-parameter 1.500000 --thickness-prior-estimate 10.000000 - --white-matter-probability-image "anat_hc_wm.nii.gz"' + "KellyKapowski --convergence "[45,0.0,10]" \ +--output "[segmentation0_cortical_thickness.nii.gz,segmentation0_warped_white_matter.nii.gz]" \ +--image-dimensionality 3 --gradient-step 0.025000 \ +--number-of-integration-points 10 \ +--segmentation-image "[segmentation0.nii.gz,2,3]" \ +--smoothing-variance 1.000000 \ +--smoothing-velocity-field-parameter 1.500000 \ +--thickness-prior-estimate 10.000000" + """ _cmd = "KellyKapowski" input_spec = KellyKapowskiInputSpec @@ -1312,7 +1313,7 @@ def _format_arg(self, opt, spec, val): if opt == "cortical_thickness": ct = self._gen_filename("cortical_thickness") wm = self._gen_filename("warped_white_matter") - newval = '[{}, {}]'.format(ct, wm) + newval = '[{},{}]'.format(ct, wm) return spec.argstr % newval return super(KellyKapowski, self)._format_arg(opt, spec, val) From 4ddbe142aa3e384800ce3b130da81d4f46333f0c Mon Sep 17 00:00:00 2001 From: Alexandre Manhaes Savio Date: Wed, 1 Mar 2017 15:44:15 +0100 Subject: [PATCH 4/6] change output listing method for kellykapowski --- nipype/interfaces/ants/segmentation.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/nipype/interfaces/ants/segmentation.py b/nipype/interfaces/ants/segmentation.py index fbb8fdd5d4..ecb275880c 100644 --- a/nipype/interfaces/ants/segmentation.py +++ b/nipype/interfaces/ants/segmentation.py @@ -1212,10 +1212,13 @@ class KellyKapowskiInputSpec(ANTSCommandInputSpec): desc="Maximum number of iterations for estimating the invert \n" "displacement field.") - cortical_thickness = File(argstr='--output "%s"', genfile=True, + cortical_thickness = File(argstr='--output "%s"', genfile=True, keep_extension=True, + name_source=["segmentation_image"], name_template='%s_cortical_thickness', desc='Filename for the cortical thickness.', hash_files=False) - warped_white_matter = File(desc='Filename for the warped white matter file.', hash_files=False) + warped_white_matter = File(name_source=["segmentation_image"], keep_extension=True, + name_template='%s_warped_white_matter', + desc='Filename for the warped white matter file.', hash_files=False) class KellyKapowskiOutputSpec(TraitedSpec): @@ -1244,7 +1247,7 @@ class KellyKapowski(ANTSCommand): >>> kk.inputs.number_integration_points = 10 >>> kk.inputs.thickness_prior_estimate = 10 >>> kk.cmdline # doctest: +ALLOW_UNICODE - "KellyKapowski --convergence "[45,0.0,10]" \ + u"KellyKapowski --convergence "[45,0.0,10]" \ --output "[segmentation0_cortical_thickness.nii.gz,segmentation0_warped_white_matter.nii.gz]" \ --image-dimensionality 3 --gradient-step 0.025000 \ --number-of-integration-points 10 \ @@ -1280,12 +1283,6 @@ def _parse_inputs(self, skip=None): skip += ['warped_white_matter', 'gray_matter_label', 'white_matter_label'] return super(KellyKapowski, self)._parse_inputs(skip=skip) - def _list_outputs(self): - outputs = self._outputs().get() - outputs['cortical_thickness'] = os.path.abspath(self._gen_filename('cortical_thickness')) - outputs['warped_white_matter'] = os.path.abspath(self._gen_filename('warped_white_matter')) - return outputs - def _gen_filename(self, name): if name == 'cortical_thickness': output = self.inputs.cortical_thickness From 615d88a78100df2767b631ebccaa71b01f991395 Mon Sep 17 00:00:00 2001 From: Alexandre Manhaes Savio Date: Thu, 2 Mar 2017 11:14:01 +0100 Subject: [PATCH 5/6] fix KellyKapowski doc example output --- nipype/interfaces/ants/segmentation.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/nipype/interfaces/ants/segmentation.py b/nipype/interfaces/ants/segmentation.py index ecb275880c..cc8bce3264 100644 --- a/nipype/interfaces/ants/segmentation.py +++ b/nipype/interfaces/ants/segmentation.py @@ -1247,14 +1247,11 @@ class KellyKapowski(ANTSCommand): >>> kk.inputs.number_integration_points = 10 >>> kk.inputs.thickness_prior_estimate = 10 >>> kk.cmdline # doctest: +ALLOW_UNICODE - u"KellyKapowski --convergence "[45,0.0,10]" \ ---output "[segmentation0_cortical_thickness.nii.gz,segmentation0_warped_white_matter.nii.gz]" \ ---image-dimensionality 3 --gradient-step 0.025000 \ ---number-of-integration-points 10 \ ---segmentation-image "[segmentation0.nii.gz,2,3]" \ ---smoothing-variance 1.000000 \ ---smoothing-velocity-field-parameter 1.500000 \ ---thickness-prior-estimate 10.000000" + u'KellyKapowski --convergence "[45,0.0,10]" \ +--output "[segmentation0_cortical_thickness.nii.gz,segmentation0_warped_white_matter.nii.gz]" \ +--image-dimensionality 3 --gradient-step 0.025000 --number-of-integration-points 10 \ +--segmentation-image "[segmentation0.nii.gz,2,3]" --smoothing-variance 1.000000 \ +--smoothing-velocity-field-parameter 1.500000 --thickness-prior-estimate 10.000000' """ _cmd = "KellyKapowski" From ecbea3dd284703030e25aa7292db601afd49ea02 Mon Sep 17 00:00:00 2001 From: Alexandre Manhaes Savio Date: Fri, 3 Mar 2017 15:44:30 +0100 Subject: [PATCH 6/6] fix parameter config in KellyKapowski --- nipype/interfaces/ants/segmentation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nipype/interfaces/ants/segmentation.py b/nipype/interfaces/ants/segmentation.py index cc8bce3264..4e8b708a13 100644 --- a/nipype/interfaces/ants/segmentation.py +++ b/nipype/interfaces/ants/segmentation.py @@ -1212,7 +1212,7 @@ class KellyKapowskiInputSpec(ANTSCommandInputSpec): desc="Maximum number of iterations for estimating the invert \n" "displacement field.") - cortical_thickness = File(argstr='--output "%s"', genfile=True, keep_extension=True, + cortical_thickness = File(argstr='--output "%s"', keep_extension=True, name_source=["segmentation_image"], name_template='%s_cortical_thickness', desc='Filename for the cortical thickness.', hash_files=False)