1+ import attrs
12from pathlib import Path
23from pydra import ShellCommandTask
34from pydra .engine .specs import ShellSpec , ShellOutSpec , File , Directory , SpecInfo
45
56
6- def dcm2niix_out_file (out_dir , filename , echo , suffix , compress ):
7- # Append echo number of NIfTI echo to select is provided
8- if suffix :
9- file_suffix = "_" + suffix
10- elif echo :
11- file_suffix = f"_e{ echo } "
12- else :
13- file_suffix = ""
14-
15- out_file = f"{ out_dir } /{ filename } { file_suffix } .nii"
16-
17- # If compressed, append the zip extension
18- if compress in ("y" , "o" , "i" ):
19- out_file += ".gz"
7+ def out_file_path (out_dir , filename , file_postfix , ext ):
8+ """Attempting to handle the different suffixes that are appended to filenames
9+ created by Dcm2niix (see https://github.com/rordenlab/dcm2niix/blob/master/FILENAMING.md)
10+ """
2011
21- out_file = Path (out_file ).absolute ()
12+ fpath = Path (out_dir ) / (filename + (file_postfix if file_postfix else "" ) + ext )
13+ fpath = fpath .absolute ()
2214
2315 # Check to see if multiple echos exist in the DICOM dataset
24- if not out_file .exists ():
25- echoes = [
26- str (p )
27- for p in out_file .parent .iterdir ()
28- if p .stem .startswith (filename + "_e" )
29- ]
30- if echoes :
16+ if not fpath .exists ():
17+ if file_postfix is not None : # NB: doesn't match attrs.NOTHING
18+ neighbours = [
19+ str (p ) for p in fpath .parent .iterdir () if p .name .endswith (ext )
20+ ]
3121 raise ValueError (
32- "DICOM dataset contains multiple echos, please specify which "
33- "echo you want via the 'echo' input:\n "
34- "\n " .join (echoes )
22+ f"\n Did not find expected file '{ fpath } ' (file_postfix={ file_postfix } ) "
23+ "after DICOM -> NIfTI conversion, please see "
24+ "https://github.com/rordenlab/dcm2niix/blob/master/FILENAMING.md for the "
25+ "list of postfixes that dcm2niix produces and provide an appropriate "
26+ "postfix, or set postfix to None to ignore matching a single file and use "
27+ "the list returned in 'out_files' instead. Found the following files "
28+ "with matching extensions:\n " + "\n " .join (neighbours )
3529 )
30+ else :
31+ fpath = attrs .NOTHING # Did not find output path and
32+
33+ return fpath
3634
37- return out_file
3835
36+ def dcm2niix_out_file (out_dir , filename , file_postfix , compress ):
3937
40- def dcm2niix_out_json (out_dir , filename , echo ):
38+ ext = ".nii"
39+ # If compressed, append the zip extension
40+ if compress in ("y" , "o" , "i" ):
41+ ext += ".gz"
42+
43+ return out_file_path (out_dir , filename , file_postfix , ext )
44+
45+
46+ def dcm2niix_out_json (out_dir , filename , file_postfix , bids ):
4147 # Append echo number of NIfTI echo to select is provided
42- if echo :
43- echo_suffix = f"_e { echo } "
48+ if bids is attrs . NOTHING or bids in ( "y" , "o" ) :
49+ fpath = out_file_path ( out_dir , filename , file_postfix , ".json" )
4450 else :
45- echo_suffix = ""
51+ fpath = attrs .NOTHING
52+ return fpath
53+
4654
47- return Path (f"{ out_dir } /{ filename } { echo_suffix } .json" ).absolute ()
55+ def dcm2niix_out_files (out_dir , filename ):
56+ return [
57+ str (p .absolute ())
58+ for p in Path (out_dir ).iterdir ()
59+ if p .name .startswith (filename )
60+ ]
4861
4962
5063input_fields = [
@@ -74,31 +87,19 @@ def dcm2niix_out_json(out_dir, filename, echo):
7487 {"argstr" : "-f '{filename}'" , "help_string" : "The output name for the file" },
7588 ),
7689 (
77- "echo" ,
78- int ,
79- {
80- "argstr" : "" ,
81- "help_string" : (
82- "The echo number to extract from the DICOM dataset. When multiple "
83- "echoes are discovered in the dataset then dcm2niix will create "
84- "separate files for each echo with the suffix '_e<echo-number>.nii'"
85- ),
86- "xor" : ["suffix" ],
87- },
88- ),
89- (
90- "suffix" ,
90+ "file_postfix" ,
9191 str ,
9292 {
93- "argstr" : "" ,
9493 "help_string" : (
95- "A suffix to append to the out_file, used to select which "
96- "of the disambiguated outputs to return (see https://github.com/"
94+ "The postfix appended to the output filename. Used to select which "
95+ "of the disambiguated nifti files created by dcm2niix to return "
96+ "in this field (see https://github.com/"
9797 "rordenlab/dcm2niix/blob/master/FILENAMING.md"
98- "#file-name-post-fixes-image-disambiguation) "
98+ "#file-name-post-fixes-image-disambiguation). Set to None to skip "
99+ "matching a single file (out_file will be set to attrs.NOTHING if the "
100+ "base path without postfixes doesn't exist) and handle the list of "
101+ "output files returned in 'out_files' instead."
99102 ),
100- "xor" : ["echo" ],
101- "allowed_values" : ["Eq" , "ph" , "imaginary" , "MoCo" , "real" , "phMag" ],
102103 },
103104 ),
104105 (
@@ -350,7 +351,13 @@ def dcm2niix_out_json(out_dir, filename, echo):
350351 "out_file" ,
351352 File ,
352353 {
353- "help_string" : "output NIfTI image" ,
354+ "help_string" : (
355+ "output NIfTI image. If multiple nifti files are created (e.g. for "
356+ "different echoes), then the 'file_postfix' input can be provided to "
357+ "select which of them is considered the 'out_file'. Otherwise it "
358+ "should be set to None and 'out_files' used instead (in which case "
359+ "'out_file' will be set to attrs.NOTHING)" ,
360+ ),
354361 "callable" : dcm2niix_out_file ,
355362 "mandatory" : True ,
356363 },
@@ -359,7 +366,7 @@ def dcm2niix_out_json(out_dir, filename, echo):
359366 "out_json" ,
360367 File ,
361368 {
362- "help_string" : "output BIDS side-car JSON" ,
369+ "help_string" : "output BIDS side-car JSON corresponding to 'out_file' " ,
363370 # "requires": [("bids", 'y')], FIXME: should be either 'y' or 'o'
364371 "callable" : dcm2niix_out_json ,
365372 },
@@ -380,6 +387,18 @@ def dcm2niix_out_json(out_dir, filename, echo):
380387 "output_file_template" : "{out_dir}/{filename}.bvec" ,
381388 },
382389 ),
390+ (
391+ "out_files" ,
392+ list ,
393+ {
394+ "help_string" : (
395+ "all output files in a list, including files disambiguated "
396+ "by their suffixes (e.g. echoes, phase-maps, etc... see "
397+ "https://github.com/rordenlab/dcm2niix/blob/master/FILENAMING.md"
398+ ),
399+ "callable" : dcm2niix_out_files ,
400+ },
401+ ),
383402]
384403
385404Dcm2NiixOutputSpec = SpecInfo (
0 commit comments