Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 6314fde

Browse files
Merge pull request #2936 from mgxd/enh/dcm2niix
RF: dcm2niix interface
2 parents 500d8de + 1f0b85c commit 6314fde

File tree

5 files changed

+57
-46
lines changed

5 files changed

+57
-46
lines changed

‎docker/generate_dockerfiles.sh‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,11 @@ function generate_base_dockerfile() {
6868
--spm12 version=r7219 \
6969
--env 'LD_LIBRARY_PATH=/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH' \
7070
--freesurfer version=6.0.0-min \
71+
--dcm2niix version=v1.0.20190902 method=source \
7172
--run 'echo "cHJpbnRmICJrcnp5c3p0b2YuZ29yZ29sZXdza2lAZ21haWwuY29tCjUxNzIKICpDdnVtdkVWM3pUZmcKRlM1Si8yYzFhZ2c0RQoiID4gL29wdC9mcmVlc3VyZmVyLTYuMC4wLW1pbi9saWNlbnNlLnR4dA==" | base64 -d | sh' \
7273
--install afni ants apt-utils bzip2 convert3d file fsl-core \
7374
fsl-mni152-templates fusefat g++ git graphviz make python ruby \
74-
unzip xvfb \
75+
unzip xvfb git-annex-standalone liblzma-dev \
7576
--add-to-entrypoint "source /etc/fsl/fsl.sh && source /etc/afni/afni.sh" \
7677
--env ANTSPATH='/usr/lib/ants' \
7778
PATH='/usr/lib/ants:$PATH' \

‎nipype/info.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ def get_nipype_gitversion():
182182
]
183183

