77import os
88import re
99from copy import deepcopy
10+ import itertools as it
11+ from glob import iglob
1012
1113from ..utils .filemanip import split_filename
1214from .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
351356class 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 )
0 commit comments