Skip to content

Commit 47fe00b

Browse files
axiezaieffigies
andauthored
ENH: Add new dwifslpreproc interface for MRtrix3 (#3278)
* added mrtrix3 dwifslpreproc as interface * use defaults added for outputs * Added dwifslpreproc interface to __init__ * edited doc string to correct order * added doctest skip * added MRtrix3 gradient empty test data * specified positions, requires for gradient exports * finalized docstring example and pytest * added entry to contribution list * simplify phase-encoding design input Moved `-rpe_` to `argstr` for simpler input. Co-authored-by: Chris Markiewicz <[email protected]> * Apply suggestions from code review Fixed typos and improved `-eddy` and `-topup` optional inputs. Co-authored-by: Chris Markiewicz <[email protected]> * Update nipype/interfaces/mrtrix3/preprocess.py Co-authored-by: Xihe Xie <[email protected]> * fixed input positions according to review * fixed doc string for new positions Co-authored-by: Chris Markiewicz <[email protected]>
1 parent 54f5029 commit 47fe00b

File tree

5 files changed

+194
-0
lines changed

5 files changed

+194
-0
lines changed

.zenodo.json

+5
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,11 @@
788788
{
789789
"name": "Tambini, Arielle"
790790
},
791+
{
792+
"affiliation": "Weill Cornell Medicine",
793+
"name": "Xie, Xihe",
794+
"orcid": "0000-0001-6595-2473"
795+
},
791796
{
792797
"affiliation": "Max Planck Institute for Human Cognitive and Brain Sciences, Leipzig, Germany.",
793798
"name": "Mihai, Paul Glad",

nipype/interfaces/mrtrix3/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
ResponseSD,
1919
ACTPrepareFSL,
2020
ReplaceFSwithFIRST,
21+
DWIPreproc,
2122
DWIDenoise,
2223
MRDeGibbs,
2324
DWIBiasCorrect,

nipype/interfaces/mrtrix3/preprocess.py

+134
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ class DWIBiasCorrect(MRTrix3Base):
233233
_cmd = "dwibiascorrect"
234234
input_spec = DWIBiasCorrectInputSpec
235235
output_spec = DWIBiasCorrectOutputSpec
236+
236237
def _format_arg(self, name, trait_spec, value):
237238
if name in ("use_ants", "use_fsl"):
238239
ver = self.version
@@ -241,6 +242,139 @@ def _format_arg(self, name, trait_spec, value):
241242
return f"-{trait_spec.argstr}"
242243
return super()._format_arg(name, trait_spec, value)
243244

245+
246+
class DWIPreprocInputSpec(MRTrix3BaseInputSpec):
247+
in_file = File(
248+
exists=True, argstr="%s", position=0, mandatory=True, desc="input DWI image"
249+
)
250+
out_file = File(
251+
"preproc.mif",
252+
argstr="%s",
253+
mandatory=True,
254+
position=1,
255+
usedefault=True,
256+
desc="output file after preprocessing",
257+
)
258+
rpe_options = traits.Enum(
259+
"none",
260+
"pair",
261+
"all",
262+
"header",
263+
argstr="-rpe_%s",
264+
position=2,
265+
mandatory=True,
266+
desc='Specify acquisition phase-encoding design. "none" for no reversed phase-encoding image, "all" for all DWIs have opposing phase-encoding acquisition, "pair" for using a pair of b0 volumes for inhomogeneity field estimation only, and "header" for phase-encoding information can be found in the image header(s)',
267+
)
268+
pe_dir = traits.Str(
269+
argstr="-pe_dir %s",
270+
mandatory=True,
271+
desc="Specify the phase encoding direction of the input series, can be a signed axis number (e.g. -0, 1, +2), an axis designator (e.g. RL, PA, IS), or NIfTI axis codes (e.g. i-, j, k)",
272+
)
273+
ro_time = traits.Float(
274+
argstr="-readout_time %f",
275+
desc="Total readout time of input series (in seconds)",
276+
)
277+
in_epi = File(
278+
exists=True,
279+
argstr="-se_epi %s",
280+
desc="Provide an additional image series consisting of spin-echo EPI images, which is to be used exclusively by topup for estimating the inhomogeneity field (i.e. it will not form part of the output image series)",
281+
)
282+
align_seepi = traits.Bool(
283+
argstr="-align_seepi",
284+
desc="Achieve alignment between the SE-EPI images used for inhomogeneity field estimation, and the DWIs",
285+
)
286+
eddy_options = traits.Str(
287+
argstr='-eddy_options "%s"',
288+
desc="Manually provide additional command-line options to the eddy command",
289+
)
290+
topup_options = traits.Str(
291+
argstr='-topup_options "%s"',
292+
desc="Manually provide additional command-line options to the topup command",
293+
)
294+
export_grad_mrtrix = traits.Bool(
295+
argstr="-export_grad_mrtrix", desc="export new gradient files in mrtrix format"
296+
)
297+
export_grad_fsl = traits.Bool(
298+
argstr="-export_grad_fsl", desc="export gradient files in FSL format"
299+
)
300+
out_grad_mrtrix = File(
301+
"grad.b",
302+
argstr="%s",
303+
usedefault=True,
304+
requires=["export_grad_mrtrix"],
305+
desc="name of new gradient file",
306+
)
307+
out_grad_fsl = traits.Tuple(
308+
File("grad.bvecs", usedefault=True, desc="bvecs"),
309+
File("grad.bvals", usedefault=True, desc="bvals"),
310+
argstr="%s, %s",
311+
requires=["export_grad_fsl"],
312+
desc="Output (bvecs, bvals) gradients FSL format",
313+
)
314+
315+
316+
class DWIPreprocOutputSpec(TraitedSpec):
317+
out_file = File(argstr="%s", desc="output preprocessed image series")
318+
out_grad_mrtrix = File(
319+
"grad.b",
320+
argstr="%s",
321+
usedefault=True,
322+
desc="preprocessed gradient file in mrtrix3 format",
323+
)
324+
out_fsl_bvec = File(
325+
"grad.bvecs",
326+
argstr="%s",
327+
usedefault=True,
328+
desc="exported fsl gradient bvec file",
329+
)
330+
out_fsl_bval = File(
331+
"grad.bvals",
332+
argstr="%s",
333+
usedefault=True,
334+
desc="exported fsl gradient bval file",
335+
)
336+
337+
338+
class DWIPreproc(MRTrix3Base):
339+
"""
340+
Perform diffusion image pre-processing using FSL's eddy tool; including inhomogeneity distortion correction using FSL's topup tool if possible
341+
342+
For more information, see
343+
<https://mrtrix.readthedocs.io/en/latest/reference/commands/dwifslpreproc.html>
344+
345+
Example
346+
-------
347+
348+
>>> import nipype.interfaces.mrtrix3 as mrt
349+
>>> preproc = mrt.DWIPreproc()
350+
>>> preproc.inputs.in_file = 'dwi.mif'
351+
>>> preproc.inputs.rpe_options = 'none'
352+
>>> preproc.inputs.out_file = "preproc.mif"
353+
>>> preproc.inputs.eddy_options = '--slm=linear --repol' # linear second level model and replace outliers
354+
>>> preproc.inputs.export_grad_mrtrix = True # export final gradient table in MRtrix format
355+
>>> preproc.inputs.ro_time = 0.165240 # 'TotalReadoutTime' in BIDS JSON metadata files
356+
>>> preproc.inputs.pe_dir = 'j' # 'PhaseEncodingDirection' in BIDS JSON metadata files
357+
>>> preproc.cmdline
358+
'dwifslpreproc dwi.mif preproc.mif -rpe_none -eddy_options "--slm=linear --repol" -export_grad_mrtrix grad.b -pe_dir j -readout_time 0.165240'
359+
>>> preproc.run() # doctest: +SKIP
360+
"""
361+
362+
_cmd = "dwifslpreproc"
363+
input_spec = DWIPreprocInputSpec
364+
output_spec = DWIPreprocOutputSpec
365+
366+
def _list_outputs(self):
367+
outputs = self.output_spec().get()
368+
outputs["out_file"] = op.abspath(self.inputs.out_file)
369+
if self.inputs.export_grad_mrtrix:
370+
outputs["out_grad_mrtrix"] = op.abspath(self.inputs.out_grad_mrtrix)
371+
if self.inputs.export_grad_fsl:
372+
outputs["out_fsl_bvec"] = op.abspath(self.inputs.out_grad_fsl[0])
373+
outputs["out_fsl_bval"] = op.abspath(self.inputs.out_grad_fsl[1])
374+
375+
return outputs
376+
377+
244378
class ResponseSDInputSpec(MRTrix3BaseInputSpec):
245379
algorithm = traits.Enum(
246380
"msmt_5tt",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
2+
from ..preprocess import DWIPreproc
3+
4+
5+
def test_DWIPreproc_inputs():
6+
input_map = dict(
7+
align_seepi=dict(argstr="-align_seepi"),
8+
args=dict(argstr="%s"),
9+
bval_scale=dict(argstr="-bvalue_scaling %s"),
10+
eddy_options=dict(argstr='-eddy_options "%s"'),
11+
environ=dict(nohash=True, usedefault=True),
12+
export_grad_fsl=dict(argstr="-export_grad_fsl"),
13+
export_grad_mrtrix=dict(argstr="-export_grad_mrtrix"),
14+
grad_file=dict(argstr="-grad %s", extensions=None, xor=["grad_fsl"]),
15+
grad_fsl=dict(argstr="-fslgrad %s %s", xor=["grad_file"]),
16+
in_bval=dict(extensions=None),
17+
in_bvec=dict(argstr="-fslgrad %s %s", extensions=None),
18+
in_epi=dict(argstr="-se_epi %s", extensions=None),
19+
in_file=dict(argstr="%s", extensions=None, mandatory=True, position=0),
20+
nthreads=dict(argstr="-nthreads %d", nohash=True),
21+
out_file=dict(
22+
argstr="%s", extensions=None, mandatory=True, position=1, usedefault=True
23+
),
24+
out_grad_fsl=dict(argstr="%s, %s", requires=["export_grad_fsl"]),
25+
out_grad_mrtrix=dict(
26+
argstr="%s",
27+
extensions=None,
28+
requires=["export_grad_mrtrix"],
29+
usedefault=True,
30+
),
31+
pe_dir=dict(argstr="-pe_dir %s", mandatory=True),
32+
ro_time=dict(argstr="-readout_time %f"),
33+
rpe_options=dict(argstr="-rpe_%s", mandatory=True, position=2),
34+
topup_options=dict(argstr='-topup_options "%s"'),
35+
)
36+
inputs = DWIPreproc.input_spec()
37+
38+
for key, metadata in list(input_map.items()):
39+
for metakey, value in list(metadata.items()):
40+
assert getattr(inputs.traits()[key], metakey) == value
41+
42+
43+
def test_DWIPreproc_outputs():
44+
output_map = dict(
45+
out_file=dict(argstr="%s", extensions=None),
46+
out_fsl_bval=dict(argstr="%s", extensions=None, usedefault=True),
47+
out_fsl_bvec=dict(argstr="%s", extensions=None, usedefault=True),
48+
out_grad_mrtrix=dict(argstr="%s", extensions=None, usedefault=True),
49+
)
50+
outputs = DWIPreproc.output_spec()
51+
52+
for key, metadata in list(output_map.items()):
53+
for metakey, value in list(metadata.items()):
54+
assert getattr(outputs.traits()[key], metakey) == value

nipype/testing/data/grad.b

Whitespace-only changes.

0 commit comments

Comments
 (0)