Skip to content

[ENH] added interface for dcm2niix #1435

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 25 commits into from
Apr 27, 2016
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
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
1 change: 1 addition & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Next release
============

* ENH: Added dcm2niix interface (https://github.com/nipy/nipype/pull/1435)
* ENH: Add nipype_crash_search command (https://github.com/nipy/nipype/pull/1422)
* ENH: Created interface for BrainSuite Cortical Surface Extraction command line tools (https://github.com/nipy/nipype/pull/1305)
* FIX: job execution on systems/approaches where locale is undefined (https://github.com/nipy/nipype/pull/1401)
Expand Down
109 changes: 109 additions & 0 deletions nipype/interfaces/dcm2nii.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,112 @@ def _gen_filename(self, name):
f.close()
return config_file
return None


class Dcm2niixInputSpec(CommandLineInputSpec):
source_names = InputMultiPath(File(exists=True), argstr="%s", position=-1,
copyfile=False, mandatory=True, xor=['source_dir'])
Copy link
Member

Choose a reason for hiding this comment

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

desc missing for all inputs.

Copy link
Member

Choose a reason for hiding this comment

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

i know dcm2nii didn't have any either. but that should be fixed as well.

source_dir = Directory(exists=True, argstr="%s", position=-1, mandatory=True,
xor=['source_names'])
out_filename = traits.Str('%t%p', argstr="-f %s", usedefault=True)
output_dir = Directory(exists=True, argstr='-o %s', genfile=True)
bids_format = traits.Bool(True, argstr='-b', usedefault=True)
compress = traits.Enum('i', ['y','i','n'], argstr='-z %s', usedefault=True)
merge_imgs = traits.Bool(False, argstr='-m', usedefault=True)
single_file = traits.Bool(False, argstr='-s', usedefault=True)
verbose = traits.Bool(False, argstr='-v', usedefault=True)


class Dcm2niixOutputSpec(TraitedSpec):
converted_files = OutputMultiPath(File(exists=True))
bvecs = OutputMultiPath(File(exists=True))
bvals = OutputMultiPath(File(exists=True))
bids = OutputMultiPath(File(exists=True))


class Dcm2niix(CommandLine):
"""Uses Chris Rorden's dcm2niix to convert dicom files
Examples
========
>>> from nipype.interfaces.dcm2nii import Dcm2niix
>>> converter = Dcm2niix()
>>> converter.inputs.source_names = ['functional_1.dcm', 'functional_2.dcm']
>>> converter.inputs.compress = 'i'
>>> converter.inputs.output_dir = '.'
>>> converter.cmdline
'dcm2niix -b y -z i -m n -f %t%p -o . -s n -v n functional_1.dcm'
"""

input_spec = Dcm2niixInputSpec
output_spec = Dcm2niixOutputSpec
_cmd = 'dcm2niix'

def _format_arg(self, opt, spec, val):
if opt in ['bids_format', 'merge_imgs', 'single_file', 'verbose']:
spec = deepcopy(spec)
if val:
spec.argstr += ' y'
else:
spec.argstr += ' n'
val = True
if opt == 'source_names':
return spec.argstr % val[0]
return super(Dcm2niix, self)._format_arg(opt, spec, val)

def _run_interface(self, runtime):
new_runtime = super(Dcm2niix, self)._run_interface(runtime)
(self.output_files,
self.bvecs, self.bvals, self.bids) = self._parse_stdout(new_runtime.stdout)
Copy link
Member

Choose a reason for hiding this comment

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

have you tested this with and without the bids option?

return new_runtime

def _parse_stdout(self, stdout):
files = []
bvecs = []
bvals = []
bids = []
skip = False
find_b = False
for line in stdout.split("\n"):
if not skip:
out_file = None
if line.startswith("Convert "): # output
fname = str(re.search('\S+/\S+', line).group(0))
if isdefined(self.inputs.output_dir):
output_dir = self.inputs.output_dir
else:
output_dir = self._gen_filename('output_dir')
out_file = os.path.abspath(os.path.join(output_dir, fname))
# extract bvals
if find_b:
bvecs.append(out_file + ".bvec")
bvals.append(out_file + ".bval")
find_b = False
# next scan will have bvals/bvecs
elif 'DTI gradient directions' in line:
find_b = True
else:
pass
if out_file:
files.append(out_file + ".nii.gz")
if self.inputs.bids_format:
bids.append(out_file + ".bids")
continue
skip = False
# just return what was done
if not bids:
return files, bvecs, bvals
else:
return files, bvecs, bvals, bids

def _list_outputs(self):
outputs = self.output_spec().get()
outputs['converted_files'] = self.output_files
outputs['bvecs'] = self.bvecs
outputs['bvals'] = self.bvals
outputs['bids'] = self.bids
return outputs

def _gen_filename(self, name):
if name == 'output_dir':
return os.getcwd()
return None