Skip to content

ENH: Adds interfaces for MRtrix utils shconv and sh2amp #3280

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
Jun 16, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
1f3d251
added predicted_signal option to tensor
tclose Sep 29, 2020
a9a8904
added SHConv and SH2Amp interfaces to mrtrix utils
tclose Dec 2, 2020
ac7490c
added name to authors list
tclose Dec 2, 2020
974ca38
touched up docs and made commands inherit from commandline instead of…
tclose Dec 2, 2020
ccd25c6
changed isdefined checks of EstimateFOD and check
tclose Dec 2, 2020
f245ba4
fixed up doctest strings and added dummy files
tclose Dec 2, 2020
c81259b
run black over touched files
tclose Dec 2, 2020
ab96460
ran make specs
tclose Dec 2, 2020
cd4bbc6
fixed up doctest failure
tclose Dec 2, 2020
35a762f
Update nipype/interfaces/mrtrix3/reconst.py
tclose May 6, 2021
7e670ff
Update nipype/interfaces/mrtrix3/utils.py
tclose May 6, 2021
8671983
Update nipype/interfaces/mrtrix3/utils.py
tclose May 6, 2021
308436d
Update nipype/interfaces/mrtrix3/utils.py
tclose May 6, 2021
f4eefeb
Update nipype/interfaces/mrtrix3/utils.py
tclose May 6, 2021
70e3bcf
Update nipype/interfaces/mrtrix3/utils.py
tclose May 6, 2021
a6e440d
Update nipype/interfaces/mrtrix3/utils.py
tclose May 6, 2021
5266a7c
Update nipype/interfaces/mrtrix3/utils.py
tclose May 6, 2021
c5d7ffe
Update nipype/interfaces/mrtrix3/utils.py
tclose May 6, 2021
fd8cc40
Update nipype/interfaces/mrtrix3/utils.py
tclose Jun 11, 2021
76ccb77
Update nipype/interfaces/mrtrix3/utils.py
tclose Jun 11, 2021
af8e01f
Update nipype/interfaces/mrtrix3/utils.py
tclose Jun 11, 2021
f698f4b
Update nipype/interfaces/mrtrix3/utils.py
tclose Jun 11, 2021
5e5ffbf
Merge branch 'master' of github.com:nipy/nipype into predicted_signal
tclose Jun 11, 2021
e096c19
TEST: make specs
effigies Jun 15, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .zenodo.json
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,11 @@
{
"name": "Marina, Ana"
},
{
"affiliation": "University of Sydney",
"name": "Close, Thomas",
"orcid": "0000-0002-4160-2134"
},
{
"name": "Davison, Andrew"
},
Expand Down
2 changes: 2 additions & 0 deletions nipype/interfaces/mrtrix3/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
MRConvert,
MRResize,
DWIExtract,
SHConv,
SH2Amp
)
from .preprocess import (
ResponseSD,
Expand Down
21 changes: 20 additions & 1 deletion nipype/interfaces/mrtrix3/reconst.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

import os.path as op

from ..base import traits, TraitedSpec, File, Undefined, InputMultiObject
from ..base import (
traits, TraitedSpec, File, Undefined, InputMultiObject, isdefined)
from .base import MRTrix3BaseInputSpec, MRTrix3Base


Expand Down Expand Up @@ -50,10 +51,16 @@ class FitTensorInputSpec(MRTrix3BaseInputSpec):
"only applies to the non-linear methods"
),
)
predicted_signal = File(
argstr='-predicted_signal %s',
desc=(
"specify a file to contain the predicted signal from the tensor "
"fits. This can be used to calculate the residual signal"))


class FitTensorOutputSpec(TraitedSpec):
out_file = File(exists=True, desc="the output DTI file")
predicted_signal = File(desc="Predicted signal from fitted tensors")


class FitTensor(MRTrix3Base):
Expand Down Expand Up @@ -81,6 +88,9 @@ class FitTensor(MRTrix3Base):
def _list_outputs(self):
outputs = self.output_spec().get()
outputs["out_file"] = op.abspath(self.inputs.out_file)
if isdefined(self.inputs.predicted_signal):
outputs['predicted_signal'] = op.abspath(
self.inputs.predicted_signal)
return outputs


Expand Down Expand Up @@ -144,12 +154,18 @@ class EstimateFODInputSpec(MRTrix3BaseInputSpec):
"[ az el ] pairs for the directions."
),
)
predicted_signal = File(
argstr='-predicted_signal %s',
desc=(
"specify a file to contain the predicted signal from the FOD "
"estimates. This can be used to calculate the residual signal"))


