2020
2121def generate_boutiques_descriptor (
2222 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 ):
2424 '''
2525 Returns a JSON string containing a JSON Boutiques description of a Nipype interface.
2626 Arguments:
@@ -32,6 +32,8 @@ def generate_boutiques_descriptor(
3232 * verbose: print information messages
3333 * save: True if you want to save descriptor to a file
3434 * 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
3537 '''
3638
3739 if not module :
@@ -53,7 +55,10 @@ def generate_boutiques_descriptor(
5355 tool_desc = {}
5456 tool_desc ['name' ] = interface_name
5557 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)"
5762 tool_desc [
5863 'description' ] = interface_name + ", as implemented in Nipype (module: " + module_name + ", interface: " + interface_name + ")."
5964 tool_desc ['inputs' ] = []
@@ -70,8 +75,10 @@ def generate_boutiques_descriptor(
7075
7176 # Generates tool inputs
7277 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 )
7479 # Handle compound inputs (inputs that can be of multiple types and are mutually exclusive)
80+ if input is None :
81+ continue
7582 if isinstance (input , list ):
7683 mutex_group_members = []
7784 tool_desc ['command-line' ] += input [0 ]['value-key' ] + " "
@@ -91,9 +98,6 @@ def generate_boutiques_descriptor(
9198 if verbose :
9299 print ("-> Adding input " + input ['name' ])
93100
94- # Remove the extra space at the end of the command line
95- tool_desc ['command-line' ] = tool_desc ['command-line' ].strip ()
96-
97101 # Generates input groups
98102 tool_desc ['groups' ] += get_boutiques_groups (interface .inputs .traits (transient = None ).items ())
99103 if len (tool_desc ['groups' ]) == 0 :
@@ -116,6 +120,9 @@ def generate_boutiques_descriptor(
116120 if output ['path-template' ] == "" :
117121 fill_in_missing_output_path (output , output ['name' ], tool_desc ['inputs' ])
118122
123+ # Remove the extra space at the end of the command line
124+ tool_desc ['command-line' ] = tool_desc ['command-line' ].strip ()
125+
119126 # Save descriptor to a file
120127 if save :
121128 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):
136143 # Otherwise, find the existing output and update its path template if it's still undefined.
137144 if first_run :
138145 tool_desc ['output-files' ].append (output )
146+ if output .get ('value-key' ):
147+ tool_desc ['command-line' ] += output ['value-key' ] + " "
139148 if verbose :
140149 print ("-> Adding output " + output ['name' ])
141150 else :
142151 for existing_output in tool_desc ['output-files' ]:
143152 if output ['id' ] == existing_output ['id' ] and existing_output ['path-template' ] == "" :
144153 existing_output ['path-template' ] = output ['path-template' ]
145154 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' ] + " "
146157
147158 if len (tool_desc ['output-files' ]) == 0 :
148159 raise Exception ("Tool has no output." )
149160
150161
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 ):
153164 """
154165 Returns a dictionary containing the Boutiques input corresponding to a Nipype intput.
155166
@@ -161,11 +172,17 @@ def get_boutiques_input(inputs, interface, input_name, spec,
161172 * verbose: print information messages.
162173 * handler: used when handling compound inputs, which don't have their own input spec
163174 * 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
164176
165177 Assumes that:
166178 * Input names are unique.
167179 """
168180
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+
169186 input = {}
170187
171188 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):
339356 output ['path-template' ] = "*"
340357 return output
341358
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+
344365 if output_value :
345366 output ['path-template' ] = os .path .relpath (output_value )
346367 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
348379
349380 return output
350381
0 commit comments