@@ -570,3 +570,87 @@ def _list_outputs(self):
570570 'subjectToTemplateLogJacobian.'  + 
571571 self .inputs .image_suffix )
572572 return  outputs 
573+ 
574+ class  JointFusionInputSpec (ANTSCommandInputSpec ):
575+  dimension  =  traits .Enum (3 , 2 , 4 , argstr = '%d' , position = 0 , usedefault = True , mandatory = True ,
576+  desc = 'image dimension (2, 3, or 4)' )
577+  modalities  =  traits .Int (argstr = '%d' , position = 1 , mandatory = True , desc = 'Number of modalities or features' )
578+  warped_intensity_images  =  InputMultiPath (File (exists = True ), argstr = "-g %s..." , mandatory = True , desc = 'Warped atlas images' )
579+  target_image  =  InputMultiPath (File (exists = True ), argstr = '-tg %s...' , mandatory = True , desc = 'Target image(s)' )
580+  warped_label_images  =  InputMultiPath (File (exists = True ), argstr = "-l %s..." , mandatory = True , desc = 'Warped atlas segmentations' )
581+  method  =  traits .Str (default = 'Joint' , argstr = '-m %s' , usedefault = True , desc = 'Select voting method. Options: Joint (Joint Label Fusion). May be followed by optional parameters in brackets, e.g., -m Joint[0.1,2]' )
582+  alpha  =  traits .Float (default = 0.1 , usedefault = True , requires = ['method' ], desc = 'Regularization term added to matrix Mx for inverse' )
583+  beta  =  traits .Int (default = 2 , usedefault = True , requires = ['method' ], desc = 'Exponent for mapping intensity difference to joint error' )
584+  output_label_image  =  File (argstr = '%s' , mandatory = True , position = - 1 , desc = 'Output fusion label map image' )
585+  patch_radius  =  traits .ListInt (minlen = 3 , maxlen = 3 , argstr = '-rp %s' , desc = 'Patch radius for similarity measures, scalar or vector. Default: 2x2x2' )
586+  search_radius  =  traits .ListInt (minlen = 3 , maxlen = 3 , argstr = '-rs %s' , desc = 'Local search radius. Default: 3x3x3' )
587+  exclusion_region  =  File (exists = True , argstr = '-x %s' , desc = 'Specify an exclusion region for the given label.' )
588+  output_posteriors_name_template  =  traits .Str ('POSTERIOR_%02d.nii.gz' , argstr = '-p %s' ,
589+  desc = "Save the posterior maps (probability that each voxel belongs to each "  + \
590+  "label) as images. The number of images saved equals the number of labels. "  + \
591+  "The filename pattern must be in C printf format, e.g. posterior%04d.nii.gz" )
592+  output_voting_weights_name_template  =  traits .Str ('WEIGHTED_%04d.nii.gz' , argstr = '-w %s' , desc = "Save the voting weights as "  + \
593+  "images. The number of images saved equals the number of atlases. The "  + \
594+  "filename pattern must be in C printf format, e.g. weight%04d.nii.gz" )
595+  atlas_group_id  =  traits .ListInt (argstr = '-gp %d...' , desc = 'Assign a group ID for each atlas' )
596+  atlas_group_weights  =  traits .ListInt (argstr = '-gpw %d...' , desc = 'Assign the voting weights to each atlas group' )
597+ 
598+ 
599+ class  JointFusionOutputSpec (TraitedSpec ):
600+  output_label_image  =  File (exists = True )
601+  # TODO: optional outputs - output_posteriors, output_voting_weights 
602+ 
603+ 
604+ class  JointFusion (ANTSCommand ):
605+  """ 
606+  Examples 
607+  -------- 
608+ 
609+  >>> from nipype.interfaces.ants import JointFusion 
610+  >>> at = JointFusion() 
611+  >>> at.inputs.dimension = 3 
612+  >>> at.inputs.modalities = 1 
613+  >>> at.inputs.method = 'Joint[0.1,2]' 
614+  >>> at.inputs.output_label_image ='fusion_labelimage_output.nii' 
615+  >>> at.inputs.warped_intensity_images = ['im1.nii', 
616+  ... 'im2.nii'] 
617+  >>> at.inputs.warped_label_images = ['segmentation0.nii.gz', 
618+  ... 'segmentation1.nii.gz'] 
619+  >>> at.inputs.target_image = 'T1.nii' 
620+  >>> at.inputs.patch_radius = [3,2,1] 
621+  >>> at.inputs.search_radius = [1,2,3] 
622+  >>> at.cmdline 
623+  'jointfusion 3 1 -m Joint[0.1,2] -rp 3x2x1 -rs 1x2x3 -tg T1.nii -g im1.nii -g im2.nii -l segmentation0.nii.gz -l segmentation1.nii.gz fusion_labelimage_output.nii' 
624+ 
625+  Alternately, you can specify the voting method and parameters more 'Pythonically': 
626+ 
627+  >>> at.inputs.method = 'Joint' 
628+  >>> at.inputs.alpha = 0.5 
629+  >>> at.inputs.beta = 1 
630+  >>> at.cmdline 
631+  'jointfusion 3 1 -m Joint[0.5,1] -rp 3x2x1 -rs 1x2x3 -tg T1.nii -g im1.nii -g im2.nii -l segmentation0.nii.gz -l segmentation1.nii.gz fusion_labelimage_output.nii' 
632+  """ 
633+  input_spec  =  JointFusionInputSpec 
634+  output_spec  =  JointFusionOutputSpec 
635+  _cmd  =  'jointfusion' 
636+ 
637+  def  _format_arg (self , opt , spec , val ):
638+  if  opt  ==  'method' :
639+  if  '['  in  val :
640+  retval  =  '-m {0}' .format (val )
641+  else :
642+  retval  =  '-m {0}[{1},{2}]' .format (self .inputs .method , self .inputs .alpha , self .inputs .beta )
643+  elif  opt  ==  'patch_radius' :
644+  retval  =  '-rp {0}' .format (self ._format_xarray (val ))
645+  elif  opt  ==  'search_radius' :
646+  retval  =  '-rs {0}' .format (self ._format_xarray (val ))
647+  else :
648+  if  opt  ==  'warped_intensity_images' :
649+  assert  len (val ) ==  len (self .inputs .warped_label_images ), "Number of intensity images and label maps must be the same" 
650+  return  super (ANTSCommand , self )._format_arg (opt , spec , val )
651+  return  retval 
652+ 
653+  def  _list_outputs (self ):
654+  outputs  =  self ._outputs ().get ()
655+  outputs ['output_label_image' ] =  os .path .abspath (self .inputs .output_label_image )
656+  return  outputs 
0 commit comments