class EstimateFODOutputSpec(TraitedSpec):
wm_odf = File(argstr="%s", desc="output WM ODF")
gm_odf = File(argstr="%s", desc="output GM ODF")
csf_odf = File(argstr="%s", desc="output CSF ODF")
predicted_signal = File(desc="output predicted signal")


class EstimateFOD(MRTrix3Base):
Expand Down Expand Up @@ -187,6 +203,9 @@ def _list_outputs(self):
outputs["gm_odf"] = op.abspath(self.inputs.gm_odf)
if self.inputs.csf_odf != Undefined:
outputs["csf_odf"] = op.abspath(self.inputs.csf_odf)
if self.inputs.predicted_signal != Undefined:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume that you're being consistent with the rest of this function. If you feel the urge, you can fix up the others, but I think we should do this the standard way.

Suggested change
if self.inputs.predicted_signal != Undefined:
if isdefined(self.inputs.predicted_signal):

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On this interface, I remembered that 'predicted_signal' is only a valid option when using the 'msmt_csd' algorithm. Is there a way to specify this in the input spec?

outputs["predicted_signal"] = op.abspath(
self.inputs.predicted_signal)
return outputs


Expand Down
129 changes: 129 additions & 0 deletions nipype/interfaces/mrtrix3/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -765,3 +765,132 @@ class MRResize(MRTrix3Base):
_cmd = "mrresize"
input_spec = MRResizeInputSpec
output_spec = MRResizeOutputSpec


class SHConvInputSpec(CommandLineInputSpec):

in_file = File(
exists=True,
argstr="%s",
mandatory=True,
position=-3,
desc="input ODF image",
)

# General options
response = File(
exists=True,
mandatory=True,
argstr="%s",
position=-2,
desc=("The response function"),
)

out_file = File(
"sh.mif",
argstr="%s",
mandatory=True,
position=-1,
usedefault=True,
desc="the output spherical harmonics",
)


class SHConvOutputSpec(TraitedSpec):
out_file = File(exists=True,
desc="the output convoluted spherical harmonics file")


class SHConv(CommandLine):
"""
Convolve spherical harmonics with a tissue response function. Useful for
checking residuals of ODF estimates.


Example
-------

>>> import nipype.interfaces.mrtrix3 as mrt
>>> sh = mrt.SHConv()
>>> sh.inputs.in_file = 'odf.mif'
>>> sh.inputs.response = 'response.txt'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These files should exist in https://github.com/nipy/nipype/tree/master/nipype/testing/data. If there isn't already one with a name that works for this tool, feel free to create an empty file with that name.

>>> sh.cmdline # doctest: +ELLIPSIS
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No ... appears in the output line.

Suggested change
>>> sh.cmdline # doctest: +ELLIPSIS
>>> sh.cmdline

'shconv odf.mif response.txt sh.mif'
>>> sh.run() # doctest: +SKIP
"""

_cmd = "shconv"
input_spec = SHConvInputSpec
output_spec = SHConvOutputSpec

def _list_outputs(self):
outputs = self.output_spec().get()
outputs["out_file"] = op.abspath(self.inputs.out_file)
return outputs



class SH2AmpInputSpec(CommandLineInputSpec):
in_file = File(
exists=True,
argstr="%s",
mandatory=True,
position=-3,
desc="input ODF image",
)

# General options
directions = File(
exists=True,
mandatory=True,
argstr="%s",
position=-2,
desc=("The gradient directions along which to sample the spherical "
"harmonics MRtrix format"),
)

out_file = File(
"amp.mif",
argstr="%s",
mandatory=True,
position=-1,
usedefault=True,
desc="the output spherical harmonics",
)

nonnegative = traits.Bool(
argstr='-nonnegative',
desc="cap all negative amplitudes to zero")


class SH2AmpOutputSpec(TraitedSpec):
out_file = File(exists=True,
desc="the output convoluted spherical harmonics file")


class SH2Amp(CommandLine):
"""
Sample spherical harmonics on a set of gradient orientations. Useful for
checking residuals of ODF estimates.


Example
-------

>>> import nipype.interfaces.mrtrix3 as mrt
>>> sh = mrt.SH2Amp()
>>> sh.inputs.in_file = 'sh.mif'
>>> sh.inputs.directions = 'grads.txt'
>>> sh.cmdline # doctest: +ELLIPSIS
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
>>> sh.cmdline # doctest: +ELLIPSIS
>>> sh.cmdline

'sh2amp sh.mif grads.txt amp.mif'
>>> sh.run() # doctest: +SKIP
"""

_cmd = "sh2amp"
input_spec = SH2AmpInputSpec
output_spec = SH2AmpOutputSpec

def _list_outputs(self):
outputs = self.output_spec().get()
outputs["out_file"] = op.abspath(self.inputs.out_file)
return outputs