Skip to content

Commit 2bf03cf

Browse files
committed
added author and ignored inputs parameters, removed nipype from command line, added logic to deal with inputs containing name_source and name_template metadata
1 parent f67d04b commit 2bf03cf

File tree

1 file changed

+42
-11
lines changed

1 file changed

+42
-11
lines changed

nipype/utils/nipype2boutiques.py

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
def 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

Comments
 (0)