def createGenericStep(id, docker_image, base_command, type, doc, input_doc, extension, output_doc): cwl_tool = cwlgen.CommandLineTool(tool_id=id, base_command=base_command) cwl_tool_docker = cwlgen.DockerRequirement(docker_pull=docker_image) implementation_file_binding = cwlgen.CommandLineBinding(position=1) cases_file_binding = cwlgen.CommandLineBinding(position=2) return createStep(cwl_tool, cwl_tool_docker, implementation_file_binding, cases_file_binding, type, doc, input_doc, extension, output_doc, base_command)
def translate_tool_input(toolinput: ToolInput) -> cwlgen.CommandInputParameter: default, value_from = toolinput.default, None if isinstance(toolinput.input_type, Filename): default = toolinput.input_type.generated_filename() # value_from = get_input_value_from_potential_selector_or_generator(toolinput.input_type, code_environment=False, toolid=toolinput.id()) elif is_selector(default): default = None value_from = get_input_value_from_potential_selector_or_generator( toolinput.default, code_environment=False, toolid=toolinput.id()) data_type = toolinput.input_type.cwl_type(default is not None) input_binding = cwlgen.CommandLineBinding( # load_contents=toolinput.load_contents, position=toolinput.position, prefix=toolinput.prefix, separate=toolinput.separate_value_from_prefix, item_separator=toolinput.separator, value_from=value_from, shell_quote=toolinput.shell_quote, ) non_optional_dt_component = ([t for t in data_type if t != "null"][0] if isinstance(data_type, list) else data_type) # Binding array inputs onto the console # https://www.commonwl.org/user_guide/09-array-inputs/ if isinstance(toolinput.input_type, Array) and isinstance( non_optional_dt_component, cwlgen.CommandInputArraySchema): if toolinput.prefix_applies_to_all_elements: input_binding.prefix = None input_binding.separate = None nested_binding = cwlgen.CommandLineBinding( # load_contents=toolinput.load_contents, prefix=toolinput.prefix, separate=toolinput.separate_value_from_prefix, # item_separator=toolinput.item_separator, # value_from=toolinput.value_from, shell_quote=toolinput.shell_quote, ) non_optional_dt_component.inputBinding = nested_binding return cwlgen.CommandInputParameter( param_id=toolinput.tag, label=toolinput.tag, secondary_files=toolinput.input_type.secondary_files(), # streamable=None, doc=toolinput.doc, input_binding=input_binding, default=default, param_type=data_type, )
def create_command_line_tool(node): """ Create a command line tool description file for a single step in a CWL workflow. NOTE: CWL only supports workflow steps that are bash shell applications Non-BashShellApp nodes are unable to be implemented in CWL """ # get inputs and outputs inputs = node.get('inputs', []) outputs = node.get('outputs', []) # strip command down to just the basic command, with no input or output parameters base_command = node.get('command', '') # TODO: find a better way of specifying command line program + arguments base_command = base_command[:base_command.index(" ")] base_command = common.u2s(base_command) # cwlgen's Serializer class doesn't support python 2.7's unicode types cwl_tool = cwlgen.CommandLineTool(tool_id=common.u2s(node['app']), label=common.u2s(node['nm']), base_command=base_command, cwl_version='v1.0') # add inputs for index, input in enumerate(inputs): file_binding = cwlgen.CommandLineBinding(position=index) input_file = cwlgen.CommandInputParameter('input_file_' + str(index), param_type='File', input_binding=file_binding, doc='input file ' + str(index)) cwl_tool.inputs.append(input_file) if len(inputs) == 0: cwl_tool.inputs.append( cwlgen.CommandInputParameter('dummy', param_type='null', doc='dummy')) # add outputs for index, output in enumerate(outputs): file_binding = cwlgen.CommandLineBinding() output_file = cwlgen.CommandOutputParameter( 'output_file_' + str(index), param_type='stdout', output_binding=file_binding, doc='output file ' + str(index)) cwl_tool.outputs.append(output_file) return cwl_tool.export_string()
def add_input_file(self, input_obj): """ Add an input to the CWL tool. :param input_obj: Input object. :type input_obj: :class:`tooldog.biotool_model.Input` """ LOGGER.info("Adding input to CwlToolGen object...") # Build parameter self.input_ct += 1 # Give unique name to the input name = 'INPUT' + str(self.input_ct) # Get all different formats for this input list_formats = [] for format_obj in input_obj.formats: list_formats.append(format_obj.uri) formats = ', '.join(list_formats) # Create the parameter param_binding = cwlgen.CommandLineBinding(prefix='--' + name) param = cwlgen.CommandInputParameter(name, param_type='File', label=input_obj.data_type.term, param_format=formats, input_binding=param_binding) # Appends parameter to inputs self.tool.inputs.append(param)
def setUp(self): self.frst_inp = cwlgen.CommandInputParameter('frst_id', param_type='File',\ label='a_label', \ default='def_value') binding = cwlgen.CommandLineBinding(position=2, prefix='--prefix') self.scnd_inp = cwlgen.CommandInputParameter('scnd_id', param_type='File',\ input_binding=binding)
def _convert_input(input, basedir): """Converts an input to a CWL input.""" entity = input.consumes type_ = 'Directory' if isinstance(entity, Collection) else 'File' sanitized_id = input.sanitized_id if input.mapped_to: sanitized_id = 'input_stdin' separate = None prefix = None if input.prefix: prefix = input.prefix separate = False if prefix.endswith(' '): prefix = prefix[:-1] separate = True return cwlgen.CommandInputParameter( sanitized_id, param_type=type_, input_binding=cwlgen.CommandLineBinding(position=input.position, prefix=prefix, separate=separate), default={ 'path': os.path.abspath(os.path.join(basedir, entity.path)), 'class': type_ })
def _convert_input(input, basedir): """Converts an input to a CWL input.""" entity = input.consumes type_ = "Directory" if isinstance(entity, Collection) else "File" sanitized_id = input.sanitized_id sanitized_id = sanitized_id.replace("/", "_") if input.mapped_to: sanitized_id = "input_stdin" separate = None prefix = None if input.prefix: prefix = input.prefix separate = False if prefix.endswith(" "): prefix = prefix[:-1] separate = True return cwlgen.CommandInputParameter( sanitized_id, param_type=type_, input_binding=cwlgen.CommandLineBinding(position=input.position, prefix=prefix, separate=separate), default={ "path": os.path.abspath(os.path.join(basedir, entity.path)), "class": type_ }, )
def createWorkflowStep(workflow, position, id, type, language="KNIME", extension=None): file_binding = cwlgen.CommandLineBinding() # Individual step input workflow_step = cwlgen.WorkflowStep(str(position), id + ".cwl") workflow_step.inputs.append( cwlgen.WorkflowStepInput("inputModule", "inputModule" + str(position))) if (not "external" in type): if (position == 1): workflow_step.inputs.append( cwlgen.WorkflowStepInput("potentialCases", "potentialCases")) else: workflow_step.inputs.append( cwlgen.WorkflowStepInput("potentialCases", source=str(position - 1) + "/output")) # Individual step output workflow_step.out.append(cwlgen.WorkflowStepOutput("output")) workflow.steps = workflow.steps + [workflow_step] # Overall workflow input if (position == 1 and (not "external" in type)): workflow_input = cwlgen.InputParameter( "potentialCases", param_type='File', input_binding=file_binding, doc="Input of potential cases for processing") workflow.inputs.append(workflow_input) workflow_input = cwlgen.InputParameter( "inputModule" + str(position), param_type='File', input_binding=file_binding, doc=language[0].upper() + language[1:] + " implementation unit") workflow.inputs.append(workflow_input) # Overall workflow output if (extension): workflow_output = cwlgen.WorkflowOutputParameter( param_id='cases', param_type="File", output_source=str(position) + "/output", output_binding=cwlgen.CommandOutputBinding(glob="*." + extension)) workflow.outputs.append(workflow_output) return workflow
def translate_tool_argument(argument): return cwlgen.CommandLineBinding( # load_contents=False, position=argument.position, prefix=argument.prefix, separate=argument.separate_value_from_prefix, # item_separator=None, value_from=get_input_value_from_potential_selector_or_generator( argument.value, code_environment=False), shell_quote=argument.shell_quote, )
def createKNIMEStep(id, type, doc, input_doc, extension, output_doc): cwl_tool = cwlgen.CommandLineTool( tool_id=id, base_command='/home/kclhi/knime_4.1.1/knime') cwl_tool_docker = cwlgen.DockerRequirement( docker_pull="kclhi/knime:amia", docker_output_dir="/home/kclhi/.eclipse") cwl_tool.arguments = [ '-data', '/home/kclhi/.eclipse', '-reset', '-nosplash', '-nosave', '-application', 'org.knime.product.KNIME_BATCH_APPLICATION' ] implementation_file_binding = cwlgen.CommandLineBinding( prefix="-workflowFile=", separate=False) cases_file_binding = cwlgen.CommandLineBinding( prefix="-workflow.variable=dm_potential_cases,file://", separate=False, value_from=" $(inputs.potentialCases.path),String") return createStep(cwl_tool, cwl_tool_docker, implementation_file_binding, cases_file_binding, type, doc, input_doc, extension, output_doc, "knime")
def _convert_output(output): """Converts an output to a CWL output.""" if output.mapped_to: return ( cwlgen.CommandOutputParameter( "output_{}".format(output.mapped_to.stream_type), param_type=output.mapped_to.stream_type, streamable=False, ), None, ) entity = output.produces type_ = "Directory" if isinstance(entity, Collection) else "File" sanitized_id = output.sanitized_id.replace("/", "_") if output.position: # output is specified as a parameter, create an input as well separate = None prefix = None if output.prefix: prefix = output.prefix separate = False if prefix.endswith(" "): prefix = prefix[:-1] separate = True arg = cwlgen.CommandInputParameter( "{}_arg".format(sanitized_id), param_type="string", input_binding=cwlgen.CommandLineBinding( position=output.position, prefix=prefix, separate=separate), default=entity.path, ) outp = cwlgen.CommandOutputParameter( sanitized_id, param_type=type_, output_binding=cwlgen.CommandOutputBinding( glob="$(inputs.{})".format(arg.id)), ) return outp, arg return ( cwlgen.CommandOutputParameter( sanitized_id, param_type=type_, output_binding=cwlgen.CommandOutputBinding(glob=entity.path)), None, )
def load_inbinding(self, input_obj, inbinding_el): """ Load the content of inputBinding into the input object. :param input_obj: input object :type input_obj: :class:`cwlgen.CommandInputParameter` :param inbinding_el: Content of inputs :type inbinding_el: DICT """ inbinding_obj = cwlgen.CommandLineBinding() for key, value in inbinding_el.items(): try: getattr(self, '_load_{}'.format(key))(inbinding_obj, value) except AttributeError: _LOGGER.warning(key + " content for inputBinding is not processed (yet).") input_obj.inputBinding = inbinding_obj
def _convert_output(output): """Converts an output to a CWL output.""" if output.mapped_to: return cwlgen.CommandOutputParameter( 'output_{}'.format(output.mapped_to.stream_type), param_type=output.mapped_to.stream_type, streamable=False), None entity = output.produces type_ = 'Directory' if isinstance(entity, Collection) else 'File' if output.position: # output is specified as a parameter, create an input as well separate = None prefix = None if output.prefix: prefix = output.prefix separate = False if prefix.endswith(' '): prefix = prefix[:-1] separate = True arg = cwlgen.CommandInputParameter( '{}_arg'.format(output.sanitized_id), param_type='string', input_binding=cwlgen.CommandLineBinding( position=output.position, prefix=prefix, separate=separate), default=entity.path) outp = cwlgen.CommandOutputParameter( output.sanitized_id, param_type=type_, output_binding=cwlgen.CommandOutputBinding( glob='$(inputs.{})'.format(arg.id))) return outp, arg return cwlgen.CommandOutputParameter( output.sanitized_id, param_type=type_, output_binding=cwlgen.CommandOutputBinding(glob=entity.path)), None
def _convert_argument(argument): """Converts an argument to a CWL input.""" value, type_ = _get_argument_type(argument.value) separate = None prefix = None if argument.prefix: prefix = argument.prefix separate = False if prefix.endswith(' '): prefix = prefix[:-1] separate = True return cwlgen.CommandInputParameter( argument.sanitized_id, param_type=type_, input_binding=cwlgen.CommandLineBinding(position=argument.position, prefix=prefix, separate=separate), default=value)
def generate_cwl(cls): """ Produces a CWL App object which can then be exported to yaml """ import cwlgen module = cls.get_module() # Basic definition of the tool cwl_tool = cwlgen.CommandLineTool(tool_id=cls.name, label=cls.name, base_command=f'python3 -m {module}') #TODO: Add documentation in ceci elements cwl_tool.doc = "Pipeline element from ceci" # Add the inputs of the tool for i,inp in enumerate(cls.input_tags()): input_binding = cwlgen.CommandLineBinding(position=(i+1)) input_param = cwlgen.CommandInputParameter(inp, param_type='File', input_binding=input_binding, doc='Some documentation about the input') cwl_tool.inputs.append(input_param) # Add the definition of the outputs for i,out in enumerate(cls.output_tags()): output_binding = cwlgen.CommandOutputBinding(glob=out) output = cwlgen.CommandOutputParameter(out, param_type='File', output_binding=output_binding, param_format='http://edamontology.org/format_2330', doc='Some results produced by the pipeline element') cwl_tool.outputs.append(output) # Potentially add more metadata metadata = {'name': cls.name, 'about': 'I let you guess', 'publication': [{'id': 'one_doi'}, {'id': 'another_doi'}], 'license': ['MIT']} cwl_tool.metadata = cwlgen.Metadata(**metadata) return cwl_tool
def generate_cwl(cls, log_dir=None): """ Produces a CWL App object which can then be exported to yaml """ import cwlgen module = cls.get_module() module = module.split(".")[0] # Basic definition of the tool cwl_tool = cwlgen.CommandLineTool( tool_id=cls.name, label=cls.name, base_command="python3", cwl_version="v1.0", doc=cls.__doc__, ) if log_dir is not None: cwl_tool.stdout = f"{cls.name}.out" cwl_tool.stderr = f"{cls.name}.err" # Adds the first input binding with the name of the module and pipeline stage input_arg = cwlgen.CommandLineBinding(position=-1, value_from=f"-m{module}") cwl_tool.arguments.append(input_arg) input_arg = cwlgen.CommandLineBinding(position=0, value_from=f"{cls.name}") cwl_tool.arguments.append(input_arg) type_dict = {int: "int", float: "float", str: "string", bool: "boolean"} # Adds the parameters of the tool for opt, def_val in cls.config_options.items(): # Handles special case of lists: if isinstance(def_val, list): v = def_val[0] param_type = { "type": "array", "items": type_dict[v] if isinstance(v, type) else type_dict[type(v)], } default = def_val if not isinstance(v, type) else None input_binding = cwlgen.CommandLineBinding( prefix=f"--{opt}=", item_separator=",", separate=False ) else: param_type = ( type_dict[def_val] if isinstance(def_val, type) else type_dict[type(def_val)] ) default = def_val if not isinstance(def_val, type) else None if param_type == "boolean": input_binding = cwlgen.CommandLineBinding(prefix=f"--{opt}") else: # pragma: no cover input_binding = cwlgen.CommandLineBinding( prefix=f"--{opt}=", separate=False ) input_param = cwlgen.CommandInputParameter( opt, label=opt, param_type=param_type, input_binding=input_binding, default=default, doc="Some documentation about this parameter", ) # We are bypassing the cwlgen builtin type check for the special case # of arrays until that gets added to the standard if isinstance(def_val, list): input_param.type = param_type cwl_tool.inputs.append(input_param) # Add the inputs of the tool for i, inp in enumerate(cls.input_tags()): input_binding = cwlgen.CommandLineBinding(prefix=f"--{inp}") input_param = cwlgen.CommandInputParameter( inp, label=inp, param_type="File", param_format=cls.inputs[i][1].format, # pylint: disable=no-member input_binding=input_binding, doc="Some documentation about the input", ) cwl_tool.inputs.append(input_param) # Adds the overall configuration file input_binding = cwlgen.CommandLineBinding(prefix="--config") input_param = cwlgen.CommandInputParameter( "config", label="config", param_type="File", param_format="http://edamontology.org/format_3750", input_binding=input_binding, doc="Configuration file", ) cwl_tool.inputs.append(input_param) # Add the definition of the outputs for i, out in enumerate(cls.output_tags()): output_name = cls.outputs[i][1].make_name(out) # pylint: disable=no-member output_binding = cwlgen.CommandOutputBinding(glob=output_name) output = cwlgen.CommandOutputParameter( out, label=out, param_type="File", output_binding=output_binding, param_format=cls.outputs[i][1].format, # pylint: disable=no-member doc="Some results produced by the pipeline element", ) cwl_tool.outputs.append(output) if log_dir is not None: output = cwlgen.CommandOutputParameter( f"{cls.name}@stdout", label="stdout", param_type="stdout", doc="Pipeline elements standard output", ) cwl_tool.outputs.append(output) error = cwlgen.CommandOutputParameter( f"{cls.name}@stderr", label="stderr", param_type="stderr", doc="Pipeline elements standard output", ) cwl_tool.outputs.append(error) # Potentially add more metadata # This requires a schema however... # metadata = {'name': cls.name, # 'about': 'Some additional info', # 'publication': [{'id': 'one_doi'}, {'id': 'another_doi'}], # 'license': ['MIT']} # cwl_tool.metadata = cwlgen.Metadata(**metadata) return cwl_tool
def generate_cwl(cls): """ Produces a CWL App object which can then be exported to yaml """ import cwlgen module = cls.get_module() module = module.split('.')[0] # Basic definition of the tool cwl_tool = cwlgen.CommandLineTool(tool_id=cls.name, label=cls.name, base_command='python3', cwl_version='v1.0', doc=cls.__doc__) # Adds the first input binding with the name of the module and pipeline stage input_arg = cwlgen.CommandLineBinding(position=-1, value_from=f'-m{module}') cwl_tool.arguments.append(input_arg) input_arg = cwlgen.CommandLineBinding(position=0, value_from=f'{cls.name}') cwl_tool.arguments.append(input_arg) type_dict = { int: 'int', float: 'float', str: 'string', bool: 'boolean' } # Adds the parameters of the tool for opt in cls.config_options: def_val = cls.config_options[opt] # Handles special case of lists: if type(def_val) is list: v = def_val[0] param_type = { 'type': 'array', 'items': type_dict[v] if type(v) == type else type_dict[type(v)] } default = def_val if type(v) != type else None input_binding = cwlgen.CommandLineBinding( prefix='--{}='.format(opt), item_separator=',', separate=False) else: param_type = type_dict[def_val] if type( def_val) == type else type_dict[type(def_val)] default = def_val if type(def_val) != type else None if param_type is 'boolean': input_binding = cwlgen.CommandLineBinding( prefix='--{}'.format(opt)) else: input_binding = cwlgen.CommandLineBinding( prefix='--{}='.format(opt), separate=False) input_param = cwlgen.CommandInputParameter( opt, label=opt, param_type=param_type, input_binding=input_binding, default=default, doc='Some documentation about this parameter') # We are bypassing the cwlgen builtin type check for the special case # of arrays until that gets added to the standard if type(def_val) is list: input_param.type = param_type cwl_tool.inputs.append(input_param) # Add the inputs of the tool for i, inp in enumerate(cls.input_tags()): input_binding = cwlgen.CommandLineBinding( prefix='--{}'.format(inp)) input_param = cwlgen.CommandInputParameter( inp, label=inp, param_type='File', param_format=cls.inputs[i][1].__name__, input_binding=input_binding, doc='Some documentation about the input') cwl_tool.inputs.append(input_param) # Adds the overall configuration file input_binding = cwlgen.CommandLineBinding(prefix='--config') input_param = cwlgen.CommandInputParameter('config', label='config', param_type='File', param_format='YamlFile', input_binding=input_binding, doc='Configuration file') cwl_tool.inputs.append(input_param) # Add the definition of the outputs for i, out in enumerate(cls.output_tags()): output_name = f'{out}.{cls.outputs[i][1].suffix}' output_binding = cwlgen.CommandOutputBinding(glob=output_name) output = cwlgen.CommandOutputParameter( out, label=out, param_type='File', output_binding=output_binding, param_format=cls.outputs[i][1].__name__, doc='Some results produced by the pipeline element') cwl_tool.outputs.append(output) # Potentially add more metadata # This requires a schema however... # metadata = {'name': cls.name, # 'about': 'Some additional info', # 'publication': [{'id': 'one_doi'}, {'id': 'another_doi'}], # 'license': ['MIT']} # cwl_tool.metadata = cwlgen.Metadata(**metadata) return cwl_tool
def setUp(self): self.line_binding = cwlgen.CommandLineBinding(load_contents=True, position=1, \ prefix='--prefix', separate=True, \ item_separator='-', shell_quote=True,\ value_from='text.txt')
if __name__ == "__main__": # Initialize workflow cwl_tool = cwlgen.workflow.Workflow(workflow_id='west_workflow_tool', label='Workflow tool to generates pw.out and wstat.out files', doc='Workflow tool to generate west code', cwl_version='v1.0') #Schema defining reuqirement for scatter feature scatter_class = cwlgen.ScatterFeatureRequirement() cwl_tool.requirements.append(scatter_class) # Add inputs (script_file, URLs, type, no_of_cores to the workflow script_binding = cwlgen.CommandLineBinding(position=1) script_file = cwlgen.workflow.InputParameter('script_file', param_type='File', input_binding=script_binding, doc='West script which generates pw.out, wstat.out based on inputs') cwl_tool.inputs.append(script_file) file_binding = cwlgen.CommandLineBinding(position=2) input_file_array = cwlgen.workflow.InputParameter('input_file_array', param_type='File[]', input_binding=file_binding, doc='Input file for west code. Can be pw.in, wstat.in') cwl_tool.inputs.append(input_file_array) url_binding = cwlgen.CommandLineBinding(position=3)
import cwlgen cwl_tool = cwlgen.CommandLineTool(tool_id='grep', label='print lines matching a pattern', base_command='grep', cwl_version='v1.0') file_binding = cwlgen.CommandLineBinding(position=2) input_file = cwlgen.CommandInputParameter( 'input_file', param_type='File', input_binding=file_binding, doc='input file from which you want to look for the pattern') cwl_tool.inputs.append(input_file) pattern_binding = cwlgen.CommandLineBinding(position=1) pattern = cwlgen.CommandInputParameter('pattern', param_type='string', input_binding=pattern_binding, doc='pattern to find in the input file') cwl_tool.inputs.append(pattern) cwl_tool.export()
########### Import ########### import cwlgen if __name__ == "__main__": # Create a tool cwl_tool = cwlgen.CommandLineTool(tool_id='my_tool', label='my_tool is magic',\ base_command='run_my_tool') # Add documentation cwl_tool.doc = "Magic is no magic without secrets..." # Add 2 inputs input_1_binding = cwlgen.CommandLineBinding(position=1) input_1 = cwlgen.CommandInputParameter('config_file', param_type='File',\ input_binding=input_1_binding,\ doc='config file',\ param_format='http://edamontology.org/format_2330') cwl_tool.inputs.append(input_1) input_2_binding = cwlgen.CommandLineBinding(prefix='-t') input_2 = cwlgen.CommandInputParameter('threads', param_type='int',\ input_binding=input_2_binding,\ doc='number of threads') cwl_tool.inputs.append(input_2) # Add 1 output output_1_binding = cwlgen.CommandOutputBinding(glob='counts.txt') output_1 = cwlgen.CommandOutputParameter('result_file', param_type='File',\ output_binding=output_1_binding,\