@@ -1159,34 +1159,27 @@ def _gen_filename(self, name):
1159
1159
class FUGUEInputSpec (FSLCommandInputSpec ):
1160
1160
in_file = File (exists = True , argstr = '--in=%s' ,
1161
1161
desc = 'filename of input volume' )
1162
+ shift_in_file = File (exists = True , argstr = '--loadshift=%s' ,
1163
+ desc = 'filename for reading pixel shift volume' )
1164
+ phasemap_in_file = File (exists = True , argstr = '--phasemap=%s' ,
1165
+ desc = 'filename for input phase image' )
1166
+ fmap_in_file = File (exists = True , argstr = '--loadfmap=%s' ,
1167
+ desc = 'filename for loading fieldmap (rad/s)' )
1162
1168
unwarped_file = File (argstr = '--unwarp=%s' , desc = 'apply unwarping and save as filename' ,
1163
- hash_files = False )
1164
- forward_warping = traits .Bool (
1165
- False , usedefault = True ,
1166
- desc = 'apply forward warping instead of unwarping' )
1167
- warped_file = File (argstr = '--warp=%s' ,
1168
- desc = 'apply forward warping and save as filename' ,
1169
- hash_files = False )
1170
- phasemap_file = File (exists = True , argstr = '--phasemap=%s' ,
1171
- desc = 'filename for input phase image' )
1169
+ xor = ['warped_file' ])
1170
+ warped_file = File (argstr = '--warp=%s' , desc = 'apply forward warping and save as filename' ,
1171
+ xor = ['unwarped_file' ])
1172
+
1173
+ forward_warping = traits .Bool (False , usedefault = True , mandatory = True ,
1174
+ desc = 'apply forward warping instead of unwarping' )
1175
+
1172
1176
dwell_to_asym_ratio = traits .Float (argstr = '--dwelltoasym=%.10f' ,
1173
1177
desc = 'set the dwell to asym time ratio' )
1174
1178
dwell_time = traits .Float (argstr = '--dwell=%.10f' ,
1175
- desc = 'set the EPI dwell time per phase-encode line - same as echo spacing - (sec)' )
1179
+ desc = ('set the EPI dwell time per phase-encode line - same as echo '
1180
+ 'spacing - (sec)' ))
1176
1181
asym_se_time = traits .Float (argstr = '--asym=%.10f' ,
1177
1182
desc = 'set the fieldmap asymmetric spin echo time (sec)' )
1178
- fmap_out_file = File (argstr = '--savefmap=%s' ,
1179
- desc = 'filename for saving fieldmap (rad/s)' , hash_files = False )
1180
- fmap_in_file = File (exists = True , argstr = '--loadfmap=%s' ,
1181
- desc = 'filename for loading fieldmap (rad/s)' )
1182
-
1183
- save_shift = traits .Bool (desc = 'output pixel shift volume' )
1184
-
1185
- shift_out_file = traits .File (argstr = '--saveshift=%s' ,
1186
- desc = 'filename for saving pixel shift volume' , hash_files = False )
1187
-
1188
- shift_in_file = File (exists = True , argstr = '--loadshift=%s' ,
1189
- desc = 'filename for reading pixel shift volume' )
1190
1183
median_2dfilter = traits .Bool (argstr = '--median' ,
1191
1184
desc = 'apply 2D median filtering' )
1192
1185
despike_2dfilter = traits .Bool (argstr = '--despike' ,
@@ -1216,16 +1209,22 @@ class FUGUEInputSpec(FSLCommandInputSpec):
1216
1209
desc = 'apply intensity correction to unwarping (pixel shift method only)' )
1217
1210
icorr_only = traits .Bool (argstr = '--icorronly' , requires = ['unwarped_file' ],
1218
1211
desc = 'apply intensity correction only' )
1219
- mask_file = File (exists = True , argstr = '--mask=%s' ,
1220
- desc = 'filename for loading valid mask ' )
1221
- save_unmasked_fmap = traits . Bool ( argstr = '--unmaskfmap' ,
1222
- requires = [ 'fmap_out_file' ],
1223
- desc = 'saves the unmasked fieldmap when using --savefmap ' )
1224
- save_unmasked_shift = traits . Bool (argstr = '--unmaskshift' ,
1225
- requires = ['save_shift' ],
1212
+ mask_file = File (exists = True , argstr = '--mask=%s' , desc = 'filename for loading valid mask' )
1213
+ nokspace = traits . Bool ( False , argstr = '--nokspace' , desc = 'do not use k-space forward warping ' )
1214
+
1215
+ # Special outputs: shift (voxel shift map, vsm)
1216
+ save_shift = traits . Bool ( False , desc = 'write pixel shift volume ' )
1217
+ shift_out_file = File (argstr = '--saveshift=%s' , desc = 'filename for saving pixel shift volume' )
1218
+ save_unmasked_shift = traits . Bool ( argstr = '--unmaskshift' , xor = ['save_shift' ],
1226
1219
desc = 'saves the unmasked shiftmap when using --saveshift' )
1227
- nokspace = traits .Bool (
1228
- argstr = '--nokspace' , desc = 'do not use k-space forward warping' )
1220
+
1221
+ # Special outputs: fieldmap (fmap)
1222
+ save_fmap = traits .Bool (False , desc = 'write field map volume' )
1223
+ fmap_out_file = File (argstr = '--savefmap=%s' , desc = 'filename for saving fieldmap (rad/s)' )
1224
+ save_unmasked_fmap = traits .Bool (False , argstr = '--unmaskfmap' , xor = ['save_fmap' ],
1225
+ desc = 'saves the unmasked fieldmap when using --savefmap' )
1226
+
1227
+
1229
1228
1230
1229
1231
1230
class FUGUEOutputSpec (TraitedSpec ):
@@ -1238,87 +1237,121 @@ class FUGUEOutputSpec(TraitedSpec):
1238
1237
class FUGUE (FSLCommand ):
1239
1238
"""Use FSL FUGUE to unwarp epi's with fieldmaps
1240
1239
1241
- Examples
1242
- --------
1240
+ Example (unwarping an input image, the shift map is known) ::
1243
1241
1244
1242
>>> from nipype.interfaces.fsl.preprocess import FUGUE
1245
1243
>>> fugue = FUGUE()
1246
- >>> fugue.inputs.forward_warping = True
1247
1244
>>> fugue.inputs.in_file = 'epi.nii'
1248
1245
>>> fugue.inputs.mask_file = 'epi_mask.nii'
1249
- >>> fugue.inputs.shift_in_file = 'image .nii' # Previously computed with fugue as well
1246
+ >>> fugue.inputs.shift_in_file = 'vsm .nii' # Previously computed with fugue as well
1250
1247
>>> fugue.inputs.unwarp_direction = 'y'
1251
1248
>>> fugue.cmdline #doctest: +ELLIPSIS
1252
- 'fugue --in=epi.nii --mask=epi_mask.nii --loadshift=image .nii --unwarpdir=y --warp =.../epi_warped .nii.gz'
1249
+ 'fugue --in=epi.nii --mask=epi_mask.nii --loadshift=vsm .nii --unwarpdir=y --unwarp =.../epi_unwarped .nii.gz'
1253
1250
>>> fugue.run() #doctest: +SKIP
1254
1251
1255
- """
1256
1252
1257
- _cmd = 'fugue'
1258
- input_spec = FUGUEInputSpec
1259
- output_spec = FUGUEOutputSpec
1253
+ Example (warping an input image, shift map is known) ::
1260
1254
1261
- def __init__ (self , ** kwargs ):
1262
- super (FUGUE , self ).__init__ (** kwargs )
1263
- warn (
1264
- 'This interface has not been fully tested. Please report any failures.' )
1265
-
1266
- def _list_outputs (self ):
1267
- outputs = self ._outputs ().get ()
1255
+ >>> from nipype.interfaces.fsl.preprocess import FUGUE
1256
+ >>> fugue = FUGUE()
1257
+ >>> fugue.inputs.forward_warping = True
1258
+ >>> fugue.inputs.in_file = 'epi.nii'
1259
+ >>> fugue.inputs.mask_file = 'epi_mask.nii'
1260
+ >>> fugue.inputs.shift_in_file = 'vsm.nii' # Previously computed with fugue as well
1261
+ >>> fugue.inputs.unwarp_direction = 'y'
1262
+ >>> fugue.cmdline #doctest: +ELLIPSIS
1263
+ 'fugue --in=epi.nii --mask=epi_mask.nii --loadshift=vsm.nii --unwarpdir=y --warp=.../epi_warped.nii.gz'
1264
+ >>> fugue.run() #doctest: +SKIP
1268
1265
1269
- if isdefined (self .inputs .forward_warping ) and self .inputs .forward_warping :
1270
- out_field = 'warped_file'
1271
- self .inputs .unwarped_file = Undefined
1272
- outputs .pop ('unwarped_file' )
1273
- else :
1274
- out_field = 'unwarped_file'
1275
- outputs .pop ('warped_file' )
1276
1266
1277
- out_file = getattr (self .inputs , out_field )
1278
- if not isdefined (out_file ):
1279
- if isdefined (self .inputs .in_file ):
1280
- out_file = self ._gen_fname (self .inputs .in_file ,
1281
- suffix = '_' + out_field [:- 5 ])
1282
- if isdefined (out_file ):
1283
- outputs [out_field ] = os .path .abspath (out_file )
1284
- if isdefined (self .inputs .fmap_out_file ):
1285
- outputs ['fmap_out_file' ] = os .path .abspath (
1286
- self .inputs .fmap_out_file )
1287
- if isdefined (self .inputs .shift_out_file ):
1288
- outputs ['shift_out_file' ] = os .path .abspath (
1289
- self .inputs .shift_out_file )
1267
+ Example (computing the vsm, unwrapped phase map is known) ::
1290
1268
1291
- return outputs
1269
+ >>> from nipype.interfaces.fsl.preprocess import FUGUE
1270
+ >>> fugue = FUGUE()
1271
+ >>> fugue.inputs.phasemap_in_file = 'epi_phasediff.nii'
1272
+ >>> fugue.inputs.mask_file = 'epi_mask.nii'
1273
+ >>> fugue.inputs.dwell_to_asym_ratio = 0.77e-3 / 2.46e-3
1274
+ >>> fugue.inputs.unwarp_direction = 'y'
1275
+ >>> fugue.inputs.save_shift = True
1276
+ >>> fugue.cmdline #doctest: +ELLIPSIS
1277
+ 'fugue --dwelltoasym=0.7000000000 --mask=epi_mask.nii --phasemap=epi_phasediff.nii --saveshift=.../epi_phasediff_vsm.nii.gz --unwarpdir=y'
1278
+ >>> fugue.run() #doctest: +SKIP
1292
1279
1293
- def _gen_filename (self , name ):
1294
- is_fwd = isdefined (self .inputs .forward_warping ) and self .inputs .forward_warping
1295
1280
1296
- if (is_fwd and name == 'warped_file' ) or (not is_fwd and name == 'unwarped_file' ):
1297
- return self ._list_outputs ()[name ]
1281
+ """
1298
1282
1299
- return None
1283
+ _cmd = 'fugue'
1284
+ input_spec = FUGUEInputSpec
1285
+ output_spec = FUGUEOutputSpec
1300
1286
1301
1287
def _parse_inputs (self , skip = None ):
1302
1288
if skip is None :
1303
1289
skip = []
1304
1290
1305
- if not isdefined (self .inputs .save_shift ) or not self . inputs . save_shift :
1306
- skip += [ 'shift_out_file' ]
1307
- else :
1308
- if not isdefined ( self . inputs . shift_out_file ):
1309
- self . inputs . shift_out_file = self . _gen_fname (
1310
- self . inputs . in_file , suffix = '_vsm ' )
1291
+ input_phase = isdefined (self .inputs .phasemap_in_file )
1292
+ input_vsm = isdefined ( self . inputs . shift_in_file )
1293
+ input_fmap = isdefined ( self . inputs . fmap_in_file )
1294
+
1295
+ if not input_phase and not input_vsm and not input_fmap :
1296
+ raise RuntimeError ( 'Either phasemap_in_file, shift_in_file or fmap_in_file must be set. ' )
1311
1297
1312
1298
if not isdefined (self .inputs .in_file ):
1313
1299
skip += ['unwarped_file' , 'warped_file' ]
1314
- elif self .inputs .forward_warping :
1315
- if not isdefined (self .inputs .warped_file ):
1316
- self .inputs .warped_file = self ._gen_fname (
1317
- self .inputs .in_file , suffix = '_warped' )
1318
- elif not self .inputs .forward_warping :
1319
- if not isdefined (self .inputs .unwarped_file ):
1320
- self .inputs .unwarped_file = self ._gen_fname (
1321
- self .inputs .in_file , suffix = '_unwarped' )
1300
+ else :
1301
+ if self .inputs .forward_warping :
1302
+ skip += ['unwarped_file' ]
1303
+ trait_spec = self .inputs .trait ('warped_file' )
1304
+ trait_spec .name_template = "%s_warped"
1305
+ trait_spec .name_source = ['in_file' ]
1306
+ trait_spec .output_name = 'warped_file'
1307
+ else :
1308
+ skip += ['warped_file' ]
1309
+ trait_spec = self .inputs .trait ('unwarped_file' )
1310
+ trait_spec .name_template = "%s_unwarped"
1311
+ trait_spec .name_source = ['in_file' ]
1312
+ trait_spec .output_name = 'unwarped_file'
1313
+
1314
+ # Handle shift output
1315
+ vsm_save_masked = isdefined (self .inputs .save_shift ) and self .inputs .save_shift
1316
+ vsm_save_unmasked = isdefined (self .inputs .save_unmasked_shift ) \
1317
+ and self .inputs .save_unmasked_shift
1318
+
1319
+ if (vsm_save_masked or vsm_save_unmasked ) and not isdefined (self .inputs .shift_out_file ):
1320
+ trait_spec = self .inputs .trait ('shift_out_file' )
1321
+ trait_spec .output_name = 'shift_out_file'
1322
+
1323
+ if vsm_save_unmasked :
1324
+ trait_spec .name_template = '%s_vsm_unmasked'
1325
+ else :
1326
+ trait_spec .name_template = '%s_vsm'
1327
+
1328
+ if input_fmap :
1329
+ trait_spec .name_source = ['fmap_in_file' ]
1330
+ elif input_phase :
1331
+ trait_spec .name_source = ['phasemap_in_file' ]
1332
+ else :
1333
+ trait_spec .name_source = ['shift_in_file' ]
1334
+
1335
+ # Handle fieldmap output
1336
+ fmap_save_masked = isdefined (self .inputs .save_fmap ) and self .inputs .save_shift
1337
+ fmap_save_unmasked = isdefined (self .inputs .save_unmasked_fmap ) and \
1338
+ self .inputs .save_unmasked_fmap
1339
+
1340
+ if (fmap_save_masked or fmap_save_unmasked ) and not isdefined (self .inputs .fmap_out_file ):
1341
+ trait_spec = self .inputs .trait ('fmap_out_file' )
1342
+ trait_spec .output_name = 'fmap_out_file'
1343
+
1344
+ if fmap_save_unmasked :
1345
+ trait_spec .name_template = '%s_fieldmap_unmasked'
1346
+ else :
1347
+ trait_spec .name_template = '%s_fieldmap'
1348
+
1349
+ if input_vsm :
1350
+ trait_spec .name_source = ['shift_in_file' ]
1351
+ elif input_phase :
1352
+ trait_spec .name_source = ['phasemap_in_file' ]
1353
+ else :
1354
+ trait_spec .name_source = ['fmap_in_file' ]
1322
1355
1323
1356
return super (FUGUE , self )._parse_inputs (skip = skip )
1324
1357
0 commit comments