@@ -869,3 +869,201 @@ def _format_arg(self, name, trait_spec, value):
869
869
870
870
return super (DenoiseImage ,
871
871
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