@@ -869,3 +869,201 @@ def _format_arg(self, name, trait_spec, value):
869869
870870 return super (DenoiseImage ,
871871 self )._format_arg (name , trait_spec , value )
872+
873+
874+ class AntsJointFusionInputSpec (ANTSCommandInputSpec ):
875+ dimension = traits .Enum (3 , 2 , 4 , argstr = '-d %d' , usedefault = False ,
876+ desc = 'This option forces the image to be treated '
877+ 'as a specified-dimensional image. If not '
878+ 'specified, the program tries to infer the '
879+ 'dimensionality from the input image.' )
880+ target_image = traits .List (InputMultiPath (File (exists = True )), argstr = '-t %s' ,
881+ mandatory = True , desc = 'The target image (or '
882+ 'multimodal target images) assumed to be '
883+ 'aligned to a common image domain.' )
884+ atlas_image = traits .List (InputMultiPath (File (exists = True )), argstr = "-g %s..." ,
885+ mandatory = True , desc = 'The atlas image (or '
886+ 'multimodal atlas images) assumed to be '
887+ 'aligned to a common image domain.' )
888+ atlas_segmentation_image = InputMultiPath (File (exists = True ), argstr = "-l %s..." ,
889+ mandatory = True , desc = 'The atlas segmentation '
890+ 'images. For performing label fusion the number '
891+ 'of specified segmentations should be identical '
892+ 'to the number of atlas image sets.' )
893+ alpha = traits .Float (default_value = 0.1 , usedefault = True , argstr = '-a %s' , desc = ('Regularization '
894+ 'term added to matrix Mx for calculating the inverse. Default = 0.1' ))
895+ beta = traits .Float (default_value = 2.0 , usedefault = True , argstr = '-b %s' , desc = ('Exponent for mapping '
896+ 'intensity difference to the joint error. Default = 2.0' ))
897+ retain_label_posterior_images = traits .Bool (False , argstr = '-r' , usedefault = True ,
898+ requires = ['atlas_segmentation_image' ],
899+ desc = ('Retain label posterior probability images. Requires '
900+ 'atlas segmentations to be specified. Default = false' ))
901+ retain_atlas_voting_images = traits .Bool (False , argstr = '-f' , usedefault = True ,
902+ desc = ('Retain atlas voting images. Default = false' ))
903+ constrain_nonnegative = traits .Bool (False , argstr = '-c' , usedefault = True ,
904+ desc = ('Constrain solution to non-negative weights.' ))
905+ patch_radius = traits .ListInt (minlen = 3 , maxlen = 3 , argstr = '-p %s' ,
906+ desc = ('Patch radius for similarity measures.'
907+ 'Default: 2x2x2' ))
908+ patch_metric = traits .Enum ('PC' , 'MSQ' , argstr = '-m %s' , usedefault = False ,
909+ desc = ('Metric to be used in determining the most similar '
910+ 'neighborhood patch. Options include Pearson\' s '
911+ 'correlation (PC) and mean squares (MSQ). Default = '
912+ 'PC (Pearson correlation).' ))
913+ search_radius = traits .List ([3 ,3 ,3 ], minlen = 1 , maxlen = 3 , argstr = '-s %s' , usedefault = True ,
914+ desc = ('Search radius for similarity measures. Default = 3x3x3. '
915+ 'One can also specify an image where the value at the '
916+ 'voxel specifies the isotropic search radius at that voxel.' ))
917+ exclusion_image_label = traits .List (traits .Str (), argstr = '-e %s' , requires = ['exclusion_image' ],
918+ desc = ('Specify a label for the exclusion region.' ))
919+ exclusion_image = traits .List (File (exists = True ),
920+ desc = ('Specify an exclusion region for the given label.' ))
921+ mask_image = File (argstr = '-x %s' , exists = True , desc = 'If a mask image '
922+ 'is specified, fusion is only performed in the mask region.' )
923+ out_label_fusion = File (argstr = "%s" , hash_files = False ,
924+ desc = 'The output label fusion image.' )
925+ out_intensity_fusion_name_format = traits .Str ('antsJointFusionIntensity_%d.nii.gz' ,
926+ argstr = "" , desc = 'Optional intensity fusion '
927+ 'image file name format.' )
928+ out_label_post_prob_name_format = traits .Str ('antsJointFusionPosterior_%d.nii.gz' ,
929+ requires = ['out_label_fusion' ,
930+ 'out_intensity_fusion_name_format' ],
931+ desc = 'Optional label posterior probability '
932+ 'image file name format.' )
933+ out_atlas_voting_weight_name_format = traits .Str ('antsJointFusionVotingWeight_%d.nii.gz' ,
934+ requires = ['out_label_fusion' ,
935+ 'out_intensity_fusion_name_format' ,
936+ 'out_label_post_prob_name_format' ],
937+ desc = 'Optional atlas voting weight image '
938+ 'file name format.' )
939+ verbose = traits .Bool (False , argstr = "-v" , desc = ('Verbose output.' ))
940+
941+
942+ class AntsJointFusionOutputSpec (TraitedSpec ):
943+ out_label_fusion = File (exists = True )
944+ out_intensity_fusion_name_format = traits .Str ()
945+ out_label_post_prob_name_format = traits .Str ()
946+ out_atlas_voting_weight_name_format = traits .Str ()
947+
948+
949+ class AntsJointFusion (ANTSCommand ):
950+ """
951+ Examples
952+ --------
953+
954+ >>> from nipype.interfaces.ants import AntsJointFusion
955+ >>> antsjointfusion = AntsJointFusion()
956+ >>> antsjointfusion.inputs.out_label_fusion = 'ants_fusion_label_output.nii'
957+ >>> antsjointfusion.inputs.atlas_image = [ ['rc1s1.nii','rc1s2.nii'] ]
958+ >>> antsjointfusion.inputs.atlas_segmentation_image = ['segmentation0.nii.gz']
959+ >>> antsjointfusion.inputs.target_image = ['im1.nii']
960+ >>> antsjointfusion.cmdline
961+ "antsJointFusion -a 0.1 -g ['rc1s1.nii', 'rc1s2.nii'] -l segmentation0.nii.gz \
962+ -b 2.0 -o ants_fusion_label_output.nii -s 3x3x3 -t ['im1.nii']"
963+
964+ >>> antsjointfusion.inputs.target_image = [ ['im1.nii', 'im2.nii'] ]
965+ >>> antsjointfusion.cmdline
966+ "antsJointFusion -a 0.1 -g ['rc1s1.nii', 'rc1s2.nii'] -l segmentation0.nii.gz \
967+ -b 2.0 -o ants_fusion_label_output.nii -s 3x3x3 -t ['im1.nii', 'im2.nii']"
968+
969+ >>> antsjointfusion.inputs.atlas_image = [ ['rc1s1.nii','rc1s2.nii'],
970+ ... ['rc2s1.nii','rc2s2.nii'] ]
971+ >>> antsjointfusion.inputs.atlas_segmentation_image = ['segmentation0.nii.gz',
972+ ... 'segmentation1.nii.gz']
973+ >>> antsjointfusion.cmdline
974+ "antsJointFusion -a 0.1 -g ['rc1s1.nii', 'rc1s2.nii'] -g ['rc2s1.nii', 'rc2s2.nii'] \
975+ -l segmentation0.nii.gz -l segmentation1.nii.gz -b 2.0 -o ants_fusion_label_output.nii \
976+ -s 3x3x3 -t ['im1.nii', 'im2.nii']"
977+
978+ >>> antsjointfusion.inputs.dimension = 3
979+ >>> antsjointfusion.inputs.alpha = 0.5
980+ >>> antsjointfusion.inputs.beta = 1.0
981+ >>> antsjointfusion.inputs.patch_radius = [3,2,1]
982+ >>> antsjointfusion.inputs.search_radius = [3]
983+ >>> antsjointfusion.cmdline
984+ "antsJointFusion -a 0.5 -g ['rc1s1.nii', 'rc1s2.nii'] -g ['rc2s1.nii', 'rc2s2.nii'] \
985+ -l segmentation0.nii.gz -l segmentation1.nii.gz -b 1.0 -d 3 -o ants_fusion_label_output.nii \
986+ -p 3x2x1 -s 3 -t ['im1.nii', 'im2.nii']"
987+
988+ >>> antsjointfusion.inputs.search_radius = ['mask.nii']
989+ >>> antsjointfusion.inputs.verbose = True
990+ >>> antsjointfusion.inputs.exclusion_image = ['roi01.nii', 'roi02.nii']
991+ >>> antsjointfusion.inputs.exclusion_image_label = ['1','2']
992+ >>> antsjointfusion.cmdline
993+ "antsJointFusion -a 0.5 -g ['rc1s1.nii', 'rc1s2.nii'] -g ['rc2s1.nii', 'rc2s2.nii'] \
994+ -l segmentation0.nii.gz -l segmentation1.nii.gz -b 1.0 -d 3 -e 1[roi01.nii] -e 2[roi02.nii] \
995+ -o ants_fusion_label_output.nii -p 3x2x1 -s mask.nii -t ['im1.nii', 'im2.nii'] -v"
996+
997+ >>> antsjointfusion.inputs.out_label_fusion = 'ants_fusion_label_output.nii'
998+ >>> antsjointfusion.inputs.out_intensity_fusion_name_format = 'ants_joint_fusion_intensity_%d.nii.gz'
999+ >>> antsjointfusion.inputs.out_label_post_prob_name_format = 'ants_joint_fusion_posterior_%d.nii.gz'
1000+ >>> antsjointfusion.inputs.out_atlas_voting_weight_name_format = 'ants_joint_fusion_voting_weight_%d.nii.gz'
1001+ >>> antsjointfusion.cmdline
1002+ "antsJointFusion -a 0.5 -g ['rc1s1.nii', 'rc1s2.nii'] -g ['rc2s1.nii', 'rc2s2.nii'] \
1003+ -l segmentation0.nii.gz -l segmentation1.nii.gz -b 1.0 -d 3 -e 1[roi01.nii] -e 2[roi02.nii] \
1004+ -o [ants_fusion_label_output.nii, ants_joint_fusion_intensity_%d.nii.gz, \
1005+ ants_joint_fusion_posterior_%d.nii.gz, ants_joint_fusion_voting_weight_%d.nii.gz] \
1006+ -p 3x2x1 -s mask.nii -t ['im1.nii', 'im2.nii'] -v"
1007+
1008+ """
1009+ input_spec = AntsJointFusionInputSpec
1010+ output_spec = AntsJointFusionOutputSpec
1011+ _cmd = 'antsJointFusion'
1012+
1013+ def _format_arg (self , opt , spec , val ):
1014+ if opt == 'exclusion_image_label' :
1015+ retval = []
1016+ for ii in range (len (self .inputs .exclusion_image_label )):
1017+ retval .append ('-e {0}[{1}]' .format (
1018+ self .inputs .exclusion_image_label [ii ],
1019+ self .inputs .exclusion_image [ii ]))
1020+ retval = ' ' .join (retval )
1021+ elif opt == 'patch_radius' :
1022+ retval = '-p {0}' .format (self ._format_xarray (val ))
1023+ elif opt == 'search_radius' :
1024+ retval = '-s {0}' .format (self ._format_xarray (val ))
1025+ elif opt == 'out_label_fusion' :
1026+ if isdefined (self .inputs .out_intensity_fusion_name_format ):
1027+ if isdefined (self .inputs .out_label_post_prob_name_format ):
1028+ if isdefined (self .inputs .out_atlas_voting_weight_name_format ):
1029+ retval = '-o [{0}, {1}, {2}, {3}]' .format (self .inputs .out_label_fusion ,
1030+ self .inputs .out_intensity_fusion_name_format ,
1031+ self .inputs .out_label_post_prob_name_format ,
1032+ self .inputs .out_atlas_voting_weight_name_format )
1033+ else :
1034+ retval = '-o [{0}, {1}, {2}]' .format (self .inputs .out_label_fusion ,
1035+ self .inputs .out_intensity_fusion_name_format ,
1036+ self .inputs .out_label_post_prob_name_format )
1037+ else :
1038+ retval = '-o [{0}, {1}]' .format (self .inputs .out_label_fusion ,
1039+ self .inputs .out_intensity_fusion_name_format )
1040+ else :
1041+ retval = '-o {0}' .format (self .inputs .out_label_fusion )
1042+ elif opt == 'out_intensity_fusion_name_format' :
1043+ retval = ''
1044+ if not isdefined (self .inputs .out_label_fusion ):
1045+ retval = '-o {0}' .format (self .inputs .out_intensity_fusion_name_format )
1046+ else :
1047+ if opt == 'atlas_segmentation_image' :
1048+ assert len (val ) == len (self .inputs .atlas_image ), "Number of specified " \
1049+ "segmentations should be identical to the number of atlas image " \
1050+ "sets {0}!={1}" .format (len (val ), len (self .inputs .atlas_image ))
1051+ return super (ANTSCommand , self )._format_arg (opt , spec , val )
1052+ return retval
1053+
1054+ def _list_outputs (self ):
1055+ outputs = self ._outputs ().get ()
1056+ if isdefined (self .inputs .out_label_fusion ):
1057+ outputs ['out_label_fusion' ] = os .path .abspath (
1058+ self .inputs .out_label_fusion )
1059+ if isdefined (self .inputs .out_intensity_fusion_name_format ):
1060+ outputs ['out_intensity_fusion_name_format' ] = os .path .abspath (
1061+ self .inputs .out_intensity_fusion_name_format )
1062+ if isdefined (self .inputs .out_label_post_prob_name_format ):
1063+ outputs ['out_label_post_prob_name_format' ] = os .path .abspath (
1064+ self .inputs .out_label_post_prob_name_format )
1065+ if isdefined (self .inputs .out_atlas_voting_weight_name_format ):
1066+ outputs ['out_atlas_voting_weight_name_format' ] = os .path .abspath (
1067+ self .inputs .out_atlas_voting_weight_name_format )
1068+
1069+ return outputs
0 commit comments