20
20
21
21
def generate_boutiques_descriptor (
22
22
module , interface_name , container_image , container_type , container_index = None ,
23
- verbose = False , save = False , save_path = None ):
23
+ verbose = False , save = False , save_path = None , author = None , ignore_inputs = None ):
24
24
'''
25
25
Returns a JSON string containing a JSON Boutiques description of a Nipype interface.
26
26
Arguments:
@@ -32,6 +32,8 @@ def generate_boutiques_descriptor(
32
32
* verbose: print information messages
33
33
* save: True if you want to save descriptor to a file
34
34
* save_path: file path for the saved descriptor (defaults to name of the interface in current directory)
35
+ * author: author of the tool (required for publishing)
36
+ * ignore_inputs: list of interface inputs to not include in the descriptor
35
37
'''
36
38
37
39
if not module :
@@ -53,7 +55,10 @@ def generate_boutiques_descriptor(
53
55
tool_desc = {}
54
56
tool_desc ['name' ] = interface_name
55
57
tool_desc [
56
- 'command-line' ] = "nipype_cmd " + module_name + " " + interface_name + " "
58
+ 'command-line' ] = interface_name + " "
59
+ tool_desc ['author' ] = "Nipype (interface)"
60
+ if author is not None :
61
+ tool_desc ['author' ] = tool_desc ['author' ] + ", " + author + " (tool)"
57
62
tool_desc [
58
63
'description' ] = interface_name + ", as implemented in Nipype (module: " + module_name + ", interface: " + interface_name + ")."
59
64
tool_desc ['inputs' ] = []
@@ -70,8 +75,10 @@ def generate_boutiques_descriptor(
70
75
71
76
# Generates tool inputs
72
77
for name , spec in sorted (interface .inputs .traits (transient = None ).items ()):
73
- input = get_boutiques_input (inputs , interface , name , spec , verbose )
78
+ input = get_boutiques_input (inputs , interface , name , spec , verbose , ignore_inputs = ignore_inputs )
74
79
# Handle compound inputs (inputs that can be of multiple types and are mutually exclusive)
80
+ if input is None :
81
+ continue
75
82
if isinstance (input , list ):
76
83
mutex_group_members = []
77
84
tool_desc ['command-line' ] += input [0 ]['value-key' ] + " "
@@ -91,9 +98,6 @@ def generate_boutiques_descriptor(
91
98
if verbose :
92
99
print ("-> Adding input " + input ['name' ])
93
100
94
- # Remove the extra space at the end of the command line
95
- tool_desc ['command-line' ] = tool_desc ['command-line' ].strip ()
96
-
97
101
# Generates input groups
98
102
tool_desc ['groups' ] += get_boutiques_groups (interface .inputs .traits (transient = None ).items ())
99
103
if len (tool_desc ['groups' ]) == 0 :
@@ -116,6 +120,9 @@ def generate_boutiques_descriptor(
116
120
if output ['path-template' ] == "" :
117
121
fill_in_missing_output_path (output , output ['name' ], tool_desc ['inputs' ])
118
122
123
+ # Remove the extra space at the end of the command line
124
+ tool_desc ['command-line' ] = tool_desc ['command-line' ].strip ()
125
+
119
126
# Save descriptor to a file
120
127
if save :
121
128
path = save_path if save_path is not None else os .path .join (os .getcwd (), interface_name + '.json' )
@@ -136,20 +143,24 @@ def generate_tool_outputs(outputs, interface, tool_desc, verbose, first_run):
136
143
# Otherwise, find the existing output and update its path template if it's still undefined.
137
144
if first_run :
138
145
tool_desc ['output-files' ].append (output )
146
+ if output .get ('value-key' ):
147
+ tool_desc ['command-line' ] += output ['value-key' ] + " "
139
148
if verbose :
140
149
print ("-> Adding output " + output ['name' ])
141
150
else :
142
151
for existing_output in tool_desc ['output-files' ]:
143
152
if output ['id' ] == existing_output ['id' ] and existing_output ['path-template' ] == "" :
144
153
existing_output ['path-template' ] = output ['path-template' ]
145
154
break
155
+ if output .get ('value-key' ) and output ['value-key' ] not in tool_desc ['command-line' ]:
156
+ tool_desc ['command-line' ] += output ['value-key' ] + " "
146
157
147
158
if len (tool_desc ['output-files' ]) == 0 :
148
159
raise Exception ("Tool has no output." )
149
160
150
161
151
- def get_boutiques_input (inputs , interface , input_name , spec ,
152
- verbose , handler = None , input_number = None ):
162
+ def get_boutiques_input (inputs , interface , input_name , spec , verbose , handler = None ,
163
+ input_number = None , ignore_inputs = None ):
153
164
"""
154
165
Returns a dictionary containing the Boutiques input corresponding to a Nipype intput.
155
166
@@ -161,11 +172,17 @@ def get_boutiques_input(inputs, interface, input_name, spec,
161
172
* verbose: print information messages.
162
173
* handler: used when handling compound inputs, which don't have their own input spec
163
174
* input_number: used when handling compound inputs to assign each a unique ID
175
+ * ignore_inputs: list of interface inputs to not include in the descriptor
164
176
165
177
Assumes that:
166
178
* Input names are unique.
167
179
"""
168
180
181
+ # If spec has a name source, means it's an output, so skip it here.
182
+ # Also skip any ignored inputs
183
+ if spec .name_source or ignore_inputs is not None and input_name in ignore_inputs :
184
+ return None
185
+
169
186
input = {}
170
187
171
188
if input_number is not None and input_number != 0 : # No need to append a number to the first of a list of compound inputs
@@ -339,12 +356,26 @@ def get_boutiques_output(outputs, name, spec, interface, tool_inputs):
339
356
output ['path-template' ] = "*"
340
357
return output
341
358
342
- # If an output value is defined, use its relative path
343
- # Otherwise, put blank string and try to fill it on another iteration
359
+ # If an output value is defined, use its relative path, if one exists.
360
+ # If no relative path, look for an input with the same name containing a name source
361
+ # and name template. Otherwise, put blank string as placeholder and try to fill it on
362
+ # another iteration.
363
+ output ['path-template' ] = ""
364
+
344
365
if output_value :
345
366
output ['path-template' ] = os .path .relpath (output_value )
346
367
else :
347
- output ['path-template' ] = ""
368
+ for inp_name , inp_spec in sorted (interface .inputs .traits (transient = None ).items ()):
369
+ if inp_name == name and inp_spec .name_source and inp_spec .name_template :
370
+ if isinstance (inp_spec .name_source , list ):
371
+ source = inp_spec .name_source [0 ]
372
+ else :
373
+ source = inp_spec .name_source
374
+ output ['path-template' ] = inp_spec .name_template .replace ("%s" , "[" + source .upper () + "]" )
375
+ output ['value-key' ] = "[" + name .upper () + "]"
376
+ if inp_spec .argstr and inp_spec .argstr .split ("%" )[0 ]:
377
+ output ['command-line-flag' ] = inp_spec .argstr .split ("%" )[0 ].strip ()
378
+ break
348
379
349
380
return output
350
381
0 commit comments