7
7
import os
8
8
import re
9
9
from copy import deepcopy
10
+ import itertools as it
11
+ from glob import iglob
10
12
11
13
from ..utils .filemanip import split_filename
12
14
from .base import (CommandLine , CommandLineInputSpec , InputMultiPath , traits ,
@@ -328,7 +330,7 @@ class Dcm2niixInputSpec(CommandLineInputSpec):
328
330
False ,
329
331
argstr = '-t' ,
330
332
usedefault = True ,
331
- desc = "Flag if text notes include private patient details" )
333
+ desc = "Text notes including private patient details" )
332
334
compression = traits .Enum (
333
335
1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ,
334
336
argstr = '-%d' ,
@@ -346,6 +348,9 @@ class Dcm2niixInputSpec(CommandLineInputSpec):
346
348
philips_float = traits .Bool (
347
349
argstr = '-p' ,
348
350
desc = "Philips precise float (not display) scaling" )
351
+ to_nrrd = traits .Bool (
352
+ argstr = "-e" ,
353
+ desc = "Export as NRRD instead of NIfTI" )
349
354
350
355
351
356
class Dcm2niixOutputSpec (TraitedSpec ):
@@ -393,8 +398,11 @@ def version(self):
393
398
return Info .version ()
394
399
395
400
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
+ ]
398
406
if opt in bools :
399
407
spec = deepcopy (spec )
400
408
if val :
@@ -410,52 +418,54 @@ def _run_interface(self, runtime):
410
418
# may use return code 1 despite conversion
411
419
runtime = super (Dcm2niix , self )._run_interface (
412
420
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 ))
419
422
return runtime
420
423
421
424
def _parse_stdout (self , stdout ):
422
- files = []
423
- bvecs = []
424
- bvals = []
425
- bids = []
426
- skip = False
427
- find_b = False
425
+ filenames = []
428
426
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" ]
451
437
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
453
460
454
461
def _list_outputs (self ):
455
462
outputs = self .output_spec ().get ()
456
463
outputs ['converted_files' ] = self .output_files
457
464
outputs ['bvecs' ] = self .bvecs
458
465
outputs ['bvals' ] = self .bvals
459
- if self .inputs .bids_format :
460
- outputs ['bids' ] = self .bids
466
+ outputs ['bids' ] = self .bids
461
467
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