184184
EXTRA_REQUIRES = {
185+
'data': ['datalad'],
185186
'doc': ['Sphinx>=1.4', 'numpydoc', 'matplotlib', 'pydotplus', 'pydot>=1.2.3'],
186187
'duecredit': ['duecredit'],
187188
'nipy': ['nitime', 'nilearn<0.5.0', 'dipy', 'nipy', 'matplotlib'],

‎nipype/interfaces/dcm2nii.py‎

Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import os
88
import re
99
from copy import deepcopy
10+
import itertools as it
11+
from glob import iglob
1012

1113
from ..utils.filemanip import split_filename
1214
from .base import (CommandLine, CommandLineInputSpec, InputMultiPath, traits,
@@ -328,7 +330,7 @@ class Dcm2niixInputSpec(CommandLineInputSpec):
328330
False,
329331
argstr='-t',
330332
usedefault=True,
331-
desc="Flag if text notes include private patient details")
333+
desc="Text notes including private patient details")
332334
compression = traits.Enum(
333335
1, 2, 3, 4, 5, 6, 7, 8, 9,
334336
argstr='-%d',
@@ -346,6 +348,9 @@ class Dcm2niixInputSpec(CommandLineInputSpec):
346348
philips_float = traits.Bool(
347349
argstr='-p',
348350
desc="Philips precise float (not display) scaling")
351+
to_nrrd = traits.Bool(
352+
argstr="-e",
353+
desc="Export as NRRD instead of NIfTI")
349354

350355

351356
class Dcm2niixOutputSpec(TraitedSpec):
@@ -393,8 +398,11 @@ def version(self):
393398
return Info.version()
394399

395400
def _format_arg(self, opt, spec, val):
396-
bools = ['bids_format', 'merge_imgs', 'single_file', 'verbose', 'crop',
397-
'has_private', 'anon_bids', 'ignore_deriv', 'philips_float']
401+
bools = [
402+
'bids_format', 'merge_imgs', 'single_file', 'verbose', 'crop',
403+
'has_private', 'anon_bids', 'ignore_deriv', 'philips_float',
404+
'to_nrrd',
405+
]
398406
if opt in bools:
399407
spec = deepcopy(spec)
400408
if val:
@@ -410,52 +418,54 @@ def _run_interface(self, runtime):
410418
# may use return code 1 despite conversion
411419
runtime = super(Dcm2niix, self)._run_interface(
412420
runtime, correct_return_codes=(0, 1, ))
413-
if self.inputs.bids_format:
414-
(self.output_files, self.bvecs, self.bvals,
415-
self.bids) = self._parse_stdout(runtime.stdout)
416-
else:
417-
(self.output_files, self.bvecs, self.bvals) = self._parse_stdout(
418-
runtime.stdout)
421+
self._parse_files(self._parse_stdout(runtime.stdout))
419422
return runtime
420423

421424
def _parse_stdout(self, stdout):
422-
files = []
423-
bvecs = []
424-
bvals = []
425-
bids = []
426-
skip = False
427-
find_b = False
425+
filenames = []
428426
for line in stdout.split("\n"):
429-
if not skip:
430-
out_file = None
431-
if line.startswith("Convert "): # output
432-
fname = str(re.search('\S+/\S+', line).group(0))
433-
out_file = os.path.abspath(fname)
434-
# extract bvals
435-
if find_b:
436-
bvecs.append(out_file + ".bvec")
437-
bvals.append(out_file + ".bval")
438-
find_b = False
439-
# next scan will have bvals/bvecs
440-
elif 'DTI gradients' in line or 'DTI gradient directions' in line or 'DTI vectors' in line:
441-
find_b = True
442-
if out_file:
443-
ext = '.nii' if self.inputs.compress == 'n' else '.nii.gz'
444-
files.append(out_file + ext)
445-
if self.inputs.bids_format:
446-
bids.append(out_file + ".json")
447-
skip = False
448-
# just return what was done
449-
if not bids:
450-
return files, bvecs, bvals
427+
if line.startswith("Convert "): # output
428+
fname = str(re.search(r'\S+/\S+', line).group(0))
429+
filenames.append(os.path.abspath(fname))
430+
return filenames
431+
432+
def _parse_files(self, filenames):
433+
outfiles, bvals, bvecs, bids = [], [], [], []
434+
outtypes = [".bval", ".bvec", ".json", ".txt"]
435+
if self.inputs.to_nrrd:
436+
outtypes += [".nrrd", ".nhdr", ".raw.gz"]
451437
else:
452-
return files, bvecs, bvals, bids
438+
outtypes += [".nii", ".nii.gz"]
439+
440+
for filename in filenames:
441+
# search for relevant files, and sort accordingly
442+
for fl in search_files(filename, outtypes):
443+
if (
444+
fl.endswith(".nii") or
445+
fl.endswith(".gz") or
446+
fl.endswith(".nrrd") or
447+
fl.endswith(".nhdr")
448+
):
449+
outfiles.append(fl)
450+
elif fl.endswith(".bval"):
451+
bvals.append(fl)
452+
elif fl.endswith(".bvec"):
453+
bvecs.append(fl)
454+
elif fl.endswith(".json") or fl.endswith(".txt"):
455+
bids.append(fl)
456+
self.output_files = outfiles
457+
self.bvecs = bvecs
458+
self.bvals = bvals
459+
self.bids = bids
453460

454461
def _list_outputs(self):
455462
outputs = self.output_spec().get()
456463
outputs['converted_files'] = self.output_files
457464
outputs['bvecs'] = self.bvecs
458465
outputs['bvals'] = self.bvals
459-
if self.inputs.bids_format:
460-
outputs['bids'] = self.bids
466+
outputs['bids'] = self.bids
461467
return outputs
468+
469+
# https://stackoverflow.com/a/4829130
470+
def search_files(prefix, outtypes):
471+
return it.chain.from_iterable(iglob(prefix + outtype) for outtype in outtypes)

‎nipype/interfaces/tests/test_auto_Dcm2niix.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ def test_Dcm2niix_inputs():
6161
position=-1,
6262
xor=['source_dir'],
6363
),
64+
to_nrrd=dict(argstr='-e', ),
6465
verbose=dict(
6566
argstr='-v',
6667
usedefault=True,

‎nipype/interfaces/tests/test_extra_dcm2nii.py‎

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,15 @@ def assert_dwi(eg, bids):
4141
# ensure all outputs are of equal lengths
4242
assert len(set(map(len, outputs))) == 1
4343
else:
44-
assert not eg2.outputs.bids
44+
assert not eg.outputs.bids
4545

4646
dcm = Dcm2niix()
4747
dcm.inputs.source_dir = datadir
4848
dcm.inputs.out_filename = '%u%z'
49-
eg1 = dcm.run()
50-
assert_dwi(eg1, True)
49+
assert_dwi(dcm.run(), True)
5150

5251
# now run specifying output directory and removing BIDS option
5352
outdir = tmpdir.mkdir('conversion').strpath
5453
dcm.inputs.output_dir = outdir
5554
dcm.inputs.bids_format = False
56-
eg2 = dcm.run()
57-
assert_dwi(eg2, False)
55+
assert_dwi(dcm.run(), False)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /