39
39
40
40
41
41
class FieldMapInputSpec (SPMCommandInputSpec ):
42
- jobtype = traits .Enum (
43
- "calculatevdm" ,
44
- "applyvdm" ,
45
- usedefault = True ,
46
- desc = "one of: calculatevdm, applyvdm" ,
47
- )
42
+
48
43
phase_file = File (
49
- # mandatory=True,
44
+ mandatory = True ,
50
45
exists = True ,
51
46
copyfile = False ,
52
47
field = "subj.data.presubphasemag.phase" ,
53
48
desc = "presubstracted phase file" ,
54
49
)
55
50
magnitude_file = File (
56
- # mandatory=True,
51
+ mandatory = True ,
57
52
exists = True ,
58
53
copyfile = False ,
59
54
field = "subj.data.presubphasemag.magnitude" ,
@@ -62,7 +57,7 @@ class FieldMapInputSpec(SPMCommandInputSpec):
62
57
echo_times = traits .Tuple (
63
58
traits .Float ,
64
59
traits .Float ,
65
- # mandatory=True,
60
+ mandatory = True ,
66
61
field = "subj.defaults.defaultsval.et" ,
67
62
desc = "short and long echo times" ,
68
63
)
@@ -169,7 +164,7 @@ class FieldMapInputSpec(SPMCommandInputSpec):
169
164
epi_file = File (
170
165
copyfile = False ,
171
166
exists = True ,
172
- # mandatory=True,
167
+ mandatory = True ,
173
168
field = "subj.session.epi" ,
174
169
desc = "EPI to unwarp" ,
175
170
)
@@ -195,6 +190,65 @@ class FieldMapInputSpec(SPMCommandInputSpec):
195
190
desc = "match anatomical image to EPI" ,
196
191
)
197
192
193
+
194
+ class FieldMapOutputSpec (TraitedSpec ):
195
+ vdm = File (exists = True , desc = "voxel difference map" )
196
+
197
+
198
+ class FieldMap (SPMCommand ):
199
+ """Use the fieldmap toolbox from spm to calculate the voxel displacement map (VDM).
200
+
201
+ http://www.fil.ion.ucl.ac.uk/spm/doc/manual.pdf#page=173
202
+
203
+ .. important::
204
+
205
+ This interface does not deal with real/imag magnitude images nor
206
+ with the two phase files case.
207
+
208
+ Examples
209
+ --------
210
+ >>> from nipype.interfaces.spm import FieldMap
211
+ >>> fm = FieldMap()
212
+ >>> fm.inputs.phase_file = 'phase.nii'
213
+ >>> fm.inputs.magnitude_file = 'magnitude.nii'
214
+ >>> fm.inputs.echo_times = (5.19, 7.65)
215
+ >>> fm.inputs.blip_direction = 1
216
+ >>> fm.inputs.total_readout_time = 15.6
217
+ >>> fm.inputs.epi_file = 'epi.nii'
218
+ >>> fm.run() # doctest: +SKIP
219
+
220
+ """
221
+
222
+ input_spec = FieldMapInputSpec
223
+ output_spec = FieldMapOutputSpec
224
+ _jobtype = "tools"
225
+ _jobname = "fieldmap"
226
+
227
+ def _format_arg (self , opt , spec , val ):
228
+ """Convert input to appropriate format for spm"""
229
+
230
+ if opt in ["phase_file" , "magnitude_file" , "anat_file" , "epi_file" ]:
231
+
232
+ return scans_for_fname (ensure_list (val ))
233
+
234
+ return super (FieldMap , self )._format_arg (opt , spec , val )
235
+
236
+ def _parse_inputs (self ):
237
+ """validate spm fieldmap options if set to None ignore"""
238
+
239
+ einputs = super (FieldMap , self )._parse_inputs ()
240
+ return [{"calculatevdm" : einputs [0 ]}]
241
+
242
+ def _list_outputs (self ):
243
+ outputs = self ._outputs ().get ()
244
+ jobtype = self .inputs .jobtype
245
+
246
+ outputs ["vdm" ] = fname_presuffix (self .inputs .phase_file , prefix = "vdm5_sc" )
247
+
248
+ return outputs
249
+
250
+ class ApplyVDMInputSpec (SPMCommandInputSpec ):
251
+
198
252
in_files = InputMultiObject (
199
253
traits .Either (
200
254
ImageFileSPM (exists = True ), traits .List (ImageFileSPM (exists = True ))
@@ -207,7 +261,7 @@ class FieldMapInputSpec(SPMCommandInputSpec):
207
261
vdmfile = File (
208
262
field = "data.vdmfile" ,
209
263
desc = "Voxel displacement map to use" ,
210
- mandatory = True ,
264
+ # mandatory=True,
211
265
copyfile = True ,
212
266
)
213
267
distortion_direction = traits .Int (
@@ -253,25 +307,17 @@ class FieldMapInputSpec(SPMCommandInputSpec):
253
307
desc = "fieldmap corrected output prefix" ,
254
308
)
255
309
256
-
257
- class FieldMapOutputSpec (TraitedSpec ):
258
- vdm = File (exists = True , desc = "voxel difference map" )
259
-
310
+ class ApplyVDMOutputSpec (TraitedSpec ):
260
311
out_files = OutputMultiPath (
261
312
traits .Either (traits .List (File (exists = True )), File (exists = True )),
262
313
desc = (
263
- "If jobtype is applyvdm, "
264
- "these will be the fieldmap corrected files."
265
- " Otherwise, they will be copies "
266
- "of in_files that have had their "
267
- "headers rewritten."
314
+ "These will be the fieldmap corrected files."
268
315
),
269
316
)
270
317
mean_image = File (exists = True , desc = "Mean image" )
271
318
272
-
273
- class FieldMap (SPMCommand ):
274
- """Use the fieldmap toolbox from spm to calculate the voxel displacement map (VDM).
319
+ class ApplyVDM (SPMCommand ):
320
+ """Use the fieldmap toolbox from spm to apply the voxel displacement map (VDM) to some epi files.
275
321
276
322
http://www.fil.ion.ucl.ac.uk/spm/doc/manual.pdf#page=173
277
323
@@ -280,114 +326,54 @@ class FieldMap(SPMCommand):
280
326
This interface does not deal with real/imag magnitude images nor
281
327
with the two phase files case.
282
328
283
- Examples
284
- --------
285
- >>> from nipype.interfaces.spm import FieldMap
286
- >>> fm = FieldMap()
287
- >>> fm.inputs.phase_file = 'phase.nii'
288
- >>> fm.inputs.magnitude_file = 'magnitude.nii'
289
- >>> fm.inputs.echo_times = (5.19, 7.65)
290
- >>> fm.inputs.blip_direction = 1
291
- >>> fm.inputs.total_readout_time = 15.6
292
- >>> fm.inputs.epi_file = 'epi.nii'
293
- >>> fm.run() # doctest: +SKIP
294
-
295
329
"""
296
330
297
- input_spec = FieldMapInputSpec
298
- output_spec = FieldMapOutputSpec
331
+ input_spec = ApplyVDMInputSpec
332
+ output_spec = ApplyVDMOutputSpec
299
333
_jobtype = "tools"
300
334
_jobname = "fieldmap"
301
335
302
336
def _format_arg (self , opt , spec , val ):
303
337
"""Convert input to appropriate format for spm"""
304
338
305
- if (self .inputs .jobtype == "calculatevdm" ) and (
306
- opt in ["phase_file" , "magnitude_file" , "anat_file" , "epi_file" ]
307
- ):
308
-
309
- return scans_for_fname (ensure_list (val ))
310
-
311
- if (self .inputs .jobtype == "applyvdm" ) and (opt == "in_files" ):
312
- return scans_for_fnames (ensure_list (val ))
313
- if (self .inputs .jobtype == "applyvdm" ) and (opt == "vdmfile" ):
339
+ if opt in ["in_files" , "vdmfile" ]:
314
340
return scans_for_fname (ensure_list (val ))
315
341
return super (FieldMap , self )._format_arg (opt , spec , val )
316
342
317
343
def _parse_inputs (self ):
318
344
"""validate spm fieldmap options if set to None ignore"""
319
345
320
- if self .inputs .jobtype == "applyvdm" :
321
- einputs = super (FieldMap , self )._parse_inputs (
322
- skip = (
323
- "jobtype" ,
324
- "phase_file" ,
325
- "magnitude_file" ,
326
- "echo_times" ,
327
- "blip_direction" ,
328
- "total_readout_time" ,
329
- "maskbrain" ,
330
- "epifm" ,
331
- "jacobian_modulation" ,
332
- "method" ,
333
- "unwarp_fwhm" ,
334
- "pad" ,
335
- "ws" ,
336
- "template" ,
337
- "mask_fwhm" ,
338
- "nerode" ,
339
- "ndilate" ,
340
- "thresh" ,
341
- "reg" ,
342
- "epi_file" ,
343
- "matchvdm" ,
344
- "sessname" ,
345
- "writeunwarped" ,
346
- "anat_file" ,
347
- "matchanat" ,
348
- )
349
- )
350
-
351
- else :
352
- einputs = super (FieldMap , self )._parse_inputs (
353
- skip = ("jobtype" , "in_files" , "vdmfile" )
354
- )
355
- jobtype = self .inputs .jobtype
346
+ einputs = super (ApplyVDM , self )._parse_inputs ()
356
347
357
- return [{"%s" % ( jobtype ) : einputs [0 ]}]
348
+ return [{"applymap" : einputs [0 ]}]
358
349
359
350
def _list_outputs (self ):
360
351
outputs = self ._outputs ().get ()
361
352
jobtype = self .inputs .jobtype
362
353
resliced_all = self .inputs .write_which [0 ] > 0
363
354
resliced_mean = self .inputs .write_which [1 ] > 0
364
- if jobtype == "calculatevdm" :
365
- outputs ["vdm" ] = fname_presuffix (self .inputs .phase_file , prefix = "vdm5_sc" )
366
- elif jobtype == "applyvdm" :
367
- if resliced_mean :
368
- if isinstance (self .inputs .in_files [0 ], list ):
369
- first_image = self .inputs .in_files [0 ][0 ]
370
- else :
371
- first_image = self .inputs .in_files [0 ]
372
- outputs ["mean_image" ] = fname_presuffix (first_image , prefix = "meanu" )
355
+ if resliced_mean :
356
+ if isinstance (self .inputs .in_files [0 ], list ):
357
+ first_image = self .inputs .in_files [0 ][0 ]
358
+ else :
359
+ first_image = self .inputs .in_files [0 ]
360
+ outputs ["mean_image" ] = fname_presuffix (first_image , prefix = "meanu" )
373
361
374
- if resliced_all :
375
- outputs ["out_files" ] = []
376
- for idx , imgf in enumerate (ensure_list (self .inputs .in_files )):
377
- appliedvdm_run = []
378
- if isinstance (imgf , list ):
379
- for i , inner_imgf in enumerate (ensure_list (imgf )):
380
- newfile = fname_presuffix (
381
- inner_imgf , prefix = self .inputs .out_prefix
382
- )
383
- appliedvdm_run .append (newfile )
384
- else :
385
- appliedvdm_run = fname_presuffix (
386
- imgf , prefix = self .inputs .out_prefix
362
+ if resliced_all :
363
+ outputs ["out_files" ] = []
364
+ for idx , imgf in enumerate (ensure_list (self .inputs .in_files )):
365
+ appliedvdm_run = []
366
+ if isinstance (imgf , list ):
367
+ for i , inner_imgf in enumerate (ensure_list (imgf )):
368
+ newfile = fname_presuffix (
369
+ inner_imgf , prefix = self .inputs .out_prefix
387
370
)
388
- outputs ["out_files" ].append (appliedvdm_run )
389
- return outputs
390
-
371
+ appliedvdm_run .append (newfile )
372
+ else :
373
+ appliedvdm_run = fname_presuffix (
374
+ imgf , prefix = self .inputs .out_prefix
375
+ )
376
+ outputs ["out_files" ].append (appliedvdm_run )
391
377
return outputs
392
378
393
379
0 commit comments