diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 1cca9bc0..88675b1a 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -27,6 +27,9 @@ If you're not used to this workflow with git, you can start with some [docs from ## Tests +You can optionally test your changes by running the pipeline locally. Then it is recommended to use the `debug` profile to +receive warnings about process selectors and other debug info. Example: `nextflow run . -profile debug,test,docker --outdir `. + When you create a pull request with changes, [GitHub Actions](https://github.com/features/actions) will run automatic tests. Typically, pull-requests are only fully reviewed when these tests are passing, though of course we can help out before then. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index ae4285a7..69a2dd8e 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -19,6 +19,7 @@ Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/taxp - [ ] If necessary, also make a PR on the nf-core/taxprofiler _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. - [ ] Make sure your code lints (`nf-core lint`). - [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). +- [ ] Check for unexpected warnings in debug mode (`nextflow run . -profile debug,test,docker --outdir `). - [ ] Usage Documentation in `docs/usage.md` is updated. - [ ] Output Documentation in `docs/output.md` is updated. - [ ] `CHANGELOG.md` is updated. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a061b247..d44aa343 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,7 +42,7 @@ jobs: steps: - name: Check out pipeline code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Nextflow uses: nf-core/setup-nextflow@v1 diff --git a/.github/workflows/fix-linting.yml b/.github/workflows/fix-linting.yml index 96ecd903..7b5ad1c7 100644 --- a/.github/workflows/fix-linting.yml +++ b/.github/workflows/fix-linting.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: # Use the @nf-core-bot token to check out so we can push later - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: token: ${{ secrets.nf_core_bot_auth_token }} @@ -24,7 +24,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.nf_core_bot_auth_token }} - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 - name: Install Prettier run: npm install -g prettier @prettier/plugin-php diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index b8bdd214..905c58e4 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -14,9 +14,9 @@ jobs: EditorConfig: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 - name: Install editorconfig-checker run: npm install -g editorconfig-checker @@ -27,9 +27,9 @@ jobs: Prettier: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 - name: Install Prettier run: npm install -g prettier @@ -40,7 +40,7 @@ jobs: PythonBlack: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Check code lints with Black uses: psf/black@stable @@ -71,7 +71,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out pipeline code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Nextflow uses: nf-core/setup-nextflow@v1 diff --git a/.github/workflows/release-announcments.yml b/.github/workflows/release-announcements.yml similarity index 100% rename from .github/workflows/release-announcments.yml rename to .github/workflows/release-announcements.yml diff --git a/.gitpod.yml b/.gitpod.yml index 25488dcc..acf72695 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -4,7 +4,9 @@ tasks: command: | pre-commit install --install-hooks nextflow self-update - + - name: unset JAVA_TOOL_OPTIONS + command: | + unset JAVA_TOOL_OPTIONS vscode: extensions: # based on nf-core.nf-core-extensionpack - codezombiech.gitignore # Language support for .gitignore files diff --git a/CHANGELOG.md b/CHANGELOG.md index d3fb99ba..fd5261af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,26 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v1.1.3 - Augmented Akita Patch [2024-01-12] + +### `Added` + +- [#424](https://github.com/nf-core/taxprofiler/pull/424) Updated to nf-core pipeline template v2.11.1 (added by @LilyAnderssonLee & @sofstam) + +### `Fixed` + +- [#419](https://github.com/nf-core/taxprofiler/pull/419) Added improved syntax highlighting for tables in documentation (fix by @mashehu) +- [#421](https://github.com/nf-core/taxprofiler/pull/421) Updated the krakenuniq/preloadedkrakenuniq module that contained a fix for saving the output reads (❤️ to @SannaAb for reporting, fix by @Midnighter) +- [#427](https://github.com/nf-core/taxprofiler/pull/427) Fixed preprint information in the recommended methods text (fix by @jfy133) + +### `Dependencies` + +| Tool | Previous version | New version | +| ------------- | ---------------- | ----------- | +| multiqc | 1.15 | 1.19 | +| fastqc | 11.9 | 12.1 | +| nf-validation | unpinned | 1.1.3 | + ## v1.1.2 - Augmented Akita Patch [2023-10-27] ### `Added` diff --git a/README.md b/README.md index 5be8affe..74451a7f 100644 --- a/README.md +++ b/README.md @@ -47,11 +47,8 @@ ## Usage -:::note -If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/usage/installation) on how -to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/usage/introduction#how-to-run-a-pipeline) -with `-profile test` before running the workflow on actual data. -::: +> [!NOTE] +> If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/usage/installation) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/usage/introduction#how-to-run-a-pipeline) with `-profile test` before running the workflow on actual data. First, prepare a samplesheet with your input data that looks as follows: @@ -89,11 +86,9 @@ nextflow run nf-core/taxprofiler \ --run_kraken2 --run_metaphlan ``` -:::warning -Please provide pipeline parameters via the CLI or Nextflow `-params-file` option. Custom config files including those -provided by the `-c` Nextflow option can be used to provide any configuration _**except for parameters**_; -see [docs](https://nf-co.re/usage/configuration#custom-configuration-files). -::: +> [!WARNING] +> Please provide pipeline parameters via the CLI or Nextflow `-params-file` option. Custom config files including those provided by the `-c` Nextflow option can be used to provide any configuration _**except for parameters**_; +> see [docs](https://nf-co.re/usage/configuration#custom-configuration-files). For more details and further functionality, please refer to the [usage documentation](https://nf-co.re/taxprofiler/usage) and the [parameter documentation](https://nf-co.re/taxprofiler/parameters). diff --git a/assets/methods_description_template.yml b/assets/methods_description_template.yml index d5119e4a..8b9a651b 100644 --- a/assets/methods_description_template.yml +++ b/assets/methods_description_template.yml @@ -3,8 +3,6 @@ description: "Suggested text and references to use when describing pipeline usag section_name: "nf-core/taxprofiler Methods Description" section_href: "https://github.com/nf-core/taxprofiler" plot_type: "html" -## TODO nf-core: Update the HTML below to your preferred methods description, e.g. add publication citation for this pipeline -## You inject any metadata in the Nextflow '${workflow}' object data: |

Methods

Data was processed using nf-core/taxprofiler v${workflow.manifest.version} ${doi_text} of the nf-core collection of workflows (Ewels et al., 2020), utilising reproducible software environments from the Bioconda (Grüning et al., 2018) and Biocontainers (da Veiga Leprevost et al., 2017) projects.

