Hi. I'm trying to make a new module (or set of mod...
# nostupidquestions
u
Hi. I'm trying to make a new module (or set of modules) to resolve https://github.com/nf-core/modules/issues/8699. I'm a bit confused about the usage of args in a module, not pipeline. The module specification (https://nf-co.re/docs/guidelines/components/modules#optional-command-arguments) says that optional arguments should be provided by the args string. However, no module has a modules.conf file, just pipelines. How am I supposed to add additional arguments to a specific module? I'd like to have the optional arguments present in a file somewhere, so people will know what to use, including when incorporating into pipelines. The non nf-core version seems to have optional arguments in the script https://github.com/Xinglab/rmats-turbo/blob/master/nextflow/rmats.nf#L21, but that doesn't seem right. I feel like I'm missing something or misunderstood something fundamental. Should I make a conf file just for this module? Can someone please help me out? Thank you, Uri David
a
Yeah I see your confusion, I'm also struggling with nf-core framework and it took me a while to grok the internals (still learning!).
I'd like to have the optional arguments present in a file somewhere, so people will know what to use, including when incorporating into pipelines.
This is something I'm interested in as well but I have a feeling it falls outside the scope of the nf-core modules. Take the
samtools_depth
module https://github.com/nf-core/modules/blob/master/modules/nf-core/samtools/depth/main.nf The actual script part is tiny:
Copy code
samtools \\
        depth \\
        --threads ${task.cpus-1} \\
        $args \\
        $positions \\
        -o ${prefix}.tsv \\
        $bam
Even though the number of possible arguments are a lot. I think it's expected that the user knows how to use the tool and would seek out the documentation or seek out its usage in other nf-core pipelines.
So write the module to allow the tool to run, make sure user can find documentation somewhere and leave it up to them.
j
Just to confirm waht @Ammar Aziz says! Were you aware of the guidelines/specification pages that Ammar linked to? Also in regard to the optional arguments, to continue wihat Ammara says
I think it's expected that the user knows how to use the tool and would seek out the documentation or seek out its usage in other nf-core pipelines.
Our philosphy is that it's the pipeline developers' responsibility to be familiar with the tool they are adding to a pipeline, and thus responsible for deciding what to 'expose' are the allowed Arguments for module. In many cases a pipeline will not be compatible with all the options a tool may have - so the pipeline developer needs to control for this. We also don't want to duplicate documentation from the tool itself, a user should ideally kknow what tool they are selecting already.
this 2
s
And if we did duplicate documentation, it can end up out of sync as the tool gets updated anyway.
✅ 1
💯 1
a
I've written wrappers (modules) in Galaxy for tools, because of the user base and the expectation I had to essentially duplicate a lot of docs and even add more because how it was written. Yeah it's a huge headache, so I'm happy nf-core modules don't aim for that!
u
Thank you all. To specifically reply to @James Fellows Yates - I looked at the documents, and that is one of the reasons I was confused. The specification for a module says that optional arguments MUST be provided in args, but it actually means that optional arguments should be in the pipeline modules.conf when using this module. So the module definition does not have any optional arguments. Maybe I'm being too literal minded, and if it is clear to everyone else, sorry. Follow-up questions 1. Can subworkflows have a modules.conf if these optional parmeters are needed to link the tasks in the subworkflow? Or should modules.conf only appear in pipelines? 2. Can tests in nf-test include these optional parameters? Or they shouldn't include it either?
I mean tests of the specific module, not tests of a pipeline
s
a subworkflow can have a modules.config yes, and it will even get highlighted when the subworkflow is installed using nf-core subworkflows install
for instance the bam_ngscheckmate subworkflow has a nextflow.config that is required to ensure that bcftools makes the right files for ngscheckmate,
image.png
If you think the wording can be improved you are welcome to submit a PR to the website 🙂
j
The specification for a module says that optional arguments MUST be provided in args, but it actually means that optional arguments should be in the pipeline modules.conf when using this module. So the module definition does not have any optional arguments.
Ah ok this sounds like bad phrasing. I guess
provided in
shoudl be replaced
supported by args
, . I can see why it might be unclear now!
How about this:
Copy code
## Optional command arguments

All _non-mandatory_ command-line tool _non-file_ arguments MUST supported in the module via the `$task.ext.args` variable.

The `$args` variable MUST be placed in the module's tool command to allow optional and/or dynamic variables to be specified by a user or a developer.
The contents of this variable is specified by a pipeline developer or user in with the `ext.args` process variable in a `modules.config` or other Nextflow config file using a closure.
The `$ext.args` variable can also be used in module tests to increase the test coverage of a tool's functionality through a companion `nextflow.config` alongside the test files themselves.

```groovy {2} title="<module>.nf"
script:
def args = task.ext.args ?: ''
def prefix = task.ext.prefix ?: "${meta.id}"
"""
fastqc \\
    $args \\
      <...>
"""
Copy code
groovy {3-6} title="modules.config"
  process {
    withName: <module> {
        ext.args = { [                                                        // Assign a closure which returns a string
            '--quiet',
            params.fastqc_kmer_size ? "-k ${params.fastqc_kmer_size}" : ''    // Parameter-dependent values can be provided in this way
        ].join(' ') }                                                         // Join converts the list to a string.
        ext.prefix = { "${meta.id}" }                                         // A closure can be used to access variables defined in the script
    }
  }
:::info{title="Rationale" collapse} Passing arguments via ext.args splits how information is passed to a module, making it harder to understand where module inputs are defined. Using
ext.args
provides more flexibility to users. As
ext.args
is derived from the configuration (e.g.,,
modules.config
), advanced users can overwrite the default
ext.args
and supply their own arguments to modify the behaviour of a module. This can increase the capabilities of a pipeline beyond what the original developers intended. Initially, these were passed via the main workflow script using custom functions (e.g.,
addParams
) and other additional nf-core custom methods, but this syntax overhead and other limitations were more difficult for pipeline developers to use and understand. Using the 'native'
ext
functionality provided by Nextflow was easier to understand, maintain, and use. Sample-specific parameters can still be provided to an instance of a process by storing these in
meta
, and providing these to the
ext.args
definition in
modules.config
. A closure is used to make Nextflow evaluate the code in the string:
Copy code
groovy
ext.args = { "--id ${meta.id}" }
::: ```
?
u
That sounds good, but I would add a little bit The contents of this variable is specified by a pipeline developer or user in with the
ext.args
process variable in a
modules.config
or other Nextflow config file using a closure. Config file are present in pipelines and subworkflows, not for each individual module. What I added is in bold. Feel free to change the phrasing. Thank you!
👍 1
j
Added!