Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handling of exclusive/dependent inputs #469

Open
bartns opened this issue Apr 15, 2024 · 1 comment
Open

Handling of exclusive/dependent inputs #469

bartns opened this issue Apr 15, 2024 · 1 comment

Comments

@bartns
Copy link

bartns commented Apr 15, 2024

More guidance on how to use dependent and mutually exclusive inputs in a multi-stepped workflow would be nice.
I could only find something in the FAQ: https://www.commonwl.org/user_guide/faq.html#contents

Some examples for dependent workflows. Credit goes to @alexiswl

command line too cwl:

cwlVersion: v1.2
class: CommandLineTool
inputs:
  dependent_parameters:
    type:
      type: record
      name: dependent_parameters
      fields:
        itemA:
          type: string
          inputBinding:
            prefix: -A
        itemB:
          type: string
          inputBinding:
            prefix: -B
outputs:
  example_out:
    type: stdout
stdout: output.txt
baseCommand: echo

If the workflow input type is the same record schema as the tool, you can simply parse them like you do with any object such as a file or directory.
record_wf.cwl

cwlVersion: v1.2
class: Workflow

inputs:
  dependent_parameters:
    type:
      type: record
      name: dependent_parameters
      fields:
        itemA:
          type: string
        itemB:
          type: string

steps:
  record:
    run: record.cwl
    in:
      dependent_parameters: dependent_parameters
    out: [example_out]

outputs:
  example_out:
    type: File
    outputSource: record/example_out

Things get a little tricky when you need to convert a record type from the directory to the workflow
i.e let's say your workflow has itemC instead of itemB, but your tool has the existing itemA / itemB record type.

One way to convert is by using the valueFrom attribute in the step input (note the requirements update needed to the workflow)
record_wf.cwl

#!/usr/bin/env cwl-runner
cwlVersion: v1.2
class: Workflow

# Requirements needed for workflow
# valueFrom requires StepInputExpressionRequirement
# While any javascript code present will require the InlineJavascriptRequirement
requirements:
  StepInputExpressionRequirement: {}
  InlineJavascriptRequirement: {}

inputs:
  dependent_parameters:
    type:
      type: record
      name: dependent_parameters
      fields:
        itemA:
          type: string
        itemC:  # New record type
          type: string

steps:
  record:
    run: record.cwl  # Expects old record type
    in:
      dependent_parameters:
        source: dependent_parameters
        valueFrom: |
          ${
            return {
              "itemA": self.itemA,
              "itemB": self.itemC
            }
          }
    out: [example_out]

outputs:
  example_out:
    type: File
    outputSource: record/example_out

Let's test this with our input yaml

dependent_parameters: 
    itemA: a_string  # type "string
    itemC: c_string  # type "string"
cwltool record-wf.cwl input.yaml

Gives

INFO /usr/bin/cwltool 3.1.20220224085855
INFO Resolved 'record-wf.cwl' to 'file:///tmp/tmp.gkj56GiQ0w/record-wf.cwl'
INFO [workflow ] start
INFO [workflow ] starting step record
INFO [step record] start
INFO [job record] /tmp/oq_5u9f8$ echo \
    -A \
    a_string \
    -B \
    c_string > /tmp/oq_5u9f8/output.txt
INFO [job record] completed success
INFO [step record] completed success
INFO [workflow ] completed success
{
    "example_out": {
        "location": "file:///tmp/tmp.gkj56GiQ0w/output.txt",
        "basename": "output.txt",
        "class": "File",
        "checksum": "sha1$f215e8565d4711ed1fac71938dee09ef7781870f",
        "size": 24,
        "path": "/tmp/tmp.gkj56GiQ0w/output.txt"
    }
}
INFO Final process status is success

output.txt

-A a_string -B c_string

Let's instead assume an eggnog-mapper tool requires the inputs input_fasta, data_dir, db and diamond_db, we can instead use the JavaScript expression / valueFrom syntax shown above to collect each of these attributes from the eggnog input record.

For example

in:
  input_fasta: bakta/sequences_cds
  data_dir:
    source: eggnog
    valueFrom: |
      ${
         return self.data_dir;
       }
  db:
    source: eggnog
    valueFrom: |
      ${
         return self.db;
       }
  diamond_db:
    source: eggnog
    valueFrom: |
      ${
         return self.diamond_db;
       }

This last example could be more generalized...

@mr-c
Copy link
Member

mr-c commented Apr 17, 2024

FYI: valueFrom: $(self.data_dir) is a shorter version of

    valueFrom: |
      ${
         return self.data_dir;
       }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants