2828
2929def generate_boutiques_descriptor (
3030 module , interface_name , container_image , container_type , container_index = None ,
31- ignored_template_inputs = (), ignore_template_numbers = False , verbose = False , save = False ):
31+ ignored_template_inputs = (), ignore_template_numbers = False , verbose = False , save = False , save_path = None ):
3232 '''
3333 Returns a JSON string containing a JSON Boutiques description of a Nipype interface.
3434 Arguments:
@@ -41,6 +41,7 @@ def generate_boutiques_descriptor(
4141 * ignore_template_numbers: True if numbers must be ignored in output path creations.
4242 * verbose: print information messages
4343 * save: True if you want to save descriptor to a file
44+ * save_path: file path for the saved descriptor (defaults to name of the interface in current directory)
4445 '''
4546
4647 if not module :
@@ -129,7 +130,8 @@ def generate_boutiques_descriptor(
129130
130131 # Save descriptor to a file
131132 if save :
132- with open (interface_name + '.json' , 'w' ) as outfile :
133+ path = save_path if save_path is not None else os .path .join (os .getcwd (), interface_name + '.json' )
134+ with open (path , 'w' ) as outfile :
133135 json .dump (tool_desc , outfile , indent = 4 , separators = (',' , ': ' ))
134136 if verbose :
135137 print ("-> Descriptor saved to file " + outfile .name )
@@ -146,18 +148,12 @@ def generate_tool_outputs(outputs, interface, tool_desc, verbose, first_run):
146148 # If this is the first time we are generating outputs, add the full output to the descriptor.
147149 # Otherwise, find the existing output and update its path template if it's still undefined.
148150 if first_run :
149- if isinstance (output , list ):
150- tool_desc ['output-files' ].extend (output )
151- if verbose :
152- print ("-> Adding output " + output [0 ]['name' ])
153- else :
154- tool_desc ['output-files' ].append (output )
155- if verbose :
156- print ("-> Adding output " + output ['name' ])
151+ tool_desc ['output-files' ].append (output )
152+ if verbose :
153+ print ("-> Adding output " + output ['name' ])
157154 else :
158155 for existing_output in tool_desc ['output-files' ]:
159- if not isinstance (output , list ) and output ['id' ] == existing_output ['id' ] \
160- and existing_output ['path-template' ] == "" :
156+ if output ['id' ] == existing_output ['id' ] and existing_output ['path-template' ] == "" :
161157 existing_output ['path-template' ] = output ['path-template' ]
162158 break
163159
@@ -258,6 +254,11 @@ def get_boutiques_input(inputs, interface, input_name, spec,
258254 if trait_handler .maxlen != six .MAXSIZE :
259255 input ['max-list-entries' ] = trait_handler .maxlen
260256
257+ # Deal with multi-input
258+ if handler_type == "InputMultiObject" :
259+ input ['type' ] = "File"
260+ input ['list' ] = True
261+
261262 input ['value-key' ] = "[" + input_name .upper (
262263 ) + "]" # assumes that input names are unique
263264
@@ -342,13 +343,18 @@ def get_boutiques_output(outputs, name, spec, interface, tool_inputs, verbose=Fa
342343
343344 # Handle multi-outputs
344345 if isinstance (output_value , list ):
345- output_list = []
346- for i in range (0 , len (output_value )):
347- output_copy = copy .deepcopy (output )
348- output_copy ['path-template' ] = os .path .relpath (output_value [i ])
349- output_copy ['id' ] += ("_" + str (i + 1 )) if i > 0 else ""
350- output_list .append (output_copy )
351- return output_list
346+ output ['list' ] = True
347+ # Check if all extensions are the same
348+ extensions = []
349+ for val in output_value :
350+ extensions .append (os .path .splitext (val )[1 ])
351+ # If extensions all the same, set path template as wildcard + extension
352+ # Otherwise just use a wildcard
353+ if len (set (extensions )) == 1 :
354+ output ['path-template' ] = "*" + extensions [0 ]
355+ else :
356+ output ['path-template' ] = "*"
357+ return output
352358
353359 # If an output value is defined, use its relative path
354360 # Otherwise, put blank string and try to fill it on another iteration
0 commit comments