Skip to content

Commit 5215480

Browse files
committed
Merge pull request #902 from armaneshaghi/master
antsCorticalThickness.sh interface with example data
2 parents f626d94 + 4e6561f commit 5215480

9 files changed

+217
-0
lines changed

nipype/interfaces/ants/segmentation.py

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,3 +334,220 @@ def _list_outputs(self):
334334
if self.inputs.save_bias or isdefined(self.inputs.bias_image):
335335
outputs['bias_image'] = os.path.abspath(self._gen_filename('bias_image'))
336336
return outputs
337+
338+
class antsCorticalThicknessInputSpec(ANTSCommandInputSpec):
339+
dimension=traits.Enum(3, 2, argstr= '-d %d', usedefault=True,
340+
desc='image dimension (2 or 3)')
341+
anatomical_image=File(exists=True,
342+
argstr='-a %s',
343+
desc=('Structural *intensity* image, typically T1.'
344+
'If more than one anatomical image is specified,'
345+
'subsequently specified images are used during the'
346+
'segmentation process. However, only the first'
347+
'image is used in the registration of priors.'
348+
'Our suggestion would be to specify the T1'
349+
'as the first image.'),
350+
mandatory=True)
351+
brain_template=File(exists=True,
352+
argstr='-e %s',
353+
desc=('Anatomical *intensity* template (possibly created using a'
354+
'population data set with buildtemplateparallel.sh in ANTs).'
355+
'This template is *not* skull-stripped.'),
356+
mandatory=True)
357+
brain_probability_mask=File(exists=True,
358+
argstr='-m %s', desc='brain probability mask in template space',
359+
copyfile=False, mandatory=True)
360+
segmentation_priors = InputMultiPath(File(exists=True),
361+
argstr='-p %s', mandatory=True)
362+
out_prefix = traits.Str('antsCT_', argstr='-o %s', usedefault=True,
363+
desc=('Prefix that is prepended to all output'
364+
' files (default = antsCT_)'))
365+
image_suffix=traits.Str('nii.gz', desc=('any of standard ITK formats,'
366+
' nii.gz is default'), argstr='-s %s', usedefault=True)
367+
t1_registration_template = File(exists=True,
368+
desc = ('Anatomical *intensity* template'
369+
'(assumed to be skull-stripped). A common'
370+
'case would be where this would be the same'
371+
'template as specified in the -e option which'
372+
'is not skull stripped.'),
373+
argstr='-t %s',
374+
mandatory=True)
375+
extraction_registration_mask=File(exists=True, argstr='-f %s',
376+
desc=('Mask (defined in the template space) used during'
377+
' registration for brain extraction.'))
378+
keep_temporary_files=traits.Int(argstr='-k %d',
379+
desc='Keep brain extraction/segmentation warps, etc (default = 0).')
380+
max_iterations=traits.Int(argstr='-i %d',
381+
desc=('ANTS registration max iterations'
382+
'(default = 100x100x70x20)'))
383+
prior_segmentation_weight=traits.Float(argstr='-w %f',
384+
desc=('Atropos spatial prior *probability* weight for'
385+
'the segmentation'))
386+
segmentation_iterations=traits.Int(argstr='-n %d',
387+
desc=('N4 -> Atropos -> N4 iterations during segmentation'
388+
'(default = 3)'))
389+
posterior_formulation=traits.Str(argstr='-b %s',
390+
desc=('Atropos posterior formulation and whether or not'
391+
'to use mixture model proportions.'
392+
'''e.g 'Socrates[1]' (default) or 'Aristotle[1]'.'''
393+
'Choose the latter if you'
394+
'want use the distance priors (see also the -l option'
395+
'for label propagation control).'))
396+
use_floatingpoint_precision=traits.Enum(0, 1, argstr='-j %d',
397+
desc='Use floating point precision in registrations (default = 0)')
398+
use_random_seeding=traits.Enum(0, 1, argstr='-u %d',
399+
desc=('Use random number generated from system clock in Atropos'
400+
'(default = 1)'))
401+
b_spline_smoothing=traits.Bool(argstr='-v',
402+
desc=('Use B-spline SyN for registrations and B-spline'
403+
'exponential mapping in DiReCT.'))
404+
cortical_label_image=File(exists=True,
405+
desc='Cortical ROI labels to use as a prior for ATITH.')
406+
label_propagation=traits.Str(argstr='-l %s',
407+
desc=('Incorporate a distance prior one the posterior formulation. Should be'
408+
'''of the form 'label[lambda,boundaryProbability]' where label'''
409+
'is a value of 1,2,3,... denoting label ID. The label'
410+
'probability for anything outside the current label'
411+
' = boundaryProbability * exp( -lambda * distanceFromBoundary )'
412+
'Intuitively, smaller lambda values will increase the spatial capture'
413+
'range of the distance prior. To apply to all label values, simply omit'
414+
'specifying the label, i.e. -l [lambda,boundaryProbability].'))
415+
quick_registration=traits.Bool(argstr='-q 1',
416+
desc=('If = 1, use antsRegistrationSyNQuick.sh as the basis for registration'
417+
'during brain extraction, brain segmentation, and'
418+
'(optional) normalization to a template.'
419+
'Otherwise use antsRegistrationSyN.sh (default = 0).'))
420+
debug=traits.Bool(argstr='-z 1',
421+
desc=('If > 0, runs a faster version of the script.'
422+
'Only for testing. Implies -u 0.'
423+
'Requires single thread computation for complete reproducibility.'))
424+
425+
class antsCorticalThicknessoutputSpec(TraitedSpec):
426+
BrainExtractionMask=File(exists=True,
427+
desc= 'brain extraction mask')
428+
BrainSegmentation=File(exists=True,
429+
desc='brain segmentaion image')
430+
BrainSegmentationN4=File(exists=True,
431+
desc='N4 corrected image')
432+
BrainSegmentationPosteriorsCSF=File(exists=True,
433+
desc='CSF posterior probability image')
434+
BrainSegmentationPosteriorsGM=File(exists=True,
435+
desc='GM posterior probability image')
436+
BrainSegmentationPosteriorsWM=File(exists=True,
437+
desc='WM posterior probability image')
438+
BrainSegmentationPosteriorsDGM=File(exists=True,
439+
desc='DGM posterior probability image')
440+
CorticalThickness=File(exists=True,
441+
desc='cortical thickness file')
442+
TemplateToSubject1GenericAffine=File(exists=True,
443+
desc='Template to subject affine')
444+
TemplateToSubject0Warp=File(exists=True,
445+
desc='Template to subject warp')
446+
SubjectToTemplate1Warp=File(exists=True,
447+
desc='Template to subject inverse warp')
448+
SubjectToTemplate0GenericAffine=File(exists=True,
449+
desc='Template to subject inverse affine')
450+
TemplateToSubjectLogJacobian=File(exists=True,
451+
desc='Template to subject log jacobian')
452+
453+
class antsCorticalThickness(ANTSCommand):
454+
"""
455+
Examples
456+
--------
457+
>>> from nipype.interfaces.ants.segmentation import antsCorticalThickness
458+
>>> corticalthickness = antsCorticalThickness()
459+
>>> corticalthickness.inputs.dimension = 3
460+
>>> corticalthickness.inputs.anatomical_image ='T1.nii.gz'
461+
>>> corticalthickness.inputs.brain_template = 'study_template.nii.gz'
462+
>>> corticalthickness.inputs.brain_probability_mask ='ProbabilityMaskOfStudyTemplate.nii.gz'
463+
>>> corticalthickness.inputs.segmentation_priors = ['BrainSegmentationPrior01.nii.gz', 'BrainSegmentationPrior02.nii.gz', 'BrainSegmentationPrior03.nii.gz', 'BrainSegmentationPrior04.nii.gz']
464+
>>> corticalthickness.inputs.t1_registration_template = 'brain_study_template.nii.gz'
465+
>>> corticalthickness.cmdline
466+
'antsCorticalThickness.sh -a T1.nii.gz -m ProbabilityMaskOfStudyTemplate.nii.gz -e study_template.nii.gz -d 3 -s nii.gz -o antsCT_ -p BrainSegmentationPrior%02d.nii.gz -t brain_study_template.nii.gz'
467+
"""
468+
469+
input_spec = antsCorticalThicknessInputSpec
470+
output_spec = antsCorticalThicknessoutputSpec
471+
_cmd = 'antsCorticalThickness.sh'
472+
def _format_arg(self, opt, spec, val):
473+
if opt == 'anatomical_image':
474+
retval = '-a %s' %(val)
475+
return retval
476+
if opt == 'brain_template':
477+
retval = '-e %s' %(val)
478+
return retval
479+
if opt == 'brain_probability_mask':
480+
retval = '-m %s' %(val)
481+
return retval
482+
if opt == 'out_prefix':
483+
retval = '-o %s' %(val)
484+
return retval
485+
if opt == 't1_registration_template':
486+
retval = '-t %s' %(val)
487+
return retval
488+
if opt == 'segmentation_priors':
489+
_, _, ext = split_filename(self.inputs.segmentation_priors[0])
490+
retval = "-p BrainSegmentationPrior%02d"
491+
retval += ext
492+
return retval
493+
return super(ANTSCommand, self)._format_arg(opt, spec, val)
494+
495+
def _run_interface(self, runtime):
496+
priors_directory = os.path.join(os.getcwd(), "priors")
497+
if not os.path.exists(priors_directory):
498+
os.makedirs(priors_directory)
499+
_, _, ext = split_filename(self.inputs.segmentation_priors[0])
500+
for i, f in enumerate(self.inputs.segmentation_priors):
501+
target = os.path.join(priors_directory,
502+
'BrainSegmentationPrior%02d' % (i + 1) + ext)
503+
if not (os.path.exists(target) and os.path.realpath(target) == os.path.abspath(f)):
504+
copyfile(os.path.abspath(f), os.path.join(priors_directory,
505+
'BrainSegmentationPrior%02d' % (i + 1) + ext))
506+
runtime = super(antsCorticalThickness, self)._run_interface(runtime)
507+
return runtime
508+
509+
def _list_outputs(self):
510+
outputs = self._outputs().get()
511+
outputs['BrainExtractionMask'] = os.path.join(os.getcwd(),
512+
self.inputs.out_prefix +
513+
'BrainExtractionMask.'+
514+
self.inputs.image_suffix)
515+
outputs['BrainSegmentation'] = os.path.join(os.getcwd(),
516+
self.inputs.out_prefix +
517+
'BrainSegmentation.' +
518+
self.inputs.image_suffix)
519+
outputs['BrainSegmentationN4'] = os.path.join(os.getcwd(),
520+
self.inputs.out_prefix +
521+
'BrainSegmentation0N4.' +
522+
self.inputs.image_suffix)
523+
outputs['BrainSegmentationPosteriorsCSF'] = os.path.join(os.getcwd(),
524+
self.inputs.out_prefix +
525+
'BrainSegmentationPosteriors01.' +
526+
self.inputs.image_suffix)
527+
outputs['BrainSegmentationPosteriorsGM'] = os.path.join(os.getcwd(),
528+
'BrainSegmentationPosteriors02.' +
529+
self.inputs.image_suffix)
530+
outputs['BrainSegmentationPosteriorsWM'] = os.path.join(os.getcwd(),
531+
'BrainSegmentationPosteriors03.' +
532+
self.inputs.image_suffix)
533+
outputs['BrainSegmentationPosteriorsDGM'] = os.path.join(os.getcwd(),
534+
'BrainSegmentationPosteriors04.' +
535+
self.inputs.image_suffix)
536+
outputs['CorticalThickness'] = os.path.join(os.getcwd(),
537+
self.inputs.out_prefix + 'CorticalThickness.' +
538+
self.inputs.image_suffix)
539+
outputs['TemplateToSubject1GenericAffine'] = os.path.join(
540+
os.getcwd(),
541+
'TemplateToSubject1GenericAffine.mat')
542+
outputs['TemplateToSubject0Warp'] = os.path.join(os.getcwd(),
543+
self.inputs.out_prefix + 'TemplateToSubject0Warp.'+
544+
self.inputs.image_suffix)
545+
outputs['SubjectToTemplate1Warp'] = os.path.join(os.getcwd(),
546+
self.inputs.out_prefix + 'SubjectToTemplate1Warp' +
547+
self.inputs.image_suffix)
548+
outputs['SubjectToTemplate0GenericAffine'] = os.path.join(os.getcwd(),
549+
self.inputs.out_prefix + 'SubjectToTemplate0GenericAffine.mat')
550+
outputs['TemplateToSubjectLogJacobian'] = os.path.join(os.getcwd(),
551+
self.inputs.out_prefix + 'subjectToTemplateLogJacobian.'+
552+
self.inputs.image_suffix)
553+
return outputs

nipype/testing/data/BrainSegmentationPrior01.nii.gz

Whitespace-only changes.

nipype/testing/data/BrainSegmentationPrior02.nii.gz

Whitespace-only changes.

nipype/testing/data/BrainSegmentationPrior03.nii.gz

Whitespace-only changes.

nipype/testing/data/BrainSegmentationPrior04.nii.gz

Whitespace-only changes.

nipype/testing/data/ProbabilityMaskOfStudyTemplate.nii.gz

Whitespace-only changes.

nipype/testing/data/T1.nii.gz

Whitespace-only changes.

nipype/testing/data/brain_study_template.nii.gz

Whitespace-only changes.

nipype/testing/data/study_template.nii.gz

Whitespace-only changes.

0 commit comments

Comments
 (0)