1010
1111from ..utils .filemanip import split_filename
1212from .base import (CommandLine , CommandLineInputSpec , InputMultiPath , traits ,
13- TraitedSpec , OutputMultiPath , isdefined , File , Directory )
13+ TraitedSpec , OutputMultiPath , isdefined , File , Directory ,
14+ PackageInfo )
15+
16+
17+ class Info (PackageInfo ):
18+ """Handle dcm2niix version information"""
19+
20+ version_cmd = 'dcm2niix'
21+
22+ @staticmethod
23+ def parse_version (raw_info ):
24+ m = re .search (r'version (\S+)' , raw_info )
25+ return m .groups ()[0 ] if m else None
1426
1527
1628class Dcm2niiInputSpec (CommandLineInputSpec ):
@@ -251,6 +263,8 @@ class Dcm2niixInputSpec(CommandLineInputSpec):
251263 argstr = "%s" ,
252264 position = - 1 ,
253265 copyfile = False ,
266+ deprecated = '1.0.2' ,
267+ new_name = 'source_dir' ,
254268 mandatory = True ,
255269 xor = ['source_dir' ])
256270 source_dir = Directory (
@@ -260,16 +274,28 @@ class Dcm2niixInputSpec(CommandLineInputSpec):
260274 mandatory = True ,
261275 xor = ['source_names' ])
262276 out_filename = traits .Str (
263- '%t%p' , argstr = "-f %s" , usedefault = True , desc = "Output filename" )
277+ argstr = "-f %s" ,
278+ desc = "Output filename" )
264279 output_dir = Directory (
265- exists = True , argstr = '-o %s' , genfile = True , desc = "Output directory" )
280+ "." ,
281+ usedefault = True ,
282+ exists = True ,
283+ argstr = '-o %s' ,
284+ desc = "Output directory" )
266285 bids_format = traits .Bool (
267- True , argstr = '-b' , usedefault = True , desc = "Create a BIDS sidecar file" )
286+ True ,
287+ argstr = '-b' ,
288+ usedefault = True ,
289+ desc = "Create a BIDS sidecar file" )
290+ anon_bids = traits .Bool (
291+ argstr = '-ba' ,
292+ requires = ["bids_format" ],
293+ desc = "Anonymize BIDS" )
268294 compress = traits .Enum (
269- 'i ' , [ 'y ' , 'i ' , 'n' ] ,
295+ 'y ' , 'i ' , 'n ' , '3' ,
270296 argstr = '-z %s' ,
271297 usedefault = True ,
272- desc = "Gzip compress images - [y=pigz, i=internal, n=no]" )
298+ desc = "Gzip compress images - [y=pigz, i=internal, n=no, 3=no,3D ]" )
273299 merge_imgs = traits .Bool (
274300 False ,
275301 argstr = '-m' ,
@@ -279,16 +305,39 @@ class Dcm2niixInputSpec(CommandLineInputSpec):
279305 False ,
280306 argstr = '-s' ,
281307 usedefault = True ,
282- desc = "Convert only one image (filename as last input " )
308+ desc = "Single file mode " )
283309 verbose = traits .Bool (
284- False , argstr = '-v' , usedefault = True , desc = "Verbose output" )
310+ False ,
311+ argstr = '-v' ,
312+ usedefault = True ,
313+ desc = "Verbose output" )
285314 crop = traits .Bool (
286- False , argstr = '-x' , usedefault = True , desc = "Crop 3D T1 acquisitions" )
315+ False ,
316+ argstr = '-x' ,
317+ usedefault = True ,
318+ desc = "Crop 3D T1 acquisitions" )
287319 has_private = traits .Bool (
288320 False ,
289321 argstr = '-t' ,
290322 usedefault = True ,
291323 desc = "Flag if text notes includes private patient details" )
324+ compression = traits .Enum (
325+ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ,
326+ argstr = '-%d' ,
327+ desc = "Gz compression level (1=fastest, 9=smallest)" )
328+ comment = traits .Str (
329+ argstr = '-c %s' ,
330+ desc = "Comment stored as NIfTI aux_file" )
331+ ignore_deriv = traits .Bool (
332+ argstr = '-i' ,
333+ desc = "Ignore derived, localizer and 2D images" )
334+ series_numbers = InputMultiPath (
335+ traits .Str (),
336+ argstr = '-n %s...' ,
337+ desc = "Selectively convert by series number - can be used up to 16 times" )
338+ philips_float = traits .Bool (
339+ argstr = '-p' ,
340+ desc = "Philips precise float (not display) scaling" )
292341
293342
294343class Dcm2niixOutputSpec (TraitedSpec ):
@@ -306,27 +355,26 @@ class Dcm2niix(CommandLine):
306355
307356 >>> from nipype.interfaces.dcm2nii import Dcm2niix
308357 >>> converter = Dcm2niix()
309- >>> converter.inputs.source_names = ['functional_1.dcm', 'functional_2.dcm']
310- >>> converter.inputs.compress = 'i'
311- >>> converter.inputs.single_file = True
312- >>> converter.inputs.output_dir = '.'
313- >>> converter.cmdline # doctest: +SKIP
314- 'dcm2niix -b y -z i -x n -t n -m n -f %t%p -o . -s y -v n functional_1.dcm'
315-
316- >>> flags = '-'.join([val.strip() + ' ' for val in sorted(' '.join(converter.cmdline.split()[1:-1]).split('-'))])
317- >>> flags
318- ' -b y -f %t%p -m n -o . -s y -t n -v n -x n -z i '
358+ >>> converter.inputs.source_dir = 'dicomdir'
359+ >>> converter.inputs.compression = 5
360+ >>> converter.inputs.output_dir = 'ds005'
361+ >>> converter.cmdline
362+ 'dcm2niix -b y -z y -5 -x n -t n -m n -o ds005 -s n -v n dicomdir'
363+ >>> converter.run() # doctest: +SKIP
319364 """
320365
321366 input_spec = Dcm2niixInputSpec
322367 output_spec = Dcm2niixOutputSpec
323368 _cmd = 'dcm2niix'
324369
370+ @property
371+ def version (self ):
372+ return Info .version ()
373+
325374 def _format_arg (self , opt , spec , val ):
326- if opt in [
327- 'bids_format' , 'merge_imgs' , 'single_file' , 'verbose' , 'crop' ,
328- 'has_private'
329- ]:
375+ bools = ['bids_format' , 'merge_imgs' , 'single_file' , 'verbose' , 'crop' ,
376+ 'has_private' , 'anon_bids' , 'ignore_deriv' , 'philips_float' ]
377+ if opt in bools :
330378 spec = deepcopy (spec )
331379 if val :
332380 spec .argstr += ' y'
@@ -338,14 +386,16 @@ def _format_arg(self, opt, spec, val):
338386 return super (Dcm2niix , self )._format_arg (opt , spec , val )
339387
340388 def _run_interface (self , runtime ):
341- new_runtime = super (Dcm2niix , self )._run_interface (runtime )
389+ # may use return code 1 despite conversion
390+ runtime = super (Dcm2niix , self )._run_interface (
391+ runtime , correct_return_codes = (0 , 1 , ))
342392 if self .inputs .bids_format :
343393 (self .output_files , self .bvecs , self .bvals ,
344- self .bids ) = self ._parse_stdout (new_runtime .stdout )
394+ self .bids ) = self ._parse_stdout (runtime .stdout )
345395 else :
346396 (self .output_files , self .bvecs , self .bvals ) = self ._parse_stdout (
347- new_runtime .stdout )
348- return new_runtime
397+ runtime .stdout )
398+ return runtime
349399
350400 def _parse_stdout (self , stdout ):
351401 files = []
@@ -359,11 +409,7 @@ def _parse_stdout(self, stdout):
359409 out_file = None
360410 if line .startswith ("Convert " ): # output
361411 fname = str (re .search ('\S+/\S+' , line ).group (0 ))
362- if isdefined (self .inputs .output_dir ):
363- output_dir = self .inputs .output_dir
364- else :
365- output_dir = self ._gen_filename ('output_dir' )
366- out_file = os .path .abspath (os .path .join (output_dir , fname ))
412+ out_file = os .path .abspath (fname )
367413 # extract bvals
368414 if find_b :
369415 bvecs .append (out_file + ".bvec" )
@@ -372,16 +418,11 @@ def _parse_stdout(self, stdout):
372418 # next scan will have bvals/bvecs
373419 elif 'DTI gradients' in line or 'DTI gradient directions' in line or 'DTI vectors' in line :
374420 find_b = True
375- else :
376- pass
377421 if out_file :
378- if self .inputs .compress == 'n' :
379- files .append (out_file + ".nii" )
380- else :
381- files .append (out_file + ".nii.gz" )
422+ ext = '.nii' if self .inputs .compress == 'n' else '.nii.gz'
423+ files .append (out_file + ext )
382424 if self .inputs .bids_format :
383425 bids .append (out_file + ".json" )
384- continue
385426 skip = False
386427 # just return what was done
387428 if not bids :
@@ -397,8 +438,3 @@ def _list_outputs(self):
397438 if self .inputs .bids_format :
398439 outputs ['bids' ] = self .bids
399440 return outputs
400-
401- def _gen_filename (self , name ):
402- if name == 'output_dir' :
403- return os .getcwd ()
404- return None
0 commit comments