diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c46cae01..6c95a2b3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,7 +36,7 @@ jobs: - "test_motus" - "test_falco" - "test_fastp" - - "test_adapterremoval" + - "test_alternativepreprocessing" - "test_bbduk" - "test_prinseqplusplus" @@ -65,8 +65,10 @@ jobs: if [[ "${{ matrix.tags }}" == "test_motus" ]]; then wget https://raw.githubusercontent.com/motu-tool/mOTUs/master/motus/downloadDB.py python downloadDB.py --no-download-progress - echo 'tool,db_name,db_params,db_path' > 'database_motus.csv' - echo "motus,db_mOTU,,db_mOTU" >> 'database_motus.csv' + echo 'tool,db_name,db_params,db_type,db_path' > 'database_motus.csv' + echo "motus,db1_mOTU,,short,db_mOTU" >> 'database_motus.csv' + echo "motus,db2_mOTU,,long,db_mOTU" >> 'database_motus.csv' + echo "motus,db3_mOTU,,short;long,db_mOTU" >> 'database_motus.csv' nextflow run ${GITHUB_WORKSPACE} -profile docker,${{ matrix.tags }} --databases ./database_motus.csv --outdir ./results_${{ matrix.tags }}; else nextflow run ${GITHUB_WORKSPACE} -profile docker,${{ matrix.tags }} --outdir ./results_${{ matrix.tags }}; diff --git a/CHANGELOG.md b/CHANGELOG.md index d512ab9f..9d13eaed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,47 @@ 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.2 - Bouncy Basenji [2024-10-03] + +### `Added` + +- [#417](https://github.com/nf-core/taxprofiler/pull/417) Added reference-free metagenome complexity/coverage estimation with Nonpareil (added by @jfy133) +- [#466](https://github.com/nf-core/taxprofiler/pull/466) Input database sheets can specify a `db_type` column to distinguish between short- and long-read databases (added by @LilyAnderssonLee) +- [#505](https://github.com/nf-core/taxprofiler/pull/505) Add small files to the file `tower.yml` (added by @LilyAnderssonLee) +- [#508](https://github.com/nf-core/taxprofiler/pull/508) Add `nanoq` as a filtering tool for nanopore reads (added by @LilyAnderssonLee) +- [#511](https://github.com/nf-core/taxprofiler/pull/511) Add `porechop_abi` as an alternative adapter removal tool for long reads nanopore data (added by @LilyAnderssonLee) +- [#512](https://github.com/nf-core/taxprofiler/pull/512) Update all tools to the latest version and include nf-test (updated by @LilyAnderssonLee & @jfy133) +- [#537](https://github.com/nf-core/taxprofiler/pull/537) Update the module `motus/merge` to the latest version (Updated by @sofstam & @LilyAnderssonLee) + +### `Fixed` + +- [#518](https://github.com/nf-core/taxprofiler/pull/518) Fixed a bug where Oxford Nanopore FASTA input files would not be processed (❤️ to @ikarls for reporting, fixed by @jfy133) +- [#523](https://github.com/nf-core/taxprofiler/pull/523) Removed hardcoded `-m lca` from GANON_CLASSIFY due to more options in new version of ganon (fixed by @LilyAnderssonLee & @jfy133) +- [#531](https://github.com/nf-core/taxprofiler/pull/531) Fix FASTA input validation in schema allowing FASTQ extension, expand allowed FASTA extensions (fixed by @jfy133) +- [#512](https://github.com/nf-core/taxprofiler/pull/532) Minor formatting and ordering improvements in MultiQC report (by @jfy133) +- [#532](https://github.com/nf-core/taxprofiler/pull/532) - Added missing documentation behind the 'ignore' BRACKEN_BRACKEN error strategy (❤️ to @Mavti for reporting, fixed by @jfy133) +- [#536](https://github.com/nf-core/taxprofiler/pull/536) - Redefine `contents_re` for filtlong to fix its missing from the MultiQC report (fixed by @LilyAnderssonLee) + +### `Dependencies` + +| Tool | Previous version | New version | +| --------- | ---------------- | ----------- | +| bbmap | 39.01 | 39.06 | +| bowtie2 | 2.4.4 | 2.5.2 | +| bracken | 2.7 | 2.9 | +| diamond | 2.0.15 | 2.1.8 | +| ganon | 1.5.1 | 2.0.0 | +| kraken2 | 2.1.2 | 2.1.3 | +| krona | 2.8 | 2.8.1 | +| megan | 6.24.20 | 6.25.9 | +| metaphlan | 4.0.6 | 4.1.1 | +| minimap2 | 2.24 | 2.28 | +| motus | 3.0.3 | 3.1.0 | +| multiqc | 1.21 | 1.25 | +| samtools | 1.17 | 1.20 | + +### `Deprecated` + ## v1.1.8 - Augmented Akita Patch [2024-06-20] ### `Added` diff --git a/CITATIONS.md b/CITATIONS.md index b82fe7d7..9079373f 100644 --- a/CITATIONS.md +++ b/CITATIONS.md @@ -30,14 +30,26 @@ > Schubert, M., Lindgreen, S., & Orlando, L. (2016). AdapterRemoval v2: rapid adapter trimming, identification, and read merging. BMC Research Notes, 9, 88. https://doi.org/10.1186/s13104-016-1900-2 +- [Nonpareil](https://doi.org/10.1128/mSystems.00039-18) + + - Rodriguez-R, L. M., Gunturu, S., Tiedje, J. M., Cole, J. R., & Konstantinidis, K. T. (2018). Nonpareil 3: Fast Estimation of Metagenomic Coverage and Sequence Diversity. mSystems, 3(3). https://doi.org/10.1128/mSystems.00039-18 + - [Porechop](https://github.com/rrwick/Porechop) > Wick, R. R., Judd, L. M., Gorrie, C. L., & Holt, K. E. (2017). Completing bacterial genome assemblies with multiplex MinION sequencing. Microbial Genomics, 3(10), e000132. https://doi.org/10.1099/mgen.0.000132 +- [Porechop_ABI](https://github.com/bonsai-team/Porechop_ABI) + + > Bonenfant, Q., Noé, L., & Touzet, H. (2023). Porechop_ABI: discovering unknown adapters in Oxford Nanopore Technology sequencing reads for downstream trimming. Bioinformatics Advances, 3(1):vbac085. https://10.1093/bioadv/vbac085 + - [Filtlong](https://github.com/rrwick/Filtlong) > Wick R (2021) Filtlong, URL: https://github.com/rrwick/Filtlong +- [nanoq](https://github.com/esteinig/nanoq) + + > Steinig, E., & Coin, L. (2022). Nanoq: ultra-fast quality control for nanopore reads. Journal of Open Source Software, 7(69). https://doi.org/10.21105/joss.02991 + - [BBTools](http://sourceforge.net/projects/bbmap/) > Bushnell B. (2022) BBMap, URL: http://sourceforge.net/projects/bbmap/ diff --git a/README.md b/README.md index 980a2212..5999cf12 100644 --- a/README.md +++ b/README.md @@ -29,11 +29,11 @@ 1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/) or [`falco`](https://github.com/smithlabcode/falco) as an alternative option) 2. Performs optional read pre-processing - - Adapter clipping and merging (short-read: [fastp](https://github.com/OpenGene/fastp), [AdapterRemoval2](https://github.com/MikkelSchubert/adapterremoval); long-read: [porechop](https://github.com/rrwick/Porechop)) - - Low complexity and quality filtering (short-read: [bbduk](https://jgi.doe.gov/data-and-tools/software-tools/bbtools/), [PRINSEQ++](https://github.com/Adrian-Cantu/PRINSEQ-plus-plus); long-read: [Filtlong](https://github.com/rrwick/Filtlong)) + - Adapter clipping and merging (short-read: [fastp](https://github.com/OpenGene/fastp), [AdapterRemoval2](https://github.com/MikkelSchubert/adapterremoval); long-read: [porechop](https://github.com/rrwick/Porechop), [Porechop_ABI](https://github.com/bonsai-team/Porechop_ABI)) + - Low complexity and quality filtering (short-read: [bbduk](https://jgi.doe.gov/data-and-tools/software-tools/bbtools/), [PRINSEQ++](https://github.com/Adrian-Cantu/PRINSEQ-plus-plus); long-read: [Filtlong](https://github.com/rrwick/Filtlong)), [Nanoq](https://github.com/esteinig/nanoq) - Host-read removal (short-read: [BowTie2](http://bowtie-bio.sourceforge.net/bowtie2/); long-read: [Minimap2](https://github.com/lh3/minimap2)) - Run merging -3. Supports statistics for host-read removal ([Samtools](http://www.htslib.org/)) +3. Supports statistics metagenome coverage estimation ([Nonpareil](https://nonpareil.readthedocs.io/en/latest/)) and for host-read removal ([Samtools](http://www.htslib.org/)) 4. Performs taxonomic classification and/or profiling using one or more of: - [Kraken2](https://ccb.jhu.edu/software/kraken2/) - [MetaPhlAn](https://huttenhower.sph.harvard.edu/metaphlan/) @@ -73,7 +73,7 @@ Additionally, you will need a database sheet that looks as follows: `databases.csv`: -``` +```csv tool,db_name,db_params,db_path kraken2,db2,--quick,///kraken2/testdb-kraken2.tar.gz metaphlan,db1,,///metaphlan/metaphlan_database/ diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index e2801c44..73863ae8 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -1,8 +1,8 @@ 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": @@ -11,6 +11,48 @@ report_section_order: order: -1001 "nf-core-taxprofiler-summary": order: -1002 + general_stats": + order: 1000 + fastqc: + order: 900 + fastqc-1: + order: 800 + fastp: + order: 750 + adapterremoval: + order: 700 + nonpareil: + order: 600 + bbduk: + order: 550 + prinseqplusplus: + order: 500 + porechop: + order: 450 + porechop_abi: + order: 400 + filtlong: + order: 350 + nanoq: + order: 300 + bowtie2: + order: 200 + samtools: + order: 100 + kraken: + order: 90 + bracken: + order: 80 + centrifuge: + order: 70 + malt: + order: 60 + diamond: + order: 50 + kaiju: + order: 40 + motus: + order: 30 export_plots: true @@ -21,14 +63,15 @@ custom_logo_title: "nf-core/taxprofiler" run_modules: - fastqc - - adapterRemoval + - adapterremoval - fastp + - nonpareil - bbduk - prinseqplusplus - porechop - filtlong + - nanoq - bowtie2 - - minimap2 - samtools - kraken - kaiju @@ -39,11 +82,16 @@ run_modules: sp: diamond: - fn_re: ".*.diamond.log$" + fn: "*.diamond.log" fastqc/data: fn_re: ".*(fastqc|falco)_data.txt$" fastqc/zip: fn: "*_fastqc.zip" + nonpareil: + fn: "nonpareil_all_samples.json" + filtlong: + contents: Scoring long reads + contents_re: " " top_modules: - "fastqc": @@ -60,13 +108,23 @@ top_modules: path_filters_exclude: - "*raw*" extra: "If used in this run, Falco is a drop-in replacement for FastQC producing the same output, written by Guilherme de Sena Brandine and Andrew D. Smith." - - "fastp" - - "adapterRemoval" + - nonpareil - "porechop": + name: "Porechop" + anchor: "porechop" + target: "Porechop" + path_filters: + - "*porechop.log" extra: "ℹ️: if you get the error message 'Error - was not able to plot data.' this means that porechop did not detect any adapters and therefore no statistics generated." - - "bbduk" - - "prinseqplusplus" - - "filtlong" + - "porechop": + name: "Porechop_ABI" + anchor: "porechop_abi" + target: "Porechop_ABI" + doi: "10.1093/bioadv/vbac085" + info: "find and remove adapters from Oxford Nanopore reads." + path_filters: + - "*porechop_abi.log" + extra: "ℹ️: if you get the error message 'Error - was not able to plot data.' this means that porechop_abi did not detect any adapters and therefore no statistics generated." - "bowtie2": name: "bowtie2" - "samtools": @@ -95,12 +153,11 @@ top_modules: - "*.centrifuge.txt" - "malt": name: "MALT" - - "diamond" - "kaiju": name: "Kaiju" - - "motus" -#It is not possible to set placement for custom kraken and centrifuge columns. +# It is not possible to set placement for custom kraken +# and centrifuge columns. table_columns_placement: FastQC / Falco (pre-Trimming): @@ -130,16 +187,33 @@ table_columns_placement: percent_aligned: 370 percent_collapsed: 380 percent_discarded: 390 + nonpareil: + nonpareil_R: 400 + nonpareil_LR: 410 + nonpareil_kappa: 420 + nonpareil_C: 430 + nonpareil_diversity: 440 Porechop: - Input Reads: 400 - Start Trimmed: 410 - Start Trimmed Percent: 420 - End Trimmed: 430 - End Trimmed Percent: 440 - Middle Split: 450 - Middle Split Percent: 460 + Input Reads: 500 + Start Trimmed: 510 + Start Trimmed Percent: 520 + End Trimmed: 530 + End Trimmed Percent: 540 + Middle Split: 550 + Middle Split Percent: 560 + Porechop_ABI: + Input Reads: 500 + Start Trimmed: 510 + Start Trimmed Percent: 520 + End Trimmed: 530 + End Trimmed Percent: 540 + Middle Split: 550 + Middle Split Percent: 560 Filtlong: - Target bases: 500 + Target bases: 600 + nanoq: + Reads: 700 + Read N50: 710 BBDuk: Input reads: 800 Total Removed bases percent: 810 @@ -203,6 +277,24 @@ table_columns_visible: percent_duplicates: False percent_gc: False percent_fails: False + Adapter Removal: + aligned_total: True + percent_aligned: True + percent_collapsed: True + percent_discarded: False + fastp: + pct_adapter: True + pct_surviving: True + pct_duplication: False + after_filtering_gc_content: False + after_filtering_q30_rate: False + after_filtering_q30_bases: False + nonpareil: + nonpareil_R: false + nonpareil_LR: false + nonpareil_kappa: true + nonpareil_C: true + nonpareil_diversity: true porechop: Input reads: False Start Trimmed: @@ -211,20 +303,19 @@ table_columns_visible: End Trimmed Percent: True Middle Split: False Middle Split Percent: True - fastp: - pct_adapter: True - pct_surviving: True - pct_duplication: False - after_filtering_gc_content: False - after_filtering_q30_rate: False - after_filtering_q30_bases: False + porechop_abi: + Input reads: False + Start Trimmed: + Start Trimmed Percent: True + End Trimmed: False + End Trimmed Percent: True + Middle Split: False + Middle Split Percent: True Filtlong: Target bases: True - Adapter Removal: - aligned_total: True - percent_aligned: True - percent_collapsed: True - percent_discarded: False + nanoq: + ReadN50: True + Reads: True BBDuk: Input reads: False Total Removed bases Percent: False @@ -276,6 +367,10 @@ extra_fn_clean_exts: - ".bbduk" - ".unmapped" - "_filtered" + - "porechop" + - "porechop_abi" + - "_processed" + - ".diamond" - type: remove pattern: "_falco" diff --git a/assets/schema_database.json b/assets/schema_database.json index e467b41d..ec04e326 100644 --- a/assets/schema_database.json +++ b/assets/schema_database.json @@ -39,6 +39,12 @@ "errorMessage": "Invalid database db_params entry. No quotes allowed.", "meta": ["db_params"] }, + "db_type": { + "type": "string", + "enum": ["short", "long", "short;long"], + "default": "short;long", + "meta": ["db_type"] + }, "db_path": { "type": "string", "exists": true, diff --git a/assets/schema_input.json b/assets/schema_input.json index cc335436..0536930b 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -38,19 +38,22 @@ "type": "string", "format": "file-path", "pattern": "^\\S+\\.f(ast)?q\\.gz$", - "errorMessage": "FastQ file for reads 1 must be provided, cannot contain spaces and must have extension '.fq.gz' or '.fastq.gz'" + "unique": true, + "errorMessage": "Gzipped FastQ file for reads 1 must be provided, cannot contain spaces and must have extension '.fq.gz' or '.fastq.gz'" }, "fastq_2": { "type": "string", "format": "file-path", "pattern": "^\\S+\\.f(ast)?q\\.gz$", - "errorMessage": "FastQ file for reads 2 cannot contain spaces and must have extension '.fq.gz' or '.fastq.gz'. If not applicable, leave it empty." + "unique": true, + "errorMessage": "Gzipped FastQ file for reads 2 cannot contain spaces and must have extension '.fq.gz' or '.fastq.gz'. If not applicable, leave it empty." }, "fasta": { "type": "string", "format": "file-path", - "pattern": "^\\S+\\.(f(ast)?q|fa(sta)?)\\.gz$", - "errorMessage": "FastA file must be provided, cannot contain spaces and must have extension '.fa.gz' or '.fasta.gz'. If not applicable, leave it empty." + "pattern": "^\\S+\\.(fasta|fas|fna|fa)\\.gz?$", + "unique": true, + "errorMessage": "Gzipped FastA file must be provided, cannot contain spaces and must have extension '.fa.gz', 'fna.gz', 'fas.gz', or '.fasta.gz'. If not applicable, leave it empty." } }, "required": ["sample", "run_accession", "instrument_platform"] diff --git a/conf/modules.config b/conf/modules.config index ee0bd5b5..1b82c9ee 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -198,6 +198,43 @@ process { ] } + // Redundancy estimation with nonpareil + withName: NONPAREIL_NONPAREIL { + ext.prefix = { "${meta.id}_${meta.run_accession}" } + publishDir = [ + path: { "${params.outdir}/nonpareil/" }, + mode: params.publish_dir_mode, + pattern: '*.np{a,c,l,o}' + ] + } + + withName: 'NONPAREIL_CURVE' { + ext.prefix = { "${meta.id}_${meta.run_accession}" } + publishDir = [ + path: { "${params.outdir}/nonpareil/" }, + mode: params.publish_dir_mode, + pattern: '*.png' + ] + } + + withName: 'NONPAREIL_SET' { + ext.prefix = { "nonpareil_all_samples_mqc" } + publishDir = [ + path: { "${params.outdir}/nonpareil/" }, + mode: params.publish_dir_mode, + pattern: '*.png' + ] + } + + withName: 'NONPAREIL_NONPAREILCURVESR' { + ext.prefix = { "nonpareil_all_samples" } + publishDir = [ + path: { "${params.outdir}/nonpareil/" }, + mode: params.publish_dir_mode, + pattern: '*.{json,csv,tsv,pdf}' + ] + } + // AdapterRemoval separate output merging withName: CAT_FASTQ { ext.prefix = { "${meta.id}_${meta.run_accession}" } @@ -213,12 +250,12 @@ process { } withName: PORECHOP_PORECHOP { - ext.prefix = { "${meta.id}_${meta.run_accession}" } + ext.prefix = { "${meta.id}_${meta.run_accession}_porechop" } publishDir = [ [ path: { "${params.outdir}/porechop" }, mode: params.publish_dir_mode, - pattern: '*_porechopped.fastq.gz', + pattern: '*_porechop.fastq.gz', enabled: params.save_preprocessed_reads ], [ @@ -229,7 +266,31 @@ process { [ path: { "${params.outdir}/analysis_ready_fastqs" }, mode: params.publish_dir_mode, - pattern: '*_porechopped.fastq.gz', + pattern: '*_porechop.fastq.gz', + enabled: params.save_analysis_ready_fastqs, + saveAs: { ( params.perform_runmerging == false || ( params.perform_runmerging && !meta.is_multirun ) ) && !params.perform_longread_hostremoval && params.longread_qc_skipqualityfilter && !params.longread_qc_skipadaptertrim && params.perform_longread_qc && params.save_analysis_ready_fastqs ? it : null } + ] + ] + } + + withName: PORECHOP_ABI { + ext.prefix = { "${meta.id}_${meta.run_accession}_porechop_abi" } + publishDir = [ + [ + path: { "${params.outdir}/porechop_abi" }, + mode: params.publish_dir_mode, + pattern: '*_porechop_abi.fastq.gz', + enabled: params.save_preprocessed_reads + ], + [ + path: { "${params.outdir}/porechop_abi" }, + mode: params.publish_dir_mode, + pattern: '*.log' + ], + [ + path: { "${params.outdir}/analysis_ready_fastqs" }, + mode: params.publish_dir_mode, + pattern: '*porechop_abi.fastq.gz', enabled: params.save_analysis_ready_fastqs, saveAs: { ( params.perform_runmerging == false || ( params.perform_runmerging && !meta.is_multirun ) ) && !params.perform_longread_hostremoval && params.longread_qc_skipqualityfilter && !params.longread_qc_skipadaptertrim && params.perform_longread_qc && params.save_analysis_ready_fastqs ? it : null } ] @@ -266,6 +327,36 @@ process { ] } + withName: NANOQ { + ext.args = [ + "-vv", + "--min-len ${params.longread_qc_qualityfilter_minlength}", + "--min-qual ${params.longread_qc_qualityfilter_minquality}" + ] + .join(' ').trim() + ext.prefix = { "${meta.id}_${meta.run_accession}_filtered" } + publishDir = [ + [ + path: { "${params.outdir}/nanoq" }, + mode: params.publish_dir_mode, + pattern: '*_filtered.fastq.gz', + enabled: params.save_preprocessed_reads + ], + [ + path: { "${params.outdir}/nanoq" }, + mode: params.publish_dir_mode, + pattern: '*_filtered.stats' + ], + [ + path: { "${params.outdir}/analysis_ready_fastqs" }, + mode: params.publish_dir_mode, + pattern: '*_filtered.fastq.gz', + enabled: params.save_analysis_ready_fastqs, + saveAs: { ( params.perform_runmerging == false || ( params.perform_runmerging && !meta.is_multirun ) ) && !params.perform_longread_hostremoval && !params.longread_qc_skipqualityfilter && params.perform_longread_qc && params.save_analysis_ready_fastqs ? it : null } + ] + ] + } + withName: BBMAP_BBDUK { ext.args = [ "entropy=${params.shortread_complexityfilter_entropy}", @@ -717,12 +808,12 @@ process { withName: GANON_CLASSIFY { tag = {"${meta.db_name}|${meta.id}"} - ext.args = params.ganon_save_readclassifications ? { "${meta.db_params} --output-all --output-lca --output-unclassified" } : { "${meta.db_params}" } + ext.args = params.ganon_save_readclassifications ? { "${meta.db_params} --output-all --output-unclassified" } : { "${meta.db_params}" } ext.prefix = params.perform_runmerging ? { "${meta.id}_${meta.db_name}.ganon" } : { "${meta.id}_${meta.run_accession}_${meta.db_name}.ganon" } publishDir = [ path: { "${params.outdir}/ganon/${meta.db_name}/" }, mode: params.publish_dir_mode, - pattern: '*.{tre,rep,lca,all,unc}' + pattern: '*.{tre,rep,one,all,unc,log}' ] } diff --git a/conf/test.config b/conf/test.config index 042dc2fa..4e457585 100644 --- a/conf/test.config +++ b/conf/test.config @@ -11,42 +11,43 @@ */ params { - config_profile_name = 'Test profile' - config_profile_description = 'Minimal test dataset to check pipeline function' + config_profile_name = 'Test profile' + config_profile_description = 'Minimal test dataset to check pipeline function' // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = '6.GB' - max_time = '6.h' + max_cpus = 2 + max_memory = '6.GB' + max_time = '6.h' // Input data - input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet.csv' - databases = params.pipelines_testdata_base_path + 'taxprofiler/database_v1.1.csv' - perform_shortread_qc = true - perform_longread_qc = true - shortread_qc_mergepairs = true - perform_shortread_complexityfilter = true - perform_shortread_hostremoval = true - perform_longread_hostremoval = true - perform_runmerging = true - hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' - run_kaiju = true - run_kraken2 = true - run_bracken = true - run_malt = false - run_metaphlan = true - run_centrifuge = true - run_diamond = true - run_krakenuniq = true - run_motus = false - run_ganon = true - run_krona = true - run_kmcp = true - krona_taxonomy_directory = params.pipelines_testdata_base_path + 'modules/data/genomics/sarscov2/metagenome/krona_taxonomy.tab' - malt_save_reads = true - kraken2_save_reads = true - centrifuge_save_reads = true - run_profile_standardisation = true + input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet.csv' + databases = params.pipelines_testdata_base_path + 'taxprofiler/database_v1.2.csv' + perform_shortread_qc = true + perform_shortread_redundancyestimation = true + perform_longread_qc = true + shortread_qc_mergepairs = true + perform_shortread_complexityfilter = true + perform_shortread_hostremoval = true + perform_longread_hostremoval = true + perform_runmerging = true + hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' + run_kaiju = true + run_kraken2 = true + run_bracken = true + run_malt = false + run_metaphlan = true + run_centrifuge = true + run_diamond = true + run_krakenuniq = true + run_motus = false + run_ganon = true + run_krona = true + run_kmcp = true + krona_taxonomy_directory = params.pipelines_testdata_base_path + 'modules/data/genomics/sarscov2/metagenome/krona_taxonomy.tab' + malt_save_reads = true + kraken2_save_reads = true + centrifuge_save_reads = true + run_profile_standardisation = true } process { @@ -60,4 +61,7 @@ process { withName: MEGAN_RMA2INFO_KRONA { maxForks = 1 } + withName: NONPAREIL_NONPAREIL { + ext.args = { "-k 5" } + } } diff --git a/conf/test_adapterremoval.config b/conf/test_adapterremoval.config deleted file mode 100644 index ee55ba55..00000000 --- a/conf/test_adapterremoval.config +++ /dev/null @@ -1,51 +0,0 @@ -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Nextflow config file for running minimal tests -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Defines input files and everything required to run a fast and simple pipeline test. - - Use as follows: - nextflow run nf-core/taxprofiler -profile test, --outdir - ----------------------------------------------------------------------------------------- -*/ - -params { - config_profile_name = 'Test profile for adapterremoval' - config_profile_description = "Minimal test to check the alternative short-read QC function, adapterremoval" - - // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = '6.GB' - max_time = '6.h' - - // Input data - input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet.csv' - databases = params.pipelines_testdata_base_path + 'taxprofiler/database_v1.1.csv' - perform_shortread_qc = true - perform_longread_qc = true - shortread_qc_tool = 'adapterremoval' - perform_shortread_complexityfilter = true - perform_shortread_hostremoval = true - perform_longread_hostremoval = true - perform_runmerging = true - hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' - run_kaiju = true - run_kraken2 = true - run_bracken = false - run_malt = false - run_metaphlan = false - run_centrifuge = false - run_diamond = false - run_krakenuniq = false - run_motus = false - run_ganon = false - run_kmcp = false -} - -process { - withName: MALT_RUN { - maxForks = 1 - ext.args = { "-m ${params.malt_mode} -J-Xmx12G" } - } -} diff --git a/conf/test_alternativepreprocessing.config b/conf/test_alternativepreprocessing.config new file mode 100644 index 00000000..6c6cb1aa --- /dev/null +++ b/conf/test_alternativepreprocessing.config @@ -0,0 +1,56 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Nextflow config file for running minimal tests +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Defines input files and everything required to run a fast and simple pipeline test. + + Use as follows: + nextflow run nf-core/taxprofiler -profile test_alternativepreprocessing, --outdir + +---------------------------------------------------------------------------------------- +*/ + +params { + config_profile_name = 'Test profile for adapterremoval' + config_profile_description = "Minimal test to check the alternative short-read QC function, adapterremoval" + + // Limit resources so that this can run on GitHub Actions + max_cpus = 2 + max_memory = '6.GB' + max_time = '6.h' + + // Input data + input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet.csv' + databases = params.pipelines_testdata_base_path + 'taxprofiler/database_v1.2.csv' + perform_shortread_qc = true + perform_longread_qc = true + shortread_qc_tool = 'adapterremoval' + longread_adapterremoval_tool = 'porechop' + longread_filter_tool = 'filtlong' + perform_shortread_complexityfilter = true + perform_shortread_hostremoval = true + perform_longread_hostremoval = true + perform_runmerging = true + hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' + run_kaiju = true + run_kraken2 = true + run_bracken = false + run_malt = false + run_metaphlan = false + run_centrifuge = false + run_diamond = false + run_krakenuniq = false + run_motus = false + run_ganon = false + run_kmcp = false +} + +process { + withName: MALT_RUN { + maxForks = 1 + ext.args = { "-m ${params.malt_mode} -J-Xmx12G" } + } + withName: NONPAREIL_NONPAREIL { + ext.args = { "-k 5" } + } +} diff --git a/conf/test_bbduk.config b/conf/test_bbduk.config index d0ff530a..184dabea 100644 --- a/conf/test_bbduk.config +++ b/conf/test_bbduk.config @@ -5,42 +5,42 @@ Defines input files and everything required to run a fast and simple pipeline test. Use as follows: - nextflow run nf-core/taxprofiler -profile test, --outdir + nextflow run nf-core/taxprofiler -profile test_bbduk, --outdir ---------------------------------------------------------------------------------------- */ params { - config_profile_name = 'Test profile for bbduk' - config_profile_description = "Minimal test to check the default tool of short-read complexity filtering, bbduk" + config_profile_name = 'Test profile for bbduk' + config_profile_description = "Minimal test to check the default tool of short-read complexity filtering, bbduk" // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = '6.GB' - max_time = '6.h' + max_cpus = 2 + max_memory = '6.GB' + max_time = '6.h' // Input data - input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet.csv' - databases = params.pipelines_testdata_base_path + 'taxprofiler/database_v1.1.csv' - perform_shortread_qc = true - perform_longread_qc = true - perform_shortread_complexityfilter = true - shortread_complexityfilter_tool = 'bbduk' - perform_shortread_hostremoval = true - perform_longread_hostremoval = true - perform_runmerging = true - hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' - run_kaiju = true - run_kraken2 = true - run_bracken = false - run_malt = false - run_metaphlan = false - run_centrifuge = false - run_diamond = false - run_krakenuniq = false - run_motus = false - run_ganon = false - run_kmcp = false + input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet.csv' + databases = params.pipelines_testdata_base_path + 'taxprofiler/database_v1.2.csv' + perform_shortread_qc = true + perform_longread_qc = true + perform_shortread_complexityfilter = true + shortread_complexityfilter_tool = 'bbduk' + perform_shortread_hostremoval = true + perform_longread_hostremoval = true + perform_runmerging = true + hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' + run_kaiju = true + run_kraken2 = true + run_bracken = false + run_malt = false + run_metaphlan = false + run_centrifuge = false + run_diamond = false + run_krakenuniq = false + run_motus = false + run_ganon = false + run_kmcp = false } process { @@ -48,4 +48,7 @@ process { maxForks = 1 ext.args = { "-m ${params.malt_mode} -J-Xmx12G" } } + withName: NONPAREIL_NONPAREIL { + ext.args = { "-k 5" } + } } diff --git a/conf/test_falco.config b/conf/test_falco.config index 8bcd9889..313a6507 100644 --- a/conf/test_falco.config +++ b/conf/test_falco.config @@ -5,42 +5,42 @@ Defines input files and everything required to run a fast and simple pipeline test. Use as follows: - nextflow run nf-core/taxprofiler -profile test, --outdir + nextflow run nf-core/taxprofiler -profile test_falco, --outdir ---------------------------------------------------------------------------------------- */ params { - config_profile_name = 'Test profile for Falco' - config_profile_description = "Minimal test dataset without performing any preprocessing nor profiling to check pipeline function but running falco instead of fastqc. Useful when you only wish to test a single profiler without having to 'opt-out' of all the others" + config_profile_name = 'Test profile for Falco' + config_profile_description = "Minimal test dataset without performing any preprocessing nor profiling to check pipeline function but running falco instead of fastqc. Useful when you only wish to test a single profiler without having to 'opt-out' of all the others" // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = '6.GB' - max_time = '6.h' + max_cpus = 2 + max_memory = '6.GB' + max_time = '6.h' // Input data - input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet.csv' - databases = params.pipelines_testdata_base_path + 'taxprofiler/database_v1.1.csv' - preprocessing_qc_tool = 'falco' - perform_shortread_qc = true - perform_longread_qc = true - perform_shortread_complexityfilter = false - perform_shortread_hostremoval = false - perform_longread_hostremoval = false - perform_runmerging = false - hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' - run_kaiju = false - run_kraken2 = false - run_bracken = false - run_malt = false - run_metaphlan = false - run_centrifuge = false - run_diamond = false - run_krakenuniq = false - run_motus = false - run_ganon = false - run_kmcp = false + input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet.csv' + databases = params.pipelines_testdata_base_path + 'taxprofiler/database_v1.2.csv' + preprocessing_qc_tool = 'falco' + perform_shortread_qc = true + perform_longread_qc = true + perform_shortread_complexityfilter = false + perform_shortread_hostremoval = false + perform_longread_hostremoval = false + perform_runmerging = false + hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' + run_kaiju = false + run_kraken2 = false + run_bracken = false + run_malt = false + run_metaphlan = false + run_centrifuge = false + run_diamond = false + run_krakenuniq = false + run_motus = false + run_ganon = false + run_kmcp = false } process { @@ -48,4 +48,7 @@ process { maxForks = 1 ext.args = { "-m ${params.malt_mode} -J-Xmx12G" } } + withName: NONPAREIL_NONPAREIL { + ext.args = { "-k 5" } + } } diff --git a/conf/test_fastp.config b/conf/test_fastp.config index 81bec14c..f68189e9 100644 --- a/conf/test_fastp.config +++ b/conf/test_fastp.config @@ -5,43 +5,44 @@ Defines input files and everything required to run a fast and simple pipeline test. Use as follows: - nextflow run nf-core/taxprofiler -profile test, --outdir + nextflow run nf-core/taxprofiler -profile test_fastp, --outdir ---------------------------------------------------------------------------------------- */ params { - config_profile_name = 'Test profile for fastp' - config_profile_description = "Minimal test to check the default short-read QC function, fastp" + config_profile_name = 'Test profile for fastp' + config_profile_description = "Minimal test to check the default short-read QC function, fastp" // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = '6.GB' - max_time = '6.h' + max_cpus = 2 + max_memory = '6.GB' + max_time = '6.h' // Input data - input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet.csv' - databases = params.pipelines_testdata_base_path + 'taxprofiler/database_v1.1.csv' - perform_shortread_qc = true - perform_longread_qc = true - shortread_qc_tool = 'fastp' - perform_shortread_complexityfilter = true - shortread_complexityfilter_tool = 'fastp' - perform_shortread_hostremoval = true - perform_longread_hostremoval = true - perform_runmerging = true - hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' - run_kaiju = true - run_kraken2 = true - run_bracken = false - run_malt = false - run_metaphlan = false - run_centrifuge = false - run_diamond = false - run_krakenuniq = false - run_motus = false - run_ganon = false - run_kmcp = false + input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet.csv' + databases = params.pipelines_testdata_base_path + 'taxprofiler/database_v1.2.csv' + perform_shortread_qc = true + perform_longread_qc = true + shortread_qc_tool = 'fastp' + perform_shortread_redundancyestimation = true + perform_shortread_complexityfilter = true + shortread_complexityfilter_tool = 'fastp' + perform_shortread_hostremoval = true + perform_longread_hostremoval = true + perform_runmerging = true + hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' + run_kaiju = true + run_kraken2 = true + run_bracken = false + run_malt = false + run_metaphlan = false + run_centrifuge = false + run_diamond = false + run_krakenuniq = false + run_motus = false + run_ganon = false + run_kmcp = false } process { @@ -49,4 +50,7 @@ process { maxForks = 1 ext.args = { "-m ${params.malt_mode} -J-Xmx12G" } } + withName: NONPAREIL_NONPAREIL { + ext.args = { "-k 5" } + } } diff --git a/conf/test_full.config b/conf/test_full.config index 067940bb..691928fd 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -9,70 +9,71 @@ */ params { - config_profile_name = 'Full test profile' - config_profile_description = 'Full test dataset to check pipeline function' + config_profile_name = 'Full test profile' + config_profile_description = 'Full test dataset to check pipeline function' // Input data for full size test - input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet_full.csv' - databases = params.pipelines_testdata_base_path + 'taxprofiler/database_full_v1.1.csv' + input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet_full.csv' + databases = params.pipelines_testdata_base_path + 'taxprofiler/database_full_v1.2.csv' // Genome references - hostremoval_reference = 'ftp://ftp.ncbi.nlm.nih.gov/genomes/all/GCA/000/819/615/GCA_000819615.1_ViralProj14015/GCA_000819615.1_ViralProj14015_genomic.fna.gz' + hostremoval_reference = 'ftp://ftp.ncbi.nlm.nih.gov/genomes/all/GCA/000/819/615/GCA_000819615.1_ViralProj14015/GCA_000819615.1_ViralProj14015_genomic.fna.gz' - save_preprocessed_reads = false + save_preprocessed_reads = false - perform_shortread_qc = true - shortread_qc_mergepairs = true - perform_shortread_complexityfilter = false - save_complexityfiltered_reads = false + perform_shortread_qc = true + perform_shortread_redundancyestimation = true + shortread_qc_mergepairs = true + perform_shortread_complexityfilter = false + save_complexityfiltered_reads = false - perform_longread_qc = true - perform_shortread_hostremoval = true - perform_longread_hostremoval = true - save_hostremoval_index = false - save_hostremoval_bam = false - save_hostremoval_unmapped = false + perform_longread_qc = true + perform_shortread_hostremoval = true + perform_longread_hostremoval = true + save_hostremoval_index = false + save_hostremoval_bam = false + save_hostremoval_unmapped = false - perform_runmerging = true - save_runmerged_reads = false + perform_runmerging = true + save_runmerged_reads = false - save_analysis_ready_fastqs = true + save_analysis_ready_fastqs = true - run_centrifuge = true - centrifuge_save_reads = false + run_centrifuge = true + centrifuge_save_reads = false - run_diamond = true + run_diamond = true - run_kaiju = true + run_kaiju = true - run_kraken2 = true - kraken2_save_reads = false - kraken2_save_readclassifications = false - kraken2_save_minimizers = false + run_kraken2 = true + kraken2_save_reads = false + kraken2_save_readclassifications = false + kraken2_save_minimizers = false - run_krakenuniq = true - krakenuniq_save_reads = false - krakenuniq_save_readclassifications = false + run_krakenuniq = true + krakenuniq_save_reads = false + krakenuniq_save_readclassifications = false - run_bracken = true + run_bracken = true - run_malt = true - malt_save_reads = false - malt_generate_megansummary = true + run_malt = true + malt_save_reads = false + malt_generate_megansummary = true - run_metaphlan = true + run_metaphlan = true - run_motus = true - motus_save_mgc_read_counts = true + run_motus = true + motus_save_mgc_read_counts = true - run_ganon = true - ganon_save_readclassifications = true + run_ganon = true + ganon_save_readclassifications = true - run_kmcp = true - kmcp_save_search = true + run_kmcp = true + kmcp_save_search = true - run_profile_standardisation = true - run_krona = true + run_profile_standardisation = true + run_krona = true } cleanup = true diff --git a/conf/test_krakenuniq.config b/conf/test_krakenuniq.config index fc6305de..de3c50da 100644 --- a/conf/test_krakenuniq.config +++ b/conf/test_krakenuniq.config @@ -5,7 +5,7 @@ Defines input files and everything required to run a fast and simple pipeline test. Use as follows: - nextflow run nf-core/taxprofiler -profile test, --outdir + nextflow run nf-core/taxprofiler -profile test_krakenuniq, --outdir ---------------------------------------------------------------------------------------- */ @@ -24,34 +24,35 @@ params { max_time = '6.h' // Input data - input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet.csv' - databases = params.pipelines_testdata_base_path + 'taxprofiler/database_krakenuniq.csv' - perform_shortread_qc = true - perform_longread_qc = true - shortread_qc_mergepairs = true - perform_shortread_complexityfilter = true - perform_shortread_hostremoval = true - perform_longread_hostremoval = true - perform_runmerging = true - hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' - run_kaiju = false - run_kraken2 = false - run_bracken = false - run_malt = false - run_metaphlan = false - run_centrifuge = false - run_diamond = false - run_krakenuniq = true - run_motus = false - run_kmcp = false - run_ganon = false - run_krona = true - krona_taxonomy_directory = params.pipelines_testdata_base_path + 'modules/data/genomics/sarscov2/metagenome/krona_taxonomy.tab' - malt_save_reads = false - kraken2_save_reads = false - centrifuge_save_reads = false - diamond_save_reads = false - run_profile_standardisation = true + input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet.csv' + databases = params.pipelines_testdata_base_path + 'taxprofiler/database_krakenuniq.csv' + perform_shortread_qc = true + perform_longread_qc = true + perform_shortread_redundancyestimation = false + shortread_qc_mergepairs = true + perform_shortread_complexityfilter = true + perform_shortread_hostremoval = true + perform_longread_hostremoval = true + perform_runmerging = true + hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' + run_kaiju = false + run_kraken2 = false + run_bracken = false + run_malt = false + run_metaphlan = false + run_centrifuge = false + run_diamond = false + run_krakenuniq = true + run_motus = false + run_kmcp = false + run_ganon = false + run_krona = true + krona_taxonomy_directory = params.pipelines_testdata_base_path + 'modules/data/genomics/sarscov2/metagenome/krona_taxonomy.tab' + malt_save_reads = false + kraken2_save_reads = false + centrifuge_save_reads = false + diamond_save_reads = false + run_profile_standardisation = true } process { @@ -64,4 +65,7 @@ process { withName: MEGAN_RMA2INFO_KRONA { maxForks = 1 } + withName: NONPAREIL_NONPAREIL { + ext.args = { "-k 5" } + } } diff --git a/conf/test_malt.config b/conf/test_malt.config index 7d9bd2b6..701453c6 100644 --- a/conf/test_malt.config +++ b/conf/test_malt.config @@ -5,7 +5,7 @@ Defines input files and everything required to run a fast and simple pipeline test. Use as follows: - nextflow run nf-core/taxprofiler -profile test, --outdir + nextflow run nf-core/taxprofiler -profile test_malt, --outdir ---------------------------------------------------------------------------------------- */ @@ -15,39 +15,43 @@ // params { - config_profile_name = 'Test profile' - config_profile_description = 'Minimal test to check malt function' + config_profile_name = 'Test profile' + config_profile_description = 'Minimal test to check malt function' // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = '6.GB' - max_time = '6.h' + max_cpus = 2 + max_memory = '6.GB' + max_time = '6.h' // Input data - input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet_malt.csv' - databases = params.pipelines_testdata_base_path + 'taxprofiler/database_v1.1.csv' - perform_shortread_qc = false - perform_longread_qc = false - perform_shortread_complexityfilter = false - perform_shortread_hostremoval = false - perform_longread_hostremoval = false - perform_runmerging = false - hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' - run_kaiju = false - run_kraken2 = false - run_bracken = false - run_malt = true - run_metaphlan = false - run_centrifuge = false - run_diamond = false - run_krakenuniq = false - run_motus = false - run_ganon = false - run_kmcp = false + input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet_malt.csv' + databases = params.pipelines_testdata_base_path + 'taxprofiler/database_v1.2.csv' + perform_shortread_qc = false + perform_longread_qc = false + perform_shortread_redundancyestimation = false + perform_shortread_complexityfilter = false + perform_shortread_hostremoval = false + perform_longread_hostremoval = false + perform_runmerging = true + hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' + run_kaiju = false + run_kraken2 = false + run_bracken = false + run_malt = true + run_metaphlan = false + run_centrifuge = false + run_diamond = false + run_krakenuniq = false + run_motus = false + run_ganon = false + run_kmcp = false } process { withName: MALT_RUN { maxForks = 1 } + withName: NONPAREIL_NONPAREIL { + ext.args = { "-k 5" } + } } diff --git a/conf/test_motus.config b/conf/test_motus.config index c2d4ac22..1152d2ae 100644 --- a/conf/test_motus.config +++ b/conf/test_motus.config @@ -5,7 +5,7 @@ Defines input files and everything required to run a fast and simple pipeline test. Use as follows: - nextflow run nf-core/taxprofiler -profile test, --outdir + nextflow run nf-core/taxprofiler -profile test_motus, --outdir ---------------------------------------------------------------------------------------- */ @@ -24,28 +24,38 @@ params { max_time = '6.h' // Input data - input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet.csv' - databases = 'database_motus.csv' - perform_shortread_qc = false - perform_longread_qc = false - perform_shortread_complexityfilter = false - perform_shortread_hostremoval = false - perform_longread_hostremoval = false - perform_runmerging = false - hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' - run_kaiju = false - run_kraken2 = false - run_bracken = false - run_malt = false - run_metaphlan = false - run_centrifuge = false - run_diamond = false - run_krakenuniq = false - run_motus = true - run_kmcp = false - run_ganon = false - motus_save_mgc_read_counts = false - motus_remove_ncbi_ids = false - motus_use_relative_abundance = false - run_profile_standardisation = true + input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet.csv' + databases = 'database_motus.csv' + perform_shortread_qc = false + perform_longread_qc = false + perform_shortread_redundancyestimation = false + perform_shortread_complexityfilter = false + perform_shortread_hostremoval = false + perform_longread_hostremoval = false + perform_runmerging = false + hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' + run_kaiju = false + run_kraken2 = false + run_bracken = false + run_malt = false + run_metaphlan = false + run_centrifuge = false + run_diamond = false + run_krakenuniq = false + run_motus = true + run_kmcp = false + run_ganon = false + motus_save_mgc_read_counts = false + motus_remove_ncbi_ids = false + motus_use_relative_abundance = false + run_profile_standardisation = true +} + +process { + withName: MALT_RUN { + maxForks = 1 + } + withName: NONPAREIL_NONPAREIL { + ext.args = { "-k 5" } + } } diff --git a/conf/test_nopreprocessing.config b/conf/test_nopreprocessing.config index 42014303..23ab7214 100644 --- a/conf/test_nopreprocessing.config +++ b/conf/test_nopreprocessing.config @@ -5,42 +5,44 @@ Defines input files and everything required to run a fast and simple pipeline test. Use as follows: - nextflow run nf-core/taxprofiler -profile test, --outdir + nextflow run nf-core/taxprofiler -profile test_nopreprocessing, --outdir ---------------------------------------------------------------------------------------- */ params { - config_profile_name = 'Test profile' - config_profile_description = 'Minimal test dataset skipping all preprocessing to check pipeline function' + config_profile_name = 'Test profile' + config_profile_description = 'Minimal test dataset skipping all preprocessing to check pipeline function' // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = '6.GB' - max_time = '6.h' + max_cpus = 2 + max_memory = '6.GB' + max_time = '6.h' // Input data - input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet.csv' - databases = params.pipelines_testdata_base_path + 'taxprofiler/database_v1.1.csv' - perform_shortread_qc = false - perform_longread_qc = false - perform_shortread_complexityfilter = false - perform_shortread_hostremoval = false - perform_longread_hostremoval = false - perform_runmerging = false - hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' - run_kaiju = true - run_kraken2 = true - run_bracken = true - run_malt = false // too big with other profiles on GHA - run_metaphlan = true - run_centrifuge = true - run_diamond = true - run_krakenuniq = true - run_motus = false - run_kmcp = true - run_ganon = true - run_krona = true + input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet.csv' + databases = params.pipelines_testdata_base_path + 'taxprofiler/database_v1.2.csv' + perform_shortread_qc = false + perform_longread_qc = false + perform_shortread_redundancyestimation = false + perform_shortread_complexityfilter = false + perform_shortread_hostremoval = false + perform_longread_hostremoval = false + perform_runmerging = false + hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' + run_kaiju = true + run_kraken2 = true + run_bracken = true + run_malt = false + // too big with other profiles on GHA + run_metaphlan = true + run_centrifuge = true + run_diamond = true + run_krakenuniq = true + run_motus = false + run_kmcp = true + run_ganon = true + run_krona = true } process { @@ -48,4 +50,7 @@ process { maxForks = 1 ext.args = { "-m ${params.malt_mode} -J-Xmx12G" } } + withName: NONPAREIL_NONPAREIL { + ext.args = { "-k 5" } + } } diff --git a/conf/test_noprofiling.config b/conf/test_noprofiling.config index 4e917fb9..70e238ee 100644 --- a/conf/test_noprofiling.config +++ b/conf/test_noprofiling.config @@ -5,46 +5,50 @@ Defines input files and everything required to run a fast and simple pipeline test. Use as follows: - nextflow run nf-core/taxprofiler -profile test, --outdir + nextflow run nf-core/taxprofiler -profile test_noprofiling, --outdir ---------------------------------------------------------------------------------------- */ params { - config_profile_name = 'Test profile' - config_profile_description = 'Minimal test dataset without performing any profiling to check pipeline function' + config_profile_name = 'Test profile' + config_profile_description = 'Minimal test dataset without performing any profiling to check pipeline function' // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = '6.GB' - max_time = '6.h' + max_cpus = 2 + max_memory = '6.GB' + max_time = '6.h' // Input data - input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet.csv' - databases = params.pipelines_testdata_base_path + 'taxprofiler/database_v1.1.csv' - perform_shortread_qc = true - perform_longread_qc = true - shortread_qc_mergepairs = true - perform_shortread_complexityfilter = true - perform_shortread_hostremoval = true - perform_longread_hostremoval = true - perform_runmerging = true - hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' - run_kaiju = false - run_kraken2 = false - run_bracken = false - run_malt = false - run_metaphlan = false - run_centrifuge = false - run_diamond = false - run_krakenuniq = false - run_motus = false - run_kmcp = false - run_ganon = false + input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet.csv' + databases = params.pipelines_testdata_base_path + 'taxprofiler/database_v1.2.csv' + perform_shortread_qc = true + perform_longread_qc = true + perform_shortread_redundancyestimation = true + shortread_qc_mergepairs = true + perform_shortread_complexityfilter = true + perform_shortread_hostremoval = true + perform_longread_hostremoval = true + perform_runmerging = true + hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' + run_kaiju = false + run_kraken2 = false + run_bracken = false + run_malt = false + run_metaphlan = false + run_centrifuge = false + run_diamond = false + run_krakenuniq = false + run_motus = false + run_kmcp = false + run_ganon = false } process { withName: MALT_RUN { maxForks = 1 } + withName: NONPAREIL_NONPAREIL { + ext.args = { "-k 5" } + } } diff --git a/conf/test_nothing.config b/conf/test_nothing.config index d36c76d4..e8b87bc7 100644 --- a/conf/test_nothing.config +++ b/conf/test_nothing.config @@ -5,41 +5,42 @@ Defines input files and everything required to run a fast and simple pipeline test. Use as follows: - nextflow run nf-core/taxprofiler -profile test, --outdir + nextflow run nf-core/taxprofiler -profile test_nothing, --outdir ---------------------------------------------------------------------------------------- */ params { - config_profile_name = 'Test profile' - config_profile_description = "Minimal test dataset without performing any preprocessing nor profiling to check pipeline function. Useful when you only wish to test a single profiler without having to 'opt-out' of all the others" + config_profile_name = 'Test profile' + config_profile_description = "Minimal test dataset without performing any preprocessing nor profiling to check pipeline function. Useful when you only wish to test a single profiler without having to 'opt-out' of all the others" // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = '6.GB' - max_time = '6.h' + max_cpus = 2 + max_memory = '6.GB' + max_time = '6.h' // Input data - input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet.csv' - databases = params.pipelines_testdata_base_path + 'taxprofiler/database_v1.1.csv' - perform_shortread_qc = false - perform_longread_qc = false - perform_shortread_complexityfilter = false - perform_shortread_hostremoval = false - perform_longread_hostremoval = false - perform_runmerging = false - hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' - run_kaiju = false - run_kraken2 = false - run_bracken = false - run_malt = false - run_metaphlan = false - run_centrifuge = false - run_diamond = false - run_krakenuniq = false - run_motus = false - run_kmcp = false - run_ganon = false + input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet.csv' + databases = params.pipelines_testdata_base_path + 'taxprofiler/database_v1.2.csv' + perform_shortread_qc = false + perform_longread_qc = false + perform_shortread_redundancyestimation = false + perform_shortread_complexityfilter = false + perform_shortread_hostremoval = false + perform_longread_hostremoval = false + perform_runmerging = false + hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' + run_kaiju = false + run_kraken2 = false + run_bracken = false + run_malt = false + run_metaphlan = false + run_centrifuge = false + run_diamond = false + run_krakenuniq = false + run_motus = false + run_kmcp = false + run_ganon = false } process { @@ -47,4 +48,7 @@ process { maxForks = 1 ext.args = { "-m ${params.malt_mode} -J-Xmx12G" } } + withName: NONPAREIL_NONPAREIL { + ext.args = { "-k 5" } + } } diff --git a/conf/test_prinseqplusplus.config b/conf/test_prinseqplusplus.config index c7ce2259..d9c576f4 100644 --- a/conf/test_prinseqplusplus.config +++ b/conf/test_prinseqplusplus.config @@ -5,42 +5,43 @@ Defines input files and everything required to run a fast and simple pipeline test. Use as follows: - nextflow run nf-core/taxprofiler -profile test, --outdir + nextflow run nf-core/taxprofiler -profile test_prinseqplusplus, --outdir ---------------------------------------------------------------------------------------- */ params { - config_profile_name = 'Test profile for prinseqplusplus' - config_profile_description = "Minimal test to check the alternative tool of short-read complexity filtering, prinseqplusplus" + config_profile_name = 'Test profile for prinseqplusplus' + config_profile_description = "Minimal test to check the alternative tool of short-read complexity filtering, prinseqplusplus" // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = '6.GB' - max_time = '6.h' + max_cpus = 2 + max_memory = '6.GB' + max_time = '6.h' // Input data - input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet.csv' - databases = params.pipelines_testdata_base_path + 'taxprofiler/database_v1.1.csv' - perform_shortread_qc = true - perform_longread_qc = true - perform_shortread_complexityfilter = true - shortread_complexityfilter_tool = 'prinseqplusplus' - perform_shortread_hostremoval = false - perform_longread_hostremoval = false - perform_runmerging = false - hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' - run_kaiju = true - run_kraken2 = true - run_bracken = false - run_malt = false - run_metaphlan = false - run_centrifuge = false - run_diamond = false - run_krakenuniq = false - run_motus = false - run_ganon = false - run_kmcp = false + input = params.pipelines_testdata_base_path + 'taxprofiler/samplesheet.csv' + databases = params.pipelines_testdata_base_path + 'taxprofiler/database_v1.2.csv' + perform_shortread_qc = true + perform_longread_qc = true + perform_shortread_redundancyestimation = false + perform_shortread_complexityfilter = true + shortread_complexityfilter_tool = 'prinseqplusplus' + perform_shortread_hostremoval = false + perform_longread_hostremoval = false + perform_runmerging = false + hostremoval_reference = params.pipelines_testdata_base_path + 'modules/data/genomics/homo_sapiens/genome/genome.fasta' + run_kaiju = true + run_kraken2 = true + run_bracken = false + run_malt = false + run_metaphlan = false + run_centrifuge = false + run_diamond = false + run_krakenuniq = false + run_motus = false + run_ganon = false + run_kmcp = false } process { @@ -48,4 +49,7 @@ process { maxForks = 1 ext.args = { "-m ${params.malt_mode} -J-Xmx12G" } } + withName: NONPAREIL_NONPAREIL { + ext.args = { "-k 5" } + } } diff --git a/docs/images/taxprofiler_tube.pdf b/docs/images/taxprofiler_tube.pdf index 024d4aca..a90aa4a0 100644 Binary files a/docs/images/taxprofiler_tube.pdf and b/docs/images/taxprofiler_tube.pdf differ diff --git a/docs/images/taxprofiler_tube.png b/docs/images/taxprofiler_tube.png index 301d406a..4af7a1e7 100644 Binary files a/docs/images/taxprofiler_tube.png and b/docs/images/taxprofiler_tube.png differ diff --git a/docs/images/taxprofiler_tube.svg b/docs/images/taxprofiler_tube.svg index 6914d622..f13e193b 100644 --- a/docs/images/taxprofiler_tube.svg +++ b/docs/images/taxprofiler_tube.svg @@ -36,9 +36,9 @@ fit-margin-left="0" fit-margin-right="0" fit-margin-bottom="0" - inkscape:zoom="1.4206694" - inkscape:cx="408.96215" - inkscape:cy="673.62613" + inkscape:zoom="1.0377583" + inkscape:cx="506.86177" + inkscape:cy="438.44506" inkscape:window-width="1920" inkscape:window-height="1136" inkscape:window-x="0" @@ -2347,15 +2347,27 @@ inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" - transform="translate(793.74988,-29.857504)">SEQUENCING(SEQUENCINGQUALITY CONTROLQUALITY CONTROL)(ADAPTER TRIMMING & (ADAPTER TRIMMING & MERGING)(COMPLEXITY (COMPLEXITY FILTERING)(COVERAGEESTIMATION)(HOST REMOVAL)(ADAPTER TRIMMING & MERGING)(HOST REMOVAL)TAXONOMIC CLASSIFICATIONSUMMARY STATISTICSfastpfastpAdapterRemovalBBDukPRINSEQ++Long ReadsBowtie2samtoolsstatssamtoolsstatscatminimap2samtoolsstatsFiltlongnanoqFiltlongKrona(Krona)PorechopPorechop_ABIPorechopfalcoFastQCfalcoNonpareilfalco(LENGTH FILTERING)(LENGTH FILTERING)v1.1v1.2 + sodipodi:nodetypes="cc" /> diff --git a/docs/output.md b/docs/output.md index 732d5964..7cf96395 100644 --- a/docs/output.md +++ b/docs/output.md @@ -15,15 +15,18 @@ The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes d - [falco](#fastqc) - Alternative to FastQC for raw read QC - [fastp](#fastp) - Adapter trimming for Illumina data - [AdapterRemoval](#adapterremoval) - Adapter trimming for Illumina data -- [Porechop](#porechop) - Adapter removal for Oxford Nanopore data +- [Nonpareil](#nonpareil) - Read redundancy and metagenome coverage estimation for short reads - [BBDuk](#bbduk) - Quality trimming and filtering for Illumina data - [PRINSEQ++](#prinseq) - Quality trimming and filtering for Illunina data +- [Porechop](#porechop) - Adapter removal for Oxford Nanopore data +- [Porechop_ABI](#porechop_abi) - Adapter removal for Oxford Nanopore data - [Filtlong](#filtlong) - Quality trimming and filtering for Nanopore data +- [Nanoq] (#nanoq) - Quality trimming and filtering for Nanopore data - [Bowtie2](#bowtie2) - Host removal for Illumina reads - [minimap2](#minimap2) - Host removal for Nanopore reads - [SAMtools stats](#samtools-stats) - Statistics from host removal - [SAMtools fastq](#samtools-fastq) - Converts unmapped BAM file to fastq format (minimap2 only) -- [Analysis Ready Reads](#analysis-read-reads) - Optional results directory containing the final processed reads used as input for classification/profiling. +- [Analysis Ready Reads](#analysis-ready-reads) - Optional results directory containing the final processed reads used as input for classification/profiling. - [Bracken](#bracken) - Taxonomic classifier using k-mers and abundance estimations - [Kraken2](#kraken2) - Taxonomic classifier using exact k-mer matches - [KrakenUniq](#krakenuniq) - Taxonomic classifier that combines the k-mer-based classification and the number of unique k-mers found in each species @@ -133,6 +136,29 @@ You will only find the `.fastq` files in the results directory if you provide ` The resulting `.fastq` files may _not_ always be the 'final' reads that go into taxprofiling, if you also run other steps such as complexity filtering, host removal, run merging etc.. ::: +### Nonpareil + +[nonpareil](https://nonpareil.readthedocs.io/en/latest/) is a tool for estimating metagenome 'coverage' from short-read libraries, i.e, whether all genomes within the metagenome have had at least one read sequenced. The lower the redundancy, the more sequencing can be done until the entire metagenome has been captured. The output can be used to guide the amount of further sequencing is required. + +
+Output files + +- `nonpareil/` + + - `.npl` - log file of the nonpareil run. + - `.npo` - redundancy summary file. This is the most useful file and contains the information for generating metagenome coverage curves. These six columns are: seq. effort (_n_ reads), average redundancy, standard deviation, quartile 1, median (quartile 2), and quartile 3. + - `.npa` - raw version of npo but with all replicates not just a summary (average) at each point. These three columns are: seq. effort (_n_ reads), replicate ID, redundancy value. + - `.npc` - raw list with the number of reads in the dataset matching a query read. + - `.png` - rendered version of a Nonpareil curve, with extrapolation and sequencing effort information. + - `nonpareil_all_samples_mqc.{png,pdf}` summary of the plot of curves for all samples with sequencing effort information. + - `nonpareil_all_samples_mqc.{json,tsv,csv}` basic summary statistics of model, with additional curve and plotting information in the JSON. + +
+ +In most cases you will just want to look at the PNG files which contain the extrapolation information for estimating how much of the metagenome 'coverage' you will recover if you sequence more (i.e., to help indicate at what point you will just keep sequencing redundant reads that provide no more new taxonomic information). + +The `.npo` files can be used for re-generating and customising the plots using the companion `Nonpareil` R package. + ### Porechop [Porechop](https://github.com/rrwick/Porechop) is a tool for finding and removing adapters from Oxford Nanopore reads. Adapters on the ends of reads are trimmed and if a read has an adapter in its middle, it is considered a chimeric and it chopped into separate reads. @@ -154,6 +180,23 @@ You will only find the `.fastq` files in the results directory if you provide ` We do **not** recommend using Porechop if you are already trimming the adapters with ONT's basecaller Guppy. ::: +### Porechop_ABI + +[Porechop_ABI](https://github.com/bonsai-team/Porechop_ABI) is an extension of [Porechop](https://github.com/rrwick/Porechop). Unlike Porechop, Porechop_ABI does not use any external knowledge or database for the adapters. Adapters are discovered directly from the reads using approximate k-mers counting and assembly. Then these sequences can be used for trimming, using all standard Porechop options. The software is able to report a combination of distinct sequences if a mix of adapters is used. It can also be used to check whether a dataset has already been trimmed out or not, or to find leftover adapters in datasets that have been previously processed with Guppy. + +
+Output files + +- `porechop_abi/` + - `.log`: Log file containing trimming statistics + - `.fastq.gz`: Adapter-trimmed file + +
+ +The output logs are saved in the output folder and are part of MultiQC report.You do not normally need to check these manually. + +You will only find the `.fastq` files in the results directory if you provide ` --save_preprocessed_reads`. Alternatively, if you wish only to have the 'final' reads that go into classification/profiling (i.e., that may have additional processing), do not specify this flag but rather specify `--save_analysis_ready_reads`, in which case the reads will be in the folder `analysis_ready_reads`. + ### BBDuk [BBDuk](https://jgi.doe.gov/data-and-tools/software-tools/bbtools/bb-tools-user-guide/bbduk-guide/) stands for Decontamination Using Kmers. BBDuk was developed to combine most common data-quality-related trimming, filtering, and masking operations into a single high-performance tool. @@ -204,7 +247,7 @@ The resulting `.fastq` files may _not_ always be the 'final' reads that go into Output files - `filtlong/` - - `_filtered.fastq.gz`: Quality or short read data filtered file + - `_filtered.fastq.gz`: Quality or long read data filtered file - `_filtered.log`: log file containing summary statistics @@ -215,6 +258,21 @@ You will only find the `.fastq` files in the results directory if you provide ` We do _not_ recommend using Filtlong if you are performing filtering of low quality reads with ONT's basecaller Guppy. ::: +### Nanoq + +[nanoq](https://github.com/esteinig/nanoq) is an ultra-fast quality filtering tool that also provides summary reports for nanopore reads. + +
+Output files + +- `nanoq/` + - `_filtered.fastq.gz`: Quality or long read data filtered file + - `_filtered.stats`: Summary statistics report + +
+ +You will only find the `.fastq` files in the results directory if you provide ` --save_preprocessed_reads`. Alternatively, if you wish only to have the 'final' reads that go into classification/profiling (i.e., that may have additional processing), do not specify this flag but rather specify `--save_analysis_ready_reads`, in which case the reads will be in the folder `analysis_ready_reads`. + ### Bowtie2 [Bowtie 2](https://bowtie-bio.sourceforge.net/bowtie2/index.shtml) is an ultrafast and memory-efficient tool for aligning sequencing reads to long reference sequences. It is particularly good at aligning reads of about 50 up to 100s or 1,000s of characters, and particularly good at aligning to relatively long (e.g. mammalian) genomes. @@ -560,9 +618,9 @@ The main taxonomic classification file from KMCP is the `*kmcp.profile` which is - `_report.tre`: output of `ganon report` containing taxonomic classifications with possible formatting and/or filtering depending on options specified. - ``.tre: output of `ganon classify` containing raw taxonomic classifications and abundance estimations with no additional formatting or filtering. - ``.rep: 'raw' report of counts against each taxon. - - ``.all: per-read summary of all hits of each reads. - - ``.lca: per-read summary of the best single hit after LCA for each read. - - ``.unc: list of read IDs with no hits. + - ``.all: per-read summary of all hits of each read. Only generated if `--ganon_save_readclassifications` specified. + - ``.one: per-read summary of the best single hit after the selection by the user specified multiple match method for each read. Only generated if `--ganon_save_readclassifications` specified. + - ``.unc: list of read IDs with no hits. Only generated if `--ganon_save_readclassifications` specified. - ``.log: the stdout console messages printed by `ganon classify`, containing some classification summary information - `ganon__combined_reports.txt`: A combined profile of all samples aligned to a given database (as generated by `ganon table`) @@ -646,10 +704,13 @@ All tools in taxprofiler supported by MultiQC will have a dedicated section show You can expect in the MultiQC reports either sections and/or general stats columns for the following tools: - fastqc -- adapterRemoval +- adapterremoval - fastp +- nonpareil - bbduk - prinseqplusplus +- nanoq +- porechop_abi - porechop - filtlong - bowtie2 @@ -664,7 +725,9 @@ You can expect in the MultiQC reports either sections and/or general stats colum - motus :::info -The 'General Stats' table by default will only show statistics referring to pre-processing steps, and will not display possible values from each classifier/profiler, unless turned on by the user within the 'Configure Columns' menu or via a custom MultiQC config file (`--multiqc_config`) +The 'General Stats' table by default will only show statistics referring to pre-processing steps, and will not display possible values from each classifier/profiler, unless turned on by the user within the 'Configure Columns' menu or via a custom MultiQC config file (`--multiqc_config`). + +For example, DIAMOND output does not have a dedicated section in the MultiQC HTML, only in the general stats table. To turn this on, copy the nf-core/taxprofiler [MultiQC config](https://github.com/nf-core/taxprofiler/blob/master/assets/multiqc_config.yml) and change the DIAMOND entry in `table_columns_visible:` to True. ::: ### Pipeline information diff --git a/docs/usage.md b/docs/usage.md index 6534b820..d9e44bc1 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -97,6 +97,10 @@ While one can include both short-read and long-read data in one run, we recommen An [example samplesheet](../assets/samplesheet.csv) has been provided with the pipeline. +:::warning +FASTA input will not go through any preprocessing steps, and will go directly to profiling. +::: + ### Full database sheet nf-core/taxprofiler supports multiple databases being classified/profiled against in parallel for each tool. @@ -107,13 +111,17 @@ Databases can be supplied either in the form of a compressed `.tar.gz` archive o nf-core/taxprofiler does not provide any databases by default, nor does it currently generate them for you. This must be performed manually by the user. See bottom of this section for more information of the expected database files, or the [building databases](usage/tutorials#retrieving-databases-or-building-custom-databases) tutorial. ::: -The pipeline takes the paths and specific classification/profiling parameters of the tool of these databases as input via a four column comma-separated sheet. +The pipeline takes the paths and specific classification/profiling parameters of the tool of these databases as input via a four (or five) column comma-separated sheet. + +The optional `db_type` column allows to use specific database/parameters against specific data types. By specifying if a database is for short-or long-reads (or even both), the samples sequenced with Illumina are combined with the short-read databases and the samples sequenced with Nanopore are combined with long-read databases. If `db_type` is not provided, it is assumed the database and parameters are applicable for both short- and long-read data. :::warning To allow user freedom, nf-core/taxprofiler does not check for mandatory or the validity of non-file database parameters for correct execution of the tool - excluding options offered via pipeline level parameters! Please validate your database parameters (cross-referencing [parameters](https://nf-co.re/taxprofiler/parameters), and the given tool documentation) before submitting the database sheet! For example, if you don't use the default read length - Bracken will require `-r ` in the `db_params` column. ::: -An example database sheet can look as follows, where 7 tools are being used, and `malt` and `kraken2` will be used against two databases each. +An example database sheet can look as follows, where 7 tools are being used, and `malt` and `kraken2` will be used against two databases each. Since the `db_type` column is missing, it is therefore assumed that the database and parameters are suitable for both short- and long-read data. + +In the second example database sheet, the `db_type` column has been provided. The valid options are `short`, `long` and `short;long`. `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`. @@ -131,6 +139,20 @@ ganon,db1,,///ganon/test-db-ganon.tar.gz kmcp,db1,;-I 20,///kmcp/test-db-kmcp.tar.gz ``` +```csv +tool,db_name,db_params,db_type,db_path +malt,malt85,-id 85,short,///malt/testdb-malt/ +malt,malt95,-id 90,short,///malt/testdb-malt.tar.gz +bracken,db1,;-r 150,short,///bracken/testdb-bracken.tar.gz +kraken2,db2,--quick,short,///kraken2/testdb-kraken2.tar.gz +krakenuniq,db3,,short;long,///krakenuniq/testdb-krakenuniq.tar.gz +centrifuge,db1,,short,///centrifuge/minigut_cf.tar.gz +metaphlan,db1,,short,///metaphlan/metaphlan_database/ +motus,db_mOTU,,long,///motus/motus_database/ +ganon,db1,,short,///ganon/test-db-ganon.tar.gz +kmcp,db1,;-I 20,short,///kmcp/test-db-kmcp.tar.gz +``` + :::warning For Bracken and KMCP, which are two step profilers, nf-core/taxprofiler has a special way of passing parameters to each steps! @@ -148,6 +170,7 @@ Column specifications are as follows: | `tool` | Taxonomic profiling tool (supported by nf-core/taxprofiler) that the database has been indexed for [required]. Please note that `bracken` also implies running `kraken2` on the same database. | | `db_name` | A unique name per tool for the particular database [required]. Please note that names need to be unique across both `kraken2` and `bracken` as well, even if re-using the same database. | | `db_params` | Any parameters of the given taxonomic classifier/profiler that you wish to specify that the taxonomic classifier/profiling tool should use when profiling against this specific database. Can be empty to use taxonomic classifier/profiler defaults. Must not be surrounded by quotes [required]. We generally do not recommend specifying parameters here that turn on/off saving of output files or specifying particular file extensions - this should be already addressed via pipeline parameters. For Bracken databases, must at a minimum contain a `;` separating Kraken2 from Bracken parameters. | +| `db_type` | An optional column to distinguish between short- and long-read databases. If the column is empty, the pipeline will assume all databases (and their settings specified in `db_params`!) will be applicable for both short and long read data. Possible values: `long`, `short`, or `short;long`. If the `db_type` column is missing from the database.csv, it will take the default value short;long | | `db_path` | Path to the database. Can either be a path to a directory containing the database index files or a `.tar.gz` file which contains the compressed database directory with the same name as the tar archive, minus `.tar.gz` [required]. | :::tip @@ -156,6 +179,8 @@ You can also specify the same database directory/file twice (ensuring unique `db nf-core/taxprofiler will automatically decompress and extract any compressed archives for you. +The optional `db_type` column enables the use of specific databases or parameters for different data types. By specifying if a database is for short-reads, long-reads, or both, Illumina samples are combined with short-read databases, while Nanopore samples are combined with long-read databases. + :::tip Click the links in the list below for short quick-reference tutorials how to generate download 'pre-made' and/or custom databases for each tool. ::: @@ -230,6 +255,7 @@ You can also generate such `YAML`/`JSON` files via [nf-core/launch](https://nf-c nf-core/taxprofiler offers four main preprocessing steps for preprocessing raw sequencing reads: - [**Read processing**](#read-processing): adapter clipping and pair-merging. +- [**Redundancy estimation**](#redundancy-estimation): short-read metagenome coverage estimation. - [**Complexity filtering**](#complexity-filtering): removal of low-sequence complexity reads. - [**Host read-removal**](#host-read-removal): removal of reads aligning to reference genome(s) of a host. - [**Run merging**](#run-merging): concatenation of multiple FASTQ chunks/sequencing runs/libraries of a sample. @@ -251,10 +277,42 @@ By default, paired-end merging is not activated. In this case paired-end 'alignm You can also turn off clipping and only perform paired-end merging, if requested. This can be useful when processing data downloaded from the ENA, SRA, or DDBJ (`--shortread_qc_skipadaptertrim`). Both tools support length filtering of reads and can be tuned with `--shortread_qc_minlength`. Performing length filtering can be useful to remove short (often low sequencing complexity) sequences that result in unspecific classification and therefore slow down runtime during classification/profiling, with minimal gain. -There is currently one option for long-read Oxford Nanopore processing: [`porechop`](https://github.com/rrwick/Porechop). +There are currently two options for long-read Oxford Nanopore processing: [`porechop`](https://github.com/rrwick/Porechop), [`porechop_abi`](https://github.com/bonsai-team/Porechop_ABI). For both short-read and long-read preprocessing, you can optionally save the resulting processed reads with `--save_preprocessed_reads`. +#### Redundancy Estimation + +Metagenome 'coverage' or sequencing complexity estimations of short-read datasets can be activated with `--perform_shortread_redundancyestimation`. + +This turns on checking of read redundancy in a sequencing library using [Nonpareil](https://nonpareil.readthedocs.io/en/latest/), to provide an estimation of whether you have sequenced enough to capture all possible genomes present in your metagenomic sample (with the assumption that once you've sequenced enough, you will keep sequencing PCR amplicons rather than unique reads). + +This is only suitable for short-read, and in nf-core/taxprofiler specifically, FASTQ files. + +Nonpareil is performed on processed reads (i.e. after fastp or AdapterRemoval). This will run on either the first read of each read pair (as recommended by the authors), or on merged reads. + +Before using this tool please note the following caveats: + +:::warning + +- It is not recommended to keep unmerged (`--shortread_qc_includeunmerged`) reads when using the calculation. +- Your shortest reads _after_ processing should not go below 24bp + If the 'kmer' value is not correct, make sure your shortest reads _after_ processing is not less than 24bp. + + If this is the case you will need to specify in a custom config + + ```nextflow + process { + withName: NONPAREIL_NONPAREIL { + ext.args = { "-k " } + } + } + ``` + + Where `` should be at least the shortest read in your library + + ::: + #### Complexity Filtering Complexity filtering can be activated via the `--perform_shortread_complexityfilter` flag. @@ -263,7 +321,7 @@ Complexity filtering is primarily a run-time optimisation step. It is not necess There are currently three options for short-read complexity filtering: [`bbduk`](https://jgi.doe.gov/data-and-tools/software-tools/bbtools/bb-tools-user-guide/bbduk-guide/), [`prinseq++`](https://github.com/Adrian-Cantu/PRINSEQ-plus-plus), and [`fastp`](https://github.com/OpenGene/fastp#low-complexity-filter). -There is one option for long-read quality filtering: [`Filtlong`](https://github.com/rrwick/Filtlong) +There are two options for long-read quality filtering: [`Filtlong`](https://github.com/rrwick/Filtlong) and [`nanoq`](https://github.com/esteinig/nanoq), with `nanoq` being the default option. The tools offer different algorithms and parameters for removing low complexity reads and quality filtering. We therefore recommend reviewing the pipeline's [parameter documentation](https://nf-co.re/taxprofiler/parameters) and the documentation of the tools (see links above) to decide on optimal methods and parameters for your dataset. @@ -327,6 +385,8 @@ Centrifuge currently does not accept FASTA files as input, therefore no output w ##### DIAMOND +DIAMOND can only accept a single input read file. To run DIAMOND on paired-end reads, please merge the reads (e.g., using `--shortread_qc_mergepairs`). + DIAMOND only allows output of a single file format at a time, therefore parameters such `--diamond_save_reads` supplied will result in only aligned reads in SAM format will be produced, no taxonomic profiles will be available. Be aware of this when setting up your pipeline runs, depending on your particular use case. ##### Kaiju diff --git a/docs/usage/faq-troubleshooting.md b/docs/usage/faq-troubleshooting.md index 3c80725d..5692cc50 100644 --- a/docs/usage/faq-troubleshooting.md +++ b/docs/usage/faq-troubleshooting.md @@ -1,9 +1,31 @@ # Troubleshooting and FAQs -## I get a warning during centrifuge_kreport process with exit status 255 +## I get a warning during CENTRIFUGE_KREPORT or KRAKENTOOLS_COMBINEKREPORTS_CENTRIFUGE process with exit status 255 When a sample has insufficient hits for abundance estimation, the resulting `report.txt` file will be empty. -When trying to convert this to a kraken-style report, the conversion tool will exit with a status code `255`, and provide a `WARN`. +When trying to convert this to a kraken-style report or merging together, the tools will exit with a status code `255`, and provide a `WARN`. -This is _not_ an error nor a failure of the pipeline, just your sample has no hits to the provided database when using centrifuge. +This is _not_ an error nor a failure of the pipeline, just your sample has no hits to the provided database when using Centrifuge. + +## Why does any error or failed process from BRACKEN_BRACKEN get ignored? + +If Kraken2 doesn't classify any reads (100% unclassified) Bracken will fail on that input. +Having no reads taxonomically classified can be a reasonable outcome for some samples, and we don't want to treat this as an error. + +Therefore to allow the remainder of a given run to complete if a single Bracken task fails, [we set the Nextflow `errorStrategy` to `ignore`](https://github.com/nf-core/taxprofiler/blob/5d3ee5513a84f92773c8376c55b5f4da39835307/conf/base.config#L61-L63). +You will still get a warning in the Nextflow console output and log that a Bracken task failed. + +If you want to change this behaviour, you can override the `errorStrategy` in your own Nextflow configuration file. + +For example: + +```nextflow +process { + withName: BRACKEN_BRACKEN { + errorStrategy = 'retry' + } +} +``` + +Other `errorStrategy` options can be found on the [Nextflow documentation](https://www.nextflow.io/docs/latest/process.html#errorstrategy). diff --git a/docs/usage/tutorials.md b/docs/usage/tutorials.md index d7a489d7..aa48a200 100644 --- a/docs/usage/tutorials.md +++ b/docs/usage/tutorials.md @@ -93,20 +93,22 @@ If you had placed your FASTQ files elsewhere, you would give the full path (i.e. #### Database sheet For the database(s), you also supply these via a `.csv` file. -This 4 column table contains the tool the database has been built for, a database name, the parameters you wish reads to be queried against the given database with, and a path to a `.tar.gz` archive file or a directory containing the database files. +This 4 (or 5) column table contains the tool the database has been built for, a database name, the parameters you wish reads to be queried against the given database with, an optional column to distinguish between short- and long-read databases, and a path to a `.tar.gz` archive file or a directory containing the database files. Open a text editor, and create a file called `database.csv`. Copy and paste the following csv file into the file and save it. ```csv title="database.csv" -tool,db_name,db_params,db_path -kraken2,db1,--quick,testdb-kraken2.tar.gz -centrifuge,db2,,test-db-centrifuge.tar.gz -centrifuge,db2_trimmed,--trim5 2 --trim3 2,test-db-centrifuge.tar.gz -kaiju,db3,,kaiju/ +tool,db_name,db_params,db_type,db_path +kraken2,db1,--quick,short,testdb-kraken2.tar.gz +centrifuge,db2,,short,test-db-centrifuge.tar.gz +centrifuge,db2_trimmed,--trim5 2 --trim3 2,long,test-db-centrifuge.tar.gz +kaiju,db3,,short;long,kaiju/ ``` You can see here we have specified the Centrifuge database twice, to allow comparison of different settings. +We have also specified different profiling parameters depending on whether a database is for short-read or long-read use. +If we don't specify this, the pipeline will assume all databases (and their settings specified in `db_params`!) will be applicable for both short and long read data. Note that the each database of the same tool has a unique name. Furthermore, while the Kraken2 and Centrifuge databases have been supplied as `.tar.gz` archives, the Kaiju database has been supplied as a directory. diff --git a/modules.json b/modules.json index b7fc0290..77bf8131 100644 --- a/modules.json +++ b/modules.json @@ -7,238 +7,268 @@ "nf-core": { "adapterremoval": { "branch": "master", - "git_sha": "5add1e8e11af620c779462936ce8bbcc1abcef2d", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "bbmap/bbduk": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "bowtie2/align": { "branch": "master", - "git_sha": "fe54581f8bed20e4c4a51c616c93fd3379d89820", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "bowtie2/build": { "branch": "master", - "git_sha": "6a24fbe314bb2e6fe6306c29a63076ea87e8eb3c", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "bracken/bracken": { "branch": "master", - "git_sha": "093e35505936bce5127e1d14966b6cac91cd137f", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "bracken/combinebrackenoutputs": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "cat/fastq": { "branch": "master", - "git_sha": "5c460c5a4736974abde2843294f35307ee2b0e5e", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "centrifuge/centrifuge": { "branch": "master", - "git_sha": "9a07a1293d9b818d1e06d0f7b58152f74d462012", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "centrifuge/kreport": { "branch": "master", - "git_sha": "9a07a1293d9b818d1e06d0f7b58152f74d462012", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "diamond/blastx": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "falco": { "branch": "master", - "git_sha": "a236d2c2ec9e68db9b8501105d804acb359552b5", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "fastp": { "branch": "master", - "git_sha": "451d49b70f1801a9e5835f111c927104af64481e", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "fastqc": { "branch": "master", - "git_sha": "285a50500f9e02578d90b3ce6382ea3c30216acd", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "filtlong": { "branch": "master", - "git_sha": "b4c8ac68ffcdabac3f63aaa5e7420b175e1d8d76", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "ganon/classify": { "branch": "master", - "git_sha": "3b9d0fd0431442facdc816ca0c731f9807c47ebd", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "ganon/report": { "branch": "master", - "git_sha": "f61e38c82ca2bbb8dfa740822df6f2b75f2d8a86", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "ganon/table": { "branch": "master", - "git_sha": "c02373677641897c9744c0f55f0c12fd79232c71", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "gunzip": { "branch": "master", - "git_sha": "e06548bfa36ee31869b81041879dd6b3a83b1d57", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "kaiju/kaiju": { "branch": "master", - "git_sha": "3db50674956b1fb3741a44eb917458d788a50197", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "kaiju/kaiju2krona": { "branch": "master", - "git_sha": "3db50674956b1fb3741a44eb917458d788a50197", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "kaiju/kaiju2table": { "branch": "master", - "git_sha": "3db50674956b1fb3741a44eb917458d788a50197", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "kmcp/profile": { "branch": "master", - "git_sha": "6f56948d0674ad5870035e80c7af209a51d8e243", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "kmcp/search": { "branch": "master", - "git_sha": "64cd3f418b191a008b9d362b8ccf0216ae0302d5", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "kraken2/kraken2": { "branch": "master", - "git_sha": "603ecbd9f45300c9788f197d2a15a005685b4220", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "krakentools/combinekreports": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "krakentools/kreport2krona": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "krakenuniq/preloadedkrakenuniq": { "branch": "master", - "git_sha": "9de9365c3ca6071ec01705919f6667c718ef47b4", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "krona/ktimporttaxonomy": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "krona/ktimporttext": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "malt/run": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "megan/rma2info": { "branch": "master", - "git_sha": "dbce8951ff9a39ad08d87e563636bbcc6ef34032", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "metaphlan/mergemetaphlantables": { "branch": "master", - "git_sha": "efae1c431e539d6a6d323ee2e9223c4b81a152ce", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "metaphlan/metaphlan": { "branch": "master", - "git_sha": "1038d3de36263159b4138324a646105941ac271a", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "minimap2/align": { "branch": "master", - "git_sha": "603ecbd9f45300c9788f197d2a15a005685b4220", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "minimap2/index": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "motus/merge": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "3cf419b5480c5ca8893f5ea6e1746d2b3a7c326d", "installed_by": ["modules"] }, "motus/profile": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "multiqc": { "branch": "master", - "git_sha": "b7ebe95761cd389603f9cc0e0dc384c0f663815a", + "git_sha": "7c316cae26baf55e0add993bed2b0c9f7105c653", + "installed_by": ["modules"] + }, + "nanoq": { + "branch": "master", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", + "installed_by": ["modules"] + }, + "nonpareil/curve": { + "branch": "master", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", + "installed_by": ["modules"] + }, + "nonpareil/nonpareil": { + "branch": "master", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", + "installed_by": ["modules"] + }, + "nonpareil/nonpareilcurvesr": { + "branch": "master", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", + "installed_by": ["modules"] + }, + "nonpareil/set": { + "branch": "master", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", + "installed_by": ["modules"] + }, + "porechop/abi": { + "branch": "master", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "porechop/porechop": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"], "patch": "modules/nf-core/porechop/porechop/porechop-porechop.diff" }, "prinseqplusplus": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "samtools/fastq": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "samtools/index": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "samtools/stats": { "branch": "master", - "git_sha": "735e1e04e7e01751d2d6e97055bbdb6f70683cc1", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "samtools/view": { "branch": "master", - "git_sha": "3ffae3598260a99e8db3207dead9f73f87f90d1f", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "taxpasta/merge": { "branch": "master", - "git_sha": "4fd9089d3cf904e0b870d5a6a7ab903ee5e1004d", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "taxpasta/standardise": { "branch": "master", - "git_sha": "4fd9089d3cf904e0b870d5a6a7ab903ee5e1004d", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] }, "untar": { "branch": "master", - "git_sha": "d0b4fc03af52a1cc8c6fb4493b921b57352b1dd8", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", "installed_by": ["modules"] } } @@ -247,12 +277,12 @@ "nf-core": { "utils_nextflow_pipeline": { "branch": "master", - "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", + "git_sha": "d20fb2a9cc3e2835e9d067d1046a63252eb17352", "installed_by": ["subworkflows"] }, "utils_nfcore_pipeline": { "branch": "master", - "git_sha": "92de218a329bfc9a9033116eb5f65fd270e72ba3", + "git_sha": "2fdce49d30c0254f76bc0f13c55c17455c1251ab", "installed_by": ["subworkflows"] }, "utils_nfvalidation_plugin": { diff --git a/modules/nf-core/adapterremoval/environment.yml b/modules/nf-core/adapterremoval/environment.yml index 1737b14b..0e089bfb 100644 --- a/modules/nf-core/adapterremoval/environment.yml +++ b/modules/nf-core/adapterremoval/environment.yml @@ -1,7 +1,5 @@ -name: adapterremoval channels: - conda-forge - bioconda - - defaults dependencies: - bioconda::adapterremoval=2.3.2 diff --git a/modules/nf-core/adapterremoval/tests/main.nf.test b/modules/nf-core/adapterremoval/tests/main.nf.test index 91c07b7e..5b5d4227 100644 --- a/modules/nf-core/adapterremoval/tests/main.nf.test +++ b/modules/nf-core/adapterremoval/tests/main.nf.test @@ -15,7 +15,7 @@ nextflow_process { """ input[0] = [ [ id:'test', single_end:true, collapse:false ], // meta map - file(params.test_data['sarscov2']['illumina']['test_1_fastq_gz'], checkIfExists: true) + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] input[1] = [] """ @@ -39,8 +39,8 @@ nextflow_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) ] + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] ] input[1] = [] """ @@ -68,8 +68,8 @@ nextflow_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.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] ] input[1] = [] """ @@ -96,8 +96,8 @@ nextflow_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) ] + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/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) diff --git a/modules/nf-core/bbmap/bbduk/environment.yml b/modules/nf-core/bbmap/bbduk/environment.yml new file mode 100644 index 00000000..cbe6f2a0 --- /dev/null +++ b/modules/nf-core/bbmap/bbduk/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::bbmap=39.06 diff --git a/modules/nf-core/bbmap/bbduk/main.nf b/modules/nf-core/bbmap/bbduk/main.nf index 001e27d4..e5747fe8 100644 --- a/modules/nf-core/bbmap/bbduk/main.nf +++ b/modules/nf-core/bbmap/bbduk/main.nf @@ -2,10 +2,10 @@ process BBMAP_BBDUK { tag "$meta.id" label 'process_medium' - conda "bioconda::bbmap=39.01" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/bbmap:39.01--h5c4e2a8_0': - 'biocontainers/bbmap:39.01--h5c4e2a8_0' }" + 'https://depot.galaxyproject.org/singularity/bbmap:39.06--h92535d8_1': + 'biocontainers/bbmap:39.06--h92535d8_1' }" input: tuple val(meta), path(reads) @@ -40,4 +40,18 @@ process BBMAP_BBDUK { bbmap: \$(bbversion.sh | grep -v "Duplicate cpuset") END_VERSIONS """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def output_command = meta.single_end ? "echo '' | gzip > ${prefix}.fastq.gz" : "echo '' | gzip > ${prefix}_1.fastq.gz ; echo '' | gzip > ${prefix}_2.fastq.gz" + """ + touch ${prefix}.bbduk.log + $output_command + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bbmap: \$(bbversion.sh | grep -v "Duplicate cpuset") + END_VERSIONS + """ } diff --git a/modules/nf-core/bbmap/bbduk/meta.yml b/modules/nf-core/bbmap/bbduk/meta.yml index c1719918..9a1f0562 100644 --- a/modules/nf-core/bbmap/bbduk/meta.yml +++ b/modules/nf-core/bbmap/bbduk/meta.yml @@ -10,9 +10,7 @@ tools: description: BBMap is a short read aligner, as well as various other bioinformatic tools. homepage: https://jgi.doe.gov/data-and-tools/bbtools/bb-tools-user-guide/ documentation: https://jgi.doe.gov/data-and-tools/bbtools/bb-tools-user-guide/ - licence: ["UC-LBL license (see package)"] - input: - meta: type: map @@ -28,7 +26,6 @@ input: type: file description: | Reference files containing adapter and/or contaminant sequences for sequence kmer matching - output: - meta: type: map @@ -47,6 +44,7 @@ output: type: file description: Bbduk log file pattern: "*bbduk.log" - authors: - "@MGordon09" +maintainers: + - "@MGordon09" diff --git a/modules/nf-core/bbmap/bbduk/tests/main.nf.test b/modules/nf-core/bbmap/bbduk/tests/main.nf.test new file mode 100644 index 00000000..0f3e8187 --- /dev/null +++ b/modules/nf-core/bbmap/bbduk/tests/main.nf.test @@ -0,0 +1,169 @@ +nextflow_process { + + name "Test Process BBMAP_BBDUK" + script "../main.nf" + process "BBMAP_BBDUK" + config "./nextflow.config" + + tag "modules" + tag "modules_nfcore" + tag "bbmap" + tag "bbmap/bbduk" + + test("sarscov2 - single end fastq - fastq") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] + ] + input[1] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert path(process.out.log.get(0).get(1)).getText().contains("Input is being processed as unpaired")}, + { assert snapshot(process.out.reads, + process.out.versions).match() } + ) + } + + } + + test("sarscov2 - paired end fastq - fastq") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] + ] + input[1] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert path(process.out.log.get(0).get(1)).getText().contains("Input is being processed as paired")}, + { assert snapshot(process.out.reads, + process.out.versions).match() } + + ) + } + } + + test("sarscov2 - single end w/ contams [fastq,fasta] - fastq") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] + ] + input[1] = [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/transcriptome.fasta', checkIfExists: true) + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert process.out.reads.get(0).get(1).endsWith("test.trim.fastq.gz") }, + { assert path(process.out.log.get(0).get(1)).getText().contains("Input is being processed as unpaired")}, + { assert snapshot(process.out.versions).match() } + + ) + } + } + + test("sarscov2 - paired end w/ contams [fastq,fasta] - fastq") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] + ] + input[1] = [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/transcriptome.fasta', checkIfExists: true) + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert process.out.reads.get(0).get(1).get(0).endsWith("test.trim_1.fastq.gz") }, + { assert process.out.reads.get(0).get(1).get(1).endsWith("test.trim_2.fastq.gz") }, + { assert path(process.out.log.get(0).get(1)).getText().contains("Input is being processed as paired")}, + { assert snapshot(process.out.versions).match() } + + ) + } + } + + test("sarscov2 - single end fastq - fastq - stub") { + + options "-stub" + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] + ] + input[1] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + + ) + } + + } + + test("sarscov2 - paired end fastq - fastq - stub") { + + options "-stub" + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] + ] + input[1] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + +} diff --git a/modules/nf-core/bbmap/bbduk/tests/main.nf.test.snap b/modules/nf-core/bbmap/bbduk/tests/main.nf.test.snap new file mode 100644 index 00000000..2f0ac2b4 --- /dev/null +++ b/modules/nf-core/bbmap/bbduk/tests/main.nf.test.snap @@ -0,0 +1,183 @@ +{ + "sarscov2 - paired end fastq - fastq": { + "content": [ + [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test.trim_1.fastq.gz:md5,4161df271f9bfcd25d5845a1e220dbec", + "test.trim_2.fastq.gz:md5,2ebae722295ea66d84075a3b042e2b42" + ] + ] + ], + [ + "versions.yml:md5,652ed24469a355fbc7a4ca892d23133e" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-03T13:11:43.393701616" + }, + "sarscov2 - single end w/ contams [fastq,fasta] - fastq": { + "content": [ + [ + "versions.yml:md5,652ed24469a355fbc7a4ca892d23133e" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-03T13:30:39.201243568" + }, + "sarscov2 - paired end w/ contams [fastq,fasta] - fastq": { + "content": [ + [ + "versions.yml:md5,652ed24469a355fbc7a4ca892d23133e" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-03T13:48:13.446399236" + }, + "sarscov2 - paired end fastq - fastq - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test.trim_1.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940", + "test.trim_2.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.trim.bbduk.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,652ed24469a355fbc7a4ca892d23133e" + ], + "log": [ + [ + { + "id": "test", + "single_end": false + }, + "test.trim.bbduk.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "reads": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test.trim_1.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940", + "test.trim_2.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ] + ], + "versions": [ + "versions.yml:md5,652ed24469a355fbc7a4ca892d23133e" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-03T13:12:31.910356296" + }, + "sarscov2 - single end fastq - fastq - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.trim.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test.trim.bbduk.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,652ed24469a355fbc7a4ca892d23133e" + ], + "log": [ + [ + { + "id": "test", + "single_end": true + }, + "test.trim.bbduk.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test.trim.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "versions": [ + "versions.yml:md5,652ed24469a355fbc7a4ca892d23133e" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-03T13:12:22.081697889" + }, + "sarscov2 - single end fastq - fastq": { + "content": [ + [ + [ + { + "id": "test", + "single_end": true + }, + "test.trim.fastq.gz:md5,4161df271f9bfcd25d5845a1e220dbec" + ] + ], + [ + "versions.yml:md5,652ed24469a355fbc7a4ca892d23133e" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-03T13:11:31.383328059" + } +} \ No newline at end of file diff --git a/modules/nf-core/bbmap/bbduk/tests/nextflow.config b/modules/nf-core/bbmap/bbduk/tests/nextflow.config new file mode 100644 index 00000000..44c775dc --- /dev/null +++ b/modules/nf-core/bbmap/bbduk/tests/nextflow.config @@ -0,0 +1,8 @@ +process { + + withName: BBMAP_BBDUK { + ext.args = 'trimq=10 qtrim=r' + ext.prefix = { "${meta.id}.trim" } + } + +} diff --git a/modules/nf-core/bbmap/bbduk/tests/tags.yml b/modules/nf-core/bbmap/bbduk/tests/tags.yml new file mode 100644 index 00000000..16d6171a --- /dev/null +++ b/modules/nf-core/bbmap/bbduk/tests/tags.yml @@ -0,0 +1,2 @@ +bbmap/bbduk: + - "modules/nf-core/bbmap/bbduk/**" diff --git a/modules/nf-core/bowtie2/align/environment.yml b/modules/nf-core/bowtie2/align/environment.yml new file mode 100644 index 00000000..9090f218 --- /dev/null +++ b/modules/nf-core/bowtie2/align/environment.yml @@ -0,0 +1,7 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::bowtie2=2.5.2 + - bioconda::samtools=1.18 + - conda-forge::pigz=2.6 diff --git a/modules/nf-core/bowtie2/align/main.nf b/modules/nf-core/bowtie2/align/main.nf index a77114d2..809525ad 100644 --- a/modules/nf-core/bowtie2/align/main.nf +++ b/modules/nf-core/bowtie2/align/main.nf @@ -1,22 +1,27 @@ process BOWTIE2_ALIGN { tag "$meta.id" - label "process_high" + label 'process_high' - conda "bioconda::bowtie2=2.4.4 bioconda::samtools=1.16.1 conda-forge::pigz=2.6" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-ac74a7f02cebcfcc07d8e8d1d750af9c83b4d45a:a0ffedb52808e102887f6ce600d092675bf3528a-0' : - 'biocontainers/mulled-v2-ac74a7f02cebcfcc07d8e8d1d750af9c83b4d45a:a0ffedb52808e102887f6ce600d092675bf3528a-0' }" + 'https://depot.galaxyproject.org/singularity/mulled-v2-ac74a7f02cebcfcc07d8e8d1d750af9c83b4d45a:f70b31a2db15c023d641c32f433fb02cd04df5a6-0' : + 'biocontainers/mulled-v2-ac74a7f02cebcfcc07d8e8d1d750af9c83b4d45a:f70b31a2db15c023d641c32f433fb02cd04df5a6-0' }" input: tuple val(meta) , path(reads) tuple val(meta2), path(index) + tuple val(meta3), path(fasta) val save_unaligned val sort_bam output: - tuple val(meta), path("*.{bam,sam}"), emit: aligned + tuple val(meta), path("*.sam") , emit: sam , optional:true + tuple val(meta), path("*.bam") , emit: bam , optional:true + tuple val(meta), path("*.cram") , emit: cram , optional:true + tuple val(meta), path("*.csi") , emit: csi , optional:true + tuple val(meta), path("*.crai") , emit: crai , optional:true tuple val(meta), path("*.log") , emit: log - tuple val(meta), path("*fastq.gz") , emit: fastq, optional:true + tuple val(meta), path("*fastq.gz") , emit: fastq , optional:true path "versions.yml" , emit: versions when: @@ -39,7 +44,10 @@ process BOWTIE2_ALIGN { def samtools_command = sort_bam ? 'sort' : 'view' def extension_pattern = /(--output-fmt|-O)+\s+(\S+)/ - def extension = (args2 ==~ extension_pattern) ? (args2 =~ extension_pattern)[0][2].toLowerCase() : "bam" + def extension_matcher = (args2 =~ extension_pattern) + def extension = extension_matcher.getCount() > 0 ? extension_matcher[0][2].toLowerCase() : "bam" + def reference = fasta && extension=="cram" ? "--reference ${fasta}" : "" + if (!fasta && extension=="cram") error "Fasta reference is required for CRAM output" """ INDEX=`find -L ./ -name "*.rev.1.bt2" | sed "s/\\.rev.1.bt2\$//"` @@ -52,8 +60,8 @@ process BOWTIE2_ALIGN { --threads $task.cpus \\ $unaligned \\ $args \\ - 2> ${prefix}.bowtie2.log \\ - | samtools $samtools_command $args2 --threads $task.cpus -o ${prefix}.${extension} - + 2> >(tee ${prefix}.bowtie2.log >&2) \\ + | samtools $samtools_command $args2 --threads $task.cpus ${reference} -o ${prefix}.${extension} - if [ -f ${prefix}.unmapped.fastq.1.gz ]; then mv ${prefix}.unmapped.fastq.1.gz ${prefix}.unmapped_1.fastq.gz @@ -76,12 +84,27 @@ process BOWTIE2_ALIGN { def prefix = task.ext.prefix ?: "${meta.id}" def extension_pattern = /(--output-fmt|-O)+\s+(\S+)/ def extension = (args2 ==~ extension_pattern) ? (args2 =~ extension_pattern)[0][2].toLowerCase() : "bam" + def create_unmapped = "" + if (meta.single_end) { + create_unmapped = save_unaligned ? "touch ${prefix}.unmapped.fastq.gz" : "" + } else { + create_unmapped = save_unaligned ? "touch ${prefix}.unmapped_1.fastq.gz && touch ${prefix}.unmapped_2.fastq.gz" : "" + } + def reference = fasta && extension=="cram" ? "--reference ${fasta}" : "" + if (!fasta && extension=="cram") error "Fasta reference is required for CRAM output" + + def create_index = "" + if (extension == "cram") { + create_index = "touch ${prefix}.crai" + } else if (extension == "bam") { + create_index = "touch ${prefix}.csi" + } """ touch ${prefix}.${extension} + ${create_index} touch ${prefix}.bowtie2.log - touch ${prefix}.unmapped_1.fastq.gz - touch ${prefix}.unmapped_2.fastq.gz + ${create_unmapped} cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/nf-core/bowtie2/align/meta.yml b/modules/nf-core/bowtie2/align/meta.yml index 60d04c12..38610e0e 100644 --- a/modules/nf-core/bowtie2/align/meta.yml +++ b/modules/nf-core/bowtie2/align/meta.yml @@ -36,6 +36,15 @@ input: type: file description: Bowtie2 genome index files pattern: "*.ebwt" + - meta3: + type: map + description: | + Groovy Map containing reference information + e.g. [ id:'test', single_end:false ] + - fasta: + type: file + description: Bowtie2 genome fasta file + pattern: "*.fasta" - save_unaligned: type: boolean description: | @@ -46,22 +55,41 @@ input: description: use samtools sort (true) or samtools view (false) pattern: "true or false" output: - - aligned: + - sam: type: file - description: Output BAM/SAM file containing read alignments - pattern: "*.{bam,sam}" - - versions: + description: Output SAM file containing read alignments + pattern: "*.sam" + - bam: type: file - description: File containing software versions - pattern: "versions.yml" - - fastq: + description: Output BAM file containing read alignments + pattern: "*.bam" + - cram: type: file - description: Unaligned FastQ files - pattern: "*.fastq.gz" + description: Output CRAM file containing read alignments + pattern: "*.cram" + - csi: + type: file + description: Output SAM/BAM index for large inputs + pattern: "*.csi" + - crai: + type: file + description: Output CRAM index + pattern: "*.crai" - log: type: file description: Aligment log pattern: "*.log" + - fastq: + type: file + description: Unaligned FastQ files + pattern: "*.fastq.gz" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@joseespinosa" - "@drpatelh" +maintainers: + - "@joseespinosa" + - "@drpatelh" diff --git a/modules/nf-core/bowtie2/align/tests/cram_crai.config b/modules/nf-core/bowtie2/align/tests/cram_crai.config new file mode 100644 index 00000000..03f1d5e5 --- /dev/null +++ b/modules/nf-core/bowtie2/align/tests/cram_crai.config @@ -0,0 +1,5 @@ +process { + withName: BOWTIE2_ALIGN { + ext.args2 = '--output-fmt cram --write-index' + } +} diff --git a/modules/nf-core/bowtie2/align/tests/large_index.config b/modules/nf-core/bowtie2/align/tests/large_index.config new file mode 100644 index 00000000..fdc1c59d --- /dev/null +++ b/modules/nf-core/bowtie2/align/tests/large_index.config @@ -0,0 +1,5 @@ +process { + withName: BOWTIE2_BUILD { + ext.args = '--large-index' + } +} \ No newline at end of file diff --git a/modules/nf-core/bowtie2/align/tests/main.nf.test b/modules/nf-core/bowtie2/align/tests/main.nf.test new file mode 100644 index 00000000..0de5950f --- /dev/null +++ b/modules/nf-core/bowtie2/align/tests/main.nf.test @@ -0,0 +1,623 @@ +nextflow_process { + + name "Test Process BOWTIE2_ALIGN" + script "../main.nf" + process "BOWTIE2_ALIGN" + tag "modules" + tag "modules_nfcore" + tag "bowtie2" + tag "bowtie2/build" + tag "bowtie2/align" + + test("sarscov2 - fastq, index, fasta, false, false - bam") { + + setup { + run("BOWTIE2_BUILD") { + script "../../build/main.nf" + process { + """ + input[0] = [ + [ id:'test'], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + """ + } + } + } + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + input[1] = BOWTIE2_BUILD.out.index + input[2] = [[ id:'test'], file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true)] + input[3] = false //save_unaligned + input[4] = false //sort + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot( + file(process.out.bam[0][1]).name, + process.out.log, + process.out.fastq, + process.out.versions + ).match() } + ) + } + + } + + test("sarscov2 - fastq, index, fasta, false, false - sam") { + + config "./sam.config" + setup { + run("BOWTIE2_BUILD") { + script "../../build/main.nf" + process { + """ + input[0] = [ + [ id:'test'], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + """ + } + } + } + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + input[1] = BOWTIE2_BUILD.out.index + input[2] = [[ id:'test'], file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true)] + input[3] = false //save_unaligned + input[4] = false //sort + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot( + file(process.out.sam[0][1]).readLines()[0..4], + process.out.log, + process.out.fastq, + process.out.versions + ).match() } + ) + } + + } + + test("sarscov2 - fastq, index, fasta, false, false - sam2") { + + config "./sam2.config" + setup { + run("BOWTIE2_BUILD") { + script "../../build/main.nf" + process { + """ + input[0] = [ + [ id:'test'], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + """ + } + } + } + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + input[1] = BOWTIE2_BUILD.out.index + input[2] = [[ id:'test'], file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true)] + input[3] = false //save_unaligned + input[4] = false //sort + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot( + file(process.out.sam[0][1]).readLines()[0..4], + process.out.log, + process.out.fastq, + process.out.versions + ).match() } + ) + } + + } + + test("sarscov2 - fastq, index, fasta, false, true - bam") { + + setup { + run("BOWTIE2_BUILD") { + script "../../build/main.nf" + process { + """ + input[0] = [ + [ id:'test'], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + """ + } + } + } + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + input[1] = BOWTIE2_BUILD.out.index + input[2] = [[ id:'test'], file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true)] + input[3] = false //save_unaligned + input[4] = false //sort + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot( + file(process.out.bam[0][1]).name, + process.out.log, + process.out.fastq, + process.out.versions + ).match() } + ) + } + + } + + test("sarscov2 - [fastq1, fastq2], index, fasta, false, false - bam") { + + setup { + run("BOWTIE2_BUILD") { + script "../../build/main.nf" + process { + """ + input[0] = [ + [ id:'test'], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + """ + } + } + } + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) + ] + ] + input[1] = BOWTIE2_BUILD.out.index + input[2] = [[ id:'test'], file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true)] + input[3] = false //save_unaligned + input[4] = false //sort + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot( + file(process.out.bam[0][1]).name, + process.out.log, + process.out.fastq, + process.out.versions + ).match() } + ) + } + + } + + test("sarscov2 - [fastq1, fastq2], index, fasta, false, true - bam") { + + setup { + run("BOWTIE2_BUILD") { + script "../../build/main.nf" + process { + """ + input[0] = [ + [ id:'test'], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + """ + } + } + } + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) + ] + ] + input[1] = BOWTIE2_BUILD.out.index + input[2] = [[ id:'test'], file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true)] + input[3] = false //save_unaligned + input[4] = false //sort + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot( + file(process.out.bam[0][1]).name, + process.out.log, + process.out.fastq, + process.out.versions + ).match() } + ) + } + + } + + test("sarscov2 - fastq, large_index, fasta, false, false - bam") { + + config "./large_index.config" + setup { + run("BOWTIE2_BUILD") { + script "../../build/main.nf" + process { + """ + input[0] = [ + [ id:'test'], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + """ + } + } + } + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + input[1] = BOWTIE2_BUILD.out.index + input[2] = [[ id:'test'], file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true)] + input[3] = false //save_unaligned + input[4] = false //sort + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot( + file(process.out.bam[0][1]).name, + process.out.log, + process.out.fastq, + process.out.versions + ).match() } + ) + } + + } + + test("sarscov2 - [fastq1, fastq2], large_index, fasta, false, false - bam") { + + config "./large_index.config" + setup { + run("BOWTIE2_BUILD") { + script "../../build/main.nf" + process { + """ + input[0] = [ + [ id:'test'], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + """ + } + } + } + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) + ] + ] + input[1] = BOWTIE2_BUILD.out.index + input[2] = [[ id:'test'], file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true)] + input[3] = false //save_unaligned + input[4] = false //sort + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot( + file(process.out.bam[0][1]).name, + process.out.log, + process.out.fastq, + process.out.versions + ).match() } + ) + } + + } + + test("sarscov2 - [fastq1, fastq2], index, fasta, true, false - bam") { + + setup { + run("BOWTIE2_BUILD") { + script "../../build/main.nf" + process { + """ + input[0] = [ + [ id:'test'], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + """ + } + } + } + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) + ] + ] + input[1] = BOWTIE2_BUILD.out.index + input[2] = [[ id:'test'], file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true)] + input[3] = false //save_unaligned + input[4] = false //sort + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot( + file(process.out.bam[0][1]).name, + process.out.log, + process.out.fastq, + process.out.versions + ).match() } + ) + } + + } + + test("sarscov2 - fastq, index, fasta, true, false - bam") { + + setup { + run("BOWTIE2_BUILD") { + script "../../build/main.nf" + process { + """ + input[0] = [ + [ id:'test'], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + """ + } + } + } + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + input[1] = BOWTIE2_BUILD.out.index + input[2] = [[ id:'test'], file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true)] + input[3] = false //save_unaligned + input[4] = false //sort + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot( + file(process.out.bam[0][1]).name, + process.out.log, + process.out.fastq, + process.out.versions + ).match() } + + ) + } + + } + + test("sarscov2 - [fastq1, fastq2], index, fasta, true, true - cram") { + + config "./cram_crai.config" + setup { + run("BOWTIE2_BUILD") { + script "../../build/main.nf" + process { + """ + input[0] = [ + [ id:'test'], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + """ + } + } + } + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) + ] + ] + input[1] = BOWTIE2_BUILD.out.index + input[2] = [[ id:'test'], file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true)] + input[3] = false //save_unaligned + input[4] = true //sort + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot( + file(process.out.cram[0][1]).name, + file(process.out.crai[0][1]).name + ).match() } + ) + } + + } + + test("sarscov2 - [fastq1, fastq2], index, fasta, false, false - stub") { + + options "-stub" + setup { + run("BOWTIE2_BUILD") { + script "../../build/main.nf" + process { + """ + input[0] = [ + [ id:'test'], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + """ + } + } + } + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) + ] + ] + input[1] = BOWTIE2_BUILD.out.index + input[2] = [[ id:'test'], file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true)] + input[3] = false //save_unaligned + input[4] = false //sort + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot( + file(process.out.bam[0][1]).name, + file(process.out.csi[0][1]).name, + file(process.out.log[0][1]).name, + process.out.fastq, + process.out.versions + ).match() } + ) + } + + } + + test("sarscov2 - fastq, index, fasta, true, false - stub") { + + options "-stub" + setup { + run("BOWTIE2_BUILD") { + script "../../build/main.nf" + process { + """ + input[0] = [ + [ id:'test'], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + """ + } + } + } + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + input[1] = BOWTIE2_BUILD.out.index + input[2] = [[ id:'test'], file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true)] + input[3] = false //save_unaligned + input[4] = false //sort + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot( + file(process.out.bam[0][1]).name, + file(process.out.csi[0][1]).name, + file(process.out.log[0][1]).name, + process.out.fastq, + process.out.versions + ).match() } + ) + } + + } + +} diff --git a/modules/nf-core/bowtie2/align/tests/main.nf.test.snap b/modules/nf-core/bowtie2/align/tests/main.nf.test.snap new file mode 100644 index 00000000..028e7da6 --- /dev/null +++ b/modules/nf-core/bowtie2/align/tests/main.nf.test.snap @@ -0,0 +1,311 @@ +{ + "sarscov2 - [fastq1, fastq2], large_index, fasta, false, false - bam": { + "content": [ + "test.bam", + [ + [ + { + "id": "test", + "single_end": false + }, + "test.bowtie2.log:md5,bd89ce1b28c93bf822bae391ffcedd19" + ] + ], + [ + + ], + [ + "versions.yml:md5,01d18ab035146ea790e9a0f70adb758f" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-03-18T13:19:25.337323" + }, + "sarscov2 - fastq, index, fasta, false, false - sam2": { + "content": [ + [ + "ERR5069949.2151832\t16\tMT192765.1\t17453\t42\t150M\t*\t0\t0\tACGCACATTGCTAACTAAGGGCACACTAGAACCAGAATATTTCAATTCAGTGTGTAGACTTATGAAAACTATAGGTCCAGACATGTTCCTCGGAACTTGTCGGCGTTGTCCTGCTGAAATTGTTGACACTGTGAGTGCTTTGGTTTATGA\tAAAA versions.yml "${task.process}": - bracken: ${VERSION} + bracken: \$(echo \$(bracken -v) | cut -f2 -d'v') + END_VERSIONS + """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + bracken_report = "${prefix}.tsv" + bracken_kraken_style_report = "${prefix}.kraken2.report_bracken.txt" + """ + touch ${prefix}.tsv + touch ${bracken_kraken_style_report} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bracken: \$(echo \$(bracken -v) | cut -f2 -d'v') END_VERSIONS """ } diff --git a/modules/nf-core/bracken/bracken/meta.yml b/modules/nf-core/bracken/bracken/meta.yml index 43f0455a..b7ff4489 100644 --- a/modules/nf-core/bracken/bracken/meta.yml +++ b/modules/nf-core/bracken/bracken/meta.yml @@ -13,7 +13,6 @@ tools: tool_dev_url: https://github.com/jenniferlu717/Bracken doi: "10.7717/peerj-cs.104" licence: ["GPL v3"] - input: - meta: type: map @@ -28,7 +27,6 @@ input: type: file description: Directory containing the kraken2/Bracken files for analysis pattern: "*" - output: - meta: type: map @@ -47,6 +45,7 @@ output: type: file description: TXT file of bracken corrected results of Kraken2 report output pattern: "*.txt" - authors: - "@Midnighter" +maintainers: + - "@Midnighter" diff --git a/modules/nf-core/bracken/bracken/tests/genus_test.config b/modules/nf-core/bracken/bracken/tests/genus_test.config new file mode 100644 index 00000000..bc5f63ae --- /dev/null +++ b/modules/nf-core/bracken/bracken/tests/genus_test.config @@ -0,0 +1,5 @@ +process { + withName: BRACKEN_BRACKEN { + ext.args = "-l G -t 10 -r 150" + } +} diff --git a/modules/nf-core/bracken/bracken/tests/main.nf.test b/modules/nf-core/bracken/bracken/tests/main.nf.test new file mode 100644 index 00000000..9d2105de --- /dev/null +++ b/modules/nf-core/bracken/bracken/tests/main.nf.test @@ -0,0 +1,167 @@ +nextflow_process { + + name "Test Process BRACKEN_BRACKEN" + script "../main.nf" + process "BRACKEN_BRACKEN" + + tag "modules" + tag "modules_nfcore" + tag "bracken" + tag "bracken/bracken" + tag "kraken2/kraken2" + tag "untar" + + setup { + run ("UNTAR") { + script "../../../untar/main.nf" + process { + """ + input[0] = [[],file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/db/kraken2_bracken.tar.gz', checkIfExists: true)] + """ + } + } + } + + test("sarscov2 - single-end - fastq") { + + config "./nextflow.config" + + setup { + run("KRAKEN2_KRAKEN2") { + script "../../../kraken2/kraken2/main.nf" + process { + """ + input[0] = [[id: 'test', single_end: true], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true)] + input[1] = UNTAR.out.untar.map{it[1]} + input[2] = false + input[3] = false + """ + } + } + } + + when { + process { + """ + input[0] = KRAKEN2_KRAKEN2.out.report + input[1] = UNTAR.out.untar.map{it[1]} + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("sarscov2 - paired-end - fastq - genus config") { + + config "./genus_test.config" + + setup { + run("KRAKEN2_KRAKEN2") { + script "../../../kraken2/kraken2/main.nf" + process { + """ + input[0] = [ + [id: 'test', single_end: false], + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) + ] + ] + input[1] = UNTAR.out.untar.map{it[1]} + input[2] = false + input[3] = false + """ + } + } + } + + when { + process { + """ + input[0] = KRAKEN2_KRAKEN2.out.report + input[1] = UNTAR.out.untar.map{it[1]} + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("sarscov2 - paired-end - fastq") { + + config "./nextflow.config" + + setup { + run("KRAKEN2_KRAKEN2") { + script "../../../kraken2/kraken2/main.nf" + process { + """ + input[0] = [ + [id: 'test', single_end: false], + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) + ] + ] + input[1] = UNTAR.out.untar.map{it[1]} + input[2] = false + input[3] = false + """ + } + } + } + + when { + process { + """ + input[0] = KRAKEN2_KRAKEN2.out.report + input[1] = UNTAR.out.untar.map{it[1]} + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("sarscov2 - stub - fastq") { + + options "-stub" + + when { + process { + """ + input[0] = [[id: 'test'],file(params.modules_testdata_base_path + 'generic/txt/hello.txt', checkIfExists: true)] + input[1] = UNTAR.out.untar.map{it[1]} + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + +} diff --git a/modules/nf-core/bracken/bracken/tests/main.nf.test.snap b/modules/nf-core/bracken/bracken/tests/main.nf.test.snap new file mode 100644 index 00000000..c97a4c71 --- /dev/null +++ b/modules/nf-core/bracken/bracken/tests/main.nf.test.snap @@ -0,0 +1,210 @@ +{ + "sarscov2 - single-end - fastq": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.tsv:md5,4a21ae14ff8a0311d55f139af5247838" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test.kraken2.report_bracken.txt:md5,ca0fbeedc4353b5fdd081688823a33df" + ] + ], + "2": [ + "versions.yml:md5,599fbbf4c1cd5851022a98788f2afdba" + ], + "reports": [ + [ + { + "id": "test", + "single_end": true + }, + "test.tsv:md5,4a21ae14ff8a0311d55f139af5247838" + ] + ], + "txt": [ + [ + { + "id": "test", + "single_end": true + }, + "test.kraken2.report_bracken.txt:md5,ca0fbeedc4353b5fdd081688823a33df" + ] + ], + "versions": [ + "versions.yml:md5,599fbbf4c1cd5851022a98788f2afdba" + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-08-06T11:35:03.995620397" + }, + "sarscov2 - paired-end - fastq - genus config": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.tsv:md5,f609b09d6edb5ebc1ea1435d1dd46cde" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.kraken2.report_bracken.txt:md5,2ce58814420a3690da1f08e10e8d3a30" + ] + ], + "2": [ + "versions.yml:md5,599fbbf4c1cd5851022a98788f2afdba" + ], + "reports": [ + [ + { + "id": "test", + "single_end": false + }, + "test.tsv:md5,f609b09d6edb5ebc1ea1435d1dd46cde" + ] + ], + "txt": [ + [ + { + "id": "test", + "single_end": false + }, + "test.kraken2.report_bracken.txt:md5,2ce58814420a3690da1f08e10e8d3a30" + ] + ], + "versions": [ + "versions.yml:md5,599fbbf4c1cd5851022a98788f2afdba" + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-08-06T12:13:33.399680181" + }, + "sarscov2 - paired-end - fastq": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.tsv:md5,4a21ae14ff8a0311d55f139af5247838" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.kraken2.report_bracken.txt:md5,ca0fbeedc4353b5fdd081688823a33df" + ] + ], + "2": [ + "versions.yml:md5,599fbbf4c1cd5851022a98788f2afdba" + ], + "reports": [ + [ + { + "id": "test", + "single_end": false + }, + "test.tsv:md5,4a21ae14ff8a0311d55f139af5247838" + ] + ], + "txt": [ + [ + { + "id": "test", + "single_end": false + }, + "test.kraken2.report_bracken.txt:md5,ca0fbeedc4353b5fdd081688823a33df" + ] + ], + "versions": [ + "versions.yml:md5,599fbbf4c1cd5851022a98788f2afdba" + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-08-06T12:09:15.465609745" + }, + "sarscov2 - stub - fastq": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.tsv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test" + }, + "test.kraken2.report_bracken.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,599fbbf4c1cd5851022a98788f2afdba" + ], + "reports": [ + [ + { + "id": "test" + }, + "test.tsv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "txt": [ + [ + { + "id": "test" + }, + "test.kraken2.report_bracken.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,599fbbf4c1cd5851022a98788f2afdba" + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-08-06T11:35:42.965471207" + } +} \ No newline at end of file diff --git a/modules/nf-core/bracken/bracken/tests/nextflow.config b/modules/nf-core/bracken/bracken/tests/nextflow.config new file mode 100644 index 00000000..b550b748 --- /dev/null +++ b/modules/nf-core/bracken/bracken/tests/nextflow.config @@ -0,0 +1,5 @@ +process { + withName: BRACKEN_BRACKEN { + ext.args = "-l S -t 10 -r 150" + } +} diff --git a/modules/nf-core/bracken/bracken/tests/tags.yml b/modules/nf-core/bracken/bracken/tests/tags.yml new file mode 100644 index 00000000..6a2cbd38 --- /dev/null +++ b/modules/nf-core/bracken/bracken/tests/tags.yml @@ -0,0 +1,2 @@ +bracken/bracken: + - "modules/nf-core/bracken/bracken/**" diff --git a/modules/nf-core/bracken/combinebrackenoutputs/environment.yml b/modules/nf-core/bracken/combinebrackenoutputs/environment.yml new file mode 100644 index 00000000..b96b00d7 --- /dev/null +++ b/modules/nf-core/bracken/combinebrackenoutputs/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - "bioconda::bracken=2.9" diff --git a/modules/nf-core/bracken/combinebrackenoutputs/main.nf b/modules/nf-core/bracken/combinebrackenoutputs/main.nf index 6a3a22e2..4360849f 100644 --- a/modules/nf-core/bracken/combinebrackenoutputs/main.nf +++ b/modules/nf-core/bracken/combinebrackenoutputs/main.nf @@ -2,11 +2,10 @@ process BRACKEN_COMBINEBRACKENOUTPUTS { tag "$meta.id" label 'process_low' - conda "bioconda::bracken=2.7" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/bracken:2.7--py39hc16433a_0': - 'biocontainers/bracken:2.7--py39hc16433a_0' }" - + 'https://depot.galaxyproject.org/singularity/bracken:2.9--py38h2494328_0': + 'biocontainers/bracken:2.9--py38h2494328_0' }" input: tuple val(meta), path(input) @@ -22,7 +21,7 @@ process BRACKEN_COMBINEBRACKENOUTPUTS { def prefix = task.ext.prefix ?: "${meta.id}" // WARN: Version information not provided by tool on CLI. // Please update version string below when bumping container versions. - def VERSION = '2.7' + def VERSION = '2.9' """ combine_bracken_outputs.py \\ $args \\ @@ -34,4 +33,19 @@ process BRACKEN_COMBINEBRACKENOUTPUTS { combine_bracken_output: ${VERSION} END_VERSIONS """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + // WARN: Version information not provided by tool on CLI. + // Please update version string below when bumping container versions. + def VERSION = '2.9' + """ + touch ${prefix}.txt + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + combine_bracken_output: ${VERSION} + END_VERSIONS + """ } diff --git a/modules/nf-core/bracken/combinebrackenoutputs/meta.yml b/modules/nf-core/bracken/combinebrackenoutputs/meta.yml index 9ad53859..426d0099 100644 --- a/modules/nf-core/bracken/combinebrackenoutputs/meta.yml +++ b/modules/nf-core/bracken/combinebrackenoutputs/meta.yml @@ -1,7 +1,10 @@ name: "bracken_combinebrackenoutputs" description: Combine output of metagenomic samples analyzed by bracken. keywords: - - sort + - bracken + - metagenomics + - postprocessing + - reporting tools: - "bracken": description: Bracken (Bayesian Reestimation of Abundance with KrakEN) is a highly accurate statistical method that computes the abundance of species in DNA sequences from a metagenomics sample. @@ -10,7 +13,6 @@ tools: tool_dev_url: https://github.com/jenniferlu717/Bracken doi: "10.7717/peerj-cs.104" licence: ["GPL v3"] - input: - meta: type: map @@ -21,7 +23,6 @@ input: type: file description: List of output files from bracken pattern: "*" - output: - meta: type: map @@ -36,6 +37,7 @@ output: type: file description: Combined output in table format pattern: "*.txt" - authors: - "@jfy133" +maintainers: + - "@jfy133" diff --git a/modules/nf-core/bracken/combinebrackenoutputs/tests/main.nf.test b/modules/nf-core/bracken/combinebrackenoutputs/tests/main.nf.test new file mode 100644 index 00000000..e1504702 --- /dev/null +++ b/modules/nf-core/bracken/combinebrackenoutputs/tests/main.nf.test @@ -0,0 +1,103 @@ +nextflow_process { + + name "Test Process BRACKEN_COMBINEBRACKENOUTPUTS" + script "../main.nf" + process "BRACKEN_COMBINEBRACKENOUTPUTS" + + tag "modules" + tag "modules_nfcore" + tag "bracken" + tag "bracken/combinebrackenoutputs" + tag "bracken/bracken" + tag "kraken2/kraken2" + tag "untar" + + setup { + run ("UNTAR") { + script "../../../untar/main.nf" + process { + """ + input[0] = [[],file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/db/kraken2_bracken.tar.gz', checkIfExists: true)] + """ + } + } + + run("KRAKEN2_KRAKEN2") { + script "../../../kraken2/kraken2/main.nf" + process { + """ + input[0] = Channel.of( + [ + [id: 'test', single_end: true], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + [id: 'test2', single_end: true], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), + ] + ) + input[1] = UNTAR.out.untar.map{it[1]} + input[2] = false + input[3] = false + """ + } + } + + run("BRACKEN_BRACKEN") { + script "../../bracken/main.nf" + process { + """ + input[0] = KRAKEN2_KRAKEN2.out.report + input[1] = UNTAR.out.untar.map{it[1]} + """ + } + } + + } + + test("sarscov2 - fastq - fastq") { + + setup { + + } + + when { + process { + """ + input[0] = BRACKEN_BRACKEN.out.reports + .map{it[1]} + .collect() + .map{ [ [id: 'db'], it ] } + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + test("sarscov2 - fastq - stub") { + + options "-stub" + + when { + process { + """ + input[0] = BRACKEN_BRACKEN.out.reports + .map{it[1]} + .collect() + .map{ [ [id: 'db'], it ] } + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + +} diff --git a/modules/nf-core/bracken/combinebrackenoutputs/tests/main.nf.test.snap b/modules/nf-core/bracken/combinebrackenoutputs/tests/main.nf.test.snap new file mode 100644 index 00000000..4687042c --- /dev/null +++ b/modules/nf-core/bracken/combinebrackenoutputs/tests/main.nf.test.snap @@ -0,0 +1,68 @@ +{ + "sarscov2 - fastq - fastq": { + "content": [ + { + "0": [ + [ + { + "id": "db" + }, + "db.txt:md5,fb22ad13f9685d5bf5026542b9b2a6b8" + ] + ], + "1": [ + "versions.yml:md5,8edd746a7a248643d2cbf1b7e576fe38" + ], + "txt": [ + [ + { + "id": "db" + }, + "db.txt:md5,fb22ad13f9685d5bf5026542b9b2a6b8" + ] + ], + "versions": [ + "versions.yml:md5,8edd746a7a248643d2cbf1b7e576fe38" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.03.0" + }, + "timestamp": "2024-04-16T15:11:43.6682881" + }, + "sarscov2 - fastq - stub": { + "content": [ + { + "0": [ + [ + { + "id": "db" + }, + "db.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,8edd746a7a248643d2cbf1b7e576fe38" + ], + "txt": [ + [ + { + "id": "db" + }, + "db.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,8edd746a7a248643d2cbf1b7e576fe38" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.03.0" + }, + "timestamp": "2024-04-16T15:11:50.686596" + } +} \ No newline at end of file diff --git a/modules/nf-core/bracken/combinebrackenoutputs/tests/tags.yml b/modules/nf-core/bracken/combinebrackenoutputs/tests/tags.yml new file mode 100644 index 00000000..0564ea40 --- /dev/null +++ b/modules/nf-core/bracken/combinebrackenoutputs/tests/tags.yml @@ -0,0 +1,2 @@ +bracken/combinebrackenoutputs: + - "modules/nf-core/bracken/combinebrackenoutputs/**" diff --git a/modules/nf-core/cat/fastq/environment.yml b/modules/nf-core/cat/fastq/environment.yml new file mode 100644 index 00000000..c7eb9bd1 --- /dev/null +++ b/modules/nf-core/cat/fastq/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - conda-forge::coreutils=8.30 diff --git a/modules/nf-core/cat/fastq/main.nf b/modules/nf-core/cat/fastq/main.nf index 5021e6fc..b68e5f91 100644 --- a/modules/nf-core/cat/fastq/main.nf +++ b/modules/nf-core/cat/fastq/main.nf @@ -2,7 +2,7 @@ process CAT_FASTQ { tag "$meta.id" label 'process_single' - conda "conda-forge::sed=4.7" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/ubuntu:20.04' : 'nf-core/ubuntu:20.04' }" @@ -53,9 +53,9 @@ process CAT_FASTQ { def prefix = task.ext.prefix ?: "${meta.id}" def readList = reads instanceof List ? reads.collect{ it.toString() } : [reads.toString()] if (meta.single_end) { - if (readList.size > 1) { + if (readList.size >= 1) { """ - touch ${prefix}.merged.fastq.gz + echo '' | gzip > ${prefix}.merged.fastq.gz cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -64,10 +64,10 @@ process CAT_FASTQ { """ } } else { - if (readList.size > 2) { + if (readList.size >= 2) { """ - touch ${prefix}_1.merged.fastq.gz - touch ${prefix}_2.merged.fastq.gz + echo '' | gzip > ${prefix}_1.merged.fastq.gz + echo '' | gzip > ${prefix}_2.merged.fastq.gz cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -76,5 +76,4 @@ process CAT_FASTQ { """ } } - } diff --git a/modules/nf-core/cat/fastq/meta.yml b/modules/nf-core/cat/fastq/meta.yml index 8a39e309..db4ac3c7 100644 --- a/modules/nf-core/cat/fastq/meta.yml +++ b/modules/nf-core/cat/fastq/meta.yml @@ -34,7 +34,9 @@ output: type: file description: File containing software versions pattern: "versions.yml" - authors: - "@joseespinosa" - "@drpatelh" +maintainers: + - "@joseespinosa" + - "@drpatelh" diff --git a/modules/nf-core/cat/fastq/tests/main.nf.test b/modules/nf-core/cat/fastq/tests/main.nf.test new file mode 100644 index 00000000..f88a78b6 --- /dev/null +++ b/modules/nf-core/cat/fastq/tests/main.nf.test @@ -0,0 +1,248 @@ +// NOTE The version snaps may not be consistant +// https://github.com/nf-core/modules/pull/4087#issuecomment-1767948035 +nextflow_process { + + name "Test Process CAT_FASTQ" + script "../main.nf" + process "CAT_FASTQ" + tag "modules" + tag "modules_nfcore" + tag "cat" + tag "cat/fastq" + + test("test_cat_fastq_single_end") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true)] + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_cat_fastq_paired_end") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_2.fastq.gz', checkIfExists: true)] + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_cat_fastq_single_end_same_name") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true)] + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_cat_fastq_paired_end_same_name") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true)] + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_cat_fastq_single_end_single_file") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true)] + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_cat_fastq_single_end - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true)] + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_cat_fastq_paired_end - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_2.fastq.gz', checkIfExists: true)] + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_cat_fastq_single_end_same_name - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true)] + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_cat_fastq_paired_end_same_name - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true)] + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_cat_fastq_single_end_single_file - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true)] + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } +} diff --git a/modules/nf-core/cat/fastq/tests/main.nf.test.snap b/modules/nf-core/cat/fastq/tests/main.nf.test.snap new file mode 100644 index 00000000..aec119a9 --- /dev/null +++ b/modules/nf-core/cat/fastq/tests/main.nf.test.snap @@ -0,0 +1,376 @@ +{ + "test_cat_fastq_single_end": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,ee314a9bd568d06617171b0c85f508da" + ] + ], + "1": [ + "versions.yml:md5,d42d6e24d67004608495883e00bd501b" + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,ee314a9bd568d06617171b0c85f508da" + ] + ], + "versions": [ + "versions.yml:md5,d42d6e24d67004608495883e00bd501b" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-01-17T17:30:39.816981" + }, + "test_cat_fastq_single_end_same_name": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,3ad9406595fafec8172368f9cd0b6a22" + ] + ], + "1": [ + "versions.yml:md5,d42d6e24d67004608495883e00bd501b" + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,3ad9406595fafec8172368f9cd0b6a22" + ] + ], + "versions": [ + "versions.yml:md5,d42d6e24d67004608495883e00bd501b" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-01-17T17:32:35.229332" + }, + "test_cat_fastq_single_end_single_file": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,4161df271f9bfcd25d5845a1e220dbec" + ] + ], + "1": [ + "versions.yml:md5,d42d6e24d67004608495883e00bd501b" + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,4161df271f9bfcd25d5845a1e220dbec" + ] + ], + "versions": [ + "versions.yml:md5,d42d6e24d67004608495883e00bd501b" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-01-17T17:34:00.058829" + }, + "test_cat_fastq_paired_end_same_name": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.merged.fastq.gz:md5,3ad9406595fafec8172368f9cd0b6a22", + "test_2.merged.fastq.gz:md5,a52cab0b840c7178b0ea83df1fdbe8d5" + ] + ] + ], + "1": [ + "versions.yml:md5,d42d6e24d67004608495883e00bd501b" + ], + "reads": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.merged.fastq.gz:md5,3ad9406595fafec8172368f9cd0b6a22", + "test_2.merged.fastq.gz:md5,a52cab0b840c7178b0ea83df1fdbe8d5" + ] + ] + ], + "versions": [ + "versions.yml:md5,d42d6e24d67004608495883e00bd501b" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-01-17T17:33:33.031555" + }, + "test_cat_fastq_single_end - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "1": [ + "versions.yml:md5,d42d6e24d67004608495883e00bd501b" + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "versions": [ + "versions.yml:md5,d42d6e24d67004608495883e00bd501b" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T12:07:28.244999" + }, + "test_cat_fastq_paired_end_same_name - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940", + "test_2.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ] + ], + "1": [ + "versions.yml:md5,d42d6e24d67004608495883e00bd501b" + ], + "reads": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940", + "test_2.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ] + ], + "versions": [ + "versions.yml:md5,d42d6e24d67004608495883e00bd501b" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T12:07:57.070911" + }, + "test_cat_fastq_single_end_same_name - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "1": [ + "versions.yml:md5,d42d6e24d67004608495883e00bd501b" + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "versions": [ + "versions.yml:md5,d42d6e24d67004608495883e00bd501b" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T12:07:46.796254" + }, + "test_cat_fastq_paired_end": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.merged.fastq.gz:md5,3ad9406595fafec8172368f9cd0b6a22", + "test_2.merged.fastq.gz:md5,a52cab0b840c7178b0ea83df1fdbe8d5" + ] + ] + ], + "1": [ + "versions.yml:md5,d42d6e24d67004608495883e00bd501b" + ], + "reads": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.merged.fastq.gz:md5,3ad9406595fafec8172368f9cd0b6a22", + "test_2.merged.fastq.gz:md5,a52cab0b840c7178b0ea83df1fdbe8d5" + ] + ] + ], + "versions": [ + "versions.yml:md5,d42d6e24d67004608495883e00bd501b" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-01-17T17:32:02.270935" + }, + "test_cat_fastq_paired_end - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940", + "test_2.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ] + ], + "1": [ + "versions.yml:md5,d42d6e24d67004608495883e00bd501b" + ], + "reads": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940", + "test_2.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ] + ], + "versions": [ + "versions.yml:md5,d42d6e24d67004608495883e00bd501b" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T12:07:37.807553" + }, + "test_cat_fastq_single_end_single_file - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "1": [ + "versions.yml:md5,d42d6e24d67004608495883e00bd501b" + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "versions": [ + "versions.yml:md5,d42d6e24d67004608495883e00bd501b" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T12:14:51.861264" + } +} \ No newline at end of file diff --git a/modules/nf-core/cat/fastq/tests/tags.yml b/modules/nf-core/cat/fastq/tests/tags.yml new file mode 100644 index 00000000..6ac43614 --- /dev/null +++ b/modules/nf-core/cat/fastq/tests/tags.yml @@ -0,0 +1,2 @@ +cat/fastq: + - modules/nf-core/cat/fastq/** diff --git a/modules/nf-core/centrifuge/centrifuge/environment.yml b/modules/nf-core/centrifuge/centrifuge/environment.yml index cf34dc0e..42592891 100644 --- a/modules/nf-core/centrifuge/centrifuge/environment.yml +++ b/modules/nf-core/centrifuge/centrifuge/environment.yml @@ -1,7 +1,5 @@ -name: centrifuge_centrifuge channels: - conda-forge - bioconda - - defaults dependencies: - bioconda::centrifuge=1.0.4.1 diff --git a/modules/nf-core/centrifuge/centrifuge/tests/main.nf.test b/modules/nf-core/centrifuge/centrifuge/tests/main.nf.test index d83b522a..f2713608 100644 --- a/modules/nf-core/centrifuge/centrifuge/tests/main.nf.test +++ b/modules/nf-core/centrifuge/centrifuge/tests/main.nf.test @@ -42,10 +42,10 @@ nextflow_process { file(process.out.results[0][1]).name, file(process.out.fastq_mapped[0][1][0]).name, file(process.out.fastq_unmapped[0][1][0]).name, + process.out.versions ).match() } ) } - } test("sarscov2_fastq_pe") { @@ -56,8 +56,8 @@ nextflow_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']['test_2_fastq_gz'], checkIfExists: true) ] + ] input[1] = UNTAR.out.untar.map{ it[1] } input[2] = true input[3] = true @@ -73,10 +73,10 @@ nextflow_process { file(process.out.results[0][1]).name, file(process.out.fastq_mapped[0][1][0]).name, file(process.out.fastq_unmapped[0][1][0]).name, + process.out.versions ).match() } ) } - } test("sarscov2_fastq_se_stub") { @@ -100,7 +100,5 @@ nextflow_process { { assert snapshot(process.out).match() } ) } - } - } diff --git a/modules/nf-core/centrifuge/centrifuge/tests/main.nf.test.snap b/modules/nf-core/centrifuge/centrifuge/tests/main.nf.test.snap index f8a2ef7b..a981e517 100644 --- a/modules/nf-core/centrifuge/centrifuge/tests/main.nf.test.snap +++ b/modules/nf-core/centrifuge/centrifuge/tests/main.nf.test.snap @@ -92,34 +92,40 @@ ], "meta": { "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nextflow": "24.04.2" }, - "timestamp": "2024-02-02T07:47:36.886757827" + "timestamp": "2024-07-09T10:36:42.919054" }, "sarscov2_fastq_se": { "content": [ "test.report.txt", "test.results.txt", "", - "" + "", + [ + "versions.yml:md5,1ce028d9f968eca6df31586fe3b77c84" + ] ], "meta": { "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nextflow": "24.04.2" }, - "timestamp": "2024-02-02T08:22:31.470316024" + "timestamp": "2024-07-09T10:36:23.087465" }, "sarscov2_fastq_pe": { "content": [ "test.report.txt", "test.results.txt", "test.mapped.fastq.1.gz", - "test.unmapped.fastq.1.gz" + "test.unmapped.fastq.1.gz", + [ + "versions.yml:md5,1ce028d9f968eca6df31586fe3b77c84" + ] ], "meta": { "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nextflow": "24.04.2" }, - "timestamp": "2024-02-02T08:22:48.866073154" + "timestamp": "2024-07-09T10:36:33.471335" } } \ No newline at end of file diff --git a/modules/nf-core/centrifuge/kreport/environment.yml b/modules/nf-core/centrifuge/kreport/environment.yml index 5c8fb451..42592891 100644 --- a/modules/nf-core/centrifuge/kreport/environment.yml +++ b/modules/nf-core/centrifuge/kreport/environment.yml @@ -1,7 +1,5 @@ -name: centrifuge_kreport channels: - conda-forge - bioconda - - defaults dependencies: - bioconda::centrifuge=1.0.4.1 diff --git a/modules/nf-core/centrifuge/kreport/tests/main.nf.test b/modules/nf-core/centrifuge/kreport/tests/main.nf.test index 6347bd7c..6d4bc6b1 100644 --- a/modules/nf-core/centrifuge/kreport/tests/main.nf.test +++ b/modules/nf-core/centrifuge/kreport/tests/main.nf.test @@ -50,8 +50,9 @@ nextflow_process { { assert process.success }, { assert snapshot( file(process.out.kreport[0][1]).name, + process.out.versions ).match() } - ) + ) } } @@ -75,7 +76,5 @@ nextflow_process { { assert snapshot(process.out).match() } ) } - } - } diff --git a/modules/nf-core/centrifuge/kreport/tests/main.nf.test.snap b/modules/nf-core/centrifuge/kreport/tests/main.nf.test.snap index 4e0aaa79..3d638acd 100644 --- a/modules/nf-core/centrifuge/kreport/tests/main.nf.test.snap +++ b/modules/nf-core/centrifuge/kreport/tests/main.nf.test.snap @@ -30,18 +30,21 @@ ], "meta": { "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nextflow": "24.04.2" }, - "timestamp": "2024-02-02T06:18:36.794405448" + "timestamp": "2024-07-09T10:37:05.883784" }, "sarscov2_fastq_se": { "content": [ - "test.txt" + "test.txt", + [ + "versions.yml:md5,43c766a19f2edf7e05d1a2a0b1816b13" + ] ], "meta": { "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nextflow": "24.04.2" }, - "timestamp": "2024-02-02T06:28:20.461891873" + "timestamp": "2024-07-09T10:36:53.971559" } } \ No newline at end of file diff --git a/modules/nf-core/diamond/blastx/environment.yml b/modules/nf-core/diamond/blastx/environment.yml new file mode 100644 index 00000000..950c3c5c --- /dev/null +++ b/modules/nf-core/diamond/blastx/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::diamond=2.1.8 diff --git a/modules/nf-core/diamond/blastx/main.nf b/modules/nf-core/diamond/blastx/main.nf index e08fb0d9..bf3f623c 100644 --- a/modules/nf-core/diamond/blastx/main.nf +++ b/modules/nf-core/diamond/blastx/main.nf @@ -1,15 +1,15 @@ process DIAMOND_BLASTX { tag "$meta.id" - label 'process_medium' + label 'process_high' - conda "bioconda::diamond=2.0.15" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/diamond:2.0.15--hb97b32f_0' : - 'biocontainers/diamond:2.0.15--hb97b32f_0' }" + 'https://depot.galaxyproject.org/singularity/diamond:2.1.8--h43eeafb_0' : + 'biocontainers/diamond:2.1.8--h43eeafb_0' }" input: - tuple val(meta), path(fasta) - path db + tuple val(meta) , path(fasta) + tuple val(meta2), path(db) val out_ext val blast_columns @@ -21,8 +21,8 @@ process DIAMOND_BLASTX { tuple val(meta), path('*.sam') , optional: true, emit: sam tuple val(meta), path('*.tsv') , optional: true, emit: tsv tuple val(meta), path('*.paf') , optional: true, emit: paf - tuple val(meta), path("*.log") , emit: log - path "versions.yml" , emit: versions + tuple val(meta), path("*.log") , emit: log + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when @@ -30,6 +30,8 @@ process DIAMOND_BLASTX { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" + def is_compressed = fasta.getExtension() == "gz" ? true : false + def fasta_name = is_compressed ? fasta.getBaseName() : fasta def columns = blast_columns ? "${blast_columns}" : '' switch ( out_ext ) { case "blast": outfmt = 0; break @@ -46,15 +48,19 @@ process DIAMOND_BLASTX { break } """ + if [ "${is_compressed}" == "true" ]; then + gzip -c -d ${fasta} > ${fasta_name} + fi + DB=`find -L ./ -name "*.dmnd" | sed 's/\\.dmnd\$//'` diamond \\ blastx \\ - --threads $task.cpus \\ + --threads ${task.cpus} \\ --db \$DB \\ - --query $fasta \\ + --query ${fasta_name} \\ --outfmt ${outfmt} ${columns} \\ - $args \\ + ${args} \\ --out ${prefix}.${out_ext} \\ --log @@ -65,4 +71,32 @@ process DIAMOND_BLASTX { diamond: \$(diamond --version 2>&1 | tail -n 1 | sed 's/^diamond version //') END_VERSIONS """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + switch ( out_ext ) { + case "blast": outfmt = 0; break + case "xml": outfmt = 5; break + case "txt": outfmt = 6; break + case "daa": outfmt = 100; break + case "sam": outfmt = 101; break + case "tsv": outfmt = 102; break + case "paf": outfmt = 103; break + default: + outfmt = '6'; + out_ext = 'txt'; + log.warn("Unknown output file format provided (${out_ext}): selecting DIAMOND default of tabular BLAST output (txt)"); + break + } + + """ + touch ${prefix}.${out_ext} + touch ${prefix}.log + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + diamond: \$(diamond --version 2>&1 | tail -n 1 | sed 's/^diamond version //') + END_VERSIONS + """ } diff --git a/modules/nf-core/diamond/blastx/meta.yml b/modules/nf-core/diamond/blastx/meta.yml index a2a6013d..17106548 100644 --- a/modules/nf-core/diamond/blastx/meta.yml +++ b/modules/nf-core/diamond/blastx/meta.yml @@ -13,7 +13,6 @@ tools: tool_dev_url: https://github.com/bbuchfink/diamond doi: "10.1038/s41592-021-01101-x" licence: ["GPL v3.0"] - input: - meta: type: map @@ -23,11 +22,16 @@ input: - fasta: type: file description: Input fasta file containing query sequences - pattern: "*.{fa,fasta}" + pattern: "*.{fa,fasta,fa.gz,fasta.gz}" + - meta2: + type: map + description: | + Groovy Map containing db information + e.g. [ id:'test2', single_end:false ] - db: - type: directory - description: Directory containing the nucelotide blast database - pattern: "*" + type: file + description: File of the indexed DIAMOND database + pattern: "*.dmnd" - out_ext: type: string description: | @@ -36,8 +40,18 @@ input: `txt` corresponds to to BLAST tabular format. `tsv` corresponds to taxonomic classification format. pattern: "blast|xml|txt|daa|sam|tsv|paf" - + - blast_columns: + type: string + description: | + Optional space separated list of DIAMOND tabular BLAST output keywords + used for in conjunction with the 'txt' out_ext option (--outfmt 6). Options: + qseqid sseqid pident length mismatch gapopen qstart qend sstart send evalue bitscore output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] - blast: type: file description: File containing blastp hits @@ -66,16 +80,20 @@ output: type: file description: File containing aligned reads in pairwise mapping format format pattern: "*.{paf}" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" - log: type: file description: Log file containing stdout information pattern: "*.{log}" - + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@spficklin" - "@jfy133" - "@mjamy" +maintainers: + - "@spficklin" + - "@jfy133" + - "@mjamy" + - "@vagkaratzas" diff --git a/modules/nf-core/diamond/blastx/tests/main.nf.test b/modules/nf-core/diamond/blastx/tests/main.nf.test new file mode 100644 index 00000000..b8757403 --- /dev/null +++ b/modules/nf-core/diamond/blastx/tests/main.nf.test @@ -0,0 +1,82 @@ +nextflow_process { + + name "Test Process DIAMOND_BLASTX" + script "../main.nf" + process "DIAMOND_BLASTX" + tag "modules" + tag "modules_nfcore" + tag "diamond" + tag "diamond/makedb" + tag "diamond/blastx" + + setup { + run("DIAMOND_MAKEDB") { + script "../../makedb/main.nf" + process { + """ + input[0] = [ [id:'test2'], [ file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/proteome.fasta', checkIfExists: true) ] ] + input[1] = [] + input[2] = [] + input[3] = [] + """ + } + } + } + + test("Should search for transcriptome hits against a DIAMOND db and return the default tab separated output file of hits") { + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = [ [id:'test'], file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/transcriptome.fasta', checkIfExists: true) ] + input[1] = DIAMOND_MAKEDB.out.db + input[2] = 'tfdfdt' // Nonsense file extension to check default case. + input[3] = 'qseqid qlen' + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert path(process.out.log.get(0).get(1)).readLines().contains("11 queries aligned.") }, + { assert snapshot( + process.out.txt, + process.out.versions + ).match() + } + ) + } + + } + + test("Should search for transcriptome hits against a DIAMOND db and return the daa format output file of hits") { + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = [ [id:'test'], file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/transcriptome.fasta', checkIfExists: true) ] + input[1] = DIAMOND_MAKEDB.out.db + input[2] = 'daa' + input[3] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert process.out.daa }, + { assert path(process.out.log.get(0).get(1)).readLines().contains("11 queries aligned.") }, + { assert snapshot(process.out.versions).match() } + ) + } + + } +} diff --git a/modules/nf-core/diamond/blastx/tests/main.nf.test.snap b/modules/nf-core/diamond/blastx/tests/main.nf.test.snap new file mode 100644 index 00000000..8a128c99 --- /dev/null +++ b/modules/nf-core/diamond/blastx/tests/main.nf.test.snap @@ -0,0 +1,34 @@ +{ + "Should search for transcriptome hits against a DIAMOND db and return the daa format output file of hits": { + "content": [ + [ + "versions.yml:md5,733d944fb173eaf1d1cdf280cd1b3b9c" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-29T14:49:26.843747" + }, + "Should search for transcriptome hits against a DIAMOND db and return the default tab separated output file of hits": { + "content": [ + [ + [ + { + "id": "test" + }, + "test.txt:md5,33dc682dabfa44c7089abbc8fe8b84e4" + ] + ], + [ + "versions.yml:md5,733d944fb173eaf1d1cdf280cd1b3b9c" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-29T14:49:20.769093" + } +} \ No newline at end of file diff --git a/modules/nf-core/diamond/blastx/tests/tags.yml b/modules/nf-core/diamond/blastx/tests/tags.yml new file mode 100644 index 00000000..a0e2964b --- /dev/null +++ b/modules/nf-core/diamond/blastx/tests/tags.yml @@ -0,0 +1,3 @@ +diamond/blastx: + - modules/nf-core/diamond/blastx/** + - modules/nf-core/diamond/makedb/** diff --git a/modules/nf-core/falco/environment.yml b/modules/nf-core/falco/environment.yml index eeedb5b7..c48809cc 100644 --- a/modules/nf-core/falco/environment.yml +++ b/modules/nf-core/falco/environment.yml @@ -1,7 +1,5 @@ -name: falco channels: - conda-forge - bioconda - - defaults dependencies: - bioconda::falco=1.2.1 diff --git a/modules/nf-core/falco/falco.diff b/modules/nf-core/falco/falco.diff deleted file mode 100644 index 4c726b9a..00000000 --- a/modules/nf-core/falco/falco.diff +++ /dev/null @@ -1,16 +0,0 @@ -Changes in module 'nf-core/falco' ---- modules/nf-core/falco/main.nf -+++ modules/nf-core/falco/main.nf -@@ -33,7 +33,9 @@ - """ - } else { - """ -- falco $args --threads $task.cpus ${reads} -+ [ ! -f ${prefix}_1.fastq.gz ] && ln -s ${reads[0]} ${prefix}_1.fastq.gz -+ [ ! -f ${prefix}_2.fastq.gz ] && ln -s ${reads[1]} ${prefix}_2.fastq.gz -+ falco $args --threads $task.cpus ${prefix}_1.fastq.gz ${prefix}_2.fastq.gz - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - -************************************************************ diff --git a/modules/nf-core/fastp/environment.yml b/modules/nf-core/fastp/environment.yml new file mode 100644 index 00000000..26d4aca5 --- /dev/null +++ b/modules/nf-core/fastp/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::fastp=0.23.4 diff --git a/modules/nf-core/fastp/main.nf b/modules/nf-core/fastp/main.nf index 831b7f12..e1b9f565 100644 --- a/modules/nf-core/fastp/main.nf +++ b/modules/nf-core/fastp/main.nf @@ -2,7 +2,7 @@ process FASTP { tag "$meta.id" label 'process_medium' - conda "bioconda::fastp=0.23.4" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/fastp:0.23.4--h5f740d0_0' : 'biocontainers/fastp:0.23.4--h5f740d0_0' }" @@ -10,6 +10,7 @@ process FASTP { input: tuple val(meta), path(reads) path adapter_fasta + val discard_trimmed_pass val save_trimmed_fail val save_merged @@ -18,9 +19,9 @@ process FASTP { tuple val(meta), path('*.json') , emit: json tuple val(meta), path('*.html') , emit: html tuple val(meta), path('*.log') , emit: log - path "versions.yml" , emit: versions tuple val(meta), path('*.fail.fastq.gz') , optional:true, emit: reads_fail tuple val(meta), path('*.merged.fastq.gz'), optional:true, emit: reads_merged + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when @@ -29,7 +30,9 @@ process FASTP { def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" def adapter_list = adapter_fasta ? "--adapter_fasta ${adapter_fasta}" : "" - def fail_fastq = save_trimmed_fail && meta.single_end ? "--failed_out ${prefix}.fail.fastq.gz" : save_trimmed_fail && !meta.single_end ? "--unpaired1 ${prefix}_1.fail.fastq.gz --unpaired2 ${prefix}_2.fail.fastq.gz" : '' + def fail_fastq = save_trimmed_fail && meta.single_end ? "--failed_out ${prefix}.fail.fastq.gz" : save_trimmed_fail && !meta.single_end ? "--failed_out ${prefix}.paired.fail.fastq.gz --unpaired1 ${prefix}_1.fail.fastq.gz --unpaired2 ${prefix}_2.fail.fastq.gz" : '' + def out_fq1 = discard_trimmed_pass ?: ( meta.single_end ? "--out1 ${prefix}.fastp.fastq.gz" : "--out1 ${prefix}_1.fastp.fastq.gz" ) + def out_fq2 = discard_trimmed_pass ?: "--out2 ${prefix}_2.fastp.fastq.gz" // Added soft-links to original fastqs for consistent naming in MultiQC // Use single ended for interleaved. Add --interleaved_in in config. if ( task.ext.args?.contains('--interleaved_in') ) { @@ -45,7 +48,7 @@ process FASTP { $adapter_list \\ $fail_fastq \\ $args \\ - 2> ${prefix}.fastp.log \\ + 2> >(tee ${prefix}.fastp.log >&2) \\ | gzip -c > ${prefix}.fastp.fastq.gz cat <<-END_VERSIONS > versions.yml @@ -59,14 +62,14 @@ process FASTP { fastp \\ --in1 ${prefix}.fastq.gz \\ - --out1 ${prefix}.fastp.fastq.gz \\ + $out_fq1 \\ --thread $task.cpus \\ --json ${prefix}.fastp.json \\ --html ${prefix}.fastp.html \\ $adapter_list \\ $fail_fastq \\ $args \\ - 2> ${prefix}.fastp.log + 2> >(tee ${prefix}.fastp.log >&2) cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -81,8 +84,8 @@ process FASTP { fastp \\ --in1 ${prefix}_1.fastq.gz \\ --in2 ${prefix}_2.fastq.gz \\ - --out1 ${prefix}_1.fastp.fastq.gz \\ - --out2 ${prefix}_2.fastp.fastq.gz \\ + $out_fq1 \\ + $out_fq2 \\ --json ${prefix}.fastp.json \\ --html ${prefix}.fastp.html \\ $adapter_list \\ @@ -91,7 +94,7 @@ process FASTP { --thread $task.cpus \\ --detect_adapter_for_pe \\ $args \\ - 2> ${prefix}.fastp.log + 2> >(tee ${prefix}.fastp.log >&2) cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -99,4 +102,24 @@ process FASTP { END_VERSIONS """ } + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + def is_single_output = task.ext.args?.contains('--interleaved_in') || meta.single_end + def touch_reads = (discard_trimmed_pass) ? "" : (is_single_output) ? "echo '' | gzip > ${prefix}.fastp.fastq.gz" : "echo '' | gzip > ${prefix}_1.fastp.fastq.gz ; echo '' | gzip > ${prefix}_2.fastp.fastq.gz" + def touch_merged = (!is_single_output && save_merged) ? "echo '' | gzip > ${prefix}.merged.fastq.gz" : "" + def touch_fail_fastq = (!save_trimmed_fail) ? "" : meta.single_end ? "echo '' | gzip > ${prefix}.fail.fastq.gz" : "echo '' | gzip > ${prefix}.paired.fail.fastq.gz ; echo '' | gzip > ${prefix}_1.fail.fastq.gz ; echo '' | gzip > ${prefix}_2.fail.fastq.gz" + """ + $touch_reads + $touch_fail_fastq + $touch_merged + touch "${prefix}.fastp.json" + touch "${prefix}.fastp.html" + touch "${prefix}.fastp.log" + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + fastp: \$(fastp --version 2>&1 | sed -e "s/fastp //g") + END_VERSIONS + """ } diff --git a/modules/nf-core/fastp/meta.yml b/modules/nf-core/fastp/meta.yml index 197ea7ca..8dfecc18 100644 --- a/modules/nf-core/fastp/meta.yml +++ b/modules/nf-core/fastp/meta.yml @@ -27,13 +27,16 @@ input: type: file description: File in FASTA format containing possible adapters to remove. pattern: "*.{fasta,fna,fas,fa}" + - discard_trimmed_pass: + type: boolean + description: Specify true to not write any reads that pass trimming thresholds. | + This can be used to use fastp for the output report only. - save_trimmed_fail: type: boolean description: Specify true to save files that failed to pass trimming thresholds ending in `*.fail.fastq.gz` - save_merged: type: boolean - description: Specify true to save all merged reads to the a file ending in `*.merged.fastq.gz` - + description: Specify true to save all merged reads to a file ending in `*.merged.fastq.gz` output: - meta: type: map @@ -71,3 +74,6 @@ output: authors: - "@drpatelh" - "@kevinmenden" +maintainers: + - "@drpatelh" + - "@kevinmenden" diff --git a/modules/nf-core/fastp/tests/main.nf.test b/modules/nf-core/fastp/tests/main.nf.test new file mode 100644 index 00000000..30dbb8aa --- /dev/null +++ b/modules/nf-core/fastp/tests/main.nf.test @@ -0,0 +1,576 @@ +nextflow_process { + + name "Test Process FASTP" + script "../main.nf" + process "FASTP" + tag "modules" + tag "modules_nfcore" + tag "fastp" + + test("test_fastp_single_end") { + + when { + + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] + ]) + input[1] = [] + input[2] = false + input[3] = false + input[4] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert path(process.out.html.get(0).get(1)).getText().contains("single end (151 cycles)") }, + { assert path(process.out.log.get(0).get(1)).getText().contains("reads passed filter: 99") }, + { assert snapshot( + process.out.json, + process.out.reads, + process.out.reads_fail, + process.out.reads_merged, + process.out.versions).match() } + ) + } + } + + test("test_fastp_paired_end") { + + when { + + process { + """ + adapter_fasta = [] + save_trimmed_pass = true + save_trimmed_fail = false + save_merged = false + + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] + ]) + input[1] = [] + input[2] = false + input[3] = false + input[4] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert path(process.out.html.get(0).get(1)).getText().contains("The input has little adapter percentage (~0.000000%), probably it's trimmed before.") }, + { assert path(process.out.log.get(0).get(1)).getText().contains("Q30 bases: 12281(88.3716%)") }, + { assert snapshot( + process.out.json, + process.out.reads, + process.out.reads_fail, + process.out.reads_merged, + process.out.versions).match() } + ) + } + } + + test("fastp test_fastp_interleaved") { + + config './nextflow.interleaved.config' + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_interleaved.fastq.gz', checkIfExists: true) ] + ]) + input[1] = [] + input[2] = false + input[3] = false + input[4] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert path(process.out.html.get(0).get(1)).getText().contains("paired end (151 cycles + 151 cycles)") }, + { assert path(process.out.log.get(0).get(1)).getText().contains("reads passed filter: 162") }, + { assert process.out.reads_fail == [] }, + { assert process.out.reads_merged == [] }, + { assert snapshot( + process.out.reads, + process.out.json, + process.out.versions).match() } + ) + } + } + + test("test_fastp_single_end_trim_fail") { + + when { + + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] + ]) + input[1] = [] + input[2] = false + input[3] = true + input[4] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert path(process.out.html.get(0).get(1)).getText().contains("single end (151 cycles)") }, + { assert path(process.out.log.get(0).get(1)).getText().contains("reads passed filter: 99") }, + { assert snapshot( + process.out.json, + process.out.reads, + process.out.reads_fail, + process.out.reads_merged, + process.out.versions).match() } + ) + } + } + + test("test_fastp_paired_end_trim_fail") { + + config './nextflow.save_failed.config' + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true)] + ]) + input[1] = [] + input[2] = false + input[3] = true + input[4] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert path(process.out.html.get(0).get(1)).getText().contains("The input has little adapter percentage (~0.000000%), probably it's trimmed before.") }, + { assert path(process.out.log.get(0).get(1)).getText().contains("reads passed filter: 162") }, + { assert snapshot( + process.out.reads, + process.out.reads_fail, + process.out.reads_merged, + process.out.json, + process.out.versions).match() } + ) + } + } + + test("test_fastp_paired_end_merged") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] + ]) + input[1] = [] + input[2] = false + input[3] = false + input[4] = true + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert path(process.out.html.get(0).get(1)).getText().contains("The input has little adapter percentage (~0.000000%), probably it's trimmed before.") }, + { assert path(process.out.log.get(0).get(1)).getText().contains("total reads: 75") }, + { assert snapshot( + process.out.json, + process.out.reads, + process.out.reads_fail, + process.out.reads_merged, + process.out.versions).match() }, + ) + } + } + + test("test_fastp_paired_end_merged_adapterlist") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] + ]) + input[1] = Channel.of([ file(params.modules_testdata_base_path + 'delete_me/fastp/adapters.fasta', checkIfExists: true) ]) + input[2] = false + input[3] = false + input[4] = true + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert path(process.out.html.get(0).get(1)).getText().contains("
") }, + { assert path(process.out.log.get(0).get(1)).getText().contains("total bases: 13683") }, + { assert snapshot( + process.out.json, + process.out.reads, + process.out.reads_fail, + process.out.reads_merged, + process.out.versions).match() } + ) + } + } + + test("test_fastp_single_end_qc_only") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] + ]) + input[1] = [] + input[2] = true + input[3] = false + input[4] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert path(process.out.html.get(0).get(1)).getText().contains("single end (151 cycles)") }, + { assert path(process.out.log.get(0).get(1)).getText().contains("reads passed filter: 99") }, + { assert snapshot( + process.out.json, + process.out.reads, + process.out.reads, + process.out.reads_fail, + process.out.reads_fail, + process.out.reads_merged, + process.out.reads_merged, + process.out.versions).match() } + ) + } + } + + test("test_fastp_paired_end_qc_only") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] + ]) + input[1] = [] + input[2] = true + input[3] = false + input[4] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert path(process.out.html.get(0).get(1)).getText().contains("The input has little adapter percentage (~0.000000%), probably it's trimmed before.") }, + { assert path(process.out.log.get(0).get(1)).getText().contains("Q30 bases: 12281(88.3716%)") }, + { assert snapshot( + process.out.json, + process.out.reads, + process.out.reads, + process.out.reads_fail, + process.out.reads_fail, + process.out.reads_merged, + process.out.reads_merged, + process.out.versions).match() } + ) + } + } + + test("test_fastp_single_end - stub") { + + options "-stub" + + when { + + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] + ]) + input[1] = [] + input[2] = false + input[3] = false + input[4] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_fastp_paired_end - stub") { + + options "-stub" + + when { + + process { + """ + adapter_fasta = [] + save_trimmed_pass = true + save_trimmed_fail = false + save_merged = false + + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] + ]) + input[1] = [] + input[2] = false + input[3] = false + input[4] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("fastp - stub test_fastp_interleaved") { + + options "-stub" + + config './nextflow.interleaved.config' + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_interleaved.fastq.gz', checkIfExists: true) ] + ]) + input[1] = [] + input[2] = false + input[3] = false + input[4] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_fastp_single_end_trim_fail - stub") { + + options "-stub" + + when { + + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] + ]) + input[1] = [] + input[2] = false + input[3] = true + input[4] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_fastp_paired_end_trim_fail - stub") { + + options "-stub" + + config './nextflow.save_failed.config' + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true)] + ]) + input[1] = [] + input[2] = false + input[3] = true + input[4] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_fastp_paired_end_merged - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] + ]) + input[1] = [] + input[2] = false + input[3] = false + input[4] = true + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_fastp_paired_end_merged_adapterlist - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] + ]) + input[1] = Channel.of([ file(params.modules_testdata_base_path + 'delete_me/fastp/adapters.fasta', checkIfExists: true) ]) + input[2] = false + input[3] = false + input[4] = true + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_fastp_single_end_qc_only - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] + ]) + input[1] = [] + input[2] = true + input[3] = false + input[4] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test_fastp_paired_end_qc_only - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] + ]) + input[1] = [] + input[2] = true + input[3] = false + input[4] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } +} \ No newline at end of file diff --git a/modules/nf-core/fastp/tests/main.nf.test.snap b/modules/nf-core/fastp/tests/main.nf.test.snap new file mode 100644 index 00000000..54be7e45 --- /dev/null +++ b/modules/nf-core/fastp/tests/main.nf.test.snap @@ -0,0 +1,1331 @@ +{ + "test_fastp_single_end_qc_only - stub": { + "content": [ + { + "0": [ + + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "3": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "4": [ + + ], + "5": [ + + ], + "6": [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ], + "html": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "json": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "log": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "reads": [ + + ], + "reads_fail": [ + + ], + "reads_merged": [ + + ], + "versions": [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T14:31:10.841098" + }, + "test_fastp_paired_end": { + "content": [ + [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.json:md5,1e0f8e27e71728e2b63fc64086be95cd" + ] + ], + [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.fastp.fastq.gz:md5,67b2bbae47f073e05a97a9c2edce23c7", + "test_2.fastp.fastq.gz:md5,25cbdca08e2083dbd4f0502de6b62f39" + ] + ] + ], + [ + + ], + [ + + ], + [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T13:43:28.665779" + }, + "test_fastp_paired_end_merged_adapterlist": { + "content": [ + [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.json:md5,5914ca3f21ce162123a824e33e8564f6" + ] + ], + [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.fastp.fastq.gz:md5,54b726a55e992a869fd3fa778afe1672", + "test_2.fastp.fastq.gz:md5,29d3b33b869f7b63417b8ff07bb128ba" + ] + ] + ], + [ + + ], + [ + [ + { + "id": "test", + "single_end": false + }, + "test.merged.fastq.gz:md5,c873bb1ab3fa859dcc47306465e749d5" + ] + ], + [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T13:44:18.210375" + }, + "test_fastp_single_end_qc_only": { + "content": [ + [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.json:md5,5cc5f01e449309e0e689ed6f51a2294a" + ] + ], + [ + + ], + [ + + ], + [ + + ], + [ + + ], + [ + + ], + [ + + ], + [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T13:44:27.380974" + }, + "test_fastp_paired_end_trim_fail": { + "content": [ + [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.fastp.fastq.gz:md5,6ff32a64c5188b9a9192be1398c262c7", + "test_2.fastp.fastq.gz:md5,db0cb7c9977e94ac2b4b446ebd017a8a" + ] + ] + ], + [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test.paired.fail.fastq.gz:md5,409b687c734cedd7a1fec14d316e1366", + "test_1.fail.fastq.gz:md5,4f273cf3159c13f79e8ffae12f5661f6", + "test_2.fail.fastq.gz:md5,f97b9edefb5649aab661fbc9e71fc995" + ] + ] + ], + [ + + ], + [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.json:md5,4c3268ddb50ea5b33125984776aa3519" + ] + ], + [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T13:43:58.749589" + }, + "fastp - stub test_fastp_interleaved": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "3": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "4": [ + + ], + "5": [ + + ], + "6": [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ], + "html": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "json": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "log": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "reads_fail": [ + + ], + "reads_merged": [ + + ], + "versions": [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T13:50:00.270029" + }, + "test_fastp_single_end - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "3": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "4": [ + + ], + "5": [ + + ], + "6": [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ], + "html": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "json": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "log": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "reads_fail": [ + + ], + "reads_merged": [ + + ], + "versions": [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T13:49:42.502789" + }, + "test_fastp_paired_end_merged_adapterlist - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.fastp.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940", + "test_2.fastp.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "3": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "4": [ + + ], + "5": [ + [ + { + "id": "test", + "single_end": false + }, + "test.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "6": [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "json": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "log": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "reads": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.fastp.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940", + "test_2.fastp.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ] + ], + "reads_fail": [ + + ], + "reads_merged": [ + [ + { + "id": "test", + "single_end": false + }, + "test.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "versions": [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T13:54:53.458252" + }, + "test_fastp_paired_end_merged - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.fastp.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940", + "test_2.fastp.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "3": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "4": [ + + ], + "5": [ + [ + { + "id": "test", + "single_end": false + }, + "test.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "6": [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "json": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "log": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "reads": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.fastp.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940", + "test_2.fastp.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ] + ], + "reads_fail": [ + + ], + "reads_merged": [ + [ + { + "id": "test", + "single_end": false + }, + "test.merged.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "versions": [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T13:50:27.689379" + }, + "test_fastp_paired_end_merged": { + "content": [ + [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.json:md5,b712fd68ed0322f4bec49ff2a5237fcc" + ] + ], + [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.fastp.fastq.gz:md5,54b726a55e992a869fd3fa778afe1672", + "test_2.fastp.fastq.gz:md5,29d3b33b869f7b63417b8ff07bb128ba" + ] + ] + ], + [ + + ], + [ + [ + { + "id": "test", + "single_end": false + }, + "test.merged.fastq.gz:md5,c873bb1ab3fa859dcc47306465e749d5" + ] + ], + [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T13:44:08.68476" + }, + "test_fastp_paired_end - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.fastp.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940", + "test_2.fastp.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "3": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "4": [ + + ], + "5": [ + + ], + "6": [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "json": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "log": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "reads": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.fastp.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940", + "test_2.fastp.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ] + ], + "reads_fail": [ + + ], + "reads_merged": [ + + ], + "versions": [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T13:49:51.679221" + }, + "test_fastp_single_end": { + "content": [ + [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.json:md5,c852d7a6dba5819e4ac8d9673bedcacc" + ] + ], + [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.fastq.gz:md5,67b2bbae47f073e05a97a9c2edce23c7" + ] + ], + [ + + ], + [ + + ], + [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T13:43:18.834322" + }, + "test_fastp_single_end_trim_fail - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "3": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "4": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fail.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "5": [ + + ], + "6": [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ], + "html": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "json": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "log": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "reads_fail": [ + [ + { + "id": "test", + "single_end": true + }, + "test.fail.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "reads_merged": [ + + ], + "versions": [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T14:05:36.898142" + }, + "test_fastp_paired_end_trim_fail - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.fastp.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940", + "test_2.fastp.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "3": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "4": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test.paired.fail.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940", + "test_1.fail.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940", + "test_2.fail.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ] + ], + "5": [ + + ], + "6": [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "json": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "log": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "reads": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.fastp.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940", + "test_2.fastp.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ] + ], + "reads_fail": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test.paired.fail.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940", + "test_1.fail.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940", + "test_2.fail.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ] + ], + "reads_merged": [ + + ], + "versions": [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T14:05:49.212847" + }, + "fastp test_fastp_interleaved": { + "content": [ + [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.fastq.gz:md5,217d62dc13a23e92513a1bd8e1bcea39" + ] + ], + [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.json:md5,b24e0624df5cc0b11cd5ba21b726fb22" + ] + ], + [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T13:43:38.910832" + }, + "test_fastp_single_end_trim_fail": { + "content": [ + [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.json:md5,9a7ee180f000e8d00c7fb67f06293eb5" + ] + ], + [ + [ + { + "id": "test", + "single_end": true + }, + "test.fastp.fastq.gz:md5,67b2bbae47f073e05a97a9c2edce23c7" + ] + ], + [ + [ + { + "id": "test", + "single_end": true + }, + "test.fail.fastq.gz:md5,3e4aaadb66a5b8fc9b881bf39c227abd" + ] + ], + [ + + ], + [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T13:43:48.22378" + }, + "test_fastp_paired_end_qc_only": { + "content": [ + [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.json:md5,623064a45912dac6f2b64e3f2e9901df" + ] + ], + [ + + ], + [ + + ], + [ + + ], + [ + + ], + [ + + ], + [ + + ], + [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T13:44:36.334938" + }, + "test_fastp_paired_end_qc_only - stub": { + "content": [ + { + "0": [ + + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "3": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "4": [ + + ], + "5": [ + + ], + "6": [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "json": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "log": [ + [ + { + "id": "test", + "single_end": false + }, + "test.fastp.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "reads": [ + + ], + "reads_fail": [ + + ], + "reads_merged": [ + + ], + "versions": [ + "versions.yml:md5,48ffc994212fb1fc9f83a74fa69c9f02" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-05T14:31:27.096468" + } +} \ No newline at end of file diff --git a/modules/nf-core/fastp/tests/nextflow.interleaved.config b/modules/nf-core/fastp/tests/nextflow.interleaved.config new file mode 100644 index 00000000..4be8dbd2 --- /dev/null +++ b/modules/nf-core/fastp/tests/nextflow.interleaved.config @@ -0,0 +1,5 @@ +process { + withName: FASTP { + ext.args = "--interleaved_in -e 30" + } +} diff --git a/modules/nf-core/fastp/tests/nextflow.save_failed.config b/modules/nf-core/fastp/tests/nextflow.save_failed.config new file mode 100644 index 00000000..53b61b0c --- /dev/null +++ b/modules/nf-core/fastp/tests/nextflow.save_failed.config @@ -0,0 +1,5 @@ +process { + withName: FASTP { + ext.args = "-e 30" + } +} diff --git a/modules/nf-core/fastp/tests/tags.yml b/modules/nf-core/fastp/tests/tags.yml new file mode 100644 index 00000000..c1afcce7 --- /dev/null +++ b/modules/nf-core/fastp/tests/tags.yml @@ -0,0 +1,2 @@ +fastp: + - modules/nf-core/fastp/** diff --git a/modules/nf-core/fastqc/environment.yml b/modules/nf-core/fastqc/environment.yml index 1787b38a..691d4c76 100644 --- a/modules/nf-core/fastqc/environment.yml +++ b/modules/nf-core/fastqc/environment.yml @@ -1,7 +1,5 @@ -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 d79f1c86..d8989f48 100644 --- a/modules/nf-core/fastqc/main.nf +++ b/modules/nf-core/fastqc/main.nf @@ -26,7 +26,10 @@ process FASTQC { def rename_to = old_new_pairs*.join(' ').join(' ') def renamed_files = old_new_pairs.collect{ old_name, new_name -> new_name }.join(' ') - def memory_in_mb = MemoryUnit.of("${task.memory}").toUnit('MB') + // The total amount of allocated RAM by FastQC is equal to the number of threads defined (--threads) time the amount of RAM defined (--memory) + // https://github.com/s-andrews/FastQC/blob/1faeea0412093224d7f6a07f777fad60a5650795/fastqc#L211-L222 + // Dividing the task.memory by task.cpu allows to stick to requested amount of RAM in the label + def memory_in_mb = MemoryUnit.of("${task.memory}").toUnit('MB') / task.cpus // FastQC memory value allowed range (100 - 10000) def fastqc_memory = memory_in_mb > 10000 ? 10000 : (memory_in_mb < 100 ? 100 : memory_in_mb) diff --git a/modules/nf-core/fastqc/tests/main.nf.test b/modules/nf-core/fastqc/tests/main.nf.test index 83586e4a..e9d79a07 100644 --- a/modules/nf-core/fastqc/tests/main.nf.test +++ b/modules/nf-core/fastqc/tests/main.nf.test @@ -23,17 +23,14 @@ nextflow_process { then { 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("File typeConventional base calls") }, - - { assert snapshot(process.out.versions).match("fastqc_versions_single") } + { 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("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } ) } } @@ -54,16 +51,14 @@ nextflow_process { 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("File typeConventional base calls") }, - { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, - - { assert snapshot(process.out.versions).match("fastqc_versions_paired") } + { 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("File typeConventional base calls") }, + { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } ) } } @@ -83,13 +78,11 @@ nextflow_process { 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("File typeConventional base calls") }, - - { assert snapshot(process.out.versions).match("fastqc_versions_interleaved") } + { 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("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } ) } } @@ -98,36 +91,70 @@ nextflow_process { when { process { - """ - input[0] = [ - [id: 'test', single_end: false], // meta map - file(params.test_data['sarscov2']['illumina']['test_paired_end_sorted_bam'], checkIfExists: true) - ] - """ + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) + ]) + """ } } then { assertAll ( - { assert process.success }, + { 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("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } + ) + } + } - { 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("File typeConventional base calls") }, + test("sarscov2 multiple [fastq]") { + + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_2.fastq.gz', checkIfExists: true) ] + ]) + """ + } + } - { assert snapshot(process.out.versions).match("versions") } + 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("File typeConventional base calls") }, + { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, + { assert path(process.out.html[0][1][2]).text.contains("File typeConventional base calls") }, + { assert path(process.out.html[0][1][3]).text.contains("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } ) } } - test("sarscov2 paired-end [bam]") { + test("sarscov2 custom_prefix") { when { process { """ input[0] = Channel.of([ - [id: 'test', single_end: false], // meta map - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) + [ id:'mysample', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ]) """ } @@ -135,28 +162,47 @@ nextflow_process { then { assertAll ( - { assert process.success }, + { 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("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } + ) + } + } + + test("sarscov2 single-end [fastq] - stub") { - { 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("File typeConventional base calls") }, + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [ id: 'test', single_end:true ], + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] + ]) + """ + } + } - { assert snapshot(process.out.versions).match("fastqc_versions_bam") } + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } ) } } - test("sarscov2 multiple [fastq]") { + test("sarscov2 paired-end [fastq] - stub") { + options "-stub" when { process { """ input[0] = Channel.of([ [id: 'test', single_end: false], // meta map [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_1.fastq.gz', checkIfExists: true), - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_2.fastq.gz', checkIfExists: true) ] + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] ]) """ } @@ -164,62 +210,68 @@ nextflow_process { 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("File typeConventional base calls") }, - { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, - { assert path(process.out.html[0][1][2]).text.contains("File typeConventional base calls") }, - { assert path(process.out.html[0][1][3]).text.contains("File typeConventional base calls") }, - - { assert snapshot(process.out.versions).match("fastqc_versions_multiple") } + { assert process.success }, + { assert snapshot(process.out).match() } ) } } - test("sarscov2 custom_prefix") { + test("sarscov2 interleaved [fastq] - stub") { + options "-stub" when { process { """ input[0] = Channel.of([ - [ id:'mysample', single_end:true ], // meta map - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + [id: 'test', single_end: false], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_interleaved.fastq.gz', checkIfExists: true) ]) - """ + """ } } then { assertAll ( - { assert process.success }, + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("sarscov2 paired-end [bam] - stub") { - { 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("File typeConventional base calls") }, + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) + ]) + """ + } + } - { assert snapshot(process.out.versions).match("fastqc_versions_custom_prefix") } + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } ) } } - test("sarscov2 single-end [fastq] - stub") { - - options "-stub" + test("sarscov2 multiple [fastq] - stub") { + options "-stub" when { process { """ input[0] = Channel.of([ - [ id: 'test', single_end:true ], - [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] + [id: 'test', single_end: false], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_2.fastq.gz', checkIfExists: true) ] ]) """ } @@ -227,12 +279,31 @@ nextflow_process { 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("fastqc_stub") } + { assert process.success }, + { assert snapshot(process.out).match() } ) } } + test("sarscov2 custom_prefix - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [ id:'mysample', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } } diff --git a/modules/nf-core/fastqc/tests/main.nf.test.snap b/modules/nf-core/fastqc/tests/main.nf.test.snap index 86f7c311..d5db3092 100644 --- a/modules/nf-core/fastqc/tests/main.nf.test.snap +++ b/modules/nf-core/fastqc/tests/main.nf.test.snap @@ -1,88 +1,392 @@ { - "fastqc_versions_interleaved": { + "sarscov2 custom_prefix": { "content": [ [ "versions.yml:md5,e1cc25ca8af856014824abd842e93978" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.3" }, - "timestamp": "2024-01-31T17:40:07.293713" + "timestamp": "2024-07-22T11:02:16.374038" }, - "fastqc_stub": { + "sarscov2 single-end [fastq] - stub": { "content": [ - [ - "test.html", - "test.zip", - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "test", + "single_end": true + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "test", + "single_end": true + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:02:24.993809" + }, + "sarscov2 custom_prefix - stub": { + "content": [ + { + "0": [ + [ + { + "id": "mysample", + "single_end": true + }, + "mysample.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "mysample", + "single_end": true + }, + "mysample.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "mysample", + "single_end": true + }, + "mysample.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "mysample", + "single_end": true + }, + "mysample.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.3" }, - "timestamp": "2024-01-31T17:31:01.425198" + "timestamp": "2024-07-22T11:03:10.93942" }, - "fastqc_versions_multiple": { + "sarscov2 interleaved [fastq]": { "content": [ [ "versions.yml:md5,e1cc25ca8af856014824abd842e93978" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.3" }, - "timestamp": "2024-01-31T17:40:55.797907" + "timestamp": "2024-07-22T11:01:42.355718" }, - "fastqc_versions_bam": { + "sarscov2 paired-end [bam]": { "content": [ [ "versions.yml:md5,e1cc25ca8af856014824abd842e93978" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.3" }, - "timestamp": "2024-01-31T17:40:26.795862" + "timestamp": "2024-07-22T11:01:53.276274" }, - "fastqc_versions_single": { + "sarscov2 multiple [fastq]": { "content": [ [ "versions.yml:md5,e1cc25ca8af856014824abd842e93978" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.3" }, - "timestamp": "2024-01-31T17:39:27.043675" + "timestamp": "2024-07-22T11:02:05.527626" }, - "fastqc_versions_paired": { + "sarscov2 paired-end [fastq]": { "content": [ [ "versions.yml:md5,e1cc25ca8af856014824abd842e93978" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:01:31.188871" + }, + "sarscov2 paired-end [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:02:34.273566" + }, + "sarscov2 multiple [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" }, - "timestamp": "2024-01-31T17:39:47.584191" + "timestamp": "2024-07-22T11:03:02.304411" }, - "fastqc_versions_custom_prefix": { + "sarscov2 single-end [fastq]": { "content": [ [ "versions.yml:md5,e1cc25ca8af856014824abd842e93978" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:01:19.095607" + }, + "sarscov2 interleaved [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:02:44.640184" + }, + "sarscov2 paired-end [bam] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" }, - "timestamp": "2024-01-31T17:41:14.576531" + "timestamp": "2024-07-22T11:02:53.550742" } } \ No newline at end of file diff --git a/modules/nf-core/filtlong/environment.yml b/modules/nf-core/filtlong/environment.yml index 0fb7e8b4..746c83a4 100644 --- a/modules/nf-core/filtlong/environment.yml +++ b/modules/nf-core/filtlong/environment.yml @@ -1,7 +1,5 @@ -name: filtlong channels: - conda-forge - bioconda - - defaults dependencies: - bioconda::filtlong=0.2.1 diff --git a/modules/nf-core/filtlong/tests/main.nf.test b/modules/nf-core/filtlong/tests/main.nf.test index b7d73e79..d54ce39c 100644 --- a/modules/nf-core/filtlong/tests/main.nf.test +++ b/modules/nf-core/filtlong/tests/main.nf.test @@ -17,10 +17,10 @@ nextflow_process { process { """ input[0] = [ - [ id:'test', single_end:false ], // meta map - [], - [ file(params.test_data['sarscov2']['nanopore']['test_fastq_gz'], checkIfExists: true) ] - ] + [ id:'test', single_end:false ], // meta map + [], + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/nanopore/fastq/test.fastq.gz', checkIfExists: true) ] + ] """ } } @@ -29,8 +29,11 @@ nextflow_process { 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") } + { assert snapshot( + process.out.reads, + process.out.versions + ).match() + } ) } @@ -46,10 +49,10 @@ nextflow_process { 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) ] - ] + [ id:'test', single_end:true ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ], + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/nanopore/fastq/test.fastq.gz', checkIfExists: true) ] + ] """ } } @@ -58,8 +61,11 @@ nextflow_process { 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") } + { assert snapshot( + process.out.reads, + process.out.versions + ).match() + } ) } @@ -75,11 +81,13 @@ nextflow_process { 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) ] - ] + [ id:'test', single_end:false ], // meta map + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) + ], + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/nanopore/fastq/test.fastq.gz', checkIfExists: true) ] + ] """ } } @@ -88,12 +96,13 @@ nextflow_process { 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") } + { assert snapshot( + process.out.reads, + process.out.versions + ).match() + } ) } } - - } diff --git a/modules/nf-core/filtlong/tests/main.nf.test.snap b/modules/nf-core/filtlong/tests/main.nf.test.snap index 49d4bb6c..1a25c3fc 100644 --- a/modules/nf-core/filtlong/tests/main.nf.test.snap +++ b/modules/nf-core/filtlong/tests/main.nf.test.snap @@ -1,5 +1,5 @@ { - "nanopore": { + "sarscov2 nanopore [fastq]": { "content": [ [ [ @@ -9,19 +9,18 @@ }, "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" + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.3" + }, + "timestamp": "2024-08-06T10:51:29.197603" }, - "nanopore_illumina_pe": { + "sarscov2 nanopore [fastq] + Illumina paired-end [fastq]": { "content": [ [ [ @@ -31,11 +30,18 @@ }, "test_lr.fastq.gz:md5,7567d853ada6ac142332619d0b541d76" ] + ], + [ + "versions.yml:md5,af5988f30157282acdb0ac50ebb4c8cc" ] ], - "timestamp": "2023-12-11T14:24:05.202047" + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.3" + }, + "timestamp": "2024-08-06T10:51:39.68464" }, - "nanopore_illumina_se": { + "sarscov2 nanopore [fastq] + Illumina single-end [fastq]": { "content": [ [ [ @@ -45,8 +51,15 @@ }, "test_lr.fastq.gz:md5,7567d853ada6ac142332619d0b541d76" ] + ], + [ + "versions.yml:md5,af5988f30157282acdb0ac50ebb4c8cc" ] ], - "timestamp": "2023-12-11T14:23:50.607338" + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.3" + }, + "timestamp": "2024-08-06T10:51:34.404022" } } \ No newline at end of file diff --git a/modules/nf-core/filtlong/tests/nextflow.config b/modules/nf-core/filtlong/tests/nextflow.config index 5e4c9fbb..d366b4c3 100644 --- a/modules/nf-core/filtlong/tests/nextflow.config +++ b/modules/nf-core/filtlong/tests/nextflow.config @@ -1,8 +1,4 @@ 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 deleted file mode 100644 index bf2cff9d..00000000 --- a/modules/nf-core/filtlong/tests/tags.yml +++ /dev/null @@ -1,2 +0,0 @@ -filtlong: - - modules/nf-core/filtlong/** diff --git a/modules/nf-core/ganon/classify/environment.yml b/modules/nf-core/ganon/classify/environment.yml new file mode 100644 index 00000000..98f34de8 --- /dev/null +++ b/modules/nf-core/ganon/classify/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::ganon=2.0.0 diff --git a/modules/nf-core/ganon/classify/main.nf b/modules/nf-core/ganon/classify/main.nf index d4130a01..d6db825e 100644 --- a/modules/nf-core/ganon/classify/main.nf +++ b/modules/nf-core/ganon/classify/main.nf @@ -2,10 +2,10 @@ process GANON_CLASSIFY { tag "$meta.id" label 'process_high' - conda "bioconda::ganon=1.5.1" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/ganon:1.5.1--py310h8abeb55_0': - 'biocontainers/ganon:1.5.1--py310h8abeb55_0' }" + 'https://depot.galaxyproject.org/singularity/ganon:2.0.0--py39ha35b9be_0': + 'biocontainers/ganon:2.0.0--py39ha35b9be_0' }" input: tuple val(meta) , path(fastqs) @@ -14,7 +14,7 @@ process GANON_CLASSIFY { output: tuple val(meta), path("*.tre"), emit: tre tuple val(meta), path("*.rep"), emit: report - tuple val(meta), path("*.lca"), emit: lca , optional: true + tuple val(meta), path("*.one"), emit: one , optional: true tuple val(meta), path("*.all"), emit: all , optional: true tuple val(meta), path("*.unc"), emit: unc , optional: true tuple val(meta), path("*.log"), emit: log @@ -28,11 +28,11 @@ process GANON_CLASSIFY { def prefix = task.ext.prefix ?: "${meta.id}" def input = meta.single_end ? "--single-reads ${fastqs}" : "--paired-reads ${fastqs}" """ - dbprefix=\$(find -L . -name '*.ibf' | sed 's/\\.ibf\$//') + dbprefix=\$(find -L . -name '*.*ibf' | sed 's/\\.h\\?ibf\$//') ganon \\ classify \\ - --db-prefix \${dbprefix%%.ibf} \\ + --db-prefix \${dbprefix%%.*ibf} \\ $args \\ --threads $task.cpus \\ --output-prefix ${prefix} \\ @@ -51,10 +51,11 @@ process GANON_CLASSIFY { def input = meta.single_end ? "--single-reads ${fastqs}" : "--paired-reads ${fastqs}" """ touch ${prefix}.tre - touch ${prefix}.report - touch ${prefix}.lca + touch ${prefix}.rep + touch ${prefix}.one touch ${prefix}.all touch ${prefix}.unc + touch ${prefix}.log cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/nf-core/ganon/classify/meta.yml b/modules/nf-core/ganon/classify/meta.yml index 692d4e56..55a8eae6 100644 --- a/modules/nf-core/ganon/classify/meta.yml +++ b/modules/nf-core/ganon/classify/meta.yml @@ -15,8 +15,7 @@ tools: documentation: "https://github.com/pirovc/ganon" tool_dev_url: "https://github.com/pirovc/ganon" doi: "10.1093/bioinformatics/btaa458" - licence: "['MIT License']" - + licence: ["MIT"] input: - meta: type: map @@ -27,11 +26,10 @@ input: type: file description: Single or paired FASTQ files, optionally gzipped pattern: "*.{fq,fq.gz,fastq,fastq.gz}" - - dbs: + - db: type: file description: Ganon database files from build or build-custom pattern: "*.{ibf,tax}" - output: - meta: type: map @@ -50,10 +48,10 @@ output: type: file description: Plain ganon report file with only targets with match pattern: "*.rep" - - lca: + - one: type: file - description: Information about the lowest common ancestor match of a given read - pattern: "*.lca" + description: Information about a single (best) match of a given read after EM or LCA algorithms + pattern: "*.one" - all: type: file description: Information of all matches to a given read @@ -66,6 +64,7 @@ output: type: file description: Text file containing console output from ganon classify pattern: "*.log" - authors: - "@jfy133" +maintainers: + - "@jfy133" diff --git a/modules/nf-core/ganon/classify/tests/main.nf.test b/modules/nf-core/ganon/classify/tests/main.nf.test new file mode 100644 index 00000000..e581ca06 --- /dev/null +++ b/modules/nf-core/ganon/classify/tests/main.nf.test @@ -0,0 +1,112 @@ +nextflow_process { + + name "Test Process GANON_CLASSIFY" + script "../main.nf" + process "GANON_CLASSIFY" + config "./nextflow.config" + + tag "modules" + tag "modules_nfcore" + tag "ganon" + tag "ganon/buildcustom" + tag "ganon/classify" + + setup { + run("GANON_BUILDCUSTOM") { + script "../../buildcustom/main.nf" + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file(params.test_data['sarscov2']['genome']['genome_fasta'], checkIfExists: true), + ] + input[1] = [] + input[2] = [] + """ + } + } + } + + test("sarscov2 single-end [fastq]") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + [ + file(params.test_data['sarscov2']['illumina']['test_1_fastq_gz'], checkIfExists: true), + ] + ] + input[1] = GANON_BUILDCUSTOM.out.db.map{it[1]} + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out.tre, + process.out.report).match()}, + { assert file(process.out.log[0][1]).text.contains("Total elapsed time:") } + ) + } + + } + + 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) + ] + ] + input[1] = GANON_BUILDCUSTOM.out.db.map{it[1]} + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out.tre, + process.out.report).match()}, + { assert file(process.out.log[0][1]).text.contains("Total elapsed time:") } + ) + } + + } + + test("sarscov2 - fastq - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // 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).match() } + ) + } + + } + +} diff --git a/modules/nf-core/ganon/classify/tests/main.nf.test.snap b/modules/nf-core/ganon/classify/tests/main.nf.test.snap new file mode 100644 index 00000000..40b36b14 --- /dev/null +++ b/modules/nf-core/ganon/classify/tests/main.nf.test.snap @@ -0,0 +1,169 @@ +{ + "sarscov2 - fastq - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.tre:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test.rep:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + { + "id": "test", + "single_end": true + }, + "test.one:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "3": [ + [ + { + "id": "test", + "single_end": true + }, + "test.all:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "4": [ + [ + { + "id": "test", + "single_end": true + }, + "test.unc:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "5": [ + [ + { + "id": "test", + "single_end": true + }, + "test.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "6": [ + "versions.yml:md5,e13af9e126ff4a9ea7ee4b706fbbc0bb" + ], + "all": [ + [ + { + "id": "test", + "single_end": true + }, + "test.all:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "log": [ + [ + { + "id": "test", + "single_end": true + }, + "test.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "one": [ + [ + { + "id": "test", + "single_end": true + }, + "test.one:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "report": [ + [ + { + "id": "test", + "single_end": true + }, + "test.rep:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "tre": [ + [ + { + "id": "test", + "single_end": true + }, + "test.tre:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "unc": [ + [ + { + "id": "test", + "single_end": true + }, + "test.unc:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e13af9e126ff4a9ea7ee4b706fbbc0bb" + ] + } + ], + "timestamp": "2024-01-06T15:08:06.626813557" + }, + "sarscov2 paired-end [fastq]": { + "content": [ + [ + [ + { + "id": "test", + "single_end": false + }, + "test.tre:md5,66c0b9ed247989682fe3bae842d37a76" + ] + ], + [ + [ + { + "id": "test", + "single_end": false + }, + "test.rep:md5,757e5cbf7a978913277401285d743336" + ] + ] + ], + "timestamp": "2024-01-06T15:07:49.528458193" + }, + "sarscov2 single-end [fastq]": { + "content": [ + [ + [ + { + "id": "test", + "single_end": true + }, + "test.tre:md5,3d2ef6fe0571d7aa7324539407a59630" + ] + ], + [ + [ + { + "id": "test", + "single_end": true + }, + "test.rep:md5,9b5f8051aa459a80a678e36259a15746" + ] + ] + ], + "timestamp": "2024-01-06T15:07:12.092925016" + } +} \ No newline at end of file diff --git a/modules/nf-core/ganon/classify/tests/nextflow.config b/modules/nf-core/ganon/classify/tests/nextflow.config new file mode 100644 index 00000000..18712875 --- /dev/null +++ b/modules/nf-core/ganon/classify/tests/nextflow.config @@ -0,0 +1,7 @@ +process { + + withName: GANON_CLASSIFY { + ext.args = "--output-one --output-all --output-unclassified" + } + +} diff --git a/modules/nf-core/ganon/classify/tests/tags.yml b/modules/nf-core/ganon/classify/tests/tags.yml new file mode 100644 index 00000000..60ebeeea --- /dev/null +++ b/modules/nf-core/ganon/classify/tests/tags.yml @@ -0,0 +1,2 @@ +ganon/classify: + - "modules/nf-core/ganon/classify/**" diff --git a/modules/nf-core/ganon/report/environment.yml b/modules/nf-core/ganon/report/environment.yml new file mode 100644 index 00000000..98f34de8 --- /dev/null +++ b/modules/nf-core/ganon/report/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::ganon=2.0.0 diff --git a/modules/nf-core/ganon/report/main.nf b/modules/nf-core/ganon/report/main.nf index bd0a2207..2b1998f1 100644 --- a/modules/nf-core/ganon/report/main.nf +++ b/modules/nf-core/ganon/report/main.nf @@ -2,10 +2,10 @@ process GANON_REPORT { tag "$meta.id" label 'process_single' - conda "bioconda::ganon=1.5.1" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/ganon:1.5.1--py310h8abeb55_0': - 'biocontainers/ganon:1.5.1--py310h8abeb55_0' }" + 'https://depot.galaxyproject.org/singularity/ganon:2.0.0--py39ha35b9be_0': + 'biocontainers/ganon:2.0.0--py39ha35b9be_0' }" input: tuple val(meta), path(rep) @@ -23,13 +23,13 @@ process GANON_REPORT { def prefix = task.ext.prefix ?: "${meta.id}" """ - dbprefix=\$(find -L . -name '*.ibf' | sed 's/\\.ibf\$//') + dbprefix=\$(find -L . -name '*.*ibf' | sed 's/\\.h\\?ibf\$//') ganon \\ report \\ --input ${rep} \\ --output-prefix ${prefix} \\ - --db-prefix \${dbprefix%%.ibf} \\ + --db-prefix \${dbprefix%%.*ibf} \\ $args cat <<-END_VERSIONS > versions.yml diff --git a/modules/nf-core/ganon/report/meta.yml b/modules/nf-core/ganon/report/meta.yml index c7852c8a..c820e9c4 100644 --- a/modules/nf-core/ganon/report/meta.yml +++ b/modules/nf-core/ganon/report/meta.yml @@ -17,8 +17,7 @@ tools: documentation: "https://github.com/pirovc/ganon" tool_dev_url: "https://github.com/pirovc/ganon" doi: "10.1093/bioinformatics/btaa458" - licence: "['MIT License']" - + licence: ["MIT"] input: - meta: type: map @@ -29,11 +28,10 @@ input: type: file description: Input 'repo' files from ganon classify pattern: "*.rep" - - dbs: + - db: type: file description: Ganon database files from build or build-custom pattern: "*.{ibf,tax}" - output: - meta: type: map @@ -48,6 +46,7 @@ output: type: file description: Output ganon report containing taxonomic profile information. Formatting of contents depends on --output-format. pattern: "*.tre" - authors: - "@jfy133" +maintainers: + - "@jfy133" diff --git a/modules/nf-core/ganon/report/tests/main.nf.test b/modules/nf-core/ganon/report/tests/main.nf.test new file mode 100644 index 00000000..d350eed0 --- /dev/null +++ b/modules/nf-core/ganon/report/tests/main.nf.test @@ -0,0 +1,87 @@ +nextflow_process { + + name "Test Process GANON_REPORT" + script "../main.nf" + process "GANON_REPORT" + config "./nextflow.config" + + tag "modules" + tag "modules_nfcore" + tag "ganon" + tag "ganon/buildcustom" + tag "ganon/classify" + tag "ganon/report" + + setup { + run("GANON_BUILDCUSTOM") { + script "../../buildcustom/main.nf" + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true), + ] + input[1] = [] + input[2] = [] + """ + } + } + run("GANON_CLASSIFY") { + script "../../classify/main.nf" + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + ] + ] + input[1] = GANON_BUILDCUSTOM.out.db.map{it[1]} + """ + } + } + } + + test("sarscov2 single-end [fastq]") { + + when { + process { + """ + input[0] = GANON_CLASSIFY.out.report + input[1] = GANON_BUILDCUSTOM.out.db.map{it[1]} + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("sarscov2 single-end [fastq] stub") { + + options "-stub" + + when { + process { + """ + input[0] = GANON_CLASSIFY.out.report + input[1] = GANON_BUILDCUSTOM.out.db.map{it[1]} + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + +} diff --git a/modules/nf-core/ganon/report/tests/main.nf.test.snap b/modules/nf-core/ganon/report/tests/main.nf.test.snap new file mode 100644 index 00000000..abad8035 --- /dev/null +++ b/modules/nf-core/ganon/report/tests/main.nf.test.snap @@ -0,0 +1,64 @@ +{ + "sarscov2 single-end [fastq] stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.tre:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,7219068902254fbc97f84e8e163213d0" + ], + "tre": [ + [ + { + "id": "test", + "single_end": true + }, + "test.tre:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,7219068902254fbc97f84e8e163213d0" + ] + } + ], + "timestamp": "2024-01-06T18:50:07.439069779" + }, + "sarscov2 single-end [fastq]": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.tre:md5,3d2ef6fe0571d7aa7324539407a59630" + ] + ], + "1": [ + "versions.yml:md5,7219068902254fbc97f84e8e163213d0" + ], + "tre": [ + [ + { + "id": "test", + "single_end": true + }, + "test.tre:md5,3d2ef6fe0571d7aa7324539407a59630" + ] + ], + "versions": [ + "versions.yml:md5,7219068902254fbc97f84e8e163213d0" + ] + } + ], + "timestamp": "2024-01-06T18:49:52.505817066" + } +} \ No newline at end of file diff --git a/modules/nf-core/ganon/report/tests/nextflow.config b/modules/nf-core/ganon/report/tests/nextflow.config new file mode 100644 index 00000000..e6dd3131 --- /dev/null +++ b/modules/nf-core/ganon/report/tests/nextflow.config @@ -0,0 +1,8 @@ +process { + withName: GANON_CLASSIFY { + ext.args = "--output-one --output-all --output-unclassified" + } + withName: GANON_REPORT { + ext.args = "--report-type reads --output-format tsv" + } +} diff --git a/modules/nf-core/ganon/report/tests/tags.yml b/modules/nf-core/ganon/report/tests/tags.yml new file mode 100644 index 00000000..c991c0ea --- /dev/null +++ b/modules/nf-core/ganon/report/tests/tags.yml @@ -0,0 +1,2 @@ +ganon/report: + - "modules/nf-core/ganon/report/**" diff --git a/modules/nf-core/ganon/table/environment.yml b/modules/nf-core/ganon/table/environment.yml new file mode 100644 index 00000000..98f34de8 --- /dev/null +++ b/modules/nf-core/ganon/table/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::ganon=2.0.0 diff --git a/modules/nf-core/ganon/table/main.nf b/modules/nf-core/ganon/table/main.nf index 5adaa65c..d8f247c1 100644 --- a/modules/nf-core/ganon/table/main.nf +++ b/modules/nf-core/ganon/table/main.nf @@ -2,10 +2,10 @@ process GANON_TABLE { tag "$meta.id" label 'process_single' - conda "bioconda::ganon=1.5.1" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/ganon:1.5.1--py310h8abeb55_0': - 'biocontainers/ganon:1.5.1--py310h8abeb55_0' }" + 'https://depot.galaxyproject.org/singularity/ganon:2.0.0--py39ha35b9be_0': + 'biocontainers/ganon:2.0.0--py39ha35b9be_0' }" input: tuple val(meta), path(tre) diff --git a/modules/nf-core/ganon/table/meta.yml b/modules/nf-core/ganon/table/meta.yml index 4fa19b74..bf15f083 100644 --- a/modules/nf-core/ganon/table/meta.yml +++ b/modules/nf-core/ganon/table/meta.yml @@ -18,8 +18,7 @@ tools: documentation: "https://github.com/pirovc/ganon" tool_dev_url: "https://github.com/pirovc/ganon" doi: "10.1093/bioinformatics/btaa458" - licence: "['MIT License']" - + licence: ["MIT"] input: - meta: type: map @@ -30,7 +29,6 @@ input: type: file description: A list of 'tre' files from ganon report pattern: "*.tre" - output: - meta: type: map @@ -45,6 +43,7 @@ output: type: file description: Output ganon table containing taxonomic profile information of multiple samples. Formatting of contents depends on --output-format. pattern: "*.txt" - authors: - "@jfy133" +maintainers: + - "@jfy133" diff --git a/modules/nf-core/ganon/table/tests/main.nf.test b/modules/nf-core/ganon/table/tests/main.nf.test new file mode 100644 index 00000000..43b6cf0a --- /dev/null +++ b/modules/nf-core/ganon/table/tests/main.nf.test @@ -0,0 +1,95 @@ +nextflow_process { + + name "Test Process GANON_TABLE" + script "../main.nf" + process "GANON_TABLE" + config "./nextflow.config" + + tag "modules" + tag "modules_nfcore" + tag "ganon" + tag "ganon/buildcustom" + tag "ganon/classify" + tag "ganon/report" + tag "ganon/table" + + setup { + run("GANON_BUILDCUSTOM") { + script "../../buildcustom/main.nf" + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true), + ] + input[1] = [] + input[2] = [] + """ + } + } + run("GANON_CLASSIFY") { + script "../../classify/main.nf" + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + ] + ] + input[1] = GANON_BUILDCUSTOM.out.db.map{it[1]} + """ + } + } + run("GANON_REPORT") { + script "../../report/main.nf" + process { + """ + input[0] = GANON_CLASSIFY.out.report + input[1] = GANON_BUILDCUSTOM.out.db.map{it[1]} + """ + } + } + } + + test("sarscov2 single-end [fastq]") { + + when { + process { + """ + input[0] = GANON_REPORT.out.tre.collect{it[1]}.map{[[id: "db1"], it]} + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("sarscov2 single-end [fastq] stub") { + + options "-stub" + + when { + process { + """ + input[0] = GANON_REPORT.out.tre.collect{it[1]}.map{[[id: "db1"], it]} + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + +} diff --git a/modules/nf-core/ganon/table/tests/main.nf.test.snap b/modules/nf-core/ganon/table/tests/main.nf.test.snap new file mode 100644 index 00000000..2c5c312d --- /dev/null +++ b/modules/nf-core/ganon/table/tests/main.nf.test.snap @@ -0,0 +1,60 @@ +{ + "sarscov2 single-end [fastq] stub": { + "content": [ + { + "0": [ + [ + { + "id": "db1" + }, + "db1.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,1cec68ee4a3dcc057d475497732b72c1" + ], + "txt": [ + [ + { + "id": "db1" + }, + "db1.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,1cec68ee4a3dcc057d475497732b72c1" + ] + } + ], + "timestamp": "2024-01-07T14:27:58.631022945" + }, + "sarscov2 single-end [fastq]": { + "content": [ + { + "0": [ + [ + { + "id": "db1" + }, + "db1.txt:md5,c2f38e9f47f8701d8f37a59dffed88a3" + ] + ], + "1": [ + "versions.yml:md5,1cec68ee4a3dcc057d475497732b72c1" + ], + "txt": [ + [ + { + "id": "db1" + }, + "db1.txt:md5,c2f38e9f47f8701d8f37a59dffed88a3" + ] + ], + "versions": [ + "versions.yml:md5,1cec68ee4a3dcc057d475497732b72c1" + ] + } + ], + "timestamp": "2024-01-07T14:27:37.318272937" + } +} \ No newline at end of file diff --git a/modules/nf-core/ganon/table/tests/nextflow.config b/modules/nf-core/ganon/table/tests/nextflow.config new file mode 100644 index 00000000..26114b4c --- /dev/null +++ b/modules/nf-core/ganon/table/tests/nextflow.config @@ -0,0 +1,12 @@ +process { + withName: GANON_CLASSIFY { + ext.args = "--output-one --output-all --output-unclassified" + } + withName: GANON_REPORT { + ext.args = "--report-type reads --output-format tsv" + } + + withName: GANON_TABLE { + ext.args = "--output-format tsv --output-value percentages" + } +} diff --git a/modules/nf-core/ganon/table/tests/tags.yml b/modules/nf-core/ganon/table/tests/tags.yml new file mode 100644 index 00000000..aa88380d --- /dev/null +++ b/modules/nf-core/ganon/table/tests/tags.yml @@ -0,0 +1,2 @@ +ganon/table: + - "modules/nf-core/ganon/table/**" diff --git a/modules/nf-core/gunzip/environment.yml b/modules/nf-core/gunzip/environment.yml new file mode 100644 index 00000000..c7794856 --- /dev/null +++ b/modules/nf-core/gunzip/environment.yml @@ -0,0 +1,7 @@ +channels: + - conda-forge + - bioconda +dependencies: + - conda-forge::grep=3.11 + - conda-forge::sed=4.8 + - conda-forge::tar=1.34 diff --git a/modules/nf-core/gunzip/main.nf b/modules/nf-core/gunzip/main.nf index 73bf08cd..5e67e3b9 100644 --- a/modules/nf-core/gunzip/main.nf +++ b/modules/nf-core/gunzip/main.nf @@ -2,10 +2,10 @@ process GUNZIP { tag "$archive" label 'process_single' - conda "conda-forge::sed=4.7" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/ubuntu:20.04' : - 'nf-core/ubuntu:20.04' }" + 'https://depot.galaxyproject.org/singularity/ubuntu:22.04' : + 'nf-core/ubuntu:22.04' }" input: tuple val(meta), path(archive) @@ -18,8 +18,11 @@ process GUNZIP { task.ext.when == null || task.ext.when script: - def args = task.ext.args ?: '' - gunzip = archive.toString() - '.gz' + def args = task.ext.args ?: '' + def extension = ( archive.toString() - '.gz' ).tokenize('.')[-1] + def name = archive.toString() - '.gz' - ".$extension" + def prefix = task.ext.prefix ?: name + gunzip = prefix + ".$extension" """ # Not calling gunzip itself because it creates files # with the original group ownership rather than the @@ -37,7 +40,11 @@ process GUNZIP { """ stub: - gunzip = archive.toString() - '.gz' + def args = task.ext.args ?: '' + def extension = ( archive.toString() - '.gz' ).tokenize('.')[-1] + def name = archive.toString() - '.gz' - ".$extension" + def prefix = task.ext.prefix ?: name + gunzip = prefix + ".$extension" """ touch $gunzip cat <<-END_VERSIONS > versions.yml diff --git a/modules/nf-core/gunzip/meta.yml b/modules/nf-core/gunzip/meta.yml index 4cdcdf4c..f32973a0 100644 --- a/modules/nf-core/gunzip/meta.yml +++ b/modules/nf-core/gunzip/meta.yml @@ -33,3 +33,8 @@ authors: - "@joseespinosa" - "@drpatelh" - "@jfy133" +maintainers: + - "@joseespinosa" + - "@drpatelh" + - "@jfy133" + - "@gallvp" diff --git a/modules/nf-core/gunzip/tests/main.nf.test b/modules/nf-core/gunzip/tests/main.nf.test new file mode 100644 index 00000000..776211ad --- /dev/null +++ b/modules/nf-core/gunzip/tests/main.nf.test @@ -0,0 +1,121 @@ +nextflow_process { + + name "Test Process GUNZIP" + script "../main.nf" + process "GUNZIP" + tag "gunzip" + tag "modules_nfcore" + tag "modules" + + test("Should run without failures") { + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = Channel.of([ + [], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + ) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("Should run without failures - prefix") { + + config './nextflow.config' + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = Channel.of([ + [ id: 'test' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + ) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("Should run without failures - stub") { + + options '-stub' + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = Channel.of([ + [], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + ) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("Should run without failures - prefix - stub") { + + options '-stub' + config './nextflow.config' + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = Channel.of([ + [ id: 'test' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + ) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + +} diff --git a/modules/nf-core/gunzip/tests/main.nf.test.snap b/modules/nf-core/gunzip/tests/main.nf.test.snap new file mode 100644 index 00000000..069967e7 --- /dev/null +++ b/modules/nf-core/gunzip/tests/main.nf.test.snap @@ -0,0 +1,134 @@ +{ + "Should run without failures - prefix - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.xyz.fastq:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,54376d32aca20e937a4ec26dac228e84" + ], + "gunzip": [ + [ + { + "id": "test" + }, + "test.xyz.fastq:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,54376d32aca20e937a4ec26dac228e84" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-25T11:35:10.861293" + }, + "Should run without failures - stub": { + "content": [ + { + "0": [ + [ + [ + + ], + "test_1.fastq:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,54376d32aca20e937a4ec26dac228e84" + ], + "gunzip": [ + [ + [ + + ], + "test_1.fastq:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,54376d32aca20e937a4ec26dac228e84" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-25T11:35:05.857145" + }, + "Should run without failures": { + "content": [ + { + "0": [ + [ + [ + + ], + "test_1.fastq:md5,4161df271f9bfcd25d5845a1e220dbec" + ] + ], + "1": [ + "versions.yml:md5,54376d32aca20e937a4ec26dac228e84" + ], + "gunzip": [ + [ + [ + + ], + "test_1.fastq:md5,4161df271f9bfcd25d5845a1e220dbec" + ] + ], + "versions": [ + "versions.yml:md5,54376d32aca20e937a4ec26dac228e84" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2023-10-17T15:35:37.690477896" + }, + "Should run without failures - prefix": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.xyz.fastq:md5,4161df271f9bfcd25d5845a1e220dbec" + ] + ], + "1": [ + "versions.yml:md5,54376d32aca20e937a4ec26dac228e84" + ], + "gunzip": [ + [ + { + "id": "test" + }, + "test.xyz.fastq:md5,4161df271f9bfcd25d5845a1e220dbec" + ] + ], + "versions": [ + "versions.yml:md5,54376d32aca20e937a4ec26dac228e84" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-25T11:33:32.921739" + } +} \ No newline at end of file diff --git a/modules/nf-core/gunzip/tests/nextflow.config b/modules/nf-core/gunzip/tests/nextflow.config new file mode 100644 index 00000000..dec77642 --- /dev/null +++ b/modules/nf-core/gunzip/tests/nextflow.config @@ -0,0 +1,5 @@ +process { + withName: GUNZIP { + ext.prefix = { "${meta.id}.xyz" } + } +} diff --git a/modules/nf-core/gunzip/tests/tags.yml b/modules/nf-core/gunzip/tests/tags.yml new file mode 100644 index 00000000..fd3f6915 --- /dev/null +++ b/modules/nf-core/gunzip/tests/tags.yml @@ -0,0 +1,2 @@ +gunzip: + - modules/nf-core/gunzip/** diff --git a/modules/nf-core/kaiju/kaiju/environment.yml b/modules/nf-core/kaiju/kaiju/environment.yml index baac450b..3bb316c1 100644 --- a/modules/nf-core/kaiju/kaiju/environment.yml +++ b/modules/nf-core/kaiju/kaiju/environment.yml @@ -1,7 +1,5 @@ -name: kaiju_kaiju channels: - conda-forge - bioconda - - defaults dependencies: - bioconda::kaiju=1.10.0 diff --git a/modules/nf-core/kaiju/kaiju2krona/environment.yml b/modules/nf-core/kaiju/kaiju2krona/environment.yml index 2905be97..3bb316c1 100644 --- a/modules/nf-core/kaiju/kaiju2krona/environment.yml +++ b/modules/nf-core/kaiju/kaiju2krona/environment.yml @@ -1,7 +1,5 @@ -name: kaiju_kaiju2krona channels: - conda-forge - bioconda - - defaults dependencies: - bioconda::kaiju=1.10.0 diff --git a/modules/nf-core/kaiju/kaiju2krona/main.nf b/modules/nf-core/kaiju/kaiju2krona/main.nf index 85d2dfd2..d75a23d9 100644 --- a/modules/nf-core/kaiju/kaiju2krona/main.nf +++ b/modules/nf-core/kaiju/kaiju2krona/main.nf @@ -49,4 +49,3 @@ process KAIJU_KAIJU2KRONA { END_VERSIONS """ } - diff --git a/modules/nf-core/kaiju/kaiju2table/environment.yml b/modules/nf-core/kaiju/kaiju2table/environment.yml index 18685f41..3bb316c1 100644 --- a/modules/nf-core/kaiju/kaiju2table/environment.yml +++ b/modules/nf-core/kaiju/kaiju2table/environment.yml @@ -1,7 +1,5 @@ -name: kaiju_kaiju2table channels: - conda-forge - bioconda - - defaults dependencies: - bioconda::kaiju=1.10.0 diff --git a/modules/nf-core/kmcp/profile/environment.yml b/modules/nf-core/kmcp/profile/environment.yml index 43de2a64..ae5b9202 100644 --- a/modules/nf-core/kmcp/profile/environment.yml +++ b/modules/nf-core/kmcp/profile/environment.yml @@ -1,7 +1,5 @@ -name: kmcp_profile channels: - conda-forge - bioconda - - defaults dependencies: - bioconda::kmcp=0.9.4 diff --git a/modules/nf-core/kmcp/profile/tests/main.nf.test.snap b/modules/nf-core/kmcp/profile/tests/main.nf.test.snap index 72b41ce8..f4a05eab 100644 --- a/modules/nf-core/kmcp/profile/tests/main.nf.test.snap +++ b/modules/nf-core/kmcp/profile/tests/main.nf.test.snap @@ -30,9 +30,9 @@ ], "meta": { "nf-test": "0.8.4", - "nextflow": "24.04.2" + "nextflow": "24.04.3" }, - "timestamp": "2024-06-07T15:36:20.331533599" + "timestamp": "2024-07-10T15:07:59.876784" }, "sarscov2 - fasta": { "content": [ diff --git a/modules/nf-core/kmcp/search/environment.yml b/modules/nf-core/kmcp/search/environment.yml index 397fcb8a..ae5b9202 100644 --- a/modules/nf-core/kmcp/search/environment.yml +++ b/modules/nf-core/kmcp/search/environment.yml @@ -1,7 +1,5 @@ -name: kmcp_search channels: - conda-forge - bioconda - - defaults dependencies: - bioconda::kmcp=0.9.4 diff --git a/modules/nf-core/kraken2/kraken2/environment.yml b/modules/nf-core/kraken2/kraken2/environment.yml new file mode 100644 index 00000000..ba776d31 --- /dev/null +++ b/modules/nf-core/kraken2/kraken2/environment.yml @@ -0,0 +1,7 @@ +channels: + - conda-forge + - bioconda +dependencies: + - "bioconda::kraken2=2.1.3" + - "coreutils=9.4" + - "pigz=2.8" diff --git a/modules/nf-core/kraken2/kraken2/main.nf b/modules/nf-core/kraken2/kraken2/main.nf index da8d8c6d..364a6fe2 100644 --- a/modules/nf-core/kraken2/kraken2/main.nf +++ b/modules/nf-core/kraken2/kraken2/main.nf @@ -2,10 +2,10 @@ process KRAKEN2_KRAKEN2 { tag "$meta.id" label 'process_high' - conda "bioconda::kraken2=2.1.2 conda-forge::pigz=2.6" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-5799ab18b5fc681e75923b2450abaa969907ec98:87fc08d11968d081f3e8a37131c1f1f6715b6542-0' : - 'biocontainers/mulled-v2-5799ab18b5fc681e75923b2450abaa969907ec98:87fc08d11968d081f3e8a37131c1f1f6715b6542-0' }" + 'https://depot.galaxyproject.org/singularity/mulled-v2-8706a1dd73c6cc426e12dd4dd33a5e917b3989ae:c8cbdc8ff4101e6745f8ede6eb5261ef98bdaff4-0' : + 'biocontainers/mulled-v2-8706a1dd73c6cc426e12dd4dd33a5e917b3989ae:c8cbdc8ff4101e6745f8ede6eb5261ef98bdaff4-0' }" input: tuple val(meta), path(reads) @@ -55,4 +55,31 @@ process KRAKEN2_KRAKEN2 { pigz: \$( pigz --version 2>&1 | sed 's/pigz //g' ) END_VERSIONS """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def paired = meta.single_end ? "" : "--paired" + def classified = meta.single_end ? "${prefix}.classified.fastq.gz" : "${prefix}.classified_1.fastq.gz ${prefix}.classified_2.fastq.gz" + def unclassified = meta.single_end ? "${prefix}.unclassified.fastq.gz" : "${prefix}.unclassified_1.fastq.gz ${prefix}.unclassified_2.fastq.gz" + def readclassification_option = save_reads_assignment ? "--output ${prefix}.kraken2.classifiedreads.txt" : "--output /dev/null" + def compress_reads_command = save_output_fastqs ? "pigz -p $task.cpus *.fastq" : "" + + """ + touch ${prefix}.kraken2.report.txt + if [ "$save_output_fastqs" == "true" ]; then + touch $classified + touch $unclassified + fi + if [ "$save_reads_assignment" == "true" ]; then + touch ${prefix}.kraken2.classifiedreads.txt + fi + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + kraken2: \$(echo \$(kraken2 --version 2>&1) | sed 's/^.*Kraken version //; s/ .*\$//') + pigz: \$( pigz --version 2>&1 | sed 's/pigz //g' ) + END_VERSIONS + """ + } diff --git a/modules/nf-core/kraken2/kraken2/meta.yml b/modules/nf-core/kraken2/kraken2/meta.yml index 4721f45b..7909ffe7 100644 --- a/modules/nf-core/kraken2/kraken2/meta.yml +++ b/modules/nf-core/kraken2/kraken2/meta.yml @@ -73,3 +73,6 @@ output: authors: - "@joseespinosa" - "@drpatelh" +maintainers: + - "@joseespinosa" + - "@drpatelh" diff --git a/modules/nf-core/kraken2/kraken2/tests/main.nf.test b/modules/nf-core/kraken2/kraken2/tests/main.nf.test new file mode 100644 index 00000000..c0843df2 --- /dev/null +++ b/modules/nf-core/kraken2/kraken2/tests/main.nf.test @@ -0,0 +1,143 @@ +nextflow_process { + name "Test Process KRAKEN2_KRAKEN2" + script "../main.nf" + process "KRAKEN2_KRAKEN2" + tag "modules" + tag "modules_nfcore" + tag "untar" + tag "kraken2" + tag "kraken2/kraken2" + + setup { + run("UNTAR") { + script "modules/nf-core/untar/main.nf" + process { + """ + input[0] = Channel.of([ + [], + file( + params.modules_testdata_base_path + "genomics/sarscov2/genome/db/kraken2.tar.gz", + checkIfExists: true + ) + ]) + """ + } + } + } + + test("sarscov2 illumina single end [fastq]") { + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + [ file( + params.modules_testdata_base_path + "genomics/sarscov2/illumina/fastq/test_1.fastq.gz", + checkIfExists: true + )] + ] + input[1] = UNTAR.out.untar.map{ it[1] } + input[2] = true + input[3] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + process.out.report, + process.out.versions, + ).match() + }, + { assert process.out.classified_reads_fastq.get(0).get(1) ==~ ".*/test.classified.fastq.gz" }, + { assert process.out.unclassified_reads_fastq.get(0).get(1) ==~ ".*/test.unclassified.fastq.gz" }, + ) + } + } + + test("sarscov2 illumina paired end [fastq]") { + when { + params { + outdir = "$outputDir" + } + + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + [ + file( + params.modules_testdata_base_path + "genomics/sarscov2/illumina/fastq/test_1.fastq.gz", + checkIfExists: true + ), + file( + params.modules_testdata_base_path + "genomics/sarscov2/illumina/fastq/test_2.fastq.gz", + checkIfExists: true + ) + + ] + ] + input[1] = UNTAR.out.untar.map{ it[1] } + input[2] = true + input[3] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + process.out.report, + process.out.versions, + ).match() + }, + { assert process.out.classified_reads_fastq.get(0).get(1).get(0) + ==~ ".*/test.classified_1.fastq.gz" }, + { assert process.out.classified_reads_fastq.get(0).get(1).get(1) + ==~ ".*/test.classified_2.fastq.gz" }, + { assert process.out.unclassified_reads_fastq.get(0).get(1).get(0) + ==~ ".*/test.unclassified_1.fastq.gz" }, + { assert process.out.unclassified_reads_fastq.get(0).get(1).get(1) + ==~ ".*/test.unclassified_2.fastq.gz" }, + ) + } + } + + test("sarscov2 illumina single end [fastq] + save_reads_assignment") { + when { + params { + outdir = "$outputDir" + } + + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + [ file( + params.modules_testdata_base_path + "genomics/sarscov2/illumina/fastq/test_1.fastq.gz", + checkIfExists: true + )] + ] + input[1] = UNTAR.out.untar.map{ it[1] } + input[2] = false + input[3] = true + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + process.out.report, + process.out.classified_reads_assignment, + process.out.versions, + ).match() + }, + ) + } + } +} diff --git a/modules/nf-core/kraken2/kraken2/tests/main.nf.test.snap b/modules/nf-core/kraken2/kraken2/tests/main.nf.test.snap new file mode 100644 index 00000000..b432f878 --- /dev/null +++ b/modules/nf-core/kraken2/kraken2/tests/main.nf.test.snap @@ -0,0 +1,74 @@ +{ + "sarscov2 illumina single end [fastq]": { + "content": [ + [ + [ + { + "id": "test", + "single_end": true + }, + "test.kraken2.report.txt:md5,4227755fe40478b8d7dc8634b489761e" + ] + ], + [ + "versions.yml:md5,79adf2ca1cfc625cb77e391b27142c43" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-04-04T18:47:03.745692" + }, + "sarscov2 illumina paired end [fastq]": { + "content": [ + [ + [ + { + "id": "test", + "single_end": false + }, + "test.kraken2.report.txt:md5,4227755fe40478b8d7dc8634b489761e" + ] + ], + [ + "versions.yml:md5,79adf2ca1cfc625cb77e391b27142c43" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-04-04T18:47:13.75649" + }, + "sarscov2 illumina single end [fastq] + save_reads_assignment": { + "content": [ + [ + [ + { + "id": "test", + "single_end": true + }, + "test.kraken2.report.txt:md5,4227755fe40478b8d7dc8634b489761e" + ] + ], + [ + [ + { + "id": "test", + "single_end": true + }, + "test.kraken2.classifiedreads.txt:md5,e7a90531f0d8d777316515c36fe4cae0" + ] + ], + [ + "versions.yml:md5,79adf2ca1cfc625cb77e391b27142c43" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-04-04T18:47:22.459465" + } +} \ No newline at end of file diff --git a/modules/nf-core/kraken2/kraken2/tests/tags.yml b/modules/nf-core/kraken2/kraken2/tests/tags.yml new file mode 100644 index 00000000..9ebfd7ab --- /dev/null +++ b/modules/nf-core/kraken2/kraken2/tests/tags.yml @@ -0,0 +1,3 @@ +kraken2/kraken2: + - modules/nf-core/kraken2/kraken2/** + - modules/nf-core/untar/** diff --git a/modules/nf-core/krakentools/combinekreports/environment.yml b/modules/nf-core/krakentools/combinekreports/environment.yml new file mode 100644 index 00000000..13814bc2 --- /dev/null +++ b/modules/nf-core/krakentools/combinekreports/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::krakentools=1.2 diff --git a/modules/nf-core/krakentools/combinekreports/main.nf b/modules/nf-core/krakentools/combinekreports/main.nf index 43cc3793..6799258b 100644 --- a/modules/nf-core/krakentools/combinekreports/main.nf +++ b/modules/nf-core/krakentools/combinekreports/main.nf @@ -1,7 +1,7 @@ process KRAKENTOOLS_COMBINEKREPORTS { label 'process_single' - conda "bioconda::krakentools=1.2" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/krakentools:1.2--pyh5e36f6f_0': 'biocontainers/krakentools:1.2--pyh5e36f6f_0' }" @@ -31,4 +31,17 @@ process KRAKENTOOLS_COMBINEKREPORTS { combine_kreports.py: ${VERSION} END_VERSIONS """ + + stub: + def args = task.ext.args ?: '' + prefix = task.ext.prefix ?: "${meta.id}" + def VERSION = '1.2' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. + """ + touch ${prefix}.txt + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + combine_kreports.py: ${VERSION} + END_VERSIONS + """ } diff --git a/modules/nf-core/krakentools/combinekreports/meta.yml b/modules/nf-core/krakentools/combinekreports/meta.yml index 213fc8c6..b35d1214 100644 --- a/modules/nf-core/krakentools/combinekreports/meta.yml +++ b/modules/nf-core/krakentools/combinekreports/meta.yml @@ -1,5 +1,5 @@ name: krakentools_combinekreports -description: Takes a Kraken report file and prints out a krona-compatible TEXT file +description: Takes multiple kraken-style reports and combines them into a single report file keywords: - kraken - krakentools @@ -12,7 +12,6 @@ tools: description: KrakenTools is a suite of scripts to be used for post-analysis of Kraken/KrakenUniq/Kraken2/Bracken results. Please cite the relevant paper if using KrakenTools with any of the listed programs. homepage: https://github.com/jenniferlu717/KrakenTools licence: ["GPL v3"] - input: - meta: type: map @@ -23,7 +22,6 @@ input: type: file description: List of kraken-style report files pattern: "*.{txt,kreport}" - output: - meta: type: map @@ -38,6 +36,7 @@ output: type: file description: Combined kreport file of all input files pattern: "*.txt" - authors: - "@jfy133" +maintainers: + - "@jfy133" diff --git a/modules/nf-core/krakentools/combinekreports/tests/main.nf.test b/modules/nf-core/krakentools/combinekreports/tests/main.nf.test new file mode 100644 index 00000000..b287e53b --- /dev/null +++ b/modules/nf-core/krakentools/combinekreports/tests/main.nf.test @@ -0,0 +1,55 @@ +nextflow_process { + + name "Test Process KRAKENTOOLS_COMBINEKREPORTS" + script "../main.nf" + process "KRAKENTOOLS_COMBINEKREPORTS" + + tag "modules" + tag "modules_nfcore" + tag "krakentools" + tag "krakentools/combinekreports" + + test ("sarscov2 - metagenome - kraken report") { + + when { + process { + """ + input[0] = Channel.of([ + [id: 'test'], + file(params.modules_testdata_base_path + 'genomics/sarscov2/metagenome/test_1.kraken2.report.txt', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot ( process.out ).match() } + ) + } + + } + + test ("sarscov2 - metagenome - kraken report - stub") { + + options '-stub' + when { + process { + """ + input[0] = Channel.of([ + [id: 'test'], + file(params.modules_testdata_base_path + 'genomics/sarscov2/metagenome/test_1.kraken2.report.txt', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot ( process.out ).match() } + ) + } + } +} diff --git a/modules/nf-core/krakentools/combinekreports/tests/main.nf.test.snap b/modules/nf-core/krakentools/combinekreports/tests/main.nf.test.snap new file mode 100644 index 00000000..439f27cb --- /dev/null +++ b/modules/nf-core/krakentools/combinekreports/tests/main.nf.test.snap @@ -0,0 +1,68 @@ +{ + "sarscov2 - metagenome - kraken report": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.txt:md5,481c4b987b922979baf74f2ce8d88b02" + ] + ], + "1": [ + "versions.yml:md5,a907962abbd9f5dcd34c9e8a4e6100d0" + ], + "txt": [ + [ + { + "id": "test" + }, + "test.txt:md5,481c4b987b922979baf74f2ce8d88b02" + ] + ], + "versions": [ + "versions.yml:md5,a907962abbd9f5dcd34c9e8a4e6100d0" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.1" + }, + "timestamp": "2024-08-07T09:12:42.382189" + }, + "sarscov2 - metagenome - kraken report - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,a907962abbd9f5dcd34c9e8a4e6100d0" + ], + "txt": [ + [ + { + "id": "test" + }, + "test.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,a907962abbd9f5dcd34c9e8a4e6100d0" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.1" + }, + "timestamp": "2024-08-07T09:12:46.705759" + } +} diff --git a/modules/nf-core/krakentools/combinekreports/tests/tags.yml b/modules/nf-core/krakentools/combinekreports/tests/tags.yml new file mode 100644 index 00000000..28911778 --- /dev/null +++ b/modules/nf-core/krakentools/combinekreports/tests/tags.yml @@ -0,0 +1,2 @@ +krakentools/combinekreports: + - "modules/nf-core/krakentools/combinekreports/**" diff --git a/modules/nf-core/krakentools/kreport2krona/environment.yml b/modules/nf-core/krakentools/kreport2krona/environment.yml new file mode 100644 index 00000000..13814bc2 --- /dev/null +++ b/modules/nf-core/krakentools/kreport2krona/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::krakentools=1.2 diff --git a/modules/nf-core/krakentools/kreport2krona/main.nf b/modules/nf-core/krakentools/kreport2krona/main.nf index a3923afe..f81dee77 100644 --- a/modules/nf-core/krakentools/kreport2krona/main.nf +++ b/modules/nf-core/krakentools/kreport2krona/main.nf @@ -3,7 +3,7 @@ process KRAKENTOOLS_KREPORT2KRONA { label 'process_single' // WARN: Version information not provided by tool on CLI. Please update version string below when bumping container versions. - conda "bioconda::krakentools=1.2" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/krakentools:1.2--pyh5e36f6f_0': 'biocontainers/krakentools:1.2--pyh5e36f6f_0' }" @@ -33,4 +33,17 @@ process KRAKENTOOLS_KREPORT2KRONA { kreport2krona.py: ${VERSION} END_VERSIONS """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def VERSION = '1.2' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. + """ + touch ${prefix}.txt + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + kreport2krona.py: ${VERSION} + END_VERSIONS + """ } diff --git a/modules/nf-core/krakentools/kreport2krona/meta.yml b/modules/nf-core/krakentools/kreport2krona/meta.yml index 2f8a163c..ae5bf2f1 100644 --- a/modules/nf-core/krakentools/kreport2krona/meta.yml +++ b/modules/nf-core/krakentools/kreport2krona/meta.yml @@ -10,7 +10,6 @@ tools: description: KrakenTools is a suite of scripts to be used for post-analysis of Kraken/KrakenUniq/Kraken2/Bracken results. Please cite the relevant paper if using KrakenTools with any of the listed programs. homepage: https://github.com/jenniferlu717/KrakenTools licence: ["GPL v3"] - input: - meta: type: map @@ -21,7 +20,6 @@ input: type: file description: Kraken report pattern: "*.{txt,kreport}" - output: - meta: type: map @@ -32,10 +30,11 @@ output: type: file description: File containing software versions pattern: "versions.yml" - - krona: + - txt: type: file description: Krona text-based input file converted from Kraken report pattern: "*.{txt,krona}" - authors: - "@MillironX" +maintainers: + - "@MillironX" diff --git a/modules/nf-core/krakentools/kreport2krona/tests/main.nf.test b/modules/nf-core/krakentools/kreport2krona/tests/main.nf.test new file mode 100644 index 00000000..1d85a0b2 --- /dev/null +++ b/modules/nf-core/krakentools/kreport2krona/tests/main.nf.test @@ -0,0 +1,85 @@ +nextflow_process { + + name "Test Process KRAKENTOOLS_KREPORT2KRONA" + script "modules/nf-core/krakentools/kreport2krona/main.nf" + process "KRAKENTOOLS_KREPORT2KRONA" + tag "modules" + tag "modules_nfcore" + tag "untar" + tag "kraken2" + tag "kraken2/kraken2" + tag "krakentools" + tag "krakentools/kreport2krona" + + setup { + run("UNTAR") { + script "modules/nf-core/untar/main.nf" + process { + """ + input[0] = Channel.of([ + [], + file( + params.modules_testdata_base_path + 'genomics/sarscov2/genome/db/kraken2.tar.gz', + checkIfExists: true + ) + ]) + """ + } + } + run("KRAKEN2_KRAKEN2") { + script "modules/nf-core/kraken2/kraken2/main.nf" + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + file( + params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', + checkIfExists: true + ) + ]) + input[1] = UNTAR.out.untar.map{ it[1] } + input[2] = false + input[3] = false + """ + } + } + } + + test("sarscov2 illumina single end [fastq]") { + + when { + process { + """ + input[0] = KRAKEN2_KRAKEN2.out.report + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("sarscov2 illumina single end [fastq] - stub") { + + options "-stub" + + when { + process { + """ + input[0] = KRAKEN2_KRAKEN2.out.report + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } +} \ No newline at end of file diff --git a/modules/nf-core/krakentools/kreport2krona/tests/main.nf.test.snap b/modules/nf-core/krakentools/kreport2krona/tests/main.nf.test.snap new file mode 100644 index 00000000..c18cee02 --- /dev/null +++ b/modules/nf-core/krakentools/kreport2krona/tests/main.nf.test.snap @@ -0,0 +1,72 @@ +{ + "sarscov2 illumina single end [fastq]": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.txt:md5,c89a9db7acbdba9dea0fe246bcaa85c1" + ] + ], + "1": [ + "versions.yml:md5,f4a5d570efec153ab0de3da130394cbb" + ], + "txt": [ + [ + { + "id": "test", + "single_end": true + }, + "test.txt:md5,c89a9db7acbdba9dea0fe246bcaa85c1" + ] + ], + "versions": [ + "versions.yml:md5,f4a5d570efec153ab0de3da130394cbb" + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "23.10.4" + }, + "timestamp": "2024-08-01T21:40:46.959343186" + }, + "sarscov2 illumina single end [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,f4a5d570efec153ab0de3da130394cbb" + ], + "txt": [ + [ + { + "id": "test", + "single_end": true + }, + "test.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,f4a5d570efec153ab0de3da130394cbb" + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "23.10.4" + }, + "timestamp": "2024-08-02T18:35:32.145822126" + } +} \ No newline at end of file diff --git a/modules/nf-core/krakentools/kreport2krona/tests/tags.yml b/modules/nf-core/krakentools/kreport2krona/tests/tags.yml new file mode 100644 index 00000000..1e582883 --- /dev/null +++ b/modules/nf-core/krakentools/kreport2krona/tests/tags.yml @@ -0,0 +1,4 @@ +krakentools/kreport2krona: + - modules/nf-core/krakentools/kreport2krona/** + - modules/nf-core/kraken2/kraken2/** + - modules/nf-core/untar/** diff --git a/modules/nf-core/krakenuniq/preloadedkrakenuniq/environment.yml b/modules/nf-core/krakenuniq/preloadedkrakenuniq/environment.yml index 11bbb879..bbf85c33 100644 --- a/modules/nf-core/krakenuniq/preloadedkrakenuniq/environment.yml +++ b/modules/nf-core/krakenuniq/preloadedkrakenuniq/environment.yml @@ -1,7 +1,5 @@ -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 78b2f3ab..d24f75d2 100644 --- a/modules/nf-core/krakenuniq/preloadedkrakenuniq/main.nf +++ b/modules/nf-core/krakenuniq/preloadedkrakenuniq/main.nf @@ -4,8 +4,8 @@ process KRAKENUNIQ_PRELOADEDKRAKENUNIQ { 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' }" + 'https://depot.galaxyproject.org/singularity/krakenuniq:1.0.4--pl5321h6dccd9a_2': + 'biocontainers/krakenuniq:1.0.4--pl5321h6dccd9a_2' }" input: tuple val(meta), path(sequences) diff --git a/modules/nf-core/krona/ktimporttaxonomy/environment.yml b/modules/nf-core/krona/ktimporttaxonomy/environment.yml new file mode 100644 index 00000000..342c5892 --- /dev/null +++ b/modules/nf-core/krona/ktimporttaxonomy/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::krona=2.8.1 diff --git a/modules/nf-core/krona/ktimporttaxonomy/main.nf b/modules/nf-core/krona/ktimporttaxonomy/main.nf index 0758a382..16f3cd98 100644 --- a/modules/nf-core/krona/ktimporttaxonomy/main.nf +++ b/modules/nf-core/krona/ktimporttaxonomy/main.nf @@ -3,10 +3,10 @@ process KRONA_KTIMPORTTAXONOMY { label 'process_single' // WARN: Version information not provided by tool on CLI. Please update version string below when bumping container versions. - conda "bioconda::krona=2.8" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/krona:2.8--pl5262hdfd78af_2' : - 'biocontainers/krona:2.8--pl5262hdfd78af_2' }" + 'https://depot.galaxyproject.org/singularity/krona:2.8.1--pl5321hdfd78af_1': + 'biocontainers/krona:2.8.1--pl5321hdfd78af_1' }" input: tuple val(meta), path(report) @@ -22,7 +22,7 @@ process KRONA_KTIMPORTTAXONOMY { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" - def VERSION = '2.8' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. + def VERSION = '2.8.1' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. """ TAXONOMY=\$(find -L . -name '*.tab' -exec dirname {} \\;) echo \$TAXONOMY @@ -38,4 +38,17 @@ process KRONA_KTIMPORTTAXONOMY { krona: $VERSION END_VERSIONS """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def VERSION = '2.8.1' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. + """ + touch ${prefix}.html + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + krona: $VERSION + END_VERSIONS + """ } diff --git a/modules/nf-core/krona/ktimporttaxonomy/meta.yml b/modules/nf-core/krona/ktimporttaxonomy/meta.yml index dfcd2f2b..3504b13e 100644 --- a/modules/nf-core/krona/ktimporttaxonomy/meta.yml +++ b/modules/nf-core/krona/ktimporttaxonomy/meta.yml @@ -13,14 +13,13 @@ tools: homepage: https://github.com/marbl/Krona/wiki/KronaTools documentation: http://manpages.ubuntu.com/manpages/impish/man1/ktImportTaxonomy.1.html doi: 10.1186/1471-2105-12-385 - input: - meta: type: map description: | Groovy Map containing sample information e.g. [ id:'test'] - - database: + - taxonomy: type: file description: | Path to a Krona taxonomy .tab file normally downloaded and generated by @@ -31,7 +30,6 @@ input: type: file description: "A tab-delimited file with taxonomy IDs and (optionally) query IDs, magnitudes, and scores. Query IDs are taken from column 1, taxonomy IDs from column 2, and scores from column 3. Lines beginning with # will be ignored." pattern: "*.{tsv}" - output: - versions: type: file @@ -41,6 +39,7 @@ output: type: file description: A html file containing an interactive krona plot. pattern: "*.{html}" - authors: - "@mjakobs" +maintainers: + - "@mjakobs" diff --git a/modules/nf-core/krona/ktimporttaxonomy/tests/main.nf.test b/modules/nf-core/krona/ktimporttaxonomy/tests/main.nf.test new file mode 100644 index 00000000..1068f305 --- /dev/null +++ b/modules/nf-core/krona/ktimporttaxonomy/tests/main.nf.test @@ -0,0 +1,61 @@ +nextflow_process { + + name "Test Process KRONA_KTIMPORTTAXONOMY" + script "../main.nf" + process "KRONA_KTIMPORTTAXONOMY" + + tag "modules" + tag "modules_nfcore" + tag "krona" + tag "krona/ktimporttaxonomy" + + test ("sarscov2 - metagenome - kraken report") { + + when { + process { + """ + input[0] = Channel.of([ + [id: 'test'], + file(params.modules_testdata_base_path + 'genomics/sarscov2/metagenome/test_1.kraken2.report.txt', checkIfExists: true) + ]) + input[1] = Channel.of([ + file(params.modules_testdata_base_path + 'genomics/sarscov2/metagenome/krona_taxonomy.tab', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot ( process.out.versions ).match() }, + { assert file(process.out.html.get(0).get(1)).exists() } + ) + } + } + + test ("sarscov2 - metagenome - kraken report - stub") { + + options '-stub' + when { + process { + """ + input[0] = Channel.of([ + [id: 'test'], + file(params.modules_testdata_base_path + 'genomics/sarscov2/metagenome/test_1.kraken2.report.txt', checkIfExists: true) + ]) + input[1] = Channel.of([ + file(params.modules_testdata_base_path + 'genomics/sarscov2/metagenome/krona_taxonomy.tab', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() }, + ) + } + } +} diff --git a/modules/nf-core/krona/ktimporttaxonomy/tests/main.nf.test.snap b/modules/nf-core/krona/ktimporttaxonomy/tests/main.nf.test.snap new file mode 100644 index 00000000..61fba868 --- /dev/null +++ b/modules/nf-core/krona/ktimporttaxonomy/tests/main.nf.test.snap @@ -0,0 +1,47 @@ +{ + "sarscov2 - metagenome - kraken report": { + "content": [ + [ + "versions.yml:md5,59fc89b6db8fad0aa9aa06f7437a18a7" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.1" + }, + "timestamp": "2024-08-08T10:34:23.760055" + }, + "sarscov2 - metagenome - kraken report - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,59fc89b6db8fad0aa9aa06f7437a18a7" + ], + "html": [ + [ + { + "id": "test" + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,59fc89b6db8fad0aa9aa06f7437a18a7" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.1" + }, + "timestamp": "2024-08-08T10:34:29.695251" + } +} diff --git a/modules/nf-core/krona/ktimporttaxonomy/tests/tags.yml b/modules/nf-core/krona/ktimporttaxonomy/tests/tags.yml new file mode 100644 index 00000000..1112970e --- /dev/null +++ b/modules/nf-core/krona/ktimporttaxonomy/tests/tags.yml @@ -0,0 +1,2 @@ +krona/ktimporttaxonomy: + - "modules/nf-core/krona/ktimporttaxonomy/**" diff --git a/modules/nf-core/krona/ktimporttext/environment.yml b/modules/nf-core/krona/ktimporttext/environment.yml new file mode 100644 index 00000000..342c5892 --- /dev/null +++ b/modules/nf-core/krona/ktimporttext/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::krona=2.8.1 diff --git a/modules/nf-core/krona/ktimporttext/main.nf b/modules/nf-core/krona/ktimporttext/main.nf index 43280191..945f8570 100644 --- a/modules/nf-core/krona/ktimporttext/main.nf +++ b/modules/nf-core/krona/ktimporttext/main.nf @@ -2,7 +2,7 @@ process KRONA_KTIMPORTTEXT { tag "$meta.id" label 'process_single' - conda "bioconda::krona=2.8.1" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/krona:2.8.1--pl5321hdfd78af_1': 'biocontainers/krona:2.8.1--pl5321hdfd78af_1' }" @@ -31,4 +31,16 @@ process KRONA_KTIMPORTTEXT { krona: \$( echo \$(ktImportText 2>&1) | sed 's/^.*KronaTools //g; s/- ktImportText.*\$//g') END_VERSIONS """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.html + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + krona: \$( echo \$(ktImportText 2>&1) | sed 's/^.*KronaTools //g; s/- ktImportText.*\$//g') + END_VERSIONS + """ } diff --git a/modules/nf-core/krona/ktimporttext/meta.yml b/modules/nf-core/krona/ktimporttext/meta.yml index a7108e0d..5288ea0b 100644 --- a/modules/nf-core/krona/ktimporttext/meta.yml +++ b/modules/nf-core/krona/ktimporttext/meta.yml @@ -15,8 +15,7 @@ tools: documentation: http://manpages.ubuntu.com/manpages/impish/man1/ktImportTaxonomy.1.html tool_dev_url: https://github.com/marbl/Krona doi: 10.1186/1471-2105-12-385 - licence: https://raw.githubusercontent.com/marbl/Krona/master/KronaTools/LICENSE.txt - + licence: ["https://raw.githubusercontent.com/marbl/Krona/master/KronaTools/LICENSE.txt"] input: - meta: type: map @@ -27,7 +26,6 @@ input: type: file description: "Tab-delimited text file. Each line should be a number followed by a list of wedges to contribute to (starting from the highest level). If no wedges are listed (and just a quantity is given), it will contribute to the top level. If the same lineage is listed more than once, the values will be added. Quantities can be omitted if -q is specified. Lines beginning with '#' will be ignored." pattern: "*.{txt}" - output: - meta: type: map @@ -42,6 +40,7 @@ output: type: file description: A html file containing an interactive krona plot. pattern: "*.{html}" - authors: - "@jianhong" +maintainers: + - "@jianhong" diff --git a/modules/nf-core/krona/ktimporttext/tests/main.nf.test b/modules/nf-core/krona/ktimporttext/tests/main.nf.test new file mode 100644 index 00000000..79b4ce90 --- /dev/null +++ b/modules/nf-core/krona/ktimporttext/tests/main.nf.test @@ -0,0 +1,54 @@ +nextflow_process { + + name "Test Process KRONA_KTIMPORTTEXT" + script "../main.nf" + process "KRONA_KTIMPORTTEXT" + tag "modules" + tag "modules_nfcore" + tag "krona" + tag "krona/ktimporttext" + + test ("sarscov2 - metagenome - kraken report") { + + when { + process { + """ + input[0] = Channel.of([ + [id: 'test'], + file(params.modules_testdata_base_path + 'genomics/sarscov2/metagenome/test_1.kraken2.report.txt', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot ( process.out.versions ).match() }, + { assert file(process.out.html.get(0).get(1)).exists() } + ) + } + } + + test ("sarscov2 - metagenome - kraken report - stub") { + + options '-stub' + when { + process { + """ + input[0] = Channel.of([ + [id: 'test'], + file(params.modules_testdata_base_path + 'genomics/sarscov2/metagenome/test_1.kraken2.report.txt', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() }, + ) + } + } +} diff --git a/modules/nf-core/krona/ktimporttext/tests/main.nf.test.snap b/modules/nf-core/krona/ktimporttext/tests/main.nf.test.snap new file mode 100644 index 00000000..3a3c3803 --- /dev/null +++ b/modules/nf-core/krona/ktimporttext/tests/main.nf.test.snap @@ -0,0 +1,47 @@ +{ + "sarscov2 - metagenome - kraken report": { + "content": [ + [ + "versions.yml:md5,b8847bf9b5b00d34a38cf6f774c4c5db" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.1" + }, + "timestamp": "2024-08-08T10:51:50.077935" + }, + "sarscov2 - metagenome - kraken report - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,b8847bf9b5b00d34a38cf6f774c4c5db" + ], + "html": [ + [ + { + "id": "test" + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,b8847bf9b5b00d34a38cf6f774c4c5db" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.1" + }, + "timestamp": "2024-08-08T10:51:56.690617" + } +} diff --git a/modules/nf-core/krona/ktimporttext/tests/tags.yml b/modules/nf-core/krona/ktimporttext/tests/tags.yml new file mode 100644 index 00000000..d1b04dfc --- /dev/null +++ b/modules/nf-core/krona/ktimporttext/tests/tags.yml @@ -0,0 +1,2 @@ +krona/ktimporttext: + - "modules/nf-core/krona/ktimporttext/**" diff --git a/modules/nf-core/malt/run/environment.yml b/modules/nf-core/malt/run/environment.yml new file mode 100644 index 00000000..15a77500 --- /dev/null +++ b/modules/nf-core/malt/run/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::malt=0.61 diff --git a/modules/nf-core/malt/run/main.nf b/modules/nf-core/malt/run/main.nf index 3ece2a45..d2ddd8aa 100644 --- a/modules/nf-core/malt/run/main.nf +++ b/modules/nf-core/malt/run/main.nf @@ -2,7 +2,7 @@ process MALT_RUN { tag "$meta.id" label 'process_high' - conda "bioconda::malt=0.61" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/malt:0.61--hdfd78af_0' : 'biocontainers/malt:0.61--hdfd78af_0' }" @@ -12,10 +12,10 @@ process MALT_RUN { path index output: - tuple val(meta), path("*.rma6") , emit: rma6 - tuple val(meta), path("*.{tab,text,sam}"), optional:true, emit: alignments - tuple val(meta), path("*.log") , emit: log - path "versions.yml" , emit: versions + tuple val(meta), path("*.rma6") , emit: rma6 + tuple val(meta), path("*.{tab,text,sam,tab.gz,text.gz,sam.gz}"), optional:true, emit: alignments + tuple val(meta), path("*.log") , emit: log + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when @@ -23,7 +23,6 @@ process MALT_RUN { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" - """ malt-run \\ -t $task.cpus \\ @@ -38,4 +37,18 @@ process MALT_RUN { malt: \$(malt-run --help 2>&1 | grep -o 'version.* ' | cut -f 1 -d ',' | cut -f2 -d ' ') END_VERSIONS """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}-malt-run.log + touch ${prefix}.rma6 + touch ${prefix}.sam + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + malt: \$(malt-run --help 2>&1 | grep -o 'version.* ' | cut -f 1 -d ',' | cut -f2 -d ' ') + END_VERSIONS + """ } diff --git a/modules/nf-core/malt/run/meta.yml b/modules/nf-core/malt/run/meta.yml index f5ee655a..5bb7d9b3 100644 --- a/modules/nf-core/malt/run/meta.yml +++ b/modules/nf-core/malt/run/meta.yml @@ -14,10 +14,8 @@ tools: description: A tool for mapping metagenomic data homepage: https://www.wsi.uni-tuebingen.de/lehrstuehle/algorithms-in-bioinformatics/software/malt/ documentation: https://software-ab.cs.uni-tuebingen.de/download/malt/manual.pdf - doi: "10.1038/s41559-017-0446-6" licence: ["GPL v3"] - input: - meta: type: map @@ -41,7 +39,7 @@ output: type: file description: MEGAN6 RMA6 file pattern: "*.rma6" - - sam: + - alignments: type: file description: Alignment files in Tab, Text or MEGAN-compatible SAM format pattern: "*.{tab,txt,sam}" @@ -49,6 +47,7 @@ output: type: file description: Log of verbose MALT stdout pattern: "*-malt-run.log" - authors: - "@jfy133" +maintainers: + - "@jfy133" diff --git a/modules/nf-core/malt/run/tests/main.nf.test b/modules/nf-core/malt/run/tests/main.nf.test new file mode 100644 index 00000000..304c01d4 --- /dev/null +++ b/modules/nf-core/malt/run/tests/main.nf.test @@ -0,0 +1,94 @@ +nextflow_process { + + name "Test Process MALT_RUN" + script "../main.nf" + process "MALT_RUN" + config './nextflow.config' + + tag "modules" + tag "modules_nfcore" + tag "malt" + tag "malt/run" + tag "malt/build" + tag "unzip" + + setup { + run("UNZIP") { + script "../../../unzip/main.nf" + process { + """ + input[0] = [[], file("s3://ngi-igenomes/test-data/createtaxdb/taxonomy/megan-nucl-Feb2022.db.zip", checkIfExists: true)] + """ + } + } + run("MALT_BUILD") { + script "../../../malt/build/main.nf" + process { + """ + input[0] = file(params.modules_testdata_base_path + "genomics/sarscov2/genome/genome.fasta", checkIfExists: true) + input[1] = [] + input[2] = UNZIP.out.unzipped_archive.map { it[1] } + """ + } + } + } + + test("sarscov2 - fastq") { + + when { + process { + """ + input[0] = [ + [ id:'test_1', single_end:false ], + [ + file(params.modules_testdata_base_path + "genomics/sarscov2/illumina/fastq/test_1.fastq.gz", checkIfExists: true) + ] + ] + input[1] = MALT_BUILD.out.index + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + process.out.alignments, + process.out.versions, + file(process.out.rma6[0][1]).name + ).match() + }, + { assert path(process.out.log[0][1]).readLines().last().contains("Peak memory") }, + ) + } + + } + + test("sarscov2 - fastq - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test_1', single_end:false ], + [ + file(params.modules_testdata_base_path + "genomics/sarscov2/illumina/fastq/test_1.fastq.gz", checkIfExists: true) + ] + ] + input[1] = MALT_BUILD.out.index + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + +} diff --git a/modules/nf-core/malt/run/tests/main.nf.test.snap b/modules/nf-core/malt/run/tests/main.nf.test.snap new file mode 100644 index 00000000..5a6c7a21 --- /dev/null +++ b/modules/nf-core/malt/run/tests/main.nf.test.snap @@ -0,0 +1,95 @@ +{ + "sarscov2 - fastq - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test_1", + "single_end": false + }, + "test_1.rma6:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test_1", + "single_end": false + }, + "test_1.sam:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + { + "id": "test_1", + "single_end": false + }, + "test_1-malt-run.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "3": [ + "versions.yml:md5,5b91a785e0342f9ef17a634c0452335a" + ], + "alignments": [ + [ + { + "id": "test_1", + "single_end": false + }, + "test_1.sam:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "log": [ + [ + { + "id": "test_1", + "single_end": false + }, + "test_1-malt-run.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "rma6": [ + [ + { + "id": "test_1", + "single_end": false + }, + "test_1.rma6:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,5b91a785e0342f9ef17a634c0452335a" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-01-26T14:15:43.18685293" + }, + "sarscov2 - fastq": { + "content": [ + [ + [ + { + "id": "test_1", + "single_end": false + }, + "test_1.blastn.sam.gz:md5,8ad56803c1674e1a8cd42fe8801e71fd" + ] + ], + [ + "versions.yml:md5,5b91a785e0342f9ef17a634c0452335a" + ], + "test_1.rma6" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-30T07:04:07.674069223" + } +} \ No newline at end of file diff --git a/modules/nf-core/malt/run/tests/nextflow.config b/modules/nf-core/malt/run/tests/nextflow.config new file mode 100644 index 00000000..34fc9b7e --- /dev/null +++ b/modules/nf-core/malt/run/tests/nextflow.config @@ -0,0 +1,13 @@ +process { + + + withName: MALT_RUN { + ext.args = "-m BlastN -J-Xmx8G -a . -f SAM" + memory = 12.GB + } + + withName: MALT_BUILD { + ext.args = "--sequenceType DNA" + } + +} diff --git a/modules/nf-core/malt/run/tests/tags.yml b/modules/nf-core/malt/run/tests/tags.yml new file mode 100644 index 00000000..a5d6b55f --- /dev/null +++ b/modules/nf-core/malt/run/tests/tags.yml @@ -0,0 +1,2 @@ +malt/run: + - "modules/nf-core/malt/run/**" diff --git a/modules/nf-core/megan/rma2info/environment.yml b/modules/nf-core/megan/rma2info/environment.yml index 471e5507..520b771d 100644 --- a/modules/nf-core/megan/rma2info/environment.yml +++ b/modules/nf-core/megan/rma2info/environment.yml @@ -1,6 +1,5 @@ channels: - conda-forge - bioconda - - defaults dependencies: - - bioconda::megan=6.21.7 + - bioconda::megan=6.25.9 diff --git a/modules/nf-core/megan/rma2info/main.nf b/modules/nf-core/megan/rma2info/main.nf index e91af504..c132bf04 100644 --- a/modules/nf-core/megan/rma2info/main.nf +++ b/modules/nf-core/megan/rma2info/main.nf @@ -2,10 +2,10 @@ process MEGAN_RMA2INFO { tag "$meta.id" label 'process_single' - conda 'modules/nf-core/megan/rma2info/environment.yml' + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/megan:6.24.20--h9ee0642_0': - 'biocontainers/megan:6.24.20--h9ee0642_0' }" + 'https://depot.galaxyproject.org/singularity/megan:6.25.9--h9ee0642_0': + 'biocontainers/megan:6.25.9--h9ee0642_0' }" input: tuple val(meta), path(rma6) @@ -35,4 +35,17 @@ process MEGAN_RMA2INFO { megan: \$(echo \$(rma2info 2>&1) | grep version | sed 's/.*version //g;s/, built.*//g') END_VERSIONS """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def summary = megan_summary ? "-es ${prefix}.megan" : "" + """ + echo "" | gzip > ${prefix}.txt.gz + touch ${prefix}.megan + cat <<-END_VERSIONS > versions.yml + "${task.process}": + megan: \$(echo \$(rma2info 2>&1) | grep version | sed 's/.*version //g;s/, built.*//g') + END_VERSIONSs + """ } diff --git a/modules/nf-core/megan/rma2info/meta.yml b/modules/nf-core/megan/rma2info/meta.yml index af3dd96c..158c8674 100644 --- a/modules/nf-core/megan/rma2info/meta.yml +++ b/modules/nf-core/megan/rma2info/meta.yml @@ -12,7 +12,7 @@ tools: documentation: "https://software-ab.cs.uni-tuebingen.de/download/megan6/welcome.html" tool_dev_url: "https://github.com/husonlab/megan-ce" doi: "10.1371/journal.pcbi.1004957" - licence: "['GPL >=3']" + licence: ["GPL >=3"] input: - meta: type: map diff --git a/modules/nf-core/megan/rma2info/tests/main.nf.test b/modules/nf-core/megan/rma2info/tests/main.nf.test new file mode 100644 index 00000000..3a3c807a --- /dev/null +++ b/modules/nf-core/megan/rma2info/tests/main.nf.test @@ -0,0 +1,63 @@ +nextflow_process { + + name "Test Process MEGAN_RMA2INFO" + script "../main.nf" + process "MEGAN_RMA2INFO" + + tag "modules" + tag "modules_nfcore" + tag "megan" + tag "megan/rma2info" + + test("malt - rma") { + + config "./nextflow.config" + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'delete_me/malt/test.rma6', checkIfExists: true) + ] + + input[1] = 'true' + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot ( process.out.versions ).match() }, + { assert file (process.out.txt.get(0).get(1)).exists() } + ) + } + } + + test("malt - rma - stub") { + + options "-stub" + config "./nextflow.config" + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'delete_me/malt/test.rma6', checkIfExists: true) + ] + + input[1] = 'true' + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot ( process.out ).match() }, + ) + } + } +} diff --git a/modules/nf-core/megan/rma2info/tests/main.nf.test.snap b/modules/nf-core/megan/rma2info/tests/main.nf.test.snap new file mode 100644 index 00000000..3acbaf59 --- /dev/null +++ b/modules/nf-core/megan/rma2info/tests/main.nf.test.snap @@ -0,0 +1,67 @@ +{ + "malt - rma": { + "content": [ + [ + "versions.yml:md5,b27ee982b4ec7793e8c3ff9f59e239e5" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.1" + }, + "timestamp": "2024-08-09T14:30:14.141999" + }, + "malt - rma - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.txt.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.megan:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,13888803285f4a513973f3ced50f26b9" + ], + "megan_summary": [ + [ + { + "id": "test", + "single_end": false + }, + "test.megan:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "txt": [ + [ + { + "id": "test", + "single_end": false + }, + "test.txt.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "versions": [ + "versions.yml:md5,13888803285f4a513973f3ced50f26b9" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.1" + }, + "timestamp": "2024-08-09T14:30:25.993511" + } +} diff --git a/modules/nf-core/megan/rma2info/tests/nextflow.config b/modules/nf-core/megan/rma2info/tests/nextflow.config new file mode 100644 index 00000000..23108504 --- /dev/null +++ b/modules/nf-core/megan/rma2info/tests/nextflow.config @@ -0,0 +1,3 @@ +process { + ext.args = '-c2c Taxonomy' +} diff --git a/modules/nf-core/megan/rma2info/tests/tags.yml b/modules/nf-core/megan/rma2info/tests/tags.yml new file mode 100644 index 00000000..dbbccf4c --- /dev/null +++ b/modules/nf-core/megan/rma2info/tests/tags.yml @@ -0,0 +1,2 @@ +megan/rma2info: + - "modules/nf-core/megan/rma2info/**" diff --git a/modules/nf-core/metaphlan/mergemetaphlantables/environment.yml b/modules/nf-core/metaphlan/mergemetaphlantables/environment.yml new file mode 100644 index 00000000..709ddf70 --- /dev/null +++ b/modules/nf-core/metaphlan/mergemetaphlantables/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::metaphlan=4.1.1 diff --git a/modules/nf-core/metaphlan/mergemetaphlantables/main.nf b/modules/nf-core/metaphlan/mergemetaphlantables/main.nf index 0403bee9..7e82a33c 100644 --- a/modules/nf-core/metaphlan/mergemetaphlantables/main.nf +++ b/modules/nf-core/metaphlan/mergemetaphlantables/main.nf @@ -1,10 +1,10 @@ process METAPHLAN_MERGEMETAPHLANTABLES { label 'process_single' - conda "bioconda::metaphlan=4.0.6" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/metaphlan:4.0.6--pyhca03a8a_0' : - 'biocontainers/metaphlan:4.0.6--pyhca03a8a_0' }" + 'https://depot.galaxyproject.org/singularity/metaphlan:4.1.1--pyhdfd78af_0' : + 'biocontainers/metaphlan:4.1.1--pyhdfd78af_0' }" input: tuple val(meta), path(profiles) @@ -30,4 +30,16 @@ process METAPHLAN_MERGEMETAPHLANTABLES { metaphlan: \$(metaphlan --version 2>&1 | awk '{print \$3}') END_VERSIONS """ + + stub: + def args = task.ext.args ?: '' + prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.txt + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + metaphlan: \$(metaphlan --version 2>&1 | awk '{print \$3}') + END_VERSIONS + """ } diff --git a/modules/nf-core/metaphlan/mergemetaphlantables/meta.yml b/modules/nf-core/metaphlan/mergemetaphlantables/meta.yml index 3c93964b..03aaae06 100644 --- a/modules/nf-core/metaphlan/mergemetaphlantables/meta.yml +++ b/modules/nf-core/metaphlan/mergemetaphlantables/meta.yml @@ -13,7 +13,6 @@ tools: documentation: https://github.com/biobakery/MetaPhlAn doi: "10.1038/s41587-023-01688-w" licence: ["MIT License"] - input: - meta: type: map @@ -24,7 +23,6 @@ input: type: file description: List of per-sample MetaPhlAn4 taxonomic abundance tables pattern: "*" - output: - meta: type: map @@ -39,7 +37,9 @@ output: type: file description: Combined MetaPhlAn4 table pattern: "*.txt" - authors: - "@jfy133" - "@LilyAnderssonLee" +maintainers: + - "@jfy133" + - "@LilyAnderssonLee" diff --git a/modules/nf-core/metaphlan/mergemetaphlantables/tests/main.nf.test b/modules/nf-core/metaphlan/mergemetaphlantables/tests/main.nf.test new file mode 100644 index 00000000..17e9400c --- /dev/null +++ b/modules/nf-core/metaphlan/mergemetaphlantables/tests/main.nf.test @@ -0,0 +1,79 @@ +nextflow_process { + + name "Test Process METAPHLAN_MERGEMETAPHLANTABLES" + script "../main.nf" + config "./nextflow.config" + process "METAPHLAN_MERGEMETAPHLANTABLES" + + tag "modules" + tag "modules_nfcore" + tag "untar" + tag "metaphlan" + tag "metaphlan/metaphlan" + tag "metaphlan/mergemetaphlantables" + + setup { + run("UNTAR") { + script "../../../untar/main.nf" + process { + """ + input[0] = Channel.of([ + [], + file( params.modules_testdata_base_path + 'delete_me/metaphlan4_database.tar.gz', checkIfExists: true ) + ]) + """ + } + } + run("METAPHLAN_METAPHLAN") { + script "../../../metaphlan/metaphlan/main.nf" + process { + """ + input[0] = Channel.of( + [ [ id: 'test', single_end: true], file( params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz',checkIfExists: true ) ], + [ [ id: 'test2', single_end: true], file( params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz',checkIfExists: true ) ], + ) + input[1] = UNTAR.out.untar.map{ it[1] } + """ + } + } + } + + test("sarscov2 - illumina single end [fastq]") { + + when { + process { + """ + input[0] = METAPHLAN_METAPHLAN.out.profile.map{meta, profile -> [[id: 'test'], profile]}.groupTuple() + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( process.out ).match() } + ) + } + } + + + test("sarscov2 - illumina single end [fastq] - stub") { + + options "-stub" + + when { + process { + """ + input[0] = METAPHLAN_METAPHLAN.out.profile.map{meta, profile -> [[id: 'test'], profile]}.groupTuple() + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( process.out ).match() } + ) + } + } +} diff --git a/modules/nf-core/metaphlan/mergemetaphlantables/tests/main.nf.test.snap b/modules/nf-core/metaphlan/mergemetaphlantables/tests/main.nf.test.snap new file mode 100644 index 00000000..3ba6d2ff --- /dev/null +++ b/modules/nf-core/metaphlan/mergemetaphlantables/tests/main.nf.test.snap @@ -0,0 +1,68 @@ +{ + "sarscov2 - illumina single end [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,4687feab0c102fdc65fe2e174431a7c7" + ], + "txt": [ + [ + { + "id": "test" + }, + "test.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,4687feab0c102fdc65fe2e174431a7c7" + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-08-15T07:57:23.888779527" + }, + "sarscov2 - illumina single end [fastq]": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.txt:md5,671ac0cf0c2561154fc44109b6d8b973" + ] + ], + "1": [ + "versions.yml:md5,4687feab0c102fdc65fe2e174431a7c7" + ], + "txt": [ + [ + { + "id": "test" + }, + "test.txt:md5,671ac0cf0c2561154fc44109b6d8b973" + ] + ], + "versions": [ + "versions.yml:md5,4687feab0c102fdc65fe2e174431a7c7" + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-08-15T07:53:05.914944433" + } +} \ No newline at end of file diff --git a/modules/nf-core/metaphlan/mergemetaphlantables/tests/nextflow.config b/modules/nf-core/metaphlan/mergemetaphlantables/tests/nextflow.config new file mode 100644 index 00000000..e64f0f92 --- /dev/null +++ b/modules/nf-core/metaphlan/mergemetaphlantables/tests/nextflow.config @@ -0,0 +1,10 @@ +docker { + fixOwnership = true + runOptions = '--platform=linux/amd64' +} + +process { + withName: UNTAR { + ext.args2 = "--no-same-owner" + } +} diff --git a/modules/nf-core/metaphlan/mergemetaphlantables/tests/tags.yml b/modules/nf-core/metaphlan/mergemetaphlantables/tests/tags.yml new file mode 100644 index 00000000..508a51b7 --- /dev/null +++ b/modules/nf-core/metaphlan/mergemetaphlantables/tests/tags.yml @@ -0,0 +1,4 @@ +metaphlan/mergemetaphlantables: + - "modules/nf-core/metaphlan/mergemetaphlantables/**" + - "modules/nf-core/metaphlan/metaphlan/**" + - "modules/nf-core/untar/**" diff --git a/modules/nf-core/metaphlan/metaphlan/environment.yml b/modules/nf-core/metaphlan/metaphlan/environment.yml new file mode 100644 index 00000000..709ddf70 --- /dev/null +++ b/modules/nf-core/metaphlan/metaphlan/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::metaphlan=4.1.1 diff --git a/modules/nf-core/metaphlan/metaphlan/main.nf b/modules/nf-core/metaphlan/metaphlan/main.nf index 24533571..c427efeb 100644 --- a/modules/nf-core/metaphlan/metaphlan/main.nf +++ b/modules/nf-core/metaphlan/metaphlan/main.nf @@ -2,10 +2,10 @@ process METAPHLAN_METAPHLAN { tag "$meta.id" label 'process_medium' - conda "bioconda::metaphlan=4.0.6" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/metaphlan:4.0.6--pyhca03a8a_0' : - 'biocontainers/metaphlan:4.0.6--pyhca03a8a_0' }" + 'https://depot.galaxyproject.org/singularity/metaphlan:4.1.1--pyhdfd78af_0' : + 'biocontainers/metaphlan:4.1.1--pyhdfd78af_0' }" input: tuple val(meta), path(input) @@ -47,4 +47,21 @@ process METAPHLAN_METAPHLAN { metaphlan: \$(metaphlan --version 2>&1 | awk '{print \$3}') END_VERSIONS """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def input_type = "$input" =~ /.*\.(fastq|fq)/ ? "--input_type fastq" : "$input" =~ /.*\.(fasta|fna|fa)/ ? "--input_type fasta" : "$input".endsWith(".bowtie2out.txt") ? "--input_type bowtie2out" : "--input_type sam" + def input_data = ("$input_type".contains("fastq")) && !meta.single_end ? "${input[0]},${input[1]}" : "$input" + def bowtie2_out = "$input_type" == "--input_type bowtie2out" || "$input_type" == "--input_type sam" ? '' : "--bowtie2out ${prefix}.bowtie2out.txt" + + """ + touch ${prefix}.biom + touch ${prefix}_profile.txt + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + metaphlan: \$(metaphlan --version 2>&1 | awk '{print \$3}') + END_VERSIONS + """ } diff --git a/modules/nf-core/metaphlan/metaphlan/meta.yml b/modules/nf-core/metaphlan/metaphlan/meta.yml index cb74bd59..d9be48e4 100644 --- a/modules/nf-core/metaphlan/metaphlan/meta.yml +++ b/modules/nf-core/metaphlan/metaphlan/meta.yml @@ -13,7 +13,6 @@ tools: documentation: https://github.com/biobakery/MetaPhlAn doi: "10.1038/s41587-023-01688-w" licence: ["MIT License"] - input: - meta: type: map @@ -24,13 +23,12 @@ input: type: file description: Metaphlan can classify the metagenome from a variety of input data types, including FASTQ files (single-end and paired-end), FASTA, bowtie2-produced SAM files (produced from alignments to the MetaPHlAn marker database) and intermediate bowtie2 alignment files (bowtie2out) pattern: "*.{fastq.gz, fasta, fasta.gz, sam, bowtie2out.txt}" - - metaphlan_db: + - metaphlan_db_latest: type: file description: | Directory containing pre-downloaded and uncompressed MetaPhlAn database downloaded from: http://cmprod1.cibio.unitn.it/biobakery4/metaphlan_databases/. Note that you will also need to specify `--index` and the database version name (e.g. 'mpa_vJan21_TOY_CHOCOPhlAnSGB_202103') in your module.conf ext.args for METAPHLAN_METAPHLAN! pattern: "*/" - output: - meta: type: map @@ -49,11 +47,13 @@ output: type: file description: General-use format for representing biological sample by observation contingency tables pattern: "*.{biom}" - - bowtie2out: + - bt2out: type: file description: Intermediate Bowtie2 output produced from mapping the metagenome against the MetaPHlAn marker database ( not compatible with `bowtie2out` files generated with MetaPhlAn versions below 3 ) pattern: "*.{bowtie2out.txt}" - authors: - "@MGordon09" - "@LilyAnderssonLee" +maintainers: + - "@MGordon09" + - "@LilyAnderssonLee" diff --git a/modules/nf-core/metaphlan/metaphlan/tests/main.nf.test b/modules/nf-core/metaphlan/metaphlan/tests/main.nf.test new file mode 100644 index 00000000..dff5cf71 --- /dev/null +++ b/modules/nf-core/metaphlan/metaphlan/tests/main.nf.test @@ -0,0 +1,136 @@ +nextflow_process { + name "Test Process METAPHLAN_METAPHLAN" + script "../main.nf" + config "./nextflow.config" + + process "METAPHLAN_METAPHLAN" + tag "modules" + tag "modules_nfcore" + tag "untar" + tag "metaphlan" + tag "metaphlan/metaphlan" + + setup { + run("UNTAR") { + script "modules/nf-core/untar/main.nf" + process { + """ + input[0] = Channel.of([ + [], + file( params.modules_testdata_base_path + 'delete_me/metaphlan4_database.tar.gz', checkIfExists: true ) + ]) + """ + } + } + } + + test("sarscov2 - illumina single end [fastq]") { + + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + file( params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz',checkIfExists: true ) + ]) + input[1] = UNTAR.out.untar.map{ it[1] } + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + path(process.out.profile[0][1]).readLines()[2..5], + path(process.out.biom[0][1]).readLines().last().contains('Biological Observation Matrix'), + process.out.bt2out, + process.out.versions + ).match() + } + ) + } + } + + test("sarscov2 - illumina pair end [fastq]") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [ file( params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz',checkIfExists: true ), + file( params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz',checkIfExists: true ) ] + ]) + input[1] = UNTAR.out.untar.map{ it[1] } + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + path(process.out.profile[0][1]).readLines()[2..5], + path(process.out.biom[0][1]).readLines().last().contains('Biological Observation Matrix'), + process.out.bt2out, + process.out.versions + ).match() + } + ) + } + } + + test("sarscov2 - illumina single end [fasta]") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:true ], // meta map + file( params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fasta/contigs.fasta',checkIfExists: true ) + ]) + input[1] = UNTAR.out.untar.map{ it[1] } + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + path(process.out.profile[0][1]).readLines()[2..5], + path(process.out.biom[0][1]).readLines().last().contains('Biological Observation Matrix'), + process.out.bt2out, + process.out.versions + ).match() + } ) + } + } + + test("sarscov2 - illumina pair end [fastq] - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + [ file( params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz',checkIfExists: true ), + file( params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz',checkIfExists: true )] + ]) + input[1] = UNTAR.out.untar.map{ it[1] } + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( process.out ).match() } + ) + } + } +} diff --git a/modules/nf-core/metaphlan/metaphlan/tests/main.nf.test.snap b/modules/nf-core/metaphlan/metaphlan/tests/main.nf.test.snap new file mode 100644 index 00000000..cbb1798e --- /dev/null +++ b/modules/nf-core/metaphlan/metaphlan/tests/main.nf.test.snap @@ -0,0 +1,145 @@ +{ + "sarscov2 - illumina pair end [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test_profile.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.biom:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + + ], + "3": [ + "versions.yml:md5,db17780c9fc65bc70e9641101c47d0e0" + ], + "biom": [ + [ + { + "id": "test", + "single_end": false + }, + "test.biom:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "bt2out": [ + + ], + "profile": [ + [ + { + "id": "test", + "single_end": false + }, + "test_profile.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,db17780c9fc65bc70e9641101c47d0e0" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.1" + }, + "timestamp": "2024-08-13T12:51:42.549393" + }, + "sarscov2 - illumina single end [fastq]": { + "content": [ + [ + "#100 reads processed", + "#SampleID\tMetaphlan_Analysis", + "#clade_name\tNCBI_tax_id\trelative_abundance\tadditional_species", + "UNCLASSIFIED\t-1\t100.0\t" + ], + true, + [ + [ + { + "id": "test", + "single_end": true + }, + "test.bowtie2out.txt:md5,ef46a9c6a8ce9cae26fbfd5527116fd5" + ] + ], + [ + "versions.yml:md5,db17780c9fc65bc70e9641101c47d0e0" + ] + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-08-27T10:33:32.269571148" + }, + "sarscov2 - illumina single end [fasta]": { + "content": [ + [ + "#4 reads processed", + "#SampleID\tMetaphlan_Analysis", + "#clade_name\tNCBI_tax_id\trelative_abundance\tadditional_species", + "UNCLASSIFIED\t-1\t100.0\t" + ], + true, + [ + [ + { + "id": "test", + "single_end": true + }, + "test.bowtie2out.txt:md5,d99d05d6b011c647adf816f10fc6acbe" + ] + ], + [ + "versions.yml:md5,db17780c9fc65bc70e9641101c47d0e0" + ] + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-08-27T10:34:10.262604527" + }, + "sarscov2 - illumina pair end [fastq]": { + "content": [ + [ + "#196 reads processed", + "#SampleID\tMetaphlan_Analysis", + "#clade_name\tNCBI_tax_id\trelative_abundance\tadditional_species", + "UNCLASSIFIED\t-1\t100.0\t" + ], + true, + [ + [ + { + "id": "test", + "single_end": false + }, + "test.bowtie2out.txt:md5,8c1bc21e1d8484b5551bf46331d61bd8" + ] + ], + [ + "versions.yml:md5,db17780c9fc65bc70e9641101c47d0e0" + ] + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-08-27T10:33:51.829732777" + } +} \ No newline at end of file diff --git a/modules/nf-core/metaphlan/metaphlan/tests/nextflow.config b/modules/nf-core/metaphlan/metaphlan/tests/nextflow.config new file mode 100644 index 00000000..e64f0f92 --- /dev/null +++ b/modules/nf-core/metaphlan/metaphlan/tests/nextflow.config @@ -0,0 +1,10 @@ +docker { + fixOwnership = true + runOptions = '--platform=linux/amd64' +} + +process { + withName: UNTAR { + ext.args2 = "--no-same-owner" + } +} diff --git a/modules/nf-core/metaphlan/metaphlan/tests/tags.yml b/modules/nf-core/metaphlan/metaphlan/tests/tags.yml new file mode 100644 index 00000000..e90a3771 --- /dev/null +++ b/modules/nf-core/metaphlan/metaphlan/tests/tags.yml @@ -0,0 +1,3 @@ +metaphlan/metaphlan: + - modules/nf-core/metaphlan/metaphlan/** + - modules/nf-core/untar/** diff --git a/modules/nf-core/minimap2/align/environment.yml b/modules/nf-core/minimap2/align/environment.yml new file mode 100644 index 00000000..dc6476b7 --- /dev/null +++ b/modules/nf-core/minimap2/align/environment.yml @@ -0,0 +1,8 @@ +channels: + - conda-forge + - bioconda + +dependencies: + - bioconda::htslib=1.20 + - bioconda::minimap2=2.28 + - bioconda::samtools=1.20 diff --git a/modules/nf-core/minimap2/align/main.nf b/modules/nf-core/minimap2/align/main.nf index 4da47c18..d82dc14d 100644 --- a/modules/nf-core/minimap2/align/main.nf +++ b/modules/nf-core/minimap2/align/main.nf @@ -1,45 +1,75 @@ process MINIMAP2_ALIGN { tag "$meta.id" - label 'process_medium' + label 'process_high' // Note: the versions here need to match the versions used in the mulled container below and minimap2/index - conda "bioconda::minimap2=2.24 bioconda::samtools=1.14" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-66534bcbb7031a148b13e2ad42583020b9cd25c4:1679e915ddb9d6b4abda91880c4b48857d471bd8-0' : - 'biocontainers/mulled-v2-66534bcbb7031a148b13e2ad42583020b9cd25c4:1679e915ddb9d6b4abda91880c4b48857d471bd8-0' }" + 'https://depot.galaxyproject.org/singularity/mulled-v2-66534bcbb7031a148b13e2ad42583020b9cd25c4:3161f532a5ea6f1dec9be5667c9efc2afdac6104-0' : + 'biocontainers/mulled-v2-66534bcbb7031a148b13e2ad42583020b9cd25c4:3161f532a5ea6f1dec9be5667c9efc2afdac6104-0' }" input: tuple val(meta), path(reads) - path reference + tuple val(meta2), path(reference) val bam_format + val bam_index_extension val cigar_paf_format val cigar_bam output: - tuple val(meta), path("*.paf"), optional: true, emit: paf - tuple val(meta), path("*.bam"), optional: true, emit: bam - path "versions.yml" , emit: versions + tuple val(meta), path("*.paf") , optional: true, emit: paf + tuple val(meta), path("*.bam") , optional: true, emit: bam + tuple val(meta), path("*.bam.${bam_index_extension}"), optional: true, emit: index + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when script: - def args = task.ext.args ?: '' + def args = task.ext.args ?: '' + def args2 = task.ext.args2 ?: '' + def args3 = task.ext.args3 ?: '' + def args4 = task.ext.args4 ?: '' def prefix = task.ext.prefix ?: "${meta.id}" - def bam_output = bam_format ? "-a | samtools sort | samtools view -@ ${task.cpus} -b -h -o ${prefix}.bam" : "-o ${prefix}.paf" + def bam_index = bam_index_extension ? "${prefix}.bam##idx##${prefix}.bam.${bam_index_extension} --write-index" : "${prefix}.bam" + def bam_output = bam_format ? "-a | samtools sort -@ ${task.cpus-1} -o ${bam_index} ${args2}" : "-o ${prefix}.paf" def cigar_paf = cigar_paf_format && !bam_format ? "-c" : '' def set_cigar_bam = cigar_bam && bam_format ? "-L" : '' + def bam_input = "${reads.extension}".matches('sam|bam|cram') + def samtools_reset_fastq = bam_input ? "samtools reset --threads ${task.cpus-1} $args3 $reads | samtools fastq --threads ${task.cpus-1} $args4 |" : '' + def query = bam_input ? "-" : reads + def target = reference ?: (bam_input ? error("BAM input requires reference") : reads) + """ + $samtools_reset_fastq \\ minimap2 \\ $args \\ -t $task.cpus \\ - "${reference ?: reads}" \\ - "$reads" \\ + $target \\ + $query \\ $cigar_paf \\ $set_cigar_bam \\ $bam_output + cat <<-END_VERSIONS > versions.yml + "${task.process}": + minimap2: \$(minimap2 --version 2>&1) + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + def output_file = bam_format ? "${prefix}.bam" : "${prefix}.paf" + def bam_index = bam_index_extension ? "touch ${prefix}.bam.${bam_index_extension}" : "" + def bam_input = "${reads.extension}".matches('sam|bam|cram') + def target = reference ?: (bam_input ? error("BAM input requires reference") : reads) + + """ + touch $output_file + ${bam_index} + cat <<-END_VERSIONS > versions.yml "${task.process}": minimap2: \$(minimap2 --version 2>&1) diff --git a/modules/nf-core/minimap2/align/meta.yml b/modules/nf-core/minimap2/align/meta.yml index 991b39a0..8996f881 100644 --- a/modules/nf-core/minimap2/align/meta.yml +++ b/modules/nf-core/minimap2/align/meta.yml @@ -25,6 +25,11 @@ input: description: | List of input FASTA or FASTQ files of size 1 and 2 for single-end and paired-end data, respectively. + - meta2: + type: map + description: | + Groovy Map containing reference information + e.g. [ id:'test_ref'] - reference: type: file description: | @@ -32,6 +37,9 @@ input: - bam_format: type: boolean description: Specify that output should be in BAM format + - bam_index_extension: + type: string + description: BAM alignment index extension (e.g. "bai") - cigar_paf_format: type: boolean description: Specify that output CIGAR should be in PAF format @@ -54,6 +62,10 @@ output: type: file description: Alignment in BAM format pattern: "*.bam" + - index: + type: file + description: BAM alignment index + pattern: "*.bam.*" - versions: type: file description: File containing software versions @@ -63,3 +75,10 @@ authors: - "@sofstam" - "@sateeshperi" - "@jfy133" + - "@fellen31" +maintainers: + - "@heuermh" + - "@sofstam" + - "@sateeshperi" + - "@jfy133" + - "@fellen31" diff --git a/modules/nf-core/minimap2/align/tests/main.nf.test b/modules/nf-core/minimap2/align/tests/main.nf.test new file mode 100644 index 00000000..4072c171 --- /dev/null +++ b/modules/nf-core/minimap2/align/tests/main.nf.test @@ -0,0 +1,441 @@ +nextflow_process { + + name "Test Process MINIMAP2_ALIGN" + script "../main.nf" + process "MINIMAP2_ALIGN" + + tag "modules" + tag "modules_nfcore" + tag "minimap2" + tag "minimap2/align" + + test("sarscov2 - fastq, fasta, true, [], false, false") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + input[1] = [ + [ id:'test_ref' ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + input[2] = true + input[3] = [] + input[4] = false + input[5] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + bam(process.out.bam[0][1]).getHeader(), + bam(process.out.bam[0][1]).getReadsMD5(), + process.out.versions + ).match() } + ) + } + + } + + test("sarscov2 - fastq, fasta, true, 'bai', false, false") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + input[1] = [ + [ id:'test_ref' ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + input[2] = true + input[3] = 'bai' + input[4] = false + input[5] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + bam(process.out.bam[0][1]).getHeader(), + bam(process.out.bam[0][1]).getReadsMD5(), + file(process.out.index[0][1]).name, + process.out.versions + ).match() } + ) + } + + } + + test("sarscov2 - [fastq1, fastq2], fasta, true, false, false") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) + ] + ] + input[1] = [ + [ id:'test_ref' ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + input[2] = true + input[3] = [] + input[4] = false + input[5] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + bam(process.out.bam[0][1]).getHeader(), + bam(process.out.bam[0][1]).getReadsMD5(), + process.out.versions + ).match() } + ) + } + + } + + test("sarscov2 - fastq, [], true, false, false") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + ] + input[1] = [ + [ id:'test_ref' ], // meta map + [] + ] + input[2] = true + input[3] = [] + input[4] = false + input[5] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + bam(process.out.bam[0][1]).getHeader(), + bam(process.out.bam[0][1]).getReadsMD5(), + process.out.versions + ).match() } + ) + } + + } + + test("sarscov2 - bam, fasta, true, [], false, false") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test3.single_end.markduplicates.sorted.bam', checkIfExists: true) + ] + input[1] = [ + [ id:'test_ref' ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + input[2] = true + input[3] = [] + input[4] = false + input[5] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + bam(process.out.bam[0][1]).getHeader(), + bam(process.out.bam[0][1]).getReadsMD5(), + process.out.versions + ).match() } + ) + } + + } + + test("sarscov2 - bam, fasta, true, 'bai', false, false") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test3.single_end.markduplicates.sorted.bam', checkIfExists: true) + ] + input[1] = [ + [ id:'test_ref' ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + input[2] = true + input[3] = 'bai' + input[4] = false + input[5] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + bam(process.out.bam[0][1]).getHeader(), + bam(process.out.bam[0][1]).getReadsMD5(), + file(process.out.index[0][1]).name, + process.out.versions + ).match() } + ) + } + + } + + test("sarscov2 - bam, [], true, false, false") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test3.single_end.markduplicates.sorted.bam', checkIfExists: true) + ] + input[1] = [ + [ id:'test_ref' ], // meta map + [] + ] + input[2] = true + input[3] = [] + input[4] = false + input[5] = false + """ + } + } + + then { + assertAll( + { assert process.failed } + ) + } + + } + + test("sarscov2 - fastq, fasta, true, [], false, false - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + input[1] = [ + [ id:'test_ref' ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + input[2] = true + input[3] = [] + input[4] = false + input[5] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("sarscov2 - fastq, fasta, true, 'bai', false, false - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + input[1] = [ + [ id:'test_ref' ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + input[2] = true + input[3] = 'bai' + input[4] = false + input[5] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("sarscov2 - fastq, fasta, false, [], false, false - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + input[1] = [ + [ id:'test_ref' ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + input[2] = false + input[3] = [] + input[4] = false + input[5] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("sarscov2 - bam, fasta, true, [], false, false - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test3.single_end.markduplicates.sorted.bam', checkIfExists: true) + ] + input[1] = [ + [ id:'test_ref' ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + input[2] = true + input[3] = [] + input[4] = false + input[5] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("sarscov2 - bam, fasta, true, 'bai', false, false - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test3.single_end.markduplicates.sorted.bam', checkIfExists: true) + ] + input[1] = [ + [ id:'test_ref' ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + input[2] = true + input[3] = 'bai' + input[4] = false + input[5] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("sarscov2 - bam, [], true, false, false - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test3.single_end.markduplicates.sorted.bam', checkIfExists: true) + ] + input[1] = [ + [ id:'test_ref' ], // meta map + [] + ] + input[2] = true + input[3] = [] + input[4] = false + input[5] = false + """ + } + } + + then { + assertAll( + { assert process.failed } + ) + } + + } + +} \ No newline at end of file diff --git a/modules/nf-core/minimap2/align/tests/main.nf.test.snap b/modules/nf-core/minimap2/align/tests/main.nf.test.snap new file mode 100644 index 00000000..12264a85 --- /dev/null +++ b/modules/nf-core/minimap2/align/tests/main.nf.test.snap @@ -0,0 +1,476 @@ +{ + "sarscov2 - bam, fasta, true, 'bai', false, false": { + "content": [ + [ + "@HD\tVN:1.6\tSO:coordinate", + "@SQ\tSN:MT192765.1\tLN:29829", + "@PG\tID:minimap2\tPN:minimap2\tVN:2.28-r1209\tCL:minimap2 -t 2 -a genome.fasta -", + "@PG\tID:samtools\tPN:samtools\tPP:minimap2\tVN:1.20\tCL:samtools sort -@ 1 -o test.bam##idx##test.bam.bai --write-index" + ], + "5d426b9a5f5b2c54f1d7f1e4c238ae94", + "test.bam.bai", + [ + "versions.yml:md5,3548eeba9066efbf8d78ea99f8d813fd" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-25T09:03:00.827260362" + }, + "sarscov2 - bam, fasta, true, 'bai', false, false - stub": { + "content": [ + { + "0": [ + + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test.bam:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + { + "id": "test", + "single_end": true + }, + "test.bam.bai:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "3": [ + "versions.yml:md5,98b8f5f36aa54b82210094f0b0d11938" + ], + "bam": [ + [ + { + "id": "test", + "single_end": true + }, + "test.bam:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "index": [ + [ + { + "id": "test", + "single_end": true + }, + "test.bam.bai:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "paf": [ + + ], + "versions": [ + "versions.yml:md5,98b8f5f36aa54b82210094f0b0d11938" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-23T11:21:37.92353539" + }, + "sarscov2 - fastq, fasta, true, 'bai', false, false - stub": { + "content": [ + { + "0": [ + + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test.bam:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + { + "id": "test", + "single_end": true + }, + "test.bam.bai:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "3": [ + "versions.yml:md5,98b8f5f36aa54b82210094f0b0d11938" + ], + "bam": [ + [ + { + "id": "test", + "single_end": true + }, + "test.bam:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "index": [ + [ + { + "id": "test", + "single_end": true + }, + "test.bam.bai:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "paf": [ + + ], + "versions": [ + "versions.yml:md5,98b8f5f36aa54b82210094f0b0d11938" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-03T11:29:44.669021368" + }, + "sarscov2 - fastq, fasta, false, [], false, false - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.paf:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + + ], + "2": [ + + ], + "3": [ + "versions.yml:md5,98b8f5f36aa54b82210094f0b0d11938" + ], + "bam": [ + + ], + "index": [ + + ], + "paf": [ + [ + { + "id": "test", + "single_end": true + }, + "test.paf:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,98b8f5f36aa54b82210094f0b0d11938" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-03T11:15:52.738781039" + }, + "sarscov2 - fastq, fasta, true, [], false, false - stub": { + "content": [ + { + "0": [ + + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test.bam:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + + ], + "3": [ + "versions.yml:md5,98b8f5f36aa54b82210094f0b0d11938" + ], + "bam": [ + [ + { + "id": "test", + "single_end": true + }, + "test.bam:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "index": [ + + ], + "paf": [ + + ], + "versions": [ + "versions.yml:md5,98b8f5f36aa54b82210094f0b0d11938" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-03T11:15:23.033808223" + }, + "sarscov2 - [fastq1, fastq2], fasta, true, false, false": { + "content": [ + [ + "@HD\tVN:1.6\tSO:coordinate", + "@SQ\tSN:MT192765.1\tLN:29829", + "@PG\tID:minimap2\tPN:minimap2\tVN:2.28-r1209\tCL:minimap2 -t 2 -a genome.fasta test_1.fastq.gz test_2.fastq.gz", + "@PG\tID:samtools\tPN:samtools\tPP:minimap2\tVN:1.20\tCL:samtools sort -@ 1 -o test.bam" + ], + "1bc392244f228bf52cf0b5a8f6a654c9", + [ + "versions.yml:md5,3548eeba9066efbf8d78ea99f8d813fd" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-23T11:18:18.964586894" + }, + "sarscov2 - fastq, fasta, true, [], false, false": { + "content": [ + [ + "@HD\tVN:1.6\tSO:coordinate", + "@SQ\tSN:MT192765.1\tLN:29829", + "@PG\tID:minimap2\tPN:minimap2\tVN:2.28-r1209\tCL:minimap2 -t 2 -a genome.fasta test_1.fastq.gz", + "@PG\tID:samtools\tPN:samtools\tPP:minimap2\tVN:1.20\tCL:samtools sort -@ 1 -o test.bam" + ], + "f194745c0ccfcb2a9c0aee094a08750", + [ + "versions.yml:md5,3548eeba9066efbf8d78ea99f8d813fd" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-23T11:17:48.667488325" + }, + "sarscov2 - fastq, fasta, true, 'bai', false, false": { + "content": [ + [ + "@HD\tVN:1.6\tSO:coordinate", + "@SQ\tSN:MT192765.1\tLN:29829", + "@PG\tID:minimap2\tPN:minimap2\tVN:2.28-r1209\tCL:minimap2 -t 2 -a genome.fasta test_1.fastq.gz", + "@PG\tID:samtools\tPN:samtools\tPP:minimap2\tVN:1.20\tCL:samtools sort -@ 1 -o test.bam##idx##test.bam.bai --write-index" + ], + "f194745c0ccfcb2a9c0aee094a08750", + "test.bam.bai", + [ + "versions.yml:md5,3548eeba9066efbf8d78ea99f8d813fd" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-23T11:18:02.517416733" + }, + "sarscov2 - bam, fasta, true, [], false, false": { + "content": [ + [ + "@HD\tVN:1.6\tSO:coordinate", + "@SQ\tSN:MT192765.1\tLN:29829", + "@PG\tID:minimap2\tPN:minimap2\tVN:2.28-r1209\tCL:minimap2 -t 2 -a genome.fasta -", + "@PG\tID:samtools\tPN:samtools\tPP:minimap2\tVN:1.20\tCL:samtools sort -@ 1 -o test.bam" + ], + "5d426b9a5f5b2c54f1d7f1e4c238ae94", + [ + "versions.yml:md5,3548eeba9066efbf8d78ea99f8d813fd" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-25T09:02:49.64829488" + }, + "sarscov2 - bam, fasta, true, [], false, false - stub": { + "content": [ + { + "0": [ + + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test.bam:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + + ], + "3": [ + "versions.yml:md5,98b8f5f36aa54b82210094f0b0d11938" + ], + "bam": [ + [ + { + "id": "test", + "single_end": true + }, + "test.bam:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "index": [ + + ], + "paf": [ + + ], + "versions": [ + "versions.yml:md5,98b8f5f36aa54b82210094f0b0d11938" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-23T11:21:22.162291795" + }, + "sarscov2 - fastq, [], true, false, false": { + "content": [ + [ + "@HD\tVN:1.6\tSO:coordinate", + "@SQ\tSN:ERR5069949.2151832\tLN:150", + "@SQ\tSN:ERR5069949.576388\tLN:77", + "@SQ\tSN:ERR5069949.501486\tLN:146", + "@SQ\tSN:ERR5069949.1331889\tLN:132", + "@SQ\tSN:ERR5069949.2161340\tLN:80", + "@SQ\tSN:ERR5069949.973930\tLN:79", + "@SQ\tSN:ERR5069949.2417063\tLN:150", + "@SQ\tSN:ERR5069949.376959\tLN:151", + "@SQ\tSN:ERR5069949.1088785\tLN:149", + "@SQ\tSN:ERR5069949.1066259\tLN:147", + "@SQ\tSN:ERR5069949.2832676\tLN:139", + "@SQ\tSN:ERR5069949.2953930\tLN:151", + "@SQ\tSN:ERR5069949.324865\tLN:151", + "@SQ\tSN:ERR5069949.2185111\tLN:150", + "@SQ\tSN:ERR5069949.937422\tLN:151", + "@SQ\tSN:ERR5069949.2431709\tLN:150", + "@SQ\tSN:ERR5069949.1246538\tLN:148", + "@SQ\tSN:ERR5069949.1189252\tLN:98", + "@SQ\tSN:ERR5069949.2216307\tLN:147", + "@SQ\tSN:ERR5069949.3273002\tLN:148", + "@SQ\tSN:ERR5069949.3277445\tLN:151", + "@SQ\tSN:ERR5069949.3022231\tLN:147", + "@SQ\tSN:ERR5069949.184542\tLN:151", + "@SQ\tSN:ERR5069949.540529\tLN:149", + "@SQ\tSN:ERR5069949.686090\tLN:150", + "@SQ\tSN:ERR5069949.2787556\tLN:106", + "@SQ\tSN:ERR5069949.2650879\tLN:150", + "@SQ\tSN:ERR5069949.2064910\tLN:149", + "@SQ\tSN:ERR5069949.2328704\tLN:150", + "@SQ\tSN:ERR5069949.1067032\tLN:150", + "@SQ\tSN:ERR5069949.3338256\tLN:151", + "@SQ\tSN:ERR5069949.1412839\tLN:147", + "@SQ\tSN:ERR5069949.1538968\tLN:150", + "@SQ\tSN:ERR5069949.147998\tLN:94", + "@SQ\tSN:ERR5069949.366975\tLN:106", + "@SQ\tSN:ERR5069949.1372331\tLN:151", + "@SQ\tSN:ERR5069949.1709367\tLN:129", + "@SQ\tSN:ERR5069949.2388984\tLN:150", + "@SQ\tSN:ERR5069949.1132353\tLN:150", + "@SQ\tSN:ERR5069949.1151736\tLN:151", + "@SQ\tSN:ERR5069949.479807\tLN:150", + "@SQ\tSN:ERR5069949.2176303\tLN:151", + "@SQ\tSN:ERR5069949.2772897\tLN:151", + "@SQ\tSN:ERR5069949.1020777\tLN:122", + "@SQ\tSN:ERR5069949.465452\tLN:151", + "@SQ\tSN:ERR5069949.1704586\tLN:149", + "@SQ\tSN:ERR5069949.1258508\tLN:151", + "@SQ\tSN:ERR5069949.986441\tLN:119", + "@SQ\tSN:ERR5069949.2674295\tLN:148", + "@SQ\tSN:ERR5069949.885966\tLN:79", + "@SQ\tSN:ERR5069949.2342766\tLN:151", + "@SQ\tSN:ERR5069949.3122970\tLN:127", + "@SQ\tSN:ERR5069949.3279513\tLN:72", + "@SQ\tSN:ERR5069949.309410\tLN:151", + "@SQ\tSN:ERR5069949.532979\tLN:149", + "@SQ\tSN:ERR5069949.2888794\tLN:151", + "@SQ\tSN:ERR5069949.2205229\tLN:150", + "@SQ\tSN:ERR5069949.786562\tLN:151", + "@SQ\tSN:ERR5069949.919671\tLN:151", + "@SQ\tSN:ERR5069949.1328186\tLN:151", + "@SQ\tSN:ERR5069949.870926\tLN:149", + "@SQ\tSN:ERR5069949.2257580\tLN:151", + "@SQ\tSN:ERR5069949.3249622\tLN:77", + "@SQ\tSN:ERR5069949.611123\tLN:125", + "@SQ\tSN:ERR5069949.651338\tLN:142", + "@SQ\tSN:ERR5069949.169513\tLN:92", + "@SQ\tSN:ERR5069949.155944\tLN:150", + "@SQ\tSN:ERR5069949.2033605\tLN:150", + "@SQ\tSN:ERR5069949.2730382\tLN:142", + "@SQ\tSN:ERR5069949.2125592\tLN:150", + "@SQ\tSN:ERR5069949.1062611\tLN:151", + "@SQ\tSN:ERR5069949.1778133\tLN:151", + "@SQ\tSN:ERR5069949.3057020\tLN:95", + "@SQ\tSN:ERR5069949.2972968\tLN:141", + "@SQ\tSN:ERR5069949.2734474\tLN:149", + "@SQ\tSN:ERR5069949.856527\tLN:151", + "@SQ\tSN:ERR5069949.2098070\tLN:151", + "@SQ\tSN:ERR5069949.1552198\tLN:150", + "@SQ\tSN:ERR5069949.2385514\tLN:150", + "@SQ\tSN:ERR5069949.2270078\tLN:151", + "@SQ\tSN:ERR5069949.114870\tLN:150", + "@SQ\tSN:ERR5069949.2668880\tLN:147", + "@SQ\tSN:ERR5069949.257821\tLN:139", + "@SQ\tSN:ERR5069949.2243023\tLN:150", + "@SQ\tSN:ERR5069949.2605155\tLN:146", + "@SQ\tSN:ERR5069949.1340552\tLN:151", + "@SQ\tSN:ERR5069949.1561137\tLN:150", + "@SQ\tSN:ERR5069949.2361683\tLN:149", + "@SQ\tSN:ERR5069949.2521353\tLN:150", + "@SQ\tSN:ERR5069949.1261808\tLN:149", + "@SQ\tSN:ERR5069949.2734873\tLN:98", + "@SQ\tSN:ERR5069949.3017828\tLN:107", + "@SQ\tSN:ERR5069949.573706\tLN:150", + "@SQ\tSN:ERR5069949.1980512\tLN:151", + "@SQ\tSN:ERR5069949.1014693\tLN:150", + "@SQ\tSN:ERR5069949.3184655\tLN:150", + "@SQ\tSN:ERR5069949.29668\tLN:89", + "@SQ\tSN:ERR5069949.3258358\tLN:151", + "@SQ\tSN:ERR5069949.1476386\tLN:151", + "@SQ\tSN:ERR5069949.2415814\tLN:150", + "@PG\tID:minimap2\tPN:minimap2\tVN:2.28-r1209\tCL:minimap2 -t 2 -a test_1.fastq.gz test_1.fastq.gz", + "@PG\tID:samtools\tPN:samtools\tPP:minimap2\tVN:1.20\tCL:samtools sort -@ 1 -o test.bam" + ], + "16c1c651f8ec67383bcdee3c55aed94f", + [ + "versions.yml:md5,3548eeba9066efbf8d78ea99f8d813fd" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-07-23T11:18:34.246998277" + } +} \ No newline at end of file diff --git a/modules/nf-core/minimap2/align/tests/tags.yml b/modules/nf-core/minimap2/align/tests/tags.yml new file mode 100644 index 00000000..39dba374 --- /dev/null +++ b/modules/nf-core/minimap2/align/tests/tags.yml @@ -0,0 +1,2 @@ +minimap2/align: + - "modules/nf-core/minimap2/align/**" diff --git a/modules/nf-core/minimap2/index/environment.yml b/modules/nf-core/minimap2/index/environment.yml new file mode 100644 index 00000000..d1c1b471 --- /dev/null +++ b/modules/nf-core/minimap2/index/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::minimap2=2.28 diff --git a/modules/nf-core/minimap2/index/main.nf b/modules/nf-core/minimap2/index/main.nf index 7a1bb227..38320214 100644 --- a/modules/nf-core/minimap2/index/main.nf +++ b/modules/nf-core/minimap2/index/main.nf @@ -1,11 +1,11 @@ process MINIMAP2_INDEX { - label 'process_medium' + label 'process_low' // Note: the versions here need to match the versions used in minimap2/align - conda "bioconda::minimap2=2.24" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/minimap2:2.24--h7132678_1' : - 'biocontainers/minimap2:2.24--h7132678_1' }" + 'https://depot.galaxyproject.org/singularity/minimap2:2.28--he4a0461_0' : + 'biocontainers/minimap2:2.28--he4a0461_0' }" input: tuple val(meta), path(fasta) @@ -31,4 +31,14 @@ process MINIMAP2_INDEX { minimap2: \$(minimap2 --version 2>&1) END_VERSIONS """ + + stub: + """ + touch ${fasta.baseName}.mmi + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + minimap2: \$(minimap2 --version 2>&1) + END_VERSIONS + """ } diff --git a/modules/nf-core/minimap2/index/meta.yml b/modules/nf-core/minimap2/index/meta.yml index b58f35c6..1d29e3f2 100644 --- a/modules/nf-core/minimap2/index/meta.yml +++ b/modules/nf-core/minimap2/index/meta.yml @@ -38,3 +38,6 @@ output: authors: - "@yuukiiwa" - "@drpatelh" +maintainers: + - "@yuukiiwa" + - "@drpatelh" diff --git a/modules/nf-core/minimap2/index/tests/main.nf.test b/modules/nf-core/minimap2/index/tests/main.nf.test new file mode 100644 index 00000000..97840ff7 --- /dev/null +++ b/modules/nf-core/minimap2/index/tests/main.nf.test @@ -0,0 +1,32 @@ +nextflow_process { + + name "Test Process MINIMAP2_INDEX" + script "../main.nf" + process "MINIMAP2_INDEX" + + tag "modules" + tag "modules_nfcore" + tag "minimap2" + tag "minimap2/index" + + test("minimap2 index") { + + when { + process { + """ + input[0] = [ + [ id:'test' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + """ + } + } + + then { + assert process.success + assert snapshot(process.out).match() + } + + } + +} \ No newline at end of file diff --git a/modules/nf-core/minimap2/index/tests/main.nf.test.snap b/modules/nf-core/minimap2/index/tests/main.nf.test.snap new file mode 100644 index 00000000..0b098828 --- /dev/null +++ b/modules/nf-core/minimap2/index/tests/main.nf.test.snap @@ -0,0 +1,68 @@ +{ + "Should run without failures": { + "content": [ + { + "0": [ + [ + { + "id": "test_ref" + }, + "genome.mmi:md5,72e450f12dc691e763c697463bdb1571" + ] + ], + "1": [ + "versions.yml:md5,0fced0ee8015e7f50b82566e3db8f7b0" + ], + "index": [ + [ + { + "id": "test_ref" + }, + "genome.mmi:md5,72e450f12dc691e763c697463bdb1571" + ] + ], + "versions": [ + "versions.yml:md5,0fced0ee8015e7f50b82566e3db8f7b0" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-03-18T11:46:30.000058092" + }, + "minimap2 index": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "genome.mmi:md5,72e450f12dc691e763c697463bdb1571" + ] + ], + "1": [ + "versions.yml:md5,2f8340380c6741e9261a284262a90bde" + ], + "index": [ + [ + { + "id": "test" + }, + "genome.mmi:md5,72e450f12dc691e763c697463bdb1571" + ] + ], + "versions": [ + "versions.yml:md5,2f8340380c6741e9261a284262a90bde" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-04-05T10:58:29.828187662" + } +} \ No newline at end of file diff --git a/modules/nf-core/minimap2/index/tests/tags.yml b/modules/nf-core/minimap2/index/tests/tags.yml new file mode 100644 index 00000000..e5ef8e19 --- /dev/null +++ b/modules/nf-core/minimap2/index/tests/tags.yml @@ -0,0 +1,2 @@ +minimap2/index: + - modules/nf-core/minimap2/index/** diff --git a/modules/nf-core/motus/merge/environment.yml b/modules/nf-core/motus/merge/environment.yml new file mode 100644 index 00000000..736a527e --- /dev/null +++ b/modules/nf-core/motus/merge/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::motus=3.0.3 diff --git a/modules/nf-core/motus/merge/main.nf b/modules/nf-core/motus/merge/main.nf index adc60dc8..392024ae 100644 --- a/modules/nf-core/motus/merge/main.nf +++ b/modules/nf-core/motus/merge/main.nf @@ -2,10 +2,10 @@ process MOTUS_MERGE { tag "$meta.id" label 'process_single' - conda "bioconda::motus=3.0.3" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/motus:3.0.3--pyhdfd78af_0': - 'biocontainers/motus:3.0.3--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/motus:3.1.0--pyhdfd78af_0': + 'biocontainers/motus:3.1.0--pyhdfd78af_0' }" input: tuple val(meta), path(input) @@ -42,4 +42,22 @@ process MOTUS_MERGE { motus: \$VERSION END_VERSIONS """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def cmd_input = input.size() > 1 ? "-i ${input.join(',')}" : input.isDirectory() ? "-d ${input}" : "-i ${input}" + def suffix = task.ext.args?.contains("-B") ? "biom" : "txt" + + """ + touch ${prefix}.txt + + VERSION=\$(cat ${profile_version_yml} | grep '/*motus:.*' | sed 's/.*otus: //g') + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + motus: \$VERSION + END_VERSIONS + """ + } diff --git a/modules/nf-core/motus/merge/meta.yml b/modules/nf-core/motus/merge/meta.yml index 24ae9399..57c95a54 100644 --- a/modules/nf-core/motus/merge/meta.yml +++ b/modules/nf-core/motus/merge/meta.yml @@ -15,40 +15,56 @@ tools: documentation: "https://github.com/motu-tool/mOTUs/wiki" tool_dev_url: "https://github.com/motu-tool/mOTUs" doi: "10.1186/s40168-022-01410-z" - licence: "['GPL v3']" - + licence: ["GPL v3"] + identifier: "" input: - - input: - type: file - description: | - List of output files (more than one) from motus profile, - or a single directory containing motus output files. - - db: - type: directory - description: | - mOTUs database downloaded by `motus downloadDB` - pattern: "db_mOTU/" - - profile_version_yml: - type: file - description: | - A single versions.yml file output from motus/profile. motus/merge cannot reconstruct - this itself without having the motus database present and configured with the tool - so here we take it from what is already reported by the upstream module. - pattern: "versions.yml" - + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'test', single_end:false ]` + - input: + type: file + description: | + List of output files (more than one) from motus profile, + or a single directory containing motus output files. + - - db: + type: directory + description: | + mOTUs database downloaded by `motus downloadDB` + pattern: "db_mOTU/" + - - profile_version_yml: + type: file + description: | + A single versions.yml file output from motus/profile. motus/merge cannot reconstruct + this itself without having the motus database present and configured with the tool + so here we take it from what is already reported by the upstream module. + pattern: "versions.yml" output: - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" - txt: - type: file - description: OTU table in txt format, if BIOM format not requested - pattern: "*.txt" + - meta: + type: file + description: OTU table in txt format, if BIOM format not requested + pattern: "*.txt" + - "*.txt": + type: file + description: OTU table in txt format, if BIOM format not requested + pattern: "*.txt" - biom: - type: file - description: OTU table in biom format, if BIOM format requested - pattern: "*.biom" - + - meta: + type: file + description: OTU table in biom format, if BIOM format requested + pattern: "*.biom" + - "*.biom": + type: file + description: OTU table in biom format, if BIOM format requested + pattern: "*.biom" + - versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@jfy133" +maintainers: + - "@jfy133" diff --git a/modules/nf-core/motus/merge/tests/main.nf.test b/modules/nf-core/motus/merge/tests/main.nf.test new file mode 100644 index 00000000..13f0121e --- /dev/null +++ b/modules/nf-core/motus/merge/tests/main.nf.test @@ -0,0 +1,89 @@ +nextflow_process { + name "Test Process MOTUS_MERGE" + script "../main.nf" + process "MOTUS_MERGE" + tag "modules" + tag "modules_nfcore" + tag "motus" + tag "motus/downloaddb" + tag "motus/profile" + tag "motus/merge" + + + setup { + run("MOTUS_DOWNLOADDB") { + script "modules/nf-core/motus/downloaddb/main.nf" + process { + """ + input[0] = Channel.of([ + file('https://raw.githubusercontent.com/motu-tool/mOTUs/master/motus/downloadDB.py') + ]) + """ + } + } + + run("MOTUS_PROFILE") { + script "modules/nf-core/motus/profile/main.nf" + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true ), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true ) + ] + ] + + input[1] = MOTUS_DOWNLOADDB.out.db + """ + } + } + } + + test("sarscov2 - illumina paired end [fastq]") { + + + when { + process { + """ + input[0] = MOTUS_PROFILE.out.out.map{ [[id:"test"], it[1]] }.groupTuple() + input[1] = MOTUS_DOWNLOADDB.out.db + input[2] = MOTUS_PROFILE.out.versions.first() + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + path(process.out.txt[0][1]).readLines()[3..10], + process.out.versions, + ).match() + } + ) + } + } + + test("sarscov2 - illumina paired end [fastq] - stub") { + + options "-stub" + + when { + process { + """ + input[0] = MOTUS_PROFILE.out.out.map{ [[id:"test"], it[1]] }.groupTuple() + input[1] = MOTUS_DOWNLOADDB.out.db + input[2] = MOTUS_PROFILE.out.versions.first() + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( process.out ).match() } + ) + } + } +} diff --git a/modules/nf-core/motus/merge/tests/main.nf.test.snap b/modules/nf-core/motus/merge/tests/main.nf.test.snap new file mode 100644 index 00000000..a8d75f4f --- /dev/null +++ b/modules/nf-core/motus/merge/tests/main.nf.test.snap @@ -0,0 +1,63 @@ +{ + "sarscov2 - illumina paired end [fastq]": { + "content": [ + [ + "Leptospira alexanderi [ref_mOTU_v31_00001]\t0.0000000000", + "Leptospira weilii [ref_mOTU_v31_00002]\t0.0000000000", + "Chryseobacterium sp. [ref_mOTU_v31_00004]\t0.0000000000", + "Chryseobacterium gallinarum [ref_mOTU_v31_00005]\t0.0000000000", + "Chryseobacterium indologenes [ref_mOTU_v31_00006]\t0.0000000000", + "Chryseobacterium artocarpi/ureilyticum [ref_mOTU_v31_00007]\t0.0000000000", + "Chryseobacterium jejuense [ref_mOTU_v31_00008]\t0.0000000000", + "Chryseobacterium sp. G972 [ref_mOTU_v31_00009]\t0.0000000000" + ], + [ + "versions.yml:md5,fb03dc5dcf4912bd54b06f9ee59a7eef" + ] + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-10-03T06:11:21.297394816" + }, + "sarscov2 - illumina paired end [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + + ], + "2": [ + "versions.yml:md5,fb03dc5dcf4912bd54b06f9ee59a7eef" + ], + "biom": [ + + ], + "txt": [ + [ + { + "id": "test" + }, + "test.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,fb03dc5dcf4912bd54b06f9ee59a7eef" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.1" + }, + "timestamp": "2024-10-02T12:18:09.391582" + } +} \ No newline at end of file diff --git a/modules/nf-core/motus/merge/tests/tags.yml b/modules/nf-core/motus/merge/tests/tags.yml new file mode 100644 index 00000000..44edb8d0 --- /dev/null +++ b/modules/nf-core/motus/merge/tests/tags.yml @@ -0,0 +1,2 @@ +motus/merge: + - modules/nf-core/motus/merge/** diff --git a/modules/nf-core/motus/profile/environment.yml b/modules/nf-core/motus/profile/environment.yml new file mode 100644 index 00000000..b8ef520e --- /dev/null +++ b/modules/nf-core/motus/profile/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::motus=3.1.0 diff --git a/modules/nf-core/motus/profile/main.nf b/modules/nf-core/motus/profile/main.nf index ca61865a..ecb15f9b 100644 --- a/modules/nf-core/motus/profile/main.nf +++ b/modules/nf-core/motus/profile/main.nf @@ -2,10 +2,10 @@ process MOTUS_PROFILE { tag "$meta.id" label 'process_medium' - conda "bioconda::motus=3.0.3" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/motus:3.0.3--pyhdfd78af_0': - 'biocontainers/motus:3.0.3--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/motus:3.1.0--pyhdfd78af_0': + 'biocontainers/motus:3.1.0--pyhdfd78af_0' }" input: tuple val(meta), path(reads) @@ -38,7 +38,7 @@ process MOTUS_PROFILE { -t $task.cpus \\ -n $prefix \\ -o ${prefix}.out \\ - 2> ${prefix}.log + 2> >(tee ${prefix}.log >&2) ## mOTUs version number is not available from command line. ## mOTUs save the version number in index database folder. @@ -53,4 +53,28 @@ process MOTUS_PROFILE { motus: \$VERSION END_VERSIONS """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def inputs = reads[0].getExtension() == 'bam' ? + "-i ${reads}" : + reads[0].getExtension() == 'mgc' ? "-m $reads" : + meta.single_end ? + "-s $reads" : "-f ${reads[0]} -r ${reads[1]}" + def refdb = db ? "-db ${db}" : "" + """ + touch ${prefix}.out + touch ${prefix}.log + + if [ "$db" == "" ]; then + VERSION=\$(echo \$(motus -h 2>&1) | sed 's/^.*Version: //; s/References.*\$//') + else + VERSION=\$(grep motus $db/db_mOTU_versions | sed 's/motus\\t//g') + fi + cat <<-END_VERSIONS > versions.yml + "${task.process}": + motus: \$VERSION + END_VERSIONS + """ } diff --git a/modules/nf-core/motus/profile/meta.yml b/modules/nf-core/motus/profile/meta.yml index 12020425..d6fffebc 100644 --- a/modules/nf-core/motus/profile/meta.yml +++ b/modules/nf-core/motus/profile/meta.yml @@ -12,8 +12,7 @@ tools: documentation: "https://github.com/motu-tool/mOTUs/wiki" tool_dev_url: "https://github.com/motu-tool/mOTUs" doi: "10.1186/s40168-022-01410-z" - licence: "['GPL v3']" - + licence: ["GPL v3"] input: - meta: type: map @@ -33,7 +32,6 @@ input: type: directory description: | mOTUs database downloaded by `motus downloadDB` - output: - meta: type: map @@ -60,6 +58,7 @@ output: type: file description: Standard error logging file containing summary statistics pattern: "*.log" - authors: - "@jianhong" +maintainers: + - "@jianhong" diff --git a/modules/nf-core/motus/profile/tests/main.nf.test b/modules/nf-core/motus/profile/tests/main.nf.test new file mode 100644 index 00000000..b0f04108 --- /dev/null +++ b/modules/nf-core/motus/profile/tests/main.nf.test @@ -0,0 +1,167 @@ +nextflow_process { + name "Test Process MOTUS_PROFILE" + script "../main.nf" + process "MOTUS_PROFILE" + tag "modules" + tag "modules_nfcore" + tag "motus" + tag "motus/downloaddb" + tag "motus/profile" + + + test("sarscov2 - illumina paired end [fastq]") { + + setup { + run("MOTUS_DOWNLOADDB") { + script "modules/nf-core/motus/downloaddb/main.nf" + process { + """ + input[0] = Channel.of([ + file('https://raw.githubusercontent.com/motu-tool/mOTUs/master/motus/downloadDB.py') + ]) + """ + } + } + } + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true ), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true ) + ] + ] + input[1] = MOTUS_DOWNLOADDB.out.db + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + path(process.out.out[0][1]).readLines()[3..10], + path(process.out.log[0][1]).readLines().last().contains('Reads are filtered for'), + process.out.versions, + ).match() + } + ) + } + } + + test("sarscov2 - illumina paired end [bam]") { + + setup { + run("MOTUS_DOWNLOADDB") { + script "modules/nf-core/motus/downloaddb/main.nf" + process { + """ + input[0] = Channel.of([ + file('https://raw.githubusercontent.com/motu-tool/mOTUs/master/motus/downloadDB.py') + ]) + """ + } + } + } + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + file( params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true )] + input[1] = MOTUS_DOWNLOADDB.out.db + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + path(process.out.out[0][1]).readLines()[3..10], + path(process.out.log[0][1]).readLines().last().contains('Reads are filtered for'), + process.out.versions + ).match() + } + ) + } + } + + test("sarscov2 - illumina single end [fastq] - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file( params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true ) + ] + input[1] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( process.out ).match() } + ) + } + } + + test("sarscov2 - illumina paired end [fastq] - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true ), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true ) + ] + ] + input[1] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( process.out ).match() } + ) + } + } + + test("sarscov2 - illumina paired end [bam] - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + file( params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true )] + input[1] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( process.out ).match() } + ) + } + } +} diff --git a/modules/nf-core/motus/profile/tests/main.nf.test.snap b/modules/nf-core/motus/profile/tests/main.nf.test.snap new file mode 100644 index 00000000..638885a2 --- /dev/null +++ b/modules/nf-core/motus/profile/tests/main.nf.test.snap @@ -0,0 +1,243 @@ +{ + "sarscov2 - illumina paired end [fastq]": { + "content": [ + [ + "Leptospira alexanderi [ref_mOTU_v31_00001]\t0.0000000000", + "Leptospira weilii [ref_mOTU_v31_00002]\t0.0000000000", + "Chryseobacterium sp. [ref_mOTU_v31_00004]\t0.0000000000", + "Chryseobacterium gallinarum [ref_mOTU_v31_00005]\t0.0000000000", + "Chryseobacterium indologenes [ref_mOTU_v31_00006]\t0.0000000000", + "Chryseobacterium artocarpi/ureilyticum [ref_mOTU_v31_00007]\t0.0000000000", + "Chryseobacterium jejuense [ref_mOTU_v31_00008]\t0.0000000000", + "Chryseobacterium sp. G972 [ref_mOTU_v31_00009]\t0.0000000000" + ], + false, + [ + "versions.yml:md5,0119e45bb894d3205c32fffc0c895d3c" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.1" + }, + "timestamp": "2024-09-04T12:54:13.029947" + }, + "sarscov2 - illumina paired end [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.out:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + + ], + "2": [ + + ], + "3": [ + [ + { + "id": "test", + "single_end": false + }, + "test.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "4": [ + "versions.yml:md5,361e07d24e9faf2fc49f5c3f4e718517" + ], + "bam": [ + + ], + "log": [ + [ + { + "id": "test", + "single_end": false + }, + "test.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "mgc": [ + + ], + "out": [ + [ + { + "id": "test", + "single_end": false + }, + "test.out:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,361e07d24e9faf2fc49f5c3f4e718517" + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-09-04T07:44:34.702236603" + }, + "sarscov2 - illumina paired end [bam]": { + "content": [ + [ + "Leptospira alexanderi [ref_mOTU_v31_00001]\t0.0000000000", + "Leptospira weilii [ref_mOTU_v31_00002]\t0.0000000000", + "Chryseobacterium sp. [ref_mOTU_v31_00004]\t0.0000000000", + "Chryseobacterium gallinarum [ref_mOTU_v31_00005]\t0.0000000000", + "Chryseobacterium indologenes [ref_mOTU_v31_00006]\t0.0000000000", + "Chryseobacterium artocarpi/ureilyticum [ref_mOTU_v31_00007]\t0.0000000000", + "Chryseobacterium jejuense [ref_mOTU_v31_00008]\t0.0000000000", + "Chryseobacterium sp. G972 [ref_mOTU_v31_00009]\t0.0000000000" + ], + false, + [ + "versions.yml:md5,0119e45bb894d3205c32fffc0c895d3c" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.1" + }, + "timestamp": "2024-09-04T12:56:30.49163" + }, + "sarscov2 - illumina single end [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.out:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + + ], + "2": [ + + ], + "3": [ + [ + { + "id": "test", + "single_end": true + }, + "test.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "4": [ + "versions.yml:md5,361e07d24e9faf2fc49f5c3f4e718517" + ], + "bam": [ + + ], + "log": [ + [ + { + "id": "test", + "single_end": true + }, + "test.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "mgc": [ + + ], + "out": [ + [ + { + "id": "test", + "single_end": true + }, + "test.out:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,361e07d24e9faf2fc49f5c3f4e718517" + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-09-04T07:44:23.635734599" + }, + "sarscov2 - illumina paired end [bam] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.out:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + + ], + "2": [ + + ], + "3": [ + [ + { + "id": "test", + "single_end": false + }, + "test.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "4": [ + "versions.yml:md5,361e07d24e9faf2fc49f5c3f4e718517" + ], + "bam": [ + + ], + "log": [ + [ + { + "id": "test", + "single_end": false + }, + "test.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "mgc": [ + + ], + "out": [ + [ + { + "id": "test", + "single_end": false + }, + "test.out:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,361e07d24e9faf2fc49f5c3f4e718517" + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-09-04T07:44:44.53280646" + } +} \ No newline at end of file diff --git a/modules/nf-core/motus/profile/tests/tags.yml b/modules/nf-core/motus/profile/tests/tags.yml new file mode 100644 index 00000000..723998c8 --- /dev/null +++ b/modules/nf-core/motus/profile/tests/tags.yml @@ -0,0 +1,2 @@ +motus/profile: + - modules/nf-core/motus/profile/** diff --git a/modules/nf-core/multiqc/environment.yml b/modules/nf-core/multiqc/environment.yml index ca39fb67..0fe12644 100644 --- a/modules/nf-core/multiqc/environment.yml +++ b/modules/nf-core/multiqc/environment.yml @@ -1,7 +1,5 @@ -name: multiqc channels: - conda-forge - bioconda - - defaults dependencies: - - bioconda::multiqc=1.21 + - bioconda::multiqc=1.25 diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index 47ac352f..b9ccebdb 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -3,14 +3,16 @@ process MULTIQC { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.21--pyhdfd78af_0' : - 'biocontainers/multiqc:1.21--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/multiqc:1.25--pyhdfd78af_0' : + 'biocontainers/multiqc:1.25--pyhdfd78af_0' }" input: path multiqc_files, stageAs: "?/*" path(multiqc_config) path(extra_multiqc_config) path(multiqc_logo) + path(replace_names) + path(sample_names) output: path "*multiqc_report.html", emit: report @@ -23,16 +25,22 @@ process MULTIQC { script: def args = task.ext.args ?: '' + def prefix = task.ext.prefix ? "--filename ${task.ext.prefix}.html" : '' 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}"'/ : '' + def logo = multiqc_logo ? "--cl-config 'custom_logo: \"${multiqc_logo}\"'" : '' + def replace = replace_names ? "--replace-names ${replace_names}" : '' + def samples = sample_names ? "--sample-names ${sample_names}" : '' """ multiqc \\ --force \\ $args \\ $config \\ + $prefix \\ $extra_config \\ $logo \\ + $replace \\ + $samples \\ . cat <<-END_VERSIONS > versions.yml diff --git a/modules/nf-core/multiqc/meta.yml b/modules/nf-core/multiqc/meta.yml index 45a9bc35..382c08cb 100644 --- a/modules/nf-core/multiqc/meta.yml +++ b/modules/nf-core/multiqc/meta.yml @@ -29,6 +29,19 @@ input: type: file description: Optional logo file for MultiQC pattern: "*.{png}" + - replace_names: + type: file + description: | + Optional two-column sample renaming file. First column a set of + patterns, second column a set of corresponding replacements. Passed via + MultiQC's `--replace-names` option. + pattern: "*.{tsv}" + - sample_names: + type: file + description: | + Optional TSV file with headers, passed to the MultiQC --sample_names + argument. + pattern: "*.{tsv}" output: - report: type: file diff --git a/modules/nf-core/multiqc/tests/main.nf.test b/modules/nf-core/multiqc/tests/main.nf.test index f1c4242e..33316a7d 100644 --- a/modules/nf-core/multiqc/tests/main.nf.test +++ b/modules/nf-core/multiqc/tests/main.nf.test @@ -8,6 +8,8 @@ nextflow_process { tag "modules_nfcore" tag "multiqc" + config "./nextflow.config" + test("sarscov2 single-end [fastqc]") { when { @@ -17,6 +19,8 @@ nextflow_process { input[1] = [] input[2] = [] input[3] = [] + input[4] = [] + input[5] = [] """ } } @@ -41,6 +45,8 @@ nextflow_process { 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] = [] + input[4] = [] + input[5] = [] """ } } @@ -66,6 +72,8 @@ nextflow_process { input[1] = [] input[2] = [] input[3] = [] + input[4] = [] + input[5] = [] """ } } diff --git a/modules/nf-core/multiqc/tests/main.nf.test.snap b/modules/nf-core/multiqc/tests/main.nf.test.snap index bfebd802..b779e469 100644 --- a/modules/nf-core/multiqc/tests/main.nf.test.snap +++ b/modules/nf-core/multiqc/tests/main.nf.test.snap @@ -2,14 +2,14 @@ "multiqc_versions_single": { "content": [ [ - "versions.yml:md5,21f35ee29416b9b3073c28733efe4b7d" + "versions.yml:md5,8c8724363a5efe0c6f43ab34faa57efd" ] ], "meta": { "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nextflow": "24.04.2" }, - "timestamp": "2024-02-29T08:48:55.657331" + "timestamp": "2024-07-10T12:41:34.562023" }, "multiqc_stub": { "content": [ @@ -17,25 +17,25 @@ "multiqc_report.html", "multiqc_data", "multiqc_plots", - "versions.yml:md5,21f35ee29416b9b3073c28733efe4b7d" + "versions.yml:md5,8c8724363a5efe0c6f43ab34faa57efd" ] ], "meta": { "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nextflow": "24.04.2" }, - "timestamp": "2024-02-29T08:49:49.071937" + "timestamp": "2024-07-10T11:27:11.933869532" }, "multiqc_versions_config": { "content": [ [ - "versions.yml:md5,21f35ee29416b9b3073c28733efe4b7d" + "versions.yml:md5,8c8724363a5efe0c6f43ab34faa57efd" ] ], "meta": { "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nextflow": "24.04.2" }, - "timestamp": "2024-02-29T08:49:25.457567" + "timestamp": "2024-07-10T11:26:56.709849369" } -} \ No newline at end of file +} diff --git a/modules/nf-core/multiqc/tests/nextflow.config b/modules/nf-core/multiqc/tests/nextflow.config new file mode 100644 index 00000000..c537a6a3 --- /dev/null +++ b/modules/nf-core/multiqc/tests/nextflow.config @@ -0,0 +1,5 @@ +process { + withName: 'MULTIQC' { + ext.prefix = null + } +} diff --git a/modules/nf-core/nanoq/environment.yml b/modules/nf-core/nanoq/environment.yml new file mode 100644 index 00000000..1a95d24e --- /dev/null +++ b/modules/nf-core/nanoq/environment.yml @@ -0,0 +1,7 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + - "bioconda::nanoq=0.10.0" diff --git a/modules/nf-core/nanoq/main.nf b/modules/nf-core/nanoq/main.nf new file mode 100644 index 00000000..6d35a407 --- /dev/null +++ b/modules/nf-core/nanoq/main.nf @@ -0,0 +1,49 @@ +process NANOQ { + tag "$meta.id" + label 'process_low' + + conda "${moduleDir}/environment.yml" + container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/nanoq:0.10.0--h031d066_2' : + 'biocontainers/nanoq:0.10.0--h031d066_2'}" + + input: + tuple val(meta), path(ontreads) + val(output_format) //One of the following: fastq, fastq.gz, fastq.bz2, fastq.lzma, fasta, fasta.gz, fasta.bz2, fasta.lzma. + + output: + tuple val(meta), path("*.{stats,json}") , emit: stats + tuple val(meta), path("*_filtered.${output_format}") , emit: reads + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}_filtered" + """ + nanoq -i $ontreads \\ + ${args} \\ + -r ${prefix}.stats \\ + -o ${prefix}.$output_format + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + nanoq: \$(nanoq --version | sed -e 's/nanoq //g') + END_VERSIONS + """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}_filtered" + """ + echo "" | gzip > ${prefix}.$output_format + touch ${prefix}.stats + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + nanoq: \$(nanoq --version | sed -e 's/nanoq //g') + END_VERSIONS + """ +} diff --git a/modules/nf-core/nanoq/meta.yml b/modules/nf-core/nanoq/meta.yml new file mode 100644 index 00000000..85c0c978 --- /dev/null +++ b/modules/nf-core/nanoq/meta.yml @@ -0,0 +1,60 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/meta-schema.json +name: "nanoq" +description: Nanoq implements ultra-fast read filters and summary reports for high-throughput nanopore reads. +keywords: + - nanoq + - Read filters + - Read trimming + - Read report +tools: + - "nanoq": + description: "Ultra-fast quality control and summary reports for nanopore reads" + homepage: "https://github.com/esteinig/nanoq" + documentation: "https://github.com/esteinig/nanoq" + tool_dev_url: "https://github.com/esteinig/nanoq" + doi: "10.21105/joss.02991" + licence: ["MIT"] + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1', single_end:false ]` + + - ontreads: + type: file + description: Compressed or uncompressed nanopore reads in fasta or fastq formats. + pattern: "*.{fa,fna,faa,fasta,fq,fastq}{,.gz,.bz2,.xz}" + + - output_format: + type: string + description: "Specifies the output format. One of these formats: fasta, fastq; fasta.gz, fastq.gz; fasta.bz2, fastq.bz2; fasta.lzma, fastq.lzma." + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1', single_end:false ]` + + - stats: + type: file + description: Summary report of reads statistics. + pattern: "*.{stats,json}" + + - reads: + type: file + description: Filtered reads. + pattern: "*.{fasta,fastq}{,.gz,.bz2,.lzma}" + + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@LilyAnderssonLee" +maintainers: + - "@LilyAnderssonLee" diff --git a/modules/nf-core/nanoq/tests/main.nf.test b/modules/nf-core/nanoq/tests/main.nf.test new file mode 100644 index 00000000..ef63d12f --- /dev/null +++ b/modules/nf-core/nanoq/tests/main.nf.test @@ -0,0 +1,122 @@ +nextflow_process { + + name "Test Process NANOQ" + script "../main.nf" + process "NANOQ" + + tag "modules" + tag "modules_nfcore" + tag "nanoq" + + test("sarscov2 - nanopore_uncompressed") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/nanopore/fastq/test.fastq.gz', checkIfExists: true) + ] + + input[1] = 'fastq' + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("sarscov2 - nanopore_compressed_gz") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/nanopore/fastq/test.fastq.gz', checkIfExists: true) + ] + input[1] = 'fastq.gz' + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + test("sarscov2 - nanopore_compressed_bz2") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/nanopore/fastq/test.fastq.gz', checkIfExists: true) + ] + input[1] = 'fastq.bz2' + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + test("sarscov2 - nanopore_compressed_lzma") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/nanopore/fastq/test.fastq.gz', checkIfExists: true) + ] + input[1] = 'fastq.lzma' + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("sarscov2 - nanopore_compressed_gz - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/nanopore/fastq/test.fastq.gz', checkIfExists: true) + ] + input[1] = 'fastq.gz' + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } +} diff --git a/modules/nf-core/nanoq/tests/main.nf.test.snap b/modules/nf-core/nanoq/tests/main.nf.test.snap new file mode 100644 index 00000000..b5dda2a7 --- /dev/null +++ b/modules/nf-core/nanoq/tests/main.nf.test.snap @@ -0,0 +1,267 @@ +{ + "sarscov2 - nanopore_compressed_gz": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test_filtered.stats:md5,5ab32af3352dfeca8268e10edf6e4dbe" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test_filtered.fastq.gz:md5,7567d853ada6ac142332619d0b541d76" + ] + ], + "2": [ + "versions.yml:md5,7a40efe417ff7dbb9e91e9c1629a04e6" + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test_filtered.fastq.gz:md5,7567d853ada6ac142332619d0b541d76" + ] + ], + "stats": [ + [ + { + "id": "test", + "single_end": true + }, + "test_filtered.stats:md5,5ab32af3352dfeca8268e10edf6e4dbe" + ] + ], + "versions": [ + "versions.yml:md5,7a40efe417ff7dbb9e91e9c1629a04e6" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.1" + }, + "timestamp": "2024-07-11T11:39:32.117229" + }, + "sarscov2 - nanopore_compressed_gz - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test_filtered.stats:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test_filtered.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "2": [ + "versions.yml:md5,7a40efe417ff7dbb9e91e9c1629a04e6" + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test_filtered.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "stats": [ + [ + { + "id": "test", + "single_end": true + }, + "test_filtered.stats:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,7a40efe417ff7dbb9e91e9c1629a04e6" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.1" + }, + "timestamp": "2024-07-11T11:42:06.039307" + }, + "sarscov2 - nanopore_compressed_bz2": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test_filtered.stats:md5,5ab32af3352dfeca8268e10edf6e4dbe" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test_filtered.fastq.bz2:md5,b53cf14fd4eb5b16c459c41f03cc8a4b" + ] + ], + "2": [ + "versions.yml:md5,7a40efe417ff7dbb9e91e9c1629a04e6" + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test_filtered.fastq.bz2:md5,b53cf14fd4eb5b16c459c41f03cc8a4b" + ] + ], + "stats": [ + [ + { + "id": "test", + "single_end": true + }, + "test_filtered.stats:md5,5ab32af3352dfeca8268e10edf6e4dbe" + ] + ], + "versions": [ + "versions.yml:md5,7a40efe417ff7dbb9e91e9c1629a04e6" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.1" + }, + "timestamp": "2024-07-11T11:39:36.674647" + }, + "sarscov2 - nanopore_compressed_lzma": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test_filtered.stats:md5,5ab32af3352dfeca8268e10edf6e4dbe" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test_filtered.fastq.lzma:md5,65dda701689f913734dc245b68c89e07" + ] + ], + "2": [ + "versions.yml:md5,7a40efe417ff7dbb9e91e9c1629a04e6" + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test_filtered.fastq.lzma:md5,65dda701689f913734dc245b68c89e07" + ] + ], + "stats": [ + [ + { + "id": "test", + "single_end": true + }, + "test_filtered.stats:md5,5ab32af3352dfeca8268e10edf6e4dbe" + ] + ], + "versions": [ + "versions.yml:md5,7a40efe417ff7dbb9e91e9c1629a04e6" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.1" + }, + "timestamp": "2024-07-11T11:39:41.51344" + }, + "sarscov2 - nanopore_uncompressed": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test_filtered.stats:md5,5ab32af3352dfeca8268e10edf6e4dbe" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test_filtered.fastq:md5,7567d853ada6ac142332619d0b541d76" + ] + ], + "2": [ + "versions.yml:md5,7a40efe417ff7dbb9e91e9c1629a04e6" + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test_filtered.fastq:md5,7567d853ada6ac142332619d0b541d76" + ] + ], + "stats": [ + [ + { + "id": "test", + "single_end": true + }, + "test_filtered.stats:md5,5ab32af3352dfeca8268e10edf6e4dbe" + ] + ], + "versions": [ + "versions.yml:md5,7a40efe417ff7dbb9e91e9c1629a04e6" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.1" + }, + "timestamp": "2024-07-11T11:39:26.868897" + } +} \ No newline at end of file diff --git a/modules/nf-core/nanoq/tests/tags.yml b/modules/nf-core/nanoq/tests/tags.yml new file mode 100644 index 00000000..37457df1 --- /dev/null +++ b/modules/nf-core/nanoq/tests/tags.yml @@ -0,0 +1,2 @@ +nanoq: + - "modules/nf-core/nanoq/**" diff --git a/modules/nf-core/nonpareil/curve/environment.yml b/modules/nf-core/nonpareil/curve/environment.yml new file mode 100644 index 00000000..89d5aa6e --- /dev/null +++ b/modules/nf-core/nonpareil/curve/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::nonpareil=3.5.5 diff --git a/modules/nf-core/nonpareil/curve/main.nf b/modules/nf-core/nonpareil/curve/main.nf new file mode 100644 index 00000000..dbe56b26 --- /dev/null +++ b/modules/nf-core/nonpareil/curve/main.nf @@ -0,0 +1,51 @@ +process NONPAREIL_CURVE { + tag "$meta.id" + label 'process_single' + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/nonpareil:3.5.5--r43hdcf5f25_0': + 'biocontainers/nonpareil:3.5.5--r43hdcf5f25_0' }" + + input: + tuple val(meta), path(npo) + + output: + tuple val(meta), path("*.png"), emit: png + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def args_cmd = args != '' ? ", ${args}" : "" + """ + #!/usr/bin/env Rscript + library(Nonpareil) + + png(file='${prefix}.png') + Nonpareil.curve('${npo}'${args_cmd}) + dev.off() + + version_file_path <- "versions.yml" + version_nonpareil <- paste(unlist(packageVersion("Nonpareil")), collapse = ".") + f <- file(version_file_path, "w") + writeLines('"${task.process}":', f) + writeLines(" nonpareil: ", f, sep = "") + writeLines(version_nonpareil, f) + close(f) + """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.png + + cat <<-END_VERSIONS > versions.yml + "${task.process}": \$(Rscript -e 'library('Nonpareil'); cat(paste(unlist(packageVersion("Nonpareil")),collapse="."))') + END_VERSIONS + """ +} diff --git a/modules/nf-core/nonpareil/curve/meta.yml b/modules/nf-core/nonpareil/curve/meta.yml new file mode 100644 index 00000000..87aaa363 --- /dev/null +++ b/modules/nf-core/nonpareil/curve/meta.yml @@ -0,0 +1,48 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/yaml-schema.json +name: "nonpareil_curve" +description: Visualise metagenome redundancy curve in PNG format from a single Nonpareil npo file +keywords: + - metagenomics + - statistics + - coverage + - complexity + - redundancy + - diversity + - visualisation +tools: + - "nonpareil": + description: "Estimate average coverage and create curves for metagenomic datasets" + homepage: "https://github.com/lmrodriguezr/nonpareil" + documentation: "https://nonpareil.readthedocs.io/en/latest/" + tool_dev_url: "https://github.com/lmrodriguezr/nonpareil" + doi: "10.1128/msystems.00039-" + licence: ["Artistic License 2.0"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'test', single_end:false ]` + - npo: + type: file + description: Single npo redundancy summary file from nonpareil itself + pattern: "*.npo" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'test', single_end:false ]` + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + - png: + type: file + description: PNG file of the Nonpareil curve + pattern: "*.png" +authors: + - "@jfy133" +maintainers: + - "@jfy133" diff --git a/modules/nf-core/nonpareil/curve/tests/main.nf.test b/modules/nf-core/nonpareil/curve/tests/main.nf.test new file mode 100644 index 00000000..ee6a16d5 --- /dev/null +++ b/modules/nf-core/nonpareil/curve/tests/main.nf.test @@ -0,0 +1,76 @@ +nextflow_process { + + name "Test Process NONPAREIL_CURVE" + script "../main.nf" + process "NONPAREIL_CURVE" + config "./nextflow.config" + tag "modules" + tag "modules_nfcore" + tag "nonpareil" + tag "nonpareil/curve" + tag "nonpareil/nonpareil" + + setup { + run("NONPAREIL_NONPAREIL") { + script "../../../nonpareil/nonpareil/main.nf" + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/prokaryotes/candidatus_portiera_aleyrodidarum/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + input[1] = 'fastq' + input[2] = 'kmer' + """ + } + } + } + + test("candidatus_portiera_aleyrodidarum") { + + when { + process { + """ + input[0] = NONPAREIL_NONPAREIL.out.npo + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + process.out.versions, + file(process.out.png[0][1]).name, + ).match() + } + ) + } + + } + + test("candidatus_portiera_aleyrodidarum - stub") { + + options "-stub" + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = NONPAREIL_NONPAREIL.out.npo + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + +} diff --git a/modules/nf-core/nonpareil/curve/tests/main.nf.test.snap b/modules/nf-core/nonpareil/curve/tests/main.nf.test.snap new file mode 100644 index 00000000..29625d71 --- /dev/null +++ b/modules/nf-core/nonpareil/curve/tests/main.nf.test.snap @@ -0,0 +1,50 @@ +{ + "candidatus_portiera_aleyrodidarum": { + "content": [ + [ + "versions.yml:md5,591a0a74569106b79c101d0059a822ad" + ], + "test.png" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.4" + }, + "timestamp": "2024-08-07T12:11:37.549218924" + }, + "candidatus_portiera_aleyrodidarum - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.png:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,ea8a60928f2d6fb3fe8895b63fba42f4" + ], + "png": [ + [ + { + "id": "test", + "single_end": false + }, + "test.png:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,ea8a60928f2d6fb3fe8895b63fba42f4" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.4" + }, + "timestamp": "2024-08-07T14:32:21.066752297" + } +} \ No newline at end of file diff --git a/modules/nf-core/nonpareil/curve/tests/nextflow.config b/modules/nf-core/nonpareil/curve/tests/nextflow.config new file mode 100644 index 00000000..d30ead9c --- /dev/null +++ b/modules/nf-core/nonpareil/curve/tests/nextflow.config @@ -0,0 +1,10 @@ +process { + withName: NONPAREIL_NONPAREIL { + ext.args = '-X 100' + } + + withName: NONPAREIL_CURVE { + ext.args = "col = 'green'" + } + +} diff --git a/modules/nf-core/nonpareil/curve/tests/tags.yml b/modules/nf-core/nonpareil/curve/tests/tags.yml new file mode 100644 index 00000000..b60cd0ec --- /dev/null +++ b/modules/nf-core/nonpareil/curve/tests/tags.yml @@ -0,0 +1,2 @@ +nonpareil/curve: + - modules/nf-core/nonpareil/curve/** diff --git a/modules/nf-core/nonpareil/nonpareil/environment.yml b/modules/nf-core/nonpareil/nonpareil/environment.yml new file mode 100644 index 00000000..89d5aa6e --- /dev/null +++ b/modules/nf-core/nonpareil/nonpareil/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::nonpareil=3.5.5 diff --git a/modules/nf-core/nonpareil/nonpareil/main.nf b/modules/nf-core/nonpareil/nonpareil/main.nf new file mode 100644 index 00000000..5c05649b --- /dev/null +++ b/modules/nf-core/nonpareil/nonpareil/main.nf @@ -0,0 +1,59 @@ +process NONPAREIL_NONPAREIL { + tag "$meta.id" + label 'process_low' + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/nonpareil:3.5.5--r43hdcf5f25_0': + 'biocontainers/nonpareil:3.5.5--r43hdcf5f25_0' }" + + input: + tuple val(meta), path(reads) + val format + val mode + + output: + tuple val(meta), path("*.npa"), emit: npa + tuple val(meta), path("*.npc"), emit: npc + tuple val(meta), path("*.npl"), emit: npl + tuple val(meta), path("*.npo"), emit: npo + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def mem_mb = task.memory.toMega() + """ + nonpareil \\ + -s $reads \\ + -f $format \\ + -T ${mode} \\ + -t $task.cpus \\ + -R ${mem_mb} \\ + -b $prefix \\ + $args + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + nonpareil: \$(echo \$(nonpareil -V 2>&1) | sed 's/Nonpareil v//' ) + END_VERSIONS + """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.npa + touch ${prefix}.npc + touch ${prefix}.npl + touch ${prefix}.npo + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + nonpareil: \$(echo \$(nonpareil -V 2>&1) | sed 's/Nonpareil v//' ) + END_VERSIONS + """ +} diff --git a/modules/nf-core/nonpareil/nonpareil/meta.yml b/modules/nf-core/nonpareil/nonpareil/meta.yml new file mode 100644 index 00000000..59f8bc05 --- /dev/null +++ b/modules/nf-core/nonpareil/nonpareil/meta.yml @@ -0,0 +1,67 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/yaml-schema.json +name: "nonpareil_nonpareil" +description: Calculate metagenome redundancy curve from FASTQ files +keywords: + - metagenomics + - statistics + - coverage + - redundancy + - diversity + - complexity +tools: + - "nonpareil": + description: "Estimate average coverage and create curves for metagenomic datasets" + homepage: "https://github.com/lmrodriguezr/nonpareil" + documentation: "https://nonpareil.readthedocs.io/en/latest/" + tool_dev_url: "https://github.com/lmrodriguezr/nonpareil" + doi: "10.1128/msystems.00039-" + licence: ["Artistic License 2.0"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'test', single_end:false ]` + - reads: + type: file + description: FASTQ or FASTA file (ideally uncompressed, but not required) + pattern: "*.{fasta,fna,fas,fa,fastq,fq,fasta.gz,fna.gz,fas.gz,fa.gz,fastq.gz,fq.gz}" + - format: + type: string + description: File format of input file + pattern: "fasta|fastq" + - mode: + type: string + description: Mode of redundancy estimation + pattern: "kmer|alignment" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'test', single_end:false ]` + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + - npa: + type: file + description: Raw redundancy values + pattern: "*.npa" + - npc: + type: file + description: Mates distribution file + pattern: "*.npc" + - npl: + type: file + description: Log file + pattern: "*.npl" + - npo: + type: file + description: Redundancy summary file + pattern: "*.npo" +authors: + - "@jfy133" +maintainers: + - "@jfy133" diff --git a/modules/nf-core/nonpareil/nonpareil/tests/main.nf.test b/modules/nf-core/nonpareil/nonpareil/tests/main.nf.test new file mode 100644 index 00000000..be4e2b3f --- /dev/null +++ b/modules/nf-core/nonpareil/nonpareil/tests/main.nf.test @@ -0,0 +1,114 @@ +nextflow_process { + + name "Test Process NONPAREIL_NONPAREIL" + script "../main.nf" + process "NONPAREIL_NONPAREIL" + config "./nextflow.config" + tag "modules" + tag "modules_nfcore" + tag "nonpareil" + tag "nonpareil/nonpareil" + tag "gunzip" + + test("candidatus_portiera_aleyrodidarum - gzipped") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/prokaryotes/candidatus_portiera_aleyrodidarum/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + input[1] = 'fastq' + input[2] = 'kmer' + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + file(process.out.npa[0][1]).name, + file(process.out.npc[0][1]).name, + path(process.out.npo[0][1]).readLines()[0], + path(process.out.npl[0][1]).readLines().last().contains("Everything seems correct"), + process.out.versions + ).match() + } + ) + } + + } + + test("candidatus_portiera_aleyrodidarum - uncompressed") { + + + setup { + run("GUNZIP") { + script "../../../gunzip/main.nf" + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/prokaryotes/candidatus_portiera_aleyrodidarum/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + """ + } + } + } + + when { + process { + """ + input[0] = GUNZIP.out.gunzip + input[1] = 'fastq' + input[2] = 'kmer' + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + file(process.out.npa[0][1]).name, + file(process.out.npc[0][1]).name, + path(process.out.npo[0][1]).readLines()[0], + path(process.out.npl[0][1]).readLines().last().contains("Everything seems correct"), + process.out.versions + ).match() + } + ) + } + + } + +test("candidatus_portiera_aleyrodidarum - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/prokaryotes/candidatus_portiera_aleyrodidarum/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + input[1] = 'fastq' + input[2] = 'kmer' + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + +} diff --git a/modules/nf-core/nonpareil/nonpareil/tests/main.nf.test.snap b/modules/nf-core/nonpareil/nonpareil/tests/main.nf.test.snap new file mode 100644 index 00000000..14f2ad73 --- /dev/null +++ b/modules/nf-core/nonpareil/nonpareil/tests/main.nf.test.snap @@ -0,0 +1,123 @@ +{ + "candidatus_portiera_aleyrodidarum - uncompressed": { + "content": [ + "test.npa", + "test.npc", + "# @impl: Nonpareil", + true, + [ + "versions.yml:md5,5a5e1b70e05a4637015adbfaeac017fd" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.4" + }, + "timestamp": "2024-08-07T14:11:57.001694911" + }, + "candidatus_portiera_aleyrodidarum - gzipped": { + "content": [ + "test.npa", + "test.npc", + "# @impl: Nonpareil", + true, + [ + "versions.yml:md5,5a5e1b70e05a4637015adbfaeac017fd" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.4" + }, + "timestamp": "2024-08-07T14:11:49.888813434" + }, + "candidatus_portiera_aleyrodidarum - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.npa:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.npc:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + { + "id": "test", + "single_end": false + }, + "test.npl:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "3": [ + [ + { + "id": "test", + "single_end": false + }, + "test.npo:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "4": [ + "versions.yml:md5,5a5e1b70e05a4637015adbfaeac017fd" + ], + "npa": [ + [ + { + "id": "test", + "single_end": false + }, + "test.npa:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "npc": [ + [ + { + "id": "test", + "single_end": false + }, + "test.npc:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "npl": [ + [ + { + "id": "test", + "single_end": false + }, + "test.npl:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "npo": [ + [ + { + "id": "test", + "single_end": false + }, + "test.npo:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,5a5e1b70e05a4637015adbfaeac017fd" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.4" + }, + "timestamp": "2024-08-07T14:38:09.784957219" + } +} \ No newline at end of file diff --git a/modules/nf-core/nonpareil/nonpareil/tests/nextflow.config b/modules/nf-core/nonpareil/nonpareil/tests/nextflow.config new file mode 100644 index 00000000..3dfce831 --- /dev/null +++ b/modules/nf-core/nonpareil/nonpareil/tests/nextflow.config @@ -0,0 +1,9 @@ +process { + + publishDir = { "${params.outdir}/${task.process.tokenize(':')[-1].tokenize('_')[0].toLowerCase()}" } + + withName: NONPAREIL_NONPAREIL { + ext.args = '-X 100' + } + +} diff --git a/modules/nf-core/nonpareil/nonpareil/tests/tags.yml b/modules/nf-core/nonpareil/nonpareil/tests/tags.yml new file mode 100644 index 00000000..f20ff56f --- /dev/null +++ b/modules/nf-core/nonpareil/nonpareil/tests/tags.yml @@ -0,0 +1,2 @@ +nonpareil/nonpareil: + - modules/nf-core/nonpareil/nonpareil/** diff --git a/modules/nf-core/nonpareil/nonpareilcurvesr/environment.yml b/modules/nf-core/nonpareil/nonpareilcurvesr/environment.yml new file mode 100644 index 00000000..78bc8437 --- /dev/null +++ b/modules/nf-core/nonpareil/nonpareilcurvesr/environment.yml @@ -0,0 +1,7 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + - "bioconda::nonpareil=3.5.5" diff --git a/modules/nf-core/nonpareil/nonpareilcurvesr/main.nf b/modules/nf-core/nonpareil/nonpareilcurvesr/main.nf new file mode 100644 index 00000000..08d0c487 --- /dev/null +++ b/modules/nf-core/nonpareil/nonpareilcurvesr/main.nf @@ -0,0 +1,57 @@ +process NONPAREIL_NONPAREILCURVESR { + tag "$meta.id" + label 'process_single' + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/nonpareil:3.5.5--r43hdcf5f25_0': + 'biocontainers/nonpareil:3.5.5--r43hdcf5f25_0' }" + + input: + tuple val(meta), path(npos) + + output: + tuple val(meta), path("*.json"), emit: json, optional: true + tuple val(meta), path("*.tsv" ), emit: tsv , optional: true + tuple val(meta), path("*.csv" ), emit: csv , optional: true + tuple val(meta), path("*.pdf" ), emit: pdf , optional: true + + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + + """ + NonpareilCurves.R \\ + $args \\ + --json ${prefix}.json \\ + --tsv ${prefix}.tsv \\ + --csv ${prefix}.csv \\ + --pdf ${prefix}.pdf \\ + $npos + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + nonpareil: \$(echo \$(nonpareil -V 2>&1) | sed 's/Nonpareil v//' ) + END_VERSIONS + """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.json + touch ${prefix}.tsv + touch ${prefix}.csv + touch ${prefix}.pdf + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + nonpareil: \$(echo \$(nonpareil -V 2>&1) | sed 's/Nonpareil v//' ) + END_VERSIONS + """ +} diff --git a/modules/nf-core/nonpareil/nonpareilcurvesr/meta.yml b/modules/nf-core/nonpareil/nonpareilcurvesr/meta.yml new file mode 100644 index 00000000..a4aeeb63 --- /dev/null +++ b/modules/nf-core/nonpareil/nonpareilcurvesr/meta.yml @@ -0,0 +1,63 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/meta-schema.json +name: "nonpareil_nonpareilcurvesr" +description: Generate summary reports with raw data for Nonpareil NPO curves, including MultiQC compatible JSON/TSV files +keywords: + - metagenomics + - statistics + - coverage + - redundancy + - diversity + - complexity + - multiqc +tools: + - "nonpareil": + description: "Estimate average coverage and create curves for metagenomic datasets" + homepage: "https://github.com/lmrodriguezr/nonpareil" + documentation: "https://nonpareil.readthedocs.io/en/latest/" + tool_dev_url: "https://github.com/lmrodriguezr/nonpareil" + doi: "10.1128/msystems.00039-" + licence: ["Artistic License 2.0"] + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1', single_end:false ]` + - npos: + type: file + description: One or a list of Nonpareil NPO files (From nonpareil/nonpareil) + pattern: "*.{npo}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1', single_end:false ]` + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + - json: + type: file + description: Raw nonpareil data used for generating and plotting curves in JSON format + pattern: "*.json" + - tsv: + type: file + description: Raw nonpareil data used for generating and plotting curves in JSON format + pattern: "*.tsv" + - csv: + type: file + description: Raw nonpareil data used for generating and plotting curves in JSON format + pattern: "*.csv" + - pdf: + type: file + description: Plotted nonpareil curves in PDF format + pattern: "*.pdf" + +authors: + - "@jfy133" +maintainers: + - "@jfy133" diff --git a/modules/nf-core/nonpareil/nonpareilcurvesr/tests/main.nf.test b/modules/nf-core/nonpareil/nonpareilcurvesr/tests/main.nf.test new file mode 100644 index 00000000..95420207 --- /dev/null +++ b/modules/nf-core/nonpareil/nonpareilcurvesr/tests/main.nf.test @@ -0,0 +1,76 @@ +nextflow_process { + + name "Test Process NONPAREIL_NONPAREILCURVESR" + script "../main.nf" + process "NONPAREIL_NONPAREILCURVESR" + + tag "modules" + tag "modules_nfcore" + tag "nonpareil" + tag "nonpareil/nonpareilcurvesr" + tag "nonpareil/nonpareil" + + setup { + run("NONPAREIL_NONPAREIL") { + script "../../../nonpareil/nonpareil/main.nf" + process { + """ + input[0] = Channel.fromList([ + [[ id:'test', single_end:false ], file(params.modules_testdata_base_path + 'genomics/prokaryotes/candidatus_portiera_aleyrodidarum/illumina/fastq/test_1.fastq.gz', checkIfExists: true)], + [[ id:'test2', single_end:false ], file(params.modules_testdata_base_path + 'genomics/prokaryotes/candidatus_portiera_aleyrodidarum/illumina/fastq/test_1.fastq.gz', checkIfExists: true)], + ]) + input[1] = 'fastq' + input[2] = 'kmer' + """ + } + } + } + + test("candidatus_portiera_aleyrodidarum") { + + when { + process { + """ + input[0] = NONPAREIL_NONPAREIL.out.npo.map{meta, npo -> [[id:'test'], npo]}.groupTuple() + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + path(process.out.json[0][1]).text.contains("modelR\": 0."), + path(process.out.tsv[0][1]).text.contains("test 0."), + path(process.out.csv[0][1]).text.contains("test\",0."), + file(process.out.pdf[0][1]).name, + process.out.versions + ).match() + } + ) + } + + } + + test("candidatus_portiera_aleyrodidarum - stub") { + + options "-stub" + + when { + process { + """ + input[0] = NONPAREIL_NONPAREIL.out.npo.map{meta, npo -> [[id:'test'], npo]}.groupTuple() + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + +} diff --git a/modules/nf-core/nonpareil/nonpareilcurvesr/tests/main.nf.test.snap b/modules/nf-core/nonpareil/nonpareilcurvesr/tests/main.nf.test.snap new file mode 100644 index 00000000..acab9a67 --- /dev/null +++ b/modules/nf-core/nonpareil/nonpareilcurvesr/tests/main.nf.test.snap @@ -0,0 +1,99 @@ +{ + "candidatus_portiera_aleyrodidarum": { + "content": [ + true, + true, + true, + "test.pdf", + [ + "versions.yml:md5,9aae4700a1ceafa37850be8d82d8d6dc" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.4" + }, + "timestamp": "2024-08-08T12:14:04.694169651" + }, + "candidatus_portiera_aleyrodidarum - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test" + }, + "test.tsv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + { + "id": "test" + }, + "test.csv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "3": [ + [ + { + "id": "test" + }, + "test.pdf:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "4": [ + "versions.yml:md5,9aae4700a1ceafa37850be8d82d8d6dc" + ], + "csv": [ + [ + { + "id": "test" + }, + "test.csv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "json": [ + [ + { + "id": "test" + }, + "test.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "pdf": [ + [ + { + "id": "test" + }, + "test.pdf:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "tsv": [ + [ + { + "id": "test" + }, + "test.tsv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,9aae4700a1ceafa37850be8d82d8d6dc" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.4" + }, + "timestamp": "2024-08-08T12:03:11.519050978" + } +} diff --git a/modules/nf-core/nonpareil/nonpareilcurvesr/tests/tags.yml b/modules/nf-core/nonpareil/nonpareilcurvesr/tests/tags.yml new file mode 100644 index 00000000..ba718e06 --- /dev/null +++ b/modules/nf-core/nonpareil/nonpareilcurvesr/tests/tags.yml @@ -0,0 +1,2 @@ +nonpareil/nonpareilcurvesr: + - "modules/nf-core/nonpareil/nonpareilcurvesr/**" diff --git a/modules/nf-core/nonpareil/set/environment.yml b/modules/nf-core/nonpareil/set/environment.yml new file mode 100644 index 00000000..89d5aa6e --- /dev/null +++ b/modules/nf-core/nonpareil/set/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::nonpareil=3.5.5 diff --git a/modules/nf-core/nonpareil/set/main.nf b/modules/nf-core/nonpareil/set/main.nf new file mode 100644 index 00000000..003c8958 --- /dev/null +++ b/modules/nf-core/nonpareil/set/main.nf @@ -0,0 +1,51 @@ +process NONPAREIL_SET { + tag "$meta.id" + label 'process_single' + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/nonpareil:3.5.5--r43hdcf5f25_0': + 'biocontainers/nonpareil:3.5.5--r43hdcf5f25_0' }" + + input: + tuple val(meta), path(npos) + + output: + tuple val(meta), path("*.png"), emit: png + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def args_cmd = args != '' ? ", ${args}" : "" + """ + #!/usr/bin/env Rscript + library(Nonpareil) + + png(file='${prefix}.png') + Nonpareil.set(list.files(pattern='*.npo')${args_cmd}) + dev.off() + + version_file_path <- "versions.yml" + version_nonpareil <- paste(unlist(packageVersion("Nonpareil")), collapse = ".") + f <- file(version_file_path, "w") + writeLines('"${task.process}":', f) + writeLines(" nonpareil: ", f, sep = "") + writeLines(version_nonpareil, f) + close(f) + """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.png + + cat <<-END_VERSIONS > versions.yml + "${task.process}": \$(Rscript -e 'library('Nonpareil'); cat(paste(unlist(packageVersion("Nonpareil")),collapse="."))') + END_VERSIONS + """ +} diff --git a/modules/nf-core/nonpareil/set/meta.yml b/modules/nf-core/nonpareil/set/meta.yml new file mode 100644 index 00000000..74a26122 --- /dev/null +++ b/modules/nf-core/nonpareil/set/meta.yml @@ -0,0 +1,48 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/yaml-schema.json +name: "nonpareil_set" +description: Visualise metagenome redundancy curves in PNG format from multiple Nonpareil npo files in a single image +keywords: + - metagenomics + - statistics + - coverage + - complexity + - redundancy + - diversity + - visualisation +tools: + - "nonpareil": + description: "Estimate average coverage and create curves for metagenomic datasets" + homepage: "https://github.com/lmrodriguezr/nonpareil" + documentation: "https://nonpareil.readthedocs.io/en/latest/" + tool_dev_url: "https://github.com/lmrodriguezr/nonpareil" + doi: "10.1128/msystems.00039-" + licence: ["Artistic License 2.0"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'test', single_end:false ]` + - npos: + type: file + description: A list of npo redundancy summary files from nonpareil itself + pattern: "*.npo" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'test', single_end:false ]` + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + - png: + type: file + description: PNG file of all the Nonpareil curves of the input npo files + pattern: "*.png" +authors: + - "@jfy133" +maintainers: + - "@jfy133" diff --git a/modules/nf-core/nonpareil/set/tests/main.nf.test b/modules/nf-core/nonpareil/set/tests/main.nf.test new file mode 100644 index 00000000..23e7fa97 --- /dev/null +++ b/modules/nf-core/nonpareil/set/tests/main.nf.test @@ -0,0 +1,73 @@ +nextflow_process { + + name "Test Process NONPAREIL_SET" + script "../main.nf" + process "NONPAREIL_SET" + config "./nextflow.config" + tag "modules" + tag "modules_nfcore" + tag "nonpareil" + tag "nonpareil/set" + tag "nonpareil/nonpareil" + + setup { + run("NONPAREIL_NONPAREIL") { + script "../../../nonpareil/nonpareil/main.nf" + process { + """ + input[0] = Channel.fromList([ + [[ id:'test', single_end:false ], file(params.modules_testdata_base_path + 'genomics/prokaryotes/candidatus_portiera_aleyrodidarum/illumina/fastq/test_1.fastq.gz', checkIfExists: true)], + [[ id:'test2', single_end:false ], file(params.modules_testdata_base_path + 'genomics/prokaryotes/candidatus_portiera_aleyrodidarum/illumina/fastq/test_1.fastq.gz', checkIfExists: true)], + ]) + input[1] = 'fastq' + input[2] = 'kmer' + """ + } + } + } + + test("candidatus_portiera_aleyrodidarum") { + + when { + process { + """ + input[0] = NONPAREIL_NONPAREIL.out.npo.map{meta, npo -> [[id:'test'], npo]}.groupTuple() + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + file(process.out.png[0][1]).name, + process.out.versions + ).match() + } + ) + } + + } + +test("candidatus_portiera_aleyrodidarum - stub") { + + options "-stub" + + when { + process { + """ + input[0] = NONPAREIL_NONPAREIL.out.npo.map{meta, npo -> [[id:'test'], npo]}.groupTuple() + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + +} diff --git a/modules/nf-core/nonpareil/set/tests/main.nf.test.snap b/modules/nf-core/nonpareil/set/tests/main.nf.test.snap new file mode 100644 index 00000000..98ff42aa --- /dev/null +++ b/modules/nf-core/nonpareil/set/tests/main.nf.test.snap @@ -0,0 +1,48 @@ +{ + "candidatus_portiera_aleyrodidarum": { + "content": [ + "test.png", + [ + "versions.yml:md5,99b7abbea8d46b0a3d15ecd35049dc8d" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.4" + }, + "timestamp": "2024-08-07T12:12:45.998873423" + }, + "candidatus_portiera_aleyrodidarum - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.png:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,e12f68cd2102c6ab64e888bec3c7e7aa" + ], + "png": [ + [ + { + "id": "test" + }, + "test.png:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e12f68cd2102c6ab64e888bec3c7e7aa" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.4" + }, + "timestamp": "2024-08-07T14:40:53.480864245" + } +} \ No newline at end of file diff --git a/modules/nf-core/nonpareil/set/tests/nextflow.config b/modules/nf-core/nonpareil/set/tests/nextflow.config new file mode 100644 index 00000000..7809cca9 --- /dev/null +++ b/modules/nf-core/nonpareil/set/tests/nextflow.config @@ -0,0 +1,11 @@ +process { + + withName: NONPAREIL_NONPAREIL { + ext.args = '-X 100' + } + + withName: NONPAREIL_SET { + ext.args = "col = c('blue', 'red')" + } + +} diff --git a/modules/nf-core/nonpareil/set/tests/tags.yml b/modules/nf-core/nonpareil/set/tests/tags.yml new file mode 100644 index 00000000..1de9e293 --- /dev/null +++ b/modules/nf-core/nonpareil/set/tests/tags.yml @@ -0,0 +1,2 @@ +nonpareil/set: + - modules/nf-core/nonpareil/set/** diff --git a/modules/nf-core/porechop/abi/environment.yml b/modules/nf-core/porechop/abi/environment.yml new file mode 100644 index 00000000..dabb4921 --- /dev/null +++ b/modules/nf-core/porechop/abi/environment.yml @@ -0,0 +1,7 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::porechop_abi=0.5.0 diff --git a/modules/nf-core/porechop/abi/main.nf b/modules/nf-core/porechop/abi/main.nf new file mode 100644 index 00000000..88ec5bd0 --- /dev/null +++ b/modules/nf-core/porechop/abi/main.nf @@ -0,0 +1,50 @@ +process PORECHOP_ABI { + tag "$meta.id" + label 'process_medium' + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/porechop_abi:0.5.0--py310h590eda1_0': + 'biocontainers/porechop_abi:0.5.0--py310h590eda1_0' }" + + input: + tuple val(meta), path(reads) + + output: + tuple val(meta), path("*.fastq.gz") , emit: reads + tuple val(meta), path("*.log") , emit: log + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}.porechop_abi" + if ("$reads" == "${prefix}.fastq.gz") error "Input and output names are the same, use \"task.ext.prefix\" to disambiguate!" + """ + porechop_abi \\ + --input $reads \\ + --threads $task.cpus \\ + $args \\ + --output ${prefix}.fastq.gz \\ + | tee ${prefix}.log + cat <<-END_VERSIONS > versions.yml + "${task.process}": + porechop_abi: \$( porechop_abi --version ) + END_VERSIONS + """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}.porechop_abi" + """ + echo "" | gzip > ${prefix}.fastq.gz + touch ${prefix}.log + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + porechop_abi: \$( porechop_abi --version ) + END_VERSIONS + """ +} diff --git a/modules/nf-core/porechop/abi/meta.yml b/modules/nf-core/porechop/abi/meta.yml new file mode 100644 index 00000000..a856ffbe --- /dev/null +++ b/modules/nf-core/porechop/abi/meta.yml @@ -0,0 +1,48 @@ +name: "porechop_abi" +description: Extension of Porechop whose purpose is to process adapter sequences in ONT reads. +keywords: + - porechop_abi + - adapter + - nanopore +tools: + - "porechop_abi": + description: Extension of Porechop whose purpose is to process adapter sequences in ONT reads. + homepage: "https://github.com/bonsai-team/Porechop_ABI" + documentation: "https://github.com/bonsai-team/Porechop_ABI" + tool_dev_url: "https://github.com/bonsai-team/Porechop_ABI" + doi: "10.1101/2022.07.07.499093" + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - reads: + type: file + description: fastq/fastq.gz file + pattern: "*.{fastq,fastq.gz,fq,fq.gz}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + - reads: + type: file + description: Adapter-trimmed fastq.gz file + pattern: "*.fastq.gz" + - log: + type: file + description: Log file containing stdout information + pattern: "*.log" +authors: + - "@sofstam" + - "LilyAnderssonLee" +maintainers: + - "@sofstam" + - "LilyAnderssonLee" diff --git a/modules/nf-core/porechop/abi/tests/main.nf.test b/modules/nf-core/porechop/abi/tests/main.nf.test new file mode 100644 index 00000000..b5a29f90 --- /dev/null +++ b/modules/nf-core/porechop/abi/tests/main.nf.test @@ -0,0 +1,59 @@ +nextflow_process { + + name "Test Process PORECHOP_ABI" + script "../main.nf" + process "PORECHOP_ABI" + tag "modules" + tag "modules_nfcore" + tag "porechop" + tag "porechop/abi" + + test("sarscov2-nanopore") { + + when { + process { + """ + input[0] = [ + [ id:'test'], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/nanopore/fastq/test.fastq.gz', checkIfExists: true) + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + process.out.reads, + file(process.out.log.get(0).get(1)).readLines()[20..40], + process.out.versions).match() + } + ) + } + } + + test("sarscov2-nanopore - stub") { + + options "-stub" + + when { + + process { + """ + input[0] = [ + [ id:'test'], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/nanopore/fastq/test.fastq.gz', checkIfExists: true) + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } +} diff --git a/modules/nf-core/porechop/abi/tests/main.nf.test.snap b/modules/nf-core/porechop/abi/tests/main.nf.test.snap new file mode 100644 index 00000000..ad63f4ed --- /dev/null +++ b/modules/nf-core/porechop/abi/tests/main.nf.test.snap @@ -0,0 +1,94 @@ +{ + "sarscov2-nanopore": { + "content": [ + [ + [ + { + "id": "test" + }, + "test.porechop_abi.fastq.gz:md5,886fdb859fb50e0dddd35007bcff043e" + ] + ], + [ + " Best \u001b[0m", + " read Best \u001b[0m", + " start read end\u001b[0m", + " \u001b[4mSet %ID %ID \u001b[0m", + " \u001b[32mSQK-NSK007 100.0 73.1\u001b[0m", + " Rapid 40.4 0.0", + " RBK004_upstream 77.5 0.0", + " SQK-MAP006 75.8 72.7", + " SQK-MAP006 short 65.5 66.7", + " PCR adapters 1 73.9 69.6", + " PCR adapters 2 80.0 72.7", + " PCR adapters 3 70.8 69.6", + " 1D^2 part 1 71.4 70.0", + " 1D^2 part 2 84.8 75.8", + " cDNA SSP 63.0 61.7", + " \u001b[32mBarcode 1 (reverse) 100.0 100.0\u001b[0m", + " Barcode 2 (reverse) 70.8 69.2", + " Barcode 3 (reverse) 76.0 70.4", + " Barcode 4 (reverse) 74.1 71.4", + " Barcode 5 (reverse) 77.8 80.8", + " Barcode 6 (reverse) 73.1 70.8" + ], + [ + "versions.yml:md5,0e9e5e0d35a68ff8e6490c949b257f98" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.1" + }, + "timestamp": "2024-07-29T13:50:49.318599" + }, + "sarscov2-nanopore - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.porechop_abi.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "1": [ + [ + { + "id": "test" + }, + "test.porechop_abi.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,0e9e5e0d35a68ff8e6490c949b257f98" + ], + "log": [ + [ + { + "id": "test" + }, + "test.porechop_abi.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "reads": [ + [ + { + "id": "test" + }, + "test.porechop_abi.fastq.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "versions": [ + "versions.yml:md5,0e9e5e0d35a68ff8e6490c949b257f98" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.1" + }, + "timestamp": "2024-07-29T13:50:54.425389" + } +} \ No newline at end of file diff --git a/modules/nf-core/porechop/porechop/environment.yml b/modules/nf-core/porechop/porechop/environment.yml new file mode 100644 index 00000000..4defeb33 --- /dev/null +++ b/modules/nf-core/porechop/porechop/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::porechop=0.2.4 diff --git a/modules/nf-core/porechop/porechop/main.nf b/modules/nf-core/porechop/porechop/main.nf index 648f2029..615ade21 100644 --- a/modules/nf-core/porechop/porechop/main.nf +++ b/modules/nf-core/porechop/porechop/main.nf @@ -2,7 +2,7 @@ process PORECHOP_PORECHOP { tag "$meta.id" label 'process_medium' - conda "bioconda::porechop=0.2.4" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/porechop:0.2.4--py39h7cff6ad_2' : 'biocontainers/porechop:0.2.4--py39h7cff6ad_2' }" @@ -11,7 +11,7 @@ process PORECHOP_PORECHOP { tuple val(meta), path(reads) output: - tuple val(meta), path("*_porechopped.fastq.gz"), emit: reads + tuple val(meta), path("*.fastq.gz"), emit: reads tuple val(meta), path("*.log") , emit: log path "versions.yml" , emit: versions @@ -21,16 +21,13 @@ process PORECHOP_PORECHOP { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" + if ("$reads" == "${prefix}.fastq.gz") error "Input and output names are the same, use \"task.ext.prefix\" to disambiguate!" """ - ## To ensure ID matches rest of pipeline based on meta.id rather than input file name - - [[ -f ${prefix}.fastq.gz ]] || ln -s $reads ${prefix}.fastq.gz - porechop \\ - -i ${prefix}.fastq.gz \\ + -i $reads \\ -t $task.cpus \\ $args \\ - -o ${prefix}_porechopped.fastq.gz \\ + -o ${prefix}.fastq.gz \\ > ${prefix}.log cat <<-END_VERSIONS > versions.yml @@ -38,4 +35,16 @@ process PORECHOP_PORECHOP { porechop: \$( porechop --version ) END_VERSIONS """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.fastq + gzip ${prefix}.fastq + touch ${prefix}.log + cat <<-END_VERSIONS > versions.yml + "${task.process}": + porechop: \$( porechop --version ) + END_VERSIONS + """ } diff --git a/modules/nf-core/porechop/porechop/meta.yml b/modules/nf-core/porechop/porechop/meta.yml index 98b838f6..13be76f2 100644 --- a/modules/nf-core/porechop/porechop/meta.yml +++ b/modules/nf-core/porechop/porechop/meta.yml @@ -12,7 +12,6 @@ tools: tool_dev_url: "https://github.com/rrwick/Porechop" doi: "10.1099/mgen.0.000132" licence: ["GPL v3"] - input: - meta: type: map @@ -23,7 +22,6 @@ input: type: file description: fastq/fastq.gz file pattern: "*.{fastq,fastq.gz,fq,fq.gz}" - output: - meta: type: map @@ -42,7 +40,6 @@ output: type: file description: Log file containing stdout information pattern: "*.log" - authors: - "@ggabernet" - "@jasmezz" @@ -53,3 +50,13 @@ authors: - "@jonoave" - "@GokceOGUZ" - "@jfy133" +maintainers: + - "@ggabernet" + - "@jasmezz" + - "@d4straub" + - "@LaurenceKuhl" + - "@SusiJo" + - "@jonasscheid" + - "@jonoave" + - "@GokceOGUZ" + - "@jfy133" diff --git a/modules/nf-core/porechop/porechop/porechop-porechop.diff b/modules/nf-core/porechop/porechop/porechop-porechop.diff index 5d51f24a..7f734c7b 100644 --- a/modules/nf-core/porechop/porechop/porechop-porechop.diff +++ b/modules/nf-core/porechop/porechop/porechop-porechop.diff @@ -1,30 +1,17 @@ Changes in module 'nf-core/porechop/porechop' --- modules/nf-core/porechop/porechop/main.nf +++ modules/nf-core/porechop/porechop/main.nf -@@ -11,7 +11,7 @@ - tuple val(meta), path(reads) - - output: -- tuple val(meta), path("*.fastq.gz"), emit: reads -+ tuple val(meta), path("*_porechopped.fastq.gz"), emit: reads - tuple val(meta), path("*.log") , emit: log - path "versions.yml" , emit: versions - -@@ -22,12 +22,17 @@ +@@ -21,6 +21,7 @@ + script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" ++ if ("$reads" == "${prefix}.fastq.gz") error "Input and output names are the same, use \"task.ext.prefix\" to disambiguate!" """ -+ ## To ensure ID matches rest of pipeline based on meta.id rather than input file name -+ -+ [[ -f ${prefix}.fastq.gz ]] || ln -s $reads ${prefix}.fastq.gz -+ porechop \\ -- -i $reads \\ -+ -i ${prefix}.fastq.gz \\ - -t $task.cpus \\ + -i $reads \\ +@@ -28,6 +29,7 @@ $args \\ -- -o ${prefix}.fastq.gz \\ -+ -o ${prefix}_porechopped.fastq.gz \\ + -o ${prefix}.fastq.gz \\ > ${prefix}.log + cat <<-END_VERSIONS > versions.yml diff --git a/modules/nf-core/porechop/porechop/tests/main.nf.test b/modules/nf-core/porechop/porechop/tests/main.nf.test new file mode 100644 index 00000000..ed3f6986 --- /dev/null +++ b/modules/nf-core/porechop/porechop/tests/main.nf.test @@ -0,0 +1,62 @@ +nextflow_process { + + name "Test Process PORECHOP_PORECHOP" + script "../main.nf" + process "PORECHOP_PORECHOP" + config "./nextflow.config" + + tag "modules" + tag "modules_nfcore" + tag "porechop" + tag "porechop/porechop" + + test("sarscov2 - nanopore - fastq") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/nanopore/fastq/test.fastq.gz', checkIfExists: true) + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out.reads).match("reads") }, + { assert snapshot(process.out.versions).match("versions") }, + // complete log is not stable. These first lines should be stable + { assert snapshot(path(process.out.log.get(0).get(1)).readLines()[0..7]).match("log")} + ) + } + + } + + + test("stub") { + options "-stub" + + when { + process { + """ + input[0] = [ [ id:'test', single_end:true ], + [] + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + +} diff --git a/modules/nf-core/porechop/porechop/tests/main.nf.test.snap b/modules/nf-core/porechop/porechop/tests/main.nf.test.snap new file mode 100644 index 00000000..cf544d2d --- /dev/null +++ b/modules/nf-core/porechop/porechop/tests/main.nf.test.snap @@ -0,0 +1,88 @@ +{ + "versions": { + "content": [ + [ + "versions.yml:md5,712c0753b56d0fb530092dfb5bdf2e5c" + ] + ], + "timestamp": "2023-12-18T07:47:16.83444" + }, + "log": { + "content": [ + [ + "", + "\u001b[1m\u001b[4mLoading reads\u001b[0m", + "test.fastq.gz", + "100 reads loaded", + "", + "", + "\u001b[1m\u001b[4mLooking for known adapter sets\u001b[0m", + "" + ] + ], + "timestamp": "2023-12-18T07:47:16.853899" + }, + "reads": { + "content": [ + [ + [ + { + "id": "test", + "single_end": true + }, + "test_porechop.fastq.gz:md5,886fdb859fb50e0dddd35007bcff043e" + ] + ] + ], + "timestamp": "2023-12-18T07:47:16.811393" + }, + "stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test_porechop.fastq.gz:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test_porechop.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,712c0753b56d0fb530092dfb5bdf2e5c" + ], + "log": [ + [ + { + "id": "test", + "single_end": true + }, + "test_porechop.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "reads": [ + [ + { + "id": "test", + "single_end": true + }, + "test_porechop.fastq.gz:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,712c0753b56d0fb530092dfb5bdf2e5c" + ] + } + ], + "timestamp": "2023-12-18T07:47:37.814949" + } +} \ No newline at end of file diff --git a/modules/nf-core/porechop/porechop/tests/nextflow.config b/modules/nf-core/porechop/porechop/tests/nextflow.config new file mode 100644 index 00000000..a9ecf7b6 --- /dev/null +++ b/modules/nf-core/porechop/porechop/tests/nextflow.config @@ -0,0 +1,9 @@ +process { + + + withName: PORECHOP_PORECHOP { + ext.args = '' + ext.prefix = { "${meta.id}_porechop" } + } + +} diff --git a/modules/nf-core/porechop/porechop/tests/tags.yml b/modules/nf-core/porechop/porechop/tests/tags.yml new file mode 100644 index 00000000..743645c2 --- /dev/null +++ b/modules/nf-core/porechop/porechop/tests/tags.yml @@ -0,0 +1,2 @@ +porechop/porechop: + - "modules/nf-core/porechop/porechop/**" diff --git a/modules/nf-core/prinseqplusplus/environment.yml b/modules/nf-core/prinseqplusplus/environment.yml new file mode 100644 index 00000000..fe598ef1 --- /dev/null +++ b/modules/nf-core/prinseqplusplus/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::prinseq-plus-plus=1.2.3 diff --git a/modules/nf-core/prinseqplusplus/main.nf b/modules/nf-core/prinseqplusplus/main.nf index 63b2c723..6981445e 100644 --- a/modules/nf-core/prinseqplusplus/main.nf +++ b/modules/nf-core/prinseqplusplus/main.nf @@ -2,7 +2,7 @@ process PRINSEQPLUSPLUS { tag "$meta.id" label 'process_low' - conda "bioconda::prinseq-plus-plus=1.2.3" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/prinseq-plus-plus:1.2.3--hc90279e_1': 'biocontainers/prinseq-plus-plus:1.2.3--hc90279e_1' }" diff --git a/modules/nf-core/prinseqplusplus/meta.yml b/modules/nf-core/prinseqplusplus/meta.yml index 8155df93..a978be4a 100644 --- a/modules/nf-core/prinseqplusplus/meta.yml +++ b/modules/nf-core/prinseqplusplus/meta.yml @@ -12,8 +12,7 @@ tools: documentation: "https://github.com/Adrian-Cantu/PRINSEQ-plus-plus" tool_dev_url: "https://github.com/Adrian-Cantu/PRINSEQ-plus-plus" doi: "10.7287/peerj.preprints.27553v1" - licence: "['GPL v2']" - + licence: ["GPL v2"] input: - meta: type: map @@ -25,7 +24,6 @@ input: description: | List of input FastQ files of size 1 and 2 for single-end and paired-end data, respectively. - output: - meta: type: map @@ -55,6 +53,7 @@ output: description: | Verbose level 2 STDOUT information in a log file pattern: "*.log" - authors: - "@jfy133" +maintainers: + - "@jfy133" diff --git a/modules/nf-core/prinseqplusplus/tests/main.nf.test b/modules/nf-core/prinseqplusplus/tests/main.nf.test new file mode 100644 index 00000000..a6708ce9 --- /dev/null +++ b/modules/nf-core/prinseqplusplus/tests/main.nf.test @@ -0,0 +1,74 @@ + +nextflow_process { + + name "Test Process PRINSEQPLUSPLUS" + script "../main.nf" + process "PRINSEQPLUSPLUS" + config "./nextflow.config" + + tag "modules" + tag "modules_nfcore" + tag "prinseqplusplus" + + test("test-prinseqplusplus-single-end") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:true ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] + ] + + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + file(process.out.good_reads[0][1]).name, // unstable + process.out.single_reads, + process.out.bad_reads, + file(process.out.log[0][1]).name, + process.out.versions + ).match() + } + ) + } + } + + test("test-prinseqplusplus-paired-end") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) + ] + ] + + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + process.out.good_reads[0][1].collect { file(it).name }, // unstable + process.out.single_reads[0][1].collect { file(it).name }, // empty: d41d8cd98f00b204e9800998ecf8427e + process.out.bad_reads, + file(process.out.log[0][1]).name, + process.out.versions + ).match() + } + ) + } + } + +} diff --git a/modules/nf-core/prinseqplusplus/tests/main.nf.test.snap b/modules/nf-core/prinseqplusplus/tests/main.nf.test.snap new file mode 100644 index 00000000..b9dcd854 --- /dev/null +++ b/modules/nf-core/prinseqplusplus/tests/main.nf.test.snap @@ -0,0 +1,61 @@ +{ + "test-prinseqplusplus-single-end": { + "content": [ + "test_good_out.fastq.gz", + [ + + ], + [ + [ + { + "id": "test", + "single_end": true + }, + "test_bad_out.fastq.gz:md5,16c592181d7763349c37f5c357374344" + ] + ], + "test.log", + [ + "versions.yml:md5,366e108ac2695a852af440e61fecad5e" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.4" + }, + "timestamp": "2024-08-27T14:55:34.731661" + }, + "test-prinseqplusplus-paired-end": { + "content": [ + [ + "test_good_out_R1.fastq.gz", + "test_good_out_R2.fastq.gz" + ], + [ + "test_single_out_R1.fastq.gz", + "test_single_out_R2.fastq.gz" + ], + [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_bad_out_R1.fastq.gz:md5,16c592181d7763349c37f5c357374344", + "test_bad_out_R2.fastq.gz:md5,e6c58927d64c132d59a33fd6a3f63951" + ] + ] + ], + "test.log", + [ + "versions.yml:md5,366e108ac2695a852af440e61fecad5e" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.4" + }, + "timestamp": "2024-08-27T14:57:53.505032" + } +} \ No newline at end of file diff --git a/modules/nf-core/prinseqplusplus/tests/nextflow.config b/modules/nf-core/prinseqplusplus/tests/nextflow.config new file mode 100644 index 00000000..14bae89f --- /dev/null +++ b/modules/nf-core/prinseqplusplus/tests/nextflow.config @@ -0,0 +1,5 @@ +process { + withName: PRINSEQPLUSPLUS { + ext.args = "-lc_entropy=0.8" + } +} diff --git a/modules/nf-core/samtools/fastq/environment.yml b/modules/nf-core/samtools/fastq/environment.yml new file mode 100644 index 00000000..da2df5e4 --- /dev/null +++ b/modules/nf-core/samtools/fastq/environment.yml @@ -0,0 +1,6 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::samtools=1.20 + - bioconda::htslib=1.20 diff --git a/modules/nf-core/samtools/fastq/main.nf b/modules/nf-core/samtools/fastq/main.nf index 15d89769..6796c02b 100644 --- a/modules/nf-core/samtools/fastq/main.nf +++ b/modules/nf-core/samtools/fastq/main.nf @@ -2,10 +2,10 @@ process SAMTOOLS_FASTQ { tag "$meta.id" label 'process_low' - conda "bioconda::samtools=1.17" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.17--h00cdaf9_0' : - 'biocontainers/samtools:1.17--h00cdaf9_0' }" + 'https://depot.galaxyproject.org/singularity/samtools:1.20--h50ea8bc_0' : + 'biocontainers/samtools:1.20--h50ea8bc_0' }" input: tuple val(meta), path(input) @@ -13,7 +13,7 @@ process SAMTOOLS_FASTQ { output: tuple val(meta), path("*_{1,2}.fastq.gz") , optional:true, emit: fastq - tuple val(meta), path("*_interleaved.fastq.gz"), optional:true, emit: interleaved + tuple val(meta), path("*_interleaved.fastq") , optional:true, emit: interleaved tuple val(meta), path("*_singleton.fastq.gz") , optional:true, emit: singleton tuple val(meta), path("*_other.fastq.gz") , optional:true, emit: other path "versions.yml" , emit: versions @@ -24,7 +24,7 @@ process SAMTOOLS_FASTQ { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" - def output = ( interleave && ! meta.single_end ) ? "> ${prefix}_interleaved.fastq.gz" : + def output = ( interleave && ! meta.single_end ) ? "> ${prefix}_interleaved.fastq" : meta.single_end ? "-1 ${prefix}_1.fastq.gz -s ${prefix}_singleton.fastq.gz" : "-1 ${prefix}_1.fastq.gz -2 ${prefix}_2.fastq.gz -s ${prefix}_singleton.fastq.gz" """ diff --git a/modules/nf-core/samtools/fastq/meta.yml b/modules/nf-core/samtools/fastq/meta.yml index b1a1ed38..c4002a45 100644 --- a/modules/nf-core/samtools/fastq/meta.yml +++ b/modules/nf-core/samtools/fastq/meta.yml @@ -15,7 +15,6 @@ tools: documentation: http://www.htslib.org/doc/samtools.html doi: 10.1093/bioinformatics/btp352 licence: ["MIT"] - input: - meta: type: map @@ -29,7 +28,6 @@ input: - interleave: type: boolean description: Set true for interleaved fastq file - output: - meta: type: map @@ -56,7 +54,9 @@ output: type: file description: Compressed FASTQ file with reads with either both READ1 and READ2 flags set or unset pattern: "*_other.fastq.gz" - authors: - "@priyanka-surana" - "@suzannejin" +maintainers: + - "@priyanka-surana" + - "@suzannejin" diff --git a/modules/nf-core/samtools/fastq/tests/main.nf.test b/modules/nf-core/samtools/fastq/tests/main.nf.test new file mode 100644 index 00000000..f6ac1123 --- /dev/null +++ b/modules/nf-core/samtools/fastq/tests/main.nf.test @@ -0,0 +1,67 @@ +nextflow_process { + + name "Test Process SAMTOOLS_FASTQ" + script "../main.nf" + process "SAMTOOLS_FASTQ" + + tag "modules" + tag "modules_nfcore" + tag "samtools" + tag "samtools/fastq" + + test("bam") { + + when { + process { + """ + interleave = false + + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.bam', checkIfExists: true) + ]) + input[1] = interleave + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out.fastq[0][1].collect { path(it).linesGzip[0..6] }).match("bam_fastq") }, + { assert snapshot(process.out.interleaved).match("bam_interleaved") }, + { assert snapshot(file(process.out.singleton[0][1]).name).match("bam_singleton") }, + { assert snapshot(file(process.out.other[0][1]).name).match("bam_other") }, + { assert snapshot(process.out.versions).match("bam_versions") } + ) + } + } + + test("bam_interleave") { + + when { + process { + """ + interleave = true + + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.bam', checkIfExists: true) + ]) + input[1] = interleave + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out.fastq).match("bam_interleave_fastq") }, + { assert snapshot(path(process.out.interleaved[0][1]).readLines()[0..6]).match("bam_interlinterleave_eaved") }, + { assert snapshot(process.out.singleton).match("bam_singinterleave_leton") }, + { assert snapshot(file(process.out.other[0][1]).name).match("bam_interleave_other") }, + { assert snapshot(process.out.versions).match("bam_verinterleave_sions") } + ) + } + } +} diff --git a/modules/nf-core/samtools/fastq/tests/main.nf.test.snap b/modules/nf-core/samtools/fastq/tests/main.nf.test.snap new file mode 100644 index 00000000..1ba09d3a --- /dev/null +++ b/modules/nf-core/samtools/fastq/tests/main.nf.test.snap @@ -0,0 +1,139 @@ +{ + "bam_interlinterleave_eaved": { + "content": [ + [ + "@ERR5069949.2151832/1", + "TCATAAACCAAAGCACTCACAGTGTCAACAATTTCAGCAGGACAACGCCGACAAGTTCCGAGGAACATGTCTGGACCTATAGTTTTCATAAGTCTACACACTGAATTGAAATATTCTGGTTCTAGTGTGCCCTTAGTTAGCAATGTGCGT", + "+", + "AAAAAAEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEAAEEEEAEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEAAEEEEE versions.yml "${task.process}": diff --git a/modules/nf-core/samtools/index/meta.yml b/modules/nf-core/samtools/index/meta.yml index 8bd2fa6f..01a4ee03 100644 --- a/modules/nf-core/samtools/index/meta.yml +++ b/modules/nf-core/samtools/index/meta.yml @@ -51,3 +51,7 @@ authors: - "@drpatelh" - "@ewels" - "@maxulysse" +maintainers: + - "@drpatelh" + - "@ewels" + - "@maxulysse" diff --git a/modules/nf-core/samtools/index/tests/csi.nextflow.config b/modules/nf-core/samtools/index/tests/csi.nextflow.config new file mode 100644 index 00000000..0ed260ef --- /dev/null +++ b/modules/nf-core/samtools/index/tests/csi.nextflow.config @@ -0,0 +1,7 @@ +process { + + withName: SAMTOOLS_INDEX { + ext.args = '-c' + } + +} diff --git a/modules/nf-core/samtools/index/tests/main.nf.test b/modules/nf-core/samtools/index/tests/main.nf.test new file mode 100644 index 00000000..ca34fb5c --- /dev/null +++ b/modules/nf-core/samtools/index/tests/main.nf.test @@ -0,0 +1,140 @@ +nextflow_process { + + name "Test Process SAMTOOLS_INDEX" + script "../main.nf" + process "SAMTOOLS_INDEX" + tag "modules" + tag "modules_nfcore" + tag "samtools" + tag "samtools/index" + + test("bai") { + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("crai") { + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.recalibrated.sorted.cram', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("csi") { + config "./csi.nextflow.config" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot( + file(process.out.csi[0][1]).name, + process.out.versions + ).match() } + ) + } + } + + test("bai - stub") { + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("crai - stub") { + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.recalibrated.sorted.cram', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("csi - stub") { + options "-stub" + config "./csi.nextflow.config" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } +} diff --git a/modules/nf-core/samtools/index/tests/main.nf.test.snap b/modules/nf-core/samtools/index/tests/main.nf.test.snap new file mode 100644 index 00000000..799d199c --- /dev/null +++ b/modules/nf-core/samtools/index/tests/main.nf.test.snap @@ -0,0 +1,250 @@ +{ + "csi - stub": { + "content": [ + { + "0": [ + + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.paired_end.sorted.bam.csi:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + + ], + "3": [ + "versions.yml:md5,802c9776d9c5e95314e888cf18e96d77" + ], + "bai": [ + + ], + "crai": [ + + ], + "csi": [ + [ + { + "id": "test", + "single_end": false + }, + "test.paired_end.sorted.bam.csi:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,802c9776d9c5e95314e888cf18e96d77" + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T16:51:53.9057" + }, + "crai - stub": { + "content": [ + { + "0": [ + + ], + "1": [ + + ], + "2": [ + [ + { + "id": "test", + "single_end": false + }, + "test.paired_end.recalibrated.sorted.cram.crai:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "3": [ + "versions.yml:md5,802c9776d9c5e95314e888cf18e96d77" + ], + "bai": [ + + ], + "crai": [ + [ + { + "id": "test", + "single_end": false + }, + "test.paired_end.recalibrated.sorted.cram.crai:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "csi": [ + + ], + "versions": [ + "versions.yml:md5,802c9776d9c5e95314e888cf18e96d77" + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T16:51:45.931558" + }, + "bai - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.paired_end.sorted.bam.bai:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + + ], + "2": [ + + ], + "3": [ + "versions.yml:md5,802c9776d9c5e95314e888cf18e96d77" + ], + "bai": [ + [ + { + "id": "test", + "single_end": false + }, + "test.paired_end.sorted.bam.bai:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "crai": [ + + ], + "csi": [ + + ], + "versions": [ + "versions.yml:md5,802c9776d9c5e95314e888cf18e96d77" + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T16:51:34.807525" + }, + "csi": { + "content": [ + "test.paired_end.sorted.bam.csi", + [ + "versions.yml:md5,802c9776d9c5e95314e888cf18e96d77" + ] + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T16:52:55.688799" + }, + "crai": { + "content": [ + { + "0": [ + + ], + "1": [ + + ], + "2": [ + [ + { + "id": "test", + "single_end": false + }, + "test.paired_end.recalibrated.sorted.cram.crai:md5,14bc3bd5c89cacc8f4541f9062429029" + ] + ], + "3": [ + "versions.yml:md5,802c9776d9c5e95314e888cf18e96d77" + ], + "bai": [ + + ], + "crai": [ + [ + { + "id": "test", + "single_end": false + }, + "test.paired_end.recalibrated.sorted.cram.crai:md5,14bc3bd5c89cacc8f4541f9062429029" + ] + ], + "csi": [ + + ], + "versions": [ + "versions.yml:md5,802c9776d9c5e95314e888cf18e96d77" + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T16:51:17.609533" + }, + "bai": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.paired_end.sorted.bam.bai:md5,704c10dd1326482448ca3073fdebc2f4" + ] + ], + "1": [ + + ], + "2": [ + + ], + "3": [ + "versions.yml:md5,802c9776d9c5e95314e888cf18e96d77" + ], + "bai": [ + [ + { + "id": "test", + "single_end": false + }, + "test.paired_end.sorted.bam.bai:md5,704c10dd1326482448ca3073fdebc2f4" + ] + ], + "crai": [ + + ], + "csi": [ + + ], + "versions": [ + "versions.yml:md5,802c9776d9c5e95314e888cf18e96d77" + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T16:51:04.16585" + } +} \ No newline at end of file diff --git a/modules/nf-core/samtools/index/tests/tags.yml b/modules/nf-core/samtools/index/tests/tags.yml new file mode 100644 index 00000000..e0f58a7a --- /dev/null +++ b/modules/nf-core/samtools/index/tests/tags.yml @@ -0,0 +1,2 @@ +samtools/index: + - modules/nf-core/samtools/index/** diff --git a/modules/nf-core/samtools/stats/environment.yml b/modules/nf-core/samtools/stats/environment.yml new file mode 100644 index 00000000..da2df5e4 --- /dev/null +++ b/modules/nf-core/samtools/stats/environment.yml @@ -0,0 +1,6 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::samtools=1.20 + - bioconda::htslib=1.20 diff --git a/modules/nf-core/samtools/stats/main.nf b/modules/nf-core/samtools/stats/main.nf index 4a2607de..982bc28e 100644 --- a/modules/nf-core/samtools/stats/main.nf +++ b/modules/nf-core/samtools/stats/main.nf @@ -2,10 +2,10 @@ process SAMTOOLS_STATS { tag "$meta.id" label 'process_single' - conda "bioconda::samtools=1.17" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.17--h00cdaf9_0' : - 'biocontainers/samtools:1.17--h00cdaf9_0' }" + 'https://depot.galaxyproject.org/singularity/samtools:1.20--h50ea8bc_0' : + 'biocontainers/samtools:1.20--h50ea8bc_0' }" input: tuple val(meta), path(input), path(input_index) diff --git a/modules/nf-core/samtools/stats/meta.yml b/modules/nf-core/samtools/stats/meta.yml index 90e6345f..735ff812 100644 --- a/modules/nf-core/samtools/stats/meta.yml +++ b/modules/nf-core/samtools/stats/meta.yml @@ -57,3 +57,7 @@ authors: - "@drpatelh" - "@FriederikeHanssen" - "@ramprasadn" +maintainers: + - "@drpatelh" + - "@FriederikeHanssen" + - "@ramprasadn" diff --git a/modules/nf-core/samtools/stats/tests/main.nf.test b/modules/nf-core/samtools/stats/tests/main.nf.test new file mode 100644 index 00000000..5bc89309 --- /dev/null +++ b/modules/nf-core/samtools/stats/tests/main.nf.test @@ -0,0 +1,113 @@ +nextflow_process { + + name "Test Process SAMTOOLS_STATS" + script "../main.nf" + process "SAMTOOLS_STATS" + + tag "modules" + tag "modules_nfcore" + tag "samtools" + tag "samtools/stats" + + test("bam") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam.bai', checkIfExists: true) + ]) + input[1] = [[],[]] + """ + } + } + + then { + assertAll( + {assert process.success}, + {assert snapshot(process.out).match()} + ) + } + } + + test("cram") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.recalibrated.sorted.cram', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.recalibrated.sorted.cram.crai', checkIfExists: true) + ]) + input[1] = Channel.of([ + [ id:'genome' ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll( + {assert process.success}, + {assert snapshot(process.out).match()} + ) + } + } + + test("bam - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam.bai', checkIfExists: true) + ]) + input[1] = [[],[]] + """ + } + } + + then { + assertAll( + {assert process.success}, + {assert snapshot(process.out).match()} + ) + } + } + + test("cram - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.recalibrated.sorted.cram', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.recalibrated.sorted.cram.crai', checkIfExists: true) + ]) + input[1] = Channel.of([ + [ id:'genome' ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll( + {assert process.success}, + {assert snapshot(process.out).match()} + ) + } + } +} diff --git a/modules/nf-core/samtools/stats/tests/main.nf.test.snap b/modules/nf-core/samtools/stats/tests/main.nf.test.snap new file mode 100644 index 00000000..3828f378 --- /dev/null +++ b/modules/nf-core/samtools/stats/tests/main.nf.test.snap @@ -0,0 +1,142 @@ +{ + "cram": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.stats:md5,c9d39b38c22de2057fc2f89949090975" + ] + ], + "1": [ + "versions.yml:md5,b3b70b126f867fdbb7dcea5e36e49d4a" + ], + "stats": [ + [ + { + "id": "test", + "single_end": false + }, + "test.stats:md5,c9d39b38c22de2057fc2f89949090975" + ] + ], + "versions": [ + "versions.yml:md5,b3b70b126f867fdbb7dcea5e36e49d4a" + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T14:20:24.885816" + }, + "bam - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.stats:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,b3b70b126f867fdbb7dcea5e36e49d4a" + ], + "stats": [ + [ + { + "id": "test", + "single_end": false + }, + "test.stats:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,b3b70b126f867fdbb7dcea5e36e49d4a" + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T14:20:39.310713" + }, + "cram - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.stats:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,b3b70b126f867fdbb7dcea5e36e49d4a" + ], + "stats": [ + [ + { + "id": "test", + "single_end": false + }, + "test.stats:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,b3b70b126f867fdbb7dcea5e36e49d4a" + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T14:21:04.771199" + }, + "bam": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.stats:md5,d522a1fa016b259d6a55620ae53dcd63" + ] + ], + "1": [ + "versions.yml:md5,b3b70b126f867fdbb7dcea5e36e49d4a" + ], + "stats": [ + [ + { + "id": "test", + "single_end": false + }, + "test.stats:md5,d522a1fa016b259d6a55620ae53dcd63" + ] + ], + "versions": [ + "versions.yml:md5,b3b70b126f867fdbb7dcea5e36e49d4a" + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T14:19:06.645466" + } +} \ No newline at end of file diff --git a/modules/nf-core/samtools/stats/tests/tags.yml b/modules/nf-core/samtools/stats/tests/tags.yml new file mode 100644 index 00000000..7c28e30f --- /dev/null +++ b/modules/nf-core/samtools/stats/tests/tags.yml @@ -0,0 +1,2 @@ +samtools/stats: + - modules/nf-core/samtools/stats/** diff --git a/modules/nf-core/samtools/view/environment.yml b/modules/nf-core/samtools/view/environment.yml new file mode 100644 index 00000000..da2df5e4 --- /dev/null +++ b/modules/nf-core/samtools/view/environment.yml @@ -0,0 +1,6 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::samtools=1.20 + - bioconda::htslib=1.20 diff --git a/modules/nf-core/samtools/view/main.nf b/modules/nf-core/samtools/view/main.nf index cb91facf..dc611448 100644 --- a/modules/nf-core/samtools/view/main.nf +++ b/modules/nf-core/samtools/view/main.nf @@ -2,10 +2,10 @@ process SAMTOOLS_VIEW { tag "$meta.id" label 'process_low' - conda "bioconda::samtools=1.17" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.17--h00cdaf9_0' : - 'biocontainers/samtools:1.17--h00cdaf9_0' }" + 'https://depot.galaxyproject.org/singularity/samtools:1.20--h50ea8bc_0' : + 'biocontainers/samtools:1.20--h50ea8bc_0' }" input: tuple val(meta), path(input), path(index) @@ -13,13 +13,15 @@ process SAMTOOLS_VIEW { path qname output: - tuple val(meta), path("*.bam"), emit: bam, optional: true - tuple val(meta), path("*.cram"), emit: cram, optional: true - tuple val(meta), path("*.sam"), emit: sam, optional: true - tuple val(meta), path("*.bai"), emit: bai, optional: true - tuple val(meta), path("*.csi"), emit: csi, optional: true - tuple val(meta), path("*.crai"), emit: crai, optional: true - path "versions.yml", emit: versions + tuple val(meta), path("${prefix}.bam"), emit: bam, optional: true + tuple val(meta), path("${prefix}.cram"), emit: cram, optional: true + tuple val(meta), path("${prefix}.sam"), emit: sam, optional: true + tuple val(meta), path("${prefix}.${file_type}.bai"), emit: bai, optional: true + tuple val(meta), path("${prefix}.${file_type}.csi"), emit: csi, optional: true + tuple val(meta), path("${prefix}.${file_type}.crai"), emit: crai, optional: true + tuple val(meta), path("${prefix}.unselected.${file_type}"), emit: unselected, optional: true + tuple val(meta), path("${prefix}.unselected.${file_type}.{bai,csi,crsi}"), emit: unselected_index, optional: true + path "versions.yml", emit: versions when: task.ext.when == null || task.ext.when @@ -27,13 +29,13 @@ process SAMTOOLS_VIEW { script: def args = task.ext.args ?: '' def args2 = task.ext.args2 ?: '' - def prefix = task.ext.prefix ?: "${meta.id}" + prefix = task.ext.prefix ?: "${meta.id}" def reference = fasta ? "--reference ${fasta}" : "" - def readnames = qname ? "--qname-file ${qname}": "" - def file_type = args.contains("--output-fmt sam") ? "sam" : - args.contains("--output-fmt bam") ? "bam" : - args.contains("--output-fmt cram") ? "cram" : - input.getExtension() + file_type = args.contains("--output-fmt sam") ? "sam" : + args.contains("--output-fmt bam") ? "bam" : + args.contains("--output-fmt cram") ? "cram" : + input.getExtension() + readnames = qname ? "--qname-file ${qname} --output-unselected ${prefix}.unselected.${file_type}": "" if ("$input" == "${prefix}.${file_type}") error "Input and output names are the same, use \"task.ext.prefix\" to disambiguate!" """ samtools \\ @@ -53,10 +55,19 @@ process SAMTOOLS_VIEW { """ stub: - def prefix = task.ext.prefix ?: "${meta.id}" + def args = task.ext.args ?: '' + prefix = task.ext.prefix ?: "${meta.id}" + file_type = args.contains("--output-fmt sam") ? "sam" : + args.contains("--output-fmt bam") ? "bam" : + args.contains("--output-fmt cram") ? "cram" : + input.getExtension() + if ("$input" == "${prefix}.${file_type}") error "Input and output names are the same, use \"task.ext.prefix\" to disambiguate!" + + def index = args.contains("--write-index") ? "touch ${prefix}.${file_type}.csi" : "" + """ - touch ${prefix}.bam - touch ${prefix}.cram + touch ${prefix}.${file_type} + ${index} cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/nf-core/samtools/view/meta.yml b/modules/nf-core/samtools/view/meta.yml index 3b05450b..27be60d0 100644 --- a/modules/nf-core/samtools/view/meta.yml +++ b/modules/nf-core/samtools/view/meta.yml @@ -73,6 +73,15 @@ output: type: file description: optional CRAM file index pattern: "*.{crai}" + # unselected and unselected_index are created when passing a qname + - unselected: + type: file + description: optional file with unselected alignments + pattern: "*.unselected.{bam,cram,sam}" + - unselected_index: + type: file + description: index for the "unselected" file + pattern: "*.unselected.{bai,csi,crai}" - versions: type: file description: File containing software versions @@ -82,3 +91,8 @@ authors: - "@joseespinosa" - "@FriederikeHanssen" - "@priyanka-surana" +maintainers: + - "@drpatelh" + - "@joseespinosa" + - "@FriederikeHanssen" + - "@priyanka-surana" diff --git a/modules/nf-core/samtools/view/tests/bam.config b/modules/nf-core/samtools/view/tests/bam.config new file mode 100644 index 00000000..c10d1081 --- /dev/null +++ b/modules/nf-core/samtools/view/tests/bam.config @@ -0,0 +1,3 @@ +process { + ext.args = "--output-fmt bam" +} \ No newline at end of file diff --git a/modules/nf-core/samtools/view/tests/bam_index.config b/modules/nf-core/samtools/view/tests/bam_index.config new file mode 100644 index 00000000..771ae033 --- /dev/null +++ b/modules/nf-core/samtools/view/tests/bam_index.config @@ -0,0 +1,3 @@ +process { + ext.args = "--output-fmt bam --write-index" +} \ No newline at end of file diff --git a/modules/nf-core/samtools/view/tests/main.nf.test b/modules/nf-core/samtools/view/tests/main.nf.test new file mode 100644 index 00000000..37b81a91 --- /dev/null +++ b/modules/nf-core/samtools/view/tests/main.nf.test @@ -0,0 +1,214 @@ +nextflow_process { + + name "Test Process SAMTOOLS_VIEW" + script "../main.nf" + process "SAMTOOLS_VIEW" + + tag "modules" + tag "modules_nfcore" + tag "samtools" + tag "samtools/view" + + test("bam") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.bam', checkIfExists: true), + [] + ]) + input[1] = [[],[]] + input[2] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(file(process.out.bam[0][1]).name).match("bam_bam") }, + { assert snapshot(process.out.bai).match("bam_bai") }, + { assert snapshot(process.out.crai).match("bam_crai") }, + { assert snapshot(process.out.cram).match("bam_cram") }, + { assert snapshot(process.out.csi).match("bam_csi") }, + { assert snapshot(process.out.sam).match("bam_sam") }, + { assert snapshot(process.out.versions).match("bam_versions") } + ) + } + } + + test("cram") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.sorted.cram', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.sorted.cram.crai', checkIfExists: true) + ]) + input[1] = Channel.of([ + [ id:'genome' ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + ]) + input[2] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(file(process.out.cram[0][1]).name).match("cram_cram") }, + { assert snapshot(process.out.bai).match("cram_bai") }, + { assert snapshot(process.out.bam).match("cram_bam") }, + { assert snapshot(process.out.crai).match("cram_crai") }, + { assert snapshot(process.out.csi).match("cram_csi") }, + { assert snapshot(process.out.sam).match("cram_sam") }, + { assert snapshot(process.out.versions).match("cram_versions") } + ) + } + } + + test("cram_to_bam") { + + config "./bam.config" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.sorted.cram', checkIfExists: true), + [] + ]) + input[1] = Channel.of([ + [ id:'genome' ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + ]) + input[2] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(file(process.out.bam[0][1]).name).match("cram_to_bam_bam") }, + { assert snapshot(process.out.bai).match("cram_to_bam_bai") }, + { assert snapshot(process.out.crai).match("cram_to_bam_crai") }, + { assert snapshot(process.out.cram).match("cram_to_bam_cram") }, + { assert snapshot(process.out.csi).match("cram_to_bam_csi") }, + { assert snapshot(process.out.sam).match("cram_to_bam_sam") }, + { assert snapshot(process.out.versions).match("cram_to_bam_versions") } + ) + } + } + + test("cram_to_bam_index") { + + config "./bam_index.config" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.sorted.cram', checkIfExists: true), + [] + ]) + input[1] = Channel.of([ + [ id:'genome' ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + ]) + input[2] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(file(process.out.bam[0][1]).name).match("cram_to_bam_index_bam") }, + { assert snapshot(file(process.out.csi[0][1]).name).match("cram_to_bam_index_csi") }, + { assert snapshot(process.out.bai).match("cram_to_bam_index_bai") }, + { assert snapshot(process.out.crai).match("cram_to_bam_index_crai") }, + { assert snapshot(process.out.cram).match("cram_to_bam_index_cram") }, + { assert snapshot(process.out.sam).match("cram_to_bam_index_sam") }, + { assert snapshot(process.out.versions).match("cram_to_bam_index_versions") } + ) + } + } + + test("cram_to_bam_index_qname") { + + config "./bam_index.config" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.sorted.cram', checkIfExists: true), + [] + ]) + input[1] = Channel.of([ + [ id:'genome' ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + ]) + input[2] = Channel.of("testN:2817", "testN:2814").collectFile(name: "readnames.list", newLine: true) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(file(process.out.bam[0][1]).name).match("cram_to_bam_index_qname_bam") }, + { assert snapshot(file(process.out.csi[0][1]).name).match("cram_to_bam_index_qname_csi") }, + { assert snapshot(process.out.bai).match("cram_to_bam_index_qname_bai") }, + { assert snapshot(process.out.crai).match("cram_to_bam_index_qname_crai") }, + { assert snapshot(process.out.cram).match("cram_to_bam_index_qname_cram") }, + { assert snapshot(process.out.sam).match("cram_to_bam_index_qname_sam") }, + { assert snapshot(file(process.out.unselected[0][1]).name).match("cram_to_bam_index_qname_unselected") }, + { assert snapshot(file(process.out.unselected_index[0][1]).name).match("cram_to_bam_index_qname_unselected_csi") }, + { assert snapshot(process.out.versions).match("cram_to_bam_index_qname_versions") } + ) + } + } + + test("bam_stub") { + + options "-stub" + config "./bam_index.config" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.bam', checkIfExists: true), + [] + ]) + input[1] = [[],[]] + input[2] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(file(process.out.bam[0][1]).name).match("bam_stub_bam") }, + { assert snapshot(file(process.out.csi[0][1]).name).match("bam_stub_csi") }, + { assert snapshot(process.out.bai).match("bam_stub_bai") }, + { assert snapshot(process.out.crai).match("bam_stub_crai") }, + { assert snapshot(process.out.cram).match("bam_stub_cram") }, + { assert snapshot(process.out.sam).match("bam_stub_sam") }, + { assert snapshot(process.out.versions).match("bam_stub_versions") } + ) + } + } +} diff --git a/modules/nf-core/samtools/view/tests/main.nf.test.snap b/modules/nf-core/samtools/view/tests/main.nf.test.snap new file mode 100644 index 00000000..6bcce9fe --- /dev/null +++ b/modules/nf-core/samtools/view/tests/main.nf.test.snap @@ -0,0 +1,508 @@ +{ + "bam_bam": { + "content": [ + "test.bam" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:51.256068" + }, + "cram_to_bam_index_csi": { + "content": [ + "test.bam.csi" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:12.958617" + }, + "bam_stub_bam": { + "content": [ + "test.bam" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:32.065301" + }, + "bam_bai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:51.258578" + }, + "bam_stub_bai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:32.071284" + }, + "bam_stub_versions": { + "content": [ + [ + "versions.yml:md5,6cd41a9a3b4a95271ec011ea990a2838" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-05-28T15:43:20.390692583" + }, + "cram_to_bam_index_cram": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:12.972288" + }, + "cram_to_bam_sam": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:04.999247" + }, + "cram_to_bam_index_sam": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:12.976457" + }, + "cram_crai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:56.497581" + }, + "cram_csi": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:56.50038" + }, + "cram_to_bam_cram": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:04.992239" + }, + "cram_to_bam_index_qname_csi": { + "content": [ + "test.bam.csi" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:23.325496" + }, + "bam_stub_sam": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:32.079529" + }, + "cram_cram": { + "content": [ + "test.cram" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:56.490286" + }, + "bam_csi": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:51.262882" + }, + "cram_to_bam_crai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:04.989247" + }, + "cram_to_bam_index_crai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:12.967681" + }, + "cram_to_bam_index_qname_versions": { + "content": [ + [ + "versions.yml:md5,6cd41a9a3b4a95271ec011ea990a2838" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-05-28T15:43:15.007493874" + }, + "cram_to_bam_bam": { + "content": [ + "test.bam" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:04.982361" + }, + "cram_to_bam_index_bam": { + "content": [ + "test.bam" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:12.95456" + }, + "cram_to_bam_index_versions": { + "content": [ + [ + "versions.yml:md5,6cd41a9a3b4a95271ec011ea990a2838" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-05-28T15:43:09.472376824" + }, + "cram_to_bam_bai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:04.98601" + }, + "cram_to_bam_versions": { + "content": [ + [ + "versions.yml:md5,6cd41a9a3b4a95271ec011ea990a2838" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-05-28T15:43:04.080050906" + }, + "cram_bam": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:56.495512" + }, + "bam_stub_cram": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:32.076908" + }, + "cram_to_bam_index_qname_bai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:23.328458" + }, + "cram_to_bam_index_qname_crai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:23.330789" + }, + "cram_bai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:56.493129" + }, + "bam_stub_crai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:32.074313" + }, + "cram_to_bam_index_qname_bam": { + "content": [ + "test.bam" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:23.322874" + }, + "cram_to_bam_index_qname_unselected": { + "content": [ + "test.unselected.bam" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:23.322874" + }, + "cram_to_bam_index_qname_unselected_csi": { + "content": [ + "test.unselected.bam.csi" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:23.328458" + }, + "bam_versions": { + "content": [ + [ + "versions.yml:md5,6cd41a9a3b4a95271ec011ea990a2838" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-05-28T15:42:52.978954857" + }, + "cram_to_bam_index_qname_cram": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:23.333248" + }, + "bam_crai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:51.259774" + }, + "bam_cram": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:51.261287" + }, + "cram_to_bam_csi": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:04.995454" + }, + "cram_sam": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:56.502625" + }, + "cram_versions": { + "content": [ + [ + "versions.yml:md5,6cd41a9a3b4a95271ec011ea990a2838" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-05-28T15:42:58.400776109" + }, + "bam_sam": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:51.264651" + }, + "cram_to_bam_index_bai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:12.962863" + }, + "cram_to_bam_index_qname_sam": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:23.337634" + }, + "bam_stub_csi": { + "content": [ + "test.bam.csi" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:32.068596" + } +} \ No newline at end of file diff --git a/modules/nf-core/samtools/view/tests/tags.yml b/modules/nf-core/samtools/view/tests/tags.yml new file mode 100644 index 00000000..4fdf1dd1 --- /dev/null +++ b/modules/nf-core/samtools/view/tests/tags.yml @@ -0,0 +1,2 @@ +samtools/view: + - "modules/nf-core/samtools/view/**" diff --git a/modules/nf-core/taxpasta/merge/environment.yml b/modules/nf-core/taxpasta/merge/environment.yml index ca1a10b7..eb48f436 100644 --- a/modules/nf-core/taxpasta/merge/environment.yml +++ b/modules/nf-core/taxpasta/merge/environment.yml @@ -1,7 +1,5 @@ -name: taxpasta_merge channels: - conda-forge - bioconda - - defaults dependencies: - bioconda::taxpasta=0.7.0 diff --git a/modules/nf-core/taxpasta/standardise/environment.yml b/modules/nf-core/taxpasta/standardise/environment.yml index a48f08e0..eb48f436 100644 --- a/modules/nf-core/taxpasta/standardise/environment.yml +++ b/modules/nf-core/taxpasta/standardise/environment.yml @@ -1,7 +1,5 @@ -name: taxpasta_standardise channels: - conda-forge - bioconda - - defaults dependencies: - bioconda::taxpasta=0.7.0 diff --git a/modules/nf-core/untar/environment.yml b/modules/nf-core/untar/environment.yml new file mode 100644 index 00000000..c7794856 --- /dev/null +++ b/modules/nf-core/untar/environment.yml @@ -0,0 +1,7 @@ +channels: + - conda-forge + - bioconda +dependencies: + - conda-forge::grep=3.11 + - conda-forge::sed=4.8 + - conda-forge::tar=1.34 diff --git a/modules/nf-core/untar/main.nf b/modules/nf-core/untar/main.nf index 61461c39..9bd8f554 100644 --- a/modules/nf-core/untar/main.nf +++ b/modules/nf-core/untar/main.nf @@ -2,10 +2,10 @@ process UNTAR { tag "$archive" label 'process_single' - conda "conda-forge::sed=4.7 conda-forge::grep=3.11 conda-forge::tar=1.34" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/ubuntu:20.04' : - 'nf-core/ubuntu:20.04' }" + 'https://depot.galaxyproject.org/singularity/ubuntu:22.04' : + 'nf-core/ubuntu:22.04' }" input: tuple val(meta), path(archive) @@ -52,8 +52,29 @@ process UNTAR { stub: prefix = task.ext.prefix ?: ( meta.id ? "${meta.id}" : archive.toString().replaceFirst(/\.[^\.]+(.gz)?$/, "")) """ - mkdir $prefix - touch ${prefix}/file.txt + mkdir ${prefix} + ## Dry-run untaring the archive to get the files and place all in prefix + if [[ \$(tar -taf ${archive} | grep -o -P "^.*?\\/" | uniq | wc -l) -eq 1 ]]; then + for i in `tar -tf ${archive}`; + do + if [[ \$(echo "\${i}" | grep -E "/\$") == "" ]]; + then + touch \${i} + else + mkdir -p \${i} + fi + done + else + for i in `tar -tf ${archive}`; + do + if [[ \$(echo "\${i}" | grep -E "/\$") == "" ]]; + then + touch ${prefix}/\${i} + else + mkdir -p ${prefix}/\${i} + fi + done + fi cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/nf-core/untar/meta.yml b/modules/nf-core/untar/meta.yml index db241a6e..a9a2110f 100644 --- a/modules/nf-core/untar/meta.yml +++ b/modules/nf-core/untar/meta.yml @@ -39,3 +39,8 @@ authors: - "@drpatelh" - "@matthdsm" - "@jfy133" +maintainers: + - "@joseespinosa" + - "@drpatelh" + - "@matthdsm" + - "@jfy133" diff --git a/modules/nf-core/untar/tests/main.nf.test b/modules/nf-core/untar/tests/main.nf.test new file mode 100644 index 00000000..c957517a --- /dev/null +++ b/modules/nf-core/untar/tests/main.nf.test @@ -0,0 +1,85 @@ +nextflow_process { + + name "Test Process UNTAR" + script "../main.nf" + process "UNTAR" + tag "modules" + tag "modules_nfcore" + tag "untar" + + test("test_untar") { + + when { + process { + """ + input[0] = [ [], file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/db/kraken2.tar.gz', checkIfExists: true) ] + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() }, + ) + } + } + + test("test_untar_onlyfiles") { + + when { + process { + """ + input[0] = [ [], file(params.modules_testdata_base_path + 'generic/tar/hello.tar.gz', checkIfExists: true) ] + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() }, + ) + } + } + + test("test_untar - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ [], file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/db/kraken2.tar.gz', checkIfExists: true) ] + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() }, + ) + } + } + + test("test_untar_onlyfiles - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ [], file(params.modules_testdata_base_path + 'generic/tar/hello.tar.gz', checkIfExists: true) ] + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() }, + ) + } + } +} diff --git a/modules/nf-core/untar/tests/main.nf.test.snap b/modules/nf-core/untar/tests/main.nf.test.snap new file mode 100644 index 00000000..ceb91b79 --- /dev/null +++ b/modules/nf-core/untar/tests/main.nf.test.snap @@ -0,0 +1,158 @@ +{ + "test_untar_onlyfiles": { + "content": [ + { + "0": [ + [ + [ + + ], + [ + "hello.txt:md5,e59ff97941044f85df5297e1c302d260" + ] + ] + ], + "1": [ + "versions.yml:md5,6063247258c56fd271d076bb04dd7536" + ], + "untar": [ + [ + [ + + ], + [ + "hello.txt:md5,e59ff97941044f85df5297e1c302d260" + ] + ] + ], + "versions": [ + "versions.yml:md5,6063247258c56fd271d076bb04dd7536" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-10T12:04:28.231047" + }, + "test_untar_onlyfiles - stub": { + "content": [ + { + "0": [ + [ + [ + + ], + [ + "hello.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "1": [ + "versions.yml:md5,6063247258c56fd271d076bb04dd7536" + ], + "untar": [ + [ + [ + + ], + [ + "hello.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "versions": [ + "versions.yml:md5,6063247258c56fd271d076bb04dd7536" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-10T12:04:45.773103" + }, + "test_untar - stub": { + "content": [ + { + "0": [ + [ + [ + + ], + [ + "hash.k2d:md5,d41d8cd98f00b204e9800998ecf8427e", + "opts.k2d:md5,d41d8cd98f00b204e9800998ecf8427e", + "taxo.k2d:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "1": [ + "versions.yml:md5,6063247258c56fd271d076bb04dd7536" + ], + "untar": [ + [ + [ + + ], + [ + "hash.k2d:md5,d41d8cd98f00b204e9800998ecf8427e", + "opts.k2d:md5,d41d8cd98f00b204e9800998ecf8427e", + "taxo.k2d:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "versions": [ + "versions.yml:md5,6063247258c56fd271d076bb04dd7536" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-10T12:04:36.777441" + }, + "test_untar": { + "content": [ + { + "0": [ + [ + [ + + ], + [ + "hash.k2d:md5,8b8598468f54a7087c203ad0190555d9", + "opts.k2d:md5,a033d00cf6759407010b21700938f543", + "taxo.k2d:md5,094d5891cdccf2f1468088855c214b2c" + ] + ] + ], + "1": [ + "versions.yml:md5,6063247258c56fd271d076bb04dd7536" + ], + "untar": [ + [ + [ + + ], + [ + "hash.k2d:md5,8b8598468f54a7087c203ad0190555d9", + "opts.k2d:md5,a033d00cf6759407010b21700938f543", + "taxo.k2d:md5,094d5891cdccf2f1468088855c214b2c" + ] + ] + ], + "versions": [ + "versions.yml:md5,6063247258c56fd271d076bb04dd7536" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-10T12:04:19.377674" + } +} \ No newline at end of file diff --git a/modules/nf-core/untar/tests/tags.yml b/modules/nf-core/untar/tests/tags.yml new file mode 100644 index 00000000..feb6f15c --- /dev/null +++ b/modules/nf-core/untar/tests/tags.yml @@ -0,0 +1,2 @@ +untar: + - modules/nf-core/untar/** diff --git a/nextflow.config b/nextflow.config index 638089c8..50295bc2 100644 --- a/nextflow.config +++ b/nextflow.config @@ -79,14 +79,21 @@ params { shortread_qc_dedup = false perform_longread_qc = false + longread_adapterremoval_tool = 'porechop_abi' longread_qc_skipadaptertrim = false longread_qc_skipqualityfilter = false + longread_filter_tool = 'nanoq' longread_qc_qualityfilter_minlength = 1000 longread_qc_qualityfilter_keeppercent = 90 + longread_qc_qualityfilter_minquality = 7 longread_qc_qualityfilter_targetbases = 500000000 save_preprocessed_reads = false + // Redundancy estimation + perform_shortread_redundancyestimation = false + shortread_redundancyestimation_mode = 'kmer' + // Complexity filtering perform_shortread_complexityfilter = false shortread_complexityfilter_tool = 'bbduk' @@ -307,20 +314,19 @@ profiles { executor.cpus = 4 executor.memory = 8.GB } - test { includeConfig 'conf/test.config' } - test_full { includeConfig 'conf/test_full.config' } - test_noprofiling { includeConfig 'conf/test_noprofiling.config' } - test_nopreprocessing { includeConfig 'conf/test_nopreprocessing.config' } - test_nothing { includeConfig 'conf/test_nothing.config' } - test_motus { includeConfig 'conf/test_motus.config' } - test_krakenuniq { includeConfig 'conf/test_krakenuniq.config' } - test_malt { includeConfig 'conf/test_malt.config' } - test_falco { includeConfig 'conf/test_falco.config' } - test_fastp { includeConfig 'conf/test_fastp.config' } - test_adapterremoval { includeConfig 'conf/test_adapterremoval.config' } - test_bbduk { includeConfig 'conf/test_bbduk.config' } - test_prinseqplusplus { includeConfig 'conf/test_prinseqplusplus.config' } - + test { includeConfig 'conf/test.config' } + test_full { includeConfig 'conf/test_full.config' } + test_noprofiling { includeConfig 'conf/test_noprofiling.config' } + test_nopreprocessing { includeConfig 'conf/test_nopreprocessing.config' } + test_nothing { includeConfig 'conf/test_nothing.config' } + test_motus { includeConfig 'conf/test_motus.config' } + test_krakenuniq { includeConfig 'conf/test_krakenuniq.config' } + test_malt { includeConfig 'conf/test_malt.config' } + test_falco { includeConfig 'conf/test_falco.config' } + test_fastp { includeConfig 'conf/test_fastp.config' } + test_alternativepreprocessing { includeConfig 'conf/test_alternativepreprocessing.config' } + test_bbduk { includeConfig 'conf/test_bbduk.config' } + test_prinseqplusplus { includeConfig 'conf/test_prinseqplusplus.config' } } // Set default registry for Apptainer, Docker, Podman and Singularity independent of -profile @@ -385,7 +391,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.8' + version = '1.2' doi = '10.1101/2023.10.20.563221' } diff --git a/nextflow_schema.json b/nextflow_schema.json index deef481a..3ada1a56 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -84,7 +84,7 @@ "type": "boolean", "fa_icon": "fas fa-save", "description": "Save reads from samples that went through the adapter clipping, pair-merging, and length filtering steps for both short and long reads", - "help_text": "This saves the FASTQ output from the following tools:\n\n- fastp\n- AdapterRemoval\n- Porechop\n- Filtlong\n\nThese reads will be a mixture of: adapter clipped, quality trimmed, pair-merged, and length filtered, depending on the parameters you set." + "help_text": "This saves the FASTQ output from the following tools:\n\n- fastp\n- AdapterRemoval\n- Porechop\n- Filtlong\n- Nanoq\n\nThese reads will be a mixture of: adapter clipped, quality trimmed, pair-merged, and length filtered, depending on the parameters you set." }, "save_analysis_ready_fastqs": { "type": "boolean", @@ -238,24 +238,40 @@ "description": "Turns on long read quality control steps (adapter clipping, length filtering etc.)", "help_text": "Turns on long read quality control steps (adapter clipping, length and/or quality filtering.)\n\nRemoving adapters (if present) is recommend to reduce false-postive hits that may occur from 'dirty' or 'contaminated' reference genomes in a profiling database that contain accidentially incorporated adapter sequences.\n\nLength filtering, and quality filtering can speed up alignment by reducing the number of unspecific reads that need to be aligned." }, + "longread_adapterremoval_tool": { + "type": "string", + "default": "porechop_abi", + "enum": ["porechop", "porechop_abi"], + "fa_icon": "fas fa-hammer", + "description": "Specify which tool to use for adapter trimming.", + "help_text": "The performance of Porechop and Porechop_ABI is same in terms of removing adapter reads. However Porechop is no longer updated, Porechop_ABI receives regular updates." + }, "longread_qc_skipadaptertrim": { "type": "boolean", "description": "Skip long-read trimming", "fa_icon": "fas fa-forward", "help_text": "Skip removal of adapters by Porechop. This can be useful in some cases to speed up run time - particularly when you are running data downloading from public databases such as the ENA/SRA that should already have adapters removed. We recommend that you check your FastQC results this is indeed the case." }, + "longread_filter_tool": { + "type": "string", + "default": "nanoq", + "enum": ["filtlong", "nanoq"], + "fa_icon": "fas fa-hammer", + "description": "Specify which tool to use for long reads filtering", + "help_text": "Nanoq is a filtering tool only for Nanopore reads. Nanoq is faster and more memory-efficient than Filtlong. Nanoq also provides a summary of input read statistics; see [benchmarking](https://github.com/esteinig/nanoq?tab=readme-ov-file#benchmarks). \n\nFiltlong is a good option if you want to keep a certain percentage of reads after filtering, and you can also use it for non-Nanopore long reads." + }, "longread_qc_skipqualityfilter": { "type": "boolean", "description": "Skip long-read length and quality filtering", "fa_icon": "fas fa-forward", - "help_text": "Skip removal of quality filtering with Filtlong. This will skip length, percent reads, and target bases filtering (see other `--longread_qc_qualityfilter_*` parameters)." + "help_text": "Skip removal of quality filtering with Filtlong or Nanoq. This will skip length, percent reads, and target bases filtering (see other `--longread_qc_qualityfilter_*` parameters)." }, "longread_qc_qualityfilter_minlength": { "type": "integer", "default": 1000, "description": "Specify the minimum length of reads to be retained", "fa_icon": "fas fa-ruler-horizontal", - "help_text": "Specify the minimum of length of reads to be kept for downstream analysis.\n\n> Modifies tool parameter(s):\n> - Filtlong: `--min_length`" + "help_text": "Specify the minimum of length of reads to be kept for downstream analysis.\n\n> Modifies tool parameter(s):\n> - Filtlong: `--min_length` or - Nanoq: `--min-len`" }, "longread_qc_qualityfilter_keeppercent": { "type": "integer", @@ -267,13 +283,43 @@ "longread_qc_qualityfilter_targetbases": { "type": "integer", "default": 500000000, - "description": "Specify the number of high-quality bases in the library to be retained", + "description": "Filtlong only: specify the number of high-quality bases in the library to be retained", "fa_icon": "fas fa-bullseye", "help_text": "Removes the worst reads until only the specified value of bases remain, useful for very large read sets. If the input read set is less than the specified value, this setting will have no effect. _Modified from [Filtlong documentation](https://github.com/rrwick/Filtlong)_\n\n> Modifies tool parameter(s):\n> - Filtlong: `--keep_percent`" + }, + "longread_qc_qualityfilter_minquality": { + "type": "integer", + "default": 7, + "description": "Nanoq only: specify the minimum average read quality filter (Q)", + "fa_icon": "fas fa-bullseye", + "help_text": "Remove the reads with quality score lower than 7. \n\n> Modifies tool parameter(s):\n> - Nanoq: `--min-qual`" } }, "fa_icon": "fas fa-expand-alt" }, + "redundancy_estimation": { + "title": "Redundancy Estimation", + "type": "object", + "description": "Estimate metagenome sequencing complexity coverage", + "default": "", + "properties": { + "perform_shortread_redundancyestimation": { + "type": "boolean", + "description": "Turn on short-read metagenome sequencing redundancy estimation with nonpareil. Warning: only use for shallow short-read sequencing datasets.", + "fa_icon": "fas fa-toggle-on", + "help_text": "Turns on [nonpareil](https://nonpareil.readthedocs.io/en/latest/), a tool for estimating metagenome 'coverage', i.e, whether all genomes within the metagenome have had at least one read sequenced.\n\nIt estimates this by checking the read redundancy between a subsample of reads versus other reads in the library.\n\nThe more redundancy that exists, the larger the assumption that all possible reads in the library have been sequenced and all 'redundant' reads are simply sequencing of PCR duplicates.\n\nThe lower the redundancy, the more sequencing should be done until the entire metagenome has been captured. The output can be used to guide the amount of further sequencing is required.\n\nNote this is not the same as _genomic_ coverage, which is the number of times a base-pair is covered by unique reads on a reference genome.\n\nBefore using this tool please note the following caveats:\n\n- It is not recommended to run this on deep sequencing data, or very large datasets\n - Your shortest reads _after_ processing should not go below 24bp (see warning below)\n- It is not recommended to keep unmerged (`--shortread_qc_includeunmerged`) reads when using the calculation.\n:::warning\nOn default settings, with 'kmer mode', you must make sure that your shortest processed reads do not go below 24 bp (the default kmer size).\n\nIf you have errors regarding kmer size, you will need to specify in a custom config in a process block\n\n```\n withName: NONPAREIL {\n ext.args = { \"-k \" }\n }\n```\n\nWhere `` should be at least the shortest read in your library\n:::" + }, + "shortread_redundancyestimation_mode": { + "type": "string", + "default": "kmer", + "description": "Specify mode for identifying redundant reads", + "enum": ["kmer", "alignment"], + "fa_icon": "fas fa-align-left", + "help_text": "Specify which read-comparison mode to use to check for redundancy.\n\nk-mer is faster but less precise but is recommended for FASTQ files. Alignment is more precise but is slower, it is recommended for FASTA files.\n\n> Modifies tool parameter(s):\n> - Nonpareil: `-T`" + } + }, + "fa_icon": "fas fa-chart-line" + }, "preprocessing_host_removal_options": { "title": "Preprocessing host removal options", "type": "object", @@ -347,7 +393,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> ⚠️ 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> \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" } }, "fa_icon": "fas fa-clipboard-check" @@ -543,7 +589,7 @@ "type": "boolean", "description": "Turn on saving of ganon per-read taxonomic assignment file(s).", "fa_icon": "fas fa-save", - "help_text": "Saves `.lca`, `.all`, and `.unc` text files that contains a list of each read that had a taxonomic assignment, with information on specific taxonomic assignment that the read received.\n\n> Modifies tool parameter(s):\n- ganon classify: `--output-all --output-lca --output-unclassified`" + "help_text": "Saves `.one`, `.all`, and `.unc` text files that contains a list of each read that had a taxonomic assignment, with information on specific taxonomic assignment that the read received.\n\n> Modifies tool parameter(s):\n- ganon classify: `--output-all --output-unclassified`" }, "ganon_report_type": { "type": "string", @@ -557,7 +603,8 @@ "type": "string", "description": "Specify the taxonomic report the ganon report file should display.", "help_text": "Specify the taxonomic rank level to report each taxonomic hit as. `all` will specify all ranks, however you can customise this from `superkingdom` through to `species` to as specific as `assembly`. ganon has a default preset, however you can customise the specific ranks in a comma separated list, e.g. `--ganon_report_rank [phylum,genus,species]`.\n\nSee the [ganon documentation](https://pirovc.github.io/ganon/outputfiles/#ganon-report) for more information of each option.\n\n> Modifies tool parameter(s):\n- ganon report: `--ranks`", - "fa_icon": "fas fa-sort-amount-down-alt" + "fa_icon": "fas fa-sort-amount-down-alt", + "default": "default" }, "ganon_report_toppercentile": { "type": "integer", @@ -910,6 +957,9 @@ { "$ref": "#/definitions/preprocessing_long_read_qc_options" }, + { + "$ref": "#/definitions/redundancy_estimation" + }, { "$ref": "#/definitions/preprocessing_host_removal_options" }, diff --git a/subworkflows/local/longread_adapterremoval.nf b/subworkflows/local/longread_adapterremoval.nf new file mode 100644 index 00000000..f8569794 --- /dev/null +++ b/subworkflows/local/longread_adapterremoval.nf @@ -0,0 +1,36 @@ +// +// Process long raw reads with porechop or porechop_abi +// + +include { PORECHOP_PORECHOP } from '../../modules/nf-core/porechop/porechop/main' +include { PORECHOP_ABI } from '../../modules/nf-core/porechop/abi/main' + +workflow LONGREAD_ADAPTERREMOVAL { + take: + reads + + main: + ch_versions = Channel.empty() + ch_multiqc_files = Channel.empty() + + if ( params.longread_adapterremoval_tool == 'porechop_abi' ) { + PORECHOP_ABI ( reads ) + ch_processed_reads = PORECHOP_ABI.out.reads + .map { meta, reads -> [meta + [ single_end: true ], reads ] } + ch_versions = ch_versions.mix( PORECHOP_ABI.out.versions.first() ) + ch_multiqc_files = ch_multiqc_files.mix( PORECHOP_ABI.out.log ) + } else if ( params.longread_adapterremoval_tool == 'porechop' ) { + PORECHOP_PORECHOP ( reads ) + ch_processed_reads = PORECHOP_PORECHOP.out.reads + .map { meta, reads -> [ meta + [ single_end: true ], reads ] } + ch_versions = ch_versions.mix( PORECHOP_PORECHOP.out.versions.first() ) + ch_multiqc_files = ch_multiqc_files.mix( PORECHOP_PORECHOP.out.log ) + } else { + ch_processed_reads = reads + } + + emit: + reads = ch_processed_reads // channel: [ val(meta), [ reads ] ] + versions = ch_versions // channel: [ versions.yml ] + mqc = ch_multiqc_files +} diff --git a/subworkflows/local/longread_filtering.nf b/subworkflows/local/longread_filtering.nf new file mode 100644 index 00000000..f52d0d64 --- /dev/null +++ b/subworkflows/local/longread_filtering.nf @@ -0,0 +1,33 @@ +// +// Perform filtering +// + +include { FILTLONG } from '../../modules/nf-core/filtlong/main' +include { NANOQ } from '../../modules/nf-core/nanoq/main' + +workflow LONGREAD_FILTERING { + take: + reads // [ [ meta ], [ reads ] ] + + main: + ch_versions = Channel.empty() + ch_multiqc_files = Channel.empty() + + // fastp complexity filtering is activated via modules.conf in shortread_preprocessing + if ( params.longread_filter_tool == 'filtlong' ) { + ch_filtered_reads = FILTLONG ( reads.map { meta, reads -> [ meta, [], reads ] } ).reads + ch_versions = ch_versions.mix( FILTLONG.out.versions.first() ) + ch_multiqc_files = ch_multiqc_files.mix( FILTLONG.out.log ) + } else if ( params.longread_filter_tool == 'nanoq' ) { + ch_filtered_reads = NANOQ ( reads , 'fastq.gz' ).reads + ch_versions = ch_versions.mix( NANOQ.out.versions.first() ) + ch_multiqc_files = ch_multiqc_files.mix( NANOQ.out.stats ) + } else { + ch_filtered_reads = reads + } + + emit: + reads = ch_filtered_reads // channel: [ val(meta), [ reads ] ] + versions = ch_versions // channel: [ versions.yml ] + mqc = ch_multiqc_files +} diff --git a/subworkflows/local/longread_hostremoval.nf b/subworkflows/local/longread_hostremoval.nf index bc146d6f..7f988366 100644 --- a/subworkflows/local/longread_hostremoval.nf +++ b/subworkflows/local/longread_hostremoval.nf @@ -20,13 +20,13 @@ workflow LONGREAD_HOSTREMOVAL { ch_multiqc_files = Channel.empty() if ( !params.longread_hostremoval_index ) { - ch_minimap2_index = MINIMAP2_INDEX ( [ [], reference ] ).index.map { it[1] } + ch_minimap2_index = MINIMAP2_INDEX ( [ [], reference ] ).index ch_versions = ch_versions.mix( MINIMAP2_INDEX.out.versions ) } else { ch_minimap2_index = index } - MINIMAP2_ALIGN ( reads, ch_minimap2_index, true, false, false ) + MINIMAP2_ALIGN ( reads, ch_minimap2_index, true, 'bai', false, false ) ch_versions = ch_versions.mix( MINIMAP2_ALIGN.out.versions.first() ) ch_minimap2_mapped = MINIMAP2_ALIGN.out.bam .map { diff --git a/subworkflows/local/longread_preprocessing.nf b/subworkflows/local/longread_preprocessing.nf index 72261013..8b1590dc 100644 --- a/subworkflows/local/longread_preprocessing.nf +++ b/subworkflows/local/longread_preprocessing.nf @@ -1,12 +1,12 @@ // -// Process long raw reads with porechop +// Perform read trimming and filtering // -include { FASTQC as FASTQC_PROCESSED } from '../../modules/nf-core/fastqc/main' -include { FALCO as FALCO_PROCESSED } from '../../modules/nf-core/falco/main' +include { FASTQC as FASTQC_PROCESSED } from '../../modules/nf-core/fastqc/main' +include { FALCO as FALCO_PROCESSED } from '../../modules/nf-core/falco/main' -include { PORECHOP_PORECHOP } from '../../modules/nf-core/porechop/porechop/main' -include { FILTLONG } from '../../modules/nf-core/filtlong/main' +include { LONGREAD_ADAPTERREMOVAL } from './longread_adapterremoval.nf' +include { LONGREAD_FILTERING } from './longread_filtering.nf' workflow LONGREAD_PREPROCESSING { take: @@ -17,41 +17,31 @@ workflow LONGREAD_PREPROCESSING { ch_multiqc_files = Channel.empty() if ( !params.longread_qc_skipadaptertrim && params.longread_qc_skipqualityfilter) { - PORECHOP_PORECHOP ( reads ) - - ch_processed_reads = PORECHOP_PORECHOP.out.reads - .map { meta, reads -> [ meta + [single_end: true], reads ] } - - ch_versions = ch_versions.mix(PORECHOP_PORECHOP.out.versions.first()) - ch_multiqc_files = ch_multiqc_files.mix( PORECHOP_PORECHOP.out.log ) - + ch_processed_reads = LONGREAD_ADAPTERREMOVAL ( reads ).reads + ch_versions = ch_versions.mix(LONGREAD_ADAPTERREMOVAL.out.versions.first()) + ch_multiqc_files = ch_multiqc_files.mix( LONGREAD_ADAPTERREMOVAL.out.mqc ) } else if ( params.longread_qc_skipadaptertrim && !params.longread_qc_skipqualityfilter) { - - ch_processed_reads = FILTLONG ( reads.map { meta, reads -> [meta, [], reads ] } ) - ch_versions = ch_versions.mix(FILTLONG.out.versions.first()) - ch_multiqc_files = ch_multiqc_files.mix( FILTLONG.out.log ) - + ch_processed_reads = LONGREAD_FILTERING ( reads ).reads + ch_versions = ch_versions.mix(LONGREAD_FILTERING.out.versions.first()) + ch_multiqc_files = ch_multiqc_files.mix( LONGREAD_FILTERING.out.mqc ) } else { - PORECHOP_PORECHOP ( reads ) - ch_clipped_reads = PORECHOP_PORECHOP.out.reads + LONGREAD_ADAPTERREMOVAL ( reads ) + ch_clipped_reads = LONGREAD_ADAPTERREMOVAL.out.reads .map { meta, reads -> [ meta + [single_end: true], reads ] } - - ch_processed_reads = FILTLONG ( ch_clipped_reads.map { meta, reads -> [ meta, [], reads ] } ).reads - - ch_versions = ch_versions.mix(PORECHOP_PORECHOP.out.versions.first()) - ch_versions = ch_versions.mix(FILTLONG.out.versions.first()) - ch_multiqc_files = ch_multiqc_files.mix( PORECHOP_PORECHOP.out.log ) - ch_multiqc_files = ch_multiqc_files.mix( FILTLONG.out.log ) + ch_processed_reads = LONGREAD_FILTERING ( ch_clipped_reads ).reads + ch_versions = ch_versions.mix(LONGREAD_ADAPTERREMOVAL.out.versions.first()) + ch_versions = ch_versions.mix(LONGREAD_FILTERING.out.versions.first()) + ch_multiqc_files = ch_multiqc_files.mix( LONGREAD_ADAPTERREMOVAL.out.mqc ) + ch_multiqc_files = ch_multiqc_files.mix( LONGREAD_FILTERING.out.mqc ) } if (params.preprocessing_qc_tool == 'fastqc') { FASTQC_PROCESSED ( ch_processed_reads ) - ch_versions = ch_versions.mix( FASTQC_PROCESSED.out.versions ) + ch_versions = ch_versions.mix( FASTQC_PROCESSED.out.versions ) ch_multiqc_files = ch_multiqc_files.mix( FASTQC_PROCESSED.out.zip ) - } else if (params.preprocessing_qc_tool == 'falco') { FALCO_PROCESSED ( ch_processed_reads ) - ch_versions = ch_versions.mix( FALCO_PROCESSED.out.versions ) + ch_versions = ch_versions.mix( FALCO_PROCESSED.out.versions ) ch_multiqc_files = ch_multiqc_files.mix( FALCO_PROCESSED.out.txt ) } @@ -60,4 +50,3 @@ workflow LONGREAD_PREPROCESSING { versions = ch_versions // channel: [ versions.yml ] mqc = ch_multiqc_files } - diff --git a/subworkflows/local/nonpareil.nf b/subworkflows/local/nonpareil.nf new file mode 100644 index 00000000..6810eb4c --- /dev/null +++ b/subworkflows/local/nonpareil.nf @@ -0,0 +1,57 @@ +include { NONPAREIL_NONPAREIL } from '../../modules/nf-core/nonpareil/nonpareil/main' +include { NONPAREIL_CURVE } from '../../modules/nf-core/nonpareil/curve/main' +include { NONPAREIL_SET } from '../../modules/nf-core/nonpareil/set/main' +include { NONPAREIL_NONPAREILCURVESR } from '../../modules/nf-core/nonpareil/nonpareilcurvesr/main' + +workflow NONPAREIL { + take: + reads // [ [ meta ], [ reads ] ] + + main: + ch_versions = Channel.empty() + ch_multiqc_files = Channel.empty() + + ch_reads_for_nonpareil = reads + .map { + meta, reads -> + def reads_new = meta.single_end ? reads : reads[0] + // taxprofiler only accepts gzipped input files, + // so don't need to account for getBaseName removing all extensions + def format = reads_new[0].getBaseName().split('\\.').last() in ['fasta', 'fna', 'fa', 'fas'] ? 'fasta' : 'fastq' + [meta, reads_new, format] + } + .multiMap { + meta, reads, format -> + reads: [meta, reads] + format: format + } + + // Calculation + NONPAREIL_NONPAREIL( ch_reads_for_nonpareil.reads, ch_reads_for_nonpareil.format, params.shortread_redundancyestimation_mode) + + ch_npos_for_nonparielset = NONPAREIL_NONPAREIL.out.npo + .map {meta, npo -> [[id: 'all'], npo] } + .groupTuple() + + // Plotting + NONPAREIL_CURVE ( NONPAREIL_NONPAREIL.out.npo ) // For static single-curve PNG + NONPAREIL_SET ( ch_npos_for_nonparielset ) // For static multi-curve PNG + NONPAREIL_NONPAREILCURVESR ( ch_npos_for_nonparielset ) // For dynamic multi-curve PNG in MultiQC and raw files + + ch_versions = ch_versions + .mix( + NONPAREIL_NONPAREIL.out.versions.first(), + NONPAREIL_CURVE.out.versions.first(), + NONPAREIL_SET.out.versions.first(), + NONPAREIL_NONPAREILCURVESR.out.versions.first() + ) + ch_multiqc_files = ch_multiqc_files.mix( NONPAREIL_NONPAREILCURVESR.out.json ) + + emit: + npo = NONPAREIL_NONPAREIL.out.npo + curve_pngs = NONPAREIL_CURVE.out.png + set_pngs = NONPAREIL_SET.out.png + nonpareilcurvesr = NONPAREIL_NONPAREILCURVESR.out.tsv + versions = ch_versions + mqc = ch_multiqc_files +} diff --git a/subworkflows/local/profiling.nf b/subworkflows/local/profiling.nf index 09b8ac19..8b38baca 100644 --- a/subworkflows/local/profiling.nf +++ b/subworkflows/local/profiling.nf @@ -60,26 +60,47 @@ workflow PROFILING { COMBINE READS WITH POSSIBLE DATABASES */ - // e.g. output [DUMP: reads_plus_db] [['id':'2612', 'run_accession':'combined', 'instrument_platform':'ILLUMINA', 'single_end':true], /2612.merged.fastq.gz, ['tool':'malt', 'db_name':'mal95', 'db_params':'"-id 90"'], /malt90] + // Separate default 'short;long' (when necessary) databases when short/long specified in database sheet + ch_dbs = databases + .map{ + meta_db, db -> + [ [meta_db.db_type.split(";")].flatten(), meta_db, db] + } + .transpose(by: 0) + .map{ + type, meta_db, db -> + [[type: type], meta_db.subMap(meta_db.keySet() - 'db_type') + [type: type], db] + } + + // Join short and long reads with their corresponding short/long database + // Note that for not-specified `short;long`, it will match with the database. + // E.g. if there is no 'long' reads the above generated 'long' database channel element + // will have nothing to join to and will be discarded + // Final output [DUMP: reads_plus_db] [['id':'2612', 'run_accession':'combined', 'instrument_platform':'ILLUMINA', 'single_end':false, 'is_fasta':false, 'type':'short'], /2612.merged.fastq.gz, ['tool':'malt', 'db_name':'malt95', 'db_params':'"-id 90"', 'type':'short'], /malt95] + ch_input_for_profiling = reads - .map { - meta, reads -> - [meta + [id: "${meta.id}${meta.single_end ? '_se' : '_pe'}"], reads] - } - .combine(databases) - .branch { - centrifuge: it[2]['tool'] == 'centrifuge' - diamond: it[2]['tool'] == 'diamond' - kaiju: it[2]['tool'] == 'kaiju' - kraken2: it[2]['tool'] == 'kraken2' || it[2]['tool'] == 'bracken' // to reuse the kraken module to produce the input data for bracken - krakenuniq: it[2]['tool'] == 'krakenuniq' - malt: it[2]['tool'] == 'malt' - metaphlan: it[2]['tool'] == 'metaphlan' - motus: it[2]['tool'] == 'motus' - kmcp: it[2]['tool'] == 'kmcp' - ganon: it[2]['tool'] == 'ganon' - unknown: true - } + .map{ + meta, reads -> + [[type: meta.type], meta, reads] + } + .combine(ch_dbs, by: 0) + .map{ + db_type, meta, reads, db_meta, db -> + [ meta, reads, db_meta, db ] + } + .branch { meta, reads, db_meta, db -> + centrifuge: db_meta.tool == 'centrifuge' + diamond: db_meta.tool == 'diamond' + kaiju: db_meta.tool == 'kaiju' + kraken2: db_meta.tool == 'kraken2' || db_meta.tool == 'bracken' // to reuse the kraken module to produce the input data for bracken + krakenuniq: db_meta.tool == 'krakenuniq' + malt: db_meta.tool == 'malt' + metaphlan: db_meta.tool == 'metaphlan' + motus: db_meta.tool == 'motus' + kmcp: db_meta.tool == 'kmcp' + ganon: db_meta.tool == 'ganon' + unknown: true + } /* PREPARE PROFILER INPUT CHANNELS & RUN PROFILING @@ -322,12 +343,16 @@ workflow PROFILING { if ( params.run_diamond ) { ch_input_for_diamond = ch_input_for_profiling.diamond + .filter { + meta, reads, meta_db, db -> + if (!meta.single_end) log.warn "[nf-core/taxprofiler] DIAMOND does not accept paired-end files as input. To run DIAMOND on this sample, please merge reads (e.g. with --shortread_qc_mergepairs). Skipping DIAMOND for sample ${meta.id}." + meta.single_end + } .multiMap { it -> reads: [it[0] + it[2], it[1]] - db: it[3] + db: [ it[2], it[3] ] } - // diamond only accepts single output file specification, therefore // this will replace output file! ch_diamond_reads_format = params.diamond_save_reads ? 'sam' : params.diamond_output_format diff --git a/subworkflows/local/shortread_fastp.nf b/subworkflows/local/shortread_fastp.nf index ac421854..0da50f37 100644 --- a/subworkflows/local/shortread_fastp.nf +++ b/subworkflows/local/shortread_fastp.nf @@ -20,9 +20,9 @@ workflow SHORTREAD_FASTP { paired: it[0]['single_end'] == false } - FASTP_SINGLE ( ch_input_for_fastp.single, adapterlist, false, false ) + FASTP_SINGLE ( ch_input_for_fastp.single, adapterlist, false, false, false ) // Last parameter here turns on merging of PE data - FASTP_PAIRED ( ch_input_for_fastp.paired, adapterlist, false, params.shortread_qc_mergepairs ) + FASTP_PAIRED ( ch_input_for_fastp.paired, adapterlist, false, false, params.shortread_qc_mergepairs ) if ( params.shortread_qc_mergepairs ) { ch_fastp_reads_prepped_pe = FASTP_PAIRED.out.reads_merged diff --git a/subworkflows/local/shortread_hostremoval.nf b/subworkflows/local/shortread_hostremoval.nf index 32d64749..355b3c2e 100644 --- a/subworkflows/local/shortread_hostremoval.nf +++ b/subworkflows/local/shortread_hostremoval.nf @@ -25,15 +25,15 @@ workflow SHORTREAD_HOSTREMOVAL { } // Map, generate BAM with all reads and unmapped reads in FASTQ for downstream - BOWTIE2_ALIGN ( reads, ch_bowtie2_index, true, true) + BOWTIE2_ALIGN ( reads, ch_bowtie2_index, [ [], reference ], true, true) ch_versions = ch_versions.mix( BOWTIE2_ALIGN.out.versions.first() ) ch_multiqc_files = ch_multiqc_files.mix( BOWTIE2_ALIGN.out.log ) // Indexing whole BAM for host removal statistics - SAMTOOLS_INDEX ( BOWTIE2_ALIGN.out.aligned ) + SAMTOOLS_INDEX ( BOWTIE2_ALIGN.out.bam ) ch_versions = ch_versions.mix( SAMTOOLS_INDEX.out.versions.first() ) - bam_bai = BOWTIE2_ALIGN.out.aligned + bam_bai = BOWTIE2_ALIGN.out.bam .join(SAMTOOLS_INDEX.out.bai, remainder: true) SAMTOOLS_STATS ( bam_bai, [[],reference] ) diff --git a/subworkflows/local/utils_nfcore_taxprofiler_pipeline/main.nf b/subworkflows/local/utils_nfcore_taxprofiler_pipeline/main.nf index 96ef64f2..9b4f6df5 100644 --- a/subworkflows/local/utils_nfcore_taxprofiler_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_taxprofiler_pipeline/main.nf @@ -85,16 +85,15 @@ workflow PIPELINE_INITIALISATION { .fromSamplesheet("input") .set { ch_samplesheet } - emit: - samplesheet = ch_samplesheet - versions = ch_versions - -// Create channel from databases file provided through params.databases + // + // Create channel from databases file provided through params.databases + // Channel .fromSamplesheet("databases") .set {ch_databases} emit: + samplesheet = ch_samplesheet databases = ch_databases versions = ch_versions } @@ -193,7 +192,7 @@ def genomeExistsError() { // def toolCitationText() { def text_seq_qc = [ - "Sequencing quality control was carried out with:", + "Sequencing quality control with", params.preprocessing_qc_tool == "falco" ? "Falco (de Sena Brandine and Smith 2021)." : "FastQC (Andrews 2010)." ].join(' ').trim() @@ -203,11 +202,17 @@ def toolCitationText() { params.shortread_qc_tool == "fastp" ? "fastp (Chen et al. 2018)." : "", ].join(' ').trim() + + def text_shortread_redundancy = [ + "Short-read reference-free metagenome coverage estimation was performed with Nonpareil (Rodriguez-R et al. 2018)." + ].join(' ').trim() + def text_longread_qc = [ "Long read preprocessing was performed with:", - !params.longread_qc_skipadaptertrim ? "Porechop (Wick et al. 2017)," : "", - !params.longread_qc_skipqualityfilter ? "Filtlong (Wick 2021)," : "", - "." + params.longread_adapterremoval_tool == "porechop_abi" ? "Porechop_ABI (Bonenfant et al. 2023)," : "", + params.longread_adapterremoval_tool == "porechop" ? "Porechop (Wick et al. 2017)," : "", + params.longread_filter_tool == "filtlong" ? "Filtlong (Wick 2021)." : "", + params.longread_filter_tool == "nanoq" ? "Nanoq (Steinig and Coin 2022)." : "", ].join(' ').trim() def text_shortreadcomplexity = [ @@ -253,14 +258,16 @@ def toolCitationText() { def citation_text = [ "Tools used in the workflow included:", text_seq_qc, - params.perform_shortread_qc ? text_shortread_qc : "", - params.perform_longread_qc ? text_longread_qc : "", - params.perform_shortread_complexityfilter ? text_shortreadcomplexity : "", - params.perform_shortread_hostremoval ? text_shortreadhostremoval : "", - params.perform_longread_hostremoval ? text_longreadhostremoval : "", - text_classification, - params.run_krona ? text_visualisation : "", - params.run_profile_standardisation ? text_postprocessing : "", + params.perform_shortread_qc ? text_shortread_qc : "", + params.perform_shortread_redundancyestimation ? text_shortread_redundancy : "", + params.perform_longread_qc ? text_longread_qc : "", + params.perform_shortread_complexityfilter ? text_shortreadcomplexity : "", + params.perform_shortread_hostremoval ? text_shortreadhostremoval : "", + params.perform_longread_hostremoval ? text_longreadhostremoval : "", + [params.run_bracken, params.run_kraken2, params.run_krakenuniq, params.run_metaphlan, params.run_malt, params.run_diamond, params.run_centrifuge, params.run_kaiju, params.run_motus, params.run_ganon, params.run_kmcp].any() ? + text_classification : "", + params.run_krona ? text_visualisation : "", + params.run_profile_standardisation ? text_postprocessing : "", "Pipeline results statistics were summarised with MultiQC (Ewels et al. 2016)." ].join(' ').trim().replaceAll("[,|.] +\\.", ".") @@ -278,9 +285,15 @@ def toolBibliographyText() { params.shortread_qc_tool == "adapterremoval" ? "
  • Schubert, M., Lindgreen, S., & Orlando, L. (2016). AdapterRemoval v2: rapid adapter trimming, identification, and read merging. BMC Research Notes, 9, 88. 10.1186/s13104-016-1900-2
  • " : "", ].join(' ').trim() + def text_shortread_redundancy = [ + "
  • Rodriguez-R, L. M., Gunturu, S., Tiedje, J. M., Cole, J. R., & Konstantinidis, K. T. (2018). Nonpareil 3: Fast Estimation of Metagenomic Coverage and Sequence Diversity. mSystems, 3(3). 10.1128/mSystems.00039-18
  • ", + ].join(' ').trim() + def text_longread_qc = [ - !params.longread_qc_skipadaptertrim ? "
  • Wick, R. R., Judd, L. M., Gorrie, C. L., & Holt, K. E. (2017). Completing bacterial genome assemblies with multiplex MinION sequencing. Microbial Genomics, 3(10), e000132. 10.1099/mgen.0.000132
  • " : "", - !params.longread_qc_skipqualityfilter ? "
  • Wick R. (2021) Filtlong, URL: https://github.com/rrwick/Filtlong
  • " : "" + params.longread_adapterremoval_tool == "porechop_abi" ? "
  • Bonenfant, Q., Noé, L., & Touzet, H. (2023). Porechop_ABI: discovering unknown adapters in Oxford Nanopore Technology sequencing reads for downstream trimming. Bioinformatics Advances, 3(1):vbac085. 10.1093/bioadv/vbac085
  • " : "", + params.longread_adapterremoval_tool == "porechop" ? "
  • Wick, R. R., Judd, L. M., Gorrie, C. L., & Holt, K. E. (2017). Completing bacterial genome assemblies with multiplex MinION sequencing. Microbial Genomics, 3(10), e000132. 10.1099/mgen.0.000132
  • " : "", + params.longread_filter_tool == "filtlong" ? "
  • Wick R. (2021) Filtlong, URL: https://github.com/rrwick/Filtlong
  • " : "", + params.longread_filter_tool == "nanoq" ? "
  • Steinig, E., & Coin, L. (2022). Nanoq: ultra-fast quality control for nanopore reads. Journal of Open Source Software, 7(69). 10.21105/joss.02991
  • " : "" ].join(' ').trim() def text_shortreadcomplexity = [ @@ -363,13 +376,11 @@ def methodsDescriptionText( mqc_methods_yaml ) { } else meta["doi_text"] = "" 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"] = "" - meta["tool_bibliography"] = "" - - // TODO nf-core: Only uncomment below if logic in toolCitationText/toolBibliographyText has been filled! - // meta["tool_citations"] = toolCitationText().replaceAll(", \\.", ".").replaceAll("\\. \\.", ".").replaceAll(", \\.", ".") - // meta["tool_bibliography"] = toolBibliographyText() + // meta["tool_citations"] = "" + // meta["tool_bibliography"] = "" + meta["tool_citations"] = toolCitationText().replaceAll(", \\.", ".").replaceAll("\\. \\.", ".").replaceAll(", \\.", ".") + meta["tool_bibliography"] = toolBibliographyText() def methods_text = mqc_methods_yaml.text diff --git a/subworkflows/local/visualization_krona.nf b/subworkflows/local/visualization_krona.nf index 77e26a22..2b57a702 100644 --- a/subworkflows/local/visualization_krona.nf +++ b/subworkflows/local/visualization_krona.nf @@ -99,6 +99,7 @@ workflow VISUALIZATION_KRONA { KRONA_KTIMPORTTAXONOMY ( ch_krona_taxonomy_for_input, file(params.krona_taxonomy_directory, checkExists: true) ) ch_krona_html.mix( KRONA_KTIMPORTTAXONOMY.out.html ) + ch_versions = ch_versions.mix( GUNZIP.out.versions.first() ) ch_versions = ch_versions.mix( MEGAN_RMA2INFO_KRONA.out.versions.first() ) ch_versions = ch_versions.mix( KRONA_KTIMPORTTAXONOMY.out.versions.first() ) } diff --git a/subworkflows/nf-core/utils_nextflow_pipeline/main.nf b/subworkflows/nf-core/utils_nextflow_pipeline/main.nf index ac31f28f..28e32b20 100644 --- a/subworkflows/nf-core/utils_nextflow_pipeline/main.nf +++ b/subworkflows/nf-core/utils_nextflow_pipeline/main.nf @@ -2,10 +2,6 @@ // Subworkflow with functionality that may be useful for any Nextflow pipeline // -import org.yaml.snakeyaml.Yaml -import groovy.json.JsonOutput -import nextflow.extension.FilesEx - /* ======================================================================================== SUBWORKFLOW DEFINITION @@ -58,7 +54,7 @@ workflow UTILS_NEXTFLOW_PIPELINE { // Generate version string // def getWorkflowVersion() { - String version_string = "" + def version_string = "" as String if (workflow.manifest.version) { def prefix_v = workflow.manifest.version[0] != 'v' ? 'v' : '' version_string += "${prefix_v}${workflow.manifest.version}" @@ -79,10 +75,10 @@ def dumpParametersToJSON(outdir) { def timestamp = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss') def filename = "params_${timestamp}.json" def temp_pf = new File(workflow.launchDir.toString(), ".${filename}") - def jsonStr = JsonOutput.toJson(params) - temp_pf.text = JsonOutput.prettyPrint(jsonStr) + def jsonStr = groovy.json.JsonOutput.toJson(params) + temp_pf.text = groovy.json.JsonOutput.prettyPrint(jsonStr) - FilesEx.copyTo(temp_pf.toPath(), "${outdir}/pipeline_info/params_${timestamp}.json") + nextflow.extension.FilesEx.copyTo(temp_pf.toPath(), "${outdir}/pipeline_info/params_${timestamp}.json") temp_pf.delete() } @@ -90,7 +86,7 @@ def dumpParametersToJSON(outdir) { // When running with -profile conda, warn if channels have not been set-up appropriately // def checkCondaChannels() { - Yaml parser = new Yaml() + def parser = new org.yaml.snakeyaml.Yaml() def channels = [] try { def config = parser.load("conda config --show channels".execute().text) @@ -102,14 +98,16 @@ def checkCondaChannels() { // Check that all channels are present // This channel list is ordered by required channel priority. - def required_channels_in_order = ['conda-forge', 'bioconda', 'defaults'] + def required_channels_in_order = ['conda-forge', 'bioconda'] def channels_missing = ((required_channels_in_order as Set) - (channels as Set)) as Boolean // Check that they are in the right order def channel_priority_violation = false - def n = required_channels_in_order.size() - for (int i = 0; i < n - 1; i++) { - channel_priority_violation |= !(channels.indexOf(required_channels_in_order[i]) < channels.indexOf(required_channels_in_order[i+1])) + + required_channels_in_order.eachWithIndex { channel, index -> + if (index < required_channels_in_order.size() - 1) { + channel_priority_violation |= !(channels.indexOf(channel) < channels.indexOf(required_channels_in_order[index+1])) + } } if (channels_missing | channel_priority_violation) { diff --git a/subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config b/subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config index d0a926bf..a09572e5 100644 --- a/subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config +++ b/subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config @@ -3,7 +3,7 @@ manifest { author = """nf-core""" homePage = 'https://127.0.0.1' description = """Dummy pipeline""" - nextflowVersion = '!>=23.04.0' + nextflowVersion = '!>=23.04.0' version = '9.9.9' doi = 'https://doi.org/10.5281/zenodo.5070524' } diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf index 14558c39..cbd8495b 100644 --- a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf +++ b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf @@ -2,9 +2,6 @@ // Subworkflow with utility functions specific to the nf-core pipeline template // -import org.yaml.snakeyaml.Yaml -import nextflow.extension.FilesEx - /* ======================================================================================== SUBWORKFLOW DEFINITION @@ -34,7 +31,7 @@ workflow UTILS_NFCORE_PIPELINE { // Warn if a -profile or Nextflow config has not been provided to run the pipeline // def checkConfigProvided() { - valid_config = true + def valid_config = true as Boolean if (workflow.profile == 'standard' && workflow.configFiles.size() <= 1) { log.warn "[$workflow.manifest.name] You are attempting to run the pipeline without any custom configuration!\n\n" + "This will be dependent on your local compute environment but can be achieved via one or more of the following:\n" + @@ -66,11 +63,13 @@ def checkProfileProvided(nextflow_cli_args) { // def workflowCitation() { def temp_doi_ref = "" - String[] manifest_doi = workflow.manifest.doi.tokenize(",") + def manifest_doi = workflow.manifest.doi.tokenize(",") // Using a loop to handle multiple DOIs // Removing `https://doi.org/` to handle pipelines using DOIs vs DOI resolvers // Removing ` ` since the manifest.doi is a string and not a proper list - for (String doi_ref: manifest_doi) temp_doi_ref += " https://doi.org/${doi_ref.replace('https://doi.org/', '').replace(' ', '')}\n" + manifest_doi.each { doi_ref -> + temp_doi_ref += " https://doi.org/${doi_ref.replace('https://doi.org/', '').replace(' ', '')}\n" + } return "If you use ${workflow.manifest.name} for your analysis please cite:\n\n" + "* The pipeline\n" + temp_doi_ref + "\n" + @@ -84,7 +83,7 @@ def workflowCitation() { // Generate workflow version string // def getWorkflowVersion() { - String version_string = "" + def version_string = "" as String if (workflow.manifest.version) { def prefix_v = workflow.manifest.version[0] != 'v' ? 'v' : '' version_string += "${prefix_v}${workflow.manifest.version}" @@ -102,8 +101,8 @@ def getWorkflowVersion() { // Get software versions for pipeline // def processVersionsFromYAML(yaml_file) { - Yaml yaml = new Yaml() - versions = yaml.load(yaml_file).collectEntries { k, v -> [ k.tokenize(':')[-1], v ] } + def yaml = new org.yaml.snakeyaml.Yaml() + def versions = yaml.load(yaml_file).collectEntries { k, v -> [ k.tokenize(':')[-1], v ] } return yaml.dumpAsMap(versions).trim() } @@ -124,7 +123,7 @@ def workflowVersionToYAML() { def softwareVersionsToYAML(ch_versions) { return ch_versions .unique() - .map { processVersionsFromYAML(it) } + .map { version -> processVersionsFromYAML(version) } .unique() .mix(Channel.of(workflowVersionToYAML())) } @@ -134,19 +133,19 @@ def softwareVersionsToYAML(ch_versions) { // def paramsSummaryMultiqc(summary_params) { def summary_section = '' - for (group in summary_params.keySet()) { + summary_params.keySet().each { group -> def group_params = summary_params.get(group) // This gets the parameters of that particular group if (group_params) { summary_section += "

    $group

    \n" summary_section += "
    \n" - for (param in group_params.keySet()) { + group_params.keySet().sort().each { param -> summary_section += "
    $param
    ${group_params.get(param) ?: 'N/A'}
    \n" } summary_section += "
    \n" } } - String yaml_file_text = "id: '${workflow.manifest.name.replace('/','-')}-summary'\n" + def yaml_file_text = "id: '${workflow.manifest.name.replace('/','-')}-summary'\n" as String yaml_file_text += "description: ' - this information is collected when the pipeline is started.'\n" yaml_file_text += "section_name: '${workflow.manifest.name} Workflow Summary'\n" yaml_file_text += "section_href: 'https://github.com/${workflow.manifest.name}'\n" @@ -161,7 +160,7 @@ def paramsSummaryMultiqc(summary_params) { // nf-core logo // def nfCoreLogo(monochrome_logs=true) { - Map colors = logColours(monochrome_logs) + def colors = logColours(monochrome_logs) as Map String.format( """\n ${dashedLine(monochrome_logs)} @@ -180,7 +179,7 @@ def nfCoreLogo(monochrome_logs=true) { // Return dashed line // def dashedLine(monochrome_logs=true) { - Map colors = logColours(monochrome_logs) + def colors = logColours(monochrome_logs) as Map return "-${colors.dim}----------------------------------------------------${colors.reset}-" } @@ -188,7 +187,7 @@ def dashedLine(monochrome_logs=true) { // ANSII colours used for terminal logging // def logColours(monochrome_logs=true) { - Map colorcodes = [:] + def colorcodes = [:] as Map // Reset / Meta colorcodes['reset'] = monochrome_logs ? '' : "\033[0m" @@ -287,7 +286,7 @@ def completionEmail(summary_params, email, email_on_fail, plaintext_email, outdi } def summary = [:] - for (group in summary_params.keySet()) { + summary_params.keySet().sort().each { group -> summary << summary_params[group] } @@ -344,10 +343,10 @@ def completionEmail(summary_params, email, email_on_fail, plaintext_email, outdi def sendmail_html = sendmail_template.toString() // Send the HTML e-mail - Map colors = logColours(monochrome_logs) + def colors = logColours(monochrome_logs) as Map if (email_address) { try { - if (plaintext_email) { throw GroovyException('Send plaintext e-mail, not HTML') } + if (plaintext_email) { throw new org.codehaus.groovy.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 } @@ -364,13 +363,13 @@ def completionEmail(summary_params, email, email_on_fail, plaintext_email, outdi // Write summary e-mail HTML to a file def output_hf = new File(workflow.launchDir.toString(), ".pipeline_report.html") output_hf.withWriter { w -> w << email_html } - FilesEx.copyTo(output_hf.toPath(), "${outdir}/pipeline_info/pipeline_report.html"); + nextflow.extension.FilesEx.copyTo(output_hf.toPath(), "${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(), "${outdir}/pipeline_info/pipeline_report.txt"); + nextflow.extension.FilesEx.copyTo(output_tf.toPath(), "${outdir}/pipeline_info/pipeline_report.txt"); output_tf.delete() } @@ -378,7 +377,7 @@ def completionEmail(summary_params, email, email_on_fail, plaintext_email, outdi // Print pipeline summary on completion // def completionSummary(monochrome_logs=true) { - Map colors = logColours(monochrome_logs) + def colors = logColours(monochrome_logs) as Map if (workflow.success) { if (workflow.stats.ignoredCount == 0) { log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Pipeline completed successfully${colors.reset}-" @@ -395,7 +394,7 @@ def completionSummary(monochrome_logs=true) { // def imNotification(summary_params, hook_url) { def summary = [:] - for (group in summary_params.keySet()) { + summary_params.keySet().sort().each { group -> summary << summary_params[group] } diff --git a/tower.yml b/tower.yml index 787aedfe..d3296955 100644 --- a/tower.yml +++ b/tower.yml @@ -1,5 +1,75 @@ reports: multiqc_report.html: display: "MultiQC HTML report" - samplesheet.csv: - display: "Auto-created samplesheet with collated metadata and FASTQ paths" + "**/fastqc/raw/*.html": + display: "A FastQC report containing quality metrics of raw reads in HTML format." + "**/fastqc/preprocessed/*.html": + display: "A FastQC report containing quality metrics of processed reads in HTML format." + "**/falco/raw/*.html": + display: "A Falco report containing quality metrics of raw reads in HTML format." + "**/falco/preprocessed/*.html": + display: "A Falco report containing quality metrics of processed reads in HTML format." + "**/fastp/*.html": + display: "Results in HTML format." + "**/fastp/*.log": + display: "A fastq log file." + "**/bracken/*_combined_reports.txt": + display: "Combined bracken results as output from Bracken's combine_bracken_outputs.py script." + "**/bracken/*/*.tsv": + display: "A TSV file containing per-sample summary of Bracken results with abundance information." + "**/bracken/*/*report_bracken_species.txt": + display: "A Kraken2 style report with Bracken abundance information." + "**/kraken2/kraken2_*_combined_reports.txt": + display: "A combined profile of all samples aligned to a given database (as generated by krakentools)." + "**/kraken2/*/*.report.txt": + display: "A Kraken2 report that summarises the fraction abundance, taxonomic ID, number of Kmers, taxonomic path of all the hits in the Kraken2 run for a given sample. Will be 6 column rather than 8 if --save_minimizers specified." + "**/krakenuniq/*/*.report.txt": + display: "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": + display: "An optional list of read IDs and the hits each read had against each database for a given sample." + "**/centrifuge/*_combined_reports.txt": + display: "A combined profile of all samples aligned to a given database (as generated by centrifuge-kreport)." + "**/centrifuge/*/*.centrifuge.report.txt": + display: "A classification report that summarises the taxonomic ID, the taxonomic rank, length of genome sequence, number of classified and uniquely classified reads." + "**/centrifuge/*/*.centrifuge.txt": + display: "A Kraken2-style report that summarises the fraction abundance, taxonomic ID, number of k-mers, taxonomic path of all the hits in the centrifuge run for a given sample." + "**/ganon/*_combined_reports.txt": + display: "A combined profile of all samples aligned to a given database (as generated by ganon table)." + "**/ganon/*/*.tre": + display: "A full ganon report file." + "**/ganon/*/*.rep": + display: "A Input 'repo' file from ganon classify." + "**/kaiju/*_combined_reports.txt": + display: "A combined profile of all samples aligned to a given database (as generated by kaiju2table)" + "**/kaiju/*/*.kaijutable.txt": + display: "Summarised Kaiju output with fraction abundance, taxonomic ID, number of reads, and taxonomic names (as generated by kaiju2table)" + "**/kmcp/*/*.profile": + display: "Tab-delimited format file with 17 columns." + "**/krona/*.html": + display: "Per-tool/per-database interactive HTML file containing hierarchical piecharts." + "**/metaphlan/*_combined_reports.txt": + display: "A combined profile of all samples aligned to a given database (as generated by metaphlan_merge_tables)." + "**/metaphlan/*/*.bowtie2out.txt": + display: "Bowtie2 alignment information (can be re-used for skipping alignment when re-running MetaPhlAn with different parameters)." + "**/metaphlan/*/*_profile.txt": + display: "A MetaPhlAn taxonomic profile including abundance estimates." + "**/motus/*_combined_reports.txt": + display: "A combined profile of all samples aligned to a given database (as generated by motus_merge)." + "**/motus/*/*.log": + display: "Standard error logging file containing summary statistics." + "**/motus/*/*.out": + display: "Results with taxonomic classification of each read." + "**/nanoq/*.stats": + display: "Summary report of reads statistics." + "**/nonpareil/*.png": + display: "PNG file of the Nonpareil curve." + "**/nonpareil/*.pdf": + display: "Plotted nonpareil curves in PDF format." + "**/porechop/*.log": + display: "Log file containing stdout information." + "**/porechop_abi/*.log": + display: "Log file containing stdout information." + "**/samtools/stats/*.stats": + display: "File containing samtools stats output." + "**/taxpasta/*tsv": + display: "Standardised taxon table containing multiple samples. The first column describes the taxonomy ID and the rest of the columns describe the read counts for each sample." diff --git a/workflows/taxprofiler.nf b/workflows/taxprofiler.nf index fdb4266c..93eb55dd 100644 --- a/workflows/taxprofiler.nf +++ b/workflows/taxprofiler.nf @@ -64,6 +64,7 @@ if ( [params.taxpasta_add_name, params.taxpasta_add_rank, params.taxpasta_add_li // include { SHORTREAD_PREPROCESSING } from '../subworkflows/local/shortread_preprocessing' +include { NONPAREIL } from '../subworkflows/local/nonpareil' include { LONGREAD_PREPROCESSING } from '../subworkflows/local/longread_preprocessing' include { SHORTREAD_HOSTREMOVAL } from '../subworkflows/local/shortread_hostremoval' include { LONGREAD_HOSTREMOVAL } from '../subworkflows/local/longread_hostremoval' @@ -134,21 +135,27 @@ workflow TAXPROFILER { } .branch { meta, run_accession, instrument_platform, fastq_1, fastq_2, fasta -> fastq: meta.single_end || fastq_2 - return [ meta, fastq_2 ? [ fastq_1, fastq_2 ] : [ fastq_1 ] ] - nanopore: instrument_platform == 'OXFORD_NANOPORE' + return [ meta + [ type: "short" ], fastq_2 ? [ fastq_1, fastq_2 ] : [ fastq_1 ] ] + nanopore: instrument_platform == 'OXFORD_NANOPORE' && !meta.is_fasta meta.single_end = true - return [ meta, [ fastq_1 ] ] - fasta: meta.is_fasta + return [ meta + [ type: "long" ], [ fastq_1 ] ] + fasta_short: meta.is_fasta && instrument_platform == 'ILLUMINA' meta.single_end = true - return [ meta, [ fasta ] ] + return [ meta + [ type: "short" ], [ fasta ] ] + fasta_long: meta.is_fasta && instrument_platform == 'OXFORD_NANOPORE' + meta.single_end = true + return [ meta + [ type: "long" ], [ fasta ] ] } // Merge ch_input.fastq and ch_input.nanopore into a single channel - def ch_input_for_fastqc = ch_input.fastq.mix( ch_input.nanopore ) + ch_input_for_fastqc = ch_input.fastq.mix( ch_input.nanopore ) // Validate and decompress databases ch_dbs_for_untar = databases .branch { db_meta, db_path -> + if ( !db_meta.db_type ) { + db_meta = db_meta + [ db_type: "short;long" ] + } untar: db_path.name.endsWith( ".tar.gz" ) skip: true } @@ -218,6 +225,15 @@ workflow TAXPROFILER { ch_longreads_preprocessed = ch_input.nanopore } + /* + MODULE: REDUNDANCY ESTIMATION + */ + + if ( params.perform_shortread_redundancyestimation ) { + NONPAREIL ( ch_shortreads_preprocessed ) + ch_versions = ch_versions.mix( NONPAREIL.out.versions ) + } + /* SUBWORKFLOW: COMPLEXITY FILTERING */ @@ -276,13 +292,13 @@ workflow TAXPROFILER { meta, reads -> [ meta, [ reads ].flatten() ] } - .mix( ch_input.fasta ) + .mix( ch_input.fasta_short, ch_input.fasta_long) ch_versions = ch_versions.mix(MERGE_RUNS.out.versions) } else { ch_reads_runmerged = ch_shortreads_hostremoved - .mix( ch_longreads_hostremoved, ch_input.fasta ) + .mix( ch_longreads_hostremoved, ch_input.fasta_short, ch_input.fasta_long ) } /* @@ -376,6 +392,10 @@ workflow TAXPROFILER { ch_multiqc_files = ch_multiqc_files.mix( LONGREAD_PREPROCESSING.out.mqc.collect{it[1]}.ifEmpty([]) ) } + if ( params.perform_shortread_redundancyestimation ) { + ch_multiqc_files = ch_multiqc_files.mix( NONPAREIL.out.mqc.collect{it[1]}.ifEmpty([]) ) + } + if (params.perform_shortread_complexityfilter && params.shortread_complexityfilter_tool != 'fastp'){ ch_multiqc_files = ch_multiqc_files.mix( SHORTREAD_COMPLEXITYFILTERING.out.mqc.collect{it[1]}.ifEmpty([]) ) } @@ -398,7 +418,9 @@ workflow TAXPROFILER { ch_multiqc_files.collect(), ch_multiqc_config.toList(), ch_multiqc_custom_config.toList(), - ch_multiqc_logo.toList() + ch_multiqc_logo.toList(), + [], + [] ) emit: