@@ -23,21 +23,35 @@ class Dcm2niiInputSpec(CommandLineInputSpec):
2323 copyfile = False , mandatory = True , xor = ['source_dir' ])
2424 source_dir = Directory (exists = True , argstr = "%s" , position = - 1 , mandatory = True ,
2525 xor = ['source_names' ])
26- anonymize = traits .Bool (True , argstr = '-a' , usedefault = True )
27- config_file = File (exists = True , argstr = "-b %s" , genfile = True )
28- collapse_folders = traits .Bool (True , argstr = '-c' , usedefault = True )
29- date_in_filename = traits .Bool (True , argstr = '-d' , usedefault = True )
30- events_in_filename = traits .Bool (True , argstr = '-e' , usedefault = True )
31- source_in_filename = traits .Bool (False , argstr = '-f' , usedefault = True )
32- gzip_output = traits .Bool (False , argstr = '-g' , usedefault = True )
33- id_in_filename = traits .Bool (False , argstr = '-i' , usedefault = True )
34- nii_output = traits .Bool (True , argstr = '-n' , usedefault = True )
35- output_dir = Directory (exists = True , argstr = '-o %s' , genfile = True )
36- protocol_in_filename = traits .Bool (True , argstr = '-p' , usedefault = True )
37- reorient = traits .Bool (argstr = '-r' )
38- spm_analyze = traits .Bool (argstr = '-s' , xor = ['nii_output' ])
39- convert_all_pars = traits .Bool (True , argstr = '-v' , usedefault = True )
40- reorient_and_crop = traits .Bool (False , argstr = '-x' , usedefault = True )
26+ anonymize = traits .Bool (True , argstr = '-a' , usedefault = True ,
27+ desc = "Remove identifying information" )
28+ config_file = File (exists = True , argstr = "-b %s" , genfile = True ,
29+ desc = "Load settings from specified inifile" )
30+ collapse_folders = traits .Bool (True , argstr = '-c' , usedefault = True ,
31+ desc = "Collapse input folders" )
32+ date_in_filename = traits .Bool (True , argstr = '-d' , usedefault = True ,
33+ desc = "Date in filename" )
34+ events_in_filename = traits .Bool (True , argstr = '-e' , usedefault = True ,
35+ desc = "Events (series/acq) in filename" )
36+ source_in_filename = traits .Bool (False , argstr = '-f' , usedefault = True ,
37+ desc = "Source filename" )
38+ gzip_output = traits .Bool (False , argstr = '-g' , usedefault = True ,
39+ desc = "Gzip output (.gz)" )
40+ id_in_filename = traits .Bool (False , argstr = '-i' , usedefault = True ,
41+ desc = "ID in filename" )
42+ nii_output = traits .Bool (True , argstr = '-n' , usedefault = True ,
43+ desc = "Save as .nii - if no, create .hdr/.img pair" )
44+ output_dir = Directory (exists = True , argstr = '-o %s' , genfile = True ,
45+ desc = "Output dir - if unspecified, source directory is used" )
46+ protocol_in_filename = traits .Bool (True , argstr = '-p' , usedefault = True ,
47+ desc = "Protocol in filename" )
48+ reorient = traits .Bool (argstr = '-r' , desc = "Reorient image to nearest orthogonal" )
49+ spm_analyze = traits .Bool (argstr = '-s' , xor = ['nii_output' ],
50+ desc = "SPM2/Analyze not SPM5/NIfTI" )
51+ convert_all_pars = traits .Bool (True , argstr = '-v' , usedefault = True ,
52+ desc = "Convert every image in directory" )
53+ reorient_and_crop = traits .Bool (False , argstr = '-x' , usedefault = True ,
54+ desc = "Reorient and crop 3D images" )
4155
4256
4357class Dcm2niiOutputSpec (TraitedSpec ):
@@ -185,3 +199,125 @@ def _gen_filename(self, name):
185199 f .close ()
186200 return config_file
187201 return None
202+
203+
204+ class Dcm2niixInputSpec (CommandLineInputSpec ):
205+ source_names = InputMultiPath (File (exists = True ), argstr = "%s" , position = - 1 ,
206+ copyfile = False , mandatory = True , xor = ['source_dir' ])
207+ source_dir = Directory (exists = True , argstr = "%s" , position = - 1 , mandatory = True ,
208+ xor = ['source_names' ])
209+ out_filename = traits .Str ('%t%p' , argstr = "-f %s" , usedefault = True ,
210+ desc = "Output filename" )
211+ output_dir = Directory (exists = True , argstr = '-o %s' , genfile = True ,
212+ desc = "Output directory" )
213+ bids_format = traits .Bool (True , argstr = '-b' , usedefault = True ,
214+ desc = "Create a BIDS sidecar file" )
215+ compress = traits .Enum ('i' , ['y' ,'i' ,'n' ], argstr = '-z %s' , usedefault = True ,
216+ desc = "Gzip compress images - [y=pigz, i=internal, n=no]" )
217+ merge_imgs = traits .Bool (False , argstr = '-m' , usedefault = True ,
218+ desc = "merge 2D slices from same series" )
219+ single_file = traits .Bool (False , argstr = '-s' , usedefault = True ,
220+ desc = "Convert only one image (filename as last input" )
221+ verbose = traits .Bool (False , argstr = '-v' , usedefault = True ,
222+ desc = "Verbose output" )
223+
224+
225+ class Dcm2niixOutputSpec (TraitedSpec ):
226+ converted_files = OutputMultiPath (File (exists = True ))
227+ bvecs = OutputMultiPath (File (exists = True ))
228+ bvals = OutputMultiPath (File (exists = True ))
229+ bids = OutputMultiPath (File (exists = True ))
230+
231+
232+ class Dcm2niix (CommandLine ):
233+ """Uses Chris Rorden's dcm2niix to convert dicom files
234+ Examples
235+ ========
236+ >>> from nipype.interfaces.dcm2nii import Dcm2niix
237+ >>> converter = Dcm2niix()
238+ >>> converter.inputs.source_names = ['functional_1.dcm', 'functional_2.dcm']
239+ >>> converter.inputs.compress = 'i'
240+ >>> converter.inputs.single_file = True
241+ >>> converter.inputs.output_dir = '.'
242+ >>> converter.cmdline
243+ 'dcm2niix -b y -z i -m n -f %t%p -o . -s y -v n functional_1.dcm'
244+ """
245+
246+ input_spec = Dcm2niixInputSpec
247+ output_spec = Dcm2niixOutputSpec
248+ _cmd = 'dcm2niix'
249+
250+ def _format_arg (self , opt , spec , val ):
251+ if opt in ['bids_format' , 'merge_imgs' , 'single_file' , 'verbose' ]:
252+ spec = deepcopy (spec )
253+ if val :
254+ spec .argstr += ' y'
255+ else :
256+ spec .argstr += ' n'
257+ val = True
258+ if opt == 'source_names' :
259+ return spec .argstr % val [0 ]
260+ return super (Dcm2niix , self )._format_arg (opt , spec , val )
261+
262+ def _run_interface (self , runtime ):
263+ new_runtime = super (Dcm2niix , self )._run_interface (runtime )
264+ if self .inputs .bids_format :
265+ (self .output_files , self .bvecs ,
266+ self .bvals , self .bids ) = self ._parse_stdout (new_runtime .stdout )
267+ else :
268+ (self .output_files , self .bvecs ,
269+ self .bvals ) = self ._parse_stdout (new_runtime .stdout )
270+ return new_runtime
271+
272+ def _parse_stdout (self , stdout ):
273+ files = []
274+ bvecs = []
275+ bvals = []
276+ bids = []
277+ skip = False
278+ find_b = False
279+ for line in stdout .split ("\n " ):
280+ if not skip :
281+ out_file = None
282+ if line .startswith ("Convert " ): # output
283+ fname = str (re .search ('\S+/\S+' , line ).group (0 ))
284+ if isdefined (self .inputs .output_dir ):
285+ output_dir = self .inputs .output_dir
286+ else :
287+ output_dir = self ._gen_filename ('output_dir' )
288+ out_file = os .path .abspath (os .path .join (output_dir , fname ))
289+ # extract bvals
290+ if find_b :
291+ bvecs .append (out_file + ".bvec" )
292+ bvals .append (out_file + ".bval" )
293+ find_b = False
294+ # next scan will have bvals/bvecs
295+ elif 'DTI gradient directions' in line :
296+ find_b = True
297+ else :
298+ pass
299+ if out_file :
300+ files .append (out_file + ".nii.gz" )
301+ if self .inputs .bids_format :
302+ bids .append (out_file + ".bids" )
303+ continue
304+ skip = False
305+ # just return what was done
306+ if not bids :
307+ return files , bvecs , bvals
308+ else :
309+ return files , bvecs , bvals , bids
310+
311+ def _list_outputs (self ):
312+ outputs = self .output_spec ().get ()
313+ outputs ['converted_files' ] = self .output_files
314+ outputs ['bvecs' ] = self .bvecs
315+ outputs ['bvals' ] = self .bvals
316+ if self .inputs .bids_format :
317+ outputs ['bids' ] = self .bids
318+ return outputs
319+
320+ def _gen_filename (self , name ):
321+ if name == 'output_dir' :
322+ return os .getcwd ()
323+ return None
0 commit comments