3939
4040
4141class FieldMapInputSpec (SPMCommandInputSpec ):
42- jobtype = traits .Enum (
43- "calculatevdm" ,
44- "applyvdm" ,
45- usedefault = True ,
46- desc = "one of: calculatevdm, applyvdm" ,
47- )
42+
4843 phase_file = File (
49- # mandatory=True,
44+ mandatory = True ,
5045 exists = True ,
5146 copyfile = False ,
5247 field = "subj.data.presubphasemag.phase" ,
5348 desc = "presubstracted phase file" ,
5449 )
5550 magnitude_file = File (
56- # mandatory=True,
51+ mandatory = True ,
5752 exists = True ,
5853 copyfile = False ,
5954 field = "subj.data.presubphasemag.magnitude" ,
@@ -62,7 +57,7 @@ class FieldMapInputSpec(SPMCommandInputSpec):
6257 echo_times = traits .Tuple (
6358 traits .Float ,
6459 traits .Float ,
65- # mandatory=True,
60+ mandatory = True ,
6661 field = "subj.defaults.defaultsval.et" ,
6762 desc = "short and long echo times" ,
6863 )
@@ -169,7 +164,7 @@ class FieldMapInputSpec(SPMCommandInputSpec):
169164 epi_file = File (
170165 copyfile = False ,
171166 exists = True ,
172- # mandatory=True,
167+ mandatory = True ,
173168 field = "subj.session.epi" ,
174169 desc = "EPI to unwarp" ,
175170 )
@@ -195,6 +190,65 @@ class FieldMapInputSpec(SPMCommandInputSpec):
195190 desc = "match anatomical image to EPI" ,
196191 )
197192
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+
198252 in_files = InputMultiObject (
199253 traits .Either (
200254 ImageFileSPM (exists = True ), traits .List (ImageFileSPM (exists = True ))
@@ -207,7 +261,7 @@ class FieldMapInputSpec(SPMCommandInputSpec):
207261 vdmfile = File (
208262 field = "data.vdmfile" ,
209263 desc = "Voxel displacement map to use" ,
210- mandatory = True ,
264+ # mandatory=True,
211265 copyfile = True ,
212266 )
213267 distortion_direction = traits .Int (
@@ -253,25 +307,17 @@ class FieldMapInputSpec(SPMCommandInputSpec):
253307 desc = "fieldmap corrected output prefix" ,
254308 )
255309
256-
257- class FieldMapOutputSpec (TraitedSpec ):
258- vdm = File (exists = True , desc = "voxel difference map" )
259-
310+ class ApplyVDMOutputSpec (TraitedSpec ):
260311 out_files = OutputMultiPath (
261312 traits .Either (traits .List (File (exists = True )), File (exists = True )),
262313 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."
268315 ),
269316 )
270317 mean_image = File (exists = True , desc = "Mean image" )
271318
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.
275321
276322 http://www.fil.ion.ucl.ac.uk/spm/doc/manual.pdf#page=173
277323
@@ -280,114 +326,54 @@ class FieldMap(SPMCommand):
280326 This interface does not deal with real/imag magnitude images nor
281327 with the two phase files case.
282328
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-
295329 """
296330
297- input_spec = FieldMapInputSpec
298- output_spec = FieldMapOutputSpec
331+ input_spec = ApplyVDMInputSpec
332+ output_spec = ApplyVDMOutputSpec
299333 _jobtype = "tools"
300334 _jobname = "fieldmap"
301335
302336 def _format_arg (self , opt , spec , val ):
303337 """Convert input to appropriate format for spm"""
304338
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" ]:
314340 return scans_for_fname (ensure_list (val ))
315341 return super (FieldMap , self )._format_arg (opt , spec , val )
316342
317343 def _parse_inputs (self ):
318344 """validate spm fieldmap options if set to None ignore"""
319345
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 ()
356347
357- return [{"%s" % ( jobtype ) : einputs [0 ]}]
348+ return [{"applymap" : einputs [0 ]}]
358349
359350 def _list_outputs (self ):
360351 outputs = self ._outputs ().get ()
361352 jobtype = self .inputs .jobtype
362353 resliced_all = self .inputs .write_which [0 ] > 0
363354 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" )
373361
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
387370 )
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 )
391377 return outputs
392378
393379
0 commit comments