From d555becb8fb798d027eeb7b9bdf3b1e1491ae4f3 Mon Sep 17 00:00:00 2001 From: JoseEspinosa Date: Mon, 27 Jun 2022 16:44:16 +0200 Subject: [PATCH 001/215] Collect bowtie index files --- subworkflows/local/genome_quant.nf | 2 +- workflows/smrnaseq.nf | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/subworkflows/local/genome_quant.nf b/subworkflows/local/genome_quant.nf index 54c7675c..8cf812d7 100644 --- a/subworkflows/local/genome_quant.nf +++ b/subworkflows/local/genome_quant.nf @@ -17,7 +17,7 @@ workflow GENOME_QUANT { if (!bt_index){ INDEX_GENOME ( fasta ) - bowtie_indices = INDEX_GENOME.out.bowtie_indices + bowtie_indices = INDEX_GENOME.out.bowtie_indices fasta_formatted = INDEX_GENOME.out.fasta ch_versions = ch_versions.mix(INDEX_GENOME.out.versions) } else { diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index cf6ed597..470bebc0 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -59,7 +59,7 @@ if (!params.mirGeneDB) { } else { if (params.mirGeneDB_mature) { reference_mature = file(params.mirGeneDB_mature, checkIfExists: true) } else { exit 1, "Mature miRNA fasta file not found: ${params.mirGeneDB_mature}" } if (params.mirGeneDB_hairpin) { reference_hairpin = file(params.mirGeneDB_hairpin, checkIfExists: true) } else { exit 1, "Hairpin miRNA fasta file not found: ${params.mirGeneDB_hairpin}" } - if (params.mirGeneDB_gff) { mirna_gtf = file(params.mirGeneDB_gff, checkIfExists: true) } else { exit 1, "MirGeneDB gff file not found: ${params.mirGeneDB_gff}"} + if (params.mirGeneDB_gff) { mirna_gtf = file(params.mirGeneDB_gff, checkIfExists: true) } else { exit 1, "MirGeneDB gff file not found: ${params.mirGeneDB_gff}"} params.filterSpecies = params.mirGeneDB_species } @@ -169,7 +169,13 @@ workflow SMRNASEQ { ch_versions = ch_versions.mix(GENOME_QUANT.out.versions) if (!params.skip_mirdeep) { - MIRDEEP2 (FASTQC_TRIMGALORE.out.reads, GENOME_QUANT.out.fasta, GENOME_QUANT.out.indices, MIRNA_QUANT.out.fasta_hairpin, MIRNA_QUANT.out.fasta_mature) + MIRDEEP2 ( + FASTQC_TRIMGALORE.out.reads, + GENOME_QUANT.out.fasta, + GENOME_QUANT.out.indices.collect(), + MIRNA_QUANT.out.fasta_hairpin, + MIRNA_QUANT.out.fasta_mature + ) ch_versions = ch_versions.mix(MIRDEEP2.out.versions) } } From 31103e098ebcd99fa0240fd2dbac0db30b92acaa Mon Sep 17 00:00:00 2001 From: JoseEspinosa Date: Mon, 27 Jun 2022 16:51:17 +0200 Subject: [PATCH 002/215] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 178452e2..a23a48bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Enhancements & fixes - Trimmed output was not as documented and not correctly published [#161](https://github.com/nf-core/smrnaseq/issues/161) +- Index files were not collected when `bowtie_indices` was used and thus mapping was failing [#159](https://github.com/nf-core/smrnaseq/issues/159) ### Other enhancements From b2ba538029689a49c9e5f74e20cb84fec8a6c9ca Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 29 Jun 2022 09:55:05 +0200 Subject: [PATCH 003/215] Updated all modules to fix some issues --- modules.json | 16 ++++++++-------- modules/nf-core/modules/cat/fastq/main.nf | 4 ++-- modules/nf-core/modules/multiqc/main.nf | 14 ++++++++++---- modules/nf-core/modules/multiqc/meta.yml | 8 ++++++++ .../nf-core/modules/samtools/flagstat/main.nf | 9 +++++---- .../nf-core/modules/samtools/idxstats/main.nf | 10 ++++++---- modules/nf-core/modules/samtools/index/main.nf | 6 +++--- modules/nf-core/modules/samtools/sort/main.nf | 6 +++--- modules/nf-core/modules/samtools/stats/main.nf | 15 ++++++++------- modules/nf-core/modules/trimgalore/main.nf | 13 ++++++++----- modules/nf-core/modules/trimgalore/meta.yml | 5 +++++ 11 files changed, 66 insertions(+), 40 deletions(-) diff --git a/modules.json b/modules.json index 81208b16..0b772f2e 100644 --- a/modules.json +++ b/modules.json @@ -4,7 +4,7 @@ "repos": { "nf-core/modules": { "cat/fastq": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d" + "git_sha": "9aadd9a6d3f5964476582319b3a1c54a3e3fe7c9" }, "custom/dumpsoftwareversions": { "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d" @@ -13,25 +13,25 @@ "git_sha": "49b18b1639f4f7104187058866a8fab33332bdfe" }, "multiqc": { - "git_sha": "49b18b1639f4f7104187058866a8fab33332bdfe" + "git_sha": "08376da6843b14c82d84d444784c0b3635bb7fd5" }, "samtools/flagstat": { - "git_sha": "1ad73f1b2abdea9398680d6d20014838135c9a35" + "git_sha": "ecece498f10b47b7c9d06f53a310cea5811b4c5f" }, "samtools/idxstats": { - "git_sha": "1ad73f1b2abdea9398680d6d20014838135c9a35" + "git_sha": "ecece498f10b47b7c9d06f53a310cea5811b4c5f" }, "samtools/index": { - "git_sha": "49b18b1639f4f7104187058866a8fab33332bdfe" + "git_sha": "897c33d5da084b61109500ee44c01da2d3e4e773" }, "samtools/sort": { - "git_sha": "49b18b1639f4f7104187058866a8fab33332bdfe" + "git_sha": "897c33d5da084b61109500ee44c01da2d3e4e773" }, "samtools/stats": { - "git_sha": "49b18b1639f4f7104187058866a8fab33332bdfe" + "git_sha": "ecece498f10b47b7c9d06f53a310cea5811b4c5f" }, "trimgalore": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d" + "git_sha": "85ec13ff1fc2196c5a507ea497de468101baabed" } } } diff --git a/modules/nf-core/modules/cat/fastq/main.nf b/modules/nf-core/modules/cat/fastq/main.nf index bf0877c3..b6854895 100644 --- a/modules/nf-core/modules/cat/fastq/main.nf +++ b/modules/nf-core/modules/cat/fastq/main.nf @@ -4,8 +4,8 @@ process CAT_FASTQ { conda (params.enable_conda ? "conda-forge::sed=4.7" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://containers.biocontainers.pro/s3/SingImgsRepo/biocontainers/v1.2.0_cv1/biocontainers_v1.2.0_cv1.img' : - 'biocontainers/biocontainers:v1.2.0_cv1' }" + 'https://depot.galaxyproject.org/singularity/ubuntu:20.04' : + 'ubuntu:20.04' }" input: tuple val(meta), path(reads, stageAs: "input*/*") diff --git a/modules/nf-core/modules/multiqc/main.nf b/modules/nf-core/modules/multiqc/main.nf index ae019dbf..3c3517bf 100644 --- a/modules/nf-core/modules/multiqc/main.nf +++ b/modules/nf-core/modules/multiqc/main.nf @@ -3,11 +3,12 @@ process MULTIQC { conda (params.enable_conda ? 'bioconda::multiqc=1.12' : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.12--pyhdfd78af_0' : - 'quay.io/biocontainers/multiqc:1.12--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/multiqc:1.13a--pyhdfd78af_1' : + 'quay.io/biocontainers/multiqc:1.13a--pyhdfd78af_1' }" input: - path multiqc_files + path multiqc_files, stageAs: "?/*" + tuple path(multiqc_config), path(multiqc_logo) output: path "*multiqc_report.html", emit: report @@ -20,8 +21,13 @@ process MULTIQC { script: def args = task.ext.args ?: '' + def config = multiqc_config ? "--config $multiqc_config" : '' """ - multiqc -f $args . + multiqc \\ + --force \\ + $config \\ + $args \\ + . cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/nf-core/modules/multiqc/meta.yml b/modules/nf-core/modules/multiqc/meta.yml index 6fa891ef..bf3a27fe 100644 --- a/modules/nf-core/modules/multiqc/meta.yml +++ b/modules/nf-core/modules/multiqc/meta.yml @@ -17,6 +17,14 @@ input: type: file description: | List of reports / files recognised by MultiQC, for example the html and zip output of FastQC + - multiqc_config: + type: file + description: Config yml for MultiQC + pattern: "*.{yml,yaml}" + - multiqc_logo: + type: file + description: Logo file for MultiQC + pattern: "*.{png}" output: - report: type: file diff --git a/modules/nf-core/modules/samtools/flagstat/main.nf b/modules/nf-core/modules/samtools/flagstat/main.nf index 9e3440ac..03ec2dcf 100644 --- a/modules/nf-core/modules/samtools/flagstat/main.nf +++ b/modules/nf-core/modules/samtools/flagstat/main.nf @@ -2,10 +2,10 @@ process SAMTOOLS_FLAGSTAT { tag "$meta.id" label 'process_low' - conda (params.enable_conda ? "bioconda::samtools=1.15" : null) + conda (params.enable_conda ? "bioconda::samtools=1.15.1" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.15--h1170115_1' : - 'quay.io/biocontainers/samtools:1.15--h1170115_1' }" + 'https://depot.galaxyproject.org/singularity/samtools:1.15.1--h1170115_0' : + 'quay.io/biocontainers/samtools:1.15.1--h1170115_0' }" input: tuple val(meta), path(bam), path(bai) @@ -19,12 +19,13 @@ process SAMTOOLS_FLAGSTAT { script: def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" """ samtools \\ flagstat \\ --threads ${task.cpus-1} \\ $bam \\ - > ${bam}.flagstat + > ${prefix}.flagstat cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/nf-core/modules/samtools/idxstats/main.nf b/modules/nf-core/modules/samtools/idxstats/main.nf index 7d5cee17..4b245419 100644 --- a/modules/nf-core/modules/samtools/idxstats/main.nf +++ b/modules/nf-core/modules/samtools/idxstats/main.nf @@ -2,10 +2,10 @@ process SAMTOOLS_IDXSTATS { tag "$meta.id" label 'process_low' - conda (params.enable_conda ? "bioconda::samtools=1.15" : null) + conda (params.enable_conda ? "bioconda::samtools=1.15.1" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.15--h1170115_1' : - 'quay.io/biocontainers/samtools:1.15--h1170115_1' }" + 'https://depot.galaxyproject.org/singularity/samtools:1.15.1--h1170115_0' : + 'quay.io/biocontainers/samtools:1.15.1--h1170115_0' }" input: tuple val(meta), path(bam), path(bai) @@ -19,11 +19,13 @@ process SAMTOOLS_IDXSTATS { script: def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ samtools \\ idxstats \\ $bam \\ - > ${bam}.idxstats + > ${prefix}.idxstats cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/nf-core/modules/samtools/index/main.nf b/modules/nf-core/modules/samtools/index/main.nf index fff6e1b8..e04e63e8 100644 --- a/modules/nf-core/modules/samtools/index/main.nf +++ b/modules/nf-core/modules/samtools/index/main.nf @@ -2,10 +2,10 @@ process SAMTOOLS_INDEX { tag "$meta.id" label 'process_low' - conda (params.enable_conda ? "bioconda::samtools=1.15" : null) + conda (params.enable_conda ? "bioconda::samtools=1.15.1" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.15--h1170115_1' : - 'quay.io/biocontainers/samtools:1.15--h1170115_1' }" + 'https://depot.galaxyproject.org/singularity/samtools:1.15.1--h1170115_0' : + 'quay.io/biocontainers/samtools:1.15.1--h1170115_0' }" input: tuple val(meta), path(input) diff --git a/modules/nf-core/modules/samtools/sort/main.nf b/modules/nf-core/modules/samtools/sort/main.nf index ba46f0c9..b4fc1cbe 100644 --- a/modules/nf-core/modules/samtools/sort/main.nf +++ b/modules/nf-core/modules/samtools/sort/main.nf @@ -2,10 +2,10 @@ process SAMTOOLS_SORT { tag "$meta.id" label 'process_medium' - conda (params.enable_conda ? "bioconda::samtools=1.15" : null) + conda (params.enable_conda ? "bioconda::samtools=1.15.1" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.15--h1170115_1' : - 'quay.io/biocontainers/samtools:1.15--h1170115_1' }" + 'https://depot.galaxyproject.org/singularity/samtools:1.15.1--h1170115_0' : + 'quay.io/biocontainers/samtools:1.15.1--h1170115_0' }" input: tuple val(meta), path(bam) diff --git a/modules/nf-core/modules/samtools/stats/main.nf b/modules/nf-core/modules/samtools/stats/main.nf index 85cb64f3..c913bc5e 100644 --- a/modules/nf-core/modules/samtools/stats/main.nf +++ b/modules/nf-core/modules/samtools/stats/main.nf @@ -2,13 +2,13 @@ process SAMTOOLS_STATS { tag "$meta.id" label 'process_low' - conda (params.enable_conda ? "bioconda::samtools=1.15" : null) + conda (params.enable_conda ? "bioconda::samtools=1.15.1" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.15--h1170115_1' : - 'quay.io/biocontainers/samtools:1.15--h1170115_1' }" + 'https://depot.galaxyproject.org/singularity/samtools:1.15.1--h1170115_0' : + 'quay.io/biocontainers/samtools:1.15.1--h1170115_0' }" input: - tuple val(meta), path(input), path(input_index) + tuple val(meta), path(bam), path(bai) path fasta output: @@ -20,14 +20,15 @@ process SAMTOOLS_STATS { script: def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" def reference = fasta ? "--reference ${fasta}" : "" """ samtools \\ stats \\ --threads ${task.cpus-1} \\ ${reference} \\ - ${input} \\ - > ${input}.stats + ${bam} \\ + > ${prefix}.stats cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -38,7 +39,7 @@ process SAMTOOLS_STATS { stub: def prefix = task.ext.prefix ?: "${meta.id}" """ - touch ${input}.stats + touch ${prefix}.stats cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/nf-core/modules/trimgalore/main.nf b/modules/nf-core/modules/trimgalore/main.nf index 9487c799..3a3fca90 100644 --- a/modules/nf-core/modules/trimgalore/main.nf +++ b/modules/nf-core/modules/trimgalore/main.nf @@ -11,12 +11,13 @@ process TRIMGALORE { tuple val(meta), path(reads) output: - tuple val(meta), path("*.fq.gz") , emit: reads - tuple val(meta), path("*report.txt"), emit: log - path "versions.yml" , emit: versions + tuple val(meta), path("*{trimmed,val}*.fq.gz"), emit: reads + tuple val(meta), path("*report.txt") , emit: log + path "versions.yml" , emit: versions - tuple val(meta), path("*.html"), emit: html optional true - tuple val(meta), path("*.zip") , emit: zip optional true + tuple val(meta), path("*unpaired*.fq.gz") , emit: unpaired, optional: true + tuple val(meta), path("*.html") , emit: html , optional: true + tuple val(meta), path("*.zip") , emit: zip , optional: true when: task.ext.when == null || task.ext.when @@ -52,6 +53,7 @@ process TRIMGALORE { $c_r1 \\ $tpc_r1 \\ ${prefix}.fastq.gz + cat <<-END_VERSIONS > versions.yml "${task.process}": trimgalore: \$(echo \$(trim_galore --version 2>&1) | sed 's/^.*version //; s/Last.*\$//') @@ -73,6 +75,7 @@ process TRIMGALORE { $tpc_r2 \\ ${prefix}_1.fastq.gz \\ ${prefix}_2.fastq.gz + cat <<-END_VERSIONS > versions.yml "${task.process}": trimgalore: \$(echo \$(trim_galore --version 2>&1) | sed 's/^.*version //; s/Last.*\$//') diff --git a/modules/nf-core/modules/trimgalore/meta.yml b/modules/nf-core/modules/trimgalore/meta.yml index e99a8833..439f566d 100644 --- a/modules/nf-core/modules/trimgalore/meta.yml +++ b/modules/nf-core/modules/trimgalore/meta.yml @@ -37,6 +37,11 @@ output: List of input adapter trimmed FastQ files of size 1 and 2 for single-end and paired-end data, respectively. pattern: "*.{fq.gz}" + - unpaired: + type: file + description: | + FastQ files containing unpaired reads from read 1 or read 2 + pattern: "*unpaired*.fq.gz" - html: type: file description: FastQC report (optional) From bdc08fbc1ec35de057fa16f30eb3762ca3058c22 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 29 Jun 2022 09:59:05 +0200 Subject: [PATCH 004/215] Add changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41dc14b0..45e6713b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Trimmed output was not as documented and not correctly published [#161](https://github.com/nf-core/smrnaseq/issues/161) - Index files were not collected when `bowtie_indices` was used and thus mapping was failing [#159](https://github.com/nf-core/smrnaseq/issues/159) +- Fixed issue with mirTop and MultiQC by upgrading to MultiQC V1.13dev [#137](https://github.com/nf-core/smrnaseq/issues/137) ### Other enhancements From 0f6bffd4f91950c50a98b57c62cdab45b5ea8668 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 29 Jun 2022 10:23:37 +0200 Subject: [PATCH 005/215] MultiQC module changed to expect 2 inputs --- workflows/smrnaseq.nf | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index e8dfc5fe..07f702d4 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -42,6 +42,7 @@ mirna_gtf = params.mirna_gtf ? params.mirna_gtf : mirna_gtf_from_species ch_multiqc_config = file("$projectDir/assets/multiqc_config.yml", checkIfExists: true) ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath(params.multiqc_config) : Channel.empty() +ch_multiqc_image = file("$projectDir/assets/smrnaseq_logo.png", checkIfExists: true) /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -155,22 +156,22 @@ workflow SMRNASEQ { // contamination_stats = Channel.empty() if (params.filter_contamination){ - CONTAMINANT_FILTER ( + CONTAMINANT_FILTER ( reference_hairpin, - params.rrna, - params.trna, - params.cdna, - params.ncrna, - params.pirna, + params.rrna, + params.trna, + params.cdna, + params.ncrna, + params.pirna, params.other_contamination, - FASTQC_TRIMGALORE.out.reads + FASTQC_TRIMGALORE.out.reads ) - + reads_for_mirna = CONTAMINANT_FILTER.out.filtered_reads ch_versions = ch_versions.mix(CONTAMINANT_FILTER.out.versions) CONTAMINANT_FILTER.out.filter_stats .set { contamination_stats } - + } MIRNA_QUANT ( @@ -233,7 +234,8 @@ workflow SMRNASEQ { ch_multiqc_files = ch_multiqc_files.mix(MIRTRACE.out.results.collect().ifEmpty([])) MULTIQC ( - ch_multiqc_files.collect() + ch_multiqc_files.collect(), + [ch_multiqc_config, ch_multiqc_image] ) multiqc_report = MULTIQC.out.report.toList() From 27575a591f8238a46ade01247fd75ec5682141a8 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 29 Jun 2022 10:40:36 +0200 Subject: [PATCH 006/215] Update workflows/smrnaseq.nf Co-authored-by: Jose Espinosa-Carrasco --- workflows/smrnaseq.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 07f702d4..be455612 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -42,7 +42,7 @@ mirna_gtf = params.mirna_gtf ? params.mirna_gtf : mirna_gtf_from_species ch_multiqc_config = file("$projectDir/assets/multiqc_config.yml", checkIfExists: true) ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath(params.multiqc_config) : Channel.empty() -ch_multiqc_image = file("$projectDir/assets/smrnaseq_logo.png", checkIfExists: true) +ch_multiqc_image = file("$projectDir/assets/smrnaseq_logo.png", checkIfExists: true) /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 9fd93dcf2dc7c14ff08dd7a5feafada66676fb2a Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 29 Jun 2022 10:50:59 +0200 Subject: [PATCH 007/215] Improve bt index handling --- CHANGELOG.md | 1 + modules/local/bowtie_map_contaminants.nf | 4 ++-- modules/local/bowtie_map_mirna.nf | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45e6713b..e8902d23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Trimmed output was not as documented and not correctly published [#161](https://github.com/nf-core/smrnaseq/issues/161) - Index files were not collected when `bowtie_indices` was used and thus mapping was failing [#159](https://github.com/nf-core/smrnaseq/issues/159) - Fixed issue with mirTop and MultiQC by upgrading to MultiQC V1.13dev [#137](https://github.com/nf-core/smrnaseq/issues/137) +- Improved Bowtie index handling which should be more stable now and follow nf-core/modules approach ### Other enhancements diff --git a/modules/local/bowtie_map_contaminants.nf b/modules/local/bowtie_map_contaminants.nf index a041e512..397aae82 100644 --- a/modules/local/bowtie_map_contaminants.nf +++ b/modules/local/bowtie_map_contaminants.nf @@ -18,13 +18,13 @@ process BOWTIE_MAP_CONTAMINANTS { path "filtered.*.stats" , emit: stats script: - def index_base = index.toString().tokenize(' ')[0].tokenize('.')[0] """ + INDEX=`find -L ./ -name "*.3.ebwt" | sed 's/.3.ebwt//'` bowtie2 \\ --threads ${task.cpus} \\ --very-sensitive-local \\ -k 1 \\ - -x $index_base \\ + -x \$INDEX \\ --un ${meta.id}.${contaminant_type}.filter.unmapped.contaminant.fastq \\ ${reads} \\ -S ${meta.id}.filter.contaminant.sam > ${meta.id}.contaminant_bowtie.log 2>&1 diff --git a/modules/local/bowtie_map_mirna.nf b/modules/local/bowtie_map_mirna.nf index 9a1301fb..316f94af 100644 --- a/modules/local/bowtie_map_mirna.nf +++ b/modules/local/bowtie_map_mirna.nf @@ -17,10 +17,10 @@ process BOWTIE_MAP_SEQ { path "versions.yml" , emit: versions script: - def index_base = index.toString().tokenize(' ')[0].tokenize('.')[0] """ + INDEX=`find -L ./ -name "*.3.ebwt" | sed 's/.3.ebwt//'` bowtie \\ - -x $index_base \\ + -x \$INDEX \\ -q <(zcat $reads) \\ -p ${task.cpus} \\ -t \\ From b762e4305b9b1fe115bdf815277210eacc1b8dcb Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 30 Jun 2022 19:20:49 +0000 Subject: [PATCH 008/215] Removed mirtrace_protocol --- CHANGELOG.md | 1 + modules/local/mirtrace.nf | 9 +++------ nextflow.config | 1 - nextflow_schema.json | 8 -------- 4 files changed, 4 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8902d23..c100756d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Index files were not collected when `bowtie_indices` was used and thus mapping was failing [#159](https://github.com/nf-core/smrnaseq/issues/159) - Fixed issue with mirTop and MultiQC by upgrading to MultiQC V1.13dev [#137](https://github.com/nf-core/smrnaseq/issues/137) - Improved Bowtie index handling which should be more stable now and follow nf-core/modules approach +- Removed `mirtrace_protocol` as the parameter was redundant and `params.protocol` is entirely sufficient [#168](https://github.com/nf-core/smrnaseq/issues/168) ### Other enhancements diff --git a/modules/local/mirtrace.nf b/modules/local/mirtrace.nf index 6dd553e9..fd04ff8d 100644 --- a/modules/local/mirtrace.nf +++ b/modules/local/mirtrace.nf @@ -30,11 +30,8 @@ process MIRTRACE_RUN { three_prime_adapter = params.three_prime_adapter } // mirtrace protocol defaults to 'params.protocol' if not set - def mirtrace_protocol = params.mirtrace_protocol - if (!params.mirtrace_protocol){ - mirtrace_protocol = params.protocol - } - def primer = (mirtrace_protocol=="cats") ? " " : " --adapter $three_prime_adapter " + def protocol = params.protocol + def primer = (protocol=="cats") ? " " : " --adapter $three_prime_adapter " def java_mem = '' if(task.memory){ tmem = task.memory.toBytes() @@ -52,7 +49,7 @@ process MIRTRACE_RUN { java $java_mem -jar \$mirtracejar/mirtrace.jar --mirtrace-wrapper-name mirtrace qc \\ --species $params.mirtrace_species \\ $primer \\ - --protocol $mirtrace_protocol \\ + --protocol $protocol \\ --config mirtrace_config \\ --write-fasta \\ --output-dir mirtrace \\ diff --git a/nextflow.config b/nextflow.config index 842645af..fe98b39c 100644 --- a/nextflow.config +++ b/nextflow.config @@ -23,7 +23,6 @@ params { mirna_gtf = null bowtie_indices = null mirtrace_species = null - mirtrace_protocol = 'illumina' mature = "https://mirbase.org/ftp/CURRENT/mature.fa.gz" hairpin = "https://mirbase.org/ftp/CURRENT/hairpin.fa.gz" mirGeneDB = false diff --git a/nextflow_schema.json b/nextflow_schema.json index 040234b3..77faa9ba 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -178,14 +178,6 @@ "fa_icon": "fas fa-text-width", "description": "Sequencing adapter sequence to use for trimming." }, - "mirtrace_protocol": { - "type": "string", - "default": "illumina", - "fa_icon": "fas fa-vial", - "description": "The miRTrace protocol for QC reporting.", - "help_text": "miRTrace can handle four protocols, each with their own primer-read structure. See the protocol descriptions [here](https://github.com/friedlanderlab/mirtrace/blob/master/release-bundle-includes/doc/manual/mirtrace_manual.pdf).", - "enum": ["illumina", "cats", "qiaseq", "nextflex"] - }, "trim_galore_max_length": { "type": "integer", "default": 40, From 6382b441fdc27d0fc192b5b790fea98b93cfe4df Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 14 Jul 2022 10:03:03 +0000 Subject: [PATCH 009/215] Tiny typo fix --- docs/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index 8e4015ba..197e6c80 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -12,7 +12,7 @@ This option indicates the experimental protocol used for the sample preparation. - 'illumina': adapter (`TGGAATTCTCGGGTGCCAAGG`) - 'nextflex': adapter (`TGGAATTCTCGGGTGCCAAGG), clip_r1 (`4`), three_prime_clip_r1 (`4`) -- 'qiaseq': adapter (`AACTGTAGGCACCATCAAT) +- 'qiaseq': adapter (`AACTGTAGGCACCATCAAT`) - 'cats': adapter (`GATCGGAAGAGCACACGTCTG), clip_r1(`3) - 'custom' (where the ser can indicate the `three_prime_adapter`, `clip_r1` and three_prime_clip_r1`) From 35bb9a4a72fe2eb79891a5ab63297d5dcacb95b5 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 14 Jul 2022 13:04:11 +0000 Subject: [PATCH 010/215] Add clearer docs --- docs/usage.md | 4 +++- modules/local/trimgalore.nf | 3 +-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 197e6c80..475dc9dc 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -14,7 +14,9 @@ This option indicates the experimental protocol used for the sample preparation. - 'nextflex': adapter (`TGGAATTCTCGGGTGCCAAGG), clip_r1 (`4`), three_prime_clip_r1 (`4`) - 'qiaseq': adapter (`AACTGTAGGCACCATCAAT`) - 'cats': adapter (`GATCGGAAGAGCACACGTCTG), clip_r1(`3) -- 'custom' (where the ser can indicate the `three_prime_adapter`, `clip_r1` and three_prime_clip_r1`) +- 'custom' (where the user can indicate the `three_prime_adapter`, `clip_r1` and `three_prime_clip_r1` manually) + +:warning: At least the `custom` protocol has to be specified, otherwise the pipeline won't run. ### `mirtrace_species or mirGeneDB_species` diff --git a/modules/local/trimgalore.nf b/modules/local/trimgalore.nf index 98519584..3dec8f2e 100644 --- a/modules/local/trimgalore.nf +++ b/modules/local/trimgalore.nf @@ -51,12 +51,11 @@ process TRIMGALORE { three_prime_clip_r1 = 0 // three_prime_adapter = "GATCGGAAGAGCACACGTCTG" three_prime_adapter = "AAAAAAAA" - } else { + } else if (params.protocol == "custom"){ //custom protocol clip_r1 = params.clip_r1 three_prime_clip_r1 = params.three_prime_clip_r1 three_prime_adapter = params.three_prime_adapter - protocol = params.protocol } def tg_length = "--length ${params.min_length}" def c_r1 = clip_r1 > 0 ? "--clip_r1 ${clip_r1}" : '' From 354600cdf24044543e1b2dbc0ea18176c19bc72a Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 14 Jul 2022 13:26:09 +0000 Subject: [PATCH 011/215] Tiny bugfix for mirtrace --- modules/local/mirtrace.nf | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/local/mirtrace.nf b/modules/local/mirtrace.nf index fd04ff8d..ab005045 100644 --- a/modules/local/mirtrace.nf +++ b/modules/local/mirtrace.nf @@ -24,11 +24,10 @@ process MIRTRACE_RUN { three_prime_adapter = "AACTGTAGGCACCATCAAT" } else if (params.protocol == "cats"){ three_prime_adapter = "AAAAAAAA" - } - if (params.three_prime_adapter){ - // to allow replace of 3' primer using one of the previous protocols + } else if (params.protocol == "custom"){ three_prime_adapter = params.three_prime_adapter } + // mirtrace protocol defaults to 'params.protocol' if not set def protocol = params.protocol def primer = (protocol=="cats") ? " " : " --adapter $three_prime_adapter " From 72cd3de0dd93885eb4b7f8a255a2c4e4493de298 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 14 Jul 2022 13:29:12 +0000 Subject: [PATCH 012/215] Another fix --- modules/local/mirtrace.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/mirtrace.nf b/modules/local/mirtrace.nf index ab005045..11203124 100644 --- a/modules/local/mirtrace.nf +++ b/modules/local/mirtrace.nf @@ -29,8 +29,8 @@ process MIRTRACE_RUN { } // mirtrace protocol defaults to 'params.protocol' if not set - def protocol = params.protocol def primer = (protocol=="cats") ? " " : " --adapter $three_prime_adapter " + def protocol = (protocol=="custom") ? "" : "--protocol $params.protocol" def java_mem = '' if(task.memory){ tmem = task.memory.toBytes() @@ -48,7 +48,7 @@ process MIRTRACE_RUN { java $java_mem -jar \$mirtracejar/mirtrace.jar --mirtrace-wrapper-name mirtrace qc \\ --species $params.mirtrace_species \\ $primer \\ - --protocol $protocol \\ + $protocol \\ --config mirtrace_config \\ --write-fasta \\ --output-dir mirtrace \\ From 5f4426b8ee95d87f86cb9195b8629a1b2a76f3a7 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 14 Jul 2022 13:34:51 +0000 Subject: [PATCH 013/215] Fix for sure --- modules/local/mirtrace.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/mirtrace.nf b/modules/local/mirtrace.nf index 11203124..e893c2e9 100644 --- a/modules/local/mirtrace.nf +++ b/modules/local/mirtrace.nf @@ -29,8 +29,8 @@ process MIRTRACE_RUN { } // mirtrace protocol defaults to 'params.protocol' if not set - def primer = (protocol=="cats") ? " " : " --adapter $three_prime_adapter " - def protocol = (protocol=="custom") ? "" : "--protocol $params.protocol" + def primer = (params.protocol=="cats") ? " " : " --adapter $three_prime_adapter " + def protocol = (params.protocol=="custom") ? " " : "--protocol $params.protocol" def java_mem = '' if(task.memory){ tmem = task.memory.toBytes() From f46c811a9854cef723a89d122ab8b0b8b0349a06 Mon Sep 17 00:00:00 2001 From: Marcel Ribeiro-Dantas Date: Fri, 15 Jul 2022 14:29:12 +0200 Subject: [PATCH 014/215] Remove extra/outdated zenodo shield --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 02689202..4dacd5e3 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![GitHub Actions CI Status](https://github.com/nf-core/smrnaseq/workflows/nf-core%20CI/badge.svg)](https://github.com/nf-core/smrnaseq/actions?query=workflow%3A%22nf-core+CI%22) [![GitHub Actions Linting Status](https://github.com/nf-core/smrnaseq/workflows/nf-core%20linting/badge.svg)](https://github.com/nf-core/smrnaseq/actions?query=workflow%3A%22nf-core+linting%22) [![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?logo=Amazon%20AWS)](https://nf-co.re/smrnaseq/results) -[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8)](https://doi.org/10.5281/zenodo.4956678) +[![DOI](https://zenodo.org/badge/140590861.svg)](https://zenodo.org/badge/latestdoi/140590861) [![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A521.10.3-23aa62.svg)](https://www.nextflow.io/) [![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?logo=anaconda)](https://docs.conda.io/en/latest/) @@ -15,7 +15,7 @@ [![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?logo=twitter)](https://twitter.com/nf_core) [![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?logo=youtube)](https://www.youtube.com/c/nf-core) -[![DOI](https://zenodo.org/badge/140590861.svg)](https://zenodo.org/badge/latestdoi/140590861) + ## Introduction From f6ad4c38349550f946d058c81db701b943c82d5b Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Fri, 15 Jul 2022 18:41:51 +0000 Subject: [PATCH 015/215] [automated] Fix linting with Prettier --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 4dacd5e3..f7c7dbc0 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,6 @@ [![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?logo=twitter)](https://twitter.com/nf_core) [![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?logo=youtube)](https://www.youtube.com/c/nf-core) - - ## Introduction **nf-core/smrnaseq** is a bioinformatics best-practice analysis pipeline for Small RNA-Seq Best Practice Analysis Pipeline. From 415d7a3d00946a3fd1f166da395bff247aa11f41 Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Tue, 30 Aug 2022 13:41:33 +0000 Subject: [PATCH 016/215] Template update for nf-core/tools version 2.5 --- .editorconfig | 2 +- .github/PULL_REQUEST_TEMPLATE.md | 3 +- .github/workflows/ci.yml | 23 ++------ .github/workflows/linting.yml | 38 +++++++++++-- CHANGELOG.md | 2 +- CITATION.cff | 56 +++++++++++++++++++ README.md | 21 +++---- assets/email_template.txt | 1 - bin/check_samplesheet.py | 41 +++++++------- conf/base.config | 5 ++ docs/usage.md | 12 ++-- lib/WorkflowMain.groovy | 9 ++- lib/WorkflowSmrnaseq.groovy | 5 +- main.nf | 2 +- modules.json | 22 +++++--- .../templates/dumpsoftwareversions.py | 14 +++-- nextflow.config | 23 +++++++- 17 files changed, 186 insertions(+), 93 deletions(-) create mode 100644 CITATION.cff diff --git a/.editorconfig b/.editorconfig index b6b31907..b78de6e6 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,7 +8,7 @@ trim_trailing_whitespace = true indent_size = 4 indent_style = space -[*.{md,yml,yaml,html,css,scss,js}] +[*.{md,yml,yaml,html,css,scss,js,cff}] indent_size = 2 # These files are edited and tested upstream in nf-core/modules diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d103b361..cf3fb13d 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -15,8 +15,7 @@ Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/smrn - [ ] This comment contains a description of changes (with reason). - [ ] If you've fixed a bug or added code that should be tested, add tests! - - [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/smrnaseq/tree/master/.github/CONTRIBUTING.md) - - [ ] If necessary, also make a PR on the nf-core/smrnaseq _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. +- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/smrnaseq/tree/master/.github/CONTRIBUTING.md)- [ ] If necessary, also make a PR on the nf-core/smrnaseq _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. - [ ] Make sure your code lints (`nf-core lint`). - [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). - [ ] Usage Documentation in `docs/usage.md` is updated. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3638a64b..00c9d511 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,6 @@ on: env: NXF_ANSI_LOG: false - CAPSULE_LOG: none jobs: test: @@ -20,27 +19,17 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - # Nextflow versions - include: - # Test pipeline minimum Nextflow version - - NXF_VER: "21.10.3" - NXF_EDGE: "" - # Test latest edge release of Nextflow - - NXF_VER: "" - NXF_EDGE: "1" + NXF_VER: + - "21.10.3" + - "latest-everything" steps: - name: Check out pipeline code uses: actions/checkout@v2 - name: Install Nextflow - env: - NXF_VER: ${{ matrix.NXF_VER }} - # Uncomment only if the edge release is more recent than the latest stable release - # See https://github.com/nextflow-io/nextflow/issues/2467 - # NXF_EDGE: ${{ matrix.NXF_EDGE }} - run: | - wget -qO- get.nextflow.io | bash - sudo mv nextflow /usr/local/bin/ + uses: nf-core/setup-nextflow@v1 + with: + version: "${{ matrix.NXF_VER }}" - name: Run pipeline with test data # TODO nf-core: You can customise CI pipeline run tests as required diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 77358dee..8a5ce69b 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -35,6 +35,36 @@ jobs: - name: Run Prettier --check run: prettier --check ${GITHUB_WORKSPACE} + PythonBlack: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Check code lints with Black + uses: psf/black@stable + + # If the above check failed, post a comment on the PR explaining the failure + - name: Post PR comment + if: failure() + uses: mshick/add-pr-comment@v1 + with: + message: | + ## Python linting (`black`) is failing + + To keep the code consistent with lots of contributors, we run automated code consistency checks. + To fix this CI test, please run: + + * Install [`black`](https://black.readthedocs.io/en/stable/): `pip install black` + * Fix formatting errors in your pipeline: `black .` + + Once you push these changes the test should pass, and you can hide this comment :+1: + + We highly recommend setting up Black in your code editor so that this formatting is done automatically on save. Ask about it on Slack for help! + + Thanks again for your contribution! + repo-token: ${{ secrets.GITHUB_TOKEN }} + allow-repeats: false + nf-core: runs-on: ubuntu-latest steps: @@ -42,15 +72,11 @@ jobs: uses: actions/checkout@v2 - name: Install Nextflow - env: - CAPSULE_LOG: none - run: | - wget -qO- get.nextflow.io | bash - sudo mv nextflow /usr/local/bin/ + uses: nf-core/setup-nextflow@v1 - uses: actions/setup-python@v3 with: - python-version: "3.6" + python-version: "3.7" architecture: "x64" - name: Install dependencies diff --git a/CHANGELOG.md b/CHANGELOG.md index 82501771..c54766b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 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). -## v2.0.0 - [date] +## v2.1.0dev - [date] Initial release of nf-core/smrnaseq, created with the [nf-core](https://nf-co.re/) template. diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 00000000..4533e2f2 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,56 @@ +cff-version: 1.2.0 +message: "If you use `nf-core tools` in your work, please cite the `nf-core` publication" +authors: + - family-names: Ewels + given-names: Philip + - family-names: Peltzer + given-names: Alexander + - family-names: Fillinger + given-names: Sven + - family-names: Patel + given-names: Harshil + - family-names: Alneberg + given-names: Johannes + - family-names: Wilm + given-names: Andreas + - family-names: Ulysse Garcia + given-names: Maxime + - family-names: Di Tommaso + given-names: Paolo + - family-names: Nahnsen + given-names: Sven +title: "The nf-core framework for community-curated bioinformatics pipelines." +version: 2.4.1 +doi: 10.1038/s41587-020-0439-x +date-released: 2022-05-16 +url: https://github.com/nf-core/tools +prefered-citation: + type: article + authors: + - family-names: Ewels + given-names: Philip + - family-names: Peltzer + given-names: Alexander + - family-names: Fillinger + given-names: Sven + - family-names: Patel + given-names: Harshil + - family-names: Alneberg + given-names: Johannes + - family-names: Wilm + given-names: Andreas + - family-names: Ulysse Garcia + given-names: Maxime + - family-names: Di Tommaso + given-names: Paolo + - family-names: Nahnsen + given-names: Sven + doi: 10.1038/s41587-020-0439-x + journal: nature biotechnology + start: 276 + end: 278 + title: "The nf-core framework for community-curated bioinformatics pipelines." + issue: 3 + volume: 38 + year: 2020 + url: https://dx.doi.org/10.1038/s41587-020-0439-x diff --git a/README.md b/README.md index 1109375e..166d0429 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,14 @@ # ![nf-core/smrnaseq](docs/images/nf-core-smrnaseq_logo_light.png#gh-light-mode-only) ![nf-core/smrnaseq](docs/images/nf-core-smrnaseq_logo_dark.png#gh-dark-mode-only) -[![GitHub Actions CI Status](https://github.com/nf-core/smrnaseq/workflows/nf-core%20CI/badge.svg)](https://github.com/nf-core/smrnaseq/actions?query=workflow%3A%22nf-core+CI%22) -[![GitHub Actions Linting Status](https://github.com/nf-core/smrnaseq/workflows/nf-core%20linting/badge.svg)](https://github.com/nf-core/smrnaseq/actions?query=workflow%3A%22nf-core+linting%22) -[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?logo=Amazon%20AWS)](https://nf-co.re/smrnaseq/results) -[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8)](https://doi.org/10.5281/zenodo.XXXXXXX) +[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/smrnaseq/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) [![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A521.10.3-23aa62.svg)](https://www.nextflow.io/) -[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?logo=anaconda)](https://docs.conda.io/en/latest/) -[![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?logo=docker)](https://www.docker.com/) -[![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg)](https://sylabs.io/docs/) +[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/) +[![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/) +[![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/) [![Launch on Nextflow Tower](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Nextflow%20Tower-%234256e7)](https://tower.nf/launch?pipeline=https://github.com/nf-core/smrnaseq) -[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23smrnaseq-4A154B?logo=slack)](https://nfcore.slack.com/channels/smrnaseq) -[![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?logo=twitter)](https://twitter.com/nf_core) -[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?logo=youtube)](https://www.youtube.com/c/nf-core) +[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23smrnaseq-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/smrnaseq)[![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?labelColor=000000&logo=twitter)](https://twitter.com/nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core) ## Introduction @@ -25,7 +20,7 @@ The pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool -On release, automated continuous integration tests run the pipeline on a full-sized dataset on the AWS cloud infrastructure. This ensures that the pipeline runs on AWS, has sensible resource allocation defaults set to run on real-world datasets, and permits the persistent storage of results to benchmark between pipeline releases and other analysis sources. The results obtained from the full-sized test can be viewed on the [nf-core website](https://nf-co.re/smrnaseq/results). +On release, automated continuous integration tests run the pipeline on a full-sized dataset on the AWS cloud infrastructure. This ensures that the pipeline runs on AWS, has sensible resource allocation defaults set to run on real-world datasets, and permits the persistent storage of results to benchmark between pipeline releases and other analysis sources.The results obtained from the full-sized test can be viewed on the [nf-core website](https://nf-co.re/smrnaseq/results). ## Pipeline summary @@ -42,7 +37,7 @@ On release, automated continuous integration tests run the pipeline on a full-si 3. Download the pipeline and test it on a minimal dataset with a single command: - ```console + ```bash nextflow run nf-core/smrnaseq -profile test,YOURPROFILE --outdir ``` @@ -57,7 +52,7 @@ On release, automated continuous integration tests run the pipeline on a full-si - ```console + ```bash nextflow run nf-core/smrnaseq --input samplesheet.csv --outdir --genome GRCh37 -profile ``` diff --git a/assets/email_template.txt b/assets/email_template.txt index 6e8b6393..654e78db 100644 --- a/assets/email_template.txt +++ b/assets/email_template.txt @@ -6,7 +6,6 @@ `._,._,' nf-core/smrnaseq v${version} ---------------------------------------------------- - Run Name: $runName <% if (success){ diff --git a/bin/check_samplesheet.py b/bin/check_samplesheet.py index 3652c63c..9a8b8962 100755 --- a/bin/check_samplesheet.py +++ b/bin/check_samplesheet.py @@ -11,7 +11,6 @@ from collections import Counter from pathlib import Path - logger = logging.getLogger() @@ -79,13 +78,15 @@ def validate_and_transform(self, row): def _validate_sample(self, row): """Assert that the sample name exists and convert spaces to underscores.""" - assert len(row[self._sample_col]) > 0, "Sample input is required." + if len(row[self._sample_col]) <= 0: + raise AssertionError("Sample input is required.") # Sanitize samples slightly. row[self._sample_col] = row[self._sample_col].replace(" ", "_") def _validate_first(self, row): """Assert that the first FASTQ entry is non-empty and has the right format.""" - assert len(row[self._first_col]) > 0, "At least the first FASTQ file is required." + if len(row[self._first_col]) <= 0: + raise AssertionError("At least the first FASTQ file is required.") self._validate_fastq_format(row[self._first_col]) def _validate_second(self, row): @@ -97,36 +98,34 @@ def _validate_pair(self, row): """Assert that read pairs have the same file extension. Report pair status.""" if row[self._first_col] and row[self._second_col]: row[self._single_col] = False - assert ( - Path(row[self._first_col]).suffixes[-2:] == Path(row[self._second_col]).suffixes[-2:] - ), "FASTQ pairs must have the same file extensions." + if Path(row[self._first_col]).suffixes[-2:] != Path(row[self._second_col]).suffixes[-2:]: + raise AssertionError("FASTQ pairs must have the same file extensions.") else: row[self._single_col] = True def _validate_fastq_format(self, filename): """Assert that a given filename has one of the expected FASTQ extensions.""" - assert any(filename.endswith(extension) for extension in self.VALID_FORMATS), ( - f"The FASTQ file has an unrecognized extension: {filename}\n" - f"It should be one of: {', '.join(self.VALID_FORMATS)}" - ) + if not any(filename.endswith(extension) for extension in self.VALID_FORMATS): + raise AssertionError( + f"The FASTQ file has an unrecognized extension: {filename}\n" + f"It should be one of: {', '.join(self.VALID_FORMATS)}" + ) def validate_unique_samples(self): """ Assert that the combination of sample name and FASTQ filename is unique. - In addition to the validation, also rename the sample if more than one sample, - FASTQ file combination exists. + In addition to the validation, also rename all samples to have a suffix of _T{n}, where n is the + number of times the same sample exist, but with different FASTQ files, e.g., multiple runs per experiment. """ - assert len(self._seen) == len(self.modified), "The pair of sample name and FASTQ must be unique." - if len({pair[0] for pair in self._seen}) < len(self._seen): - counts = Counter(pair[0] for pair in self._seen) - seen = Counter() - for row in self.modified: - sample = row[self._sample_col] - seen[sample] += 1 - if counts[sample] > 1: - row[self._sample_col] = f"{sample}_T{seen[sample]}" + if len(self._seen) != len(self.modified): + raise AssertionError("The pair of sample name and FASTQ must be unique.") + seen = Counter() + for row in self.modified: + sample = row[self._sample_col] + seen[sample] += 1 + row[self._sample_col] = f"{sample}_T{seen[sample]}" def read_head(handle, num_lines=10): diff --git a/conf/base.config b/conf/base.config index 23890a7e..6f4a15a6 100644 --- a/conf/base.config +++ b/conf/base.config @@ -26,6 +26,11 @@ process { // adding in your local modules too. // TODO nf-core: Customise requirements for specific processes. // See https://www.nextflow.io/docs/latest/config.html#config-process-selectors + withLabel:process_single { + cpus = { check_max( 1 , 'cpus' ) } + memory = { check_max( 6.GB * task.attempt, 'memory' ) } + time = { check_max( 4.h * task.attempt, 'time' ) } + } withLabel:process_low { cpus = { check_max( 2 * task.attempt, 'cpus' ) } memory = { check_max( 12.GB * task.attempt, 'memory' ) } diff --git a/docs/usage.md b/docs/usage.md index 08a222a9..b75cbc81 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -12,7 +12,7 @@ You will need to create a samplesheet with information about the samples you would like to analyse before running the pipeline. Use this parameter to specify its location. It has to be a comma-separated file with 3 columns, and a header row as shown in the examples below. -```console +```bash --input '[path to samplesheet file]' ``` @@ -56,7 +56,7 @@ An [example samplesheet](../assets/samplesheet.csv) has been provided with the p The typical command for running the pipeline is as follows: -```console +```bash nextflow run nf-core/smrnaseq --input samplesheet.csv --outdir --genome GRCh37 -profile docker ``` @@ -64,9 +64,9 @@ This will launch the pipeline with the `docker` configuration profile. See below Note that the pipeline will create the following files in your working directory: -```console +```bash work # Directory containing the nextflow working files - # Finished results in specified location (defined with --outdir) + # Finished results in specified location (defined with --outdir) .nextflow_log # Log file from Nextflow # Other nextflow hidden files, eg. history of pipeline runs and old logs. ``` @@ -75,7 +75,7 @@ work # Directory containing the nextflow working files When you run the above command, Nextflow automatically pulls the pipeline code from GitHub and stores it as a cached version. When running the pipeline after this, it will always use the cached version if available - even if the pipeline has been updated since. To make sure that you're running the latest version of the pipeline, make sure that you regularly update the cached version of the pipeline: -```console +```bash nextflow pull nf-core/smrnaseq ``` @@ -251,6 +251,6 @@ Some HPC setups also allow you to run nextflow within a cluster job submitted yo In some cases, the Nextflow Java virtual machines can start to request a large amount of memory. We recommend adding the following line to your environment to limit this (typically in `~/.bashrc` or `~./bash_profile`): -```console +```bash NXF_OPTS='-Xms1g -Xmx4g' ``` diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 74b5820a..417fde67 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -59,6 +59,7 @@ class WorkflowMain { } // Print parameter summary log to screen + log.info paramsSummaryLog(workflow, params, log) // Check that a -profile or Nextflow config has been provided to run the pipeline @@ -78,17 +79,15 @@ class WorkflowMain { System.exit(1) } } - // // Get attribute from genome config file e.g. fasta // - public static String getGenomeAttribute(params, attribute) { - def val = '' + public static Object getGenomeAttribute(params, attribute) { if (params.genomes && params.genome && params.genomes.containsKey(params.genome)) { if (params.genomes[ params.genome ].containsKey(attribute)) { - val = params.genomes[ params.genome ][ attribute ] + return params.genomes[ params.genome ][ attribute ] } } - return val + return null } } diff --git a/lib/WorkflowSmrnaseq.groovy b/lib/WorkflowSmrnaseq.groovy index f33ecd7e..5bc00333 100755 --- a/lib/WorkflowSmrnaseq.groovy +++ b/lib/WorkflowSmrnaseq.groovy @@ -10,6 +10,7 @@ class WorkflowSmrnaseq { public static void initialise(params, log) { genomeExistsError(params, log) + if (!params.fasta) { log.error "Genome fasta file not specified with e.g. '--fasta genome.fa' or via a detectable config file." System.exit(1) @@ -41,9 +42,7 @@ class WorkflowSmrnaseq { yaml_file_text += "data: |\n" yaml_file_text += "${summary_section}" return yaml_file_text - } - - // + }// // Exit pipeline if incorrect --genome key provided // private static void genomeExistsError(params, log) { diff --git a/main.nf b/main.nf index 5b057014..a7e6c457 100644 --- a/main.nf +++ b/main.nf @@ -4,7 +4,7 @@ nf-core/smrnaseq ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Github : https://github.com/nf-core/smrnaseq - Website: https://nf-co.re/smrnaseq +Website: https://nf-co.re/smrnaseq Slack : https://nfcore.slack.com/channels/smrnaseq ---------------------------------------------------------------------------------------- */ diff --git a/modules.json b/modules.json index b7e26668..81f0ce77 100644 --- a/modules.json +++ b/modules.json @@ -3,14 +3,20 @@ "homePage": "https://github.com/nf-core/smrnaseq", "repos": { "nf-core/modules": { - "custom/dumpsoftwareversions": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d" - }, - "fastqc": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d" - }, - "multiqc": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d" + "git_url": "https://github.com/nf-core/modules.git", + "modules": { + "custom/dumpsoftwareversions": { + "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d", + "branch": "master" + }, + "fastqc": { + "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d", + "branch": "master" + }, + "multiqc": { + "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d", + "branch": "master" + } } } } diff --git a/modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py b/modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py index d1390392..787bdb7b 100644 --- a/modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py +++ b/modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py @@ -1,9 +1,10 @@ #!/usr/bin/env python -import yaml import platform from textwrap import dedent +import yaml + def _make_versions_html(versions): html = [ @@ -58,11 +59,12 @@ def _make_versions_html(versions): for process, process_versions in versions_by_process.items(): module = process.split(":")[-1] try: - assert versions_by_module[module] == process_versions, ( - "We assume that software versions are the same between all modules. " - "If you see this error-message it means you discovered an edge-case " - "and should open an issue in nf-core/tools. " - ) + if versions_by_module[module] != process_versions: + raise AssertionError( + "We assume that software versions are the same between all modules. " + "If you see this error-message it means you discovered an edge-case " + "and should open an issue in nf-core/tools. " + ) except KeyError: versions_by_module[module] = process_versions diff --git a/nextflow.config b/nextflow.config index d6c8e23c..e4a50caa 100644 --- a/nextflow.config +++ b/nextflow.config @@ -13,11 +13,11 @@ params { // Input options input = null + // References genome = null igenomes_base = 's3://ngi-igenomes/igenomes' igenomes_ignore = false - // MultiQC options multiqc_config = null multiqc_title = null @@ -37,6 +37,7 @@ params { schema_ignore_params = 'genomes' enable_conda = false + // Config options custom_config_version = 'master' custom_config_base = "https://raw.githubusercontent.com/nf-core/configs/${params.custom_config_version}" @@ -45,6 +46,7 @@ params { config_profile_url = null config_profile_name = null + // Max resource options // Defaults only, expecting to be overwritten max_memory = '128.GB' @@ -72,6 +74,7 @@ try { // } + profiles { debug { process.beforeScript = 'echo $HOSTNAME' } conda { @@ -82,6 +85,15 @@ profiles { shifter.enabled = false charliecloud.enabled = false } + mamba { + params.enable_conda = true + conda.useMamba = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } docker { docker.enabled = true docker.userEmulation = true @@ -119,10 +131,16 @@ profiles { podman.enabled = false shifter.enabled = false } + gitpod { + executor.name = 'local' + executor.cpus = 16 + executor.memory = 60.GB + } test { includeConfig 'conf/test.config' } test_full { includeConfig 'conf/test_full.config' } } + // Load igenomes.config if required if (!params.igenomes_ignore) { includeConfig 'conf/igenomes.config' @@ -130,6 +148,7 @@ if (!params.igenomes_ignore) { params.genomes = [:] } + // Export these variables to prevent local Python/R libraries from conflicting with those in the container // The JULIA depot path has been adjusted to a fixed path `/usr/local/share/julia` that needs to be used for packages in the container. // See https://apeltzer.github.io/post/03-julia-lang-nextflow/ for details on that. Once we have a common agreement on where to keep Julia packages, this is adjustable. @@ -169,7 +188,7 @@ manifest { description = 'Small RNA-Seq Best Practice Analysis Pipeline.' mainScript = 'main.nf' nextflowVersion = '!>=21.10.3' - version = '2.0.0' + version = '2.1.0dev' } // Load modules.config for DSL2 module specific options From 37885c5491e82a8fa3afddd37a58315d5091e24a Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Thu, 1 Sep 2022 13:33:01 +0000 Subject: [PATCH 017/215] Template update for nf-core/tools version 2.5.1 --- bin/check_samplesheet.py | 9 ++++++--- pyproject.toml | 10 ++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 pyproject.toml diff --git a/bin/check_samplesheet.py b/bin/check_samplesheet.py index 9a8b8962..11b15572 100755 --- a/bin/check_samplesheet.py +++ b/bin/check_samplesheet.py @@ -98,7 +98,9 @@ def _validate_pair(self, row): """Assert that read pairs have the same file extension. Report pair status.""" if row[self._first_col] and row[self._second_col]: row[self._single_col] = False - if Path(row[self._first_col]).suffixes[-2:] != Path(row[self._second_col]).suffixes[-2:]: + first_col_suffix = Path(row[self._first_col]).suffixes[-2:] + second_col_suffix = Path(row[self._second_col]).suffixes[-2:] + if first_col_suffix != second_col_suffix: raise AssertionError("FASTQ pairs must have the same file extensions.") else: row[self._single_col] = True @@ -157,7 +159,7 @@ def sniff_format(handle): handle.seek(0) sniffer = csv.Sniffer() if not sniffer.has_header(peek): - logger.critical(f"The given sample sheet does not appear to contain a header.") + logger.critical("The given sample sheet does not appear to contain a header.") sys.exit(1) dialect = sniffer.sniff(peek) return dialect @@ -195,7 +197,8 @@ def check_samplesheet(file_in, file_out): reader = csv.DictReader(in_handle, dialect=sniff_format(in_handle)) # Validate the existence of the expected header columns. if not required_columns.issubset(reader.fieldnames): - logger.critical(f"The sample sheet **must** contain the column headers: {', '.join(required_columns)}.") + req_cols = ", ".join(required_columns) + logger.critical(f"The sample sheet **must** contain these column headers: {req_cols}.") sys.exit(1) # Validate each row. checker = RowChecker() diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..0d62beb6 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,10 @@ +# Config file for Python. Mostly used to configure linting of bin/check_samplesheet.py with Black. +# Should be kept the same as nf-core/tools to avoid fighting with template synchronisation. +[tool.black] +line-length = 120 +target_version = ["py37", "py38", "py39", "py310"] + +[tool.isort] +profile = "black" +known_first_party = ["nf_core"] +multi_line_output = 3 From 2a8d9fbd2a30dc3abbfdd87cea9abfa814cac601 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Tue, 6 Sep 2022 13:03:00 +0100 Subject: [PATCH 018/215] Use snake_case for mirGeneDB parameters --- CHANGELOG.md | 10 +++++----- docs/usage.md | 12 ++++++------ modules/local/mirtop_quant.nf | 8 ++++---- modules/local/parse_fasta_mirna.nf | 4 ++-- nextflow.config | 10 +++++----- nextflow_schema.json | 26 +++++++++++++------------- workflows/smrnaseq.nf | 12 ++++++------ 7 files changed, 41 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c100756d..ce1f3077 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,11 +22,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | Old parameter | New parameter | | ------------- | ------------------------ | -| | `--mirGeneDB` | -| | `--mirGeneDB_species` | -| | `--mirGeneDB_gff` | -| | `--mirGeneDB_mature` | -| | `--mirGeneDB_hairpin` | +| | `--mirgenedb` | +| | `--mirgenedb_species` | +| | `--mirgenedb_gff` | +| | `--mirgenedb_mature` | +| | `--mirgenedb_hairpin` | | | `--contamination_filter` | | | `--rrna` | | | `--trna` | diff --git a/docs/usage.md b/docs/usage.md index 475dc9dc..f42023a1 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -18,9 +18,9 @@ This option indicates the experimental protocol used for the sample preparation. :warning: At least the `custom` protocol has to be specified, otherwise the pipeline won't run. -### `mirtrace_species or mirGeneDB_species` +### `mirtrace_species` or `mirgenedb_species` -It should point to the 3-letter species name used by `miRBase`, or `MirGeneDB`. Note the difference in case for the two databases. +It should point to the 3-letter species name used by [miRBase](https://www.mirbase.org/help/genome_summary.shtml) or MirGeneDB. Note the difference in case for the two databases. ### miRNA related files @@ -30,11 +30,11 @@ Different parameters can be set for the two supported datbases. By default `miRB - `mature`: points to the FASTA file of mature miRNA sequences. `https://mirbase.org/ftp/CURRENT/mature.fa.gz` - `hairpin`: points to the FASTA file of precursor miRNA sequences. `https://mirbase.org/ftp/CURRENT/hairpin.fa.gz` -If `MirGeneDB` should be used instead it needs to be specified using `--mirGeneDB` and use the parameters below . +If MirGeneDB should be used instead it needs to be specified using `--mirgenedb` and use the parameters below . -- `mirGeneDB_gff`: The data can not be downloaded automatically, thus the user needs to supply the gff file for either his species, or all species downloaded from `https://mirgenedb.org/download`. The total set will automatically be subsetted to the species specified with `mirGeneDB_species`. -- `mirGeneDB_mature`: points to the FASTA file of mature miRNA sequences. Download from `https://mirgenedb.org/download`. -- `mirGeneDB_hairpin`: points to the FASTA file of precursor miRNA sequences. Download from `https://mirgenedb.org/download`. Note that `MirGeneDB` does not have a dedicated `hairpin` file, but the `Precursor sequences` are to be used. +- `mirgenedb_gff`: The data can not be downloaded automatically, thus the user needs to supply the gff file for either his species, or all species downloaded from `https://mirgenedb.org/download`. The total set will automatically be subsetted to the species specified with `--mirgenedb_species`. +- `mirgenedb_mature`: points to the FASTA file of mature miRNA sequences. Download from `https://mirgenedb.org/download`. +- `mirgenedb_hairpin`: points to the FASTA file of precursor miRNA sequences. Download from `https://mirgenedb.org/download`. Note that MirGeneDB does not have a dedicated `hairpin` file, but the `Precursor sequences` are to be used. ### Genome diff --git a/modules/local/mirtop_quant.nf b/modules/local/mirtop_quant.nf index ffbfc0a0..6f903add 100644 --- a/modules/local/mirtop_quant.nf +++ b/modules/local/mirtop_quant.nf @@ -11,7 +11,7 @@ process MIRTOP_QUANT { path hairpin path gtf - //if (!params.mirGeneDB) {params.filterSpecies = params.mirtrace_species} else {params.filterSpecies = params.mirGeneDB_species} + //if (!params.mirgenedb) {params.filter_species = params.mirtrace_species} else {params.filter_species = params.mirgenedb_species} output: path "mirtop/mirtop.gff" @@ -22,9 +22,9 @@ process MIRTOP_QUANT { script: """ - mirtop gff --hairpin $hairpin --gtf $gtf -o mirtop --sps $params.filterSpecies ./bams/* - mirtop counts --hairpin $hairpin --gtf $gtf -o mirtop --sps $params.filterSpecies --add-extra --gff mirtop/mirtop.gff - mirtop export --format isomir --hairpin $hairpin --gtf $gtf --sps $params.filterSpecies -o mirtop mirtop/mirtop.gff + mirtop gff --hairpin $hairpin --gtf $gtf -o mirtop --sps $params.filter_species ./bams/* + mirtop counts --hairpin $hairpin --gtf $gtf -o mirtop --sps $params.filter_species --add-extra --gff mirtop/mirtop.gff + mirtop export --format isomir --hairpin $hairpin --gtf $gtf --sps $params.filter_species -o mirtop mirtop/mirtop.gff mirtop stats mirtop/mirtop.gff --out mirtop/stats mv mirtop/stats/mirtop_stats.log mirtop/stats/full_mirtop_stats.log diff --git a/modules/local/parse_fasta_mirna.nf b/modules/local/parse_fasta_mirna.nf index 18b51066..27caf42b 100644 --- a/modules/local/parse_fasta_mirna.nf +++ b/modules/local/parse_fasta_mirna.nf @@ -9,7 +9,7 @@ process PARSE_FASTA_MIRNA { input: path fasta - //if (!params.mirGeneDB) {params.filterSpecies = params.mirtrace_species} else {params.filterSpecies = params.mirGeneDB_species} + //if (!params.mirgenedb) {params.filter_species = params.mirtrace_species} else {params.filter_species = params.mirgenedb_species} output: path '*_igenome.fa', emit: parsed_fasta @@ -29,7 +29,7 @@ process PARSE_FASTA_MIRNA { # TODO perl -ane 's/[ybkmrsw]/N/ig;print;' \${FASTA}_parsed_tmp.fa > \${FASTA}_parsed.fa sed -i 's/\s.*//' \${FASTA}_parsed.fa - seqkit grep -r --pattern \".*${params.filterSpecies}-.*\" \${FASTA}_parsed.fa > \${FASTA}_sps.fa + seqkit grep -r --pattern \".*${params.filter_species}-.*\" \${FASTA}_parsed.fa > \${FASTA}_sps.fa seqkit seq --rna2dna \${FASTA}_sps.fa > \${FASTA}_igenome.fa cat <<-END_VERSIONS > versions.yml diff --git a/nextflow.config b/nextflow.config index fe98b39c..08978844 100644 --- a/nextflow.config +++ b/nextflow.config @@ -25,11 +25,11 @@ params { mirtrace_species = null mature = "https://mirbase.org/ftp/CURRENT/mature.fa.gz" hairpin = "https://mirbase.org/ftp/CURRENT/hairpin.fa.gz" - mirGeneDB = false - mirGeneDB_mature = "/Users/chriskub/Downloads/ALL-mat.fas" - mirGeneDB_hairpin = "/Users/chriskub/Downloads/ALL-pre.fas" - mirGeneDB_gff = "/Users/chriskub/Downloads/ALL.gff" - mirGeneDB_species = null + mirgenedb = false + mirgenedb_mature = "/Users/chriskub/Downloads/ALL-mat.fas" + mirgenedb_hairpin = "/Users/chriskub/Downloads/ALL-pre.fas" + mirgenedb_gff = "/Users/chriskub/Downloads/ALL.gff" + mirgenedb_species = null // Trimming options clip_r1 = 0 diff --git a/nextflow_schema.json b/nextflow_schema.json index 77faa9ba..2ca88862 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -62,22 +62,22 @@ "fa_icon": "fas fa-book", "help_text": "If using a reference genome configured in the pipeline using iGenomes, use this parameter to give the ID for the reference. This is then used to build the full paths for all required reference genome files e.g. `--genome GRCh38`. \n\nSee the [nf-core website docs](https://nf-co.re/usage/reference_genomes) for more details." }, - "mirGeneDB": { + "mirgenedb": { "type": "boolean", - "description": "Boolean wether mirGeneDB should be used instead of miRBase", - "help_text": "This allows you to use mirGeneDB instead of miRBase as the database. \n Note that you will need to set the additional flags `--mirGeneDB_species`, `--mirGeneDB_gff`, `--mirGeneDB_mature` and `--mirGeneDB_hairpin`", + "description": "Boolean whether MirGeneDB should be used instead of miRBase", + "help_text": "This allows you to use MirGeneDB instead of miRBase as the database. \n Note that you will need to set the additional flags `--mirgenedb_species`, `--mirgenedb_gff`, `--mirgenedb_mature` and `--mirgenedb_hairpin`", "default": "false" }, "mirtrace_species": { "type": "string", "description": "Species for miRTrace.", - "help_text": "This is automatically set when using `--genome`. Example values: `hsa`, `mmu`...\n Note that mirTrace relies on miRBase for its species reference. See available references [here](https://mirbase.org/ftp/CURRENT/genomes/).", + "help_text": "This is automatically set when using `--genome`. Example values: `hsa`, `mmu`...\n Note that mirTrace relies on miRBase for its species reference. See available references [here](https://www.mirbase.org/help/genome_summary.shtml).", "fa_icon": "fas fa-journal-whills" }, - "mirGeneDB_species": { + "mirgenedb_species": { "type": "string", - "description": "Species of mirGeneDB.", - "help_text": "This replaces the value of `--mirtrace_species` if `--mirGeneDB` is used. \n Note the difference in case for species names used in MirGeneDB and miRBase." + "description": "Species of MirGeneDB.", + "help_text": "This replaces the value of `--mirtrace_species` if `--mirgenedb` is used. \n Note the difference in case for species names used in MirGeneDB and miRBase." }, "fasta": { "type": "string", @@ -91,10 +91,10 @@ "help_text": "miRBase `.gff3` file, typically downloaded from [`https://mirbase.org/ftp/CURRENT/genomes/`](https://mirbase.org/ftp/CURRENT/genomes/)\n\nIf using iGenomes with `--genome` this file will be downloaded from miRBase automatically during the pipeline run.\n\n", "fa_icon": "fas fa-address-book" }, - "mirGeneDB_gff": { + "mirgenedb_gff": { "type": "string", "description": "GFF/GTF file with coordinates positions of precursor and miRNAs.", - "help_text": "mirGeneDB `.gff3` file, typically downloaded from [`https://mirgenedb.org/download`]. This replaces the value of --mirna_gff if --mirGeneDB is used." + "help_text": "MirGeneDB `.gff3` file, typically downloaded from [`https://mirgenedb.org/download`]. This replaces the value of --mirna_gff if --mirgenedb is used." }, "mature": { "type": "string", @@ -103,9 +103,9 @@ "help_text": "Typically this will be the `mature.fa` file from miRBase. Can be given either as a plain text `.fa` file or a compressed `.gz` file.\n\nDefaults to the current miRBase release URL, from which the file will be downloaded.", "default": "https://mirbase.org/ftp/CURRENT/mature.fa.gz" }, - "mirGeneDB_mature": { + "mirgenedb_mature": { "type": "string", - "description": "Path to FASTA file with mirGeneDB mature miRNAs.", + "description": "Path to FASTA file with MirGeneDB mature miRNAs.", "help_text": "This file needs to be downloaded from [`https://mirgenedb.org/download`]. Can be given either as a plain text `.fa` file or a compressed `.gz` file." }, "hairpin": { @@ -115,10 +115,10 @@ "help_text": "Typically this will be the `mature.fa` file from miRBase. Can be given either as a plain text `.fa` file or a compressed `.gz` file.\n\nDefaults to the current miRBase release URL, from which the file will be downloaded.", "default": "https://mirbase.org/ftp/CURRENT/hairpin.fa.gz" }, - "mirGeneDB_hairpin": { + "mirgenedb_hairpin": { "type": "string", "description": "Path to FASTA file with miRNAs precursors.", - "help_text": "This file needs to be downloaded from [`https://mirgenedb.org/download`]. Can be given either as a plain text `.fa` file or a compressed `.gz` file.\nNote that mirGeneDB does not have a dedicated hairpin file. The equivalent is the `Precursor sequences`." + "help_text": "This file needs to be downloaded from [`https://mirgenedb.org/download`]. Can be given either as a plain text `.fa` file or a compressed `.gz` file.\nNote that MirGeneDB does not have a dedicated hairpin file. The equivalent is the `Precursor sequences`." }, "bowtie_indices": { "type": "string", diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index be455612..a32ef4d8 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -53,15 +53,15 @@ ch_multiqc_image = file("$projectDir/assets/smrnaseq_logo.png", checkIfE // // SUBWORKFLOW: Consisting of a mix of local and nf-core/modules // -if (!params.mirGeneDB) { +if (!params.mirgenedb) { if (params.mature) { reference_mature = file(params.mature, checkIfExists: true) } else { exit 1, "Mature miRNA fasta file not found: ${params.mature}" } if (params.hairpin) { reference_hairpin = file(params.hairpin, checkIfExists: true) } else { exit 1, "Hairpin miRNA fasta file not found: ${params.hairpin}" } - params.filterSpecies = params.mirtrace_species + params.filter_species = params.mirtrace_species } else { - if (params.mirGeneDB_mature) { reference_mature = file(params.mirGeneDB_mature, checkIfExists: true) } else { exit 1, "Mature miRNA fasta file not found: ${params.mirGeneDB_mature}" } - if (params.mirGeneDB_hairpin) { reference_hairpin = file(params.mirGeneDB_hairpin, checkIfExists: true) } else { exit 1, "Hairpin miRNA fasta file not found: ${params.mirGeneDB_hairpin}" } - if (params.mirGeneDB_gff) { mirna_gtf = file(params.mirGeneDB_gff, checkIfExists: true) } else { exit 1, "MirGeneDB gff file not found: ${params.mirGeneDB_gff}"} - params.filterSpecies = params.mirGeneDB_species + if (params.mirgenedb_mature) { reference_mature = file(params.mirgenedb_mature, checkIfExists: true) } else { exit 1, "Mature miRNA fasta file not found: ${params.mirgenedb_mature}" } + if (params.mirgenedb_hairpin) { reference_hairpin = file(params.mirgenedb_hairpin, checkIfExists: true) } else { exit 1, "Hairpin miRNA fasta file not found: ${params.mirgenedb_hairpin}" } + if (params.mirgenedb_gff) { mirna_gtf = file(params.mirgenedb_gff, checkIfExists: true) } else { exit 1, "MirGeneDB gff file not found: ${params.mirgenedb_gff}"} + params.filter_species = params.mirgenedb_species } include { INPUT_CHECK } from '../subworkflows/local/input_check' From 4d57a000a015cbe9a5112487fa4a181e58b4cc43 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Tue, 6 Sep 2022 13:27:29 +0100 Subject: [PATCH 019/215] Fix nf-core lint --- .github/PULL_REQUEST_TEMPLATE.md | 3 +- .github/workflows/ci.yml | 23 +++-------- .github/workflows/linting.yml | 39 +++++++++++++++--- .nf-core.yml | 9 +--- assets/email_template.txt | 1 - modules.json | 71 +++++++++++++++++++------------- pyproject.toml | 10 +++++ 7 files changed, 93 insertions(+), 63 deletions(-) create mode 100644 pyproject.toml diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d103b361..cf3fb13d 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -15,8 +15,7 @@ Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/smrn - [ ] This comment contains a description of changes (with reason). - [ ] If you've fixed a bug or added code that should be tested, add tests! - - [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/smrnaseq/tree/master/.github/CONTRIBUTING.md) - - [ ] If necessary, also make a PR on the nf-core/smrnaseq _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. +- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/smrnaseq/tree/master/.github/CONTRIBUTING.md)- [ ] If necessary, also make a PR on the nf-core/smrnaseq _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. - [ ] Make sure your code lints (`nf-core lint`). - [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). - [ ] Usage Documentation in `docs/usage.md` is updated. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 31a2a000..265fffee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,6 @@ on: env: NXF_ANSI_LOG: false - CAPSULE_LOG: none jobs: test: @@ -20,27 +19,17 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - # Nextflow versions - include: - # Test pipeline minimum Nextflow version - - NXF_VER: "21.10.3" - NXF_EDGE: "" - # Test latest edge release of Nextflow - - NXF_VER: "" - NXF_EDGE: "1" + NXF_VER: + - "21.10.3" + - "latest-everything" steps: - name: Check out pipeline code uses: actions/checkout@v2 - name: Install Nextflow - env: - NXF_VER: ${{ matrix.NXF_VER }} - # Uncomment only if the edge release is more recent than the latest stable release - # See https://github.com/nextflow-io/nextflow/issues/2467 - # NXF_EDGE: ${{ matrix.NXF_EDGE }} - run: | - wget -qO- get.nextflow.io | bash - sudo mv nextflow /usr/local/bin/ + uses: nf-core/setup-nextflow@v1 + with: + version: "${{ matrix.NXF_VER }}" - name: Run pipeline with test data run: | diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 8a092d87..8a5ce69b 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -35,6 +35,36 @@ jobs: - name: Run Prettier --check run: prettier --check ${GITHUB_WORKSPACE} + PythonBlack: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Check code lints with Black + uses: psf/black@stable + + # If the above check failed, post a comment on the PR explaining the failure + - name: Post PR comment + if: failure() + uses: mshick/add-pr-comment@v1 + with: + message: | + ## Python linting (`black`) is failing + + To keep the code consistent with lots of contributors, we run automated code consistency checks. + To fix this CI test, please run: + + * Install [`black`](https://black.readthedocs.io/en/stable/): `pip install black` + * Fix formatting errors in your pipeline: `black .` + + Once you push these changes the test should pass, and you can hide this comment :+1: + + We highly recommend setting up Black in your code editor so that this formatting is done automatically on save. Ask about it on Slack for help! + + Thanks again for your contribution! + repo-token: ${{ secrets.GITHUB_TOKEN }} + allow-repeats: false + nf-core: runs-on: ubuntu-latest steps: @@ -42,21 +72,18 @@ jobs: uses: actions/checkout@v2 - name: Install Nextflow - env: - CAPSULE_LOG: none - run: | - wget -qO- get.nextflow.io | bash - sudo mv nextflow /usr/local/bin/ + uses: nf-core/setup-nextflow@v1 - uses: actions/setup-python@v3 with: - python-version: "3.6" + python-version: "3.7" architecture: "x64" - name: Install dependencies run: | python -m pip install --upgrade pip pip install nf-core + - name: Run nf-core lint env: GITHUB_COMMENTS_URL: ${{ github.event.pull_request.comments_url }} diff --git a/.nf-core.yml b/.nf-core.yml index 9de90de2..b1a7f0e9 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,8 +1 @@ -repository_type: pipeline -lint: - files_unchanged: - - .github/workflows/linting.yml - - .github/workflows/branch.yml - - .github/workflows/ci.yml - - .github/workflows/linting.yml - - .github/workflows/linting_comment.yml +repository_type: pipeline \ No newline at end of file diff --git a/assets/email_template.txt b/assets/email_template.txt index 6e8b6393..654e78db 100644 --- a/assets/email_template.txt +++ b/assets/email_template.txt @@ -6,7 +6,6 @@ `._,._,' nf-core/smrnaseq v${version} ---------------------------------------------------- - Run Name: $runName <% if (success){ diff --git a/modules.json b/modules.json index 0b772f2e..49ac89e7 100644 --- a/modules.json +++ b/modules.json @@ -3,35 +3,48 @@ "homePage": "https://github.com/nf-core/smrnaseq", "repos": { "nf-core/modules": { - "cat/fastq": { - "git_sha": "9aadd9a6d3f5964476582319b3a1c54a3e3fe7c9" - }, - "custom/dumpsoftwareversions": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d" - }, - "fastqc": { - "git_sha": "49b18b1639f4f7104187058866a8fab33332bdfe" - }, - "multiqc": { - "git_sha": "08376da6843b14c82d84d444784c0b3635bb7fd5" - }, - "samtools/flagstat": { - "git_sha": "ecece498f10b47b7c9d06f53a310cea5811b4c5f" - }, - "samtools/idxstats": { - "git_sha": "ecece498f10b47b7c9d06f53a310cea5811b4c5f" - }, - "samtools/index": { - "git_sha": "897c33d5da084b61109500ee44c01da2d3e4e773" - }, - "samtools/sort": { - "git_sha": "897c33d5da084b61109500ee44c01da2d3e4e773" - }, - "samtools/stats": { - "git_sha": "ecece498f10b47b7c9d06f53a310cea5811b4c5f" - }, - "trimgalore": { - "git_sha": "85ec13ff1fc2196c5a507ea497de468101baabed" + "git_url": "https://github.com/nf-core/modules.git", + "modules": { + "cat/fastq": { + "branch": "master", + "git_sha": "9aadd9a6d3f5964476582319b3a1c54a3e3fe7c9" + }, + "custom/dumpsoftwareversions": { + "branch": "master", + "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d" + }, + "fastqc": { + "branch": "master", + "git_sha": "49b18b1639f4f7104187058866a8fab33332bdfe" + }, + "multiqc": { + "branch": "master", + "git_sha": "08376da6843b14c82d84d444784c0b3635bb7fd5" + }, + "samtools/flagstat": { + "branch": "master", + "git_sha": "ecece498f10b47b7c9d06f53a310cea5811b4c5f" + }, + "samtools/idxstats": { + "branch": "master", + "git_sha": "ecece498f10b47b7c9d06f53a310cea5811b4c5f" + }, + "samtools/index": { + "branch": "master", + "git_sha": "897c33d5da084b61109500ee44c01da2d3e4e773" + }, + "samtools/sort": { + "branch": "master", + "git_sha": "897c33d5da084b61109500ee44c01da2d3e4e773" + }, + "samtools/stats": { + "branch": "master", + "git_sha": "ecece498f10b47b7c9d06f53a310cea5811b4c5f" + }, + "trimgalore": { + "branch": "master", + "git_sha": "85ec13ff1fc2196c5a507ea497de468101baabed" + } } } } diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..0d62beb6 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,10 @@ +# Config file for Python. Mostly used to configure linting of bin/check_samplesheet.py with Black. +# Should be kept the same as nf-core/tools to avoid fighting with template synchronisation. +[tool.black] +line-length = 120 +target_version = ["py37", "py38", "py39", "py310"] + +[tool.isort] +profile = "black" +known_first_party = ["nf_core"] +multi_line_output = 3 From cbb18f1d6d8aaae819c5e88635aee0acc8809f12 Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Tue, 6 Sep 2022 12:35:01 +0000 Subject: [PATCH 020/215] [automated] Fix linting with Prettier --- .nf-core.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nf-core.yml b/.nf-core.yml index b1a7f0e9..3805dc81 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1 +1 @@ -repository_type: pipeline \ No newline at end of file +repository_type: pipeline From ed1ac84e9ce550b82a2f1a408eb28748b1f6bf1a Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Tue, 6 Sep 2022 13:40:52 +0100 Subject: [PATCH 021/215] Fix PythonBlack --- bin/check_samplesheet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/check_samplesheet.py b/bin/check_samplesheet.py index 00a4c93a..3ca65774 100755 --- a/bin/check_samplesheet.py +++ b/bin/check_samplesheet.py @@ -79,7 +79,7 @@ def check_samplesheet(file_in, file_out): ) ## Check sample name entries - sample, fastq_1 = lspl[: len(HEADER)] + sample, fastq_1 = lspl[: len(HEADER)] sample = sample.replace(" ", "_") if not sample: print_error("Sample entry has not been specified!", "Line", line) From 3bf9ab72a38b4e94372ed47808c42758c561a7c8 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Tue, 6 Sep 2022 13:50:44 +0100 Subject: [PATCH 022/215] Split out CI to parallelise --- .github/workflows/ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 265fffee..d0bd4ac8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,6 +22,9 @@ jobs: NXF_VER: - "21.10.3" - "latest-everything" + profile: + - "test" + - "test_no_genome" steps: - name: Check out pipeline code uses: actions/checkout@v2 @@ -33,5 +36,4 @@ jobs: - name: Run pipeline with test data run: | - nextflow run ${GITHUB_WORKSPACE} -profile test,docker --outdir ./results - nextflow run ${GITHUB_WORKSPACE} -profile test_no_genome,docker --outdir ./results + nextflow run ${GITHUB_WORKSPACE} -profile ${{ matrix.profile }},docker --outdir ./results From 05ae7d227c1bd64c009762e70e13faf5bf10cace Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Wed, 7 Sep 2022 16:34:06 +0100 Subject: [PATCH 023/215] Fix linting --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index ad773211..499134b1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) P. Ewels , C. Wang , R. Hammarén , L. Pantano +Copyright (c) P. Ewels, C. Wang, R. Hammarén, L. Pantano Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From eb60d8556ffcb29ab4e36d801890b90668fa2c86 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 12 Sep 2022 16:07:34 +0200 Subject: [PATCH 024/215] Update Modules before release 2.1.0 --- modules.json | 10 +++---- modules/nf-core/modules/cat/fastq/main.nf | 29 +++++++++++++++++++ .../custom/dumpsoftwareversions/main.nf | 8 ++--- .../templates/dumpsoftwareversions.py | 14 ++++----- modules/nf-core/modules/multiqc/main.nf | 9 +++--- modules/nf-core/modules/multiqc/meta.yml | 7 +++-- .../nf-core/modules/samtools/flagstat/main.nf | 4 +-- .../nf-core/modules/samtools/stats/main.nf | 8 ++--- 8 files changed, 60 insertions(+), 29 deletions(-) diff --git a/modules.json b/modules.json index 49ac89e7..d169ad11 100644 --- a/modules.json +++ b/modules.json @@ -7,11 +7,11 @@ "modules": { "cat/fastq": { "branch": "master", - "git_sha": "9aadd9a6d3f5964476582319b3a1c54a3e3fe7c9" + "git_sha": "b034029b59b1198075da8019074bc02051a6100e" }, "custom/dumpsoftwareversions": { "branch": "master", - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d" + "git_sha": "5e7b1ef9a5a2d9258635bcbf70fcf37dacd1b247" }, "fastqc": { "branch": "master", @@ -19,11 +19,11 @@ }, "multiqc": { "branch": "master", - "git_sha": "08376da6843b14c82d84d444784c0b3635bb7fd5" + "git_sha": "5587389874dac9c9953a2ab6f01d49af81969492" }, "samtools/flagstat": { "branch": "master", - "git_sha": "ecece498f10b47b7c9d06f53a310cea5811b4c5f" + "git_sha": "bbb99cb8d679555cc01c98766de7869f83283545" }, "samtools/idxstats": { "branch": "master", @@ -39,7 +39,7 @@ }, "samtools/stats": { "branch": "master", - "git_sha": "ecece498f10b47b7c9d06f53a310cea5811b4c5f" + "git_sha": "f4eab7945952dc4934224309701a49913ea05ae6" }, "trimgalore": { "branch": "master", diff --git a/modules/nf-core/modules/cat/fastq/main.nf b/modules/nf-core/modules/cat/fastq/main.nf index b6854895..d275f19c 100644 --- a/modules/nf-core/modules/cat/fastq/main.nf +++ b/modules/nf-core/modules/cat/fastq/main.nf @@ -48,4 +48,33 @@ process CAT_FASTQ { """ } } + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + def readList = reads.collect{ it.toString() } + if (meta.single_end) { + if (readList.size > 1) { + """ + touch ${prefix}.merged.fastq.gz + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + cat: \$(echo \$(cat --version 2>&1) | sed 's/^.*coreutils) //; s/ .*\$//') + END_VERSIONS + """ + } + } else { + if (readList.size > 2) { + """ + touch ${prefix}_1.merged.fastq.gz + touch ${prefix}_2.merged.fastq.gz + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + cat: \$(echo \$(cat --version 2>&1) | sed 's/^.*coreutils) //; s/ .*\$//') + END_VERSIONS + """ + } + } + } diff --git a/modules/nf-core/modules/custom/dumpsoftwareversions/main.nf b/modules/nf-core/modules/custom/dumpsoftwareversions/main.nf index 327d5100..34b50b9f 100644 --- a/modules/nf-core/modules/custom/dumpsoftwareversions/main.nf +++ b/modules/nf-core/modules/custom/dumpsoftwareversions/main.nf @@ -1,11 +1,11 @@ process CUSTOM_DUMPSOFTWAREVERSIONS { - label 'process_low' + label 'process_single' // Requires `pyyaml` which does not have a dedicated container but is in the MultiQC container - conda (params.enable_conda ? "bioconda::multiqc=1.11" : null) + conda (params.enable_conda ? 'bioconda::multiqc=1.13a' : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.11--pyhdfd78af_0' : - 'quay.io/biocontainers/multiqc:1.11--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/multiqc:1.13a--pyhdfd78af_1' : + 'quay.io/biocontainers/multiqc:1.13a--pyhdfd78af_1' }" input: path versions diff --git a/modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py b/modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py index 787bdb7b..d1390392 100644 --- a/modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py +++ b/modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py @@ -1,10 +1,9 @@ #!/usr/bin/env python +import yaml import platform from textwrap import dedent -import yaml - def _make_versions_html(versions): html = [ @@ -59,12 +58,11 @@ def _make_versions_html(versions): for process, process_versions in versions_by_process.items(): module = process.split(":")[-1] try: - if versions_by_module[module] != process_versions: - raise AssertionError( - "We assume that software versions are the same between all modules. " - "If you see this error-message it means you discovered an edge-case " - "and should open an issue in nf-core/tools. " - ) + assert versions_by_module[module] == process_versions, ( + "We assume that software versions are the same between all modules. " + "If you see this error-message it means you discovered an edge-case " + "and should open an issue in nf-core/tools. " + ) except KeyError: versions_by_module[module] = process_versions diff --git a/modules/nf-core/modules/multiqc/main.nf b/modules/nf-core/modules/multiqc/main.nf index 3c3517bf..d10dae69 100644 --- a/modules/nf-core/modules/multiqc/main.nf +++ b/modules/nf-core/modules/multiqc/main.nf @@ -1,14 +1,15 @@ process MULTIQC { label 'process_medium' - conda (params.enable_conda ? 'bioconda::multiqc=1.12' : null) + conda (params.enable_conda ? 'bioconda::multiqc=1.13' : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.13a--pyhdfd78af_1' : - 'quay.io/biocontainers/multiqc:1.13a--pyhdfd78af_1' }" + 'https://depot.galaxyproject.org/singularity/multiqc:1.13--pyhdfd78af_0' : + 'quay.io/biocontainers/multiqc:1.13--pyhdfd78af_0' }" input: path multiqc_files, stageAs: "?/*" - tuple path(multiqc_config), path(multiqc_logo) + path(multiqc_config) + path(multiqc_logo) output: path "*multiqc_report.html", emit: report diff --git a/modules/nf-core/modules/multiqc/meta.yml b/modules/nf-core/modules/multiqc/meta.yml index bf3a27fe..a1029f33 100644 --- a/modules/nf-core/modules/multiqc/meta.yml +++ b/modules/nf-core/modules/multiqc/meta.yml @@ -12,6 +12,7 @@ tools: homepage: https://multiqc.info/ documentation: https://multiqc.info/docs/ licence: ["GPL-3.0-or-later"] + input: - multiqc_files: type: file @@ -19,12 +20,13 @@ input: List of reports / files recognised by MultiQC, for example the html and zip output of FastQC - multiqc_config: type: file - description: Config yml for MultiQC + description: Optional config yml for MultiQC pattern: "*.{yml,yaml}" - multiqc_logo: type: file - description: Logo file for MultiQC + description: Optional logo file for MultiQC pattern: "*.{png}" + output: - report: type: file @@ -46,3 +48,4 @@ authors: - "@abhi18av" - "@bunop" - "@drpatelh" + - "@jfy133" diff --git a/modules/nf-core/modules/samtools/flagstat/main.nf b/modules/nf-core/modules/samtools/flagstat/main.nf index 03ec2dcf..c3152aca 100644 --- a/modules/nf-core/modules/samtools/flagstat/main.nf +++ b/modules/nf-core/modules/samtools/flagstat/main.nf @@ -1,6 +1,6 @@ process SAMTOOLS_FLAGSTAT { tag "$meta.id" - label 'process_low' + label 'process_single' conda (params.enable_conda ? "bioconda::samtools=1.15.1" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? @@ -23,7 +23,7 @@ process SAMTOOLS_FLAGSTAT { """ samtools \\ flagstat \\ - --threads ${task.cpus-1} \\ + --threads ${task.cpus} \\ $bam \\ > ${prefix}.flagstat diff --git a/modules/nf-core/modules/samtools/stats/main.nf b/modules/nf-core/modules/samtools/stats/main.nf index c913bc5e..9b0c3867 100644 --- a/modules/nf-core/modules/samtools/stats/main.nf +++ b/modules/nf-core/modules/samtools/stats/main.nf @@ -1,6 +1,6 @@ process SAMTOOLS_STATS { tag "$meta.id" - label 'process_low' + label 'process_single' conda (params.enable_conda ? "bioconda::samtools=1.15.1" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? @@ -8,7 +8,7 @@ process SAMTOOLS_STATS { 'quay.io/biocontainers/samtools:1.15.1--h1170115_0' }" input: - tuple val(meta), path(bam), path(bai) + tuple val(meta), path(input), path(input_index) path fasta output: @@ -25,9 +25,9 @@ process SAMTOOLS_STATS { """ samtools \\ stats \\ - --threads ${task.cpus-1} \\ + --threads ${task.cpus} \\ ${reference} \\ - ${bam} \\ + ${input} \\ > ${prefix}.stats cat <<-END_VERSIONS > versions.yml From 3e9fc14ab442cbc48952cb25b405e56860ae3eb0 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 12 Sep 2022 16:11:59 +0200 Subject: [PATCH 025/215] Bugfix for mqc channels --- workflows/smrnaseq.nf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index a32ef4d8..f9675425 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -235,7 +235,8 @@ workflow SMRNASEQ { MULTIQC ( ch_multiqc_files.collect(), - [ch_multiqc_config, ch_multiqc_image] + ch_multiqc_config, + ch_multiqc_image ) multiqc_report = MULTIQC.out.report.toList() From 1b6b8c65e9ddb5d4abc92a42c5bdc1f98f635812 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Tue, 13 Sep 2022 15:03:00 +0100 Subject: [PATCH 026/215] Fix empty channel logic for versions --- subworkflows/local/mirna_quant.nf | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/subworkflows/local/mirna_quant.nf b/subworkflows/local/mirna_quant.nf index a851d729..9a8259d4 100644 --- a/subworkflows/local/mirna_quant.nf +++ b/subworkflows/local/mirna_quant.nf @@ -64,7 +64,6 @@ workflow MIRNA_QUANT { .dump (tag:'hsux') .set { reads_hairpin } - BOWTIE_MAP_HAIRPIN ( reads_hairpin, hairpin_bowtie.collect() ) ch_versions = ch_versions.mix(BOWTIE_MAP_HAIRPIN.out.versions) @@ -93,8 +92,10 @@ workflow MIRNA_QUANT { BOWTIE_MAP_SEQCLUSTER ( reads_collapsed, hairpin_bowtie.collect() ) ch_versions = ch_versions.mix(BOWTIE_MAP_SEQCLUSTER.out.versions) + ch_mirtop_logs = Channel.empty() if (params.mirtrace_species){ MIRTOP_QUANT ( BOWTIE_MAP_SEQCLUSTER.out.bam.collect{it[1]}, FORMAT_HAIRPIN.out.formatted_fasta, gtf ) + ch_mirtop_logs = MIRTOP_QUANT.out.logs ch_versions = ch_versions.mix(MIRTOP_QUANT.out.versions) TABLE_MERGE ( MIRTOP_QUANT.out.mirtop_table ) @@ -109,22 +110,16 @@ workflow MIRNA_QUANT { fasta_mature = FORMAT_MATURE.out.formatted_fasta fasta_hairpin = FORMAT_HAIRPIN.out.formatted_fasta unmapped = reads_genome - bowtie_versions = BOWTIE_MAP_MATURE.out.versions - samtools_versions = BAM_STATS_MATURE.out.versions - seqcluster_versions = SEQCLUSTER_SEQUENCES.out.versions - mirtop_versions = MIRTOP_QUANT.out.versions mature_stats = BAM_STATS_MATURE.out.stats hairpin_stats = BAM_STATS_HAIRPIN.out.stats - mirtop_logs = MIRTOP_QUANT.out.logs - merge_versions = TABLE_MERGE.out.versions + mirtop_logs = ch_mirtop_logs versions = ch_versions } - def add_suffix(row, suffix) { def meta = [:] - meta.id = "${row[0].id}_${suffix}" + meta.id = "${row[0].id}_${suffix}" def array = [] array = [ meta, row[1] ] return array From e3f89f11d415781296b9e3ff35d9ac0a24d6c20a Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Tue, 13 Sep 2022 15:52:11 +0100 Subject: [PATCH 027/215] Standardise genome parameters and fix bugs --- CHANGELOG.md | 2 +- conf/modules.config | 64 +++++++++++------------- conf/test_full.config | 2 - main.nf | 6 ++- modules/local/bowtie_contaminants.nf | 2 +- modules/local/bowtie_genome.nf | 2 +- modules/local/bowtie_mirna.nf | 2 +- modules/local/mirtop_quant.nf | 9 ++-- modules/local/parse_fasta_mirna.nf | 5 +- nextflow.config | 13 ++--- nextflow_schema.json | 5 +- subworkflows/local/contaminant_filter.nf | 12 ++--- subworkflows/local/genome_quant.nf | 16 +++--- subworkflows/local/mirdeep2.nf | 4 +- subworkflows/local/mirna_quant.nf | 4 +- workflows/smrnaseq.nf | 26 ++++------ 16 files changed, 78 insertions(+), 96 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dfe96c92..08ee6520 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [[#12](https://github.com/nf-core/smrnaseq/issues/12)] - Enabled the use of `MirGeneDB` as an alternative database insted of `miRBase` - [[#113](https://github.com/nf-core/smrnaseq/issues/113)] - Added a optional contamination filtering step, including MultiQC plot - [[#137](https://github.com/nf-core/smrnaseq/issues/137)] - Fixed issue with mirTop and MultiQC by upgrading to MultiQC V1.13dev -- [[#159](https://github.com/nf-core/smrnaseq/issues/159)] - Index files were not collected when `bowtie_indices` was used and thus mapping was failing +- [[#159](https://github.com/nf-core/smrnaseq/issues/159)] - Index files were not collected when `bowtie_index` was used and thus mapping was failing - [[#161](https://github.com/nf-core/smrnaseq/issues/161)] - Trimmed output was not as documented and not correctly published - [[#168](https://github.com/nf-core/smrnaseq/issues/168)] - Removed `mirtrace_protocol` as the parameter was redundant and `params.protocol` is entirely sufficient - Updated pipeline template to [nf-core/tools 2.5.1](https://github.com/nf-core/tools/releases/tag/2.5.1) diff --git a/conf/modules.config b/conf/modules.config index bb28301b..04d47b37 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -179,47 +179,41 @@ process { } } -def fasta_from_species = false -def fasta = false -fasta_from_species = params.genome ? params.genomes[ params.genome ].fasta ?: false : false -fasta = params.fasta ?: fasta_from_species -if (fasta) { +process { + withName: 'NFCORE_SMRNASEQ:SMRNASEQ:GENOME_QUANT:BAM_SORT_SAMTOOLS:SAMTOOLS_.*' { + ext.prefix = { "${meta.id}.sorted" } + publishDir = [ + path: { "${params.outdir}/samtools" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] + } + withName: 'NFCORE_SMRNASEQ:SMRNASEQ:GENOME_QUANT:BAM_SORT_SAMTOOLS:BAM_STATS_SAMTOOLS:.*' { + ext.prefix = { "${meta.id}.sorted" } + publishDir = [ + path: { "${params.outdir}/samtools/samtools_stats" }, + mode: params.publish_dir_mode, + pattern: "*.{stats,flagstat,idxstats}" + ] + } + withName: 'NFCORE_SMRNASEQ:SMRNASEQ:GENOME_QUANT:BOWTIE_MAP_.*' { + publishDir = [ + path: { "${params.outdir}/unmapped/fastq" }, + mode: params.publish_dir_mode, + pattern: "unmapped/*.gz" + ] + } +} + +if (!params.skip_mirdeep) { process { - withName: 'NFCORE_SMRNASEQ:SMRNASEQ:GENOME_QUANT:BAM_SORT_SAMTOOLS:SAMTOOLS_.*' { - ext.prefix = { "${meta.id}.sorted" } + withName: 'MIRDEEP2_MAPPER' { publishDir = [ - path: { "${params.outdir}/samtools" }, + path: { "${params.outdir}/mirdeep" }, mode: params.publish_dir_mode, saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] } - withName: 'NFCORE_SMRNASEQ:SMRNASEQ:GENOME_QUANT:BAM_SORT_SAMTOOLS:BAM_STATS_SAMTOOLS:.*' { - ext.prefix = { "${meta.id}.sorted" } - publishDir = [ - path: { "${params.outdir}/samtools/samtools_stats" }, - mode: params.publish_dir_mode, - pattern: "*.{stats,flagstat,idxstats}" - ] - } - withName: 'NFCORE_SMRNASEQ:SMRNASEQ:GENOME_QUANT:BOWTIE_MAP_.*' { - publishDir = [ - path: { "${params.outdir}/unmapped/fastq" }, - mode: params.publish_dir_mode, - pattern: "unmapped/*.gz" - ] - } - } - - if (!params.skip_mirdeep) { - process { - withName: 'MIRDEEP2_MAPPER' { - publishDir = [ - path: { "${params.outdir}/mirdeep" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } - ] - } - } } } diff --git a/conf/test_full.config b/conf/test_full.config index 8d82bef5..cc5ecd92 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -11,8 +11,6 @@ */ params { - max_memory = '12.GB' - max_cpus = 8 config_profile_name = 'Full test profile' config_profile_description = 'Full test dataset to check pipeline function' diff --git a/main.nf b/main.nf index ae52f738..68e88980 100644 --- a/main.nf +++ b/main.nf @@ -4,7 +4,7 @@ nf-core/smrnaseq ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Github : https://github.com/nf-core/smrnaseq -Website: https://nf-co.re/smrnaseq + Website: https://nf-co.re/smrnaseq Slack : https://nfcore.slack.com/channels/smrnaseq ---------------------------------------------------------------------------------------- */ @@ -17,6 +17,10 @@ nextflow.enable.dsl = 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +params.fasta = WorkflowMain.getGenomeAttribute(params, 'fasta') +params.mirtrace_species = WorkflowMain.getGenomeAttribute(params, 'mirtrace_species') +params.bowtie_index = WorkflowMain.getGenomeAttribute(params, 'bowtie') + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VALIDATE & PRINT PARAMETER SUMMARY diff --git a/modules/local/bowtie_contaminants.nf b/modules/local/bowtie_contaminants.nf index 7a86cd1d..4fd04643 100644 --- a/modules/local/bowtie_contaminants.nf +++ b/modules/local/bowtie_contaminants.nf @@ -10,7 +10,7 @@ process INDEX_CONTAMINANTS { path fasta output: - path 'fasta_bidx*' , emit: bt_indices + path 'fasta_bidx*' , emit: index path "versions.yml" , emit: versions script: diff --git a/modules/local/bowtie_genome.nf b/modules/local/bowtie_genome.nf index 723100db..cdf572f7 100644 --- a/modules/local/bowtie_genome.nf +++ b/modules/local/bowtie_genome.nf @@ -11,7 +11,7 @@ process INDEX_GENOME { path fasta output: - path 'genome*ebwt' , emit: bowtie_indices + path 'genome*ebwt' , emit: index path 'genome.edited.fa', emit: fasta path "versions.yml" , emit: versions diff --git a/modules/local/bowtie_mirna.nf b/modules/local/bowtie_mirna.nf index 1f340cdf..07050538 100644 --- a/modules/local/bowtie_mirna.nf +++ b/modules/local/bowtie_mirna.nf @@ -10,7 +10,7 @@ process INDEX_MIRNA { path fasta output: - path 'fasta_bidx*' , emit: bowtie_indices + path 'fasta_bidx*' , emit: index path "versions.yml", emit: versions script: diff --git a/modules/local/mirtop_quant.nf b/modules/local/mirtop_quant.nf index 6f903add..2ce3e1c6 100644 --- a/modules/local/mirtop_quant.nf +++ b/modules/local/mirtop_quant.nf @@ -11,8 +11,6 @@ process MIRTOP_QUANT { path hairpin path gtf - //if (!params.mirgenedb) {params.filter_species = params.mirtrace_species} else {params.filter_species = params.mirgenedb_species} - output: path "mirtop/mirtop.gff" path "mirtop/mirtop.tsv" , emit: mirtop_table @@ -21,10 +19,11 @@ process MIRTOP_QUANT { path "versions.yml" , emit: versions script: + def filter_species = params.mirgenedb ? params.mirgenedb_species : params.mirtrace_species """ - mirtop gff --hairpin $hairpin --gtf $gtf -o mirtop --sps $params.filter_species ./bams/* - mirtop counts --hairpin $hairpin --gtf $gtf -o mirtop --sps $params.filter_species --add-extra --gff mirtop/mirtop.gff - mirtop export --format isomir --hairpin $hairpin --gtf $gtf --sps $params.filter_species -o mirtop mirtop/mirtop.gff + mirtop gff --hairpin $hairpin --gtf $gtf -o mirtop --sps $filter_species ./bams/* + mirtop counts --hairpin $hairpin --gtf $gtf -o mirtop --sps $filter_species --add-extra --gff mirtop/mirtop.gff + mirtop export --format isomir --hairpin $hairpin --gtf $gtf --sps $filter_species -o mirtop mirtop/mirtop.gff mirtop stats mirtop/mirtop.gff --out mirtop/stats mv mirtop/stats/mirtop_stats.log mirtop/stats/full_mirtop_stats.log diff --git a/modules/local/parse_fasta_mirna.nf b/modules/local/parse_fasta_mirna.nf index 27caf42b..88626bec 100644 --- a/modules/local/parse_fasta_mirna.nf +++ b/modules/local/parse_fasta_mirna.nf @@ -9,13 +9,12 @@ process PARSE_FASTA_MIRNA { input: path fasta - //if (!params.mirgenedb) {params.filter_species = params.mirtrace_species} else {params.filter_species = params.mirgenedb_species} - output: path '*_igenome.fa', emit: parsed_fasta path "versions.yml", emit: versions script: + def filter_species = params.mirgenedb ? params.mirgenedb_species : params.mirtrace_species """ # Uncompress FASTA reference files if necessary FASTA="$fasta" @@ -29,7 +28,7 @@ process PARSE_FASTA_MIRNA { # TODO perl -ane 's/[ybkmrsw]/N/ig;print;' \${FASTA}_parsed_tmp.fa > \${FASTA}_parsed.fa sed -i 's/\s.*//' \${FASTA}_parsed.fa - seqkit grep -r --pattern \".*${params.filter_species}-.*\" \${FASTA}_parsed.fa > \${FASTA}_sps.fa + seqkit grep -r --pattern \".*${filter_species}-.*\" \${FASTA}_parsed.fa > \${FASTA}_sps.fa seqkit seq --rna2dna \${FASTA}_sps.fa > \${FASTA}_igenome.fa cat <<-END_VERSIONS > versions.yml diff --git a/nextflow.config b/nextflow.config index 08de9d63..40795723 100644 --- a/nextflow.config +++ b/nextflow.config @@ -19,21 +19,18 @@ params { genome = null igenomes_base = 's3://ngi-igenomes/igenomes' igenomes_ignore = false - fasta = null mirna_gtf = null - bowtie_indices = null - mirtrace_species = null mature = "https://mirbase.org/ftp/CURRENT/mature.fa.gz" hairpin = "https://mirbase.org/ftp/CURRENT/hairpin.fa.gz" mirgenedb = false - mirgenedb_mature = "/Users/chriskub/Downloads/ALL-mat.fas" - mirgenedb_hairpin = "/Users/chriskub/Downloads/ALL-pre.fas" - mirgenedb_gff = "/Users/chriskub/Downloads/ALL.gff" + mirgenedb_mature = null + mirgenedb_hairpin = null + mirgenedb_gff = null mirgenedb_species = null // Trimming options - clip_r1 = 0 - three_prime_clip_r1 = 0 + clip_r1 = null + three_prime_clip_r1 = null three_prime_adapter = "TGGAATTCTCGGGTGCCAAGG" min_length = 17 skip_qc = false diff --git a/nextflow_schema.json b/nextflow_schema.json index 2ca88862..7d89945c 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -65,8 +65,7 @@ "mirgenedb": { "type": "boolean", "description": "Boolean whether MirGeneDB should be used instead of miRBase", - "help_text": "This allows you to use MirGeneDB instead of miRBase as the database. \n Note that you will need to set the additional flags `--mirgenedb_species`, `--mirgenedb_gff`, `--mirgenedb_mature` and `--mirgenedb_hairpin`", - "default": "false" + "help_text": "This allows you to use MirGeneDB instead of miRBase as the database. \n Note that you will need to set the additional flags `--mirgenedb_species`, `--mirgenedb_gff`, `--mirgenedb_mature` and `--mirgenedb_hairpin`" }, "mirtrace_species": { "type": "string", @@ -120,7 +119,7 @@ "description": "Path to FASTA file with miRNAs precursors.", "help_text": "This file needs to be downloaded from [`https://mirgenedb.org/download`]. Can be given either as a plain text `.fa` file or a compressed `.gz` file.\nNote that MirGeneDB does not have a dedicated hairpin file. The equivalent is the `Precursor sequences`." }, - "bowtie_indices": { + "bowtie_index": { "type": "string", "description": "Path to a Bowtie 1 index directory", "fa_icon": "fas fa-book", diff --git a/subworkflows/local/contaminant_filter.nf b/subworkflows/local/contaminant_filter.nf index 848682ea..4ab180c7 100644 --- a/subworkflows/local/contaminant_filter.nf +++ b/subworkflows/local/contaminant_filter.nf @@ -49,7 +49,7 @@ workflow CONTAMINANT_FILTER { // Index DB and filter $reads emit: $rrna_reads INDEX_RRNA ( rrna ) ch_versions = ch_versions.mix(INDEX_RRNA.out.versions) - MAP_RRNA ( reads, INDEX_RRNA.out.bt_indices, 'rRNA' ) + MAP_RRNA ( reads, INDEX_RRNA.out.index, 'rRNA' ) ch_versions = ch_versions.mix(MAP_RRNA.out.versions) ch_filter_stats = ch_filter_stats.mix(MAP_RRNA.out.stats.ifEmpty(null)) MAP_RRNA.out.unmapped.set { rrna_reads } @@ -61,7 +61,7 @@ workflow CONTAMINANT_FILTER { // Index DB and filter $rrna_reads emit: $trna_reads INDEX_TRNA ( trna ) ch_versions = ch_versions.mix(INDEX_TRNA.out.versions) - MAP_TRNA ( rrna_reads, INDEX_TRNA.out.bt_indices, 'tRNA') + MAP_TRNA ( rrna_reads, INDEX_TRNA.out.index, 'tRNA') ch_versions = ch_versions.mix(MAP_TRNA.out.versions) ch_filter_stats = ch_filter_stats.mix(MAP_TRNA.out.stats.ifEmpty(null)) MAP_TRNA.out.unmapped.set { trna_reads } @@ -75,7 +75,7 @@ workflow CONTAMINANT_FILTER { ch_versions = ch_versions.mix(BLAT_CDNA.out.versions) INDEX_CDNA ( BLAT_CDNA.out.filtered_set ) ch_versions = ch_versions.mix(INDEX_CDNA.out.versions) - MAP_CDNA ( trna_reads, INDEX_CDNA.out.bt_indices, 'cDNA' ) + MAP_CDNA ( trna_reads, INDEX_CDNA.out.index, 'cDNA' ) ch_versions = ch_versions.mix(MAP_CDNA.out.versions) ch_filter_stats = ch_filter_stats.mix(MAP_CDNA.out.stats.ifEmpty(null)) MAP_CDNA.out.unmapped.set { cdna_reads } @@ -88,7 +88,7 @@ workflow CONTAMINANT_FILTER { ch_versions = ch_versions.mix(BLAT_NCRNA.out.versions) INDEX_NCRNA ( BLAT_NCRNA.out.filtered_set ) ch_versions = ch_versions.mix(INDEX_NCRNA.out.versions) - MAP_NCRNA ( cdna_reads, INDEX_NCRNA.out.bt_indices, 'ncRNA' ) + MAP_NCRNA ( cdna_reads, INDEX_NCRNA.out.index, 'ncRNA' ) ch_versions = ch_versions.mix(MAP_NCRNA.out.versions) ch_filter_stats = ch_filter_stats.mix(MAP_NCRNA.out.stats.ifEmpty(null)) MAP_NCRNA.out.unmapped.set { ncrna_reads } @@ -101,7 +101,7 @@ workflow CONTAMINANT_FILTER { ch_versions = ch_versions.mix(BLAT_PIRNA.out.versions) INDEX_PIRNA ( BLAT_PIRNA.out.filtered_set ) ch_versions = ch_versions.mix(INDEX_PIRNA.out.versions) - MAP_PIRNA (ncrna_reads, INDEX_PIRNA.out.bt_indices, 'piRNA' ) + MAP_PIRNA (ncrna_reads, INDEX_PIRNA.out.index, 'piRNA' ) ch_versions = ch_versions.mix(MAP_PIRNA.out.versions) ch_filter_stats = ch_filter_stats.mix(MAP_PIRNA.out.stats.ifEmpty(null)) MAP_PIRNA.out.unmapped.set { pirna_reads } @@ -114,7 +114,7 @@ workflow CONTAMINANT_FILTER { ch_versions = ch_versions.mix(BLAT_OTHER.out.versions) INDEX_OTHER ( BLAT_OTHER.out.filtered_set ) ch_versions = ch_versions.mix(INDEX_OTHER.out.versions) - MAP_OTHER (ncrna_reads, INDEX_OTHER.out.bt_indices, 'other' ) + MAP_OTHER (ncrna_reads, INDEX_OTHER.out.index, 'other' ) ch_versions = ch_versions.mix(MAP_OTHER.out.versions) ch_filter_stats = ch_filter_stats.mix(MAP_OTHER.out.stats.ifEmpty(null)) MAP_OTHER.out.unmapped.set { other_cont_reads } diff --git a/subworkflows/local/genome_quant.nf b/subworkflows/local/genome_quant.nf index 8cf812d7..033f59ad 100644 --- a/subworkflows/local/genome_quant.nf +++ b/subworkflows/local/genome_quant.nf @@ -9,24 +9,24 @@ include { BOWTIE_MAP_SEQ as BOWTIE_MAP_GENOME } from '../../modules/local/bowtie workflow GENOME_QUANT { take: fasta - bt_index - reads // channel: [ val(meta), [ reads ] ] + index + reads // channel: [ val(meta), [ reads ] ] main: ch_versions = Channel.empty() - if (!bt_index){ + if (!index){ INDEX_GENOME ( fasta ) - bowtie_indices = INDEX_GENOME.out.bowtie_indices + bowtie_index = INDEX_GENOME.out.index fasta_formatted = INDEX_GENOME.out.fasta ch_versions = ch_versions.mix(INDEX_GENOME.out.versions) } else { - bowtie_indices = Channel.fromPath("${bt_index}**ebwt", checkIfExists: true).ifEmpty { exit 1, "Bowtie1 index directory not found: ${bt_index}" } + bowtie_index = Channel.fromPath("${index}**ebwt", checkIfExists: true).ifEmpty { exit 1, "Bowtie1 index directory not found: ${index}" } fasta_formatted = fasta } - if (bowtie_indices){ - BOWTIE_MAP_GENOME ( reads, bowtie_indices.collect() ) + if (bowtie_index){ + BOWTIE_MAP_GENOME ( reads, bowtie_index.collect() ) ch_versions = ch_versions.mix(BOWTIE_MAP_GENOME.out.versions) BAM_SORT_SAMTOOLS ( BOWTIE_MAP_GENOME.out.bam, Channel.empty() ) @@ -35,7 +35,7 @@ workflow GENOME_QUANT { emit: fasta = fasta_formatted - indices = bowtie_indices + index = bowtie_index stats = BAM_SORT_SAMTOOLS.out.stats versions = ch_versions diff --git a/subworkflows/local/mirdeep2.nf b/subworkflows/local/mirdeep2.nf index a790189f..f8098ba5 100644 --- a/subworkflows/local/mirdeep2.nf +++ b/subworkflows/local/mirdeep2.nf @@ -10,7 +10,7 @@ workflow MIRDEEP2 { take: reads // channel: [ val(meta), [ reads ] ] fasta - indices + index hairpin mature @@ -20,7 +20,7 @@ workflow MIRDEEP2 { MIRDEEP2_PIGZ ( reads ) ch_versions = ch_versions.mix(MIRDEEP2_PIGZ.out.versions.first()) - MIRDEEP2_MAPPER ( MIRDEEP2_PIGZ.out.reads, indices ) + MIRDEEP2_MAPPER ( MIRDEEP2_PIGZ.out.reads, index ) ch_versions = ch_versions.mix(MIRDEEP2_MAPPER.out.versions.first()) MIRDEEP2_RUN ( fasta, MIRDEEP2_MAPPER.out.mirdeep2_inputs, hairpin, mature ) diff --git a/subworkflows/local/mirna_quant.nf b/subworkflows/local/mirna_quant.nf index 9a8259d4..dd8a8412 100644 --- a/subworkflows/local/mirna_quant.nf +++ b/subworkflows/local/mirna_quant.nf @@ -45,10 +45,10 @@ workflow MIRNA_QUANT { FORMAT_HAIRPIN ( hairpin_parsed ) ch_versions = ch_versions.mix(FORMAT_HAIRPIN.out.versions) - INDEX_MATURE ( FORMAT_MATURE.out.formatted_fasta ).bowtie_indices.set { mature_bowtie } + INDEX_MATURE ( FORMAT_MATURE.out.formatted_fasta ).index.set { mature_bowtie } ch_versions = ch_versions.mix(INDEX_MATURE.out.versions) - INDEX_HAIRPIN ( FORMAT_HAIRPIN.out.formatted_fasta ).bowtie_indices.set { hairpin_bowtie } + INDEX_HAIRPIN ( FORMAT_HAIRPIN.out.formatted_fasta ).index.set { hairpin_bowtie } ch_versions = ch_versions.mix(INDEX_HAIRPIN.out.versions) reads diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index f9675425..ca1b265e 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -20,19 +20,13 @@ for (param in checkPathParamList) { if (param) { file(param, checkIfExists: true if (params.input) { ch_input = file(params.input) } else { exit 1, 'Input samplesheet not specified!' } // Check optional parameters -if (!params.mirtrace_species){ - exit 1, "Reference species for miRTrace is not defined." +if (!params.mirtrace_species) { + exit 1, "Reference species for miRTrace is not defined via the --mirtrace_species parameter." } -// Genome options -bt_index_from_species = params.genome ? params.genomes[ params.genome ].bowtie ?: false : false -bt_index = params.bowtie_indices ?: bt_index_from_species -mirtrace_species_from_species = params.genome ? params.genomes[ params.genome ].mirtrace_species ?: false : false -mirtrace_species = params.mirtrace_species ?: mirtrace_species_from_species -fasta_from_species = params.genome ? params.genomes[ params.genome ].fasta ?: false : false -fasta = params.fasta ?: fasta_from_species -mirna_gtf_from_species = params.mirtrace_species ? "https://mirbase.org/ftp/CURRENT/genomes/${params.mirtrace_species}.gff3" : false -mirna_gtf = params.mirna_gtf ? params.mirna_gtf : mirna_gtf_from_species +// Genome options +def mirna_gtf_from_species = params.mirtrace_species ? "https://mirbase.org/ftp/CURRENT/genomes/${params.mirtrace_species}.gff3" : false +def mirna_gtf = params.mirna_gtf ?: mirna_gtf_from_species /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -56,12 +50,10 @@ ch_multiqc_image = file("$projectDir/assets/smrnaseq_logo.png", checkIfE if (!params.mirgenedb) { if (params.mature) { reference_mature = file(params.mature, checkIfExists: true) } else { exit 1, "Mature miRNA fasta file not found: ${params.mature}" } if (params.hairpin) { reference_hairpin = file(params.hairpin, checkIfExists: true) } else { exit 1, "Hairpin miRNA fasta file not found: ${params.hairpin}" } - params.filter_species = params.mirtrace_species } else { if (params.mirgenedb_mature) { reference_mature = file(params.mirgenedb_mature, checkIfExists: true) } else { exit 1, "Mature miRNA fasta file not found: ${params.mirgenedb_mature}" } if (params.mirgenedb_hairpin) { reference_hairpin = file(params.mirgenedb_hairpin, checkIfExists: true) } else { exit 1, "Hairpin miRNA fasta file not found: ${params.mirgenedb_hairpin}" } if (params.mirgenedb_gff) { mirna_gtf = file(params.mirgenedb_gff, checkIfExists: true) } else { exit 1, "MirGeneDB gff file not found: ${params.mirgenedb_gff}"} - params.filter_species = params.mirgenedb_species } include { INPUT_CHECK } from '../subworkflows/local/input_check' @@ -186,9 +178,9 @@ workflow SMRNASEQ { // GENOME // genome_stats = Channel.empty() - if (fasta){ - fasta_ch = file(fasta) - GENOME_QUANT ( fasta_ch, bt_index, MIRNA_QUANT.out.unmapped ) + if (params.fasta){ + ch_fasta = file(params.fasta) + GENOME_QUANT ( ch_fasta, params.bowtie_index, MIRNA_QUANT.out.unmapped ) GENOME_QUANT.out.stats .set { genome_stats } ch_versions = ch_versions.mix(GENOME_QUANT.out.versions) @@ -197,7 +189,7 @@ workflow SMRNASEQ { MIRDEEP2 ( FASTQC_TRIMGALORE.out.reads, GENOME_QUANT.out.fasta, - GENOME_QUANT.out.indices.collect(), + GENOME_QUANT.out.index.collect(), MIRNA_QUANT.out.fasta_hairpin, MIRNA_QUANT.out.fasta_mature ) From 1df1792130acd8eb4e448957e1c3926e8c081586 Mon Sep 17 00:00:00 2001 From: Robert Syme Date: Wed, 14 Sep 2022 02:38:58 +0000 Subject: [PATCH 028/215] Add basic tower.yml --- tower.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 tower.yml diff --git a/tower.yml b/tower.yml new file mode 100644 index 00000000..1a72c200 --- /dev/null +++ b/tower.yml @@ -0,0 +1,29 @@ +reports: + multiqc_report.html: + display: "MultiQC HTML report" + "**/edger/hairpin_counts.csv": + display: "EdgeR Read counts for known hairpins (raw counts)" + "**/edger/hairpin_logtpm.csv": + display: "EdgeR Read counts for known hairpins (log TPM)" + "**/edger/hairpin_normalized_CPM.txt": + display: "EdgeR Read counts for known hairpins (normalised)" + "**/edger/mature_counts.csv": + display: "EdgeR Read counts for known mature miRNAs (raw)" + "**/edger/mature_logtpm.csv": + display: "EdgeR Read counts for known mature miRNAs (log TPM)" + "**/edger/mature_normalized_CPM.txt": + display: "EdgeR Read counts for known mature miRNAs (normalised)" + "**/edger/hairpin_CPM_heatmap.pdf": + display: "EdgeR Heatmap of hairpin sequences for all samples" + "**/edger/hairpin_edgeR_MDS_plot.pdf": + display: "EdgeR Dimensionality reduction plot of samples from hairpin counts" + "**/edger/hairpin_log2CPM_sample_distances_dendrogram.pdf": + display: "EdgeR dendrogram from hairpin counts" + "**/edger/hairpin_log2CPM_sample_distances_heatmap.pdf": + display: "EdgeR distances from hairpin counts" + "**/mirtop/mirna.tsv": + display: "Mirtop miRNA summary table" + "**/mirtop/mirtop.tsv": + display: "Mirtop summary table" + "**/mirtrace/mirtrace-report.html": + display: "Mirtrace report" From 03142a903f22e767fffe41dd6cebae201ffd46a0 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 22 Sep 2022 14:00:19 +0000 Subject: [PATCH 029/215] Draft for fastp auto-detection and auto-setting of protocol params --- lib/WorkflowSmrnaseq.groovy | 36 +++++++++ modules.json | 4 + modules/local/trimgalore.nf | 73 ------------------ modules/nf-core/modules/fastp/main.nf | 98 ++++++++++++++++++++++++ modules/nf-core/modules/fastp/meta.yml | 69 +++++++++++++++++ nextflow.config | 4 +- nextflow_schema.json | 36 ++++++--- subworkflows/nf-core/fastp_fastqc.nf | 100 +++++++++++++++++++++++++ workflows/smrnaseq.nf | 24 +++--- 9 files changed, 348 insertions(+), 96 deletions(-) delete mode 100644 modules/local/trimgalore.nf create mode 100644 modules/nf-core/modules/fastp/main.nf create mode 100644 modules/nf-core/modules/fastp/meta.yml create mode 100644 subworkflows/nf-core/fastp_fastqc.nf diff --git a/lib/WorkflowSmrnaseq.groovy b/lib/WorkflowSmrnaseq.groovy index b0564d30..c1701ab5 100755 --- a/lib/WorkflowSmrnaseq.groovy +++ b/lib/WorkflowSmrnaseq.groovy @@ -54,4 +54,40 @@ class WorkflowSmrnaseq { System.exit(1) } } + + /* + * Format the protocol + * Given the protocol parameter (params.protocol), + * this function formats the protocol such that it is fit for the respective + * subworkflow + */ + static formatProtocol(protocol) { + Int clip_r1 = protocol + Int three_prime_clip_r1 = '' + String three_prime_adapter = '' + + switch(protocol){ + case 'illumina': + clip_r1 = 0 + three_prime_clip_r1 = 0 + three_prime_adapter = "TGGAATTCTCGGGTGCCAAGG" + case 'nextflex': + clip_r1 = 4 + three_prime_clip_r1 = 4 + three_prime_adapter = "TGGAATTCTCGGGTGCCAAGG" + case 'qiaseq': + clip_r1 = 0 + three_prime_clip_r1 = 0 + three_prime_adapter = "AACTGTAGGCACCATCAAT" + case 'cats': + clip_r1 = 3 + three_prime_clip_r1 = 0 + three_prime_adapter = "AAAAAAAA" + case 'custom': + clip_r1 = params.clip_r1 + three_prime_clip_r1 = params.three_prime_clip_r1 + three_prime_adapter = params.three_prime_adapter + } + return [clip_r1, three_prime_clip_r1, three_prime_adapter] + } } diff --git a/modules.json b/modules.json index d169ad11..7c426975 100644 --- a/modules.json +++ b/modules.json @@ -13,6 +13,10 @@ "branch": "master", "git_sha": "5e7b1ef9a5a2d9258635bcbf70fcf37dacd1b247" }, + "fastp": { + "branch": "master", + "git_sha": "2c70c1c1951aaf884d2e8d8d9c871db79f7b35aa" + }, "fastqc": { "branch": "master", "git_sha": "49b18b1639f4f7104187058866a8fab33332bdfe" diff --git a/modules/local/trimgalore.nf b/modules/local/trimgalore.nf deleted file mode 100644 index 3dec8f2e..00000000 --- a/modules/local/trimgalore.nf +++ /dev/null @@ -1,73 +0,0 @@ -process TRIMGALORE { - tag "$meta.id" - label 'process_high' - - conda (params.enable_conda ? 'bioconda::trim-galore=0.6.7' : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/trim-galore:0.6.7--hdfd78af_0' : - 'quay.io/biocontainers/trim-galore:0.6.7--hdfd78af_0' }" - - input: - tuple val(meta), path(reads) - - output: - tuple val(meta), path("*.fq.gz") , emit: reads - tuple val(meta), path("*report.txt"), emit: log - path "versions.yml" , emit: versions - - tuple val(meta), path("*.html"), emit: html optional true - tuple val(meta), path("*.zip") , emit: zip optional true - - script: - def args = task.ext.args ?: '' - def cores = 1 - if (task.cpus) { - cores = (task.cpus as int) - 4 - if (meta.single_end) cores = (task.cpus as int) - 3 - if (cores < 1) cores = 1 - if (cores > 4) cores = 4 - } - def prefix = "${meta.id}" - // Define regular variables so that they can be overwritten - def clip_r1 = params.clip_r1 - def three_prime_clip_r1 = params.three_prime_clip_r1 - def three_prime_adapter = params.three_prime_adapter - def protocol = params.protocol - // Presets - if (params.protocol == "illumina"){ - clip_r1 = 0 - three_prime_clip_r1 = 0 - three_prime_adapter = "TGGAATTCTCGGGTGCCAAGG" - } else if (params.protocol == "nextflex"){ - clip_r1 = 4 - three_prime_clip_r1 = 4 - three_prime_adapter = "TGGAATTCTCGGGTGCCAAGG" - } else if (params.protocol == "qiaseq"){ - clip_r1 = 0 - three_prime_clip_r1 = 0 - three_prime_adapter = "AACTGTAGGCACCATCAAT" - } else if (params.protocol == "cats"){ - clip_r1 = 3 - three_prime_clip_r1 = 0 - // three_prime_adapter = "GATCGGAAGAGCACACGTCTG" - three_prime_adapter = "AAAAAAAA" - } else if (params.protocol == "custom"){ - //custom protocol - clip_r1 = params.clip_r1 - three_prime_clip_r1 = params.three_prime_clip_r1 - three_prime_adapter = params.three_prime_adapter - } - def tg_length = "--length ${params.min_length}" - def c_r1 = clip_r1 > 0 ? "--clip_r1 ${clip_r1}" : '' - def tpc_r1 = three_prime_clip_r1 > 0 ? "--three_prime_clip_r1 ${three_prime_clip_r1}" : '' - """ - [ ! -f ${prefix}.fastq.gz ] && ln -s $reads ${prefix}.fastq.gz - trim_galore $args --cores $cores --adapter ${three_prime_adapter} $tg_length $c_r1 $tpc_r1 --max_length ${params.trim_galore_max_length} --gzip ${prefix}.fastq.gz - - cat <<-END_VERSIONS > versions.yml - ${task.process}": - trimgalore: \$(echo \$(trim_galore --version 2>&1) | sed 's/^.*version //; s/Last.*\$//') - cutadapt: \$(cutadapt --version) - END_VERSIONS - """ -} diff --git a/modules/nf-core/modules/fastp/main.nf b/modules/nf-core/modules/fastp/main.nf new file mode 100644 index 00000000..11ea4db3 --- /dev/null +++ b/modules/nf-core/modules/fastp/main.nf @@ -0,0 +1,98 @@ +process FASTP { + tag "$meta.id" + label 'process_medium' + + conda (params.enable_conda ? 'bioconda::fastp=0.23.2' : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/fastp:0.23.2--h79da9fb_0' : + 'quay.io/biocontainers/fastp:0.23.2--h79da9fb_0' }" + + input: + tuple val(meta), path(reads) + val save_trimmed_fail + val save_merged + + output: + tuple val(meta), path('*.fastp.fastq.gz') , optional:true, emit: reads + 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 + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + 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" : '' + // 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') ) { + """ + [ ! -f ${prefix}.fastq.gz ] && ln -sf $reads ${prefix}.fastq.gz + + fastp \\ + --stdout \\ + --in1 ${prefix}.fastq.gz \\ + --thread $task.cpus \\ + --json ${prefix}.fastp.json \\ + --html ${prefix}.fastp.html \\ + $fail_fastq \\ + $args \\ + 2> ${prefix}.fastp.log \\ + | gzip -c > ${prefix}.fastp.fastq.gz + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + fastp: \$(fastp --version 2>&1 | sed -e "s/fastp //g") + END_VERSIONS + """ + } else if (meta.single_end) { + """ + [ ! -f ${prefix}.fastq.gz ] && ln -sf $reads ${prefix}.fastq.gz + + fastp \\ + --stdout \\ + --in1 ${prefix}.fastq.gz \\ + --out1 ${prefix}.fastp.fastq.gz \\ + --thread $task.cpus \\ + --json ${prefix}.fastp.json \\ + --html ${prefix}.fastp.html \\ + $fail_fastq \\ + $args \\ + 2> ${prefix}.fastp.log + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + fastp: \$(fastp --version 2>&1 | sed -e "s/fastp //g") + END_VERSIONS + """ + } else { + def merge_fastq = save_merged ? "-m --merged_out ${prefix}.merged.fastq.gz" : '' + """ + [ ! -f ${prefix}_1.fastq.gz ] && ln -sf ${reads[0]} ${prefix}_1.fastq.gz + [ ! -f ${prefix}_2.fastq.gz ] && ln -sf ${reads[1]} ${prefix}_2.fastq.gz + fastp \\ + --in1 ${prefix}_1.fastq.gz \\ + --in2 ${prefix}_2.fastq.gz \\ + --out1 ${prefix}_1.fastp.fastq.gz \\ + --out2 ${prefix}_2.fastp.fastq.gz \\ + --json ${prefix}.fastp.json \\ + --html ${prefix}.fastp.html \\ + $fail_fastq \\ + $merge_fastq \\ + --thread $task.cpus \\ + --detect_adapter_for_pe \\ + $args \\ + 2> ${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/modules/fastp/meta.yml b/modules/nf-core/modules/fastp/meta.yml new file mode 100644 index 00000000..2368fded --- /dev/null +++ b/modules/nf-core/modules/fastp/meta.yml @@ -0,0 +1,69 @@ +name: fastp +description: Perform adapter/quality trimming on sequencing reads +keywords: + - trimming + - quality control + - fastq +tools: + - fastp: + description: | + A tool designed to provide fast all-in-one preprocessing for FastQ files. This tool is developed in C++ with multithreading supported to afford high performance. + documentation: https://github.com/OpenGene/fastp + doi: https://doi.org/10.1093/bioinformatics/bty560 + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information. Use 'single_end: true' to specify single ended or interleaved FASTQs. Use 'single_end: false' for paired-end reads. + e.g. [ id:'test', single_end:false ] + - reads: + type: file + description: | + List of input FastQ files of size 1 and 2 for single-end and paired-end data, + respectively. If you wish to run interleaved paired-end data, supply as single-end data + but with `--interleaved_in` in your `modules.conf`'s `ext.args` for the module. + - 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` + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - reads: + type: file + description: The trimmed/modified/unmerged fastq reads + pattern: "*fastp.fastq.gz" + - json: + type: file + description: Results in JSON format + pattern: "*.json" + - html: + type: file + description: Results in HTML format + pattern: "*.html" + - log: + type: file + description: fastq log file + pattern: "*.log" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + - reads_fail: + type: file + description: Reads the failed the preprocessing + pattern: "*fail.fastq.gz" + - reads_merged: + type: file + description: Reads that were successfully merged + pattern: "*.{merged.fastq.gz}" +authors: + - "@drpatelh" + - "@kevinmenden" diff --git a/nextflow.config b/nextflow.config index 40795723..6ea448aa 100644 --- a/nextflow.config +++ b/nextflow.config @@ -31,13 +31,13 @@ params { // Trimming options clip_r1 = null three_prime_clip_r1 = null - three_prime_adapter = "TGGAATTCTCGGGTGCCAAGG" + three_prime_adapter = '' min_length = 17 skip_qc = false skip_fastqc = false skip_multiqc = false skip_mirdeep = false - skip_trimming = false + skip_fastp = false save_reference = false trim_galore_max_length = 40 diff --git a/nextflow_schema.json b/nextflow_schema.json index 7d89945c..82c2ee86 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -10,7 +10,10 @@ "type": "object", "fa_icon": "fas fa-terminal", "description": "Define where the pipeline should find input data and save output data.", - "required": ["input", "outdir"], + "required": [ + "input", + "outdir" + ], "properties": { "input": { "type": "string", @@ -28,7 +31,13 @@ "fa_icon": "fas fa-vial", "description": "Protocol for constructing smRNA-seq libraries.", "help_text": "Presets for trimming parameters and 3' adapter sequence with a specified protocol.\n\n| Protocol | Library Prep Kit | Trimming Parameter | 3' Adapter Sequence |\n| :------------ | :-------------------------------------- | :-------------------------------------- | :--------------------- |\n| illumina | Illumina TruSeq Small RNA | `clip_r1 = 0` `three_prime_clip_r1 = 0` | `TGGAATTCTCGGGTGCCAAGG` |\n| nextflex | BIOO SCIENTIFIC NEXTFLEX Small RNA-Seq | `clip_r1 = 4` `three_prime_clip_r1 = 4` | `TGGAATTCTCGGGTGCCAAGG` |\n| qiaseq | QIAGEN QIAseq miRNA | `clip_r1 = 0` `three_prime_clip_r1 = 0` | `AACTGTAGGCACCATCAAT` |\n| cats | Diagenode CATS Small RNA-seq | `clip_r1 = 3` `three_prime_clip_r1 = 0` | `AAAAAAAAAAA` + `GATCGGAAGAGCACACGTCTG` (only polyA is used for trimming) |\n| custom | user defined | user defined | user defined |\n\n> NB: When running `--protocol custom` the user ***must define the 3' Adapter Sequence***.\n> If trimming parameters aren't provided the pipeline will deafult to `clip_R1 = 0` and `three_prime_clip_R1 = 0` (i.e. no extra clipping).", - "enum": ["illumina", "nextflex", "qiaseq", "cats", "custom"] + "enum": [ + "illumina", + "nextflex", + "qiaseq", + "cats", + "custom" + ] }, "outdir": { "type": "string", @@ -257,12 +266,6 @@ "fa_icon": "fas fa-fast-forward", "description": "Skip MultiQC", "default": false - }, - "skip_trimming": { - "type": "boolean", - "fa_icon": "fas fa-fast-forward", - "description": "Skip all trimming steps.", - "default": false } } }, @@ -368,7 +371,14 @@ "description": "Method used to save pipeline results to output directory.", "help_text": "The Nextflow `publishDir` option specifies which intermediate files should be saved to the output directory. This option tells the pipeline what method should be used to move these files. See [Nextflow docs](https://www.nextflow.io/docs/latest/process.html#publishdir) for details.", "fa_icon": "fas fa-copy", - "enum": ["symlink", "rellink", "link", "copy", "copyNoFollow", "move"], + "enum": [ + "symlink", + "rellink", + "link", + "copy", + "copyNoFollow", + "move" + ], "hidden": true }, "email_on_fail": { @@ -460,5 +470,11 @@ { "$ref": "#/definitions/generic_options" } - ] + ], + "properties": { + "skip_fastp": { + "type": "string", + "default": "false" + } + } } diff --git a/subworkflows/nf-core/fastp_fastqc.nf b/subworkflows/nf-core/fastp_fastqc.nf new file mode 100644 index 00000000..87edb94f --- /dev/null +++ b/subworkflows/nf-core/fastp_fastqc.nf @@ -0,0 +1,100 @@ +// +// Read QC and trimming +// + +include { FASTQC as FASTQC_RAW } from '../../modules/nf-core/modules/fastqc/main' +include { FASTQC as FASTQC_TRIM } from '../../modules/nf-core/modules/fastqc/main' +include { FASTP } from '../../modules/nf-core/modules/fastp/main' + +// +// Function that parses fastp json output file to get total number of reads after trimming +// +import groovy.json.JsonSlurper + +def getFastpReadsAfterFiltering(json_file) { + def Map json = (Map) new JsonSlurper().parseText(json_file.text).get('summary') + return json['after_filtering']['total_reads'].toInteger() +} + +workflow FASTQC_FASTP { + take: + reads // channel: [ val(meta), [ reads ] ] + save_trimmed_fail // value: boolean + save_merged // value: boolean + + + main: + + ch_versions = Channel.empty() + + fastqc_raw_html = Channel.empty() + fastqc_raw_zip = Channel.empty() + if (!params.skip_fastqc) { + FASTQC_RAW ( + reads + ) + fastqc_raw_html = FASTQC_RAW.out.html + fastqc_raw_zip = FASTQC_RAW.out.zip + ch_versions = ch_versions.mix(FASTQC_RAW.out.versions.first()) + } + + trim_reads = reads + trim_json = Channel.empty() + trim_html = Channel.empty() + trim_log = Channel.empty() + trim_reads_fail = Channel.empty() + trim_reads_merged = Channel.empty() + fastqc_trim_html = Channel.empty() + fastqc_trim_zip = Channel.empty() + if (!params.skip_fastp) { + FASTP ( + reads, + save_trimmed_fail, + save_merged + ) + trim_reads = FASTP.out.reads + trim_json = FASTP.out.json + trim_html = FASTP.out.html + trim_log = FASTP.out.log + trim_reads_fail = FASTP.out.reads_fail + trim_reads_merged = FASTP.out.reads_merged + ch_versions = ch_versions.mix(FASTP.out.versions.first()) + + // + // Filter empty FastQ files after adapter trimming so FastQC doesn't fail + // + trim_reads + .join(trim_json) + .map { + meta, reads, json -> + if (getFastpReadsAfterFiltering(json) > 0) { + [ meta, reads ] + } + } + .set { trim_reads } + + if (!params.skip_fastqc) { + FASTQC_TRIM ( + trim_reads + ) + fastqc_trim_html = FASTQC_TRIM.out.html + fastqc_trim_zip = FASTQC_TRIM.out.zip + ch_versions = ch_versions.mix(FASTQC_TRIM.out.versions.first()) + } + } + + emit: + reads = trim_reads // channel: [ val(meta), [ reads ] ] + trim_json // channel: [ val(meta), [ json ] ] + trim_html // channel: [ val(meta), [ html ] ] + trim_log // channel: [ val(meta), [ log ] ] + trim_reads_fail // channel: [ val(meta), [ fastq.gz ] ] + trim_reads_merged // channel: [ val(meta), [ fastq.gz ] ] + + fastqc_raw_html // channel: [ val(meta), [ html ] ] + fastqc_raw_zip // channel: [ val(meta), [ zip ] ] + fastqc_trim_html // channel: [ val(meta), [ html ] ] + fastqc_trim_zip // channel: [ val(meta), [ zip ] ] + + versions = ch_versions.ifEmpty(null) // channel: [ versions.yml ] +} diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index ca1b265e..4c8a1d96 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -57,7 +57,7 @@ if (!params.mirgenedb) { } include { INPUT_CHECK } from '../subworkflows/local/input_check' -include { FASTQC_TRIMGALORE } from '../subworkflows/nf-core/fastqc_trimgalore' +include { FASTP_FASTQC } from '../subworkflows/nf-core/fastp_fastqc' include { CONTAMINANT_FILTER } from '../subworkflows/local/contaminant_filter' include { MIRNA_QUANT } from '../subworkflows/local/mirna_quant' include { GENOME_QUANT } from '../subworkflows/local/genome_quant' @@ -74,7 +74,6 @@ include { MIRDEEP2 } from '../subworkflows/local/mirdeep2' // MODULE: Installed directly from nf-core/modules // include { CAT_FASTQ } from '../modules/nf-core/modules/cat/fastq/main' -include { FASTQC } from '../modules/nf-core/modules/fastqc/main' include { MULTIQC } from '../modules/nf-core/modules/multiqc/main' include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/modules/custom/dumpsoftwareversions/main' @@ -133,16 +132,18 @@ workflow SMRNASEQ { ch_versions = ch_versions.mix(MIRTRACE.out.versions.ifEmpty(null)) // - // SUBWORKFLOW: Read QC, extract UMI and trim adapters + // SUBWORKFLOW: Read QC and trim adapters // - FASTQC_TRIMGALORE ( + + (clip_r1, three_prime_clip_r1, three_prime_adapter) = WorkflowSmrnaseq.formatProtocol(params.protocol) + + FASTP_FASTQC ( ch_cat_fastq, - params.skip_fastqc || params.skip_qc, - params.skip_trimming + false ) - ch_versions = ch_versions.mix(FASTQC_TRIMGALORE.out.versions) + ch_versions = ch_versions.mix(FASTP_FASTQC.out.versions) - reads_for_mirna = FASTQC_TRIMGALORE.out.reads + reads_for_mirna = FASTP_FASTQC.out.reads // // SUBWORKFLOW: remove contaminants from reads // @@ -156,7 +157,7 @@ workflow SMRNASEQ { params.ncrna, params.pirna, params.other_contamination, - FASTQC_TRIMGALORE.out.reads + FASTP_FASTQC.out.reads ) reads_for_mirna = CONTAMINANT_FILTER.out.filtered_reads @@ -187,7 +188,7 @@ workflow SMRNASEQ { if (!params.skip_mirdeep) { MIRDEEP2 ( - FASTQC_TRIMGALORE.out.reads, + FASTP_FASTQC.out.reads, GENOME_QUANT.out.fasta, GENOME_QUANT.out.index.collect(), MIRNA_QUANT.out.fasta_hairpin, @@ -217,7 +218,8 @@ workflow SMRNASEQ { ch_multiqc_files = ch_multiqc_files.mix(ch_multiqc_custom_config.collect().ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) - ch_multiqc_files = ch_multiqc_files.mix(FASTQC_TRIMGALORE.out.fastqc_zip.collect{it[1]}.ifEmpty([])) + ch_multiqc_files = ch_multiqc_files.mix(FASTQC_FASTP.out.fastqc_raw_zip.collect{it[1]}.ifEmpty([])), + ch_multiqc_files = ch_multiqc_files.mix(FASTQC_FASTP.out.trim_json.collect{it[1]}.ifEmpty([])), ch_multiqc_files = ch_multiqc_files.mix(contamination_stats.collect().ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(MIRNA_QUANT.out.mature_stats.collect({it[1]}).ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(MIRNA_QUANT.out.hairpin_stats.collect({it[1]}).ifEmpty([])) From 4a15e26c82cdf05f26a53aaba9d2a75b34dfcf16 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 22 Sep 2022 14:37:19 +0000 Subject: [PATCH 030/215] Added fix for groovy replace --- conf/modules.config | 43 ++++++++++++++++++++++++++++++------- lib/WorkflowSmrnaseq.groovy | 31 +++++++++++--------------- nextflow.config | 5 +++-- workflows/smrnaseq.nf | 3 ++- 4 files changed, 53 insertions(+), 29 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 04d47b37..9fb5d7fc 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -89,29 +89,56 @@ process { if (!(params.skip_fastqc || params.skip_qc)) { process { - withName: '.*:FASTQC_TRIMGALORE:FASTQC' { + withName: '.*:FASTP_FASTQC:FASTQC' { ext.args = '--quiet' } } } -if (!params.skip_trimming) { +if (!params.skip_fastp) { process { - withName: '.*:FASTQC_TRIMGALORE:TRIMGALORE' { - ext.args = '--fastqc' + withName: 'FASTP' { + ext.args = [ "", + params.trim_fastq ?: "--disable_adapter_trimming", + params.clip_r1 > 0 ? "--trim_front1 ${params.clip_r1}" : "", // Remove bp from the 5' end of read 1. + params.three_prime_clip_r1 > 0 ? "--trim_tail1 ${params.three_prime_clip_r1}" : "", // Remove bp from the 3' end of read 1 AFTER adapter/quality trimming has been performed. + params.fastp_min_length > 0 ? "-l ${params.fastp_min_length}", + params.fastp_max_length > 0 ? "--max_len1 ${params.fastp_max_length}", + params.three_prime_adapter ? "--adapter_sequence ${params.three_prime_adapter}" + ].join(" ").trim() publishDir = [ [ - path: { "${params.outdir}/trimmed/fastqc" }, + path: { "${params.outdir}/fastp" }, mode: params.publish_dir_mode, - pattern: "*.{html,zip}" + pattern: "*.{json,html}" ], [ - path: { "${params.outdir}/trimmed" }, + path: { "${params.outdir}/fastp/log" }, mode: params.publish_dir_mode, - pattern: "*.{txt,fastq.gz}" + pattern: "*.log" + ], + [ + path: { "${params.outdir}/fastp" }, + mode: params.publish_dir_mode, + pattern: "*.fail.fastq.gz", + enabled: params.save_trimmed_fail ] ] } + + } + + if (!params.skip_fastqc) { + process { + withName: '.*:.*:FASTQC_FASTP:FASTQC_TRIM' { + ext.args = '--quiet' + publishDir = [ + path: { "${params.outdir}/fastqc/trim" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] + } + } } } diff --git a/lib/WorkflowSmrnaseq.groovy b/lib/WorkflowSmrnaseq.groovy index c1701ab5..f8ea2bfa 100755 --- a/lib/WorkflowSmrnaseq.groovy +++ b/lib/WorkflowSmrnaseq.groovy @@ -68,26 +68,21 @@ class WorkflowSmrnaseq { switch(protocol){ case 'illumina': - clip_r1 = 0 - three_prime_clip_r1 = 0 - three_prime_adapter = "TGGAATTCTCGGGTGCCAAGG" + params.replace("clip_r1", 0) + params.replace("three_prime_clip_r1",0) + params.replace("three_prime_adapter", "TGGAATTCTCGGGTGCCAAGG") case 'nextflex': - clip_r1 = 4 - three_prime_clip_r1 = 4 - three_prime_adapter = "TGGAATTCTCGGGTGCCAAGG" + params.replace("clip_r1", 4) + params.replace("three_prime_clip_r1", 4) + params.replace("three_prime_adapter", "TGGAATTCTCGGGTGCCAAGG") case 'qiaseq': - clip_r1 = 0 - three_prime_clip_r1 = 0 - three_prime_adapter = "AACTGTAGGCACCATCAAT" + params.replace("clip_r1",0) + params.replace("three_prime_clip_r1",0) + params.replace("three_prime_adapter","AACTGTAGGCACCATCAAT") case 'cats': - clip_r1 = 3 - three_prime_clip_r1 = 0 - three_prime_adapter = "AAAAAAAA" - case 'custom': - clip_r1 = params.clip_r1 - three_prime_clip_r1 = params.three_prime_clip_r1 - three_prime_adapter = params.three_prime_adapter - } - return [clip_r1, three_prime_clip_r1, three_prime_adapter] + params.replace("clip_r1",3) + params.replace("three_prime_clip_r1", 0) + params.replace("three_prime_adapter", "AAAAAAAA") + default: log.warn("No protocol specified, please ensure that you specified parameters for clipping/trimming or otherwise only auto-detection of adapters will be performed.") } } diff --git a/nextflow.config b/nextflow.config index 6ea448aa..28dbafbf 100644 --- a/nextflow.config +++ b/nextflow.config @@ -32,14 +32,15 @@ params { clip_r1 = null three_prime_clip_r1 = null three_prime_adapter = '' - min_length = 17 + trim_fastq = true + fastp_min_length = 17 skip_qc = false skip_fastqc = false skip_multiqc = false skip_mirdeep = false skip_fastp = false save_reference = false - trim_galore_max_length = 40 + fastp_max_length = 40 // Contamination filtering filter_contamination = false diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 4c8a1d96..28b870b0 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -135,12 +135,13 @@ workflow SMRNASEQ { // SUBWORKFLOW: Read QC and trim adapters // - (clip_r1, three_prime_clip_r1, three_prime_adapter) = WorkflowSmrnaseq.formatProtocol(params.protocol) + WorkflowSmrnaseq.formatProtocol(params.protocol) FASTP_FASTQC ( ch_cat_fastq, false ) + ch_versions = ch_versions.mix(FASTP_FASTQC.out.versions) reads_for_mirna = FASTP_FASTQC.out.reads From f8614894b9935d17128d9a83795339b0e856ab12 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 22 Sep 2022 14:46:24 +0000 Subject: [PATCH 031/215] Adjust configs --- conf/modules.config | 6 +++--- nextflow_schema.json | 24 ++++++++++++------------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 9fb5d7fc..fe7c83d4 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -102,9 +102,9 @@ if (!params.skip_fastp) { params.trim_fastq ?: "--disable_adapter_trimming", params.clip_r1 > 0 ? "--trim_front1 ${params.clip_r1}" : "", // Remove bp from the 5' end of read 1. params.three_prime_clip_r1 > 0 ? "--trim_tail1 ${params.three_prime_clip_r1}" : "", // Remove bp from the 3' end of read 1 AFTER adapter/quality trimming has been performed. - params.fastp_min_length > 0 ? "-l ${params.fastp_min_length}", - params.fastp_max_length > 0 ? "--max_len1 ${params.fastp_max_length}", - params.three_prime_adapter ? "--adapter_sequence ${params.three_prime_adapter}" + params.fastp_min_length > 0 ? "-l ${params.fastp_min_length}" : "", + params.fastp_max_length > 0 ? "--max_len1 ${params.fastp_max_length}" : "", + params.three_prime_adapter ? "--adapter_sequence ${params.three_prime_adapter}" : "" ].join(" ").trim() publishDir = [ [ diff --git a/nextflow_schema.json b/nextflow_schema.json index 82c2ee86..b82d7d6c 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -164,12 +164,6 @@ "description": "Options for trimming reads and primers.", "fa_icon": "fas fa-cut", "properties": { - "min_length": { - "type": "integer", - "default": 17, - "description": "Discard reads that are shorter than this after quality / adapter trimming.", - "fa_icon": "fas fa-ruler" - }, "clip_r1": { "type": "integer", "fa_icon": "fas fa-cut", @@ -185,12 +179,6 @@ "default": "TGGAATTCTCGGGTGCCAAGG", "fa_icon": "fas fa-text-width", "description": "Sequencing adapter sequence to use for trimming." - }, - "trim_galore_max_length": { - "type": "integer", - "default": 40, - "description": "The max-length parameter used for trimming with TrimGalore!.", - "fa_icon": "fas fa-ruler" } } }, @@ -475,6 +463,18 @@ "skip_fastp": { "type": "string", "default": "false" + }, + "trim_fastq": { + "type": "string", + "default": "true" + }, + "fastp_min_length": { + "type": "integer", + "default": 17 + }, + "fastp_max_length": { + "type": "integer", + "default": 40 } } } From a8ec05584fdf85bb9b520c0bdd78c6da8c9eb476 Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Thu, 22 Sep 2022 14:48:09 +0000 Subject: [PATCH 032/215] [automated] Fix linting with Prettier --- nextflow_schema.json | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/nextflow_schema.json b/nextflow_schema.json index b82d7d6c..1ab04811 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -10,10 +10,7 @@ "type": "object", "fa_icon": "fas fa-terminal", "description": "Define where the pipeline should find input data and save output data.", - "required": [ - "input", - "outdir" - ], + "required": ["input", "outdir"], "properties": { "input": { "type": "string", @@ -31,13 +28,7 @@ "fa_icon": "fas fa-vial", "description": "Protocol for constructing smRNA-seq libraries.", "help_text": "Presets for trimming parameters and 3' adapter sequence with a specified protocol.\n\n| Protocol | Library Prep Kit | Trimming Parameter | 3' Adapter Sequence |\n| :------------ | :-------------------------------------- | :-------------------------------------- | :--------------------- |\n| illumina | Illumina TruSeq Small RNA | `clip_r1 = 0` `three_prime_clip_r1 = 0` | `TGGAATTCTCGGGTGCCAAGG` |\n| nextflex | BIOO SCIENTIFIC NEXTFLEX Small RNA-Seq | `clip_r1 = 4` `three_prime_clip_r1 = 4` | `TGGAATTCTCGGGTGCCAAGG` |\n| qiaseq | QIAGEN QIAseq miRNA | `clip_r1 = 0` `three_prime_clip_r1 = 0` | `AACTGTAGGCACCATCAAT` |\n| cats | Diagenode CATS Small RNA-seq | `clip_r1 = 3` `three_prime_clip_r1 = 0` | `AAAAAAAAAAA` + `GATCGGAAGAGCACACGTCTG` (only polyA is used for trimming) |\n| custom | user defined | user defined | user defined |\n\n> NB: When running `--protocol custom` the user ***must define the 3' Adapter Sequence***.\n> If trimming parameters aren't provided the pipeline will deafult to `clip_R1 = 0` and `three_prime_clip_R1 = 0` (i.e. no extra clipping).", - "enum": [ - "illumina", - "nextflex", - "qiaseq", - "cats", - "custom" - ] + "enum": ["illumina", "nextflex", "qiaseq", "cats", "custom"] }, "outdir": { "type": "string", @@ -359,14 +350,7 @@ "description": "Method used to save pipeline results to output directory.", "help_text": "The Nextflow `publishDir` option specifies which intermediate files should be saved to the output directory. This option tells the pipeline what method should be used to move these files. See [Nextflow docs](https://www.nextflow.io/docs/latest/process.html#publishdir) for details.", "fa_icon": "fas fa-copy", - "enum": [ - "symlink", - "rellink", - "link", - "copy", - "copyNoFollow", - "move" - ], + "enum": ["symlink", "rellink", "link", "copy", "copyNoFollow", "move"], "hidden": true }, "email_on_fail": { From 6c0150b09f47695c584e9efb3b897f416de42c8f Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 22 Sep 2022 14:54:31 +0000 Subject: [PATCH 033/215] Fix missing params --- nextflow.config | 3 +- nextflow_schema.json | 71 ++++++++++++++++++++++++++++---------------- 2 files changed, 48 insertions(+), 26 deletions(-) diff --git a/nextflow.config b/nextflow.config index 28dbafbf..214d12bf 100644 --- a/nextflow.config +++ b/nextflow.config @@ -31,9 +31,10 @@ params { // Trimming options clip_r1 = null three_prime_clip_r1 = null - three_prime_adapter = '' + three_prime_adapter = null trim_fastq = true fastp_min_length = 17 + save_trimmed_fail = false skip_qc = false skip_fastqc = false skip_multiqc = false diff --git a/nextflow_schema.json b/nextflow_schema.json index 1ab04811..ce73b58a 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -10,7 +10,10 @@ "type": "object", "fa_icon": "fas fa-terminal", "description": "Define where the pipeline should find input data and save output data.", - "required": ["input", "outdir"], + "required": [ + "input", + "outdir" + ], "properties": { "input": { "type": "string", @@ -28,7 +31,13 @@ "fa_icon": "fas fa-vial", "description": "Protocol for constructing smRNA-seq libraries.", "help_text": "Presets for trimming parameters and 3' adapter sequence with a specified protocol.\n\n| Protocol | Library Prep Kit | Trimming Parameter | 3' Adapter Sequence |\n| :------------ | :-------------------------------------- | :-------------------------------------- | :--------------------- |\n| illumina | Illumina TruSeq Small RNA | `clip_r1 = 0` `three_prime_clip_r1 = 0` | `TGGAATTCTCGGGTGCCAAGG` |\n| nextflex | BIOO SCIENTIFIC NEXTFLEX Small RNA-Seq | `clip_r1 = 4` `three_prime_clip_r1 = 4` | `TGGAATTCTCGGGTGCCAAGG` |\n| qiaseq | QIAGEN QIAseq miRNA | `clip_r1 = 0` `three_prime_clip_r1 = 0` | `AACTGTAGGCACCATCAAT` |\n| cats | Diagenode CATS Small RNA-seq | `clip_r1 = 3` `three_prime_clip_r1 = 0` | `AAAAAAAAAAA` + `GATCGGAAGAGCACACGTCTG` (only polyA is used for trimming) |\n| custom | user defined | user defined | user defined |\n\n> NB: When running `--protocol custom` the user ***must define the 3' Adapter Sequence***.\n> If trimming parameters aren't provided the pipeline will deafult to `clip_R1 = 0` and `three_prime_clip_R1 = 0` (i.e. no extra clipping).", - "enum": ["illumina", "nextflex", "qiaseq", "cats", "custom"] + "enum": [ + "illumina", + "nextflex", + "qiaseq", + "cats", + "custom" + ] }, "outdir": { "type": "string", @@ -142,7 +151,6 @@ "igenomes_ignore": { "type": "boolean", "description": "Do not load the iGenomes reference config.", - "default": false, "fa_icon": "fas fa-ban", "help_text": "Do not load `igenomes.config` when running the pipeline. You may choose this option if you observe clashes between custom parameters and those supplied in `igenomes.config`.", "hidden": true @@ -170,6 +178,29 @@ "default": "TGGAATTCTCGGGTGCCAAGG", "fa_icon": "fas fa-text-width", "description": "Sequencing adapter sequence to use for trimming." + }, + "trim_fastq": { + "type": "string", + "default": "true", + "fa_icon": "fas fa-hand-scissors", + "description": "Trim FastQ files" + }, + "fastp_min_length": { + "type": "integer", + "default": 17, + "description": "Minimum filter length for raw reads.", + "fa_icon": "fas fa-ruler-horizontal" + }, + "fastp_max_length": { + "type": "integer", + "default": 40, + "description": "Maximum filter length for raw reads.", + "fa_icon": "fas fa-ruler-horizontal" + }, + "save_trimmed_fail": { + "type": "boolean", + "fa_icon": "fas fa-cloud-download-alt", + "description": "Save reads failing trimming" } } }, @@ -181,7 +212,6 @@ "properties": { "filter_contamination": { "type": "boolean", - "default": false, "description": "Enables the contamination filtering." }, "rrna": { @@ -225,26 +255,22 @@ "skip_qc": { "type": "boolean", "fa_icon": "fas fa-fast-forward", - "description": "Skip all QC steps", - "default": false + "description": "Skip all QC steps" }, "skip_fastqc": { "type": "boolean", "fa_icon": "fas fa-fast-forward", - "description": "Skip FastQC", - "default": false + "description": "Skip FastQC" }, "skip_mirdeep": { "type": "boolean", "fa_icon": "fas fa-fast-forward", - "description": "Skip miRDeep", - "default": false + "description": "Skip miRDeep" }, "skip_multiqc": { "type": "boolean", "fa_icon": "fas fa-fast-forward", - "description": "Skip MultiQC", - "default": false + "description": "Skip MultiQC" } } }, @@ -350,7 +376,14 @@ "description": "Method used to save pipeline results to output directory.", "help_text": "The Nextflow `publishDir` option specifies which intermediate files should be saved to the output directory. This option tells the pipeline what method should be used to move these files. See [Nextflow docs](https://www.nextflow.io/docs/latest/process.html#publishdir) for details.", "fa_icon": "fas fa-copy", - "enum": ["symlink", "rellink", "link", "copy", "copyNoFollow", "move"], + "enum": [ + "symlink", + "rellink", + "link", + "copy", + "copyNoFollow", + "move" + ], "hidden": true }, "email_on_fail": { @@ -447,18 +480,6 @@ "skip_fastp": { "type": "string", "default": "false" - }, - "trim_fastq": { - "type": "string", - "default": "true" - }, - "fastp_min_length": { - "type": "integer", - "default": 17 - }, - "fastp_max_length": { - "type": "integer", - "default": 40 } } } From b9e500aba94eda094b56efbb54405e4666c86f38 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 22 Sep 2022 15:02:19 +0000 Subject: [PATCH 034/215] Fix schema --- nextflow_schema.json | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/nextflow_schema.json b/nextflow_schema.json index ce73b58a..81a320aa 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -180,8 +180,8 @@ "description": "Sequencing adapter sequence to use for trimming." }, "trim_fastq": { - "type": "string", - "default": "true", + "type": "boolean", + "default": true, "fa_icon": "fas fa-hand-scissors", "description": "Trim FastQ files" }, @@ -271,6 +271,11 @@ "type": "boolean", "fa_icon": "fas fa-fast-forward", "description": "Skip MultiQC" + }, + "skip_fastp": { + "type": "boolean", + "description": "Skip FastP", + "fa_icon": "fas fa-forward" } } }, @@ -475,11 +480,5 @@ { "$ref": "#/definitions/generic_options" } - ], - "properties": { - "skip_fastp": { - "type": "string", - "default": "false" - } - } + ] } From b59d3e7c734249bbae6f3c4491a35237c460a49d Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 22 Sep 2022 15:12:47 +0000 Subject: [PATCH 035/215] Adjust tests, add public statement --- conf/test.config | 1 + conf/test_full.config | 1 + lib/WorkflowSmrnaseq.groovy | 5 +---- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/conf/test.config b/conf/test.config index b4facb58..518ced5f 100644 --- a/conf/test.config +++ b/conf/test.config @@ -27,6 +27,7 @@ params { hairpin = 'https://github.com/nf-core/test-datasets/raw/smrnaseq/reference/hairpin.fa' mirna_gtf = 'https://github.com/nf-core/test-datasets/raw/smrnaseq/reference/hsa.gff3' mirtrace_species = 'hsa' + protocol = 'illumina' skip_mirdeep = true } diff --git a/conf/test_full.config b/conf/test_full.config index cc5ecd92..964dc5b2 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -18,6 +18,7 @@ params { input = 'https://github.com/nf-core/test-datasets/raw/smrnaseq/samplesheet/v2.0/samplesheet-full.csv' genome = 'GRCh37' mirtrace_species = 'hsa' + protocol = 'illumina' } diff --git a/lib/WorkflowSmrnaseq.groovy b/lib/WorkflowSmrnaseq.groovy index f8ea2bfa..877fbda6 100755 --- a/lib/WorkflowSmrnaseq.groovy +++ b/lib/WorkflowSmrnaseq.groovy @@ -61,10 +61,7 @@ class WorkflowSmrnaseq { * this function formats the protocol such that it is fit for the respective * subworkflow */ - static formatProtocol(protocol) { - Int clip_r1 = protocol - Int three_prime_clip_r1 = '' - String three_prime_adapter = '' + public static void formatProtocol(protocol) { switch(protocol){ case 'illumina': From 1803adc7e6acfd688730ac96bb2a71f6af849bc2 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 22 Sep 2022 15:18:51 +0000 Subject: [PATCH 036/215] Adjust groovy functionality --- lib/WorkflowSmrnaseq.groovy | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/lib/WorkflowSmrnaseq.groovy b/lib/WorkflowSmrnaseq.groovy index 877fbda6..615b1cc9 100755 --- a/lib/WorkflowSmrnaseq.groovy +++ b/lib/WorkflowSmrnaseq.groovy @@ -64,22 +64,27 @@ class WorkflowSmrnaseq { public static void formatProtocol(protocol) { switch(protocol){ + log.info "Running with Protocol ${params.protocol} \n Clipping ${params.clip_r1} bases \n Clipping ${params.three_prime_clip_r1} 3' bases \n with Adapter ${params.three_prime_adapter}" case 'illumina': - params.replace("clip_r1", 0) - params.replace("three_prime_clip_r1",0) - params.replace("three_prime_adapter", "TGGAATTCTCGGGTGCCAAGG") + params.replace("clip_r1", 0); + params.replace("three_prime_clip_r1",0); + params.replace("three_prime_adapter", "TGGAATTCTCGGGTGCCAAGG"); + break case 'nextflex': - params.replace("clip_r1", 4) - params.replace("three_prime_clip_r1", 4) - params.replace("three_prime_adapter", "TGGAATTCTCGGGTGCCAAGG") + params.replace("clip_r1", 4); + params.replace("three_prime_clip_r1", 4); + params.replace("three_prime_adapter", "TGGAATTCTCGGGTGCCAAGG"); + break case 'qiaseq': - params.replace("clip_r1",0) - params.replace("three_prime_clip_r1",0) - params.replace("three_prime_adapter","AACTGTAGGCACCATCAAT") + params.replace("clip_r1",0); + params.replace("three_prime_clip_r1",0); + params.replace("three_prime_adapter","AACTGTAGGCACCATCAAT"); + break case 'cats': - params.replace("clip_r1",3) - params.replace("three_prime_clip_r1", 0) - params.replace("three_prime_adapter", "AAAAAAAA") + params.replace("clip_r1",3); + params.replace("three_prime_clip_r1", 0); + params.replace("three_prime_adapter", "AAAAAAAA"); + break default: log.warn("No protocol specified, please ensure that you specified parameters for clipping/trimming or otherwise only auto-detection of adapters will be performed.") } } From 3246932cf0d7f44749d728e4377e6272bc999ec1 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 22 Sep 2022 15:44:18 +0000 Subject: [PATCH 037/215] Conf not fully there --- conf/modules.config | 2 +- lib/WorkflowMain.groovy | 3 +++ lib/WorkflowSmrnaseq.groovy | 8 ++++---- .../nf-core/{fastp_fastqc.nf => fastqc_fastp.nf} | 0 workflows/smrnaseq.nf | 15 +++++++-------- 5 files changed, 15 insertions(+), 13 deletions(-) rename subworkflows/nf-core/{fastp_fastqc.nf => fastqc_fastp.nf} (100%) diff --git a/conf/modules.config b/conf/modules.config index fe7c83d4..30a4d558 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -89,7 +89,7 @@ process { if (!(params.skip_fastqc || params.skip_qc)) { process { - withName: '.*:FASTP_FASTQC:FASTQC' { + withName: '.*:FASTP_FASTQC:FASTQC_*' { ext.args = '--quiet' } } diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index ce87a8d8..0e509e5d 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -77,6 +77,9 @@ class WorkflowMain { log.error "Please provide an input samplesheet to the pipeline e.g. '--input samplesheet.csv'" System.exit(1) } + + //Detect Protocol setting + WorkflowSmrnaseq.formatProtocol(params,log) } // // Get attribute from genome config file e.g. fasta diff --git a/lib/WorkflowSmrnaseq.groovy b/lib/WorkflowSmrnaseq.groovy index 615b1cc9..7551b441 100755 --- a/lib/WorkflowSmrnaseq.groovy +++ b/lib/WorkflowSmrnaseq.groovy @@ -61,10 +61,10 @@ class WorkflowSmrnaseq { * this function formats the protocol such that it is fit for the respective * subworkflow */ - public static void formatProtocol(protocol) { + public static String formatProtocol(params,log) { - switch(protocol){ - log.info "Running with Protocol ${params.protocol} \n Clipping ${params.clip_r1} bases \n Clipping ${params.three_prime_clip_r1} 3' bases \n with Adapter ${params.three_prime_adapter}" + switch(params.protocol){ + //log.warn("Running with Protocol ${params.protocol} \n Clipping ${params.clip_r1} bases \n Clipping ${params.three_prime_clip_r1} 3' bases \n with Adapter ${params.three_prime_adapter}") case 'illumina': params.replace("clip_r1", 0); params.replace("three_prime_clip_r1",0); @@ -85,6 +85,6 @@ class WorkflowSmrnaseq { params.replace("three_prime_clip_r1", 0); params.replace("three_prime_adapter", "AAAAAAAA"); break - default: log.warn("No protocol specified, please ensure that you specified parameters for clipping/trimming or otherwise only auto-detection of adapters will be performed.") + } } } diff --git a/subworkflows/nf-core/fastp_fastqc.nf b/subworkflows/nf-core/fastqc_fastp.nf similarity index 100% rename from subworkflows/nf-core/fastp_fastqc.nf rename to subworkflows/nf-core/fastqc_fastp.nf diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 28b870b0..816a1fe7 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -57,7 +57,7 @@ if (!params.mirgenedb) { } include { INPUT_CHECK } from '../subworkflows/local/input_check' -include { FASTP_FASTQC } from '../subworkflows/nf-core/fastp_fastqc' +include { FASTQC_FASTP } from '../subworkflows/nf-core/fastqc_fastp' include { CONTAMINANT_FILTER } from '../subworkflows/local/contaminant_filter' include { MIRNA_QUANT } from '../subworkflows/local/mirna_quant' include { GENOME_QUANT } from '../subworkflows/local/genome_quant' @@ -135,16 +135,15 @@ workflow SMRNASEQ { // SUBWORKFLOW: Read QC and trim adapters // - WorkflowSmrnaseq.formatProtocol(params.protocol) - - FASTP_FASTQC ( + FASTQC_FASTP ( ch_cat_fastq, + false, false ) - ch_versions = ch_versions.mix(FASTP_FASTQC.out.versions) + ch_versions = ch_versions.mix(FASTQC_FASTP.out.versions) - reads_for_mirna = FASTP_FASTQC.out.reads + reads_for_mirna = FASTQC_FASTP.out.reads // // SUBWORKFLOW: remove contaminants from reads // @@ -158,7 +157,7 @@ workflow SMRNASEQ { params.ncrna, params.pirna, params.other_contamination, - FASTP_FASTQC.out.reads + FASTQC_FASTP.out.reads ) reads_for_mirna = CONTAMINANT_FILTER.out.filtered_reads @@ -189,7 +188,7 @@ workflow SMRNASEQ { if (!params.skip_mirdeep) { MIRDEEP2 ( - FASTP_FASTQC.out.reads, + FASTQC_FASTP.out.reads, GENOME_QUANT.out.fasta, GENOME_QUANT.out.index.collect(), MIRNA_QUANT.out.fasta_hairpin, From 21b8aa8f50073dae5ba98405944a3a26d534e982 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 22 Sep 2022 15:52:56 +0000 Subject: [PATCH 038/215] Explicit conf --- conf/modules.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/modules.config b/conf/modules.config index 30a4d558..091b87a2 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -99,7 +99,7 @@ if (!params.skip_fastp) { process { withName: 'FASTP' { ext.args = [ "", - params.trim_fastq ?: "--disable_adapter_trimming", + params.trim_fastq ? "" : "--disable_adapter_trimming", params.clip_r1 > 0 ? "--trim_front1 ${params.clip_r1}" : "", // Remove bp from the 5' end of read 1. params.three_prime_clip_r1 > 0 ? "--trim_tail1 ${params.three_prime_clip_r1}" : "", // Remove bp from the 3' end of read 1 AFTER adapter/quality trimming has been performed. params.fastp_min_length > 0 ? "-l ${params.fastp_min_length}" : "", From fe231d8a044ffe14d2f8ebd4dc2fe01ad0455e04 Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Thu, 22 Sep 2022 15:53:44 +0000 Subject: [PATCH 039/215] [automated] Fix linting with Prettier --- nextflow_schema.json | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/nextflow_schema.json b/nextflow_schema.json index 81a320aa..7f95c921 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -10,10 +10,7 @@ "type": "object", "fa_icon": "fas fa-terminal", "description": "Define where the pipeline should find input data and save output data.", - "required": [ - "input", - "outdir" - ], + "required": ["input", "outdir"], "properties": { "input": { "type": "string", @@ -31,13 +28,7 @@ "fa_icon": "fas fa-vial", "description": "Protocol for constructing smRNA-seq libraries.", "help_text": "Presets for trimming parameters and 3' adapter sequence with a specified protocol.\n\n| Protocol | Library Prep Kit | Trimming Parameter | 3' Adapter Sequence |\n| :------------ | :-------------------------------------- | :-------------------------------------- | :--------------------- |\n| illumina | Illumina TruSeq Small RNA | `clip_r1 = 0` `three_prime_clip_r1 = 0` | `TGGAATTCTCGGGTGCCAAGG` |\n| nextflex | BIOO SCIENTIFIC NEXTFLEX Small RNA-Seq | `clip_r1 = 4` `three_prime_clip_r1 = 4` | `TGGAATTCTCGGGTGCCAAGG` |\n| qiaseq | QIAGEN QIAseq miRNA | `clip_r1 = 0` `three_prime_clip_r1 = 0` | `AACTGTAGGCACCATCAAT` |\n| cats | Diagenode CATS Small RNA-seq | `clip_r1 = 3` `three_prime_clip_r1 = 0` | `AAAAAAAAAAA` + `GATCGGAAGAGCACACGTCTG` (only polyA is used for trimming) |\n| custom | user defined | user defined | user defined |\n\n> NB: When running `--protocol custom` the user ***must define the 3' Adapter Sequence***.\n> If trimming parameters aren't provided the pipeline will deafult to `clip_R1 = 0` and `three_prime_clip_R1 = 0` (i.e. no extra clipping).", - "enum": [ - "illumina", - "nextflex", - "qiaseq", - "cats", - "custom" - ] + "enum": ["illumina", "nextflex", "qiaseq", "cats", "custom"] }, "outdir": { "type": "string", @@ -381,14 +372,7 @@ "description": "Method used to save pipeline results to output directory.", "help_text": "The Nextflow `publishDir` option specifies which intermediate files should be saved to the output directory. This option tells the pipeline what method should be used to move these files. See [Nextflow docs](https://www.nextflow.io/docs/latest/process.html#publishdir) for details.", "fa_icon": "fas fa-copy", - "enum": [ - "symlink", - "rellink", - "link", - "copy", - "copyNoFollow", - "move" - ], + "enum": ["symlink", "rellink", "link", "copy", "copyNoFollow", "move"], "hidden": true }, "email_on_fail": { From 853397e4cf69e15f77ebf96d132930439b0e4839 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 22 Sep 2022 16:00:07 +0000 Subject: [PATCH 040/215] Add a protocol to running the pipeline --- conf/test_no_genome.config | 1 + 1 file changed, 1 insertion(+) diff --git a/conf/test_no_genome.config b/conf/test_no_genome.config index 8724f431..485870de 100644 --- a/conf/test_no_genome.config +++ b/conf/test_no_genome.config @@ -26,5 +26,6 @@ params { mirna_gtf = 'https://github.com/nf-core/test-datasets/raw/smrnaseq-better-input/reference/hsa.gff3' mirtrace_species = 'hsa' skip_mirdeep = true + protocol = 'illumina' } From 0224ede0b111d56904ec00a7b19203a975f37933 Mon Sep 17 00:00:00 2001 From: Rob Syme Date: Thu, 22 Sep 2022 16:16:50 +0000 Subject: [PATCH 041/215] Process selector name fix --- conf/modules.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/modules.config b/conf/modules.config index 091b87a2..c47b5fea 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -89,7 +89,7 @@ process { if (!(params.skip_fastqc || params.skip_qc)) { process { - withName: '.*:FASTP_FASTQC:FASTQC_*' { + withName: '.*:FASTQC_FASTP:FASTQC_.*' { ext.args = '--quiet' } } From 6a295bbd1b55af283aa1241b6bab769a60cfbf3b Mon Sep 17 00:00:00 2001 From: Rob Syme Date: Thu, 22 Sep 2022 23:00:28 +0000 Subject: [PATCH 042/215] Ensure that pigz works for fq and fastq extensions --- modules/local/mirdeep2_prepare.nf | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/local/mirdeep2_prepare.nf b/modules/local/mirdeep2_prepare.nf index a62a5845..d49270ff 100644 --- a/modules/local/mirdeep2_prepare.nf +++ b/modules/local/mirdeep2_prepare.nf @@ -12,11 +12,10 @@ process MIRDEEP2_PIGZ { tuple val(meta), path(reads) output: - tuple val(meta), path("*.fq"), emit: reads - path "versions.yml" , emit: versions + tuple val(meta), path("*.{fastq,fq}"), emit: reads + path "versions.yml" , emit: versions script: - def unzip = reads.toString() - '.gz' """ pigz -f -d -p $task.cpus $reads From 56a67eebca604bc344feb37d9301aea972d9f00c Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 23 Sep 2022 11:39:04 +0000 Subject: [PATCH 043/215] Removed trimgalore --- modules.json | 4 - modules/nf-core/modules/trimgalore/main.nf | 86 --------------------- modules/nf-core/modules/trimgalore/meta.yml | 64 --------------- 3 files changed, 154 deletions(-) delete mode 100644 modules/nf-core/modules/trimgalore/main.nf delete mode 100644 modules/nf-core/modules/trimgalore/meta.yml diff --git a/modules.json b/modules.json index 7c426975..9ca284a9 100644 --- a/modules.json +++ b/modules.json @@ -44,10 +44,6 @@ "samtools/stats": { "branch": "master", "git_sha": "f4eab7945952dc4934224309701a49913ea05ae6" - }, - "trimgalore": { - "branch": "master", - "git_sha": "85ec13ff1fc2196c5a507ea497de468101baabed" } } } diff --git a/modules/nf-core/modules/trimgalore/main.nf b/modules/nf-core/modules/trimgalore/main.nf deleted file mode 100644 index 3a3fca90..00000000 --- a/modules/nf-core/modules/trimgalore/main.nf +++ /dev/null @@ -1,86 +0,0 @@ -process TRIMGALORE { - tag "$meta.id" - label 'process_high' - - conda (params.enable_conda ? 'bioconda::trim-galore=0.6.7' : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/trim-galore:0.6.7--hdfd78af_0' : - 'quay.io/biocontainers/trim-galore:0.6.7--hdfd78af_0' }" - - input: - tuple val(meta), path(reads) - - output: - tuple val(meta), path("*{trimmed,val}*.fq.gz"), emit: reads - tuple val(meta), path("*report.txt") , emit: log - path "versions.yml" , emit: versions - - tuple val(meta), path("*unpaired*.fq.gz") , emit: unpaired, optional: true - tuple val(meta), path("*.html") , emit: html , optional: true - tuple val(meta), path("*.zip") , emit: zip , optional: true - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - // Calculate number of --cores for TrimGalore based on value of task.cpus - // See: https://github.com/FelixKrueger/TrimGalore/blob/master/Changelog.md#version-060-release-on-1-mar-2019 - // See: https://github.com/nf-core/atacseq/pull/65 - def cores = 1 - if (task.cpus) { - cores = (task.cpus as int) - 4 - if (meta.single_end) cores = (task.cpus as int) - 3 - if (cores < 1) cores = 1 - if (cores > 4) cores = 4 - } - - // Clipping presets have to be evaluated in the context of SE/PE - def c_r1 = params.clip_r1 > 0 ? "--clip_r1 ${params.clip_r1}" : '' - def c_r2 = params.clip_r2 > 0 ? "--clip_r2 ${params.clip_r2}" : '' - def tpc_r1 = params.three_prime_clip_r1 > 0 ? "--three_prime_clip_r1 ${params.three_prime_clip_r1}" : '' - def tpc_r2 = params.three_prime_clip_r2 > 0 ? "--three_prime_clip_r2 ${params.three_prime_clip_r2}" : '' - - // Added soft-links to original fastqs for consistent naming in MultiQC - def prefix = task.ext.prefix ?: "${meta.id}" - if (meta.single_end) { - """ - [ ! -f ${prefix}.fastq.gz ] && ln -s $reads ${prefix}.fastq.gz - trim_galore \\ - $args \\ - --cores $cores \\ - --gzip \\ - $c_r1 \\ - $tpc_r1 \\ - ${prefix}.fastq.gz - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - trimgalore: \$(echo \$(trim_galore --version 2>&1) | sed 's/^.*version //; s/Last.*\$//') - cutadapt: \$(cutadapt --version) - END_VERSIONS - """ - } else { - """ - [ ! -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 - trim_galore \\ - $args \\ - --cores $cores \\ - --paired \\ - --gzip \\ - $c_r1 \\ - $c_r2 \\ - $tpc_r1 \\ - $tpc_r2 \\ - ${prefix}_1.fastq.gz \\ - ${prefix}_2.fastq.gz - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - trimgalore: \$(echo \$(trim_galore --version 2>&1) | sed 's/^.*version //; s/Last.*\$//') - cutadapt: \$(cutadapt --version) - END_VERSIONS - """ - } -} diff --git a/modules/nf-core/modules/trimgalore/meta.yml b/modules/nf-core/modules/trimgalore/meta.yml deleted file mode 100644 index 439f566d..00000000 --- a/modules/nf-core/modules/trimgalore/meta.yml +++ /dev/null @@ -1,64 +0,0 @@ -name: trimgalore -description: Trim FastQ files using Trim Galore! -keywords: - - trimming - - adapters - - sequencing adapters - - fastq -tools: - - trimgalore: - description: | - A wrapper tool around Cutadapt and FastQC to consistently apply quality - and adapter trimming to FastQ files, with some extra functionality for - MspI-digested RRBS-type (Reduced Representation Bisufite-Seq) libraries. - homepage: https://www.bioinformatics.babraham.ac.uk/projects/trim_galore/ - documentation: https://github.com/FelixKrueger/TrimGalore/blob/master/Docs/Trim_Galore_User_Guide.md - licence: ["GPL-3.0-or-later"] -input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - reads: - type: file - description: | - List of input FastQ files of size 1 and 2 for single-end and paired-end data, - respectively. -output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - reads: - type: file - description: | - List of input adapter trimmed FastQ files of size 1 and 2 for - single-end and paired-end data, respectively. - pattern: "*.{fq.gz}" - - unpaired: - type: file - description: | - FastQ files containing unpaired reads from read 1 or read 2 - pattern: "*unpaired*.fq.gz" - - html: - type: file - description: FastQC report (optional) - pattern: "*_{fastqc.html}" - - zip: - type: file - description: FastQC report archive (optional) - pattern: "*_{fastqc.zip}" - - log: - type: file - description: Trim Galore! trimming report - pattern: "*_{report.txt}" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" -authors: - - "@drpatelh" - - "@ewels" - - "@FelixKrueger" From de95d049525510966c8a961a12e5e87cb768dc0c Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 23 Sep 2022 11:40:22 +0000 Subject: [PATCH 044/215] Adjust setting protocol early on in workflow --- lib/WorkflowMain.groovy | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 0e509e5d..f092760b 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -46,6 +46,10 @@ class WorkflowMain { // Validate parameters and print summary to screen // public static void initialise(workflow, params, log) { + + //Detect Protocol setting, set this early before help so help shows proper adapters etc pp + WorkflowSmrnaseq.formatProtocol(params,log) + // Print help to screen if required if (params.help) { log.info help(workflow, params, log) @@ -78,8 +82,6 @@ class WorkflowMain { System.exit(1) } - //Detect Protocol setting - WorkflowSmrnaseq.formatProtocol(params,log) } // // Get attribute from genome config file e.g. fasta From 5989773f2516e051d4e2d47442a6e29a50990e23 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 23 Sep 2022 13:39:10 +0000 Subject: [PATCH 045/215] More helpful error messages --- conf/modules.config | 2 +- lib/WorkflowSmrnaseq.groovy | 50 ++++++++++++++++++++----------------- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index c47b5fea..02237e06 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -104,7 +104,7 @@ if (!params.skip_fastp) { params.three_prime_clip_r1 > 0 ? "--trim_tail1 ${params.three_prime_clip_r1}" : "", // Remove bp from the 3' end of read 1 AFTER adapter/quality trimming has been performed. params.fastp_min_length > 0 ? "-l ${params.fastp_min_length}" : "", params.fastp_max_length > 0 ? "--max_len1 ${params.fastp_max_length}" : "", - params.three_prime_adapter ? "--adapter_sequence ${params.three_prime_adapter}" : "" + params.three_prime_adapter != null ? "--adapter_sequence ${params.three_prime_adapter}" : "" ].join(" ").trim() publishDir = [ [ diff --git a/lib/WorkflowSmrnaseq.groovy b/lib/WorkflowSmrnaseq.groovy index 7551b441..6d530271 100755 --- a/lib/WorkflowSmrnaseq.groovy +++ b/lib/WorkflowSmrnaseq.groovy @@ -63,28 +63,32 @@ class WorkflowSmrnaseq { */ public static String formatProtocol(params,log) { - switch(params.protocol){ - //log.warn("Running with Protocol ${params.protocol} \n Clipping ${params.clip_r1} bases \n Clipping ${params.three_prime_clip_r1} 3' bases \n with Adapter ${params.three_prime_adapter}") - case 'illumina': - params.replace("clip_r1", 0); - params.replace("three_prime_clip_r1",0); - params.replace("three_prime_adapter", "TGGAATTCTCGGGTGCCAAGG"); - break - case 'nextflex': - params.replace("clip_r1", 4); - params.replace("three_prime_clip_r1", 4); - params.replace("three_prime_adapter", "TGGAATTCTCGGGTGCCAAGG"); - break - case 'qiaseq': - params.replace("clip_r1",0); - params.replace("three_prime_clip_r1",0); - params.replace("three_prime_adapter","AACTGTAGGCACCATCAAT"); - break - case 'cats': - params.replace("clip_r1",3); - params.replace("three_prime_clip_r1", 0); - params.replace("three_prime_adapter", "AAAAAAAA"); - break + switch(params.protocol){ + case 'illumina': + params.replace("clip_r1", 0); + params.replace("three_prime_clip_r1",0); + params.replace("three_prime_adapter", "TGGAATTCTCGGGTGCCAAGG"); + break + case 'nextflex': + params.replace("clip_r1", 4); + params.replace("three_prime_clip_r1", 4); + params.replace("three_prime_adapter", "TGGAATTCTCGGGTGCCAAGG"); + break + case 'qiaseq': + params.replace("clip_r1",0); + params.replace("three_prime_clip_r1",0); + params.replace("three_prime_adapter","AACTGTAGGCACCATCAAT"); + break + case 'cats': + params.replace("clip_r1",3); + params.replace("three_prime_clip_r1", 0); + params.replace("three_prime_adapter", "AAAAAAAA"); + break } - } + + log.warn "Running with Protocol ${params.protocol}" + log.warn "Therefore using Adapter: ${params.three_prime_adapter}" + log.warn "Clipping ${params.clip_r1} bases from R1" + log.warn "And clipping ${params.three_prime_clip_r1} bases from 3' end" + } } From 23f1ea25e3c8b7846e3dc7679f08dcb1322f183d Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 23 Sep 2022 13:48:00 +0000 Subject: [PATCH 046/215] Working default --- nextflow.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow.config b/nextflow.config index 214d12bf..09417e42 100644 --- a/nextflow.config +++ b/nextflow.config @@ -31,7 +31,7 @@ params { // Trimming options clip_r1 = null three_prime_clip_r1 = null - three_prime_adapter = null + three_prime_adapter = "TGGAATTCTCGGGTGCCAAGG" trim_fastq = true fastp_min_length = 17 save_trimmed_fail = false From f6ac76100334319c4f4ce6a34f64a00f964ec58c Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 23 Sep 2022 13:49:58 +0000 Subject: [PATCH 047/215] Proper default settings, should allow overriding with "" --- conf/modules.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/modules.config b/conf/modules.config index 02237e06..189e3011 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -104,7 +104,7 @@ if (!params.skip_fastp) { params.three_prime_clip_r1 > 0 ? "--trim_tail1 ${params.three_prime_clip_r1}" : "", // Remove bp from the 3' end of read 1 AFTER adapter/quality trimming has been performed. params.fastp_min_length > 0 ? "-l ${params.fastp_min_length}" : "", params.fastp_max_length > 0 ? "--max_len1 ${params.fastp_max_length}" : "", - params.three_prime_adapter != null ? "--adapter_sequence ${params.three_prime_adapter}" : "" + params.three_prime_adapter.isEmpty() ? "" : "--adapter_sequence ${params.three_prime_adapter}" ].join(" ").trim() publishDir = [ [ From 8cb032d7189d13ee51b06fd9ccbd82f651f2dbec Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 23 Sep 2022 13:54:31 +0000 Subject: [PATCH 048/215] Better for custom profiles --- lib/WorkflowSmrnaseq.groovy | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/WorkflowSmrnaseq.groovy b/lib/WorkflowSmrnaseq.groovy index 6d530271..d2d1d66a 100755 --- a/lib/WorkflowSmrnaseq.groovy +++ b/lib/WorkflowSmrnaseq.groovy @@ -84,6 +84,8 @@ class WorkflowSmrnaseq { params.replace("three_prime_clip_r1", 0); params.replace("three_prime_adapter", "AAAAAAAA"); break + default: + log.warn "Please make sure to specify all required clipping and trimming parameters, otherwise only adapter detection will be performed." } log.warn "Running with Protocol ${params.protocol}" From 08ead6c74d6da537cebd0134cdcab3b37e3f9021 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 23 Sep 2022 14:44:11 +0000 Subject: [PATCH 049/215] Add changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08ee6520..73b0b8ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [[#161](https://github.com/nf-core/smrnaseq/issues/161)] - Trimmed output was not as documented and not correctly published - [[#168](https://github.com/nf-core/smrnaseq/issues/168)] - Removed `mirtrace_protocol` as the parameter was redundant and `params.protocol` is entirely sufficient - Updated pipeline template to [nf-core/tools 2.5.1](https://github.com/nf-core/tools/releases/tag/2.5.1) +- [[#188](https://github.com/nf-core/smrnaseq/pull/188)] - Dropped TrimGalore in favor of fastp QC and adapter trimming, improved handling of adapters and trimming parameters ### Parameters From 75e5e40917a3e3c2cbe1d57f94e53a990fb66c6d Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 23 Sep 2022 14:54:37 +0000 Subject: [PATCH 050/215] Add some details on how to use custom properly --- docs/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index ebcd6c15..bbaeeca6 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -16,7 +16,7 @@ This option indicates the experimental protocol used for the sample preparation. - 'cats': adapter (`GATCGGAAGAGCACACGTCTG), clip_r1(`3) - 'custom' (where the user can indicate the `three_prime_adapter`, `clip_r1` and `three_prime_clip_r1` manually) -:warning: At least the `custom` protocol has to be specified, otherwise the pipeline won't run. +:warning: At least the `custom` protocol has to be specified, otherwise the pipeline won't run. In case you specify the `custom` protocol, ensure that the parameters above are set accordingly or the defaults will be applied. If you want to auto-detect the adapters using `fastp`, please set `--three_prime_adapter` to `""`. ### `mirtrace_species` or `mirgenedb_species` From 47a8ebd90922ca11e0d3116641cea765a725f055 Mon Sep 17 00:00:00 2001 From: Rob Syme Date: Sun, 2 Oct 2022 04:01:21 +0000 Subject: [PATCH 051/215] Ensure users can override params set by protocol --- lib/WorkflowSmrnaseq.groovy | 24 ++++++++++++------------ modules/local/mirtrace.nf | 18 ++---------------- 2 files changed, 14 insertions(+), 28 deletions(-) diff --git a/lib/WorkflowSmrnaseq.groovy b/lib/WorkflowSmrnaseq.groovy index d2d1d66a..cfcb9abd 100755 --- a/lib/WorkflowSmrnaseq.groovy +++ b/lib/WorkflowSmrnaseq.groovy @@ -65,24 +65,24 @@ class WorkflowSmrnaseq { switch(params.protocol){ case 'illumina': - params.replace("clip_r1", 0); - params.replace("three_prime_clip_r1",0); - params.replace("three_prime_adapter", "TGGAATTCTCGGGTGCCAAGG"); + params.putIfAbsent("clip_r1", 1); + params.putIfAbsent("three_prime_clip_r1",2); + params.putIfAbsent("three_prime_adapter", "TGGAATTCTCGGGTGCCAAGG"); break case 'nextflex': - params.replace("clip_r1", 4); - params.replace("three_prime_clip_r1", 4); - params.replace("three_prime_adapter", "TGGAATTCTCGGGTGCCAAGG"); + params.putIfAbsent("clip_r1", 4); + params.putIfAbsent("three_prime_clip_r1", 4); + params.putIfAbsent("three_prime_adapter", "TGGAATTCTCGGGTGCCAAGG"); break case 'qiaseq': - params.replace("clip_r1",0); - params.replace("three_prime_clip_r1",0); - params.replace("three_prime_adapter","AACTGTAGGCACCATCAAT"); + params.putIfAbsent("clip_r1",0); + params.putIfAbsent("three_prime_clip_r1",0); + params.putIfAbsent("three_prime_adapter","AACTGTAGGCACCATCAAT"); break case 'cats': - params.replace("clip_r1",3); - params.replace("three_prime_clip_r1", 0); - params.replace("three_prime_adapter", "AAAAAAAA"); + params.putIfAbsent("clip_r1",3); + params.putIfAbsent("three_prime_clip_r1", 0); + params.putIfAbsent("three_prime_adapter", "AAAAAAAA"); break default: log.warn "Please make sure to specify all required clipping and trimming parameters, otherwise only adapter detection will be performed." diff --git a/modules/local/mirtrace.nf b/modules/local/mirtrace.nf index e893c2e9..fee8e071 100644 --- a/modules/local/mirtrace.nf +++ b/modules/local/mirtrace.nf @@ -14,23 +14,9 @@ process MIRTRACE_RUN { path "versions.yml", emit: versions script: - def three_prime_adapter = params.three_prime_adapter - // Presets - if (params.protocol == "illumina"){ - three_prime_adapter = "TGGAATTCTCGGGTGCCAAGG" - } else if (params.protocol == "nextflex"){ - three_prime_adapter = "TGGAATTCTCGGGTGCCAAGG" - } else if (params.protocol == "qiaseq"){ - three_prime_adapter = "AACTGTAGGCACCATCAAT" - } else if (params.protocol == "cats"){ - three_prime_adapter = "AAAAAAAA" - } else if (params.protocol == "custom"){ - three_prime_adapter = params.three_prime_adapter - } - // mirtrace protocol defaults to 'params.protocol' if not set - def primer = (params.protocol=="cats") ? " " : " --adapter $three_prime_adapter " - def protocol = (params.protocol=="custom") ? " " : "--protocol $params.protocol" + def primer = params.protocol == 'cats' ? '' : "--adapter ${params.three_prime_adapter}" + def protocol = params.protocol == 'custom' ? '' : "--protocol $params.protocol" def java_mem = '' if(task.memory){ tmem = task.memory.toBytes() From 7c2e4b5444ba5f03de122584025561ce3d37c8fe Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Tue, 4 Oct 2022 22:05:52 +0000 Subject: [PATCH 052/215] Template update for nf-core/tools version 2.6 --- .github/workflows/awsfulltest.yml | 4 ++ .github/workflows/awstest.yml | 4 ++ .prettierignore | 1 + CITATION.cff | 8 +-- LICENSE | 2 +- README.md | 2 +- assets/adaptivecard.json | 67 +++++++++++++++++++ assets/methods_description_template.yml | 25 +++++++ assets/multiqc_config.yml | 6 +- docs/usage.md | 8 +++ lib/NfcoreTemplate.groovy | 55 +++++++++++++++ lib/Utils.groovy | 21 ++++-- lib/WorkflowSmrnaseq.groovy | 19 ++++++ main.nf | 3 +- modules.json | 27 ++++---- .../custom/dumpsoftwareversions/main.nf | 8 +-- .../custom/dumpsoftwareversions/meta.yml | 0 .../templates/dumpsoftwareversions.py | 0 modules/nf-core/{modules => }/fastqc/main.nf | 12 ++++ modules/nf-core/{modules => }/fastqc/meta.yml | 0 modules/nf-core/modules/multiqc/main.nf | 31 --------- modules/nf-core/multiqc/main.nf | 53 +++++++++++++++ .../nf-core/{modules => }/multiqc/meta.yml | 15 +++++ nextflow.config | 7 +- nextflow_schema.json | 18 +++++ workflows/smrnaseq.nf | 26 ++++--- 26 files changed, 348 insertions(+), 74 deletions(-) create mode 100644 assets/adaptivecard.json create mode 100644 assets/methods_description_template.yml mode change 100755 => 100644 lib/Utils.groovy rename modules/nf-core/{modules => }/custom/dumpsoftwareversions/main.nf (79%) rename modules/nf-core/{modules => }/custom/dumpsoftwareversions/meta.yml (100%) rename modules/nf-core/{modules => }/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py (100%) rename modules/nf-core/{modules => }/fastqc/main.nf (85%) rename modules/nf-core/{modules => }/fastqc/meta.yml (100%) delete mode 100644 modules/nf-core/modules/multiqc/main.nf create mode 100644 modules/nf-core/multiqc/main.nf rename modules/nf-core/{modules => }/multiqc/meta.yml (73%) diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index 94527ff0..76c16e75 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -28,3 +28,7 @@ jobs: "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/smrnaseq/results-${{ github.sha }}" } profiles: test_full,aws_tower + - uses: actions/upload-artifact@v3 + with: + name: Tower debug log file + path: tower_action_*.log diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml index ea00f80e..03a442a1 100644 --- a/.github/workflows/awstest.yml +++ b/.github/workflows/awstest.yml @@ -23,3 +23,7 @@ jobs: "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/smrnaseq/results-test-${{ github.sha }}" } profiles: test,aws_tower + - uses: actions/upload-artifact@v3 + with: + name: Tower debug log file + path: tower_action_*.log diff --git a/.prettierignore b/.prettierignore index d0e7ae58..eb74a574 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,5 @@ email_template.html +adaptivecard.json .nextflow* work/ data/ diff --git a/CITATION.cff b/CITATION.cff index 4533e2f2..017666c0 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -13,8 +13,8 @@ authors: given-names: Johannes - family-names: Wilm given-names: Andreas - - family-names: Ulysse Garcia - given-names: Maxime + - family-names: Garcia + given-names: Maxime Ulysse - family-names: Di Tommaso given-names: Paolo - family-names: Nahnsen @@ -39,8 +39,8 @@ prefered-citation: given-names: Johannes - family-names: Wilm given-names: Andreas - - family-names: Ulysse Garcia - given-names: Maxime + - family-names: Garcia + given-names: Maxime Ulysse - family-names: Di Tommaso given-names: Paolo - family-names: Nahnsen diff --git a/LICENSE b/LICENSE index ad773211..499134b1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) P. Ewels , C. Wang , R. Hammarén , L. Pantano +Copyright (c) P. Ewels, C. Wang, R. Hammarén, L. Pantano Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 166d0429..9caac333 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ The nf-core/smrnaseq pipeline comes with documentation about the pipeline [usage ## Credits -nf-core/smrnaseq was originally written by P. Ewels , C. Wang , R. Hammarén , L. Pantano . +nf-core/smrnaseq was originally written by P. Ewels, C. Wang, R. Hammarén, L. Pantano. We thank the following people for their extensive assistance in the development of this pipeline: diff --git a/assets/adaptivecard.json b/assets/adaptivecard.json new file mode 100644 index 00000000..0b804f3d --- /dev/null +++ b/assets/adaptivecard.json @@ -0,0 +1,67 @@ +{ + "type": "message", + "attachments": [ + { + "contentType": "application/vnd.microsoft.card.adaptive", + "contentUrl": null, + "content": { + "\$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "msteams": { + "width": "Full" + }, + "type": "AdaptiveCard", + "version": "1.2", + "body": [ + { + "type": "TextBlock", + "size": "Large", + "weight": "Bolder", + "color": "<% if (success) { %>Good<% } else { %>Attention<%} %>", + "text": "nf-core/smrnaseq v${version} - ${runName}", + "wrap": true + }, + { + "type": "TextBlock", + "spacing": "None", + "text": "Completed at ${dateComplete} (duration: ${duration})", + "isSubtle": true, + "wrap": true + }, + { + "type": "TextBlock", + "text": "<% if (success) { %>Pipeline completed successfully!<% } else { %>Pipeline completed with errors. The full error message was: ${errorReport}.<% } %>", + "wrap": true + }, + { + "type": "TextBlock", + "text": "The command used to launch the workflow was as follows:", + "wrap": true + }, + { + "type": "TextBlock", + "text": "${commandLine}", + "isSubtle": true, + "wrap": true + } + ], + "actions": [ + { + "type": "Action.ShowCard", + "title": "Pipeline Configuration", + "card": { + "type": "AdaptiveCard", + "\$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "body": [ + { + "type": "FactSet", + "facts": [<% out << summary.collect{ k,v -> "{\"title\": \"$k\", \"value\" : \"$v\"}"}.join(",\n") %> + ] + } + ] + } + } + ] + } + } + ] +} diff --git a/assets/methods_description_template.yml b/assets/methods_description_template.yml new file mode 100644 index 00000000..247628aa --- /dev/null +++ b/assets/methods_description_template.yml @@ -0,0 +1,25 @@ +id: "nf-core-smrnaseq-methods-description" +description: "Suggested text and references to use when describing pipeline usage within the methods section of a publication." +section_name: "nf-core/smrnaseq Methods Description" +section_href: "https://github.com/nf-core/smrnaseq" +plot_type: "html" +## TODO nf-core: Update the HTML below to your prefered methods description, e.g. add publication citation for this pipeline +## You inject any metadata in the Nextflow '${workflow}' object +data: | +

Methods

+

Data was processed using nf-core/smrnaseq v${workflow.manifest.version} ${doi_text} of the nf-core collection of workflows (Ewels et al., 2020).

+

The pipeline was executed with Nextflow v${workflow.nextflow.version} (Di Tommaso et al., 2017) with the following command:

+
${workflow.commandLine}
+

References

+
    +
  • Di Tommaso, P., Chatzou, M., Floden, E. W., Barja, P. P., Palumbo, E., & Notredame, C. (2017). Nextflow enables reproducible computational workflows. Nature Biotechnology, 35(4), 316-319. https://doi.org/10.1038/nbt.3820
  • +
  • Ewels, P. A., Peltzer, A., Fillinger, S., Patel, H., Alneberg, J., Wilm, A., Garcia, M. U., Di Tommaso, P., & Nahnsen, S. (2020). The nf-core framework for community-curated bioinformatics pipelines. Nature Biotechnology, 38(3), 276-278. https://doi.org/10.1038/s41587-020-0439-x
  • +
+
+
Notes:
+
    + ${nodoi_text} +
  • The command above does not include parameters contained in any configs or profiles that may have been used. Ensure the config file is also uploaded with your publication!
  • +
  • You should also cite all software used within this run. Check the "Software Versions" of this report to get version information.
  • +
+
diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index f7715e34..df5ec37a 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -3,9 +3,11 @@ report_comment: > analysis pipeline. For information about how to interpret these results, please see the documentation. report_section_order: - software_versions: + "nf-core-smrnaseq-methods-description": order: -1000 - "nf-core-smrnaseq-summary": + software_versions: order: -1001 + "nf-core-smrnaseq-summary": + order: -1002 export_plots: true diff --git a/docs/usage.md b/docs/usage.md index b75cbc81..3d01eda4 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -237,6 +237,14 @@ See the main [Nextflow documentation](https://www.nextflow.io/docs/latest/config If you have any questions or issues please send us a message on [Slack](https://nf-co.re/join/slack) on the [`#configs` channel](https://nfcore.slack.com/channels/configs). +## Azure Resource Requests + +To be used with the `azurebatch` profile by specifying the `-profile azurebatch`. +We recommend providing a compute `params.vm_type` of `Standard_D16_v3` VMs by default but these options can be changed if required. + +Note that the choice of VM size depends on your quota and the overall workload during the analysis. +For a thorough list, please refer the [Azure Sizes for virtual machines in Azure](https://docs.microsoft.com/en-us/azure/virtual-machines/sizes). + ## Running in the background Nextflow handles job submissions and supervises the running jobs. The Nextflow process must run until the pipeline is finished. diff --git a/lib/NfcoreTemplate.groovy b/lib/NfcoreTemplate.groovy index 2fc0a9b9..27feb009 100755 --- a/lib/NfcoreTemplate.groovy +++ b/lib/NfcoreTemplate.groovy @@ -145,6 +145,61 @@ class NfcoreTemplate { output_tf.withWriter { w -> w << email_txt } } + // + // Construct and send adaptive card + // https://adaptivecards.io + // + public static void adaptivecard(workflow, params, summary_params, projectDir, log) { + def hook_url = params.hook_url + + def summary = [:] + for (group in summary_params.keySet()) { + summary << summary_params[group] + } + + def misc_fields = [:] + misc_fields['start'] = workflow.start + misc_fields['complete'] = workflow.complete + misc_fields['scriptfile'] = workflow.scriptFile + misc_fields['scriptid'] = workflow.scriptId + if (workflow.repository) misc_fields['repository'] = workflow.repository + if (workflow.commitId) misc_fields['commitid'] = workflow.commitId + if (workflow.revision) misc_fields['revision'] = workflow.revision + misc_fields['nxf_version'] = workflow.nextflow.version + misc_fields['nxf_build'] = workflow.nextflow.build + misc_fields['nxf_timestamp'] = workflow.nextflow.timestamp + + def msg_fields = [:] + msg_fields['version'] = workflow.manifest.version + msg_fields['runName'] = workflow.runName + msg_fields['success'] = workflow.success + msg_fields['dateComplete'] = workflow.complete + msg_fields['duration'] = workflow.duration + msg_fields['exitStatus'] = workflow.exitStatus + msg_fields['errorMessage'] = (workflow.errorMessage ?: 'None') + msg_fields['errorReport'] = (workflow.errorReport ?: 'None') + msg_fields['commandLine'] = workflow.commandLine + msg_fields['projectDir'] = workflow.projectDir + msg_fields['summary'] = summary << misc_fields + + // Render the JSON template + def engine = new groovy.text.GStringTemplateEngine() + def hf = new File("$projectDir/assets/adaptivecard.json") + def json_template = engine.createTemplate(hf).make(msg_fields) + def json_message = json_template.toString() + + // POST + def post = new URL(hook_url).openConnection(); + post.setRequestMethod("POST") + post.setDoOutput(true) + post.setRequestProperty("Content-Type", "application/json") + post.getOutputStream().write(json_message.getBytes("UTF-8")); + def postRC = post.getResponseCode(); + if (! postRC.equals(200)) { + log.warn(post.getErrorStream().getText()); + } + } + // // Print pipeline summary on completion // diff --git a/lib/Utils.groovy b/lib/Utils.groovy old mode 100755 new mode 100644 index 28567bd7..8d030f4e --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -21,19 +21,26 @@ class Utils { } // Check that all channels are present - def required_channels = ['conda-forge', 'bioconda', 'defaults'] - def conda_check_failed = !required_channels.every { ch -> ch in channels } + // This channel list is ordered by required channel priority. + def required_channels_in_order = ['conda-forge', 'bioconda', 'defaults'] + def channels_missing = ((required_channels_in_order as Set) - (channels as Set)) as Boolean // Check that they are in the right order - conda_check_failed |= !(channels.indexOf('conda-forge') < channels.indexOf('bioconda')) - conda_check_failed |= !(channels.indexOf('bioconda') < channels.indexOf('defaults')) + 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])) + } - if (conda_check_failed) { + if (channels_missing | channel_priority_violation) { log.warn "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " There is a problem with your Conda configuration!\n\n" + " You will need to set-up the conda-forge and bioconda channels correctly.\n" + - " Please refer to https://bioconda.github.io/user/install.html#set-up-channels\n" + - " NB: The order of the channels matters!\n" + + " Please refer to https://bioconda.github.io/\n" + + " The observed channel order is \n" + + " ${channels}\n" + + " but the following channel order is required:\n" + + " ${required_channels_in_order}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" } } diff --git a/lib/WorkflowSmrnaseq.groovy b/lib/WorkflowSmrnaseq.groovy index 5bc00333..3190e322 100755 --- a/lib/WorkflowSmrnaseq.groovy +++ b/lib/WorkflowSmrnaseq.groovy @@ -2,6 +2,8 @@ // This file holds several functions specific to the workflow/smrnaseq.nf in the nf-core/smrnaseq pipeline // +import groovy.text.SimpleTemplateEngine + class WorkflowSmrnaseq { // @@ -42,6 +44,23 @@ class WorkflowSmrnaseq { yaml_file_text += "data: |\n" yaml_file_text += "${summary_section}" return yaml_file_text + } + + public static String methodsDescriptionText(run_workflow, mqc_methods_yaml) { + // Convert to a named map so can be used as with familar NXF ${workflow} variable syntax in the MultiQC YML file + def meta = [:] + meta.workflow = run_workflow.toMap() + meta["manifest_map"] = run_workflow.manifest.toMap() + + meta["doi_text"] = meta.manifest_map.doi ? "(doi: ${meta.manifest_map.doi})" : "" + 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.
  • " + + def methods_text = mqc_methods_yaml.text + + def engine = new SimpleTemplateEngine() + def description_html = engine.createTemplate(methods_text).make(meta) + + return description_html }// // Exit pipeline if incorrect --genome key provided // diff --git a/main.nf b/main.nf index a7e6c457..adbfad48 100644 --- a/main.nf +++ b/main.nf @@ -4,7 +4,8 @@ nf-core/smrnaseq ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Github : https://github.com/nf-core/smrnaseq -Website: https://nf-co.re/smrnaseq + + Website: https://nf-co.re/smrnaseq Slack : https://nfcore.slack.com/channels/smrnaseq ---------------------------------------------------------------------------------------- */ diff --git a/modules.json b/modules.json index 81f0ce77..70345a21 100644 --- a/modules.json +++ b/modules.json @@ -2,20 +2,21 @@ "name": "nf-core/smrnaseq", "homePage": "https://github.com/nf-core/smrnaseq", "repos": { - "nf-core/modules": { - "git_url": "https://github.com/nf-core/modules.git", + "https://github.com/nf-core/modules.git": { "modules": { - "custom/dumpsoftwareversions": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d", - "branch": "master" - }, - "fastqc": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d", - "branch": "master" - }, - "multiqc": { - "git_sha": "e745e167c1020928ef20ea1397b6b4d230681b4d", - "branch": "master" + "nf-core": { + "custom/dumpsoftwareversions": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "fastqc": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "multiqc": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + } } } } diff --git a/modules/nf-core/modules/custom/dumpsoftwareversions/main.nf b/modules/nf-core/custom/dumpsoftwareversions/main.nf similarity index 79% rename from modules/nf-core/modules/custom/dumpsoftwareversions/main.nf rename to modules/nf-core/custom/dumpsoftwareversions/main.nf index 327d5100..cebb6e05 100644 --- a/modules/nf-core/modules/custom/dumpsoftwareversions/main.nf +++ b/modules/nf-core/custom/dumpsoftwareversions/main.nf @@ -1,11 +1,11 @@ process CUSTOM_DUMPSOFTWAREVERSIONS { - label 'process_low' + label 'process_single' // Requires `pyyaml` which does not have a dedicated container but is in the MultiQC container - conda (params.enable_conda ? "bioconda::multiqc=1.11" : null) + conda (params.enable_conda ? 'bioconda::multiqc=1.13' : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.11--pyhdfd78af_0' : - 'quay.io/biocontainers/multiqc:1.11--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/multiqc:1.13--pyhdfd78af_0' : + 'quay.io/biocontainers/multiqc:1.13--pyhdfd78af_0' }" input: path versions diff --git a/modules/nf-core/modules/custom/dumpsoftwareversions/meta.yml b/modules/nf-core/custom/dumpsoftwareversions/meta.yml similarity index 100% rename from modules/nf-core/modules/custom/dumpsoftwareversions/meta.yml rename to modules/nf-core/custom/dumpsoftwareversions/meta.yml diff --git a/modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py similarity index 100% rename from modules/nf-core/modules/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py rename to modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py diff --git a/modules/nf-core/modules/fastqc/main.nf b/modules/nf-core/fastqc/main.nf similarity index 85% rename from modules/nf-core/modules/fastqc/main.nf rename to modules/nf-core/fastqc/main.nf index ed6b8c50..05730368 100644 --- a/modules/nf-core/modules/fastqc/main.nf +++ b/modules/nf-core/fastqc/main.nf @@ -44,4 +44,16 @@ process FASTQC { END_VERSIONS """ } + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.html + touch ${prefix}.zip + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + fastqc: \$( fastqc --version | sed -e "s/FastQC v//g" ) + END_VERSIONS + """ } diff --git a/modules/nf-core/modules/fastqc/meta.yml b/modules/nf-core/fastqc/meta.yml similarity index 100% rename from modules/nf-core/modules/fastqc/meta.yml rename to modules/nf-core/fastqc/meta.yml diff --git a/modules/nf-core/modules/multiqc/main.nf b/modules/nf-core/modules/multiqc/main.nf deleted file mode 100644 index 1264aac1..00000000 --- a/modules/nf-core/modules/multiqc/main.nf +++ /dev/null @@ -1,31 +0,0 @@ -process MULTIQC { - label 'process_medium' - - conda (params.enable_conda ? 'bioconda::multiqc=1.12' : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.12--pyhdfd78af_0' : - 'quay.io/biocontainers/multiqc:1.12--pyhdfd78af_0' }" - - input: - path multiqc_files - - output: - path "*multiqc_report.html", emit: report - path "*_data" , emit: data - path "*_plots" , optional:true, emit: plots - path "versions.yml" , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - """ - multiqc -f $args . - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) - END_VERSIONS - """ -} diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf new file mode 100644 index 00000000..a8159a57 --- /dev/null +++ b/modules/nf-core/multiqc/main.nf @@ -0,0 +1,53 @@ +process MULTIQC { + label 'process_single' + + conda (params.enable_conda ? 'bioconda::multiqc=1.13' : null) + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/multiqc:1.13--pyhdfd78af_0' : + 'quay.io/biocontainers/multiqc:1.13--pyhdfd78af_0' }" + + input: + path multiqc_files, stageAs: "?/*" + path(multiqc_config) + path(extra_multiqc_config) + path(multiqc_logo) + + output: + path "*multiqc_report.html", emit: report + path "*_data" , emit: data + path "*_plots" , optional:true, emit: plots + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def config = multiqc_config ? "--config $multiqc_config" : '' + def extra_config = extra_multiqc_config ? "--config $extra_multiqc_config" : '' + """ + multiqc \\ + --force \\ + $args \\ + $config \\ + $extra_config \\ + . + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) + END_VERSIONS + """ + + stub: + """ + touch multiqc_data + touch multiqc_plots + touch multiqc_report.html + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) + END_VERSIONS + """ +} diff --git a/modules/nf-core/modules/multiqc/meta.yml b/modules/nf-core/multiqc/meta.yml similarity index 73% rename from modules/nf-core/modules/multiqc/meta.yml rename to modules/nf-core/multiqc/meta.yml index 6fa891ef..ebc29b27 100644 --- a/modules/nf-core/modules/multiqc/meta.yml +++ b/modules/nf-core/multiqc/meta.yml @@ -12,11 +12,25 @@ tools: homepage: https://multiqc.info/ documentation: https://multiqc.info/docs/ licence: ["GPL-3.0-or-later"] + input: - multiqc_files: type: file description: | List of reports / files recognised by MultiQC, for example the html and zip output of FastQC + - multiqc_config: + type: file + description: Optional config yml for MultiQC + pattern: "*.{yml,yaml}" + - extra_multiqc_config: + type: file + description: Second optional config yml for MultiQC. Will override common sections in multiqc_config. + pattern: "*.{yml,yaml}" + - multiqc_logo: + type: file + description: Optional logo file for MultiQC + pattern: "*.{png}" + output: - report: type: file @@ -38,3 +52,4 @@ authors: - "@abhi18av" - "@bunop" - "@drpatelh" + - "@jfy133" diff --git a/nextflow.config b/nextflow.config index e4a50caa..c9ccb710 100644 --- a/nextflow.config +++ b/nextflow.config @@ -21,7 +21,9 @@ params { // MultiQC options multiqc_config = null multiqc_title = null + multiqc_logo = null max_multiqc_email_size = '25.MB' + multiqc_methods_description = null // Boilerplate options outdir = null @@ -31,6 +33,7 @@ params { email_on_fail = null plaintext_email = false monochrome_logs = false + hook_url = null help = false validate_params = true show_hidden_params = false @@ -74,7 +77,6 @@ try { // } - profiles { debug { process.beforeScript = 'echo $HOSTNAME' } conda { @@ -183,12 +185,13 @@ dag { manifest { name = 'nf-core/smrnaseq' - author = 'P. Ewels , C. Wang , R. Hammarén , L. Pantano ' + author = 'P. Ewels, C. Wang, R. Hammarén, L. Pantano' homePage = 'https://github.com/nf-core/smrnaseq' description = 'Small RNA-Seq Best Practice Analysis Pipeline.' mainScript = 'main.nf' nextflowVersion = '!>=21.10.3' version = '2.1.0dev' + doi = '' } // Load modules.config for DSL2 module specific options diff --git a/nextflow_schema.json b/nextflow_schema.json index 84b4768e..8aaa69c5 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -213,12 +213,30 @@ "fa_icon": "fas fa-palette", "hidden": true }, + "hook_url": { + "type": "string", + "description": "Incoming hook URL for messaging service", + "fa_icon": "fas fa-people-group", + "help_text": "Incoming hook URL for messaging service. Currently, only MS Teams is supported.", + "hidden": true + }, "multiqc_config": { "type": "string", "description": "Custom config file to supply to MultiQC.", "fa_icon": "fas fa-cog", "hidden": true }, + "multiqc_logo": { + "type": "string", + "description": "Custom logo file to supply to MultiQC. File name must also be set in the MultiQC config file", + "fa_icon": "fas fa-image", + "hidden": true + }, + "multiqc_methods_description": { + "type": "string", + "description": "Custom MultiQC yaml file containing HTML including a methods description.", + "fa_icon": "fas fa-cog" + }, "tracedir": { "type": "string", "description": "Directory to keep pipeline Nextflow logs and reports.", diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index b439836c..1d5a682d 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -23,8 +23,10 @@ if (params.input) { ch_input = file(params.input) } else { exit 1, 'Input sample ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -ch_multiqc_config = file("$projectDir/assets/multiqc_config.yml", checkIfExists: true) -ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath(params.multiqc_config) : Channel.empty() +ch_multiqc_config = Channel.fromPath("$projectDir/assets/multiqc_config.yml", checkIfExists: true) +ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath( params.multiqc_config, checkIfExists: true ) : Channel.empty() +ch_multiqc_logo = params.multiqc_logo ? Channel.fromPath( params.multiqc_logo, checkIfExists: true ) : Channel.empty() +ch_multiqc_custom_methods_description = params.multiqc_methods_description ? file(params.multiqc_methods_description, checkIfExists: true) : file("$projectDir/assets/methods_description_template.yml", checkIfExists: true) /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -46,9 +48,9 @@ include { INPUT_CHECK } from '../subworkflows/local/input_check' // // MODULE: Installed directly from nf-core/modules // -include { FASTQC } from '../modules/nf-core/modules/fastqc/main' -include { MULTIQC } from '../modules/nf-core/modules/multiqc/main' -include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/modules/custom/dumpsoftwareversions/main' +include { FASTQC } from '../modules/nf-core/fastqc/main' +include { MULTIQC } from '../modules/nf-core/multiqc/main' +include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoftwareversions/main' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -89,15 +91,20 @@ workflow SMRNASEQ { workflow_summary = WorkflowSmrnaseq.paramsSummaryMultiqc(workflow, summary_params) ch_workflow_summary = Channel.value(workflow_summary) + methods_description = WorkflowSmrnaseq.methodsDescriptionText(workflow, ch_multiqc_custom_methods_description) + ch_methods_description = Channel.value(methods_description) + ch_multiqc_files = Channel.empty() - ch_multiqc_files = ch_multiqc_files.mix(Channel.from(ch_multiqc_config)) - ch_multiqc_files = ch_multiqc_files.mix(ch_multiqc_custom_config.collect().ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) + ch_multiqc_files = ch_multiqc_files.mix(ch_methods_description.collectFile(name: 'methods_description_mqc.yaml')) ch_multiqc_files = ch_multiqc_files.mix(CUSTOM_DUMPSOFTWAREVERSIONS.out.mqc_yml.collect()) ch_multiqc_files = ch_multiqc_files.mix(FASTQC.out.zip.collect{it[1]}.ifEmpty([])) MULTIQC ( - ch_multiqc_files.collect() + ch_multiqc_files.collect(), + ch_multiqc_config.collect().ifEmpty([]), + ch_multiqc_custom_config.collect().ifEmpty([]), + ch_multiqc_logo.collect().ifEmpty([]) ) multiqc_report = MULTIQC.out.report.toList() ch_versions = ch_versions.mix(MULTIQC.out.versions) @@ -114,6 +121,9 @@ workflow.onComplete { NfcoreTemplate.email(workflow, params, summary_params, projectDir, log, multiqc_report) } NfcoreTemplate.summary(workflow, params, log) + if (params.hook_url) { + NfcoreTemplate.adaptivecard(workflow, params, summary_params, projectDir, log) + } } /* From b694ee171e1dcdcc01abb1443bd4c52a1f6971a8 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 7 Oct 2022 12:55:34 +0000 Subject: [PATCH 053/215] Tiny changes --- modules.json | 80 +++++++-------- .../nf-core/{modules => }/cat/fastq/main.nf | 10 +- .../nf-core/{modules => }/cat/fastq/meta.yml | 0 .../templates/dumpsoftwareversions.py | 98 +++++++++++-------- modules/nf-core/modules/multiqc/main.nf | 50 ---------- .../{modules => }/samtools/flagstat/main.nf | 0 .../{modules => }/samtools/flagstat/meta.yml | 0 .../{modules => }/samtools/idxstats/main.nf | 1 + .../{modules => }/samtools/idxstats/meta.yml | 0 .../{modules => }/samtools/index/main.nf | 0 .../{modules => }/samtools/index/meta.yml | 0 .../{modules => }/samtools/sort/main.nf | 1 + .../{modules => }/samtools/sort/meta.yml | 4 + .../{modules => }/samtools/stats/main.nf | 0 .../{modules => }/samtools/stats/meta.yml | 0 .../nf-core/{modules => }/trimgalore/main.nf | 2 +- .../nf-core/{modules => }/trimgalore/meta.yml | 0 subworkflows/nf-core/bam_sort_samtools.nf | 4 +- subworkflows/nf-core/bam_stats_samtools.nf | 6 +- subworkflows/nf-core/fastqc_trimgalore.nf | 2 +- workflows/smrnaseq.nf | 4 + 21 files changed, 118 insertions(+), 144 deletions(-) rename modules/nf-core/{modules => }/cat/fastq/main.nf (88%) rename modules/nf-core/{modules => }/cat/fastq/meta.yml (100%) mode change 100644 => 100755 modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py delete mode 100644 modules/nf-core/modules/multiqc/main.nf rename modules/nf-core/{modules => }/samtools/flagstat/main.nf (100%) rename modules/nf-core/{modules => }/samtools/flagstat/meta.yml (100%) rename modules/nf-core/{modules => }/samtools/idxstats/main.nf (96%) rename modules/nf-core/{modules => }/samtools/idxstats/meta.yml (100%) rename modules/nf-core/{modules => }/samtools/index/main.nf (100%) rename modules/nf-core/{modules => }/samtools/index/meta.yml (100%) rename modules/nf-core/{modules => }/samtools/sort/main.nf (95%) rename modules/nf-core/{modules => }/samtools/sort/meta.yml (92%) rename modules/nf-core/{modules => }/samtools/stats/main.nf (100%) rename modules/nf-core/{modules => }/samtools/stats/meta.yml (100%) rename modules/nf-core/{modules => }/trimgalore/main.nf (99%) rename modules/nf-core/{modules => }/trimgalore/meta.yml (100%) diff --git a/modules.json b/modules.json index 3c50ceaf..96095adf 100644 --- a/modules.json +++ b/modules.json @@ -4,45 +4,47 @@ "repos": { "https://github.com/nf-core/modules.git": { "modules": { - "cat/fastq": { - "branch": "master", - "git_sha": "b034029b59b1198075da8019074bc02051a6100e" - }, - "custom/dumpsoftwareversions": { - "branch": "master", - "git_sha": "5e7b1ef9a5a2d9258635bcbf70fcf37dacd1b247" - }, - "fastqc": { - "branch": "master", - "git_sha": "49b18b1639f4f7104187058866a8fab33332bdfe" - }, - "multiqc": { - "branch": "master", - "git_sha": "5587389874dac9c9953a2ab6f01d49af81969492" - }, - "samtools/flagstat": { - "branch": "master", - "git_sha": "bbb99cb8d679555cc01c98766de7869f83283545" - }, - "samtools/idxstats": { - "branch": "master", - "git_sha": "ecece498f10b47b7c9d06f53a310cea5811b4c5f" - }, - "samtools/index": { - "branch": "master", - "git_sha": "897c33d5da084b61109500ee44c01da2d3e4e773" - }, - "samtools/sort": { - "branch": "master", - "git_sha": "897c33d5da084b61109500ee44c01da2d3e4e773" - }, - "samtools/stats": { - "branch": "master", - "git_sha": "f4eab7945952dc4934224309701a49913ea05ae6" - }, - "trimgalore": { - "branch": "master", - "git_sha": "85ec13ff1fc2196c5a507ea497de468101baabed" + "nf-core": { + "cat/fastq": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "custom/dumpsoftwareversions": { + "branch": "master", + "git_sha": "8022c68e7403eecbd8ba9c49496f69f8c49d50f0" + }, + "fastqc": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "multiqc": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "samtools/flagstat": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "samtools/idxstats": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "samtools/index": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "samtools/sort": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "samtools/stats": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "trimgalore": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + } } } } diff --git a/modules/nf-core/modules/cat/fastq/main.nf b/modules/nf-core/cat/fastq/main.nf similarity index 88% rename from modules/nf-core/modules/cat/fastq/main.nf rename to modules/nf-core/cat/fastq/main.nf index d275f19c..4fa365d3 100644 --- a/modules/nf-core/modules/cat/fastq/main.nf +++ b/modules/nf-core/cat/fastq/main.nf @@ -1,6 +1,6 @@ process CAT_FASTQ { tag "$meta.id" - label 'process_low' + label 'process_single' conda (params.enable_conda ? "conda-forge::sed=4.7" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? @@ -20,9 +20,9 @@ process CAT_FASTQ { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" - def readList = reads.collect{ it.toString() } + def readList = reads instanceof List ? reads.collect{ it.toString() } : [reads.toString()] if (meta.single_end) { - if (readList.size > 1) { + if (readList.size >= 1) { """ cat ${readList.join(' ')} > ${prefix}.merged.fastq.gz @@ -33,7 +33,7 @@ process CAT_FASTQ { """ } } else { - if (readList.size > 2) { + if (readList.size >= 2) { def read1 = [] def read2 = [] readList.eachWithIndex{ v, ix -> ( ix & 1 ? read2 : read1 ) << v } @@ -51,7 +51,7 @@ process CAT_FASTQ { stub: def prefix = task.ext.prefix ?: "${meta.id}" - def readList = reads.collect{ it.toString() } + def readList = reads instanceof List ? reads.collect{ it.toString() } : [reads.toString()] if (meta.single_end) { if (readList.size > 1) { """ diff --git a/modules/nf-core/modules/cat/fastq/meta.yml b/modules/nf-core/cat/fastq/meta.yml similarity index 100% rename from modules/nf-core/modules/cat/fastq/meta.yml rename to modules/nf-core/cat/fastq/meta.yml diff --git a/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py old mode 100644 new mode 100755 index d1390392..da033408 --- a/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py +++ b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py @@ -1,11 +1,16 @@ #!/usr/bin/env python + +"""Provide functions to merge multiple versions.yml files.""" + + import yaml import platform from textwrap import dedent def _make_versions_html(versions): + """Generate a tabular HTML output of all versions for MultiQC.""" html = [ dedent( """\\ @@ -44,46 +49,53 @@ def _make_versions_html(versions): return "\\n".join(html) -versions_this_module = {} -versions_this_module["${task.process}"] = { - "python": platform.python_version(), - "yaml": yaml.__version__, -} - -with open("$versions") as f: - versions_by_process = yaml.load(f, Loader=yaml.BaseLoader) | versions_this_module - -# aggregate versions by the module name (derived from fully-qualified process name) -versions_by_module = {} -for process, process_versions in versions_by_process.items(): - module = process.split(":")[-1] - try: - assert versions_by_module[module] == process_versions, ( - "We assume that software versions are the same between all modules. " - "If you see this error-message it means you discovered an edge-case " - "and should open an issue in nf-core/tools. " - ) - except KeyError: - versions_by_module[module] = process_versions - -versions_by_module["Workflow"] = { - "Nextflow": "$workflow.nextflow.version", - "$workflow.manifest.name": "$workflow.manifest.version", -} - -versions_mqc = { - "id": "software_versions", - "section_name": "${workflow.manifest.name} Software Versions", - "section_href": "https://github.com/${workflow.manifest.name}", - "plot_type": "html", - "description": "are collected at run time from the software output.", - "data": _make_versions_html(versions_by_module), -} - -with open("software_versions.yml", "w") as f: - yaml.dump(versions_by_module, f, default_flow_style=False) -with open("software_versions_mqc.yml", "w") as f: - yaml.dump(versions_mqc, f, default_flow_style=False) - -with open("versions.yml", "w") as f: - yaml.dump(versions_this_module, f, default_flow_style=False) +def main(): + """Load all version files and generate merged output.""" + versions_this_module = {} + versions_this_module["${task.process}"] = { + "python": platform.python_version(), + "yaml": yaml.__version__, + } + + with open("$versions") as f: + versions_by_process = yaml.load(f, Loader=yaml.BaseLoader) | versions_this_module + + # aggregate versions by the module name (derived from fully-qualified process name) + versions_by_module = {} + for process, process_versions in versions_by_process.items(): + module = process.split(":")[-1] + try: + if versions_by_module[module] != process_versions: + raise AssertionError( + "We assume that software versions are the same between all modules. " + "If you see this error-message it means you discovered an edge-case " + "and should open an issue in nf-core/tools. " + ) + except KeyError: + versions_by_module[module] = process_versions + + versions_by_module["Workflow"] = { + "Nextflow": "$workflow.nextflow.version", + "$workflow.manifest.name": "$workflow.manifest.version", + } + + versions_mqc = { + "id": "software_versions", + "section_name": "${workflow.manifest.name} Software Versions", + "section_href": "https://github.com/${workflow.manifest.name}", + "plot_type": "html", + "description": "are collected at run time from the software output.", + "data": _make_versions_html(versions_by_module), + } + + with open("software_versions.yml", "w") as f: + yaml.dump(versions_by_module, f, default_flow_style=False) + with open("software_versions_mqc.yml", "w") as f: + yaml.dump(versions_mqc, f, default_flow_style=False) + + with open("versions.yml", "w") as f: + yaml.dump(versions_this_module, f, default_flow_style=False) + + +if __name__ == "__main__": + main() diff --git a/modules/nf-core/modules/multiqc/main.nf b/modules/nf-core/modules/multiqc/main.nf deleted file mode 100644 index d10dae69..00000000 --- a/modules/nf-core/modules/multiqc/main.nf +++ /dev/null @@ -1,50 +0,0 @@ -process MULTIQC { - label 'process_medium' - - conda (params.enable_conda ? 'bioconda::multiqc=1.13' : null) - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.13--pyhdfd78af_0' : - 'quay.io/biocontainers/multiqc:1.13--pyhdfd78af_0' }" - - input: - path multiqc_files, stageAs: "?/*" - path(multiqc_config) - path(multiqc_logo) - - output: - path "*multiqc_report.html", emit: report - path "*_data" , emit: data - path "*_plots" , optional:true, emit: plots - path "versions.yml" , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def config = multiqc_config ? "--config $multiqc_config" : '' - """ - multiqc \\ - --force \\ - $config \\ - $args \\ - . - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) - END_VERSIONS - """ - - stub: - """ - touch multiqc_data - touch multiqc_plots - touch multiqc_report.html - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) - END_VERSIONS - """ -} diff --git a/modules/nf-core/modules/samtools/flagstat/main.nf b/modules/nf-core/samtools/flagstat/main.nf similarity index 100% rename from modules/nf-core/modules/samtools/flagstat/main.nf rename to modules/nf-core/samtools/flagstat/main.nf diff --git a/modules/nf-core/modules/samtools/flagstat/meta.yml b/modules/nf-core/samtools/flagstat/meta.yml similarity index 100% rename from modules/nf-core/modules/samtools/flagstat/meta.yml rename to modules/nf-core/samtools/flagstat/meta.yml diff --git a/modules/nf-core/modules/samtools/idxstats/main.nf b/modules/nf-core/samtools/idxstats/main.nf similarity index 96% rename from modules/nf-core/modules/samtools/idxstats/main.nf rename to modules/nf-core/samtools/idxstats/main.nf index 4b245419..87618e5f 100644 --- a/modules/nf-core/modules/samtools/idxstats/main.nf +++ b/modules/nf-core/samtools/idxstats/main.nf @@ -24,6 +24,7 @@ process SAMTOOLS_IDXSTATS { """ samtools \\ idxstats \\ + --threads ${task.cpus-1} \\ $bam \\ > ${prefix}.idxstats diff --git a/modules/nf-core/modules/samtools/idxstats/meta.yml b/modules/nf-core/samtools/idxstats/meta.yml similarity index 100% rename from modules/nf-core/modules/samtools/idxstats/meta.yml rename to modules/nf-core/samtools/idxstats/meta.yml diff --git a/modules/nf-core/modules/samtools/index/main.nf b/modules/nf-core/samtools/index/main.nf similarity index 100% rename from modules/nf-core/modules/samtools/index/main.nf rename to modules/nf-core/samtools/index/main.nf diff --git a/modules/nf-core/modules/samtools/index/meta.yml b/modules/nf-core/samtools/index/meta.yml similarity index 100% rename from modules/nf-core/modules/samtools/index/meta.yml rename to modules/nf-core/samtools/index/meta.yml diff --git a/modules/nf-core/modules/samtools/sort/main.nf b/modules/nf-core/samtools/sort/main.nf similarity index 95% rename from modules/nf-core/modules/samtools/sort/main.nf rename to modules/nf-core/samtools/sort/main.nf index b4fc1cbe..ab7f1cca 100644 --- a/modules/nf-core/modules/samtools/sort/main.nf +++ b/modules/nf-core/samtools/sort/main.nf @@ -12,6 +12,7 @@ process SAMTOOLS_SORT { output: tuple val(meta), path("*.bam"), emit: bam + tuple val(meta), path("*.csi"), emit: csi, optional: true path "versions.yml" , emit: versions when: diff --git a/modules/nf-core/modules/samtools/sort/meta.yml b/modules/nf-core/samtools/sort/meta.yml similarity index 92% rename from modules/nf-core/modules/samtools/sort/meta.yml rename to modules/nf-core/samtools/sort/meta.yml index a820c55a..09289751 100644 --- a/modules/nf-core/modules/samtools/sort/meta.yml +++ b/modules/nf-core/samtools/sort/meta.yml @@ -39,6 +39,10 @@ output: type: file description: File containing software versions pattern: "versions.yml" + - csi: + type: file + description: BAM index file (optional) + pattern: "*.csi" authors: - "@drpatelh" - "@ewels" diff --git a/modules/nf-core/modules/samtools/stats/main.nf b/modules/nf-core/samtools/stats/main.nf similarity index 100% rename from modules/nf-core/modules/samtools/stats/main.nf rename to modules/nf-core/samtools/stats/main.nf diff --git a/modules/nf-core/modules/samtools/stats/meta.yml b/modules/nf-core/samtools/stats/meta.yml similarity index 100% rename from modules/nf-core/modules/samtools/stats/meta.yml rename to modules/nf-core/samtools/stats/meta.yml diff --git a/modules/nf-core/modules/trimgalore/main.nf b/modules/nf-core/trimgalore/main.nf similarity index 99% rename from modules/nf-core/modules/trimgalore/main.nf rename to modules/nf-core/trimgalore/main.nf index 3a3fca90..a69e3de6 100644 --- a/modules/nf-core/modules/trimgalore/main.nf +++ b/modules/nf-core/trimgalore/main.nf @@ -32,7 +32,7 @@ process TRIMGALORE { cores = (task.cpus as int) - 4 if (meta.single_end) cores = (task.cpus as int) - 3 if (cores < 1) cores = 1 - if (cores > 4) cores = 4 + if (cores > 8) cores = 8 } // Clipping presets have to be evaluated in the context of SE/PE diff --git a/modules/nf-core/modules/trimgalore/meta.yml b/modules/nf-core/trimgalore/meta.yml similarity index 100% rename from modules/nf-core/modules/trimgalore/meta.yml rename to modules/nf-core/trimgalore/meta.yml diff --git a/subworkflows/nf-core/bam_sort_samtools.nf b/subworkflows/nf-core/bam_sort_samtools.nf index a3f2741a..ded07b32 100644 --- a/subworkflows/nf-core/bam_sort_samtools.nf +++ b/subworkflows/nf-core/bam_sort_samtools.nf @@ -2,8 +2,8 @@ // Sort, index BAM file and run samtools stats, flagstat and idxstats // -include { SAMTOOLS_SORT } from '../../modules/nf-core/modules/samtools/sort/main' -include { SAMTOOLS_INDEX } from '../../modules/nf-core/modules/samtools/index/main' +include { SAMTOOLS_SORT } from '../../modules/nf-core/samtools/sort/main' +include { SAMTOOLS_INDEX } from '../../modules/nf-core/samtools/index/main' include { BAM_STATS_SAMTOOLS } from './bam_stats_samtools' workflow BAM_SORT_SAMTOOLS { diff --git a/subworkflows/nf-core/bam_stats_samtools.nf b/subworkflows/nf-core/bam_stats_samtools.nf index 857ae2c1..38d2569b 100644 --- a/subworkflows/nf-core/bam_stats_samtools.nf +++ b/subworkflows/nf-core/bam_stats_samtools.nf @@ -2,9 +2,9 @@ // Run SAMtools stats, flagstat and idxstats // -include { SAMTOOLS_STATS } from '../../modules/nf-core/modules/samtools/stats/main' -include { SAMTOOLS_IDXSTATS } from '../../modules/nf-core/modules/samtools/idxstats/main' -include { SAMTOOLS_FLAGSTAT } from '../../modules/nf-core/modules/samtools/flagstat/main' +include { SAMTOOLS_STATS } from '../../modules/nf-core/samtools/stats/main' +include { SAMTOOLS_IDXSTATS } from '../../modules/nf-core/samtools/idxstats/main' +include { SAMTOOLS_FLAGSTAT } from '../../modules/nf-core/samtools/flagstat/main' workflow BAM_STATS_SAMTOOLS { take: diff --git a/subworkflows/nf-core/fastqc_trimgalore.nf b/subworkflows/nf-core/fastqc_trimgalore.nf index ba2deecd..3eaee69f 100644 --- a/subworkflows/nf-core/fastqc_trimgalore.nf +++ b/subworkflows/nf-core/fastqc_trimgalore.nf @@ -2,7 +2,7 @@ // Read QC, UMI extraction and trimming // -include { FASTQC } from '../../modules/nf-core/modules/fastqc/main' +include { FASTQC } from '../../modules/nf-core/fastqc/main' include { TRIMGALORE } from '../../modules/local/trimgalore' workflow FASTQC_TRIMGALORE { diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index af0def5b..7fd887d9 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -37,6 +37,7 @@ def mirna_gtf = params.mirna_gtf ?: mirna_gtf_from_species ch_multiqc_config = Channel.fromPath("$projectDir/assets/multiqc_config.yml", checkIfExists: true) ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath( params.multiqc_config, checkIfExists: true ) : Channel.empty() ch_multiqc_logo = params.multiqc_logo ? Channel.fromPath( params.multiqc_logo, checkIfExists: true ) : Channel.empty() +ch_multiqc_image = file("$projectDir/assets/smrnaseq_logo.png", checkIfExists: true) ch_multiqc_custom_methods_description = params.multiqc_methods_description ? file(params.multiqc_methods_description, checkIfExists: true) : file("$projectDir/assets/methods_description_template.yml", checkIfExists: true) /* @@ -211,12 +212,15 @@ workflow SMRNASEQ { if (!params.skip_multiqc) { workflow_summary = WorkflowSmrnaseq.paramsSummaryMultiqc(workflow, summary_params) ch_workflow_summary = Channel.value(workflow_summary) + methods_description = WorkflowSmrnaseq.methodsDescriptionText(workflow, ch_multiqc_custom_methods_description) + ch_methods_description = Channel.value(methods_description) ch_multiqc_files = Channel.empty() ch_multiqc_files = ch_multiqc_files.mix(Channel.from(ch_multiqc_config)) ch_multiqc_files = ch_multiqc_files.mix(CUSTOM_DUMPSOFTWAREVERSIONS.out.mqc_yml.collect()) ch_multiqc_files = ch_multiqc_files.mix(ch_multiqc_custom_config.collect().ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) + ch_multiqc_files = ch_multiqc_files.mix(ch_methods_description.collectFile(name: 'methods_description_mqc.yaml')) ch_multiqc_files = ch_multiqc_files.mix(FASTQC_TRIMGALORE.out.fastqc_zip.collect{it[1]}.ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(contamination_stats.collect().ifEmpty([])) From 56b99c43ea29a733baf89dea70819004811cb7b1 Mon Sep 17 00:00:00 2001 From: Jose Espinosa-Carrasco Date: Fri, 7 Oct 2022 15:52:55 +0200 Subject: [PATCH 054/215] Update workflows/smrnaseq.nf --- workflows/smrnaseq.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 7fd887d9..d9a7d9c7 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -236,7 +236,7 @@ workflow SMRNASEQ { ch_multiqc_custom_config.collect().ifEmpty([]), ch_multiqc_logo.collect().ifEmpty([]) ) - multiqc_report = MULTIQC.out.report.toList() + multiqc_report = MULTIQC.out.report.toList(), ch_versions = ch_versions.mix(MULTIQC.out.versions) } From 1aa9e9f6db63e5bb38059ec60684efab551bbad2 Mon Sep 17 00:00:00 2001 From: Jose Espinosa-Carrasco Date: Fri, 7 Oct 2022 16:00:18 +0200 Subject: [PATCH 055/215] Update workflows/smrnaseq.nf --- workflows/smrnaseq.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index d9a7d9c7..7fd887d9 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -236,7 +236,7 @@ workflow SMRNASEQ { ch_multiqc_custom_config.collect().ifEmpty([]), ch_multiqc_logo.collect().ifEmpty([]) ) - multiqc_report = MULTIQC.out.report.toList(), + multiqc_report = MULTIQC.out.report.toList() ch_versions = ch_versions.mix(MULTIQC.out.versions) } From 68b0403c3647ccb3fac874d928ec74191198d79c Mon Sep 17 00:00:00 2001 From: Jose Espinosa-Carrasco Date: Fri, 7 Oct 2022 16:05:34 +0200 Subject: [PATCH 056/215] Update workflows/smrnaseq.nf --- workflows/smrnaseq.nf | 1 + 1 file changed, 1 insertion(+) diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 7fd887d9..b5d75ca0 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -238,6 +238,7 @@ workflow SMRNASEQ { ) multiqc_report = MULTIQC.out.report.toList() ch_versions = ch_versions.mix(MULTIQC.out.versions) + } } /* From 8a19dab58bd42cba80919220d54dd082d221cbd3 Mon Sep 17 00:00:00 2001 From: JoseEspinosa Date: Fri, 7 Oct 2022 16:11:35 +0200 Subject: [PATCH 057/215] Fix modules include --- workflows/smrnaseq.nf | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index b5d75ca0..6a70bb7d 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -75,10 +75,10 @@ include { MIRDEEP2 } from '../subworkflows/local/mirdeep2' // // MODULE: Installed directly from nf-core/modules // -include { CAT_FASTQ } from '../modules/nf-core/modules/cat/fastq/main' -include { FASTQC } from '../modules/nf-core/modules/fastqc/main' -include { MULTIQC } from '../modules/nf-core/modules/multiqc/main' -include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/modules/custom/dumpsoftwareversions/main' +include { CAT_FASTQ } from '../modules/nf-core/cat/fastq/main' +include { FASTQC } from '../modules/nf-core/fastqc/main' +include { MULTIQC } from '../modules/nf-core/multiqc/main' +include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoftwareversions/main' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -230,14 +230,14 @@ workflow SMRNASEQ { ch_multiqc_files = ch_multiqc_files.mix(MIRNA_QUANT.out.mirtop_logs.collect().ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(MIRTRACE.out.results.collect().ifEmpty([])) - MULTIQC ( - ch_multiqc_files.collect(), - ch_multiqc_config.collect().ifEmpty([]), - ch_multiqc_custom_config.collect().ifEmpty([]), - ch_multiqc_logo.collect().ifEmpty([]) - ) - multiqc_report = MULTIQC.out.report.toList() - ch_versions = ch_versions.mix(MULTIQC.out.versions) + MULTIQC ( + ch_multiqc_files.collect(), + ch_multiqc_config.collect().ifEmpty([]), + ch_multiqc_custom_config.collect().ifEmpty([]), + ch_multiqc_logo.collect().ifEmpty([]) + ) + multiqc_report = MULTIQC.out.report.toList() + ch_versions = ch_versions.mix(MULTIQC.out.versions) } } From d6d5d61eff7de5ac4ec295bd9764c0a6688a756d Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Sun, 9 Oct 2022 11:18:02 +0200 Subject: [PATCH 058/215] Use toList() for input channels of multiqc --- workflows/smrnaseq.nf | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 6a70bb7d..bef00935 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -218,23 +218,23 @@ workflow SMRNASEQ { ch_multiqc_files = Channel.empty() ch_multiqc_files = ch_multiqc_files.mix(Channel.from(ch_multiqc_config)) ch_multiqc_files = ch_multiqc_files.mix(CUSTOM_DUMPSOFTWAREVERSIONS.out.mqc_yml.collect()) - ch_multiqc_files = ch_multiqc_files.mix(ch_multiqc_custom_config.collect().ifEmpty([])) + ch_multiqc_files = ch_multiqc_files.mix(ch_multiqc_custom_config.toList() ch_multiqc_files = ch_multiqc_files.mix(ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) ch_multiqc_files = ch_multiqc_files.mix(ch_methods_description.collectFile(name: 'methods_description_mqc.yaml')) ch_multiqc_files = ch_multiqc_files.mix(FASTQC_TRIMGALORE.out.fastqc_zip.collect{it[1]}.ifEmpty([])) - ch_multiqc_files = ch_multiqc_files.mix(contamination_stats.collect().ifEmpty([])) + ch_multiqc_files = ch_multiqc_files.mix(contamination_stats.toList()) ch_multiqc_files = ch_multiqc_files.mix(MIRNA_QUANT.out.mature_stats.collect({it[1]}).ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(MIRNA_QUANT.out.hairpin_stats.collect({it[1]}).ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(genome_stats.collect({it[1]}).ifEmpty([])) - ch_multiqc_files = ch_multiqc_files.mix(MIRNA_QUANT.out.mirtop_logs.collect().ifEmpty([])) - ch_multiqc_files = ch_multiqc_files.mix(MIRTRACE.out.results.collect().ifEmpty([])) + ch_multiqc_files = ch_multiqc_files.mix(MIRNA_QUANT.out.mirtop_logs.toList() + ch_multiqc_files = ch_multiqc_files.mix(MIRTRACE.out.results.toList() MULTIQC ( ch_multiqc_files.collect(), - ch_multiqc_config.collect().ifEmpty([]), - ch_multiqc_custom_config.collect().ifEmpty([]), - ch_multiqc_logo.collect().ifEmpty([]) + ch_multiqc_config.toList(), + ch_multiqc_custom_config.toList(), + ch_multiqc_logo.toList() ) multiqc_report = MULTIQC.out.report.toList() ch_versions = ch_versions.mix(MULTIQC.out.versions) From c4e15c10ebb49c5a7a21b409807e74e9c7f60dd1 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Sun, 9 Oct 2022 11:19:28 +0200 Subject: [PATCH 059/215] Typo fix --- workflows/smrnaseq.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index bef00935..a579685a 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -218,7 +218,7 @@ workflow SMRNASEQ { ch_multiqc_files = Channel.empty() ch_multiqc_files = ch_multiqc_files.mix(Channel.from(ch_multiqc_config)) ch_multiqc_files = ch_multiqc_files.mix(CUSTOM_DUMPSOFTWAREVERSIONS.out.mqc_yml.collect()) - ch_multiqc_files = ch_multiqc_files.mix(ch_multiqc_custom_config.toList() + ch_multiqc_files = ch_multiqc_files.mix(ch_multiqc_custom_config.toList()) ch_multiqc_files = ch_multiqc_files.mix(ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) ch_multiqc_files = ch_multiqc_files.mix(ch_methods_description.collectFile(name: 'methods_description_mqc.yaml')) From f34f0d0625f1c39ff121522f5be6209b07942c09 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Sun, 9 Oct 2022 11:20:40 +0200 Subject: [PATCH 060/215] Its typo sunday --- workflows/smrnaseq.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index a579685a..38a8bf03 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -227,8 +227,8 @@ workflow SMRNASEQ { ch_multiqc_files = ch_multiqc_files.mix(MIRNA_QUANT.out.mature_stats.collect({it[1]}).ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(MIRNA_QUANT.out.hairpin_stats.collect({it[1]}).ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(genome_stats.collect({it[1]}).ifEmpty([])) - ch_multiqc_files = ch_multiqc_files.mix(MIRNA_QUANT.out.mirtop_logs.toList() - ch_multiqc_files = ch_multiqc_files.mix(MIRTRACE.out.results.toList() + ch_multiqc_files = ch_multiqc_files.mix(MIRNA_QUANT.out.mirtop_logs.toList()) + ch_multiqc_files = ch_multiqc_files.mix(MIRTRACE.out.results.toList()) MULTIQC ( ch_multiqc_files.collect(), From e41c7d670492d20ab1fb8d0e22bf3df5d417c469 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Sun, 9 Oct 2022 14:11:37 +0200 Subject: [PATCH 061/215] Cleaned up MQC config stuff --- workflows/smrnaseq.nf | 3 --- 1 file changed, 3 deletions(-) diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 38a8bf03..9ef916b9 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -37,7 +37,6 @@ def mirna_gtf = params.mirna_gtf ?: mirna_gtf_from_species ch_multiqc_config = Channel.fromPath("$projectDir/assets/multiqc_config.yml", checkIfExists: true) ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath( params.multiqc_config, checkIfExists: true ) : Channel.empty() ch_multiqc_logo = params.multiqc_logo ? Channel.fromPath( params.multiqc_logo, checkIfExists: true ) : Channel.empty() -ch_multiqc_image = file("$projectDir/assets/smrnaseq_logo.png", checkIfExists: true) ch_multiqc_custom_methods_description = params.multiqc_methods_description ? file(params.multiqc_methods_description, checkIfExists: true) : file("$projectDir/assets/methods_description_template.yml", checkIfExists: true) /* @@ -216,9 +215,7 @@ workflow SMRNASEQ { ch_methods_description = Channel.value(methods_description) ch_multiqc_files = Channel.empty() - ch_multiqc_files = ch_multiqc_files.mix(Channel.from(ch_multiqc_config)) ch_multiqc_files = ch_multiqc_files.mix(CUSTOM_DUMPSOFTWAREVERSIONS.out.mqc_yml.collect()) - ch_multiqc_files = ch_multiqc_files.mix(ch_multiqc_custom_config.toList()) ch_multiqc_files = ch_multiqc_files.mix(ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) ch_multiqc_files = ch_multiqc_files.mix(ch_methods_description.collectFile(name: 'methods_description_mqc.yaml')) From 56e57fe37c32209a95cb6a10f05f6a597695fefd Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 10 Oct 2022 07:56:55 +0000 Subject: [PATCH 062/215] Fix everything, back to old normal --- workflows/smrnaseq.nf | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 9ef916b9..f39fb7bd 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -218,14 +218,13 @@ workflow SMRNASEQ { ch_multiqc_files = ch_multiqc_files.mix(CUSTOM_DUMPSOFTWAREVERSIONS.out.mqc_yml.collect()) ch_multiqc_files = ch_multiqc_files.mix(ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) ch_multiqc_files = ch_multiqc_files.mix(ch_methods_description.collectFile(name: 'methods_description_mqc.yaml')) - ch_multiqc_files = ch_multiqc_files.mix(FASTQC_TRIMGALORE.out.fastqc_zip.collect{it[1]}.ifEmpty([])) - ch_multiqc_files = ch_multiqc_files.mix(contamination_stats.toList()) + ch_multiqc_files = ch_multiqc_files.mix(contamination_stats.collect().ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(MIRNA_QUANT.out.mature_stats.collect({it[1]}).ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(MIRNA_QUANT.out.hairpin_stats.collect({it[1]}).ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(genome_stats.collect({it[1]}).ifEmpty([])) - ch_multiqc_files = ch_multiqc_files.mix(MIRNA_QUANT.out.mirtop_logs.toList()) - ch_multiqc_files = ch_multiqc_files.mix(MIRTRACE.out.results.toList()) + ch_multiqc_files = ch_multiqc_files.mix(MIRNA_QUANT.out.mirtop_logs.collect().ifEmpty([])) + ch_multiqc_files = ch_multiqc_files.mix(MIRTRACE.out.results.collect().ifEmpty([])) MULTIQC ( ch_multiqc_files.collect(), From 706ed69a2a9fc61f5d4389e87e8bc10849d2c3e8 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 10 Oct 2022 08:25:46 +0000 Subject: [PATCH 063/215] Added back fastp, not sure what went wrong --- modules.json | 80 ++++++++++---------- modules/nf-core/{modules => }/fastp/main.nf | 0 modules/nf-core/{modules => }/fastp/meta.yml | 0 subworkflows/nf-core/fastqc_fastp.nf | 6 +- 4 files changed, 44 insertions(+), 42 deletions(-) rename modules/nf-core/{modules => }/fastp/main.nf (100%) rename modules/nf-core/{modules => }/fastp/meta.yml (100%) diff --git a/modules.json b/modules.json index 4a74b7f4..173e2bf0 100644 --- a/modules.json +++ b/modules.json @@ -4,45 +4,47 @@ "repos": { "https://github.com/nf-core/modules.git": { "modules": { - "cat/fastq": { - "branch": "master", - "git_sha": "b034029b59b1198075da8019074bc02051a6100e" - }, - "custom/dumpsoftwareversions": { - "branch": "master", - "git_sha": "5e7b1ef9a5a2d9258635bcbf70fcf37dacd1b247" - }, - "fastp": { - "branch": "master", - "git_sha": "2c70c1c1951aaf884d2e8d8d9c871db79f7b35aa" - }, - "fastqc": { - "branch": "master", - "git_sha": "49b18b1639f4f7104187058866a8fab33332bdfe" - }, - "multiqc": { - "branch": "master", - "git_sha": "5587389874dac9c9953a2ab6f01d49af81969492" - }, - "samtools/flagstat": { - "branch": "master", - "git_sha": "bbb99cb8d679555cc01c98766de7869f83283545" - }, - "samtools/idxstats": { - "branch": "master", - "git_sha": "ecece498f10b47b7c9d06f53a310cea5811b4c5f" - }, - "samtools/index": { - "branch": "master", - "git_sha": "897c33d5da084b61109500ee44c01da2d3e4e773" - }, - "samtools/sort": { - "branch": "master", - "git_sha": "897c33d5da084b61109500ee44c01da2d3e4e773" - }, - "samtools/stats": { - "branch": "master", - "git_sha": "f4eab7945952dc4934224309701a49913ea05ae6" + "nf-core": { + "cat/fastq": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "custom/dumpsoftwareversions": { + "branch": "master", + "git_sha": "8022c68e7403eecbd8ba9c49496f69f8c49d50f0" + }, + "fastp": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "fastqc": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "multiqc": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "samtools/flagstat": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "samtools/idxstats": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "samtools/index": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "samtools/sort": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + }, + "samtools/stats": { + "branch": "master", + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + } } } } diff --git a/modules/nf-core/modules/fastp/main.nf b/modules/nf-core/fastp/main.nf similarity index 100% rename from modules/nf-core/modules/fastp/main.nf rename to modules/nf-core/fastp/main.nf diff --git a/modules/nf-core/modules/fastp/meta.yml b/modules/nf-core/fastp/meta.yml similarity index 100% rename from modules/nf-core/modules/fastp/meta.yml rename to modules/nf-core/fastp/meta.yml diff --git a/subworkflows/nf-core/fastqc_fastp.nf b/subworkflows/nf-core/fastqc_fastp.nf index 87edb94f..27fdce53 100644 --- a/subworkflows/nf-core/fastqc_fastp.nf +++ b/subworkflows/nf-core/fastqc_fastp.nf @@ -2,9 +2,9 @@ // Read QC and trimming // -include { FASTQC as FASTQC_RAW } from '../../modules/nf-core/modules/fastqc/main' -include { FASTQC as FASTQC_TRIM } from '../../modules/nf-core/modules/fastqc/main' -include { FASTP } from '../../modules/nf-core/modules/fastp/main' +include { FASTQC as FASTQC_RAW } from '../../modules/nf-core/fastqc/main' +include { FASTQC as FASTQC_TRIM } from '../../modules/nf-core/fastqc/main' +include { FASTP } from '../../modules/nf-core/fastp/main' // // Function that parses fastp json output file to get total number of reads after trimming From 4524c6245d464f3bc13a9d42ee47edc14bc83482 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 10 Oct 2022 08:32:15 +0000 Subject: [PATCH 064/215] Added when statements to most local modules --- modules/local/blat_mirna.nf | 4 +++- modules/local/bowtie_contaminants.nf | 3 +++ modules/local/bowtie_genome.nf | 3 +++ modules/local/bowtie_map_contaminants.nf | 5 ++++- modules/local/bowtie_map_mirna.nf | 3 +++ modules/local/bowtie_mirna.nf | 3 +++ modules/local/datatable_merge.nf | 3 +++ modules/local/edger_qc.nf | 3 +++ modules/local/filter_stats.nf | 3 +++ modules/local/format_fasta_mirna.nf | 3 +++ modules/local/mirdeep2_mapper.nf | 2 ++ modules/local/mirdeep2_prepare.nf | 3 +++ modules/local/mirdeep2_run.nf | 3 +++ modules/local/mirtop_quant.nf | 3 +++ modules/local/mirtrace.nf | 3 +++ modules/local/parse_fasta_mirna.nf | 3 +++ modules/local/samplesheet_check.nf | 3 +++ modules/local/seqcluster_collapse.nf | 3 +++ 18 files changed, 54 insertions(+), 2 deletions(-) diff --git a/modules/local/blat_mirna.nf b/modules/local/blat_mirna.nf index b0037565..da7f6449 100644 --- a/modules/local/blat_mirna.nf +++ b/modules/local/blat_mirna.nf @@ -17,8 +17,10 @@ process BLAT_MIRNA { path 'filtered.fa' , emit: filtered_set path "versions.yml" , emit: versions - script: + when: + task.ext.when == null || task.ext.when + script: if ( db_type == "cdna" ) """ echo $db_type diff --git a/modules/local/bowtie_contaminants.nf b/modules/local/bowtie_contaminants.nf index 4fd04643..bd8324b0 100644 --- a/modules/local/bowtie_contaminants.nf +++ b/modules/local/bowtie_contaminants.nf @@ -13,6 +13,9 @@ process INDEX_CONTAMINANTS { path 'fasta_bidx*' , emit: index path "versions.yml" , emit: versions + when: + task.ext.when == null || task.ext.when + script: """ bowtie2-build ${fasta} fasta_bidx --threads ${task.cpus} diff --git a/modules/local/bowtie_genome.nf b/modules/local/bowtie_genome.nf index cdf572f7..08379866 100644 --- a/modules/local/bowtie_genome.nf +++ b/modules/local/bowtie_genome.nf @@ -15,6 +15,9 @@ process INDEX_GENOME { path 'genome.edited.fa', emit: fasta path "versions.yml" , emit: versions + when: + task.ext.when == null || task.ext.when + script: """ # Remove any special base characters from reference genome FASTA file diff --git a/modules/local/bowtie_map_contaminants.nf b/modules/local/bowtie_map_contaminants.nf index 397aae82..07ce3a28 100644 --- a/modules/local/bowtie_map_contaminants.nf +++ b/modules/local/bowtie_map_contaminants.nf @@ -15,7 +15,10 @@ process BOWTIE_MAP_CONTAMINANTS { tuple val(meta), path("*sam") , emit: bam tuple val(meta), path('*.filter.unmapped.contaminant.fastq'), emit: unmapped path "versions.yml" , emit: versions - path "filtered.*.stats" , emit: stats + path "filtered.*.stats" + , emit: stats + when: + task.ext.when == null || task.ext.when script: """ diff --git a/modules/local/bowtie_map_mirna.nf b/modules/local/bowtie_map_mirna.nf index 316f94af..c35f9a68 100644 --- a/modules/local/bowtie_map_mirna.nf +++ b/modules/local/bowtie_map_mirna.nf @@ -16,6 +16,9 @@ process BOWTIE_MAP_SEQ { tuple val(meta), path('unmapped/*fq.gz'), emit: unmapped path "versions.yml" , emit: versions + when: + task.ext.when == null || task.ext.when + script: """ INDEX=`find -L ./ -name "*.3.ebwt" | sed 's/.3.ebwt//'` diff --git a/modules/local/bowtie_mirna.nf b/modules/local/bowtie_mirna.nf index 07050538..0da7349c 100644 --- a/modules/local/bowtie_mirna.nf +++ b/modules/local/bowtie_mirna.nf @@ -13,6 +13,9 @@ process INDEX_MIRNA { path 'fasta_bidx*' , emit: index path "versions.yml", emit: versions + when: + task.ext.when == null || task.ext.when + script: """ bowtie-build ${fasta} fasta_bidx --threads ${task.cpus} diff --git a/modules/local/datatable_merge.nf b/modules/local/datatable_merge.nf index 3fec291b..8a1ed3b5 100644 --- a/modules/local/datatable_merge.nf +++ b/modules/local/datatable_merge.nf @@ -13,6 +13,9 @@ process TABLE_MERGE { path "mirna.tsv" , emit: mirna_tsv path "versions.yml", emit: versions + when: + task.ext.when == null || task.ext.when + script: """ collapse_mirtop.r ${mirtop} diff --git a/modules/local/edger_qc.nf b/modules/local/edger_qc.nf index d8a4c520..023f70be 100644 --- a/modules/local/edger_qc.nf +++ b/modules/local/edger_qc.nf @@ -13,6 +13,9 @@ process EDGER_QC { path '*.{txt,pdf,csv}', emit: edger_files path "versions.yml" , emit: versions + when: + task.ext.when == null || task.ext.when + script: """ edgeR_miRBase.r $input_files diff --git a/modules/local/filter_stats.nf b/modules/local/filter_stats.nf index f0819e99..1db0d49b 100644 --- a/modules/local/filter_stats.nf +++ b/modules/local/filter_stats.nf @@ -14,6 +14,9 @@ process FILTER_STATS { path "*_mqc.yaml" , emit: stats tuple val(meta), path('*.filtered.fastq.gz') , emit: reads + when: + task.ext.when == null || task.ext.when + script: """ readnumber=\$(wc -l ${reads} | awk '{ print \$1/4 }') diff --git a/modules/local/format_fasta_mirna.nf b/modules/local/format_fasta_mirna.nf index ae8a3fda..d19901fd 100644 --- a/modules/local/format_fasta_mirna.nf +++ b/modules/local/format_fasta_mirna.nf @@ -16,6 +16,9 @@ process FORMAT_FASTA_MIRNA { path '*_idx.fa' , emit: formatted_fasta path "versions.yml", emit: versions + when: + task.ext.when == null || task.ext.when + script: """ fasta_formatter -w 0 -i $fasta -o ${fasta}_idx.fa diff --git a/modules/local/mirdeep2_mapper.nf b/modules/local/mirdeep2_mapper.nf index 7368f4b0..7d90712b 100644 --- a/modules/local/mirdeep2_mapper.nf +++ b/modules/local/mirdeep2_mapper.nf @@ -17,6 +17,8 @@ process MIRDEEP2_MAPPER { tuple path('*_collapsed.fa'), path('*reads_vs_refdb.arf'), emit: mirdeep2_inputs path "versions.yml" , emit: versions + when: + task.ext.when == null || task.ext.when script: def index_base = index.toString().tokenize(' ')[0].tokenize('.')[0] diff --git a/modules/local/mirdeep2_prepare.nf b/modules/local/mirdeep2_prepare.nf index d49270ff..9fcc2ed5 100644 --- a/modules/local/mirdeep2_prepare.nf +++ b/modules/local/mirdeep2_prepare.nf @@ -15,6 +15,9 @@ process MIRDEEP2_PIGZ { tuple val(meta), path("*.{fastq,fq}"), emit: reads path "versions.yml" , emit: versions + when: + task.ext.when == null || task.ext.when + script: """ pigz -f -d -p $task.cpus $reads diff --git a/modules/local/mirdeep2_run.nf b/modules/local/mirdeep2_run.nf index 8f72cbe2..ee4cfc0d 100644 --- a/modules/local/mirdeep2_run.nf +++ b/modules/local/mirdeep2_run.nf @@ -19,6 +19,9 @@ process MIRDEEP2_RUN { path 'result*.{bed,csv,html}', emit: result path "versions.yml" , emit: versions + when: + task.ext.when == null || task.ext.when + script: """ miRDeep2.pl \\ diff --git a/modules/local/mirtop_quant.nf b/modules/local/mirtop_quant.nf index 2ce3e1c6..b6f72a89 100644 --- a/modules/local/mirtop_quant.nf +++ b/modules/local/mirtop_quant.nf @@ -18,6 +18,9 @@ process MIRTOP_QUANT { path "mirtop/stats/*" , emit: logs path "versions.yml" , emit: versions + when: + task.ext.when == null || task.ext.when + script: def filter_species = params.mirgenedb ? params.mirgenedb_species : params.mirtrace_species """ diff --git a/modules/local/mirtrace.nf b/modules/local/mirtrace.nf index fee8e071..cd44adb8 100644 --- a/modules/local/mirtrace.nf +++ b/modules/local/mirtrace.nf @@ -13,6 +13,9 @@ process MIRTRACE_RUN { path "mirtrace/*" , emit: mirtrace path "versions.yml", emit: versions + when: + task.ext.when == null || task.ext.when + script: // mirtrace protocol defaults to 'params.protocol' if not set def primer = params.protocol == 'cats' ? '' : "--adapter ${params.three_prime_adapter}" diff --git a/modules/local/parse_fasta_mirna.nf b/modules/local/parse_fasta_mirna.nf index 88626bec..5a92b202 100644 --- a/modules/local/parse_fasta_mirna.nf +++ b/modules/local/parse_fasta_mirna.nf @@ -13,6 +13,9 @@ process PARSE_FASTA_MIRNA { path '*_igenome.fa', emit: parsed_fasta path "versions.yml", emit: versions + when: + task.ext.when == null || task.ext.when + script: def filter_species = params.mirgenedb ? params.mirgenedb_species : params.mirtrace_species """ diff --git a/modules/local/samplesheet_check.nf b/modules/local/samplesheet_check.nf index c0265a72..74f5a8c9 100644 --- a/modules/local/samplesheet_check.nf +++ b/modules/local/samplesheet_check.nf @@ -14,6 +14,9 @@ process SAMPLESHEET_CHECK { path '*.csv' , emit: csv path "versions.yml", emit: versions + when: + task.ext.when == null || task.ext.when + script: // This script is bundled with the pipeline, in nf-core/smrnaseq/bin/ """ check_samplesheet.py \\ diff --git a/modules/local/seqcluster_collapse.nf b/modules/local/seqcluster_collapse.nf index f430e65f..46239775 100644 --- a/modules/local/seqcluster_collapse.nf +++ b/modules/local/seqcluster_collapse.nf @@ -14,6 +14,9 @@ process SEQCLUSTER_SEQUENCES { tuple val(meta), path("final/*.fastq.gz"), emit: collapsed path "versions.yml" , emit: versions + when: + task.ext.when == null || task.ext.when + script: """ seqcluster collapse -f $reads -m 1 --min_size 15 -o collapsed From ccfd277101649e902e0b2b20688561ae52c6fb36 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 10 Oct 2022 08:38:31 +0000 Subject: [PATCH 065/215] Tiny module update --- modules/local/bowtie_genome.nf | 8 ++++---- modules/local/bowtie_mirna.nf | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/local/bowtie_genome.nf b/modules/local/bowtie_genome.nf index 08379866..1fb38551 100644 --- a/modules/local/bowtie_genome.nf +++ b/modules/local/bowtie_genome.nf @@ -2,10 +2,10 @@ process INDEX_GENOME { tag "$fasta" label 'process_medium' - conda (params.enable_conda ? 'bioconda::bowtie=1.3.0-2' : null) + conda (params.enable_conda ? 'bioconda::bowtie=1.3.1-4' : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/bowtie:1.3.0--py38hcf49a77_2' : - 'quay.io/biocontainers/bowtie:1.3.0--py38hcf49a77_2' }" + 'https://depot.galaxyproject.org/singularity/bowtie%3A1.3.1--py39hd400a0c_2' : + 'quay.io/biocontainers/bowtie:1.3.1--py310h4070885_4' }" input: path fasta @@ -17,7 +17,7 @@ process INDEX_GENOME { when: task.ext.when == null || task.ext.when - + script: """ # Remove any special base characters from reference genome FASTA file diff --git a/modules/local/bowtie_mirna.nf b/modules/local/bowtie_mirna.nf index 0da7349c..0be5888b 100644 --- a/modules/local/bowtie_mirna.nf +++ b/modules/local/bowtie_mirna.nf @@ -3,8 +3,8 @@ process INDEX_MIRNA { conda (params.enable_conda ? 'bioconda::bowtie=1.3.0-2' : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/bowtie:1.3.0--py38hcf49a77_2' : - 'quay.io/biocontainers/bowtie:1.3.0--py38hcf49a77_2' }" + 'https://depot.galaxyproject.org/singularity/bowtie%3A1.3.1--py39hd400a0c_2' : + 'quay.io/biocontainers/bowtie:1.3.1--py310h4070885_4' }" input: path fasta From df2ee0e13d5ef267bbb34b561055150cd97a3734 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 10 Oct 2022 08:41:43 +0000 Subject: [PATCH 066/215] Hopefully fixing editorconfig --- modules/local/bowtie_contaminants.nf | 4 ++-- modules/local/bowtie_map_mirna.nf | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/local/bowtie_contaminants.nf b/modules/local/bowtie_contaminants.nf index bd8324b0..1145b56f 100644 --- a/modules/local/bowtie_contaminants.nf +++ b/modules/local/bowtie_contaminants.nf @@ -4,7 +4,7 @@ process INDEX_CONTAMINANTS { conda (params.enable_conda ? 'bowtie2=2.4.5' : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/bowtie2:2.4.5--py39hd2f7db1_2' : - 'quay.io/biocontainers/bowtie2:2.4.5--py36hfca12d5_2' }" + 'quay.io/biocontainers/bowtie2:2.4.5--py36hfca12d5_2'}" input: path fasta @@ -15,7 +15,7 @@ process INDEX_CONTAMINANTS { when: task.ext.when == null || task.ext.when - + script: """ bowtie2-build ${fasta} fasta_bidx --threads ${task.cpus} diff --git a/modules/local/bowtie_map_mirna.nf b/modules/local/bowtie_map_mirna.nf index c35f9a68..82d7acf8 100644 --- a/modules/local/bowtie_map_mirna.nf +++ b/modules/local/bowtie_map_mirna.nf @@ -18,7 +18,7 @@ process BOWTIE_MAP_SEQ { when: task.ext.when == null || task.ext.when - + script: """ INDEX=`find -L ./ -name "*.3.ebwt" | sed 's/.3.ebwt//'` From 2afe4181f50069993340372e743ee502c00e05fe Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 10 Oct 2022 08:59:53 +0000 Subject: [PATCH 067/215] Add back when statements --- modules/local/bowtie_map_contaminants.nf | 5 +++-- workflows/smrnaseq.nf | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/modules/local/bowtie_map_contaminants.nf b/modules/local/bowtie_map_contaminants.nf index 07ce3a28..c3daa9be 100644 --- a/modules/local/bowtie_map_contaminants.nf +++ b/modules/local/bowtie_map_contaminants.nf @@ -15,8 +15,8 @@ process BOWTIE_MAP_CONTAMINANTS { tuple val(meta), path("*sam") , emit: bam tuple val(meta), path('*.filter.unmapped.contaminant.fastq'), emit: unmapped path "versions.yml" , emit: versions - path "filtered.*.stats" - , emit: stats + path "filtered.*.stats" , emit: stats + when: task.ext.when == null || task.ext.when @@ -30,6 +30,7 @@ process BOWTIE_MAP_CONTAMINANTS { -x \$INDEX \\ --un ${meta.id}.${contaminant_type}.filter.unmapped.contaminant.fastq \\ ${reads} \\ + ${args} \\ -S ${meta.id}.filter.contaminant.sam > ${meta.id}.contaminant_bowtie.log 2>&1 # extracting number of reads from bowtie logs diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 104b4c67..80aab3d7 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -74,9 +74,9 @@ include { MIRDEEP2 } from '../subworkflows/local/mirdeep2' // // MODULE: Installed directly from nf-core/modules // -include { CAT_FASTQ } from '../modules/nf-core/modules/cat/fastq/main' -include { MULTIQC } from '../modules/nf-core/modules/multiqc/main' -include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/modules/custom/dumpsoftwareversions/main' +include { CAT_FASTQ } from '../modules/nf-core/cat/fastq/main' +include { MULTIQC } from '../modules/nf-core/multiqc/main' +include { CUSTOM_DUMPSOFTWAREVERSIONS } from '../modules/nf-core/custom/dumpsoftwareversions/main' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 75d11a2bd5d9f79684fbe4e1366a610a62ad0685 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 10 Oct 2022 09:16:03 +0000 Subject: [PATCH 068/215] Tried adding more stuff --- conf/modules.config | 2 +- lib/WorkflowSmrnaseq.groovy | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 189e3011..439d30b9 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -104,7 +104,7 @@ if (!params.skip_fastp) { params.three_prime_clip_r1 > 0 ? "--trim_tail1 ${params.three_prime_clip_r1}" : "", // Remove bp from the 3' end of read 1 AFTER adapter/quality trimming has been performed. params.fastp_min_length > 0 ? "-l ${params.fastp_min_length}" : "", params.fastp_max_length > 0 ? "--max_len1 ${params.fastp_max_length}" : "", - params.three_prime_adapter.isEmpty() ? "" : "--adapter_sequence ${params.three_prime_adapter}" + params.three_prime_adapter == "" ? "" : "--adapter_sequence ${params.three_prime_adapter}" ].join(" ").trim() publishDir = [ [ diff --git a/lib/WorkflowSmrnaseq.groovy b/lib/WorkflowSmrnaseq.groovy index 9075116a..cd8b1e1e 100755 --- a/lib/WorkflowSmrnaseq.groovy +++ b/lib/WorkflowSmrnaseq.groovy @@ -11,11 +11,6 @@ class WorkflowSmrnaseq { // public static void initialise(params, log) { genomeExistsError(params, log) - - // if (!params.fasta) { - // log.error "Genome fasta file not specified with e.g. '--fasta genome.fa' or via a detectable config file." - // System.exit(1) - // } } // @@ -103,6 +98,9 @@ class WorkflowSmrnaseq { params.putIfAbsent("three_prime_clip_r1", 0); params.putIfAbsent("three_prime_adapter", "AAAAAAAA"); break + case 'custom': + params.putIfAbsent("clip_r1", params.clip_r1) + params.putIfAbsent("three_prime_clip_r1", params.three_prime_clip_r1) default: log.warn "Please make sure to specify all required clipping and trimming parameters, otherwise only adapter detection will be performed." } From d0e64f1c50babce1fea990c975a9003e846452a8 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 10 Oct 2022 09:22:26 +0000 Subject: [PATCH 069/215] Try going back to '' --- conf/modules.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/modules.config b/conf/modules.config index 439d30b9..32386bfd 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -104,7 +104,7 @@ if (!params.skip_fastp) { params.three_prime_clip_r1 > 0 ? "--trim_tail1 ${params.three_prime_clip_r1}" : "", // Remove bp from the 3' end of read 1 AFTER adapter/quality trimming has been performed. params.fastp_min_length > 0 ? "-l ${params.fastp_min_length}" : "", params.fastp_max_length > 0 ? "--max_len1 ${params.fastp_max_length}" : "", - params.three_prime_adapter == "" ? "" : "--adapter_sequence ${params.three_prime_adapter}" + params.three_prime_adapter == '' ? "" : "--adapter_sequence ${params.three_prime_adapter}" ].join(" ").trim() publishDir = [ [ From 5ba44edf4a8c9da206b644ab52b16799f74bda5f Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 10 Oct 2022 09:30:51 +0000 Subject: [PATCH 070/215] Hopefully should do the trick --- conf/modules.config | 2 +- nextflow.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 32386bfd..c7b7e140 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -104,7 +104,7 @@ if (!params.skip_fastp) { params.three_prime_clip_r1 > 0 ? "--trim_tail1 ${params.three_prime_clip_r1}" : "", // Remove bp from the 3' end of read 1 AFTER adapter/quality trimming has been performed. params.fastp_min_length > 0 ? "-l ${params.fastp_min_length}" : "", params.fastp_max_length > 0 ? "--max_len1 ${params.fastp_max_length}" : "", - params.three_prime_adapter == '' ? "" : "--adapter_sequence ${params.three_prime_adapter}" + params.three_prime_adapter == '' ? '' : "--adapter_sequence ${params.three_prime_adapter}" ].join(" ").trim() publishDir = [ [ diff --git a/nextflow.config b/nextflow.config index 4003031f..34ed3c9b 100644 --- a/nextflow.config +++ b/nextflow.config @@ -71,7 +71,7 @@ params { help = false validate_params = true show_hidden_params = false - schema_ignore_params = 'genomes' + schema_ignore_params = 'genomes,three_prime_adapter' enable_conda = false // Config options From c861998ddebccc9b54b8fb9746544c7c5dd110ab Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 10 Oct 2022 09:36:47 +0000 Subject: [PATCH 071/215] Fix things properly --- conf/modules.config | 2 +- nextflow.config | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index c7b7e140..cdd5a80f 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -104,7 +104,7 @@ if (!params.skip_fastp) { params.three_prime_clip_r1 > 0 ? "--trim_tail1 ${params.three_prime_clip_r1}" : "", // Remove bp from the 3' end of read 1 AFTER adapter/quality trimming has been performed. params.fastp_min_length > 0 ? "-l ${params.fastp_min_length}" : "", params.fastp_max_length > 0 ? "--max_len1 ${params.fastp_max_length}" : "", - params.three_prime_adapter == '' ? '' : "--adapter_sequence ${params.three_prime_adapter}" + params.three_prime_adapter == null ? '' : "--adapter_sequence ${params.three_prime_adapter}" ].join(" ").trim() publishDir = [ [ diff --git a/nextflow.config b/nextflow.config index 34ed3c9b..afb1b01f 100644 --- a/nextflow.config +++ b/nextflow.config @@ -31,7 +31,7 @@ params { // Trimming options clip_r1 = null three_prime_clip_r1 = null - three_prime_adapter = "TGGAATTCTCGGGTGCCAAGG" + three_prime_adapter = null trim_fastq = true fastp_min_length = 17 save_trimmed_fail = false @@ -71,7 +71,7 @@ params { help = false validate_params = true show_hidden_params = false - schema_ignore_params = 'genomes,three_prime_adapter' + schema_ignore_params = 'genomes' enable_conda = false // Config options From 43bed1c38b08d5517eed6958141e30aee6ebbba0 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 10 Oct 2022 10:37:36 +0000 Subject: [PATCH 072/215] add function for adapter sequence output --- subworkflows/nf-core/fastqc_fastp.nf | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/subworkflows/nf-core/fastqc_fastp.nf b/subworkflows/nf-core/fastqc_fastp.nf index 27fdce53..a4b5f3db 100644 --- a/subworkflows/nf-core/fastqc_fastp.nf +++ b/subworkflows/nf-core/fastqc_fastp.nf @@ -16,6 +16,11 @@ def getFastpReadsAfterFiltering(json_file) { return json['after_filtering']['total_reads'].toInteger() } +def getFastpAdapterSequence(json_file){ + def Map json = (Map) new JsonSlurper().parseText(json_file.text).get('adapter_cutting') + return json['read1_adapter_sequence'].toString() +} + workflow FASTQC_FASTP { take: reads // channel: [ val(meta), [ reads ] ] From 171288d60d3632a84de6c2fd86f4ac5f54c09865 Mon Sep 17 00:00:00 2001 From: Rob Syme Date: Mon, 10 Oct 2022 14:16:41 +0000 Subject: [PATCH 073/215] Document that a second fastq file will be ignored. --- docs/usage.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index 89d438ad..b44ac8c6 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -56,7 +56,9 @@ Contamination filtering of the sequencing reads is optional and can be invoked u ## Samplesheet input -You will need to create a samplesheet with information about the samples you would like to analyse before running the pipeline. Use this parameter to specify its location. It has to be a comma-separated file with 3 columns, and a header row as shown in the examples below. +You will need to create a samplesheet with information about the samples you would like to analyse before running the pipeline. Use this parameter to specify its location. It has to be a comma-separated file with 2 columns ("sample" and "fastq_1"), and a header row as shown in the examples below. + +If a second fastq file is provided using another column, the extra data are ignored by this pipeline. The smRNA species should be sufficiently contained in the first read, and so the second read is superfluous data in this smRNA context. ```bash --input '[path to samplesheet file]' From 9c845d37ee95dc010c51fe7c4834d3cead221bcc Mon Sep 17 00:00:00 2001 From: Rob Syme Date: Mon, 10 Oct 2022 15:30:19 +0000 Subject: [PATCH 074/215] Include adapter sequence in fastq_fastp --- subworkflows/nf-core/fastqc_fastp.nf | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/subworkflows/nf-core/fastqc_fastp.nf b/subworkflows/nf-core/fastqc_fastp.nf index a4b5f3db..b93672bf 100644 --- a/subworkflows/nf-core/fastqc_fastp.nf +++ b/subworkflows/nf-core/fastqc_fastp.nf @@ -12,13 +12,17 @@ include { FASTP } from '../../modules/nf-core/fastp/main' import groovy.json.JsonSlurper def getFastpReadsAfterFiltering(json_file) { - def Map json = (Map) new JsonSlurper().parseText(json_file.text).get('summary') - return json['after_filtering']['total_reads'].toInteger() + return new JsonSlurper().parseText(json_file.text) + ?.get('summary') + ?.get('after_filtering') + ?.get('total_reads') + ?.toInteger() } -def getFastpAdapterSequence(json_file){ - def Map json = (Map) new JsonSlurper().parseText(json_file.text).get('adapter_cutting') - return json['read1_adapter_sequence'].toString() +String getFastpAdapterSequence(json_file){ + return new JsonSlurper().parseText(json_file.text) + ?.get('adapter_cutting') + ?.get('read1_adapter_sequence') } workflow FASTQC_FASTP { @@ -78,6 +82,10 @@ workflow FASTQC_FASTP { } .set { trim_reads } + trim_json + .map { meta, json -> [meta, getFastpAdapterSequence(json)] } + .set { adapterseq } + if (!params.skip_fastqc) { FASTQC_TRIM ( trim_reads @@ -95,6 +103,7 @@ workflow FASTQC_FASTP { trim_log // channel: [ val(meta), [ log ] ] trim_reads_fail // channel: [ val(meta), [ fastq.gz ] ] trim_reads_merged // channel: [ val(meta), [ fastq.gz ] ] + adapterseq // channel: [ val(meat), [ adapterseq ] ] fastqc_raw_html // channel: [ val(meta), [ html ] ] fastqc_raw_zip // channel: [ val(meta), [ zip ] ] From d70b70cf09f4a7a20320065a215ddc68a8ee91b7 Mon Sep 17 00:00:00 2001 From: Rob Syme Date: Mon, 10 Oct 2022 15:30:39 +0000 Subject: [PATCH 075/215] Thread adapter sequence through workflow --- conf/modules.config | 2 +- modules/local/mirtrace.nf | 4 ++-- subworkflows/local/mirtrace.nf | 7 +------ workflows/smrnaseq.nf | 17 +++++++++++------ 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index cdd5a80f..0c5365fb 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -80,7 +80,7 @@ process { process { withName: 'MIRTRACE_RUN' { publishDir = [ - path: { "${params.outdir}/mirtrace" }, + path: { "${params.outdir}/mirtrace/${meta.id}" }, mode: params.publish_dir_mode, saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] diff --git a/modules/local/mirtrace.nf b/modules/local/mirtrace.nf index cd44adb8..8683d5ce 100644 --- a/modules/local/mirtrace.nf +++ b/modules/local/mirtrace.nf @@ -7,7 +7,7 @@ process MIRTRACE_RUN { 'quay.io/biocontainers/mirtrace:1.0.1--hdfd78af_1' }" input: - path reads + tuple val(meta), path(reads) output: path "mirtrace/*" , emit: mirtrace @@ -18,7 +18,7 @@ process MIRTRACE_RUN { script: // mirtrace protocol defaults to 'params.protocol' if not set - def primer = params.protocol == 'cats' ? '' : "--adapter ${params.three_prime_adapter}" + def primer = meta.adapter ? "--adapter ${meta.adapter}" : "" def protocol = params.protocol == 'custom' ? '' : "--protocol $params.protocol" def java_mem = '' if(task.memory){ diff --git a/subworkflows/local/mirtrace.nf b/subworkflows/local/mirtrace.nf index ea4fc3a7..38d51975 100644 --- a/subworkflows/local/mirtrace.nf +++ b/subworkflows/local/mirtrace.nf @@ -10,12 +10,7 @@ workflow MIRTRACE { main: reads - .map { it[1] } - .flatten() - .dump(tag:'mirtrace') - .set { all_reads } - - MIRTRACE_RUN ( all_reads.collect() ) + | MIRTRACE_RUN emit: results = MIRTRACE_RUN.out.mirtrace diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 80aab3d7..5e1fca50 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -126,12 +126,6 @@ workflow SMRNASEQ { .set { ch_cat_fastq } ch_versions = ch_versions.mix(CAT_FASTQ.out.versions.first().ifEmpty(null)) - // - // SUBWORKFLOW: mirtrace QC - // - MIRTRACE (ch_cat_fastq) - ch_versions = ch_versions.mix(MIRTRACE.out.versions.ifEmpty(null)) - // // SUBWORKFLOW: Read QC and trim adapters // @@ -145,6 +139,17 @@ workflow SMRNASEQ { ch_versions = ch_versions.mix(FASTQC_FASTP.out.versions) reads_for_mirna = FASTQC_FASTP.out.reads + + // + // SUBWORKFLOW: mirtrace QC + // + FASTQC_FASTP.out.adapterseq + | join( ch_cat_fastq ) + | map { meta, adapterseq, fastq -> [meta + [adapter:adapterseq], fastq] } + | MIRTRACE + + ch_versions = ch_versions.mix(MIRTRACE.out.versions.ifEmpty(null)) + // // SUBWORKFLOW: remove contaminants from reads // From f8f30fa24b9d740783ebe9a77c00234b4267652a Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Tue, 11 Oct 2022 09:12:56 +0000 Subject: [PATCH 076/215] Update changelog for 2.1.0 release, add config changes and update module --- CHANGELOG.md | 2 +- modules/local/parse_fasta_mirna.nf | 6 +++--- nextflow.config | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73b0b8ba..afa672fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 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). -## v2.1.0dev - [date] +## v2.1.0 - (https://github.com/nf-core/smrnaseq/releases/tag/2.1.0) - 2022-10-11 Maroon Tin Dalmatian ### Enhancements & fixes diff --git a/modules/local/parse_fasta_mirna.nf b/modules/local/parse_fasta_mirna.nf index 5a92b202..619cb427 100644 --- a/modules/local/parse_fasta_mirna.nf +++ b/modules/local/parse_fasta_mirna.nf @@ -1,10 +1,10 @@ process PARSE_FASTA_MIRNA { label 'process_medium' - conda (params.enable_conda ? 'bioconda::seqkit=2.0.0' : null) + conda (params.enable_conda ? 'bioconda::seqkit=2.3.1' : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/seqkit:2.0.0--h9ee0642_0' : - 'quay.io/biocontainers/seqkit:2.0.0--h9ee0642_0' }" + 'https://depot.galaxyproject.org/singularity/seqkit:2.3.1--h9ee0642_0' : + 'quay.io/biocontainers/seqkit:2.3.1--h9ee0642_0' }" input: path fasta diff --git a/nextflow.config b/nextflow.config index afb1b01f..c1469e06 100644 --- a/nextflow.config +++ b/nextflow.config @@ -221,7 +221,7 @@ manifest { description = 'Small RNA-Seq Best Practice Analysis Pipeline.' mainScript = 'main.nf' nextflowVersion = '!>=21.10.3' - version = '2.1.0dev' + version = '2.1.0' doi = '' } From 577cd851df80dbcc46e39bf53cab3ae8579ab944 Mon Sep 17 00:00:00 2001 From: Rob Syme Date: Tue, 11 Oct 2022 12:51:35 +0000 Subject: [PATCH 077/215] More flexible samplesheet handling In preparation for handling adapter sequences in the samplesheet, we now pass through all columns in the samplesheet as keys in the meta map. The commit also removes a bunch of redundant fastq_2 checking which we don't use. --- bin/check_samplesheet.py | 74 +++++++++++++------------------ subworkflows/local/input_check.nf | 11 ++--- workflows/smrnaseq.nf | 6 --- 3 files changed, 34 insertions(+), 57 deletions(-) diff --git a/bin/check_samplesheet.py b/bin/check_samplesheet.py index 3ca65774..24252b4b 100755 --- a/bin/check_samplesheet.py +++ b/bin/check_samplesheet.py @@ -55,55 +55,45 @@ def check_samplesheet(file_in, file_out): MIN_COLS = 2 HEADER = ["sample", "fastq_1"] header = [x.strip('"') for x in fin.readline().strip().split(",")] - if header[: len(HEADER)] != HEADER: - print("ERROR: Please check samplesheet header -> {} != {}".format(",".join(header), ",".join(HEADER))) + if any([item not in header for item in HEADER]): + missing = [item for item in HEADER if item not in header] + eprint("ERROR: Please check samplesheet header. Missing columns: '{}'".format(",".join(missing))) sys.exit(1) ## Check sample entries - for line in fin: + for line_number, line in enumerate(fin): lspl = [x.strip().strip('"') for x in line.strip().split(",")] + row = {k: v for k, v in zip(header, lspl)} # Check valid number of columns per row - if len(lspl) < len(HEADER): + if len(lspl) != len(header): print_error( - "Invalid number of columns (minimum = {})!".format(len(HEADER)), - "Line", - line, - ) - num_cols = len([x for x in lspl if x]) - if num_cols < MIN_COLS: - print_error( - "Invalid number of populated columns (minimum = {})!".format(MIN_COLS), - "Line", + "Invalid number of columns: found {} columns (header has {})".format( + line_number, len(lspl), len(header) + ), + f"Line #{line_number+2}", line, ) ## Check sample name entries - sample, fastq_1 = lspl[: len(HEADER)] - sample = sample.replace(" ", "_") + sample = row.get("sample", "").replace(" ", "_") if not sample: - print_error("Sample entry has not been specified!", "Line", line) + print_error("Sample entry has not been specified!", f"Line #{line_number+2}", line) ## Check FastQ file extension - for fastq in [fastq_1]: - if fastq: - if fastq.find(" ") != -1: - print_error("FastQ file contains spaces!", "Line", line) - if not fastq.endswith(".fastq.gz") and not fastq.endswith(".fq.gz"): - print_error( - "FastQ file does not have extension '.fastq.gz' or '.fq.gz'!", - "Line", - line, - ) - - ## Auto-detect paired-end/single-end - sample_info = [] ## [single_end, fastq_1, fastq_2] - if sample and fastq_1: ## Single-end short reads - sample_info = ["1", fastq_1] - else: - print_error("Invalid combination of columns provided!", "Line", line) - - ## Create sample mapping dictionary = { sample: [ single_end, fastq_1 ] } + fastq = row.get("fastq_1", None) + if fastq: + if fastq.find(" ") != -1: + print_error("FastQ file contains spaces!", f"Line #{line_number+2}", line) + if not fastq.endswith(".fastq.gz") and not fastq.endswith(".fq.gz"): + print_error( + "FastQ file does not have extension '.fastq.gz' or '.fq.gz'!", + "Line", + line, + ) + + ## Create sample mapping dictionary + sample_info = {"single_end": "1", "fastq_1": fastq} if sample not in sample_mapping_dict: sample_mapping_dict[sample] = [sample_info] else: @@ -113,19 +103,17 @@ def check_samplesheet(file_in, file_out): sample_mapping_dict[sample].append(sample_info) ## Write validated samplesheet with appropriate columns + output_cols = ["id", "intrasample_id", "single_end", "fastq_1"] if len(sample_mapping_dict) > 0: out_dir = os.path.dirname(file_out) make_dir(out_dir) with open(file_out, "w") as fout: - fout.write(",".join(["sample", "single_end", "fastq_1"]) + "\n") + fout.write(",".join(output_cols) + "\n") for sample in sorted(sample_mapping_dict.keys()): - - ## Check that multiple runs of the same sample are of the same datatype - if not all(x[0] == sample_mapping_dict[sample][0][0] for x in sample_mapping_dict[sample]): - print_error("Multiple runs of a sample must be of the same datatype!", "Sample: {}".format(sample)) - - for idx, val in enumerate(sample_mapping_dict[sample]): - fout.write(",".join(["{}_T{}".format(sample, idx + 1)] + val) + "\n") + for intrasample_id, val in enumerate(sample_mapping_dict[sample]): + sample_info = {**{"id": sample, "intrasample_id": str(intrasample_id)}, **val} + outrow = [sample_info.get(colname, None) for colname in output_cols] + fout.write(",".join(outrow) + "\n") else: print_error("No entries to process!", "Samplesheet: {}".format(file_in)) diff --git a/subworkflows/local/input_check.nf b/subworkflows/local/input_check.nf index 136e28be..910afd05 100644 --- a/subworkflows/local/input_check.nf +++ b/subworkflows/local/input_check.nf @@ -20,16 +20,11 @@ workflow INPUT_CHECK { versions = SAMPLESHEET_CHECK.out.versions // channel: [ versions.yml ] } -// Function to get list of [ meta, [ fastq_1, fastq_2 ] ] +// Function to get list of [ meta, [ fastq_1 ] ] def create_fastq_channel(LinkedHashMap row) { - // create meta map - def meta = [:] - meta.id = row.sample - meta.single_end = 1 - def array = [] + def meta = row.findAll {it.key != "fastq_1"} if (!file(row.fastq_1).exists()) { exit 1, "ERROR: Please check input samplesheet -> Read 1 FastQ file does not exist!\n${row.fastq_1}" } - array = [ meta, [ file(row.fastq_1) ] ] - return array + return [ meta, [ file(row.fastq_1) ] ] } diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 5e1fca50..09f2c2a6 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -98,12 +98,6 @@ workflow SMRNASEQ { ch_input ) .reads - .map { - meta, fastq -> - meta.id = meta.id.split('_')[0..-2].join('_') - [ meta, fastq ] } - .dump(tag: 'map') - .groupTuple(by: [0]) .dump(tag: 'group') .branch { meta, fastq -> From 334804bf0431f89d3621b0c510408c71e51aaa7a Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Tue, 11 Oct 2022 16:28:22 +0000 Subject: [PATCH 078/215] Add known adapters to workflow --- CHANGELOG.md | 2 +- assets/known_adapters.fa | 6 ++++++ conf/modules.config | 1 + nextflow.config | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 assets/known_adapters.fa diff --git a/CHANGELOG.md b/CHANGELOG.md index 73b0b8ba..49871022 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [[#168](https://github.com/nf-core/smrnaseq/issues/168)] - Removed `mirtrace_protocol` as the parameter was redundant and `params.protocol` is entirely sufficient - Updated pipeline template to [nf-core/tools 2.5.1](https://github.com/nf-core/tools/releases/tag/2.5.1) - [[#188](https://github.com/nf-core/smrnaseq/pull/188)] - Dropped TrimGalore in favor of fastp QC and adapter trimming, improved handling of adapters and trimming parameters - +- [[#194](https://github.com/nf-core/smrnaseq/issues/194)] - Added default adapters file for FastP improved miRNA adapter trimming ### Parameters | Old parameter | New parameter | diff --git a/assets/known_adapters.fa b/assets/known_adapters.fa new file mode 100644 index 00000000..6b54be80 --- /dev/null +++ b/assets/known_adapters.fa @@ -0,0 +1,6 @@ +> QIAseq miRNA adapter +AACTGTAGGCACCATCAAT +> Illumina miRNA adapter +TGGAATTCTCGGGTGCCAAGG +> Nextflex miRNA adapter +TGGAATTCTCGGGTGCCAAGG diff --git a/conf/modules.config b/conf/modules.config index 0c5365fb..648c5d20 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -105,6 +105,7 @@ if (!params.skip_fastp) { params.fastp_min_length > 0 ? "-l ${params.fastp_min_length}" : "", params.fastp_max_length > 0 ? "--max_len1 ${params.fastp_max_length}" : "", params.three_prime_adapter == null ? '' : "--adapter_sequence ${params.three_prime_adapter}" + params.fastp_known_mirna_adapters == null ? '' : "--adapter_fasta ${params.fastp_known_mirna_adapters}" ].join(" ").trim() publishDir = [ [ diff --git a/nextflow.config b/nextflow.config index afb1b01f..7794ab08 100644 --- a/nextflow.config +++ b/nextflow.config @@ -34,6 +34,7 @@ params { three_prime_adapter = null trim_fastq = true fastp_min_length = 17 + fastp_known_mirna_adapters = "$projectDir/assets/known_adapters.fa" save_trimmed_fail = false skip_qc = false skip_fastqc = false From 0e7398f8cc948d5cf332c22dba93c24da1ebefce Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Tue, 11 Oct 2022 16:32:48 +0000 Subject: [PATCH 079/215] Add parameter to schema --- conf/modules.config | 2 +- nextflow_schema.json | 27 ++++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 648c5d20..951a4719 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -104,7 +104,7 @@ if (!params.skip_fastp) { params.three_prime_clip_r1 > 0 ? "--trim_tail1 ${params.three_prime_clip_r1}" : "", // Remove bp from the 3' end of read 1 AFTER adapter/quality trimming has been performed. params.fastp_min_length > 0 ? "-l ${params.fastp_min_length}" : "", params.fastp_max_length > 0 ? "--max_len1 ${params.fastp_max_length}" : "", - params.three_prime_adapter == null ? '' : "--adapter_sequence ${params.three_prime_adapter}" + params.three_prime_adapter == null ? '' : "--adapter_sequence ${params.three_prime_adapter}", params.fastp_known_mirna_adapters == null ? '' : "--adapter_fasta ${params.fastp_known_mirna_adapters}" ].join(" ").trim() publishDir = [ diff --git a/nextflow_schema.json b/nextflow_schema.json index 17e971e8..7eb0a44d 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -10,7 +10,10 @@ "type": "object", "fa_icon": "fas fa-terminal", "description": "Define where the pipeline should find input data and save output data.", - "required": ["input", "outdir"], + "required": [ + "input", + "outdir" + ], "properties": { "input": { "type": "string", @@ -28,7 +31,13 @@ "fa_icon": "fas fa-vial", "description": "Protocol for constructing smRNA-seq libraries.", "help_text": "Presets for trimming parameters and 3' adapter sequence with a specified protocol.\n\n| Protocol | Library Prep Kit | Trimming Parameter | 3' Adapter Sequence |\n| :------------ | :-------------------------------------- | :-------------------------------------- | :--------------------- |\n| illumina | Illumina TruSeq Small RNA | `clip_r1 = 0` `three_prime_clip_r1 = 0` | `TGGAATTCTCGGGTGCCAAGG` |\n| nextflex | BIOO SCIENTIFIC NEXTFLEX Small RNA-Seq | `clip_r1 = 4` `three_prime_clip_r1 = 4` | `TGGAATTCTCGGGTGCCAAGG` |\n| qiaseq | QIAGEN QIAseq miRNA | `clip_r1 = 0` `three_prime_clip_r1 = 0` | `AACTGTAGGCACCATCAAT` |\n| cats | Diagenode CATS Small RNA-seq | `clip_r1 = 3` `three_prime_clip_r1 = 0` | `AAAAAAAAAAA` + `GATCGGAAGAGCACACGTCTG` (only polyA is used for trimming) |\n| custom | user defined | user defined | user defined |\n\n> NB: When running `--protocol custom` the user ***must define the 3' Adapter Sequence***.\n> If trimming parameters aren't provided the pipeline will deafult to `clip_R1 = 0` and `three_prime_clip_R1 = 0` (i.e. no extra clipping).", - "enum": ["illumina", "nextflex", "qiaseq", "cats", "custom"] + "enum": [ + "illumina", + "nextflex", + "qiaseq", + "cats", + "custom" + ] }, "outdir": { "type": "string", @@ -192,6 +201,11 @@ "type": "boolean", "fa_icon": "fas fa-cloud-download-alt", "description": "Save reads failing trimming" + }, + "fastp_known_mirna_adapters": { + "type": "string", + "default": "${projectDir}/assets/known_adapters.fa", + "fa_icon": "far fa-question-circle" } } }, @@ -372,7 +386,14 @@ "description": "Method used to save pipeline results to output directory.", "help_text": "The Nextflow `publishDir` option specifies which intermediate files should be saved to the output directory. This option tells the pipeline what method should be used to move these files. See [Nextflow docs](https://www.nextflow.io/docs/latest/process.html#publishdir) for details.", "fa_icon": "fas fa-copy", - "enum": ["symlink", "rellink", "link", "copy", "copyNoFollow", "move"], + "enum": [ + "symlink", + "rellink", + "link", + "copy", + "copyNoFollow", + "move" + ], "hidden": true }, "email_on_fail": { From 1a09686d56542a9d30f7bb01628009ab382f8601 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Tue, 11 Oct 2022 16:33:40 +0000 Subject: [PATCH 080/215] Prettier --- CHANGELOG.md | 1 + nextflow_schema.json | 23 ++++------------------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49871022..245d985e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updated pipeline template to [nf-core/tools 2.5.1](https://github.com/nf-core/tools/releases/tag/2.5.1) - [[#188](https://github.com/nf-core/smrnaseq/pull/188)] - Dropped TrimGalore in favor of fastp QC and adapter trimming, improved handling of adapters and trimming parameters - [[#194](https://github.com/nf-core/smrnaseq/issues/194)] - Added default adapters file for FastP improved miRNA adapter trimming + ### Parameters | Old parameter | New parameter | diff --git a/nextflow_schema.json b/nextflow_schema.json index 7eb0a44d..b5c52a3e 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -10,10 +10,7 @@ "type": "object", "fa_icon": "fas fa-terminal", "description": "Define where the pipeline should find input data and save output data.", - "required": [ - "input", - "outdir" - ], + "required": ["input", "outdir"], "properties": { "input": { "type": "string", @@ -31,13 +28,7 @@ "fa_icon": "fas fa-vial", "description": "Protocol for constructing smRNA-seq libraries.", "help_text": "Presets for trimming parameters and 3' adapter sequence with a specified protocol.\n\n| Protocol | Library Prep Kit | Trimming Parameter | 3' Adapter Sequence |\n| :------------ | :-------------------------------------- | :-------------------------------------- | :--------------------- |\n| illumina | Illumina TruSeq Small RNA | `clip_r1 = 0` `three_prime_clip_r1 = 0` | `TGGAATTCTCGGGTGCCAAGG` |\n| nextflex | BIOO SCIENTIFIC NEXTFLEX Small RNA-Seq | `clip_r1 = 4` `three_prime_clip_r1 = 4` | `TGGAATTCTCGGGTGCCAAGG` |\n| qiaseq | QIAGEN QIAseq miRNA | `clip_r1 = 0` `three_prime_clip_r1 = 0` | `AACTGTAGGCACCATCAAT` |\n| cats | Diagenode CATS Small RNA-seq | `clip_r1 = 3` `three_prime_clip_r1 = 0` | `AAAAAAAAAAA` + `GATCGGAAGAGCACACGTCTG` (only polyA is used for trimming) |\n| custom | user defined | user defined | user defined |\n\n> NB: When running `--protocol custom` the user ***must define the 3' Adapter Sequence***.\n> If trimming parameters aren't provided the pipeline will deafult to `clip_R1 = 0` and `three_prime_clip_R1 = 0` (i.e. no extra clipping).", - "enum": [ - "illumina", - "nextflex", - "qiaseq", - "cats", - "custom" - ] + "enum": ["illumina", "nextflex", "qiaseq", "cats", "custom"] }, "outdir": { "type": "string", @@ -205,6 +196,7 @@ "fastp_known_mirna_adapters": { "type": "string", "default": "${projectDir}/assets/known_adapters.fa", + "description": "FastA with known miRNA adapter sequences for adapter trimming", "fa_icon": "far fa-question-circle" } } @@ -386,14 +378,7 @@ "description": "Method used to save pipeline results to output directory.", "help_text": "The Nextflow `publishDir` option specifies which intermediate files should be saved to the output directory. This option tells the pipeline what method should be used to move these files. See [Nextflow docs](https://www.nextflow.io/docs/latest/process.html#publishdir) for details.", "fa_icon": "fas fa-copy", - "enum": [ - "symlink", - "rellink", - "link", - "copy", - "copyNoFollow", - "move" - ], + "enum": ["symlink", "rellink", "link", "copy", "copyNoFollow", "move"], "hidden": true }, "email_on_fail": { From ce95631e96cc2f2c789b56ec13a1fe2ac93efe2f Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Tue, 11 Oct 2022 16:43:37 +0000 Subject: [PATCH 081/215] Docs ++, remove old trimgalore stuff --- docs/images/cutadapt_plot.png | Bin 98738 -> 0 bytes docs/output.md | 20 ++++++++------------ 2 files changed, 8 insertions(+), 12 deletions(-) delete mode 100644 docs/images/cutadapt_plot.png diff --git a/docs/images/cutadapt_plot.png b/docs/images/cutadapt_plot.png deleted file mode 100644 index 8b4c978abeef6d0948191868ada3df8cf79d23f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 98738 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 z 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 Date: Thu, 20 Oct 2022 10:06:20 +0200 Subject: [PATCH 082/215] Adjust title of changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fb037eb..20c42871 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 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). -## v2.1.0 - (https://github.com/nf-core/smrnaseq/releases/tag/2.1.0) - 2022-10-11 Maroon Tin Dalmatian +## [v2.0.0](https://github.com/nf-core/smrnaseq/releases/tag/2.1.0) - 2022-10-20 Maroon Tin Dalmatian ### Enhancements & fixes From 8beb03e5208cece49f839e03d11fd0ca21b30947 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 20 Oct 2022 10:06:41 +0200 Subject: [PATCH 083/215] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20c42871..c20ab933 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [[#159](https://github.com/nf-core/smrnaseq/issues/159)] - Index files were not collected when `bowtie_index` was used and thus mapping was failing - [[#161](https://github.com/nf-core/smrnaseq/issues/161)] - Trimmed output was not as documented and not correctly published - [[#168](https://github.com/nf-core/smrnaseq/issues/168)] - Removed `mirtrace_protocol` as the parameter was redundant and `params.protocol` is entirely sufficient -- Updated pipeline template to [nf-core/tools 2.5.1](https://github.com/nf-core/tools/releases/tag/2.5.1) +- Updated pipeline template to [nf-core/tools 2.5.1](https://github.com/nf-core/tools/releases/tag/2.6.0) - [[#188](https://github.com/nf-core/smrnaseq/pull/188)] - Dropped TrimGalore in favor of fastp QC and adapter trimming, improved handling of adapters and trimming parameters - [[#194](https://github.com/nf-core/smrnaseq/issues/194)] - Added default adapters file for FastP improved miRNA adapter trimming From af2fed5271e5c18ff49ea0fea1605e3e85d77c1c Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 20 Oct 2022 10:06:57 +0200 Subject: [PATCH 084/215] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c20ab933..fc29c0db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [[#159](https://github.com/nf-core/smrnaseq/issues/159)] - Index files were not collected when `bowtie_index` was used and thus mapping was failing - [[#161](https://github.com/nf-core/smrnaseq/issues/161)] - Trimmed output was not as documented and not correctly published - [[#168](https://github.com/nf-core/smrnaseq/issues/168)] - Removed `mirtrace_protocol` as the parameter was redundant and `params.protocol` is entirely sufficient -- Updated pipeline template to [nf-core/tools 2.5.1](https://github.com/nf-core/tools/releases/tag/2.6.0) +- Updated pipeline template to [nf-core/tools 2.6.0](https://github.com/nf-core/tools/releases/tag/2.6.0) - [[#188](https://github.com/nf-core/smrnaseq/pull/188)] - Dropped TrimGalore in favor of fastp QC and adapter trimming, improved handling of adapters and trimming parameters - [[#194](https://github.com/nf-core/smrnaseq/issues/194)] - Added default adapters file for FastP improved miRNA adapter trimming From b12a6036163921b507c38e780a9f4d8cb4631d18 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 24 Oct 2022 12:47:35 +0000 Subject: [PATCH 085/215] Add online video as per Joses suggestion :-) --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index e1054a4c..b0cecd05 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,12 @@ The pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool On release, automated continuous integration tests run the pipeline on a full-sized dataset on the AWS cloud infrastructure. This ensures that the pipeline runs on AWS, has sensible resource allocation defaults set to run on real-world datasets, and permits the persistent storage of results to benchmark between pipeline releases and other analysis sources. The results obtained from the full-sized test can be viewed on the [nf-core website](https://nf-co.re/smrnaseq/results). +## Online videos + +A short talk about the history, current status and functionality on offer in this pipeline was given by Lorena Pantano (@lpantano) on [9th November 2021](https://youtu.be/4YLQ2VwpCJE) as part of the nf-core/bytesize series. + +You can find numerous talks on the nf-core events page from various topics including writing pipelines/modules in Nextflow DSL2, using nf-core tooling, running nf-core pipelines as well as more generic content like contributing to Github. Please check them out! + ## Pipeline summary 1. Raw read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/)) From 051128f3ea013faf691b5903334c6d33ea0935f7 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 24 Oct 2022 14:47:51 +0200 Subject: [PATCH 086/215] Update docs/usage.md Co-authored-by: Jose Espinosa-Carrasco --- docs/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index 3e3a3960..8a924d3b 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -24,7 +24,7 @@ It should point to the 3-letter species name used by [miRBase](https://www.mirba ### miRNA related files -Different parameters can be set for the two supported datbases. By default `miRBase` will be used with the parameters below. +Different parameters can be set for the two supported databases. By default `miRBase` will be used with the parameters below. - `mirna_gtf`: If not supplied by the user, then `mirna_gtf` will point to the latest GFF3 file in miRbase: `https://mirbase.org/ftp/CURRENT/genomes/${params.mirtrace_species}.gff3` - `mature`: points to the FASTA file of mature miRNA sequences. `https://mirbase.org/ftp/CURRENT/mature.fa.gz` From b9afa72f4c0e436c1aa6f2b411e147d2da36b51a Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 24 Oct 2022 14:48:01 +0200 Subject: [PATCH 087/215] Update docs/usage.md Co-authored-by: Jose Espinosa-Carrasco --- docs/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index 8a924d3b..b45f449a 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -45,7 +45,7 @@ If MirGeneDB should be used instead it needs to be specified using `--mirgenedb` This step has, until now, only been tested for human data. Unexpected behaviour can occur when using it with a different species. -Contamination filtering of the sequencing reads is optional and can be invoked using `filter_contamination`. FASTA files with contamination sequences to use need to be supplied using the following commands. Otherwise the contamination filtering of the specific type will be omitted. +Contamination filtering of the sequencing reads is optional and can be invoked using the `filter_contamination` parameter. FASTA files with - `rrna`: Used to supply a FASTA file containing rRNA contamination sequence. - `trna`: Used to supply a FASTA file containing tRNA contamination sequence. e.g. `http://gtrnadb.ucsc.edu/genomes/eukaryota/Hsapi38/hg38-tRNAs.fa` From 6f85c3604c1a0dbf865fa422099aeed96bdab589 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 24 Oct 2022 14:51:39 +0200 Subject: [PATCH 088/215] Apply suggestions from code review Co-authored-by: Jose Espinosa-Carrasco --- modules/local/blat_mirna.nf | 3 ++- modules/local/filter_stats.nf | 4 ++-- subworkflows/local/contaminant_filter.nf | 1 - 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/local/blat_mirna.nf b/modules/local/blat_mirna.nf index da7f6449..2b50d7db 100644 --- a/modules/local/blat_mirna.nf +++ b/modules/local/blat_mirna.nf @@ -52,7 +52,8 @@ process BLAT_MIRNA { echo $db_type blat -out=blast8 $mirna $contaminants /dev/stdout | awk 'BEGIN{FS="\t"}{if(\$11 < 1e-5)print \$1;}' | uniq > mirnahit.txt awk 'BEGIN { while((getline<"mirnahit.txt")>0) l[">"\$1]=1 } /^>/ {x = l[\$1]} {if(!x) print }' $contaminants > filtered.fa - cat <<-END_VERSIONS > versions.yml + +cat <<-END_VERSIONS > versions.yml "${task.process}": blat: \$(echo \$(blat) | grep Standalone | awk '{ if (match(\$0,/[0-9]*[0-9]/,m)) print m[0] }') END_VERSIONS diff --git a/modules/local/filter_stats.nf b/modules/local/filter_stats.nf index 1db0d49b..4d94d9b1 100644 --- a/modules/local/filter_stats.nf +++ b/modules/local/filter_stats.nf @@ -11,8 +11,8 @@ process FILTER_STATS { path stats_files output: - path "*_mqc.yaml" , emit: stats - tuple val(meta), path('*.filtered.fastq.gz') , emit: reads + path "*_mqc.yaml" , emit: stats + tuple val(meta), path('*.filtered.fastq.gz'), emit: reads when: task.ext.when == null || task.ext.when diff --git a/subworkflows/local/contaminant_filter.nf b/subworkflows/local/contaminant_filter.nf index 4ab180c7..19ce7bea 100644 --- a/subworkflows/local/contaminant_filter.nf +++ b/subworkflows/local/contaminant_filter.nf @@ -44,7 +44,6 @@ workflow CONTAMINANT_FILTER { reads.set { rrna_reads } - if (params.rrna) { // Index DB and filter $reads emit: $rrna_reads INDEX_RRNA ( rrna ) From 5aa27a312b2ec39c80e90455ae5b90f42e0d3875 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 24 Oct 2022 12:53:43 +0000 Subject: [PATCH 089/215] Added url for mirgenedb --- docs/usage.md | 2 +- nextflow_schema.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 3e3a3960..901084fc 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -20,7 +20,7 @@ This option indicates the experimental protocol used for the sample preparation. ### `mirtrace_species` or `mirgenedb_species` -It should point to the 3-letter species name used by [miRBase](https://www.mirbase.org/help/genome_summary.shtml) or MirGeneDB. Note the difference in case for the two databases. +It should point to the 3-letter species name used by [miRBase](https://www.mirbase.org/help/genome_summary.shtml) or [MirGeneDB](https://www.mirgenedb.org/browse). Note the difference in case for the two databases. ### miRNA related files diff --git a/nextflow_schema.json b/nextflow_schema.json index b5c52a3e..77b04352 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -76,7 +76,7 @@ "mirgenedb_species": { "type": "string", "description": "Species of MirGeneDB.", - "help_text": "This replaces the value of `--mirtrace_species` if `--mirgenedb` is used. \n Note the difference in case for species names used in MirGeneDB and miRBase." + "help_text": "This replaces the value of `--mirtrace_species` if `--mirgenedb` is used. \n Note the difference in case for species names used in MirGeneDB and miRBase. See https://www.mirgenedb.org/browse for more information." }, "fasta": { "type": "string", From 4a30e4aff4e567bc55e573fefc24bd0e3908ad3b Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Tue, 25 Oct 2022 00:10:39 +0200 Subject: [PATCH 090/215] Update CHANGELOG.md Co-authored-by: Edmund Miller --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc29c0db..ee8bd744 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 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). -## [v2.0.0](https://github.com/nf-core/smrnaseq/releases/tag/2.1.0) - 2022-10-20 Maroon Tin Dalmatian +## [v2.1.0](https://github.com/nf-core/smrnaseq/releases/tag/2.1.0) - 2022-10-20 Maroon Tin Dalmatian ### Enhancements & fixes From 9fe7a4f8d04374cb2c4a70e58db60a3bc5f6bb0d Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 24 Oct 2022 22:15:35 +0000 Subject: [PATCH 091/215] Add note why no download possible --- docs/usage.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index 1bfa8051..bc6c3a4b 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -32,10 +32,12 @@ Different parameters can be set for the two supported databases. By default `miR If MirGeneDB should be used instead it needs to be specified using `--mirgenedb` and use the parameters below . -- `mirgenedb_gff`: The data can not be downloaded automatically, thus the user needs to supply the gff file for either his species, or all species downloaded from `https://mirgenedb.org/download`. The total set will automatically be subsetted to the species specified with `--mirgenedb_species`. +- `mirgenedb_gff`: The data can not be downloaded automatically (URLs are created with short term tokens in it), thus the user needs to supply the gff file for either his species, or all species downloaded from `https://mirgenedb.org/download`. The total set will automatically be subsetted to the species specified with `--mirgenedb_species`. - `mirgenedb_mature`: points to the FASTA file of mature miRNA sequences. Download from `https://mirgenedb.org/download`. - `mirgenedb_hairpin`: points to the FASTA file of precursor miRNA sequences. Download from `https://mirgenedb.org/download`. Note that MirGeneDB does not have a dedicated `hairpin` file, but the `Precursor sequences` are to be used. + + ### Genome - `fasta`: the reference genome FASTA file From 4a6d9d94005ae0976b97933511db72636bd4da4e Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Tue, 25 Oct 2022 00:15:43 +0200 Subject: [PATCH 092/215] Update modules/local/bowtie_map_contaminants.nf Co-authored-by: Edmund Miller --- modules/local/bowtie_map_contaminants.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/bowtie_map_contaminants.nf b/modules/local/bowtie_map_contaminants.nf index c3daa9be..bbfb66fd 100644 --- a/modules/local/bowtie_map_contaminants.nf +++ b/modules/local/bowtie_map_contaminants.nf @@ -15,7 +15,7 @@ process BOWTIE_MAP_CONTAMINANTS { tuple val(meta), path("*sam") , emit: bam tuple val(meta), path('*.filter.unmapped.contaminant.fastq'), emit: unmapped path "versions.yml" , emit: versions - path "filtered.*.stats" , emit: stats + path "filtered.*.stats" , emit: stats when: task.ext.when == null || task.ext.when From 6363ae31c5d15aa397d24d6339e11e7b4b11743a Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Tue, 25 Oct 2022 00:19:56 +0200 Subject: [PATCH 093/215] Apply suggestions from code review Co-authored-by: Edmund Miller --- subworkflows/local/contaminant_filter.nf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subworkflows/local/contaminant_filter.nf b/subworkflows/local/contaminant_filter.nf index 19ce7bea..383c85ad 100644 --- a/subworkflows/local/contaminant_filter.nf +++ b/subworkflows/local/contaminant_filter.nf @@ -74,7 +74,7 @@ workflow CONTAMINANT_FILTER { ch_versions = ch_versions.mix(BLAT_CDNA.out.versions) INDEX_CDNA ( BLAT_CDNA.out.filtered_set ) ch_versions = ch_versions.mix(INDEX_CDNA.out.versions) - MAP_CDNA ( trna_reads, INDEX_CDNA.out.index, 'cDNA' ) + MAP_CDNA ( trna_reads, INDEX_CDNA.out.index, 'cDNA' ) ch_versions = ch_versions.mix(MAP_CDNA.out.versions) ch_filter_stats = ch_filter_stats.mix(MAP_CDNA.out.stats.ifEmpty(null)) MAP_CDNA.out.unmapped.set { cdna_reads } @@ -100,7 +100,7 @@ workflow CONTAMINANT_FILTER { ch_versions = ch_versions.mix(BLAT_PIRNA.out.versions) INDEX_PIRNA ( BLAT_PIRNA.out.filtered_set ) ch_versions = ch_versions.mix(INDEX_PIRNA.out.versions) - MAP_PIRNA (ncrna_reads, INDEX_PIRNA.out.index, 'piRNA' ) + MAP_PIRNA ( ncrna_reads, INDEX_PIRNA.out.index, 'piRNA' ) ch_versions = ch_versions.mix(MAP_PIRNA.out.versions) ch_filter_stats = ch_filter_stats.mix(MAP_PIRNA.out.stats.ifEmpty(null)) MAP_PIRNA.out.unmapped.set { pirna_reads } @@ -113,7 +113,7 @@ workflow CONTAMINANT_FILTER { ch_versions = ch_versions.mix(BLAT_OTHER.out.versions) INDEX_OTHER ( BLAT_OTHER.out.filtered_set ) ch_versions = ch_versions.mix(INDEX_OTHER.out.versions) - MAP_OTHER (ncrna_reads, INDEX_OTHER.out.index, 'other' ) + MAP_OTHER ( ncrna_reads, INDEX_OTHER.out.index, 'other' ) ch_versions = ch_versions.mix(MAP_OTHER.out.versions) ch_filter_stats = ch_filter_stats.mix(MAP_OTHER.out.stats.ifEmpty(null)) MAP_OTHER.out.unmapped.set { other_cont_reads } From 2ff08d92da17f7ae78da85380f959dc3e74aa3e6 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 24 Oct 2022 22:20:23 +0000 Subject: [PATCH 094/215] Adjust = to be same everywhere --- nextflow.config | 208 ++++++++++++++++++++++++------------------------ 1 file changed, 104 insertions(+), 104 deletions(-) diff --git a/nextflow.config b/nextflow.config index b1b24dbc..759cf40d 100644 --- a/nextflow.config +++ b/nextflow.config @@ -10,84 +10,84 @@ params { // Input options - input = null + input = null // Workflow flags - protocol = 'illumina' + protocol = 'illumina' // References - genome = null - igenomes_base = 's3://ngi-igenomes/igenomes' - igenomes_ignore = false - mirna_gtf = null - mature = "https://mirbase.org/ftp/CURRENT/mature.fa.gz" - hairpin = "https://mirbase.org/ftp/CURRENT/hairpin.fa.gz" - mirgenedb = false - mirgenedb_mature = null - mirgenedb_hairpin = null - mirgenedb_gff = null - mirgenedb_species = null + genome = null + igenomes_base = 's3://ngi-igenomes/igenomes' + igenomes_ignore = false + mirna_gtf = null + mature = "https://mirbase.org/ftp/CURRENT/mature.fa.gz" + hairpin = "https://mirbase.org/ftp/CURRENT/hairpin.fa.gz" + mirgenedb = false + mirgenedb_mature = null + mirgenedb_hairpin = null + mirgenedb_gff = null + mirgenedb_species = null // Trimming options - clip_r1 = null - three_prime_clip_r1 = null - three_prime_adapter = null - trim_fastq = true - fastp_min_length = 17 - fastp_known_mirna_adapters = "$projectDir/assets/known_adapters.fa" - save_trimmed_fail = false - skip_qc = false - skip_fastqc = false - skip_multiqc = false - skip_mirdeep = false - skip_fastp = false - save_reference = false - fastp_max_length = 40 + clip_r1 = null + three_prime_clip_r1 = null + three_prime_adapter = null + trim_fastq = true + fastp_min_length = 17 + fastp_known_mirna_adapters = "$projectDir/assets/known_adapters.fa" + save_trimmed_fail = false + skip_qc = false + skip_fastqc = false + skip_multiqc = false + skip_mirdeep = false + skip_fastp = false + save_reference = false + fastp_max_length = 40 // Contamination filtering - filter_contamination = false - rrna = null - trna = null - cdna = null - ncrna = null - pirna = null - other_contamination = null + filter_contamination = false + rrna = null + trna = null + cdna = null + ncrna = null + pirna = null + other_contamination = null // MultiQC options - multiqc_config = null - multiqc_title = null - multiqc_logo = null - max_multiqc_email_size = '25.MB' + multiqc_config = null + multiqc_title = null + multiqc_logo = null + max_multiqc_email_size = '25.MB' multiqc_methods_description = null // Boilerplate options - outdir = null - tracedir = "${params.outdir}/pipeline_info" - publish_dir_mode = 'copy' - email = null - email_on_fail = null - plaintext_email = false - monochrome_logs = false - hook_url = null - help = false - validate_params = true - show_hidden_params = false - schema_ignore_params = 'genomes' - enable_conda = false + outdir = null + tracedir = "${params.outdir}/pipeline_info" + publish_dir_mode = 'copy' + email = null + email_on_fail = null + plaintext_email = false + monochrome_logs = false + hook_url = null + help = false + validate_params = true + show_hidden_params = false + schema_ignore_params = 'genomes' + enable_conda = false // Config options - custom_config_version = 'master' - custom_config_base = "https://raw.githubusercontent.com/nf-core/configs/${params.custom_config_version}" - config_profile_description = null - config_profile_contact = null - config_profile_url = null - config_profile_name = null + custom_config_version = 'master' + custom_config_base = "https://raw.githubusercontent.com/nf-core/configs/${params.custom_config_version}" + config_profile_description = null + config_profile_contact = null + config_profile_url = null + config_profile_name = null // Max resource options // Defaults only, expecting to be overwritten - max_memory = '128.GB' - max_cpus = 16 - max_time = '240.h' + max_memory = '128.GB' + max_cpus = 16 + max_time = '240.h' } @@ -112,64 +112,64 @@ try { profiles { debug { process.beforeScript = 'echo $HOSTNAME' } conda { - params.enable_conda = true - docker.enabled = false - singularity.enabled = false - podman.enabled = false - shifter.enabled = false - charliecloud.enabled = false + params.enable_conda = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false } mamba { - params.enable_conda = true - conda.useMamba = true - docker.enabled = false - singularity.enabled = false - podman.enabled = false - shifter.enabled = false - charliecloud.enabled = false + params.enable_conda = true + conda.useMamba = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false } docker { - docker.enabled = true - docker.userEmulation = true - singularity.enabled = false - podman.enabled = false - shifter.enabled = false - charliecloud.enabled = false - docker.runOptions = '-u $(id -u):$(id -g)' + docker.enabled = true + docker.userEmulation = true + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + docker.runOptions = '-u $(id -u):$(id -g)' } singularity { - singularity.enabled = true - singularity.autoMounts = true - docker.enabled = false - podman.enabled = false - shifter.enabled = false - charliecloud.enabled = false + singularity.enabled = true + singularity.autoMounts = true + docker.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false } podman { - podman.enabled = true - docker.enabled = false - singularity.enabled = false - shifter.enabled = false - charliecloud.enabled = false + podman.enabled = true + docker.enabled = false + singularity.enabled = false + shifter.enabled = false + charliecloud.enabled = false } shifter { - shifter.enabled = true - docker.enabled = false - singularity.enabled = false - podman.enabled = false - charliecloud.enabled = false + shifter.enabled = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + charliecloud.enabled = false } charliecloud { - charliecloud.enabled = true - docker.enabled = false - singularity.enabled = false - podman.enabled = false - shifter.enabled = false + charliecloud.enabled = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false } gitpod { - executor.name = 'local' - executor.cpus = 16 - executor.memory = 60.GB + executor.name = 'local' + executor.cpus = 16 + executor.memory = 60.GB } test { includeConfig 'conf/test.config' } test_no_genome { includeConfig 'conf/test_no_genome.config' } From bf3ef92df3bd77a90a44bc18f500021067c5e6fd Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 24 Oct 2022 22:20:47 +0000 Subject: [PATCH 095/215] Fix prettier --- docs/usage.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index bc6c3a4b..28373e00 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -36,8 +36,6 @@ If MirGeneDB should be used instead it needs to be specified using `--mirgenedb` - `mirgenedb_mature`: points to the FASTA file of mature miRNA sequences. Download from `https://mirgenedb.org/download`. - `mirgenedb_hairpin`: points to the FASTA file of precursor miRNA sequences. Download from `https://mirgenedb.org/download`. Note that MirGeneDB does not have a dedicated `hairpin` file, but the `Precursor sequences` are to be used. - - ### Genome - `fasta`: the reference genome FASTA file From 27514c40c08d1eab8249521096f4f2f7be875104 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Tue, 25 Oct 2022 00:40:52 +0200 Subject: [PATCH 096/215] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee8bd744..69a23be8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 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). -## [v2.1.0](https://github.com/nf-core/smrnaseq/releases/tag/2.1.0) - 2022-10-20 Maroon Tin Dalmatian +## [v2.1.0](https://github.com/nf-core/smrnaseq/releases/tag/2.1.0) - 2022-10-25 Maroon Tin Dalmatian ### Enhancements & fixes From a171b59af7203fdc5a19e6b4b8308fa1ab757e6f Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 24 Oct 2022 22:43:21 +0000 Subject: [PATCH 097/215] Update dev --- CHANGELOG.md | 2 ++ nextflow.config | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee8bd744..e31be347 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ 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). +## Dev + ## [v2.1.0](https://github.com/nf-core/smrnaseq/releases/tag/2.1.0) - 2022-10-20 Maroon Tin Dalmatian ### Enhancements & fixes diff --git a/nextflow.config b/nextflow.config index 759cf40d..d9a384df 100644 --- a/nextflow.config +++ b/nextflow.config @@ -222,7 +222,7 @@ manifest { description = 'Small RNA-Seq Best Practice Analysis Pipeline.' mainScript = 'main.nf' nextflowVersion = '!>=21.10.3' - version = '2.1.0' + version = '2.1.1dev' doi = '' } From 021dcb2135165272ca86dcfe31956a5cd1eb7888 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 27 Oct 2022 09:37:31 +0000 Subject: [PATCH 098/215] Fix for issue #201 --- CHANGELOG.md | 2 ++ conf/modules.config | 1 - modules.json | 4 ++-- modules/nf-core/fastp/main.nf | 5 ++++ modules/nf-core/fastp/meta.yml | 4 ++++ modules/nf-core/fastqc/main.nf | 34 ++++++++-------------------- subworkflows/nf-core/fastqc_fastp.nf | 2 ++ workflows/smrnaseq.nf | 2 ++ 8 files changed, 27 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e31be347..79e4e5cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Dev +* Updated FASTP module to allow direct addition of adapter_fasta file to it + ## [v2.1.0](https://github.com/nf-core/smrnaseq/releases/tag/2.1.0) - 2022-10-20 Maroon Tin Dalmatian ### Enhancements & fixes diff --git a/conf/modules.config b/conf/modules.config index 951a4719..64d851f6 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -105,7 +105,6 @@ if (!params.skip_fastp) { params.fastp_min_length > 0 ? "-l ${params.fastp_min_length}" : "", params.fastp_max_length > 0 ? "--max_len1 ${params.fastp_max_length}" : "", params.three_prime_adapter == null ? '' : "--adapter_sequence ${params.three_prime_adapter}", - params.fastp_known_mirna_adapters == null ? '' : "--adapter_fasta ${params.fastp_known_mirna_adapters}" ].join(" ").trim() publishDir = [ [ diff --git a/modules.json b/modules.json index 173e2bf0..10f2aa99 100644 --- a/modules.json +++ b/modules.json @@ -15,11 +15,11 @@ }, "fastp": { "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + "git_sha": "1e49f31e93c56a3832833eef90a02d3cde5a3f7e" }, "fastqc": { "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + "git_sha": "f6a11408536fbee6cbea1f5977605011873de3ca" }, "multiqc": { "branch": "master", diff --git a/modules/nf-core/fastp/main.nf b/modules/nf-core/fastp/main.nf index 11ea4db3..207258ad 100644 --- a/modules/nf-core/fastp/main.nf +++ b/modules/nf-core/fastp/main.nf @@ -9,6 +9,7 @@ process FASTP { input: tuple val(meta), path(reads) + path adapter_fasta val save_trimmed_fail val save_merged @@ -27,6 +28,7 @@ process FASTP { script: 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" : '' // Added soft-links to original fastqs for consistent naming in MultiQC // Use single ended for interleaved. Add --interleaved_in in config. @@ -40,6 +42,7 @@ process FASTP { --thread $task.cpus \\ --json ${prefix}.fastp.json \\ --html ${prefix}.fastp.html \\ + $adapter_list \\ $fail_fastq \\ $args \\ 2> ${prefix}.fastp.log \\ @@ -61,6 +64,7 @@ process FASTP { --thread $task.cpus \\ --json ${prefix}.fastp.json \\ --html ${prefix}.fastp.html \\ + $adapter_list \\ $fail_fastq \\ $args \\ 2> ${prefix}.fastp.log @@ -82,6 +86,7 @@ process FASTP { --out2 ${prefix}_2.fastp.fastq.gz \\ --json ${prefix}.fastp.json \\ --html ${prefix}.fastp.html \\ + $adapter_list \\ $fail_fastq \\ $merge_fastq \\ --thread $task.cpus \\ diff --git a/modules/nf-core/fastp/meta.yml b/modules/nf-core/fastp/meta.yml index 2368fded..6f6fad74 100644 --- a/modules/nf-core/fastp/meta.yml +++ b/modules/nf-core/fastp/meta.yml @@ -23,6 +23,10 @@ input: List of input FastQ files of size 1 and 2 for single-end and paired-end data, respectively. If you wish to run interleaved paired-end data, supply as single-end data but with `--interleaved_in` in your `modules.conf`'s `ext.args` for the module. + - adapter_fasta: + type: file + description: File in FASTA format containing possible adapters to remove. + pattern: "*.{fasta,fna,fas,fa}" - save_trimmed_fail: type: boolean description: Specify true to save files that failed to pass trimming thresholds ending in `*.fail.fastq.gz` diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf index 05730368..55c50c87 100644 --- a/modules/nf-core/fastqc/main.nf +++ b/modules/nf-core/fastqc/main.nf @@ -8,7 +8,7 @@ process FASTQC { 'quay.io/biocontainers/fastqc:0.11.9--0' }" input: - tuple val(meta), path(reads) + tuple val(meta), path(reads, stageAs: "?/*") output: tuple val(meta), path("*.html"), emit: html @@ -20,30 +20,16 @@ process FASTQC { script: def args = task.ext.args ?: '' - // Add soft-links to original FastQs for consistent naming in pipeline def prefix = task.ext.prefix ?: "${meta.id}" - if (meta.single_end) { - """ - [ ! -f ${prefix}.fastq.gz ] && ln -s $reads ${prefix}.fastq.gz - fastqc $args --threads $task.cpus ${prefix}.fastq.gz - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - fastqc: \$( fastqc --version | sed -e "s/FastQC v//g" ) - END_VERSIONS - """ - } else { - """ - [ ! -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 - fastqc $args --threads $task.cpus ${prefix}_1.fastq.gz ${prefix}_2.fastq.gz - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - fastqc: \$( fastqc --version | sed -e "s/FastQC v//g" ) - END_VERSIONS - """ - } + """ + printf "%s\\n" $reads | while read f; do ln -s \$f ${prefix}_\$(basename \$f) ; done + fastqc $args --threads $task.cpus ${prefix}_* + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + fastqc: \$( fastqc --version | sed -e "s/FastQC v//g" ) + END_VERSIONS + """ stub: def prefix = task.ext.prefix ?: "${meta.id}" diff --git a/subworkflows/nf-core/fastqc_fastp.nf b/subworkflows/nf-core/fastqc_fastp.nf index b93672bf..5cec3149 100644 --- a/subworkflows/nf-core/fastqc_fastp.nf +++ b/subworkflows/nf-core/fastqc_fastp.nf @@ -28,6 +28,7 @@ String getFastpAdapterSequence(json_file){ workflow FASTQC_FASTP { take: reads // channel: [ val(meta), [ reads ] ] + adapter_list // String [path/to/adapters.fa] save_trimmed_fail // value: boolean save_merged // value: boolean @@ -58,6 +59,7 @@ workflow FASTQC_FASTP { if (!params.skip_fastp) { FASTP ( reads, + adapter_list, save_trimmed_fail, save_merged ) diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 09f2c2a6..92338f25 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -38,6 +38,7 @@ ch_multiqc_config = Channel.fromPath("$projectDir/assets/multiqc_config ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath( params.multiqc_config, checkIfExists: true ) : Channel.empty() ch_multiqc_logo = params.multiqc_logo ? Channel.fromPath( params.multiqc_logo, checkIfExists: true ) : Channel.empty() ch_multiqc_custom_methods_description = params.multiqc_methods_description ? file(params.multiqc_methods_description, checkIfExists: true) : file("$projectDir/assets/methods_description_template.yml", checkIfExists: true) +ch_fastp_adapters = Channel.fromPath(params.fastp_known_mirna_adapters, checkIfExists: true) /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -126,6 +127,7 @@ workflow SMRNASEQ { FASTQC_FASTP ( ch_cat_fastq, + ch_fastp_adapters, false, false ) From 1a2a2a0c9b945c41c51bb1f9638d0949a1076e99 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 2 Dec 2022 13:57:18 +0000 Subject: [PATCH 099/215] Fix for 206 hopefully --- CHANGELOG.md | 2 ++ modules/local/parse_fasta_mirna.nf | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e31be347..952eb2b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Dev +* [[#206](https://github.com/nf-core/smrnaseq/issues/206)] - Use % as separator in sed commands to enable conda working properly on OSX and Linux + ## [v2.1.0](https://github.com/nf-core/smrnaseq/releases/tag/2.1.0) - 2022-10-20 Maroon Tin Dalmatian ### Enhancements & fixes diff --git a/modules/local/parse_fasta_mirna.nf b/modules/local/parse_fasta_mirna.nf index 619cb427..4eedde8c 100644 --- a/modules/local/parse_fasta_mirna.nf +++ b/modules/local/parse_fasta_mirna.nf @@ -27,10 +27,10 @@ process PARSE_FASTA_MIRNA { fi # Remove spaces from miRBase FASTA files # sed -i 's, ,_,g' \$FASTA - sed '/^[^>]/s/[^AUGCaugc]/N/g' \$FASTA > \${FASTA}_parsed.fa + sed '%^[^>]%s%[^AUGCaugc]%N%g' \$FASTA > \${FASTA}_parsed.fa # TODO perl -ane 's/[ybkmrsw]/N/ig;print;' \${FASTA}_parsed_tmp.fa > \${FASTA}_parsed.fa - sed -i 's/\s.*//' \${FASTA}_parsed.fa + sed -i 's%\s.*%%' \${FASTA}_parsed.fa seqkit grep -r --pattern \".*${filter_species}-.*\" \${FASTA}_parsed.fa > \${FASTA}_sps.fa seqkit seq --rna2dna \${FASTA}_sps.fa > \${FASTA}_igenome.fa From ae02a7607d9aba540e21ec61baaddcba4565623e Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 2 Dec 2022 14:05:23 +0000 Subject: [PATCH 100/215] FIXES 208 --- CHANGELOG.md | 3 ++ subworkflows/nf-core/fastqc_trimgalore.nf | 48 ----------------------- workflows/smrnaseq.nf | 12 +++++- 3 files changed, 13 insertions(+), 50 deletions(-) delete mode 100644 subworkflows/nf-core/fastqc_trimgalore.nf diff --git a/CHANGELOG.md b/CHANGELOG.md index e31be347..2fb77be4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Dev +- [[#208](https://github.com/nf-core/smrnaseq/issues/208)] - Fixed usability of `--skip_qc` parameter + + ## [v2.1.0](https://github.com/nf-core/smrnaseq/releases/tag/2.1.0) - 2022-10-20 Maroon Tin Dalmatian ### Enhancements & fixes diff --git a/subworkflows/nf-core/fastqc_trimgalore.nf b/subworkflows/nf-core/fastqc_trimgalore.nf deleted file mode 100644 index 3eaee69f..00000000 --- a/subworkflows/nf-core/fastqc_trimgalore.nf +++ /dev/null @@ -1,48 +0,0 @@ -// -// Read QC, UMI extraction and trimming -// - -include { FASTQC } from '../../modules/nf-core/fastqc/main' -include { TRIMGALORE } from '../../modules/local/trimgalore' - -workflow FASTQC_TRIMGALORE { - take: - reads // channel: [ val(meta), [ reads ] ] - skip_fastqc // boolean: true/false - skip_trimming // boolean: true/false - - main: - ch_versions = Channel.empty() - fastqc_html = Channel.empty() - fastqc_zip = Channel.empty() - if (!skip_fastqc) { - FASTQC ( reads ).html.set { fastqc_html } - fastqc_zip = FASTQC.out.zip - ch_versions = ch_versions.mix(FASTQC.out.versions.first()) - } - - trim_reads = reads - trim_html = Channel.empty() - trim_zip = Channel.empty() - trim_log = Channel.empty() - trimgalore_versions = Channel.empty() - if (!skip_trimming) { - TRIMGALORE ( reads ).reads.set { trim_reads } - trim_html = TRIMGALORE.out.html - trim_zip = TRIMGALORE.out.zip - trim_log = TRIMGALORE.out.log - ch_versions = ch_versions.mix(TRIMGALORE.out.versions.first()) - } - - emit: - reads = trim_reads // channel: [ val(meta), [ reads ] ] - - fastqc_html // channel: [ val(meta), [ html ] ] - fastqc_zip // channel: [ val(meta), [ zip ] ] - - trim_html // channel: [ val(meta), [ html ] ] - trim_zip // channel: [ val(meta), [ zip ] ] - trim_log // channel: [ val(meta), [ txt ] ] - - versions = ch_versions // channel: [ versions.yml ] -} diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 09f2c2a6..2f44638c 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -124,16 +124,16 @@ workflow SMRNASEQ { // SUBWORKFLOW: Read QC and trim adapters // + if(!params.skip_qc){ FASTQC_FASTP ( ch_cat_fastq, false, false ) - ch_versions = ch_versions.mix(FASTQC_FASTP.out.versions) - reads_for_mirna = FASTQC_FASTP.out.reads + // // SUBWORKFLOW: mirtrace QC // @@ -144,6 +144,14 @@ workflow SMRNASEQ { ch_versions = ch_versions.mix(MIRTRACE.out.versions.ifEmpty(null)) + } else{ + //TODO - rob? :-) + + } + + + + // // SUBWORKFLOW: remove contaminants from reads // From fff2161225693aeb6650ac04fa1c5b75ebf9bc2a Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 2 Dec 2022 14:09:59 +0000 Subject: [PATCH 101/215] Should do the trick now --- modules/local/parse_fasta_mirna.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/parse_fasta_mirna.nf b/modules/local/parse_fasta_mirna.nf index 4eedde8c..e09242eb 100644 --- a/modules/local/parse_fasta_mirna.nf +++ b/modules/local/parse_fasta_mirna.nf @@ -27,10 +27,10 @@ process PARSE_FASTA_MIRNA { fi # Remove spaces from miRBase FASTA files # sed -i 's, ,_,g' \$FASTA - sed '%^[^>]%s%[^AUGCaugc]%N%g' \$FASTA > \${FASTA}_parsed.fa + sed '#^[^>]#s#[^AUGCaugc]#N#g' \$FASTA > \${FASTA}_parsed.fa # TODO perl -ane 's/[ybkmrsw]/N/ig;print;' \${FASTA}_parsed_tmp.fa > \${FASTA}_parsed.fa - sed -i 's%\s.*%%' \${FASTA}_parsed.fa + sed -i 's#\s.*##' \${FASTA}_parsed.fa seqkit grep -r --pattern \".*${filter_species}-.*\" \${FASTA}_parsed.fa > \${FASTA}_sps.fa seqkit seq --rna2dna \${FASTA}_sps.fa > \${FASTA}_igenome.fa From 8eac40a27785d5220352c12686fedf51c8911e6d Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 2 Dec 2022 14:10:33 +0000 Subject: [PATCH 102/215] Fix changelog prettier --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fb77be4..3929f0c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [[#208](https://github.com/nf-core/smrnaseq/issues/208)] - Fixed usability of `--skip_qc` parameter - ## [v2.1.0](https://github.com/nf-core/smrnaseq/releases/tag/2.1.0) - 2022-10-20 Maroon Tin Dalmatian ### Enhancements & fixes From cf39b469b8874e02a82d015389141b0be0d15e2d Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 2 Dec 2022 14:11:38 +0000 Subject: [PATCH 103/215] Prettier goddamnit! --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 952eb2b0..5615588f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Dev -* [[#206](https://github.com/nf-core/smrnaseq/issues/206)] - Use % as separator in sed commands to enable conda working properly on OSX and Linux +- [[#206](https://github.com/nf-core/smrnaseq/issues/206)] - Use % as separator in sed commands to enable conda working properly on OSX and Linux ## [v2.1.0](https://github.com/nf-core/smrnaseq/releases/tag/2.1.0) - 2022-10-20 Maroon Tin Dalmatian From 55eb719eaf6de62116c012371fb022bb8c7714fb Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 2 Dec 2022 14:28:49 +0000 Subject: [PATCH 104/215] Yabadabadoooh --- CHANGELOG.md | 2 ++ .../execution_trace_2022-12-02_14-28-46.txt | 1 + workflows/smrnaseq.nf | 10 ++++++---- 3 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 muchasmuchasgracias/pipeline_info/execution_trace_2022-12-02_14-28-46.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index e31be347..8ce2e696 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Dev +- [[#205](https://github.com/nf-core/smrnaseq/issues/205)] - Fix mirTrace Report to be a single report again instead of per sample reports + ## [v2.1.0](https://github.com/nf-core/smrnaseq/releases/tag/2.1.0) - 2022-10-20 Maroon Tin Dalmatian ### Enhancements & fixes diff --git a/muchasmuchasgracias/pipeline_info/execution_trace_2022-12-02_14-28-46.txt b/muchasmuchasgracias/pipeline_info/execution_trace_2022-12-02_14-28-46.txt new file mode 100644 index 00000000..6b739acd --- /dev/null +++ b/muchasmuchasgracias/pipeline_info/execution_trace_2022-12-02_14-28-46.txt @@ -0,0 +1 @@ +task_id hash native_id name status exit submit duration realtime %cpu peak_rss peak_vmem rchar wchar diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 09f2c2a6..77783a36 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -137,10 +137,12 @@ workflow SMRNASEQ { // // SUBWORKFLOW: mirtrace QC // - FASTQC_FASTP.out.adapterseq - | join( ch_cat_fastq ) - | map { meta, adapterseq, fastq -> [meta + [adapter:adapterseq], fastq] } - | MIRTRACE + ch_outputs_for_mirtrace = FASTQC_FASTP.out.adapterseq + .join( ch_cat_fastq ) + .map { meta, adapterseq, fastq -> [meta + [adapter:adapterseq], fastq] } + .collect() + + MIRTRACE(ch_outputs_for_mirtrace) ch_versions = ch_versions.mix(MIRTRACE.out.versions.ifEmpty(null)) From 4cee6d069537c1c17cdfa97df9c0112a0dab4ba7 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 2 Dec 2022 16:32:23 +0100 Subject: [PATCH 105/215] Delete execution_trace_2022-12-02_14-28-46.txt --- .../pipeline_info/execution_trace_2022-12-02_14-28-46.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 muchasmuchasgracias/pipeline_info/execution_trace_2022-12-02_14-28-46.txt diff --git a/muchasmuchasgracias/pipeline_info/execution_trace_2022-12-02_14-28-46.txt b/muchasmuchasgracias/pipeline_info/execution_trace_2022-12-02_14-28-46.txt deleted file mode 100644 index 6b739acd..00000000 --- a/muchasmuchasgracias/pipeline_info/execution_trace_2022-12-02_14-28-46.txt +++ /dev/null @@ -1 +0,0 @@ -task_id hash native_id name status exit submit duration realtime %cpu peak_rss peak_vmem rchar wchar From 2e0fc78b05a6ee786d835826a7c6d6408132c7df Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Thu, 8 Dec 2022 13:14:47 +0000 Subject: [PATCH 106/215] Template update for nf-core/tools version 2.7.1 --- .devcontainer/devcontainer.json | 27 +++++++++++++ .gitattributes | 1 + .github/CONTRIBUTING.md | 16 ++++++++ .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- .github/workflows/ci.yml | 8 +++- .github/workflows/fix-linting.yml | 6 +-- .github/workflows/linting.yml | 18 +++++---- .github/workflows/linting_comment.yml | 2 +- .prettierignore | 2 + CHANGELOG.md | 2 +- CITATION.cff | 56 --------------------------- README.md | 4 +- assets/slackreport.json | 34 ++++++++++++++++ docs/usage.md | 24 +++++++----- lib/NfcoreSchema.groovy | 1 - lib/NfcoreTemplate.groovy | 41 +++++++++++++++----- lib/WorkflowMain.groovy | 18 ++++++--- modules.json | 9 +++-- modules/local/samplesheet_check.nf | 4 ++ nextflow.config | 14 +++++-- nextflow_schema.json | 8 +++- workflows/smrnaseq.nf | 11 +++--- 22 files changed, 195 insertions(+), 113 deletions(-) create mode 100644 .devcontainer/devcontainer.json delete mode 100644 CITATION.cff create mode 100644 assets/slackreport.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..ea27a584 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,27 @@ +{ + "name": "nfcore", + "image": "nfcore/gitpod:latest", + "remoteUser": "gitpod", + + // Configure tool-specific properties. + "customizations": { + // Configure properties specific to VS Code. + "vscode": { + // Set *default* container specific settings.json values on container create. + "settings": { + "python.defaultInterpreterPath": "/opt/conda/bin/python", + "python.linting.enabled": true, + "python.linting.pylintEnabled": true, + "python.formatting.autopep8Path": "/opt/conda/bin/autopep8", + "python.formatting.yapfPath": "/opt/conda/bin/yapf", + "python.linting.flake8Path": "/opt/conda/bin/flake8", + "python.linting.pycodestylePath": "/opt/conda/bin/pycodestyle", + "python.linting.pydocstylePath": "/opt/conda/bin/pydocstyle", + "python.linting.pylintPath": "/opt/conda/bin/pylint" + }, + + // Add the IDs of extensions you want installed when the container is created. + "extensions": ["ms-python.python", "ms-python.vscode-pylance", "nf-core.nf-core-extensionpack"] + } + } +} diff --git a/.gitattributes b/.gitattributes index 050bb120..7a2dabc2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,4 @@ *.config linguist-language=nextflow +*.nf.test linguist-language=nextflow modules/nf-core/** linguist-generated subworkflows/nf-core/** linguist-generated diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 4f0eaee3..b24dd094 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -101,3 +101,19 @@ If you are using a new feature from core Nextflow, you may bump the minimum requ ### Images and figures For overview images and other documents we follow the nf-core [style guidelines and examples](https://nf-co.re/developers/design_guidelines). + +## GitHub Codespaces + +This repo includes a devcontainer configuration which will create a GitHub Codespaces for Nextflow development! This is an online developer environment that runs in your browser, complete with VSCode and a terminal. + +To get started: + +- Open the repo in [Codespaces](https://github.com/nf-core/smrnaseq/codespaces) +- Tools installed + - nf-core + - Nextflow + +Devcontainer specs: + +- [DevContainer config](.devcontainer/devcontainer.json) +- [Dockerfile](.devcontainer/Dockerfile) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index af04ee73..b280b79e 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -42,7 +42,7 @@ body: attributes: label: System information description: | - * Nextflow version _(eg. 21.10.3)_ + * Nextflow version _(eg. 22.10.1)_ * Hardware _(eg. HPC, Desktop, Cloud)_ * Executor _(eg. slurm, local, awsbatch)_ * Container engine: _(e.g. Docker, Singularity, Conda, Podman, Shifter or Charliecloud)_ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 00c9d511..d0902c8c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,10 @@ on: env: NXF_ANSI_LOG: false +concurrency: + group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}" + cancel-in-progress: true + jobs: test: name: Run pipeline with test data @@ -20,11 +24,11 @@ jobs: strategy: matrix: NXF_VER: - - "21.10.3" + - "22.10.1" - "latest-everything" steps: - name: Check out pipeline code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install Nextflow uses: nf-core/setup-nextflow@v1 diff --git a/.github/workflows/fix-linting.yml b/.github/workflows/fix-linting.yml index 8f76fa7f..4fe16754 100644 --- a/.github/workflows/fix-linting.yml +++ b/.github/workflows/fix-linting.yml @@ -24,7 +24,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.nf_core_bot_auth_token }} - - uses: actions/setup-node@v2 + - uses: actions/setup-node@v3 - name: Install Prettier run: npm install -g prettier @prettier/plugin-php @@ -34,9 +34,9 @@ jobs: id: prettier_status run: | if prettier --check ${GITHUB_WORKSPACE}; then - echo "::set-output name=result::pass" + echo "name=result::pass" >> $GITHUB_OUTPUT else - echo "::set-output name=result::fail" + echo "name=result::fail" >> $GITHUB_OUTPUT fi - name: Run 'prettier --write' diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 8a5ce69b..858d622e 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -4,6 +4,8 @@ name: nf-core linting # that the code meets the nf-core guidelines. on: push: + branches: + - dev pull_request: release: types: [published] @@ -12,9 +14,9 @@ jobs: EditorConfig: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - - uses: actions/setup-node@v2 + - uses: actions/setup-node@v3 - name: Install editorconfig-checker run: npm install -g editorconfig-checker @@ -25,9 +27,9 @@ jobs: Prettier: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - - uses: actions/setup-node@v2 + - uses: actions/setup-node@v3 - name: Install Prettier run: npm install -g prettier @@ -38,7 +40,7 @@ jobs: PythonBlack: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Check code lints with Black uses: psf/black@stable @@ -69,12 +71,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out pipeline code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install Nextflow uses: nf-core/setup-nextflow@v1 - - uses: actions/setup-python@v3 + - uses: actions/setup-python@v4 with: python-version: "3.7" architecture: "x64" @@ -97,7 +99,7 @@ jobs: - name: Upload linting log file artifact if: ${{ always() }} - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: linting-logs path: | diff --git a/.github/workflows/linting_comment.yml b/.github/workflows/linting_comment.yml index 04758f61..39635186 100644 --- a/.github/workflows/linting_comment.yml +++ b/.github/workflows/linting_comment.yml @@ -18,7 +18,7 @@ jobs: - name: Get PR number id: pr_number - run: echo "::set-output name=pr_number::$(cat linting-logs/PR_number.txt)" + run: echo "name=pr_number::$(cat linting-logs/PR_number.txt)" >> $GITHUB_OUTPUT - name: Post PR comment uses: marocchino/sticky-pull-request-comment@v2 diff --git a/.prettierignore b/.prettierignore index eb74a574..437d763d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,5 +1,6 @@ email_template.html adaptivecard.json +slackreport.json .nextflow* work/ data/ @@ -8,3 +9,4 @@ results/ testing/ testing* *.pyc +bin/ diff --git a/CHANGELOG.md b/CHANGELOG.md index c54766b2..946bdd84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 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). -## v2.1.0dev - [date] +## v2.1.1dev - [date] Initial release of nf-core/smrnaseq, created with the [nf-core](https://nf-co.re/) template. diff --git a/CITATION.cff b/CITATION.cff deleted file mode 100644 index 017666c0..00000000 --- a/CITATION.cff +++ /dev/null @@ -1,56 +0,0 @@ -cff-version: 1.2.0 -message: "If you use `nf-core tools` in your work, please cite the `nf-core` publication" -authors: - - family-names: Ewels - given-names: Philip - - family-names: Peltzer - given-names: Alexander - - family-names: Fillinger - given-names: Sven - - family-names: Patel - given-names: Harshil - - family-names: Alneberg - given-names: Johannes - - family-names: Wilm - given-names: Andreas - - family-names: Garcia - given-names: Maxime Ulysse - - family-names: Di Tommaso - given-names: Paolo - - family-names: Nahnsen - given-names: Sven -title: "The nf-core framework for community-curated bioinformatics pipelines." -version: 2.4.1 -doi: 10.1038/s41587-020-0439-x -date-released: 2022-05-16 -url: https://github.com/nf-core/tools -prefered-citation: - type: article - authors: - - family-names: Ewels - given-names: Philip - - family-names: Peltzer - given-names: Alexander - - family-names: Fillinger - given-names: Sven - - family-names: Patel - given-names: Harshil - - family-names: Alneberg - given-names: Johannes - - family-names: Wilm - given-names: Andreas - - family-names: Garcia - given-names: Maxime Ulysse - - family-names: Di Tommaso - given-names: Paolo - - family-names: Nahnsen - given-names: Sven - doi: 10.1038/s41587-020-0439-x - journal: nature biotechnology - start: 276 - end: 278 - title: "The nf-core framework for community-curated bioinformatics pipelines." - issue: 3 - volume: 38 - year: 2020 - url: https://dx.doi.org/10.1038/s41587-020-0439-x diff --git a/README.md b/README.md index 9caac333..3431bbf0 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/smrnaseq/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) -[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A521.10.3-23aa62.svg)](https://www.nextflow.io/) +[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A522.10.1-23aa62.svg)](https://www.nextflow.io/) [![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/) [![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/) [![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/) @@ -31,7 +31,7 @@ On release, automated continuous integration tests run the pipeline on a full-si ## Quick Start -1. Install [`Nextflow`](https://www.nextflow.io/docs/latest/getstarted.html#installation) (`>=21.10.3`) +1. Install [`Nextflow`](https://www.nextflow.io/docs/latest/getstarted.html#installation) (`>=22.10.1`) 2. Install any of [`Docker`](https://docs.docker.com/engine/installation/), [`Singularity`](https://www.sylabs.io/guides/3.0/user-guide/) (you can follow [this tutorial](https://singularity-tutorial.github.io/01-installation/)), [`Podman`](https://podman.io/), [`Shifter`](https://nersc.gitlab.io/development/shifter/how-to-use/) or [`Charliecloud`](https://hpc.github.io/charliecloud/) for full pipeline reproducibility _(you can use [`Conda`](https://conda.io/miniconda.html) both to install Nextflow itself and also to manage software within pipelines. Please only use it within pipelines as a last resort; see [docs](https://nf-co.re/usage/configuration#basic-configuration-profiles))_. diff --git a/assets/slackreport.json b/assets/slackreport.json new file mode 100644 index 00000000..043d02f2 --- /dev/null +++ b/assets/slackreport.json @@ -0,0 +1,34 @@ +{ + "attachments": [ + { + "fallback": "Plain-text summary of the attachment.", + "color": "<% if (success) { %>good<% } else { %>danger<%} %>", + "author_name": "sanger-tol/readmapping v${version} - ${runName}", + "author_icon": "https://www.nextflow.io/docs/latest/_static/favicon.ico", + "text": "<% if (success) { %>Pipeline completed successfully!<% } else { %>Pipeline completed with errors<% } %>", + "fields": [ + { + "title": "Command used to launch the workflow", + "value": "```${commandLine}```", + "short": false + } + <% + if (!success) { %> + , + { + "title": "Full error message", + "value": "```${errorReport}```", + "short": false + }, + { + "title": "Pipeline configuration", + "value": "<% out << summary.collect{ k,v -> k == "hook_url" ? "_${k}_: (_hidden_)" : ( ( v.class.toString().contains('Path') || ( v.class.toString().contains('String') && v.contains('/') ) ) ? "_${k}_: `${v}`" : (v.class.toString().contains('DateTime') ? ("_${k}_: " + v.format(java.time.format.DateTimeFormatter.ofLocalizedDateTime(java.time.format.FormatStyle.MEDIUM))) : "_${k}_: ${v}") ) }.join(",\n") %>", + "short": false + } + <% } + %> + ], + "footer": "Completed at <% out << dateComplete.format(java.time.format.DateTimeFormatter.ofLocalizedDateTime(java.time.format.FormatStyle.MEDIUM)) %> (duration: ${duration})" + } + ] +} diff --git a/docs/usage.md b/docs/usage.md index 3d01eda4..1b923e23 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -83,9 +83,9 @@ nextflow pull nf-core/smrnaseq It is a good idea to specify a pipeline version when running the pipeline on your data. This ensures that a specific version of the pipeline code and software are used when you run your pipeline. If you keep using the same tag, you'll be running the same version of the pipeline, even if there have been changes to the code since. -First, go to the [nf-core/smrnaseq releases page](https://github.com/nf-core/smrnaseq/releases) and find the latest version number - numeric only (eg. `1.3.1`). Then specify this when running the pipeline with `-r` (one hyphen) - eg. `-r 1.3.1`. +First, go to the [nf-core/smrnaseq releases page](https://github.com/nf-core/smrnaseq/releases) and find the latest pipeline version - numeric only (eg. `1.3.1`). Then specify this when running the pipeline with `-r` (one hyphen) - eg. `-r 1.3.1`. Of course, you can switch to another version by changing the number after the `-r` flag. -This version number will be logged in reports when you run the pipeline, so that you'll know what you used when you look back in the future. +This version number will be logged in reports when you run the pipeline, so that you'll know what you used when you look back in the future. For example, at the bottom of the MultiQC reports. ## Core Nextflow arguments @@ -95,7 +95,7 @@ This version number will be logged in reports when you run the pipeline, so that Use this parameter to choose a configuration profile. Profiles can give configuration presets for different compute environments. -Several generic profiles are bundled with the pipeline which instruct the pipeline to use software packaged using different methods (Docker, Singularity, Podman, Shifter, Charliecloud, Conda) - see below. When using Biocontainers, most of these software packaging methods pull Docker containers from quay.io e.g [FastQC](https://quay.io/repository/biocontainers/fastqc) except for Singularity which directly downloads Singularity images via https hosted by the [Galaxy project](https://depot.galaxyproject.org/singularity/) and Conda which downloads and installs software locally from [Bioconda](https://bioconda.github.io/). +Several generic profiles are bundled with the pipeline which instruct the pipeline to use software packaged using different methods (Docker, Singularity, Podman, Shifter, Charliecloud, Conda) - see below. > We highly recommend the use of Docker or Singularity containers for full pipeline reproducibility, however when this is not possible, Conda is also supported. @@ -104,8 +104,11 @@ The pipeline also dynamically loads configurations from [https://github.com/nf-c Note that multiple profiles can be loaded, for example: `-profile test,docker` - the order of arguments is important! They are loaded in sequence, so later profiles can overwrite earlier profiles. -If `-profile` is not specified, the pipeline will run locally and expect all software to be installed and available on the `PATH`. This is _not_ recommended. +If `-profile` is not specified, the pipeline will run locally and expect all software to be installed and available on the `PATH`. This is _not_ recommended, since it can lead to different results on different machines dependent on the computer enviroment. +- `test` + - A profile with a complete configuration for automated testing + - Includes links to test data so needs no other parameters - `docker` - A generic configuration profile to be used with [Docker](https://docker.com/) - `singularity` @@ -118,9 +121,6 @@ If `-profile` is not specified, the pipeline will run locally and expect all sof - A generic configuration profile to be used with [Charliecloud](https://hpc.github.io/charliecloud/) - `conda` - A generic configuration profile to be used with [Conda](https://conda.io/docs/). Please only use Conda as a last resort i.e. when it's not possible to run the pipeline with Docker, Singularity, Podman, Shifter or Charliecloud. -- `test` - - A profile with a complete configuration for automated testing - - Includes links to test data so needs no other parameters ### `-resume` @@ -169,8 +169,14 @@ Work dir: Tip: you can replicate the issue by changing to the process work dir and entering the command `bash .command.run` ``` +#### For beginners + +A first step to bypass this error, you could try to increase the amount of CPUs, memory, and time for the whole pipeline. Therefor you can try to increase the resource for the parameters `--max_cpus`, `--max_memory`, and `--max_time`. Based on the error above, you have to increase the amount of memory. Therefore you can go to the [parameter documentation of rnaseq](https://nf-co.re/rnaseq/3.9/parameters) and scroll down to the `show hidden parameter` button to get the default value for `--max_memory`. In this case 128GB, you than can try to run your pipeline again with `--max_memory 200GB -resume` to skip all process, that were already calculated. If you can not increase the resource of the complete pipeline, you can try to adapt the resource for a single process as mentioned below. + +#### Advanced option on process level + To bypass this error you would need to find exactly which resources are set by the `STAR_ALIGN` process. The quickest way is to search for `process STAR_ALIGN` in the [nf-core/rnaseq Github repo](https://github.com/nf-core/rnaseq/search?q=process+STAR_ALIGN). -We have standardised the structure of Nextflow DSL2 pipelines such that all module files will be present in the `modules/` directory and so, based on the search results, the file we want is `modules/nf-core/software/star/align/main.nf`. +We have standardised the structure of Nextflow DSL2 pipelines such that all module files will be present in the `modules/` directory and so, based on the search results, the file we want is `modules/nf-core/star/align/main.nf`. If you click on the link to that file you will notice that there is a `label` directive at the top of the module that is set to [`label process_high`](https://github.com/nf-core/rnaseq/blob/4c27ef5610c87db00c3c5a3eed10b1d161abf575/modules/nf-core/software/star/align/main.nf#L9). The [Nextflow `label`](https://www.nextflow.io/docs/latest/process.html#label) directive allows us to organise workflow processes in separate groups which can be referenced in a configuration file to select and configure subset of processes having similar computing requirements. The default values for the `process_high` label are set in the pipeline's [`base.config`](https://github.com/nf-core/rnaseq/blob/4c27ef5610c87db00c3c5a3eed10b1d161abf575/conf/base.config#L33-L37) which in this case is defined as 72GB. @@ -189,7 +195,7 @@ process { > > If you get a warning suggesting that the process selector isn't recognised check that the process name has been specified correctly. -### Updating containers +### Updating containers (advanced users) The [Nextflow DSL2](https://www.nextflow.io/docs/latest/dsl2.html) implementation of this pipeline uses one container per process which makes it much easier to maintain and update software dependencies. If for some reason you need to use a different version of a particular tool with the pipeline then you just need to identify the `process` name and override the Nextflow `container` definition for that process using the `withName` declaration. For example, in the [nf-core/viralrecon](https://nf-co.re/viralrecon) pipeline a tool called [Pangolin](https://github.com/cov-lineages/pangolin) has been used during the COVID-19 pandemic to assign lineages to SARS-CoV-2 genome sequenced samples. Given that the lineage assignments change quite frequently it doesn't make sense to re-release the nf-core/viralrecon everytime a new version of Pangolin has been released. However, you can override the default container used by the pipeline by creating a custom config file and passing it as a command-line argument via `-c custom.config`. diff --git a/lib/NfcoreSchema.groovy b/lib/NfcoreSchema.groovy index b3d092f8..33cd4f6e 100755 --- a/lib/NfcoreSchema.groovy +++ b/lib/NfcoreSchema.groovy @@ -46,7 +46,6 @@ class NfcoreSchema { 'quiet', 'syslog', 'v', - 'version', // Options for `nextflow run` command 'ansi', diff --git a/lib/NfcoreTemplate.groovy b/lib/NfcoreTemplate.groovy index 27feb009..25a0a74a 100755 --- a/lib/NfcoreTemplate.groovy +++ b/lib/NfcoreTemplate.groovy @@ -32,6 +32,25 @@ class NfcoreTemplate { } } + // + // Generate version string + // + public static String version(workflow) { + String version_string = "" + + if (workflow.manifest.version) { + def prefix_v = workflow.manifest.version[0] != 'v' ? 'v' : '' + version_string += "${prefix_v}${workflow.manifest.version}" + } + + if (workflow.commitId) { + def git_shortsha = workflow.commitId.substring(0, 7) + version_string += "-g${git_shortsha}" + } + + return version_string + } + // // Construct and send completion email // @@ -61,7 +80,7 @@ class NfcoreTemplate { misc_fields['Nextflow Compile Timestamp'] = workflow.nextflow.timestamp def email_fields = [:] - email_fields['version'] = workflow.manifest.version + email_fields['version'] = NfcoreTemplate.version(workflow) email_fields['runName'] = workflow.runName email_fields['success'] = workflow.success email_fields['dateComplete'] = workflow.complete @@ -146,10 +165,10 @@ class NfcoreTemplate { } // - // Construct and send adaptive card - // https://adaptivecards.io + // Construct and send a notification to a web server as JSON + // e.g. Microsoft Teams and Slack // - public static void adaptivecard(workflow, params, summary_params, projectDir, log) { + public static void IM_notification(workflow, params, summary_params, projectDir, log) { def hook_url = params.hook_url def summary = [:] @@ -170,7 +189,7 @@ class NfcoreTemplate { misc_fields['nxf_timestamp'] = workflow.nextflow.timestamp def msg_fields = [:] - msg_fields['version'] = workflow.manifest.version + msg_fields['version'] = NfcoreTemplate.version(workflow) msg_fields['runName'] = workflow.runName msg_fields['success'] = workflow.success msg_fields['dateComplete'] = workflow.complete @@ -178,13 +197,16 @@ class NfcoreTemplate { msg_fields['exitStatus'] = workflow.exitStatus msg_fields['errorMessage'] = (workflow.errorMessage ?: 'None') msg_fields['errorReport'] = (workflow.errorReport ?: 'None') - msg_fields['commandLine'] = workflow.commandLine + msg_fields['commandLine'] = workflow.commandLine.replaceFirst(/ +--hook_url +[^ ]+/, "") msg_fields['projectDir'] = workflow.projectDir msg_fields['summary'] = summary << misc_fields // Render the JSON template def engine = new groovy.text.GStringTemplateEngine() - def hf = new File("$projectDir/assets/adaptivecard.json") + // Different JSON depending on the service provider + // Defaults to "Adaptive Cards" (https://adaptivecards.io), except Slack which has its own format + def json_path = hook_url.contains("hooks.slack.com") ? "slackreport.json" : "adaptivecard.json" + def hf = new File("$projectDir/assets/${json_path}") def json_template = engine.createTemplate(hf).make(msg_fields) def json_message = json_template.toString() @@ -209,7 +231,7 @@ class NfcoreTemplate { if (workflow.stats.ignoredCount == 0) { log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Pipeline completed successfully${colors.reset}-" } else { - log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed successfully, but with errored process(es) ${colors.reset}-" + log.info "-${colors.purple}[$workflow.manifest.name]${colors.yellow} Pipeline completed successfully, but with errored process(es) ${colors.reset}-" } } else { log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed with errors${colors.reset}-" @@ -297,6 +319,7 @@ class NfcoreTemplate { // public static String logo(workflow, monochrome_logs) { Map colors = logColours(monochrome_logs) + String workflow_version = NfcoreTemplate.version(workflow) String.format( """\n ${dashedLine(monochrome_logs)} @@ -305,7 +328,7 @@ class NfcoreTemplate { ${colors.blue} |\\ | |__ __ / ` / \\ |__) |__ ${colors.yellow}} {${colors.reset} ${colors.blue} | \\| | \\__, \\__/ | \\ |___ ${colors.green}\\`-._,-`-,${colors.reset} ${colors.green}`._,._,\'${colors.reset} - ${colors.purple} ${workflow.manifest.name} v${workflow.manifest.version}${colors.reset} + ${colors.purple} ${workflow.manifest.name} ${workflow_version}${colors.reset} ${dashedLine(monochrome_logs)} """.stripIndent() ) diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 417fde67..6cbc7987 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -19,7 +19,7 @@ class WorkflowMain { } // - // Print help to screen if required + // Generate help string // public static String help(workflow, params, log) { def command = "nextflow run ${workflow.manifest.name} --input samplesheet.csv --genome GRCh37 -profile docker" @@ -32,7 +32,7 @@ class WorkflowMain { } // - // Print parameter summary log to screen + // Generate parameter summary log string // public static String paramsSummaryLog(workflow, params, log) { def summary_log = '' @@ -53,15 +53,21 @@ class WorkflowMain { System.exit(0) } - // Validate workflow parameters via the JSON schema - if (params.validate_params) { - NfcoreSchema.validateParameters(workflow, params, log) + // Print workflow version and exit on --version + if (params.version) { + String workflow_version = NfcoreTemplate.version(workflow) + log.info "${workflow.manifest.name} ${workflow_version}" + System.exit(0) } // Print parameter summary log to screen - log.info paramsSummaryLog(workflow, params, log) + // Validate workflow parameters via the JSON schema + if (params.validate_params) { + NfcoreSchema.validateParameters(workflow, params, log) + } + // Check that a -profile or Nextflow config has been provided to run the pipeline NfcoreTemplate.checkConfigProvided(workflow, log) diff --git a/modules.json b/modules.json index 70345a21..574bc334 100644 --- a/modules.json +++ b/modules.json @@ -7,15 +7,18 @@ "nf-core": { "custom/dumpsoftwareversions": { "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905", + "installed_by": ["modules"] }, "fastqc": { "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905", + "installed_by": ["modules"] }, "multiqc": { "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905", + "installed_by": ["modules"] } } } diff --git a/modules/local/samplesheet_check.nf b/modules/local/samplesheet_check.nf index 79054ff8..d9a84b5e 100644 --- a/modules/local/samplesheet_check.nf +++ b/modules/local/samplesheet_check.nf @@ -1,5 +1,6 @@ process SAMPLESHEET_CHECK { tag "$samplesheet" + label 'process_single' conda (params.enable_conda ? "conda-forge::python=3.8.3" : null) container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? @@ -13,6 +14,9 @@ process SAMPLESHEET_CHECK { path '*.csv' , emit: csv path "versions.yml", emit: versions + when: + task.ext.when == null || task.ext.when + script: // This script is bundled with the pipeline, in nf-core/smrnaseq/bin/ """ check_samplesheet.py \\ diff --git a/nextflow.config b/nextflow.config index c9ccb710..07b9d56f 100644 --- a/nextflow.config +++ b/nextflow.config @@ -35,6 +35,7 @@ params { monochrome_logs = false hook_url = null help = false + version = false validate_params = true show_hidden_params = false schema_ignore_params = 'genomes' @@ -81,6 +82,7 @@ profiles { debug { process.beforeScript = 'echo $HOSTNAME' } conda { params.enable_conda = true + conda.enabled = true docker.enabled = false singularity.enabled = false podman.enabled = false @@ -89,6 +91,7 @@ profiles { } mamba { params.enable_conda = true + conda.enabled = true conda.useMamba = true docker.enabled = false singularity.enabled = false @@ -104,6 +107,9 @@ profiles { shifter.enabled = false charliecloud.enabled = false } + arm { + docker.runOptions = '-u $(id -u):$(id -g) --platform=linux/amd64' + } singularity { singularity.enabled = true singularity.autoMounts = true @@ -185,12 +191,12 @@ dag { manifest { name = 'nf-core/smrnaseq' - author = 'P. Ewels, C. Wang, R. Hammarén, L. Pantano' + author = """P. Ewels, C. Wang, R. Hammarén, L. Pantano""" homePage = 'https://github.com/nf-core/smrnaseq' - description = 'Small RNA-Seq Best Practice Analysis Pipeline.' + description = """Small RNA-Seq Best Practice Analysis Pipeline.""" mainScript = 'main.nf' - nextflowVersion = '!>=21.10.3' - version = '2.1.0dev' + nextflowVersion = '!>=22.10.1' + version = '2.1.1dev' doi = '' } diff --git a/nextflow_schema.json b/nextflow_schema.json index 8aaa69c5..4b6dbf49 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -176,6 +176,12 @@ "fa_icon": "fas fa-question-circle", "hidden": true }, + "version": { + "type": "boolean", + "description": "Display version and exit.", + "fa_icon": "fas fa-question-circle", + "hidden": true + }, "publish_dir_mode": { "type": "string", "default": "copy", @@ -217,7 +223,7 @@ "type": "string", "description": "Incoming hook URL for messaging service", "fa_icon": "fas fa-people-group", - "help_text": "Incoming hook URL for messaging service. Currently, only MS Teams is supported.", + "help_text": "Incoming hook URL for messaging service. Currently, MS Teams and Slack are supported.", "hidden": true }, "multiqc_config": { diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 1d5a682d..24f02ded 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -82,7 +82,7 @@ workflow SMRNASEQ { ch_versions = ch_versions.mix(FASTQC.out.versions.first()) CUSTOM_DUMPSOFTWAREVERSIONS ( - ch_versions.unique().collectFile(name: 'collated_versions.yml') + ch_versions.unique{ it.text }.collectFile(name: 'collated_versions.yml') ) // @@ -102,12 +102,11 @@ workflow SMRNASEQ { MULTIQC ( ch_multiqc_files.collect(), - ch_multiqc_config.collect().ifEmpty([]), - ch_multiqc_custom_config.collect().ifEmpty([]), - ch_multiqc_logo.collect().ifEmpty([]) + ch_multiqc_config.toList(), + ch_multiqc_custom_config.toList(), + ch_multiqc_logo.toList() ) multiqc_report = MULTIQC.out.report.toList() - ch_versions = ch_versions.mix(MULTIQC.out.versions) } /* @@ -122,7 +121,7 @@ workflow.onComplete { } NfcoreTemplate.summary(workflow, params, log) if (params.hook_url) { - NfcoreTemplate.adaptivecard(workflow, params, summary_params, projectDir, log) + NfcoreTemplate.IM_notification(workflow, params, summary_params, projectDir, log) } } From e29f9cc290dbdf11de807e4ba8884d0256f37b31 Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Mon, 19 Dec 2022 12:09:16 +0000 Subject: [PATCH 107/215] Template update for nf-core/tools version 2.7.2 --- .github/workflows/fix-linting.yml | 4 +- .github/workflows/linting_comment.yml | 2 +- lib/WorkflowMain.groovy | 2 +- modules.json | 6 +- modules/local/samplesheet_check.nf | 2 +- .../custom/dumpsoftwareversions/main.nf | 2 +- .../templates/dumpsoftwareversions.py | 99 ++++++++++--------- modules/nf-core/fastqc/main.nf | 40 +++----- modules/nf-core/multiqc/main.nf | 2 +- nextflow.config | 3 - nextflow_schema.json | 6 -- workflows/smrnaseq.nf | 2 +- 12 files changed, 82 insertions(+), 88 deletions(-) mode change 100644 => 100755 modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py diff --git a/.github/workflows/fix-linting.yml b/.github/workflows/fix-linting.yml index 4fe16754..ae6a0d7b 100644 --- a/.github/workflows/fix-linting.yml +++ b/.github/workflows/fix-linting.yml @@ -34,9 +34,9 @@ jobs: id: prettier_status run: | if prettier --check ${GITHUB_WORKSPACE}; then - echo "name=result::pass" >> $GITHUB_OUTPUT + echo "result=pass" >> $GITHUB_OUTPUT else - echo "name=result::fail" >> $GITHUB_OUTPUT + echo "result=fail" >> $GITHUB_OUTPUT fi - name: Run 'prettier --write' diff --git a/.github/workflows/linting_comment.yml b/.github/workflows/linting_comment.yml index 39635186..0bbcd30f 100644 --- a/.github/workflows/linting_comment.yml +++ b/.github/workflows/linting_comment.yml @@ -18,7 +18,7 @@ jobs: - name: Get PR number id: pr_number - run: echo "name=pr_number::$(cat linting-logs/PR_number.txt)" >> $GITHUB_OUTPUT + run: echo "pr_number=$(cat linting-logs/PR_number.txt)" >> $GITHUB_OUTPUT - name: Post PR comment uses: marocchino/sticky-pull-request-comment@v2 diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 6cbc7987..d5372d8c 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -72,7 +72,7 @@ class WorkflowMain { NfcoreTemplate.checkConfigProvided(workflow, log) // Check that conda channels are set-up correctly - if (params.enable_conda) { + if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { Utils.checkCondaChannels(log) } diff --git a/modules.json b/modules.json index 574bc334..6a70e5a9 100644 --- a/modules.json +++ b/modules.json @@ -7,17 +7,17 @@ "nf-core": { "custom/dumpsoftwareversions": { "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905", + "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", "installed_by": ["modules"] }, "fastqc": { "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905", + "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", "installed_by": ["modules"] }, "multiqc": { "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905", + "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", "installed_by": ["modules"] } } diff --git a/modules/local/samplesheet_check.nf b/modules/local/samplesheet_check.nf index d9a84b5e..94247c70 100644 --- a/modules/local/samplesheet_check.nf +++ b/modules/local/samplesheet_check.nf @@ -2,7 +2,7 @@ process SAMPLESHEET_CHECK { tag "$samplesheet" label 'process_single' - conda (params.enable_conda ? "conda-forge::python=3.8.3" : null) + conda "conda-forge::python=3.8.3" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/python:3.8.3' : 'quay.io/biocontainers/python:3.8.3' }" diff --git a/modules/nf-core/custom/dumpsoftwareversions/main.nf b/modules/nf-core/custom/dumpsoftwareversions/main.nf index cebb6e05..3df21765 100644 --- a/modules/nf-core/custom/dumpsoftwareversions/main.nf +++ b/modules/nf-core/custom/dumpsoftwareversions/main.nf @@ -2,7 +2,7 @@ process CUSTOM_DUMPSOFTWAREVERSIONS { label 'process_single' // Requires `pyyaml` which does not have a dedicated container but is in the MultiQC container - conda (params.enable_conda ? 'bioconda::multiqc=1.13' : null) + conda "bioconda::multiqc=1.13" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/multiqc:1.13--pyhdfd78af_0' : 'quay.io/biocontainers/multiqc:1.13--pyhdfd78af_0' }" diff --git a/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py old mode 100644 new mode 100755 index 787bdb7b..e55b8d43 --- a/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py +++ b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py @@ -1,5 +1,9 @@ #!/usr/bin/env python + +"""Provide functions to merge multiple versions.yml files.""" + + import platform from textwrap import dedent @@ -7,6 +11,7 @@ def _make_versions_html(versions): + """Generate a tabular HTML output of all versions for MultiQC.""" html = [ dedent( """\\ @@ -45,47 +50,53 @@ def _make_versions_html(versions): return "\\n".join(html) -versions_this_module = {} -versions_this_module["${task.process}"] = { - "python": platform.python_version(), - "yaml": yaml.__version__, -} - -with open("$versions") as f: - versions_by_process = yaml.load(f, Loader=yaml.BaseLoader) | versions_this_module - -# aggregate versions by the module name (derived from fully-qualified process name) -versions_by_module = {} -for process, process_versions in versions_by_process.items(): - module = process.split(":")[-1] - try: - if versions_by_module[module] != process_versions: - raise AssertionError( - "We assume that software versions are the same between all modules. " - "If you see this error-message it means you discovered an edge-case " - "and should open an issue in nf-core/tools. " - ) - except KeyError: - versions_by_module[module] = process_versions - -versions_by_module["Workflow"] = { - "Nextflow": "$workflow.nextflow.version", - "$workflow.manifest.name": "$workflow.manifest.version", -} - -versions_mqc = { - "id": "software_versions", - "section_name": "${workflow.manifest.name} Software Versions", - "section_href": "https://github.com/${workflow.manifest.name}", - "plot_type": "html", - "description": "are collected at run time from the software output.", - "data": _make_versions_html(versions_by_module), -} - -with open("software_versions.yml", "w") as f: - yaml.dump(versions_by_module, f, default_flow_style=False) -with open("software_versions_mqc.yml", "w") as f: - yaml.dump(versions_mqc, f, default_flow_style=False) - -with open("versions.yml", "w") as f: - yaml.dump(versions_this_module, f, default_flow_style=False) +def main(): + """Load all version files and generate merged output.""" + versions_this_module = {} + versions_this_module["${task.process}"] = { + "python": platform.python_version(), + "yaml": yaml.__version__, + } + + with open("$versions") as f: + versions_by_process = yaml.load(f, Loader=yaml.BaseLoader) | versions_this_module + + # aggregate versions by the module name (derived from fully-qualified process name) + versions_by_module = {} + for process, process_versions in versions_by_process.items(): + module = process.split(":")[-1] + try: + if versions_by_module[module] != process_versions: + raise AssertionError( + "We assume that software versions are the same between all modules. " + "If you see this error-message it means you discovered an edge-case " + "and should open an issue in nf-core/tools. " + ) + except KeyError: + versions_by_module[module] = process_versions + + versions_by_module["Workflow"] = { + "Nextflow": "$workflow.nextflow.version", + "$workflow.manifest.name": "$workflow.manifest.version", + } + + versions_mqc = { + "id": "software_versions", + "section_name": "${workflow.manifest.name} Software Versions", + "section_href": "https://github.com/${workflow.manifest.name}", + "plot_type": "html", + "description": "are collected at run time from the software output.", + "data": _make_versions_html(versions_by_module), + } + + with open("software_versions.yml", "w") as f: + yaml.dump(versions_by_module, f, default_flow_style=False) + with open("software_versions_mqc.yml", "w") as f: + yaml.dump(versions_mqc, f, default_flow_style=False) + + with open("versions.yml", "w") as f: + yaml.dump(versions_this_module, f, default_flow_style=False) + + +if __name__ == "__main__": + main() diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf index 05730368..9ae58381 100644 --- a/modules/nf-core/fastqc/main.nf +++ b/modules/nf-core/fastqc/main.nf @@ -2,7 +2,7 @@ process FASTQC { tag "$meta.id" label 'process_medium' - conda (params.enable_conda ? "bioconda::fastqc=0.11.9" : null) + conda "bioconda::fastqc=0.11.9" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/fastqc:0.11.9--0' : 'quay.io/biocontainers/fastqc:0.11.9--0' }" @@ -20,30 +20,22 @@ process FASTQC { script: def args = task.ext.args ?: '' - // Add soft-links to original FastQs for consistent naming in pipeline def prefix = task.ext.prefix ?: "${meta.id}" - if (meta.single_end) { - """ - [ ! -f ${prefix}.fastq.gz ] && ln -s $reads ${prefix}.fastq.gz - fastqc $args --threads $task.cpus ${prefix}.fastq.gz - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - fastqc: \$( fastqc --version | sed -e "s/FastQC v//g" ) - END_VERSIONS - """ - } else { - """ - [ ! -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 - fastqc $args --threads $task.cpus ${prefix}_1.fastq.gz ${prefix}_2.fastq.gz - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - fastqc: \$( fastqc --version | sed -e "s/FastQC v//g" ) - END_VERSIONS - """ - } + // Make list of old name and new name pairs to use for renaming in the bash while loop + def old_new_pairs = reads instanceof Path || reads.size() == 1 ? [[ reads, "${prefix}.${reads.extension}" ]] : reads.withIndex().collect { entry, index -> [ entry, "${prefix}_${index + 1}.${entry.extension}" ] } + def rename_to = old_new_pairs*.join(' ').join(' ') + def renamed_files = old_new_pairs.collect{ old_name, new_name -> new_name }.join(' ') + """ + printf "%s %s\\n" $rename_to | while read old_name new_name; do + [ -f "\${new_name}" ] || ln -s \$old_name \$new_name + done + fastqc $args --threads $task.cpus $renamed_files + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + fastqc: \$( fastqc --version | sed -e "s/FastQC v//g" ) + END_VERSIONS + """ stub: def prefix = task.ext.prefix ?: "${meta.id}" diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index a8159a57..68f66bea 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -1,7 +1,7 @@ process MULTIQC { label 'process_single' - conda (params.enable_conda ? 'bioconda::multiqc=1.13' : null) + conda "bioconda::multiqc=1.13" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/multiqc:1.13--pyhdfd78af_0' : 'quay.io/biocontainers/multiqc:1.13--pyhdfd78af_0' }" diff --git a/nextflow.config b/nextflow.config index 07b9d56f..4a87aa48 100644 --- a/nextflow.config +++ b/nextflow.config @@ -39,7 +39,6 @@ params { validate_params = true show_hidden_params = false schema_ignore_params = 'genomes' - enable_conda = false // Config options @@ -81,7 +80,6 @@ try { profiles { debug { process.beforeScript = 'echo $HOSTNAME' } conda { - params.enable_conda = true conda.enabled = true docker.enabled = false singularity.enabled = false @@ -90,7 +88,6 @@ profiles { charliecloud.enabled = false } mamba { - params.enable_conda = true conda.enabled = true conda.useMamba = true docker.enabled = false diff --git a/nextflow_schema.json b/nextflow_schema.json index 4b6dbf49..f8d98d8c 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -263,12 +263,6 @@ "description": "Show all params when using `--help`", "hidden": true, "help_text": "By default, parameters set as _hidden_ in the schema are not shown on the command line when a user runs with `--help`. Specifying this option will tell the pipeline to show all parameters." - }, - "enable_conda": { - "type": "boolean", - "description": "Run this workflow with Conda. You can also use '-profile conda' instead of providing this parameter.", - "hidden": true, - "fa_icon": "fas fa-bacon" } } } diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 24f02ded..01491244 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -82,7 +82,7 @@ workflow SMRNASEQ { ch_versions = ch_versions.mix(FASTQC.out.versions.first()) CUSTOM_DUMPSOFTWAREVERSIONS ( - ch_versions.unique{ it.text }.collectFile(name: 'collated_versions.yml') + ch_versions.unique().collectFile(name: 'collated_versions.yml') ) // From 65d04a4d9683b1c52b0b541186a89d386e20047a Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Sat, 4 Feb 2023 13:27:44 +0000 Subject: [PATCH 108/215] Update modules --- modules.json | 50 ++++++------------- .../templates/dumpsoftwareversions.py | 49 ------------------ modules/nf-core/fastp/main.nf | 2 +- modules/nf-core/fastqc/main.nf | 3 -- modules/nf-core/multiqc/main.nf | 6 +-- modules/nf-core/samtools/flagstat/main.nf | 6 +-- modules/nf-core/samtools/idxstats/main.nf | 8 +-- modules/nf-core/samtools/index/main.nf | 6 +-- modules/nf-core/samtools/sort/main.nf | 6 +-- 9 files changed, 31 insertions(+), 105 deletions(-) diff --git a/modules.json b/modules.json index 06119514..de67a7e7 100644 --- a/modules.json +++ b/modules.json @@ -12,65 +12,43 @@ }, "custom/dumpsoftwareversions": { "branch": "master", - "git_sha": "8022c68e7403eecbd8ba9c49496f69f8c49d50f0" - }, - "fastp": { - "branch": "master", - "git_sha": "1e49f31e93c56a3832833eef90a02d3cde5a3f7e" - }, - "custom/dumpsoftwareversions": { - "branch": "master", - "git_sha": "8022c68e7403eecbd8ba9c49496f69f8c49d50f0", + "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", "installed_by": ["modules"] }, "fastp": { "branch": "master", - "git_sha": "1e49f31e93c56a3832833eef90a02d3cde5a3f7e" + "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", + "installed_by": ["modules"] }, "fastqc": { "branch": "master", - "git_sha": "f6a11408536fbee6cbea1f5977605011873de3ca" + "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", "installed_by": ["modules"] }, "multiqc": { "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" - }, - "samtools/flagstat": { - "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" - }, - "samtools/idxstats": { - "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" - }, - "samtools/index": { - "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" - }, - "samtools/sort": { - "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" - }, - "samtools/stats": { - "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + "git_sha": "ee80d14721e76e2e079103b8dcd5d57129e584ba", + "installed_by": ["modules"] }, "samtools/flagstat": { "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", + "installed_by": ["modules"] }, "samtools/idxstats": { "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", + "installed_by": ["modules"] }, "samtools/index": { "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", + "installed_by": ["modules"] }, "samtools/sort": { "branch": "master", - "git_sha": "5e34754d42cd2d5d248ca8673c0a53cdf5624905" + "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", + "installed_by": ["modules"] }, "samtools/stats": { "branch": "master", diff --git a/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py index 5b34099f..da033408 100755 --- a/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py +++ b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py @@ -1,10 +1,6 @@ #!/usr/bin/env python -"""Provide functions to merge multiple versions.yml files.""" - - - """Provide functions to merge multiple versions.yml files.""" @@ -14,7 +10,6 @@ def _make_versions_html(versions): - """Generate a tabular HTML output of all versions for MultiQC.""" """Generate a tabular HTML output of all versions for MultiQC.""" html = [ dedent( @@ -54,13 +49,6 @@ def _make_versions_html(versions): return "\\n".join(html) -def main(): - """Load all version files and generate merged output.""" - versions_this_module = {} - versions_this_module["${task.process}"] = { - "python": platform.python_version(), - "yaml": yaml.__version__, - } def main(): """Load all version files and generate merged output.""" versions_this_module = {} @@ -69,26 +57,11 @@ def main(): "yaml": yaml.__version__, } - with open("$versions") as f: - versions_by_process = yaml.load(f, Loader=yaml.BaseLoader) | versions_this_module with open("$versions") as f: versions_by_process = yaml.load(f, Loader=yaml.BaseLoader) | versions_this_module # aggregate versions by the module name (derived from fully-qualified process name) versions_by_module = {} - for process, process_versions in versions_by_process.items(): - module = process.split(":")[-1] - try: - if versions_by_module[module] != process_versions: - raise AssertionError( - "We assume that software versions are the same between all modules. " - "If you see this error-message it means you discovered an edge-case " - "and should open an issue in nf-core/tools. " - ) - except KeyError: - versions_by_module[module] = process_versions - # aggregate versions by the module name (derived from fully-qualified process name) - versions_by_module = {} for process, process_versions in versions_by_process.items(): module = process.split(":")[-1] try: @@ -105,19 +78,7 @@ def main(): "Nextflow": "$workflow.nextflow.version", "$workflow.manifest.name": "$workflow.manifest.version", } - versions_by_module["Workflow"] = { - "Nextflow": "$workflow.nextflow.version", - "$workflow.manifest.name": "$workflow.manifest.version", - } - versions_mqc = { - "id": "software_versions", - "section_name": "${workflow.manifest.name} Software Versions", - "section_href": "https://github.com/${workflow.manifest.name}", - "plot_type": "html", - "description": "are collected at run time from the software output.", - "data": _make_versions_html(versions_by_module), - } versions_mqc = { "id": "software_versions", "section_name": "${workflow.manifest.name} Software Versions", @@ -127,10 +88,6 @@ def main(): "data": _make_versions_html(versions_by_module), } - with open("software_versions.yml", "w") as f: - yaml.dump(versions_by_module, f, default_flow_style=False) - with open("software_versions_mqc.yml", "w") as f: - yaml.dump(versions_mqc, f, default_flow_style=False) with open("software_versions.yml", "w") as f: yaml.dump(versions_by_module, f, default_flow_style=False) with open("software_versions_mqc.yml", "w") as f: @@ -138,12 +95,6 @@ def main(): with open("versions.yml", "w") as f: yaml.dump(versions_this_module, f, default_flow_style=False) - with open("versions.yml", "w") as f: - yaml.dump(versions_this_module, f, default_flow_style=False) - - -if __name__ == "__main__": - main() if __name__ == "__main__": diff --git a/modules/nf-core/fastp/main.nf b/modules/nf-core/fastp/main.nf index 207258ad..e1ed9288 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 (params.enable_conda ? 'bioconda::fastp=0.23.2' : null) + conda "bioconda::fastp=0.23.2" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/fastp:0.23.2--h79da9fb_0' : 'quay.io/biocontainers/fastp:0.23.2--h79da9fb_0' }" diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf index 510978af..9ae58381 100644 --- a/modules/nf-core/fastqc/main.nf +++ b/modules/nf-core/fastqc/main.nf @@ -30,9 +30,6 @@ process FASTQC { [ -f "\${new_name}" ] || ln -s \$old_name \$new_name done fastqc $args --threads $task.cpus $renamed_files - """ - printf "%s\\n" $reads | while read f; do ln -s \$f ${prefix}_\$(basename \$f) ; done - fastqc $args --threads $task.cpus ${prefix}_* cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index 68f66bea..4b604749 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -1,10 +1,10 @@ process MULTIQC { label 'process_single' - conda "bioconda::multiqc=1.13" + conda "bioconda::multiqc=1.14" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.13--pyhdfd78af_0' : - 'quay.io/biocontainers/multiqc:1.13--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/multiqc:1.14--pyhdfd78af_0' : + 'quay.io/biocontainers/multiqc:1.14--pyhdfd78af_0' }" input: path multiqc_files, stageAs: "?/*" diff --git a/modules/nf-core/samtools/flagstat/main.nf b/modules/nf-core/samtools/flagstat/main.nf index c3152aca..2120cd7d 100644 --- a/modules/nf-core/samtools/flagstat/main.nf +++ b/modules/nf-core/samtools/flagstat/main.nf @@ -2,10 +2,10 @@ process SAMTOOLS_FLAGSTAT { tag "$meta.id" label 'process_single' - conda (params.enable_conda ? "bioconda::samtools=1.15.1" : null) + conda "bioconda::samtools=1.16.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.15.1--h1170115_0' : - 'quay.io/biocontainers/samtools:1.15.1--h1170115_0' }" + 'https://depot.galaxyproject.org/singularity/samtools:1.16.1--h6899075_1' : + 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" input: tuple val(meta), path(bam), path(bai) diff --git a/modules/nf-core/samtools/idxstats/main.nf b/modules/nf-core/samtools/idxstats/main.nf index 87618e5f..a7b87d8b 100644 --- a/modules/nf-core/samtools/idxstats/main.nf +++ b/modules/nf-core/samtools/idxstats/main.nf @@ -1,11 +1,11 @@ process SAMTOOLS_IDXSTATS { tag "$meta.id" - label 'process_low' + label 'process_single' - conda (params.enable_conda ? "bioconda::samtools=1.15.1" : null) + conda "bioconda::samtools=1.16.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.15.1--h1170115_0' : - 'quay.io/biocontainers/samtools:1.15.1--h1170115_0' }" + 'https://depot.galaxyproject.org/singularity/samtools:1.16.1--h6899075_1' : + 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" input: tuple val(meta), path(bam), path(bai) diff --git a/modules/nf-core/samtools/index/main.nf b/modules/nf-core/samtools/index/main.nf index e04e63e8..8b95687a 100644 --- a/modules/nf-core/samtools/index/main.nf +++ b/modules/nf-core/samtools/index/main.nf @@ -2,10 +2,10 @@ process SAMTOOLS_INDEX { tag "$meta.id" label 'process_low' - conda (params.enable_conda ? "bioconda::samtools=1.15.1" : null) + conda "bioconda::samtools=1.16.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.15.1--h1170115_0' : - 'quay.io/biocontainers/samtools:1.15.1--h1170115_0' }" + 'https://depot.galaxyproject.org/singularity/samtools:1.16.1--h6899075_1' : + 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" input: tuple val(meta), path(input) diff --git a/modules/nf-core/samtools/sort/main.nf b/modules/nf-core/samtools/sort/main.nf index ab7f1cca..84c167cd 100644 --- a/modules/nf-core/samtools/sort/main.nf +++ b/modules/nf-core/samtools/sort/main.nf @@ -2,10 +2,10 @@ process SAMTOOLS_SORT { tag "$meta.id" label 'process_medium' - conda (params.enable_conda ? "bioconda::samtools=1.15.1" : null) + conda "bioconda::samtools=1.16.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.15.1--h1170115_0' : - 'quay.io/biocontainers/samtools:1.15.1--h1170115_0' }" + 'https://depot.galaxyproject.org/singularity/samtools:1.16.1--h6899075_1' : + 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" input: tuple val(meta), path(bam) From bb8c60374c4d3e5f4846c5e02ad08ae13a941502 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Sat, 4 Feb 2023 13:31:00 +0000 Subject: [PATCH 109/215] Fix prettier --- CHANGELOG.md | 2 +- docs/usage.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79e4e5cc..6e73c128 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Dev -* Updated FASTP module to allow direct addition of adapter_fasta file to it +- Updated FASTP module to allow direct addition of adapter_fasta file to it ## [v2.1.0](https://github.com/nf-core/smrnaseq/releases/tag/2.1.0) - 2022-10-20 Maroon Tin Dalmatian diff --git a/docs/usage.md b/docs/usage.md index 056c0b77..f0027bcf 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -139,7 +139,7 @@ This version number will be logged in reports when you run the pipeline, so that The `bin` directory contains some scripts used by the pipeline which may also be run manually: - `edgeR_miRBase.r`: R script using for processing reads counts of mature miRNAs and miRNA precursors (hairpins). -This version number will be logged in reports when you run the pipeline, so that you'll know what you used when you look back in the future. For example, at the bottom of the MultiQC reports. + This version number will be logged in reports when you run the pipeline, so that you'll know what you used when you look back in the future. For example, at the bottom of the MultiQC reports. ## Core Nextflow arguments From bba81497cbde8b656c73e3657f102bf58c014012 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Tue, 7 Feb 2023 20:06:55 +0000 Subject: [PATCH 110/215] Fix black --- assets/methods_description_template.yml | 2 -- bin/check_samplesheet.py | 1 - modules/nf-core/cat/fastq/main.nf | 2 +- modules/nf-core/samtools/stats/main.nf | 6 +++--- nextflow.config | 1 - 5 files changed, 4 insertions(+), 8 deletions(-) diff --git a/assets/methods_description_template.yml b/assets/methods_description_template.yml index 247628aa..1f05424e 100644 --- a/assets/methods_description_template.yml +++ b/assets/methods_description_template.yml @@ -3,8 +3,6 @@ description: "Suggested text and references to use when describing pipeline usag section_name: "nf-core/smrnaseq Methods Description" section_href: "https://github.com/nf-core/smrnaseq" plot_type: "html" -## TODO nf-core: Update the HTML below to your prefered methods description, e.g. add publication citation for this pipeline -## You inject any metadata in the Nextflow '${workflow}' object data: |

    Methods

    Data was processed using nf-core/smrnaseq v${workflow.manifest.version} ${doi_text} of the nf-core collection of workflows (Ewels et al., 2020).

    diff --git a/bin/check_samplesheet.py b/bin/check_samplesheet.py index 24252b4b..757199ac 100755 --- a/bin/check_samplesheet.py +++ b/bin/check_samplesheet.py @@ -50,7 +50,6 @@ def check_samplesheet(file_in, file_out): sample_mapping_dict = {} with open(file_in, "r") as fin: - ## Check header MIN_COLS = 2 HEADER = ["sample", "fastq_1"] diff --git a/modules/nf-core/cat/fastq/main.nf b/modules/nf-core/cat/fastq/main.nf index 4fa365d3..8a0b5600 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 (params.enable_conda ? "conda-forge::sed=4.7" : null) + conda "conda-forge::sed=4.7" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/ubuntu:20.04' : 'ubuntu:20.04' }" diff --git a/modules/nf-core/samtools/stats/main.nf b/modules/nf-core/samtools/stats/main.nf index 9b0c3867..0a2a3640 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 (params.enable_conda ? "bioconda::samtools=1.15.1" : null) + conda "bioconda::samtools=1.16.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.15.1--h1170115_0' : - 'quay.io/biocontainers/samtools:1.15.1--h1170115_0' }" + 'https://depot.galaxyproject.org/singularity/samtools:1.16.1--h6899075_1' : + 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" input: tuple val(meta), path(input), path(input_index) diff --git a/nextflow.config b/nextflow.config index 80a6263f..fbe64350 100644 --- a/nextflow.config +++ b/nextflow.config @@ -74,7 +74,6 @@ params { validate_params = true show_hidden_params = false schema_ignore_params = 'genomes' - enable_conda = false // Config options From c3a4201de91142f54fc2318c08bc9a4cddc26ccc Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Tue, 7 Feb 2023 20:36:17 +0000 Subject: [PATCH 111/215] Fix Conda directives --- modules/local/blat_mirna.nf | 2 +- modules/local/bowtie_contaminants.nf | 2 +- modules/local/bowtie_genome.nf | 2 +- modules/local/bowtie_map_contaminants.nf | 2 +- modules/local/bowtie_map_mirna.nf | 2 +- modules/local/bowtie_mirna.nf | 2 +- modules/local/datatable_merge.nf | 2 +- modules/local/edger_qc.nf | 2 +- modules/local/filter_stats.nf | 2 +- modules/local/format_fasta_mirna.nf | 2 +- modules/local/mirdeep2_mapper.nf | 2 +- modules/local/mirdeep2_prepare.nf | 2 +- modules/local/mirdeep2_run.nf | 2 +- modules/local/mirtop_quant.nf | 2 +- modules/local/mirtrace.nf | 2 +- modules/local/parse_fasta_mirna.nf | 2 +- modules/local/seqcluster_collapse.nf | 2 +- workflows/smrnaseq.nf | 2 ++ 18 files changed, 19 insertions(+), 17 deletions(-) diff --git a/modules/local/blat_mirna.nf b/modules/local/blat_mirna.nf index 2b50d7db..198e001c 100644 --- a/modules/local/blat_mirna.nf +++ b/modules/local/blat_mirna.nf @@ -2,7 +2,7 @@ process BLAT_MIRNA { tag "$fasta" label 'process_medium' - conda (params.enable_conda ? 'bioconda::blat=36' : null) + conda 'bioconda::blat=36' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/blat:36--0' : 'quay.io/biocontainers/blat:36--0' }" diff --git a/modules/local/bowtie_contaminants.nf b/modules/local/bowtie_contaminants.nf index 1145b56f..a68b8530 100644 --- a/modules/local/bowtie_contaminants.nf +++ b/modules/local/bowtie_contaminants.nf @@ -1,7 +1,7 @@ process INDEX_CONTAMINANTS { label 'process_medium' - conda (params.enable_conda ? 'bowtie2=2.4.5' : null) + conda 'bowtie2=2.4.5' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/bowtie2:2.4.5--py39hd2f7db1_2' : 'quay.io/biocontainers/bowtie2:2.4.5--py36hfca12d5_2'}" diff --git a/modules/local/bowtie_genome.nf b/modules/local/bowtie_genome.nf index 1fb38551..1405467a 100644 --- a/modules/local/bowtie_genome.nf +++ b/modules/local/bowtie_genome.nf @@ -2,7 +2,7 @@ process INDEX_GENOME { tag "$fasta" label 'process_medium' - conda (params.enable_conda ? 'bioconda::bowtie=1.3.1-4' : null) + conda 'bioconda::bowtie=1.3.1-4' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/bowtie%3A1.3.1--py39hd400a0c_2' : 'quay.io/biocontainers/bowtie:1.3.1--py310h4070885_4' }" diff --git a/modules/local/bowtie_map_contaminants.nf b/modules/local/bowtie_map_contaminants.nf index bbfb66fd..09ad0162 100644 --- a/modules/local/bowtie_map_contaminants.nf +++ b/modules/local/bowtie_map_contaminants.nf @@ -1,7 +1,7 @@ process BOWTIE_MAP_CONTAMINANTS { label 'process_medium' - conda (params.enable_conda ? 'bowtie2=2.4.5' : null) + conda 'bowtie2=2.4.5' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/bowtie2:2.4.5--py39hd2f7db1_2' : 'quay.io/biocontainers/bowtie2:2.4.5--py36hfca12d5_2' }" diff --git a/modules/local/bowtie_map_mirna.nf b/modules/local/bowtie_map_mirna.nf index 82d7acf8..8202838f 100644 --- a/modules/local/bowtie_map_mirna.nf +++ b/modules/local/bowtie_map_mirna.nf @@ -2,7 +2,7 @@ process BOWTIE_MAP_SEQ { tag "$meta.id" label 'process_medium' - conda (params.enable_conda ? 'bowtie=1.3.0-2 bioconda::samtools=1.13' : null) + conda 'bowtie=1.3.0-2 bioconda::samtools=1.13' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/mulled-v2-ffbf83a6b0ab6ec567a336cf349b80637135bca3:40128b496751b037e2bd85f6789e83d4ff8a4837-0' : 'quay.io/biocontainers/mulled-v2-ffbf83a6b0ab6ec567a336cf349b80637135bca3:40128b496751b037e2bd85f6789e83d4ff8a4837-0' }" diff --git a/modules/local/bowtie_mirna.nf b/modules/local/bowtie_mirna.nf index 0be5888b..601c9f43 100644 --- a/modules/local/bowtie_mirna.nf +++ b/modules/local/bowtie_mirna.nf @@ -1,7 +1,7 @@ process INDEX_MIRNA { label 'process_medium' - conda (params.enable_conda ? 'bioconda::bowtie=1.3.0-2' : null) + conda 'bioconda::bowtie=1.3.0-2' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/bowtie%3A1.3.1--py39hd400a0c_2' : 'quay.io/biocontainers/bowtie:1.3.1--py310h4070885_4' }" diff --git a/modules/local/datatable_merge.nf b/modules/local/datatable_merge.nf index 8a1ed3b5..5b238c06 100644 --- a/modules/local/datatable_merge.nf +++ b/modules/local/datatable_merge.nf @@ -1,7 +1,7 @@ process TABLE_MERGE { label 'process_medium' - conda (params.enable_conda ? 'conda-base::r-data.table=1.12.2' : null) + conda 'conda-base::r-data.table=1.12.2' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/r-data.table:1.12.2' : 'quay.io/biocontainers/r-data.table:1.12.2' }" diff --git a/modules/local/edger_qc.nf b/modules/local/edger_qc.nf index 023f70be..0d8efe64 100644 --- a/modules/local/edger_qc.nf +++ b/modules/local/edger_qc.nf @@ -1,7 +1,7 @@ process EDGER_QC { label 'process_medium' - conda (params.enable_conda ? 'bioconda::bioconductor-limma=3.50.0 bioconda::bioconductor-edger=3.36.0 conda-forge::r-data.table=1.14.2 conda-forge::r-gplots=3.1.1 conda-forge::r-statmod=1.4.36' : null) + conda 'bioconda::bioconductor-limma=3.50.0 bioconda::bioconductor-edger=3.36.0 conda-forge::r-data.table=1.14.2 conda-forge::r-gplots=3.1.1 conda-forge::r-statmod=1.4.36' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/mulled-v2-419bd7f10b2b902489ac63bbaafc7db76f8e0ae1:709335c37934db1b481054cbec637c6e5b5971cb-0' : 'quay.io/biocontainers/mulled-v2-419bd7f10b2b902489ac63bbaafc7db76f8e0ae1:709335c37934db1b481054cbec637c6e5b5971cb-0' }" diff --git a/modules/local/filter_stats.nf b/modules/local/filter_stats.nf index 4d94d9b1..c9336f22 100644 --- a/modules/local/filter_stats.nf +++ b/modules/local/filter_stats.nf @@ -1,7 +1,7 @@ process FILTER_STATS { label 'process_medium' - conda (params.enable_conda ? 'bowtie2=2.4.5' : null) + conda 'bowtie2=2.4.5' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/bowtie2:2.4.5--py39hd2f7db1_2' : 'quay.io/biocontainers/bowtie2:2.4.5--py36hfca12d5_2' }" diff --git a/modules/local/format_fasta_mirna.nf b/modules/local/format_fasta_mirna.nf index d19901fd..2c39c0aa 100644 --- a/modules/local/format_fasta_mirna.nf +++ b/modules/local/format_fasta_mirna.nf @@ -4,7 +4,7 @@ process FORMAT_FASTA_MIRNA { tag "$fasta" label 'process_medium' - conda (params.enable_conda ? 'bioconda::fastx_toolkit=0.0.14-9' : null) + conda 'bioconda::fastx_toolkit=0.0.14-9' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/fastx_toolkit:0.0.14--he1b5a44_8' : 'quay.io/biocontainers/fastx_toolkit:0.0.14--he1b5a44_8' }" diff --git a/modules/local/mirdeep2_mapper.nf b/modules/local/mirdeep2_mapper.nf index 7d90712b..2293ef87 100644 --- a/modules/local/mirdeep2_mapper.nf +++ b/modules/local/mirdeep2_mapper.nf @@ -4,7 +4,7 @@ process MIRDEEP2_MAPPER { label 'process_medium' tag "$meta.id" - conda (params.enable_conda ? 'bioconda::mirdeep2=2.0.1' : null) + conda 'bioconda::mirdeep2=2.0.1' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/mirdeep2:2.0.1.3--hdfd78af_1' : 'quay.io/biocontainers/mirdeep2:2.0.1.3--hdfd78af_1' }" diff --git a/modules/local/mirdeep2_prepare.nf b/modules/local/mirdeep2_prepare.nf index 9fcc2ed5..3d117d4a 100644 --- a/modules/local/mirdeep2_prepare.nf +++ b/modules/local/mirdeep2_prepare.nf @@ -3,7 +3,7 @@ process MIRDEEP2_PIGZ { tag "$meta.id" // TODO maybe create a mulled container and uncompress within mirdeep2_mapper? - conda (params.enable_conda ? 'bioconda::bioconvert=0.4.3' : null) + conda 'bioconda::bioconvert=0.4.3' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/bioconvert:0.4.3--py_0' : 'quay.io/biocontainers/bioconvert:0.4.3--py_0' }" diff --git a/modules/local/mirdeep2_run.nf b/modules/local/mirdeep2_run.nf index ee4cfc0d..2035658c 100644 --- a/modules/local/mirdeep2_run.nf +++ b/modules/local/mirdeep2_run.nf @@ -4,7 +4,7 @@ process MIRDEEP2_RUN { label 'process_medium' errorStrategy 'ignore' - conda (params.enable_conda ? 'bioconda::mirdeep2=2.0.1' : null) + conda 'bioconda::mirdeep2=2.0.1' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/mirdeep2:2.0.1.3--hdfd78af_1' : 'quay.io/biocontainers/mirdeep2:2.0.1.3--hdfd78af_1' }" diff --git a/modules/local/mirtop_quant.nf b/modules/local/mirtop_quant.nf index b6f72a89..c4e76a3c 100644 --- a/modules/local/mirtop_quant.nf +++ b/modules/local/mirtop_quant.nf @@ -1,7 +1,7 @@ process MIRTOP_QUANT { label 'process_medium' - conda (params.enable_conda ? 'mirtop=0.4.25 bioconda::samtools=1.15.1 conda-base::r-base=4.1.1 conda-base::r-data.table=1.14.2' : null) + conda 'mirtop=0.4.25 bioconda::samtools=1.15.1 conda-base::r-base=4.1.1 conda-base::r-data.table=1.14.2' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/mulled-v2-0c13ef770dd7cc5c76c2ce23ba6669234cf03385:63be019f50581cc5dfe4fc0f73ae50f2d4d661f7-0' : 'quay.io/biocontainers/mulled-v2-0c13ef770dd7cc5c76c2ce23ba6669234cf03385:63be019f50581cc5dfe4fc0f73ae50f2d4d661f7-0' }" diff --git a/modules/local/mirtrace.nf b/modules/local/mirtrace.nf index 8683d5ce..8c2102f6 100644 --- a/modules/local/mirtrace.nf +++ b/modules/local/mirtrace.nf @@ -1,7 +1,7 @@ process MIRTRACE_RUN { label 'process_medium' - conda (params.enable_conda ? 'bioconda::mirtrace=1.0.1' : null) + conda 'bioconda::mirtrace=1.0.1' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/mirtrace:1.0.1--hdfd78af_1' : 'quay.io/biocontainers/mirtrace:1.0.1--hdfd78af_1' }" diff --git a/modules/local/parse_fasta_mirna.nf b/modules/local/parse_fasta_mirna.nf index e09242eb..5418f597 100644 --- a/modules/local/parse_fasta_mirna.nf +++ b/modules/local/parse_fasta_mirna.nf @@ -1,7 +1,7 @@ process PARSE_FASTA_MIRNA { label 'process_medium' - conda (params.enable_conda ? 'bioconda::seqkit=2.3.1' : null) + conda 'bioconda::seqkit=2.3.1' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/seqkit:2.3.1--h9ee0642_0' : 'quay.io/biocontainers/seqkit:2.3.1--h9ee0642_0' }" diff --git a/modules/local/seqcluster_collapse.nf b/modules/local/seqcluster_collapse.nf index 46239775..36645ee1 100644 --- a/modules/local/seqcluster_collapse.nf +++ b/modules/local/seqcluster_collapse.nf @@ -2,7 +2,7 @@ process SEQCLUSTER_SEQUENCES { label 'process_medium' tag "$meta.id" - conda (params.enable_conda ? 'bioconda::seqcluster=1.2.9-0' : null) + conda 'bioconda::seqcluster=1.2.9-0' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/seqcluster:1.2.9--pyh5e36f6f_0' : 'quay.io/biocontainers/seqcluster:1.2.8--pyh5e36f6f_0' }" diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 61e87545..3176aead 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -238,8 +238,10 @@ workflow SMRNASEQ { ch_multiqc_logo.toList() ) multiqc_report = MULTIQC.out.report.toList() + } } + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ COMPLETION EMAIL AND SUMMARY From 33de978788ed4dfdf0d4f51aa15ce6d3fce6f64a Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Tue, 7 Feb 2023 21:38:15 +0100 Subject: [PATCH 112/215] Apply suggestions from code review Co-authored-by: Maxime U. Garcia --- conf/modules.config | 2 +- nextflow.config | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 64d851f6..0c5365fb 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -104,7 +104,7 @@ if (!params.skip_fastp) { params.three_prime_clip_r1 > 0 ? "--trim_tail1 ${params.three_prime_clip_r1}" : "", // Remove bp from the 3' end of read 1 AFTER adapter/quality trimming has been performed. params.fastp_min_length > 0 ? "-l ${params.fastp_min_length}" : "", params.fastp_max_length > 0 ? "--max_len1 ${params.fastp_max_length}" : "", - params.three_prime_adapter == null ? '' : "--adapter_sequence ${params.three_prime_adapter}", + params.three_prime_adapter == null ? '' : "--adapter_sequence ${params.three_prime_adapter}" ].join(" ").trim() publishDir = [ [ diff --git a/nextflow.config b/nextflow.config index fbe64350..1df2f6de 100644 --- a/nextflow.config +++ b/nextflow.config @@ -141,9 +141,6 @@ profiles { arm { docker.runOptions = '-u $(id -u):$(id -g) --platform=linux/amd64' } - arm { - docker.runOptions = '-u $(id -u):$(id -g) --platform=linux/amd64' - } singularity { singularity.enabled = true singularity.autoMounts = true @@ -224,7 +221,7 @@ dag { manifest { name = 'nf-core/smrnaseq' - author = """P. Ewels, C. Wang, R. Hammarén, L. Pantano""" + author = """P. Ewels, C. Wang, R. Hammarén, L. Pantano, A. Peltzer""" homePage = 'https://github.com/nf-core/smrnaseq' description = """Small RNA-Seq Best Practice Analysis Pipeline.""" mainScript = 'main.nf' From f81ddb4871882c32e92b9172efbf85295962697c Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Tue, 7 Feb 2023 20:41:20 +0000 Subject: [PATCH 113/215] Redid licence, to match lint --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 499134b1..d6a83450 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) P. Ewels, C. Wang, R. Hammarén, L. Pantano +Copyright (c) P. Ewels, C. Wang, R. Hammarén, L. Pantano, A. Peltzer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 8810b086b2956dc25187a915e1c468b48d1d063b Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 17 Feb 2023 22:36:39 +0100 Subject: [PATCH 114/215] Fix for edgeR QC Co-authored-by: Sean Corbett @sean-at-tessera --- bin/edgeR_miRBase.r | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/edgeR_miRBase.r b/bin/edgeR_miRBase.r index d6647a31..5be691fc 100755 --- a/bin/edgeR_miRBase.r +++ b/bin/edgeR_miRBase.r @@ -43,7 +43,7 @@ for (i in 1:2) { # Only subset if at least one sample is remaining nr_keep <- sum(row_sub) if (nr_keep > 0){ - data<-data[!row_sub,] + data<-data[!row_sub,, drop=FALSE] } #Also check for colSums > 0, otherwise DGEList will fail if samples have entirely colSum == 0 #Fixes #134 drop_colsum_zero <- (colSums(data, na.rm=T) != 0) # T if colSum is not 0, F otherwise From 1b1bea521fb59dfec64e09783ecab191d52c0832 Mon Sep 17 00:00:00 2001 From: Barry digby Date: Sat, 18 Feb 2023 15:22:38 +0000 Subject: [PATCH 115/215] FASTP fix --- subworkflows/nf-core/fastqc_fastp.nf | 2 +- workflows/smrnaseq.nf | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/subworkflows/nf-core/fastqc_fastp.nf b/subworkflows/nf-core/fastqc_fastp.nf index 5cec3149..5eb2b545 100644 --- a/subworkflows/nf-core/fastqc_fastp.nf +++ b/subworkflows/nf-core/fastqc_fastp.nf @@ -28,7 +28,7 @@ String getFastpAdapterSequence(json_file){ workflow FASTQC_FASTP { take: reads // channel: [ val(meta), [ reads ] ] - adapter_list // String [path/to/adapters.fa] + adapter_list // channel: [ path/to/adapters.fa ] save_trimmed_fail // value: boolean save_merged // value: boolean diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 2a63ee64..dd52ea2f 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -38,7 +38,7 @@ ch_multiqc_config = Channel.fromPath("$projectDir/assets/multiqc_config ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath( params.multiqc_config, checkIfExists: true ) : Channel.empty() ch_multiqc_logo = params.multiqc_logo ? Channel.fromPath( params.multiqc_logo, checkIfExists: true ) : Channel.empty() ch_multiqc_custom_methods_description = params.multiqc_methods_description ? file(params.multiqc_methods_description, checkIfExists: true) : file("$projectDir/assets/methods_description_template.yml", checkIfExists: true) -ch_fastp_adapters = Channel.fromPath(params.fastp_known_mirna_adapters, checkIfExists: true) +ch_fastp_adapters = Channel.fromPath(params.fastp_known_mirna_adapters, checkIfExists: true).collect() // collect to consume for all incoming samples to FASTP /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -150,7 +150,7 @@ workflow SMRNASEQ { } else{ //TODO - rob? :-) - + } From 2ceaa97c61b29bc0377a1da66fb63888fa4e5726 Mon Sep 17 00:00:00 2001 From: Denis O'Meally Date: Sun, 19 Feb 2023 20:08:56 -0800 Subject: [PATCH 116/215] mirtrace fix --- modules/local/mirtrace.nf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/local/mirtrace.nf b/modules/local/mirtrace.nf index 8c2102f6..90dbd5f1 100644 --- a/modules/local/mirtrace.nf +++ b/modules/local/mirtrace.nf @@ -21,6 +21,7 @@ process MIRTRACE_RUN { def primer = meta.adapter ? "--adapter ${meta.adapter}" : "" def protocol = params.protocol == 'custom' ? '' : "--protocol $params.protocol" def java_mem = '' + def prefix = "${meta.id}" if(task.memory){ tmem = task.memory.toBytes() java_mem = "-Xms${tmem} -Xmx${tmem}" @@ -30,7 +31,7 @@ process MIRTRACE_RUN { for i in $reads do path=\$(realpath \${i}) - prefix=\$(echo \${i} | sed -e 's/.gz//' -e 's/.fastq//' -e 's/.fq//' -e 's/_val_1//' -e 's/_trimmed//' -e 's/_R1//' -e 's/.R1//') + prefix=$prefix echo \$path","\$prefix done > mirtrace_config From 922ba8aa8dc25ca22ede14d801d6a2bd7c2d60d2 Mon Sep 17 00:00:00 2001 From: Denis OMeally Date: Mon, 20 Feb 2023 12:30:25 -0800 Subject: [PATCH 117/215] Update CHANGELOG.md Fix #220 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a881780..953f295a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Dev +- [[#220](https://github.com/nf-core/smrnaseq/issues/220)] - Fixed an issue where miRTrace reports fastq basename instead of sample ID - [[#208](https://github.com/nf-core/smrnaseq/issues/208)] - Fixed usability of `--skip_qc` parameter - Updated FASTP module to allow direct addition of adapter_fasta file to it - [[#205](https://github.com/nf-core/smrnaseq/issues/205)] - Fix mirTrace Report to be a single report again instead of per sample reports From fb26c3dcdaf5df3e3866b0a14f18a5cccc84c467 Mon Sep 17 00:00:00 2001 From: MagdalenaZZ Date: Thu, 30 Mar 2023 15:37:26 +0100 Subject: [PATCH 118/215] Update check_samplesheet.py Change eprint to print_error on line 60, to remain consistent with error messaging throughout, and to remove dependency on eprint. --- bin/check_samplesheet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/check_samplesheet.py b/bin/check_samplesheet.py index 24252b4b..2ed13416 100755 --- a/bin/check_samplesheet.py +++ b/bin/check_samplesheet.py @@ -57,7 +57,7 @@ def check_samplesheet(file_in, file_out): header = [x.strip('"') for x in fin.readline().strip().split(",")] if any([item not in header for item in HEADER]): missing = [item for item in HEADER if item not in header] - eprint("ERROR: Please check samplesheet header. Missing columns: '{}'".format(",".join(missing))) + print_error("ERROR: Please check samplesheet header. Missing columns: '{}'".format(",".join(missing))) sys.exit(1) ## Check sample entries From b7321042e9bf30429add9457a899c9c1251647d2 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Tue, 4 Apr 2023 14:23:30 +0200 Subject: [PATCH 119/215] Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69a23be8..d0cd1f34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ 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). +## dev + +- Fix issue in Samplesheet checking + ## [v2.1.0](https://github.com/nf-core/smrnaseq/releases/tag/2.1.0) - 2022-10-25 Maroon Tin Dalmatian ### Enhancements & fixes From b9a7fcedef61cb5588afca4a1aaec50097a07750 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Wed, 19 Apr 2023 14:05:46 +0100 Subject: [PATCH 120/215] Update all nf-core/modules --- modules.json | 14 +++++++------- .../nf-core/custom/dumpsoftwareversions/main.nf | 6 +++--- .../templates/dumpsoftwareversions.py | 0 modules/nf-core/fastp/main.nf | 1 - modules/nf-core/fastp/meta.yml | 2 +- modules/nf-core/samtools/flagstat/meta.yml | 2 +- modules/nf-core/samtools/idxstats/meta.yml | 2 +- modules/nf-core/samtools/index/meta.yml | 2 +- modules/nf-core/samtools/sort/meta.yml | 2 +- modules/nf-core/samtools/stats/meta.yml | 14 +++++++------- 10 files changed, 22 insertions(+), 23 deletions(-) mode change 100755 => 100644 modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py diff --git a/modules.json b/modules.json index de67a7e7..a4d925ab 100644 --- a/modules.json +++ b/modules.json @@ -12,12 +12,12 @@ }, "custom/dumpsoftwareversions": { "branch": "master", - "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", + "git_sha": "7101db4432d3268b7fcb5b8f75fa0a022dc5561b", "installed_by": ["modules"] }, "fastp": { "branch": "master", - "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", + "git_sha": "20a508676f40d0fd3f911ac595af91ec845704c4", "installed_by": ["modules"] }, "fastqc": { @@ -32,27 +32,27 @@ }, "samtools/flagstat": { "branch": "master", - "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", + "git_sha": "0f8a77ff00e65eaeebc509b8156eaa983192474b", "installed_by": ["modules"] }, "samtools/idxstats": { "branch": "master", - "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", + "git_sha": "0f8a77ff00e65eaeebc509b8156eaa983192474b", "installed_by": ["modules"] }, "samtools/index": { "branch": "master", - "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", + "git_sha": "0f8a77ff00e65eaeebc509b8156eaa983192474b", "installed_by": ["modules"] }, "samtools/sort": { "branch": "master", - "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", + "git_sha": "0f8a77ff00e65eaeebc509b8156eaa983192474b", "installed_by": ["modules"] }, "samtools/stats": { "branch": "master", - "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", + "git_sha": "0f8a77ff00e65eaeebc509b8156eaa983192474b", "installed_by": ["modules"] } } diff --git a/modules/nf-core/custom/dumpsoftwareversions/main.nf b/modules/nf-core/custom/dumpsoftwareversions/main.nf index 3df21765..800a6099 100644 --- a/modules/nf-core/custom/dumpsoftwareversions/main.nf +++ b/modules/nf-core/custom/dumpsoftwareversions/main.nf @@ -2,10 +2,10 @@ process CUSTOM_DUMPSOFTWAREVERSIONS { label 'process_single' // Requires `pyyaml` which does not have a dedicated container but is in the MultiQC container - conda "bioconda::multiqc=1.13" + conda "bioconda::multiqc=1.14" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.13--pyhdfd78af_0' : - 'quay.io/biocontainers/multiqc:1.13--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/multiqc:1.14--pyhdfd78af_0' : + 'quay.io/biocontainers/multiqc:1.14--pyhdfd78af_0' }" input: path versions diff --git a/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py old mode 100755 new mode 100644 diff --git a/modules/nf-core/fastp/main.nf b/modules/nf-core/fastp/main.nf index e1ed9288..5eeb9b09 100644 --- a/modules/nf-core/fastp/main.nf +++ b/modules/nf-core/fastp/main.nf @@ -58,7 +58,6 @@ process FASTP { [ ! -f ${prefix}.fastq.gz ] && ln -sf $reads ${prefix}.fastq.gz fastp \\ - --stdout \\ --in1 ${prefix}.fastq.gz \\ --out1 ${prefix}.fastp.fastq.gz \\ --thread $task.cpus \\ diff --git a/modules/nf-core/fastp/meta.yml b/modules/nf-core/fastp/meta.yml index 6f6fad74..197ea7ca 100644 --- a/modules/nf-core/fastp/meta.yml +++ b/modules/nf-core/fastp/meta.yml @@ -9,7 +9,7 @@ tools: description: | A tool designed to provide fast all-in-one preprocessing for FastQ files. This tool is developed in C++ with multithreading supported to afford high performance. documentation: https://github.com/OpenGene/fastp - doi: https://doi.org/10.1093/bioinformatics/bty560 + doi: 10.1093/bioinformatics/bty560 licence: ["MIT"] input: - meta: diff --git a/modules/nf-core/samtools/flagstat/meta.yml b/modules/nf-core/samtools/flagstat/meta.yml index 95269063..954225df 100644 --- a/modules/nf-core/samtools/flagstat/meta.yml +++ b/modules/nf-core/samtools/flagstat/meta.yml @@ -14,7 +14,7 @@ tools: short DNA sequence read alignments in the SAM, BAM and CRAM formats, written by Heng Li. These files are generated as output by short read aligners like BWA. homepage: http://www.htslib.org/ - documentation: hhttp://www.htslib.org/doc/samtools.html + documentation: http://www.htslib.org/doc/samtools.html doi: 10.1093/bioinformatics/btp352 licence: ["MIT"] input: diff --git a/modules/nf-core/samtools/idxstats/meta.yml b/modules/nf-core/samtools/idxstats/meta.yml index 3710ab88..dda87e1e 100644 --- a/modules/nf-core/samtools/idxstats/meta.yml +++ b/modules/nf-core/samtools/idxstats/meta.yml @@ -15,7 +15,7 @@ tools: short DNA sequence read alignments in the SAM, BAM and CRAM formats, written by Heng Li. These files are generated as output by short read aligners like BWA. homepage: http://www.htslib.org/ - documentation: hhttp://www.htslib.org/doc/samtools.html + documentation: http://www.htslib.org/doc/samtools.html doi: 10.1093/bioinformatics/btp352 licence: ["MIT"] input: diff --git a/modules/nf-core/samtools/index/meta.yml b/modules/nf-core/samtools/index/meta.yml index e5cadbc2..8bd2fa6f 100644 --- a/modules/nf-core/samtools/index/meta.yml +++ b/modules/nf-core/samtools/index/meta.yml @@ -12,7 +12,7 @@ tools: short DNA sequence read alignments in the SAM, BAM and CRAM formats, written by Heng Li. These files are generated as output by short read aligners like BWA. homepage: http://www.htslib.org/ - documentation: hhttp://www.htslib.org/doc/samtools.html + documentation: http://www.htslib.org/doc/samtools.html doi: 10.1093/bioinformatics/btp352 licence: ["MIT"] input: diff --git a/modules/nf-core/samtools/sort/meta.yml b/modules/nf-core/samtools/sort/meta.yml index 09289751..07328431 100644 --- a/modules/nf-core/samtools/sort/meta.yml +++ b/modules/nf-core/samtools/sort/meta.yml @@ -12,7 +12,7 @@ tools: short DNA sequence read alignments in the SAM, BAM and CRAM formats, written by Heng Li. These files are generated as output by short read aligners like BWA. homepage: http://www.htslib.org/ - documentation: hhttp://www.htslib.org/doc/samtools.html + documentation: http://www.htslib.org/doc/samtools.html doi: 10.1093/bioinformatics/btp352 licence: ["MIT"] input: diff --git a/modules/nf-core/samtools/stats/meta.yml b/modules/nf-core/samtools/stats/meta.yml index cac50b1c..1d68a5d8 100644 --- a/modules/nf-core/samtools/stats/meta.yml +++ b/modules/nf-core/samtools/stats/meta.yml @@ -13,7 +13,7 @@ tools: short DNA sequence read alignments in the SAM, BAM and CRAM formats, written by Heng Li. These files are generated as output by short read aligners like BWA. homepage: http://www.htslib.org/ - documentation: hhttp://www.htslib.org/doc/samtools.html + documentation: http://www.htslib.org/doc/samtools.html doi: 10.1093/bioinformatics/btp352 licence: ["MIT"] input: @@ -23,13 +23,13 @@ input: Groovy Map containing sample information e.g. [ id:'test', single_end:false ] - input: - type: file - description: BAM/CRAM file from alignment - pattern: "*.{bam,cram}" + type: file + description: BAM/CRAM file from alignment + pattern: "*.{bam,cram}" - input_index: - type: file - description: BAI/CRAI file from alignment - pattern: "*.{bai,crai}" + type: file + description: BAI/CRAI file from alignment + pattern: "*.{bai,crai}" - fasta: type: optional file description: Reference file the CRAM was created with From 70071d73e09a90f558608d595693858c78ba5049 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Mon, 24 Apr 2023 09:31:29 +0100 Subject: [PATCH 121/215] Bump pipeline version to 2.2.0 --- CHANGELOG.md | 2 +- nextflow.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc82b1f8..61f0e022 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 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). -## Dev +## [v2.2.0](https://github.com/nf-core/smrnaseq/releases/tag/2.2.0) - 2023-04-25 - [[#220](https://github.com/nf-core/smrnaseq/issues/220)] - Fixed an issue where miRTrace reports fastq basename instead of sample ID - [[#208](https://github.com/nf-core/smrnaseq/issues/208)] - Fixed usability of `--skip_qc` parameter diff --git a/nextflow.config b/nextflow.config index 1df2f6de..c53e2a86 100644 --- a/nextflow.config +++ b/nextflow.config @@ -226,7 +226,7 @@ manifest { description = """Small RNA-Seq Best Practice Analysis Pipeline.""" mainScript = 'main.nf' nextflowVersion = '!>=22.10.1' - version = '2.1.1dev' + version = '2.2.0' doi = '' } From 2625e11d5469ca802a5367c12723c1a8b755a2cd Mon Sep 17 00:00:00 2001 From: Rob Syme Date: Mon, 24 Apr 2023 23:40:35 -0400 Subject: [PATCH 122/215] Remove skip_qc parameter --- conf/modules.config | 2 +- nextflow.config | 1 - nextflow_schema.json | 5 ----- workflows/smrnaseq.nf | 41 +++++++++++++++-------------------------- 4 files changed, 16 insertions(+), 33 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 0c5365fb..8644dd3c 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -87,7 +87,7 @@ process { } } -if (!(params.skip_fastqc || params.skip_qc)) { +if (!(params.skip_fastqc)) { process { withName: '.*:FASTQC_FASTP:FASTQC_.*' { ext.args = '--quiet' diff --git a/nextflow.config b/nextflow.config index c53e2a86..7b6f2d8e 100644 --- a/nextflow.config +++ b/nextflow.config @@ -36,7 +36,6 @@ params { fastp_min_length = 17 fastp_known_mirna_adapters = "$projectDir/assets/known_adapters.fa" save_trimmed_fail = false - skip_qc = false skip_fastqc = false skip_multiqc = false skip_mirdeep = false diff --git a/nextflow_schema.json b/nextflow_schema.json index f6911a15..213199c1 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -249,11 +249,6 @@ "description": "Switches to skip specific pipeline steps, if desired.", "fa_icon": "fas fa-fast-forward", "properties": { - "skip_qc": { - "type": "boolean", - "fa_icon": "fas fa-fast-forward", - "description": "Skip all QC steps" - }, "skip_fastqc": { "type": "boolean", "fa_icon": "fas fa-fast-forward", diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index dd52ea2f..c3aaa55f 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -125,7 +125,6 @@ workflow SMRNASEQ { // SUBWORKFLOW: Read QC and trim adapters // - if(!params.skip_qc){ FASTQC_FASTP ( ch_cat_fastq, ch_fastp_adapters, @@ -133,28 +132,21 @@ workflow SMRNASEQ { false ) ch_versions = ch_versions.mix(FASTQC_FASTP.out.versions) - reads_for_mirna = FASTQC_FASTP.out.reads - + ch_reads = FASTQC_FASTP.out.reads // // SUBWORKFLOW: mirtrace QC // - ch_outputs_for_mirtrace = FASTQC_FASTP.out.adapterseq + FASTQC_FASTP.out.adapterseq .join( ch_cat_fastq ) .map { meta, adapterseq, fastq -> [meta + [adapter:adapterseq], fastq] } .collect() + .set { ch_mitrace_inputs } - MIRTRACE(ch_outputs_for_mirtrace) + MIRTRACE(ch_mitrace_inputs) ch_versions = ch_versions.mix(MIRTRACE.out.versions.ifEmpty(null)) - } else{ - //TODO - rob? :-) - - } - - - // // SUBWORKFLOW: remove contaminants from reads @@ -172,10 +164,8 @@ workflow SMRNASEQ { FASTQC_FASTP.out.reads ) - reads_for_mirna = CONTAMINANT_FILTER.out.filtered_reads + contamination_stats = CONTAMINANT_FILTER.out.filter_stats ch_versions = ch_versions.mix(CONTAMINANT_FILTER.out.versions) - CONTAMINANT_FILTER.out.filter_stats - .set { contamination_stats } } @@ -183,7 +173,7 @@ workflow SMRNASEQ { reference_mature, reference_hairpin, mirna_gtf, - reads_for_mirna + CONTAMINANT_FILTER.out.filtered_reads ) ch_versions = ch_versions.mix(MIRNA_QUANT.out.versions.ifEmpty(null)) @@ -229,9 +219,8 @@ workflow SMRNASEQ { ch_multiqc_files = Channel.empty() ch_multiqc_files = ch_multiqc_files.mix(CUSTOM_DUMPSOFTWAREVERSIONS.out.mqc_yml.collect()) ch_multiqc_files = ch_multiqc_files.mix(ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) - - ch_multiqc_files = ch_multiqc_files.mix(FASTQC_FASTP.out.fastqc_raw_zip.collect{it[1]}.ifEmpty([])), - ch_multiqc_files = ch_multiqc_files.mix(FASTQC_FASTP.out.trim_json.collect{it[1]}.ifEmpty([])), + ch_multiqc_files = ch_multiqc_files.mix(FASTQC_FASTP.out.fastqc_raw_zip.collect{it[1]}.ifEmpty([])) + ch_multiqc_files = ch_multiqc_files.mix(FASTQC_FASTP.out.trim_json.collect{it[1]}.ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(contamination_stats.collect().ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(MIRNA_QUANT.out.mature_stats.collect({it[1]}).ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(MIRNA_QUANT.out.hairpin_stats.collect({it[1]}).ifEmpty([])) @@ -239,13 +228,13 @@ workflow SMRNASEQ { ch_multiqc_files = ch_multiqc_files.mix(MIRNA_QUANT.out.mirtop_logs.collect().ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(MIRTRACE.out.results.collect().ifEmpty([])) - MULTIQC ( - ch_multiqc_files.collect(), - ch_multiqc_config.toList(), - ch_multiqc_custom_config.toList(), - ch_multiqc_logo.toList() - ) - multiqc_report = MULTIQC.out.report.toList() + MULTIQC ( + ch_multiqc_files.collect(), + ch_multiqc_config.toList(), + ch_multiqc_custom_config.toList(), + ch_multiqc_logo.toList() + ) + multiqc_report = MULTIQC.out.report.toList() } } From e64be28c92d31cb5c5e75244caa62d785d6e0182 Mon Sep 17 00:00:00 2001 From: Rob Syme Date: Tue, 25 Apr 2023 05:36:16 +0000 Subject: [PATCH 123/215] Run mirtrace once for each adapter --- CHANGELOG.md | 2 ++ modules/local/mirtrace.nf | 16 +++++++--------- subworkflows/local/mirtrace.nf | 3 ++- workflows/smrnaseq.nf | 15 ++++++--------- 4 files changed, 17 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61f0e022..b5ff257a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ 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). +- Group samples by adapter sequence before running mirtrace. + ## [v2.2.0](https://github.com/nf-core/smrnaseq/releases/tag/2.2.0) - 2023-04-25 - [[#220](https://github.com/nf-core/smrnaseq/issues/220)] - Fixed an issue where miRTrace reports fastq basename instead of sample ID diff --git a/modules/local/mirtrace.nf b/modules/local/mirtrace.nf index 90dbd5f1..1815bf1b 100644 --- a/modules/local/mirtrace.nf +++ b/modules/local/mirtrace.nf @@ -7,7 +7,7 @@ process MIRTRACE_RUN { 'quay.io/biocontainers/mirtrace:1.0.1--hdfd78af_1' }" input: - tuple val(meta), path(reads) + tuple val(adapter), val(ids), path(reads) output: path "mirtrace/*" , emit: mirtrace @@ -18,22 +18,20 @@ process MIRTRACE_RUN { script: // mirtrace protocol defaults to 'params.protocol' if not set - def primer = meta.adapter ? "--adapter ${meta.adapter}" : "" + def primer = adapter ? "--adapter ${adapter}" : "" def protocol = params.protocol == 'custom' ? '' : "--protocol $params.protocol" def java_mem = '' - def prefix = "${meta.id}" if(task.memory){ tmem = task.memory.toBytes() java_mem = "-Xms${tmem} -Xmx${tmem}" } + def config_lines = [ids,reads] + .transpose() + .collect({ id, path -> "echo '${path},${id}' >> mirtrace_config" }) """ export mirtracejar=\$(dirname \$(which mirtrace)) - for i in $reads - do - path=\$(realpath \${i}) - prefix=$prefix - echo \$path","\$prefix - done > mirtrace_config + + ${config_lines.join("\n ")} java $java_mem -jar \$mirtracejar/mirtrace.jar --mirtrace-wrapper-name mirtrace qc \\ --species $params.mirtrace_species \\ diff --git a/subworkflows/local/mirtrace.nf b/subworkflows/local/mirtrace.nf index 38d51975..566b7a1b 100644 --- a/subworkflows/local/mirtrace.nf +++ b/subworkflows/local/mirtrace.nf @@ -6,10 +6,11 @@ include { MIRTRACE_RUN } from '../../modules/local/mirtrace' workflow MIRTRACE { take: - reads // channel: [ val(meta), [ reads ] ] + reads // channel: [ val(adapterseq), [ val(ids) ], [ path(reads) ] ] main: reads + | map { adapterseq, ids, read_collection -> [adapterseq, ids, read_collection*.first()]} | MIRTRACE_RUN emit: diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index c3aaa55f..5b46b3db 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -139,11 +139,10 @@ workflow SMRNASEQ { // FASTQC_FASTP.out.adapterseq .join( ch_cat_fastq ) - .map { meta, adapterseq, fastq -> [meta + [adapter:adapterseq], fastq] } - .collect() + .map { meta, adapterseq, fastq -> [adapterseq, meta.id, fastq] } + .groupTuple() .set { ch_mitrace_inputs } - MIRTRACE(ch_mitrace_inputs) ch_versions = ch_versions.mix(MIRTRACE.out.versions.ifEmpty(null)) @@ -173,7 +172,7 @@ workflow SMRNASEQ { reference_mature, reference_hairpin, mirna_gtf, - CONTAMINANT_FILTER.out.filtered_reads + contamination_stats ) ch_versions = ch_versions.mix(MIRNA_QUANT.out.versions.ifEmpty(null)) @@ -182,10 +181,8 @@ workflow SMRNASEQ { // genome_stats = Channel.empty() if (params.fasta){ - ch_fasta = file(params.fasta) - GENOME_QUANT ( ch_fasta, params.bowtie_index, MIRNA_QUANT.out.unmapped ) - GENOME_QUANT.out.stats - .set { genome_stats } + GENOME_QUANT ( file(params.fasta), params.bowtie_index, MIRNA_QUANT.out.unmapped ) + genome_stats = GENOME_QUANT.out.stats ch_versions = ch_versions.mix(GENOME_QUANT.out.versions) if (!params.skip_mirdeep) { @@ -222,9 +219,9 @@ workflow SMRNASEQ { ch_multiqc_files = ch_multiqc_files.mix(FASTQC_FASTP.out.fastqc_raw_zip.collect{it[1]}.ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(FASTQC_FASTP.out.trim_json.collect{it[1]}.ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(contamination_stats.collect().ifEmpty([])) + ch_multiqc_files = ch_multiqc_files.mix(genome_stats.collect({it[1]}).ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(MIRNA_QUANT.out.mature_stats.collect({it[1]}).ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(MIRNA_QUANT.out.hairpin_stats.collect({it[1]}).ifEmpty([])) - ch_multiqc_files = ch_multiqc_files.mix(genome_stats.collect({it[1]}).ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(MIRNA_QUANT.out.mirtop_logs.collect().ifEmpty([])) ch_multiqc_files = ch_multiqc_files.mix(MIRTRACE.out.results.collect().ifEmpty([])) From f6e87e4c11fe1a0d8e6353aa29cad2cbe842d915 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Tue, 25 Apr 2023 10:53:56 +0100 Subject: [PATCH 124/215] Update CHANGELOG.md --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5ff257a..83024af7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,6 @@ 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). -- Group samples by adapter sequence before running mirtrace. - ## [v2.2.0](https://github.com/nf-core/smrnaseq/releases/tag/2.2.0) - 2023-04-25 - [[#220](https://github.com/nf-core/smrnaseq/issues/220)] - Fixed an issue where miRTrace reports fastq basename instead of sample ID @@ -13,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [[#205](https://github.com/nf-core/smrnaseq/issues/205)] - Fix mirTrace Report to be a single report again instead of per sample reports - [[#206](https://github.com/nf-core/smrnaseq/issues/206)] - Use % as separator in sed commands to enable conda working properly on OSX and Linux - [[#207](https://github.com/nf-core/smrnaseq/issues/224)] - Fix Samplesheet print error +- Group samples by adapter sequence before running mirtrace ## [v2.1.0](https://github.com/nf-core/smrnaseq/releases/tag/2.1.0) - 2022-10-20 Maroon Tin Dalmatian From b405f204e93b9c71bd24d52add5827539cfdc23e Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Tue, 25 Apr 2023 10:54:42 +0100 Subject: [PATCH 125/215] Update mirtrace.nf --- modules/local/mirtrace.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/mirtrace.nf b/modules/local/mirtrace.nf index 1815bf1b..f37a4b3c 100644 --- a/modules/local/mirtrace.nf +++ b/modules/local/mirtrace.nf @@ -30,7 +30,7 @@ process MIRTRACE_RUN { .collect({ id, path -> "echo '${path},${id}' >> mirtrace_config" }) """ export mirtracejar=\$(dirname \$(which mirtrace)) - + ${config_lines.join("\n ")} java $java_mem -jar \$mirtracejar/mirtrace.jar --mirtrace-wrapper-name mirtrace qc \\ From 6f85f8f78500b4a4df4153589c27ba79e315a3aa Mon Sep 17 00:00:00 2001 From: Rob Syme Date: Wed, 26 Apr 2023 01:56:28 +0000 Subject: [PATCH 126/215] Ensure that users can skip fastp without breaking the workflow. Also move fastqc_fastp.nf to local subworkflow as it's no longer available in nf-core. --- subworkflows/{nf-core => local}/fastqc_fastp.nf | 4 ++-- workflows/smrnaseq.nf | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) rename subworkflows/{nf-core => local}/fastqc_fastp.nf (97%) diff --git a/subworkflows/nf-core/fastqc_fastp.nf b/subworkflows/local/fastqc_fastp.nf similarity index 97% rename from subworkflows/nf-core/fastqc_fastp.nf rename to subworkflows/local/fastqc_fastp.nf index 5eb2b545..3ab260a8 100644 --- a/subworkflows/nf-core/fastqc_fastp.nf +++ b/subworkflows/local/fastqc_fastp.nf @@ -35,10 +35,10 @@ workflow FASTQC_FASTP { main: - ch_versions = Channel.empty() - + ch_versions = Channel.empty() fastqc_raw_html = Channel.empty() fastqc_raw_zip = Channel.empty() + adapterseq = reads.map { meta, _ -> [meta, null] } if (!params.skip_fastqc) { FASTQC_RAW ( reads diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 5b46b3db..0f8b16a7 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -59,7 +59,7 @@ if (!params.mirgenedb) { } include { INPUT_CHECK } from '../subworkflows/local/input_check' -include { FASTQC_FASTP } from '../subworkflows/nf-core/fastqc_fastp' +include { FASTQC_FASTP } from '../subworkflows/local/fastqc_fastp' include { CONTAMINANT_FILTER } from '../subworkflows/local/contaminant_filter' include { MIRNA_QUANT } from '../subworkflows/local/mirna_quant' include { GENOME_QUANT } from '../subworkflows/local/genome_quant' @@ -132,7 +132,6 @@ workflow SMRNASEQ { false ) ch_versions = ch_versions.mix(FASTQC_FASTP.out.versions) - ch_reads = FASTQC_FASTP.out.reads // // SUBWORKFLOW: mirtrace QC From 50b1ce88d86c23e4f7e6cd4a65a3a984d537b3ab Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 26 Apr 2023 10:29:59 +0200 Subject: [PATCH 127/215] Update CHANGELOG.md Co-authored-by: Harshil Patel --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83024af7..c115fd34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [[#206](https://github.com/nf-core/smrnaseq/issues/206)] - Use % as separator in sed commands to enable conda working properly on OSX and Linux - [[#207](https://github.com/nf-core/smrnaseq/issues/224)] - Fix Samplesheet print error - Group samples by adapter sequence before running mirtrace +- Remove `--skip_qc` parameter ## [v2.1.0](https://github.com/nf-core/smrnaseq/releases/tag/2.1.0) - 2022-10-20 Maroon Tin Dalmatian From 5c2b35491ef02c3d92aea743fcd9040ddeb6f48e Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Wed, 26 Apr 2023 12:08:11 +0100 Subject: [PATCH 128/215] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c115fd34..fe86157a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 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). -## [v2.2.0](https://github.com/nf-core/smrnaseq/releases/tag/2.2.0) - 2023-04-25 +## [v2.2.0](https://github.com/nf-core/smrnaseq/releases/tag/2.2.0) - 2023-04-26 - [[#220](https://github.com/nf-core/smrnaseq/issues/220)] - Fixed an issue where miRTrace reports fastq basename instead of sample ID - [[#208](https://github.com/nf-core/smrnaseq/issues/208)] - Fixed usability of `--skip_qc` parameter From 68b0204bfb222dd9323fc1ead86dc1927e87ef36 Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Fri, 28 Apr 2023 14:26:32 +0000 Subject: [PATCH 129/215] Template update for nf-core/tools version 2.8 --- .editorconfig | 2 +- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- .github/PULL_REQUEST_TEMPLATE.md | 3 +- .github/workflows/awsfulltest.yml | 2 +- .github/workflows/awstest.yml | 2 +- .github/workflows/branch.yml | 2 +- .github/workflows/clean-up.yml | 24 ++++ .github/workflows/linting.yml | 2 +- .pre-commit-config.yaml | 5 + CHANGELOG.md | 2 +- LICENSE | 2 +- README.md | 76 +++++----- bin/check_samplesheet.py | 3 - conf/base.config | 2 +- conf/igenomes.config | 8 ++ conf/test_full.config | 2 + docs/usage.md | 130 +++++------------- lib/NfcoreSchema.groovy | 4 +- lib/WorkflowMain.groovy | 13 +- lib/WorkflowSmrnaseq.groovy | 12 +- main.nf | 1 - modules.json | 4 +- modules/local/samplesheet_check.nf | 2 +- .../custom/dumpsoftwareversions/main.nf | 6 +- .../custom/dumpsoftwareversions/meta.yml | 2 + modules/nf-core/multiqc/main.nf | 6 +- modules/nf-core/multiqc/meta.yml | 3 +- nextflow.config | 33 ++++- tower.yml | 5 + 29 files changed, 198 insertions(+), 162 deletions(-) create mode 100644 .github/workflows/clean-up.yml create mode 100644 .pre-commit-config.yaml create mode 100644 tower.yml diff --git a/.editorconfig b/.editorconfig index b78de6e6..b6b31907 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,7 +8,7 @@ trim_trailing_whitespace = true indent_size = 4 indent_style = space -[*.{md,yml,yaml,html,css,scss,js,cff}] +[*.{md,yml,yaml,html,css,scss,js}] indent_size = 2 # These files are edited and tested upstream in nf-core/modules diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index b280b79e..137da49f 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -45,6 +45,6 @@ body: * Nextflow version _(eg. 22.10.1)_ * Hardware _(eg. HPC, Desktop, Cloud)_ * Executor _(eg. slurm, local, awsbatch)_ - * Container engine: _(e.g. Docker, Singularity, Conda, Podman, Shifter or Charliecloud)_ + * Container engine: _(e.g. Docker, Singularity, Conda, Podman, Shifter, Charliecloud, or Apptainer)_ * OS _(eg. CentOS Linux, macOS, Linux Mint)_ * Version of nf-core/smrnaseq _(eg. 1.1, 1.5, 1.8.2)_ diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index cf3fb13d..e278390b 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -15,7 +15,8 @@ Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/smrn - [ ] This comment contains a description of changes (with reason). - [ ] If you've fixed a bug or added code that should be tested, add tests! -- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/smrnaseq/tree/master/.github/CONTRIBUTING.md)- [ ] If necessary, also make a PR on the nf-core/smrnaseq _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. +- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/smrnaseq/tree/master/.github/CONTRIBUTING.md) +- [ ] If necessary, also make a PR on the nf-core/smrnaseq _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. - [ ] Make sure your code lints (`nf-core lint`). - [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). - [ ] Usage Documentation in `docs/usage.md` is updated. diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index 76c16e75..5fe68194 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Launch workflow via tower - uses: nf-core/tower-action@v3 + uses: seqeralabs/action-tower-launch@v1 # TODO nf-core: You can customise AWS full pipeline tests as required # Add full size test data (but still relatively small datasets for few samples) # on the `test_full.config` test runs with only one set of parameters diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml index 03a442a1..ea58cd42 100644 --- a/.github/workflows/awstest.yml +++ b/.github/workflows/awstest.yml @@ -12,7 +12,7 @@ jobs: steps: # Launch workflow using Tower CLI tool action - name: Launch workflow via tower - uses: nf-core/tower-action@v3 + uses: seqeralabs/action-tower-launch@v1 with: workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }} access_token: ${{ secrets.TOWER_ACCESS_TOKEN }} diff --git a/.github/workflows/branch.yml b/.github/workflows/branch.yml index afde4c08..96080391 100644 --- a/.github/workflows/branch.yml +++ b/.github/workflows/branch.yml @@ -13,7 +13,7 @@ jobs: - name: Check PRs if: github.repository == 'nf-core/smrnaseq' run: | - { [[ ${{github.event.pull_request.head.repo.full_name }} == nf-core/smrnaseq ]] && [[ $GITHUB_HEAD_REF = "dev" ]]; } || [[ $GITHUB_HEAD_REF == "patch" ]] + { [[ ${{github.event.pull_request.head.repo.full_name }} == nf-core/smrnaseq ]] && [[ $GITHUB_HEAD_REF == "dev" ]]; } || [[ $GITHUB_HEAD_REF == "patch" ]] # If the above check failed, post a comment on the PR explaining the failure # NOTE - this doesn't currently work if the PR is coming from a fork, due to limitations in GitHub actions secrets diff --git a/.github/workflows/clean-up.yml b/.github/workflows/clean-up.yml new file mode 100644 index 00000000..694e90ec --- /dev/null +++ b/.github/workflows/clean-up.yml @@ -0,0 +1,24 @@ +name: "Close user-tagged issues and PRs" +on: + schedule: + - cron: "0 0 * * 0" # Once a week + +jobs: + clean-up: + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - uses: actions/stale@v7 + with: + stale-issue-message: "This issue has been tagged as awaiting-changes or awaiting-feedback by an nf-core contributor. Remove stale label or add a comment otherwise this issue will be closed in 20 days." + stale-pr-message: "This PR has been tagged as awaiting-changes or awaiting-feedback by an nf-core contributor. Remove stale label or add a comment if it is still useful." + close-issue-message: "This issue was closed because it has been tagged as awaiting-changes or awaiting-feedback by an nf-core contributor and then staled for 20 days with no activity." + days-before-stale: 30 + days-before-close: 20 + days-before-pr-close: -1 + any-of-labels: "awaiting-changes,awaiting-feedback" + exempt-issue-labels: "WIP" + exempt-pr-labels: "WIP" + repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 858d622e..888cb4bc 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -78,7 +78,7 @@ jobs: - uses: actions/setup-python@v4 with: - python-version: "3.7" + python-version: "3.8" architecture: "x64" - name: Install dependencies diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..0c31cdb9 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,5 @@ +repos: + - repo: https://github.com/pre-commit/mirrors-prettier + rev: "v2.7.1" + hooks: + - id: prettier diff --git a/CHANGELOG.md b/CHANGELOG.md index 946bdd84..0ba2e33a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 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). -## v2.1.1dev - [date] +## v2.2.0 - [date] Initial release of nf-core/smrnaseq, created with the [nf-core](https://nf-co.re/) template. diff --git a/LICENSE b/LICENSE index 499134b1..d6a83450 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) P. Ewels, C. Wang, R. Hammarén, L. Pantano +Copyright (c) P. Ewels, C. Wang, R. Hammarén, L. Pantano, A. Peltzer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 3431bbf0..ddf5126f 100644 --- a/README.md +++ b/README.md @@ -8,61 +8,75 @@ [![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/) [![Launch on Nextflow Tower](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Nextflow%20Tower-%234256e7)](https://tower.nf/launch?pipeline=https://github.com/nf-core/smrnaseq) -[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23smrnaseq-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/smrnaseq)[![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?labelColor=000000&logo=twitter)](https://twitter.com/nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core) +[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23smrnaseq-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/smrnaseq)[![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?labelColor=000000&logo=twitter)](https://twitter.com/nf_core)[![Follow on Mastodon](https://img.shields.io/badge/mastodon-nf__core-6364ff?labelColor=FFFFFF&logo=mastodon)](https://mstdn.science/@nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core) ## Introduction - +**nf-core/smrnaseq** is a bioinformatics pipeline that ... -**nf-core/smrnaseq** is a bioinformatics best-practice analysis pipeline for Small RNA-Seq Best Practice Analysis Pipeline.. - -The pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool to run tasks across multiple compute infrastructures in a very portable manner. It uses Docker/Singularity containers making installation trivial and results highly reproducible. The [Nextflow DSL2](https://www.nextflow.io/docs/latest/dsl2.html) implementation of this pipeline uses one container per process which makes it much easier to maintain and update software dependencies. Where possible, these processes have been submitted to and installed from [nf-core/modules](https://github.com/nf-core/modules) in order to make them available to all nf-core pipelines, and to everyone within the Nextflow community! - - - -On release, automated continuous integration tests run the pipeline on a full-sized dataset on the AWS cloud infrastructure. This ensures that the pipeline runs on AWS, has sensible resource allocation defaults set to run on real-world datasets, and permits the persistent storage of results to benchmark between pipeline releases and other analysis sources.The results obtained from the full-sized test can be viewed on the [nf-core website](https://nf-co.re/smrnaseq/results). - -## Pipeline summary + + 1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/)) 2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/)) -## Quick Start +## Usage + +> **Note** +> If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/usage/installation) on how +> to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/usage/introduction#how-to-run-a-pipeline) +> with `-profile test` before running the workflow on actual data. + + - Note that some form of configuration will be needed so that Nextflow knows how to fetch the required software. This is usually done in the form of a config profile (`YOURPROFILE` in the example command above). You can chain multiple config profiles in a comma-separated string. +Now, you can run the pipeline using: - > - The pipeline comes with config profiles called `docker`, `singularity`, `podman`, `shifter`, `charliecloud` and `conda` which instruct the pipeline to use the named tool for software management. For example, `-profile test,docker`. - > - Please check [nf-core/configs](https://github.com/nf-core/configs#documentation) to see if a custom config file to run nf-core pipelines already exists for your Institute. If so, you can simply use `-profile ` in your command. This will enable either `docker` or `singularity` and set the appropriate execution settings for your local compute environment. - > - If you are using `singularity`, please use the [`nf-core download`](https://nf-co.re/tools/#downloading-pipelines-for-offline-use) command to download images first, before running the pipeline. Setting the [`NXF_SINGULARITY_CACHEDIR` or `singularity.cacheDir`](https://www.nextflow.io/docs/latest/singularity.html?#singularity-docker-hub) Nextflow options enables you to store and re-use the images from a central location for future pipeline runs. - > - If you are using `conda`, it is highly recommended to use the [`NXF_CONDA_CACHEDIR` or `conda.cacheDir`](https://www.nextflow.io/docs/latest/conda.html) settings to store the environments in a central location for future pipeline runs. + -4. Start running your own analysis! +```bash +nextflow run nf-core/smrnaseq \ + -profile \ + --input samplesheet.csv \ + --outdir +``` - +> **Warning:** +> Please provide pipeline parameters via the CLI or Nextflow `-params-file` option. Custom config files including those +> provided by the `-c` Nextflow option can be used to provide any configuration _**except for parameters**_; +> see [docs](https://nf-co.re/usage/configuration#custom-configuration-files). - ```bash - nextflow run nf-core/smrnaseq --input samplesheet.csv --outdir --genome GRCh37 -profile - ``` +For more details, please refer to the [usage documentation](https://nf-co.re/smrnaseq/usage) and the [parameter documentation](https://nf-co.re/smrnaseq/parameters). -## Documentation +## Pipeline output -The nf-core/smrnaseq pipeline comes with documentation about the pipeline [usage](https://nf-co.re/smrnaseq/usage), [parameters](https://nf-co.re/smrnaseq/parameters) and [output](https://nf-co.re/smrnaseq/output). +To see the the results of a test run with a full size dataset refer to the [results](https://nf-co.re/smrnaseq/results) tab on the nf-core website pipeline page. +For more details about the output files and reports, please refer to the +[output documentation](https://nf-co.re/smrnaseq/output). ## Credits -nf-core/smrnaseq was originally written by P. Ewels, C. Wang, R. Hammarén, L. Pantano. +nf-core/smrnaseq was originally written by P. Ewels, C. Wang, R. Hammarén, L. Pantano, A. Peltzer. We thank the following people for their extensive assistance in the development of this pipeline: diff --git a/bin/check_samplesheet.py b/bin/check_samplesheet.py index 11b15572..4a758fe0 100755 --- a/bin/check_samplesheet.py +++ b/bin/check_samplesheet.py @@ -158,9 +158,6 @@ def sniff_format(handle): peek = read_head(handle) handle.seek(0) sniffer = csv.Sniffer() - if not sniffer.has_header(peek): - logger.critical("The given sample sheet does not appear to contain a header.") - sys.exit(1) dialect = sniffer.sniff(peek) return dialect diff --git a/conf/base.config b/conf/base.config index 6f4a15a6..21e478c8 100644 --- a/conf/base.config +++ b/conf/base.config @@ -15,7 +15,7 @@ process { memory = { check_max( 6.GB * task.attempt, 'memory' ) } time = { check_max( 4.h * task.attempt, 'time' ) } - errorStrategy = { task.exitStatus in [143,137,104,134,139] ? 'retry' : 'finish' } + errorStrategy = { task.exitStatus in ((130..145) + 104) ? 'retry' : 'finish' } maxRetries = 1 maxErrors = '-1' diff --git a/conf/igenomes.config b/conf/igenomes.config index 7a1b3ac6..3f114377 100644 --- a/conf/igenomes.config +++ b/conf/igenomes.config @@ -36,6 +36,14 @@ params { macs_gsize = "2.7e9" blacklist = "${projectDir}/assets/blacklists/hg38-blacklist.bed" } + 'CHM13' { + fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/CHM13/Sequence/WholeGenomeFasta/genome.fa" + bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/CHM13/Sequence/BWAIndex/" + bwamem2 = "${params.igenomes_base}/Homo_sapiens/UCSC/CHM13/Sequence/BWAmem2Index/" + gtf = "${params.igenomes_base}/Homo_sapiens/NCBI/CHM13/Annotation/Genes/genes.gtf" + gff = "ftp://ftp.ncbi.nlm.nih.gov/genomes/all/GCF/009/914/755/GCF_009914755.1_T2T-CHM13v2.0/GCF_009914755.1_T2T-CHM13v2.0_genomic.gff.gz" + mito_name = "chrM" + } 'GRCm38' { fasta = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/WholeGenomeFasta/genome.fa" bwa = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BWAIndex/version0.6.0/" diff --git a/conf/test_full.config b/conf/test_full.config index 16409b22..6128e665 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -10,6 +10,8 @@ ---------------------------------------------------------------------------------------- */ +cleanup = true + params { config_profile_name = 'Full test profile' config_profile_description = 'Full test dataset to check pipeline function' diff --git a/docs/usage.md b/docs/usage.md index 1b923e23..1af385d2 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -71,6 +71,29 @@ work # Directory containing the nextflow working files # Other nextflow hidden files, eg. history of pipeline runs and old logs. ``` +If you wish to repeatedly use the same parameters for multiple runs, rather than specifying each flag in the command, you can specify these in a params file. + +Pipeline settings can be provided in a `yaml` or `json` file via `-params-file `. + +> ⚠️ Do not use `-c ` to specify parameters as this will result in errors. Custom config files specified with `-c` must only be used for [tuning process resource specifications](https://nf-co.re/docs/usage/configuration#tuning-workflow-resources), other infrastructural tweaks (such as output directories), or module arguments (args). +> The above pipeline run specified with a params file in yaml format: + +```bash +nextflow run nf-core/smrnaseq -profile docker -params-file params.yaml +``` + +with `params.yaml` containing: + +```yaml +input: './samplesheet.csv' +outdir: './results/' +genome: 'GRCh37' +input: 'data' +<...> +``` + +You can also generate such `YAML`/`JSON` files via [nf-core/launch](https://nf-co.re/launch). + ### Updating the pipeline When you run the above command, Nextflow automatically pulls the pipeline code from GitHub and stores it as a cached version. When running the pipeline after this, it will always use the cached version if available - even if the pipeline has been updated since. To make sure that you're running the latest version of the pipeline, make sure that you regularly update the cached version of the pipeline: @@ -87,6 +110,10 @@ First, go to the [nf-core/smrnaseq releases page](https://github.com/nf-core/smr This version number will be logged in reports when you run the pipeline, so that you'll know what you used when you look back in the future. For example, at the bottom of the MultiQC reports. +To further assist in reproducbility, you can use share and re-use [parameter files](#running-the-pipeline) to repeat pipeline runs with the same settings without having to write out a command with every single parameter. + +> 💡 If you wish to share such profile (such as upload as supplementary material for academic publications), make sure to NOT include cluster specific paths to files, nor institutional specific profiles. + ## Core Nextflow arguments > **NB:** These options are part of Nextflow and use a _single_ hyphen (pipeline parameters use a double-hyphen). @@ -95,7 +122,7 @@ This version number will be logged in reports when you run the pipeline, so that Use this parameter to choose a configuration profile. Profiles can give configuration presets for different compute environments. -Several generic profiles are bundled with the pipeline which instruct the pipeline to use software packaged using different methods (Docker, Singularity, Podman, Shifter, Charliecloud, Conda) - see below. +Several generic profiles are bundled with the pipeline which instruct the pipeline to use software packaged using different methods (Docker, Singularity, Podman, Shifter, Charliecloud, Apptainer, Conda) - see below. > We highly recommend the use of Docker or Singularity containers for full pipeline reproducibility, however when this is not possible, Conda is also supported. @@ -119,8 +146,10 @@ If `-profile` is not specified, the pipeline will run locally and expect all sof - A generic configuration profile to be used with [Shifter](https://nersc.gitlab.io/development/shifter/how-to-use/) - `charliecloud` - A generic configuration profile to be used with [Charliecloud](https://hpc.github.io/charliecloud/) +- `apptainer` + - A generic configuration profile to be used with [Apptainer](https://apptainer.org/) - `conda` - - A generic configuration profile to be used with [Conda](https://conda.io/docs/). Please only use Conda as a last resort i.e. when it's not possible to run the pipeline with Docker, Singularity, Podman, Shifter or Charliecloud. + - A generic configuration profile to be used with [Conda](https://conda.io/docs/). Please only use Conda as a last resort i.e. when it's not possible to run the pipeline with Docker, Singularity, Podman, Shifter, Charliecloud, or Apptainer. ### `-resume` @@ -138,102 +167,19 @@ Specify the path to a specific config file (this is a core Nextflow command). Se Whilst the default requirements set within the pipeline will hopefully work for most people and with most input data, you may find that you want to customise the compute resources that the pipeline requests. Each step in the pipeline has a default set of requirements for number of CPUs, memory and time. For most of the steps in the pipeline, if the job exits with any of the error codes specified [here](https://github.com/nf-core/rnaseq/blob/4c27ef5610c87db00c3c5a3eed10b1d161abf575/conf/base.config#L18) it will automatically be resubmitted with higher requests (2 x original, then 3 x original). If it still fails after the third attempt then the pipeline execution is stopped. -For example, if the nf-core/rnaseq pipeline is failing after multiple re-submissions of the `STAR_ALIGN` process due to an exit code of `137` this would indicate that there is an out of memory issue: - -```console -[62/149eb0] NOTE: Process `NFCORE_RNASEQ:RNASEQ:ALIGN_STAR:STAR_ALIGN (WT_REP1)` terminated with an error exit status (137) -- Execution is retried (1) -Error executing process > 'NFCORE_RNASEQ:RNASEQ:ALIGN_STAR:STAR_ALIGN (WT_REP1)' - -Caused by: - Process `NFCORE_RNASEQ:RNASEQ:ALIGN_STAR:STAR_ALIGN (WT_REP1)` terminated with an error exit status (137) - -Command executed: - STAR \ - --genomeDir star \ - --readFilesIn WT_REP1_trimmed.fq.gz \ - --runThreadN 2 \ - --outFileNamePrefix WT_REP1. \ - - -Command exit status: - 137 - -Command output: - (empty) - -Command error: - .command.sh: line 9: 30 Killed STAR --genomeDir star --readFilesIn WT_REP1_trimmed.fq.gz --runThreadN 2 --outFileNamePrefix WT_REP1. -Work dir: - /home/pipelinetest/work/9d/172ca5881234073e8d76f2a19c88fb - -Tip: you can replicate the issue by changing to the process work dir and entering the command `bash .command.run` -``` - -#### For beginners - -A first step to bypass this error, you could try to increase the amount of CPUs, memory, and time for the whole pipeline. Therefor you can try to increase the resource for the parameters `--max_cpus`, `--max_memory`, and `--max_time`. Based on the error above, you have to increase the amount of memory. Therefore you can go to the [parameter documentation of rnaseq](https://nf-co.re/rnaseq/3.9/parameters) and scroll down to the `show hidden parameter` button to get the default value for `--max_memory`. In this case 128GB, you than can try to run your pipeline again with `--max_memory 200GB -resume` to skip all process, that were already calculated. If you can not increase the resource of the complete pipeline, you can try to adapt the resource for a single process as mentioned below. - -#### Advanced option on process level - -To bypass this error you would need to find exactly which resources are set by the `STAR_ALIGN` process. The quickest way is to search for `process STAR_ALIGN` in the [nf-core/rnaseq Github repo](https://github.com/nf-core/rnaseq/search?q=process+STAR_ALIGN). -We have standardised the structure of Nextflow DSL2 pipelines such that all module files will be present in the `modules/` directory and so, based on the search results, the file we want is `modules/nf-core/star/align/main.nf`. -If you click on the link to that file you will notice that there is a `label` directive at the top of the module that is set to [`label process_high`](https://github.com/nf-core/rnaseq/blob/4c27ef5610c87db00c3c5a3eed10b1d161abf575/modules/nf-core/software/star/align/main.nf#L9). -The [Nextflow `label`](https://www.nextflow.io/docs/latest/process.html#label) directive allows us to organise workflow processes in separate groups which can be referenced in a configuration file to select and configure subset of processes having similar computing requirements. -The default values for the `process_high` label are set in the pipeline's [`base.config`](https://github.com/nf-core/rnaseq/blob/4c27ef5610c87db00c3c5a3eed10b1d161abf575/conf/base.config#L33-L37) which in this case is defined as 72GB. -Providing you haven't set any other standard nf-core parameters to **cap** the [maximum resources](https://nf-co.re/usage/configuration#max-resources) used by the pipeline then we can try and bypass the `STAR_ALIGN` process failure by creating a custom config file that sets at least 72GB of memory, in this case increased to 100GB. -The custom config below can then be provided to the pipeline via the [`-c`](#-c) parameter as highlighted in previous sections. - -```nextflow -process { - withName: 'NFCORE_RNASEQ:RNASEQ:ALIGN_STAR:STAR_ALIGN' { - memory = 100.GB - } -} -``` - -> **NB:** We specify the full process name i.e. `NFCORE_RNASEQ:RNASEQ:ALIGN_STAR:STAR_ALIGN` in the config file because this takes priority over the short name (`STAR_ALIGN`) and allows existing configuration using the full process name to be correctly overridden. -> -> If you get a warning suggesting that the process selector isn't recognised check that the process name has been specified correctly. - -### Updating containers (advanced users) - -The [Nextflow DSL2](https://www.nextflow.io/docs/latest/dsl2.html) implementation of this pipeline uses one container per process which makes it much easier to maintain and update software dependencies. If for some reason you need to use a different version of a particular tool with the pipeline then you just need to identify the `process` name and override the Nextflow `container` definition for that process using the `withName` declaration. For example, in the [nf-core/viralrecon](https://nf-co.re/viralrecon) pipeline a tool called [Pangolin](https://github.com/cov-lineages/pangolin) has been used during the COVID-19 pandemic to assign lineages to SARS-CoV-2 genome sequenced samples. Given that the lineage assignments change quite frequently it doesn't make sense to re-release the nf-core/viralrecon everytime a new version of Pangolin has been released. However, you can override the default container used by the pipeline by creating a custom config file and passing it as a command-line argument via `-c custom.config`. - -1. Check the default version used by the pipeline in the module file for [Pangolin](https://github.com/nf-core/viralrecon/blob/a85d5969f9025409e3618d6c280ef15ce417df65/modules/nf-core/software/pangolin/main.nf#L14-L19) -2. Find the latest version of the Biocontainer available on [Quay.io](https://quay.io/repository/biocontainers/pangolin?tag=latest&tab=tags) -3. Create the custom config accordingly: - - - For Docker: +To change the resource requests, please see the [max resources](https://nf-co.re/docs/usage/configuration#max-resources) and [tuning workflow resources](https://nf-co.re/docs/usage/configuration#tuning-workflow-resources) section of the nf-core website. - ```nextflow - process { - withName: PANGOLIN { - container = 'quay.io/biocontainers/pangolin:3.0.5--pyhdfd78af_0' - } - } - ``` +### Custom Containers - - For Singularity: +In some cases you may wish to change which container or conda environment a step of the pipeline uses for a particular tool. By default nf-core pipelines use containers and software from the [biocontainers](https://biocontainers.pro/) or [bioconda](https://bioconda.github.io/) projects. However in some cases the pipeline specified version maybe out of date. - ```nextflow - process { - withName: PANGOLIN { - container = 'https://depot.galaxyproject.org/singularity/pangolin:3.0.5--pyhdfd78af_0' - } - } - ``` +To use a different container from the default container or conda environment specified in a pipeline, please see the [updating tool versions](https://nf-co.re/docs/usage/configuration#updating-tool-versions) section of the nf-core website. - - For Conda: +### Custom Tool Arguments - ```nextflow - process { - withName: PANGOLIN { - conda = 'bioconda::pangolin=3.0.5' - } - } - ``` +A pipeline might not always support every possible argument or option of a particular tool used in pipeline. Fortunately, nf-core pipelines provide some freedom to users to insert additional parameters that the pipeline does not include by default. -> **NB:** If you wish to periodically update individual tool-specific results (e.g. Pangolin) generated by the pipeline then you must ensure to keep the `work/` directory otherwise the `-resume` ability of the pipeline will be compromised and it will restart from scratch. +To learn how to provide additional arguments to a particular tool of the pipeline, please see the [customising tool arguments](https://nf-co.re/docs/usage/configuration#customising-tool-arguments) section of the nf-core website. ### nf-core/configs diff --git a/lib/NfcoreSchema.groovy b/lib/NfcoreSchema.groovy index 33cd4f6e..9b34804d 100755 --- a/lib/NfcoreSchema.groovy +++ b/lib/NfcoreSchema.groovy @@ -2,6 +2,7 @@ // This file holds several functions used to perform JSON parameter validation, help and summary rendering for the nf-core pipeline template. // +import nextflow.Nextflow import org.everit.json.schema.Schema import org.everit.json.schema.loader.SchemaLoader import org.everit.json.schema.ValidationException @@ -83,6 +84,7 @@ class NfcoreSchema { 'stub-run', 'test', 'w', + 'with-apptainer', 'with-charliecloud', 'with-conda', 'with-dag', @@ -177,7 +179,7 @@ class NfcoreSchema { } if (has_error) { - System.exit(1) + Nextflow.error('Exiting!') } } diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index d5372d8c..892c41e7 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -2,6 +2,8 @@ // This file holds several functions specific to the main.nf workflow in the nf-core/smrnaseq pipeline // +import nextflow.Nextflow + class WorkflowMain { // @@ -21,7 +23,7 @@ class WorkflowMain { // // Generate help string // - public static String help(workflow, params, log) { + public static String help(workflow, params) { def command = "nextflow run ${workflow.manifest.name} --input samplesheet.csv --genome GRCh37 -profile docker" def help_string = '' help_string += NfcoreTemplate.logo(workflow, params.monochrome_logs) @@ -34,7 +36,7 @@ class WorkflowMain { // // Generate parameter summary log string // - public static String paramsSummaryLog(workflow, params, log) { + public static String paramsSummaryLog(workflow, params) { def summary_log = '' summary_log += NfcoreTemplate.logo(workflow, params.monochrome_logs) summary_log += NfcoreSchema.paramsSummaryLog(workflow, params) @@ -49,7 +51,7 @@ class WorkflowMain { public static void initialise(workflow, params, log) { // Print help to screen if required if (params.help) { - log.info help(workflow, params, log) + log.info help(workflow, params) System.exit(0) } @@ -61,7 +63,7 @@ class WorkflowMain { } // Print parameter summary log to screen - log.info paramsSummaryLog(workflow, params, log) + log.info paramsSummaryLog(workflow, params) // Validate workflow parameters via the JSON schema if (params.validate_params) { @@ -81,8 +83,7 @@ class WorkflowMain { // Check input has been provided if (!params.input) { - log.error "Please provide an input samplesheet to the pipeline e.g. '--input samplesheet.csv'" - System.exit(1) + Nextflow.error("Please provide an input samplesheet to the pipeline e.g. '--input samplesheet.csv'") } } // diff --git a/lib/WorkflowSmrnaseq.groovy b/lib/WorkflowSmrnaseq.groovy index 3190e322..7ab5bd21 100755 --- a/lib/WorkflowSmrnaseq.groovy +++ b/lib/WorkflowSmrnaseq.groovy @@ -2,6 +2,7 @@ // This file holds several functions specific to the workflow/smrnaseq.nf in the nf-core/smrnaseq pipeline // +import nextflow.Nextflow import groovy.text.SimpleTemplateEngine class WorkflowSmrnaseq { @@ -14,8 +15,7 @@ class WorkflowSmrnaseq { if (!params.fasta) { - log.error "Genome fasta file not specified with e.g. '--fasta genome.fa' or via a detectable config file." - System.exit(1) + Nextflow.error "Genome fasta file not specified with e.g. '--fasta genome.fa' or via a detectable config file." } } @@ -61,17 +61,19 @@ class WorkflowSmrnaseq { def description_html = engine.createTemplate(methods_text).make(meta) return description_html - }// + } + + // // Exit pipeline if incorrect --genome key provided // private static void genomeExistsError(params, log) { if (params.genomes && params.genome && !params.genomes.containsKey(params.genome)) { - log.error "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + def error_string = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " Genome '${params.genome}' not found in any config files provided to the pipeline.\n" + " Currently, the available genome keys are:\n" + " ${params.genomes.keySet().join(", ")}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - System.exit(1) + Nextflow.error(error_string) } } } diff --git a/main.nf b/main.nf index adbfad48..5b057014 100644 --- a/main.nf +++ b/main.nf @@ -4,7 +4,6 @@ nf-core/smrnaseq ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Github : https://github.com/nf-core/smrnaseq - Website: https://nf-co.re/smrnaseq Slack : https://nfcore.slack.com/channels/smrnaseq ---------------------------------------------------------------------------------------- diff --git a/modules.json b/modules.json index 6a70e5a9..87ce4b65 100644 --- a/modules.json +++ b/modules.json @@ -7,7 +7,7 @@ "nf-core": { "custom/dumpsoftwareversions": { "branch": "master", - "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", + "git_sha": "76cc4938c1f6ea5c7d83fed1eeffc146787f9543", "installed_by": ["modules"] }, "fastqc": { @@ -17,7 +17,7 @@ }, "multiqc": { "branch": "master", - "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", + "git_sha": "f2d63bd5b68925f98f572eed70993d205cc694b7", "installed_by": ["modules"] } } diff --git a/modules/local/samplesheet_check.nf b/modules/local/samplesheet_check.nf index 94247c70..351d2322 100644 --- a/modules/local/samplesheet_check.nf +++ b/modules/local/samplesheet_check.nf @@ -5,7 +5,7 @@ process SAMPLESHEET_CHECK { conda "conda-forge::python=3.8.3" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/python:3.8.3' : - 'quay.io/biocontainers/python:3.8.3' }" + 'biocontainers/python:3.8.3' }" input: path samplesheet diff --git a/modules/nf-core/custom/dumpsoftwareversions/main.nf b/modules/nf-core/custom/dumpsoftwareversions/main.nf index 3df21765..800a6099 100644 --- a/modules/nf-core/custom/dumpsoftwareversions/main.nf +++ b/modules/nf-core/custom/dumpsoftwareversions/main.nf @@ -2,10 +2,10 @@ process CUSTOM_DUMPSOFTWAREVERSIONS { label 'process_single' // Requires `pyyaml` which does not have a dedicated container but is in the MultiQC container - conda "bioconda::multiqc=1.13" + conda "bioconda::multiqc=1.14" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.13--pyhdfd78af_0' : - 'quay.io/biocontainers/multiqc:1.13--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/multiqc:1.14--pyhdfd78af_0' : + 'quay.io/biocontainers/multiqc:1.14--pyhdfd78af_0' }" input: path versions diff --git a/modules/nf-core/custom/dumpsoftwareversions/meta.yml b/modules/nf-core/custom/dumpsoftwareversions/meta.yml index 60b546a0..c32657de 100644 --- a/modules/nf-core/custom/dumpsoftwareversions/meta.yml +++ b/modules/nf-core/custom/dumpsoftwareversions/meta.yml @@ -1,7 +1,9 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/yaml-schema.json name: custom_dumpsoftwareversions description: Custom module used to dump software versions within the nf-core pipeline template keywords: - custom + - dump - version tools: - custom: diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index 68f66bea..4b604749 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -1,10 +1,10 @@ process MULTIQC { label 'process_single' - conda "bioconda::multiqc=1.13" + conda "bioconda::multiqc=1.14" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.13--pyhdfd78af_0' : - 'quay.io/biocontainers/multiqc:1.13--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/multiqc:1.14--pyhdfd78af_0' : + 'quay.io/biocontainers/multiqc:1.14--pyhdfd78af_0' }" input: path multiqc_files, stageAs: "?/*" diff --git a/modules/nf-core/multiqc/meta.yml b/modules/nf-core/multiqc/meta.yml index ebc29b27..f93b5ee5 100644 --- a/modules/nf-core/multiqc/meta.yml +++ b/modules/nf-core/multiqc/meta.yml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/yaml-schema.json name: MultiQC description: Aggregate results from bioinformatics analyses across many samples into a single report keywords: @@ -37,7 +38,7 @@ output: description: MultiQC report file pattern: "multiqc_report.html" - data: - type: dir + type: directory description: MultiQC data dir pattern: "multiqc_data" - plots: diff --git a/nextflow.config b/nextflow.config index 4a87aa48..ba0a8e73 100644 --- a/nextflow.config +++ b/nextflow.config @@ -78,7 +78,11 @@ try { profiles { - debug { process.beforeScript = 'echo $HOSTNAME' } + debug { + dumpHashes = true + process.beforeScript = 'echo $HOSTNAME' + cleanup = false + } conda { conda.enabled = true docker.enabled = false @@ -86,6 +90,7 @@ profiles { podman.enabled = false shifter.enabled = false charliecloud.enabled = false + apptainer.enabled = false } mamba { conda.enabled = true @@ -95,14 +100,18 @@ profiles { podman.enabled = false shifter.enabled = false charliecloud.enabled = false + apptainer.enabled = false } docker { docker.enabled = true + docker.registry = 'quay.io' docker.userEmulation = true + conda.enabled = false singularity.enabled = false podman.enabled = false shifter.enabled = false charliecloud.enabled = false + apptainer.enabled = false } arm { docker.runOptions = '-u $(id -u):$(id -g) --platform=linux/amd64' @@ -110,31 +119,49 @@ profiles { singularity { singularity.enabled = true singularity.autoMounts = true + conda.enabled = false docker.enabled = false podman.enabled = false shifter.enabled = false charliecloud.enabled = false + apptainer.enabled = false } podman { podman.enabled = true + podman.registry = 'quay.io' + conda.enabled = false docker.enabled = false singularity.enabled = false shifter.enabled = false charliecloud.enabled = false + apptainer.enabled = false } shifter { shifter.enabled = true + conda.enabled = false docker.enabled = false singularity.enabled = false podman.enabled = false charliecloud.enabled = false + apptainer.enabled = false } charliecloud { charliecloud.enabled = true + conda.enabled = false docker.enabled = false singularity.enabled = false podman.enabled = false shifter.enabled = false + apptainer.enabled = false + } + apptainer { + apptainer.enabled = true + conda.enabled = false + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false } gitpod { executor.name = 'local' @@ -188,12 +215,12 @@ dag { manifest { name = 'nf-core/smrnaseq' - author = """P. Ewels, C. Wang, R. Hammarén, L. Pantano""" + author = """P. Ewels, C. Wang, R. Hammarén, L. Pantano, A. Peltzer""" homePage = 'https://github.com/nf-core/smrnaseq' description = """Small RNA-Seq Best Practice Analysis Pipeline.""" mainScript = 'main.nf' nextflowVersion = '!>=22.10.1' - version = '2.1.1dev' + version = '2.2.0' doi = '' } diff --git a/tower.yml b/tower.yml new file mode 100644 index 00000000..787aedfe --- /dev/null +++ b/tower.yml @@ -0,0 +1,5 @@ +reports: + multiqc_report.html: + display: "MultiQC HTML report" + samplesheet.csv: + display: "Auto-created samplesheet with collated metadata and FASTQ paths" From 805048d714fc24d67d4c01fc8ea1d1ad10454f7b Mon Sep 17 00:00:00 2001 From: Rob Syme Date: Fri, 5 May 2023 20:49:48 +0000 Subject: [PATCH 130/215] Pass filtered or unfiltered reads to MIRNA_QUANT. If params.filter_contamination is true, then pass in reads returned from CONTAMINANT_FILTER. Otherwise, use FASTQC_FASTP.out.reads. --- workflows/smrnaseq.nf | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 0f8b16a7..f98bcc74 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -150,6 +150,7 @@ workflow SMRNASEQ { // SUBWORKFLOW: remove contaminants from reads // contamination_stats = Channel.empty() + mirna_reads = FASTQC_FASTP.out.reads if (params.filter_contamination){ CONTAMINANT_FILTER ( reference_hairpin, @@ -164,6 +165,7 @@ workflow SMRNASEQ { contamination_stats = CONTAMINANT_FILTER.out.filter_stats ch_versions = ch_versions.mix(CONTAMINANT_FILTER.out.versions) + mirna_reads = CONTAMINANT_FILTER.out.filtered_reads } @@ -171,7 +173,7 @@ workflow SMRNASEQ { reference_mature, reference_hairpin, mirna_gtf, - contamination_stats + mirna_reads ) ch_versions = ch_versions.mix(MIRNA_QUANT.out.versions.ifEmpty(null)) From 07afcb0dd1795016faf85b128e501e8b8bec7288 Mon Sep 17 00:00:00 2001 From: maxulysse Date: Mon, 8 May 2023 10:21:02 +0200 Subject: [PATCH 131/215] bump to 2.2.1 + MD syntax fix --- CHANGELOG.md | 34 ++++++++++++++++++++-------------- nextflow.config | 2 +- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe86157a..ebedaef2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,14 +3,20 @@ 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). +## [v2.2.1](https://github.com/nf-core/smrnaseq/releases/tag/2.2.1) - 2023-05-08 + +### Enhancements & fixes + +- [[#238](https://github.com/nf-core/smrnaseq/issues/238) - Restored the missing mirtop outputs + ## [v2.2.0](https://github.com/nf-core/smrnaseq/releases/tag/2.2.0) - 2023-04-26 -- [[#220](https://github.com/nf-core/smrnaseq/issues/220)] - Fixed an issue where miRTrace reports fastq basename instead of sample ID -- [[#208](https://github.com/nf-core/smrnaseq/issues/208)] - Fixed usability of `--skip_qc` parameter +- [[#220](https://github.com/nf-core/smrnaseq/issues/220) - Fixed an issue where miRTrace reports fastq basename instead of sample ID +- [[#208](https://github.com/nf-core/smrnaseq/issues/208) - Fixed usability of `--skip_qc` parameter - Updated FASTP module to allow direct addition of adapter_fasta file to it -- [[#205](https://github.com/nf-core/smrnaseq/issues/205)] - Fix mirTrace Report to be a single report again instead of per sample reports -- [[#206](https://github.com/nf-core/smrnaseq/issues/206)] - Use % as separator in sed commands to enable conda working properly on OSX and Linux -- [[#207](https://github.com/nf-core/smrnaseq/issues/224)] - Fix Samplesheet print error +- [[#205](https://github.com/nf-core/smrnaseq/issues/205) - Fix mirTrace Report to be a single report again instead of per sample reports +- [[#206](https://github.com/nf-core/smrnaseq/issues/206) - Use % as separator in sed commands to enable conda working properly on OSX and Linux +- [[#207](https://github.com/nf-core/smrnaseq/issues/224) - Fix Samplesheet print error - Group samples by adapter sequence before running mirtrace - Remove `--skip_qc` parameter @@ -18,15 +24,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Enhancements & fixes -- [[#12](https://github.com/nf-core/smrnaseq/issues/12)] - Enabled the use of `MirGeneDB` as an alternative database insted of `miRBase` -- [[#113](https://github.com/nf-core/smrnaseq/issues/113)] - Added a optional contamination filtering step, including MultiQC plot -- [[#137](https://github.com/nf-core/smrnaseq/issues/137)] - Fixed issue with mirTop and MultiQC by upgrading to MultiQC V1.13dev -- [[#159](https://github.com/nf-core/smrnaseq/issues/159)] - Index files were not collected when `bowtie_index` was used and thus mapping was failing -- [[#161](https://github.com/nf-core/smrnaseq/issues/161)] - Trimmed output was not as documented and not correctly published -- [[#168](https://github.com/nf-core/smrnaseq/issues/168)] - Removed `mirtrace_protocol` as the parameter was redundant and `params.protocol` is entirely sufficient +- [[#12](https://github.com/nf-core/smrnaseq/issues/12) - Enabled the use of `MirGeneDB` as an alternative database insted of `miRBase` +- [[#113](https://github.com/nf-core/smrnaseq/issues/113) - Added a optional contamination filtering step, including MultiQC plot +- [[#137](https://github.com/nf-core/smrnaseq/issues/137) - Fixed issue with mirTop and MultiQC by upgrading to MultiQC V1.13dev +- [[#159](https://github.com/nf-core/smrnaseq/issues/159) - Index files were not collected when `bowtie_index` was used and thus mapping was failing +- [[#161](https://github.com/nf-core/smrnaseq/issues/161) - Trimmed output was not as documented and not correctly published +- [[#168](https://github.com/nf-core/smrnaseq/issues/168) - Removed `mirtrace_protocol` as the parameter was redundant and `params.protocol` is entirely sufficient - Updated pipeline template to [nf-core/tools 2.6.0](https://github.com/nf-core/tools/releases/tag/2.6.0) -- [[#188](https://github.com/nf-core/smrnaseq/pull/188)] - Dropped TrimGalore in favor of fastp QC and adapter trimming, improved handling of adapters and trimming parameters -- [[#194](https://github.com/nf-core/smrnaseq/issues/194)] - Added default adapters file for FastP improved miRNA adapter trimming +- [[#188](https://github.com/nf-core/smrnaseq/pull/188) - Dropped TrimGalore in favor of fastp QC and adapter trimming, improved handling of adapters and trimming parameters +- [[#194](https://github.com/nf-core/smrnaseq/issues/194) - Added default adapters file for FastP improved miRNA adapter trimming ### Parameters @@ -50,7 +56,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Major enhancements - Updated pipeline template to [nf-core/tools 2.4.1](https://github.com/nf-core/tools/releases/tag/2.4.1) -- [[#137](https://github.com/nf-core/smrnaseq/issues/137)] - Update mirtop container to version `0.4.25` to fix multiqc error +- [[#137](https://github.com/nf-core/smrnaseq/issues/137) - Update mirtop container to version `0.4.25` to fix multiqc error - Port pipeline to the updated Nextflow DSL2 syntax adopted on nf-core/modules - Bump minimum Nextflow version from `20.04.0` -> `21.10.3` - Point to the proper test data branch diff --git a/nextflow.config b/nextflow.config index 7b6f2d8e..e00b1fa6 100644 --- a/nextflow.config +++ b/nextflow.config @@ -225,7 +225,7 @@ manifest { description = """Small RNA-Seq Best Practice Analysis Pipeline.""" mainScript = 'main.nf' nextflowVersion = '!>=22.10.1' - version = '2.2.0' + version = '2.2.1' doi = '' } From 8f7bb8e7d2c21a98b7fcaebc0912770d4e7c0d9b Mon Sep 17 00:00:00 2001 From: maxulysse Date: Mon, 8 May 2023 10:24:06 +0200 Subject: [PATCH 132/215] reverse changes on bracket, MD symtax was fine --- CHANGELOG.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ebedaef2..3ce24b8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,16 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Enhancements & fixes -- [[#238](https://github.com/nf-core/smrnaseq/issues/238) - Restored the missing mirtop outputs +- [[#238](https://github.com/nf-core/smrnaseq/issues/238)] - Restored the missing mirtop outputs ## [v2.2.0](https://github.com/nf-core/smrnaseq/releases/tag/2.2.0) - 2023-04-26 -- [[#220](https://github.com/nf-core/smrnaseq/issues/220) - Fixed an issue where miRTrace reports fastq basename instead of sample ID -- [[#208](https://github.com/nf-core/smrnaseq/issues/208) - Fixed usability of `--skip_qc` parameter +- [[#220](https://github.com/nf-core/smrnaseq/issues/220)] - Fixed an issue where miRTrace reports fastq basename instead of sample ID +- [[#208](https://github.com/nf-core/smrnaseq/issues/208)] - Fixed usability of `--skip_qc` parameter - Updated FASTP module to allow direct addition of adapter_fasta file to it -- [[#205](https://github.com/nf-core/smrnaseq/issues/205) - Fix mirTrace Report to be a single report again instead of per sample reports -- [[#206](https://github.com/nf-core/smrnaseq/issues/206) - Use % as separator in sed commands to enable conda working properly on OSX and Linux -- [[#207](https://github.com/nf-core/smrnaseq/issues/224) - Fix Samplesheet print error +- [[#205](https://github.com/nf-core/smrnaseq/issues/205)] - Fix mirTrace Report to be a single report again instead of per sample reports +- [[#206](https://github.com/nf-core/smrnaseq/issues/206)] - Use % as separator in sed commands to enable conda working properly on OSX and Linux +- [[#207](https://github.com/nf-core/smrnaseq/issues/224)] - Fix Samplesheet print error - Group samples by adapter sequence before running mirtrace - Remove `--skip_qc` parameter @@ -24,15 +24,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Enhancements & fixes -- [[#12](https://github.com/nf-core/smrnaseq/issues/12) - Enabled the use of `MirGeneDB` as an alternative database insted of `miRBase` -- [[#113](https://github.com/nf-core/smrnaseq/issues/113) - Added a optional contamination filtering step, including MultiQC plot -- [[#137](https://github.com/nf-core/smrnaseq/issues/137) - Fixed issue with mirTop and MultiQC by upgrading to MultiQC V1.13dev -- [[#159](https://github.com/nf-core/smrnaseq/issues/159) - Index files were not collected when `bowtie_index` was used and thus mapping was failing -- [[#161](https://github.com/nf-core/smrnaseq/issues/161) - Trimmed output was not as documented and not correctly published -- [[#168](https://github.com/nf-core/smrnaseq/issues/168) - Removed `mirtrace_protocol` as the parameter was redundant and `params.protocol` is entirely sufficient +- [[#12](https://github.com/nf-core/smrnaseq/issues/12)] - Enabled the use of `MirGeneDB` as an alternative database insted of `miRBase` +- [[#113](https://github.com/nf-core/smrnaseq/issues/113)] - Added a optional contamination filtering step, including MultiQC plot +- [[#137](https://github.com/nf-core/smrnaseq/issues/137)] - Fixed issue with mirTop and MultiQC by upgrading to MultiQC V1.13dev +- [[#159](https://github.com/nf-core/smrnaseq/issues/159)] - Index files were not collected when `bowtie_index` was used and thus mapping was failing +- [[#161](https://github.com/nf-core/smrnaseq/issues/161)] - Trimmed output was not as documented and not correctly published +- [[#168](https://github.com/nf-core/smrnaseq/issues/168)] - Removed `mirtrace_protocol` as the parameter was redundant and `params.protocol` is entirely sufficient - Updated pipeline template to [nf-core/tools 2.6.0](https://github.com/nf-core/tools/releases/tag/2.6.0) -- [[#188](https://github.com/nf-core/smrnaseq/pull/188) - Dropped TrimGalore in favor of fastp QC and adapter trimming, improved handling of adapters and trimming parameters -- [[#194](https://github.com/nf-core/smrnaseq/issues/194) - Added default adapters file for FastP improved miRNA adapter trimming +- [[#188](https://github.com/nf-core/smrnaseq/pull/188)] - Dropped TrimGalore in favor of fastp QC and adapter trimming, improved handling of adapters and trimming parameters +- [[#194](https://github.com/nf-core/smrnaseq/issues/194)] - Added default adapters file for FastP improved miRNA adapter trimming ### Parameters @@ -56,7 +56,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Major enhancements - Updated pipeline template to [nf-core/tools 2.4.1](https://github.com/nf-core/tools/releases/tag/2.4.1) -- [[#137](https://github.com/nf-core/smrnaseq/issues/137) - Update mirtop container to version `0.4.25` to fix multiqc error +- [[#137](https://github.com/nf-core/smrnaseq/issues/137)] - Update mirtop container to version `0.4.25` to fix multiqc error - Port pipeline to the updated Nextflow DSL2 syntax adopted on nf-core/modules - Bump minimum Nextflow version from `20.04.0` -> `21.10.3` - Point to the proper test data branch From 0e3a7d33ad6008f08b3dba1dd9fb96fe809b0e54 Mon Sep 17 00:00:00 2001 From: Maxime U Garcia Date: Mon, 8 May 2023 13:26:23 +0200 Subject: [PATCH 133/215] Apply suggestions from code review --- README.md | 4 ++-- conf/test_full.config | 2 -- nextflow.config | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ddf5126f..6059a16e 100644 --- a/README.md +++ b/README.md @@ -42,8 +42,8 @@ First, prepare a samplesheet with your input data that looks as follows: `samplesheet.csv`: ```csv -sample,fastq_1,fastq_2 -CONTROL_REP1,AEG588A1_S1_L002_R1_001.fastq.gz,AEG588A1_S1_L002_R2_001.fastq.gz +sample,fastq_1 +CONTROL_REP1,AEG588A1_S1_L002_001.fastq.gz ``` Each row represents a fastq file (single-end) or a pair of fastq files (paired end). diff --git a/conf/test_full.config b/conf/test_full.config index 6128e665..16409b22 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -10,8 +10,6 @@ ---------------------------------------------------------------------------------------- */ -cleanup = true - params { config_profile_name = 'Full test profile' config_profile_description = 'Full test dataset to check pipeline function' diff --git a/nextflow.config b/nextflow.config index ba0a8e73..f7f454d8 100644 --- a/nextflow.config +++ b/nextflow.config @@ -81,7 +81,7 @@ profiles { debug { dumpHashes = true process.beforeScript = 'echo $HOSTNAME' - cleanup = false + cleanup. = false } conda { conda.enabled = true From 6682440167f8d0d8a7a47c92ce375f9518f6b082 Mon Sep 17 00:00:00 2001 From: Maxime U Garcia Date: Mon, 8 May 2023 13:36:44 +0200 Subject: [PATCH 134/215] Apply suggestions from code review --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6059a16e..fb258218 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ ## Introduction -**nf-core/smrnaseq** is a bioinformatics pipeline that ... +**nf-core/smrnaseq** is a bioinformatics best-practice analysis pipeline for Small RNA-Seq. @@ -58,6 +58,9 @@ Now, you can run the pipeline using: nextflow run nf-core/smrnaseq \ -profile \ --input samplesheet.csv \ + --genome 'GRCh37' \ + --mirtrace_species 'hsa' \ + --protocol 'illumina' \ --outdir ``` From 85b368f4de1a3b5718c7236c435d4cd4c3b2a94b Mon Sep 17 00:00:00 2001 From: Maxime U Garcia Date: Mon, 8 May 2023 13:50:01 +0200 Subject: [PATCH 135/215] Apply suggestions from code review --- nextflow.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nextflow.config b/nextflow.config index 3608eaca..6f7f0088 100644 --- a/nextflow.config +++ b/nextflow.config @@ -113,7 +113,7 @@ profiles { debug { dumpHashes = true process.beforeScript = 'echo $HOSTNAME' - cleanup. = false + cleanup = false } conda { conda.enabled = true @@ -138,7 +138,7 @@ profiles { docker.enabled = true docker.registry = 'quay.io' docker.userEmulation = true - docker.runOptions = '-u $(id -u):$(id -g)' + docker.runOptions = '-u $(id -u):$(id -g)' conda.enabled = false singularity.enabled = false podman.enabled = false From 998c3df19c0855414d63c1d02208795d0a261b23 Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Mon, 8 May 2023 11:51:38 +0000 Subject: [PATCH 136/215] [automated] Fix linting with Prettier --- README.md | 1 - tower.yml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 203a08f9..fe5e6816 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,6 @@ nextflow run nf-core/smrnaseq \ For more details, please refer to the [usage documentation](https://nf-co.re/smrnaseq/usage) and the [parameter documentation](https://nf-co.re/smrnaseq/parameters). - ## Pipeline output To see the the results of a test run with a full size dataset refer to the [results](https://nf-co.re/smrnaseq/results) tab on the nf-core website pipeline page. diff --git a/tower.yml b/tower.yml index 972981d9..1a72c200 100644 --- a/tower.yml +++ b/tower.yml @@ -26,4 +26,4 @@ reports: "**/mirtop/mirtop.tsv": display: "Mirtop summary table" "**/mirtrace/mirtrace-report.html": - display: "Mirtrace report" \ No newline at end of file + display: "Mirtrace report" From 681213b7ad0c6cb41d3fa80bc260c769c646bc6e Mon Sep 17 00:00:00 2001 From: Maxime U Garcia Date: Mon, 8 May 2023 13:52:59 +0200 Subject: [PATCH 137/215] Update README.md Co-authored-by: Jose Espinosa-Carrasco --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fe5e6816..6fb16c5e 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ nextflow run nf-core/smrnaseq \ --genome 'GRCh37' \ --mirtrace_species 'hsa' \ --protocol 'illumina' \ - --outdir + --outdir ``` > **Warning:** From 7b23315157d175581d49562e275aac4507f4873e Mon Sep 17 00:00:00 2001 From: maxulysse Date: Mon, 8 May 2023 13:58:43 +0200 Subject: [PATCH 138/215] fix modules --- modules.json | 62 ++++++++++++------- modules/nf-core/cat/fastq/main.nf | 2 +- modules/nf-core/cat/fastq/meta.yml | 3 +- .../custom/dumpsoftwareversions/main.nf | 2 +- .../templates/dumpsoftwareversions.py | 0 modules/nf-core/fastp/main.nf | 2 +- modules/nf-core/fastqc/main.nf | 2 +- modules/nf-core/multiqc/main.nf | 2 +- modules/nf-core/samtools/flagstat/main.nf | 6 +- modules/nf-core/samtools/idxstats/main.nf | 6 +- modules/nf-core/samtools/index/main.nf | 6 +- modules/nf-core/samtools/sort/main.nf | 16 +++-- modules/nf-core/samtools/stats/main.nf | 6 +- 13 files changed, 72 insertions(+), 43 deletions(-) mode change 100644 => 100755 modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py diff --git a/modules.json b/modules.json index 50d33851..3a3ddeff 100644 --- a/modules.json +++ b/modules.json @@ -7,56 +7,76 @@ "nf-core": { "cat/fastq": { "branch": "master", - "git_sha": "76cc4938c1f6ea5c7d83fed1eeffc146787f9543", - "installed_by": ["modules"] + "git_sha": "5c460c5a4736974abde2843294f35307ee2b0e5e", + "installed_by": [ + "modules" + ] }, "custom/dumpsoftwareversions": { "branch": "master", - "git_sha": "7101db4432d3268b7fcb5b8f75fa0a022dc5561b", - "installed_by": ["modules"] + "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "installed_by": [ + "modules" + ] }, "fastp": { "branch": "master", - "git_sha": "20a508676f40d0fd3f911ac595af91ec845704c4", - "installed_by": ["modules"] + "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "installed_by": [ + "modules" + ] }, "fastqc": { "branch": "master", - "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", - "installed_by": ["modules"] + "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "installed_by": [ + "modules" + ] }, "multiqc": { "branch": "master", - "git_sha": "ee80d14721e76e2e079103b8dcd5d57129e584ba", - "installed_by": ["modules"] + "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "installed_by": [ + "modules" + ] }, "samtools/flagstat": { "branch": "master", - "git_sha": "0f8a77ff00e65eaeebc509b8156eaa983192474b", - "installed_by": ["modules"] + "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "installed_by": [ + "modules" + ] }, "samtools/idxstats": { "branch": "master", - "git_sha": "0f8a77ff00e65eaeebc509b8156eaa983192474b", - "installed_by": ["modules"] + "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "installed_by": [ + "modules" + ] }, "samtools/index": { "branch": "master", - "git_sha": "0f8a77ff00e65eaeebc509b8156eaa983192474b", - "installed_by": ["modules"] + "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "installed_by": [ + "modules" + ] }, "samtools/sort": { "branch": "master", - "git_sha": "0f8a77ff00e65eaeebc509b8156eaa983192474b", - "installed_by": ["modules"] + "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "installed_by": [ + "modules" + ] }, "samtools/stats": { "branch": "master", - "git_sha": "0f8a77ff00e65eaeebc509b8156eaa983192474b", - "installed_by": ["modules"] + "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "installed_by": [ + "modules" + ] } } } } } -} +} \ No newline at end of file diff --git a/modules/nf-core/cat/fastq/main.nf b/modules/nf-core/cat/fastq/main.nf index 8a0b5600..5021e6fc 100644 --- a/modules/nf-core/cat/fastq/main.nf +++ b/modules/nf-core/cat/fastq/main.nf @@ -5,7 +5,7 @@ process CAT_FASTQ { conda "conda-forge::sed=4.7" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/ubuntu:20.04' : - 'ubuntu:20.04' }" + 'nf-core/ubuntu:20.04' }" input: tuple val(meta), path(reads, stageAs: "input*/*") diff --git a/modules/nf-core/cat/fastq/meta.yml b/modules/nf-core/cat/fastq/meta.yml index c836598e..8a39e309 100644 --- a/modules/nf-core/cat/fastq/meta.yml +++ b/modules/nf-core/cat/fastq/meta.yml @@ -1,6 +1,7 @@ name: cat_fastq description: Concatenates fastq files keywords: + - cat - fastq - concatenate tools: @@ -16,7 +17,7 @@ input: Groovy Map containing sample information e.g. [ id:'test', single_end:false ] - reads: - type: list + type: file description: | List of input FastQ files to be concatenated. output: diff --git a/modules/nf-core/custom/dumpsoftwareversions/main.nf b/modules/nf-core/custom/dumpsoftwareversions/main.nf index 800a6099..ebc87273 100644 --- a/modules/nf-core/custom/dumpsoftwareversions/main.nf +++ b/modules/nf-core/custom/dumpsoftwareversions/main.nf @@ -5,7 +5,7 @@ process CUSTOM_DUMPSOFTWAREVERSIONS { conda "bioconda::multiqc=1.14" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/multiqc:1.14--pyhdfd78af_0' : - 'quay.io/biocontainers/multiqc:1.14--pyhdfd78af_0' }" + 'biocontainers/multiqc:1.14--pyhdfd78af_0' }" input: path versions diff --git a/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py old mode 100644 new mode 100755 diff --git a/modules/nf-core/fastp/main.nf b/modules/nf-core/fastp/main.nf index 5eeb9b09..2ca2d3ee 100644 --- a/modules/nf-core/fastp/main.nf +++ b/modules/nf-core/fastp/main.nf @@ -5,7 +5,7 @@ process FASTP { conda "bioconda::fastp=0.23.2" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/fastp:0.23.2--h79da9fb_0' : - 'quay.io/biocontainers/fastp:0.23.2--h79da9fb_0' }" + 'biocontainers/fastp:0.23.2--h79da9fb_0' }" input: tuple val(meta), path(reads) diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf index 9ae58381..07d5e433 100644 --- a/modules/nf-core/fastqc/main.nf +++ b/modules/nf-core/fastqc/main.nf @@ -5,7 +5,7 @@ process FASTQC { conda "bioconda::fastqc=0.11.9" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/fastqc:0.11.9--0' : - 'quay.io/biocontainers/fastqc:0.11.9--0' }" + 'biocontainers/fastqc:0.11.9--0' }" input: tuple val(meta), path(reads) diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index 4b604749..1fc387be 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -4,7 +4,7 @@ process MULTIQC { conda "bioconda::multiqc=1.14" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/multiqc:1.14--pyhdfd78af_0' : - 'quay.io/biocontainers/multiqc:1.14--pyhdfd78af_0' }" + 'biocontainers/multiqc:1.14--pyhdfd78af_0' }" input: path multiqc_files, stageAs: "?/*" diff --git a/modules/nf-core/samtools/flagstat/main.nf b/modules/nf-core/samtools/flagstat/main.nf index 2120cd7d..eb7e72fc 100644 --- a/modules/nf-core/samtools/flagstat/main.nf +++ b/modules/nf-core/samtools/flagstat/main.nf @@ -2,10 +2,10 @@ process SAMTOOLS_FLAGSTAT { tag "$meta.id" label 'process_single' - conda "bioconda::samtools=1.16.1" + conda "bioconda::samtools=1.17" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.16.1--h6899075_1' : - 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" + 'https://depot.galaxyproject.org/singularity/samtools:1.17--h00cdaf9_0' : + 'biocontainers/samtools:1.17--h00cdaf9_0' }" input: tuple val(meta), path(bam), path(bai) diff --git a/modules/nf-core/samtools/idxstats/main.nf b/modules/nf-core/samtools/idxstats/main.nf index a7b87d8b..a257d700 100644 --- a/modules/nf-core/samtools/idxstats/main.nf +++ b/modules/nf-core/samtools/idxstats/main.nf @@ -2,10 +2,10 @@ process SAMTOOLS_IDXSTATS { tag "$meta.id" label 'process_single' - conda "bioconda::samtools=1.16.1" + conda "bioconda::samtools=1.17" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.16.1--h6899075_1' : - 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" + 'https://depot.galaxyproject.org/singularity/samtools:1.17--h00cdaf9_0' : + 'biocontainers/samtools:1.17--h00cdaf9_0' }" input: tuple val(meta), path(bam), path(bai) diff --git a/modules/nf-core/samtools/index/main.nf b/modules/nf-core/samtools/index/main.nf index 8b95687a..0b20aa4b 100644 --- a/modules/nf-core/samtools/index/main.nf +++ b/modules/nf-core/samtools/index/main.nf @@ -2,10 +2,10 @@ process SAMTOOLS_INDEX { tag "$meta.id" label 'process_low' - conda "bioconda::samtools=1.16.1" + conda "bioconda::samtools=1.17" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.16.1--h6899075_1' : - 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" + 'https://depot.galaxyproject.org/singularity/samtools:1.17--h00cdaf9_0' : + 'biocontainers/samtools:1.17--h00cdaf9_0' }" input: tuple val(meta), path(input) diff --git a/modules/nf-core/samtools/sort/main.nf b/modules/nf-core/samtools/sort/main.nf index 84c167cd..1e5181d4 100644 --- a/modules/nf-core/samtools/sort/main.nf +++ b/modules/nf-core/samtools/sort/main.nf @@ -2,10 +2,10 @@ process SAMTOOLS_SORT { tag "$meta.id" label 'process_medium' - conda "bioconda::samtools=1.16.1" + conda "bioconda::samtools=1.17" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.16.1--h6899075_1' : - 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" + 'https://depot.galaxyproject.org/singularity/samtools:1.17--h00cdaf9_0' : + 'biocontainers/samtools:1.17--h00cdaf9_0' }" input: tuple val(meta), path(bam) @@ -21,9 +21,17 @@ process SAMTOOLS_SORT { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" + def sort_memory = (task.memory.mega/task.cpus).intValue() if ("$bam" == "${prefix}.bam") error "Input and output names are the same, use \"task.ext.prefix\" to disambiguate!" """ - samtools sort $args -@ $task.cpus -o ${prefix}.bam -T $prefix $bam + samtools sort \\ + $args \\ + -@ $task.cpus \\ + -m ${sort_memory}M \\ + -o ${prefix}.bam \\ + -T $prefix \\ + $bam + cat <<-END_VERSIONS > versions.yml "${task.process}": samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') diff --git a/modules/nf-core/samtools/stats/main.nf b/modules/nf-core/samtools/stats/main.nf index 0a2a3640..eb7f098b 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.16.1" + conda "bioconda::samtools=1.17" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.16.1--h6899075_1' : - 'quay.io/biocontainers/samtools:1.16.1--h6899075_1' }" + 'https://depot.galaxyproject.org/singularity/samtools:1.17--h00cdaf9_0' : + 'biocontainers/samtools:1.17--h00cdaf9_0' }" input: tuple val(meta), path(input), path(input_index) From 3ec4beb457699dd988d4c0933beba74074ab09d2 Mon Sep 17 00:00:00 2001 From: maxulysse Date: Mon, 8 May 2023 14:00:58 +0200 Subject: [PATCH 139/215] prettier --- modules.json | 42 +++++++++++------------------------------- 1 file changed, 11 insertions(+), 31 deletions(-) diff --git a/modules.json b/modules.json index 3a3ddeff..0b6daac5 100644 --- a/modules.json +++ b/modules.json @@ -8,75 +8,55 @@ "cat/fastq": { "branch": "master", "git_sha": "5c460c5a4736974abde2843294f35307ee2b0e5e", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "custom/dumpsoftwareversions": { "branch": "master", "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "fastp": { "branch": "master", "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "fastqc": { "branch": "master", "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "multiqc": { "branch": "master", "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "samtools/flagstat": { "branch": "master", "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "samtools/idxstats": { "branch": "master", "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "samtools/index": { "branch": "master", "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "samtools/sort": { "branch": "master", "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "samtools/stats": { "branch": "master", "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] } } } } } -} \ No newline at end of file +} From fcbff438bb3cdd894cfb864b31afc4a16f2dba2d Mon Sep 17 00:00:00 2001 From: maxulysse Date: Mon, 8 May 2023 14:03:46 +0200 Subject: [PATCH 140/215] drop quay.io from URI --- modules/local/blat_mirna.nf | 2 +- modules/local/bowtie_contaminants.nf | 2 +- modules/local/bowtie_genome.nf | 2 +- modules/local/bowtie_map_contaminants.nf | 2 +- modules/local/bowtie_map_mirna.nf | 2 +- modules/local/bowtie_mirna.nf | 2 +- modules/local/datatable_merge.nf | 2 +- modules/local/edger_qc.nf | 2 +- modules/local/filter_stats.nf | 2 +- modules/local/format_fasta_mirna.nf | 2 +- modules/local/mirdeep2_mapper.nf | 2 +- modules/local/mirdeep2_prepare.nf | 2 +- modules/local/mirdeep2_run.nf | 2 +- modules/local/mirtop_quant.nf | 2 +- modules/local/mirtrace.nf | 2 +- modules/local/parse_fasta_mirna.nf | 2 +- modules/local/seqcluster_collapse.nf | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/modules/local/blat_mirna.nf b/modules/local/blat_mirna.nf index 198e001c..7f8a2324 100644 --- a/modules/local/blat_mirna.nf +++ b/modules/local/blat_mirna.nf @@ -5,7 +5,7 @@ process BLAT_MIRNA { conda 'bioconda::blat=36' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/blat:36--0' : - 'quay.io/biocontainers/blat:36--0' }" + 'biocontainers/blat:36--0' }" input: val db_type diff --git a/modules/local/bowtie_contaminants.nf b/modules/local/bowtie_contaminants.nf index a68b8530..e6a594a7 100644 --- a/modules/local/bowtie_contaminants.nf +++ b/modules/local/bowtie_contaminants.nf @@ -4,7 +4,7 @@ process INDEX_CONTAMINANTS { conda 'bowtie2=2.4.5' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/bowtie2:2.4.5--py39hd2f7db1_2' : - 'quay.io/biocontainers/bowtie2:2.4.5--py36hfca12d5_2'}" + 'biocontainers/bowtie2:2.4.5--py36hfca12d5_2'}" input: path fasta diff --git a/modules/local/bowtie_genome.nf b/modules/local/bowtie_genome.nf index 1405467a..b132e1da 100644 --- a/modules/local/bowtie_genome.nf +++ b/modules/local/bowtie_genome.nf @@ -5,7 +5,7 @@ process INDEX_GENOME { conda 'bioconda::bowtie=1.3.1-4' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/bowtie%3A1.3.1--py39hd400a0c_2' : - 'quay.io/biocontainers/bowtie:1.3.1--py310h4070885_4' }" + 'biocontainers/bowtie:1.3.1--py310h4070885_4' }" input: path fasta diff --git a/modules/local/bowtie_map_contaminants.nf b/modules/local/bowtie_map_contaminants.nf index 09ad0162..d10f13b5 100644 --- a/modules/local/bowtie_map_contaminants.nf +++ b/modules/local/bowtie_map_contaminants.nf @@ -4,7 +4,7 @@ process BOWTIE_MAP_CONTAMINANTS { conda 'bowtie2=2.4.5' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/bowtie2:2.4.5--py39hd2f7db1_2' : - 'quay.io/biocontainers/bowtie2:2.4.5--py36hfca12d5_2' }" + 'biocontainers/bowtie2:2.4.5--py36hfca12d5_2' }" input: tuple val(meta), path(reads) diff --git a/modules/local/bowtie_map_mirna.nf b/modules/local/bowtie_map_mirna.nf index 8202838f..148b47f5 100644 --- a/modules/local/bowtie_map_mirna.nf +++ b/modules/local/bowtie_map_mirna.nf @@ -5,7 +5,7 @@ process BOWTIE_MAP_SEQ { conda 'bowtie=1.3.0-2 bioconda::samtools=1.13' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/mulled-v2-ffbf83a6b0ab6ec567a336cf349b80637135bca3:40128b496751b037e2bd85f6789e83d4ff8a4837-0' : - 'quay.io/biocontainers/mulled-v2-ffbf83a6b0ab6ec567a336cf349b80637135bca3:40128b496751b037e2bd85f6789e83d4ff8a4837-0' }" + 'biocontainers/mulled-v2-ffbf83a6b0ab6ec567a336cf349b80637135bca3:40128b496751b037e2bd85f6789e83d4ff8a4837-0' }" input: tuple val(meta), path(reads) diff --git a/modules/local/bowtie_mirna.nf b/modules/local/bowtie_mirna.nf index 601c9f43..9390730a 100644 --- a/modules/local/bowtie_mirna.nf +++ b/modules/local/bowtie_mirna.nf @@ -4,7 +4,7 @@ process INDEX_MIRNA { conda 'bioconda::bowtie=1.3.0-2' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/bowtie%3A1.3.1--py39hd400a0c_2' : - 'quay.io/biocontainers/bowtie:1.3.1--py310h4070885_4' }" + 'biocontainers/bowtie:1.3.1--py310h4070885_4' }" input: path fasta diff --git a/modules/local/datatable_merge.nf b/modules/local/datatable_merge.nf index 5b238c06..c71b9c4d 100644 --- a/modules/local/datatable_merge.nf +++ b/modules/local/datatable_merge.nf @@ -4,7 +4,7 @@ process TABLE_MERGE { conda 'conda-base::r-data.table=1.12.2' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/r-data.table:1.12.2' : - 'quay.io/biocontainers/r-data.table:1.12.2' }" + 'biocontainers/r-data.table:1.12.2' }" input: path mirtop diff --git a/modules/local/edger_qc.nf b/modules/local/edger_qc.nf index 0d8efe64..729d5eed 100644 --- a/modules/local/edger_qc.nf +++ b/modules/local/edger_qc.nf @@ -4,7 +4,7 @@ process EDGER_QC { conda 'bioconda::bioconductor-limma=3.50.0 bioconda::bioconductor-edger=3.36.0 conda-forge::r-data.table=1.14.2 conda-forge::r-gplots=3.1.1 conda-forge::r-statmod=1.4.36' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/mulled-v2-419bd7f10b2b902489ac63bbaafc7db76f8e0ae1:709335c37934db1b481054cbec637c6e5b5971cb-0' : - 'quay.io/biocontainers/mulled-v2-419bd7f10b2b902489ac63bbaafc7db76f8e0ae1:709335c37934db1b481054cbec637c6e5b5971cb-0' }" + 'biocontainers/mulled-v2-419bd7f10b2b902489ac63bbaafc7db76f8e0ae1:709335c37934db1b481054cbec637c6e5b5971cb-0' }" input: path input_files diff --git a/modules/local/filter_stats.nf b/modules/local/filter_stats.nf index c9336f22..18e7016b 100644 --- a/modules/local/filter_stats.nf +++ b/modules/local/filter_stats.nf @@ -4,7 +4,7 @@ process FILTER_STATS { conda 'bowtie2=2.4.5' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/bowtie2:2.4.5--py39hd2f7db1_2' : - 'quay.io/biocontainers/bowtie2:2.4.5--py36hfca12d5_2' }" + 'biocontainers/bowtie2:2.4.5--py36hfca12d5_2' }" input: tuple val(meta), path(reads) diff --git a/modules/local/format_fasta_mirna.nf b/modules/local/format_fasta_mirna.nf index 2c39c0aa..3e247ce4 100644 --- a/modules/local/format_fasta_mirna.nf +++ b/modules/local/format_fasta_mirna.nf @@ -7,7 +7,7 @@ process FORMAT_FASTA_MIRNA { conda 'bioconda::fastx_toolkit=0.0.14-9' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/fastx_toolkit:0.0.14--he1b5a44_8' : - 'quay.io/biocontainers/fastx_toolkit:0.0.14--he1b5a44_8' }" + 'biocontainers/fastx_toolkit:0.0.14--he1b5a44_8' }" input: path fasta diff --git a/modules/local/mirdeep2_mapper.nf b/modules/local/mirdeep2_mapper.nf index 2293ef87..842af6e6 100644 --- a/modules/local/mirdeep2_mapper.nf +++ b/modules/local/mirdeep2_mapper.nf @@ -7,7 +7,7 @@ process MIRDEEP2_MAPPER { conda 'bioconda::mirdeep2=2.0.1' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/mirdeep2:2.0.1.3--hdfd78af_1' : - 'quay.io/biocontainers/mirdeep2:2.0.1.3--hdfd78af_1' }" + 'biocontainers/mirdeep2:2.0.1.3--hdfd78af_1' }" input: tuple val(meta), path(reads) diff --git a/modules/local/mirdeep2_prepare.nf b/modules/local/mirdeep2_prepare.nf index 3d117d4a..7e2f2437 100644 --- a/modules/local/mirdeep2_prepare.nf +++ b/modules/local/mirdeep2_prepare.nf @@ -6,7 +6,7 @@ process MIRDEEP2_PIGZ { conda 'bioconda::bioconvert=0.4.3' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/bioconvert:0.4.3--py_0' : - 'quay.io/biocontainers/bioconvert:0.4.3--py_0' }" + 'biocontainers/bioconvert:0.4.3--py_0' }" input: tuple val(meta), path(reads) diff --git a/modules/local/mirdeep2_run.nf b/modules/local/mirdeep2_run.nf index 2035658c..74044e4a 100644 --- a/modules/local/mirdeep2_run.nf +++ b/modules/local/mirdeep2_run.nf @@ -7,7 +7,7 @@ process MIRDEEP2_RUN { conda 'bioconda::mirdeep2=2.0.1' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/mirdeep2:2.0.1.3--hdfd78af_1' : - 'quay.io/biocontainers/mirdeep2:2.0.1.3--hdfd78af_1' }" + 'biocontainers/mirdeep2:2.0.1.3--hdfd78af_1' }" input: path fasta diff --git a/modules/local/mirtop_quant.nf b/modules/local/mirtop_quant.nf index c4e76a3c..3ebb65ac 100644 --- a/modules/local/mirtop_quant.nf +++ b/modules/local/mirtop_quant.nf @@ -4,7 +4,7 @@ process MIRTOP_QUANT { conda 'mirtop=0.4.25 bioconda::samtools=1.15.1 conda-base::r-base=4.1.1 conda-base::r-data.table=1.14.2' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/mulled-v2-0c13ef770dd7cc5c76c2ce23ba6669234cf03385:63be019f50581cc5dfe4fc0f73ae50f2d4d661f7-0' : - 'quay.io/biocontainers/mulled-v2-0c13ef770dd7cc5c76c2ce23ba6669234cf03385:63be019f50581cc5dfe4fc0f73ae50f2d4d661f7-0' }" + 'biocontainers/mulled-v2-0c13ef770dd7cc5c76c2ce23ba6669234cf03385:63be019f50581cc5dfe4fc0f73ae50f2d4d661f7-0' }" input: path ("bams/*") diff --git a/modules/local/mirtrace.nf b/modules/local/mirtrace.nf index f37a4b3c..f576ebc0 100644 --- a/modules/local/mirtrace.nf +++ b/modules/local/mirtrace.nf @@ -4,7 +4,7 @@ process MIRTRACE_RUN { conda 'bioconda::mirtrace=1.0.1' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/mirtrace:1.0.1--hdfd78af_1' : - 'quay.io/biocontainers/mirtrace:1.0.1--hdfd78af_1' }" + 'biocontainers/mirtrace:1.0.1--hdfd78af_1' }" input: tuple val(adapter), val(ids), path(reads) diff --git a/modules/local/parse_fasta_mirna.nf b/modules/local/parse_fasta_mirna.nf index 5418f597..ab7a91f0 100644 --- a/modules/local/parse_fasta_mirna.nf +++ b/modules/local/parse_fasta_mirna.nf @@ -4,7 +4,7 @@ process PARSE_FASTA_MIRNA { conda 'bioconda::seqkit=2.3.1' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/seqkit:2.3.1--h9ee0642_0' : - 'quay.io/biocontainers/seqkit:2.3.1--h9ee0642_0' }" + 'biocontainers/seqkit:2.3.1--h9ee0642_0' }" input: path fasta diff --git a/modules/local/seqcluster_collapse.nf b/modules/local/seqcluster_collapse.nf index 36645ee1..39f6ce85 100644 --- a/modules/local/seqcluster_collapse.nf +++ b/modules/local/seqcluster_collapse.nf @@ -5,7 +5,7 @@ process SEQCLUSTER_SEQUENCES { conda 'bioconda::seqcluster=1.2.9-0' container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/seqcluster:1.2.9--pyh5e36f6f_0' : - 'quay.io/biocontainers/seqcluster:1.2.8--pyh5e36f6f_0' }" + 'biocontainers/seqcluster:1.2.8--pyh5e36f6f_0' }" input: tuple val(meta), path(reads) From 33ce882f44555d14b0f996ae88ded1a9a2fc4b62 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 8 May 2023 13:03:14 +0000 Subject: [PATCH 141/215] Proposed fix for MirTrace uses untrimmed fastq input #242 --- CHANGELOG.md | 1 + subworkflows/local/fastqc_fastp.nf | 2 +- workflows/smrnaseq.nf | 8 ++++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ce24b8f..8024dbeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Enhancements & fixes - [[#238](https://github.com/nf-core/smrnaseq/issues/238)] - Restored the missing mirtop outputs +- [[#242](https://github.com/nf-core/smrnaseq/issues/242)] - Fixed mirtrace using wrong input fastq files (untrimmed) ## [v2.2.0](https://github.com/nf-core/smrnaseq/releases/tag/2.2.0) - 2023-04-26 diff --git a/subworkflows/local/fastqc_fastp.nf b/subworkflows/local/fastqc_fastp.nf index 3ab260a8..9e4d952e 100644 --- a/subworkflows/local/fastqc_fastp.nf +++ b/subworkflows/local/fastqc_fastp.nf @@ -105,7 +105,7 @@ workflow FASTQC_FASTP { trim_log // channel: [ val(meta), [ log ] ] trim_reads_fail // channel: [ val(meta), [ fastq.gz ] ] trim_reads_merged // channel: [ val(meta), [ fastq.gz ] ] - adapterseq // channel: [ val(meat), [ adapterseq ] ] + adapterseq // channel: [ val(meta), [ adapterseq ] ] fastqc_raw_html // channel: [ val(meta), [ html ] ] fastqc_raw_zip // channel: [ val(meta), [ zip ] ] diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index f98bcc74..ad5ecfef 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -137,12 +137,12 @@ workflow SMRNASEQ { // SUBWORKFLOW: mirtrace QC // FASTQC_FASTP.out.adapterseq - .join( ch_cat_fastq ) - .map { meta, adapterseq, fastq -> [adapterseq, meta.id, fastq] } + .join( FASTQC_FASTP.out.reads ) + .map { meta, adapterseq, reads -> [adapterseq, meta.id, reads] } .groupTuple() - .set { ch_mitrace_inputs } + .set { ch_mirtrace_inputs } - MIRTRACE(ch_mitrace_inputs) + MIRTRACE(ch_mirtrace_inputs) ch_versions = ch_versions.mix(MIRTRACE.out.versions.ifEmpty(null)) From 54554a315ed0d56a1568702fb3f68a028d2b9bde Mon Sep 17 00:00:00 2001 From: Rob Syme Date: Mon, 8 May 2023 13:43:19 +0000 Subject: [PATCH 142/215] Remove `map` operation in mirtrace subworkflow --- subworkflows/local/mirtrace.nf | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/subworkflows/local/mirtrace.nf b/subworkflows/local/mirtrace.nf index 566b7a1b..317c4444 100644 --- a/subworkflows/local/mirtrace.nf +++ b/subworkflows/local/mirtrace.nf @@ -9,9 +9,7 @@ workflow MIRTRACE { reads // channel: [ val(adapterseq), [ val(ids) ], [ path(reads) ] ] main: - reads - | map { adapterseq, ids, read_collection -> [adapterseq, ids, read_collection*.first()]} - | MIRTRACE_RUN + reads | MIRTRACE_RUN emit: results = MIRTRACE_RUN.out.mirtrace From 635c621be85abfc6f5e1654f5906974208e7b87a Mon Sep 17 00:00:00 2001 From: Maxime U Garcia Date: Thu, 11 May 2023 12:17:31 +0200 Subject: [PATCH 143/215] Update nextflow.config --- nextflow.config | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/nextflow.config b/nextflow.config index 6f7f0088..e1ed76d6 100644 --- a/nextflow.config +++ b/nextflow.config @@ -136,7 +136,6 @@ profiles { } docker { docker.enabled = true - docker.registry = 'quay.io' docker.userEmulation = true docker.runOptions = '-u $(id -u):$(id -g)' conda.enabled = false @@ -161,7 +160,6 @@ profiles { } podman { podman.enabled = true - podman.registry = 'quay.io' conda.enabled = false docker.enabled = false singularity.enabled = false @@ -227,6 +225,12 @@ env { // Capture exit codes from upstream processes when piping process.shell = ['/bin/bash', '-euo', 'pipefail'] +// Set default registry for Docker and Podman independent of -profile +// Will not be used unless Docker / Podman are enabled +// Set to your registry if you have a mirror of containers +docker.registry = 'quay.io' +podman.registry = 'quay.io' + def trace_timestamp = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss') timeline { enabled = true From 920c439eec2e1341d30e9332c48c209dc25b5fc9 Mon Sep 17 00:00:00 2001 From: Adam Talbot Date: Thu, 11 May 2023 16:51:47 +0100 Subject: [PATCH 144/215] Adds awsecr profile for using with AWS containers where possible Adds: - Additional profile awsecr which includes conf/awsecr.config - awsecr.config sets the default registry to public.ecr.aws and pulls as many biocontainers from that registry as possible - Where unavailable, sets full URI to docker containers that are available. --- .github/workflows/awsfulltest.yml | 2 +- conf/awsecr.config | 26 ++++++++++++++++++++++++++ nextflow.config | 3 +++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 conf/awsecr.config diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index b1d5f94e..15766549 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -24,7 +24,7 @@ jobs: { "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/smrnaseq/results-${{ github.sha }}" } - profiles: test_full,aws_tower + profiles: test_full,aws_tower,awsecr - uses: actions/upload-artifact@v3 with: name: Tower debug log file diff --git a/conf/awsecr.config b/conf/awsecr.config new file mode 100644 index 00000000..799c13d1 --- /dev/null +++ b/conf/awsecr.config @@ -0,0 +1,26 @@ +/* +Config to set public AWS ECR images wherever possible +This improves speed when running on AWS infrastructure. +Use this as an example template when using your own private registry. +*/ + +docker.registry = 'public.ecr.aws' +podman.registry = 'public.ecr.aws' + +process { + withName: '.*:SAMPLESHEET_CHECK' { + container = "public.ecr.aws/docker/library/python:3.8.16" + } + withName: '.*:BOWTIE_MAP.*' { + container = "quay.io/biocontainers/mulled-v2-ffbf83a6b0ab6ec567a336cf349b80637135bca3:40128b496751b037e2bd85f6789e83d4ff8a4837-0" + } + withName: '.*:EDGER_QC' { + container = 'quay.io/biocontainers/mulled-v2-419bd7f10b2b902489ac63bbaafc7db76f8e0ae1:709335c37934db1b481054cbec637c6e5b5971cb-0' + } + withName: '.*:MIRTOP_QUANT' { + container = "quay.io/biocontainers/mulled-v2-0c13ef770dd7cc5c76c2ce23ba6669234cf03385:63be019f50581cc5dfe4fc0f73ae50f2d4d661f7-0" + } + withName: '.*:TABLE_MERGE' { + container = "quay.io/biocontainers/r-data.table:1.12.2" + } +} \ No newline at end of file diff --git a/nextflow.config b/nextflow.config index e1ed76d6..3aed9f26 100644 --- a/nextflow.config +++ b/nextflow.config @@ -199,6 +199,9 @@ profiles { executor.cpus = 16 executor.memory = 60.GB } + awsecr { + includeConfig 'conf/awsecr.config' + } test { includeConfig 'conf/test.config' } test_no_genome { includeConfig 'conf/test_no_genome.config' } test_full { includeConfig 'conf/test_full.config' } From f098cadec1412345d777b6541ef760d5098415b1 Mon Sep 17 00:00:00 2001 From: Adam Talbot Date: Thu, 11 May 2023 16:56:25 +0100 Subject: [PATCH 145/215] Add AWS ECR profile to small AWS test --- .github/workflows/awstest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml index ea58cd42..b021f0fe 100644 --- a/.github/workflows/awstest.yml +++ b/.github/workflows/awstest.yml @@ -22,7 +22,7 @@ jobs: { "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/smrnaseq/results-test-${{ github.sha }}" } - profiles: test,aws_tower + profiles: test,aws_tower,awsecr - uses: actions/upload-artifact@v3 with: name: Tower debug log file From b6a090fd46810c9928b4e5ad670597a224a5424f Mon Sep 17 00:00:00 2001 From: Adam Talbot Date: Thu, 11 May 2023 16:58:44 +0100 Subject: [PATCH 146/215] Remove aws_tower profile --- .github/workflows/awsfulltest.yml | 2 +- .github/workflows/awstest.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index 15766549..c50e6d2d 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -24,7 +24,7 @@ jobs: { "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/smrnaseq/results-${{ github.sha }}" } - profiles: test_full,aws_tower,awsecr + profiles: test_full,awsecr - uses: actions/upload-artifact@v3 with: name: Tower debug log file diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml index b021f0fe..8d249d69 100644 --- a/.github/workflows/awstest.yml +++ b/.github/workflows/awstest.yml @@ -22,7 +22,7 @@ jobs: { "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/smrnaseq/results-test-${{ github.sha }}" } - profiles: test,aws_tower,awsecr + profiles: test,awsecr - uses: actions/upload-artifact@v3 with: name: Tower debug log file From 11c0f976e2eb1fec0a130a8f978e77dee29372b6 Mon Sep 17 00:00:00 2001 From: Adam Talbot Date: Thu, 11 May 2023 16:59:51 +0100 Subject: [PATCH 147/215] Add final newline to awsecr.config --- conf/awsecr.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/awsecr.config b/conf/awsecr.config index 799c13d1..86abed2d 100644 --- a/conf/awsecr.config +++ b/conf/awsecr.config @@ -23,4 +23,4 @@ process { withName: '.*:TABLE_MERGE' { container = "quay.io/biocontainers/r-data.table:1.12.2" } -} \ No newline at end of file +} From 4742751fc0f168dacf36595a7bef62adfc3863c3 Mon Sep 17 00:00:00 2001 From: Adam Talbot Date: Fri, 12 May 2023 10:27:58 +0100 Subject: [PATCH 148/215] Style and language improvements --- .github/workflows/awsfulltest.yml | 2 +- .github/workflows/awstest.yml | 2 +- conf/awsecr.config | 26 -------------------------- conf/public_aws_ecr.config | 30 ++++++++++++++++++++++++++++++ nextflow.config | 4 ++-- 5 files changed, 34 insertions(+), 30 deletions(-) delete mode 100644 conf/awsecr.config create mode 100644 conf/public_aws_ecr.config diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index c50e6d2d..f96fb17c 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -24,7 +24,7 @@ jobs: { "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/smrnaseq/results-${{ github.sha }}" } - profiles: test_full,awsecr + profiles: test_full,public_aws_ecr - uses: actions/upload-artifact@v3 with: name: Tower debug log file diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml index 8d249d69..a1f96d73 100644 --- a/.github/workflows/awstest.yml +++ b/.github/workflows/awstest.yml @@ -22,7 +22,7 @@ jobs: { "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/smrnaseq/results-test-${{ github.sha }}" } - profiles: test,awsecr + profiles: test,public_aws_ecr - uses: actions/upload-artifact@v3 with: name: Tower debug log file diff --git a/conf/awsecr.config b/conf/awsecr.config deleted file mode 100644 index 86abed2d..00000000 --- a/conf/awsecr.config +++ /dev/null @@ -1,26 +0,0 @@ -/* -Config to set public AWS ECR images wherever possible -This improves speed when running on AWS infrastructure. -Use this as an example template when using your own private registry. -*/ - -docker.registry = 'public.ecr.aws' -podman.registry = 'public.ecr.aws' - -process { - withName: '.*:SAMPLESHEET_CHECK' { - container = "public.ecr.aws/docker/library/python:3.8.16" - } - withName: '.*:BOWTIE_MAP.*' { - container = "quay.io/biocontainers/mulled-v2-ffbf83a6b0ab6ec567a336cf349b80637135bca3:40128b496751b037e2bd85f6789e83d4ff8a4837-0" - } - withName: '.*:EDGER_QC' { - container = 'quay.io/biocontainers/mulled-v2-419bd7f10b2b902489ac63bbaafc7db76f8e0ae1:709335c37934db1b481054cbec637c6e5b5971cb-0' - } - withName: '.*:MIRTOP_QUANT' { - container = "quay.io/biocontainers/mulled-v2-0c13ef770dd7cc5c76c2ce23ba6669234cf03385:63be019f50581cc5dfe4fc0f73ae50f2d4d661f7-0" - } - withName: '.*:TABLE_MERGE' { - container = "quay.io/biocontainers/r-data.table:1.12.2" - } -} diff --git a/conf/public_aws_ecr.config b/conf/public_aws_ecr.config new file mode 100644 index 00000000..8152e14a --- /dev/null +++ b/conf/public_aws_ecr.config @@ -0,0 +1,30 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + AWS ECR Config +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Config to set public AWS ECR images wherever possible + This improves speed when running on AWS infrastructure. + Use this as an example template when using your own private registry. +---------------------------------------------------------------------------------------- +*/ + +docker.registry = 'public.ecr.aws' +podman.registry = 'public.ecr.aws' + +process { + withName: '.*:SAMPLESHEET_CHECK' { + container = "quay.io/biocontainers/python:3.8.3" + } + withName: '.*:BOWTIE_MAP.*' { + container = 'quay.io/biocontainers/mulled-v2-ffbf83a6b0ab6ec567a336cf349b80637135bca3:40128b496751b037e2bd85f6789e83d4ff8a4837-0' + } + withName: '.*:EDGER_QC' { + container = 'quay.io/biocontainers/mulled-v2-419bd7f10b2b902489ac63bbaafc7db76f8e0ae1:709335c37934db1b481054cbec637c6e5b5971cb-0' + } + withName: '.*:MIRTOP_QUANT' { + container = 'quay.io/biocontainers/mulled-v2-0c13ef770dd7cc5c76c2ce23ba6669234cf03385:63be019f50581cc5dfe4fc0f73ae50f2d4d661f7-0' + } + withName: '.*:TABLE_MERGE' { + container = 'quay.io/biocontainers/r-data.table:1.12.2' + } +} diff --git a/nextflow.config b/nextflow.config index 3aed9f26..2f9dd945 100644 --- a/nextflow.config +++ b/nextflow.config @@ -199,8 +199,8 @@ profiles { executor.cpus = 16 executor.memory = 60.GB } - awsecr { - includeConfig 'conf/awsecr.config' + public_aws_ecr { + includeConfig 'conf/public_aws_ecr.config' } test { includeConfig 'conf/test.config' } test_no_genome { includeConfig 'conf/test_no_genome.config' } From 5f4f3386c62bb6cb896465922d13a98ebcf6fbdb Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 12 May 2023 13:36:15 +0000 Subject: [PATCH 149/215] Bump to 2.3.0dev --- CHANGELOG.md | 5 ++++- nextflow.config | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8024dbeb..2a55827c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,10 @@ 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). -## [v2.2.1](https://github.com/nf-core/smrnaseq/releases/tag/2.2.1) - 2023-05-08 +## Current dev + +Nothing yet +## [v2.2.1](https://github.com/nf-core/smrnaseq/releases/tag/2.2.1) - 2023-05-12 ### Enhancements & fixes diff --git a/nextflow.config b/nextflow.config index 2f9dd945..68d6dee4 100644 --- a/nextflow.config +++ b/nextflow.config @@ -259,7 +259,7 @@ manifest { description = """Small RNA-Seq Best Practice Analysis Pipeline.""" mainScript = 'main.nf' nextflowVersion = '!>=22.10.1' - version = '2.2.1' + version = '2.3.0dev' doi = '' } From dd0595f38d4eea49c113ab3425d831f9727344dd Mon Sep 17 00:00:00 2001 From: Adam Talbot Date: Wed, 31 May 2023 11:36:09 +0100 Subject: [PATCH 150/215] Remove glob from process definition when using ECR container --- CHANGELOG.md | 3 ++- conf/public_aws_ecr.config | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a55827c..ba115168 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Current dev -Nothing yet +- Remove globs from process alias when using ECR containers + ## [v2.2.1](https://github.com/nf-core/smrnaseq/releases/tag/2.2.1) - 2023-05-12 ### Enhancements & fixes diff --git a/conf/public_aws_ecr.config b/conf/public_aws_ecr.config index 8152e14a..39c8f881 100644 --- a/conf/public_aws_ecr.config +++ b/conf/public_aws_ecr.config @@ -12,19 +12,19 @@ docker.registry = 'public.ecr.aws' podman.registry = 'public.ecr.aws' process { - withName: '.*:SAMPLESHEET_CHECK' { + withName: 'SAMPLESHEET_CHECK' { container = "quay.io/biocontainers/python:3.8.3" } - withName: '.*:BOWTIE_MAP.*' { + withName: 'BOWTIE_MAP' { container = 'quay.io/biocontainers/mulled-v2-ffbf83a6b0ab6ec567a336cf349b80637135bca3:40128b496751b037e2bd85f6789e83d4ff8a4837-0' } - withName: '.*:EDGER_QC' { + withName: 'EDGER_QC' { container = 'quay.io/biocontainers/mulled-v2-419bd7f10b2b902489ac63bbaafc7db76f8e0ae1:709335c37934db1b481054cbec637c6e5b5971cb-0' } - withName: '.*:MIRTOP_QUANT' { + withName: 'MIRTOP_QUANT' { container = 'quay.io/biocontainers/mulled-v2-0c13ef770dd7cc5c76c2ce23ba6669234cf03385:63be019f50581cc5dfe4fc0f73ae50f2d4d661f7-0' } - withName: '.*:TABLE_MERGE' { + withName: 'TABLE_MERGE' { container = 'quay.io/biocontainers/r-data.table:1.12.2' } } From dbe981d2006f679484b8ec3a0c5bd0799d06bb00 Mon Sep 17 00:00:00 2001 From: Adam Talbot Date: Wed, 31 May 2023 11:38:59 +0100 Subject: [PATCH 151/215] fixup --- conf/public_aws_ecr.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/public_aws_ecr.config b/conf/public_aws_ecr.config index 39c8f881..4febe35f 100644 --- a/conf/public_aws_ecr.config +++ b/conf/public_aws_ecr.config @@ -15,7 +15,7 @@ process { withName: 'SAMPLESHEET_CHECK' { container = "quay.io/biocontainers/python:3.8.3" } - withName: 'BOWTIE_MAP' { + withName: 'BOWTIE_MAP.*' { container = 'quay.io/biocontainers/mulled-v2-ffbf83a6b0ab6ec567a336cf349b80637135bca3:40128b496751b037e2bd85f6789e83d4ff8a4837-0' } withName: 'EDGER_QC' { From 0e76821dd3ae4aac9f265b029bfcd8c00a8f2ef4 Mon Sep 17 00:00:00 2001 From: Adam Talbot Date: Wed, 31 May 2023 11:40:23 +0100 Subject: [PATCH 152/215] Changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba115168..1dcf9a6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Current dev -- Remove globs from process alias when using ECR containers +- [[#253]](https://github.com/nf-core/smrnaseq/pull/253) - Remove globs from process alias when using ECR containers ## [v2.2.1](https://github.com/nf-core/smrnaseq/releases/tag/2.2.1) - 2023-05-12 From f570c385c1364831045fe72332b026f01c40edfd Mon Sep 17 00:00:00 2001 From: Maxime U Garcia Date: Wed, 31 May 2023 16:47:55 +0200 Subject: [PATCH 153/215] Apply suggestions from code review --- CHANGELOG.md | 2 +- nextflow.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1dcf9a6a..5553c523 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 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). -## Current dev +## [v2.2.2](https://github.com/nf-core/smrnaseq/releases/tag/2.2.2) - 2023-06-01``` - [[#253]](https://github.com/nf-core/smrnaseq/pull/253) - Remove globs from process alias when using ECR containers diff --git a/nextflow.config b/nextflow.config index 68d6dee4..5a6952df 100644 --- a/nextflow.config +++ b/nextflow.config @@ -259,7 +259,7 @@ manifest { description = """Small RNA-Seq Best Practice Analysis Pipeline.""" mainScript = 'main.nf' nextflowVersion = '!>=22.10.1' - version = '2.3.0dev' + version = '2.2.2' doi = '' } From 16ac6b2611ae686cd4db70356eaa421b281eb438 Mon Sep 17 00:00:00 2001 From: Maxime U Garcia Date: Wed, 31 May 2023 16:48:16 +0200 Subject: [PATCH 154/215] Apply suggestions from code review --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5553c523..c5b5af39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 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). -## [v2.2.2](https://github.com/nf-core/smrnaseq/releases/tag/2.2.2) - 2023-06-01``` +## [v2.2.2](https://github.com/nf-core/smrnaseq/releases/tag/2.2.2) - 2023-06-01 - [[#253]](https://github.com/nf-core/smrnaseq/pull/253) - Remove globs from process alias when using ECR containers From dd3e01677061777d3aa4d92839b3814d25330d10 Mon Sep 17 00:00:00 2001 From: Maxime U Garcia Date: Wed, 31 May 2023 16:51:03 +0200 Subject: [PATCH 155/215] Update ci.yml --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c4bd5555..1afd21e8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: strategy: matrix: NXF_VER: - - "22.10.1" + - "23.04.1" - "latest-everything" profile: - "test" From dda769d91c14b79e3a1d922bf2f6bd3ae8cab90b Mon Sep 17 00:00:00 2001 From: Adam Talbot <12817534+adamrtalbot@users.noreply.github.com> Date: Mon, 19 Jun 2023 13:51:11 +0000 Subject: [PATCH 156/215] Remove public_aws_ecr profile --- .github/workflows/awsfulltest.yml | 2 +- .github/workflows/awstest.yml | 2 +- CHANGELOG.md | 4 ++++ conf/public_aws_ecr.config | 30 ------------------------------ nextflow.config | 3 --- 5 files changed, 6 insertions(+), 35 deletions(-) delete mode 100644 conf/public_aws_ecr.config diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index f96fb17c..5d00bc97 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -24,7 +24,7 @@ jobs: { "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/smrnaseq/results-${{ github.sha }}" } - profiles: test_full,public_aws_ecr + profiles: test_full - uses: actions/upload-artifact@v3 with: name: Tower debug log file diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml index a1f96d73..7d4c357c 100644 --- a/.github/workflows/awstest.yml +++ b/.github/workflows/awstest.yml @@ -22,7 +22,7 @@ jobs: { "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/smrnaseq/results-test-${{ github.sha }}" } - profiles: test,public_aws_ecr + profiles: test - uses: actions/upload-artifact@v3 with: name: Tower debug log file diff --git a/CHANGELOG.md b/CHANGELOG.md index c5b5af39..2ca1a1cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ 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). +## dev + +- Remove public_aws_ecr profile + ## [v2.2.2](https://github.com/nf-core/smrnaseq/releases/tag/2.2.2) - 2023-06-01 - [[#253]](https://github.com/nf-core/smrnaseq/pull/253) - Remove globs from process alias when using ECR containers diff --git a/conf/public_aws_ecr.config b/conf/public_aws_ecr.config deleted file mode 100644 index 4febe35f..00000000 --- a/conf/public_aws_ecr.config +++ /dev/null @@ -1,30 +0,0 @@ -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - AWS ECR Config -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Config to set public AWS ECR images wherever possible - This improves speed when running on AWS infrastructure. - Use this as an example template when using your own private registry. ----------------------------------------------------------------------------------------- -*/ - -docker.registry = 'public.ecr.aws' -podman.registry = 'public.ecr.aws' - -process { - withName: 'SAMPLESHEET_CHECK' { - container = "quay.io/biocontainers/python:3.8.3" - } - withName: 'BOWTIE_MAP.*' { - container = 'quay.io/biocontainers/mulled-v2-ffbf83a6b0ab6ec567a336cf349b80637135bca3:40128b496751b037e2bd85f6789e83d4ff8a4837-0' - } - withName: 'EDGER_QC' { - container = 'quay.io/biocontainers/mulled-v2-419bd7f10b2b902489ac63bbaafc7db76f8e0ae1:709335c37934db1b481054cbec637c6e5b5971cb-0' - } - withName: 'MIRTOP_QUANT' { - container = 'quay.io/biocontainers/mulled-v2-0c13ef770dd7cc5c76c2ce23ba6669234cf03385:63be019f50581cc5dfe4fc0f73ae50f2d4d661f7-0' - } - withName: 'TABLE_MERGE' { - container = 'quay.io/biocontainers/r-data.table:1.12.2' - } -} diff --git a/nextflow.config b/nextflow.config index 5a6952df..ecaa7ccb 100644 --- a/nextflow.config +++ b/nextflow.config @@ -199,9 +199,6 @@ profiles { executor.cpus = 16 executor.memory = 60.GB } - public_aws_ecr { - includeConfig 'conf/public_aws_ecr.config' - } test { includeConfig 'conf/test.config' } test_no_genome { includeConfig 'conf/test_no_genome.config' } test_full { includeConfig 'conf/test_full.config' } From 891ccfaa00bb9496d2f99d8551a5371ed8e6d759 Mon Sep 17 00:00:00 2001 From: Adam Talbot Date: Tue, 27 Jun 2023 09:21:35 +0100 Subject: [PATCH 157/215] Min nextflow test 22.10.1 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1afd21e8..c4bd5555 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: strategy: matrix: NXF_VER: - - "23.04.1" + - "22.10.1" - "latest-everything" profile: - "test" From d0d600a043fac5dee97d03bd0d9e359ba8babe0f Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Fri, 30 Jun 2023 16:15:30 +0000 Subject: [PATCH 158/215] Template update for nf-core/tools version 2.9 --- .github/CONTRIBUTING.md | 1 - .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- .github/workflows/awsfulltest.yml | 11 +- .github/workflows/awstest.yml | 10 +- .github/workflows/ci.yml | 2 +- .gitpod.yml | 5 + CHANGELOG.md | 2 +- CITATIONS.md | 6 + README.md | 6 +- assets/methods_description_template.yml | 12 +- assets/multiqc_config.yml | 4 +- assets/nf-core-smrnaseq_logo_light.png | Bin 11484 -> 74188 bytes assets/slackreport.json | 2 +- conf/test_full.config | 2 - docs/usage.md | 6 +- lib/NfcoreSchema.groovy | 530 ------------------------ lib/NfcoreTemplate.groovy | 2 +- lib/WorkflowMain.groovy | 37 -- lib/WorkflowSmrnaseq.groovy | 45 +- main.nf | 16 + nextflow.config | 54 ++- nextflow_schema.json | 36 +- workflows/smrnaseq.nf | 25 +- 23 files changed, 177 insertions(+), 639 deletions(-) delete mode 100755 lib/NfcoreSchema.groovy diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index b24dd094..33a2c027 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -116,4 +116,3 @@ To get started: Devcontainer specs: - [DevContainer config](.devcontainer/devcontainer.json) -- [Dockerfile](.devcontainer/Dockerfile) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 137da49f..335a06b1 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -42,7 +42,7 @@ body: attributes: label: System information description: | - * Nextflow version _(eg. 22.10.1)_ + * Nextflow version _(eg. 23.04.0)_ * Hardware _(eg. HPC, Desktop, Cloud)_ * Executor _(eg. slurm, local, awsbatch)_ * Container engine: _(e.g. Docker, Singularity, Conda, Podman, Shifter, Charliecloud, or Apptainer)_ diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index 5fe68194..f8707f63 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Launch workflow via tower - uses: seqeralabs/action-tower-launch@v1 + uses: seqeralabs/action-tower-launch@v2 # TODO nf-core: You can customise AWS full pipeline tests as required # Add full size test data (but still relatively small datasets for few samples) # on the `test_full.config` test runs with only one set of parameters @@ -22,13 +22,18 @@ jobs: workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }} access_token: ${{ secrets.TOWER_ACCESS_TOKEN }} compute_env: ${{ secrets.TOWER_COMPUTE_ENV }} + revision: ${{ github.sha }} workdir: s3://${{ secrets.AWS_S3_BUCKET }}/work/smrnaseq/work-${{ github.sha }} parameters: | { + "hook_url": "${{ secrets.MEGATESTS_ALERTS_SLACK_HOOK_URL }}", "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/smrnaseq/results-${{ github.sha }}" } - profiles: test_full,aws_tower + profiles: test_full + - uses: actions/upload-artifact@v3 with: name: Tower debug log file - path: tower_action_*.log + path: | + tower_action_*.log + tower_action_*.json diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml index ea58cd42..84d22f1c 100644 --- a/.github/workflows/awstest.yml +++ b/.github/workflows/awstest.yml @@ -12,18 +12,22 @@ jobs: steps: # Launch workflow using Tower CLI tool action - name: Launch workflow via tower - uses: seqeralabs/action-tower-launch@v1 + uses: seqeralabs/action-tower-launch@v2 with: workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }} access_token: ${{ secrets.TOWER_ACCESS_TOKEN }} compute_env: ${{ secrets.TOWER_COMPUTE_ENV }} + revision: ${{ github.sha }} workdir: s3://${{ secrets.AWS_S3_BUCKET }}/work/smrnaseq/work-${{ github.sha }} parameters: | { "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/smrnaseq/results-test-${{ github.sha }}" } - profiles: test,aws_tower + profiles: test + - uses: actions/upload-artifact@v3 with: name: Tower debug log file - path: tower_action_*.log + path: | + tower_action_*.log + tower_action_*.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d0902c8c..d40ffd75 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: strategy: matrix: NXF_VER: - - "22.10.1" + - "23.04.0" - "latest-everything" steps: - name: Check out pipeline code diff --git a/.gitpod.yml b/.gitpod.yml index 85d95ecc..25488dcc 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -1,4 +1,9 @@ image: nfcore/gitpod:latest +tasks: + - name: Update Nextflow and setup pre-commit + command: | + pre-commit install --install-hooks + nextflow self-update vscode: extensions: # based on nf-core.nf-core-extensionpack diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ba2e33a..900274f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 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). -## v2.2.0 - [date] +## v2.2.2 - [date] Initial release of nf-core/smrnaseq, created with the [nf-core](https://nf-co.re/) template. diff --git a/CITATIONS.md b/CITATIONS.md index eacec813..a2b9d427 100644 --- a/CITATIONS.md +++ b/CITATIONS.md @@ -12,7 +12,10 @@ - [FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/) + > Andrews, S. (2010). FastQC: A Quality Control Tool for High Throughput Sequence Data [Online]. Available online https://www.bioinformatics.babraham.ac.uk/projects/fastqc/. + - [MultiQC](https://pubmed.ncbi.nlm.nih.gov/27312411/) + > Ewels P, Magnusson M, Lundin S, Käller M. MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics. 2016 Oct 1;32(19):3047-8. doi: 10.1093/bioinformatics/btw354. Epub 2016 Jun 16. PubMed PMID: 27312411; PubMed Central PMCID: PMC5039924. ## Software packaging/containerisation tools @@ -31,5 +34,8 @@ - [Docker](https://dl.acm.org/doi/10.5555/2600239.2600241) + > Merkel, D. (2014). Docker: lightweight linux containers for consistent development and deployment. Linux Journal, 2014(239), 2. doi: 10.5555/2600239.2600241. + - [Singularity](https://pubmed.ncbi.nlm.nih.gov/28494014/) + > Kurtzer GM, Sochat V, Bauer MW. Singularity: Scientific containers for mobility of compute. PLoS One. 2017 May 11;12(5):e0177459. doi: 10.1371/journal.pone.0177459. eCollection 2017. PubMed PMID: 28494014; PubMed Central PMCID: PMC5426675. diff --git a/README.md b/README.md index ddf5126f..d8eb9be8 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/smrnaseq/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) -[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A522.10.1-23aa62.svg)](https://www.nextflow.io/) +[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A523.04.0-23aa62.svg)](https://www.nextflow.io/) [![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/) [![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/) [![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/) @@ -66,11 +66,11 @@ nextflow run nf-core/smrnaseq \ > provided by the `-c` Nextflow option can be used to provide any configuration _**except for parameters**_; > see [docs](https://nf-co.re/usage/configuration#custom-configuration-files). -For more details, please refer to the [usage documentation](https://nf-co.re/smrnaseq/usage) and the [parameter documentation](https://nf-co.re/smrnaseq/parameters). +For more details and further functionality, please refer to the [usage documentation](https://nf-co.re/smrnaseq/usage) and the [parameter documentation](https://nf-co.re/smrnaseq/parameters). ## Pipeline output -To see the the results of a test run with a full size dataset refer to the [results](https://nf-co.re/smrnaseq/results) tab on the nf-core website pipeline page. +To see the results of an example test run with a full size dataset refer to the [results](https://nf-co.re/smrnaseq/results) tab on the nf-core website pipeline page. For more details about the output files and reports, please refer to the [output documentation](https://nf-co.re/smrnaseq/output). diff --git a/assets/methods_description_template.yml b/assets/methods_description_template.yml index 247628aa..c1f4ad89 100644 --- a/assets/methods_description_template.yml +++ b/assets/methods_description_template.yml @@ -3,17 +3,21 @@ description: "Suggested text and references to use when describing pipeline usag section_name: "nf-core/smrnaseq Methods Description" section_href: "https://github.com/nf-core/smrnaseq" plot_type: "html" -## TODO nf-core: Update the HTML below to your prefered methods description, e.g. add publication citation for this pipeline +## TODO nf-core: Update the HTML below to your preferred methods description, e.g. add publication citation for this pipeline ## You inject any metadata in the Nextflow '${workflow}' object data: |

    Methods

    -

    Data was processed using nf-core/smrnaseq v${workflow.manifest.version} ${doi_text} of the nf-core collection of workflows (Ewels et al., 2020).

    +

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

    The pipeline was executed with Nextflow v${workflow.nextflow.version} (Di Tommaso et al., 2017) with the following command:

    ${workflow.commandLine}
    +

    ${tool_citations}

    References

      -
    • Di Tommaso, P., Chatzou, M., Floden, E. W., Barja, P. P., Palumbo, E., & Notredame, C. (2017). Nextflow enables reproducible computational workflows. Nature Biotechnology, 35(4), 316-319. https://doi.org/10.1038/nbt.3820
    • -
    • Ewels, P. A., Peltzer, A., Fillinger, S., Patel, H., Alneberg, J., Wilm, A., Garcia, M. U., Di Tommaso, P., & Nahnsen, S. (2020). The nf-core framework for community-curated bioinformatics pipelines. Nature Biotechnology, 38(3), 276-278. https://doi.org/10.1038/s41587-020-0439-x
    • +
    • Di Tommaso, P., Chatzou, M., Floden, E. W., Barja, P. P., Palumbo, E., & Notredame, C. (2017). Nextflow enables reproducible computational workflows. Nature Biotechnology, 35(4), 316-319. doi: 10.1038/nbt.3820
    • +
    • Ewels, P. A., Peltzer, A., Fillinger, S., Patel, H., Alneberg, J., Wilm, A., Garcia, M. U., Di Tommaso, P., & Nahnsen, S. (2020). The nf-core framework for community-curated bioinformatics pipelines. Nature Biotechnology, 38(3), 276-278. doi: 10.1038/s41587-020-0439-x
    • +
    • Grüning, B., Dale, R., Sjödin, A., Chapman, B. A., Rowe, J., Tomkins-Tinch, C. H., Valieris, R., Köster, J., & Bioconda Team. (2018). Bioconda: sustainable and comprehensive software distribution for the life sciences. Nature Methods, 15(7), 475–476. doi: 10.1038/s41592-018-0046-7
    • +
    • da Veiga Leprevost, F., Grüning, B. A., Alves Aflitos, S., Röst, H. L., Uszkoreit, J., Barsnes, H., Vaudel, M., Moreno, P., Gatto, L., Weber, J., Bai, M., Jimenez, R. C., Sachsenberg, T., Pfeuffer, J., Vera Alvarez, R., Griss, J., Nesvizhskii, A. I., & Perez-Riverol, Y. (2017). BioContainers: an open-source and community-driven framework for software standardization. Bioinformatics (Oxford, England), 33(16), 2580–2582. doi: 10.1093/bioinformatics/btx192
    • + ${tool_bibliography}
    Notes:
    diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index df5ec37a..23da1135 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -1,7 +1,7 @@ report_comment: > - This report has been generated by the nf-core/smrnaseq + This report has been generated by the nf-core/smrnaseq analysis pipeline. For information about how to interpret these results, please see the - documentation. + documentation. report_section_order: "nf-core-smrnaseq-methods-description": order: -1000 diff --git a/assets/nf-core-smrnaseq_logo_light.png b/assets/nf-core-smrnaseq_logo_light.png index 2ecc50a7721db40c53d63ab96945b624cdd188ea..262fa1b099eb8b3cbd5f7d838f87a54dc0ec4ebe 100644 GIT binary patch literal 74188 zcmeEt`9IX_`~RRQS?ZKSWhn*~p=96c5GGq9OZHNfecuPCQz(&w!1jG0qM))u18{N;szxKLnntC7*Z0~7*=;B1!jv^4p5Gb_^hQ29NgTYTSd@O|5 zS3HI44fR<@BwC_WweNAg^K`t?ay|Ua^`zuS;o*5X;p5j0nLR_3TdTw-*C$<<{Vk$; z9`%au>-b1%=CCl=x~!Jp!Br{RFpzjKp!3X+Tb;*QRKss@Kb){h^c+@seV?p-3zMBT zv9)Zlu({<`v3Pc z_~QTk@G~L)&kz6ShyTBGp!b^mFYH1%8g&}PE+NMRdy{Rgwkaa9QvrRQY2HJz)6`6H z9;J$!8p?T$p0J;N*Ye!J#ykH8M)iUCxVX5E!@pK|Rzc1t45Gxe-2E^GvsRWhY(8G+ zqQw!LH!;zIl^)J$8$X^IcCItbD!;xEnF(K*M&+X@JSfW~(%%?AjAD}I{FvT)!b;+< zT`3RVvHyDV#tr{F?pFSzX|tN{P8k1QHN6RI-9sVD@-lUEm%l0Eg`Uqb{CpIznVgoC zqUmmd=@Irb{U+;BnnF@S4JpEd=f8=bxA|}L4A?vsm9JMY?xEj%PSrz{(B9T6zCrD{ z5aNCa{cB^cli-wq*o{Dpv7Lu_ua|VKlQa68K&C3~Q72#9XybNMzba}b4=Acza~8q2n+%iDoFDn0jDk39X?^7A)!^mJ;E z5ekGVYdquWg)k>J@LX5^<&$Ub>jptvS20#izP!}h(}bdq;~{4o<`Z~-?Z6?eBvmOx zsE#!^me;!Al9p_BB9-oh+Bc@3zYqDCn3hx{MhJ+VI+>dJOaT*E;koA-_dUK}Uzf&# zH;{fF7_10)<{MQM8t=)+Bc#9Hzz?%a`@_R0){SISt$Kn@K8L}>h6mZ|Sq!BZKB@H20kftU}^PiE` z)c*Xdd@3S@t0+sw_uO~aLtzgUG2d;xQ1Q*1H#0qHdV%)wP1#8svyWz%C}A74L_x?B3pf9H&Y@2X=|G$}7iYO?E5Lr+QZ zunjfr@njOx!!AI9VRd9th^kl#?3g$t5Dxfn?H4g>K($Nt+fHaOY#hv@QlJIXl)td!4Cw33#odkl6Y zV>S|OhL=y33;S(CMLA9S@}2)++OhBFrXf0zRg_T_+T~HTPwd7xJV6cPBJX{fB~&hK zs$Fc?B(tfBkrDJu$X3Q1{1zTNRk(@T;z!+JtsYJ#VQFEI95Bp+1d)p+`Gk3TG-5Wg zkhB!>_0%li8!7wS)(5l@KDF!}dm%NoRf{a39g|I_D;7#><0*1`M%3kp01AB_Dq!Zg z8ht}kcgMfVhs)|`f(tl+ixNr3KYnoDKRVH}!H24qCWtT&%xd}zW+opB3MoDNJ0-8f zNvx7d#yy3T+j3B!o%L;!;b>EGDQXB~+h}0EX^k<%)ZBpGVwTz%Bc=Z{6LNVVmQ)Zs z#qHX&f?Rw4S8Pz4H6Vlw2CL`ph1rxV>T3%^&1h1dBkPo8>RjJw|7HE<#P4E!4_OE` zO$@0HI!7pPZx!b@3)8f7f(6Vl`(n8hAxh@*>=H@8QQ)g9oK9SqBFr%3t$}fQ3U0|& zMTUI5{BLzyt1e{`H?CqHGJTzP#T38;zV<;^=nNbG6N-_k!KrUQDx)Z|AC(bG|5a8Z zB*H@M#uON%NKm+sWqkHO`)aB@we3grs9;DMV?Q{%PqLj~`hASTUIF*q`ZO5WR)wVFI`G?Zxevi{$Td5LndKR;aC(U=|9wR~L8w;+zr-%IHsbY> zUgGTk{6DWrVb zYX7qj`>+ae$t5+}$|T_!B3=Erhn`P}k1ai*^PzUqmU{4eDXuat%oMLHRxej$e~5m@ z@ADVp?D3O)y6!#xyXd$s{yrf~zYM$Yrd~^{xM%^*VgG&MleV6Y&|SUNwG!INi~rl; z<-XXdqpn!99)UghSN}nCVm|NOx&~&TmiGceJ?{6R>laTmSZ>pxJbelcMsk4R0F=Ar(?q*%!}BhZw%+9K`8y{Yh!MT%%c;Bib&k(wxLRjmW=N{ro zoje;XgQ^~##P@&C)S#ViS*=Lu%Jg6vf7wA7B1zehn!53h9Ut=hiFVdZ2A1)BWO+Or zT}sR*gJqqhOx-8b1SCR0`&Ue?BhO8gDxoY*R=fY z+Cyn|_k)xr7Y`wB{C-T)JdQ-^IL_#4Kt|xti;{O2Uif`>)vlM+z~WAes&vp2#~e;> zaP#^zhn)Ghwj{nES?XIu)mFnEPiGi7&MHYgMRFdBqLYyRcM0|3NrSwRzt{zDC$Q16 z*lJ*$9KIG@s!K*lv(_p8gm-n5bjuuJKPNIbLluNw9-=Anc+g>>{ftA1)Liqyomg7G z0lZGlRAqUVOzOE5hF~nSdqkDH#ahTn%b<|fSG~?U$lf?xD}R^!j=>M6H8HyWF6y2} zPGPZ%iKNdTp7uW4JWgAQE8vm;X_WJc)Enn#$({*pabQ-s4krlc*`UTUP?m@IrR(4uk6XT&bDN%A5aA~}3fQZ}+Rd6c3 z*IAG-N{$P(j4Q>Srfr2tpV8=0h{!#~3-AoOv!u9tWom_0YBxR+7|^?x3!H1(U)HeMcJvM;GiZDK%TC8~?<`}ApK9*l&Oz?(AV;afU?!7R7^1E3 zn(zjAZ>L6+)k_BZ;z(Js8zvb4U#rVK@}KTN_B?4j^DOxi6XO26e;wx5>Meq@OeH16 zPKhP&D9lsS_dDnqJvA_TPayL?T-&Eo4MaN$Vsh~LOFAw$sP98vj^)e3erB(Ix)0Ed zcRcmT-^mAK97kIoOzJos^3BBIn=oowuyWRsVNp-Q8QI%4?47^vYmBj55kB(7-5G-Jw=*jed)*MV}zlKa?!7quxNI9Dqv5~0*qxF{ z-|ays&_rj1kTx$F^uK@^zBGGr$N8@D5U_4!fjHEh%d}?#HzMqS1VBYf&^KYut?s3z z#x(Dl-G0}fkFA#VYCT#)Cajcq(Xx9}P9Gs}$ynv!cB`zU=s>7GEmrr*<+Gsc;!_6q z1=Fl1&esa#1l?YLx5t#zFs9X%$7g7LW1T&4gw?plYc~G0M)WlGL4fi~%|d=l{ONR0 z(ExtJ#m(uPIko8AUgyCi5<6xC?H?P${GQ>p{S!2bzAysv+#gde=;uWi-SN!d&Z0cl z=Vxa<6L=w~xspnfYZmT}S`g$EU~=c)X2)i+nZgjfLi{{7BR9A9V@M?IiAzae66wR{ zbVBUFuw%J$iY49n2)JM4(tQT$^3x(BBAJp1iSJ3%-4{`4VM1nRNn{A0Wy;eaWAc95 zmX5rTQxA~AmcS{swE)2-o_n~AHzPLsJI(%{&@RtXp}uWD?G!-#W|yZ}HlXQ(*l93tqTy}~zd~*$CAgPi|Hx9G?WY5}M z02i&|#Gzt|tMhtL2iunNy9`lKjcFtdl5U(c0=}qQSucG4Onn{mfpPuC~ zUODq^;@FC~c)^rubE~#vvhN#etKRV16JtlmZIYdM@X)Bpn0CtGAJ@B}v82Whya624 zAWNK=gJR5mxMhoFA9d`R9<}|+y@96bmehO5?J{6J#mA%^uw=C3g0&=Yhgqk{lD6Pl zA2MNCrS_F=zGQJRW^*O@TbhT;+S9Ov8I?CaYg*B%^XJm?+K0UD#yYZ6KNnk=2?@=p zc=mdfEVeY#XB$fMFMFYgxxJ-=GENxkH(mxUP$i=}qjnpYz~jsE$`XWx{Ko z{su~~zYEKQH!jQXa{LphLJz|!xE7Bz&XW0HhkW@%MrHfMT?G}tx!TNXzI;CFJ5KS| z+d?rqica4@b;u}fj(?1w;vxQs=2i$^nPv}O^2q1a?fY1*LTE(|m4YKGJh`lI0QgB5 zLd7Q`gSl>EmtO3M%k!8F{Q_tbt)Q?GgUEKEQ{K}&yDmX?P&-6cwO7Pf5_I02N$U;D z^>}L)h~66K!L}xBeQR1XE4$^_To%#xacxYw<_$IFVFHr~HRaRStq6wUxxh^9K{nwv zGSbBg62eHHrLdO9f=R$peChd;#blkTAnf=uz@z{+E z09mH;dkVd2@B;WHFHWdCk-9TsY`B4HF0mG@Y0w_n%lfxep=Py_`>pF8HAic zI5>Dzt5K|fzC3L9WK7<5F*_$RAK>TKRTAWIyYol#>f`FxkO*AF7vCO4Eh?p$q_x59cLmsMlbT+}V zaI|PtAk*V&lNx5bTV?I&R}u~D-glvDnrJQ!d9;*d={1AV_H|(ab9o^1DGx zEg*8wH=cWZ&jMWl(Bb3=VVJ2CsbSv&R{t)jDfS@mUP+~{)vZwNT@_+ChG}txxpgN5 zoEUkoKQHx6+acPT(tX;P1!#WopOG#Ay=mGdgRh0xa7Yzn`F)du8^WH4JELXyeXy9XZNETOysflQOlCGBF*;iJnGrL6%1H`;Ol5>#tPMvU^qdFg6f+ zJ15{3Uw%mDwl9BEHY@WzC}z+7&<^JkfyR=ThRTwkPyL*}H=xoj`;$p= zzvcr(!zV$+TpgsJOE5~&Iu_a!B5G-Szdsm3JB-9Fv?8G!dg;0Im|<{;?oNIT>Mw_u zc)4N9LGY&l#N!Pr@+CYtT`7<%?rS-11^B9A3X|D zz`k>awRwQ!@Zpjy&@Rq`BKE}8fF_hR1+je_VFF#Pw4WYkP`_+9>`NqEb*gHg1zKK# z9$UEbB;f-%d{2K8i4zlOMLs6c2Alex9lj=y7xD?ln8j|GV)T%Ht{_O8$oT_~^dpxb zh6WP}2HLBBFTy$k4vuWXZp^LOJN}+>so%B{$y?m^&t!i3t`;ZptDkukl%4!I;I-4amD{4_C|db zZO)L6QpS)3z?ueRT_Op~KDooYukNekjPxi;Afr7!vZ@W`8FH7KQEehTFy}6Xhdg}Bj%BxLhz^5<=~ zrJ&XZ1!n?b)vw=MrncjT`pUz!c7_Mm_2vn-!H_(%@uWNm`l$j4BYD3>1G>f&!KDEh zuXthGF+96Nj(Oc46AUNoKh0wc3yq*^&k*k3OQ%^>h~DYB_{L#K11?8(IF=tl4VlX` zMOG$&kXWFZlMd!&o2S^Ck@w$&+a4-RQxde8 zhGZVKLiQTS?|R%5$A%c8!MMTUp3#~rR4ufb%a_T=gv~&9CX$k42Q1}xh5@QxJ5-Se zO<11i9!(6?i7+79&@ktMc#3qHQhSn3jY# zn()HALZ!onAgu|0NiBT3VTe(OOFYa_MqYyO+Igr4F>MH!VT0Sdb_l2_5AA)BkRplz zY67NS#Pi%uH)8<~6fiX}J=utEmR9nJ$b(Slx}(J%bj-eu-&-8ZJ$G2ML6xQA zAn$*S1b*Nrux5H7vK9w{fGcQ-XFC?hb{WqE`jYR|FDtK<7QdrH5269ZQVSZR5JsC% zYD*y4oDl33NA7(pbp}7Lf=ANz3oMdIKMMhB_~RphsVuLXpoz@ncSX`BrMlA2&3=Le zr=R#GVf5O_Xw@XE`ka;gE+ojMDkPy4EYh2}2^PujSTtg^Dwjxl`x8^S*#Bo-a)~MA z>X3;%V(y9P{#itTa%OHjdaY7hm6%u0FA6rueZa!(z z55fR4_!W(|Y)7QOjkW(ASX(RZ05^mIM!wMa#KRYB6NL2nLt0$|L~%@$H13UkWcF=r z`R6Sb*U{lvTj&`WWK&2m$Hbo+Hj_uVHq@qrle~7EG{CIF^po4H9ib5MAw#`nF)#2a zskzw?mkZ`ZT3m&w({4j*Y3f&}v`ym3{rX>ST8FkF4wX+EYy#6Da?BGl^l2ksF*uF_ zSf~FIiseqVB)Xk7I-U)Z3xPLz)#r(2_XdOp+Q|V>M&R-JqC5!o-U^;CyNQJ96Fkol z0ui+IH8F;9L=Cclw!91!P9v0{6Ux$3o=Kw61;|qUDTx1^F2F78u$?LlqwQc#!YOyj z3wao0qG>yrwC#IMe%(Q5{p2e7gCJtkB>*DP;%-TMG&e^bSEfYxsr6E4u8>&@`vA)k zxdcFVEn&Lu2qsQM&ZGW+Xv1=NzHkVxy8(U~=QJ_fFaS@1l%flfx{Z7aNx5?ikptdu z{Iz(pIxZe5Lz~Z)10m7UbOc0FEs_(8Gq;xm5{Y)7VO{DbvU5p+_xE>uE!9gj!Iaau z%TFIXWBQcl8QS$m&d-|+{G1^WoC~bS1nb3WC$J$>;x_+XN(!O`AFjVa!rEXG5`K;b zLkucjdLoFq=2sw)uk#>uh1rhcpfy5-0i{s0rF|25=m!O-h2=Vit8$brH`j`EeQw`? zL6`I+b)0m}!FGYHzOt7qDQX zIS6n~695KoovaVSl!6c;GgU4mm$Y?s0f=D8&_)T~62QOo>)(U|a=<8| zmh<}3Vo5buv9oOvSK7;t4{f@qTbfzW%O{eaBbhLPRl$D5)gGw(des^iu6^*W01VD= zV`SCyCXV!F^g(CP^s5eD;YpQ(DVV+nE2t1WsC?LjMo#~>30v%zN7F=bEEDaTetXht zD1o#E_J1y^GsUSdbxb#c*pR9T1iLgE)cIhl2K;)5od|btFs`W=y+@_Ni2Go$G z@Q{h=CgX5+t#?(wO8mjy&(d?s1W;^(en=qu=JwRZH31Ya4A+#T-}62FOj(4Ize6K}@W6YZr^?Dem#2jOqCXeRmww! zGoXHbb(q>X%pi-d^xzQ?UExb;e0Y9E7+$IvUKF2wG*%JQ^{QuCsPZgsEN-9sivbU` z^o-vqspl3owq}(i0*$Rkr}*|_c^%3<0OR+;sp0(+>IjV)o+Gz$AOr8Yi18q}9&GBb zhCVk~4W$D)%R_z?rKpk>Y~a!^-}tp}xLZErW@WFlQsU52v7F)kHR6QLkLPa`e7PWu zP*($;n`-Gse6jdZF{fFHdOy&oao;`%FPORU1nYRZVCpQF<}Y*}i+P1BV@o7}St8x_r>2-9wNP;M8 zcD9UX^E6p$%+jaBD+&%Za`9O#c7)A0(g;|qKb}NcWL6&jTBlfN|LX0O_N>=8LS}~s zEG>-LxD6U{;Q6zLS7gq*oU)Xj)4UHIuOt8#v3%G9OgVIN1CN5DR`a*hn4WcMhgXDB zET3mhL~RFhA}g0OW>3rX=Z(1R8A>B*u+jHze?P<-rw@NK&kIl&y4o0 z%LA25?zFbbb0q!k(@9RF=!8@GnzM3FN?D7!<#~RA`YxsQ0HN@LgA74Kd!kPf;JS7( z{bOMTc9-*QcbLo2OA#@Kh`ezN@SyqA0S*o(*?$tUfu^W(7FFBZ2>=wKiV0x*H62-`5Fclu*L zA~Ipi-Mq2=6WV6m{YiUEZ;SypCJhiu0!L}LK>g?tkyI=$n*VCQQ_2pQKnKvZ`dcf( zW!^7Wh9_W1bPC5%$)`mLLn%YIqI6mGFsa$VK&*8n>!rELxi1ZUF(i)7X}Hj`zyj*c{HII61u=Y<{rl8{jrhqkAEU5q=%DQdXOIh0xDvYHV8Foh+13dBI$3Yd4~3b%RKPN&QF6obt$IcIBy*HauFFq|vp$<%f`KJ5a8XFyi<8}qXRuV}*ahZQ{g zB#I4Eenr^N1*2yg6?F<4vjkE^Y?n-RvKCWFXJJauev8uSfw0=yUMsh4+Z)tnp0TtN zhyM5PYvE0}LBHz<(y1Rt%#K}6GXFh~JA5SnU z(4kC|If7CaB`fZtoKX}kjSw>H4J{xGWQ8v&vsvc129b3({jj$U9dAK)8^_krX6J!# zIxW_rTP7Mp)wT=zd62oUF0=NxDXnf+`wUUv71&SpDi__ySdKB&|8%(&Ba<$!0N(do?Y0_U~$B}&=QlWP~%Hr~FH$qctY?fm)58_koMPp*h( zJn3j+J$KN@k#?RE6iF6U1l#d{Cx%pb1cTHP~un?rQDjRQ5zSi@)HkbH|YsJFE} z%IdEucy<51w_zb#xgMV1E)d6-W~&UlNK=dTyp9)j12D5bqpWdPHZl%RmduPR=4A;e0bB0cAG9A(?*V0)a!t%S*Pumi8vLLfTp)urZ-phYc`kn znQgB;!M50G<(_T&5zyFZTCoXVP2ukAo;;Y=wPf?8DSysHM5M?H_ zM?Wme+|<<6)Qt}@hB3?{hFEjUbOat=K2*|1U#4c`%Hy{-#+zE$7d#W!Jx0&BJ4!lA zfa!-QG4}*ZK9e$>O|?5TBlv}c?B5%;0m^F+?`B+!rxzE*;;)*`YcRhV4_Pc=nV4M|q$8`7S9o({=o;ipR}!KWvPa>3ogeEH1k6m9Ibd z*&c6fMz6k4v9uNlNMFG7E4_Rd&GH2dKT9!=t9!6PxVA|wDCi6ghLEN0zV&88OHD1q zXW-+DVY*u(O|nr_*!s|ws&Z<�ev`Q}H7y#R1zKkC5n?0_OP7^FqWWeXhX0t0pNK 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

    )bNtXB<>| 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 literal 11484 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 diff --git a/assets/slackreport.json b/assets/slackreport.json index 043d02f2..214c7fa9 100644 --- a/assets/slackreport.json +++ b/assets/slackreport.json @@ -3,7 +3,7 @@ { "fallback": "Plain-text summary of the attachment.", "color": "<% if (success) { %>good<% } else { %>danger<%} %>", - "author_name": "sanger-tol/readmapping v${version} - ${runName}", + "author_name": "nf-core/smrnaseq v${version} - ${runName}", "author_icon": "https://www.nextflow.io/docs/latest/_static/favicon.ico", "text": "<% if (success) { %>Pipeline completed successfully!<% } else { %>Pipeline completed with errors<% } %>", "fields": [ diff --git a/conf/test_full.config b/conf/test_full.config index 6128e665..16409b22 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -10,8 +10,6 @@ ---------------------------------------------------------------------------------------- */ -cleanup = true - params { config_profile_name = 'Full test profile' config_profile_description = 'Full test dataset to check pipeline function' diff --git a/docs/usage.md b/docs/usage.md index 1af385d2..49e6df24 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -57,7 +57,7 @@ An [example samplesheet](../assets/samplesheet.csv) has been provided with the p The typical command for running the pipeline is as follows: ```bash -nextflow run nf-core/smrnaseq --input samplesheet.csv --outdir --genome GRCh37 -profile docker +nextflow run nf-core/smrnaseq --input ./samplesheet.csv --outdir ./results --genome GRCh37 -profile docker ``` This will launch the pipeline with the `docker` configuration profile. See below for more information about profiles. @@ -76,7 +76,8 @@ If you wish to repeatedly use the same parameters for multiple runs, rather than Pipeline settings can be provided in a `yaml` or `json` file via `-params-file `. > ⚠️ Do not use `-c ` to specify parameters as this will result in errors. Custom config files specified with `-c` must only be used for [tuning process resource specifications](https://nf-co.re/docs/usage/configuration#tuning-workflow-resources), other infrastructural tweaks (such as output directories), or module arguments (args). -> The above pipeline run specified with a params file in yaml format: + +The above pipeline run specified with a params file in yaml format: ```bash nextflow run nf-core/smrnaseq -profile docker -params-file params.yaml @@ -88,7 +89,6 @@ with `params.yaml` containing: input: './samplesheet.csv' outdir: './results/' genome: 'GRCh37' -input: 'data' <...> ``` diff --git a/lib/NfcoreSchema.groovy b/lib/NfcoreSchema.groovy deleted file mode 100755 index 9b34804d..00000000 --- a/lib/NfcoreSchema.groovy +++ /dev/null @@ -1,530 +0,0 @@ -// -// This file holds several functions used to perform JSON parameter validation, help and summary rendering for the nf-core pipeline template. -// - -import nextflow.Nextflow -import org.everit.json.schema.Schema -import org.everit.json.schema.loader.SchemaLoader -import org.everit.json.schema.ValidationException -import org.json.JSONObject -import org.json.JSONTokener -import org.json.JSONArray -import groovy.json.JsonSlurper -import groovy.json.JsonBuilder - -class NfcoreSchema { - - // - // Resolve Schema path relative to main workflow directory - // - public static String getSchemaPath(workflow, schema_filename='nextflow_schema.json') { - return "${workflow.projectDir}/${schema_filename}" - } - - // - // Function to loop over all parameters defined in schema and check - // whether the given parameters adhere to the specifications - // - /* groovylint-disable-next-line UnusedPrivateMethodParameter */ - public static void validateParameters(workflow, params, log, schema_filename='nextflow_schema.json') { - def has_error = false - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// - // Check for nextflow core params and unexpected params - def json = new File(getSchemaPath(workflow, schema_filename=schema_filename)).text - def Map schemaParams = (Map) new JsonSlurper().parseText(json).get('definitions') - def nf_params = [ - // Options for base `nextflow` command - 'bg', - 'c', - 'C', - 'config', - 'd', - 'D', - 'dockerize', - 'h', - 'log', - 'q', - 'quiet', - 'syslog', - 'v', - - // Options for `nextflow run` command - 'ansi', - 'ansi-log', - 'bg', - 'bucket-dir', - 'c', - 'cache', - 'config', - 'dsl2', - 'dump-channels', - 'dump-hashes', - 'E', - 'entry', - 'latest', - 'lib', - 'main-script', - 'N', - 'name', - 'offline', - 'params-file', - 'pi', - 'plugins', - 'poll-interval', - 'pool-size', - 'profile', - 'ps', - 'qs', - 'queue-size', - 'r', - 'resume', - 'revision', - 'stdin', - 'stub', - 'stub-run', - 'test', - 'w', - 'with-apptainer', - 'with-charliecloud', - 'with-conda', - 'with-dag', - 'with-docker', - 'with-mpi', - 'with-notification', - 'with-podman', - 'with-report', - 'with-singularity', - 'with-timeline', - 'with-tower', - 'with-trace', - 'with-weblog', - 'without-docker', - 'without-podman', - 'work-dir' - ] - def unexpectedParams = [] - - // Collect expected parameters from the schema - def expectedParams = [] - def enums = [:] - for (group in schemaParams) { - for (p in group.value['properties']) { - expectedParams.push(p.key) - if (group.value['properties'][p.key].containsKey('enum')) { - enums[p.key] = group.value['properties'][p.key]['enum'] - } - } - } - - for (specifiedParam in params.keySet()) { - // nextflow params - if (nf_params.contains(specifiedParam)) { - log.error "ERROR: You used a core Nextflow option with two hyphens: '--${specifiedParam}'. Please resubmit with '-${specifiedParam}'" - has_error = true - } - // unexpected params - def params_ignore = params.schema_ignore_params.split(',') + 'schema_ignore_params' - def expectedParamsLowerCase = expectedParams.collect{ it.replace("-", "").toLowerCase() } - def specifiedParamLowerCase = specifiedParam.replace("-", "").toLowerCase() - def isCamelCaseBug = (specifiedParam.contains("-") && !expectedParams.contains(specifiedParam) && expectedParamsLowerCase.contains(specifiedParamLowerCase)) - if (!expectedParams.contains(specifiedParam) && !params_ignore.contains(specifiedParam) && !isCamelCaseBug) { - // Temporarily remove camelCase/camel-case params #1035 - def unexpectedParamsLowerCase = unexpectedParams.collect{ it.replace("-", "").toLowerCase()} - if (!unexpectedParamsLowerCase.contains(specifiedParamLowerCase)){ - unexpectedParams.push(specifiedParam) - } - } - } - - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// - // Validate parameters against the schema - InputStream input_stream = new File(getSchemaPath(workflow, schema_filename=schema_filename)).newInputStream() - JSONObject raw_schema = new JSONObject(new JSONTokener(input_stream)) - - // Remove anything that's in params.schema_ignore_params - raw_schema = removeIgnoredParams(raw_schema, params) - - Schema schema = SchemaLoader.load(raw_schema) - - // Clean the parameters - def cleanedParams = cleanParameters(params) - - // Convert to JSONObject - def jsonParams = new JsonBuilder(cleanedParams) - JSONObject params_json = new JSONObject(jsonParams.toString()) - - // Validate - try { - schema.validate(params_json) - } catch (ValidationException e) { - println '' - log.error 'ERROR: Validation of pipeline parameters failed!' - JSONObject exceptionJSON = e.toJSON() - printExceptions(exceptionJSON, params_json, log, enums) - println '' - has_error = true - } - - // Check for unexpected parameters - if (unexpectedParams.size() > 0) { - Map colors = NfcoreTemplate.logColours(params.monochrome_logs) - println '' - def warn_msg = 'Found unexpected parameters:' - for (unexpectedParam in unexpectedParams) { - warn_msg = warn_msg + "\n* --${unexpectedParam}: ${params[unexpectedParam].toString()}" - } - log.warn warn_msg - log.info "- ${colors.dim}Ignore this warning: params.schema_ignore_params = \"${unexpectedParams.join(',')}\" ${colors.reset}" - println '' - } - - if (has_error) { - Nextflow.error('Exiting!') - } - } - - // - // Beautify parameters for --help - // - public static String paramsHelp(workflow, params, command, schema_filename='nextflow_schema.json') { - Map colors = NfcoreTemplate.logColours(params.monochrome_logs) - Integer num_hidden = 0 - String output = '' - output += 'Typical pipeline command:\n\n' - output += " ${colors.cyan}${command}${colors.reset}\n\n" - Map params_map = paramsLoad(getSchemaPath(workflow, schema_filename=schema_filename)) - Integer max_chars = paramsMaxChars(params_map) + 1 - Integer desc_indent = max_chars + 14 - Integer dec_linewidth = 160 - desc_indent - for (group in params_map.keySet()) { - Integer num_params = 0 - String group_output = colors.underlined + colors.bold + group + colors.reset + '\n' - def group_params = params_map.get(group) // This gets the parameters of that particular group - for (param in group_params.keySet()) { - if (group_params.get(param).hidden && !params.show_hidden_params) { - num_hidden += 1 - continue; - } - def type = '[' + group_params.get(param).type + ']' - def description = group_params.get(param).description - def defaultValue = group_params.get(param).default != null ? " [default: " + group_params.get(param).default.toString() + "]" : '' - def description_default = description + colors.dim + defaultValue + colors.reset - // Wrap long description texts - // Loosely based on https://dzone.com/articles/groovy-plain-text-word-wrap - if (description_default.length() > dec_linewidth){ - List olines = [] - String oline = "" // " " * indent - description_default.split(" ").each() { wrd -> - if ((oline.size() + wrd.size()) <= dec_linewidth) { - oline += wrd + " " - } else { - olines += oline - oline = wrd + " " - } - } - olines += oline - description_default = olines.join("\n" + " " * desc_indent) - } - group_output += " --" + param.padRight(max_chars) + colors.dim + type.padRight(10) + colors.reset + description_default + '\n' - num_params += 1 - } - group_output += '\n' - if (num_params > 0){ - output += group_output - } - } - if (num_hidden > 0){ - output += colors.dim + "!! Hiding $num_hidden params, use --show_hidden_params to show them !!\n" + colors.reset - } - output += NfcoreTemplate.dashedLine(params.monochrome_logs) - return output - } - - // - // Groovy Map summarising parameters/workflow options used by the pipeline - // - public static LinkedHashMap paramsSummaryMap(workflow, params, schema_filename='nextflow_schema.json') { - // Get a selection of core Nextflow workflow options - def Map workflow_summary = [:] - if (workflow.revision) { - workflow_summary['revision'] = workflow.revision - } - workflow_summary['runName'] = workflow.runName - if (workflow.containerEngine) { - workflow_summary['containerEngine'] = workflow.containerEngine - } - if (workflow.container) { - workflow_summary['container'] = workflow.container - } - workflow_summary['launchDir'] = workflow.launchDir - workflow_summary['workDir'] = workflow.workDir - workflow_summary['projectDir'] = workflow.projectDir - workflow_summary['userName'] = workflow.userName - workflow_summary['profile'] = workflow.profile - workflow_summary['configFiles'] = workflow.configFiles.join(', ') - - // Get pipeline parameters defined in JSON Schema - def Map params_summary = [:] - def params_map = paramsLoad(getSchemaPath(workflow, schema_filename=schema_filename)) - for (group in params_map.keySet()) { - def sub_params = new LinkedHashMap() - def group_params = params_map.get(group) // This gets the parameters of that particular group - for (param in group_params.keySet()) { - if (params.containsKey(param)) { - def params_value = params.get(param) - def schema_value = group_params.get(param).default - def param_type = group_params.get(param).type - if (schema_value != null) { - if (param_type == 'string') { - if (schema_value.contains('$projectDir') || schema_value.contains('${projectDir}')) { - def sub_string = schema_value.replace('\$projectDir', '') - sub_string = sub_string.replace('\${projectDir}', '') - if (params_value.contains(sub_string)) { - schema_value = params_value - } - } - if (schema_value.contains('$params.outdir') || schema_value.contains('${params.outdir}')) { - def sub_string = schema_value.replace('\$params.outdir', '') - sub_string = sub_string.replace('\${params.outdir}', '') - if ("${params.outdir}${sub_string}" == params_value) { - schema_value = params_value - } - } - } - } - - // We have a default in the schema, and this isn't it - if (schema_value != null && params_value != schema_value) { - sub_params.put(param, params_value) - } - // No default in the schema, and this isn't empty - else if (schema_value == null && params_value != "" && params_value != null && params_value != false) { - sub_params.put(param, params_value) - } - } - } - params_summary.put(group, sub_params) - } - return [ 'Core Nextflow options' : workflow_summary ] << params_summary - } - - // - // Beautify parameters for summary and return as string - // - public static String paramsSummaryLog(workflow, params) { - Map colors = NfcoreTemplate.logColours(params.monochrome_logs) - String output = '' - def params_map = paramsSummaryMap(workflow, params) - def max_chars = paramsMaxChars(params_map) - for (group in params_map.keySet()) { - def group_params = params_map.get(group) // This gets the parameters of that particular group - if (group_params) { - output += colors.bold + group + colors.reset + '\n' - for (param in group_params.keySet()) { - output += " " + colors.blue + param.padRight(max_chars) + ": " + colors.green + group_params.get(param) + colors.reset + '\n' - } - output += '\n' - } - } - output += "!! Only displaying parameters that differ from the pipeline defaults !!\n" - output += NfcoreTemplate.dashedLine(params.monochrome_logs) - return output - } - - // - // Loop over nested exceptions and print the causingException - // - private static void printExceptions(ex_json, params_json, log, enums, limit=5) { - def causingExceptions = ex_json['causingExceptions'] - if (causingExceptions.length() == 0) { - def m = ex_json['message'] =~ /required key \[([^\]]+)\] not found/ - // Missing required param - if (m.matches()) { - log.error "* Missing required parameter: --${m[0][1]}" - } - // Other base-level error - else if (ex_json['pointerToViolation'] == '#') { - log.error "* ${ex_json['message']}" - } - // Error with specific param - else { - def param = ex_json['pointerToViolation'] - ~/^#\// - def param_val = params_json[param].toString() - if (enums.containsKey(param)) { - def error_msg = "* --${param}: '${param_val}' is not a valid choice (Available choices" - if (enums[param].size() > limit) { - log.error "${error_msg} (${limit} of ${enums[param].size()}): ${enums[param][0..limit-1].join(', ')}, ... )" - } else { - log.error "${error_msg}: ${enums[param].join(', ')})" - } - } else { - log.error "* --${param}: ${ex_json['message']} (${param_val})" - } - } - } - for (ex in causingExceptions) { - printExceptions(ex, params_json, log, enums) - } - } - - // - // Remove an element from a JSONArray - // - private static JSONArray removeElement(json_array, element) { - def list = [] - int len = json_array.length() - for (int i=0;i - if(raw_schema.keySet().contains('definitions')){ - raw_schema.definitions.each { definition -> - for (key in definition.keySet()){ - if (definition[key].get("properties").keySet().contains(ignore_param)){ - // Remove the param to ignore - definition[key].get("properties").remove(ignore_param) - // If the param was required, change this - if (definition[key].has("required")) { - def cleaned_required = removeElement(definition[key].required, ignore_param) - definition[key].put("required", cleaned_required) - } - } - } - } - } - if(raw_schema.keySet().contains('properties') && raw_schema.get('properties').keySet().contains(ignore_param)) { - raw_schema.get("properties").remove(ignore_param) - } - if(raw_schema.keySet().contains('required') && raw_schema.required.contains(ignore_param)) { - def cleaned_required = removeElement(raw_schema.required, ignore_param) - raw_schema.put("required", cleaned_required) - } - } - return raw_schema - } - - // - // Clean and check parameters relative to Nextflow native classes - // - private static Map cleanParameters(params) { - def new_params = params.getClass().newInstance(params) - for (p in params) { - // remove anything evaluating to false - if (!p['value']) { - new_params.remove(p.key) - } - // Cast MemoryUnit to String - if (p['value'].getClass() == nextflow.util.MemoryUnit) { - new_params.replace(p.key, p['value'].toString()) - } - // Cast Duration to String - if (p['value'].getClass() == nextflow.util.Duration) { - new_params.replace(p.key, p['value'].toString().replaceFirst(/d(?!\S)/, "day")) - } - // Cast LinkedHashMap to String - if (p['value'].getClass() == LinkedHashMap) { - new_params.replace(p.key, p['value'].toString()) - } - } - return new_params - } - - // - // This function tries to read a JSON params file - // - private static LinkedHashMap paramsLoad(String json_schema) { - def params_map = new LinkedHashMap() - try { - params_map = paramsRead(json_schema) - } catch (Exception e) { - println "Could not read parameters settings from JSON. $e" - params_map = new LinkedHashMap() - } - return params_map - } - - // - // Method to actually read in JSON file using Groovy. - // Group (as Key), values are all parameters - // - Parameter1 as Key, Description as Value - // - Parameter2 as Key, Description as Value - // .... - // Group - // - - private static LinkedHashMap paramsRead(String json_schema) throws Exception { - def json = new File(json_schema).text - def Map schema_definitions = (Map) new JsonSlurper().parseText(json).get('definitions') - def Map schema_properties = (Map) new JsonSlurper().parseText(json).get('properties') - /* Tree looks like this in nf-core schema - * definitions <- this is what the first get('definitions') gets us - group 1 - title - description - properties - parameter 1 - type - description - parameter 2 - type - description - group 2 - title - description - properties - parameter 1 - type - description - * properties <- parameters can also be ungrouped, outside of definitions - parameter 1 - type - description - */ - - // Grouped params - def params_map = new LinkedHashMap() - schema_definitions.each { key, val -> - def Map group = schema_definitions."$key".properties // Gets the property object of the group - def title = schema_definitions."$key".title - def sub_params = new LinkedHashMap() - group.each { innerkey, value -> - sub_params.put(innerkey, value) - } - params_map.put(title, sub_params) - } - - // Ungrouped params - def ungrouped_params = new LinkedHashMap() - schema_properties.each { innerkey, value -> - ungrouped_params.put(innerkey, value) - } - params_map.put("Other parameters", ungrouped_params) - - return params_map - } - - // - // Get maximum number of characters across all parameter names - // - private static Integer paramsMaxChars(params_map) { - Integer max_chars = 0 - for (group in params_map.keySet()) { - def group_params = params_map.get(group) // This gets the parameters of that particular group - for (param in group_params.keySet()) { - if (param.size() > max_chars) { - max_chars = param.size() - } - } - } - return max_chars - } -} diff --git a/lib/NfcoreTemplate.groovy b/lib/NfcoreTemplate.groovy index 25a0a74a..408951ae 100755 --- a/lib/NfcoreTemplate.groovy +++ b/lib/NfcoreTemplate.groovy @@ -128,7 +128,7 @@ class NfcoreTemplate { def email_html = html_template.toString() // Render the sendmail template - def max_multiqc_email_size = params.max_multiqc_email_size as nextflow.util.MemoryUnit + def max_multiqc_email_size = (params.containsKey('max_multiqc_email_size') ? params.max_multiqc_email_size : 0) as nextflow.util.MemoryUnit def smail_fields = [ email: email_address, subject: subject, email_txt: email_txt, email_html: email_html, projectDir: "$projectDir", mqcFile: mqc_report, mqcMaxSize: max_multiqc_email_size.toBytes() ] def sf = new File("$projectDir/assets/sendmail_template.txt") def sendmail_template = engine.createTemplate(sf).make(smail_fields) diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 892c41e7..3b09f790 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -20,40 +20,11 @@ class WorkflowMain { " https://github.com/${workflow.manifest.name}/blob/master/CITATIONS.md" } - // - // Generate help string - // - public static String help(workflow, params) { - def command = "nextflow run ${workflow.manifest.name} --input samplesheet.csv --genome GRCh37 -profile docker" - def help_string = '' - help_string += NfcoreTemplate.logo(workflow, params.monochrome_logs) - help_string += NfcoreSchema.paramsHelp(workflow, params, command) - help_string += '\n' + citation(workflow) + '\n' - help_string += NfcoreTemplate.dashedLine(params.monochrome_logs) - return help_string - } - - // - // Generate parameter summary log string - // - public static String paramsSummaryLog(workflow, params) { - def summary_log = '' - summary_log += NfcoreTemplate.logo(workflow, params.monochrome_logs) - summary_log += NfcoreSchema.paramsSummaryLog(workflow, params) - summary_log += '\n' + citation(workflow) + '\n' - summary_log += NfcoreTemplate.dashedLine(params.monochrome_logs) - return summary_log - } // // Validate parameters and print summary to screen // public static void initialise(workflow, params, log) { - // Print help to screen if required - if (params.help) { - log.info help(workflow, params) - System.exit(0) - } // Print workflow version and exit on --version if (params.version) { @@ -62,14 +33,6 @@ class WorkflowMain { System.exit(0) } - // Print parameter summary log to screen - log.info paramsSummaryLog(workflow, params) - - // Validate workflow parameters via the JSON schema - if (params.validate_params) { - NfcoreSchema.validateParameters(workflow, params, log) - } - // Check that a -profile or Nextflow config has been provided to run the pipeline NfcoreTemplate.checkConfigProvided(workflow, log) diff --git a/lib/WorkflowSmrnaseq.groovy b/lib/WorkflowSmrnaseq.groovy index 7ab5bd21..9a5e266e 100755 --- a/lib/WorkflowSmrnaseq.groovy +++ b/lib/WorkflowSmrnaseq.groovy @@ -11,6 +11,7 @@ class WorkflowSmrnaseq { // Check and validate parameters // public static void initialise(params, log) { + genomeExistsError(params, log) @@ -46,15 +47,57 @@ class WorkflowSmrnaseq { return yaml_file_text } - public static String methodsDescriptionText(run_workflow, mqc_methods_yaml) { + // + // Generate methods description for MultiQC + // + + public static String toolCitationText(params) { + + // TODO Optionally add in-text citation tools to this list. + // Can use ternary operators to dynamically construct based conditions, e.g. params["run_xyz"] ? "Tool (Foo et al. 2023)" : "", + // Uncomment function in methodsDescriptionText to render in MultiQC report + def citation_text = [ + "Tools used in the workflow included:", + "FastQC (Andrews 2010),", + "MultiQC (Ewels et al. 2016)", + "." + ].join(' ').trim() + + return citation_text + } + + public static String toolBibliographyText(params) { + + // TODO Optionally add bibliographic entries to this list. + // Can use ternary operators to dynamically construct based conditions, e.g. params["run_xyz"] ? "

  • Author (2023) Pub name, Journal, DOI
  • " : "", + // Uncomment function in methodsDescriptionText to render in MultiQC report + def reference_text = [ + "
  • Andrews S, (2010) FastQC, URL: https://www.bioinformatics.babraham.ac.uk/projects/fastqc/).
  • ", + "
  • Ewels, P., Magnusson, M., Lundin, S., & Käller, M. (2016). MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics , 32(19), 3047–3048. doi: /10.1093/bioinformatics/btw354
  • " + ].join(' ').trim() + + return reference_text + } + + public static String methodsDescriptionText(run_workflow, mqc_methods_yaml, params) { // Convert to a named map so can be used as with familar NXF ${workflow} variable syntax in the MultiQC YML file def meta = [:] meta.workflow = run_workflow.toMap() meta["manifest_map"] = run_workflow.manifest.toMap() + // Pipeline DOI meta["doi_text"] = meta.manifest_map.doi ? "(doi: ${meta.manifest_map.doi})" : "" 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.
  • " + // Tool references + meta["tool_citations"] = "" + meta["tool_bibliography"] = "" + + // TODO Only uncomment below if logic in toolCitationText/toolBibliographyText has been filled! + //meta["tool_citations"] = toolCitationText(params).replaceAll(", \\.", ".").replaceAll("\\. \\.", ".").replaceAll(", \\.", ".") + //meta["tool_bibliography"] = toolBibliographyText(params) + + def methods_text = mqc_methods_yaml.text def engine = new SimpleTemplateEngine() diff --git a/main.nf b/main.nf index 5b057014..8d738016 100644 --- a/main.nf +++ b/main.nf @@ -25,6 +25,22 @@ params.fasta = WorkflowMain.getGenomeAttribute(params, 'fasta') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +include { validateParameters; paramsHelp } from 'plugin/nf-validation' + +// Print help message if needed +if (params.help) { + def logo = NfcoreTemplate.logo(workflow, params.monochrome_logs) + def citation = '\n' + WorkflowMain.citation(workflow) + '\n' + def String command = "nextflow run ${workflow.manifest.name} --input samplesheet.csv --genome GRCh37 -profile docker" + log.info logo + paramsHelp(command) + citation + NfcoreTemplate.dashedLine(params.monochrome_logs) + System.exit(0) +} + +// Validate input parameters +if (params.validate_params) { + validateParameters() +} + WorkflowMain.initialise(workflow, params, log) /* diff --git a/nextflow.config b/nextflow.config index ba0a8e73..ebf5d0a9 100644 --- a/nextflow.config +++ b/nextflow.config @@ -12,12 +12,12 @@ params { // TODO nf-core: Specify your pipeline's command line flags // Input options input = null - - // References genome = null igenomes_base = 's3://ngi-igenomes/igenomes' igenomes_ignore = false + + // MultiQC options multiqc_config = null multiqc_title = null @@ -27,7 +27,6 @@ params { // Boilerplate options outdir = null - tracedir = "${params.outdir}/pipeline_info" publish_dir_mode = 'copy' email = null email_on_fail = null @@ -36,19 +35,15 @@ params { hook_url = null help = false version = false - validate_params = true - show_hidden_params = false - schema_ignore_params = 'genomes' - // Config options + config_profile_name = null + config_profile_description = null custom_config_version = 'master' custom_config_base = "https://raw.githubusercontent.com/nf-core/configs/${params.custom_config_version}" - config_profile_description = null config_profile_contact = null config_profile_url = null - config_profile_name = null - + // Max resource options // Defaults only, expecting to be overwritten @@ -56,6 +51,13 @@ params { max_cpus = 16 max_time = '240.h' + // Schema validation default options + validationFailUnrecognisedParams = false + validationLenientMode = false + validationSchemaIgnoreParams = 'genomes' + validationShowHiddenParams = false + validate_params = true + } // Load base.config by default for all pipelines @@ -75,13 +77,11 @@ try { // } catch (Exception e) { // System.err.println("WARNING: Could not load nf-core/config/smrnaseq profiles: ${params.custom_config_base}/pipeline/smrnaseq.config") // } - - profiles { debug { dumpHashes = true process.beforeScript = 'echo $HOSTNAME' - cleanup = false + cleanup = false } conda { conda.enabled = true @@ -104,7 +104,6 @@ profiles { } docker { docker.enabled = true - docker.registry = 'quay.io' docker.userEmulation = true conda.enabled = false singularity.enabled = false @@ -128,7 +127,6 @@ profiles { } podman { podman.enabled = true - podman.registry = 'quay.io' conda.enabled = false docker.enabled = false singularity.enabled = false @@ -172,6 +170,18 @@ profiles { test_full { includeConfig 'conf/test_full.config' } } +// Set default registry for Apptainer, Docker, Podman and Singularity independent of -profile +// Will not be used unless Apptainer / Docker / Podman / Singularity are enabled +// Set to your registry if you have a mirror of containers +apptainer.registry = 'quay.io' +docker.registry = 'quay.io' +podman.registry = 'quay.io' +singularity.registry = 'quay.io' + +// Nextflow plugins +plugins { + id 'nf-validation' // Validation of pipeline parameters and creation of an input channel from a sample sheet +} // Load igenomes.config if required if (!params.igenomes_ignore) { @@ -179,8 +189,6 @@ if (!params.igenomes_ignore) { } else { params.genomes = [:] } - - // Export these variables to prevent local Python/R libraries from conflicting with those in the container // The JULIA depot path has been adjusted to a fixed path `/usr/local/share/julia` that needs to be used for packages in the container. // See https://apeltzer.github.io/post/03-julia-lang-nextflow/ for details on that. Once we have a common agreement on where to keep Julia packages, this is adjustable. @@ -198,19 +206,19 @@ process.shell = ['/bin/bash', '-euo', 'pipefail'] def trace_timestamp = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss') timeline { enabled = true - file = "${params.tracedir}/execution_timeline_${trace_timestamp}.html" + file = "${params.outdir}/pipeline_info/execution_timeline_${trace_timestamp}.html" } report { enabled = true - file = "${params.tracedir}/execution_report_${trace_timestamp}.html" + file = "${params.outdir}/pipeline_info/execution_report_${trace_timestamp}.html" } trace { enabled = true - file = "${params.tracedir}/execution_trace_${trace_timestamp}.txt" + file = "${params.outdir}/pipeline_info/execution_trace_${trace_timestamp}.txt" } dag { enabled = true - file = "${params.tracedir}/pipeline_dag_${trace_timestamp}.html" + file = "${params.outdir}/pipeline_info/pipeline_dag_${trace_timestamp}.html" } manifest { @@ -219,8 +227,8 @@ manifest { homePage = 'https://github.com/nf-core/smrnaseq' description = """Small RNA-Seq Best Practice Analysis Pipeline.""" mainScript = 'main.nf' - nextflowVersion = '!>=22.10.1' - version = '2.2.0' + nextflowVersion = '!>=23.04.0' + version = '2.2.2' doi = '' } diff --git a/nextflow_schema.json b/nextflow_schema.json index f8d98d8c..0a4ede95 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -15,9 +15,9 @@ "input": { "type": "string", "format": "file-path", + "exists": true, "mimetype": "text/csv", "pattern": "^\\S+\\.csv$", - "schema": "assets/schema_input.json", "description": "Path to comma-separated file containing information about the samples in the experiment.", "help_text": "You will need to create a design file with information about the samples in your experiment before running the pipeline. Use this parameter to specify its location. It has to be a comma-separated file with 3 columns, and a header row. See [usage docs](https://nf-co.re/smrnaseq/usage#samplesheet-input).", "fa_icon": "fas fa-file-csv" @@ -57,6 +57,7 @@ "fasta": { "type": "string", "format": "file-path", + "exists": true, "mimetype": "text/plain", "pattern": "^\\S+\\.fn?a(sta)?(\\.gz)?$", "description": "Path to FASTA genome file.", @@ -157,7 +158,7 @@ "description": "Maximum amount of time that can be requested for any single job.", "default": "240.h", "fa_icon": "far fa-clock", - "pattern": "^(\\d+\\.?\\s*(s|m|h|day)\\s*)+$", + "pattern": "^(\\d+\\.?\\s*(s|m|h|d|day)\\s*)+$", "hidden": true, "help_text": "Use to set an upper-limit for the time requirement for each process. Should be a string in the format integer-unit e.g. `--max_time '2.h'`" } @@ -174,12 +175,14 @@ "type": "boolean", "description": "Display help text.", "fa_icon": "fas fa-question-circle", + "default": false, "hidden": true }, "version": { "type": "boolean", "description": "Display version and exit.", "fa_icon": "fas fa-question-circle", + "default": false, "hidden": true }, "publish_dir_mode": { @@ -203,6 +206,7 @@ "type": "boolean", "description": "Send plain-text email instead of HTML.", "fa_icon": "fas fa-remove-format", + "default": false, "hidden": true }, "max_multiqc_email_size": { @@ -217,6 +221,7 @@ "type": "boolean", "description": "Do not use coloured log outputs.", "fa_icon": "fas fa-palette", + "default": false, "hidden": true }, "hook_url": { @@ -228,6 +233,7 @@ }, "multiqc_config": { "type": "string", + "format": "file-path", "description": "Custom config file to supply to MultiQC.", "fa_icon": "fas fa-cog", "hidden": true @@ -243,13 +249,6 @@ "description": "Custom MultiQC yaml file containing HTML including a methods description.", "fa_icon": "fas fa-cog" }, - "tracedir": { - "type": "string", - "description": "Directory to keep pipeline Nextflow logs and reports.", - "default": "${params.outdir}/pipeline_info", - "fa_icon": "fas fa-cogs", - "hidden": true - }, "validate_params": { "type": "boolean", "description": "Boolean whether to validate parameters against the schema at runtime", @@ -257,12 +256,29 @@ "fa_icon": "fas fa-check-square", "hidden": true }, - "show_hidden_params": { + "validationShowHiddenParams": { "type": "boolean", "fa_icon": "far fa-eye-slash", "description": "Show all params when using `--help`", + "default": false, "hidden": true, "help_text": "By default, parameters set as _hidden_ in the schema are not shown on the command line when a user runs with `--help`. Specifying this option will tell the pipeline to show all parameters." + }, + "validationFailUnrecognisedParams": { + "type": "boolean", + "fa_icon": "far fa-check-circle", + "description": "Validation of parameters fails when an unrecognised parameter is found.", + "default": false, + "hidden": true, + "help_text": "By default, when an unrecognised parameter is found, it returns a warinig." + }, + "validationLenientMode": { + "type": "boolean", + "fa_icon": "far fa-check-circle", + "description": "Validation of parameters in lenient more.", + "default": false, + "hidden": true, + "help_text": "Allows string values that are parseable as numbers or booleans. For further information see [JSONSchema docs](https://github.com/everit-org/json-schema#lenient-mode)." } } } diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 01491244..8c8362a9 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -1,21 +1,19 @@ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - VALIDATE INPUTS + PRINT PARAMS SUMMARY ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -def summary_params = NfcoreSchema.paramsSummaryMap(workflow, params) +include { paramsSummaryLog; paramsSummaryMap } from 'plugin/nf-validation' -// Validate input parameters -WorkflowSmrnaseq.initialise(params, log) +def logo = NfcoreTemplate.logo(workflow, params.monochrome_logs) +def citation = '\n' + WorkflowMain.citation(workflow) + '\n' +def summary_params = paramsSummaryMap(workflow) -// TODO nf-core: Add all file path parameters for the pipeline to the list below -// Check input path parameters to see if they exist -def checkPathParamList = [ params.input, params.multiqc_config, params.fasta ] -for (param in checkPathParamList) { if (param) { file(param, checkIfExists: true) } } +// Print parameter summary log to screen +log.info logo + paramsSummaryLog(workflow) + citation -// Check mandatory parameters -if (params.input) { ch_input = file(params.input) } else { exit 1, 'Input samplesheet not specified!' } +WorkflowSmrnaseq.initialise(params, log) /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -69,9 +67,12 @@ workflow SMRNASEQ { // SUBWORKFLOW: Read in samplesheet, validate and stage input files // INPUT_CHECK ( - ch_input + file(params.input) ) ch_versions = ch_versions.mix(INPUT_CHECK.out.versions) + // TODO: OPTIONAL, you can use nf-validation plugin to create an input channel from the samplesheet with Channel.fromSamplesheet("input") + // See the documentation https://nextflow-io.github.io/nf-validation/samplesheets/fromSamplesheet/ + // ! There is currently no tooling to help you write a sample sheet schema // // MODULE: Run FastQC @@ -91,7 +92,7 @@ workflow SMRNASEQ { workflow_summary = WorkflowSmrnaseq.paramsSummaryMultiqc(workflow, summary_params) ch_workflow_summary = Channel.value(workflow_summary) - methods_description = WorkflowSmrnaseq.methodsDescriptionText(workflow, ch_multiqc_custom_methods_description) + methods_description = WorkflowSmrnaseq.methodsDescriptionText(workflow, ch_multiqc_custom_methods_description, params) ch_methods_description = Channel.value(methods_description) ch_multiqc_files = Channel.empty() From 7ea85c446f542dae37fb7b960dd37d18b0afb6d3 Mon Sep 17 00:00:00 2001 From: Rob Syme Date: Wed, 23 Aug 2023 12:58:33 -0400 Subject: [PATCH 159/215] Mirbase has changed their URL structure, so we need to update the URLs in the configuration files and docs. Signed-off-by: Rob Syme --- docs/usage.md | 6 +++--- nextflow.config | 4 ++-- nextflow_schema.json | 6 +++--- workflows/smrnaseq.nf | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 1893e2e6..7a01c1fa 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -26,9 +26,9 @@ It should point to the 3-letter species name used by [miRBase](https://www.mirba Different parameters can be set for the two supported databases. By default `miRBase` will be used with the parameters below. -- `mirna_gtf`: If not supplied by the user, then `mirna_gtf` will point to the latest GFF3 file in miRbase: `https://mirbase.org/ftp/CURRENT/genomes/${params.mirtrace_species}.gff3` -- `mature`: points to the FASTA file of mature miRNA sequences. `https://mirbase.org/ftp/CURRENT/mature.fa.gz` -- `hairpin`: points to the FASTA file of precursor miRNA sequences. `https://mirbase.org/ftp/CURRENT/hairpin.fa.gz` +- `mirna_gtf`: If not supplied by the user, then `mirna_gtf` will point to the latest GFF3 file in miRbase: `https://mirbase.org/download/CURRENT/genomes/${params.mirtrace_species}.gff3` +- `mature`: points to the FASTA file of mature miRNA sequences. `https://mirbase.org/download/CURRENT/mature.fa` +- `hairpin`: points to the FASTA file of precursor miRNA sequences. `https://mirbase.org/download/CURRENT/hairpin.fa` If MirGeneDB should be used instead it needs to be specified using `--mirgenedb` and use the parameters below . diff --git a/nextflow.config b/nextflow.config index ecaa7ccb..61114b48 100644 --- a/nextflow.config +++ b/nextflow.config @@ -20,8 +20,8 @@ params { igenomes_base = 's3://ngi-igenomes/igenomes' igenomes_ignore = false mirna_gtf = null - mature = "https://mirbase.org/ftp/CURRENT/mature.fa.gz" - hairpin = "https://mirbase.org/ftp/CURRENT/hairpin.fa.gz" + mature = "https://mirbase.org/download/CURRENT/mature.fa" + hairpin = "https://mirbase.org/download/CURRENT/hairpin.fa" mirgenedb = false mirgenedb_mature = null mirgenedb_hairpin = null diff --git a/nextflow_schema.json b/nextflow_schema.json index 213199c1..48fda3e7 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -87,7 +87,7 @@ "mirna_gtf": { "type": "string", "description": "GFF/GTF file with coordinates positions of precursor and miRNAs.", - "help_text": "miRBase `.gff3` file, typically downloaded from [`https://mirbase.org/ftp/CURRENT/genomes/`](https://mirbase.org/ftp/CURRENT/genomes/)\n\nIf using iGenomes with `--genome` this file will be downloaded from miRBase automatically during the pipeline run.\n\n", + "help_text": "miRBase `.gff3` file, typically downloaded from [`https://mirbase.org/download/CURRENT/genomes/`](https://mirbase.org/download/CURRENT/genomes/)\n\nIf using iGenomes with `--genome` this file will be downloaded from miRBase automatically during the pipeline run.\n\n", "fa_icon": "fas fa-address-book" }, "mirgenedb_gff": { @@ -100,7 +100,7 @@ "description": "Path to FASTA file with mature miRNAs.", "fa_icon": "fas fa-wheelchair", "help_text": "Typically this will be the `mature.fa` file from miRBase. Can be given either as a plain text `.fa` file or a compressed `.gz` file.\n\nDefaults to the current miRBase release URL, from which the file will be downloaded.", - "default": "https://mirbase.org/ftp/CURRENT/mature.fa.gz" + "default": "https://mirbase.org/download/CURRENT/mature.fa" }, "mirgenedb_mature": { "type": "string", @@ -112,7 +112,7 @@ "description": "Path to FASTA file with miRNAs precursors.", "fa_icon": "fab fa-cuttlefish", "help_text": "Typically this will be the `mature.fa` file from miRBase. Can be given either as a plain text `.fa` file or a compressed `.gz` file.\n\nDefaults to the current miRBase release URL, from which the file will be downloaded.", - "default": "https://mirbase.org/ftp/CURRENT/hairpin.fa.gz" + "default": "https://mirbase.org/download/CURRENT/hairpin.fa" }, "mirgenedb_hairpin": { "type": "string", diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index ad5ecfef..ed8f87c8 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -25,7 +25,7 @@ if (!params.mirtrace_species) { } // Genome options -def mirna_gtf_from_species = params.mirtrace_species ? "https://mirbase.org/ftp/CURRENT/genomes/${params.mirtrace_species}.gff3" : false +def mirna_gtf_from_species = params.mirtrace_species ? "https://mirbase.org/download/CURRENT/genomes/${params.mirtrace_species}.gff3" : false def mirna_gtf = params.mirna_gtf ?: mirna_gtf_from_species /* From d3a0df94251016cdb006dcb3521969b2119dcb4e Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 30 Aug 2023 06:57:12 +0000 Subject: [PATCH 160/215] Template merge and modules updates --- .github/CONTRIBUTING.md | 1 - .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- .github/workflows/awsfulltest.yml | 9 +- .github/workflows/awstest.yml | 8 +- .github/workflows/ci.yml | 2 +- .gitpod.yml | 5 + CITATIONS.md | 5 + README.md | 6 +- assets/methods_description_template.yml | 10 +- assets/multiqc_config.yml | 4 +- assets/nf-core-smrnaseq_logo_light.png | Bin 11484 -> 74188 bytes assets/slackreport.json | 2 +- docs/usage.md | 6 +- lib/NfcoreSchema.groovy | 530 ------------------------ lib/NfcoreTemplate.groovy | 2 +- lib/WorkflowMain.groovy | 32 -- lib/WorkflowSmrnaseq.groovy | 45 +- main.nf | 16 + nextflow.config | 42 +- nextflow_schema.json | 37 +- workflows/smrnaseq.nf | 17 +- 21 files changed, 174 insertions(+), 607 deletions(-) delete mode 100755 lib/NfcoreSchema.groovy diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index b24dd094..33a2c027 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -116,4 +116,3 @@ To get started: Devcontainer specs: - [DevContainer config](.devcontainer/devcontainer.json) -- [Dockerfile](.devcontainer/Dockerfile) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 137da49f..335a06b1 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -42,7 +42,7 @@ body: attributes: label: System information description: | - * Nextflow version _(eg. 22.10.1)_ + * Nextflow version _(eg. 23.04.0)_ * Hardware _(eg. HPC, Desktop, Cloud)_ * Executor _(eg. slurm, local, awsbatch)_ * Container engine: _(e.g. Docker, Singularity, Conda, Podman, Shifter, Charliecloud, or Apptainer)_ diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index 5d00bc97..2ac5826b 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -14,18 +14,23 @@ jobs: runs-on: ubuntu-latest steps: - name: Launch workflow via tower - uses: seqeralabs/action-tower-launch@v1 + uses: seqeralabs/action-tower-launch@v2 with: workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }} access_token: ${{ secrets.TOWER_ACCESS_TOKEN }} compute_env: ${{ secrets.TOWER_COMPUTE_ENV }} + revision: ${{ github.sha }} workdir: s3://${{ secrets.AWS_S3_BUCKET }}/work/smrnaseq/work-${{ github.sha }} parameters: | { + "hook_url": "${{ secrets.MEGATESTS_ALERTS_SLACK_HOOK_URL }}", "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/smrnaseq/results-${{ github.sha }}" } profiles: test_full + - uses: actions/upload-artifact@v3 with: name: Tower debug log file - path: tower_action_*.log + path: | + tower_action_*.log + tower_action_*.json diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml index 7d4c357c..84d22f1c 100644 --- a/.github/workflows/awstest.yml +++ b/.github/workflows/awstest.yml @@ -12,18 +12,22 @@ jobs: steps: # Launch workflow using Tower CLI tool action - name: Launch workflow via tower - uses: seqeralabs/action-tower-launch@v1 + uses: seqeralabs/action-tower-launch@v2 with: workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }} access_token: ${{ secrets.TOWER_ACCESS_TOKEN }} compute_env: ${{ secrets.TOWER_COMPUTE_ENV }} + revision: ${{ github.sha }} workdir: s3://${{ secrets.AWS_S3_BUCKET }}/work/smrnaseq/work-${{ github.sha }} parameters: | { "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/smrnaseq/results-test-${{ github.sha }}" } profiles: test + - uses: actions/upload-artifact@v3 with: name: Tower debug log file - path: tower_action_*.log + path: | + tower_action_*.log + tower_action_*.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c4bd5555..45ad5219 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: strategy: matrix: NXF_VER: - - "22.10.1" + - "23.04.0" - "latest-everything" profile: - "test" diff --git a/.gitpod.yml b/.gitpod.yml index 85d95ecc..25488dcc 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -1,4 +1,9 @@ image: nfcore/gitpod:latest +tasks: + - name: Update Nextflow and setup pre-commit + command: | + pre-commit install --install-hooks + nextflow self-update vscode: extensions: # based on nf-core.nf-core-extensionpack diff --git a/CITATIONS.md b/CITATIONS.md index 11f752b9..67b98c96 100644 --- a/CITATIONS.md +++ b/CITATIONS.md @@ -12,6 +12,8 @@ - [FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/) + > Andrews, S. (2010). FastQC: A Quality Control Tool for High Throughput Sequence Data [Online]. Available online https://www.bioinformatics.babraham.ac.uk/projects/fastqc/. + * [trimgalore](https://www.bioinformatics.babraham.ac.uk/projects/trim_galore/) * [samtools](https://pubmed.ncbi.nlm.nih.gov/19505943/) @@ -56,5 +58,8 @@ - [Docker](https://dl.acm.org/doi/10.5555/2600239.2600241) + > Merkel, D. (2014). Docker: lightweight linux containers for consistent development and deployment. Linux Journal, 2014(239), 2. doi: 10.5555/2600239.2600241. + - [Singularity](https://pubmed.ncbi.nlm.nih.gov/28494014/) + > Kurtzer GM, Sochat V, Bauer MW. Singularity: Scientific containers for mobility of compute. PLoS One. 2017 May 11;12(5):e0177459. doi: 10.1371/journal.pone.0177459. eCollection 2017. PubMed PMID: 28494014; PubMed Central PMCID: PMC5426675. diff --git a/README.md b/README.md index 6fb16c5e..24226773 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/smrnaseq/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.3456879-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.3456879) -[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A522.10.1-23aa62.svg)](https://www.nextflow.io/) +[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A523.04.0-23aa62.svg)](https://www.nextflow.io/) [![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/) [![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/) [![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/) @@ -92,11 +92,11 @@ nextflow run nf-core/smrnaseq \ > provided by the `-c` Nextflow option can be used to provide any configuration _**except for parameters**_; > see [docs](https://nf-co.re/usage/configuration#custom-configuration-files). -For more details, please refer to the [usage documentation](https://nf-co.re/smrnaseq/usage) and the [parameter documentation](https://nf-co.re/smrnaseq/parameters). +For more details and further functionality, please refer to the [usage documentation](https://nf-co.re/smrnaseq/usage) and the [parameter documentation](https://nf-co.re/smrnaseq/parameters). ## Pipeline output -To see the the results of a test run with a full size dataset refer to the [results](https://nf-co.re/smrnaseq/results) tab on the nf-core website pipeline page. +To see the results of an example test run with a full size dataset refer to the [results](https://nf-co.re/smrnaseq/results) tab on the nf-core website pipeline page. For more details about the output files and reports, please refer to the [output documentation](https://nf-co.re/smrnaseq/output). diff --git a/assets/methods_description_template.yml b/assets/methods_description_template.yml index 1f05424e..87cc6194 100644 --- a/assets/methods_description_template.yml +++ b/assets/methods_description_template.yml @@ -5,13 +5,17 @@ section_href: "https://github.com/nf-core/smrnaseq" plot_type: "html" data: |

    Methods

    -

    Data was processed using nf-core/smrnaseq v${workflow.manifest.version} ${doi_text} of the nf-core collection of workflows (Ewels et al., 2020).

    +

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

    The pipeline was executed with Nextflow v${workflow.nextflow.version} (Di Tommaso et al., 2017) with the following command:

    ${workflow.commandLine}
    +

    ${tool_citations}

    References

      -
    • Di Tommaso, P., Chatzou, M., Floden, E. W., Barja, P. P., Palumbo, E., & Notredame, C. (2017). Nextflow enables reproducible computational workflows. Nature Biotechnology, 35(4), 316-319. https://doi.org/10.1038/nbt.3820
    • -
    • Ewels, P. A., Peltzer, A., Fillinger, S., Patel, H., Alneberg, J., Wilm, A., Garcia, M. U., Di Tommaso, P., & Nahnsen, S. (2020). The nf-core framework for community-curated bioinformatics pipelines. Nature Biotechnology, 38(3), 276-278. https://doi.org/10.1038/s41587-020-0439-x
    • +
    • Di Tommaso, P., Chatzou, M., Floden, E. W., Barja, P. P., Palumbo, E., & Notredame, C. (2017). Nextflow enables reproducible computational workflows. Nature Biotechnology, 35(4), 316-319. doi: 10.1038/nbt.3820
    • +
    • Ewels, P. A., Peltzer, A., Fillinger, S., Patel, H., Alneberg, J., Wilm, A., Garcia, M. U., Di Tommaso, P., & Nahnsen, S. (2020). The nf-core framework for community-curated bioinformatics pipelines. Nature Biotechnology, 38(3), 276-278. doi: 10.1038/s41587-020-0439-x
    • +
    • Grüning, B., Dale, R., Sjödin, A., Chapman, B. A., Rowe, J., Tomkins-Tinch, C. H., Valieris, R., Köster, J., & Bioconda Team. (2018). Bioconda: sustainable and comprehensive software distribution for the life sciences. Nature Methods, 15(7), 475–476. doi: 10.1038/s41592-018-0046-7
    • +
    • da Veiga Leprevost, F., Grüning, B. A., Alves Aflitos, S., Röst, H. L., Uszkoreit, J., Barsnes, H., Vaudel, M., Moreno, P., Gatto, L., Weber, J., Bai, M., Jimenez, R. C., Sachsenberg, T., Pfeuffer, J., Vera Alvarez, R., Griss, J., Nesvizhskii, A. I., & Perez-Riverol, Y. (2017). BioContainers: an open-source and community-driven framework for software standardization. Bioinformatics (Oxford, England), 33(16), 2580–2582. doi: 10.1093/bioinformatics/btx192
    • + ${tool_bibliography}
    Notes:
    diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index df5ec37a..23da1135 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -1,7 +1,7 @@ report_comment: > - This report has been generated by the nf-core/smrnaseq + This report has been generated by the nf-core/smrnaseq analysis pipeline. For information about how to interpret these results, please see the - documentation. + documentation. report_section_order: "nf-core-smrnaseq-methods-description": order: -1000 diff --git a/assets/nf-core-smrnaseq_logo_light.png b/assets/nf-core-smrnaseq_logo_light.png index 2ecc50a7721db40c53d63ab96945b624cdd188ea..262fa1b099eb8b3cbd5f7d838f87a54dc0ec4ebe 100644 GIT binary patch literal 74188 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�ev`Q}H7y#R1zKkC5n?0_OP7^FqWWeXhX0t0pNK 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

    )bNtXB<>| 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 literal 11484 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 diff --git a/assets/slackreport.json b/assets/slackreport.json index 043d02f2..214c7fa9 100644 --- a/assets/slackreport.json +++ b/assets/slackreport.json @@ -3,7 +3,7 @@ { "fallback": "Plain-text summary of the attachment.", "color": "<% if (success) { %>good<% } else { %>danger<%} %>", - "author_name": "sanger-tol/readmapping v${version} - ${runName}", + "author_name": "nf-core/smrnaseq v${version} - ${runName}", "author_icon": "https://www.nextflow.io/docs/latest/_static/favicon.ico", "text": "<% if (success) { %>Pipeline completed successfully!<% } else { %>Pipeline completed with errors<% } %>", "fields": [ diff --git a/docs/usage.md b/docs/usage.md index 1893e2e6..f7810e59 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -104,7 +104,7 @@ An [example samplesheet](../assets/samplesheet.csv) has been provided with the p The typical command for running the pipeline is as follows: ```bash -nextflow run nf-core/smrnaseq --input samplesheet.csv --outdir --genome GRCh37 -profile docker +nextflow run nf-core/smrnaseq --input ./samplesheet.csv --outdir ./results --genome GRCh37 -profile docker ``` This will launch the pipeline with the `docker` configuration profile. See below for more information about profiles. @@ -123,7 +123,8 @@ If you wish to repeatedly use the same parameters for multiple runs, rather than Pipeline settings can be provided in a `yaml` or `json` file via `-params-file `. > ⚠️ Do not use `-c ` to specify parameters as this will result in errors. Custom config files specified with `-c` must only be used for [tuning process resource specifications](https://nf-co.re/docs/usage/configuration#tuning-workflow-resources), other infrastructural tweaks (such as output directories), or module arguments (args). -> The above pipeline run specified with a params file in yaml format: + +The above pipeline run specified with a params file in yaml format: ```bash nextflow run nf-core/smrnaseq -profile docker -params-file params.yaml @@ -135,7 +136,6 @@ with `params.yaml` containing: input: './samplesheet.csv' outdir: './results/' genome: 'GRCh37' -input: 'data' <...> ``` diff --git a/lib/NfcoreSchema.groovy b/lib/NfcoreSchema.groovy deleted file mode 100755 index 9b34804d..00000000 --- a/lib/NfcoreSchema.groovy +++ /dev/null @@ -1,530 +0,0 @@ -// -// This file holds several functions used to perform JSON parameter validation, help and summary rendering for the nf-core pipeline template. -// - -import nextflow.Nextflow -import org.everit.json.schema.Schema -import org.everit.json.schema.loader.SchemaLoader -import org.everit.json.schema.ValidationException -import org.json.JSONObject -import org.json.JSONTokener -import org.json.JSONArray -import groovy.json.JsonSlurper -import groovy.json.JsonBuilder - -class NfcoreSchema { - - // - // Resolve Schema path relative to main workflow directory - // - public static String getSchemaPath(workflow, schema_filename='nextflow_schema.json') { - return "${workflow.projectDir}/${schema_filename}" - } - - // - // Function to loop over all parameters defined in schema and check - // whether the given parameters adhere to the specifications - // - /* groovylint-disable-next-line UnusedPrivateMethodParameter */ - public static void validateParameters(workflow, params, log, schema_filename='nextflow_schema.json') { - def has_error = false - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// - // Check for nextflow core params and unexpected params - def json = new File(getSchemaPath(workflow, schema_filename=schema_filename)).text - def Map schemaParams = (Map) new JsonSlurper().parseText(json).get('definitions') - def nf_params = [ - // Options for base `nextflow` command - 'bg', - 'c', - 'C', - 'config', - 'd', - 'D', - 'dockerize', - 'h', - 'log', - 'q', - 'quiet', - 'syslog', - 'v', - - // Options for `nextflow run` command - 'ansi', - 'ansi-log', - 'bg', - 'bucket-dir', - 'c', - 'cache', - 'config', - 'dsl2', - 'dump-channels', - 'dump-hashes', - 'E', - 'entry', - 'latest', - 'lib', - 'main-script', - 'N', - 'name', - 'offline', - 'params-file', - 'pi', - 'plugins', - 'poll-interval', - 'pool-size', - 'profile', - 'ps', - 'qs', - 'queue-size', - 'r', - 'resume', - 'revision', - 'stdin', - 'stub', - 'stub-run', - 'test', - 'w', - 'with-apptainer', - 'with-charliecloud', - 'with-conda', - 'with-dag', - 'with-docker', - 'with-mpi', - 'with-notification', - 'with-podman', - 'with-report', - 'with-singularity', - 'with-timeline', - 'with-tower', - 'with-trace', - 'with-weblog', - 'without-docker', - 'without-podman', - 'work-dir' - ] - def unexpectedParams = [] - - // Collect expected parameters from the schema - def expectedParams = [] - def enums = [:] - for (group in schemaParams) { - for (p in group.value['properties']) { - expectedParams.push(p.key) - if (group.value['properties'][p.key].containsKey('enum')) { - enums[p.key] = group.value['properties'][p.key]['enum'] - } - } - } - - for (specifiedParam in params.keySet()) { - // nextflow params - if (nf_params.contains(specifiedParam)) { - log.error "ERROR: You used a core Nextflow option with two hyphens: '--${specifiedParam}'. Please resubmit with '-${specifiedParam}'" - has_error = true - } - // unexpected params - def params_ignore = params.schema_ignore_params.split(',') + 'schema_ignore_params' - def expectedParamsLowerCase = expectedParams.collect{ it.replace("-", "").toLowerCase() } - def specifiedParamLowerCase = specifiedParam.replace("-", "").toLowerCase() - def isCamelCaseBug = (specifiedParam.contains("-") && !expectedParams.contains(specifiedParam) && expectedParamsLowerCase.contains(specifiedParamLowerCase)) - if (!expectedParams.contains(specifiedParam) && !params_ignore.contains(specifiedParam) && !isCamelCaseBug) { - // Temporarily remove camelCase/camel-case params #1035 - def unexpectedParamsLowerCase = unexpectedParams.collect{ it.replace("-", "").toLowerCase()} - if (!unexpectedParamsLowerCase.contains(specifiedParamLowerCase)){ - unexpectedParams.push(specifiedParam) - } - } - } - - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// - // Validate parameters against the schema - InputStream input_stream = new File(getSchemaPath(workflow, schema_filename=schema_filename)).newInputStream() - JSONObject raw_schema = new JSONObject(new JSONTokener(input_stream)) - - // Remove anything that's in params.schema_ignore_params - raw_schema = removeIgnoredParams(raw_schema, params) - - Schema schema = SchemaLoader.load(raw_schema) - - // Clean the parameters - def cleanedParams = cleanParameters(params) - - // Convert to JSONObject - def jsonParams = new JsonBuilder(cleanedParams) - JSONObject params_json = new JSONObject(jsonParams.toString()) - - // Validate - try { - schema.validate(params_json) - } catch (ValidationException e) { - println '' - log.error 'ERROR: Validation of pipeline parameters failed!' - JSONObject exceptionJSON = e.toJSON() - printExceptions(exceptionJSON, params_json, log, enums) - println '' - has_error = true - } - - // Check for unexpected parameters - if (unexpectedParams.size() > 0) { - Map colors = NfcoreTemplate.logColours(params.monochrome_logs) - println '' - def warn_msg = 'Found unexpected parameters:' - for (unexpectedParam in unexpectedParams) { - warn_msg = warn_msg + "\n* --${unexpectedParam}: ${params[unexpectedParam].toString()}" - } - log.warn warn_msg - log.info "- ${colors.dim}Ignore this warning: params.schema_ignore_params = \"${unexpectedParams.join(',')}\" ${colors.reset}" - println '' - } - - if (has_error) { - Nextflow.error('Exiting!') - } - } - - // - // Beautify parameters for --help - // - public static String paramsHelp(workflow, params, command, schema_filename='nextflow_schema.json') { - Map colors = NfcoreTemplate.logColours(params.monochrome_logs) - Integer num_hidden = 0 - String output = '' - output += 'Typical pipeline command:\n\n' - output += " ${colors.cyan}${command}${colors.reset}\n\n" - Map params_map = paramsLoad(getSchemaPath(workflow, schema_filename=schema_filename)) - Integer max_chars = paramsMaxChars(params_map) + 1 - Integer desc_indent = max_chars + 14 - Integer dec_linewidth = 160 - desc_indent - for (group in params_map.keySet()) { - Integer num_params = 0 - String group_output = colors.underlined + colors.bold + group + colors.reset + '\n' - def group_params = params_map.get(group) // This gets the parameters of that particular group - for (param in group_params.keySet()) { - if (group_params.get(param).hidden && !params.show_hidden_params) { - num_hidden += 1 - continue; - } - def type = '[' + group_params.get(param).type + ']' - def description = group_params.get(param).description - def defaultValue = group_params.get(param).default != null ? " [default: " + group_params.get(param).default.toString() + "]" : '' - def description_default = description + colors.dim + defaultValue + colors.reset - // Wrap long description texts - // Loosely based on https://dzone.com/articles/groovy-plain-text-word-wrap - if (description_default.length() > dec_linewidth){ - List olines = [] - String oline = "" // " " * indent - description_default.split(" ").each() { wrd -> - if ((oline.size() + wrd.size()) <= dec_linewidth) { - oline += wrd + " " - } else { - olines += oline - oline = wrd + " " - } - } - olines += oline - description_default = olines.join("\n" + " " * desc_indent) - } - group_output += " --" + param.padRight(max_chars) + colors.dim + type.padRight(10) + colors.reset + description_default + '\n' - num_params += 1 - } - group_output += '\n' - if (num_params > 0){ - output += group_output - } - } - if (num_hidden > 0){ - output += colors.dim + "!! Hiding $num_hidden params, use --show_hidden_params to show them !!\n" + colors.reset - } - output += NfcoreTemplate.dashedLine(params.monochrome_logs) - return output - } - - // - // Groovy Map summarising parameters/workflow options used by the pipeline - // - public static LinkedHashMap paramsSummaryMap(workflow, params, schema_filename='nextflow_schema.json') { - // Get a selection of core Nextflow workflow options - def Map workflow_summary = [:] - if (workflow.revision) { - workflow_summary['revision'] = workflow.revision - } - workflow_summary['runName'] = workflow.runName - if (workflow.containerEngine) { - workflow_summary['containerEngine'] = workflow.containerEngine - } - if (workflow.container) { - workflow_summary['container'] = workflow.container - } - workflow_summary['launchDir'] = workflow.launchDir - workflow_summary['workDir'] = workflow.workDir - workflow_summary['projectDir'] = workflow.projectDir - workflow_summary['userName'] = workflow.userName - workflow_summary['profile'] = workflow.profile - workflow_summary['configFiles'] = workflow.configFiles.join(', ') - - // Get pipeline parameters defined in JSON Schema - def Map params_summary = [:] - def params_map = paramsLoad(getSchemaPath(workflow, schema_filename=schema_filename)) - for (group in params_map.keySet()) { - def sub_params = new LinkedHashMap() - def group_params = params_map.get(group) // This gets the parameters of that particular group - for (param in group_params.keySet()) { - if (params.containsKey(param)) { - def params_value = params.get(param) - def schema_value = group_params.get(param).default - def param_type = group_params.get(param).type - if (schema_value != null) { - if (param_type == 'string') { - if (schema_value.contains('$projectDir') || schema_value.contains('${projectDir}')) { - def sub_string = schema_value.replace('\$projectDir', '') - sub_string = sub_string.replace('\${projectDir}', '') - if (params_value.contains(sub_string)) { - schema_value = params_value - } - } - if (schema_value.contains('$params.outdir') || schema_value.contains('${params.outdir}')) { - def sub_string = schema_value.replace('\$params.outdir', '') - sub_string = sub_string.replace('\${params.outdir}', '') - if ("${params.outdir}${sub_string}" == params_value) { - schema_value = params_value - } - } - } - } - - // We have a default in the schema, and this isn't it - if (schema_value != null && params_value != schema_value) { - sub_params.put(param, params_value) - } - // No default in the schema, and this isn't empty - else if (schema_value == null && params_value != "" && params_value != null && params_value != false) { - sub_params.put(param, params_value) - } - } - } - params_summary.put(group, sub_params) - } - return [ 'Core Nextflow options' : workflow_summary ] << params_summary - } - - // - // Beautify parameters for summary and return as string - // - public static String paramsSummaryLog(workflow, params) { - Map colors = NfcoreTemplate.logColours(params.monochrome_logs) - String output = '' - def params_map = paramsSummaryMap(workflow, params) - def max_chars = paramsMaxChars(params_map) - for (group in params_map.keySet()) { - def group_params = params_map.get(group) // This gets the parameters of that particular group - if (group_params) { - output += colors.bold + group + colors.reset + '\n' - for (param in group_params.keySet()) { - output += " " + colors.blue + param.padRight(max_chars) + ": " + colors.green + group_params.get(param) + colors.reset + '\n' - } - output += '\n' - } - } - output += "!! Only displaying parameters that differ from the pipeline defaults !!\n" - output += NfcoreTemplate.dashedLine(params.monochrome_logs) - return output - } - - // - // Loop over nested exceptions and print the causingException - // - private static void printExceptions(ex_json, params_json, log, enums, limit=5) { - def causingExceptions = ex_json['causingExceptions'] - if (causingExceptions.length() == 0) { - def m = ex_json['message'] =~ /required key \[([^\]]+)\] not found/ - // Missing required param - if (m.matches()) { - log.error "* Missing required parameter: --${m[0][1]}" - } - // Other base-level error - else if (ex_json['pointerToViolation'] == '#') { - log.error "* ${ex_json['message']}" - } - // Error with specific param - else { - def param = ex_json['pointerToViolation'] - ~/^#\// - def param_val = params_json[param].toString() - if (enums.containsKey(param)) { - def error_msg = "* --${param}: '${param_val}' is not a valid choice (Available choices" - if (enums[param].size() > limit) { - log.error "${error_msg} (${limit} of ${enums[param].size()}): ${enums[param][0..limit-1].join(', ')}, ... )" - } else { - log.error "${error_msg}: ${enums[param].join(', ')})" - } - } else { - log.error "* --${param}: ${ex_json['message']} (${param_val})" - } - } - } - for (ex in causingExceptions) { - printExceptions(ex, params_json, log, enums) - } - } - - // - // Remove an element from a JSONArray - // - private static JSONArray removeElement(json_array, element) { - def list = [] - int len = json_array.length() - for (int i=0;i - if(raw_schema.keySet().contains('definitions')){ - raw_schema.definitions.each { definition -> - for (key in definition.keySet()){ - if (definition[key].get("properties").keySet().contains(ignore_param)){ - // Remove the param to ignore - definition[key].get("properties").remove(ignore_param) - // If the param was required, change this - if (definition[key].has("required")) { - def cleaned_required = removeElement(definition[key].required, ignore_param) - definition[key].put("required", cleaned_required) - } - } - } - } - } - if(raw_schema.keySet().contains('properties') && raw_schema.get('properties').keySet().contains(ignore_param)) { - raw_schema.get("properties").remove(ignore_param) - } - if(raw_schema.keySet().contains('required') && raw_schema.required.contains(ignore_param)) { - def cleaned_required = removeElement(raw_schema.required, ignore_param) - raw_schema.put("required", cleaned_required) - } - } - return raw_schema - } - - // - // Clean and check parameters relative to Nextflow native classes - // - private static Map cleanParameters(params) { - def new_params = params.getClass().newInstance(params) - for (p in params) { - // remove anything evaluating to false - if (!p['value']) { - new_params.remove(p.key) - } - // Cast MemoryUnit to String - if (p['value'].getClass() == nextflow.util.MemoryUnit) { - new_params.replace(p.key, p['value'].toString()) - } - // Cast Duration to String - if (p['value'].getClass() == nextflow.util.Duration) { - new_params.replace(p.key, p['value'].toString().replaceFirst(/d(?!\S)/, "day")) - } - // Cast LinkedHashMap to String - if (p['value'].getClass() == LinkedHashMap) { - new_params.replace(p.key, p['value'].toString()) - } - } - return new_params - } - - // - // This function tries to read a JSON params file - // - private static LinkedHashMap paramsLoad(String json_schema) { - def params_map = new LinkedHashMap() - try { - params_map = paramsRead(json_schema) - } catch (Exception e) { - println "Could not read parameters settings from JSON. $e" - params_map = new LinkedHashMap() - } - return params_map - } - - // - // Method to actually read in JSON file using Groovy. - // Group (as Key), values are all parameters - // - Parameter1 as Key, Description as Value - // - Parameter2 as Key, Description as Value - // .... - // Group - // - - private static LinkedHashMap paramsRead(String json_schema) throws Exception { - def json = new File(json_schema).text - def Map schema_definitions = (Map) new JsonSlurper().parseText(json).get('definitions') - def Map schema_properties = (Map) new JsonSlurper().parseText(json).get('properties') - /* Tree looks like this in nf-core schema - * definitions <- this is what the first get('definitions') gets us - group 1 - title - description - properties - parameter 1 - type - description - parameter 2 - type - description - group 2 - title - description - properties - parameter 1 - type - description - * properties <- parameters can also be ungrouped, outside of definitions - parameter 1 - type - description - */ - - // Grouped params - def params_map = new LinkedHashMap() - schema_definitions.each { key, val -> - def Map group = schema_definitions."$key".properties // Gets the property object of the group - def title = schema_definitions."$key".title - def sub_params = new LinkedHashMap() - group.each { innerkey, value -> - sub_params.put(innerkey, value) - } - params_map.put(title, sub_params) - } - - // Ungrouped params - def ungrouped_params = new LinkedHashMap() - schema_properties.each { innerkey, value -> - ungrouped_params.put(innerkey, value) - } - params_map.put("Other parameters", ungrouped_params) - - return params_map - } - - // - // Get maximum number of characters across all parameter names - // - private static Integer paramsMaxChars(params_map) { - Integer max_chars = 0 - for (group in params_map.keySet()) { - def group_params = params_map.get(group) // This gets the parameters of that particular group - for (param in group_params.keySet()) { - if (param.size() > max_chars) { - max_chars = param.size() - } - } - } - return max_chars - } -} diff --git a/lib/NfcoreTemplate.groovy b/lib/NfcoreTemplate.groovy index 25a0a74a..408951ae 100755 --- a/lib/NfcoreTemplate.groovy +++ b/lib/NfcoreTemplate.groovy @@ -128,7 +128,7 @@ class NfcoreTemplate { def email_html = html_template.toString() // Render the sendmail template - def max_multiqc_email_size = params.max_multiqc_email_size as nextflow.util.MemoryUnit + def max_multiqc_email_size = (params.containsKey('max_multiqc_email_size') ? params.max_multiqc_email_size : 0) as nextflow.util.MemoryUnit def smail_fields = [ email: email_address, subject: subject, email_txt: email_txt, email_html: email_html, projectDir: "$projectDir", mqcFile: mqc_report, mqcMaxSize: max_multiqc_email_size.toBytes() ] def sf = new File("$projectDir/assets/sendmail_template.txt") def sendmail_template = engine.createTemplate(sf).make(smail_fields) diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy index 9a0db96c..ed5a126c 100755 --- a/lib/WorkflowMain.groovy +++ b/lib/WorkflowMain.groovy @@ -19,30 +19,6 @@ class WorkflowMain { " https://github.com/${workflow.manifest.name}/blob/master/CITATIONS.md" } - // - // Generate help string - // - public static String help(workflow, params) { - def command = "nextflow run ${workflow.manifest.name} --input samplesheet.csv --genome GRCh37 -profile docker" - def help_string = '' - help_string += NfcoreTemplate.logo(workflow, params.monochrome_logs) - help_string += NfcoreSchema.paramsHelp(workflow, params, command) - help_string += '\n' + citation(workflow) + '\n' - help_string += NfcoreTemplate.dashedLine(params.monochrome_logs) - return help_string - } - - // - // Generate parameter summary log string - // - public static String paramsSummaryLog(workflow, params) { - def summary_log = '' - summary_log += NfcoreTemplate.logo(workflow, params.monochrome_logs) - summary_log += NfcoreSchema.paramsSummaryLog(workflow, params) - summary_log += '\n' + citation(workflow) + '\n' - summary_log += NfcoreTemplate.dashedLine(params.monochrome_logs) - return summary_log - } // // Validate parameters and print summary to screen @@ -65,14 +41,6 @@ class WorkflowMain { System.exit(0) } - // Print parameter summary log to screen - log.info paramsSummaryLog(workflow, params) - - // Validate workflow parameters via the JSON schema - if (params.validate_params) { - NfcoreSchema.validateParameters(workflow, params, log) - } - // Check that a -profile or Nextflow config has been provided to run the pipeline NfcoreTemplate.checkConfigProvided(workflow, log) diff --git a/lib/WorkflowSmrnaseq.groovy b/lib/WorkflowSmrnaseq.groovy index 7013e903..703c1342 100755 --- a/lib/WorkflowSmrnaseq.groovy +++ b/lib/WorkflowSmrnaseq.groovy @@ -11,6 +11,7 @@ class WorkflowSmrnaseq { // Check and validate parameters // public static void initialise(params, log) { + genomeExistsError(params, log) } @@ -41,15 +42,57 @@ class WorkflowSmrnaseq { return yaml_file_text } - public static String methodsDescriptionText(run_workflow, mqc_methods_yaml) { + // + // Generate methods description for MultiQC + // + + public static String toolCitationText(params) { + + // TODO Optionally add in-text citation tools to this list. + // Can use ternary operators to dynamically construct based conditions, e.g. params["run_xyz"] ? "Tool (Foo et al. 2023)" : "", + // Uncomment function in methodsDescriptionText to render in MultiQC report + def citation_text = [ + "Tools used in the workflow included:", + "FastQC (Andrews 2010),", + "MultiQC (Ewels et al. 2016)", + "." + ].join(' ').trim() + + return citation_text + } + + public static String toolBibliographyText(params) { + + // TODO Optionally add bibliographic entries to this list. + // Can use ternary operators to dynamically construct based conditions, e.g. params["run_xyz"] ? "

  • Author (2023) Pub name, Journal, DOI
  • " : "", + // Uncomment function in methodsDescriptionText to render in MultiQC report + def reference_text = [ + "
  • Andrews S, (2010) FastQC, URL: https://www.bioinformatics.babraham.ac.uk/projects/fastqc/).
  • ", + "
  • Ewels, P., Magnusson, M., Lundin, S., & Käller, M. (2016). MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics , 32(19), 3047–3048. doi: /10.1093/bioinformatics/btw354
  • " + ].join(' ').trim() + + return reference_text + } + + public static String methodsDescriptionText(run_workflow, mqc_methods_yaml, params) { // Convert to a named map so can be used as with familar NXF ${workflow} variable syntax in the MultiQC YML file def meta = [:] meta.workflow = run_workflow.toMap() meta["manifest_map"] = run_workflow.manifest.toMap() + // Pipeline DOI meta["doi_text"] = meta.manifest_map.doi ? "(doi: ${meta.manifest_map.doi})" : "" 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.
  • " + // Tool references + meta["tool_citations"] = "" + meta["tool_bibliography"] = "" + + // TODO Only uncomment below if logic in toolCitationText/toolBibliographyText has been filled! + //meta["tool_citations"] = toolCitationText(params).replaceAll(", \\.", ".").replaceAll("\\. \\.", ".").replaceAll(", \\.", ".") + //meta["tool_bibliography"] = toolBibliographyText(params) + + def methods_text = mqc_methods_yaml.text def engine = new SimpleTemplateEngine() diff --git a/main.nf b/main.nf index 68e88980..e0072925 100644 --- a/main.nf +++ b/main.nf @@ -27,6 +27,22 @@ params.bowtie_index = WorkflowMain.getGenomeAttribute(params, 'bowtie') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +include { validateParameters; paramsHelp } from 'plugin/nf-validation' + +// Print help message if needed +if (params.help) { + def logo = NfcoreTemplate.logo(workflow, params.monochrome_logs) + def citation = '\n' + WorkflowMain.citation(workflow) + '\n' + def String command = "nextflow run ${workflow.manifest.name} --input samplesheet.csv --genome GRCh37 -profile docker" + log.info logo + paramsHelp(command) + citation + NfcoreTemplate.dashedLine(params.monochrome_logs) + System.exit(0) +} + +// Validate input parameters +if (params.validate_params) { + validateParameters() +} + WorkflowMain.initialise(workflow, params, log) /* diff --git a/nextflow.config b/nextflow.config index ecaa7ccb..a808d4aa 100644 --- a/nextflow.config +++ b/nextflow.config @@ -61,7 +61,6 @@ params { // Boilerplate options outdir = null - tracedir = "${params.outdir}/pipeline_info" publish_dir_mode = 'copy' email = null email_on_fail = null @@ -70,10 +69,6 @@ params { hook_url = null help = false version = false - validate_params = true - show_hidden_params = false - schema_ignore_params = 'genomes' - // Config options custom_config_version = 'master' @@ -89,6 +84,20 @@ params { max_cpus = 16 max_time = '240.h' + // Schema validation default options + validationFailUnrecognisedParams = false + validationLenientMode = false + validationSchemaIgnoreParams = 'genomes' + validationShowHiddenParams = false + validate_params = true + + // Schema validation default options + validationFailUnrecognisedParams = false + validationLenientMode = false + validationSchemaIgnoreParams = 'genomes' + validationShowHiddenParams = false + validate_params = true + } // Load base.config by default for all pipelines @@ -204,6 +213,19 @@ profiles { test_full { includeConfig 'conf/test_full.config' } } +// Set default registry for Apptainer, Docker, Podman and Singularity independent of -profile +// Will not be used unless Apptainer / Docker / Podman / Singularity are enabled +// Set to your registry if you have a mirror of containers +apptainer.registry = 'quay.io' +docker.registry = 'quay.io' +podman.registry = 'quay.io' +singularity.registry = 'quay.io' + +// Nextflow plugins +plugins { + id 'nf-validation' // Validation of pipeline parameters and creation of an input channel from a sample sheet +} + // Load igenomes.config if required if (!params.igenomes_ignore) { includeConfig 'conf/igenomes.config' @@ -234,19 +256,19 @@ podman.registry = 'quay.io' def trace_timestamp = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss') timeline { enabled = true - file = "${params.tracedir}/execution_timeline_${trace_timestamp}.html" + file = "${params.outdir}/pipeline_info/execution_timeline_${trace_timestamp}.html" } report { enabled = true - file = "${params.tracedir}/execution_report_${trace_timestamp}.html" + file = "${params.outdir}/pipeline_info/execution_report_${trace_timestamp}.html" } trace { enabled = true - file = "${params.tracedir}/execution_trace_${trace_timestamp}.txt" + file = "${params.outdir}/pipeline_info/execution_trace_${trace_timestamp}.txt" } dag { enabled = true - file = "${params.tracedir}/pipeline_dag_${trace_timestamp}.html" + file = "${params.outdir}/pipeline_info/pipeline_dag_${trace_timestamp}.html" } manifest { @@ -255,7 +277,7 @@ manifest { homePage = 'https://github.com/nf-core/smrnaseq' description = """Small RNA-Seq Best Practice Analysis Pipeline.""" mainScript = 'main.nf' - nextflowVersion = '!>=22.10.1' + nextflowVersion = '!>=23.04.0' version = '2.2.2' doi = '' } diff --git a/nextflow_schema.json b/nextflow_schema.json index 213199c1..331a41b6 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -15,9 +15,9 @@ "input": { "type": "string", "format": "file-path", + "exists": true, "mimetype": "text/csv", "pattern": "^\\S+\\.csv$", - "schema": "assets/schema_input.json", "description": "Path to comma-separated file containing information about the samples in the experiment.", "help_text": "You will need to create a design file with information about the samples in your experiment before running the pipeline. Use this parameter to specify its location. It has to be a comma-separated file with 3 columns, and a header row. See [usage docs](https://nf-co.re/smrnaseq/usage#samplesheet-input).", "fa_icon": "fas fa-file-csv" @@ -80,6 +80,8 @@ }, "fasta": { "type": "string", + "format": "file-path", + "exists": true, "fa_icon": "fas fa-font", "description": "Path to reference genome FASTA genome file.", "help_text": "If you have no genome reference available, the pipeline can build one using a FASTA file. This requires additional time and resources, so it's better to use a pre-build index if possible." @@ -348,7 +350,7 @@ "description": "Maximum amount of time that can be requested for any single job.", "default": "240.h", "fa_icon": "far fa-clock", - "pattern": "^(\\d+\\.?\\s*(s|m|h|day)\\s*)+$", + "pattern": "^(\\d+\\.?\\s*(s|m|h|d|day)\\s*)+$", "hidden": true, "help_text": "Use to set an upper-limit for the time requirement for each process. Should be a string in the format integer-unit e.g. `--max_time '2.h'`" } @@ -365,12 +367,14 @@ "type": "boolean", "description": "Display help text.", "fa_icon": "fas fa-question-circle", + "default": false, "hidden": true }, "version": { "type": "boolean", "description": "Display version and exit.", "fa_icon": "fas fa-question-circle", + "default": false, "hidden": true }, "publish_dir_mode": { @@ -394,6 +398,7 @@ "type": "boolean", "description": "Send plain-text email instead of HTML.", "fa_icon": "fas fa-remove-format", + "default": false, "hidden": true }, "max_multiqc_email_size": { @@ -408,6 +413,7 @@ "type": "boolean", "description": "Do not use coloured log outputs.", "fa_icon": "fas fa-palette", + "default": false, "hidden": true }, "hook_url": { @@ -419,6 +425,7 @@ }, "multiqc_config": { "type": "string", + "format": "file-path", "description": "Custom config file to supply to MultiQC.", "fa_icon": "fas fa-cog", "hidden": true @@ -434,13 +441,6 @@ "description": "Custom MultiQC yaml file containing HTML including a methods description.", "fa_icon": "fas fa-cog" }, - "tracedir": { - "type": "string", - "description": "Directory to keep pipeline Nextflow logs and reports.", - "default": "${params.outdir}/pipeline_info", - "fa_icon": "fas fa-cogs", - "hidden": true - }, "validate_params": { "type": "boolean", "description": "Boolean whether to validate parameters against the schema at runtime", @@ -448,12 +448,29 @@ "fa_icon": "fas fa-check-square", "hidden": true }, - "show_hidden_params": { + "validationShowHiddenParams": { "type": "boolean", "fa_icon": "far fa-eye-slash", "description": "Show all params when using `--help`", + "default": false, "hidden": true, "help_text": "By default, parameters set as _hidden_ in the schema are not shown on the command line when a user runs with `--help`. Specifying this option will tell the pipeline to show all parameters." + }, + "validationFailUnrecognisedParams": { + "type": "boolean", + "fa_icon": "far fa-check-circle", + "description": "Validation of parameters fails when an unrecognised parameter is found.", + "default": false, + "hidden": true, + "help_text": "By default, when an unrecognised parameter is found, it returns a warinig." + }, + "validationLenientMode": { + "type": "boolean", + "fa_icon": "far fa-check-circle", + "description": "Validation of parameters in lenient more.", + "default": false, + "hidden": true, + "help_text": "Allows string values that are parseable as numbers or booleans. For further information see [JSONSchema docs](https://github.com/everit-org/json-schema#lenient-mode)." } } } diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index ad5ecfef..ac9d1646 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -1,12 +1,18 @@ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - VALIDATE INPUTS + PRINT PARAMS SUMMARY ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -def summary_params = NfcoreSchema.paramsSummaryMap(workflow, params) +include { paramsSummaryLog; paramsSummaryMap } from 'plugin/nf-validation' + +def logo = NfcoreTemplate.logo(workflow, params.monochrome_logs) +def citation = '\n' + WorkflowMain.citation(workflow) + '\n' +def summary_params = paramsSummaryMap(workflow) + +// Print parameter summary log to screen +log.info logo + paramsSummaryLog(workflow) + citation -// Validate input parameters WorkflowSmrnaseq.initialise(params, log) // Check input path parameters to see if they exist @@ -96,7 +102,7 @@ workflow SMRNASEQ { // SUBWORKFLOW: Read in samplesheet, validate and stage input files // INPUT_CHECK ( - ch_input + file(params.input) ) .reads .dump(tag: 'group') @@ -109,6 +115,9 @@ workflow SMRNASEQ { } .set { ch_fastq } ch_versions = ch_versions.mix(INPUT_CHECK.out.versions) + // TODO: OPTIONAL, you can use nf-validation plugin to create an input channel from the samplesheet with Channel.fromSamplesheet("input") + // See the documentation https://nextflow-io.github.io/nf-validation/samplesheets/fromSamplesheet/ + // ! There is currently no tooling to help you write a sample sheet schema // // MODULE: Concatenate FastQ files from same sample if required From 6223c35a9cbe37f5f4e90a7d465d5c955a84b19f Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 30 Aug 2023 06:57:33 +0000 Subject: [PATCH 161/215] Modules updates --- modules.json | 16 ++++++++-------- modules/local/mirtop_quant.nf | 4 ++-- modules/local/samplesheet_check.nf | 1 - .../nf-core/custom/dumpsoftwareversions/main.nf | 6 +++--- modules/nf-core/fastp/main.nf | 6 +++--- modules/nf-core/fastqc/main.nf | 6 +++++- modules/nf-core/multiqc/main.nf | 6 +++--- modules/nf-core/samtools/flagstat/main.nf | 11 +++++++++++ modules/nf-core/samtools/idxstats/main.nf | 12 ++++++++++++ modules/nf-core/samtools/sort/main.nf | 2 -- modules/nf-core/samtools/stats/main.nf | 2 +- modules/nf-core/samtools/stats/meta.yml | 10 ++++++++-- 12 files changed, 56 insertions(+), 26 deletions(-) diff --git a/modules.json b/modules.json index 0b6daac5..defa77af 100644 --- a/modules.json +++ b/modules.json @@ -12,32 +12,32 @@ }, "custom/dumpsoftwareversions": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "05c280924b6c768d484c7c443dad5e605c4ff4b4", "installed_by": ["modules"] }, "fastp": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "d497a4868ace3302016ea8ed4b395072d5e833cd", "installed_by": ["modules"] }, "fastqc": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "bd8092b67b5103bdd52e300f75889442275c3117", "installed_by": ["modules"] }, "multiqc": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "a6e11ac655e744f7ebc724be669dd568ffdc0e80", "installed_by": ["modules"] }, "samtools/flagstat": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "570ec5bcfe19c49e16c9ca35a7a116563af6cc1c", "installed_by": ["modules"] }, "samtools/idxstats": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "e662ab16e0c11f1e62983e21de9871f59371a639", "installed_by": ["modules"] }, "samtools/index": { @@ -47,12 +47,12 @@ }, "samtools/sort": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "a0f7be95788366c1923171e358da7d049eb440f9", "installed_by": ["modules"] }, "samtools/stats": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "735e1e04e7e01751d2d6e97055bbdb6f70683cc1", "installed_by": ["modules"] } } diff --git a/modules/local/mirtop_quant.nf b/modules/local/mirtop_quant.nf index 3ebb65ac..cc8d29a7 100644 --- a/modules/local/mirtop_quant.nf +++ b/modules/local/mirtop_quant.nf @@ -12,9 +12,9 @@ process MIRTOP_QUANT { path gtf output: - path "mirtop/mirtop.gff" + path "mirtop/mirtop.gff" , emit: mirtop_gff path "mirtop/mirtop.tsv" , emit: mirtop_table - path "mirtop/mirtop_rawData.tsv" + path "mirtop/mirtop_rawData.tsv", emit: mirtop_rawdata path "mirtop/stats/*" , emit: logs path "versions.yml" , emit: versions diff --git a/modules/local/samplesheet_check.nf b/modules/local/samplesheet_check.nf index c1b0967f..351d2322 100644 --- a/modules/local/samplesheet_check.nf +++ b/modules/local/samplesheet_check.nf @@ -1,5 +1,4 @@ process SAMPLESHEET_CHECK { - label 'process_low' tag "$samplesheet" label 'process_single' diff --git a/modules/nf-core/custom/dumpsoftwareversions/main.nf b/modules/nf-core/custom/dumpsoftwareversions/main.nf index ebc87273..c9d014b1 100644 --- a/modules/nf-core/custom/dumpsoftwareversions/main.nf +++ b/modules/nf-core/custom/dumpsoftwareversions/main.nf @@ -2,10 +2,10 @@ process CUSTOM_DUMPSOFTWAREVERSIONS { label 'process_single' // Requires `pyyaml` which does not have a dedicated container but is in the MultiQC container - conda "bioconda::multiqc=1.14" + conda "bioconda::multiqc=1.15" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.14--pyhdfd78af_0' : - 'biocontainers/multiqc:1.14--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/multiqc:1.15--pyhdfd78af_0' : + 'biocontainers/multiqc:1.15--pyhdfd78af_0' }" input: path versions diff --git a/modules/nf-core/fastp/main.nf b/modules/nf-core/fastp/main.nf index 2ca2d3ee..831b7f12 100644 --- a/modules/nf-core/fastp/main.nf +++ b/modules/nf-core/fastp/main.nf @@ -2,10 +2,10 @@ process FASTP { tag "$meta.id" label 'process_medium' - conda "bioconda::fastp=0.23.2" + conda "bioconda::fastp=0.23.4" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/fastp:0.23.2--h79da9fb_0' : - 'biocontainers/fastp:0.23.2--h79da9fb_0' }" + 'https://depot.galaxyproject.org/singularity/fastp:0.23.4--h5f740d0_0' : + 'biocontainers/fastp:0.23.4--h5f740d0_0' }" input: tuple val(meta), path(reads) diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf index 07d5e433..249f9064 100644 --- a/modules/nf-core/fastqc/main.nf +++ b/modules/nf-core/fastqc/main.nf @@ -29,7 +29,11 @@ process FASTQC { printf "%s %s\\n" $rename_to | while read old_name new_name; do [ -f "\${new_name}" ] || ln -s \$old_name \$new_name done - fastqc $args --threads $task.cpus $renamed_files + + fastqc \\ + $args \\ + --threads $task.cpus \\ + $renamed_files cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index 1fc387be..65d7dd0d 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -1,10 +1,10 @@ process MULTIQC { label 'process_single' - conda "bioconda::multiqc=1.14" + conda "bioconda::multiqc=1.15" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.14--pyhdfd78af_0' : - 'biocontainers/multiqc:1.14--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/multiqc:1.15--pyhdfd78af_0' : + 'biocontainers/multiqc:1.15--pyhdfd78af_0' }" input: path multiqc_files, stageAs: "?/*" diff --git a/modules/nf-core/samtools/flagstat/main.nf b/modules/nf-core/samtools/flagstat/main.nf index eb7e72fc..b75707ec 100644 --- a/modules/nf-core/samtools/flagstat/main.nf +++ b/modules/nf-core/samtools/flagstat/main.nf @@ -32,4 +32,15 @@ process SAMTOOLS_FLAGSTAT { samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') END_VERSIONS """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.flagstat + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ } diff --git a/modules/nf-core/samtools/idxstats/main.nf b/modules/nf-core/samtools/idxstats/main.nf index a257d700..83c7c34b 100644 --- a/modules/nf-core/samtools/idxstats/main.nf +++ b/modules/nf-core/samtools/idxstats/main.nf @@ -33,4 +33,16 @@ process SAMTOOLS_IDXSTATS { samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') END_VERSIONS """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + + """ + touch ${prefix}.idxstats + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ } diff --git a/modules/nf-core/samtools/sort/main.nf b/modules/nf-core/samtools/sort/main.nf index 1e5181d4..2b7753fd 100644 --- a/modules/nf-core/samtools/sort/main.nf +++ b/modules/nf-core/samtools/sort/main.nf @@ -21,13 +21,11 @@ process SAMTOOLS_SORT { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" - def sort_memory = (task.memory.mega/task.cpus).intValue() if ("$bam" == "${prefix}.bam") error "Input and output names are the same, use \"task.ext.prefix\" to disambiguate!" """ samtools sort \\ $args \\ -@ $task.cpus \\ - -m ${sort_memory}M \\ -o ${prefix}.bam \\ -T $prefix \\ $bam diff --git a/modules/nf-core/samtools/stats/main.nf b/modules/nf-core/samtools/stats/main.nf index eb7f098b..4a2607de 100644 --- a/modules/nf-core/samtools/stats/main.nf +++ b/modules/nf-core/samtools/stats/main.nf @@ -9,7 +9,7 @@ process SAMTOOLS_STATS { input: tuple val(meta), path(input), path(input_index) - path fasta + tuple val(meta2), path(fasta) output: tuple val(meta), path("*.stats"), emit: stats diff --git a/modules/nf-core/samtools/stats/meta.yml b/modules/nf-core/samtools/stats/meta.yml index 1d68a5d8..90e6345f 100644 --- a/modules/nf-core/samtools/stats/meta.yml +++ b/modules/nf-core/samtools/stats/meta.yml @@ -30,9 +30,14 @@ input: type: file description: BAI/CRAI file from alignment pattern: "*.{bai,crai}" + - meta2: + type: map + description: | + Groovy Map containing reference information + e.g. [ id:'genome' ] - fasta: - type: optional file - description: Reference file the CRAM was created with + type: file + description: Reference file the CRAM was created with (optional) pattern: "*.{fasta,fa}" output: - meta: @@ -51,3 +56,4 @@ output: authors: - "@drpatelh" - "@FriederikeHanssen" + - "@ramprasadn" From e3867b016b0ecc7472a1c9230ec4162b9793df35 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 30 Aug 2023 07:21:05 +0000 Subject: [PATCH 162/215] Fixing merge issue --- workflows/smrnaseq.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index ac9d1646..3489b83c 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -220,7 +220,7 @@ workflow SMRNASEQ { if (!params.skip_multiqc) { workflow_summary = WorkflowSmrnaseq.paramsSummaryMultiqc(workflow, summary_params) ch_workflow_summary = Channel.value(workflow_summary) - methods_description = WorkflowSmrnaseq.methodsDescriptionText(workflow, ch_multiqc_custom_methods_description) + methods_description = WorkflowSmrnaseq.methodsDescriptionText(workflow, ch_multiqc_custom_methods_description, params) ch_methods_description = Channel.value(methods_description) ch_multiqc_files = Channel.empty() From 75f4c301f40d8bf21a984ef3b92451fe929429e8 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 30 Aug 2023 07:26:19 +0000 Subject: [PATCH 163/215] 2.2.1dev --- nextflow.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow.config b/nextflow.config index a808d4aa..5ac1c01e 100644 --- a/nextflow.config +++ b/nextflow.config @@ -278,7 +278,7 @@ manifest { description = """Small RNA-Seq Best Practice Analysis Pipeline.""" mainScript = 'main.nf' nextflowVersion = '!>=23.04.0' - version = '2.2.2' + version = '2.2.1dev' doi = '' } From 157e6d89d09198926366855c7b02ea0828314ba5 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 30 Aug 2023 07:30:04 +0000 Subject: [PATCH 164/215] 2.2.1dev --- README.md | 18 ------------------ assets/multiqc_config.yml | 4 ++-- nextflow.config | 2 +- 3 files changed, 3 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 24226773..7bab3d6b 100644 --- a/README.md +++ b/README.md @@ -57,26 +57,8 @@ You can find numerous talks on the nf-core events page from various topics inclu > to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/usage/introduction#how-to-run-a-pipeline) > with `-profile test` before running the workflow on actual data. - - Now, you can run the pipeline using: - - ```bash nextflow run nf-core/smrnaseq \ -profile \ diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index 23da1135..7c483b48 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -1,7 +1,7 @@ report_comment: > - This report has been generated by the nf-core/smrnaseq + This report has been generated by the nf-core/smrnaseq analysis pipeline. For information about how to interpret these results, please see the - documentation. + documentation. report_section_order: "nf-core-smrnaseq-methods-description": order: -1000 diff --git a/nextflow.config b/nextflow.config index 5ac1c01e..62c608b1 100644 --- a/nextflow.config +++ b/nextflow.config @@ -278,7 +278,7 @@ manifest { description = """Small RNA-Seq Best Practice Analysis Pipeline.""" mainScript = 'main.nf' nextflowVersion = '!>=23.04.0' - version = '2.2.1dev' + version = '2.2.1dev' doi = '' } From 86a5047c7431e6cff574996d4e173dd4c97a5cb9 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 30 Aug 2023 09:50:52 +0200 Subject: [PATCH 165/215] Apply suggestions from code review Co-authored-by: Gregor Sturm --- nextflow.config | 6 ------ 1 file changed, 6 deletions(-) diff --git a/nextflow.config b/nextflow.config index 62c608b1..10181292 100644 --- a/nextflow.config +++ b/nextflow.config @@ -84,12 +84,6 @@ params { max_cpus = 16 max_time = '240.h' - // Schema validation default options - validationFailUnrecognisedParams = false - validationLenientMode = false - validationSchemaIgnoreParams = 'genomes' - validationShowHiddenParams = false - validate_params = true // Schema validation default options validationFailUnrecognisedParams = false From 6b7d36c4adf9f5f8f1109f1fb5c5f186cf8fc868 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 30 Aug 2023 07:51:07 +0000 Subject: [PATCH 166/215] Adjust based on review --- README.md | 26 +++++++++++++++++++++----- assets/multiqc_config.yml | 4 ++-- nextflow.config | 2 +- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 7bab3d6b..005775f2 100644 --- a/README.md +++ b/README.md @@ -57,16 +57,32 @@ You can find numerous talks on the nf-core events page from various topics inclu > to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/usage/introduction#how-to-run-a-pipeline) > with `-profile test` before running the workflow on actual data. +First, prepare a samplesheet with your input data that looks as follows: + +`samplesheet.csv`: +```csv +sample,fastq_1 +Clone1_N1,s3://ngi-igenomes/test-data/smrnaseq/C1-N1-R1_S4_L001_R1_001.fastq.gz +Clone1_N3,s3://ngi-igenomes/test-data/smrnaseq/C1-N3-R1_S6_L001_R1_001.fastq.gz +Clone9_N1,s3://ngi-igenomes/test-data/smrnaseq/C9-N1-R1_S7_L001_R1_001.fastq.gz +Clone9_N2,s3://ngi-igenomes/test-data/smrnaseq/C9-N2-R1_S8_L001_R1_001.fastq.gz +Clone9_N3,s3://ngi-igenomes/test-data/smrnaseq/C9-N3-R1_S9_L001_R1_001.fastq.gz +Control_N1,s3://ngi-igenomes/test-data/smrnaseq/Ctl-N1-R1_S1_L001_R1_001.fastq.gz +Control_N2,s3://ngi-igenomes/test-data/smrnaseq/Ctl-N2-R1_S2_L001_R1_001.fastq.gz +Control_N3,s3://ngi-igenomes/test-data/smrnaseq/Ctl-N3-R1_S3_L001_R1_001.fastq.gz +``` +Each row represents a fastq file (single-end). + Now, you can run the pipeline using: ```bash nextflow run nf-core/smrnaseq \ -profile \ - --input samplesheet.csv \ - --genome 'GRCh37' \ - --mirtrace_species 'hsa' \ - --protocol 'illumina' \ - --outdir + --input samplesheet.csv \ + --genome 'GRCh37' \ + --mirtrace_species 'hsa' \ + --protocol 'illumina' \ + --outdir ``` > **Warning:** diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index 7c483b48..fe2c8740 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -1,7 +1,7 @@ report_comment: > - This report has been generated by the nf-core/smrnaseq + This report has been generated by the nf-core/smrnaseq analysis pipeline. For information about how to interpret these results, please see the - documentation. + documentation. report_section_order: "nf-core-smrnaseq-methods-description": order: -1000 diff --git a/nextflow.config b/nextflow.config index 62c608b1..6d12aa98 100644 --- a/nextflow.config +++ b/nextflow.config @@ -278,7 +278,7 @@ manifest { description = """Small RNA-Seq Best Practice Analysis Pipeline.""" mainScript = 'main.nf' nextflowVersion = '!>=23.04.0' - version = '2.2.1dev' + version = '2.2.2dev' doi = '' } From 845832b5a40a34c7bcbe4f4ca4df1a88d9b579dc Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 30 Aug 2023 07:52:08 +0000 Subject: [PATCH 167/215] Prettier --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 005775f2..44066051 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ You can find numerous talks on the nf-core events page from various topics inclu First, prepare a samplesheet with your input data that looks as follows: `samplesheet.csv`: + ```csv sample,fastq_1 Clone1_N1,s3://ngi-igenomes/test-data/smrnaseq/C1-N1-R1_S4_L001_R1_001.fastq.gz @@ -71,6 +72,7 @@ Control_N1,s3://ngi-igenomes/test-data/smrnaseq/Ctl-N1-R1_S1_L001_R1_001.fastq.g Control_N2,s3://ngi-igenomes/test-data/smrnaseq/Ctl-N2-R1_S2_L001_R1_001.fastq.gz Control_N3,s3://ngi-igenomes/test-data/smrnaseq/Ctl-N3-R1_S3_L001_R1_001.fastq.gz ``` + Each row represents a fastq file (single-end). Now, you can run the pipeline using: From 9a46d676df47c481e69c2204411fe452cb7b277f Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 30 Aug 2023 10:50:07 +0000 Subject: [PATCH 168/215] Update imported nf-core workflows --- modules.json | 24 +++++-- .../main.nf} | 15 +++-- .../nf-core/bam_sort_stats_samtools/meta.yml | 67 +++++++++++++++++++ subworkflows/nf-core/bam_stats_samtools.nf | 32 --------- .../nf-core/bam_stats_samtools/main.nf | 32 +++++++++ .../nf-core/bam_stats_samtools/meta.yml | 41 ++++++++++++ 6 files changed, 167 insertions(+), 44 deletions(-) rename subworkflows/nf-core/{bam_sort_samtools.nf => bam_sort_stats_samtools/main.nf} (77%) create mode 100644 subworkflows/nf-core/bam_sort_stats_samtools/meta.yml delete mode 100644 subworkflows/nf-core/bam_stats_samtools.nf create mode 100644 subworkflows/nf-core/bam_stats_samtools/main.nf create mode 100644 subworkflows/nf-core/bam_stats_samtools/meta.yml diff --git a/modules.json b/modules.json index defa77af..758f1b84 100644 --- a/modules.json +++ b/modules.json @@ -33,27 +33,41 @@ "samtools/flagstat": { "branch": "master", "git_sha": "570ec5bcfe19c49e16c9ca35a7a116563af6cc1c", - "installed_by": ["modules"] + "installed_by": ["bam_stats_samtools", "modules"] }, "samtools/idxstats": { "branch": "master", "git_sha": "e662ab16e0c11f1e62983e21de9871f59371a639", - "installed_by": ["modules"] + "installed_by": ["bam_stats_samtools", "modules"] }, "samtools/index": { "branch": "master", "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": ["modules"] + "installed_by": ["bam_sort_stats_samtools", "modules"] }, "samtools/sort": { "branch": "master", "git_sha": "a0f7be95788366c1923171e358da7d049eb440f9", - "installed_by": ["modules"] + "installed_by": ["bam_sort_stats_samtools", "modules"] }, "samtools/stats": { "branch": "master", "git_sha": "735e1e04e7e01751d2d6e97055bbdb6f70683cc1", - "installed_by": ["modules"] + "installed_by": ["bam_stats_samtools", "modules"] + } + } + }, + "subworkflows": { + "nf-core": { + "bam_sort_stats_samtools": { + "branch": "master", + "git_sha": "dedc0e31087f3306101c38835d051bf49789445a", + "installed_by": ["subworkflows"] + }, + "bam_stats_samtools": { + "branch": "master", + "git_sha": "dedc0e31087f3306101c38835d051bf49789445a", + "installed_by": ["subworkflows", "bam_sort_stats_samtools"] } } } diff --git a/subworkflows/nf-core/bam_sort_samtools.nf b/subworkflows/nf-core/bam_sort_stats_samtools/main.nf similarity index 77% rename from subworkflows/nf-core/bam_sort_samtools.nf rename to subworkflows/nf-core/bam_sort_stats_samtools/main.nf index ded07b32..fc1c652b 100644 --- a/subworkflows/nf-core/bam_sort_samtools.nf +++ b/subworkflows/nf-core/bam_sort_stats_samtools/main.nf @@ -2,16 +2,17 @@ // Sort, index BAM file and run samtools stats, flagstat and idxstats // -include { SAMTOOLS_SORT } from '../../modules/nf-core/samtools/sort/main' -include { SAMTOOLS_INDEX } from '../../modules/nf-core/samtools/index/main' -include { BAM_STATS_SAMTOOLS } from './bam_stats_samtools' +include { SAMTOOLS_SORT } from '../../../modules/nf-core/samtools/sort/main' +include { SAMTOOLS_INDEX } from '../../../modules/nf-core/samtools/index/main' +include { BAM_STATS_SAMTOOLS } from '../bam_stats_samtools/main' -workflow BAM_SORT_SAMTOOLS { +workflow BAM_SORT_STATS_SAMTOOLS { take: - ch_bam // channel: [ val(meta), [ bam ] ] - fasta + ch_bam // channel: [ val(meta), [ bam ] ] + ch_fasta // channel: [ val(meta), path(fasta) ] main: + ch_versions = Channel.empty() SAMTOOLS_SORT ( ch_bam ) @@ -33,7 +34,7 @@ workflow BAM_SORT_SAMTOOLS { } .set { ch_bam_bai } - BAM_STATS_SAMTOOLS ( ch_bam_bai, fasta ) + BAM_STATS_SAMTOOLS ( ch_bam_bai, ch_fasta ) ch_versions = ch_versions.mix(BAM_STATS_SAMTOOLS.out.versions) emit: diff --git a/subworkflows/nf-core/bam_sort_stats_samtools/meta.yml b/subworkflows/nf-core/bam_sort_stats_samtools/meta.yml new file mode 100644 index 00000000..69c16be4 --- /dev/null +++ b/subworkflows/nf-core/bam_sort_stats_samtools/meta.yml @@ -0,0 +1,67 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json +name: bam_sort_stats_samtools +description: Sort SAM/BAM/CRAM file +keywords: + - sort + - bam + - sam + - cram +components: + - samtools/sort + - samtools/index + - samtools/stats + - samtools/idxstats + - samtools/flagstat + - bam_stats_samtools +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - bam: + type: file + description: BAM/CRAM/SAM file + pattern: "*.{bam,cram,sam}" + - fasta: + type: file + description: Reference genome fasta file + pattern: "*.{fasta,fa}" +# TODO Update when we decide on a standard for subworkflow docs +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - bam: + type: file + description: Sorted BAM/CRAM/SAM file + pattern: "*.{bam,cram,sam}" + - bai: + type: file + description: BAM/CRAM/SAM index file + pattern: "*.{bai,crai,sai}" + - crai: + type: file + description: BAM/CRAM/SAM index file + pattern: "*.{bai,crai,sai}" + - stats: + type: file + description: File containing samtools stats output + pattern: "*.{stats}" + - flagstat: + type: file + description: File containing samtools flagstat output + pattern: "*.{flagstat}" + - idxstats: + type: file + description: File containing samtools idxstats output + pattern: "*.{idxstats}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@drpatelh" + - "@ewels" diff --git a/subworkflows/nf-core/bam_stats_samtools.nf b/subworkflows/nf-core/bam_stats_samtools.nf deleted file mode 100644 index 38d2569b..00000000 --- a/subworkflows/nf-core/bam_stats_samtools.nf +++ /dev/null @@ -1,32 +0,0 @@ -// -// Run SAMtools stats, flagstat and idxstats -// - -include { SAMTOOLS_STATS } from '../../modules/nf-core/samtools/stats/main' -include { SAMTOOLS_IDXSTATS } from '../../modules/nf-core/samtools/idxstats/main' -include { SAMTOOLS_FLAGSTAT } from '../../modules/nf-core/samtools/flagstat/main' - -workflow BAM_STATS_SAMTOOLS { - take: - ch_bam_bai // channel: [ val(meta), [ bam ], [bai/csi] ] - fasta - - main: - ch_versions = Channel.empty() - - SAMTOOLS_STATS ( ch_bam_bai, fasta ) - ch_versions = ch_versions.mix(SAMTOOLS_STATS.out.versions.first()) - - SAMTOOLS_FLAGSTAT ( ch_bam_bai ) - ch_versions = ch_versions.mix(SAMTOOLS_FLAGSTAT.out.versions.first()) - - SAMTOOLS_IDXSTATS ( ch_bam_bai ) - ch_versions = ch_versions.mix(SAMTOOLS_IDXSTATS.out.versions.first()) - - emit: - stats = SAMTOOLS_STATS.out.stats // channel: [ val(meta), [ stats ] ] - flagstat = SAMTOOLS_FLAGSTAT.out.flagstat // channel: [ val(meta), [ flagstat ] ] - idxstats = SAMTOOLS_IDXSTATS.out.idxstats // channel: [ val(meta), [ idxstats ] ] - - versions = ch_versions // channel: [ versions.yml ] -} diff --git a/subworkflows/nf-core/bam_stats_samtools/main.nf b/subworkflows/nf-core/bam_stats_samtools/main.nf new file mode 100644 index 00000000..44d4c010 --- /dev/null +++ b/subworkflows/nf-core/bam_stats_samtools/main.nf @@ -0,0 +1,32 @@ +// +// Run SAMtools stats, flagstat and idxstats +// + +include { SAMTOOLS_STATS } from '../../../modules/nf-core/samtools/stats/main' +include { SAMTOOLS_IDXSTATS } from '../../../modules/nf-core/samtools/idxstats/main' +include { SAMTOOLS_FLAGSTAT } from '../../../modules/nf-core/samtools/flagstat/main' + +workflow BAM_STATS_SAMTOOLS { + take: + ch_bam_bai // channel: [ val(meta), path(bam), path(bai) ] + ch_fasta // channel: [ val(meta), path(fasta) ] + + main: + ch_versions = Channel.empty() + + SAMTOOLS_STATS ( ch_bam_bai, ch_fasta ) + ch_versions = ch_versions.mix(SAMTOOLS_STATS.out.versions) + + SAMTOOLS_FLAGSTAT ( ch_bam_bai ) + ch_versions = ch_versions.mix(SAMTOOLS_FLAGSTAT.out.versions) + + SAMTOOLS_IDXSTATS ( ch_bam_bai ) + ch_versions = ch_versions.mix(SAMTOOLS_IDXSTATS.out.versions) + + emit: + stats = SAMTOOLS_STATS.out.stats // channel: [ val(meta), path(stats) ] + flagstat = SAMTOOLS_FLAGSTAT.out.flagstat // channel: [ val(meta), path(flagstat) ] + idxstats = SAMTOOLS_IDXSTATS.out.idxstats // channel: [ val(meta), path(idxstats) ] + + versions = ch_versions // channel: [ path(versions.yml) ] +} diff --git a/subworkflows/nf-core/bam_stats_samtools/meta.yml b/subworkflows/nf-core/bam_stats_samtools/meta.yml new file mode 100644 index 00000000..87863b11 --- /dev/null +++ b/subworkflows/nf-core/bam_stats_samtools/meta.yml @@ -0,0 +1,41 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json +name: bam_stats_samtools +description: Produces comprehensive statistics from SAM/BAM/CRAM file +keywords: + - statistics + - counts + - bam + - sam + - cram +components: + - samtools/stats + - samtools/idxstats + - samtools/flagstat +input: + - ch_bam_bai: + description: | + The input channel containing the BAM/CRAM and it's index + Structure: [ val(meta), path(bam), path(bai) ] + - ch_fasta: + description: | + Reference genome fasta file + Structure: [ path(fasta) ] +output: + - stats: + description: | + File containing samtools stats output + Structure: [ val(meta), path(stats) ] + - flagstat: + description: | + File containing samtools flagstat output + Structure: [ val(meta), path(flagstat) ] + - idxstats: + description: | + File containing samtools idxstats output + Structure: [ val(meta), path(idxstats)] + - versions: + description: | + Files containing software versions + Structure: [ path(versions.yml) ] +authors: + - "@drpatelh" From cbebb5a824849620b0c4836bcb069b08f8774ba7 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 30 Aug 2023 10:56:19 +0000 Subject: [PATCH 169/215] Update workflows with nf-core ones --- subworkflows/local/genome_quant.nf | 8 ++++---- subworkflows/local/mirna_quant.nf | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/subworkflows/local/genome_quant.nf b/subworkflows/local/genome_quant.nf index 033f59ad..a20a7c1f 100644 --- a/subworkflows/local/genome_quant.nf +++ b/subworkflows/local/genome_quant.nf @@ -3,7 +3,7 @@ // include { INDEX_GENOME } from '../../modules/local/bowtie_genome' -include { BAM_SORT_SAMTOOLS } from '../nf-core/bam_sort_samtools' +include { BAM_SORT_STATS_SAMTOOLS } from '../nf-core/bam_sort_stats_samtools' include { BOWTIE_MAP_SEQ as BOWTIE_MAP_GENOME } from '../../modules/local/bowtie_map_mirna' workflow GENOME_QUANT { @@ -29,14 +29,14 @@ workflow GENOME_QUANT { BOWTIE_MAP_GENOME ( reads, bowtie_index.collect() ) ch_versions = ch_versions.mix(BOWTIE_MAP_GENOME.out.versions) - BAM_SORT_SAMTOOLS ( BOWTIE_MAP_GENOME.out.bam, Channel.empty() ) - ch_versions = ch_versions.mix(BAM_SORT_SAMTOOLS.out.versions) + BAM_SORT_STATS_SAMTOOLS ( BOWTIE_MAP_GENOME.out.bam, Channel.empty() ) + ch_versions = ch_versions.mix(BAM_SORT_STATS_SAMTOOLS.out.versions) } emit: fasta = fasta_formatted index = bowtie_index - stats = BAM_SORT_SAMTOOLS.out.stats + stats = BAM_SORT_STATS_SAMTOOLS.out.stats versions = ch_versions } diff --git a/subworkflows/local/mirna_quant.nf b/subworkflows/local/mirna_quant.nf index dd8a8412..70b872e3 100644 --- a/subworkflows/local/mirna_quant.nf +++ b/subworkflows/local/mirna_quant.nf @@ -15,8 +15,8 @@ include { BOWTIE_MAP_SEQ as BOWTIE_MAP_MATURE BOWTIE_MAP_SEQ as BOWTIE_MAP_HAIRPIN BOWTIE_MAP_SEQ as BOWTIE_MAP_SEQCLUSTER } from '../../modules/local/bowtie_map_mirna' -include { BAM_SORT_SAMTOOLS as BAM_STATS_MATURE - BAM_SORT_SAMTOOLS as BAM_STATS_HAIRPIN } from '../nf-core/bam_sort_samtools' +include { BAM_SORT_STATS_SAMTOOLS as BAM_STATS_MATURE + BAM_SORT_STATS_SAMTOOLS as BAM_STATS_HAIRPIN } from '../nf-core/bam_sort_stats_samtools' include { SEQCLUSTER_SEQUENCES } from '../../modules/local/seqcluster_collapse.nf' include { MIRTOP_QUANT } from '../../modules/local/mirtop_quant.nf' From 37f85f790caf26dfa833639e919361e1a3ecb9ac Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 30 Aug 2023 11:43:00 +0000 Subject: [PATCH 170/215] Fix prefix --- conf/modules.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 8644dd3c..556d8509 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -207,7 +207,7 @@ process { } process { - withName: 'NFCORE_SMRNASEQ:SMRNASEQ:GENOME_QUANT:BAM_SORT_SAMTOOLS:SAMTOOLS_.*' { + withName: 'NFCORE_SMRNASEQ:SMRNASEQ:GENOME_QUANT:BAM_SORT_STATS_SAMTOOLS:SAMTOOLS_.*' { ext.prefix = { "${meta.id}.sorted" } publishDir = [ path: { "${params.outdir}/samtools" }, @@ -215,7 +215,7 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] } - withName: 'NFCORE_SMRNASEQ:SMRNASEQ:GENOME_QUANT:BAM_SORT_SAMTOOLS:BAM_STATS_SAMTOOLS:.*' { + withName: 'NFCORE_SMRNASEQ:SMRNASEQ:GENOME_QUANT:BAM_SORT_STATS_SAMTOOLS:BAM_STATS_SAMTOOLS:.*' { ext.prefix = { "${meta.id}.sorted" } publishDir = [ path: { "${params.outdir}/samtools/samtools_stats" }, From ec610e6d0a5ecdddc0bd53fafe6d0c14aac56832 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 1 Sep 2023 07:09:47 +0000 Subject: [PATCH 171/215] Attempt at introducing meta2 everywhere --- modules/local/bowtie_genome.nf | 2 +- modules/local/bowtie_mirna.nf | 2 +- modules/local/format_fasta_mirna.nf | 4 ++-- modules/local/mirdeep2_run.nf | 2 +- modules/local/parse_fasta_mirna.nf | 2 +- subworkflows/local/genome_quant.nf | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/local/bowtie_genome.nf b/modules/local/bowtie_genome.nf index b132e1da..91a6cd53 100644 --- a/modules/local/bowtie_genome.nf +++ b/modules/local/bowtie_genome.nf @@ -8,7 +8,7 @@ process INDEX_GENOME { 'biocontainers/bowtie:1.3.1--py310h4070885_4' }" input: - path fasta + tuple val(meta2), path(fasta) output: path 'genome*ebwt' , emit: index diff --git a/modules/local/bowtie_mirna.nf b/modules/local/bowtie_mirna.nf index 9390730a..2be45bb8 100644 --- a/modules/local/bowtie_mirna.nf +++ b/modules/local/bowtie_mirna.nf @@ -7,7 +7,7 @@ process INDEX_MIRNA { 'biocontainers/bowtie:1.3.1--py310h4070885_4' }" input: - path fasta + tuple val(meta2), path(fasta) output: path 'fasta_bidx*' , emit: index diff --git a/modules/local/format_fasta_mirna.nf b/modules/local/format_fasta_mirna.nf index 3e247ce4..637a6604 100644 --- a/modules/local/format_fasta_mirna.nf +++ b/modules/local/format_fasta_mirna.nf @@ -10,10 +10,10 @@ process FORMAT_FASTA_MIRNA { 'biocontainers/fastx_toolkit:0.0.14--he1b5a44_8' }" input: - path fasta + tuple val(meta2), path(fasta) output: - path '*_idx.fa' , emit: formatted_fasta + tuple meta2, path '*_idx.fa' , emit: formatted_fasta path "versions.yml", emit: versions when: diff --git a/modules/local/mirdeep2_run.nf b/modules/local/mirdeep2_run.nf index 74044e4a..e4e2aaaf 100644 --- a/modules/local/mirdeep2_run.nf +++ b/modules/local/mirdeep2_run.nf @@ -10,7 +10,7 @@ process MIRDEEP2_RUN { 'biocontainers/mirdeep2:2.0.1.3--hdfd78af_1' }" input: - path fasta + tuple val(meta2), path(fasta) tuple path(reads), path(arf) path hairpin path mature diff --git a/modules/local/parse_fasta_mirna.nf b/modules/local/parse_fasta_mirna.nf index ab7a91f0..22950833 100644 --- a/modules/local/parse_fasta_mirna.nf +++ b/modules/local/parse_fasta_mirna.nf @@ -7,7 +7,7 @@ process PARSE_FASTA_MIRNA { 'biocontainers/seqkit:2.3.1--h9ee0642_0' }" input: - path fasta + tuple val(meta2), path(fasta) output: path '*_igenome.fa', emit: parsed_fasta diff --git a/subworkflows/local/genome_quant.nf b/subworkflows/local/genome_quant.nf index a20a7c1f..39d17e8a 100644 --- a/subworkflows/local/genome_quant.nf +++ b/subworkflows/local/genome_quant.nf @@ -8,7 +8,7 @@ include { BOWTIE_MAP_SEQ as BOWTIE_MAP_GENOME } from '../../modules/local/bowtie workflow GENOME_QUANT { take: - fasta + fasta //channel: [ val(meta2), [ reads ] ] index reads // channel: [ val(meta), [ reads ] ] From 26f95a119940c4348245ada3a501e9bf523fe46b Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 1 Sep 2023 09:19:07 +0200 Subject: [PATCH 172/215] Update modules/local/format_fasta_mirna.nf Co-authored-by: Christopher Mohr --- modules/local/format_fasta_mirna.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/format_fasta_mirna.nf b/modules/local/format_fasta_mirna.nf index 637a6604..c2efca97 100644 --- a/modules/local/format_fasta_mirna.nf +++ b/modules/local/format_fasta_mirna.nf @@ -13,7 +13,7 @@ process FORMAT_FASTA_MIRNA { tuple val(meta2), path(fasta) output: - tuple meta2, path '*_idx.fa' , emit: formatted_fasta + tuple val(meta2), path('*_idx.fa') , emit: formatted_fasta path "versions.yml", emit: versions when: From cd6c2ab3bbd004f50bfc71b1d6bddc4d8c22fe4a Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 1 Sep 2023 07:49:56 +0000 Subject: [PATCH 173/215] Add chanel description --- subworkflows/local/mirna_quant.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subworkflows/local/mirna_quant.nf b/subworkflows/local/mirna_quant.nf index 70b872e3..b1904296 100644 --- a/subworkflows/local/mirna_quant.nf +++ b/subworkflows/local/mirna_quant.nf @@ -25,8 +25,8 @@ include { EDGER_QC } from '../../modules/local/edger_qc.nf' workflow MIRNA_QUANT { take: - mature // channel: fasta file - hairpin // channel: fasta file + mature // channel: [ val(meta), fasta file] + hairpin // channel: [ val(meta), fasta file] gtf // channle: GTF file reads // channel: [ val(meta), [ reads ] ] From ea6b8e61c7172844f09534484936f7490ae9b367 Mon Sep 17 00:00:00 2001 From: Christopher Mohr Date: Fri, 1 Sep 2023 09:33:08 +0000 Subject: [PATCH 174/215] adapt fasta channel of modules and subworkflows --- modules/local/format_fasta_mirna.nf | 4 ++-- modules/local/parse_fasta_mirna.nf | 4 ++-- subworkflows/local/genome_quant.nf | 2 +- subworkflows/local/mirna_quant.nf | 2 +- workflows/smrnaseq.nf | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/local/format_fasta_mirna.nf b/modules/local/format_fasta_mirna.nf index c2efca97..489879a5 100644 --- a/modules/local/format_fasta_mirna.nf +++ b/modules/local/format_fasta_mirna.nf @@ -13,8 +13,8 @@ process FORMAT_FASTA_MIRNA { tuple val(meta2), path(fasta) output: - tuple val(meta2), path('*_idx.fa') , emit: formatted_fasta - path "versions.yml", emit: versions + tuple val(meta2), path('*_idx.fa') , emit: formatted_fasta + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/modules/local/parse_fasta_mirna.nf b/modules/local/parse_fasta_mirna.nf index 22950833..71f5c85a 100644 --- a/modules/local/parse_fasta_mirna.nf +++ b/modules/local/parse_fasta_mirna.nf @@ -10,8 +10,8 @@ process PARSE_FASTA_MIRNA { tuple val(meta2), path(fasta) output: - path '*_igenome.fa', emit: parsed_fasta - path "versions.yml", emit: versions + tuple val(meta2), path('*_igenome.fa'), emit: parsed_fasta + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when diff --git a/subworkflows/local/genome_quant.nf b/subworkflows/local/genome_quant.nf index 39d17e8a..07f4fa53 100644 --- a/subworkflows/local/genome_quant.nf +++ b/subworkflows/local/genome_quant.nf @@ -16,7 +16,7 @@ workflow GENOME_QUANT { ch_versions = Channel.empty() if (!index){ - INDEX_GENOME ( fasta ) + INDEX_GENOME ( [ [:], fasta ] ) bowtie_index = INDEX_GENOME.out.index fasta_formatted = INDEX_GENOME.out.fasta ch_versions = ch_versions.mix(INDEX_GENOME.out.versions) diff --git a/subworkflows/local/mirna_quant.nf b/subworkflows/local/mirna_quant.nf index b1904296..dfa16ab4 100644 --- a/subworkflows/local/mirna_quant.nf +++ b/subworkflows/local/mirna_quant.nf @@ -94,7 +94,7 @@ workflow MIRNA_QUANT { ch_mirtop_logs = Channel.empty() if (params.mirtrace_species){ - MIRTOP_QUANT ( BOWTIE_MAP_SEQCLUSTER.out.bam.collect{it[1]}, FORMAT_HAIRPIN.out.formatted_fasta, gtf ) + MIRTOP_QUANT ( BOWTIE_MAP_SEQCLUSTER.out.bam.collect{it[1]}, FORMAT_HAIRPIN.out.formatted_fasta.collect{it[1]}, gtf ) ch_mirtop_logs = MIRTOP_QUANT.out.logs ch_versions = ch_versions.mix(MIRTOP_QUANT.out.versions) diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 3489b83c..cce83e56 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -179,8 +179,8 @@ workflow SMRNASEQ { } MIRNA_QUANT ( - reference_mature, - reference_hairpin, + [ [:], reference_mature], + [ [:], reference_hairpin], mirna_gtf, mirna_reads ) From a026ba147e10833d46968b1b49a291ae3deb0817 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 1 Sep 2023 11:47:08 +0000 Subject: [PATCH 175/215] Fix adapter trim for illumina case --- CHANGELOG.md | 1 + lib/WorkflowSmrnaseq.groovy | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ca1a1cc..c9ce51eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [v2.2.2](https://github.com/nf-core/smrnaseq/releases/tag/2.2.2) - 2023-06-01 - [[#253]](https://github.com/nf-core/smrnaseq/pull/253) - Remove globs from process alias when using ECR containers +- [[#237]](https://github.com/nf-core/smrnaseq/issues/237) - Fix illumina protocol clip parameters to default ## [v2.2.1](https://github.com/nf-core/smrnaseq/releases/tag/2.2.1) - 2023-05-12 diff --git a/lib/WorkflowSmrnaseq.groovy b/lib/WorkflowSmrnaseq.groovy index 703c1342..5b94bad7 100755 --- a/lib/WorkflowSmrnaseq.groovy +++ b/lib/WorkflowSmrnaseq.groovy @@ -125,8 +125,8 @@ class WorkflowSmrnaseq { switch(params.protocol){ case 'illumina': - params.putIfAbsent("clip_r1", 1); - params.putIfAbsent("three_prime_clip_r1",2); + params.putIfAbsent("clip_r1", 0); + params.putIfAbsent("three_prime_clip_r1",0); params.putIfAbsent("three_prime_adapter", "TGGAATTCTCGGGTGCCAAGG"); break case 'nextflex': From 9637f9b7700a534010e7c4b55f793dc3f45e3e82 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 4 Sep 2023 11:38:53 +0200 Subject: [PATCH 176/215] Update nextflow.config Co-authored-by: Christopher Mohr --- nextflow.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow.config b/nextflow.config index 29d41588..ff524df5 100644 --- a/nextflow.config +++ b/nextflow.config @@ -272,7 +272,7 @@ manifest { description = """Small RNA-Seq Best Practice Analysis Pipeline.""" mainScript = 'main.nf' nextflowVersion = '!>=23.04.0' - version = '2.2.2dev' + version = '2.2.2' doi = '' } From 83b20b2de704954f620cb734c06ee65e9ef43db7 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 4 Sep 2023 11:44:41 +0200 Subject: [PATCH 177/215] Update subworkflows/local/genome_quant.nf Co-authored-by: Christopher Mohr --- subworkflows/local/genome_quant.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/genome_quant.nf b/subworkflows/local/genome_quant.nf index 07f4fa53..edb60a2a 100644 --- a/subworkflows/local/genome_quant.nf +++ b/subworkflows/local/genome_quant.nf @@ -8,7 +8,7 @@ include { BOWTIE_MAP_SEQ as BOWTIE_MAP_GENOME } from '../../modules/local/bowtie workflow GENOME_QUANT { take: - fasta //channel: [ val(meta2), [ reads ] ] + fasta index reads // channel: [ val(meta), [ reads ] ] From 0752c18dd6cb29ce691839b953e49eec7dd01513 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 4 Sep 2023 09:49:46 +0000 Subject: [PATCH 178/215] Adjust bits from PR review --- CHANGELOG.md | 12 ++++++++---- assets/multiqc_config.yml | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9ce51eb..65e46193 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,14 +3,18 @@ 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). -## dev +## [v2.2.2](https://github.com/nf-core/smrnaseq/releases/tag/2.2.2) - 2023-09-04 +- [[#253]](https://github.com/nf-core/smrnaseq/pull/253) - Remove globs from process alias when using ECR containers +- [[#237]](https://github.com/nf-core/smrnaseq/issues/237) - Fix illumina protocol clip parameters to default - Remove public_aws_ecr profile -## [v2.2.2](https://github.com/nf-core/smrnaseq/releases/tag/2.2.2) - 2023-06-01 +### Software dependencies -- [[#253]](https://github.com/nf-core/smrnaseq/pull/253) - Remove globs from process alias when using ECR containers -- [[#237]](https://github.com/nf-core/smrnaseq/issues/237) - Fix illumina protocol clip parameters to default +| Dependency | Old version | New version | +| ---------- | ----------- | ----------- | +| `multiqc` | 1.13 | 1.15 | +| `fastp` | 0.23.2 | 0.23.4 | ## [v2.2.1](https://github.com/nf-core/smrnaseq/releases/tag/2.2.1) - 2023-05-12 diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index fe2c8740..23da1135 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -1,7 +1,7 @@ report_comment: > - This report has been generated by the nf-core/smrnaseq + This report has been generated by the nf-core/smrnaseq analysis pipeline. For information about how to interpret these results, please see the - documentation. + documentation. report_section_order: "nf-core-smrnaseq-methods-description": order: -1000 From 0602c6136a8f3f18ae83dd33314d6affc749a7e3 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 4 Sep 2023 12:50:55 +0000 Subject: [PATCH 179/215] Adjust changelog [skip ci] --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65e46193..fc874c04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [[#253]](https://github.com/nf-core/smrnaseq/pull/253) - Remove globs from process alias when using ECR containers - [[#237]](https://github.com/nf-core/smrnaseq/issues/237) - Fix illumina protocol clip parameters to default - Remove public_aws_ecr profile +- [[#269]](https://github.com/nf-core/smrnaseq/pull/269) - Updated miRBase URLs with new location (old ones were broken) ### Software dependencies From c55210f92ed5d303a889595b14603692d6bedc98 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 4 Sep 2023 17:35:18 +0200 Subject: [PATCH 180/215] Update nextflow.config Bugfix for users who are running offline / with -all distribution as seen in discussion with @bentsherman https://github.com/nextflow-io/nextflow/discussions/4126 --- nextflow.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow.config b/nextflow.config index ff524df5..44544307 100644 --- a/nextflow.config +++ b/nextflow.config @@ -217,7 +217,7 @@ singularity.registry = 'quay.io' // Nextflow plugins plugins { - id 'nf-validation' // Validation of pipeline parameters and creation of an input channel from a sample sheet + id 'nf-validation@0.3.1'// Validation of pipeline parameters and creation of an input channel from a sample sheet } // Load igenomes.config if required From 703bf6173bae08c5ea08637d36202dadc3542865 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 4 Sep 2023 15:56:45 +0000 Subject: [PATCH 181/215] Revert to latest --- nextflow.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow.config b/nextflow.config index 44544307..c9f81e43 100644 --- a/nextflow.config +++ b/nextflow.config @@ -217,7 +217,7 @@ singularity.registry = 'quay.io' // Nextflow plugins plugins { - id 'nf-validation@0.3.1'// Validation of pipeline parameters and creation of an input channel from a sample sheet + id 'nf-validation'// Validation of pipeline parameters and creation of an input channel from a sample sheet } // Load igenomes.config if required From d0be63a91577f9914a0466bfa90c658a4f44f146 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Tue, 5 Sep 2023 11:14:50 +0200 Subject: [PATCH 182/215] Update genome_quant.nf [skip ci] --- subworkflows/local/genome_quant.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/genome_quant.nf b/subworkflows/local/genome_quant.nf index edb60a2a..967b2757 100644 --- a/subworkflows/local/genome_quant.nf +++ b/subworkflows/local/genome_quant.nf @@ -8,7 +8,7 @@ include { BOWTIE_MAP_SEQ as BOWTIE_MAP_GENOME } from '../../modules/local/bowtie workflow GENOME_QUANT { take: - fasta + fasta index reads // channel: [ val(meta), [ reads ] ] From 884cdad0482b538e8f09c0db465cc85f819616f3 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Tue, 5 Sep 2023 19:15:20 +0000 Subject: [PATCH 183/215] Bump versions + fix 271 --- CHANGELOG.md | 3 +++ assets/multiqc_config.yml | 4 ++-- nextflow.config | 2 +- workflows/smrnaseq.nf | 10 +++++----- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc874c04..e24f6cc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ 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). +## [v2.2.3](https://github.com/nf-core/smrnaseq/releases/tag/2.2.3) - 2023-09-06 + +- [[#271]](https://github.com/nf-core/smrnaseq/issues/271) - Bugfix for parsing hairpint mature files ## [v2.2.2](https://github.com/nf-core/smrnaseq/releases/tag/2.2.2) - 2023-09-04 - [[#253]](https://github.com/nf-core/smrnaseq/pull/253) - Remove globs from process alias when using ECR containers diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index 23da1135..f549128c 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -1,7 +1,7 @@ report_comment: > - This report has been generated by the nf-core/smrnaseq + This report has been generated by the nf-core/smrnaseq analysis pipeline. For information about how to interpret these results, please see the - documentation. + documentation. report_section_order: "nf-core-smrnaseq-methods-description": order: -1000 diff --git a/nextflow.config b/nextflow.config index c9f81e43..7f1cfb44 100644 --- a/nextflow.config +++ b/nextflow.config @@ -272,7 +272,7 @@ manifest { description = """Small RNA-Seq Best Practice Analysis Pipeline.""" mainScript = 'main.nf' nextflowVersion = '!>=23.04.0' - version = '2.2.2' + version = '2.2.3dev' doi = '' } diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index 049851d0..f99b0d34 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -56,12 +56,12 @@ ch_fastp_adapters = Channel.fromPath(params.fastp_known_mirna_adapters, // SUBWORKFLOW: Consisting of a mix of local and nf-core/modules // if (!params.mirgenedb) { - if (params.mature) { reference_mature = file(params.mature, checkIfExists: true) } else { exit 1, "Mature miRNA fasta file not found: ${params.mature}" } - if (params.hairpin) { reference_hairpin = file(params.hairpin, checkIfExists: true) } else { exit 1, "Hairpin miRNA fasta file not found: ${params.hairpin}" } + if (params.mature) { reference_mature = path(params.mature, checkIfExists: true) } else { exit 1, "Mature miRNA fasta file not found: ${params.mature}" } + if (params.hairpin) { reference_hairpin = path(params.hairpin, checkIfExists: true) } else { exit 1, "Hairpin miRNA fasta file not found: ${params.hairpin}" } } else { - if (params.mirgenedb_mature) { reference_mature = file(params.mirgenedb_mature, checkIfExists: true) } else { exit 1, "Mature miRNA fasta file not found: ${params.mirgenedb_mature}" } - if (params.mirgenedb_hairpin) { reference_hairpin = file(params.mirgenedb_hairpin, checkIfExists: true) } else { exit 1, "Hairpin miRNA fasta file not found: ${params.mirgenedb_hairpin}" } - if (params.mirgenedb_gff) { mirna_gtf = file(params.mirgenedb_gff, checkIfExists: true) } else { exit 1, "MirGeneDB gff file not found: ${params.mirgenedb_gff}"} + if (params.mirgenedb_mature) { reference_mature = path(params.mirgenedb_mature, checkIfExists: true) } else { exit 1, "Mature miRNA fasta file not found: ${params.mirgenedb_mature}" } + if (params.mirgenedb_hairpin) { reference_hairpin = path(params.mirgenedb_hairpin, checkIfExists: true) } else { exit 1, "Hairpin miRNA fasta file not found: ${params.mirgenedb_hairpin}" } + if (params.mirgenedb_gff) { mirna_gtf = path(params.mirgenedb_gff, checkIfExists: true) } else { exit 1, "MirGeneDB gff file not found: ${params.mirgenedb_gff}"} } include { INPUT_CHECK } from '../subworkflows/local/input_check' From 4f93a99b8657ac39e806e180d06626fd933f4827 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Tue, 5 Sep 2023 19:22:52 +0000 Subject: [PATCH 184/215] Fixing tests --- conf/test.config | 6 +++--- workflows/smrnaseq.nf | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/conf/test.config b/conf/test.config index 518ced5f..1a81afee 100644 --- a/conf/test.config +++ b/conf/test.config @@ -23,9 +23,9 @@ params { input = 'https://github.com/nf-core/test-datasets/raw/smrnaseq/samplesheet/v2.0/samplesheet.csv' fasta = 'https://github.com/nf-core/test-datasets/raw/smrnaseq/reference/genome.fa' - mature = 'https://github.com/nf-core/test-datasets/raw/smrnaseq/reference/mature.fa' - hairpin = 'https://github.com/nf-core/test-datasets/raw/smrnaseq/reference/hairpin.fa' - mirna_gtf = 'https://github.com/nf-core/test-datasets/raw/smrnaseq/reference/hsa.gff3' + mature = 'https://mirbase.org/download/CURRENT/mature.fa' + hairpin = 'https://mirbase.org/download/CURRENT/hairpin.fa' + mirna_gtf = 'https://mirbase.org/download/hsa.gff3' mirtrace_species = 'hsa' protocol = 'illumina' skip_mirdeep = true diff --git a/workflows/smrnaseq.nf b/workflows/smrnaseq.nf index f99b0d34..049851d0 100644 --- a/workflows/smrnaseq.nf +++ b/workflows/smrnaseq.nf @@ -56,12 +56,12 @@ ch_fastp_adapters = Channel.fromPath(params.fastp_known_mirna_adapters, // SUBWORKFLOW: Consisting of a mix of local and nf-core/modules // if (!params.mirgenedb) { - if (params.mature) { reference_mature = path(params.mature, checkIfExists: true) } else { exit 1, "Mature miRNA fasta file not found: ${params.mature}" } - if (params.hairpin) { reference_hairpin = path(params.hairpin, checkIfExists: true) } else { exit 1, "Hairpin miRNA fasta file not found: ${params.hairpin}" } + if (params.mature) { reference_mature = file(params.mature, checkIfExists: true) } else { exit 1, "Mature miRNA fasta file not found: ${params.mature}" } + if (params.hairpin) { reference_hairpin = file(params.hairpin, checkIfExists: true) } else { exit 1, "Hairpin miRNA fasta file not found: ${params.hairpin}" } } else { - if (params.mirgenedb_mature) { reference_mature = path(params.mirgenedb_mature, checkIfExists: true) } else { exit 1, "Mature miRNA fasta file not found: ${params.mirgenedb_mature}" } - if (params.mirgenedb_hairpin) { reference_hairpin = path(params.mirgenedb_hairpin, checkIfExists: true) } else { exit 1, "Hairpin miRNA fasta file not found: ${params.mirgenedb_hairpin}" } - if (params.mirgenedb_gff) { mirna_gtf = path(params.mirgenedb_gff, checkIfExists: true) } else { exit 1, "MirGeneDB gff file not found: ${params.mirgenedb_gff}"} + if (params.mirgenedb_mature) { reference_mature = file(params.mirgenedb_mature, checkIfExists: true) } else { exit 1, "Mature miRNA fasta file not found: ${params.mirgenedb_mature}" } + if (params.mirgenedb_hairpin) { reference_hairpin = file(params.mirgenedb_hairpin, checkIfExists: true) } else { exit 1, "Hairpin miRNA fasta file not found: ${params.mirgenedb_hairpin}" } + if (params.mirgenedb_gff) { mirna_gtf = file(params.mirgenedb_gff, checkIfExists: true) } else { exit 1, "MirGeneDB gff file not found: ${params.mirgenedb_gff}"} } include { INPUT_CHECK } from '../subworkflows/local/input_check' From 6ebe3d5fa1057518eafadf9da03dba98ff95760b Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 6 Sep 2023 07:26:13 +0000 Subject: [PATCH 185/215] Attempt at fixing HTML tags from downloading --- modules/local/parse_fasta_mirna.nf | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/local/parse_fasta_mirna.nf b/modules/local/parse_fasta_mirna.nf index 71f5c85a..c774d3ad 100644 --- a/modules/local/parse_fasta_mirna.nf +++ b/modules/local/parse_fasta_mirna.nf @@ -25,10 +25,9 @@ process PARSE_FASTA_MIRNA { gunzip -f \$FASTA FASTA=\${FASTA%%.gz} fi + sed 's/>/>/g' \$FASTA | sed 's/
    /\n/g' | sed 's#

    ##g' | sed 's#

    ##g' > \${FASTA}_html_cleaned.fa # Remove spaces from miRBase FASTA files - # sed -i 's, ,_,g' \$FASTA - sed '#^[^>]#s#[^AUGCaugc]#N#g' \$FASTA > \${FASTA}_parsed.fa - # TODO perl -ane 's/[ybkmrsw]/N/ig;print;' \${FASTA}_parsed_tmp.fa > \${FASTA}_parsed.fa + sed '#^[^>]#s#[^AUGCaugc]#N#g' \${FASTA}_html_cleaned.fa \${FASTA}_parsed.fa sed -i 's#\s.*##' \${FASTA}_parsed.fa seqkit grep -r --pattern \".*${filter_species}-.*\" \${FASTA}_parsed.fa > \${FASTA}_sps.fa From 23085189dd280406b5861cbf22c6c41fc4f3317a Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 6 Sep 2023 07:39:52 +0000 Subject: [PATCH 186/215] Expression for newline was incorrect --- modules/local/parse_fasta_mirna.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/parse_fasta_mirna.nf b/modules/local/parse_fasta_mirna.nf index c774d3ad..2649ebc1 100644 --- a/modules/local/parse_fasta_mirna.nf +++ b/modules/local/parse_fasta_mirna.nf @@ -25,9 +25,9 @@ process PARSE_FASTA_MIRNA { gunzip -f \$FASTA FASTA=\${FASTA%%.gz} fi - sed 's/>/>/g' \$FASTA | sed 's/
    /\n/g' | sed 's#

    ##g' | sed 's#

    ##g' > \${FASTA}_html_cleaned.fa + sed 's/>/>/g' \$FASTA | sed 's#
    #\\n#g' | sed 's#

    ##g' | sed 's#

    ##g' > \${FASTA}_html_cleaned.fa # Remove spaces from miRBase FASTA files - sed '#^[^>]#s#[^AUGCaugc]#N#g' \${FASTA}_html_cleaned.fa \${FASTA}_parsed.fa + sed '#^[^>]#s#[^AUGCaugc]#N#g' \${FASTA}_html_cleaned.fa > \${FASTA}_parsed.fa sed -i 's#\s.*##' \${FASTA}_parsed.fa seqkit grep -r --pattern \".*${filter_species}-.*\" \${FASTA}_parsed.fa > \${FASTA}_sps.fa From 6f79a99c0539dc966c97b285d7949dbb6998b685 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 6 Sep 2023 07:42:41 +0000 Subject: [PATCH 187/215] Prettier --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e24f6cc3..a0360e6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [v2.2.3](https://github.com/nf-core/smrnaseq/releases/tag/2.2.3) - 2023-09-06 - [[#271]](https://github.com/nf-core/smrnaseq/issues/271) - Bugfix for parsing hairpint mature files + ## [v2.2.2](https://github.com/nf-core/smrnaseq/releases/tag/2.2.2) - 2023-09-04 - [[#253]](https://github.com/nf-core/smrnaseq/pull/253) - Remove globs from process alias when using ECR containers From d42cfefb96ea43ca11c57d6ba3522fb88abe8e6b Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 6 Sep 2023 10:04:16 +0200 Subject: [PATCH 188/215] Update CHANGELOG.md Co-authored-by: Christopher Mohr --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0360e6f..7663b023 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [v2.2.3](https://github.com/nf-core/smrnaseq/releases/tag/2.2.3) - 2023-09-06 -- [[#271]](https://github.com/nf-core/smrnaseq/issues/271) - Bugfix for parsing hairpint mature files +- [[#271]](https://github.com/nf-core/smrnaseq/issues/271) - Bugfix for parsing hairpin and mature fasta files ## [v2.2.2](https://github.com/nf-core/smrnaseq/releases/tag/2.2.2) - 2023-09-04 From a3ed96d6b8f810654e9ee530ed93ee07e81296f3 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 6 Sep 2023 09:04:57 +0000 Subject: [PATCH 189/215] Bump to 2.2.3 --- assets/multiqc_config.yml | 4 ++-- nextflow.config | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index f549128c..8490cf0f 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -1,7 +1,7 @@ report_comment: > - This report has been generated by the nf-core/smrnaseq + This report has been generated by the nf-core/smrnaseq analysis pipeline. For information about how to interpret these results, please see the - documentation. + documentation. report_section_order: "nf-core-smrnaseq-methods-description": order: -1000 diff --git a/nextflow.config b/nextflow.config index 7f1cfb44..8ce36712 100644 --- a/nextflow.config +++ b/nextflow.config @@ -272,7 +272,7 @@ manifest { description = """Small RNA-Seq Best Practice Analysis Pipeline.""" mainScript = 'main.nf' nextflowVersion = '!>=23.04.0' - version = '2.2.3dev' + version = '2.2.3' doi = '' } From c8e225051c8cc1f3861d6c4028c01e3c0e8b2445 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Wed, 6 Sep 2023 19:57:45 +0000 Subject: [PATCH 190/215] Also clean up GFF --- modules/local/mirtop_quant.nf | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/local/mirtop_quant.nf b/modules/local/mirtop_quant.nf index cc8d29a7..3eed97dc 100644 --- a/modules/local/mirtop_quant.nf +++ b/modules/local/mirtop_quant.nf @@ -24,9 +24,11 @@ process MIRTOP_QUANT { script: def filter_species = params.mirgenedb ? params.mirgenedb_species : params.mirtrace_species """ - mirtop gff --hairpin $hairpin --gtf $gtf -o mirtop --sps $filter_species ./bams/* - mirtop counts --hairpin $hairpin --gtf $gtf -o mirtop --sps $filter_species --add-extra --gff mirtop/mirtop.gff - mirtop export --format isomir --hairpin $hairpin --gtf $gtf --sps $filter_species -o mirtop mirtop/mirtop.gff + #Cleanup the GTF if mirbase html form is broken + sed 's/>/>/g' \$gtf | sed 's#
    #\\n#g' | sed 's#

    ##g' | sed 's#

    ##g' > \${gtf}_html_cleaned.fa + mirtop gff --hairpin $hairpin --gtf \${gtf}_html_cleaned.fa -o mirtop --sps $filter_species ./bams/* + mirtop counts --hairpin $hairpin --gtf \${gtf}_html_cleaned.fa -o mirtop --sps $filter_species --add-extra --gff mirtop/mirtop.gff + mirtop export --format isomir --hairpin $hairpin --gtf \${gtf}_html_cleaned.fa --sps $filter_species -o mirtop mirtop/mirtop.gff mirtop stats mirtop/mirtop.gff --out mirtop/stats mv mirtop/stats/mirtop_stats.log mirtop/stats/full_mirtop_stats.log From 25adf7979dba7918ffa88c7ce162b465b8d1c335 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 7 Sep 2023 12:21:10 +0000 Subject: [PATCH 191/215] Push fix --- modules/local/mirtop_quant.nf | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/local/mirtop_quant.nf b/modules/local/mirtop_quant.nf index 3eed97dc..e15ce9e3 100644 --- a/modules/local/mirtop_quant.nf +++ b/modules/local/mirtop_quant.nf @@ -25,10 +25,11 @@ process MIRTOP_QUANT { def filter_species = params.mirgenedb ? params.mirgenedb_species : params.mirtrace_species """ #Cleanup the GTF if mirbase html form is broken - sed 's/>/>/g' \$gtf | sed 's#
    #\\n#g' | sed 's#

    ##g' | sed 's#

    ##g' > \${gtf}_html_cleaned.fa - mirtop gff --hairpin $hairpin --gtf \${gtf}_html_cleaned.fa -o mirtop --sps $filter_species ./bams/* - mirtop counts --hairpin $hairpin --gtf \${gtf}_html_cleaned.fa -o mirtop --sps $filter_species --add-extra --gff mirtop/mirtop.gff - mirtop export --format isomir --hairpin $hairpin --gtf \${gtf}_html_cleaned.fa --sps $filter_species -o mirtop mirtop/mirtop.gff + GTF="$gtf" + sed 's/>/>/g' \$GTF | sed 's#
    #\\n#g' | sed 's#

    ##g' | sed 's#

    ##g' > \${GTF}_html_cleaned.fa + mirtop gff --hairpin $hairpin --gtf \${GTF}_html_cleaned.fa -o mirtop --sps $filter_species ./bams/* + mirtop counts --hairpin $hairpin --gtf \${GTF}_html_cleaned.fa -o mirtop --sps $filter_species --add-extra --gff mirtop/mirtop.gff + mirtop export --format isomir --hairpin $hairpin --gtf \${GTF}_html_cleaned.fa --sps $filter_species -o mirtop mirtop/mirtop.gff mirtop stats mirtop/mirtop.gff --out mirtop/stats mv mirtop/stats/mirtop_stats.log mirtop/stats/full_mirtop_stats.log From c6c3ff90285f8feca0052e153989cedef9fcf148 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 7 Sep 2023 13:06:02 +0000 Subject: [PATCH 192/215] Bump version and changelog --- CHANGELOG.md | 3 +++ assets/multiqc_config.yml | 4 ++-- nextflow.config | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7663b023..62acd27c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ 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). +## [v2.2.4](https://github.com/nf-core/smrnaseq/releases/tag/2.2.4) - 2023-09-07 + +- Bugfix for issue with handling malformed GFF3 from mirbase (was forgotten in 2.2.3) ## [v2.2.3](https://github.com/nf-core/smrnaseq/releases/tag/2.2.3) - 2023-09-06 - [[#271]](https://github.com/nf-core/smrnaseq/issues/271) - Bugfix for parsing hairpin and mature fasta files diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index 8490cf0f..d2bfd50f 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -1,7 +1,7 @@ report_comment: > - This report has been generated by the nf-core/smrnaseq + This report has been generated by the nf-core/smrnaseq analysis pipeline. For information about how to interpret these results, please see the - documentation. + documentation. report_section_order: "nf-core-smrnaseq-methods-description": order: -1000 diff --git a/nextflow.config b/nextflow.config index 8ce36712..059feffe 100644 --- a/nextflow.config +++ b/nextflow.config @@ -272,7 +272,7 @@ manifest { description = """Small RNA-Seq Best Practice Analysis Pipeline.""" mainScript = 'main.nf' nextflowVersion = '!>=23.04.0' - version = '2.2.3' + version = '2.2.4' doi = '' } From 0ab71aed2e8e4e2d0ac2b2529a1331ee843a4ad0 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 7 Sep 2023 13:06:16 +0000 Subject: [PATCH 193/215] Prettier --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62acd27c..cbc0610e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [v2.2.4](https://github.com/nf-core/smrnaseq/releases/tag/2.2.4) - 2023-09-07 - Bugfix for issue with handling malformed GFF3 from mirbase (was forgotten in 2.2.3) + ## [v2.2.3](https://github.com/nf-core/smrnaseq/releases/tag/2.2.3) - 2023-09-06 - [[#271]](https://github.com/nf-core/smrnaseq/issues/271) - Bugfix for parsing hairpin and mature fasta files From 0d6aeef2453f59dc46965c9a4985e076bc7da408 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 8 Sep 2023 10:03:01 +0000 Subject: [PATCH 194/215] More sed magic --- modules/local/mirtop_quant.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/mirtop_quant.nf b/modules/local/mirtop_quant.nf index e15ce9e3..2d23c347 100644 --- a/modules/local/mirtop_quant.nf +++ b/modules/local/mirtop_quant.nf @@ -26,7 +26,7 @@ process MIRTOP_QUANT { """ #Cleanup the GTF if mirbase html form is broken GTF="$gtf" - sed 's/>/>/g' \$GTF | sed 's#
    #\\n#g' | sed 's#

    ##g' | sed 's#

    ##g' > \${GTF}_html_cleaned.fa + sed 's/>/>/g' \$GTF | sed 's#
    #\\n#g' | sed 's#

    ##g' | sed 's#

    ##g' | sed -e :a -e '/^\n*$/{$d;N;};/\n$/ba' > \${GTF}_html_cleaned.fa mirtop gff --hairpin $hairpin --gtf \${GTF}_html_cleaned.fa -o mirtop --sps $filter_species ./bams/* mirtop counts --hairpin $hairpin --gtf \${GTF}_html_cleaned.fa -o mirtop --sps $filter_species --add-extra --gff mirtop/mirtop.gff mirtop export --format isomir --hairpin $hairpin --gtf \${GTF}_html_cleaned.fa --sps $filter_species -o mirtop mirtop/mirtop.gff From d33232da43ad2570e46c4df0ef2e785c7847a368 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 8 Sep 2023 10:09:24 +0000 Subject: [PATCH 195/215] Proper exiting of variables in sed expression ... --- modules/local/mirtop_quant.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/mirtop_quant.nf b/modules/local/mirtop_quant.nf index 2d23c347..905c1761 100644 --- a/modules/local/mirtop_quant.nf +++ b/modules/local/mirtop_quant.nf @@ -26,7 +26,7 @@ process MIRTOP_QUANT { """ #Cleanup the GTF if mirbase html form is broken GTF="$gtf" - sed 's/>/>/g' \$GTF | sed 's#
    #\\n#g' | sed 's#

    ##g' | sed 's#

    ##g' | sed -e :a -e '/^\n*$/{$d;N;};/\n$/ba' > \${GTF}_html_cleaned.fa + sed 's/>/>/g' \$GTF | sed 's#
    #\\n#g' | sed 's#

    ##g' | sed 's#

    ##g' | sed -e :a -e '/^\n*\$/{\$d;N;};/\n\$/ba' > \${GTF}_html_cleaned.fa mirtop gff --hairpin $hairpin --gtf \${GTF}_html_cleaned.fa -o mirtop --sps $filter_species ./bams/* mirtop counts --hairpin $hairpin --gtf \${GTF}_html_cleaned.fa -o mirtop --sps $filter_species --add-extra --gff mirtop/mirtop.gff mirtop export --format isomir --hairpin $hairpin --gtf \${GTF}_html_cleaned.fa --sps $filter_species -o mirtop mirtop/mirtop.gff From ce3894a8e6a9e02c60a6f568dc7c8d22efe590c9 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 8 Sep 2023 11:59:51 +0000 Subject: [PATCH 196/215] Hopefully fix --- modules/local/mirtop_quant.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/mirtop_quant.nf b/modules/local/mirtop_quant.nf index 905c1761..82d06fad 100644 --- a/modules/local/mirtop_quant.nf +++ b/modules/local/mirtop_quant.nf @@ -26,7 +26,7 @@ process MIRTOP_QUANT { """ #Cleanup the GTF if mirbase html form is broken GTF="$gtf" - sed 's/>/>/g' \$GTF | sed 's#
    #\\n#g' | sed 's#

    ##g' | sed 's#

    ##g' | sed -e :a -e '/^\n*\$/{\$d;N;};/\n\$/ba' > \${GTF}_html_cleaned.fa + sed 's/>/>/g' \$GTF | sed 's#
    #\\n#g' | sed 's#

    ##g' | sed 's#

    ##g' | sed -e :a -e '/^\\n*\$/{\$d;N;};/\\n\$/ba' > \${GTF}_html_cleaned.fa mirtop gff --hairpin $hairpin --gtf \${GTF}_html_cleaned.fa -o mirtop --sps $filter_species ./bams/* mirtop counts --hairpin $hairpin --gtf \${GTF}_html_cleaned.fa -o mirtop --sps $filter_species --add-extra --gff mirtop/mirtop.gff mirtop export --format isomir --hairpin $hairpin --gtf \${GTF}_html_cleaned.fa --sps $filter_species -o mirtop mirtop/mirtop.gff From 53c0608e369ec7c4a9087aef4f9ebbfa3b2a332e Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Fri, 8 Sep 2023 18:47:04 +0000 Subject: [PATCH 197/215] Remove trailing newlines in FastA too --- modules/local/parse_fasta_mirna.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/parse_fasta_mirna.nf b/modules/local/parse_fasta_mirna.nf index 2649ebc1..a0bbc75e 100644 --- a/modules/local/parse_fasta_mirna.nf +++ b/modules/local/parse_fasta_mirna.nf @@ -25,7 +25,7 @@ process PARSE_FASTA_MIRNA { gunzip -f \$FASTA FASTA=\${FASTA%%.gz} fi - sed 's/>/>/g' \$FASTA | sed 's#
    #\\n#g' | sed 's#

    ##g' | sed 's#

    ##g' > \${FASTA}_html_cleaned.fa + sed 's/>/>/g' \$FASTA | sed 's#
    #\\n#g' | sed 's#

    ##g' | sed 's#

    ##g' | sed -e :a -e '/^\\n*\$/{\$d;N;};/\\n\$/ba' > \${FASTA}_html_cleaned.fa # Remove spaces from miRBase FASTA files sed '#^[^>]#s#[^AUGCaugc]#N#g' \${FASTA}_html_cleaned.fa > \${FASTA}_parsed.fa From 263fb6234cf2f2f502c3284f84e80b5e5deb4302 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 11 Sep 2023 08:51:42 +0000 Subject: [PATCH 198/215] Cleaned up --- modules/local/mirtop_quant.nf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/local/mirtop_quant.nf b/modules/local/mirtop_quant.nf index 82d06fad..90bdfc1d 100644 --- a/modules/local/mirtop_quant.nf +++ b/modules/local/mirtop_quant.nf @@ -26,9 +26,9 @@ process MIRTOP_QUANT { """ #Cleanup the GTF if mirbase html form is broken GTF="$gtf" - sed 's/>/>/g' \$GTF | sed 's#
    #\\n#g' | sed 's#

    ##g' | sed 's#

    ##g' | sed -e :a -e '/^\\n*\$/{\$d;N;};/\\n\$/ba' > \${GTF}_html_cleaned.fa - mirtop gff --hairpin $hairpin --gtf \${GTF}_html_cleaned.fa -o mirtop --sps $filter_species ./bams/* - mirtop counts --hairpin $hairpin --gtf \${GTF}_html_cleaned.fa -o mirtop --sps $filter_species --add-extra --gff mirtop/mirtop.gff + sed 's/>/>/g' \$GTF | sed 's#
    #\\n#g' | sed 's#

    ##g' | sed 's#

    ##g' | sed -e :a -e '/^\\n*\$/{\$d;N;};/\\n\$/ba' > \${GTF}_html_cleaned.gtf + mirtop gff --hairpin $hairpin --gtf \${GTF}_html_cleaned.gtf -o mirtop --sps $filter_species ./bams/* + mirtop counts --hairpin $hairpin --gtf \${GTF}_html_cleaned.gtf -o mirtop --sps $filter_species --add-extra --gff mirtop/mirtop.gff mirtop export --format isomir --hairpin $hairpin --gtf \${GTF}_html_cleaned.fa --sps $filter_species -o mirtop mirtop/mirtop.gff mirtop stats mirtop/mirtop.gff --out mirtop/stats mv mirtop/stats/mirtop_stats.log mirtop/stats/full_mirtop_stats.log From c65dc160a542f6136ac9163dab87ed5260fea1c6 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 11 Sep 2023 10:01:22 +0000 Subject: [PATCH 199/215] Fix for mirTop --- modules/local/mirtop_quant.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/mirtop_quant.nf b/modules/local/mirtop_quant.nf index 90bdfc1d..e97d6a09 100644 --- a/modules/local/mirtop_quant.nf +++ b/modules/local/mirtop_quant.nf @@ -29,7 +29,7 @@ process MIRTOP_QUANT { sed 's/>/>/g' \$GTF | sed 's#
    #\\n#g' | sed 's#

    ##g' | sed 's#

    ##g' | sed -e :a -e '/^\\n*\$/{\$d;N;};/\\n\$/ba' > \${GTF}_html_cleaned.gtf mirtop gff --hairpin $hairpin --gtf \${GTF}_html_cleaned.gtf -o mirtop --sps $filter_species ./bams/* mirtop counts --hairpin $hairpin --gtf \${GTF}_html_cleaned.gtf -o mirtop --sps $filter_species --add-extra --gff mirtop/mirtop.gff - mirtop export --format isomir --hairpin $hairpin --gtf \${GTF}_html_cleaned.fa --sps $filter_species -o mirtop mirtop/mirtop.gff + mirtop export --format isomir --hairpin $hairpin --gtf \${GTF}_html_cleaned.gtf --sps $filter_species -o mirtop mirtop/mirtop.gff mirtop stats mirtop/mirtop.gff --out mirtop/stats mv mirtop/stats/mirtop_stats.log mirtop/stats/full_mirtop_stats.log From 21b10e98836f6a671709d3a0437e0f3905651955 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 11 Sep 2023 10:15:26 +0000 Subject: [PATCH 200/215] Add suggestions by @mdozmorov --- bin/check_samplesheet.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/check_samplesheet.py b/bin/check_samplesheet.py index 96bf1394..94077cd4 100755 --- a/bin/check_samplesheet.py +++ b/bin/check_samplesheet.py @@ -67,8 +67,8 @@ def check_samplesheet(file_in, file_out): # Check valid number of columns per row if len(lspl) != len(header): print_error( - "Invalid number of columns: found {} columns (header has {})".format( - line_number, len(lspl), len(header) + "Invalid number of columns found - header has {} columns, content has {}. Number of rows {})".format( + len(header), len(lspl), line_number ), f"Line #{line_number+2}", line, From 1c25684c420d6d1679df1aea408005be9adbdbec Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Tue, 26 Sep 2023 08:09:07 +0000 Subject: [PATCH 201/215] Template update for nf-core/tools version 2.10 --- .devcontainer/devcontainer.json | 1 + .github/CONTRIBUTING.md | 4 +- .github/workflows/linting.yml | 2 +- .github/workflows/release-announcments.yml | 68 +++++++++ CHANGELOG.md | 2 +- CITATIONS.md | 2 +- CODE_OF_CONDUCT.md | 133 ++++++++++++++---- README.md | 21 +-- assets/multiqc_config.yml | 6 +- conf/modules.config | 9 ++ docs/output.md | 5 +- docs/usage.md | 16 ++- lib/NfcoreTemplate.groovy | 16 +++ lib/WorkflowSmrnaseq.groovy | 2 +- main.nf | 3 + modules.json | 6 +- .../custom/dumpsoftwareversions/main.nf | 2 +- modules/nf-core/fastqc/main.nf | 8 +- modules/nf-core/multiqc/main.nf | 2 +- nextflow.config | 9 +- nextflow_schema.json | 15 -- workflows/smrnaseq.nf | 1 + 22 files changed, 255 insertions(+), 78 deletions(-) create mode 100644 .github/workflows/release-announcments.yml diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index ea27a584..4ecfbfe3 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -2,6 +2,7 @@ "name": "nfcore", "image": "nfcore/gitpod:latest", "remoteUser": "gitpod", + "runArgs": ["--privileged"], // Configure tool-specific properties. "customizations": { diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 33a2c027..4d09370b 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -9,7 +9,9 @@ Please use the pre-filled template to save time. However, don't be put off by this template - other more general issues and suggestions are welcome! Contributions to the code are even more welcome ;) -> If you need help using or modifying nf-core/smrnaseq then the best place to ask is on the nf-core Slack [#smrnaseq](https://nfcore.slack.com/channels/smrnaseq) channel ([join our Slack here](https://nf-co.re/join/slack)). +:::info +If you need help using or modifying nf-core/smrnaseq then the best place to ask is on the nf-core Slack [#smrnaseq](https://nfcore.slack.com/channels/smrnaseq) channel ([join our Slack here](https://nf-co.re/join/slack)). +::: ## Contribution workflow diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 888cb4bc..b8bdd214 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -78,7 +78,7 @@ jobs: - uses: actions/setup-python@v4 with: - python-version: "3.8" + python-version: "3.11" architecture: "x64" - name: Install dependencies diff --git a/.github/workflows/release-announcments.yml b/.github/workflows/release-announcments.yml new file mode 100644 index 00000000..6ad33927 --- /dev/null +++ b/.github/workflows/release-announcments.yml @@ -0,0 +1,68 @@ +name: release-announcements +# Automatic release toot and tweet anouncements +on: + release: + types: [published] + workflow_dispatch: + +jobs: + toot: + runs-on: ubuntu-latest + steps: + - uses: rzr/fediverse-action@master + with: + access-token: ${{ secrets.MASTODON_ACCESS_TOKEN }} + host: "mstdn.science" # custom host if not "mastodon.social" (default) + # GitHub event payload + # https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#release + message: | + Pipeline release! ${{ github.repository }} v${{ github.event.release.tag_name }} - ${{ github.event.release.name }}! + + Please see the changelog: ${{ github.event.release.html_url }} + + send-tweet: + runs-on: ubuntu-latest + + steps: + - uses: actions/setup-python@v4 + with: + python-version: "3.10" + - name: Install dependencies + run: pip install tweepy==4.14.0 + - name: Send tweet + shell: python + run: | + import os + import tweepy + + client = tweepy.Client( + access_token=os.getenv("TWITTER_ACCESS_TOKEN"), + access_token_secret=os.getenv("TWITTER_ACCESS_TOKEN_SECRET"), + consumer_key=os.getenv("TWITTER_CONSUMER_KEY"), + consumer_secret=os.getenv("TWITTER_CONSUMER_SECRET"), + ) + tweet = os.getenv("TWEET") + client.create_tweet(text=tweet) + env: + TWEET: | + Pipeline release! ${{ github.repository }} v${{ github.event.release.tag_name }} - ${{ github.event.release.name }}! + + Please see the changelog: ${{ github.event.release.html_url }} + TWITTER_CONSUMER_KEY: ${{ secrets.TWITTER_CONSUMER_KEY }} + TWITTER_CONSUMER_SECRET: ${{ secrets.TWITTER_CONSUMER_SECRET }} + TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }} + TWITTER_ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }} + + bsky-post: + runs-on: ubuntu-latest + steps: + - uses: zentered/bluesky-post-action@v0.0.2 + with: + post: | + Pipeline release! ${{ github.repository }} v${{ github.event.release.tag_name }} - ${{ github.event.release.name }}! + + Please see the changelog: ${{ github.event.release.html_url }} + env: + BSKY_IDENTIFIER: ${{ secrets.BSKY_IDENTIFIER }} + BSKY_PASSWORD: ${{ secrets.BSKY_PASSWORD }} + # diff --git a/CHANGELOG.md b/CHANGELOG.md index 900274f3..d6c4fb89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 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). -## v2.2.2 - [date] +## v2.2.3 - [date] Initial release of nf-core/smrnaseq, created with the [nf-core](https://nf-co.re/) template. diff --git a/CITATIONS.md b/CITATIONS.md index a2b9d427..c33b0d8a 100644 --- a/CITATIONS.md +++ b/CITATIONS.md @@ -12,7 +12,7 @@ - [FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/) - > Andrews, S. (2010). FastQC: A Quality Control Tool for High Throughput Sequence Data [Online]. Available online https://www.bioinformatics.babraham.ac.uk/projects/fastqc/. + > Andrews, S. (2010). FastQC: A Quality Control Tool for High Throughput Sequence Data [Online]. - [MultiQC](https://pubmed.ncbi.nlm.nih.gov/27312411/) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index f4fd052f..c089ec78 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,18 +1,20 @@ -# Code of Conduct at nf-core (v1.0) +# Code of Conduct at nf-core (v1.4) ## Our Pledge -In the interest of fostering an open, collaborative, and welcoming environment, we as contributors and maintainers of nf-core, pledge to making participation in our projects and community a harassment-free experience for everyone, regardless of: +In the interest of fostering an open, collaborative, and welcoming environment, we as contributors and maintainers of nf-core pledge to making participation in our projects and community a harassment-free experience for everyone, regardless of: - Age +- Ability - Body size +- Caste - Familial status - Gender identity and expression - Geographical location - Level of experience - Nationality and national origins - Native language -- Physical and neurological ability +- Neurodiversity - Race or ethnicity - Religion - Sexual identity and orientation @@ -22,80 +24,133 @@ Please note that the list above is alphabetised and is therefore not ranked in a ## Preamble -> Note: This Code of Conduct (CoC) has been drafted by the nf-core Safety Officer and been edited after input from members of the nf-core team and others. "We", in this document, refers to the Safety Officer and members of the nf-core core team, both of whom are deemed to be members of the nf-core community and are therefore required to abide by this Code of Conduct. This document will amended periodically to keep it up-to-date, and in case of any dispute, the most current version will apply. +:::note +This Code of Conduct (CoC) has been drafted by Renuka Kudva, Cris Tuñí, and Michael Heuer, with input from the nf-core Core Team and Susanna Marquez from the nf-core community. "We", in this document, refers to the Safety Officers and members of the nf-core Core Team, both of whom are deemed to be members of the nf-core community and are therefore required to abide by this Code of Conduct. This document will be amended periodically to keep it up-to-date. In case of any dispute, the most current version will apply. +::: -An up-to-date list of members of the nf-core core team can be found [here](https://nf-co.re/about). Our current safety officer is Renuka Kudva. +An up-to-date list of members of the nf-core core team can be found [here](https://nf-co.re/about). + +Our Safety Officers are Saba Nafees, Cris Tuñí, and Michael Heuer. nf-core is a young and growing community that welcomes contributions from anyone with a shared vision for [Open Science Policies](https://www.fosteropenscience.eu/taxonomy/term/8). Open science policies encompass inclusive behaviours and we strive to build and maintain a safe and inclusive environment for all individuals. -We have therefore adopted this code of conduct (CoC), which we require all members of our community and attendees in nf-core events to adhere to in all our workspaces at all times. Workspaces include but are not limited to Slack, meetings on Zoom, Jitsi, YouTube live etc. +We have therefore adopted this CoC, which we require all members of our community and attendees of nf-core events to adhere to in all our workspaces at all times. Workspaces include, but are not limited to, Slack, meetings on Zoom, gather.town, YouTube live etc. -Our CoC will be strictly enforced and the nf-core team reserve the right to exclude participants who do not comply with our guidelines from our workspaces and future nf-core activities. +Our CoC will be strictly enforced and the nf-core team reserves the right to exclude participants who do not comply with our guidelines from our workspaces and future nf-core activities. -We ask all members of our community to help maintain a supportive and productive workspace and to avoid behaviours that can make individuals feel unsafe or unwelcome. Please help us maintain and uphold this CoC. +We ask all members of our community to help maintain supportive and productive workspaces and to avoid behaviours that can make individuals feel unsafe or unwelcome. Please help us maintain and uphold this CoC. -Questions, concerns or ideas on what we can include? Contact safety [at] nf-co [dot] re +Questions, concerns, or ideas on what we can include? Contact members of the Safety Team on Slack or email safety [at] nf-co [dot] re. ## Our Responsibilities -The safety officer is responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behaviour. +Members of the Safety Team (the Safety Officers) are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behaviour. -The safety officer in consultation with the nf-core core team have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. +The Safety Team, in consultation with the nf-core core team, have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this CoC, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. -Members of the core team or the safety officer who violate the CoC will be required to recuse themselves pending investigation. They will not have access to any reports of the violations and be subject to the same actions as others in violation of the CoC. +Members of the core team or the Safety Team who violate the CoC will be required to recuse themselves pending investigation. They will not have access to any reports of the violations and will be subject to the same actions as others in violation of the CoC. -## When are where does this Code of Conduct apply? +## When and where does this Code of Conduct apply? -Participation in the nf-core community is contingent on following these guidelines in all our workspaces and events. This includes but is not limited to the following listed alphabetically and therefore in no order of preference: +Participation in the nf-core community is contingent on following these guidelines in all our workspaces and events, such as hackathons, workshops, bytesize, and collaborative workspaces on gather.town. These guidelines include, but are not limited to, the following (listed alphabetically and therefore in no order of preference): - Communicating with an official project email address. - Communicating with community members within the nf-core Slack channel. - Participating in hackathons organised by nf-core (both online and in-person events). -- Participating in collaborative work on GitHub, Google Suite, community calls, mentorship meetings, email correspondence. -- Participating in workshops, training, and seminar series organised by nf-core (both online and in-person events). This applies to events hosted on web-based platforms such as Zoom, Jitsi, YouTube live etc. +- Participating in collaborative work on GitHub, Google Suite, community calls, mentorship meetings, email correspondence, and on the nf-core gather.town workspace. +- Participating in workshops, training, and seminar series organised by nf-core (both online and in-person events). This applies to events hosted on web-based platforms such as Zoom, gather.town, Jitsi, YouTube live etc. - Representing nf-core on social media. This includes both official and personal accounts. ## nf-core cares 😊 -nf-core's CoC and expectations of respectful behaviours for all participants (including organisers and the nf-core team) include but are not limited to the following (listed in alphabetical order): +nf-core's CoC and expectations of respectful behaviours for all participants (including organisers and the nf-core team) include, but are not limited to, the following (listed in alphabetical order): - Ask for consent before sharing another community member’s personal information (including photographs) on social media. - Be respectful of differing viewpoints and experiences. We are all here to learn from one another and a difference in opinion can present a good learning opportunity. -- Celebrate your accomplishments at events! (Get creative with your use of emojis 🎉 🥳 💯 🙌 !) +- Celebrate your accomplishments! (Get creative with your use of emojis 🎉 🥳 💯 🙌 !) - Demonstrate empathy towards other community members. (We don’t all have the same amount of time to dedicate to nf-core. If tasks are pending, don’t hesitate to gently remind members of your team. If you are leading a task, ask for help if you feel overwhelmed.) - Engage with and enquire after others. (This is especially important given the geographically remote nature of the nf-core community, so let’s do this the best we can) - Focus on what is best for the team and the community. (When in doubt, ask) -- Graciously accept constructive criticism, yet be unafraid to question, deliberate, and learn. +- Accept feedback, yet be unafraid to question, deliberate, and learn. - Introduce yourself to members of the community. (We’ve all been outsiders and we know that talking to strangers can be hard for some, but remember we’re interested in getting to know you and your visions for open science!) -- Show appreciation and **provide clear feedback**. (This is especially important because we don’t see each other in person and it can be harder to interpret subtleties. Also remember that not everyone understands a certain language to the same extent as you do, so **be clear in your communications to be kind.**) +- Show appreciation and **provide clear feedback**. (This is especially important because we don’t see each other in person and it can be harder to interpret subtleties. Also remember that not everyone understands a certain language to the same extent as you do, so **be clear in your communication to be kind.**) - Take breaks when you feel like you need them. -- Using welcoming and inclusive language. (Participants are encouraged to display their chosen pronouns on Zoom or in communication on Slack.) +- Use welcoming and inclusive language. (Participants are encouraged to display their chosen pronouns on Zoom or in communication on Slack) ## nf-core frowns on 😕 -The following behaviours from any participants within the nf-core community (including the organisers) will be considered unacceptable under this code of conduct. Engaging or advocating for any of the following could result in expulsion from nf-core workspaces. +The following behaviours from any participants within the nf-core community (including the organisers) will be considered unacceptable under this CoC. Engaging or advocating for any of the following could result in expulsion from nf-core workspaces: - Deliberate intimidation, stalking or following and sustained disruption of communication among participants of the community. This includes hijacking shared screens through actions such as using the annotate tool in conferencing software such as Zoom. - “Doxing” i.e. posting (or threatening to post) another person’s personal identifying information online. - Spamming or trolling of individuals on social media. -- Use of sexual or discriminatory imagery, comments, or jokes and unwelcome sexual attention. -- Verbal and text comments that reinforce social structures of domination related to gender, gender identity and expression, sexual orientation, ability, physical appearance, body size, race, age, religion or work experience. +- Use of sexual or discriminatory imagery, comments, jokes, or unwelcome sexual attention. +- Verbal and text comments that reinforce social structures of domination related to gender, gender identity and expression, sexual orientation, ability, physical appearance, body size, race, age, religion, or work experience. ### Online Trolling -The majority of nf-core interactions and events are held online. Unfortunately, holding events online comes with the added issue of online trolling. This is unacceptable, reports of such behaviour will be taken very seriously, and perpetrators will be excluded from activities immediately. +The majority of nf-core interactions and events are held online. Unfortunately, holding events online comes with the risk of online trolling. This is unacceptable — reports of such behaviour will be taken very seriously and perpetrators will be excluded from activities immediately. -All community members are required to ask members of the group they are working within for explicit consent prior to taking screenshots of individuals during video calls. +All community members are **required** to ask members of the group they are working with for explicit consent prior to taking screenshots of individuals during video calls. -## Procedures for Reporting CoC violations +## Procedures for reporting CoC violations If someone makes you feel uncomfortable through their behaviours or actions, report it as soon as possible. -You can reach out to members of the [nf-core core team](https://nf-co.re/about) and they will forward your concerns to the safety officer(s). +You can reach out to members of the Safety Team (Saba Nafees, Cris Tuñí, and Michael Heuer) on Slack. Alternatively, contact a member of the nf-core core team [nf-core core team](https://nf-co.re/about), and they will forward your concerns to the Safety Team. + +Issues directly concerning members of the Core Team or the Safety Team will be dealt with by other members of the core team and the safety manager — possible conflicts of interest will be taken into account. nf-core is also in discussions about having an ombudsperson and details will be shared in due course. + +All reports will be handled with the utmost discretion and confidentiality. + +You can also report any CoC violations to safety [at] nf-co [dot] re. In your email report, please do your best to include: + +- Your contact information. +- Identifying information (e.g. names, nicknames, pseudonyms) of the participant who has violated the Code of Conduct. +- The behaviour that was in violation and the circumstances surrounding the incident. +- The approximate time of the behaviour (if different than the time the report was made). +- Other people involved in the incident, if applicable. +- If you believe the incident is ongoing. +- If there is a publicly available record (e.g. mailing list record, a screenshot). +- Any additional information. + +After you file a report, one or more members of our Safety Team will contact you to follow up on your report. + +## Who will read and handle reports + +All reports will be read and handled by the members of the Safety Team at nf-core. + +If members of the Safety Team are deemed to have a conflict of interest with a report, they will be required to recuse themselves as per our Code of Conduct and will not have access to any follow-ups. + +To keep this first report confidential from any of the Safety Team members, please submit your first report by direct messaging on Slack/direct email to any of the nf-core members you are comfortable disclosing the information to, and be explicit about which member(s) you do not consent to sharing the information with. + +## Reviewing reports + +After receiving the report, members of the Safety Team will review the incident report to determine whether immediate action is required, for example, whether there is immediate threat to participants’ safety. + +The Safety Team, in consultation with members of the nf-core core team, will assess the information to determine whether the report constitutes a Code of Conduct violation, for them to decide on a course of action. + +In the case of insufficient information, one or more members of the Safety Team may contact the reporter, the reportee, or any other attendees to obtain more information. -Issues directly concerning members of the core team will be dealt with by other members of the core team and the safety manager, and possible conflicts of interest will be taken into account. nf-core is also in discussions about having an ombudsperson, and details will be shared in due course. +Once additional information is gathered, the Safety Team will collectively review and decide on the best course of action to take, if any. The Safety Team reserves the right to not act on a report. -All reports will be handled with utmost discretion and confidentially. +## Confidentiality + +All reports, and any additional information included, are only shared with the team of safety officers (and possibly members of the core team, in case the safety officer is in violation of the CoC). We will respect confidentiality requests for the purpose of protecting victims of abuse. + +We will not name harassment victims, beyond discussions between the safety officer and members of the nf-core team, without the explicit consent of the individuals involved. + +## Enforcement + +Actions taken by the nf-core’s Safety Team may include, but are not limited to: + +- Asking anyone to stop a behaviour. +- Asking anyone to leave the event and online spaces either temporarily, for the remainder of the event, or permanently. +- Removing access to the gather.town and Slack, either temporarily or permanently. +- Communicating to all participants to reinforce our expectations for conduct and remind what is unacceptable behaviour; this may be public for practical reasons. +- Communicating to all participants that an incident has taken place and how we will act or have acted — this may be for the purpose of letting event participants know we are aware of and dealing with the incident. +- Banning anyone from participating in nf-core-managed spaces, future events, and activities, either temporarily or permanently. +- No action. ## Attribution and Acknowledgements @@ -106,6 +161,22 @@ All reports will be handled with utmost discretion and confidentially. ## Changelog -### v1.0 - March 12th, 2021 +### v1.4 - February 8th, 2022 + +- Included a new member of the Safety Team. Corrected a typographical error in the text. + +### v1.3 - December 10th, 2021 + +- Added a statement that the CoC applies to nf-core gather.town workspaces. Corrected typographical errors in the text. + +### v1.2 - November 12th, 2021 + +- Removed information specific to reporting CoC violations at the Hackathon in October 2021. + +### v1.1 - October 14th, 2021 + +- Updated with names of new Safety Officers and specific information for the hackathon in October 2021. + +### v1.0 - March 15th, 2021 - Complete rewrite from original [Contributor Covenant](http://contributor-covenant.org/) CoC. diff --git a/README.md b/README.md index d8eb9be8..e5dc1d80 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # ![nf-core/smrnaseq](docs/images/nf-core-smrnaseq_logo_light.png#gh-light-mode-only) ![nf-core/smrnaseq](docs/images/nf-core-smrnaseq_logo_dark.png#gh-dark-mode-only) -[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/smrnaseq/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) +[![GitHub Actions CI Status](https://github.com/nf-core/smrnaseq/workflows/nf-core%20CI/badge.svg)](https://github.com/nf-core/smrnaseq/actions?query=workflow%3A%22nf-core+CI%22) +[![GitHub Actions Linting Status](https://github.com/nf-core/smrnaseq/workflows/nf-core%20linting/badge.svg)](https://github.com/nf-core/smrnaseq/actions?query=workflow%3A%22nf-core+linting%22)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/smrnaseq/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) [![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A523.04.0-23aa62.svg)](https://www.nextflow.io/) [![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/) @@ -29,10 +30,11 @@ ## Usage -> **Note** -> If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/usage/installation) on how -> to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/usage/introduction#how-to-run-a-pipeline) -> with `-profile test` before running the workflow on actual data. +:::note +If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/usage/installation) on how +to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/usage/introduction#how-to-run-a-pipeline) +with `-profile test` before running the workflow on actual data. +:::