nf-core / nf-core/modules

Best practices for multiple process inputs

Open
#4,311 10 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Nextflow
Stars
429
Forks
1.1k
Avg merge
1d 6h
Merged PRs (30d)
153

Description

Is your feature request related to a problem? Please describe

Howdy folks

I'd like to discuss a common convention I see with nf-core modules, where a process has two separate inputs for e.g. a sample and an index. Here are a few examples I found:

So you have two inputs:

    input:
    tuple val(meta), path(reads)
    tuple val(meta2), path(index)

This convention works fine as long as you have a single index, in which case you can provide the index as a value channel and it will be "broadcast" to every sample, basically an implicit cross product.

But what if you have multiple indices? The process inputs are not really set up to handle this, so you have to do a bit of hacking:

ch_samples = Channel.of( /* ... */ )
ch_indices = Channel.of( /* ... */ )

ch_inputs = ch_samples.combine(ch_indices)
ch_multi = ch_inputs.multiMap { it ->
    samples: it[0..2],
    indices: it[2..4]
}

PROC(ch_multi.samples, ch_multi.indices)

But now you're wondering if multiMap preserves the order of its inputs, and that question leads down a deep rabbit hole. I have now led multiple people through that rabbit hole, and every time it leads me back to the original problem of multiple inputs. It's the reason why I added this note to the docs.

It's not always nf-core modules that are the cause, just "someone else's process that I'm trying to re-use". In any case, I'm hoping that I can broach the subject and spread this best practice to the community. Are people aware of this issue? Have you debated over this convention in the past? If so I would prefer to build on whatever previous discussions were had.

By the way, here's how I think you SHOULD do it:

process PROC {
    input:
    tuple val(meta), path(reads), val(meta2), path(index)

    // ...
}

workflow {
    ch_samples = Channel.of( /* ... */ )
    ch_indices = Channel.of( /* ... */ )

    PROC( ch_samples.combine(ch_indices) )
}

Easy! It works in all cases (one-to-one, many-to-one, many-to-many), and it doesn't require you play fast and loose with your dataflow

Describe the solution you'd like

No response

Describe alternatives you've considered

No response

Additional context

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the linked Nextflow documentation note on multiple input channels and the referenced nf-core bowtie2/align and bwa/mem module files. Review the multiMap ordering discussion before proposing any change; done would require an agreed community convention and a clearly identified documentation update.

Written by the indexing model from the issue text.

Assessment

Domain
documentation
Issue type
Documentation
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.