Skip to content

Commit 83fda45

Browse files
author
Fabio Bernardoni
committed
separate apply and calculate VDM in two classes
1 parent 7929843 commit 83fda45

File tree

1 file changed

+94
-108
lines changed

1 file changed

+94
-108
lines changed

nipype/interfaces/spm/preprocess.py

Lines changed: 94 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,16 @@
3939

4040

4141
class 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

Comments
 (0)