@@ -17,12 +15,13 @@ data: |
  • Ewels, P. A., Peltzer, A., Fillinger, S., Patel, H., Alneberg, J., Wilm, A., Garcia, M. U., Di Tommaso, P., & Nahnsen, S. (2020). The nf-core framework for community-curated bioinformatics pipelines. Nature Biotechnology, 38(3), 276-278. doi: 10.1038/s41587-020-0439-x
  • Grüning, B., Dale, R., Sjödin, A., Chapman, B. A., Rowe, J., Tomkins-Tinch, C. H., Valieris, R., Köster, J., & Bioconda Team. (2018). Bioconda: sustainable and comprehensive software distribution for the life sciences. Nature Methods, 15(7), 475–476. doi: 10.1038/s41592-018-0046-7
  • da Veiga Leprevost, F., Grüning, B. A., Alves Aflitos, S., Röst, H. L., Uszkoreit, J., Barsnes, H., Vaudel, M., Moreno, P., Gatto, L., Weber, J., Bai, M., Jimenez, R. C., Sachsenberg, T., Pfeuffer, J., Vera Alvarez, R., Griss, J., Nesvizhskii, A. I., & Perez-Riverol, Y. (2017). BioContainers: an open-source and community-driven framework for software standardization. Bioinformatics (Oxford, England), 33(16), 2580–2582. doi: 10.1093/bioinformatics/btx192
  • +
  • Stamouli, S., Beber, M. E., Normark, T., Christensen, T. A., Andersson-Li, L., Borry, M., Jamy, M., nf-core community, & Fellows Yates, J. A. (2023). nf-core/taxprofiler: Highly parallelised and flexible pipeline for metagenomic taxonomic classification and profiling. (Preprint). bioRxiv 2023.10.20.563221. doi: 10.1101/2023.10.20.563221
  • ${tool_bibliography}
    Notes:
      - ${nodoi_text} + ${doi_text}
    • The command above does not include parameters contained in any configs or profiles that may have been used. Ensure the config file is also uploaded with your publication!
    • You should also cite all software used within this run. Check the "Software Versions" of this report to get version information.
    diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index 90a87168..58524b75 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -1,7 +1,7 @@ report_comment: > - This report has been generated by the nf-core/taxprofiler + This report has been generated by the nf-core/taxprofiler analysis pipeline. For information about how to interpret these results, please see the - documentation. + documentation. report_section_order: "nf-core-taxprofiler-methods-description": diff --git a/assets/slackreport.json b/assets/slackreport.json index d168147d..01c8319d 100644 --- a/assets/slackreport.json +++ b/assets/slackreport.json @@ -3,7 +3,7 @@ { "fallback": "Plain-text summary of the attachment.", "color": "<% if (success) { %>good<% } else { %>danger<%} %>", - "author_name": "nf-core/taxprofiler v${version} - ${runName}", + "author_name": "nf-core/taxprofiler ${version} - ${runName}", "author_icon": "https://www.nextflow.io/docs/latest/_static/favicon.ico", "text": "<% if (success) { %>Pipeline completed successfully!<% } else { %>Pipeline completed with errors<% } %>", "fields": [ diff --git a/conf/modules.config b/conf/modules.config index 90ca6919..b45267be 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -500,7 +500,7 @@ process { publishDir = [ path: { "${params.outdir}/krakenuniq/${meta.db_name}/" }, mode: params.publish_dir_mode, - pattern: '*.{txt,fastq.gz}' + pattern: '*.{txt,fasta.gz}' ] } @@ -769,7 +769,7 @@ process { } withName: 'MULTIQC' { - ext.args = params.multiqc_title ? "--title \"$params.multiqc_title\"" : '' + ext.args = { params.multiqc_title ? "--title \"$params.multiqc_title\"" : '' } publishDir = [ path: { "${params.outdir}/multiqc" }, mode: params.publish_dir_mode, diff --git a/docs/output.md b/docs/output.md index 11b07fe5..cf4678c3 100644 --- a/docs/output.md +++ b/docs/output.md @@ -375,23 +375,23 @@ You will only receive the `.fastq` and `*classifiedreads.txt` file if you supply ### KrakenUniq -[KrakenUniq](https://github.com/fbreitwieser/krakenuniq) (formerly KrakenHLL) is an extenson to the fast k-mer-based classification [Kraken](https://github.com/DerrickWood/kraken) with an efficient algorithm for additionally assessing the coverage of unique k-mers found in each species in a dataset. +[KrakenUniq](https://github.com/fbreitwieser/krakenuniq) (formerly KrakenHLL) is an extension to the fast k-mer-based classification performed by [Kraken](https://github.com/DerrickWood/kraken) with an efficient algorithm for additionally assessing the coverage of unique k-mers found in each species in a dataset.
    Output files - `krakenuniq/` - `/` - - `_.classified.fastq.gz`: FASTQ file containing all reads that had a hit against a reference in the database for a given sample - - `_.unclassified.fastq.gz`: FASTQ file containing all reads that did not have a hit in the database for a given sample - - `_.report.txt`: A Kraken2-style report that summarises the fraction abundance, taxonomic ID, number of Kmers, taxonomic path of all the hits, with an additional column for k-mer coverage, that allows for more accurate distinguishing between false-positive/true-postitive hits - - `_.classifiedreads.txt`: A list of read IDs and the hits each read had against each database for a given sample + - `_[.merged].classified.fasta.gz`: Optional FASTA file containing all reads that had a hit against a reference in the database for a given sample. Paired-end input reads are merged in this output. + - `_[.merged].unclassified.fasta.gz`: Optional FASTA file containing all reads that did not have a hit in the database for a given sample. Paired-end input reads are merged in this output. + - `_.krakenuniq.report.txt`: A Kraken2-style report that summarises the fraction abundance, taxonomic ID, number of Kmers, taxonomic path of all the hits, with an additional column for k-mer coverage, that allows for more accurate distinguishing between false-positive/true-postitive hits. + - `_.krakenuniq.classified.txt`: An optional list of read IDs and the hits each read had against each database for a given sample.
    -The main taxonomic classification file from KrakenUniq is the `*report.txt` file. This is an extension of the Kraken2 report with the additional k-mer coverage information that provides more information about the accuracy of hits. +The main taxonomic classification file from KrakenUniq is the `*.krakenuniq.report.txt` file. This is an extension of the Kraken2 report with the additional k-mer coverage information that provides more information about the accuracy of hits. -You will only receive the `.fastq` and `*classifiedreads.txt` file if you supply `--krakenuniq_save_reads` and/or `--krakenuniq_save_readclassification` parameters to the pipeline. +You will only receive the `.fasta.gz` and `*.krakenuniq.classified.txt` file if you supply `--krakenuniq_save_reads` and/or `--krakenuniq_save_readclassification` parameters to the pipeline. :::info The output system of KrakenUniq can result in other `stdout` or `stderr` logging information being saved in the report file, therefore you must check your report files before downstream use! diff --git a/docs/usage.md b/docs/usage.md index 205d200d..dc398350 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -44,12 +44,11 @@ This samplesheet is then specified on the command line as follows: The `sample` identifiers have to be the same when you have re-sequenced the same sample more than once e.g. to increase sequencing depth. The pipeline will concatenate different runs FASTQ files of the same sample before performing profiling, when `--perform_runmerging` is supplied. Below is an example for the same sample sequenced across 3 lanes: -```console +```csv title="samplesheet.csv" sample,run_accession,instrument_platform,fastq_1,fastq_2,fasta 2612,run1,ILLUMINA,2612_run1_R1.fq.gz,, 2612,run2,ILLUMINA,2612_run2_R1.fq.gz,, 2612,run3,ILLUMINA,2612_run3_R1.fq.gz,2612_run3_R2.fq.gz, - ``` :::warning @@ -62,7 +61,7 @@ The pipeline will auto-detect whether a sample is single- or paired-end using th A final samplesheet file consisting of both single- and paired-end data, as well as long-read FASTA files may look something like the one below. This is for 6 samples, where `2612` has been sequenced twice. -```console +```csv title="samplesheet.csv" sample,run_accession,instrument_platform,fastq_1,fastq_2,fasta 2611,ERR5766174,ILLUMINA,,,///fasta/ERX5474930_ERR5766174_1.fa.gz 2612,ERR5766176,ILLUMINA,///fastq/ERX5474932_ERR5766176_1.fastq.gz,///fastq/ERX5474932_ERR5766176_2.fastq.gz, @@ -110,7 +109,7 @@ An example database sheet can look as follows, where 7 tools are being used, and `kraken2` will be run twice even though only having a single 'dedicated' database because specifying `bracken` implies first running `kraken2` on the `bracken` database, as required by `bracken`. -```console +```csv tool,db_name,db_params,db_path malt,malt85,-id 85,///malt/testdb-malt/ malt,malt95,-id 90,///malt/testdb-malt.tar.gz diff --git a/lib/NfcoreTemplate.groovy b/lib/NfcoreTemplate.groovy index 01b8653d..e248e4c3 100755 --- a/lib/NfcoreTemplate.groovy +++ b/lib/NfcoreTemplate.groovy @@ -4,6 +4,7 @@ import org.yaml.snakeyaml.Yaml import groovy.json.JsonOutput +import nextflow.extension.FilesEx class NfcoreTemplate { @@ -141,12 +142,14 @@ class NfcoreTemplate { try { if (params.plaintext_email) { throw GroovyException('Send plaintext e-mail, not HTML') } // Try to send HTML e-mail using sendmail + def sendmail_tf = new File(workflow.launchDir.toString(), ".sendmail_tmp.html") + sendmail_tf.withWriter { w -> w << sendmail_html } [ 'sendmail', '-t' ].execute() << sendmail_html log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (sendmail)-" } catch (all) { // Catch failures and try with plaintext def mail_cmd = [ 'mail', '-s', subject, '--content-type=text/html', email_address ] - if ( mqc_report.size() <= max_multiqc_email_size.toBytes() ) { + if ( mqc_report != null && mqc_report.size() <= max_multiqc_email_size.toBytes() ) { mail_cmd += [ '-A', mqc_report ] } mail_cmd.execute() << email_html @@ -155,14 +158,16 @@ class NfcoreTemplate { } // Write summary e-mail HTML to a file - def output_d = new File("${params.outdir}/pipeline_info/") - if (!output_d.exists()) { - output_d.mkdirs() - } - def output_hf = new File(output_d, "pipeline_report.html") + def output_hf = new File(workflow.launchDir.toString(), ".pipeline_report.html") output_hf.withWriter { w -> w << email_html } - def output_tf = new File(output_d, "pipeline_report.txt") + FilesEx.copyTo(output_hf.toPath(), "${params.outdir}/pipeline_info/pipeline_report.html"); + output_hf.delete() + + // Write summary e-mail TXT to a file + def output_tf = new File(workflow.launchDir.toString(), ".pipeline_report.txt") output_tf.withWriter { w -> w << email_txt } + FilesEx.copyTo(output_tf.toPath(), "${params.outdir}/pipeline_info/pipeline_report.txt"); + output_tf.delete() } // @@ -227,15 +232,14 @@ class NfcoreTemplate { // Dump pipeline parameters in a json file // public static void dump_parameters(workflow, params) { - def output_d = new File("${params.outdir}/pipeline_info/") - if (!output_d.exists()) { - output_d.mkdirs() - } - def timestamp = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss') - def output_pf = new File(output_d, "params_${timestamp}.json") + def filename = "params_${timestamp}.json" + def temp_pf = new File(workflow.launchDir.toString(), ".${filename}") def jsonStr = JsonOutput.toJson(params) - output_pf.text = JsonOutput.prettyPrint(jsonStr) + temp_pf.text = JsonOutput.prettyPrint(jsonStr) + + FilesEx.copyTo(temp_pf.toPath(), "${params.outdir}/pipeline_info/params_${timestamp}.json") + temp_pf.delete() } // diff --git a/lib/WorkflowTaxprofiler.groovy b/lib/WorkflowTaxprofiler.groovy index 6a9ce565..d6f45909 100755 --- a/lib/WorkflowTaxprofiler.groovy +++ b/lib/WorkflowTaxprofiler.groovy @@ -216,7 +216,7 @@ class WorkflowTaxprofiler { meta["manifest_map"] = run_workflow.manifest.toMap() // Pipeline DOI - meta["doi_text"] = meta.manifest_map.doi ? "(doi: ${meta.manifest_map.doi})" : "" + meta["doi_text"] = meta.manifest_map.doi ? "(doi: Stamouli et al. 2023)" : "" meta["nodoi_text"] = meta.manifest_map.doi ? "": "
  • If available, make sure to update the text to include the Zenodo DOI of version of the pipeline used.
  • " meta["tool_citations"] = "" diff --git a/main.nf b/main.nf index 54760e0f..a016b517 100644 --- a/main.nf +++ b/main.nf @@ -17,10 +17,6 @@ nextflow.enable.dsl = 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -// TODO nf-core: Remove this line if you don't need a FASTA file -// This is an example of how to use getGenomeAttribute() to fetch parameters -// from igenomes.config using `--genome` - /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VALIDATE & PRINT PARAMETER SUMMARY diff --git a/modules.json b/modules.json index aa63d31d..9f195992 100644 --- a/modules.json +++ b/modules.json @@ -7,7 +7,7 @@ "nf-core": { "adapterremoval": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "5add1e8e11af620c779462936ce8bbcc1abcef2d", "installed_by": ["modules"] }, "bbmap/bbduk": { @@ -52,7 +52,7 @@ }, "custom/dumpsoftwareversions": { "branch": "master", - "git_sha": "05c280924b6c768d484c7c443dad5e605c4ff4b4", + "git_sha": "8ec825f465b9c17f9d83000022995b4f7de6fe93", "installed_by": ["modules"] }, "diamond/blastx": { @@ -73,12 +73,12 @@ }, "fastqc": { "branch": "master", - "git_sha": "bd8092b67b5103bdd52e300f75889442275c3117", + "git_sha": "617777a807a1770f73deb38c80004bac06807eef", "installed_by": ["modules"] }, "filtlong": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "b4c8ac68ffcdabac3f63aaa5e7420b175e1d8d76", "installed_by": ["modules"] }, "ganon/classify": { @@ -143,7 +143,7 @@ }, "krakenuniq/preloadedkrakenuniq": { "branch": "master", - "git_sha": "451df5258e0c03cb4e835bb02c22a9a31b44eb0d", + "git_sha": "8bbaa881ab9e59f3e18680550d65d52339640630", "installed_by": ["modules"] }, "krona/ktimporttaxonomy": { @@ -198,7 +198,7 @@ }, "multiqc": { "branch": "master", - "git_sha": "a6e11ac655e744f7ebc724be669dd568ffdc0e80", + "git_sha": "8ec825f465b9c17f9d83000022995b4f7de6fe93", "installed_by": ["modules"] }, "porechop/porechop": { diff --git a/modules/nf-core/adapterremoval/environment.yml b/modules/nf-core/adapterremoval/environment.yml new file mode 100644 index 00000000..1737b14b --- /dev/null +++ b/modules/nf-core/adapterremoval/environment.yml @@ -0,0 +1,7 @@ +name: adapterremoval +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::adapterremoval=2.3.2 diff --git a/modules/nf-core/adapterremoval/main.nf b/modules/nf-core/adapterremoval/main.nf index 29aac1c0..d128d324 100644 --- a/modules/nf-core/adapterremoval/main.nf +++ b/modules/nf-core/adapterremoval/main.nf @@ -2,7 +2,7 @@ process ADAPTERREMOVAL { tag "$meta.id" label 'process_medium' - conda "bioconda::adapterremoval=2.3.2" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/adapterremoval:2.3.2--hb7ba0dd_0' : 'biocontainers/adapterremoval:2.3.2--hb7ba0dd_0' }" diff --git a/modules/nf-core/adapterremoval/meta.yml b/modules/nf-core/adapterremoval/meta.yml index 77273f60..2deb613b 100644 --- a/modules/nf-core/adapterremoval/meta.yml +++ b/modules/nf-core/adapterremoval/meta.yml @@ -11,7 +11,6 @@ tools: homepage: https://github.com/MikkelSchubert/adapterremoval documentation: https://adapterremoval.readthedocs.io licence: ["GPL v3"] - input: - meta: type: map @@ -26,17 +25,8 @@ input: pattern: "*.{fq,fastq,fq.gz,fastq.gz}" - adapterlist: type: file - description: Optional text file containing list of adapters to look for for removal - with one adapter per line. Otherwise will look for default adapters (see - AdapterRemoval man page), or can be modified to remove user-specified - adapters via ext.args. - + description: Optional text file containing list of adapters to look for for removal with one adapter per line. Otherwise will look for default adapters (see AdapterRemoval man page), or can be modified to remove user-specified adapters via ext.args. output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - singles_truncated: type: file description: | @@ -50,20 +40,13 @@ output: Adapter trimmed FastQ files of reads that did not pass filtering thresholds. pattern: "*.discarded.fastq.gz" - - pair1_truncated: + - paired_truncated: type: file description: | - Adapter trimmed R1 FastQ files of paired-end reads that did not merge - with their respective R2 pair due to long templates. The respective pair - is stored in 'pair2_truncated'. - pattern: "*.pair1.truncated.fastq.gz" - - pair2_truncated: - type: file - description: | - Adapter trimmed R2 FastQ files of paired-end reads that did not merge - with their respective R1 pair due to long templates. The respective pair - is stored in 'pair1_truncated'. - pattern: "*.pair2.truncated.fastq.gz" + Adapter trimmed R{1,2} FastQ files of paired-end reads that did not merge + with their respective R{1,2} pair due to long templates. The respective pair + is stored in 'pair{1,2}_truncated'. + pattern: "*.pair{1,2}.truncated.fastq.gz" - collapsed: type: file description: | @@ -76,7 +59,12 @@ output: Collapsed FastQ of paired-end reads that successfully merged with their respective R1 pair and were trimmed of adapter due to sufficient overlap. pattern: "*.collapsed.truncated.fastq.gz" - - log: + - paired_interleaved: + type: file + description: | + Write paired-end reads to a single file, interleaving mate 1 and mate 2 reads + pattern: "*.paired.fastq.gz" + - settings: type: file description: AdapterRemoval log file pattern: "*.settings" @@ -84,7 +72,9 @@ output: type: file description: File containing software versions pattern: "versions.yml" - authors: - "@maxibor" - "@jfy133" +maintainers: + - "@maxibor" + - "@jfy133" diff --git a/modules/nf-core/adapterremoval/tests/main.nf.test b/modules/nf-core/adapterremoval/tests/main.nf.test new file mode 100644 index 00000000..91c07b7e --- /dev/null +++ b/modules/nf-core/adapterremoval/tests/main.nf.test @@ -0,0 +1,120 @@ +nextflow_process { + + name "Test Process ADAPTERREMOVAL" + script "../main.nf" + process "ADAPTERREMOVAL" + + tag "modules" + tag "modules_nfcore" + tag "adapterremoval" + + test("single-end - sarscov2 - [fastq]") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true, collapse:false ], // meta map + file(params.test_data['sarscov2']['illumina']['test_1_fastq_gz'], checkIfExists: true) + ] + input[1] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out.singles_truncated, + process.out.settings, + process.out.versions).match() }, + ) + } + } + + test("paired-end - sarscov2 - [fastq]") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false, collapse:false ], // meta map + [ file(params.test_data['sarscov2']['illumina']['test_1_fastq_gz'], checkIfExists: true), + file(params.test_data['sarscov2']['illumina']['test_2_fastq_gz'], checkIfExists: true) ] + ] + input[1] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out.paired_truncated, + process.out.settings, + process.out.versions).match() }, + { assert process.out.discarded } + ) + } + + } + + test("paired-end collapse - sarscov2 - [fastq]") { + + options "--collapse" + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + [ file(params.test_data['sarscov2']['illumina']['test_1_fastq_gz'], checkIfExists: true), + file(params.test_data['sarscov2']['illumina']['test_2_fastq_gz'], checkIfExists: true) ] + ] + input[1] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out.paired_truncated, + process.out.collapsed, + process.out.settings, + process.out.versions).match() }, + { assert process.out.discarded } + ) + } + + } + + test("paired-end adapterlist - sarscov2 - [fastq]") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false, collapse:false ], // meta map + [ file(params.test_data['sarscov2']['illumina']['test_1_fastq_gz'], checkIfExists: true), + file(params.test_data['sarscov2']['illumina']['test_2_fastq_gz'], checkIfExists: true) ] + ] + input[1] = file("https://github.com/nf-core/test-datasets/raw/modules/data/delete_me/adapterremoval/adapterremoval_adapterlist.txt", + checkIfExists: true) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out.paired_truncated, + process.out.settings, + process.out.versions).match() }, + { assert process.out.discarded } + ) + } + + } + +} diff --git a/modules/nf-core/adapterremoval/tests/main.nf.test.snap b/modules/nf-core/adapterremoval/tests/main.nf.test.snap new file mode 100644 index 00000000..f890167a --- /dev/null +++ b/modules/nf-core/adapterremoval/tests/main.nf.test.snap @@ -0,0 +1,124 @@ +{ + "single-end - sarscov2 - [fastq]": { + "content": [ + [ + [ + { + "id": "test", + "single_end": true, + "collapse": false + }, + "test.truncated.fastq.gz:md5,119d1b1a0a71ca6e080ff7c53ee0b690" + ] + ], + [ + [ + { + "id": "test", + "single_end": true, + "collapse": false + }, + "test.settings:md5,2fd3d5d703b63ba33a83021fccf25f77" + ] + ], + [ + "versions.yml:md5,00bcc9f0b864b96eeee21bc11773ee67" + ] + ], + "timestamp": "2023-12-09T19:19:36.429445996" + }, + "paired-end - sarscov2 - [fastq]": { + "content": [ + [ + [ + { + "id": "test", + "single_end": false, + "collapse": false + }, + [ + "test.pair1.truncated.fastq.gz:md5,e3da014fbb9b428e952c62e8f0fb6402", + "test.pair2.truncated.fastq.gz:md5,2ebae722295ea66d84075a3b042e2b42" + ] + ] + ], + [ + [ + { + "id": "test", + "single_end": false, + "collapse": false + }, + "test.settings:md5,b8a451d3981b327f3fdb44f40ba2d6d1" + ] + ], + [ + "versions.yml:md5,00bcc9f0b864b96eeee21bc11773ee67" + ] + ], + "timestamp": "2023-12-09T19:19:42.88672676" + }, + "paired-end collapse - sarscov2 - [fastq]": { + "content": [ + [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test.pair1.truncated.fastq.gz:md5,e3da014fbb9b428e952c62e8f0fb6402", + "test.pair2.truncated.fastq.gz:md5,2ebae722295ea66d84075a3b042e2b42" + ] + ] + ], + [ + + ], + [ + [ + { + "id": "test", + "single_end": false + }, + "test.settings:md5,b8a451d3981b327f3fdb44f40ba2d6d1" + ] + ], + [ + "versions.yml:md5,00bcc9f0b864b96eeee21bc11773ee67" + ] + ], + "timestamp": "2023-12-09T19:19:49.299792876" + }, + "paired-end adapterlist - sarscov2 - [fastq]": { + "content": [ + [ + [ + { + "id": "test", + "single_end": false, + "collapse": false + }, + [ + "test.pair1.truncated.fastq.gz:md5,e3da014fbb9b428e952c62e8f0fb6402", + "test.pair2.truncated.fastq.gz:md5,2ebae722295ea66d84075a3b042e2b42" + ] + ] + ], + [ + [ + { + "id": "test", + "single_end": false, + "collapse": false + }, + "test.settings:md5,36d47d9b40dbc178167d1ae0274d18f3" + ] + ], + [ + "versions.yml:md5,00bcc9f0b864b96eeee21bc11773ee67" + ] + ], + "timestamp": "2023-12-09T19:19:57.26567964" + } +} \ No newline at end of file diff --git a/modules/nf-core/adapterremoval/tests/tags.yml b/modules/nf-core/adapterremoval/tests/tags.yml new file mode 100644 index 00000000..d3375ec5 --- /dev/null +++ b/modules/nf-core/adapterremoval/tests/tags.yml @@ -0,0 +1,2 @@ +adapterremoval: + - "modules/nf-core/adapterremoval/**" diff --git a/modules/nf-core/custom/dumpsoftwareversions/environment.yml b/modules/nf-core/custom/dumpsoftwareversions/environment.yml new file mode 100644 index 00000000..9b3272bc --- /dev/null +++ b/modules/nf-core/custom/dumpsoftwareversions/environment.yml @@ -0,0 +1,7 @@ +name: custom_dumpsoftwareversions +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::multiqc=1.19 diff --git a/modules/nf-core/custom/dumpsoftwareversions/main.nf b/modules/nf-core/custom/dumpsoftwareversions/main.nf index c9d014b1..f2187611 100644 --- a/modules/nf-core/custom/dumpsoftwareversions/main.nf +++ b/modules/nf-core/custom/dumpsoftwareversions/main.nf @@ -2,10 +2,10 @@ process CUSTOM_DUMPSOFTWAREVERSIONS { label 'process_single' // Requires `pyyaml` which does not have a dedicated container but is in the MultiQC container - conda "bioconda::multiqc=1.15" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.15--pyhdfd78af_0' : - 'biocontainers/multiqc:1.15--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/multiqc:1.19--pyhdfd78af_0' : + 'biocontainers/multiqc:1.19--pyhdfd78af_0' }" input: path versions diff --git a/modules/nf-core/custom/dumpsoftwareversions/meta.yml b/modules/nf-core/custom/dumpsoftwareversions/meta.yml index c32657de..5f15a5fd 100644 --- a/modules/nf-core/custom/dumpsoftwareversions/meta.yml +++ b/modules/nf-core/custom/dumpsoftwareversions/meta.yml @@ -1,4 +1,4 @@ -# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/yaml-schema.json +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/meta-schema.json name: custom_dumpsoftwareversions description: Custom module used to dump software versions within the nf-core pipeline template keywords: @@ -16,7 +16,6 @@ input: type: file description: YML file containing software versions pattern: "*.yml" - output: - yml: type: file @@ -30,7 +29,9 @@ output: type: file description: File containing software versions pattern: "versions.yml" - authors: - "@drpatelh" - "@grst" +maintainers: + - "@drpatelh" + - "@grst" diff --git a/modules/nf-core/custom/dumpsoftwareversions/tests/main.nf.test b/modules/nf-core/custom/dumpsoftwareversions/tests/main.nf.test new file mode 100644 index 00000000..b1e1630b --- /dev/null +++ b/modules/nf-core/custom/dumpsoftwareversions/tests/main.nf.test @@ -0,0 +1,43 @@ +nextflow_process { + + name "Test Process CUSTOM_DUMPSOFTWAREVERSIONS" + script "../main.nf" + process "CUSTOM_DUMPSOFTWAREVERSIONS" + tag "modules" + tag "modules_nfcore" + tag "custom" + tag "dumpsoftwareversions" + tag "custom/dumpsoftwareversions" + + test("Should run without failures") { + when { + process { + """ + def tool1_version = ''' + TOOL1: + tool1: 0.11.9 + '''.stripIndent() + + def tool2_version = ''' + TOOL2: + tool2: 1.9 + '''.stripIndent() + + input[0] = Channel.of(tool1_version, tool2_version).collectFile() + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + process.out.versions, + file(process.out.mqc_yml[0]).readLines()[0..10], + file(process.out.yml[0]).readLines()[0..7] + ).match() + } + ) + } + } +} diff --git a/modules/nf-core/custom/dumpsoftwareversions/tests/main.nf.test.snap b/modules/nf-core/custom/dumpsoftwareversions/tests/main.nf.test.snap new file mode 100644 index 00000000..5f59a936 --- /dev/null +++ b/modules/nf-core/custom/dumpsoftwareversions/tests/main.nf.test.snap @@ -0,0 +1,33 @@ +{ + "Should run without failures": { + "content": [ + [ + "versions.yml:md5,76d454d92244589d32455833f7c1ba6d" + ], + [ + "data: \"\\n\\n \\n \\n \\n \\n \\n \\n \\n\\", + " \\n\\n\\n \\n \\n\\", + " \\ \\n\\n\\n\\n \\n \\", + " \\ \\n \\n\\n\\n\\n\\", + " \\n\\n \\n \\n\\", + " \\ \\n\\n\\n\\n\\n\\n \\n\\", + " \\ \\n \\n\\n\\n\\n\\", + " \\n\\n \\n \\n\\" + ], + [ + "CUSTOM_DUMPSOFTWAREVERSIONS:", + " python: 3.11.7", + " yaml: 5.4.1", + "TOOL1:", + " tool1: 0.11.9", + "TOOL2:", + " tool2: '1.9'", + "Workflow:" + ] + ], + "timestamp": "2024-01-09T23:01:18.710682" + } +} \ No newline at end of file diff --git a/modules/nf-core/custom/dumpsoftwareversions/tests/tags.yml b/modules/nf-core/custom/dumpsoftwareversions/tests/tags.yml new file mode 100644 index 00000000..405aa24a --- /dev/null +++ b/modules/nf-core/custom/dumpsoftwareversions/tests/tags.yml @@ -0,0 +1,2 @@ +custom/dumpsoftwareversions: + - modules/nf-core/custom/dumpsoftwareversions/** diff --git a/modules/nf-core/fastqc/environment.yml b/modules/nf-core/fastqc/environment.yml new file mode 100644 index 00000000..1787b38a --- /dev/null +++ b/modules/nf-core/fastqc/environment.yml @@ -0,0 +1,7 @@ +name: fastqc +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::fastqc=0.12.1 diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf index 249f9064..9e19a74c 100644 --- a/modules/nf-core/fastqc/main.nf +++ b/modules/nf-core/fastqc/main.nf @@ -2,10 +2,10 @@ process FASTQC { tag "$meta.id" label 'process_medium' - conda "bioconda::fastqc=0.11.9" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/fastqc:0.11.9--0' : - 'biocontainers/fastqc:0.11.9--0' }" + 'https://depot.galaxyproject.org/singularity/fastqc:0.12.1--hdfd78af_0' : + 'biocontainers/fastqc:0.12.1--hdfd78af_0' }" input: tuple val(meta), path(reads) @@ -37,7 +37,7 @@ process FASTQC { cat <<-END_VERSIONS > versions.yml "${task.process}": - fastqc: \$( fastqc --version | sed -e "s/FastQC v//g" ) + fastqc: \$( fastqc --version | sed '/FastQC v/!d; s/.*v//' ) END_VERSIONS """ @@ -49,7 +49,7 @@ process FASTQC { cat <<-END_VERSIONS > versions.yml "${task.process}": - fastqc: \$( fastqc --version | sed -e "s/FastQC v//g" ) + fastqc: \$( fastqc --version | sed '/FastQC v/!d; s/.*v//' ) END_VERSIONS """ } diff --git a/modules/nf-core/fastqc/meta.yml b/modules/nf-core/fastqc/meta.yml index 4da5bb5a..ee5507e0 100644 --- a/modules/nf-core/fastqc/meta.yml +++ b/modules/nf-core/fastqc/meta.yml @@ -50,3 +50,8 @@ authors: - "@grst" - "@ewels" - "@FelixKrueger" +maintainers: + - "@drpatelh" + - "@grst" + - "@ewels" + - "@FelixKrueger" diff --git a/modules/nf-core/fastqc/tests/main.nf.test b/modules/nf-core/fastqc/tests/main.nf.test index 3961de60..ad9bc54f 100644 --- a/modules/nf-core/fastqc/tests/main.nf.test +++ b/modules/nf-core/fastqc/tests/main.nf.test @@ -1,32 +1,220 @@ nextflow_process { name "Test Process FASTQC" - script "modules/nf-core/fastqc/main.nf" + script "../main.nf" process "FASTQC" + + tag "modules" + tag "modules_nfcore" tag "fastqc" - test("Single-Read") { + test("sarscov2 single-end [fastq]") { when { process { """ input[0] = [ - [ id: 'test', single_end:true ], - [ - file(params.test_data['sarscov2']['illumina']['test_1_fastq_gz'], checkIfExists: true) - ] + [ id: 'test', single_end:true ], + [ + file(params.test_data['sarscov2']['illumina']['test_1_fastq_gz'], checkIfExists: true) + ] ] """ } } then { - assert process.success - assert process.out.html.get(0).get(1) ==~ ".*/test_fastqc.html" - assert path(process.out.html.get(0).get(1)).getText().contains("") - assert process.out.zip.get(0).get(1) ==~ ".*/test_fastqc.zip" + assertAll ( + { assert process.success }, + + // NOTE The report contains the date inside it, which means that the md5sum is stable per day, but not longer than that. So you can't md5sum it. + // looks like this:
    Mon 2 Oct 2023
    test.gz
    + // https://github.com/nf-core/modules/pull/3903#issuecomment-1743620039 + + { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("") }, + + { assert snapshot(process.out.versions).match("versions") } + ) + } + } + + test("sarscov2 paired-end [fastq]") { + + when { + process { + """ + input[0] = [ + [id: 'test', single_end: false], // meta map + [ + file(params.test_data['sarscov2']['illumina']['test_1_fastq_gz'], checkIfExists: true), + file(params.test_data['sarscov2']['illumina']['test_2_fastq_gz'], checkIfExists: true) + ] + ] + """ + } + } + + then { + assertAll ( + { assert process.success }, + + { assert process.out.html[0][1][0] ==~ ".*/test_1_fastqc.html" }, + { assert process.out.html[0][1][1] ==~ ".*/test_2_fastqc.html" }, + { assert process.out.zip[0][1][0] ==~ ".*/test_1_fastqc.zip" }, + { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, + { assert path(process.out.html[0][1][0]).text.contains("") }, + { assert path(process.out.html[0][1][1]).text.contains("") }, + + { assert snapshot(process.out.versions).match("versions") } + ) + } + } + + test("sarscov2 interleaved [fastq]") { + + when { + process { + """ + input[0] = [ + [id: 'test', single_end: false], // meta map + file(params.test_data['sarscov2']['illumina']['test_interleaved_fastq_gz'], checkIfExists: true) + ] + """ + } + } + + then { + assertAll ( + { assert process.success }, + + { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("") }, + + { assert snapshot(process.out.versions).match("versions") } + ) + } + } + + test("sarscov2 paired-end [bam]") { + + when { + process { + """ + input[0] = [ + [id: 'test', single_end: false], // meta map + file(params.test_data['sarscov2']['illumina']['test_paired_end_sorted_bam'], checkIfExists: true) + ] + """ + } + } + + then { + assertAll ( + { assert process.success }, + + { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("") }, + + { assert snapshot(process.out.versions).match("versions") } + ) + } + } + + test("sarscov2 multiple [fastq]") { + + when { + process { + """ + input[0] = [ + [id: 'test', single_end: false], // meta map + [ + file(params.test_data['sarscov2']['illumina']['test_1_fastq_gz'], checkIfExists: true), + file(params.test_data['sarscov2']['illumina']['test_2_fastq_gz'], checkIfExists: true), + file(params.test_data['sarscov2']['illumina']['test2_1_fastq_gz'], checkIfExists: true), + file(params.test_data['sarscov2']['illumina']['test2_2_fastq_gz'], checkIfExists: true) + ] + ] + """ + } + } + + then { + assertAll ( + { assert process.success }, + + { assert process.out.html[0][1][0] ==~ ".*/test_1_fastqc.html" }, + { assert process.out.html[0][1][1] ==~ ".*/test_2_fastqc.html" }, + { assert process.out.html[0][1][2] ==~ ".*/test_3_fastqc.html" }, + { assert process.out.html[0][1][3] ==~ ".*/test_4_fastqc.html" }, + { assert process.out.zip[0][1][0] ==~ ".*/test_1_fastqc.zip" }, + { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, + { assert process.out.zip[0][1][2] ==~ ".*/test_3_fastqc.zip" }, + { assert process.out.zip[0][1][3] ==~ ".*/test_4_fastqc.zip" }, + { assert path(process.out.html[0][1][0]).text.contains("") }, + { assert path(process.out.html[0][1][1]).text.contains("") }, + { assert path(process.out.html[0][1][2]).text.contains("") }, + { assert path(process.out.html[0][1][3]).text.contains("") }, + + { assert snapshot(process.out.versions).match("versions") } + ) + } + } + + test("sarscov2 custom_prefix") { + + when { + process { + """ + input[0] = [ + [ id:'mysample', single_end:true ], // meta map + file(params.test_data['sarscov2']['illumina']['test_1_fastq_gz'], checkIfExists: true) + ] + """ + } + } + + then { + assertAll ( + { assert process.success }, + + { assert process.out.html[0][1] ==~ ".*/mysample_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/mysample_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("") }, + + { assert snapshot(process.out.versions).match("versions") } + ) + } + } + + test("sarscov2 single-end [fastq] - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id: 'test', single_end:true ], + [ + file(params.test_data['sarscov2']['illumina']['test_1_fastq_gz'], checkIfExists: true) + ] + ] + """ + } } + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out.html.collect { file(it[1]).getName() } + + process.out.zip.collect { file(it[1]).getName() } + + process.out.versions ).match() } + ) + } } } diff --git a/modules/nf-core/fastqc/tests/main.nf.test.snap b/modules/nf-core/fastqc/tests/main.nf.test.snap new file mode 100644 index 00000000..5ef5afbd --- /dev/null +++ b/modules/nf-core/fastqc/tests/main.nf.test.snap @@ -0,0 +1,20 @@ +{ + "sarscov2 single-end [fastq] - stub": { + "content": [ + [ + "test.html", + "test.zip", + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ] + ], + "timestamp": "2023-12-29T02:48:05.126117287" + }, + "versions": { + "content": [ + [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ] + ], + "timestamp": "2023-12-29T02:46:49.507942667" + } +} \ No newline at end of file diff --git a/modules/nf-core/fastqc/tests/tags.yml b/modules/nf-core/fastqc/tests/tags.yml new file mode 100644 index 00000000..7834294b --- /dev/null +++ b/modules/nf-core/fastqc/tests/tags.yml @@ -0,0 +1,2 @@ +fastqc: + - modules/nf-core/fastqc/** diff --git a/modules/nf-core/filtlong/environment.yml b/modules/nf-core/filtlong/environment.yml new file mode 100644 index 00000000..0fb7e8b4 --- /dev/null +++ b/modules/nf-core/filtlong/environment.yml @@ -0,0 +1,7 @@ +name: filtlong +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::filtlong=0.2.1 diff --git a/modules/nf-core/filtlong/main.nf b/modules/nf-core/filtlong/main.nf index a377095c..627247fe 100644 --- a/modules/nf-core/filtlong/main.nf +++ b/modules/nf-core/filtlong/main.nf @@ -2,7 +2,7 @@ process FILTLONG { tag "$meta.id" label 'process_low' - conda "bioconda::filtlong=0.2.1" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/filtlong:0.2.1--h9a82719_0' : 'biocontainers/filtlong:0.2.1--h9a82719_0' }" @@ -28,7 +28,7 @@ process FILTLONG { $short_reads \\ $args \\ $longreads \\ - 2> ${prefix}.log \\ + 2> >(tee ${prefix}.log >&2) \\ | gzip -n > ${prefix}.fastq.gz cat <<-END_VERSIONS > versions.yml diff --git a/modules/nf-core/filtlong/meta.yml b/modules/nf-core/filtlong/meta.yml index 9be850b0..4a0f072a 100644 --- a/modules/nf-core/filtlong/meta.yml +++ b/modules/nf-core/filtlong/meta.yml @@ -11,11 +11,8 @@ tools: - filtlong: description: Filtlong is a tool for filtering long reads. It can take a set of long reads and produce a smaller, better subset. It uses both read length (longer is better) and read identity (higher is better) when choosing which reads pass the filter. homepage: https://anaconda.org/bioconda/filtlong - tool_dev_url: https://github.com/rrwick/Filtlong - licence: ["GPL v3"] - input: - meta: type: map @@ -30,7 +27,6 @@ input: type: file description: fastq file pattern: "*.{fq,fastq,fq.gz,fastq.gz}" - output: - meta: type: map @@ -49,7 +45,9 @@ output: type: file description: Standard error logging file containing summary statistics pattern: "*.log" - authors: - "@d4straub" - "@sofstam" +maintainers: + - "@d4straub" + - "@sofstam" diff --git a/modules/nf-core/filtlong/tests/main.nf.test b/modules/nf-core/filtlong/tests/main.nf.test new file mode 100644 index 00000000..b7d73e79 --- /dev/null +++ b/modules/nf-core/filtlong/tests/main.nf.test @@ -0,0 +1,99 @@ +nextflow_process { + + name "Test Process FILTLONG" + script "../main.nf" + process "FILTLONG" + config "./nextflow.config" + tag "filtlong" + tag "modules" + tag "modules_nfcore" + + test("sarscov2 nanopore [fastq]") { + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + [], + [ file(params.test_data['sarscov2']['nanopore']['test_fastq_gz'], checkIfExists: true) ] + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert path(process.out.log.get(0).get(1)).readLines().contains("Scoring long reads")}, + { assert snapshot(process.out.reads).match("nanopore") }, + { assert snapshot(process.out.versions).match("versions") } + ) + } + + } + + + test("sarscov2 nanopore [fastq] + Illumina single-end [fastq]") { + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + [ file(params.test_data['sarscov2']['illumina']['test_1_fastq_gz'], checkIfExists: true) ], + [ file(params.test_data['sarscov2']['nanopore']['test_fastq_gz'], checkIfExists: true) ] + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert path(process.out.log.get(0).get(1)).readLines().contains("Scoring long reads")}, + { assert snapshot(process.out.reads).match("nanopore_illumina_se") }, + { assert snapshot(process.out.versions).match("versions") } + ) + } + + } + + + test("sarscov2 nanopore [fastq] + Illumina paired-end [fastq]") { + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + [ file(params.test_data['sarscov2']['illumina']['test_1_fastq_gz'], checkIfExists: true), + file(params.test_data['sarscov2']['illumina']['test_2_fastq_gz'], checkIfExists: true) ], + [ file(params.test_data['sarscov2']['nanopore']['test_fastq_gz'], checkIfExists: true) ] + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert path(process.out.log.get(0).get(1)).readLines().contains("Scoring long reads")}, + { assert snapshot(process.out.reads).match("nanopore_illumina_pe") }, + { assert snapshot(process.out.versions).match("versions") } + ) + } + + } + + +} diff --git a/modules/nf-core/filtlong/tests/main.nf.test.snap b/modules/nf-core/filtlong/tests/main.nf.test.snap new file mode 100644 index 00000000..49d4bb6c --- /dev/null +++ b/modules/nf-core/filtlong/tests/main.nf.test.snap @@ -0,0 +1,52 @@ +{ + "nanopore": { + "content": [ + [ + [ + { + "id": "test", + "single_end": false + }, + "test_lr.fastq.gz:md5,7567d853ada6ac142332619d0b541d76" + ] + ] + ], + "timestamp": "2023-12-11T14:23:36.351509" + }, + "versions": { + "content": [ + [ + "versions.yml:md5,af5988f30157282acdb0ac50ebb4c8cc" + ] + ], + "timestamp": "2023-12-11T14:23:36.372189" + }, + "nanopore_illumina_pe": { + "content": [ + [ + [ + { + "id": "test", + "single_end": false + }, + "test_lr.fastq.gz:md5,7567d853ada6ac142332619d0b541d76" + ] + ] + ], + "timestamp": "2023-12-11T14:24:05.202047" + }, + "nanopore_illumina_se": { + "content": [ + [ + [ + { + "id": "test", + "single_end": true + }, + "test_lr.fastq.gz:md5,7567d853ada6ac142332619d0b541d76" + ] + ] + ], + "timestamp": "2023-12-11T14:23:50.607338" + } +} \ No newline at end of file diff --git a/modules/nf-core/filtlong/tests/nextflow.config b/modules/nf-core/filtlong/tests/nextflow.config new file mode 100644 index 00000000..5e4c9fbb --- /dev/null +++ b/modules/nf-core/filtlong/tests/nextflow.config @@ -0,0 +1,8 @@ +process { + + publishDir = { "${params.outdir}/${task.process.tokenize(':')[-1].tokenize('_')[0].toLowerCase()}" } + + ext.args = "--min_length 10" + ext.prefix = "test_lr" + +} diff --git a/modules/nf-core/filtlong/tests/tags.yml b/modules/nf-core/filtlong/tests/tags.yml new file mode 100644 index 00000000..bf2cff9d --- /dev/null +++ b/modules/nf-core/filtlong/tests/tags.yml @@ -0,0 +1,2 @@ +filtlong: + - modules/nf-core/filtlong/** diff --git a/modules/nf-core/krakenuniq/preloadedkrakenuniq/environment.yml b/modules/nf-core/krakenuniq/preloadedkrakenuniq/environment.yml new file mode 100644 index 00000000..11bbb879 --- /dev/null +++ b/modules/nf-core/krakenuniq/preloadedkrakenuniq/environment.yml @@ -0,0 +1,7 @@ +name: krakenuniq_preloadedkrakenuniq +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::krakenuniq=1.0.4 diff --git a/modules/nf-core/krakenuniq/preloadedkrakenuniq/main.nf b/modules/nf-core/krakenuniq/preloadedkrakenuniq/main.nf index 7083d3f0..59055bdb 100644 --- a/modules/nf-core/krakenuniq/preloadedkrakenuniq/main.nf +++ b/modules/nf-core/krakenuniq/preloadedkrakenuniq/main.nf @@ -2,7 +2,7 @@ process KRAKENUNIQ_PRELOADEDKRAKENUNIQ { tag "$meta.id" label 'process_high' - conda "bioconda::krakenuniq=1.0.4" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/krakenuniq:1.0.4--pl5321h19e8d03_0': 'biocontainers/krakenuniq:1.0.4--pl5321h19e8d03_0' }" @@ -11,17 +11,16 @@ process KRAKENUNIQ_PRELOADEDKRAKENUNIQ { tuple val(meta), path(fastqs) path db val ram_chunk_size - val save_output_fastqs + val save_output_reads val report_file val save_output output: - tuple val(meta), path('*.classified{.,_}*') , optional:true, emit: classified_reads_fastq - tuple val(meta), path('*.unclassified{.,_}*') , optional:true, emit: unclassified_reads_fastq - tuple val(meta), path('*classified.txt') , optional:true, emit: classified_assignment - tuple val(meta), path('*report.txt') , emit: report - - path "versions.yml" , emit: versions + tuple val(meta), path('*.classified.fasta.gz') , optional:true, emit: classified_reads_fasta + tuple val(meta), path('*.unclassified.fasta.gz') , optional:true, emit: unclassified_reads_fasta + tuple val(meta), path('*.krakenuniq.classified.txt'), optional:true, emit: classified_assignment + tuple val(meta), path('*.krakenuniq.report.txt') , emit: report + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when @@ -30,21 +29,21 @@ process KRAKENUNIQ_PRELOADEDKRAKENUNIQ { def args = task.ext.args ?: '' def args2 = task.ext.args ?: '' - def classified = meta.single_end ? '"\${PREFIX}.classified.fastq"' : '"\${PREFIX}.classified#.fastq"' - def unclassified = meta.single_end ? '"\${PREFIX}.unclassified.fastq"' : '"\${PREFIX}.unclassified#.fastq"' - def classified_option = save_output_fastqs ? "--classified-out ${classified}" : '' - def unclassified_option = save_output_fastqs ? "--unclassified-out ${unclassified}" : '' + def classified = meta.single_end ? '"\${PREFIX}.classified.fasta"' : '"\${PREFIX}.merged.classified.fasta"' + def unclassified = meta.single_end ? '"\${PREFIX}.unclassified.fasta"' : '"\${PREFIX}.merged.unclassified.fasta"' + def classified_option = save_output_reads ? "--classified-out ${classified}" : '' + def unclassified_option = save_output_reads ? "--unclassified-out ${unclassified}" : '' def output_option = save_output ? '--output "\${PREFIX}.krakenuniq.classified.txt"' : '' def report = report_file ? '--report-file "\${PREFIX}.krakenuniq.report.txt"' : '' - def compress_reads_command = save_output_fastqs ? 'gzip --no-name *.fastq' : '' + def compress_reads_command = save_output_reads ? 'gzip --no-name *.fasta' : '' if (meta.single_end) { """ krakenuniq \\ + $args \\ --db $db \\ --preload \\ --preload-size $ram_chunk_size \\ - --threads $task.cpus \\ - $args + --threads $task.cpus strip_suffix() { local result=\$1 @@ -62,7 +61,6 @@ process KRAKENUNIQ_PRELOADEDKRAKENUNIQ { $output_option \\ $unclassified_option \\ $classified_option \\ - $output_option \\ $args2 \\ "\${FASTQ}" done @@ -77,11 +75,11 @@ process KRAKENUNIQ_PRELOADEDKRAKENUNIQ { } else { """ krakenuniq \\ + $args \\ --db $db \\ --preload \\ --preload-size $ram_chunk_size \\ - --threads $task.cpus \\ - $args + --threads $task.cpus strip_suffix() { local result @@ -102,7 +100,6 @@ process KRAKENUNIQ_PRELOADEDKRAKENUNIQ { $output_option \\ $unclassified_option \\ $classified_option \\ - $output_option \\ --paired \\ $args2 \\ "\${FASTQ[@]}" @@ -121,21 +118,21 @@ process KRAKENUNIQ_PRELOADEDKRAKENUNIQ { def args = task.ext.args ?: '' def args2 = task.ext.args ?: '' - def classified = meta.single_end ? '"\${PREFIX}.classified.fastq"' : '"\${PREFIX}.classified#.fastq"' - def unclassified = meta.single_end ? '"\${PREFIX}.unclassified.fastq"' : '"\${PREFIX}.unclassified#.fastq"' - def classified_option = save_output_fastqs ? "--classified-out ${classified}" : '' - def unclassified_option = save_output_fastqs ? "--unclassified-out ${unclassified}" : '' + def classified = meta.single_end ? '"\${PREFIX}.classified.fasta"' : '"\${PREFIX}.merged.classified.fasta"' + def unclassified = meta.single_end ? '"\${PREFIX}.unclassified.fasta"' : '"\${PREFIX}.merged.unclassified.fasta"' + def classified_option = save_output_reads ? "--classified-out ${classified}" : '' + def unclassified_option = save_output_reads ? "--unclassified-out ${unclassified}" : '' def output_option = save_output ? '--output "\${PREFIX}.krakenuniq.classified.txt"' : '' def report = report_file ? '--report-file "\${PREFIX}.krakenuniq.report.txt"' : '' - def compress_reads_command = save_output_fastqs ? 'gzip --no-name *.fastq' : '' + def compress_reads_command = save_output_reads ? 'gzip --no-name *.fasta' : '' if (meta.single_end) { """ echo krakenuniq \\ + $args \\ --db $db \\ --preload \\ --preload-size $ram_chunk_size \\ - --threads $task.cpus \\ - $args + --threads $task.cpus strip_suffix() { local result=\$1 @@ -143,6 +140,14 @@ process KRAKENUNIQ_PRELOADEDKRAKENUNIQ { echo "\${result%%.*}" } + create_file() { + echo '<3 nf-core' > "\$1" + } + + create_gzip_file() { + echo '<3 nf-core' | gzip -n > "\$1" + } + printf "%s\\n" ${fastqs} | while read FASTQ; do \\ echo "\${FASTQ}" PREFIX="\$(strip_suffix "\${FASTQ}")" @@ -155,14 +160,13 @@ process KRAKENUNIQ_PRELOADEDKRAKENUNIQ { $output_option \\ $unclassified_option \\ $classified_option \\ - $output_option \\ $args2 \\ "\${FASTQ}" - touch "\${PREFIX}.classified.fastq.gz" - touch "\${PREFIX}.krakenuniq.classified.txt" - touch "\${PREFIX}.krakenuniq.report.txt" - touch "\${PREFIX}.unclassified.fastq.gz" + create_file "\${PREFIX}.krakenuniq.classified.txt" + create_file "\${PREFIX}.krakenuniq.report.txt" + create_gzip_file "\${PREFIX}.classified.fasta.gz" + create_gzip_file "\${PREFIX}.unclassified.fasta.gz" done echo $compress_reads_command @@ -175,11 +179,11 @@ process KRAKENUNIQ_PRELOADEDKRAKENUNIQ { } else { """ echo krakenuniq \\ + $args \\ --db $db \\ --preload \\ --preload-size $ram_chunk_size \\ - --threads $task.cpus \\ - $args + --threads $task.cpus strip_suffix() { local result @@ -189,6 +193,14 @@ process KRAKENUNIQ_PRELOADEDKRAKENUNIQ { echo "\${result%.}" } + create_file() { + echo '<3 nf-core' > "\$1" + } + + create_gzip_file() { + echo '<3 nf-core' | gzip -n > "\$1" + } + printf "%s %s\\n" ${fastqs} | while read FASTQ; do \\ read -r -a FASTQ <<< "\${FASTQ}" echo "\${FASTQ[@]}" @@ -202,15 +214,14 @@ process KRAKENUNIQ_PRELOADEDKRAKENUNIQ { $output_option \\ $unclassified_option \\ $classified_option \\ - $output_option \\ --paired \\ $args2 \\ "\${FASTQ[@]}" - touch "\${PREFIX}.classified_1.fastq.gz" "\${PREFIX}.classified_2.fastq.gz" - touch "\${PREFIX}.krakenuniq.classified.txt" - touch "\${PREFIX}.krakenuniq.report.txt" - touch "\${PREFIX}.unclassified_1.fastq.gz" "\${PREFIX}.unclassified_2.fastq.gz" + create_file "\${PREFIX}.krakenuniq.classified.txt" + create_file "\${PREFIX}.krakenuniq.report.txt" + create_gzip_file "\${PREFIX}.merged.classified.fasta.gz" + create_gzip_file "\${PREFIX}.merged.unclassified.fasta.gz" done echo $compress_reads_command diff --git a/modules/nf-core/krakenuniq/preloadedkrakenuniq/meta.yml b/modules/nf-core/krakenuniq/preloadedkrakenuniq/meta.yml index 41620c7b..4a6dffee 100644 --- a/modules/nf-core/krakenuniq/preloadedkrakenuniq/meta.yml +++ b/modules/nf-core/krakenuniq/preloadedkrakenuniq/meta.yml @@ -13,7 +13,6 @@ tools: documentation: https://github.com/fbreitwieser/krakenuniq doi: 10.1186/s13059-018-1568-0 licence: ["MIT"] - input: - meta: type: map @@ -30,11 +29,11 @@ input: type: string description: Amount of maximum amount of RAM each chunk of database that should be loaded at any one time pattern: "*GB" - - save_output_fastqs: + - save_output_reads: type: boolean description: | - If true, optional commands are added to save classified and unclassified reads - as fastq files + Optionally commands are added to save classified and unclassified reads as FASTA files. + When the input is paired-end, the single output FASTA contains merged reads. - save_reads_assignment: type: boolean description: | @@ -46,29 +45,30 @@ output: description: | Groovy Map containing sample information e.g. [ id:'test', single_end:false ] - - classified_reads_fastq: + - classified_reads_fasta: type: file description: | Reads classified as belonging to any of the taxa - on the KrakenUniq database. - pattern: "*.fastq.gz" - - unclassified_reads_fastq: + in the KrakenUniq reference database. + pattern: "*.classified.fasta.gz" + - unclassified_reads_fasta: type: file description: | Reads not classified to any of the taxa - on the KrakenUniq database. - pattern: "*.fastq.gz" + in the KrakenUniq reference database. + pattern: "*.unclassified.fasta.gz" - classified_assignment: type: file description: | KrakenUniq output file indicating the taxonomic assignment of each input read ## DOUBLE CHECK!! + pattern: "*.krakenuniq.classified.txt" - report: type: file description: | - KrakenUniq report containing stats about classified - and not classifed reads. - pattern: "*.report.txt" + KrakenUniq report containing statistics about classified + and unclassified reads. + pattern: "*.krakenuniq.report.txt" - versions: type: file description: File containing software versions @@ -76,3 +76,6 @@ output: authors: - "@mjamy" - "@Midnighter" +maintainers: + - "@mjamy" + - "@Midnighter" diff --git a/modules/nf-core/krakenuniq/preloadedkrakenuniq/tests/main.nf.test b/modules/nf-core/krakenuniq/preloadedkrakenuniq/tests/main.nf.test new file mode 100644 index 00000000..a7c44707 --- /dev/null +++ b/modules/nf-core/krakenuniq/preloadedkrakenuniq/tests/main.nf.test @@ -0,0 +1,77 @@ +nextflow_process { + + name "Test Process KRAKENUNIQ_PRELOADEDKRAKENUNIQ" + script "../main.nf" + process "KRAKENUNIQ_PRELOADEDKRAKENUNIQ" + tag "modules" + tag "modules_nfcore" + tag "krakenuniq" + tag "krakenuniq/preloadedkrakenuniq" + + test("sarscov2 - Illumina FASTQ single - stub-run") { + options "-stub-run" + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = [ + [id:'test', single_end:true], + [ + file(params.test_data['sarscov2']['illumina']['test_1_fastq_gz'], checkIfExists: true) + ] + ] + input[1] = [] + input[2] = '8GB' + input[3] = true + input[4] = true + input[5] = true + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() }, + ) + } + + } + + test("sarscov2 - Illumina FASTQ paired-end - stub-run") { + options "-stub-run" + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = [ + [id:'test', single_end:false], + [ + file(params.test_data['sarscov2']['illumina']['test_1_fastq_gz'], checkIfExists: true), + file(params.test_data['sarscov2']['illumina']['test_2_fastq_gz'], checkIfExists: true) + ] + ] + input[1] = [] + input[2] = '8GB' + input[3] = true + input[4] = true + input[5] = true + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() }, + ) + } + + } +} diff --git a/modules/nf-core/krakenuniq/preloadedkrakenuniq/tests/main.nf.test.snap b/modules/nf-core/krakenuniq/preloadedkrakenuniq/tests/main.nf.test.snap new file mode 100644 index 00000000..970865bd --- /dev/null +++ b/modules/nf-core/krakenuniq/preloadedkrakenuniq/tests/main.nf.test.snap @@ -0,0 +1,172 @@ +{ + "sarscov2 - Illumina FASTQ paired-end - stub-run": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.merged.classified.fasta.gz:md5,34ed306e94fa7eed00b1adccd2e0de20" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.merged.unclassified.fasta.gz:md5,34ed306e94fa7eed00b1adccd2e0de20" + ] + ], + "2": [ + [ + { + "id": "test", + "single_end": false + }, + "test.krakenuniq.classified.txt:md5,a5704c35e6b573a45e3a344768fe6975" + ] + ], + "3": [ + [ + { + "id": "test", + "single_end": false + }, + "test.krakenuniq.report.txt:md5,a5704c35e6b573a45e3a344768fe6975" + ] + ], + "4": [ + "versions.yml:md5,6abf6c733f53fa3b6aaaa6f06864ef0c" + ], + "classified_assignment": [ + [ + { + "id": "test", + "single_end": false + }, + "test.krakenuniq.classified.txt:md5,a5704c35e6b573a45e3a344768fe6975" + ] + ], + "classified_reads_fasta": [ + [ + { + "id": "test", + "single_end": false + }, + "test.merged.classified.fasta.gz:md5,34ed306e94fa7eed00b1adccd2e0de20" + ] + ], + "report": [ + [ + { + "id": "test", + "single_end": false + }, + "test.krakenuniq.report.txt:md5,a5704c35e6b573a45e3a344768fe6975" + ] + ], + "unclassified_reads_fasta": [ + [ + { + "id": "test", + "single_end": false + }, + "test.merged.unclassified.fasta.gz:md5,34ed306e94fa7eed00b1adccd2e0de20" + ] + ], + "versions": [ + "versions.yml:md5,6abf6c733f53fa3b6aaaa6f06864ef0c" + ] + } + ], + "timestamp": "2023-11-21T15:38:47.810576872" + }, + "sarscov2 - Illumina FASTQ single - stub-run": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test_1.classified.fasta.gz:md5,34ed306e94fa7eed00b1adccd2e0de20" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test_1.unclassified.fasta.gz:md5,34ed306e94fa7eed00b1adccd2e0de20" + ] + ], + "2": [ + [ + { + "id": "test", + "single_end": true + }, + "test_1.krakenuniq.classified.txt:md5,a5704c35e6b573a45e3a344768fe6975" + ] + ], + "3": [ + [ + { + "id": "test", + "single_end": true + }, + "test_1.krakenuniq.report.txt:md5,a5704c35e6b573a45e3a344768fe6975" + ] + ], + "4": [ + "versions.yml:md5,6abf6c733f53fa3b6aaaa6f06864ef0c" + ], + "classified_assignment": [ + [ + { + "id": "test", + "single_end": true + }, + "test_1.krakenuniq.classified.txt:md5,a5704c35e6b573a45e3a344768fe6975" + ] + ], + "classified_reads_fasta": [ + [ + { + "id": "test", + "single_end": true + }, + "test_1.classified.fasta.gz:md5,34ed306e94fa7eed00b1adccd2e0de20" + ] + ], + "report": [ + [ + { + "id": "test", + "single_end": true + }, + "test_1.krakenuniq.report.txt:md5,a5704c35e6b573a45e3a344768fe6975" + ] + ], + "unclassified_reads_fasta": [ + [ + { + "id": "test", + "single_end": true + }, + "test_1.unclassified.fasta.gz:md5,34ed306e94fa7eed00b1adccd2e0de20" + ] + ], + "versions": [ + "versions.yml:md5,6abf6c733f53fa3b6aaaa6f06864ef0c" + ] + } + ], + "timestamp": "2023-11-21T15:38:42.894597091" + } +} \ No newline at end of file diff --git a/modules/nf-core/krakenuniq/preloadedkrakenuniq/tests/tags.yml b/modules/nf-core/krakenuniq/preloadedkrakenuniq/tests/tags.yml new file mode 100644 index 00000000..35ffde4d --- /dev/null +++ b/modules/nf-core/krakenuniq/preloadedkrakenuniq/tests/tags.yml @@ -0,0 +1,2 @@ +krakenuniq/preloadedkrakenuniq: + - modules/nf-core/krakenuniq/preloadedkrakenuniq/** diff --git a/modules/nf-core/multiqc/environment.yml b/modules/nf-core/multiqc/environment.yml new file mode 100644 index 00000000..7625b752 --- /dev/null +++ b/modules/nf-core/multiqc/environment.yml @@ -0,0 +1,7 @@ +name: multiqc +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::multiqc=1.19 diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index 65d7dd0d..1b9f7c43 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -1,10 +1,10 @@ process MULTIQC { label 'process_single' - conda "bioconda::multiqc=1.15" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.15--pyhdfd78af_0' : - 'biocontainers/multiqc:1.15--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/multiqc:1.19--pyhdfd78af_0' : + 'biocontainers/multiqc:1.19--pyhdfd78af_0' }" input: path multiqc_files, stageAs: "?/*" @@ -25,12 +25,14 @@ process MULTIQC { def args = task.ext.args ?: '' def config = multiqc_config ? "--config $multiqc_config" : '' def extra_config = extra_multiqc_config ? "--config $extra_multiqc_config" : '' + def logo = multiqc_logo ? /--cl-config 'custom_logo: "${multiqc_logo}"'/ : '' """ multiqc \\ --force \\ $args \\ $config \\ $extra_config \\ + $logo \\ . cat <<-END_VERSIONS > versions.yml @@ -41,7 +43,7 @@ process MULTIQC { stub: """ - touch multiqc_data + mkdir multiqc_data touch multiqc_plots touch multiqc_report.html diff --git a/modules/nf-core/multiqc/meta.yml b/modules/nf-core/multiqc/meta.yml index f93b5ee5..45a9bc35 100644 --- a/modules/nf-core/multiqc/meta.yml +++ b/modules/nf-core/multiqc/meta.yml @@ -1,5 +1,4 @@ -# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/yaml-schema.json -name: MultiQC +name: multiqc description: Aggregate results from bioinformatics analyses across many samples into a single report keywords: - QC @@ -13,7 +12,6 @@ tools: homepage: https://multiqc.info/ documentation: https://multiqc.info/docs/ licence: ["GPL-3.0-or-later"] - input: - multiqc_files: type: file @@ -31,7 +29,6 @@ input: type: file description: Optional logo file for MultiQC pattern: "*.{png}" - output: - report: type: file @@ -54,3 +51,8 @@ authors: - "@bunop" - "@drpatelh" - "@jfy133" +maintainers: + - "@abhi18av" + - "@bunop" + - "@drpatelh" + - "@jfy133" diff --git a/modules/nf-core/multiqc/tests/main.nf.test b/modules/nf-core/multiqc/tests/main.nf.test new file mode 100644 index 00000000..d0438eda --- /dev/null +++ b/modules/nf-core/multiqc/tests/main.nf.test @@ -0,0 +1,83 @@ +nextflow_process { + + name "Test Process MULTIQC" + script "../main.nf" + process "MULTIQC" + tag "modules" + tag "modules_nfcore" + tag "multiqc" + + test("sarscov2 single-end [fastqc]") { + + when { + process { + """ + input[0] = Channel.of([file(params.test_data['sarscov2']['illumina']['test_1_fastq_gz_fastqc_zip'], checkIfExists: true)]) + input[1] = [] + input[2] = [] + input[3] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert process.out.report[0] ==~ ".*/multiqc_report.html" }, + { assert process.out.data[0] ==~ ".*/multiqc_data" }, + { assert snapshot(process.out.versions).match("versions") } + ) + } + + } + + test("sarscov2 single-end [fastqc] [config]") { + + when { + process { + """ + input[0] = Channel.of([file(params.test_data['sarscov2']['illumina']['test_1_fastq_gz_fastqc_zip'], checkIfExists: true)]) + input[1] = Channel.of(file("https://github.com/nf-core/tools/raw/dev/nf_core/pipeline-template/assets/multiqc_config.yml", checkIfExists: true)) + input[2] = [] + input[3] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert process.out.report[0] ==~ ".*/multiqc_report.html" }, + { assert process.out.data[0] ==~ ".*/multiqc_data" }, + { assert snapshot(process.out.versions).match("versions") } + ) + } + } + + test("sarscov2 single-end [fastqc] - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([file(params.test_data['sarscov2']['illumina']['test_1_fastq_gz_fastqc_zip'], checkIfExists: true)]) + input[1] = [] + input[2] = [] + input[3] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out.report.collect { file(it).getName() } + + process.out.data.collect { file(it).getName() } + + process.out.plots.collect { file(it).getName() } + + process.out.versions ).match() } + ) + } + + } +} diff --git a/modules/nf-core/multiqc/tests/main.nf.test.snap b/modules/nf-core/multiqc/tests/main.nf.test.snap new file mode 100644 index 00000000..d37e7304 --- /dev/null +++ b/modules/nf-core/multiqc/tests/main.nf.test.snap @@ -0,0 +1,21 @@ +{ + "versions": { + "content": [ + [ + "versions.yml:md5,14e9a2661241abd828f4f06a7b5c222d" + ] + ], + "timestamp": "2024-01-09T23:02:49.911994" + }, + "sarscov2 single-end [fastqc] - stub": { + "content": [ + [ + "multiqc_report.html", + "multiqc_data", + "multiqc_plots", + "versions.yml:md5,14e9a2661241abd828f4f06a7b5c222d" + ] + ], + "timestamp": "2024-01-09T23:03:14.524346" + } +} \ No newline at end of file diff --git a/modules/nf-core/multiqc/tests/tags.yml b/modules/nf-core/multiqc/tests/tags.yml new file mode 100644 index 00000000..bea6c0d3 --- /dev/null +++ b/modules/nf-core/multiqc/tests/tags.yml @@ -0,0 +1,2 @@ +multiqc: + - modules/nf-core/multiqc/** diff --git a/nextflow.config b/nextflow.config index 1b32246c..518a4e92 100644 --- a/nextflow.config +++ b/nextflow.config @@ -13,7 +13,7 @@ params { input = null // References genome = null - igenomes_base = 's3://ngi-igenomes/igenomes' + igenomes_base = 's3://ngi-igenomes/igenomes/' igenomes_ignore = false // MultiQC options @@ -208,6 +208,7 @@ profiles { dumpHashes = true process.beforeScript = 'echo $HOSTNAME' cleanup = false + nextflow.enable.configProcessNamesValidation = true } conda { conda.enabled = true @@ -230,16 +231,16 @@ profiles { } docker { docker.enabled = true - docker.userEmulation = true conda.enabled = false singularity.enabled = false podman.enabled = false shifter.enabled = false charliecloud.enabled = false apptainer.enabled = false + docker.runOptions = '-u $(id -u):$(id -g)' } arm { - docker.runOptions = '-u $(id -u):$(id -g) --platform=linux/amd64' + docker.runOptions = '-u $(id -u):$(id -g) --platform=linux/amd64' } singularity { singularity.enabled = true @@ -319,7 +320,7 @@ singularity.registry = 'quay.io' // Nextflow plugins plugins { - id 'nf-validation' // Validation of pipeline parameters and creation of an input channel from a sample sheet + id 'nf-validation@1.1.3' // Validation of pipeline parameters and creation of an input channel from a sample sheet } // Load igenomes.config if required @@ -343,6 +344,9 @@ env { // Capture exit codes from upstream processes when piping process.shell = ['/bin/bash', '-euo', 'pipefail'] +// Disable process selector warnings by default. Use debug profile to enable warnings. +nextflow.enable.configProcessNamesValidation = false + def trace_timestamp = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss') timeline { enabled = true @@ -368,7 +372,7 @@ manifest { description = """Taxonomic classification and profiling of shotgun short- and long-read metagenomic data""" mainScript = 'main.nf' nextflowVersion = '!>=23.04.0' - version = '1.1.2' + version = '1.1.3' doi = '10.1101/2023.10.20.563221' } diff --git a/nextflow_schema.json b/nextflow_schema.json index 5897da32..23cad833 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -331,7 +331,7 @@ "type": "boolean", "fa_icon": "fas fa-save", "description": "Save reads from samples that went through the run-merging step", - "help_text": "Save the run- and library-concatenated reads of a given sample in FASTQ format.\n\n> \u26a0\ufe0f Only samples that went through the run-merging step of the pipeline will be stored in the resulting directory. \n\nIf you wish to save the files that go to the classification/profiling steps for samples that _did not_ go through run merging, you must supply the appropriate upstream `--save_` flag.\n\n" + "help_text": "Save the run- and library-concatenated reads of a given sample in FASTQ format.\n\n> ⚠️ Only samples that went through the run-merging step of the pipeline will be stored in the resulting directory. \n\nIf you wish to save the files that go to the classification/profiling steps for samples that _did not_ go through run merging, you must supply the appropriate upstream `--save_` flag.\n\n" } }, "fa_icon": "fas fa-clipboard-check" @@ -417,32 +417,32 @@ "run_krakenuniq": { "type": "boolean", "fa_icon": "fas fa-toggle-on", - "description": "Turn on profiling with KrakenUniq. Requires database to be present CSV file passed to --databases" + "description": "Turn on profiling with KrakenUniq. Requires one or more KrakenUniq databases to be present in the CSV file passed to --databases." }, "krakenuniq_save_reads": { "type": "boolean", "fa_icon": "fas fa-save", - "description": "Turn on saving of KrakenUniq-aligned reads", - "help_text": "Save reads that do and do not have a taxonomic classification in your output results directory in FASTQ format.\n\n> Modifies tool parameter(s):\n> - krakenuniq: `--classified-out` and `--unclassified-out`" + "description": "Turn on saving of KrakenUniq (un-)classified reads as FASTA.", + "help_text": "Save reads that do and do not have a taxonomic classification in your output results directory in FASTA format. Reads from paired-end input are merged.\n\n> Modifies tool parameter(s):\n> - krakenuniq: `--classified-out` and `--unclassified-out`" }, "krakenuniq_ram_chunk_size": { "type": "string", "default": "16G", - "description": "Specify how large to chunk database when loading into memory for KrakenUniq", + "description": "Specify how large to chunk the database when loading into memory for KrakenUniq.", "fa_icon": "fas fa-database", "help_text": "nf-core/taxprofiler utilises a 'low memory' option for KrakenUniq that can reduce the amount of RAM the process requires using the `--preloaded` option.\n\nA further extension to this option is that you can specify how large each chunk of the database should be that gets loaded into memory at any one time. You can specify the amount of RAM to chunk the database to with this parameter, and is particularly useful for people with limited computational resources.\n\nMore information about this parameter can be seen [here](https://github.com/fbreitwieser/krakenuniq/blob/master/README.md#new-release-v07).\n\n> Modifies KrakenUniq parameter: --preload-size\n\n" }, "krakenuniq_save_readclassifications": { "type": "boolean", "fa_icon": "fas fa-save", - "description": "Turn on saving of KrakenUniq per-read taxonomic assignment file", - "help_text": "Save a text file that contains a list of each read that had a taxonomic assignment, with information on specific taxonomic taxonomic assignment that that read recieved.\n\n> Modifies tool parameter(s):\n> - krakenuniq: `--output`" + "description": "Turn on saving of KrakenUniq per-read taxonomic assignment file.", + "help_text": "Save a text file that contains a list of each read that had a taxonomic assignment, with information on specific taxonomic taxonomic assignment that that read received.\n\n> Modifies tool parameter(s):\n> - krakenuniq: `--output`" }, "krakenuniq_batch_size": { "type": "integer", "default": 20, "fa_icon": "far fa-window-restore", - "description": "Specify the number of samples for each KrakenUniq run", + "description": "Specify the number of samples for each KrakenUniq run.", "help_text": "Specify the batch size for KrakenUniq. The reference database for KrakenUniq is loaded into memory once per nextflow process and then used to classify many samples. When you have many samples, a single KrakenUniq run can be rather slow. Alternatively, we can split up KrakenUniq runs for a 'batch' of samples, allowing a balance between shared use of database for multiple samples, but also faster parallelised KrakenUniq runs. This parameter determines for how many samples at a time." }, "run_bracken": {
    Process Name \\", + " \\ Software Version
    CUSTOM_DUMPSOFTWAREVERSIONSpython3.11.7
    yaml5.4.1
    TOOL1tool10.11.9
    TOOL2tool21.9
    WorkflowNextflow
    File typeConventional base calls
    File typeConventional base calls
    File typeConventional base calls
    File typeConventional base calls
    File typeConventional base calls
    File typeConventional base calls
    File typeConventional base calls
    File typeConventional base calls
    File typeConventional base calls
    File typeConventional base calls
    File typeConventional base calls