1
+ import attrs
1
2
from pathlib import Path
2
3
from pydra import ShellCommandTask
3
4
from pydra .engine .specs import ShellSpec , ShellOutSpec , File , Directory , SpecInfo
4
5
5
6
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
+ """
20
11
21
- out_file = Path (out_file ).absolute ()
12
+ fpath = Path (out_dir ) / (filename + (file_postfix if file_postfix else "" ) + ext )
13
+ fpath = fpath .absolute ()
22
14
23
15
# 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
+ ]
31
21
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 )
35
29
)
30
+ else :
31
+ fpath = attrs .NOTHING # Did not find output path and
32
+
33
+ return fpath
36
34
37
- return out_file
38
35
36
+ def dcm2niix_out_file (out_dir , filename , file_postfix , compress ):
39
37
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 ):
41
47
# 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" )
44
50
else :
45
- echo_suffix = ""
51
+ fpath = attrs .NOTHING
52
+ return fpath
53
+
46
54
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
+ ]
48
61
49
62
50
63
input_fields = [
@@ -74,31 +87,19 @@ def dcm2niix_out_json(out_dir, filename, echo):
74
87
{"argstr" : "-f '{filename}'" , "help_string" : "The output name for the file" },
75
88
),
76
89
(
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" ,
91
91
str ,
92
92
{
93
- "argstr" : "" ,
94
93
"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/"
97
97
"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."
99
102
),
100
- "xor" : ["echo" ],
101
- "allowed_values" : ["Eq" , "ph" , "imaginary" , "MoCo" , "real" , "phMag" ],
102
103
},
103
104
),
104
105
(
@@ -350,7 +351,13 @@ def dcm2niix_out_json(out_dir, filename, echo):
350
351
"out_file" ,
351
352
File ,
352
353
{
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
+ ),
354
361
"callable" : dcm2niix_out_file ,
355
362
"mandatory" : True ,
356
363
},
@@ -359,7 +366,7 @@ def dcm2niix_out_json(out_dir, filename, echo):
359
366
"out_json" ,
360
367
File ,
361
368
{
362
- "help_string" : "output BIDS side-car JSON" ,
369
+ "help_string" : "output BIDS side-car JSON corresponding to 'out_file' " ,
363
370
# "requires": [("bids", 'y')], FIXME: should be either 'y' or 'o'
364
371
"callable" : dcm2niix_out_json ,
365
372
},
@@ -380,6 +387,18 @@ def dcm2niix_out_json(out_dir, filename, echo):
380
387
"output_file_template" : "{out_dir}/{filename}.bvec" ,
381
388
},
382
389
),
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
+ ),
383
402
]
384
403
385
404
Dcm2NiixOutputSpec = SpecInfo (
0 commit comments