10
10
11
11
from ..utils .filemanip import split_filename
12
12
from .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
14
26
15
27
16
28
class Dcm2niiInputSpec (CommandLineInputSpec ):
@@ -251,6 +263,8 @@ class Dcm2niixInputSpec(CommandLineInputSpec):
251
263
argstr = "%s" ,
252
264
position = - 1 ,
253
265
copyfile = False ,
266
+ deprecated = '1.0.2' ,
267
+ new_name = 'source_dir' ,
254
268
mandatory = True ,
255
269
xor = ['source_dir' ])
256
270
source_dir = Directory (
@@ -260,16 +274,28 @@ class Dcm2niixInputSpec(CommandLineInputSpec):
260
274
mandatory = True ,
261
275
xor = ['source_names' ])
262
276
out_filename = traits .Str (
263
- '%t%p' , argstr = "-f %s" , usedefault = True , desc = "Output filename" )
277
+ argstr = "-f %s" ,
278
+ desc = "Output filename" )
264
279
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" )
266
285
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" )
268
294
compress = traits .Enum (
269
- 'i ' , [ 'y ' , 'i ' , 'n' ] ,
295
+ 'y ' , 'i ' , 'n ' , '3' ,
270
296
argstr = '-z %s' ,
271
297
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 ]" )
273
299
merge_imgs = traits .Bool (
274
300
False ,
275
301
argstr = '-m' ,
@@ -279,16 +305,39 @@ class Dcm2niixInputSpec(CommandLineInputSpec):
279
305
False ,
280
306
argstr = '-s' ,
281
307
usedefault = True ,
282
- desc = "Convert only one image (filename as last input " )
308
+ desc = "Single file mode " )
283
309
verbose = traits .Bool (
284
- False , argstr = '-v' , usedefault = True , desc = "Verbose output" )
310
+ False ,
311
+ argstr = '-v' ,
312
+ usedefault = True ,
313
+ desc = "Verbose output" )
285
314
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" )
287
319
has_private = traits .Bool (
288
320
False ,
289
321
argstr = '-t' ,
290
322
usedefault = True ,
291
323
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" )
292
341
293
342
294
343
class Dcm2niixOutputSpec (TraitedSpec ):
@@ -306,27 +355,26 @@ class Dcm2niix(CommandLine):
306
355
307
356
>>> from nipype.interfaces.dcm2nii import Dcm2niix
308
357
>>> 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
319
364
"""
320
365
321
366
input_spec = Dcm2niixInputSpec
322
367
output_spec = Dcm2niixOutputSpec
323
368
_cmd = 'dcm2niix'
324
369
370
+ @property
371
+ def version (self ):
372
+ return Info .version ()
373
+
325
374
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 :
330
378
spec = deepcopy (spec )
331
379
if val :
332
380
spec .argstr += ' y'
@@ -338,14 +386,16 @@ def _format_arg(self, opt, spec, val):
338
386
return super (Dcm2niix , self )._format_arg (opt , spec , val )
339
387
340
388
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 , ))
342
392
if self .inputs .bids_format :
343
393
(self .output_files , self .bvecs , self .bvals ,
344
- self .bids ) = self ._parse_stdout (new_runtime .stdout )
394
+ self .bids ) = self ._parse_stdout (runtime .stdout )
345
395
else :
346
396
(self .output_files , self .bvecs , self .bvals ) = self ._parse_stdout (
347
- new_runtime .stdout )
348
- return new_runtime
397
+ runtime .stdout )
398
+ return runtime
349
399
350
400
def _parse_stdout (self , stdout ):
351
401
files = []
@@ -359,11 +409,7 @@ def _parse_stdout(self, stdout):
359
409
out_file = None
360
410
if line .startswith ("Convert " ): # output
361
411
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 )
367
413
# extract bvals
368
414
if find_b :
369
415
bvecs .append (out_file + ".bvec" )
@@ -372,16 +418,11 @@ def _parse_stdout(self, stdout):
372
418
# next scan will have bvals/bvecs
373
419
elif 'DTI gradients' in line or 'DTI gradient directions' in line or 'DTI vectors' in line :
374
420
find_b = True
375
- else :
376
- pass
377
421
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 )
382
424
if self .inputs .bids_format :
383
425
bids .append (out_file + ".json" )
384
- continue
385
426
skip = False
386
427
# just return what was done
387
428
if not bids :
@@ -397,8 +438,3 @@ def _list_outputs(self):
397
438
if self .inputs .bids_format :
398
439
outputs ['bids' ] = self .bids
399
440
return outputs
400
-
401
- def _gen_filename (self , name ):
402
- if name == 'output_dir' :
403
- return os .getcwd ()
404
- return None
0 commit comments