@@ -1088,3 +1088,276 @@ def _list_outputs(self):
1088
1088
_ , fname = os .path .split (filename )
1089
1089
outputs ['out_files' ].append (os .path .realpath ('w%s' % fname ))
1090
1090
return outputs
1091
+
1092
+ class VBMSegmentInputSpec (SPMCommandInputSpec ):
1093
+
1094
+ in_files = InputMultiPath (
1095
+ File (exists = True ),
1096
+ desc = "A list of files to be segmented" ,
1097
+ field = 'estwrite.data' , copyfile = False , mandatory = True )
1098
+
1099
+ tissues = File (
1100
+ exists = True , field = 'estwrite.tpm' ,
1101
+ desc = 'tissue probability map' )
1102
+ gaussians_per_class = traits .Tuple (
1103
+ (2 , 2 , 2 , 3 , 4 , 2 ), * ([traits .Int ()]* 6 ),
1104
+ usedefault = True ,
1105
+ desc = 'number of gaussians for each tissue class' )
1106
+ bias_regularization = traits .Enum (
1107
+ 0.0001 ,
1108
+ (0 , 0.00001 , 0.0001 , 0.001 , 0.01 , 0.1 , 1 , 10 ),
1109
+ field = 'estwrite.opts.biasreg' , usedefault = True ,
1110
+ desc = 'no(0) - extremely heavy (10)' )
1111
+
1112
+ bias_fwhm = traits .Enum (
1113
+ 60 ,
1114
+ (30 , 40 , 50 , 60 , 70 , 80 , 90 , 100 , 110 , 120 , 130 , 'Inf' ),
1115
+ field = 'estwrite.opts.biasfwhm' ,
1116
+ usedefault = True ,
1117
+ desc = 'FWHM of Gaussian smoothness of bias' )
1118
+ sampling_distance = traits .Float (
1119
+ 3 , usedefault = True , field = 'estwrite.opts.samp' ,
1120
+ desc = 'Sampling distance on data for parameter estimation' )
1121
+ warping_regularization = traits .Float (
1122
+ 4 , usedefault = True , field = 'estwrite.opts.warpreg' ,
1123
+ desc = 'Controls balance between parameters and data' )
1124
+
1125
+ spatial_normalization = traits .Enum (
1126
+ 'high' , 'low' , usedefault = True ,)
1127
+ dartel_template = File (
1128
+ exists = True ,
1129
+ field = 'estwrite.extopts.dartelwarp.normhigh.darteltpm' )
1130
+ use_sanlm_denoising_filter = traits .Range (
1131
+ 0 , 2 , 2 , usedefault = True , field = 'estwrite.extopts.sanlm' ,
1132
+ desc = "0=No denoising, 1=denoising,2=denoising multi-threaded" )
1133
+ mrf_weighting = traits .Float (
1134
+ 0.15 , usedefault = True , field = 'estwrite.extopts.mrf' )
1135
+ cleanup_partitions = traits .Int (
1136
+ 1 , usedefault = True , field = 'estwrite.extopts.cleanup' ,
1137
+ desc = "0=None,1=light,2=thorough" )
1138
+ display_results = traits .Bool (
1139
+ True , usedefault = True , field = 'estwrite.extopts.print' )
1140
+
1141
+ gm_native = traits .Bool (
1142
+ False , usedefault = True , field = 'estwrite.output.GM.native' ,)
1143
+ gm_normalized = traits .Bool (
1144
+ False , usedefault = True , field = 'estwrite.output.GM.warped' ,)
1145
+ gm_modulated_normalized = traits .Range (
1146
+ 0 , 2 , 2 , usedefault = True , field = 'estwrite.output.GM.modulated' ,
1147
+ desc = '0=none,1=affine+non-linear(SPM8 default),2=non-linear only' )
1148
+ gm_dartel = traits .Range (
1149
+ 0 , 2 , 0 , usedefault = True , field = 'estwrite.output.GM.dartel' ,
1150
+ desc = "0=None,1=rigid(SPM8 default),2=affine" )
1151
+
1152
+ wm_native = traits .Bool (
1153
+ False , usedefault = True , field = 'estwrite.output.WM.native' ,)
1154
+ wm_normalized = traits .Bool (
1155
+ False , usedefault = True , field = 'estwrite.output.WM.warped' ,)
1156
+ wm_modulated_normalized = traits .Range (
1157
+ 0 , 2 , 2 , usedefault = True , field = 'estwrite.output.WM.modulated' ,
1158
+ desc = '0=none,1=affine+non-linear(SPM8 default),2=non-linear only' )
1159
+ wm_dartel = traits .Range (
1160
+ 0 , 2 , 0 , usedefault = True , field = 'estwrite.output.WM.dartel' ,
1161
+ desc = "0=None,1=rigid(SPM8 default),2=affine" )
1162
+
1163
+ csf_native = traits .Bool (
1164
+ False , usedefault = True , field = 'estwrite.output.CSF.native' ,)
1165
+ csf_normalized = traits .Bool (
1166
+ False , usedefault = True , field = 'estwrite.output.CSF.warped' ,)
1167
+ csf_modulated_normalized = traits .Range (
1168
+ 0 , 2 , 2 , usedefault = True , field = 'estwrite.output.CSF.modulated' ,
1169
+ desc = '0=none,1=affine+non-linear(SPM8 default),2=non-linear only' )
1170
+ csf_dartel = traits .Range (
1171
+ 0 , 2 , 0 , usedefault = True , field = 'estwrite.output.CSF.dartel' ,
1172
+ desc = "0=None,1=rigid(SPM8 default),2=affine" )
1173
+
1174
+ bias_corrected_native = traits .Bool (
1175
+ False , usedefault = True , field = 'estwrite.output.bias.native' ,)
1176
+ bias_corrected_normalized = traits .Bool (
1177
+ True , usedefault = True , field = 'estwrite.output.bias.warped' ,)
1178
+ bias_corrected_affine = traits .Bool (
1179
+ False , usedefault = True , field = 'estwrite.output.bias.affine' ,)
1180
+
1181
+ pve_label_native = traits .Bool (
1182
+ False , usedefault = True , field = 'estwrite.output.label.native' )
1183
+ pve_label_normalized = traits .Bool (
1184
+ False , usedefault = True , field = 'estwrite.output.label.warped' )
1185
+ pve_label_dartel = traits .Range (
1186
+ 0 , 2 , 0 , usedefault = True , field = 'estwrite.output.label.dartel' ,
1187
+ desc = "0=None,1=rigid(SPM8 default),2=affine" )
1188
+
1189
+ jacobian_determinant = traits .Bool (
1190
+ False , usedefault = True , field = 'estwrite.jacobian.warped' )
1191
+
1192
+ deformation_field = traits .Tuple (
1193
+ (0 , 0 ), traits .Bool , traits .Bool , usedefault = True ,
1194
+ field = 'estwrite.output.warps' ,
1195
+ desc = 'forward and inverse field' )
1196
+
1197
+ class VBMSegmentOuputSpec (TraitedSpec ):
1198
+
1199
+ native_class_images = traits .List (traits .List (File (exists = True )),
1200
+ desc = 'native space probability maps' )
1201
+ dartel_input_images = traits .List (traits .List (File (exists = True )),
1202
+ desc = 'dartel imported class images' )
1203
+ normalized_class_images = traits .List (traits .List (File (exists = True )),
1204
+ desc = 'normalized class images' )
1205
+ modulated_class_images = traits .List (traits .List (File (exists = True )),
1206
+ desc = 'modulated+normalized class images' )
1207
+ transformation_mat = OutputMultiPath (File (exists = True ),
1208
+ desc = 'Normalization transformation' )
1209
+
1210
+ bias_corrected_images = OutputMultiPath (
1211
+ File (exists = True ),
1212
+ desc = 'bias corrected images' )
1213
+ normalized_bias_corrected_images = OutputMultiPath (
1214
+ File (exists = True ),
1215
+ desc = 'bias corrected images' )
1216
+
1217
+ pve_label_native_images = OutputMultiPath (File (exists = True ))
1218
+ pve_label_normalized_images = OutputMultiPath (File (exists = True ))
1219
+ pve_label_registered_images = OutputMultiPath (File (exists = True ))
1220
+
1221
+ forward_deformation_field = OutputMultiPath (File (exists = True ))
1222
+ inverse_deformation_field = OutputMultiPath (File (exists = True ))
1223
+
1224
+ jacobian_determinant_images = OutputMultiPath (File (exists = True ))
1225
+
1226
+ class VBMSegment (SPMCommand ):
1227
+
1228
+ """Use VBM8 toolbox to separate structural images into different
1229
+ tissue classes.
1230
+
1231
+ Example
1232
+ -------
1233
+ >>> import nipype.interfaces.spm as spm
1234
+ >>> seg = spm.VBMSegment()
1235
+ >>> seg.inputs.tissues = 'TPM.nii'
1236
+ >>> seg.inputs.dartel_template = 'Template_1_IXI550_MNI152.nii'
1237
+ >>> seg.inputs.bias_corrected_native = True
1238
+ >>> seg.inputs.gm_native = True
1239
+ >>> seg.inputs.wm_native = True
1240
+ >>> seg.inputs.csf_native = True
1241
+ >>> seg.inputs.pve_label_native = True
1242
+ >>> seg.inputs.deformation_field = (True, False)
1243
+ >>> seg.run() # doctest: +SKIP
1244
+ """
1245
+
1246
+ input_spec = VBMSegmentInputSpec
1247
+ output_spec = VBMSegmentOuputSpec
1248
+
1249
+ _jobtype = 'tools'
1250
+ _jobname = 'vbm8'
1251
+
1252
+ def _list_outputs (self ):
1253
+ outputs = self ._outputs ().get ()
1254
+
1255
+ do_dartel = self .inputs .spatial_normalization
1256
+ dartel_px = ''
1257
+ if do_dartel :
1258
+ dartel_px = 'r'
1259
+
1260
+ outputs ['native_class_images' ] = [[], [], []]
1261
+ outputs ['dartel_input_images' ] = [[], [], []]
1262
+ outputs ['normalized_class_images' ] = [[], [], []]
1263
+ outputs ['modulated_class_images' ] = [[], [], []]
1264
+
1265
+ outputs ['transformation_mat' ] = []
1266
+
1267
+ outputs ['bias_corrected_images' ] = []
1268
+ outputs ['normalized_bias_corrected_images' ] = []
1269
+
1270
+ outputs ['inverse_deformation_field' ] = []
1271
+ outputs ['forward_deformation_field' ] = []
1272
+ outputs ['jacobian_determinant_images' ] = []
1273
+
1274
+ outputs ['pve_label_native_images' ] = []
1275
+ outputs ['pve_label_normalized_images' ] = []
1276
+ outputs ['pve_label_registered_images' ] = []
1277
+
1278
+ for filename in self .inputs .in_files :
1279
+ pth , base , ext = split_filename (filename )
1280
+
1281
+ outputs ['transformation_mat' ].append (
1282
+ os .path .join (pth , "%s_seg8.mat" % base ))
1283
+
1284
+ for i , tis in enumerate (['gm' , 'wm' , 'csf' ]):
1285
+ # native space
1286
+
1287
+ if getattr (self .inputs , '%s_native' % tis ):
1288
+ outputs ['native_class_images' ][i ].append (
1289
+ os .path .join (pth , "p%d%s.nii" % (i + 1 , base )))
1290
+ if getattr (self .inputs , '%s_dartel' % tis ) == 1 :
1291
+ outputs ['dartel_input_images' ][i ].append (
1292
+ os .path .join (pth , "rp%d%s.nii" % (i + 1 , base )))
1293
+ elif getattr (self .inputs , '%s_dartel' % tis ) == 2 :
1294
+ outputs ['dartel_input_images' ][i ].append (
1295
+ os .path .join (pth , "rp%d%s_affine.nii" % (i + 1 , base )))
1296
+
1297
+ # normalized space
1298
+ if getattr (self .inputs , '%s_normalized' % tis ):
1299
+ outputs ['normalized_class_images' ][i ].append (
1300
+ os .path .join (pth , "w%sp%d%s.nii" % (dartel_px , i + 1 , base )))
1301
+
1302
+ if getattr (self .inputs , '%s_modulated_normalized' % tis ) == 1 :
1303
+ outputs ['modulated_class_images' ][i ].append (os .path .join (
1304
+ pth , "mw%sp%d%s.nii" % (dartel_px , i + 1 , base )))
1305
+ elif getattr (self .inputs , '%s_modulated_normalized' % tis ) == 2 :
1306
+ outputs ['normalized_class_images' ][i ].append (os .path .join (
1307
+ pth , "m0w%sp%d%s.nii" % (dartel_px , i + 1 , base )))
1308
+
1309
+ if self .inputs .pve_label_native :
1310
+ outputs ['pve_label_native_images' ].append (
1311
+ os .path .join (pth , "p0%s.nii" % (base )))
1312
+ if self .inputs .pve_label_normalized :
1313
+ outputs ['pve_label_normalized_images' ].append (
1314
+ os .path .join (pth , "w%sp0%s.nii" % (dartel_px , base )))
1315
+ if self .inputs .pve_label_dartel == 1 :
1316
+ outputs ['pve_label_registered_images' ].append (
1317
+ os .path .join (pth , "rp0%s.nii" % (base )))
1318
+ elif self .inputs .pve_label_dartel == 2 :
1319
+ outputs ['pve_label_registered_images' ].append (
1320
+ os .path .join (pth , "rp0%s_affine.nii" % (base )))
1321
+
1322
+ if self .inputs .bias_corrected_native :
1323
+ outputs ['bias_corrected_images' ].append (
1324
+ os .path .join (pth , "m%s.nii" % (base )))
1325
+ if self .inputs .bias_corrected_normalized :
1326
+ outputs ['normalized_bias_corrected_images' ].append (
1327
+ os .path .join (pth , "wm%s%s.nii" % (dartel_px , base )))
1328
+
1329
+ if self .inputs .deformation_field [0 ]:
1330
+ outputs ['forward_deformation_field' ].append (
1331
+ os .path .join (pth , "y_%s%s.nii" % (dartel_px , base )))
1332
+ if self .inputs .deformation_field [1 ]:
1333
+ outputs ['inverse_deformation_field' ].append (
1334
+ os .path .join (pth , "iy_%s%s.nii" % (dartel_px , base )))
1335
+
1336
+ if self .inputs .jacobian_determinant and do_dartel :
1337
+ outputs ['jacobian_determinant_images' ].append (
1338
+ os .path .join (pth , "jac_wrp1%s.nii" % (base )))
1339
+ return outputs
1340
+
1341
+ def _format_arg (self , opt , spec , val ):
1342
+ """Convert input to appropriate format for spm
1343
+ """
1344
+ if opt in ['in_files' ]:
1345
+ return scans_for_fnames (val , keep4d = True )
1346
+ elif opt in ['spatial_normalization' ]:
1347
+ if val == 'low' :
1348
+ return {'normlow' : []}
1349
+ elif opt in ['dartel_template' ]:
1350
+ return np .array ([val ], dtype = object )
1351
+ elif opt in ['deformation_field' ]:
1352
+ return super (VBMSegment , self )._format_arg (opt , spec , [int (val [0 ]), int (val [1 ])])
1353
+ else :
1354
+ return super (VBMSegment , self )._format_arg (opt , spec , val )
1355
+
1356
+ def _parse_inputs (self ):
1357
+ if self .inputs .spatial_normalization == 'low' :
1358
+ einputs = super (VBMSegment , self )._parse_inputs (
1359
+ skip = ('spatial_normalization' , 'dartel_template' ))
1360
+ einputs [0 ]['estwrite' ]['extopts' ]['dartelwarp' ] = {'normlow' : 1 }
1361
+ return einputs
1362
+ else :
1363
+ return super (VBMSegment , self )._parse_inputs (skip = ('spatial_normalization' ))
0 commit comments