From 69a7493f54f6877bd64a4ca19b11bcf0e4c0df16 Mon Sep 17 00:00:00 2001 From: Xihe Xie Date: Wed, 25 Nov 2020 19:20:29 -0500 Subject: [PATCH 01/14] added mrtrix3 dwifslpreproc as interface --- nipype/interfaces/mrtrix3/preprocess.py | 115 ++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/nipype/interfaces/mrtrix3/preprocess.py b/nipype/interfaces/mrtrix3/preprocess.py index aa3347c7f9..b29c54242a 100644 --- a/nipype/interfaces/mrtrix3/preprocess.py +++ b/nipype/interfaces/mrtrix3/preprocess.py @@ -233,6 +233,7 @@ class DWIBiasCorrect(MRTrix3Base): _cmd = "dwibiascorrect" input_spec = DWIBiasCorrectInputSpec output_spec = DWIBiasCorrectOutputSpec + def _format_arg(self, name, trait_spec, value): if name in ("use_ants", "use_fsl"): ver = self.version @@ -241,6 +242,120 @@ def _format_arg(self, name, trait_spec, value): return f"-{trait_spec.argstr}" return super()._format_arg(name, trait_spec, value) + +class DWIPreprocInputSpec(MRTrix3BaseInputSpec): + in_file = File( + exists=True, argstr="%s", position=-5, mandatory=True, desc="input DWI image" + ) + out_file = File( + "preproc.mif", + argstr="%s", + mandatory=True, + position=-4, + usedefault=True, + desc="output file after preprocessing", + ) + rpe_options = traits.Enum( + "-rpe_none", + "-rpe_pair", + "-rpe_all", + "-rpe_header", + argstr="%s", + position=-3, + mandatory=True, + desc="Specify acquisition phase-encoding design, one of the -rpe_* options must be provided", + ) + pe_dir = traits.Str( + argstr="-pe_dir %s", + position=-2, + mandatory=True, + 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)", + ) + ro_time = traits.Float( + argstr="-readout_time %f", + position=-1, + desc="Total readout time of input series (in seconds)", + ) + in_epi = File( + exists=True, + argstr="-se_epi %s", + 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)", + ) + align_seepi = traits.Bool( + argstr="-align_seepi", + desc="Achieve alignment between the SE-EPI images used for inhomogeneity field estimation, and the DWIs", + ) + eddy_options = traits.Str( + argstr="-eddy_options %s", + desc="-eddy_options ” EddyOptions” Manually provide additional command-line options to the eddy command (provide a string within quotation marks that contains at least one space, even if only passing a single command-line option to eddy)", + ) + topup_options = traits.Str( + argstr="-topup_options %s", + desc="-topup_options ” TopupOptions” Manually provide additional command-line options to the topup command (provide a string within quotation marks that contains at least one space, even if only passing a single command-line option to topup)", + ) + export_grad_mrtrix = traits.Bool( + argstr="-export_grad_mrtrix", desc="export new gradientt files in mrtrix format" + ) + export_grad_fsl = traits.Bool( + argstr="-export_grad_fsl", desc="export gradient files in FSL format" + ) + out_grad_mrtrix = File("dwi.b", argstrt="%s", desc="name of new gradient file") + out_grad_fsl = traits.Tuple( + File("dwi.bvecs", desc="bvecs"), + File("dwi.bvals", desc="bvals"), + argstr="%s, %s", + desc="Output (bvecs, bvals) gradients FSL format", + ) + + +class DWIPreprocOutputtSpec(TraitedSpec): + out_file = File(argstr="%s", desc="output preprocessed image series") + out_grad_mrtrix = File( + argstr="%s", desc="preprocessed gradient file in mrtrix3 format" + ) + out_fsl_bvec = File("dwi.bvecs", desc="exported fsl gradient bvec file") + out_fsl_bval = File("dwi.bvals", desc="exported fsl gradient bval file") + + +class DWIPreproc(MRTrix3Base): + """ + Perform diffusion image pre-processing using FSL's eddy tool; including inhomogeneity distortion correction using FSL's topup tool if possible + + For more information, see + + + Example + ------- + + >>> import nipype.interfaces.mrtrix3 as mrt + >>> preproc = mrt.DWIPreproc() + >>> preproc.inputs.in_file = 'dwi.mif' + >>> preproc.inputs.rpe_options = '-rpe_none' + >>> preproc.inputs.eddy_options = '"--slm=linear --repol"' + >>> preproc.inputs.out_file = "preproc.mif" + >>> preproc.inputs.grad_file = "dwi.b" + >>> preproc.inputs.ro_time = 0.165240 # 'TotalReadoutTime' in BIDS JSON metadata files + >>> preproc.inputs.pe_dir = 'j' # 'PhaseEncodingDirection' in BIDS JSON metadata files + >>> preproc.cmdline + `dwifslpreproc dwi.mif preproc.mif -eddy_options "--slm=linear " -rpe_none -pe_dir j -grad dwi.b -readout_time 0.165240` + """ + + _cmd = "dwifslpreproc" + input_spec = DWIPreprocInputSpec + output_spec = DWIPreprocOutputtSpec + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs["out_file"] = op.abspath(self.inputs.out_file) + if self.inputs.export_grad_mrtrix == True: + outputs["out_grad_mrtrix"] = op.abspath(self.inputs.out_grad_mrtrix) + if self.inputs.export_grad_fsl == True: + outputs["out_fsl_bvec"] = op.abspath(self.inputs.out_grad_fsl[0]) + outputs["out_fsl_bval"] = op.abspath(self.inputs.out_grad_fsl[1]) + + return outputs + + class ResponseSDInputSpec(MRTrix3BaseInputSpec): algorithm = traits.Enum( "msmt_5tt", From 7544744b2ec32a38fad58e0300f5fd647e10f2a6 Mon Sep 17 00:00:00 2001 From: Xihe Xie Date: Wed, 25 Nov 2020 21:49:40 -0500 Subject: [PATCH 02/14] use defaults added for outputs --- nipype/interfaces/mrtrix3/preprocess.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/nipype/interfaces/mrtrix3/preprocess.py b/nipype/interfaces/mrtrix3/preprocess.py index b29c54242a..feef9af418 100644 --- a/nipype/interfaces/mrtrix3/preprocess.py +++ b/nipype/interfaces/mrtrix3/preprocess.py @@ -299,10 +299,12 @@ class DWIPreprocInputSpec(MRTrix3BaseInputSpec): export_grad_fsl = traits.Bool( argstr="-export_grad_fsl", desc="export gradient files in FSL format" ) - out_grad_mrtrix = File("dwi.b", argstrt="%s", desc="name of new gradient file") + out_grad_mrtrix = File( + "dwi.b", argstr="%s", usedefault=True, desc="name of new gradient file" + ) out_grad_fsl = traits.Tuple( - File("dwi.bvecs", desc="bvecs"), - File("dwi.bvals", desc="bvals"), + File("dwi.bvecs", usedefault=True, desc="bvecs"), + File("dwi.bvals", usedefault=True, desc="bvals"), argstr="%s, %s", desc="Output (bvecs, bvals) gradients FSL format", ) @@ -313,8 +315,18 @@ class DWIPreprocOutputtSpec(TraitedSpec): out_grad_mrtrix = File( argstr="%s", desc="preprocessed gradient file in mrtrix3 format" ) - out_fsl_bvec = File("dwi.bvecs", desc="exported fsl gradient bvec file") - out_fsl_bval = File("dwi.bvals", desc="exported fsl gradient bval file") + out_fsl_bvec = File( + "dwi.bvecs", + argstr="%s", + usedefault=True, + desc="exported fsl gradient bvec file", + ) + out_fsl_bval = File( + "dwi.bvals", + argstr="%s", + usedefault=True, + desc="exported fsl gradient bval file", + ) class DWIPreproc(MRTrix3Base): From 33df5fc751f7458ade5308446eb4f11f3d50ce92 Mon Sep 17 00:00:00 2001 From: Xihe Xie Date: Sat, 28 Nov 2020 10:56:49 -0500 Subject: [PATCH 03/14] Added dwifslpreproc interface to __init__ --- nipype/interfaces/mrtrix3/__init__.py | 1 + nipype/interfaces/mrtrix3/preprocess.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/nipype/interfaces/mrtrix3/__init__.py b/nipype/interfaces/mrtrix3/__init__.py index f60e837310..53af56ef65 100644 --- a/nipype/interfaces/mrtrix3/__init__.py +++ b/nipype/interfaces/mrtrix3/__init__.py @@ -18,6 +18,7 @@ ResponseSD, ACTPrepareFSL, ReplaceFSwithFIRST, + DWIPreproc, DWIDenoise, MRDeGibbs, DWIBiasCorrect, diff --git a/nipype/interfaces/mrtrix3/preprocess.py b/nipype/interfaces/mrtrix3/preprocess.py index feef9af418..de2fdf610e 100644 --- a/nipype/interfaces/mrtrix3/preprocess.py +++ b/nipype/interfaces/mrtrix3/preprocess.py @@ -310,7 +310,7 @@ class DWIPreprocInputSpec(MRTrix3BaseInputSpec): ) -class DWIPreprocOutputtSpec(TraitedSpec): +class DWIPreprocOutputSpec(TraitedSpec): out_file = File(argstr="%s", desc="output preprocessed image series") out_grad_mrtrix = File( argstr="%s", desc="preprocessed gradient file in mrtrix3 format" @@ -354,7 +354,7 @@ class DWIPreproc(MRTrix3Base): _cmd = "dwifslpreproc" input_spec = DWIPreprocInputSpec - output_spec = DWIPreprocOutputtSpec + output_spec = DWIPreprocOutputSpec def _list_outputs(self): outputs = self.output_spec().get() From 30ab4ebb3cbbe9002fcccd06611b6d227889064a Mon Sep 17 00:00:00 2001 From: Xihe Xie Date: Sat, 28 Nov 2020 11:15:27 -0500 Subject: [PATCH 04/14] edited doc string to correct order --- nipype/interfaces/mrtrix3/preprocess.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nipype/interfaces/mrtrix3/preprocess.py b/nipype/interfaces/mrtrix3/preprocess.py index de2fdf610e..fe743b6ee5 100644 --- a/nipype/interfaces/mrtrix3/preprocess.py +++ b/nipype/interfaces/mrtrix3/preprocess.py @@ -343,13 +343,12 @@ class DWIPreproc(MRTrix3Base): >>> preproc = mrt.DWIPreproc() >>> preproc.inputs.in_file = 'dwi.mif' >>> preproc.inputs.rpe_options = '-rpe_none' - >>> preproc.inputs.eddy_options = '"--slm=linear --repol"' >>> preproc.inputs.out_file = "preproc.mif" >>> preproc.inputs.grad_file = "dwi.b" >>> preproc.inputs.ro_time = 0.165240 # 'TotalReadoutTime' in BIDS JSON metadata files >>> preproc.inputs.pe_dir = 'j' # 'PhaseEncodingDirection' in BIDS JSON metadata files >>> preproc.cmdline - `dwifslpreproc dwi.mif preproc.mif -eddy_options "--slm=linear " -rpe_none -pe_dir j -grad dwi.b -readout_time 0.165240` + `dwifslpreproc dwi.mif preproc.mif -rpe_none -pe_dir j -readout_time 0.165240 -grad dwi.b` """ _cmd = "dwifslpreproc" From 8fcf5ec63fc9398bdc66769f628784b2fa964239 Mon Sep 17 00:00:00 2001 From: Xihe Xie Date: Mon, 30 Nov 2020 11:50:16 -0500 Subject: [PATCH 05/14] added doctest skip --- nipype/interfaces/mrtrix3/preprocess.py | 1 + 1 file changed, 1 insertion(+) diff --git a/nipype/interfaces/mrtrix3/preprocess.py b/nipype/interfaces/mrtrix3/preprocess.py index fe743b6ee5..38b99cbcd6 100644 --- a/nipype/interfaces/mrtrix3/preprocess.py +++ b/nipype/interfaces/mrtrix3/preprocess.py @@ -349,6 +349,7 @@ class DWIPreproc(MRTrix3Base): >>> preproc.inputs.pe_dir = 'j' # 'PhaseEncodingDirection' in BIDS JSON metadata files >>> preproc.cmdline `dwifslpreproc dwi.mif preproc.mif -rpe_none -pe_dir j -readout_time 0.165240 -grad dwi.b` + >>> preproc.run() # doctest: +SKIP """ _cmd = "dwifslpreproc" From 2be461c726c586cfc28759a75d5daac5ffbff26d Mon Sep 17 00:00:00 2001 From: Xihe Xie Date: Mon, 30 Nov 2020 12:10:49 -0500 Subject: [PATCH 06/14] added MRtrix3 gradient empty test data --- nipype/testing/data/grad.b | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 nipype/testing/data/grad.b diff --git a/nipype/testing/data/grad.b b/nipype/testing/data/grad.b new file mode 100644 index 0000000000..e69de29bb2 From fb3f6194bac36bebf1440c373622f2c60bb41af7 Mon Sep 17 00:00:00 2001 From: Xihe Xie Date: Mon, 30 Nov 2020 12:11:51 -0500 Subject: [PATCH 07/14] specified positions, requires for gradient exports --- nipype/interfaces/mrtrix3/preprocess.py | 47 +++++++++++++++++-------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/nipype/interfaces/mrtrix3/preprocess.py b/nipype/interfaces/mrtrix3/preprocess.py index 38b99cbcd6..cb4fcadf26 100644 --- a/nipype/interfaces/mrtrix3/preprocess.py +++ b/nipype/interfaces/mrtrix3/preprocess.py @@ -245,13 +245,13 @@ def _format_arg(self, name, trait_spec, value): class DWIPreprocInputSpec(MRTrix3BaseInputSpec): in_file = File( - exists=True, argstr="%s", position=-5, mandatory=True, desc="input DWI image" + exists=True, argstr="%s", position=-6, mandatory=True, desc="input DWI image" ) out_file = File( "preproc.mif", argstr="%s", mandatory=True, - position=-4, + position=-5, usedefault=True, desc="output file after preprocessing", ) @@ -261,51 +261,66 @@ class DWIPreprocInputSpec(MRTrix3BaseInputSpec): "-rpe_all", "-rpe_header", argstr="%s", - position=-3, + position=-4, mandatory=True, desc="Specify acquisition phase-encoding design, one of the -rpe_* options must be provided", ) pe_dir = traits.Str( argstr="-pe_dir %s", - position=-2, + position=-3, mandatory=True, 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)", ) ro_time = traits.Float( argstr="-readout_time %f", - position=-1, + position=-2, desc="Total readout time of input series (in seconds)", ) in_epi = File( exists=True, argstr="-se_epi %s", + position=-1, 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)", ) align_seepi = traits.Bool( argstr="-align_seepi", + position=0, desc="Achieve alignment between the SE-EPI images used for inhomogeneity field estimation, and the DWIs", ) eddy_options = traits.Str( argstr="-eddy_options %s", + position=1, desc="-eddy_options ” EddyOptions” Manually provide additional command-line options to the eddy command (provide a string within quotation marks that contains at least one space, even if only passing a single command-line option to eddy)", ) topup_options = traits.Str( argstr="-topup_options %s", + position=1, desc="-topup_options ” TopupOptions” Manually provide additional command-line options to the topup command (provide a string within quotation marks that contains at least one space, even if only passing a single command-line option to topup)", ) export_grad_mrtrix = traits.Bool( - argstr="-export_grad_mrtrix", desc="export new gradientt files in mrtrix format" + argstr="-export_grad_mrtrix", + position=2, + desc="export new gradientt files in mrtrix format", ) export_grad_fsl = traits.Bool( - argstr="-export_grad_fsl", desc="export gradient files in FSL format" + argstr="-export_grad_fsl", + position=2, + desc="export gradient files in FSL format", ) out_grad_mrtrix = File( - "dwi.b", argstr="%s", usedefault=True, desc="name of new gradient file" + "grad.b", + argstr="%s", + usedefault=True, + position=3, + requires=["export_grad_mrtrix"], + desc="name of new gradient file", ) out_grad_fsl = traits.Tuple( - File("dwi.bvecs", usedefault=True, desc="bvecs"), - File("dwi.bvals", usedefault=True, desc="bvals"), + File("grad.bvecs", usedefault=True, desc="bvecs"), + File("grad.bvals", usedefault=True, desc="bvals"), argstr="%s, %s", + position=3, + requires=["export_grad_fsl"], desc="Output (bvecs, bvals) gradients FSL format", ) @@ -313,16 +328,19 @@ class DWIPreprocInputSpec(MRTrix3BaseInputSpec): class DWIPreprocOutputSpec(TraitedSpec): out_file = File(argstr="%s", desc="output preprocessed image series") out_grad_mrtrix = File( - argstr="%s", desc="preprocessed gradient file in mrtrix3 format" + "grad.b", + argstr="%s", + usedefault=True, + desc="preprocessed gradient file in mrtrix3 format", ) out_fsl_bvec = File( - "dwi.bvecs", + "grad.bvecs", argstr="%s", usedefault=True, desc="exported fsl gradient bvec file", ) out_fsl_bval = File( - "dwi.bvals", + "grad.bvals", argstr="%s", usedefault=True, desc="exported fsl gradient bval file", @@ -344,7 +362,8 @@ class DWIPreproc(MRTrix3Base): >>> preproc.inputs.in_file = 'dwi.mif' >>> preproc.inputs.rpe_options = '-rpe_none' >>> preproc.inputs.out_file = "preproc.mif" - >>> preproc.inputs.grad_file = "dwi.b" + >>> preproc.inputs.eddy_options = '"--slm=linear --repol"' + >>> preproc.inputs.export_grad_mrtrix = True # export final gradient table in MRtrix format >>> preproc.inputs.ro_time = 0.165240 # 'TotalReadoutTime' in BIDS JSON metadata files >>> preproc.inputs.pe_dir = 'j' # 'PhaseEncodingDirection' in BIDS JSON metadata files >>> preproc.cmdline From 4f4f9e50abcbee7c0751da1b62766ff0e338d057 Mon Sep 17 00:00:00 2001 From: Xihe Xie Date: Mon, 30 Nov 2020 12:49:54 -0500 Subject: [PATCH 08/14] finalized docstring example and pytest --- nipype/interfaces/mrtrix3/preprocess.py | 30 +++++----- .../mrtrix3/tests/test_auto_DWIPreproc.py | 55 +++++++++++++++++++ 2 files changed, 70 insertions(+), 15 deletions(-) create mode 100644 nipype/interfaces/mrtrix3/tests/test_auto_DWIPreproc.py diff --git a/nipype/interfaces/mrtrix3/preprocess.py b/nipype/interfaces/mrtrix3/preprocess.py index cb4fcadf26..f1ef381a2a 100644 --- a/nipype/interfaces/mrtrix3/preprocess.py +++ b/nipype/interfaces/mrtrix3/preprocess.py @@ -245,13 +245,13 @@ def _format_arg(self, name, trait_spec, value): class DWIPreprocInputSpec(MRTrix3BaseInputSpec): in_file = File( - exists=True, argstr="%s", position=-6, mandatory=True, desc="input DWI image" + exists=True, argstr="%s", position=-10, mandatory=True, desc="input DWI image" ) out_file = File( "preproc.mif", argstr="%s", mandatory=True, - position=-5, + position=-9, usedefault=True, desc="output file after preprocessing", ) @@ -261,57 +261,57 @@ class DWIPreprocInputSpec(MRTrix3BaseInputSpec): "-rpe_all", "-rpe_header", argstr="%s", - position=-4, + position=-8, mandatory=True, desc="Specify acquisition phase-encoding design, one of the -rpe_* options must be provided", ) pe_dir = traits.Str( argstr="-pe_dir %s", - position=-3, + position=-7, mandatory=True, 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)", ) ro_time = traits.Float( argstr="-readout_time %f", - position=-2, + position=-6, desc="Total readout time of input series (in seconds)", ) in_epi = File( exists=True, argstr="-se_epi %s", - position=-1, + position=-5, 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)", ) align_seepi = traits.Bool( argstr="-align_seepi", - position=0, + position=-4, desc="Achieve alignment between the SE-EPI images used for inhomogeneity field estimation, and the DWIs", ) eddy_options = traits.Str( argstr="-eddy_options %s", - position=1, + position=-3, desc="-eddy_options ” EddyOptions” Manually provide additional command-line options to the eddy command (provide a string within quotation marks that contains at least one space, even if only passing a single command-line option to eddy)", ) topup_options = traits.Str( argstr="-topup_options %s", - position=1, + position=-3, desc="-topup_options ” TopupOptions” Manually provide additional command-line options to the topup command (provide a string within quotation marks that contains at least one space, even if only passing a single command-line option to topup)", ) export_grad_mrtrix = traits.Bool( argstr="-export_grad_mrtrix", - position=2, + position=-2, desc="export new gradientt files in mrtrix format", ) export_grad_fsl = traits.Bool( argstr="-export_grad_fsl", - position=2, + position=-2, desc="export gradient files in FSL format", ) out_grad_mrtrix = File( "grad.b", argstr="%s", usedefault=True, - position=3, + position=-1, requires=["export_grad_mrtrix"], desc="name of new gradient file", ) @@ -319,7 +319,7 @@ class DWIPreprocInputSpec(MRTrix3BaseInputSpec): File("grad.bvecs", usedefault=True, desc="bvecs"), File("grad.bvals", usedefault=True, desc="bvals"), argstr="%s, %s", - position=3, + position=-1, requires=["export_grad_fsl"], desc="Output (bvecs, bvals) gradients FSL format", ) @@ -362,12 +362,12 @@ class DWIPreproc(MRTrix3Base): >>> preproc.inputs.in_file = 'dwi.mif' >>> preproc.inputs.rpe_options = '-rpe_none' >>> preproc.inputs.out_file = "preproc.mif" - >>> preproc.inputs.eddy_options = '"--slm=linear --repol"' + >>> preproc.inputs.eddy_options = '"--slm=linear --repol "' # linear second level model and replace outliers >>> preproc.inputs.export_grad_mrtrix = True # export final gradient table in MRtrix format >>> preproc.inputs.ro_time = 0.165240 # 'TotalReadoutTime' in BIDS JSON metadata files >>> preproc.inputs.pe_dir = 'j' # 'PhaseEncodingDirection' in BIDS JSON metadata files >>> preproc.cmdline - `dwifslpreproc dwi.mif preproc.mif -rpe_none -pe_dir j -readout_time 0.165240 -grad dwi.b` + 'dwifslpreproc dwi.mif preproc.mif -rpe_none -pe_dir j -readout_time 0.165240 -eddy_options "--slm=linear --repol " -export_grad_mrtrix grad.b' >>> preproc.run() # doctest: +SKIP """ diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_DWIPreproc.py b/nipype/interfaces/mrtrix3/tests/test_auto_DWIPreproc.py new file mode 100644 index 0000000000..55793a873b --- /dev/null +++ b/nipype/interfaces/mrtrix3/tests/test_auto_DWIPreproc.py @@ -0,0 +1,55 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from ..preprocess import DWIPreproc + + +def test_DWIPreproc_inputs(): + input_map = dict( + align_seepi=dict(argstr="-align_seepi", position=-4), + args=dict(argstr="%s"), + bval_scale=dict(argstr="-bvalue_scaling %s"), + eddy_options=dict(argstr="-eddy_options %s", position=-3), + environ=dict(nohash=True, usedefault=True), + export_grad_fsl=dict(argstr="-export_grad_fsl", position=-2), + export_grad_mrtrix=dict(argstr="-export_grad_mrtrix", position=-2), + grad_file=dict(argstr="-grad %s", extensions=None, xor=["grad_fsl"]), + grad_fsl=dict(argstr="-fslgrad %s %s", xor=["grad_file"]), + in_bval=dict(extensions=None), + in_bvec=dict(argstr="-fslgrad %s %s", extensions=None), + in_epi=dict(argstr="-se_epi %s", extensions=None, position=-5), + in_file=dict(argstr="%s", extensions=None, mandatory=True, position=-10), + nthreads=dict(argstr="-nthreads %d", nohash=True), + out_file=dict( + argstr="%s", extensions=None, mandatory=True, position=-9, usedefault=True + ), + out_grad_fsl=dict(argstr="%s, %s", position=-1, requires=["export_grad_fsl"]), + out_grad_mrtrix=dict( + argstr="%s", + extensions=None, + position=-1, + requires=["export_grad_mrtrix"], + usedefault=True, + ), + pe_dir=dict(argstr="-pe_dir %s", mandatory=True, position=-7), + ro_time=dict(argstr="-readout_time %f", position=-6), + rpe_options=dict(argstr="%s", mandatory=True, position=-8), + topup_options=dict(argstr="-topup_options %s", position=-3), + ) + inputs = DWIPreproc.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value + + +def test_DWIPreproc_outputs(): + output_map = dict( + out_file=dict(argstr="%s", extensions=None), + out_fsl_bval=dict(argstr="%s", extensions=None, usedefault=True), + out_fsl_bvec=dict(argstr="%s", extensions=None, usedefault=True), + out_grad_mrtrix=dict(argstr="%s", extensions=None, usedefault=True), + ) + outputs = DWIPreproc.output_spec() + + for key, metadata in list(output_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(outputs.traits()[key], metakey) == value From 983840c5657f34c203c02fbfdce5b723bf41a6d1 Mon Sep 17 00:00:00 2001 From: Xihe Xie Date: Mon, 30 Nov 2020 13:05:46 -0500 Subject: [PATCH 09/14] added entry to contribution list --- .zenodo.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.zenodo.json b/.zenodo.json index 0baed9eaa9..eb0bafe320 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -788,6 +788,11 @@ { "name": "Tambini, Arielle" }, + { + "affiliation": "Weill Cornell Medicine", + "name": "Xie, Xihe", + "orcid": "0000-0001-6595-2473" + }, { "affiliation": "Max Planck Institute for Human Cognitive and Brain Sciences, Leipzig, Germany.", "name": "Mihai, Paul Glad", From 7926025ad466dbab44508b508e53e98a538d1d39 Mon Sep 17 00:00:00 2001 From: Xihe Xie Date: Thu, 3 Dec 2020 14:55:30 -0500 Subject: [PATCH 10/14] simplify phase-encoding design input Moved `-rpe_` to `argstr` for simpler input. Co-authored-by: Chris Markiewicz --- nipype/interfaces/mrtrix3/preprocess.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/nipype/interfaces/mrtrix3/preprocess.py b/nipype/interfaces/mrtrix3/preprocess.py index f1ef381a2a..0a38f1a492 100644 --- a/nipype/interfaces/mrtrix3/preprocess.py +++ b/nipype/interfaces/mrtrix3/preprocess.py @@ -256,11 +256,11 @@ class DWIPreprocInputSpec(MRTrix3BaseInputSpec): desc="output file after preprocessing", ) rpe_options = traits.Enum( - "-rpe_none", - "-rpe_pair", - "-rpe_all", - "-rpe_header", - argstr="%s", + "none", + "pair", + "all", + "header", + argstr="-rpe_%s", position=-8, mandatory=True, desc="Specify acquisition phase-encoding design, one of the -rpe_* options must be provided", From e8bddbc9a72482c775429ee015428a1400d23718 Mon Sep 17 00:00:00 2001 From: Xihe Xie Date: Thu, 3 Dec 2020 15:12:47 -0500 Subject: [PATCH 11/14] Apply suggestions from code review Fixed typos and improved `-eddy` and `-topup` optional inputs. Co-authored-by: Chris Markiewicz --- nipype/interfaces/mrtrix3/preprocess.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/nipype/interfaces/mrtrix3/preprocess.py b/nipype/interfaces/mrtrix3/preprocess.py index 0a38f1a492..e24de6c702 100644 --- a/nipype/interfaces/mrtrix3/preprocess.py +++ b/nipype/interfaces/mrtrix3/preprocess.py @@ -288,19 +288,19 @@ class DWIPreprocInputSpec(MRTrix3BaseInputSpec): desc="Achieve alignment between the SE-EPI images used for inhomogeneity field estimation, and the DWIs", ) eddy_options = traits.Str( - argstr="-eddy_options %s", + argstr="-eddy_options \"%s\"", position=-3, - desc="-eddy_options ” EddyOptions” Manually provide additional command-line options to the eddy command (provide a string within quotation marks that contains at least one space, even if only passing a single command-line option to eddy)", + desc="Manually provide additional command-line options to the eddy command", ) topup_options = traits.Str( - argstr="-topup_options %s", + argstr="-topup_options \"%s\"", position=-3, - desc="-topup_options ” TopupOptions” Manually provide additional command-line options to the topup command (provide a string within quotation marks that contains at least one space, even if only passing a single command-line option to topup)", + desc="Manually provide additional command-line options to the topup command", ) export_grad_mrtrix = traits.Bool( argstr="-export_grad_mrtrix", position=-2, - desc="export new gradientt files in mrtrix format", + desc="export new gradient files in mrtrix format", ) export_grad_fsl = traits.Bool( argstr="-export_grad_fsl", @@ -360,14 +360,14 @@ class DWIPreproc(MRTrix3Base): >>> import nipype.interfaces.mrtrix3 as mrt >>> preproc = mrt.DWIPreproc() >>> preproc.inputs.in_file = 'dwi.mif' - >>> preproc.inputs.rpe_options = '-rpe_none' + >>> preproc.inputs.rpe_options = 'none' >>> preproc.inputs.out_file = "preproc.mif" - >>> preproc.inputs.eddy_options = '"--slm=linear --repol "' # linear second level model and replace outliers + >>> preproc.inputs.eddy_options = '--slm=linear --repol' # linear second level model and replace outliers >>> preproc.inputs.export_grad_mrtrix = True # export final gradient table in MRtrix format >>> preproc.inputs.ro_time = 0.165240 # 'TotalReadoutTime' in BIDS JSON metadata files >>> preproc.inputs.pe_dir = 'j' # 'PhaseEncodingDirection' in BIDS JSON metadata files >>> preproc.cmdline - 'dwifslpreproc dwi.mif preproc.mif -rpe_none -pe_dir j -readout_time 0.165240 -eddy_options "--slm=linear --repol " -export_grad_mrtrix grad.b' + 'dwifslpreproc dwi.mif preproc.mif -rpe_none -pe_dir j -readout_time 0.165240 -eddy_options "--slm=linear --repol" -export_grad_mrtrix grad.b' >>> preproc.run() # doctest: +SKIP """ @@ -378,9 +378,9 @@ class DWIPreproc(MRTrix3Base): def _list_outputs(self): outputs = self.output_spec().get() outputs["out_file"] = op.abspath(self.inputs.out_file) - if self.inputs.export_grad_mrtrix == True: + if self.inputs.export_grad_mrtrix: outputs["out_grad_mrtrix"] = op.abspath(self.inputs.out_grad_mrtrix) - if self.inputs.export_grad_fsl == True: + if self.inputs.export_grad_fsl: outputs["out_fsl_bvec"] = op.abspath(self.inputs.out_grad_fsl[0]) outputs["out_fsl_bval"] = op.abspath(self.inputs.out_grad_fsl[1]) From 4ac4e622f66753f559687fee9695d4e407fb5ebb Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Sun, 6 Dec 2020 16:08:39 -0500 Subject: [PATCH 12/14] Update nipype/interfaces/mrtrix3/preprocess.py Co-authored-by: Xihe Xie --- nipype/interfaces/mrtrix3/preprocess.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nipype/interfaces/mrtrix3/preprocess.py b/nipype/interfaces/mrtrix3/preprocess.py index e24de6c702..7f13d14a30 100644 --- a/nipype/interfaces/mrtrix3/preprocess.py +++ b/nipype/interfaces/mrtrix3/preprocess.py @@ -263,7 +263,7 @@ class DWIPreprocInputSpec(MRTrix3BaseInputSpec): argstr="-rpe_%s", position=-8, mandatory=True, - desc="Specify acquisition phase-encoding design, one of the -rpe_* options must be provided", + 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)", ) pe_dir = traits.Str( argstr="-pe_dir %s", From d33e9b4520ab1559ed1d7cfd9d850228cb218429 Mon Sep 17 00:00:00 2001 From: Xihe Xie Date: Mon, 7 Dec 2020 22:47:59 -0500 Subject: [PATCH 13/14] fixed input positions according to review --- nipype/interfaces/mrtrix3/preprocess.py | 28 ++++++------------- .../mrtrix3/tests/test_auto_DWIPreproc.py | 25 ++++++++--------- 2 files changed, 20 insertions(+), 33 deletions(-) diff --git a/nipype/interfaces/mrtrix3/preprocess.py b/nipype/interfaces/mrtrix3/preprocess.py index 7f13d14a30..dd215a4802 100644 --- a/nipype/interfaces/mrtrix3/preprocess.py +++ b/nipype/interfaces/mrtrix3/preprocess.py @@ -245,13 +245,13 @@ def _format_arg(self, name, trait_spec, value): class DWIPreprocInputSpec(MRTrix3BaseInputSpec): in_file = File( - exists=True, argstr="%s", position=-10, mandatory=True, desc="input DWI image" + exists=True, argstr="%s", position=0, mandatory=True, desc="input DWI image" ) out_file = File( "preproc.mif", argstr="%s", mandatory=True, - position=-9, + position=1, usedefault=True, desc="output file after preprocessing", ) @@ -261,57 +261,46 @@ class DWIPreprocInputSpec(MRTrix3BaseInputSpec): "all", "header", argstr="-rpe_%s", - position=-8, + position=2, mandatory=True, - 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)", + 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)', ) pe_dir = traits.Str( argstr="-pe_dir %s", - position=-7, mandatory=True, 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)", ) ro_time = traits.Float( argstr="-readout_time %f", - position=-6, desc="Total readout time of input series (in seconds)", ) in_epi = File( exists=True, argstr="-se_epi %s", - position=-5, 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)", ) align_seepi = traits.Bool( argstr="-align_seepi", - position=-4, desc="Achieve alignment between the SE-EPI images used for inhomogeneity field estimation, and the DWIs", ) eddy_options = traits.Str( - argstr="-eddy_options \"%s\"", - position=-3, + argstr='-eddy_options "%s"', desc="Manually provide additional command-line options to the eddy command", ) topup_options = traits.Str( - argstr="-topup_options \"%s\"", - position=-3, + argstr='-topup_options "%s"', desc="Manually provide additional command-line options to the topup command", ) export_grad_mrtrix = traits.Bool( - argstr="-export_grad_mrtrix", - position=-2, - desc="export new gradient files in mrtrix format", + argstr="-export_grad_mrtrix", desc="export new gradient files in mrtrix format" ) export_grad_fsl = traits.Bool( - argstr="-export_grad_fsl", - position=-2, - desc="export gradient files in FSL format", + argstr="-export_grad_fsl", desc="export gradient files in FSL format" ) out_grad_mrtrix = File( "grad.b", argstr="%s", usedefault=True, - position=-1, requires=["export_grad_mrtrix"], desc="name of new gradient file", ) @@ -319,7 +308,6 @@ class DWIPreprocInputSpec(MRTrix3BaseInputSpec): File("grad.bvecs", usedefault=True, desc="bvecs"), File("grad.bvals", usedefault=True, desc="bvals"), argstr="%s, %s", - position=-1, requires=["export_grad_fsl"], desc="Output (bvecs, bvals) gradients FSL format", ) diff --git a/nipype/interfaces/mrtrix3/tests/test_auto_DWIPreproc.py b/nipype/interfaces/mrtrix3/tests/test_auto_DWIPreproc.py index 55793a873b..76fae6548f 100644 --- a/nipype/interfaces/mrtrix3/tests/test_auto_DWIPreproc.py +++ b/nipype/interfaces/mrtrix3/tests/test_auto_DWIPreproc.py @@ -4,35 +4,34 @@ def test_DWIPreproc_inputs(): input_map = dict( - align_seepi=dict(argstr="-align_seepi", position=-4), + align_seepi=dict(argstr="-align_seepi"), args=dict(argstr="%s"), bval_scale=dict(argstr="-bvalue_scaling %s"), - eddy_options=dict(argstr="-eddy_options %s", position=-3), + eddy_options=dict(argstr='-eddy_options "%s"'), environ=dict(nohash=True, usedefault=True), - export_grad_fsl=dict(argstr="-export_grad_fsl", position=-2), - export_grad_mrtrix=dict(argstr="-export_grad_mrtrix", position=-2), + export_grad_fsl=dict(argstr="-export_grad_fsl"), + export_grad_mrtrix=dict(argstr="-export_grad_mrtrix"), grad_file=dict(argstr="-grad %s", extensions=None, xor=["grad_fsl"]), grad_fsl=dict(argstr="-fslgrad %s %s", xor=["grad_file"]), in_bval=dict(extensions=None), in_bvec=dict(argstr="-fslgrad %s %s", extensions=None), - in_epi=dict(argstr="-se_epi %s", extensions=None, position=-5), - in_file=dict(argstr="%s", extensions=None, mandatory=True, position=-10), + in_epi=dict(argstr="-se_epi %s", extensions=None), + in_file=dict(argstr="%s", extensions=None, mandatory=True, position=0), nthreads=dict(argstr="-nthreads %d", nohash=True), out_file=dict( - argstr="%s", extensions=None, mandatory=True, position=-9, usedefault=True + argstr="%s", extensions=None, mandatory=True, position=1, usedefault=True ), - out_grad_fsl=dict(argstr="%s, %s", position=-1, requires=["export_grad_fsl"]), + out_grad_fsl=dict(argstr="%s, %s", requires=["export_grad_fsl"]), out_grad_mrtrix=dict( argstr="%s", extensions=None, - position=-1, requires=["export_grad_mrtrix"], usedefault=True, ), - pe_dir=dict(argstr="-pe_dir %s", mandatory=True, position=-7), - ro_time=dict(argstr="-readout_time %f", position=-6), - rpe_options=dict(argstr="%s", mandatory=True, position=-8), - topup_options=dict(argstr="-topup_options %s", position=-3), + pe_dir=dict(argstr="-pe_dir %s", mandatory=True), + ro_time=dict(argstr="-readout_time %f"), + rpe_options=dict(argstr="-rpe_%s", mandatory=True, position=2), + topup_options=dict(argstr='-topup_options "%s"'), ) inputs = DWIPreproc.input_spec() From a1c43ad68e28a5063e3f04a87d48efe968ebda3a Mon Sep 17 00:00:00 2001 From: Xihe Xie Date: Mon, 7 Dec 2020 22:53:59 -0500 Subject: [PATCH 14/14] fixed doc string for new positions --- nipype/interfaces/mrtrix3/preprocess.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nipype/interfaces/mrtrix3/preprocess.py b/nipype/interfaces/mrtrix3/preprocess.py index dd215a4802..ef67365f0b 100644 --- a/nipype/interfaces/mrtrix3/preprocess.py +++ b/nipype/interfaces/mrtrix3/preprocess.py @@ -355,7 +355,7 @@ class DWIPreproc(MRTrix3Base): >>> preproc.inputs.ro_time = 0.165240 # 'TotalReadoutTime' in BIDS JSON metadata files >>> preproc.inputs.pe_dir = 'j' # 'PhaseEncodingDirection' in BIDS JSON metadata files >>> preproc.cmdline - 'dwifslpreproc dwi.mif preproc.mif -rpe_none -pe_dir j -readout_time 0.165240 -eddy_options "--slm=linear --repol" -export_grad_mrtrix grad.b' + 'dwifslpreproc dwi.mif preproc.mif -rpe_none -eddy_options "--slm=linear --repol" -export_grad_mrtrix grad.b -pe_dir j -readout_time 0.165240' >>> preproc.run() # doctest: +SKIP """