From 7dc983838452bd4af29d02eefb6e15c6491aa23e Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 15 Aug 2024 20:06:14 +0300 Subject: [PATCH 001/132] added two new nf-core modules 'agat/sptatistics and agat/sqstatbasic' --- .../nf-core/agat/spstatistics/environment.yml | 7 +++ modules/nf-core/agat/spstatistics/main.nf | 46 +++++++++++++++ modules/nf-core/agat/spstatistics/meta.yml | 40 +++++++++++++ .../agat/spstatistics/tests/main.nf.test | 59 +++++++++++++++++++ .../agat/spstatistics/tests/main.nf.test.snap | 48 +++++++++++++++ .../nf-core/agat/spstatistics/tests/tags.yml | 2 + .../nf-core/agat/sqstatbasic/environment.yml | 7 +++ modules/nf-core/agat/sqstatbasic/main.nf | 46 +++++++++++++++ modules/nf-core/agat/sqstatbasic/meta.yml | 40 +++++++++++++ .../agat/sqstatbasic/tests/main.nf.test | 59 +++++++++++++++++++ .../agat/sqstatbasic/tests/main.nf.test.snap | 48 +++++++++++++++ .../nf-core/agat/sqstatbasic/tests/tags.yml | 2 + 12 files changed, 404 insertions(+) create mode 100644 modules/nf-core/agat/spstatistics/environment.yml create mode 100644 modules/nf-core/agat/spstatistics/main.nf create mode 100644 modules/nf-core/agat/spstatistics/meta.yml create mode 100644 modules/nf-core/agat/spstatistics/tests/main.nf.test create mode 100644 modules/nf-core/agat/spstatistics/tests/main.nf.test.snap create mode 100644 modules/nf-core/agat/spstatistics/tests/tags.yml create mode 100644 modules/nf-core/agat/sqstatbasic/environment.yml create mode 100644 modules/nf-core/agat/sqstatbasic/main.nf create mode 100644 modules/nf-core/agat/sqstatbasic/meta.yml create mode 100644 modules/nf-core/agat/sqstatbasic/tests/main.nf.test create mode 100644 modules/nf-core/agat/sqstatbasic/tests/main.nf.test.snap create mode 100644 modules/nf-core/agat/sqstatbasic/tests/tags.yml diff --git a/modules/nf-core/agat/spstatistics/environment.yml b/modules/nf-core/agat/spstatistics/environment.yml new file mode 100644 index 00000000..c868b7b8 --- /dev/null +++ b/modules/nf-core/agat/spstatistics/environment.yml @@ -0,0 +1,7 @@ +name: agat_spstatistics +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::agat=1.4.0 diff --git a/modules/nf-core/agat/spstatistics/main.nf b/modules/nf-core/agat/spstatistics/main.nf new file mode 100644 index 00000000..fd69d9c5 --- /dev/null +++ b/modules/nf-core/agat/spstatistics/main.nf @@ -0,0 +1,46 @@ +process AGAT_SPSTATISTICS { + tag "$meta.id" + label 'process_low' + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/agat:1.4.0--pl5321hdfd78af_0' : + 'biocontainers/agat:1.4.0--pl5321hdfd78af_0' }" + + input: + tuple val(meta), path(gff) + + output: + tuple val(meta), path("*.txt"), emit: stats_txt + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + agat_sp_statistics.pl \\ + --gff $gff \\ + --output ${prefix}.stats.txt \\ + $args + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + agat: \$(agat_sp_statistics.pl --help | sed -n 's/.*(AGAT) - Version: \\(.*\\) .*/\\1/p') + END_VERSIONS + """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.stats.txt + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + agat: \$(agat_sp_statistics.pl --help | sed -n 's/.*(AGAT) - Version: \\(.*\\) .*/\\1/p') + END_VERSIONS + """ +} diff --git a/modules/nf-core/agat/spstatistics/meta.yml b/modules/nf-core/agat/spstatistics/meta.yml new file mode 100644 index 00000000..c6cb21dd --- /dev/null +++ b/modules/nf-core/agat/spstatistics/meta.yml @@ -0,0 +1,40 @@ +name: agat_spstatistics +description: | + Provides different type of statistics in text format from a GFF/GTF annotation file +keywords: + - genome + - gff + - gtf + - statistics +tools: + - agat: + description: "AGAT is a toolkit for manipulation and getting information from GFF/GTF files" + homepage: "https://github.com/NBISweden/AGAT" + documentation: "https://agat.readthedocs.io/" + tool_dev_url: "https://github.com/NBISweden/AGAT" + doi: "10.5281/zenodo.3552717" + licence: ["GPL v3"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - gff: + type: file + description: Annotation file in GFF3/GTF format + pattern: "*.{gff, gtf}" +output: + - stats_txt: + type: file + description: Output of Statistics execution + pattern: "*.{txt}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@toniher" +maintainers: + - "@toniher" + - "@gallvp" diff --git a/modules/nf-core/agat/spstatistics/tests/main.nf.test b/modules/nf-core/agat/spstatistics/tests/main.nf.test new file mode 100644 index 00000000..ef867576 --- /dev/null +++ b/modules/nf-core/agat/spstatistics/tests/main.nf.test @@ -0,0 +1,59 @@ +nextflow_process { + + name "Test Process AGAT_SPSTATISTICS" + script "../main.nf" + process "AGAT_SPSTATISTICS" + + tag "modules" + tag "modules_nfcore" + tag "agat" + tag "agat/spstatistics" + + test("sarscov2 genome [gff]") { + + when { + process { + """ + input[0] = [ + [ id: 'test' ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.gff3', checkIfExists: true) + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("sarscov2 genome [gff] - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id: 'test' ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.gff3', checkIfExists: true) + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out.stats_txt.collect { file(it[1]).getName() } + + process.out.versions ).match() } + ) + } + + } + +} diff --git a/modules/nf-core/agat/spstatistics/tests/main.nf.test.snap b/modules/nf-core/agat/spstatistics/tests/main.nf.test.snap new file mode 100644 index 00000000..41f91740 --- /dev/null +++ b/modules/nf-core/agat/spstatistics/tests/main.nf.test.snap @@ -0,0 +1,48 @@ +{ + "sarscov2 genome [gff] - stub": { + "content": [ + [ + "test.stats.txt", + "versions.yml:md5,33c0e3094afa9dabe8f773db494bceb9" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-05-08T10:14:09.802927" + }, + "sarscov2 genome [gff]": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.stats.txt:md5,0a27bb5a911615023decd8223ba67812" + ] + ], + "1": [ + "versions.yml:md5,33c0e3094afa9dabe8f773db494bceb9" + ], + "stats_txt": [ + [ + { + "id": "test" + }, + "test.stats.txt:md5,0a27bb5a911615023decd8223ba67812" + ] + ], + "versions": [ + "versions.yml:md5,33c0e3094afa9dabe8f773db494bceb9" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-05-08T10:14:05.328436" + } +} \ No newline at end of file diff --git a/modules/nf-core/agat/spstatistics/tests/tags.yml b/modules/nf-core/agat/spstatistics/tests/tags.yml new file mode 100644 index 00000000..6cf47ac6 --- /dev/null +++ b/modules/nf-core/agat/spstatistics/tests/tags.yml @@ -0,0 +1,2 @@ +agat/spstatistics: + - "modules/nf-core/agat/spstatistics/**" diff --git a/modules/nf-core/agat/sqstatbasic/environment.yml b/modules/nf-core/agat/sqstatbasic/environment.yml new file mode 100644 index 00000000..58b04205 --- /dev/null +++ b/modules/nf-core/agat/sqstatbasic/environment.yml @@ -0,0 +1,7 @@ +name: agat_sqstatbasic +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::agat=1.4.0 diff --git a/modules/nf-core/agat/sqstatbasic/main.nf b/modules/nf-core/agat/sqstatbasic/main.nf new file mode 100644 index 00000000..d9b98c6b --- /dev/null +++ b/modules/nf-core/agat/sqstatbasic/main.nf @@ -0,0 +1,46 @@ +process AGAT_SQSTATBASIC { + tag "$meta.id" + label 'process_low' + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/agat:1.4.0--pl5321hdfd78af_0' : + 'biocontainers/agat:1.4.0--pl5321hdfd78af_0' }" + + input: + tuple val(meta), path(gff) + + output: + tuple val(meta), path("*.txt"), emit: stats_txt + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + agat_sq_stat_basic.pl \\ + -i $gff \\ + --output ${prefix}.stats.txt \\ + $args + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + agat: \$(agat_sq_stat_basic.pl --help | sed -n 's/.*(AGAT) - Version: \\(.*\\) .*/\\1/p') + END_VERSIONS + """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.stats.txt + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + agat: \$(agat_sq_stat_basic.pl --help | sed -n 's/.*(AGAT) - Version: \\(.*\\) .*/\\1/p') + END_VERSIONS + """ +} diff --git a/modules/nf-core/agat/sqstatbasic/meta.yml b/modules/nf-core/agat/sqstatbasic/meta.yml new file mode 100644 index 00000000..aba57e89 --- /dev/null +++ b/modules/nf-core/agat/sqstatbasic/meta.yml @@ -0,0 +1,40 @@ +name: agat_sqstatbasic +description: | + Provides basic statistics in text format from a GFF/GTF annotation file +keywords: + - genome + - gff + - gtf + - statistics +tools: + - agat: + description: "AGAT is a toolkit for manipulation and getting information from GFF/GTF files" + homepage: "https://github.com/NBISweden/AGAT" + documentation: "https://agat.readthedocs.io/" + tool_dev_url: "https://github.com/NBISweden/AGAT" + doi: "10.5281/zenodo.3552717" + licence: ["GPL v3"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - gff: + type: file + description: Annotation file in GFF3/GTF format + pattern: "*.{gff, gtf}" +output: + - stats_txt: + type: file + description: Output of Statistics execution + pattern: "*.{txt}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@toniher" +maintainers: + - "@toniher" + - "@gallvp" diff --git a/modules/nf-core/agat/sqstatbasic/tests/main.nf.test b/modules/nf-core/agat/sqstatbasic/tests/main.nf.test new file mode 100644 index 00000000..4803f51e --- /dev/null +++ b/modules/nf-core/agat/sqstatbasic/tests/main.nf.test @@ -0,0 +1,59 @@ +nextflow_process { + + name "Test Process AGAT_SQSTATBASIC" + script "../main.nf" + process "AGAT_SQSTATBASIC" + + tag "modules" + tag "modules_nfcore" + tag "agat" + tag "agat/sqstatbasic" + + test("sarscov2 - genome [gff3]") { + + when { + process { + """ + input[0] = [ + [ id: 'test' ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.gff3', checkIfExists: true) + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("sarscov2 - genome [gff3] - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id: 'test' ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.gff3', checkIfExists: true) + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out.stats_txt.collect { file(it[1]).getName() } + + process.out.versions ).match() } + ) + } + + } + +} diff --git a/modules/nf-core/agat/sqstatbasic/tests/main.nf.test.snap b/modules/nf-core/agat/sqstatbasic/tests/main.nf.test.snap new file mode 100644 index 00000000..10b75f48 --- /dev/null +++ b/modules/nf-core/agat/sqstatbasic/tests/main.nf.test.snap @@ -0,0 +1,48 @@ +{ + "sarscov2 - genome [gff3] - stub": { + "content": [ + [ + "test.stats.txt", + "versions.yml:md5,b5447c68fa61b8a04fdd7a95c4489775" + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-05-08T10:16:10.187496" + }, + "sarscov2 - genome [gff3]": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.stats.txt:md5,a41a0a9cfba3ed7cc1aff28815843c78" + ] + ], + "1": [ + "versions.yml:md5,b5447c68fa61b8a04fdd7a95c4489775" + ], + "stats_txt": [ + [ + { + "id": "test" + }, + "test.stats.txt:md5,a41a0a9cfba3ed7cc1aff28815843c78" + ] + ], + "versions": [ + "versions.yml:md5,b5447c68fa61b8a04fdd7a95c4489775" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-05-08T10:16:05.681598" + } +} \ No newline at end of file diff --git a/modules/nf-core/agat/sqstatbasic/tests/tags.yml b/modules/nf-core/agat/sqstatbasic/tests/tags.yml new file mode 100644 index 00000000..ad0ea18f --- /dev/null +++ b/modules/nf-core/agat/sqstatbasic/tests/tags.yml @@ -0,0 +1,2 @@ +agat/sqstatbasic: + - "modules/nf-core/agat/sqstatbasic/**" From 0548d90bf4acf8be978822f0359ed3dd9ba91a12 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 15 Aug 2024 20:06:49 +0300 Subject: [PATCH 002/132] added two new nf-core modules 'agat/sptatistics and agat/sqstatbasic' --- modules.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/modules.json b/modules.json index ced0be8a..ee455d45 100644 --- a/modules.json +++ b/modules.json @@ -5,6 +5,16 @@ "https://github.com/nf-core/modules.git": { "modules": { "nf-core": { + "agat/spstatistics": { + "branch": "master", + "git_sha": "0a0b723d114e502207072603479b635dfbc2bf59", + "installed_by": ["modules"] + }, + "agat/sqstatbasic": { + "branch": "master", + "git_sha": "0a0b723d114e502207072603479b635dfbc2bf59", + "installed_by": ["modules"] + }, "bedtools/bamtobed": { "branch": "master", "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", From cfafbaa324c7eee6d5283db327387d81dec2e178 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 15 Aug 2024 20:08:49 +0300 Subject: [PATCH 003/132] added new subworkflow to obtain annotation summary statistics --- subworkflows/local/annotation_statistics.nf | 44 +++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 subworkflows/local/annotation_statistics.nf diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf new file mode 100644 index 00000000..f0538a30 --- /dev/null +++ b/subworkflows/local/annotation_statistics.nf @@ -0,0 +1,44 @@ +// include modules from nf-core + +include { AGAT_SPSTATISTICS } from '../../modules/nf-core/agat/spstatistics/main' +include { AGAT_SQSTATBASIC } from '../../modules/nf-core/agat/spstatistics/main' +include { GUNZIP } from '../../modules/nf-core/gunzip/main' + + +workflow ANNOTATION_STATS { + + take: + gff // channel: /path/to/annotation file + + main: + ch_versions = Channel.empty() + + + // Map the GFF channel to create a tuple with metadata and the file + gff + | map { file -> [ [ 'id': file.baseName ], file ] } + | set {ch_gff_tupple} + + // Compress the gff files if needed + if (params.annotation_set.endsWith('.gz')) { + ch_unzipped = GUNZIP(ch_gff_tupple).gunzip + } else { + ch_unzipped = ch_gff_tupple + } + + + // Basic Annotation summary statistics + AGAT_SQSTATBASIC(ch_unzipped) + ch_versions = ch_versions.mix ( AGAT_SQSTATBASIC.out.versions.first() ) + + + // Other feature stats e.g intron count & length etc + AGAT_SPSTATISTICS(ch_unzipped) + ch_versions = ch_versions.mix ( AGAT_SPSTATISTICS.out.versions.first() ) + + + emit: + versions = ch_versions // channel: [ versions.yml ] + +} + From ddc3edc5f45ede5cf75c1a7bf10c7778b9131224 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 15 Aug 2024 20:09:32 +0300 Subject: [PATCH 004/132] added params.annotation_set --- nextflow.config | 1 + 1 file changed, 1 insertion(+) diff --git a/nextflow.config b/nextflow.config index c0e9ee66..5630e9a4 100644 --- a/nextflow.config +++ b/nextflow.config @@ -13,6 +13,7 @@ params { input = null binsize = 1000 kmer_size = 31 + annotation_set = null // Metadata assembly = null From 3bd733aaba165a851c02540526946ef6c733a041 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 15 Aug 2024 20:10:00 +0300 Subject: [PATCH 005/132] added documentation for params.annotation_set --- nextflow_schema.json | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/nextflow_schema.json b/nextflow_schema.json index 9525f1d8..65c94318 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -140,7 +140,16 @@ "type": "string", "description": "The name for the namespace used in the Kubernetes cluster running the HiGlass server.", "hidden": true - } + }, + "annotation_set": { + "type": "string", + "format": "file-path", + "mimetype": "text/plain", + "pattern": "^(?:[\\w/]+/)?\\S+\\.gff3?\\.gz?$", + "description": "Path to annotation file :gff.", + "help_text": "You will need to specify the path to the annotation file as eith gff or gff.gz.", + "fa_icon": "fas fa-file-code" + } } }, From 131b7b87ecefd1ed8798606b2fb43d1a6c5055b6 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 15 Aug 2024 20:12:23 +0300 Subject: [PATCH 006/132] added annotation_stats as specific output directory --- conf/modules.config | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/conf/modules.config b/conf/modules.config index fd9d477a..34fbf406 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -120,5 +120,22 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] } + withName: AGAT_SQSTATBASIC { + publishDir = [ + path: { "${params.outdir}/annotation_stats" }, + mode: params.publish_dir_mode, + pattern: '*.stats.txt', + saveAs: {'basic_features.stats.txt'} + ] + } + + withName: AGAT_SPSTATISTICS { + publishDir = [ + path: { "${params.outdir}/annotation_stats" }, + mode: params.publish_dir_mode, + pattern: '*.stats.txt', + saveAs: { 'other_features.stats.txt' } + ] + } } From e98a375eece4558c1031c7a2f53f9b80762bcfea Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 15 Aug 2024 20:13:21 +0300 Subject: [PATCH 007/132] allocated resources for the two new processes 'AGAT-SPSTATISTICS and AGAT_SQSTATBASIC' --- conf/base.config | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/conf/base.config b/conf/base.config index fae443f1..d70b5f3c 100644 --- a/conf/base.config +++ b/conf/base.config @@ -86,4 +86,11 @@ process { withName:CUSTOM_DUMPSOFTWAREVERSIONS { cache = false } + withName: AGAT_SQSTATBASIC { + memory = { check_max( 300.MB * task.attempt, 'memory' ) } + } + + withName: AGAT_SPSTATISTICS { + memory = { check_max( 300.MB * task.attempt, 'memory' ) } + } } From 5a2abe70edc54c1d83d2eef1bc1192b6b3fa4e19 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 15 Aug 2024 20:14:11 +0300 Subject: [PATCH 008/132] added new subworkflow and params.annotation_set --- workflows/genomenote.nf | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/workflows/genomenote.nf b/workflows/genomenote.nf index 2d264c51..73a90d38 100644 --- a/workflows/genomenote.nf +++ b/workflows/genomenote.nf @@ -26,6 +26,7 @@ if (params.lineage_tax_ids) { ch_lineage_tax_ids = Channel.fromPath(params.linea // Check optional parameters if (params.lineage_db) { ch_lineage_db = Channel.fromPath(params.lineage_db) } else { ch_lineage_db = Channel.empty() } if (params.note_template) { ch_note_template = Channel.fromPath(params.note_template) } else { ch_note_template = Channel.empty() } +if (params.annotation_set) { ch_gff = Channel.fromPath(params.annotation_set) } else { ch_gff = Channel.empty() } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -148,7 +149,13 @@ workflow GENOMENOTE { COMBINE_NOTE_DATA (GENOME_METADATA.out.consistent, GENOME_METADATA.out.inconsistent, GENOME_STATISTICS.out.summary, ch_note_template) ch_versions = ch_versions.mix ( COMBINE_NOTE_DATA.out.versions ) - + + // + // SUBWORKFLOW : Obtain feature statistics from the annotation file : GFF + // + ch_gff = Channel.fromPath(params.annotation_set) + ANNOTATION_STATS (ch_gff) + ch_versions = ch_versions.mix ( ANNOTATION_STATS.out.versions ) // // MODULE: Combine different versions.yml From c35db05095119a4a1ee830178a3227beefd3e15f Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 15 Aug 2024 20:15:03 +0300 Subject: [PATCH 009/132] added path to the test annotation file --- conf/test.config | 3 +++ conf/test_full.config | 3 +++ 2 files changed, 6 insertions(+) diff --git a/conf/test.config b/conf/test.config index aef2428f..6ca3ca4e 100644 --- a/conf/test.config +++ b/conf/test.config @@ -22,6 +22,9 @@ params { // Input data input = "${projectDir}/assets/samplesheet.csv" + // Annotation file + annotation_set = "https://tolit.cog.sanger.ac.uk/test-data/Cloeon_dipterum/annotation/GCF_949628265.1_ieCloDipt1.1_genomic.gff3.gz" + // Fasta references fasta = "https://tolit.cog.sanger.ac.uk/test-data/Cloeon_dipterum/assembly/release/ieCloDipt1.1/insdc/GCA_949628265.1.fasta.gz" diff --git a/conf/test_full.config b/conf/test_full.config index 6f151b91..94d80da7 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -19,6 +19,9 @@ params { // Input data for full size test input = "${projectDir}/assets/samplesheet_full.csv" + // Annotation file + annotation_set = "https://tolit.cog.sanger.ac.uk/test-data/Ypsolopha_sequella/annotation/GCA_934047225.1.braker.2022_09.gff3.gz" + // Fasta references fasta = "/lustre/scratch124/tol/projects/darwin/data/insects/Ypsolopha_sequella/assembly/release/ilYpsSequ2.1/insdc/GCA_934047225.1.fasta.gz" From 2fc43e81ac4f298dc2f8264bb14fa1606b315862 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 15 Aug 2024 21:12:32 +0300 Subject: [PATCH 010/132] modified the file after running prettier --- nextflow_schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow_schema.json b/nextflow_schema.json index 65c94318..679bd20c 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -149,7 +149,7 @@ "description": "Path to annotation file :gff.", "help_text": "You will need to specify the path to the annotation file as eith gff or gff.gz.", "fa_icon": "fas fa-file-code" - } + } } }, From a8dbd78931db17594b2e5c892edeaaebe716e23a Mon Sep 17 00:00:00 2001 From: Sandra Babirye <99010085+SandraBabirye@users.noreply.github.com> Date: Fri, 16 Aug 2024 14:30:58 +0300 Subject: [PATCH 011/132] added a new subworkflow 'ANNOTATION_STATS) --- workflows/genomenote.nf | 1 + 1 file changed, 1 insertion(+) diff --git a/workflows/genomenote.nf b/workflows/genomenote.nf index 73a90d38..41dde883 100644 --- a/workflows/genomenote.nf +++ b/workflows/genomenote.nf @@ -56,6 +56,7 @@ include { GENOME_METADATA } from '../subworkflows/local/genome_metadata' include { CONTACT_MAPS } from '../subworkflows/local/contact_maps' include { GENOME_STATISTICS } from '../subworkflows/local/genome_statistics' include { COMBINE_NOTE_DATA } from '../subworkflows/local/combine_note_data' +include { ANNOTATION_STATS } from '../subworkflows/local/annotation_statistics' /* From da91c575458400eecf0fb8ddb314a633e7c043d1 Mon Sep 17 00:00:00 2001 From: Sandra Babirye <99010085+SandraBabirye@users.noreply.github.com> Date: Fri, 16 Aug 2024 14:32:36 +0300 Subject: [PATCH 012/132] Edited annotation_statistics.nf file --- subworkflows/local/annotation_statistics.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index f0538a30..ab6f49f4 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -1,7 +1,7 @@ // include modules from nf-core include { AGAT_SPSTATISTICS } from '../../modules/nf-core/agat/spstatistics/main' -include { AGAT_SQSTATBASIC } from '../../modules/nf-core/agat/spstatistics/main' +include { AGAT_SQSTATBASIC } from '../../modules/nf-core/agat/sqstatbasic/main' include { GUNZIP } from '../../modules/nf-core/gunzip/main' From 65b463e8bbdd99d00ec90bcb0cab192f959871f4 Mon Sep 17 00:00:00 2001 From: Sandra Babirye <99010085+SandraBabirye@users.noreply.github.com> Date: Fri, 16 Aug 2024 14:36:16 +0300 Subject: [PATCH 013/132] edited the pattern for --annotation_set to include gff rather than gff3 --- nextflow_schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow_schema.json b/nextflow_schema.json index 679bd20c..e3046da9 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -145,7 +145,7 @@ "type": "string", "format": "file-path", "mimetype": "text/plain", - "pattern": "^(?:[\\w/]+/)?\\S+\\.gff3?\\.gz?$", + "pattern": "^(?:[\\w/]+/)?\\S+\\.gff(?:3)?\\.gz?$", "description": "Path to annotation file :gff.", "help_text": "You will need to specify the path to the annotation file as eith gff or gff.gz.", "fa_icon": "fas fa-file-code" From 85ac5053951078b0866e0c62a6984a20e44ab52d Mon Sep 17 00:00:00 2001 From: Sandra Babirye <99010085+SandraBabirye@users.noreply.github.com> Date: Fri, 16 Aug 2024 14:42:15 +0300 Subject: [PATCH 014/132] edited the pattern for --annotation_set to include gff rather than gff3 --- nextflow_schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow_schema.json b/nextflow_schema.json index e3046da9..2ee77194 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -145,7 +145,7 @@ "type": "string", "format": "file-path", "mimetype": "text/plain", - "pattern": "^(?:[\\w/]+/)?\\S+\\.gff(?:3)?\\.gz?$", + "pattern": "^(?:[\\w/]+/)?\\S+\\.gff3?(?:\\.gz)?$", "description": "Path to annotation file :gff.", "help_text": "You will need to specify the path to the annotation file as eith gff or gff.gz.", "fa_icon": "fas fa-file-code" From 26bd58c51b082f1e3563b60b5fb66c59f79c49d5 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 06:56:26 +0300 Subject: [PATCH 015/132] added a python script that extracts the relevant annotation statistics information from the txt files --- bin/extract_annotation_statistics_info.py | 133 ++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 bin/extract_annotation_statistics_info.py diff --git a/bin/extract_annotation_statistics_info.py b/bin/extract_annotation_statistics_info.py new file mode 100644 index 00000000..82ec8749 --- /dev/null +++ b/bin/extract_annotation_statistics_info.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python3 +import re +import csv +import sys +import argparse + +# Extract CDS information from mrna and transcript sections +def extract_cds_info(file): + # Define regex patterns for different statistics + patterns = { + 'TRANSC_MRNA': re.compile(r'Number of mrna\s+(\d+)'), + 'PCG': re.compile(r'Number of gene\s+(\d+)'), + 'CDS_PER_GENE': re.compile(r'mean mrnas per gene\s+([\d.]+)'), + 'EXONS_PER_TRANSC': re.compile(r'mean exons per transcript\s+([\d.]+)'), + 'CDS_LENGTH': re.compile(r'mean cds length \(bp\)\s+([\d.]+)'), + 'EXON_SIZE': re.compile(r'mean exon length \(bp\)\s+([\d.]+)'), + 'INTRON_SIZE': re.compile(r'mean intron in cds length \(bp\)\s+([\d.]+)') + } + + # Initialize a dictionary to store content for different sections + section_content = { + 'mrna': '', + 'transcript': '' + } + + # Variable to keep track of the current section being processed + current_section = None + + with open(file, 'r') as f: + lines = f.read().splitlines()# read all lines in the file + + for line in lines: + line = line.strip() # Remove any leading/trailing whitespace including newline characters + + if '---------------------------------- mrna ----------------------------------' in line: + current_section = 'mrna' # Switch to 'mrna' section + elif '---------------------------------- transcript ----------------------------------' in line: + current_section = 'transcript' # Switch to 'transcript' section + elif '----------' in line: + current_section = None # End of current section + elif current_section: + section_content[current_section] += line + ' ' # Accumulate content for the current section, separate lines by a space + + + cds_info = {} + + for label, pattern in patterns.items(): + text_to_search = section_content['mrna'] if label != 'EXONS_PER_TRANSC' else section_content['transcript'] + match = re.search(pattern, text_to_search) + if match: + cds_info[label] = match.group(1) + + return cds_info + + +# Function to extract the number of non-coding genes from the second file +def extract_non_coding_genes(file): + non_coding_genes = { + 'lnc_rna': 0, + 'ncrna': 0, + 'pseudogene': 0, + 'snorna': 0, + 'snrna': 0, + 'rrna': 0, + 'trna': 0 + } + + with open(file, 'r') as f: + for line in f: + parts = line.split() + if len(parts) < 2: + continue + + gene_type = parts[0] + try: + count = int(parts[1]) + except ValueError: + continue + + if gene_type in non_coding_genes: + non_coding_genes[gene_type] += count + + NCG = sum(non_coding_genes.values()) + return {'NCG': NCG} + +# Function to write the extracted data to a CSV file +def write_to_csv(data, output_file): + descriptions = { + 'TRANSC_MRNA': 'The number of transcribed mRNAs', + 'PCG': 'The number of protein coding genes', + 'NCG': 'The number of non-coding genes', + 'CDS_PER_GENE': 'The average number of coding transcripts per gene', + 'EXONS_PER_TRANSC': 'The average number of exons per transcript', + 'CDS_LENGTH': 'The average length of coding sequence', + 'EXON_SIZE': 'The average length of a coding exon', + 'INTRON_SIZE': 'The average length of coding intron size' + } + + with open(output_file, 'w', newline='') as csvfile: + writer = csv.writer(csvfile) + + # Write descriptions at the top of the CSV file + for key, description in descriptions.items(): + csvfile.write(f"# {key}: {description}\n") + + # Write the Variable and Value columns header + writer.writerow(['Variable', 'Value']) + + # Write the data + for key, value in data.items(): + writer.writerow([key, value]) + + + +# Main function to take input files and output file as arguments +def main(): + Description = "Parse contents of the agat_spstatistics and agat_sqstatbasic to extract relevant annotation statistics information." + Epilog = "Example usage: python extract_annotation_statistics_info.py " + + parser = argparse.ArgumentParser(description=Description, epilog=Epilog) + parser.add_argument("FILE_1", help="Input txt file with basic_feature_statistics.") + parser.add_argument("FILE_2", help="Input txt file with other_feature_statistics.") + parser.add_argument("FILE_OUT", help="Output file.") + parser.add_argument("--version", action="version", version="%(prog)s 1.0") + args = parser.parse_args() + + cds_info = extract_cds_info(args.FILE_2) + non_coding_genes = extract_non_coding_genes(args.FILE_1) + data = {**cds_info, **non_coding_genes} + write_to_csv(data, args.FILE_OUT) + +if __name__ == "__main__": + sys.exit(main()) From fe3c78e4d510df9c673d4e4cbe6872d4dcd0c5ff Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 06:57:13 +0300 Subject: [PATCH 016/132] added a new local module to extract annotation statistics information --- .../extract_annotation_statistics_info.nf | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 modules/local/extract_annotation_statistics_info.nf diff --git a/modules/local/extract_annotation_statistics_info.nf b/modules/local/extract_annotation_statistics_info.nf new file mode 100644 index 00000000..74ebf73d --- /dev/null +++ b/modules/local/extract_annotation_statistics_info.nf @@ -0,0 +1,33 @@ +// EXtracting essential annotation statistics information from the output txt files +process EXTRACT_ANNOTATION_STATISTICS_INFO { + publishDir "${params.outdir}/annotation_stats", mode: 'copy' + label 'process_single' + conda "conda-forge::python=3.9.1" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/python:3.9--1' : + 'quay.io/biocontainers/python:3.9--1' }" + input: + tuple val(sample_id), path(basic_stats_txt) + tuple val(sample_id), path(other_stats_txt) + output: + tuple val(sample_id), path("*.csv"), emit: file_path + path "versions.yml", emit: versions + when: + task.ext.when == null || task.ext.when + script: + // Define the prefix, using task.ext.prefix if provided, otherwise default to sample_id + def prefix = task.ext.prefix ?: sample_id + // Define the output file name using the prefix + def output_file = "${prefix}.csv" + """ + bin/extract_annotation_statistics_info.py \\ + $basic_stats \\ + $other_stats \\ + $output_file + cat <<-END_VERSIONS > versions.yml + "${task.process}": + python: \$(python --version | sed 's/Python //g') + END_VERSIONS + """ +} + From fd0d99200029783fa97842c11b1741c938b9706a Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 06:57:49 +0300 Subject: [PATCH 017/132] edited the annotation_stats subworkflow to include the new local module --- subworkflows/local/annotation_statistics.nf | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index ab6f49f4..7a71dade 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -1,9 +1,9 @@ // include modules from nf-core -include { AGAT_SPSTATISTICS } from '../../modules/nf-core/agat/spstatistics/main' -include { AGAT_SQSTATBASIC } from '../../modules/nf-core/agat/sqstatbasic/main' -include { GUNZIP } from '../../modules/nf-core/gunzip/main' - +include { AGAT_SPSTATISTICS } from '../../modules/nf-core/agat/spstatistics/main' +include { AGAT_SQSTATBASIC } from '../../modules/nf-core/agat/sqstatbasic/main' +include { GUNZIP } from '../../modules/nf-core/gunzip/main' +include { EXTRACT_ANNOTATION_STATISTICS_INFO } from '../../modules/local/extract_annotation_statistics_info.nf' workflow ANNOTATION_STATS { @@ -28,14 +28,16 @@ workflow ANNOTATION_STATS { // Basic Annotation summary statistics - AGAT_SQSTATBASIC(ch_unzipped) - ch_versions = ch_versions.mix ( AGAT_SQSTATBASIC.out.versions.first() ) + basic_stats = AGAT_SQSTATBASIC(ch_unzipped) + ch_versions = ch_versions.mix (basic_stats.out.versions.first() ) // Other feature stats e.g intron count & length etc - AGAT_SPSTATISTICS(ch_unzipped) - ch_versions = ch_versions.mix ( AGAT_SPSTATISTICS.out.versions.first() ) + other_stats = AGAT_SPSTATISTICS(ch_unzipped) + ch_versions = ch_versions.mix ( other_stats.out.versions.first() ) + // Parsing the txt files as input for the local module + EXTRACT_ANNOTATION_STATISTICS_INFO((basic_stats.out.stats_txt, other_stats.out.stats_txt)) emit: versions = ch_versions // channel: [ versions.yml ] From e6c6778b17855d6852fa7425745ce5e169359562 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 07:00:12 +0300 Subject: [PATCH 018/132] adjusted the allocated memory for agat_spstatistics and agat_sqstatbasic processes --- conf/base.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conf/base.config b/conf/base.config index d70b5f3c..d86d5c3e 100644 --- a/conf/base.config +++ b/conf/base.config @@ -87,10 +87,10 @@ process { cache = false } withName: AGAT_SQSTATBASIC { - memory = { check_max( 300.MB * task.attempt, 'memory' ) } + memory = { check_max( 500.MB * task.attempt, 'memory' ) } } withName: AGAT_SPSTATISTICS { - memory = { check_max( 300.MB * task.attempt, 'memory' ) } + memory = { check_max( 3.GB * task.attempt, 'memory' ) } } } From ead429877ce9312afc4b6d11b555c4c3f1de0d96 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 07:07:05 +0300 Subject: [PATCH 019/132] edited the annotation_stats subworkflow to include the new local module --- subworkflows/local/annotation_statistics.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 7a71dade..c5300fb3 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -37,7 +37,7 @@ workflow ANNOTATION_STATS { ch_versions = ch_versions.mix ( other_stats.out.versions.first() ) // Parsing the txt files as input for the local module - EXTRACT_ANNOTATION_STATISTICS_INFO((basic_stats.out.stats_txt, other_stats.out.stats_txt)) + EXTRACT_ANNOTATION_STATISTICS_INFO(basic_stats.out.stats_txt, other_stats.out.stats_txt) emit: versions = ch_versions // channel: [ versions.yml ] From a52bc5d67dfd33df98fccc1b8062b5ae70090df4 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 07:14:30 +0300 Subject: [PATCH 020/132] edited the annotation_stats subworkflow to include the new local module --- subworkflows/local/annotation_statistics.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index c5300fb3..2cec6fc8 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -34,10 +34,10 @@ workflow ANNOTATION_STATS { // Other feature stats e.g intron count & length etc other_stats = AGAT_SPSTATISTICS(ch_unzipped) - ch_versions = ch_versions.mix ( other_stats.out.versions.first() ) + ch_versions = ch_versions.mix ( other_stats.versions.first() ) // Parsing the txt files as input for the local module - EXTRACT_ANNOTATION_STATISTICS_INFO(basic_stats.out.stats_txt, other_stats.out.stats_txt) + EXTRACT_ANNOTATION_STATISTICS_INFO(basic_stats.stats_txt, other_stats.stats_txt) emit: versions = ch_versions // channel: [ versions.yml ] From 054dade63215b0a2211200f5f5a2b6ecbb6906a2 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 07:15:56 +0300 Subject: [PATCH 021/132] edited the annotation_stats subworkflow and removed .out --- subworkflows/local/annotation_statistics.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 2cec6fc8..23848f0e 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -29,7 +29,7 @@ workflow ANNOTATION_STATS { // Basic Annotation summary statistics basic_stats = AGAT_SQSTATBASIC(ch_unzipped) - ch_versions = ch_versions.mix (basic_stats.out.versions.first() ) + ch_versions = ch_versions.mix (basic_stats.versions.first() ) // Other feature stats e.g intron count & length etc From 0e316cd2367c6eefef94e3fb353b43ec72fec4ec Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 07:25:56 +0300 Subject: [PATCH 022/132] edited the modules.confif file --- conf/modules.config | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/conf/modules.config b/conf/modules.config index 34fbf406..5ccb92a4 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -137,5 +137,12 @@ process { saveAs: { 'other_features.stats.txt' } ] } + withName: EXTRACT_ANNOTATION_STATISTICS_INFO { + publishDir = [ + path: { "${params.outdir}/annotation_stats" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] + } } From 5902545f815043239a0116bd67b82b48219dfb74 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 07:26:43 +0300 Subject: [PATCH 023/132] edited the file --- .../local/extract_annotation_statistics_info.nf | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/modules/local/extract_annotation_statistics_info.nf b/modules/local/extract_annotation_statistics_info.nf index 74ebf73d..a138592e 100644 --- a/modules/local/extract_annotation_statistics_info.nf +++ b/modules/local/extract_annotation_statistics_info.nf @@ -1,29 +1,25 @@ // EXtracting essential annotation statistics information from the output txt files process EXTRACT_ANNOTATION_STATISTICS_INFO { - publishDir "${params.outdir}/annotation_stats", mode: 'copy' + label 'process_single' conda "conda-forge::python=3.9.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'https://depot.galaxyproject.org/singularity/python:3.9--1' : 'quay.io/biocontainers/python:3.9--1' }" input: - tuple val(sample_id), path(basic_stats_txt) - tuple val(sample_id), path(other_stats_txt) + path(basic_stats) + path(other_stats) output: - tuple val(sample_id), path("*.csv"), emit: file_path + path("assemblyID.csv"), emit: csv path "versions.yml", emit: versions when: task.ext.when == null || task.ext.when script: - // Define the prefix, using task.ext.prefix if provided, otherwise default to sample_id - def prefix = task.ext.prefix ?: sample_id - // Define the output file name using the prefix - def output_file = "${prefix}.csv" """ - bin/extract_annotation_statistics_info.py \\ + extract_annotation_statistics_info.py \\ $basic_stats \\ $other_stats \\ - $output_file + assemblyID.csv cat <<-END_VERSIONS > versions.yml "${task.process}": python: \$(python --version | sed 's/Python //g') From 0f8b9aeffc1358a687a3a5176effefcb629668f8 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 07:32:41 +0300 Subject: [PATCH 024/132] edited the file --- subworkflows/local/annotation_statistics.nf | 1 + 1 file changed, 1 insertion(+) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 23848f0e..b50ed828 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -38,6 +38,7 @@ workflow ANNOTATION_STATS { // Parsing the txt files as input for the local module EXTRACT_ANNOTATION_STATISTICS_INFO(basic_stats.stats_txt, other_stats.stats_txt) + ch_versions = ch_versions.mix( EXTRACT_ANNOTATION_STATISTICS_INFO.out.versions.first() ) emit: versions = ch_versions // channel: [ versions.yml ] From 5b6db7a4a51d1e07384fcf94db9418941e0a9367 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 08:38:11 +0300 Subject: [PATCH 025/132] edited file --- conf/modules.config | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 5ccb92a4..ac4293d5 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -124,8 +124,8 @@ process { publishDir = [ path: { "${params.outdir}/annotation_stats" }, mode: params.publish_dir_mode, - pattern: '*.stats.txt', - saveAs: {'basic_features.stats.txt'} + pattern: '*.txt', + saveAs: {'basic_features_stats.txt'} ] } @@ -133,8 +133,8 @@ process { publishDir = [ path: { "${params.outdir}/annotation_stats" }, mode: params.publish_dir_mode, - pattern: '*.stats.txt', - saveAs: { 'other_features.stats.txt' } + pattern: '*.txt', + saveAs: { 'other_features_stats.txt' } ] } withName: EXTRACT_ANNOTATION_STATISTICS_INFO { From fe446598eb951695017339d738f97abfa50d87c0 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 09:18:17 +0300 Subject: [PATCH 026/132] edited file --- .../extract_annotation_statistics_info.nf | 25 ++++++++++++++++++- subworkflows/local/annotation_statistics.nf | 6 +++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/modules/local/extract_annotation_statistics_info.nf b/modules/local/extract_annotation_statistics_info.nf index a138592e..10ed6844 100644 --- a/modules/local/extract_annotation_statistics_info.nf +++ b/modules/local/extract_annotation_statistics_info.nf @@ -9,17 +9,40 @@ process EXTRACT_ANNOTATION_STATISTICS_INFO { input: path(basic_stats) path(other_stats) + output: path("assemblyID.csv"), emit: csv path "versions.yml", emit: versions + when: task.ext.when == null || task.ext.when script: """ - extract_annotation_statistics_info.py \\ + echo "Basic stats file: $basic_stats" + echo "Other stats file: $other_stats" + + # Verify files exist + if [ ! -f $basic_stats ]; then + echo "Error: Basic stats file $basic_stats does not exist" >&2 + exit 1 + fi + + if [ ! -f $other_stats ]; then + echo "Error: Other stats file $other_stats does not exist" >&2 + exit 1 + fi + + bin/extract_annotation_statistics_info.py \\ $basic_stats \\ $other_stats \\ assemblyID.csv + + # Check if Python script ran successfully + if [ $? -ne 0 ]; then + echo "Error: Python script failed" >&2 + exit 1 + fi + cat <<-END_VERSIONS > versions.yml "${task.process}": python: \$(python --version | sed 's/Python //g') diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index b50ed828..7ab801d8 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -31,11 +31,17 @@ workflow ANNOTATION_STATS { basic_stats = AGAT_SQSTATBASIC(ch_unzipped) ch_versions = ch_versions.mix (basic_stats.versions.first() ) + // Print basic_stats outputs to inspect + basic_stats.stats_txt.view { "Basic Stats TXT: ${it}" } + // Other feature stats e.g intron count & length etc other_stats = AGAT_SPSTATISTICS(ch_unzipped) ch_versions = ch_versions.mix ( other_stats.versions.first() ) + // Print other_stats outputs to inspect + other_stats.stats_txt.view { "Other Stats TXT: ${it}" } + // Parsing the txt files as input for the local module EXTRACT_ANNOTATION_STATISTICS_INFO(basic_stats.stats_txt, other_stats.stats_txt) ch_versions = ch_versions.mix( EXTRACT_ANNOTATION_STATISTICS_INFO.out.versions.first() ) From d715b26fdff9c1d71e4ea81e5ed3b7365123aaa0 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 09:24:35 +0300 Subject: [PATCH 027/132] edited file --- .../local/extract_annotation_statistics_info.nf | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/modules/local/extract_annotation_statistics_info.nf b/modules/local/extract_annotation_statistics_info.nf index 10ed6844..b075e6b2 100644 --- a/modules/local/extract_annotation_statistics_info.nf +++ b/modules/local/extract_annotation_statistics_info.nf @@ -21,27 +21,12 @@ process EXTRACT_ANNOTATION_STATISTICS_INFO { echo "Basic stats file: $basic_stats" echo "Other stats file: $other_stats" - # Verify files exist - if [ ! -f $basic_stats ]; then - echo "Error: Basic stats file $basic_stats does not exist" >&2 - exit 1 - fi - - if [ ! -f $other_stats ]; then - echo "Error: Other stats file $other_stats does not exist" >&2 - exit 1 - fi - bin/extract_annotation_statistics_info.py \\ $basic_stats \\ $other_stats \\ assemblyID.csv - # Check if Python script ran successfully - if [ $? -ne 0 ]; then - echo "Error: Python script failed" >&2 - exit 1 - fi + cat <<-END_VERSIONS > versions.yml "${task.process}": From 9b21ccf205cc9ba29d11ce353e37cd36ca905cb7 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 09:26:33 +0300 Subject: [PATCH 028/132] edited file --- subworkflows/local/annotation_statistics.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 7ab801d8..2e6f88aa 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -32,7 +32,7 @@ workflow ANNOTATION_STATS { ch_versions = ch_versions.mix (basic_stats.versions.first() ) // Print basic_stats outputs to inspect - basic_stats.stats_txt.view { "Basic Stats TXT: ${it}" } + basic_stats.view { "Basic Stats TXT: ${it}" } // Other feature stats e.g intron count & length etc @@ -40,7 +40,7 @@ workflow ANNOTATION_STATS { ch_versions = ch_versions.mix ( other_stats.versions.first() ) // Print other_stats outputs to inspect - other_stats.stats_txt.view { "Other Stats TXT: ${it}" } + other_stats.view { "Other Stats TXT: ${it}" } // Parsing the txt files as input for the local module EXTRACT_ANNOTATION_STATISTICS_INFO(basic_stats.stats_txt, other_stats.stats_txt) From 5735681cd2da473158b16a17454f997d4e125d28 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 09:29:07 +0300 Subject: [PATCH 029/132] edited file --- subworkflows/local/annotation_statistics.nf | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 2e6f88aa..7d572eb4 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -32,7 +32,9 @@ workflow ANNOTATION_STATS { ch_versions = ch_versions.mix (basic_stats.versions.first() ) // Print basic_stats outputs to inspect - basic_stats.view { "Basic Stats TXT: ${it}" } + // Use .view to inspect basic_stats output + basic_stats.stats_txt.view { "Basic Stats TXT: ${it}" } + basic_stats.versions.view { "Basic Stats Versions: ${it}" } // Other feature stats e.g intron count & length etc @@ -40,7 +42,7 @@ workflow ANNOTATION_STATS { ch_versions = ch_versions.mix ( other_stats.versions.first() ) // Print other_stats outputs to inspect - other_stats.view { "Other Stats TXT: ${it}" } + other_stats.versions.view { "Other Stats TXT: ${it}" } // Parsing the txt files as input for the local module EXTRACT_ANNOTATION_STATISTICS_INFO(basic_stats.stats_txt, other_stats.stats_txt) From ee54ce08b0876b809be944890752870a0264d379 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 09:31:41 +0300 Subject: [PATCH 030/132] edited file --- subworkflows/local/annotation_statistics.nf | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 7d572eb4..7debe82a 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -26,24 +26,14 @@ workflow ANNOTATION_STATS { ch_unzipped = ch_gff_tupple } - // Basic Annotation summary statistics basic_stats = AGAT_SQSTATBASIC(ch_unzipped) ch_versions = ch_versions.mix (basic_stats.versions.first() ) - // Print basic_stats outputs to inspect - // Use .view to inspect basic_stats output - basic_stats.stats_txt.view { "Basic Stats TXT: ${it}" } - basic_stats.versions.view { "Basic Stats Versions: ${it}" } - - // Other feature stats e.g intron count & length etc other_stats = AGAT_SPSTATISTICS(ch_unzipped) ch_versions = ch_versions.mix ( other_stats.versions.first() ) - // Print other_stats outputs to inspect - other_stats.versions.view { "Other Stats TXT: ${it}" } - // Parsing the txt files as input for the local module EXTRACT_ANNOTATION_STATISTICS_INFO(basic_stats.stats_txt, other_stats.stats_txt) ch_versions = ch_versions.mix( EXTRACT_ANNOTATION_STATISTICS_INFO.out.versions.first() ) From af5ae871297066a70ba76e8c2ca93f2a6deea9c4 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 09:34:34 +0300 Subject: [PATCH 031/132] edited file --- subworkflows/local/annotation_statistics.nf | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 7debe82a..46c102c2 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -27,15 +27,15 @@ workflow ANNOTATION_STATS { } // Basic Annotation summary statistics - basic_stats = AGAT_SQSTATBASIC(ch_unzipped) - ch_versions = ch_versions.mix (basic_stats.versions.first() ) + AGAT_SQSTATBASIC(ch_unzipped) + ch_versions = ch_versions.mix (AGAT_SQSTATBASIC.versions.first() ) // Other feature stats e.g intron count & length etc - other_stats = AGAT_SPSTATISTICS(ch_unzipped) - ch_versions = ch_versions.mix ( other_stats.versions.first() ) + AGAT_SPSTATISTICS(ch_unzipped) + ch_versions = ch_versions.mix ( AGAT_SPSTATISTICS.versions.first() ) // Parsing the txt files as input for the local module - EXTRACT_ANNOTATION_STATISTICS_INFO(basic_stats.stats_txt, other_stats.stats_txt) + EXTRACT_ANNOTATION_STATISTICS_INFO(AGAT_SQSTATBASIC.stats_txt, AGAT_SPSTATISTICS.stats_txt) ch_versions = ch_versions.mix( EXTRACT_ANNOTATION_STATISTICS_INFO.out.versions.first() ) emit: From 0b47a555e3a5eea4650608a95a4fd7219fdab84e Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 09:36:37 +0300 Subject: [PATCH 032/132] edited file --- subworkflows/local/annotation_statistics.nf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 46c102c2..90cd511c 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -28,14 +28,14 @@ workflow ANNOTATION_STATS { // Basic Annotation summary statistics AGAT_SQSTATBASIC(ch_unzipped) - ch_versions = ch_versions.mix (AGAT_SQSTATBASIC.versions.first() ) + ch_versions = ch_versions.mix (AGAT_SQSTATBASIC.versions.out.versions.first() ) // Other feature stats e.g intron count & length etc AGAT_SPSTATISTICS(ch_unzipped) - ch_versions = ch_versions.mix ( AGAT_SPSTATISTICS.versions.first() ) + ch_versions = ch_versions.mix ( AGAT_SPSTATISTICS.out.versions.first() ) // Parsing the txt files as input for the local module - EXTRACT_ANNOTATION_STATISTICS_INFO(AGAT_SQSTATBASIC.stats_txt, AGAT_SPSTATISTICS.stats_txt) + EXTRACT_ANNOTATION_STATISTICS_INFO(AGAT_SQSTATBASIC.out.stats_txt, AGAT_SPSTATISTICS.out.stats_txt) ch_versions = ch_versions.mix( EXTRACT_ANNOTATION_STATISTICS_INFO.out.versions.first() ) emit: From 9f6d5703496f18c5641ebf1c47c65dfba8858f4e Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 09:40:10 +0300 Subject: [PATCH 033/132] edited file --- subworkflows/local/annotation_statistics.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 90cd511c..cb0a1a69 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -28,7 +28,7 @@ workflow ANNOTATION_STATS { // Basic Annotation summary statistics AGAT_SQSTATBASIC(ch_unzipped) - ch_versions = ch_versions.mix (AGAT_SQSTATBASIC.versions.out.versions.first() ) + ch_versions = ch_versions.mix ( AGAT_SQSTATBASIC.out.versions.first() ) // Other feature stats e.g intron count & length etc AGAT_SPSTATISTICS(ch_unzipped) From 8276619b6df7c7a343f382a9fdc1077007c11a3e Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 10:06:05 +0300 Subject: [PATCH 034/132] edited file --- subworkflows/local/annotation_statistics.nf | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index cb0a1a69..5b17e61b 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -30,10 +30,26 @@ workflow ANNOTATION_STATS { AGAT_SQSTATBASIC(ch_unzipped) ch_versions = ch_versions.mix ( AGAT_SQSTATBASIC.out.versions.first() ) + / View the outputs from the subworkflow + AGAT_SQSTATBASIC.stats_txt.view { file -> + println "Stats file: $file" + } + + AGAT_SQSTATBASIC.versions.view { file -> + println "Versions file: $file" + // Other feature stats e.g intron count & length etc AGAT_SPSTATISTICS(ch_unzipped) ch_versions = ch_versions.mix ( AGAT_SPSTATISTICS.out.versions.first() ) + / View the outputs from the subworkflow + AGAT_SPSTATISTICS.stats_txt.view { file -> + println "Stats file: $file" + } + + AGAT_SPSTATISTICS.versions.view { file -> + println "Versions file: $file" + // Parsing the txt files as input for the local module EXTRACT_ANNOTATION_STATISTICS_INFO(AGAT_SQSTATBASIC.out.stats_txt, AGAT_SPSTATISTICS.out.stats_txt) ch_versions = ch_versions.mix( EXTRACT_ANNOTATION_STATISTICS_INFO.out.versions.first() ) From 71db7fb13e305450f0d09d04656a35d54c39552a Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 10:11:46 +0300 Subject: [PATCH 035/132] edited file --- subworkflows/local/annotation_statistics.nf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 5b17e61b..84623689 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -37,6 +37,7 @@ workflow ANNOTATION_STATS { AGAT_SQSTATBASIC.versions.view { file -> println "Versions file: $file" + } // Other feature stats e.g intron count & length etc AGAT_SPSTATISTICS(ch_unzipped) @@ -49,6 +50,7 @@ workflow ANNOTATION_STATS { AGAT_SPSTATISTICS.versions.view { file -> println "Versions file: $file" + } // Parsing the txt files as input for the local module EXTRACT_ANNOTATION_STATISTICS_INFO(AGAT_SQSTATBASIC.out.stats_txt, AGAT_SPSTATISTICS.out.stats_txt) From c4420412fadae7ded91c7fa3034b64f8b67a1965 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 10:12:58 +0300 Subject: [PATCH 036/132] edited file --- subworkflows/local/annotation_statistics.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 84623689..c44beba5 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -43,7 +43,7 @@ workflow ANNOTATION_STATS { AGAT_SPSTATISTICS(ch_unzipped) ch_versions = ch_versions.mix ( AGAT_SPSTATISTICS.out.versions.first() ) - / View the outputs from the subworkflow + // View the outputs from the subworkflow AGAT_SPSTATISTICS.stats_txt.view { file -> println "Stats file: $file" } From 65ce7b455dfcb32f30f12315ab20a23a581cb407 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 10:14:51 +0300 Subject: [PATCH 037/132] edited file --- subworkflows/local/annotation_statistics.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index c44beba5..5a7bc6b3 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -30,7 +30,7 @@ workflow ANNOTATION_STATS { AGAT_SQSTATBASIC(ch_unzipped) ch_versions = ch_versions.mix ( AGAT_SQSTATBASIC.out.versions.first() ) - / View the outputs from the subworkflow + // View the outputs from the subworkflow AGAT_SQSTATBASIC.stats_txt.view { file -> println "Stats file: $file" } From 8fc6d6acf0862ae38512708a29783488e043338c Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 10:16:30 +0300 Subject: [PATCH 038/132] edited file --- subworkflows/local/annotation_statistics.nf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 5a7bc6b3..b8e11312 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -31,11 +31,11 @@ workflow ANNOTATION_STATS { ch_versions = ch_versions.mix ( AGAT_SQSTATBASIC.out.versions.first() ) // View the outputs from the subworkflow - AGAT_SQSTATBASIC.stats_txt.view { file -> + AGAT_SQSTATBASIC.out.stats_txt.view { file -> println "Stats file: $file" } - AGAT_SQSTATBASIC.versions.view { file -> + AGAT_SQSTATBASIC.out.versions.view { file -> println "Versions file: $file" } @@ -44,11 +44,11 @@ workflow ANNOTATION_STATS { ch_versions = ch_versions.mix ( AGAT_SPSTATISTICS.out.versions.first() ) // View the outputs from the subworkflow - AGAT_SPSTATISTICS.stats_txt.view { file -> + AGAT_SPSTATISTICS.out.stats_txt.view { file -> println "Stats file: $file" } - AGAT_SPSTATISTICS.versions.view { file -> + AGAT_SPSTATISTICS.out.versions.view { file -> println "Versions file: $file" } From a86d691cff2489b5c87a7d2636cdfe0072f21e89 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 10:43:16 +0300 Subject: [PATCH 039/132] edited file --- modules/local/extract_annotation_statistics_info.nf | 4 ++-- subworkflows/local/annotation_statistics.nf | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/modules/local/extract_annotation_statistics_info.nf b/modules/local/extract_annotation_statistics_info.nf index b075e6b2..9c7ceb76 100644 --- a/modules/local/extract_annotation_statistics_info.nf +++ b/modules/local/extract_annotation_statistics_info.nf @@ -7,8 +7,8 @@ process EXTRACT_ANNOTATION_STATISTICS_INFO { 'https://depot.galaxyproject.org/singularity/python:3.9--1' : 'quay.io/biocontainers/python:3.9--1' }" input: - path(basic_stats) - path(other_stats) + file(basic_stats) from ch_basic_stats + file(other_stats) from ch_other_stats output: path("assemblyID.csv"), emit: csv diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index b8e11312..c35ec980 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -51,9 +51,13 @@ workflow ANNOTATION_STATS { AGAT_SPSTATISTICS.out.versions.view { file -> println "Versions file: $file" } + + // Create channels for stats_txt outputs + ch_basic_stats = AGAT_SQSTATBASIC.out.stats_txt + ch_other_stats = AGAT_SPSTATISTICS.out.stats_txt // Parsing the txt files as input for the local module - EXTRACT_ANNOTATION_STATISTICS_INFO(AGAT_SQSTATBASIC.out.stats_txt, AGAT_SPSTATISTICS.out.stats_txt) + EXTRACT_ANNOTATION_STATISTICS_INFO(ch_basic_stats, ch_other_stats) ch_versions = ch_versions.mix( EXTRACT_ANNOTATION_STATISTICS_INFO.out.versions.first() ) emit: From 2993e069fc7386f82ab5d8d70d54d36c37dd18d0 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 10:54:22 +0300 Subject: [PATCH 040/132] edited file --- modules/local/extract_annotation_statistics_info.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/extract_annotation_statistics_info.nf b/modules/local/extract_annotation_statistics_info.nf index 9c7ceb76..bc462719 100644 --- a/modules/local/extract_annotation_statistics_info.nf +++ b/modules/local/extract_annotation_statistics_info.nf @@ -7,8 +7,8 @@ process EXTRACT_ANNOTATION_STATISTICS_INFO { 'https://depot.galaxyproject.org/singularity/python:3.9--1' : 'quay.io/biocontainers/python:3.9--1' }" input: - file(basic_stats) from ch_basic_stats - file(other_stats) from ch_other_stats + path (basic_stats) + path (other_stats) output: path("assemblyID.csv"), emit: csv From 1e5066fec7ae110840f867b0a6b32392eff1838a Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 13:17:59 +0300 Subject: [PATCH 041/132] edited the input channels --- modules/local/extract_annotation_statistics_info.nf | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/modules/local/extract_annotation_statistics_info.nf b/modules/local/extract_annotation_statistics_info.nf index bc462719..16ab12e1 100644 --- a/modules/local/extract_annotation_statistics_info.nf +++ b/modules/local/extract_annotation_statistics_info.nf @@ -7,11 +7,11 @@ process EXTRACT_ANNOTATION_STATISTICS_INFO { 'https://depot.galaxyproject.org/singularity/python:3.9--1' : 'quay.io/biocontainers/python:3.9--1' }" input: - path (basic_stats) - path (other_stats) + tuple val(meta), path(basic_stats) + tuple val(meta), path(other_stats) output: - path("assemblyID.csv"), emit: csv + path("$meta.csv"), emit: csv path "versions.yml", emit: versions when: @@ -26,8 +26,6 @@ process EXTRACT_ANNOTATION_STATISTICS_INFO { $other_stats \\ assemblyID.csv - - cat <<-END_VERSIONS > versions.yml "${task.process}": python: \$(python --version | sed 's/Python //g') From 38edfb1d864eb980d9cee0e5103c3b9f936731dc Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 13:18:36 +0300 Subject: [PATCH 042/132] created a tuple to extract meta id and file path --- subworkflows/local/annotation_statistics.nf | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index c35ec980..4961fce9 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -52,9 +52,13 @@ workflow ANNOTATION_STATS { println "Versions file: $file" } - // Create channels for stats_txt outputs - ch_basic_stats = AGAT_SQSTATBASIC.out.stats_txt - ch_other_stats = AGAT_SPSTATISTICS.out.stats_txt + // Create channels for stats_txt outputs : Extracts both the ID:filepath + //ch_basic_stats = AGAT_SQSTATBASIC.out.stats_txt + //ch_other_stats = AGAT_SPSTATISTICS.out.stats_txt + + // Create tuples with metadata and file paths + ch_basic_stats = AGAT_SQSTATBASIC.out.stats_txt.map { [id: it[0], path: it[1]] } + ch_other_stats = AGAT_SPSTATISTICS.out.stats_txt.map { [id: it[0], path: it[1]] } // Parsing the txt files as input for the local module EXTRACT_ANNOTATION_STATISTICS_INFO(ch_basic_stats, ch_other_stats) From db4f0a287f7906e11e12ebc73c5e5ae495200ac6 Mon Sep 17 00:00:00 2001 From: Sandra Babirye <99010085+SandraBabirye@users.noreply.github.com> Date: Thu, 29 Aug 2024 13:24:04 +0300 Subject: [PATCH 043/132] edited output channel --- modules/local/extract_annotation_statistics_info.nf | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/local/extract_annotation_statistics_info.nf b/modules/local/extract_annotation_statistics_info.nf index 16ab12e1..b43546d2 100644 --- a/modules/local/extract_annotation_statistics_info.nf +++ b/modules/local/extract_annotation_statistics_info.nf @@ -11,20 +11,22 @@ process EXTRACT_ANNOTATION_STATISTICS_INFO { tuple val(meta), path(other_stats) output: - path("$meta.csv"), emit: csv + tuple val (meta), path("${meta.id}.csv") , emit: csv path "versions.yml", emit: versions when: task.ext.when == null || task.ext.when + def prefix = task.ext.prefix ?: meta.id + script: """ echo "Basic stats file: $basic_stats" echo "Other stats file: $other_stats" - bin/extract_annotation_statistics_info.py \\ + extract_annotation_statistics_info.py \\ $basic_stats \\ $other_stats \\ - assemblyID.csv + ${prefix}.csv cat <<-END_VERSIONS > versions.yml "${task.process}": From 269e1f3e421dccd55f38916e9deecdb0441ab2ab Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 16:33:12 +0300 Subject: [PATCH 044/132] removal of the full publishDir block for both of the nf-core AGAT processes --- conf/modules.config | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index ac4293d5..8e050eee 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -121,21 +121,11 @@ process { ] } withName: AGAT_SQSTATBASIC { - publishDir = [ - path: { "${params.outdir}/annotation_stats" }, - mode: params.publish_dir_mode, - pattern: '*.txt', - saveAs: {'basic_features_stats.txt'} - ] + ext.prefix = { "${meta.id}_sqstats" } } withName: AGAT_SPSTATISTICS { - publishDir = [ - path: { "${params.outdir}/annotation_stats" }, - mode: params.publish_dir_mode, - pattern: '*.txt', - saveAs: { 'other_features_stats.txt' } - ] + ext.prefix = { "${meta.id}_spstats" } } withName: EXTRACT_ANNOTATION_STATISTICS_INFO { publishDir = [ From 5ac5e4bd63026fb2da06b43b2a238a02ab1eb85e Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 16:45:26 +0300 Subject: [PATCH 045/132] edited the output channel --- modules/local/extract_annotation_statistics_info.nf | 6 +++--- subworkflows/local/annotation_statistics.nf | 5 +---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/modules/local/extract_annotation_statistics_info.nf b/modules/local/extract_annotation_statistics_info.nf index b43546d2..c9568e03 100644 --- a/modules/local/extract_annotation_statistics_info.nf +++ b/modules/local/extract_annotation_statistics_info.nf @@ -7,11 +7,11 @@ process EXTRACT_ANNOTATION_STATISTICS_INFO { 'https://depot.galaxyproject.org/singularity/python:3.9--1' : 'quay.io/biocontainers/python:3.9--1' }" input: - tuple val(meta), path(basic_stats) - tuple val(meta), path(other_stats) + tuple val(meta), path(basic_stats) + tuple val(meta), path(other_stats) output: - tuple val (meta), path("${meta.id}.csv") , emit: csv + tuple val (meta), path("*.csv") , emit: csv path "versions.yml", emit: versions when: diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 4961fce9..fb462f99 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -51,10 +51,6 @@ workflow ANNOTATION_STATS { AGAT_SPSTATISTICS.out.versions.view { file -> println "Versions file: $file" } - - // Create channels for stats_txt outputs : Extracts both the ID:filepath - //ch_basic_stats = AGAT_SQSTATBASIC.out.stats_txt - //ch_other_stats = AGAT_SPSTATISTICS.out.stats_txt // Create tuples with metadata and file paths ch_basic_stats = AGAT_SQSTATBASIC.out.stats_txt.map { [id: it[0], path: it[1]] } @@ -65,6 +61,7 @@ workflow ANNOTATION_STATS { ch_versions = ch_versions.mix( EXTRACT_ANNOTATION_STATISTICS_INFO.out.versions.first() ) emit: + stats = EXTRACT_ANNOTATION_STATISTICS_INFO.out.csv // channel: [ csv ] versions = ch_versions // channel: [ versions.yml ] } From 54c908d30ad8ef6c02f5d89b6734bb0dcee88f55 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 16:58:35 +0300 Subject: [PATCH 046/132] edited the output file name --- modules/local/extract_annotation_statistics_info.nf | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/local/extract_annotation_statistics_info.nf b/modules/local/extract_annotation_statistics_info.nf index c9568e03..accbbcd9 100644 --- a/modules/local/extract_annotation_statistics_info.nf +++ b/modules/local/extract_annotation_statistics_info.nf @@ -17,16 +17,15 @@ process EXTRACT_ANNOTATION_STATISTICS_INFO { when: task.ext.when == null || task.ext.when def prefix = task.ext.prefix ?: meta.id + def output_file = "${prefix}.csv" script: """ - echo "Basic stats file: $basic_stats" - echo "Other stats file: $other_stats" extract_annotation_statistics_info.py \\ $basic_stats \\ $other_stats \\ - ${prefix}.csv + $output_file cat <<-END_VERSIONS > versions.yml "${task.process}": From c40cb4f6e9919e9aeb7b2406be77b16af953747a Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Thu, 29 Aug 2024 17:06:54 +0300 Subject: [PATCH 047/132] edited the output file name --- modules/local/extract_annotation_statistics_info.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/extract_annotation_statistics_info.nf b/modules/local/extract_annotation_statistics_info.nf index accbbcd9..0bf2394f 100644 --- a/modules/local/extract_annotation_statistics_info.nf +++ b/modules/local/extract_annotation_statistics_info.nf @@ -17,7 +17,7 @@ process EXTRACT_ANNOTATION_STATISTICS_INFO { when: task.ext.when == null || task.ext.when def prefix = task.ext.prefix ?: meta.id - def output_file = "${prefix}.csv" + def output_file = "\${prefix}.csv" script: """ From 1f10c833c07933b493bbf933d6620eec715c594d Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Tue, 3 Sep 2024 19:10:38 +0300 Subject: [PATCH 048/132] edited the output file and input channels --- .../extract_annotation_statistics_info.nf | 12 +++---- subworkflows/local/annotation_statistics.nf | 34 ++++--------------- 2 files changed, 12 insertions(+), 34 deletions(-) diff --git a/modules/local/extract_annotation_statistics_info.nf b/modules/local/extract_annotation_statistics_info.nf index 0bf2394f..70152ca4 100644 --- a/modules/local/extract_annotation_statistics_info.nf +++ b/modules/local/extract_annotation_statistics_info.nf @@ -8,24 +8,24 @@ process EXTRACT_ANNOTATION_STATISTICS_INFO { 'quay.io/biocontainers/python:3.9--1' }" input: tuple val(meta), path(basic_stats) - tuple val(meta), path(other_stats) + tuple val(meta2), path(other_stats) output: - tuple val (meta), path("*.csv") , emit: csv + path path "versions.yml", emit: versions when: task.ext.when == null || task.ext.when - def prefix = task.ext.prefix ?: meta.id - def output_file = "\${prefix}.csv" - + script: + def prefix = task.ext.prefix ?: meta.id + def output_file = "${prefix}.csv" """ extract_annotation_statistics_info.py \\ $basic_stats \\ $other_stats \\ - $output_file + ${output_file} cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index fb462f99..31146229 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -30,34 +30,12 @@ workflow ANNOTATION_STATS { AGAT_SQSTATBASIC(ch_unzipped) ch_versions = ch_versions.mix ( AGAT_SQSTATBASIC.out.versions.first() ) - // View the outputs from the subworkflow - AGAT_SQSTATBASIC.out.stats_txt.view { file -> - println "Stats file: $file" - } - - AGAT_SQSTATBASIC.out.versions.view { file -> - println "Versions file: $file" - } - - // Other feature stats e.g intron count & length etc - AGAT_SPSTATISTICS(ch_unzipped) - ch_versions = ch_versions.mix ( AGAT_SPSTATISTICS.out.versions.first() ) - - // View the outputs from the subworkflow - AGAT_SPSTATISTICS.out.stats_txt.view { file -> - println "Stats file: $file" - } - - AGAT_SPSTATISTICS.out.versions.view { file -> - println "Versions file: $file" - } - - // Create tuples with metadata and file paths - ch_basic_stats = AGAT_SQSTATBASIC.out.stats_txt.map { [id: it[0], path: it[1]] } - ch_other_stats = AGAT_SPSTATISTICS.out.stats_txt.map { [id: it[0], path: it[1]] } - - // Parsing the txt files as input for the local module - EXTRACT_ANNOTATION_STATISTICS_INFO(ch_basic_stats, ch_other_stats) + // Parsing the stats_txt files as input channels + EXTRACT_ANNOTATION_STATISTICS_INFO( + AGAT_SQSTATBASIC.out.stats_txt, + AGAT_SPSTATISTICS.out.stats_txt + ) + ch_versions = ch_versions.mix( EXTRACT_ANNOTATION_STATISTICS_INFO.out.versions.first() ) emit: From 886fc6ee2e521667e815fe5bb1cb2ac95645af80 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Tue, 3 Sep 2024 19:21:49 +0300 Subject: [PATCH 049/132] edited the output file --- modules/local/extract_annotation_statistics_info.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/local/extract_annotation_statistics_info.nf b/modules/local/extract_annotation_statistics_info.nf index 70152ca4..46cc8415 100644 --- a/modules/local/extract_annotation_statistics_info.nf +++ b/modules/local/extract_annotation_statistics_info.nf @@ -11,7 +11,7 @@ process EXTRACT_ANNOTATION_STATISTICS_INFO { tuple val(meta2), path(other_stats) output: - path + tuple val (meta), path("*.csv") , emit: csv path "versions.yml", emit: versions when: @@ -25,7 +25,7 @@ process EXTRACT_ANNOTATION_STATISTICS_INFO { extract_annotation_statistics_info.py \\ $basic_stats \\ $other_stats \\ - ${output_file} + $output_file cat <<-END_VERSIONS > versions.yml "${task.process}": From 601abc73b5f79aba9180c53e14ac264a78f4bbf4 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Tue, 3 Sep 2024 11:34:10 -0500 Subject: [PATCH 050/132] edited the file permisions --- bin/extract_annotation_statistics_info.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 bin/extract_annotation_statistics_info.py diff --git a/bin/extract_annotation_statistics_info.py b/bin/extract_annotation_statistics_info.py old mode 100644 new mode 100755 From b0c449051060f078483394d2bb2dcf35ce5dde65 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Tue, 3 Sep 2024 11:40:47 -0500 Subject: [PATCH 051/132] edited the annotation_statistics.nf file --- subworkflows/local/annotation_statistics.nf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 31146229..b4d3b249 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -30,6 +30,10 @@ workflow ANNOTATION_STATS { AGAT_SQSTATBASIC(ch_unzipped) ch_versions = ch_versions.mix ( AGAT_SQSTATBASIC.out.versions.first() ) + // Other annotation statistics + AGAT_SPSTATISTICS(ch_unzipped) + ch_versions = ch_versions.mix ( AGAT_SQSTATBASIC.out.versions.first() ) + // Parsing the stats_txt files as input channels EXTRACT_ANNOTATION_STATISTICS_INFO( AGAT_SQSTATBASIC.out.stats_txt, From 2fcca2cd23968cae08d9895c201e9bca6e3c41c0 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Tue, 3 Sep 2024 11:56:58 -0500 Subject: [PATCH 052/132] Fix code formatting with Black --- bin/extract_annotation_statistics_info.py | 100 ++++++++++------------ 1 file changed, 46 insertions(+), 54 deletions(-) diff --git a/bin/extract_annotation_statistics_info.py b/bin/extract_annotation_statistics_info.py index 82ec8749..fb3336bd 100755 --- a/bin/extract_annotation_statistics_info.py +++ b/bin/extract_annotation_statistics_info.py @@ -4,48 +4,47 @@ import sys import argparse -# Extract CDS information from mrna and transcript sections + +# Extract CDS information from mrna and transcript sections def extract_cds_info(file): # Define regex patterns for different statistics patterns = { - 'TRANSC_MRNA': re.compile(r'Number of mrna\s+(\d+)'), - 'PCG': re.compile(r'Number of gene\s+(\d+)'), - 'CDS_PER_GENE': re.compile(r'mean mrnas per gene\s+([\d.]+)'), - 'EXONS_PER_TRANSC': re.compile(r'mean exons per transcript\s+([\d.]+)'), - 'CDS_LENGTH': re.compile(r'mean cds length \(bp\)\s+([\d.]+)'), - 'EXON_SIZE': re.compile(r'mean exon length \(bp\)\s+([\d.]+)'), - 'INTRON_SIZE': re.compile(r'mean intron in cds length \(bp\)\s+([\d.]+)') + "TRANSC_MRNA": re.compile(r"Number of mrna\s+(\d+)"), + "PCG": re.compile(r"Number of gene\s+(\d+)"), + "CDS_PER_GENE": re.compile(r"mean mrnas per gene\s+([\d.]+)"), + "EXONS_PER_TRANSC": re.compile(r"mean exons per transcript\s+([\d.]+)"), + "CDS_LENGTH": re.compile(r"mean cds length \(bp\)\s+([\d.]+)"), + "EXON_SIZE": re.compile(r"mean exon length \(bp\)\s+([\d.]+)"), + "INTRON_SIZE": re.compile(r"mean intron in cds length \(bp\)\s+([\d.]+)"), } # Initialize a dictionary to store content for different sections - section_content = { - 'mrna': '', - 'transcript': '' - } - + section_content = {"mrna": "", "transcript": ""} + # Variable to keep track of the current section being processed current_section = None - - with open(file, 'r') as f: - lines = f.read().splitlines()# read all lines in the file + + with open(file, "r") as f: + lines = f.read().splitlines() # read all lines in the file for line in lines: line = line.strip() # Remove any leading/trailing whitespace including newline characters - - if '---------------------------------- mrna ----------------------------------' in line: - current_section = 'mrna' # Switch to 'mrna' section - elif '---------------------------------- transcript ----------------------------------' in line: - current_section = 'transcript' # Switch to 'transcript' section - elif '----------' in line: - current_section = None # End of current section - elif current_section: - section_content[current_section] += line + ' ' # Accumulate content for the current section, separate lines by a space + if "---------------------------------- mrna ----------------------------------" in line: + current_section = "mrna" # Switch to 'mrna' section + elif "---------------------------------- transcript ----------------------------------" in line: + current_section = "transcript" # Switch to 'transcript' section + elif "----------" in line: + current_section = None # End of current section + elif current_section: + section_content[current_section] += ( + line + " " + ) # Accumulate content for the current section, separate lines by a space cds_info = {} - + for label, pattern in patterns.items(): - text_to_search = section_content['mrna'] if label != 'EXONS_PER_TRANSC' else section_content['transcript'] + text_to_search = section_content["mrna"] if label != "EXONS_PER_TRANSC" else section_content["transcript"] match = re.search(pattern, text_to_search) if match: cds_info[label] = match.group(1) @@ -55,79 +54,72 @@ def extract_cds_info(file): # Function to extract the number of non-coding genes from the second file def extract_non_coding_genes(file): - non_coding_genes = { - 'lnc_rna': 0, - 'ncrna': 0, - 'pseudogene': 0, - 'snorna': 0, - 'snrna': 0, - 'rrna': 0, - 'trna': 0 - } + non_coding_genes = {"lnc_rna": 0, "ncrna": 0, "pseudogene": 0, "snorna": 0, "snrna": 0, "rrna": 0, "trna": 0} - with open(file, 'r') as f: + with open(file, "r") as f: for line in f: parts = line.split() if len(parts) < 2: continue - + gene_type = parts[0] try: count = int(parts[1]) except ValueError: continue - + if gene_type in non_coding_genes: non_coding_genes[gene_type] += count NCG = sum(non_coding_genes.values()) - return {'NCG': NCG} + return {"NCG": NCG} + # Function to write the extracted data to a CSV file def write_to_csv(data, output_file): descriptions = { - 'TRANSC_MRNA': 'The number of transcribed mRNAs', - 'PCG': 'The number of protein coding genes', - 'NCG': 'The number of non-coding genes', - 'CDS_PER_GENE': 'The average number of coding transcripts per gene', - 'EXONS_PER_TRANSC': 'The average number of exons per transcript', - 'CDS_LENGTH': 'The average length of coding sequence', - 'EXON_SIZE': 'The average length of a coding exon', - 'INTRON_SIZE': 'The average length of coding intron size' + "TRANSC_MRNA": "The number of transcribed mRNAs", + "PCG": "The number of protein coding genes", + "NCG": "The number of non-coding genes", + "CDS_PER_GENE": "The average number of coding transcripts per gene", + "EXONS_PER_TRANSC": "The average number of exons per transcript", + "CDS_LENGTH": "The average length of coding sequence", + "EXON_SIZE": "The average length of a coding exon", + "INTRON_SIZE": "The average length of coding intron size", } - with open(output_file, 'w', newline='') as csvfile: + with open(output_file, "w", newline="") as csvfile: writer = csv.writer(csvfile) # Write descriptions at the top of the CSV file for key, description in descriptions.items(): csvfile.write(f"# {key}: {description}\n") - + # Write the Variable and Value columns header - writer.writerow(['Variable', 'Value']) + writer.writerow(["Variable", "Value"]) # Write the data for key, value in data.items(): writer.writerow([key, value]) - # Main function to take input files and output file as arguments def main(): Description = "Parse contents of the agat_spstatistics and agat_sqstatbasic to extract relevant annotation statistics information." Epilog = "Example usage: python extract_annotation_statistics_info.py " - + parser = argparse.ArgumentParser(description=Description, epilog=Epilog) parser.add_argument("FILE_1", help="Input txt file with basic_feature_statistics.") parser.add_argument("FILE_2", help="Input txt file with other_feature_statistics.") parser.add_argument("FILE_OUT", help="Output file.") parser.add_argument("--version", action="version", version="%(prog)s 1.0") - args = parser.parse_args() + args = parser.parse_args() cds_info = extract_cds_info(args.FILE_2) non_coding_genes = extract_non_coding_genes(args.FILE_1) data = {**cds_info, **non_coding_genes} write_to_csv(data, args.FILE_OUT) + if __name__ == "__main__": sys.exit(main()) From 77c6d5e531987d0fa24183f8a037d705bc16258a Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Tue, 3 Sep 2024 20:09:35 +0300 Subject: [PATCH 053/132] Fix EditorConfig linting issues --- conf/modules.config | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 8e050eee..1177fe34 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -97,7 +97,7 @@ process { ] } - withName: COMBINE_STATISTICS_AND_METADATA { + withName: COMBINE_STATISTICS_AND_METADATA { publishDir = [ path: { "${params.outdir}/genome_note" }, mode: params.publish_dir_mode, @@ -105,7 +105,7 @@ process { ] } - withName: POPULATE_TEMPLATE { + withName: POPULATE_TEMPLATE { publishDir = [ path: { "${params.outdir}/genome_note" }, mode: params.publish_dir_mode, @@ -113,13 +113,14 @@ process { ] } - withName: GENERATE_HIGLASS_LINK { + withName: GENERATE_HIGLASS_LINK { publishDir = [ path: { "${params.outdir}/contact_maps" }, mode: params.publish_dir_mode, saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] } + withName: AGAT_SQSTATBASIC { ext.prefix = { "${meta.id}_sqstats" } } @@ -127,6 +128,7 @@ process { withName: AGAT_SPSTATISTICS { ext.prefix = { "${meta.id}_spstats" } } + withName: EXTRACT_ANNOTATION_STATISTICS_INFO { publishDir = [ path: { "${params.outdir}/annotation_stats" }, From fd7ca06f5463246111124ff1862ff4611854fb3d Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Tue, 3 Sep 2024 20:20:51 +0300 Subject: [PATCH 054/132] Fix EditorConfig linting issues --- conf/modules.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/modules.config b/conf/modules.config index 1177fe34..2b982f15 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -120,7 +120,7 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] } - + withName: AGAT_SQSTATBASIC { ext.prefix = { "${meta.id}_sqstats" } } From 09630ed53665cc5a48c9e76853a57c9713094bb6 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Tue, 3 Sep 2024 20:27:36 +0300 Subject: [PATCH 055/132] Fix EditorConfig linting issues --- modules/local/extract_annotation_statistics_info.nf | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/local/extract_annotation_statistics_info.nf b/modules/local/extract_annotation_statistics_info.nf index 46cc8415..2a40fb79 100644 --- a/modules/local/extract_annotation_statistics_info.nf +++ b/modules/local/extract_annotation_statistics_info.nf @@ -1,6 +1,5 @@ // EXtracting essential annotation statistics information from the output txt files -process EXTRACT_ANNOTATION_STATISTICS_INFO { - +process EXTRACT_ANNOTATION_STATISTICS_INFO { label 'process_single' conda "conda-forge::python=3.9.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? @@ -16,7 +15,7 @@ process EXTRACT_ANNOTATION_STATISTICS_INFO { when: task.ext.when == null || task.ext.when - + script: def prefix = task.ext.prefix ?: meta.id def output_file = "${prefix}.csv" From f94429edbe215abac1cde705f355bdc48f0ed025 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Tue, 3 Sep 2024 20:29:48 +0300 Subject: [PATCH 056/132] Fix EditorConfig linting issues --- conf/modules.config | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 2b982f15..a2c24dfd 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -119,8 +119,7 @@ process { mode: params.publish_dir_mode, saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] - } - + } withName: AGAT_SQSTATBASIC { ext.prefix = { "${meta.id}_sqstats" } } From 093c653623774dc209074385a5066300797b6235 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Tue, 3 Sep 2024 20:37:53 +0300 Subject: [PATCH 057/132] Fix EditorConfig linting issues --- conf/modules.config | 2 +- modules/local/extract_annotation_statistics_info.nf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index a2c24dfd..98055a2a 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -119,7 +119,7 @@ process { mode: params.publish_dir_mode, saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] - } + } withName: AGAT_SQSTATBASIC { ext.prefix = { "${meta.id}_sqstats" } } diff --git a/modules/local/extract_annotation_statistics_info.nf b/modules/local/extract_annotation_statistics_info.nf index 2a40fb79..4ff4f5d6 100644 --- a/modules/local/extract_annotation_statistics_info.nf +++ b/modules/local/extract_annotation_statistics_info.nf @@ -1,5 +1,5 @@ // EXtracting essential annotation statistics information from the output txt files -process EXTRACT_ANNOTATION_STATISTICS_INFO { +process EXTRACT_ANNOTATION_STATISTICS_INFO{ label 'process_single' conda "conda-forge::python=3.9.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? From f2d479a8b2518a2ab14280366b300e206dc70fce Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Tue, 3 Sep 2024 12:44:30 -0500 Subject: [PATCH 058/132] Fix EditorConfig linting issues --- modules/local/extract_annotation_statistics_info.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/extract_annotation_statistics_info.nf b/modules/local/extract_annotation_statistics_info.nf index 4ff4f5d6..5bb90230 100644 --- a/modules/local/extract_annotation_statistics_info.nf +++ b/modules/local/extract_annotation_statistics_info.nf @@ -1,5 +1,5 @@ // EXtracting essential annotation statistics information from the output txt files -process EXTRACT_ANNOTATION_STATISTICS_INFO{ +process EXTRACT_ANNOTATION_STATISTICS_INFO{ label 'process_single' conda "conda-forge::python=3.9.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? From 6f12169b46ad1b9f2fbcc3ce17b49249231c9867 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Tue, 3 Sep 2024 12:49:58 -0500 Subject: [PATCH 059/132] Fix EditorConfig linting issues --- modules/local/extract_annotation_statistics_info.nf | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/local/extract_annotation_statistics_info.nf b/modules/local/extract_annotation_statistics_info.nf index 5bb90230..318c03fe 100644 --- a/modules/local/extract_annotation_statistics_info.nf +++ b/modules/local/extract_annotation_statistics_info.nf @@ -1,5 +1,6 @@ // EXtracting essential annotation statistics information from the output txt files process EXTRACT_ANNOTATION_STATISTICS_INFO{ + tag "${meta.id}" label 'process_single' conda "conda-forge::python=3.9.1" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? From b053f15fe42093d1d2f377d085f2ee1968ef0b47 Mon Sep 17 00:00:00 2001 From: Sandra Babirye <99010085+SandraBabirye@users.noreply.github.com> Date: Wed, 4 Sep 2024 13:56:14 +0300 Subject: [PATCH 060/132] edited the ch_versions for AGAT_SPSTATISTICS --- subworkflows/local/annotation_statistics.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index b4d3b249..94a2cfc3 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -32,7 +32,7 @@ workflow ANNOTATION_STATS { // Other annotation statistics AGAT_SPSTATISTICS(ch_unzipped) - ch_versions = ch_versions.mix ( AGAT_SQSTATBASIC.out.versions.first() ) + ch_versions = ch_versions.mix ( AGAT_SPSTATISTICS.out.versions.first() ) // Parsing the stats_txt files as input channels EXTRACT_ANNOTATION_STATISTICS_INFO( From e0f5a8c23cbe69a1e165c77682686162740c627c Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Tue, 17 Sep 2024 23:04:09 -0500 Subject: [PATCH 061/132] added gffread nf-core module --- modules.json | 5 + modules/nf-core/gffread/environment.yml | 5 + modules/nf-core/gffread/main.nf | 60 ++++ modules/nf-core/gffread/meta.yml | 55 ++++ modules/nf-core/gffread/tests/main.nf.test | 223 ++++++++++++++ .../nf-core/gffread/tests/main.nf.test.snap | 272 ++++++++++++++++++ .../gffread/tests/nextflow-fasta.config | 5 + .../gffread/tests/nextflow-gff3.config | 5 + modules/nf-core/gffread/tests/nextflow.config | 5 + modules/nf-core/gffread/tests/tags.yml | 2 + 10 files changed, 637 insertions(+) create mode 100644 modules/nf-core/gffread/environment.yml create mode 100644 modules/nf-core/gffread/main.nf create mode 100644 modules/nf-core/gffread/meta.yml create mode 100644 modules/nf-core/gffread/tests/main.nf.test create mode 100644 modules/nf-core/gffread/tests/main.nf.test.snap create mode 100644 modules/nf-core/gffread/tests/nextflow-fasta.config create mode 100644 modules/nf-core/gffread/tests/nextflow-gff3.config create mode 100644 modules/nf-core/gffread/tests/nextflow.config create mode 100644 modules/nf-core/gffread/tests/tags.yml diff --git a/modules.json b/modules.json index ee455d45..a0211476 100644 --- a/modules.json +++ b/modules.json @@ -52,6 +52,11 @@ "installed_by": ["modules"], "patch": "modules/nf-core/fastk/fastk/fastk-fastk.diff" }, + "gffread": { + "branch": "master", + "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", + "installed_by": ["modules"] + }, "gnu/sort": { "branch": "master", "git_sha": "88f6e982fb8bd40488d837b3b08a65008e602840", diff --git a/modules/nf-core/gffread/environment.yml b/modules/nf-core/gffread/environment.yml new file mode 100644 index 00000000..ee239841 --- /dev/null +++ b/modules/nf-core/gffread/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::gffread=0.12.7 diff --git a/modules/nf-core/gffread/main.nf b/modules/nf-core/gffread/main.nf new file mode 100644 index 00000000..da55cbab --- /dev/null +++ b/modules/nf-core/gffread/main.nf @@ -0,0 +1,60 @@ +process GFFREAD { + tag "$meta.id" + label 'process_low' + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/gffread:0.12.7--hdcf5f25_4' : + 'biocontainers/gffread:0.12.7--hdcf5f25_4' }" + + input: + tuple val(meta), path(gff) + path fasta + + output: + tuple val(meta), path("*.gtf") , emit: gtf , optional: true + tuple val(meta), path("*.gff3") , emit: gffread_gff , optional: true + tuple val(meta), path("*.fasta"), emit: gffread_fasta , optional: true + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def extension = args.contains("-T") ? 'gtf' : ( ( ['-w', '-x', '-y' ].any { args.contains(it) } ) ? 'fasta' : 'gff3' ) + def fasta_arg = fasta ? "-g $fasta" : '' + def output_name = "${prefix}.${extension}" + def output = extension == "fasta" ? "$output_name" : "-o $output_name" + def args_sorted = args.replaceAll(/(.*)(-[wxy])(.*)/) { all, pre, param, post -> "$pre $post $param" }.trim() + // args_sorted = Move '-w', '-x', and '-y' to the end of the args string as gffread expects the file name after these parameters + if ( "$output_name" in [ "$gff", "$fasta" ] ) error "Input and output names are the same, use \"task.ext.prefix\" to disambiguate!" + """ + gffread \\ + $gff \\ + $fasta_arg \\ + $args_sorted \\ + $output + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gffread: \$(gffread --version 2>&1) + END_VERSIONS + """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def extension = args.contains("-T") ? 'gtf' : ( ( ['-w', '-x', '-y' ].any { args.contains(it) } ) ? 'fasta' : 'gff3' ) + def output_name = "${prefix}.${extension}" + if ( "$output_name" in [ "$gff", "$fasta" ] ) error "Input and output names are the same, use \"task.ext.prefix\" to disambiguate!" + """ + touch $output_name + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + gffread: \$(gffread --version 2>&1) + END_VERSIONS + """ +} diff --git a/modules/nf-core/gffread/meta.yml b/modules/nf-core/gffread/meta.yml new file mode 100644 index 00000000..c0602820 --- /dev/null +++ b/modules/nf-core/gffread/meta.yml @@ -0,0 +1,55 @@ +name: gffread +description: Validate, filter, convert and perform various other operations on GFF files +keywords: + - gff + - conversion + - validation +tools: + - gffread: + description: GFF/GTF utility providing format conversions, region filtering, FASTA sequence extraction and more. + homepage: http://ccb.jhu.edu/software/stringtie/gff.shtml#gffread + documentation: http://ccb.jhu.edu/software/stringtie/gff.shtml#gffread + tool_dev_url: https://github.com/gpertea/gffread + doi: 10.12688/f1000research.23297.1 + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing meta data + e.g. [ id:'test' ] + - gff: + type: file + description: A reference file in either the GFF3, GFF2 or GTF format. + pattern: "*.{gff, gtf}" + - fasta: + type: file + description: A multi-fasta file with the genomic sequences + pattern: "*.{fasta,fa,faa,fas,fsa}" +output: + - meta: + type: map + description: | + Groovy Map containing meta data + e.g. [ id:'test' ] + - gtf: + type: file + description: GTF file resulting from the conversion of the GFF input file if '-T' argument is present + pattern: "*.{gtf}" + - gffread_gff: + type: file + description: GFF3 file resulting from the conversion of the GFF input file if '-T' argument is absent + pattern: "*.gff3" + - gffread_fasta: + type: file + description: Fasta file produced when either of '-w', '-x', '-y' parameters is present + pattern: "*.fasta" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@edmundmiller" +maintainers: + - "@edmundmiller" + - "@gallvp" diff --git a/modules/nf-core/gffread/tests/main.nf.test b/modules/nf-core/gffread/tests/main.nf.test new file mode 100644 index 00000000..4cd13dcd --- /dev/null +++ b/modules/nf-core/gffread/tests/main.nf.test @@ -0,0 +1,223 @@ +nextflow_process { + + name "Test Process GFFREAD" + script "../main.nf" + process "GFFREAD" + + tag "gffread" + tag "modules_nfcore" + tag "modules" + + test("sarscov2-gff3-gtf") { + + config "./nextflow.config" + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = [ + [id: 'test'], + file(params.modules_testdata_base_path + "genomics/sarscov2/genome/genome.gff3", checkIfExists: true) + ] + input[1] = [] + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() }, + { assert process.out.gffread_gff == [] }, + { assert process.out.gffread_fasta == [] } + ) + } + + } + + test("sarscov2-gff3-gtf-stub") { + + options '-stub' + config "./nextflow.config" + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = [ + [id: 'test'], + file(params.modules_testdata_base_path + "genomics/sarscov2/genome/genome.gff3", checkIfExists: true) + ] + input[1] = [] + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() }, + { assert process.out.gffread_gff == [] }, + { assert process.out.gffread_fasta == [] } + ) + } + + } + + test("sarscov2-gff3-gff3") { + + config "./nextflow-gff3.config" + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = [ + [id: 'test'], + file(params.modules_testdata_base_path + "genomics/sarscov2/genome/genome.gff3", checkIfExists: true) + ] + input[1] = [] + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() }, + { assert process.out.gtf == [] }, + { assert process.out.gffread_fasta == [] } + ) + } + + } + + test("sarscov2-gff3-gff3-stub") { + + options '-stub' + config "./nextflow-gff3.config" + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = [ + [id: 'test'], + file(params.modules_testdata_base_path + "genomics/sarscov2/genome/genome.gff3", checkIfExists: true) + ] + input[1] = [] + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() }, + { assert process.out.gtf == [] }, + { assert process.out.gffread_fasta == [] } + ) + } + + } + + test("sarscov2-gff3-fasta") { + + config "./nextflow-fasta.config" + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = [ + [id: 'test'], + file(params.modules_testdata_base_path + "genomics/sarscov2/genome/genome.gff3", checkIfExists: true) + ] + input[1] = file(params.modules_testdata_base_path + "genomics/sarscov2/genome/genome.fasta", checkIfExists: true) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() }, + { assert process.out.gtf == [] }, + { assert process.out.gffread_gff == [] } + ) + } + + } + + test("sarscov2-gff3-fasta-stub") { + + options '-stub' + config "./nextflow-fasta.config" + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = [ + [id: 'test'], + file(params.modules_testdata_base_path + "genomics/sarscov2/genome/genome.gff3", checkIfExists: true) + ] + input[1] = file(params.modules_testdata_base_path + "genomics/sarscov2/genome/genome.fasta", checkIfExists: true) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() }, + { assert process.out.gtf == [] }, + { assert process.out.gffread_gff == [] } + ) + } + + } + + test("sarscov2-gff3-fasta-fail-catch") { + + options '-stub' + config "./nextflow-fasta.config" + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = [ + [id: 'genome'], + file(params.modules_testdata_base_path + "genomics/sarscov2/genome/genome.gff3", checkIfExists: true) + ] + input[1] = file(params.modules_testdata_base_path + "genomics/sarscov2/genome/genome.fasta", checkIfExists: true) + """ + } + } + + then { + assertAll ( + { assert ! process.success }, + { assert process.stdout.toString().contains("Input and output names are the same") } + ) + } + + } + +} diff --git a/modules/nf-core/gffread/tests/main.nf.test.snap b/modules/nf-core/gffread/tests/main.nf.test.snap new file mode 100644 index 00000000..15262320 --- /dev/null +++ b/modules/nf-core/gffread/tests/main.nf.test.snap @@ -0,0 +1,272 @@ +{ + "sarscov2-gff3-gtf": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.gtf:md5,1ea0ae98d3388e0576407dc4a24ef428" + ] + ], + "1": [ + + ], + "2": [ + + ], + "3": [ + "versions.yml:md5,05f671c6c6e530acedad0af0a5948dbd" + ], + "gffread_fasta": [ + + ], + "gffread_gff": [ + + ], + "gtf": [ + [ + { + "id": "test" + }, + "test.gtf:md5,1ea0ae98d3388e0576407dc4a24ef428" + ] + ], + "versions": [ + "versions.yml:md5,05f671c6c6e530acedad0af0a5948dbd" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-04-09T10:48:56.496187" + }, + "sarscov2-gff3-gff3": { + "content": [ + { + "0": [ + + ], + "1": [ + [ + { + "id": "test" + }, + "test.gff3:md5,c4e5da6267c6bee5899a2c204ae1ad91" + ] + ], + "2": [ + + ], + "3": [ + "versions.yml:md5,05f671c6c6e530acedad0af0a5948dbd" + ], + "gffread_fasta": [ + + ], + "gffread_gff": [ + [ + { + "id": "test" + }, + "test.gff3:md5,c4e5da6267c6bee5899a2c204ae1ad91" + ] + ], + "gtf": [ + + ], + "versions": [ + "versions.yml:md5,05f671c6c6e530acedad0af0a5948dbd" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-04-09T10:49:00.892782" + }, + "sarscov2-gff3-gtf-stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.gtf:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + + ], + "2": [ + + ], + "3": [ + "versions.yml:md5,05f671c6c6e530acedad0af0a5948dbd" + ], + "gffread_fasta": [ + + ], + "gffread_gff": [ + + ], + "gtf": [ + [ + { + "id": "test" + }, + "test.gtf:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,05f671c6c6e530acedad0af0a5948dbd" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-04-09T11:11:26.975666" + }, + "sarscov2-gff3-fasta-stub": { + "content": [ + { + "0": [ + + ], + "1": [ + + ], + "2": [ + [ + { + "id": "test" + }, + "test.fasta:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "3": [ + "versions.yml:md5,05f671c6c6e530acedad0af0a5948dbd" + ], + "gffread_fasta": [ + [ + { + "id": "test" + }, + "test.fasta:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "gffread_gff": [ + + ], + "gtf": [ + + ], + "versions": [ + "versions.yml:md5,05f671c6c6e530acedad0af0a5948dbd" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-04-09T11:11:44.34792" + }, + "sarscov2-gff3-gff3-stub": { + "content": [ + { + "0": [ + + ], + "1": [ + [ + { + "id": "test" + }, + "test.gff3:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + + ], + "3": [ + "versions.yml:md5,05f671c6c6e530acedad0af0a5948dbd" + ], + "gffread_fasta": [ + + ], + "gffread_gff": [ + [ + { + "id": "test" + }, + "test.gff3:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "gtf": [ + + ], + "versions": [ + "versions.yml:md5,05f671c6c6e530acedad0af0a5948dbd" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-04-09T11:11:35.221671" + }, + "sarscov2-gff3-fasta": { + "content": [ + { + "0": [ + + ], + "1": [ + + ], + "2": [ + [ + { + "id": "test" + }, + "test.fasta:md5,5f8108fb51739a0588ccf0a251de919a" + ] + ], + "3": [ + "versions.yml:md5,05f671c6c6e530acedad0af0a5948dbd" + ], + "gffread_fasta": [ + [ + { + "id": "test" + }, + "test.fasta:md5,5f8108fb51739a0588ccf0a251de919a" + ] + ], + "gffread_gff": [ + + ], + "gtf": [ + + ], + "versions": [ + "versions.yml:md5,05f671c6c6e530acedad0af0a5948dbd" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-04-09T10:54:02.88143" + } +} \ No newline at end of file diff --git a/modules/nf-core/gffread/tests/nextflow-fasta.config b/modules/nf-core/gffread/tests/nextflow-fasta.config new file mode 100644 index 00000000..ac6cb148 --- /dev/null +++ b/modules/nf-core/gffread/tests/nextflow-fasta.config @@ -0,0 +1,5 @@ +process { + withName: GFFREAD { + ext.args = '-w -S' + } +} diff --git a/modules/nf-core/gffread/tests/nextflow-gff3.config b/modules/nf-core/gffread/tests/nextflow-gff3.config new file mode 100644 index 00000000..afe0830e --- /dev/null +++ b/modules/nf-core/gffread/tests/nextflow-gff3.config @@ -0,0 +1,5 @@ +process { + withName: GFFREAD { + ext.args = '' + } +} diff --git a/modules/nf-core/gffread/tests/nextflow.config b/modules/nf-core/gffread/tests/nextflow.config new file mode 100644 index 00000000..74b25094 --- /dev/null +++ b/modules/nf-core/gffread/tests/nextflow.config @@ -0,0 +1,5 @@ +process { + withName: GFFREAD { + ext.args = '-T' + } +} diff --git a/modules/nf-core/gffread/tests/tags.yml b/modules/nf-core/gffread/tests/tags.yml new file mode 100644 index 00000000..05576065 --- /dev/null +++ b/modules/nf-core/gffread/tests/tags.yml @@ -0,0 +1,2 @@ +gffread: + - modules/nf-core/gffread/** From b339b7a9b5c5cd7a3d7cf2f9ee8e4faf88ee861a Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 18 Sep 2024 07:30:55 +0300 Subject: [PATCH 062/132] added busco to run in protein mode --- subworkflows/local/annotation_statistics.nf | 33 ++++++++++++++++----- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 94a2cfc3..a3e4d01c 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -4,12 +4,15 @@ include { AGAT_SPSTATISTICS } from '../../modules/nf-core/agat/ include { AGAT_SQSTATBASIC } from '../../modules/nf-core/agat/sqstatbasic/main' include { GUNZIP } from '../../modules/nf-core/gunzip/main' include { EXTRACT_ANNOTATION_STATISTICS_INFO } from '../../modules/local/extract_annotation_statistics_info.nf' +include { BUSCO } from '../../modules/nf-core/busco/main' +include { GFFREAD } from '../../modules/nf-core/gffread/main' workflow ANNOTATION_STATS { take: - gff // channel: /path/to/annotation file - + gff // channel: /path/to/annotation file + genome // channel: [ meta, fasta ] + main: ch_versions = Channel.empty() @@ -19,25 +22,39 @@ workflow ANNOTATION_STATS { | map { file -> [ [ 'id': file.baseName ], file ] } | set {ch_gff_tupple} - // Compress the gff files if needed + // Uncompress the gff files if needed if (params.annotation_set.endsWith('.gz')) { - ch_unzipped = GUNZIP(ch_gff_tupple).gunzip + ch_gff_unzipped = GUNZIP(ch_gff_tupple).gunzip } else { - ch_unzipped = ch_gff_tupple + ch_gff_unzipped = ch_gff_tupple } // Basic Annotation summary statistics - AGAT_SQSTATBASIC(ch_unzipped) + AGAT_SQSTATBASIC(ch_gff_unzipped) ch_versions = ch_versions.mix ( AGAT_SQSTATBASIC.out.versions.first() ) // Other annotation statistics - AGAT_SPSTATISTICS(ch_unzipped) + AGAT_SPSTATISTICS(ch_gff_unzipped) ch_versions = ch_versions.mix ( AGAT_SPSTATISTICS.out.versions.first() ) + // Obtaining the protein fasta file from the gff3 + GFFREAD(ch_gff_unzipped, genome) + ch_versions = ch_versions.mix ( GFFREAD.out.versions.first() ) + + // Running Busco in protein mode + BUSCO(GFFREAD.out.gffread_fasta) + ch_versions = ch_versions.mix ( BUSCO.out.versions.first() ) + + BUSCO.out.short_summaries_json + | ifEmpty ( [ [], [] ] ) + | set { ch_busco } + // Parsing the stats_txt files as input channels EXTRACT_ANNOTATION_STATISTICS_INFO( AGAT_SQSTATBASIC.out.stats_txt, - AGAT_SPSTATISTICS.out.stats_txt + AGAT_SPSTATISTICS.out.stats_txt, + ch_busco + ) ch_versions = ch_versions.mix( EXTRACT_ANNOTATION_STATISTICS_INFO.out.versions.first() ) From c3336b2f533a2daf36d03d62f5eb7f72685ffbcb Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 18 Sep 2024 07:37:13 +0300 Subject: [PATCH 063/132] added input channel ch_fasta to subworkflow ANNOTATION_STATS --- workflows/genomenote.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/genomenote.nf b/workflows/genomenote.nf index 41dde883..90c1a6dd 100644 --- a/workflows/genomenote.nf +++ b/workflows/genomenote.nf @@ -155,7 +155,7 @@ workflow GENOMENOTE { // SUBWORKFLOW : Obtain feature statistics from the annotation file : GFF // ch_gff = Channel.fromPath(params.annotation_set) - ANNOTATION_STATS (ch_gff) + ANNOTATION_STATS (ch_gff, ch_fasta) ch_versions = ch_versions.mix ( ANNOTATION_STATS.out.versions ) // From e7e15f695e1768b4f97a4eafb5c39663ffad382a Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 18 Sep 2024 07:43:21 +0300 Subject: [PATCH 064/132] edited the input channels for the BUSCO process --- subworkflows/local/annotation_statistics.nf | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index a3e4d01c..38f219b1 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -12,6 +12,8 @@ workflow ANNOTATION_STATS { take: gff // channel: /path/to/annotation file genome // channel: [ meta, fasta ] + lineage_tax_ids // channel: /path/to/lineage_tax_ids + lineage_db // channel: /path/to/buscoDB main: ch_versions = Channel.empty() @@ -42,7 +44,7 @@ workflow ANNOTATION_STATS { ch_versions = ch_versions.mix ( GFFREAD.out.versions.first() ) // Running Busco in protein mode - BUSCO(GFFREAD.out.gffread_fasta) + BUSCO(GFFREAD.out.gffread_fasta, ch_lineage, lineage_db.ifEmpty([]), []) ch_versions = ch_versions.mix ( BUSCO.out.versions.first() ) BUSCO.out.short_summaries_json From 18f07a84c8ccc961d6350d91701e5917e2fd3525 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 18 Sep 2024 07:55:34 +0300 Subject: [PATCH 065/132] added the protein mode --- subworkflows/local/annotation_statistics.nf | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 38f219b1..06d227f7 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -12,7 +12,6 @@ workflow ANNOTATION_STATS { take: gff // channel: /path/to/annotation file genome // channel: [ meta, fasta ] - lineage_tax_ids // channel: /path/to/lineage_tax_ids lineage_db // channel: /path/to/buscoDB main: @@ -44,7 +43,10 @@ workflow ANNOTATION_STATS { ch_versions = ch_versions.mix ( GFFREAD.out.versions.first() ) // Running Busco in protein mode - BUSCO(GFFREAD.out.gffread_fasta, ch_lineage, lineage_db.ifEmpty([]), []) + Channel.value('proteins') \ + .set { ch_mode } + + BUSCO(GFFREAD.out.gffread_fasta, lineage_db, ch_mode) ch_versions = ch_versions.mix ( BUSCO.out.versions.first() ) BUSCO.out.short_summaries_json From e69d60e5425f335f2ab9445e9d9b18ace727ac51 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 18 Sep 2024 07:56:15 +0300 Subject: [PATCH 066/132] added the lineage_db as input channel for the ANNOTATION_STATS subworkflow --- workflows/genomenote.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/genomenote.nf b/workflows/genomenote.nf index 90c1a6dd..7c138b1c 100644 --- a/workflows/genomenote.nf +++ b/workflows/genomenote.nf @@ -155,7 +155,7 @@ workflow GENOMENOTE { // SUBWORKFLOW : Obtain feature statistics from the annotation file : GFF // ch_gff = Channel.fromPath(params.annotation_set) - ANNOTATION_STATS (ch_gff, ch_fasta) + ANNOTATION_STATS (ch_gff, ch_fasta, ch_lineage_db) ch_versions = ch_versions.mix ( ANNOTATION_STATS.out.versions ) // From ce859c0ea51281968ee00a2063a9f721171f3f60 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 18 Sep 2024 08:00:48 +0300 Subject: [PATCH 067/132] edited the input channels for BUSCO --- subworkflows/local/annotation_statistics.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 06d227f7..75c9d9ea 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -46,7 +46,7 @@ workflow ANNOTATION_STATS { Channel.value('proteins') \ .set { ch_mode } - BUSCO(GFFREAD.out.gffread_fasta, lineage_db, ch_mode) + BUSCO(GFFREAD.out.gffread_fasta, lineage_db, ch_mode, [] ) ch_versions = ch_versions.mix ( BUSCO.out.versions.first() ) BUSCO.out.short_summaries_json From c64153ebfaf0487f80bbabe3268be5934103d171 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 18 Sep 2024 08:06:52 +0300 Subject: [PATCH 068/132] added an input channel for busco stats in the local module --- modules/local/extract_annotation_statistics_info.nf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/local/extract_annotation_statistics_info.nf b/modules/local/extract_annotation_statistics_info.nf index 318c03fe..20388cb3 100644 --- a/modules/local/extract_annotation_statistics_info.nf +++ b/modules/local/extract_annotation_statistics_info.nf @@ -9,6 +9,7 @@ process EXTRACT_ANNOTATION_STATISTICS_INFO{ input: tuple val(meta), path(basic_stats) tuple val(meta2), path(other_stats) + path(busco_stats) output: tuple val (meta), path("*.csv") , emit: csv @@ -25,6 +26,7 @@ process EXTRACT_ANNOTATION_STATISTICS_INFO{ extract_annotation_statistics_info.py \\ $basic_stats \\ $other_stats \\ + $busco_stats \\ $output_file cat <<-END_VERSIONS > versions.yml From 9f6870ed02f81fe94dc3c65383e6392b532a34b7 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 18 Sep 2024 08:28:12 +0300 Subject: [PATCH 069/132] edited input channels for the ANNOTATION_STATS subworkflow --- workflows/genomenote.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/genomenote.nf b/workflows/genomenote.nf index 7c138b1c..805f85e9 100644 --- a/workflows/genomenote.nf +++ b/workflows/genomenote.nf @@ -155,7 +155,7 @@ workflow GENOMENOTE { // SUBWORKFLOW : Obtain feature statistics from the annotation file : GFF // ch_gff = Channel.fromPath(params.annotation_set) - ANNOTATION_STATS (ch_gff, ch_fasta, ch_lineage_db) + ANNOTATION_STATS (ch_gff, ch_unzipped, ch_lineage_db) ch_versions = ch_versions.mix ( ANNOTATION_STATS.out.versions ) // From 1813b2d48625b8360e2ded18054b0301cbdfbfae Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 18 Sep 2024 08:31:58 +0300 Subject: [PATCH 070/132] edited input channels for the ANNOTATION_STATS subworkflow --- workflows/genomenote.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/genomenote.nf b/workflows/genomenote.nf index 805f85e9..57c0a02a 100644 --- a/workflows/genomenote.nf +++ b/workflows/genomenote.nf @@ -155,7 +155,7 @@ workflow GENOMENOTE { // SUBWORKFLOW : Obtain feature statistics from the annotation file : GFF // ch_gff = Channel.fromPath(params.annotation_set) - ANNOTATION_STATS (ch_gff, ch_unzipped, ch_lineage_db) + ANNOTATION_STATS (ch_gff, ch_genome, ch_lineage_db) ch_versions = ch_versions.mix ( ANNOTATION_STATS.out.versions ) // From 0e9fdbcbb44ac817ec86084eacc58c8609d9d093 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 18 Sep 2024 08:34:52 +0300 Subject: [PATCH 071/132] edited input channels for the ANNOTATION_STATS subworkflow --- workflows/genomenote.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/genomenote.nf b/workflows/genomenote.nf index 57c0a02a..805f85e9 100644 --- a/workflows/genomenote.nf +++ b/workflows/genomenote.nf @@ -155,7 +155,7 @@ workflow GENOMENOTE { // SUBWORKFLOW : Obtain feature statistics from the annotation file : GFF // ch_gff = Channel.fromPath(params.annotation_set) - ANNOTATION_STATS (ch_gff, ch_genome, ch_lineage_db) + ANNOTATION_STATS (ch_gff, ch_unzipped, ch_lineage_db) ch_versions = ch_versions.mix ( ANNOTATION_STATS.out.versions ) // From 554f1c54719d3a5a01b754c5afd23c4d054b676e Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 18 Sep 2024 08:45:08 +0300 Subject: [PATCH 072/132] edited the file to extract fasta file path --- subworkflows/local/annotation_statistics.nf | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 75c9d9ea..dd72db1c 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -36,10 +36,13 @@ workflow ANNOTATION_STATS { // Other annotation statistics AGAT_SPSTATISTICS(ch_gff_unzipped) - ch_versions = ch_versions.mix ( AGAT_SPSTATISTICS.out.versions.first() ) + ch_versions = ch_versions.mix ( AGAT_SPSTATISTICS.out.versions.first() ) + + // Extracting the FASTA file path from the genome channel + genome_fasta = genome.map { meta, fasta -> fasta } // Obtaining the protein fasta file from the gff3 - GFFREAD(ch_gff_unzipped, genome) + GFFREAD(ch_gff_unzipped, genome_fasta) ch_versions = ch_versions.mix ( GFFREAD.out.versions.first() ) // Running Busco in protein mode From 6a391175bc1bb29250297dca8263b8d206507fda Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 18 Sep 2024 08:54:54 +0300 Subject: [PATCH 073/132] edited the file to extract fasta file path --- subworkflows/local/annotation_statistics.nf | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index dd72db1c..09cab812 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -38,11 +38,12 @@ workflow ANNOTATION_STATS { AGAT_SPSTATISTICS(ch_gff_unzipped) ch_versions = ch_versions.mix ( AGAT_SPSTATISTICS.out.versions.first() ) - // Extracting the FASTA file path from the genome channel - genome_fasta = genome.map { meta, fasta -> fasta } + genome + | map { meta, fasta -> fasta } + | set { ch_fasta } // Obtaining the protein fasta file from the gff3 - GFFREAD(ch_gff_unzipped, genome_fasta) + GFFREAD(ch_gff_unzipped, ch_fasta) ch_versions = ch_versions.mix ( GFFREAD.out.versions.first() ) // Running Busco in protein mode From 6bad994e5a885be718225731860cf4d1c3855a50 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 18 Sep 2024 01:37:13 -0500 Subject: [PATCH 074/132] edited the input channel for the extract annotation statistics local module --- modules/local/extract_annotation_statistics_info.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/extract_annotation_statistics_info.nf b/modules/local/extract_annotation_statistics_info.nf index 20388cb3..1de4f934 100644 --- a/modules/local/extract_annotation_statistics_info.nf +++ b/modules/local/extract_annotation_statistics_info.nf @@ -9,7 +9,7 @@ process EXTRACT_ANNOTATION_STATISTICS_INFO{ input: tuple val(meta), path(basic_stats) tuple val(meta2), path(other_stats) - path(busco_stats) + tuple val(meta3), path(busco_stats) output: tuple val (meta), path("*.csv") , emit: csv From 7c4c49678b9622ae49efc26442d339d80bfeb55a Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 18 Sep 2024 09:40:59 +0300 Subject: [PATCH 075/132] removed the trailing white space --- modules/local/extract_annotation_statistics_info.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/local/extract_annotation_statistics_info.nf b/modules/local/extract_annotation_statistics_info.nf index 1de4f934..054c93b3 100644 --- a/modules/local/extract_annotation_statistics_info.nf +++ b/modules/local/extract_annotation_statistics_info.nf @@ -9,7 +9,7 @@ process EXTRACT_ANNOTATION_STATISTICS_INFO{ input: tuple val(meta), path(basic_stats) tuple val(meta2), path(other_stats) - tuple val(meta3), path(busco_stats) + tuple val(meta3), path(busco_stats) output: tuple val (meta), path("*.csv") , emit: csv From 7fe58fca4ab29ee5471a75f2f5de537ea45da910 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Mon, 23 Sep 2024 05:00:30 -0500 Subject: [PATCH 076/132] added -y argument to the GFFREAD process --- conf/modules.config | 1 + 1 file changed, 1 insertion(+) diff --git a/conf/modules.config b/conf/modules.config index 98055a2a..81a65aeb 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -135,5 +135,6 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] } + withName: GFFREAD { ext.args = "-y" } } From 21f95b7e340a3475f7db30bc4c3b35a5f02d1eec Mon Sep 17 00:00:00 2001 From: Tyler Chafin Date: Fri, 11 Oct 2024 08:49:08 +0100 Subject: [PATCH 077/132] Update CITATION.cff --- CITATION.cff | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index 969f1a7c..b619d6fe 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -8,8 +8,8 @@ message: >- metadata from this file. type: software authors: - - given-names: Sandra - family-names: Babiyre + - given-names: Sandra Ruth + family-names: Babirye affiliation: Wellcome Sanger Institute orcid: "https://orcid.org/0009-0004-7773-7008" - given-names: Tyler From bc7809fed041abddc0a69bb430a46046d51afe77 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 23 Oct 2024 13:07:37 -0500 Subject: [PATCH 078/132] edited files --- conf/base.config | 5 +++++ conf/modules.config | 7 ++++++- workflows/genomenote.nf | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/conf/base.config b/conf/base.config index d86d5c3e..72a04015 100644 --- a/conf/base.config +++ b/conf/base.config @@ -93,4 +93,9 @@ process { withName: AGAT_SPSTATISTICS { memory = { check_max( 3.GB * task.attempt, 'memory' ) } } + withName: BUSCOPROTEINS { + memory = { check_max( 4.GB * task.attempt, 'memory' ) } + cpus = { log_increase_cpus(2, 2*task.attempt, 1, 2) } + time = { check_max( 2.h * task.attempt, 'time') } + } } diff --git a/conf/modules.config b/conf/modules.config index 81a65aeb..1d103ca9 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -135,6 +135,11 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] } - withName: GFFREAD { ext.args = "-y" } + withName: GFFREAD { + ext.args = "-y" + } + withName: BUSCOPROTEINS { + scratch = true ext.args = { '--mode proteins --tar' } + } } diff --git a/workflows/genomenote.nf b/workflows/genomenote.nf index 805f85e9..1cc6eef1 100644 --- a/workflows/genomenote.nf +++ b/workflows/genomenote.nf @@ -155,7 +155,7 @@ workflow GENOMENOTE { // SUBWORKFLOW : Obtain feature statistics from the annotation file : GFF // ch_gff = Channel.fromPath(params.annotation_set) - ANNOTATION_STATS (ch_gff, ch_unzipped, ch_lineage_db) + ANNOTATION_STATS (ch_gff, ch_fasta, ch_lineage_tax_ids, ch_lineage_db) ch_versions = ch_versions.mix ( ANNOTATION_STATS.out.versions ) // From 6db68598a7a3c35eb4bde89d2d8b7ce9ec5d34cd Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 23 Oct 2024 13:24:55 -0500 Subject: [PATCH 079/132] edited the file to run busco in protein mode --- subworkflows/local/annotation_statistics.nf | 33 +++++++++++++++------ 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 09cab812..1db8aa83 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -1,11 +1,13 @@ // include modules from nf-core -include { AGAT_SPSTATISTICS } from '../../modules/nf-core/agat/spstatistics/main' -include { AGAT_SQSTATBASIC } from '../../modules/nf-core/agat/sqstatbasic/main' -include { GUNZIP } from '../../modules/nf-core/gunzip/main' -include { EXTRACT_ANNOTATION_STATISTICS_INFO } from '../../modules/local/extract_annotation_statistics_info.nf' -include { BUSCO } from '../../modules/nf-core/busco/main' -include { GFFREAD } from '../../modules/nf-core/gffread/main' +include { AGAT_SPSTATISTICS } from '../../modules/nf-core/agat/spstatistics/main' +include { AGAT_SQSTATBASIC } from '../../modules/nf-core/agat/sqstatbasic/main' +include { GUNZIP } from '../../modules/nf-core/gunzip/main' +include { EXTRACT_ANNOTATION_STATISTICS_INFO } from '../../modules/local/extract_annotation_statistics_info.nf' +include { BUSCO as BUSCOPROTEINS } from '../../modules/nf-core/busco/main' +include { NCBIDATASETS_SUMMARYGENOME as SUMMARYGENOME } from '../../modules/local/ncbidatasets/summarygenome' +include { GFFREAD } from '../../modules/nf-core/gffread/main' +include { NCBI_GET_ODB } from '../../modules/local/ncbidatasets/get_odb' workflow ANNOTATION_STATS { @@ -13,6 +15,7 @@ workflow ANNOTATION_STATS { gff // channel: /path/to/annotation file genome // channel: [ meta, fasta ] lineage_db // channel: /path/to/buscoDB + lineage_tax_ids // channel: /path/to/lineage_tax_ids main: ch_versions = Channel.empty() @@ -46,14 +49,26 @@ workflow ANNOTATION_STATS { GFFREAD(ch_gff_unzipped, ch_fasta) ch_versions = ch_versions.mix ( GFFREAD.out.versions.first() ) + // Get ODB lineage value + NCBI_GET_ODB ( SUMMARYGENOME.out.summary, lineage_tax_ids ) + ch_versions = ch_versions.mix ( NCBI_GET_ODB.out.versions.first() ) + + // BUSCO + NCBI_GET_ODB.out.csv + | map { meta, csv -> csv } + | splitCsv() + | map { row -> row[1] } + | set { ch_lineage } + + // Running Busco in protein mode Channel.value('proteins') \ .set { ch_mode } - BUSCO(GFFREAD.out.gffread_fasta, lineage_db, ch_mode, [] ) - ch_versions = ch_versions.mix ( BUSCO.out.versions.first() ) + BUSCOPROTEINS(GFFREAD.out.gffread_fasta, ch_lineage, ch_mode, lineage_db.ifEmpty([]), [] ) + ch_versions = ch_versions.mix ( BUSCOPROTEINS.out.versions.first() ) - BUSCO.out.short_summaries_json + BUSCOPROTEINS.out.short_summaries_json | ifEmpty ( [ [], [] ] ) | set { ch_busco } From 1feb2a682bd390e8a1aa321a977c4a4d2f9f0b43 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 23 Oct 2024 13:57:28 -0500 Subject: [PATCH 080/132] edited python script to include the busco stats file --- bin/extract_annotation_statistics_info.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/bin/extract_annotation_statistics_info.py b/bin/extract_annotation_statistics_info.py index fb3336bd..4a65143b 100755 --- a/bin/extract_annotation_statistics_info.py +++ b/bin/extract_annotation_statistics_info.py @@ -75,8 +75,21 @@ def extract_non_coding_genes(file): return {"NCG": NCG} +# Extract the busco score +def parse_busco_stats(busco_stats_file): + busco_score = None + with open(busco_stats_file, "r") as file: + for line in file: + if line.startswith("results.one_line_summary"): + busco_score = line.strip() # Store the entire summary or parse the desired part + break + return busco_score + + # Function to write the extracted data to a CSV file -def write_to_csv(data, output_file): +def write_to_csv(data, output_file, busco_stats_file): + busco_score = parse_busco_stats(busco_stats_file) + descriptions = { "TRANSC_MRNA": "The number of transcribed mRNAs", "PCG": "The number of protein coding genes", @@ -101,16 +114,20 @@ def write_to_csv(data, output_file): # Write the data for key, value in data.items(): writer.writerow([key, value]) + # Add the BUSCO score as a new line + if busco_score: + writer.writerow(["BUSCO_PROTEIN", busco_score]) # Main function to take input files and output file as arguments def main(): - Description = "Parse contents of the agat_spstatistics and agat_sqstatbasic to extract relevant annotation statistics information." - Epilog = "Example usage: python extract_annotation_statistics_info.py " + Description = "Parse contents of the agat_spstatistics, buscoproteins and agat_sqstatbasic to extract relevant annotation statistics information." + Epilog = "Example usage: python extract_annotation_statistics_info.py " parser = argparse.ArgumentParser(description=Description, epilog=Epilog) parser.add_argument("FILE_1", help="Input txt file with basic_feature_statistics.") parser.add_argument("FILE_2", help="Input txt file with other_feature_statistics.") + parser.add_argument("FILE_3", help="Input file for the busco statistics.") parser.add_argument("FILE_OUT", help="Output file.") parser.add_argument("--version", action="version", version="%(prog)s 1.0") args = parser.parse_args() From ee4e2a95e8585d7cc3df1b4970d55a92c5ef73fe Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 23 Oct 2024 13:58:00 -0500 Subject: [PATCH 081/132] edited files --- lint_log.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 lint_log.txt diff --git a/lint_log.txt b/lint_log.txt new file mode 100644 index 00000000..e69de29b From 21f2b4d65f2f7b794c8340d21eb8cbec9e3974ee Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 23 Oct 2024 14:30:19 -0500 Subject: [PATCH 082/132] edited files --- conf/modules.config | 3 ++- subworkflows/local/annotation_statistics.nf | 13 +++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 1d103ca9..759706dd 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -139,7 +139,8 @@ process { ext.args = "-y" } withName: BUSCOPROTEINS { - scratch = true ext.args = { '--mode proteins --tar' } + scratch = true + ext.args = { '--mode proteins --tar' } } } diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 1db8aa83..533be1ce 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -49,6 +49,10 @@ workflow ANNOTATION_STATS { GFFREAD(ch_gff_unzipped, ch_fasta) ch_versions = ch_versions.mix ( GFFREAD.out.versions.first() ) + // Genome summary statistics + SUMMARYGENOME ( genome ) + ch_versions = ch_versions.mix ( SUMMARYGENOME.out.versions.first() ) + // Get ODB lineage value NCBI_GET_ODB ( SUMMARYGENOME.out.summary, lineage_tax_ids ) ch_versions = ch_versions.mix ( NCBI_GET_ODB.out.versions.first() ) @@ -58,14 +62,11 @@ workflow ANNOTATION_STATS { | map { meta, csv -> csv } | splitCsv() | map { row -> row[1] } - | set { ch_lineage } - + | set { ch_lineage} - // Running Busco in protein mode - Channel.value('proteins') \ - .set { ch_mode } + // Running BUSCO in protein mode - BUSCOPROTEINS(GFFREAD.out.gffread_fasta, ch_lineage, ch_mode, lineage_db.ifEmpty([]), [] ) + BUSCOPROTEINS(GFFREAD.out.gffread_fasta,ch_lineage,lineage_db.ifEmpty([]), [] ) ch_versions = ch_versions.mix ( BUSCOPROTEINS.out.versions.first() ) BUSCOPROTEINS.out.short_summaries_json From 64a39d533d621cf669b2462750106e64464138f5 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 23 Oct 2024 14:31:36 -0500 Subject: [PATCH 083/132] fixed black linting issues --- bin/extract_annotation_statistics_info.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/extract_annotation_statistics_info.py b/bin/extract_annotation_statistics_info.py index 4a65143b..8fa6e277 100755 --- a/bin/extract_annotation_statistics_info.py +++ b/bin/extract_annotation_statistics_info.py @@ -122,12 +122,12 @@ def write_to_csv(data, output_file, busco_stats_file): # Main function to take input files and output file as arguments def main(): Description = "Parse contents of the agat_spstatistics, buscoproteins and agat_sqstatbasic to extract relevant annotation statistics information." - Epilog = "Example usage: python extract_annotation_statistics_info.py " + Epilog = "Example usage: python extract_annotation_statistics_info.py " parser = argparse.ArgumentParser(description=Description, epilog=Epilog) parser.add_argument("FILE_1", help="Input txt file with basic_feature_statistics.") parser.add_argument("FILE_2", help="Input txt file with other_feature_statistics.") - parser.add_argument("FILE_3", help="Input file for the busco statistics.") + # parser.add_argument("FILE_3", help="Input file for the busco statistics.") parser.add_argument("FILE_OUT", help="Output file.") parser.add_argument("--version", action="version", version="%(prog)s 1.0") args = parser.parse_args() From 8e5490cb27287ddf63a5cb29712297131e0d984f Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 23 Oct 2024 14:58:58 -0500 Subject: [PATCH 084/132] added a busco stats file as parameter --- bin/extract_annotation_statistics_info.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/bin/extract_annotation_statistics_info.py b/bin/extract_annotation_statistics_info.py index 8fa6e277..1dff5d3c 100755 --- a/bin/extract_annotation_statistics_info.py +++ b/bin/extract_annotation_statistics_info.py @@ -122,20 +122,20 @@ def write_to_csv(data, output_file, busco_stats_file): # Main function to take input files and output file as arguments def main(): Description = "Parse contents of the agat_spstatistics, buscoproteins and agat_sqstatbasic to extract relevant annotation statistics information." - Epilog = "Example usage: python extract_annotation_statistics_info.py " + Epilog = "Example usage: python extract_annotation_statistics_info.py " parser = argparse.ArgumentParser(description=Description, epilog=Epilog) - parser.add_argument("FILE_1", help="Input txt file with basic_feature_statistics.") - parser.add_argument("FILE_2", help="Input txt file with other_feature_statistics.") - # parser.add_argument("FILE_3", help="Input file for the busco statistics.") - parser.add_argument("FILE_OUT", help="Output file.") + parser.add_argument("basic_stats", help="Input txt file with basic_feature_statistics.") + parser.add_argument("other_stats", help="Input txt file with other_feature_statistics.") + parser.add_argument("busco_stats", help="Input file for the busco statistics.") + parser.add_argument("output", help="Output file.") parser.add_argument("--version", action="version", version="%(prog)s 1.0") args = parser.parse_args() - cds_info = extract_cds_info(args.FILE_2) - non_coding_genes = extract_non_coding_genes(args.FILE_1) + cds_info = extract_cds_info(args.other_stats) + non_coding_genes = extract_non_coding_genes(args.basic_stats) data = {**cds_info, **non_coding_genes} - write_to_csv(data, args.FILE_OUT) + write_to_csv(data,args.output, args.busco_stats) if __name__ == "__main__": From 208e3ab198df83bc5e8206ba9d5ef6fa9c0244ca Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 23 Oct 2024 15:07:39 -0500 Subject: [PATCH 085/132] edited the arguments --- bin/extract_annotation_statistics_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/extract_annotation_statistics_info.py b/bin/extract_annotation_statistics_info.py index 1dff5d3c..de1f0c68 100755 --- a/bin/extract_annotation_statistics_info.py +++ b/bin/extract_annotation_statistics_info.py @@ -87,7 +87,7 @@ def parse_busco_stats(busco_stats_file): # Function to write the extracted data to a CSV file -def write_to_csv(data, output_file, busco_stats_file): +def write_to_csv(data, output, busco_stats_file): busco_score = parse_busco_stats(busco_stats_file) descriptions = { From b060f6ef5e7f54494d73e4d9322324f7a44b9652 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Wed, 23 Oct 2024 15:12:09 -0500 Subject: [PATCH 086/132] fixing black linting issues --- bin/extract_annotation_statistics_info.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bin/extract_annotation_statistics_info.py b/bin/extract_annotation_statistics_info.py index de1f0c68..b63c0d23 100755 --- a/bin/extract_annotation_statistics_info.py +++ b/bin/extract_annotation_statistics_info.py @@ -122,7 +122,9 @@ def write_to_csv(data, output, busco_stats_file): # Main function to take input files and output file as arguments def main(): Description = "Parse contents of the agat_spstatistics, buscoproteins and agat_sqstatbasic to extract relevant annotation statistics information." - Epilog = "Example usage: python extract_annotation_statistics_info.py " + Epilog = ( + "Example usage: python extract_annotation_statistics_info.py " + ) parser = argparse.ArgumentParser(description=Description, epilog=Epilog) parser.add_argument("basic_stats", help="Input txt file with basic_feature_statistics.") @@ -135,7 +137,7 @@ def main(): cds_info = extract_cds_info(args.other_stats) non_coding_genes = extract_non_coding_genes(args.basic_stats) data = {**cds_info, **non_coding_genes} - write_to_csv(data,args.output, args.busco_stats) + write_to_csv(data, args.output, args.busco_stats) if __name__ == "__main__": From 80301fe212280e40b344f9fd65300ec4834e1c08 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Fri, 25 Oct 2024 01:57:23 -0500 Subject: [PATCH 087/132] edited the python script to extract busco stats --- bin/extract_annotation_statistics_info.py | 36 +++++++++++++++-------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/bin/extract_annotation_statistics_info.py b/bin/extract_annotation_statistics_info.py index b63c0d23..b3ccd5cb 100755 --- a/bin/extract_annotation_statistics_info.py +++ b/bin/extract_annotation_statistics_info.py @@ -75,20 +75,30 @@ def extract_non_coding_genes(file): return {"NCG": NCG} -# Extract the busco score -def parse_busco_stats(busco_stats_file): - busco_score = None +# Extract BUSCO Scores +def extract_busco_results(busco_stats_file): + busco_results = [] + with open(busco_stats_file, "r") as file: + capture_results = False + for line in file: - if line.startswith("results.one_line_summary"): - busco_score = line.strip() # Store the entire summary or parse the desired part - break - return busco_score + line = line.strip() + if line.startswith("***** Results: *****"): + capture_results = True + continue + + if capture_results: + if line.startswith("Assembly Statistics:"): + break # Stop capturing when reaching the assembly statistics + busco_results.append(line) + + return busco_results # Function to write the extracted data to a CSV file -def write_to_csv(data, output, busco_stats_file): - busco_score = parse_busco_stats(busco_stats_file) +def write_to_csv(data, output_file, busco_stats_file): + busco_results = extract_busco_results(busco_stats_file) descriptions = { "TRANSC_MRNA": "The number of transcribed mRNAs", @@ -99,6 +109,7 @@ def write_to_csv(data, output, busco_stats_file): "CDS_LENGTH": "The average length of coding sequence", "EXON_SIZE": "The average length of a coding exon", "INTRON_SIZE": "The average length of coding intron size", + "BUSCO_PROTEIN_SCORES": "BUSCO results summary from the analysis", } with open(output_file, "w", newline="") as csvfile: @@ -114,9 +125,10 @@ def write_to_csv(data, output, busco_stats_file): # Write the data for key, value in data.items(): writer.writerow([key, value]) - # Add the BUSCO score as a new line - if busco_score: - writer.writerow(["BUSCO_PROTEIN", busco_score]) + + # Add the BUSCO results as new lines + for result in busco_results: + writer.writerow([result]) # Main function to take input files and output file as arguments From f4d28c7e75952ef90ecbb1e4d98f163ee32a1bc8 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Fri, 25 Oct 2024 01:58:13 -0500 Subject: [PATCH 088/132] edited the input channels for buscoproteins process --- subworkflows/local/annotation_statistics.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 533be1ce..3698c1b4 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -69,9 +69,9 @@ workflow ANNOTATION_STATS { BUSCOPROTEINS(GFFREAD.out.gffread_fasta,ch_lineage,lineage_db.ifEmpty([]), [] ) ch_versions = ch_versions.mix ( BUSCOPROTEINS.out.versions.first() ) - BUSCOPROTEINS.out.short_summaries_json + BUSCOPROTEINS.out.short_summaries_txt | ifEmpty ( [ [], [] ] ) - | set { ch_busco } + | set { ch_busco} // Parsing the stats_txt files as input channels EXTRACT_ANNOTATION_STATISTICS_INFO( From d95f4b52a3805fb79a272569af1a0372e5eaf06c Mon Sep 17 00:00:00 2001 From: Sandra Babirye <99010085+SandraBabirye@users.noreply.github.com> Date: Fri, 25 Oct 2024 13:08:13 +0300 Subject: [PATCH 089/132] Changed the order of inputs for ANNOTATION_STATS --- subworkflows/local/annotation_statistics.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 3698c1b4..23a6814a 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -14,8 +14,8 @@ workflow ANNOTATION_STATS { take: gff // channel: /path/to/annotation file genome // channel: [ meta, fasta ] - lineage_db // channel: /path/to/buscoDB lineage_tax_ids // channel: /path/to/lineage_tax_ids + lineage_db // channel: /path/to/buscoDB main: ch_versions = Channel.empty() From 164b74d694c438f74385d9deeab96f7284bb7299 Mon Sep 17 00:00:00 2001 From: Sandra Babirye <99010085+SandraBabirye@users.noreply.github.com> Date: Fri, 25 Oct 2024 13:24:23 +0300 Subject: [PATCH 090/132] edited the busco output file channel to json --- subworkflows/local/annotation_statistics.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 23a6814a..9520f487 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -69,7 +69,7 @@ workflow ANNOTATION_STATS { BUSCOPROTEINS(GFFREAD.out.gffread_fasta,ch_lineage,lineage_db.ifEmpty([]), [] ) ch_versions = ch_versions.mix ( BUSCOPROTEINS.out.versions.first() ) - BUSCOPROTEINS.out.short_summaries_txt + BUSCOPROTEINS.out.short_summaries_json | ifEmpty ( [ [], [] ] ) | set { ch_busco} From 99a6e2650320a5e36b8269e5bbb87d64917ff0cf Mon Sep 17 00:00:00 2001 From: Sandra Babirye <99010085+SandraBabirye@users.noreply.github.com> Date: Fri, 25 Oct 2024 13:36:25 +0300 Subject: [PATCH 091/132] edited the python script to extract the one_line_summary information from BUSCO json file --- bin/extract_annotation_statistics_info.py | 52 ++++++++++++----------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/bin/extract_annotation_statistics_info.py b/bin/extract_annotation_statistics_info.py index b3ccd5cb..0e101598 100755 --- a/bin/extract_annotation_statistics_info.py +++ b/bin/extract_annotation_statistics_info.py @@ -3,6 +3,7 @@ import csv import sys import argparse +import json # Extract CDS information from mrna and transcript sections @@ -54,7 +55,13 @@ def extract_cds_info(file): # Function to extract the number of non-coding genes from the second file def extract_non_coding_genes(file): - non_coding_genes = {"lnc_rna": 0, "ncrna": 0, "pseudogene": 0, "snorna": 0, "snrna": 0, "rrna": 0, "trna": 0} + non_coding_genes = {"lnc_rna": 0, + "ncrna": 0, + "pseudogene": 0, + "snorna": 0, + "snrna": 0, + "rrna": 0, + "trna": 0 } with open(file, "r") as f: for line in f: @@ -75,25 +82,22 @@ def extract_non_coding_genes(file): return {"NCG": NCG} -# Extract BUSCO Scores +# Extract the one_line_summary from a BUSCO JSON file def extract_busco_results(busco_stats_file): - busco_results = [] - - with open(busco_stats_file, "r") as file: - capture_results = False - - for line in file: - line = line.strip() - if line.startswith("***** Results: *****"): - capture_results = True - continue - - if capture_results: - if line.startswith("Assembly Statistics:"): - break # Stop capturing when reaching the assembly statistics - busco_results.append(line) - - return busco_results + try: + with open(busco_stats_file, "r") as file: + busco_data = json.load(file) + # Extract the one_line_summary from the results section + one_line_summary = busco_data.get("results", {}).get("one_line_summary") + if one_line_summary: + # Use regex to extract everything after the first colon + match = re.search(r':\s*"(.*)"', one_line_summary) + if match: + one_line_summary = match.group(1) # Get text after the colon + return {"BUSCO_PROTEIN_SCORES": one_line_summary} if one_line_summary else {} + except (json.JSONDecodeError, FileNotFoundError) as e: + print(f"Error loading BUSCO JSON file: {e}") + return {} # Function to write the extracted data to a CSV file @@ -109,7 +113,7 @@ def write_to_csv(data, output_file, busco_stats_file): "CDS_LENGTH": "The average length of coding sequence", "EXON_SIZE": "The average length of a coding exon", "INTRON_SIZE": "The average length of coding intron size", - "BUSCO_PROTEIN_SCORES": "BUSCO results summary from the analysis", + "BUSCO_PROTEIN_SCORES": "BUSCO results summary from running BUSCO in protein mode", } with open(output_file, "w", newline="") as csvfile: @@ -126,9 +130,9 @@ def write_to_csv(data, output_file, busco_stats_file): for key, value in data.items(): writer.writerow([key, value]) - # Add the BUSCO results as new lines - for result in busco_results: - writer.writerow([result]) + # Add the BUSCO results summary + for key, value in busco_results.items(): + writer.writerow([key, value]) # Main function to take input files and output file as arguments @@ -141,7 +145,7 @@ def main(): parser = argparse.ArgumentParser(description=Description, epilog=Epilog) parser.add_argument("basic_stats", help="Input txt file with basic_feature_statistics.") parser.add_argument("other_stats", help="Input txt file with other_feature_statistics.") - parser.add_argument("busco_stats", help="Input file for the busco statistics.") + parser.add_argument("busco_stats", help="Input JSON file for the BUSCO statistics.") parser.add_argument("output", help="Output file.") parser.add_argument("--version", action="version", version="%(prog)s 1.0") args = parser.parse_args() From dfdb0cf4179bfff8904f3bb297553100ada6d1a4 Mon Sep 17 00:00:00 2001 From: Sandra Babirye <99010085+SandraBabirye@users.noreply.github.com> Date: Fri, 25 Oct 2024 13:46:42 +0300 Subject: [PATCH 092/132] Updated annotation_statistics.nf file --- subworkflows/local/annotation_statistics.nf | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 9520f487..0912fea6 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -65,19 +65,14 @@ workflow ANNOTATION_STATS { | set { ch_lineage} // Running BUSCO in protein mode - BUSCOPROTEINS(GFFREAD.out.gffread_fasta,ch_lineage,lineage_db.ifEmpty([]), [] ) ch_versions = ch_versions.mix ( BUSCOPROTEINS.out.versions.first() ) - BUSCOPROTEINS.out.short_summaries_json - | ifEmpty ( [ [], [] ] ) - | set { ch_busco} - // Parsing the stats_txt files as input channels EXTRACT_ANNOTATION_STATISTICS_INFO( AGAT_SQSTATBASIC.out.stats_txt, AGAT_SPSTATISTICS.out.stats_txt, - ch_busco + BUSCOPROTEINS.out.short_summaries_json ) From fbc3deb95bb92e698597cb8fe31230f359ad0b0a Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Fri, 25 Oct 2024 10:07:35 -0500 Subject: [PATCH 093/132] fixing black issues --- bin/extract_annotation_statistics_info.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/bin/extract_annotation_statistics_info.py b/bin/extract_annotation_statistics_info.py index 0e101598..bd777941 100755 --- a/bin/extract_annotation_statistics_info.py +++ b/bin/extract_annotation_statistics_info.py @@ -55,13 +55,7 @@ def extract_cds_info(file): # Function to extract the number of non-coding genes from the second file def extract_non_coding_genes(file): - non_coding_genes = {"lnc_rna": 0, - "ncrna": 0, - "pseudogene": 0, - "snorna": 0, - "snrna": 0, - "rrna": 0, - "trna": 0 } + non_coding_genes = {"lnc_rna": 0, "ncrna": 0, "pseudogene": 0, "snorna": 0, "snrna": 0, "rrna": 0, "trna": 0} with open(file, "r") as f: for line in f: From af3a412555a61601f3ecbafd9dee891622fa720d Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Fri, 25 Oct 2024 10:10:52 -0500 Subject: [PATCH 094/132] fixing linting issues --- .github/workflows/linting.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index e86c6a9f..0c05417c 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/setup-node@v3 - name: Install editorconfig-checker - run: npm install -g editorconfig-checker + run: npm install -g editorconfig-checker@3.0.2 - name: Run ECLint check run: editorconfig-checker -exclude README.md $(find .* -type f | grep -v '.git\|.py\|.md\|cff\|json\|yml\|yaml\|html\|css\|work\|.nextflow\|build\|nf_core.egg-info\|log.txt\|Makefile') From 7acb7b89d4c4ab0e9b4c098a4e8026e532babc3f Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Fri, 25 Oct 2024 10:25:55 -0500 Subject: [PATCH 095/132] remove trailing whitespace --- conf/base.config | 8 ++++---- conf/modules.config | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/conf/base.config b/conf/base.config index 72a04015..e32c2740 100644 --- a/conf/base.config +++ b/conf/base.config @@ -93,9 +93,9 @@ process { withName: AGAT_SPSTATISTICS { memory = { check_max( 3.GB * task.attempt, 'memory' ) } } - withName: BUSCOPROTEINS { - memory = { check_max( 4.GB * task.attempt, 'memory' ) } - cpus = { log_increase_cpus(2, 2*task.attempt, 1, 2) } - time = { check_max( 2.h * task.attempt, 'time') } + withName: BUSCOPROTEINS { + memory = { check_max( 4.GB * task.attempt, 'memory' ) } + cpus = { log_increase_cpus(2, 2*task.attempt, 1, 2) } + time = { check_max( 2.h * task.attempt, 'time') } } } diff --git a/conf/modules.config b/conf/modules.config index 759706dd..4918cd65 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -135,12 +135,12 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] } - withName: GFFREAD { - ext.args = "-y" + withName: GFFREAD { + ext.args = "-y" } - withName: BUSCOPROTEINS { - scratch = true - ext.args = { '--mode proteins --tar' } + withName: BUSCOPROTEINS { + scratch = true + ext.args = { '--mode proteins --tar' } } } From 5ad88dd8b5c71e88865066064ae255dc2d4952ec Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Fri, 25 Oct 2024 10:36:00 -0500 Subject: [PATCH 096/132] removed the left padding space --- conf/base.config | 2 +- conf/modules.config | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/conf/base.config b/conf/base.config index e32c2740..747401e7 100644 --- a/conf/base.config +++ b/conf/base.config @@ -97,5 +97,5 @@ process { memory = { check_max( 4.GB * task.attempt, 'memory' ) } cpus = { log_increase_cpus(2, 2*task.attempt, 1, 2) } time = { check_max( 2.h * task.attempt, 'time') } - } + } } diff --git a/conf/modules.config b/conf/modules.config index 4918cd65..05096cf2 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -135,12 +135,12 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] } - withName: GFFREAD { + withName: GFFREAD { ext.args = "-y" - } + } withName: BUSCOPROTEINS { scratch = true - ext.args = { '--mode proteins --tar' } - } + ext.args = { '--mode proteins --tar' + } } From cf1e9d1a7643da280b691a369a070a2c7a2f3978 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Fri, 25 Oct 2024 10:42:42 -0500 Subject: [PATCH 097/132] removed the left padding space --- conf/modules.config | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 05096cf2..90dc2234 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -135,12 +135,12 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] } - withName: GFFREAD { - ext.args = "-y" + withName: GFFREAD { + ext.args = "-y" } - withName: BUSCOPROTEINS { - scratch = true - ext.args = { '--mode proteins --tar' + withName: BUSCOPROTEINS { + scratch = true + ext.args = { '--mode proteins --tar' } } From 067833cd1d5673b319d9a8e79740ebc979996560 Mon Sep 17 00:00:00 2001 From: SandraBabirye Date: Fri, 25 Oct 2024 10:49:05 -0500 Subject: [PATCH 098/132] updated modules.config --- conf/modules.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/modules.config b/conf/modules.config index 90dc2234..2824a793 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -140,7 +140,7 @@ process { } withName: BUSCOPROTEINS { scratch = true - ext.args = { '--mode proteins --tar' + ext.args = { '--mode proteins --tar'} } } From 7a0887476d2f41fbd1625331e1f1db1f525fb9f8 Mon Sep 17 00:00:00 2001 From: Bethan Yates Date: Wed, 13 Nov 2024 17:53:48 +0000 Subject: [PATCH 099/132] Added annotation statistics to the full parameter list and genomenote document when assembly annotation has been provided as input --- assets/genome_note_template.docx | Bin 369873 -> 369977 bytes bin/combine_statistics_data.py | 18 ++++++-- bin/extract_annotation_statistics_info.py | 4 +- .../local/combine_statistics_and_metadata.nf | 8 +++- subworkflows/local/annotation_statistics.nf | 13 +++--- subworkflows/local/combine_note_data.nf | 5 ++- workflows/genomenote.nf | 39 +++++++++--------- 7 files changed, 52 insertions(+), 35 deletions(-) diff --git a/assets/genome_note_template.docx b/assets/genome_note_template.docx index 15b1f94c58af08c7aa35be78e8051eda7f9a2c6e..e40657e3986e3964d63459cf567cfa47def45d06 100644 GIT binary patch delta 112847 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

!BNakbUw-JX#S>(h#b8inPWM`q!agR(%VmtX7 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

bL_xMmM>kCd8 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 z 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%0DT|Gn@3rfO?zYo~U0dwY6jy1(g!Uyooy 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 diff --git a/bin/combine_statistics_data.py b/bin/combine_statistics_data.py index 2e48c1dc..08ae5849 100755 --- a/bin/combine_statistics_data.py +++ b/bin/combine_statistics_data.py @@ -8,7 +8,8 @@ files = [ ("CONSISTENT", "in_consistent"), - ("STATISITCS", "in_statistics"), + ("GENOME_STATISITCS", "in_genome_statistics"), + ("ANNOTATION_STATISITCS", "in_annotation_statistics"), ] @@ -19,7 +20,13 @@ def parse_args(args=None): parser = argparse.ArgumentParser(description=Description, epilog=Epilog) parser.add_argument("--in_consistent", help="Input consistent params file.", required=True) parser.add_argument("--in_inconsistent", help="Input consistent params file.", required=True) - parser.add_argument("--in_statistics", help="Input parsed genome statistics params file.", required=True) + parser.add_argument("--in_genome_statistics", help="Input parsed genome statistics params file.", required=True) + parser.add_argument( + "--in_annotation_statistics", + help="Input parsed annotation statistics params file.", + required=False, + default=None, + ) parser.add_argument("--out_consistent", help="Output file.", required=True) parser.add_argument("--out_inconsistent", help="Output file.", required=True) parser.add_argument("--version", action="version", version="%(prog)s 1.0") @@ -36,7 +43,7 @@ def process_file(file_in, file_type, params, param_sets): reader = csv.reader(infile) for row in reader: - if row[0] == "#paramName": + if row[0].startswith("#"): continue key = row.pop(0) @@ -95,7 +102,10 @@ def main(args=None): params_inconsistent = {} for file in files: - (params, param_sets) = process_file(getattr(args, file[1]), file[0], params, param_sets) + if file[0] == "ANNOTATION_STATISITCS" and args.in_annotation_statistics == None: + continue + else: + (params, param_sets) = process_file(getattr(args, file[1]), file[0], params, param_sets) for key in params.keys(): value_set = {v for v in params[key]} diff --git a/bin/extract_annotation_statistics_info.py b/bin/extract_annotation_statistics_info.py index bd777941..6fa9edc7 100755 --- a/bin/extract_annotation_statistics_info.py +++ b/bin/extract_annotation_statistics_info.py @@ -55,7 +55,7 @@ def extract_cds_info(file): # Function to extract the number of non-coding genes from the second file def extract_non_coding_genes(file): - non_coding_genes = {"lnc_rna": 0, "ncrna": 0, "pseudogene": 0, "snorna": 0, "snrna": 0, "rrna": 0, "trna": 0} + non_coding_genes = {"ncrna_gene": 0} with open(file, "r") as f: for line in f: @@ -118,7 +118,7 @@ def write_to_csv(data, output_file, busco_stats_file): csvfile.write(f"# {key}: {description}\n") # Write the Variable and Value columns header - writer.writerow(["Variable", "Value"]) + writer.writerow(["#paramName", "paramValue"]) # Write the data for key, value in data.items(): diff --git a/modules/local/combine_statistics_and_metadata.nf b/modules/local/combine_statistics_and_metadata.nf index 05b03ace..907fe43c 100644 --- a/modules/local/combine_statistics_and_metadata.nf +++ b/modules/local/combine_statistics_and_metadata.nf @@ -10,7 +10,8 @@ process COMBINE_STATISTICS_AND_METADATA { input: tuple val(meta), path(consistent_params) tuple val(meta2), path(inconsistent_params) - tuple val(meta3), path(statistics_params) + tuple val(meta3), path(genome_statistics_params) + tuple val(meta4), path(annotation_statistics_params) output: tuple val (meta), path("${meta.id}_genome_note_consistent.csv") , emit: consistent @@ -22,14 +23,17 @@ process COMBINE_STATISTICS_AND_METADATA { script: def prefix = task.ext.prefix ?: meta.id + def annotation = annotation_statistics_params ? "--in_annotation_statistics $annotation_statistics_params" : '' """ + echo combine_statistics_data.py \\ --in_consistent $consistent_params \\ --in_inconsistent $inconsistent_params \\ - --in_statistics $statistics_params \\ + --in_genome_statistics $genome_statistics_params \\ --out_consistent ${prefix}_genome_note_consistent.csv \\ --out_inconsistent ${prefix}_genome_note_inconsistent.csv \\ + $annotation \\ cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index b1626345..4b596a5c 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -9,7 +9,7 @@ include { NCBIDATASETS_SUMMARYGENOME as SUMMARYGENOME } from '../../modules/lo include { GFFREAD } from '../../modules/nf-core/gffread/main' include { NCBI_GET_ODB } from '../../modules/local/ncbidatasets/get_odb' -workflow ANNOTATION_STATS { +workflow ANNOTATION_STATISTICS { take: gff // channel: /path/to/annotation file @@ -20,15 +20,17 @@ workflow ANNOTATION_STATS { main: ch_versions = Channel.empty() - // Map the GFF channel to create a tuple with metadata and the file gff - | map { file -> [ [ 'id': file.baseName ], file ] } - | set {ch_gff_tupple} + | map { file -> + [ [ 'id': params.assembly + '_annotation', 'ext': "gff" ], file ] + } + | set { ch_gff_tupple } // Uncompress the gff files if needed if (params.annotation_set.endsWith('.gz')) { ch_gff_unzipped = GUNZIP(ch_gff_tupple).gunzip + ch_versions = ch_versions.mix ( GUNZIP.out.versions.first() ) } else { ch_gff_unzipped = ch_gff_tupple } @@ -73,13 +75,12 @@ workflow ANNOTATION_STATS { AGAT_SQSTATBASIC.out.stats_txt, AGAT_SPSTATISTICS.out.stats_txt, BUSCOPROTEINS.out.short_summaries_json - ) ch_versions = ch_versions.mix( EXTRACT_ANNOTATION_STATISTICS_INFO.out.versions.first() ) emit: - stats = EXTRACT_ANNOTATION_STATISTICS_INFO.out.csv // channel: [ csv ] + summary = EXTRACT_ANNOTATION_STATISTICS_INFO.out.csv // channel: [ csv ] versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/combine_note_data.nf b/subworkflows/local/combine_note_data.nf index b9a34611..b6e405c1 100644 --- a/subworkflows/local/combine_note_data.nf +++ b/subworkflows/local/combine_note_data.nf @@ -13,6 +13,7 @@ workflow COMBINE_NOTE_DATA { ch_params_consistent // channel: /path/to/csv/file/consistent_parameters from GENOME_METADATA subworkflow ch_params_inconsistent // channel: /path/to/csv/file/consistent_parameters from GENOME_METADATA subworkflow ch_summary // channel: /path/to/csv/summary/file from GENOME_STATISTICS subworkflow + ch_annotation_summary // channel: /path/to/csv/summary/file from ANNOTATION_STATISTICS subworkflow ch_higlass // channel: /path/to/csv/higlass_link from CONTACT_MAPS subworkflow ch_note_template // channel: /path/to/genome_note_doc_template @@ -30,11 +31,11 @@ workflow COMBINE_NOTE_DATA { } | set { ch_summary_meta } + PARSE_METADATA(ch_summary_meta) ch_versions = ch_versions.mix( PARSE_METADATA.out.versions.first() ) - - COMBINE_STATISTICS_AND_METADATA(ch_params_consistent, ch_params_inconsistent, PARSE_METADATA.out.file_path) + COMBINE_STATISTICS_AND_METADATA(ch_params_consistent, ch_params_inconsistent, PARSE_METADATA.out.file_path, ch_annotation_summary) ch_versions = ch_versions.mix( COMBINE_STATISTICS_AND_METADATA.out.versions.first() ) ch_higlass diff --git a/workflows/genomenote.nf b/workflows/genomenote.nf index 4b75db39..7af41c21 100644 --- a/workflows/genomenote.nf +++ b/workflows/genomenote.nf @@ -21,7 +21,7 @@ if (params.fasta) { ch_fasta = Channel.fromPath(params.fasta) } else { exit if (params.binsize) { ch_bin = Channel.of(params.binsize) } else { exit 1, 'Bin size for cooler/cload not specified!' } if (params.kmer_size) { ch_kmer = Channel.of(params.kmer_size) } else { exit 1, 'Kmer library size for fastk not specified' } -if (params.lineage_tax_ids) { ch_lineage_tax_ids = Channel.fromPath(params.lineage_tax_ids) } else { exit 1, 'Mapping BUSCO lineage <-> taxon_ids not specified' } +if (params.lineage_tax_ids) { ch_lineage_tax_ids = Channel.fromPath(params.lineage_tax_ids) } else { exit 1, 'Mapping BUSCO lineage equivalent taxon_ids not specified' } // Check optional parameters if (params.lineage_db) { ch_lineage_db = Channel.fromPath(params.lineage_db) } else { ch_lineage_db = Channel.empty() } @@ -29,7 +29,8 @@ if (params.note_template) { ch_note_template = Channel.fromPath(params.note_temp if (params.cool_order) { ch_cool_order = Channel.fromPath(params.cool_order) } else { ch_cool_order = Channel.empty() } if (params.biosample_hic) metadata_inputs.add(params.biosample_hic) else metadata_inputs.add(null) if (params.biosample_rna) metadata_inputs.add(params.biosample_rna) else metadata_inputs.add(null) -if (params.annotation_set) { ch_gff = Channel.fromPath(params.annotation_set) } else { ch_gff = Channel.empty() } +if (params.annotation_set) { ch_gff = Channel.fromPath(params.annotation_set) } else { ch_gff = Channel.empty()} + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -53,12 +54,12 @@ ch_multiqc_custom_methods_description = params.multiqc_methods_description ? fil // // SUBWORKFLOW: Consisting of a mix of local and nf-core/modules // -include { INPUT_CHECK } from '../subworkflows/local/input_check' -include { GENOME_METADATA } from '../subworkflows/local/genome_metadata' -include { CONTACT_MAPS } from '../subworkflows/local/contact_maps' -include { GENOME_STATISTICS } from '../subworkflows/local/genome_statistics' -include { COMBINE_NOTE_DATA } from '../subworkflows/local/combine_note_data' -include { ANNOTATION_STATS } from '../subworkflows/local/annotation_statistics' +include { INPUT_CHECK } from '../subworkflows/local/input_check' +include { GENOME_METADATA } from '../subworkflows/local/genome_metadata' +include { CONTACT_MAPS } from '../subworkflows/local/contact_maps' +include { GENOME_STATISTICS } from '../subworkflows/local/genome_statistics' +include { COMBINE_NOTE_DATA } from '../subworkflows/local/combine_note_data' +include { ANNOTATION_STATISTICS } from '../subworkflows/local/annotation_statistics' /* @@ -87,7 +88,7 @@ def multiqc_report = [] workflow GENOMENOTE { ch_versions = Channel.empty() - + ch_annotation_stats = Channel.empty() // // SUBWORKFLOW: Read in samplesheet, validate and stage input files // @@ -152,25 +153,25 @@ workflow GENOMENOTE { ch_versions = ch_versions.mix ( CONTACT_MAPS.out.versions ) // - // SUBWORKFLOW: Combine data from previous steps to create formatted genome note + // SUBWORKFLOW : Obtain feature statistics from the annotation file : GFF // + if ( params.annotation_set ) { + ANNOTATION_STATISTICS (ch_gff, ch_fasta, ch_lineage_tax_ids, ch_lineage_db) + ch_versions = ch_versions.mix ( ANNOTATION_STATISTICS.out.versions ) + ch_annotation_stats = ch_annotation_stats.mix (ANNOTATION_STATISTICS.out.summary) + } - COMBINE_NOTE_DATA (GENOME_METADATA.out.consistent, GENOME_METADATA.out.inconsistent, GENOME_STATISTICS.out.summary, CONTACT_MAPS.out.link, ch_note_template) - ch_versions = ch_versions.mix ( COMBINE_NOTE_DATA.out.versions ) - // - // SUBWORKFLOW : Obtain feature statistics from the annotation file : GFF + // SUBWORKFLOW: Combine data from previous steps to create formatted genome note // - ch_gff = Channel.fromPath(params.annotation_set) - ANNOTATION_STATS (ch_gff, ch_fasta, ch_lineage_tax_ids, ch_lineage_db) - ch_versions = ch_versions.mix ( ANNOTATION_STATS.out.versions ) - + COMBINE_NOTE_DATA (GENOME_METADATA.out.consistent, GENOME_METADATA.out.inconsistent, GENOME_STATISTICS.out.summary, ch_annotation_stats.ifEmpty([[],[]]), CONTACT_MAPS.out.link, ch_note_template) + ch_versions = ch_versions.mix ( COMBINE_NOTE_DATA.out.versions ) + // // MODULE: Combine different versions.yml // CUSTOM_DUMPSOFTWAREVERSIONS ( ch_versions.unique().collectFile(name: 'collated_versions.yml') ) - // // MODULE: MultiQC // From 37b9838033e18e5ce3f375521c18ed7cded10bbd Mon Sep 17 00:00:00 2001 From: Bethan Yates Date: Wed, 13 Nov 2024 17:58:43 +0000 Subject: [PATCH 100/132] typo --- modules/local/combine_statistics_and_metadata.nf | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/local/combine_statistics_and_metadata.nf b/modules/local/combine_statistics_and_metadata.nf index 907fe43c..be31568e 100644 --- a/modules/local/combine_statistics_and_metadata.nf +++ b/modules/local/combine_statistics_and_metadata.nf @@ -26,7 +26,6 @@ process COMBINE_STATISTICS_AND_METADATA { def annotation = annotation_statistics_params ? "--in_annotation_statistics $annotation_statistics_params" : '' """ - echo combine_statistics_data.py \\ --in_consistent $consistent_params \\ --in_inconsistent $inconsistent_params \\ From 70a80b81f6615611abb43087a76a8c1a2b57c7ea Mon Sep 17 00:00:00 2001 From: Bethan Yates Date: Thu, 14 Nov 2024 11:51:02 +0000 Subject: [PATCH 101/132] corrected some of the statistics being being returned, we should be using mrna rather than cds/transcript --- bin/extract_annotation_statistics_info.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/extract_annotation_statistics_info.py b/bin/extract_annotation_statistics_info.py index 6fa9edc7..a4f2b964 100755 --- a/bin/extract_annotation_statistics_info.py +++ b/bin/extract_annotation_statistics_info.py @@ -13,8 +13,8 @@ def extract_cds_info(file): "TRANSC_MRNA": re.compile(r"Number of mrna\s+(\d+)"), "PCG": re.compile(r"Number of gene\s+(\d+)"), "CDS_PER_GENE": re.compile(r"mean mrnas per gene\s+([\d.]+)"), - "EXONS_PER_TRANSC": re.compile(r"mean exons per transcript\s+([\d.]+)"), - "CDS_LENGTH": re.compile(r"mean cds length \(bp\)\s+([\d.]+)"), + "EXONS_PER_TRANSC": re.compile(r"mean exons per mrna\s+([\d.]+)"), + "CDS_LENGTH": re.compile(r"mean mrna length \(bp\)\s+([\d.]+)"), "EXON_SIZE": re.compile(r"mean exon length \(bp\)\s+([\d.]+)"), "INTRON_SIZE": re.compile(r"mean intron in cds length \(bp\)\s+([\d.]+)"), } From 96cf0bd0df573af293d5b613714c6d9bb437a71c Mon Sep 17 00:00:00 2001 From: Bethan Yates Date: Thu, 14 Nov 2024 12:36:38 +0000 Subject: [PATCH 102/132] updated docs to include annotation statistics subworkflow --- README.md | 6 ++++-- docs/output.md | 15 ++++++++++++++- docs/usage.md | 21 +++++++++++++++------ 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 7b324815..5596fc39 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ ## Introduction -**sanger-tol/genomenote** is a bioinformatics pipeline that takes aligned HiC reads, creates contact maps and chromosomal grid using Cooler, and display on a [HiGlass server](https://genome-note-higlass.tol.sanger.ac.uk/app). The pipeline also collates (1) assembly information, statistics and chromosome details from NCBI datasets, (2) genome completeness from BUSCO, (3) consensus quality and k-mer completeness from MerquryFK, and (4) HiC primary mapped percentage from samtools flagstat. +**sanger-tol/genomenote** is a bioinformatics pipeline that takes aligned HiC reads, creates contact maps and chromosomal grid using Cooler, and display on a [HiGlass server](https://genome-note-higlass.tol.sanger.ac.uk/app). The pipeline also collates (1) assembly information, statistics and chromosome details from NCBI datasets, (2) genome completeness from BUSCO, (3) consensus quality and k-mer completeness from MerquryFK, (4) HiC primary mapped percentage from samtools flagstat and optionally (5) Annotation statistics from AGAT and BUSCO. The pipeline combines the calculated statistics and collated assembly metadata with a template document to output a genome note document. @@ -25,7 +25,9 @@ 6. Genome completeness ([`NCBI API`](https://www.ncbi.nlm.nih.gov/datasets/docs/v1/reference-docs/rest-api/), [`BUSCO`](https://busco.ezlab.org)) 7. Consensus quality and k-mer completeness ([`FASTK`](https://github.com/thegenemyers/FASTK), [`MERQURY.FK`](https://github.com/thegenemyers/MERQURY.FK)) 8. Collated summary table ([`createtable`](bin/create_table.py)) -9. Present results and visualisations ([`MultiQC`](http://multiqc.info/), [`R`](https://www.r-project.org/)) +9. Optionally calculates some annotation statistics and completeness , ([`AGAT`](https://github.com/NBISweden/AGAT), [`BUSCO`](https://busco.ezlab.org)) +10. Combines calculated statisics and assembly metadata with a template file to produce a genome note document. +11. Present results and visualisations ([`MultiQC`](http://multiqc.info/), [`R`](https://www.r-project.org/)) ## Usage diff --git a/docs/output.md b/docs/output.md index f742e4cc..333065f5 100644 --- a/docs/output.md +++ b/docs/output.md @@ -10,8 +10,10 @@ The directories listed below will be created in the results directory after the The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes data using the following steps: + - [Contact maps](#contact-maps) – Contact matrix created using HiC sequencing data - [Genome statistics](#genome-statistics) – Collated assembly information, genome statistics and alignment quality information +- [Annotation statistics](#annotation-statistics) - Statistics calculated on the annotated protein set for the assembly (if GFF annotation file is provided as input) - [BUSCO](#busco) - BUSCO results - [MultiQC](#multiqc) - Aggregate report describing results from the whole pipeline - [Pipeline information](#pipeline-information) - Report metrics generated during the workflow execution @@ -38,13 +40,24 @@ This pipeline collates (1) assembly information, statistics and chromosome detai

Output files - `genome_note/` - - `.csv`: collate genome statistics file + - `.csv`: collated genome statistics file - `.{docx|xml}`: partially completed genome note template file - `_genome_note_consistent.csv`: a file of genome metadata parameters pulled from various public data repositories where all source agree on the paramter value. - `_genome_note_inconsistent.csv`: a file of genome metadata parameters, and their sources pulled from various public data repositories where the paramter value differs between data sources. +### Annotation statistics +This pipeline can generate some statistics using AGAT and a BUSCO completeness score on the assembly annotation if a GFF file of protein annotations is given as input. This file should be a GFF3 format file describing the annotated protein set. + + +Output files + +- `annotation_stats/` + -`_annotation.csv`: collated annotation statistics file + + + ### BUSCO BUSCO results generated by the pipeline (all BUSCO lineages that match the claassification of the species). diff --git a/docs/usage.md b/docs/usage.md index 529ec0a3..9e98d4d3 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -13,18 +13,27 @@ These typically include: 1. Assembly metadata from COPO, ENA, GoaT, GBIF and NCBI 2. Assembly information, statistics and chromosome details from NCBI datasets. 3. Genome completeness from BUSCO. -4. Consensus quality and k-mer completeness from MerquryFK - when high-quality reads are available. -5. Hi-C contact map and chromosomal grid using Cooler, as well as primary mapped percentage from samtools flagstat - when Hi-C reads are provided. These files can be displayed on a [HiGlass](http://higlass.io) server, like the one use by the [Sanger Institute](https://genome-note-higlass.tol.sanger.ac.uk/app). +4. Annotation statistics from AGAT and completeness from BUSCO. +5. Consensus quality and k-mer completeness from MerquryFK - when high-quality reads are available. +6. Hi-C contact map and chromosomal grid using Cooler, as well as primary mapped percentage from samtools flagstat - when Hi-C reads are provided. These files can be displayed on a [HiGlass](http://higlass.io) server, like the one use by the [Sanger Institute](https://genome-note-higlass.tol.sanger.ac.uk/app). ## Genome metadata input You will need to supply the assembly accession for the genome you would like to analyse along with the biosample acession(s) linked to this genome assembly. ```bash - --assembly '[assembly accession]' - --biosample_wgs '[biosample accession of the biosample used to produce the genomic sequence]' - --biosample_hic '[biosample accession of the biosample used to produce the HiC data]' - --biosample_rna '[biosample accession of the biosample used to produce the RNASeq data] +--assembly '[assembly accession]' +--biosample_wgs '[biosample accession of the biosample used to produce the genomic sequence]' +--biosample_hic '[biosample accession of the biosample used to produce the HiC data]' +--biosample_rna '[biosample accession of the biosample used to produce the RNASeq data] +``` + +## Annotation input + +If you want to generate statistics on the set of proteins annotated for the assembly you will need to supply a GFF3 file of the predicted protein sequences. The assembly region names used in this file must match the assembly regions names used in the assembly fasta file provided with --fasta + +```bash +--annotation_set '[Path to annotation file :gff] ``` ## Samplesheet input From 06e2b20d47f0e42ae51351b337ed547a6dd9ede0 Mon Sep 17 00:00:00 2001 From: Bethan Yates Date: Thu, 14 Nov 2024 12:37:42 +0000 Subject: [PATCH 103/132] prettier fixes --- README.md | 2 +- docs/output.md | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 5596fc39..01a1a915 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ 6. Genome completeness ([`NCBI API`](https://www.ncbi.nlm.nih.gov/datasets/docs/v1/reference-docs/rest-api/), [`BUSCO`](https://busco.ezlab.org)) 7. Consensus quality and k-mer completeness ([`FASTK`](https://github.com/thegenemyers/FASTK), [`MERQURY.FK`](https://github.com/thegenemyers/MERQURY.FK)) 8. Collated summary table ([`createtable`](bin/create_table.py)) -9. Optionally calculates some annotation statistics and completeness , ([`AGAT`](https://github.com/NBISweden/AGAT), [`BUSCO`](https://busco.ezlab.org)) +9. Optionally calculates some annotation statistics and completeness , ([`AGAT`](https://github.com/NBISweden/AGAT), [`BUSCO`](https://busco.ezlab.org)) 10. Combines calculated statisics and assembly metadata with a template file to produce a genome note document. 11. Present results and visualisations ([`MultiQC`](http://multiqc.info/), [`R`](https://www.r-project.org/)) diff --git a/docs/output.md b/docs/output.md index 333065f5..fbedfe78 100644 --- a/docs/output.md +++ b/docs/output.md @@ -10,7 +10,6 @@ The directories listed below will be created in the results directory after the The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes data using the following steps: - - [Contact maps](#contact-maps) – Contact matrix created using HiC sequencing data - [Genome statistics](#genome-statistics) – Collated assembly information, genome statistics and alignment quality information - [Annotation statistics](#annotation-statistics) - Statistics calculated on the annotated protein set for the assembly (if GFF annotation file is provided as input) @@ -47,14 +46,14 @@ This pipeline collates (1) assembly information, statistics and chromosome detai -### Annotation statistics -This pipeline can generate some statistics using AGAT and a BUSCO completeness score on the assembly annotation if a GFF file of protein annotations is given as input. This file should be a GFF3 format file describing the annotated protein set. +### Annotation statistics + +This pipeline can generate some statistics using AGAT and a BUSCO completeness score on the assembly annotation if a GFF file of protein annotations is given as input. This file should be a GFF3 format file describing the annotated protein set. Output files -- `annotation_stats/` - -`_annotation.csv`: collated annotation statistics file +- `annotation_stats/` -`_annotation.csv`: collated annotation statistics file From fb20ba45e41966ab1aa2ad9ee40c32ffe03d9618 Mon Sep 17 00:00:00 2001 From: Bethan Yates Date: Thu, 14 Nov 2024 16:51:38 +0000 Subject: [PATCH 104/132] Query Ensembl's new metadata API to determine if this assembly has been annotated --- assets/genome_note_template.docx | Bin 369873 -> 370073 bytes bin/combine_parsed_data.py | 2 + bin/fetch_ensembl_metadata.py | 89 ++++++++++++++++++++++++ modules/local/fetch_ensembl_metadata.nf | 34 +++++++++ subworkflows/local/genome_metadata.nf | 7 +- 5 files changed, 131 insertions(+), 1 deletion(-) create mode 100755 bin/fetch_ensembl_metadata.py create mode 100644 modules/local/fetch_ensembl_metadata.nf diff --git a/assets/genome_note_template.docx b/assets/genome_note_template.docx index 15b1f94c58af08c7aa35be78e8051eda7f9a2c6e..d1f6e68d38559d0dd6ac33372dacd2c7193bfa71 100644 GIT binary patch delta 110737 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

~`NY<+Z+tz{C;Gdy*xwf!`rg6J&B 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

2nD^o_o{S;GEc? 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 YJXpQxjhnj^uwxN`?j2ti;H{7U2UF}m)Bpeg diff --git a/bin/combine_parsed_data.py b/bin/combine_parsed_data.py index fc82bfb6..5e22d833 100755 --- a/bin/combine_parsed_data.py +++ b/bin/combine_parsed_data.py @@ -21,6 +21,7 @@ ("COPO_BIOSAMPLE_HIC", "copo_biosample_hic_file"), ("COPO_BIOSAMPLE_RNA", "copo_biosample_rna_file"), ("GBIF_TAXONOMY", "gbif_taxonomy_file"), + ("ENSEMBL_ANNOTATION", "ensembl_annotation_file"), ] @@ -42,6 +43,7 @@ def parse_args(args=None): parser.add_argument("--copo_biosample_hic_file", help="Input parsed COPO HiC biosample file.", required=False) parser.add_argument("--copo_biosample_rna_file", help="Input parsed COPO RNASeq biosample file.", required=False) parser.add_argument("--gbif_taxonomy_file", help="Input parsed GBIF taxonomy file.", required=False) + parser.add_argument("--ensembl_annotation_file", help="Input parsed Ensembl annotation file.", required=False) parser.add_argument("--out_consistent", help="Output file.", required=True) parser.add_argument("--out_inconsistent", help="Output file.", required=True) parser.add_argument("--version", action="version", version="%(prog)s 1.0") diff --git a/bin/fetch_ensembl_metadata.py b/bin/fetch_ensembl_metadata.py new file mode 100755 index 00000000..2cdff508 --- /dev/null +++ b/bin/fetch_ensembl_metadata.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 + +import os +import sys +import requests +import argparse + + +def parse_args(args=None): + Description = "Query the Ensembl Metadata API to pull out annotation information required by a genome note." + Epilog = "Example usage: python fetch_ensembl_metadata.py --species --output" + + parser = argparse.ArgumentParser(description=Description, epilog=Epilog) + parser.add_argument("--species", required=True, help="The species name") + parser.add_argument("--output", required=True, help="Output file path") + parser.add_argument("--version", action="version", version="%(prog)s 1.0") + + return parser.parse_args() + + +def make_dir(path): + if len(path) > 0: + os.makedirs(path, exist_ok=True) + + +def fetch_ensembl_data(species, output_file): + # Use the species name to query the Ensembl Metadata API to determine if the + # species has been annotated. Return assmbly accesssion of annotated data and + # a url linking to that species on the Ensembl Rapid website + + url = "https://beta.ensembl.org/data/graphql" + sp = species.replace("_", " ") + variables = { "species": sp } + query = """ + query Annotation($species: String) + { + genomes(by_keyword: {scientific_name: $species }) { + assembly_accession + scientific_name + tol_id + dataset { + name + type + dataset_type + } + genome_id + } + } + """ + response = requests.post(url=url, json={'query': query, 'variables': variables }) + + if response.status_code == 200: + param_list = [] + data = response.json() + if data["data"]["genomes"] is not None: + genomes = data["data"]["genomes"][0] + + if genomes["assembly_accession"]: + accession = genomes["assembly_accession"] + acc = f'"{accession}"' + param_list.append(("ANNOT_ACCESSION", acc)) + annot_url =f"https://rapid.ensembl.org/{species}_{accession}/Info/Index" + annot_url = f'"{annot_url}"' + param_list.append(("ANNOT_URL", annot_url)) + + + + # Write out file even if there is no annotation data to write + out_dir = os.path.dirname(output_file) + make_dir(out_dir) # Create directory if it does not exist + + with open(output_file, "w") as fout: + # Write header + fout.write(",".join(["#paramName", "paramValue"]) + "\n") + + for param_pair in param_list: + fout.write(",".join(param_pair) + "\n") + + return output_file + + + +def main(args=None): + args = parse_args(args) + fetch_ensembl_data(args.species, args.output) + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/modules/local/fetch_ensembl_metadata.nf b/modules/local/fetch_ensembl_metadata.nf new file mode 100644 index 00000000..9bf585b3 --- /dev/null +++ b/modules/local/fetch_ensembl_metadata.nf @@ -0,0 +1,34 @@ +process FETCH_ENSEMBL_METADATA { + tag "$assembly" + label 'process_single' + + conda "conda-forge::python=3.9.1" + + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/requests:2.26.0': + 'quay.io/biocontainers/requests:2.26.0'}" + + input: + tuple val(assembly), val(species) + + + output: + path "*.csv", emit: file_path + path "versions.yml", emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def script_name = "fetch_ensembl_metadata.py" + def output_file = "${assembly}_ensembl_annotation.csv" + + """ + $script_name --species $species --output $output_file + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + fetch_ensembl_metadata.py: \$(fetch_ensembl_metadata.py --version | cut -d' ' -f2) + END_VERSIONS + """ +} diff --git a/subworkflows/local/genome_metadata.nf b/subworkflows/local/genome_metadata.nf index 22088de9..f5c28013 100755 --- a/subworkflows/local/genome_metadata.nf +++ b/subworkflows/local/genome_metadata.nf @@ -8,6 +8,7 @@ include { RUN_WGET } from '../../modules/local/run_wget' include { PARSE_METADATA } from '../../modules/local/parse_metadata' include { COMBINE_METADATA } from '../../modules/local/combine_metadata' include { FETCH_GBIF_METADATA } from '../../modules/local/fetch_gbif_metadata' +include { FETCH_ENSEMBL_METADATA } from '../../modules/local/fetch_ensembl_metadata' workflow GENOME_METADATA { @@ -92,11 +93,15 @@ workflow GENOME_METADATA { | map { it -> tuple( it )} | set { ch_gbif } + // Query Ensembl Metadata API to see if this species has been annotated + FETCH_ENSEMBL_METADATA ( ch_gbif_params ) + ch_versions = ch_versions.mix( FETCH_ENSEMBL_METADATA.out.versions.first() ) + PARSE_METADATA.out.file_path | map { it -> tuple( it[1] )} | set { ch_parsed } - ch_parsed.mix(ch_gbif) + ch_parsed.mix(ch_gbif, FETCH_ENSEMBL_METADATA.out.file_path) | collect | map { it -> [ it ] From d2a5b17b650aa7bd094c6b965479f0f215382daf Mon Sep 17 00:00:00 2001 From: Bethan Yates Date: Thu, 14 Nov 2024 16:51:58 +0000 Subject: [PATCH 105/132] documentation updates --- bin/fetch_gbif_metadata.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/fetch_gbif_metadata.py b/bin/fetch_gbif_metadata.py index ccac54cd..4a47aa27 100755 --- a/bin/fetch_gbif_metadata.py +++ b/bin/fetch_gbif_metadata.py @@ -7,8 +7,8 @@ def parse_args(args=None): - Description = "Parse contents of an ENA Taxonomy report and pull out metadata required by a genome note." - Epilog = "Example usage: python fetch_gbif_metadata.py --genus --species --output" + Description = "Query GBIF for species taxonomy information and pull out metadata required by a genome note." + Epilog = "Example usage: python fetch_gbif_metadata.py --species --output" parser = argparse.ArgumentParser(description=Description, epilog=Epilog) parser.add_argument("--species", required=True, help="The species name") From 3f5274633b1d0e4b29abb550b5755b29d1a58624 Mon Sep 17 00:00:00 2001 From: Bethan Yates Date: Thu, 14 Nov 2024 16:57:04 +0000 Subject: [PATCH 106/132] black fix --- bin/fetch_ensembl_metadata.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/bin/fetch_ensembl_metadata.py b/bin/fetch_ensembl_metadata.py index 2cdff508..7280917f 100755 --- a/bin/fetch_ensembl_metadata.py +++ b/bin/fetch_ensembl_metadata.py @@ -30,7 +30,7 @@ def fetch_ensembl_data(species, output_file): url = "https://beta.ensembl.org/data/graphql" sp = species.replace("_", " ") - variables = { "species": sp } + variables = {"species": sp} query = """ query Annotation($species: String) { @@ -47,7 +47,7 @@ def fetch_ensembl_data(species, output_file): } } """ - response = requests.post(url=url, json={'query': query, 'variables': variables }) + response = requests.post(url=url, json={"query": query, "variables": variables}) if response.status_code == 200: param_list = [] @@ -59,12 +59,10 @@ def fetch_ensembl_data(species, output_file): accession = genomes["assembly_accession"] acc = f'"{accession}"' param_list.append(("ANNOT_ACCESSION", acc)) - annot_url =f"https://rapid.ensembl.org/{species}_{accession}/Info/Index" + annot_url = f"https://rapid.ensembl.org/{species}_{accession}/Info/Index" annot_url = f'"{annot_url}"' param_list.append(("ANNOT_URL", annot_url)) - - # Write out file even if there is no annotation data to write out_dir = os.path.dirname(output_file) make_dir(out_dir) # Create directory if it does not exist @@ -72,14 +70,13 @@ def fetch_ensembl_data(species, output_file): with open(output_file, "w") as fout: # Write header fout.write(",".join(["#paramName", "paramValue"]) + "\n") - + for param_pair in param_list: fout.write(",".join(param_pair) + "\n") return output_file - def main(args=None): args = parse_args(args) fetch_ensembl_data(args.species, args.output) From 3490b8e8411c96f70dac493e3bf81c6f1e5f8af8 Mon Sep 17 00:00:00 2001 From: Bethan Yates Date: Fri, 15 Nov 2024 15:53:26 +0000 Subject: [PATCH 107/132] switch to beta url as ensembl rapid site data is now frozen and all data populated on beta --- bin/fetch_ensembl_metadata.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bin/fetch_ensembl_metadata.py b/bin/fetch_ensembl_metadata.py index 7280917f..7106c88f 100755 --- a/bin/fetch_ensembl_metadata.py +++ b/bin/fetch_ensembl_metadata.py @@ -59,7 +59,8 @@ def fetch_ensembl_data(species, output_file): accession = genomes["assembly_accession"] acc = f'"{accession}"' param_list.append(("ANNOT_ACCESSION", acc)) - annot_url = f"https://rapid.ensembl.org/{species}_{accession}/Info/Index" + species_id = genomes["genome_id"] + annot_url = f"https://beta.ensembl.org/species/{species_id}" annot_url = f'"{annot_url}"' param_list.append(("ANNOT_URL", annot_url)) From 6a12288aeb43aae7c126def0618efc730d327c06 Mon Sep 17 00:00:00 2001 From: Bethan Yates Date: Tue, 19 Nov 2024 15:49:28 +0000 Subject: [PATCH 108/132] query by taxon_id rather than species name --- bin/fetch_ensembl_metadata.py | 13 ++++++------- modules/local/fetch_ensembl_metadata.nf | 4 ++-- subworkflows/local/genome_metadata.nf | 11 ++++++++++- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/bin/fetch_ensembl_metadata.py b/bin/fetch_ensembl_metadata.py index 7106c88f..288a63fc 100755 --- a/bin/fetch_ensembl_metadata.py +++ b/bin/fetch_ensembl_metadata.py @@ -11,7 +11,7 @@ def parse_args(args=None): Epilog = "Example usage: python fetch_ensembl_metadata.py --species --output" parser = argparse.ArgumentParser(description=Description, epilog=Epilog) - parser.add_argument("--species", required=True, help="The species name") + parser.add_argument("--taxon_id", required=True, help="The species taxon id") parser.add_argument("--output", required=True, help="Output file path") parser.add_argument("--version", action="version", version="%(prog)s 1.0") @@ -23,18 +23,17 @@ def make_dir(path): os.makedirs(path, exist_ok=True) -def fetch_ensembl_data(species, output_file): +def fetch_ensembl_data(taxon, output_file): # Use the species name to query the Ensembl Metadata API to determine if the # species has been annotated. Return assmbly accesssion of annotated data and # a url linking to that species on the Ensembl Rapid website url = "https://beta.ensembl.org/data/graphql" - sp = species.replace("_", " ") - variables = {"species": sp} + variables = {"taxon": taxon} query = """ - query Annotation($species: String) + query Annotation($taxon: String) { - genomes(by_keyword: {scientific_name: $species }) { + genomes(by_keyword: {species_taxonomy_id: $taxon }) { assembly_accession scientific_name tol_id @@ -80,7 +79,7 @@ def fetch_ensembl_data(species, output_file): def main(args=None): args = parse_args(args) - fetch_ensembl_data(args.species, args.output) + fetch_ensembl_data(args.taxon_id, args.output) if __name__ == "__main__": diff --git a/modules/local/fetch_ensembl_metadata.nf b/modules/local/fetch_ensembl_metadata.nf index 9bf585b3..d48b0540 100644 --- a/modules/local/fetch_ensembl_metadata.nf +++ b/modules/local/fetch_ensembl_metadata.nf @@ -9,7 +9,7 @@ process FETCH_ENSEMBL_METADATA { 'quay.io/biocontainers/requests:2.26.0'}" input: - tuple val(assembly), val(species) + tuple val(assembly), val(taxon_id) output: @@ -24,7 +24,7 @@ process FETCH_ENSEMBL_METADATA { def output_file = "${assembly}_ensembl_annotation.csv" """ - $script_name --species $species --output $output_file + $script_name --taxon_id $taxon_id --output $output_file cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/subworkflows/local/genome_metadata.nf b/subworkflows/local/genome_metadata.nf index f5c28013..b08f24cb 100755 --- a/subworkflows/local/genome_metadata.nf +++ b/subworkflows/local/genome_metadata.nf @@ -93,8 +93,17 @@ workflow GENOME_METADATA { | map { it -> tuple( it )} | set { ch_gbif } + + ch_file_list + | map { meta, it -> + def assembly = meta.id + def taxon_id = meta.taxon_id + [assembly, taxon_id] + } + | set { ch_ensembl_params} + // Query Ensembl Metadata API to see if this species has been annotated - FETCH_ENSEMBL_METADATA ( ch_gbif_params ) + FETCH_ENSEMBL_METADATA ( ch_ensembl_params ) ch_versions = ch_versions.mix( FETCH_ENSEMBL_METADATA.out.versions.first() ) PARSE_METADATA.out.file_path From 019e9ae2550afab5ad8613d2da2bcd18aef4d928 Mon Sep 17 00:00:00 2001 From: Bethan Yates Date: Tue, 19 Nov 2024 16:04:17 +0000 Subject: [PATCH 109/132] updated comments/usage to refelect change to querying using taxon_id rather than species name --- bin/fetch_ensembl_metadata.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/fetch_ensembl_metadata.py b/bin/fetch_ensembl_metadata.py index 288a63fc..da6c87e1 100755 --- a/bin/fetch_ensembl_metadata.py +++ b/bin/fetch_ensembl_metadata.py @@ -8,7 +8,7 @@ def parse_args(args=None): Description = "Query the Ensembl Metadata API to pull out annotation information required by a genome note." - Epilog = "Example usage: python fetch_ensembl_metadata.py --species --output" + Epilog = "Example usage: python fetch_ensembl_metadata.py --taxon_id --output" parser = argparse.ArgumentParser(description=Description, epilog=Epilog) parser.add_argument("--taxon_id", required=True, help="The species taxon id") @@ -24,7 +24,7 @@ def make_dir(path): def fetch_ensembl_data(taxon, output_file): - # Use the species name to query the Ensembl Metadata API to determine if the + # Use the species taxon_id to query the Ensembl Metadata API to determine if the # species has been annotated. Return assmbly accesssion of annotated data and # a url linking to that species on the Ensembl Rapid website From a343c27a206b2df4b1b636eb71ca6abf570d5fad Mon Sep 17 00:00:00 2001 From: Bethan Yates Date: Tue, 19 Nov 2024 16:37:20 +0000 Subject: [PATCH 110/132] deleted empty file --- lint_log.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 lint_log.txt diff --git a/lint_log.txt b/lint_log.txt deleted file mode 100644 index e69de29b..00000000 From 748a32510d4b50e4b1b1a92477c29a6ea30d7ac1 Mon Sep 17 00:00:00 2001 From: Bethan Yates Date: Tue, 19 Nov 2024 16:37:33 +0000 Subject: [PATCH 111/132] fixed typo --- bin/combine_statistics_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/combine_statistics_data.py b/bin/combine_statistics_data.py index 08ae5849..5517169b 100755 --- a/bin/combine_statistics_data.py +++ b/bin/combine_statistics_data.py @@ -8,7 +8,7 @@ files = [ ("CONSISTENT", "in_consistent"), - ("GENOME_STATISITCS", "in_genome_statistics"), + ("GENOME_STATISTICS", "in_genome_statistics"), ("ANNOTATION_STATISITCS", "in_annotation_statistics"), ] From 14614fb36efe2dba493315d32bf40ee0902f14ea Mon Sep 17 00:00:00 2001 From: Bethan Yates Date: Tue, 19 Nov 2024 17:09:55 +0000 Subject: [PATCH 112/132] modified output file name and directory of annotation_statistics subworkflow to mirror that used by the ensemblgenedownload pipeline --- conf/modules.config | 2 +- docs/output.md | 2 +- modules/local/extract_annotation_statistics_info.nf | 4 ++-- subworkflows/local/annotation_statistics.nf | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 9638ac28..be46ebd7 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -141,7 +141,7 @@ process { withName: EXTRACT_ANNOTATION_STATISTICS_INFO { publishDir = [ - path: { "${params.outdir}/annotation_stats" }, + path: { "${params.outdir}/gene" }, mode: params.publish_dir_mode, saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] diff --git a/docs/output.md b/docs/output.md index fbedfe78..4920f6d5 100644 --- a/docs/output.md +++ b/docs/output.md @@ -53,7 +53,7 @@ This pipeline can generate some statistics using AGAT and a BUSCO completeness s

Output files -- `annotation_stats/` -`_annotation.csv`: collated annotation statistics file +- `gene/` -`_stats.csv`: collated annotation statistics file diff --git a/modules/local/extract_annotation_statistics_info.nf b/modules/local/extract_annotation_statistics_info.nf index 054c93b3..f87bfd1f 100644 --- a/modules/local/extract_annotation_statistics_info.nf +++ b/modules/local/extract_annotation_statistics_info.nf @@ -19,8 +19,8 @@ process EXTRACT_ANNOTATION_STATISTICS_INFO{ task.ext.when == null || task.ext.when script: - def prefix = task.ext.prefix ?: meta.id - def output_file = "${prefix}.csv" + def prefix = task.ext.prefix ?: meta.filename + def output_file = "${prefix}.stats.csv" """ extract_annotation_statistics_info.py \\ diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 4b596a5c..41ab6c42 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -23,7 +23,7 @@ workflow ANNOTATION_STATISTICS { // Map the GFF channel to create a tuple with metadata and the file gff | map { file -> - [ [ 'id': params.assembly + '_annotation', 'ext': "gff" ], file ] + [ [ 'id': params.assembly + '_annotation', 'ext': "gff", 'filename': file.baseName ], file ] } | set { ch_gff_tupple } From ae8db5c266081742cd17fe114496cb55b4f15b0a Mon Sep 17 00:00:00 2001 From: Bethan Yates Date: Wed, 20 Nov 2024 15:00:10 +0000 Subject: [PATCH 113/132] Updated docs ahead of release --- CHANGELOG.md | 26 ++++++++++++++++++++++++++ CITATIONS.md | 8 ++++++++ docs/usage.md | 2 +- nextflow.config | 2 +- 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ed60a41..d03a9b77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,32 @@ 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). +## [[2.1.0](https://github.com/sanger-tol/genomenote/releases/tag/2.1.0)] - Pembroke Welsh Corgi [2024-11-20] + +### Enhancements & fixes + +- New annotation_statistics subworkfow which runs BUSCO in protein mode and generates some basic statistics on the the annotated gene set if provided with a GFF3 file of gene annotations using the `--annotation_set` option. +- The genome_metadata subworkflow now queries Ensembl's GraphQL API to determine if Ensembl has released gene annotation for the assembly being processed. + +### Parameters + +| Old parameter | New parameter | +| ------------- | ---------------- | +| | --annotation_set | + +> **NB:** Parameter has been **updated** if both old and new parameter information is present.
**NB:** Parameter has been **added** if just the new parameter information is present.
**NB:** Parameter has been **removed** if new parameter information isn't present. + +### Software dependencies + +Note, since the pipeline is using Nextflow DSL2, each process will be run with its own [Biocontainer](https://biocontainers.pro/#/registry). This means that on occasion it is entirely possible for the pipeline to be using different versions of the same tool. However, the overall software dependency changes compared to the last release have been listed below for reference. + +| Dependency | Old version | New version | +| ---------- | ----------- | ----------- | +| gffread | | 0.12.7 | +| agat | | 1.4.0 | + +> **NB:** Dependency has been **updated** if both old and new version information is present.
**NB:** Dependency has been **added** if just the new version information is present.
**NB:** Dependency has been **removed** if version information isn't present. + ## [[2.0.0](https://github.com/sanger-tol/genomenote/releases/tag/2.0.0)] - English Cocker Spaniel [2024-10-10] ### Enhancements & fixes diff --git a/CITATIONS.md b/CITATIONS.md index 8bff25a0..392829c8 100644 --- a/CITATIONS.md +++ b/CITATIONS.md @@ -12,6 +12,10 @@ ## Pipeline tools +- [AGAT](https://github.com/NBISweden/AGAT) + + > Dainat J. AGAT: Another Gff Analysis Toolkit to handle annotations in any GTF/GFF format. (Version v1.4.0). Zenodo. https://www.doi.org/10.5281/zenodo.3552717 + - [BedTools](https://bedtools.readthedocs.io/en/latest/) > Quinlan, Aaron R., and Ira M. Hall. “BEDTools: A Flexible Suite of Utilities for Comparing Genomic Features.” Bioinformatics, vol. 26, no. 6, 2010, pp. 841–842., https://doi.org/10.1093/bioinformatics/btq033. @@ -30,6 +34,10 @@ - [FastK](https://github.com/thegenemyers/FASTK) +- [GFFREAD](https://github.com/gpertea/gffread) + + > Pertea G and Pertea M. "GFF Utilities: GffRead and GffCompare [version 1; peer review: 3 approved]". F1000Research 2020, 9:304 https://doi.org/10.12688/f1000research.23297.1 + - [MerquryFK](https://github.com/thegenemyers/MERQURY.FK) - [MultiQC](https://multiqc.info) diff --git a/docs/usage.md b/docs/usage.md index 9e98d4d3..f8baa6ee 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -30,7 +30,7 @@ You will need to supply the assembly accession for the genome you would like to ## Annotation input -If you want to generate statistics on the set of proteins annotated for the assembly you will need to supply a GFF3 file of the predicted protein sequences. The assembly region names used in this file must match the assembly regions names used in the assembly fasta file provided with --fasta +If you want to generate statistics on the geneset annotated for the assembly you will need to supply a GFF3 file of the predicted gene sequences. The assembly region names used in this file must match the assembly regions names used in the assembly fasta file provided with --fasta ```bash --annotation_set '[Path to annotation file :gff] diff --git a/nextflow.config b/nextflow.config index 25151ebc..636d52e5 100644 --- a/nextflow.config +++ b/nextflow.config @@ -243,7 +243,7 @@ manifest { description = """Creating standarised genome assembly publications""" mainScript = 'main.nf' nextflowVersion = '!>=22.10.1' - version = '2.0.0' + version = '2.1.0' doi = '10.5281/zenodo.7949384' } From d61696d49bcb24dd5459cafdccc51b0159d7b71f Mon Sep 17 00:00:00 2001 From: Tyler Chafin Date: Fri, 22 Nov 2024 15:28:42 +0000 Subject: [PATCH 114/132] updated nf-core/agat modules --- modules.json | 4 +- .../nf-core/agat/spstatistics/environment.yml | 2 - modules/nf-core/agat/spstatistics/meta.yml | 40 +++++++++++-------- .../nf-core/agat/sqstatbasic/environment.yml | 2 - modules/nf-core/agat/sqstatbasic/meta.yml | 40 +++++++++++-------- 5 files changed, 50 insertions(+), 38 deletions(-) diff --git a/modules.json b/modules.json index 1cc4f784..b4010ca8 100644 --- a/modules.json +++ b/modules.json @@ -7,12 +7,12 @@ "nf-core": { "agat/spstatistics": { "branch": "master", - "git_sha": "0a0b723d114e502207072603479b635dfbc2bf59", + "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", "installed_by": ["modules"] }, "agat/sqstatbasic": { "branch": "master", - "git_sha": "0a0b723d114e502207072603479b635dfbc2bf59", + "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", "installed_by": ["modules"] }, "bedtools/bamtobed": { diff --git a/modules/nf-core/agat/spstatistics/environment.yml b/modules/nf-core/agat/spstatistics/environment.yml index c868b7b8..0410ee76 100644 --- a/modules/nf-core/agat/spstatistics/environment.yml +++ b/modules/nf-core/agat/spstatistics/environment.yml @@ -1,7 +1,5 @@ -name: agat_spstatistics channels: - conda-forge - bioconda - - defaults dependencies: - bioconda::agat=1.4.0 diff --git a/modules/nf-core/agat/spstatistics/meta.yml b/modules/nf-core/agat/spstatistics/meta.yml index c6cb21dd..a2f897b8 100644 --- a/modules/nf-core/agat/spstatistics/meta.yml +++ b/modules/nf-core/agat/spstatistics/meta.yml @@ -8,31 +8,39 @@ keywords: - statistics tools: - agat: - description: "AGAT is a toolkit for manipulation and getting information from GFF/GTF files" + description: "AGAT is a toolkit for manipulation and getting information from + GFF/GTF files" homepage: "https://github.com/NBISweden/AGAT" documentation: "https://agat.readthedocs.io/" tool_dev_url: "https://github.com/NBISweden/AGAT" doi: "10.5281/zenodo.3552717" licence: ["GPL v3"] + identifier: biotools:AGAT input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - gff: - type: file - description: Annotation file in GFF3/GTF format - pattern: "*.{gff, gtf}" + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - gff: + type: file + description: Annotation file in GFF3/GTF format + pattern: "*.{gff, gtf}" output: - stats_txt: - type: file - description: Output of Statistics execution - pattern: "*.{txt}" + - meta: + type: file + description: Output of Statistics execution + pattern: "*.{txt}" + - "*.txt": + type: file + description: Output of Statistics execution + pattern: "*.{txt}" - versions: - type: file - description: File containing software versions - pattern: "versions.yml" + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@toniher" maintainers: diff --git a/modules/nf-core/agat/sqstatbasic/environment.yml b/modules/nf-core/agat/sqstatbasic/environment.yml index 58b04205..0410ee76 100644 --- a/modules/nf-core/agat/sqstatbasic/environment.yml +++ b/modules/nf-core/agat/sqstatbasic/environment.yml @@ -1,7 +1,5 @@ -name: agat_sqstatbasic channels: - conda-forge - bioconda - - defaults dependencies: - bioconda::agat=1.4.0 diff --git a/modules/nf-core/agat/sqstatbasic/meta.yml b/modules/nf-core/agat/sqstatbasic/meta.yml index aba57e89..b813a4a8 100644 --- a/modules/nf-core/agat/sqstatbasic/meta.yml +++ b/modules/nf-core/agat/sqstatbasic/meta.yml @@ -8,31 +8,39 @@ keywords: - statistics tools: - agat: - description: "AGAT is a toolkit for manipulation and getting information from GFF/GTF files" + description: "AGAT is a toolkit for manipulation and getting information from + GFF/GTF files" homepage: "https://github.com/NBISweden/AGAT" documentation: "https://agat.readthedocs.io/" tool_dev_url: "https://github.com/NBISweden/AGAT" doi: "10.5281/zenodo.3552717" licence: ["GPL v3"] + identifier: biotools:AGAT input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - gff: - type: file - description: Annotation file in GFF3/GTF format - pattern: "*.{gff, gtf}" + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - gff: + type: file + description: Annotation file in GFF3/GTF format + pattern: "*.{gff, gtf}" output: - stats_txt: - type: file - description: Output of Statistics execution - pattern: "*.{txt}" + - meta: + type: file + description: Output of Statistics execution + pattern: "*.{txt}" + - "*.txt": + type: file + description: Output of Statistics execution + pattern: "*.{txt}" - versions: - type: file - description: File containing software versions - pattern: "versions.yml" + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@toniher" maintainers: From 6cc12cd4dee67f335e48fbd45556f4f49245d3de Mon Sep 17 00:00:00 2001 From: Tyler Chafin Date: Fri, 22 Nov 2024 15:41:49 +0000 Subject: [PATCH 115/132] update nf-core/bamtobed --- modules.json | 2 +- .../nf-core/bedtools/bamtobed/environment.yml | 5 ++ modules/nf-core/bedtools/bamtobed/main.nf | 17 +++++- modules/nf-core/bedtools/bamtobed/meta.yml | 49 +++++++++------- .../bedtools/bamtobed/tests/main.nf.test | 56 +++++++++++++++++++ .../bedtools/bamtobed/tests/main.nf.test.snap | 37 ++++++++++++ .../nf-core/bedtools/bamtobed/tests/tags.yml | 2 + 7 files changed, 144 insertions(+), 24 deletions(-) create mode 100644 modules/nf-core/bedtools/bamtobed/environment.yml create mode 100644 modules/nf-core/bedtools/bamtobed/tests/main.nf.test create mode 100644 modules/nf-core/bedtools/bamtobed/tests/main.nf.test.snap create mode 100644 modules/nf-core/bedtools/bamtobed/tests/tags.yml diff --git a/modules.json b/modules.json index b4010ca8..7e319f3a 100644 --- a/modules.json +++ b/modules.json @@ -17,7 +17,7 @@ }, "bedtools/bamtobed": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", "installed_by": ["modules"] }, "busco": { diff --git a/modules/nf-core/bedtools/bamtobed/environment.yml b/modules/nf-core/bedtools/bamtobed/environment.yml new file mode 100644 index 00000000..5683bc05 --- /dev/null +++ b/modules/nf-core/bedtools/bamtobed/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::bedtools=2.31.1 diff --git a/modules/nf-core/bedtools/bamtobed/main.nf b/modules/nf-core/bedtools/bamtobed/main.nf index 29f5a62f..bb8295dc 100644 --- a/modules/nf-core/bedtools/bamtobed/main.nf +++ b/modules/nf-core/bedtools/bamtobed/main.nf @@ -2,10 +2,10 @@ process BEDTOOLS_BAMTOBED { tag "$meta.id" label 'process_medium' - conda "bioconda::bedtools=2.30.0" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/bedtools:2.30.0--hc088bd4_0' : - 'biocontainers/bedtools:2.30.0--hc088bd4_0' }" + 'https://depot.galaxyproject.org/singularity/bedtools:2.31.1--hf5e1c6e_0' : + 'biocontainers/bedtools:2.31.1--hf5e1c6e_0' }" input: tuple val(meta), path(bam) @@ -32,4 +32,15 @@ process BEDTOOLS_BAMTOBED { bedtools: \$(bedtools --version | sed -e "s/bedtools v//g") END_VERSIONS """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.bed + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bedtools: \$(bedtools --version | sed -e "s/bedtools v//g") + END_VERSIONS + """ } diff --git a/modules/nf-core/bedtools/bamtobed/meta.yml b/modules/nf-core/bedtools/bamtobed/meta.yml index 5a4ff73a..20171885 100644 --- a/modules/nf-core/bedtools/bamtobed/meta.yml +++ b/modules/nf-core/bedtools/bamtobed/meta.yml @@ -3,36 +3,45 @@ description: Converts a bam file to a bed12 file. keywords: - bam - bed + - bedtools + - bamtobed + - converter tools: - bedtools: description: | A set of tools for genomic analysis tasks, specifically enabling genome arithmetic (merge, count, complement) on various file types. documentation: https://bedtools.readthedocs.io/en/latest/content/tools/complement.html licence: ["MIT"] + identifier: biotools:bedtools input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - bam: - type: file - description: Input BAM file - pattern: "*.{bam}" + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - bam: + type: file + description: Input BAM file + pattern: "*.{bam}" output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - bed: - type: file - description: Bed file containing genomic intervals. - pattern: "*.{bed}" + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.bed": + type: file + description: Bed file containing genomic intervals. + pattern: "*.{bed}" - versions: - type: file - description: File containing software versions - pattern: "versions.yml" + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@yuukiiwa" - "@drpatelh" +maintainers: + - "@yuukiiwa" + - "@drpatelh" diff --git a/modules/nf-core/bedtools/bamtobed/tests/main.nf.test b/modules/nf-core/bedtools/bamtobed/tests/main.nf.test new file mode 100644 index 00000000..297f1813 --- /dev/null +++ b/modules/nf-core/bedtools/bamtobed/tests/main.nf.test @@ -0,0 +1,56 @@ +nextflow_process { + name "Test Process BEDTOOLS_BAMTOBED" + script "../main.nf" + process "BEDTOOLS_BAMTOBED" + + tag "modules" + tag "modules_nfcore" + tag "bedtools" + tag "bedtools/bamtobed" + + test("sarscov2 - bam") { + when { + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.single_end.bam', checkIfExists: true) + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.single_end.bam', checkIfExists: true) + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(file(process.out.bed[0][1]).name).match() } + ) + } + + } + +} diff --git a/modules/nf-core/bedtools/bamtobed/tests/main.nf.test.snap b/modules/nf-core/bedtools/bamtobed/tests/main.nf.test.snap new file mode 100644 index 00000000..d28ddd3e --- /dev/null +++ b/modules/nf-core/bedtools/bamtobed/tests/main.nf.test.snap @@ -0,0 +1,37 @@ +{ + "stub": { + "content": [ + "test.bed" + ], + "timestamp": "2023-12-05T17:37:27.785556" + }, + "sarscov2 - bam": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.bed:md5,a6a299bd39dc56225f8029c05ea97dcb" + ] + ], + "1": [ + "versions.yml:md5,90a53b0acd234b4f7d125dadd0dbbdfb" + ], + "bed": [ + [ + { + "id": "test" + }, + "test.bed:md5,a6a299bd39dc56225f8029c05ea97dcb" + ] + ], + "versions": [ + "versions.yml:md5,90a53b0acd234b4f7d125dadd0dbbdfb" + ] + } + ], + "timestamp": "2023-12-05T17:37:20.997988" + } +} \ No newline at end of file diff --git a/modules/nf-core/bedtools/bamtobed/tests/tags.yml b/modules/nf-core/bedtools/bamtobed/tests/tags.yml new file mode 100644 index 00000000..54510dda --- /dev/null +++ b/modules/nf-core/bedtools/bamtobed/tests/tags.yml @@ -0,0 +1,2 @@ +bedtools/bamtobed: + - "modules/nf-core/bedtools/bamtobed/**" From 13687d9a691c76336ff312f221dc2436f9e1d2d2 Mon Sep 17 00:00:00 2001 From: Tyler Chafin Date: Fri, 22 Nov 2024 16:19:22 +0000 Subject: [PATCH 116/132] nf-core/busco updated to 5.7.1 and patched --- conf/modules.config | 4 +- modules.json | 68 +- .../{busco.diff => busco/busco-busco.diff} | 8 +- .../nf-core/busco/{ => busco}/environment.yml | 4 +- modules/nf-core/busco/{ => busco}/main.nf | 33 +- modules/nf-core/busco/busco/meta.yml | 152 +++++ .../nf-core/busco/busco/tests/main.nf.test | 415 ++++++++++++ .../busco/busco/tests/main.nf.test.snap | 230 +++++++ .../busco/tests/nextflow.augustus.config | 5 + .../nf-core/busco/busco/tests/nextflow.config | 5 + .../busco/busco/tests/nextflow.metaeuk.config | 5 + .../nf-core/busco/busco/tests/old_test.yml | 624 ++++++++++++++++++ modules/nf-core/busco/busco/tests/tags.yml | 2 + modules/nf-core/busco/meta.yml | 96 --- subworkflows/local/annotation_statistics.nf | 14 +- subworkflows/local/genome_statistics.nf | 12 +- 16 files changed, 1530 insertions(+), 147 deletions(-) rename modules/nf-core/busco/{busco.diff => busco/busco-busco.diff} (87%) rename modules/nf-core/busco/{ => busco}/environment.yml (50%) rename modules/nf-core/busco/{ => busco}/main.nf (80%) create mode 100644 modules/nf-core/busco/busco/meta.yml create mode 100644 modules/nf-core/busco/busco/tests/main.nf.test create mode 100644 modules/nf-core/busco/busco/tests/main.nf.test.snap create mode 100644 modules/nf-core/busco/busco/tests/nextflow.augustus.config create mode 100644 modules/nf-core/busco/busco/tests/nextflow.config create mode 100644 modules/nf-core/busco/busco/tests/nextflow.metaeuk.config create mode 100644 modules/nf-core/busco/busco/tests/old_test.yml create mode 100644 modules/nf-core/busco/busco/tests/tags.yml delete mode 100644 modules/nf-core/busco/meta.yml diff --git a/conf/modules.config b/conf/modules.config index be46ebd7..342574a4 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -55,8 +55,8 @@ process { ext.args = { 'test' in workflow.profile.tokenize(',') ? // Additional configuration to speed processes up during testing. // Note: BUSCO *must* see the double-quotes around the parameters - '--tar --metaeuk_parameters \'"-s=2"\' --metaeuk_rerun_parameters \'"-s=2"\'' - : '--tar' } + '--tar --metaeuk --metaeuk_parameters \'"-s=2"\' --metaeuk_rerun_parameters \'"-s=2"\'' + : '--tar --metaeuk ' } } withName: "RESTRUCTUREBUSCODIR" { diff --git a/modules.json b/modules.json index 7e319f3a..0a622365 100644 --- a/modules.json +++ b/modules.json @@ -8,83 +8,113 @@ "agat/spstatistics": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "agat/sqstatbasic": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "bedtools/bamtobed": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, - "busco": { + "busco/busco": { "branch": "master", - "git_sha": "e3126f437c336c826f242842fe51769cfce0ec2d", - "installed_by": ["modules"], - "patch": "modules/nf-core/busco/busco.diff" + "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", + "installed_by": [ + "modules" + ], + "patch": "modules/nf-core/busco/busco/busco-busco.diff" }, "cooler/cload": { "branch": "master", "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "cooler/dump": { "branch": "master", "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "cooler/zoomify": { "branch": "master", "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "custom/dumpsoftwareversions": { "branch": "master", "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "fastk/fastk": { "branch": "master", "git_sha": "0f8a77ff00e65eaeebc509b8156eaa983192474b", - "installed_by": ["modules"], + "installed_by": [ + "modules" + ], "patch": "modules/nf-core/fastk/fastk/fastk-fastk.diff" }, "gffread": { "branch": "master", "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "gnu/sort": { "branch": "master", "git_sha": "88f6e982fb8bd40488d837b3b08a65008e602840", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "gunzip": { "branch": "master", "git_sha": "5c460c5a4736974abde2843294f35307ee2b0e5e", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "merquryfk/merquryfk": { "branch": "master", "git_sha": "0f8a77ff00e65eaeebc509b8156eaa983192474b", - "installed_by": ["modules"], + "installed_by": [ + "modules" + ], "patch": "modules/nf-core/merquryfk/merquryfk/merquryfk-merquryfk.diff" }, "multiqc": { "branch": "master", "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "samtools/view": { "branch": "master", "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] } } } } } -} +} \ No newline at end of file diff --git a/modules/nf-core/busco/busco.diff b/modules/nf-core/busco/busco/busco-busco.diff similarity index 87% rename from modules/nf-core/busco/busco.diff rename to modules/nf-core/busco/busco/busco-busco.diff index 775788fb..1317574a 100644 --- a/modules/nf-core/busco/busco.diff +++ b/modules/nf-core/busco/busco/busco-busco.diff @@ -1,8 +1,8 @@ -Changes in module 'nf-core/busco' ---- modules/nf-core/busco/main.nf -+++ modules/nf-core/busco/main.nf +Changes in module 'nf-core/busco/busco' +--- modules/nf-core/busco/busco/main.nf ++++ modules/nf-core/busco/busco/main.nf @@ -1,6 +1,5 @@ - process BUSCO { + process BUSCO_BUSCO { - tag "$meta.id" - label 'process_medium' + tag "${meta.id}_${lineage}" diff --git a/modules/nf-core/busco/environment.yml b/modules/nf-core/busco/busco/environment.yml similarity index 50% rename from modules/nf-core/busco/environment.yml rename to modules/nf-core/busco/busco/environment.yml index f872d057..5b918b45 100644 --- a/modules/nf-core/busco/environment.yml +++ b/modules/nf-core/busco/busco/environment.yml @@ -1,7 +1,5 @@ -name: busco channels: - conda-forge - bioconda - - defaults dependencies: - - bioconda::busco=5.5.0 + - bioconda::busco=5.7.1 diff --git a/modules/nf-core/busco/main.nf b/modules/nf-core/busco/busco/main.nf similarity index 80% rename from modules/nf-core/busco/main.nf rename to modules/nf-core/busco/busco/main.nf index 83d8eacd..319f7235 100644 --- a/modules/nf-core/busco/main.nf +++ b/modules/nf-core/busco/busco/main.nf @@ -1,13 +1,13 @@ -process BUSCO { +process BUSCO_BUSCO { tag "${meta.id}_${lineage}" conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/busco:5.5.0--pyhdfd78af_0': - 'biocontainers/busco:5.5.0--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/busco:5.7.1--pyhdfd78af_0': + 'biocontainers/busco:5.7.1--pyhdfd78af_0' }" input: - tuple val(meta), path('tmp_input/*') + tuple val(meta), path(fasta, stageAs:'tmp_input/*') val mode // Required: One of genome, proteins, or transcriptome val lineage // Required: lineage to check against, "auto" enables --auto-lineage instead path busco_lineages_path // Recommended: path to busco lineages - downloads if not set @@ -15,13 +15,13 @@ process BUSCO { output: tuple val(meta), path("*-busco.batch_summary.txt") , emit: batch_summary - tuple val(meta), path("short_summary.*.txt") , emit: short_summaries_txt, optional: true - tuple val(meta), path("short_summary.*.json") , emit: short_summaries_json, optional: true - tuple val(meta), path("*-busco/*/run_*/full_table.tsv") , emit: full_table, optional: true - tuple val(meta), path("*-busco/*/run_*/missing_busco_list.tsv") , emit: missing_busco_list, optional: true - tuple val(meta), path("*-busco/*/run_*/single_copy_proteins.faa") , emit: single_copy_proteins, optional: true + tuple val(meta), path("short_summary.*.txt") , emit: short_summaries_txt , optional: true + tuple val(meta), path("short_summary.*.json") , emit: short_summaries_json , optional: true + tuple val(meta), path("*-busco/*/run_*/full_table.tsv") , emit: full_table , optional: true + tuple val(meta), path("*-busco/*/run_*/missing_busco_list.tsv") , emit: missing_busco_list , optional: true + tuple val(meta), path("*-busco/*/run_*/single_copy_proteins.faa") , emit: single_copy_proteins , optional: true tuple val(meta), path("*-busco/*/run_*/busco_sequences") , emit: seq_dir - tuple val(meta), path("*-busco/*/translated_proteins") , emit: translated_dir, optional: true + tuple val(meta), path("*-busco/*/translated_proteins") , emit: translated_dir , optional: true tuple val(meta), path("*-busco") , emit: busco_dir path "versions.yml" , emit: versions @@ -90,4 +90,17 @@ process BUSCO { busco: \$( busco --version 2>&1 | sed 's/^BUSCO //' ) END_VERSIONS """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}-${lineage}" + def fasta_name = files(fasta).first().name - '.gz' + """ + touch ${prefix}-busco.batch_summary.txt + mkdir -p ${prefix}-busco/$fasta_name/run_${lineage}/busco_sequences + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + busco: \$( busco --version 2>&1 | sed 's/^BUSCO //' ) + END_VERSIONS + """ } diff --git a/modules/nf-core/busco/busco/meta.yml b/modules/nf-core/busco/busco/meta.yml new file mode 100644 index 00000000..7cb6d69c --- /dev/null +++ b/modules/nf-core/busco/busco/meta.yml @@ -0,0 +1,152 @@ +name: busco_busco +description: Benchmarking Universal Single Copy Orthologs +keywords: + - quality control + - genome + - transcriptome + - proteome +tools: + - busco: + description: BUSCO provides measures for quantitative assessment of genome assembly, + gene set, and transcriptome completeness based on evolutionarily informed expectations + of gene content from near-universal single-copy orthologs selected from OrthoDB. + homepage: https://busco.ezlab.org/ + documentation: https://busco.ezlab.org/busco_userguide.html + tool_dev_url: https://gitlab.com/ezlab/busco + doi: "10.1007/978-1-4939-9173-0_14" + licence: ["MIT"] + identifier: biotools:busco +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - fasta: + type: file + description: Nucleic or amino acid sequence file in FASTA format. + pattern: "*.{fasta,fna,fa,fasta.gz,fna.gz,fa.gz}" + - - mode: + type: string + description: The mode to run Busco in. One of genome, proteins, or transcriptome + pattern: "{genome,proteins,transcriptome}" + - - lineage: + type: string + description: The BUSCO lineage to use, or "auto" to automatically select lineage + - - busco_lineages_path: + type: directory + description: Path to local BUSCO lineages directory. + - - config_file: + type: file + description: Path to BUSCO config file. +output: + - batch_summary: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*-busco.batch_summary.txt": + type: file + description: Summary of all sequence files analyzed + pattern: "*-busco.batch_summary.txt" + - short_summaries_txt: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - short_summary.*.txt: + type: file + description: Short Busco summary in plain text format + pattern: "short_summary.*.txt" + - short_summaries_json: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - short_summary.*.json: + type: file + description: Short Busco summary in JSON format + pattern: "short_summary.*.json" + - full_table: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*-busco/*/run_*/full_table.tsv": + type: file + description: Full BUSCO results table + pattern: "full_table.tsv" + - missing_busco_list: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*-busco/*/run_*/missing_busco_list.tsv": + type: file + description: List of missing BUSCOs + pattern: "missing_busco_list.tsv" + - single_copy_proteins: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*-busco/*/run_*/single_copy_proteins.faa": + type: file + description: Fasta file of single copy proteins (transcriptome mode) + pattern: "single_copy_proteins.faa" + - seq_dir: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*-busco/*/run_*/busco_sequences": + type: directory + description: BUSCO sequence directory + pattern: "busco_sequences" + - translated_dir: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*-busco/*/translated_proteins": + type: directory + description: Six frame translations of each transcript made by the transcriptome + mode + pattern: "translated_dir" + - busco_dir: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*-busco": + type: directory + description: BUSCO lineage specific output + pattern: "*-busco" + - versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@priyanka-surana" + - "@charles-plessy" + - "@mahesh-panchal" + - "@muffato" + - "@jvhagey" + - "@gallvp" +maintainers: + - "@priyanka-surana" + - "@charles-plessy" + - "@mahesh-panchal" + - "@muffato" + - "@jvhagey" + - "@gallvp" diff --git a/modules/nf-core/busco/busco/tests/main.nf.test b/modules/nf-core/busco/busco/tests/main.nf.test new file mode 100644 index 00000000..bb7b49a9 --- /dev/null +++ b/modules/nf-core/busco/busco/tests/main.nf.test @@ -0,0 +1,415 @@ +nextflow_process { + + name "Test Process BUSCO_BUSCO" + script "../main.nf" + process "BUSCO_BUSCO" + + tag "modules" + tag "modules_nfcore" + tag "busco" + tag "busco/busco" + + test("test_busco_genome_single_fasta") { + + config './nextflow.config' + + when { + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file(params.modules_testdata_base_path + 'genomics/prokaryotes/bacteroides_fragilis/genome/genome.fna.gz', checkIfExists: true) + ] + input[1] = 'genome' + input[2] = 'bacteria_odb10' // Launch with 'auto' to use --auto-lineage, and specified lineages // 'auto' removed from test due to memory issues + input[3] = [] // Download busco lineage + input[4] = [] // No config + """ + } + } + + then { + assert process.success + + with(path(process.out.short_summaries_txt[0][1]).text) { + assert contains('BUSCO version') + assert contains('The lineage dataset is') + assert contains('BUSCO was run in mode') + assert contains('Complete BUSCOs') + assert contains('Missing BUSCOs') + assert contains('Dependencies and versions') + } + + with(path(process.out.short_summaries_json[0][1]).text) { + assert contains('one_line_summary') + assert contains('mode') + assert contains('dataset') + } + + assert snapshot( + process.out.batch_summary[0][1], + process.out.full_table[0][1], + process.out.missing_busco_list[0][1], + process.out.versions[0] + ).match() + + with(file(process.out.seq_dir[0][1]).listFiles().collect { it.name }) { + assert contains('single_copy_busco_sequences.tar.gz') + assert contains('multi_copy_busco_sequences.tar.gz') + assert contains('fragmented_busco_sequences.tar.gz') + } + + with(path("${process.out.busco_dir[0][1]}/logs/busco.log").text) { + assert contains('DEBUG:busco.run_BUSCO') + assert contains('Results from dataset') + assert contains('how to cite BUSCO') + } + + assert process.out.single_copy_proteins == [] + assert process.out.translated_dir == [] + } + } + + test("test_busco_genome_multi_fasta") { + + config './nextflow.config' + + when { + process { + """ + input[0] = [ + [ id:'test' ], // meta map + [ + file(params.modules_testdata_base_path + 'genomics/prokaryotes/bacteroides_fragilis/genome/genome.fna.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/prokaryotes/candidatus_portiera_aleyrodidarum/genome/genome.fasta', checkIfExists: true) + ] + ] + input[1] = 'genome' + input[2] = 'bacteria_odb10' + input[3] = [] + input[4] = [] + """ + } + } + + then { + assert process.success + + with(path(process.out.short_summaries_txt[0][1][0]).text) { + assert contains('BUSCO version') + assert contains('The lineage dataset is') + assert contains('BUSCO was run in mode') + assert contains('Complete BUSCOs') + assert contains('Missing BUSCOs') + assert contains('Dependencies and versions') + } + + with(path(process.out.short_summaries_txt[0][1][1]).text) { + assert contains('BUSCO version') + assert contains('The lineage dataset is') + assert contains('BUSCO was run in mode') + assert contains('Complete BUSCOs') + assert contains('Missing BUSCOs') + assert contains('Dependencies and versions') + } + + with(path(process.out.short_summaries_json[0][1][0]).text) { + assert contains('one_line_summary') + assert contains('mode') + assert contains('dataset') + } + + with(path(process.out.short_summaries_json[0][1][1]).text) { + assert contains('one_line_summary') + assert contains('mode') + assert contains('dataset') + } + + assert snapshot( + process.out.batch_summary[0][1], + process.out.full_table[0][1], + process.out.missing_busco_list[0][1], + process.out.versions[0] + ).match() + + with(file(process.out.seq_dir[0][1][0]).listFiles().collect { it.name }) { + assert contains('single_copy_busco_sequences.tar.gz') + assert contains('multi_copy_busco_sequences.tar.gz') + assert contains('fragmented_busco_sequences.tar.gz') + } + + with(file(process.out.seq_dir[0][1][1]).listFiles().collect { it.name }) { + assert contains('single_copy_busco_sequences.tar.gz') + assert contains('multi_copy_busco_sequences.tar.gz') + assert contains('fragmented_busco_sequences.tar.gz') + } + + with(path("${process.out.busco_dir[0][1]}/logs/busco.log").text) { + assert contains('DEBUG:busco.run_BUSCO') + assert contains('Results from dataset') + assert contains('how to cite BUSCO') + } + + assert process.out.single_copy_proteins == [] + assert process.out.translated_dir == [] + } + + } + + test("test_busco_eukaryote_metaeuk") { + + config './nextflow.metaeuk.config' + + when { + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + ] + input[1] = 'genome' + input[2] = 'eukaryota_odb10' + input[3] = [] + input[4] = [] + """ + } + } + + then { + assert process.success + + with(path(process.out.short_summaries_txt[0][1]).text) { + assert contains('BUSCO version') + assert contains('The lineage dataset is') + assert contains('BUSCO was run in mode') + assert contains('Complete BUSCOs') + assert contains('Missing BUSCOs') + assert contains('Dependencies and versions') + } + + with(path(process.out.short_summaries_json[0][1]).text) { + assert contains('one_line_summary') + assert contains('mode') + assert contains('dataset') + } + + assert snapshot( + process.out.batch_summary[0][1], + process.out.full_table[0][1], + process.out.missing_busco_list[0][1], + process.out.versions[0] + ).match() + + with(file(process.out.seq_dir[0][1]).listFiles().collect { it.name }) { + assert contains('single_copy_busco_sequences.tar.gz') + assert contains('multi_copy_busco_sequences.tar.gz') + assert contains('fragmented_busco_sequences.tar.gz') + } + + with(path("${process.out.busco_dir[0][1]}/logs/busco.log").text) { + assert contains('DEBUG:busco.run_BUSCO') + assert contains('Results from dataset') + assert contains('how to cite BUSCO') + + } + + assert process.out.single_copy_proteins == [] + assert process.out.translated_dir == [] + } + + } + + test("test_busco_eukaryote_augustus") { + + config './nextflow.augustus.config' + + when { + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + ] + input[1] = 'genome' + input[2] = 'eukaryota_odb10' + input[3] = [] + input[4] = [] + """ + } + } + + then { + assert process.success + + assert snapshot( + process.out.batch_summary[0][1], + process.out.versions[0] + ).match() + + with(path("${process.out.busco_dir[0][1]}/logs/busco.log").text) { + assert contains('DEBUG:busco.run_BUSCO') + assert contains('Augustus did not recognize any genes') + + } + + assert process.out.short_summaries_json == [] + assert process.out.short_summaries_txt == [] + assert process.out.missing_busco_list == [] + assert process.out.full_table == [] + assert process.out.single_copy_proteins == [] + assert process.out.translated_dir == [] + } + + } + + test("test_busco_protein") { + + config './nextflow.config' + + when { + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file(params.modules_testdata_base_path + 'genomics/prokaryotes/candidatus_portiera_aleyrodidarum/genome/proteome.fasta', checkIfExists: true) + ] + input[1] = 'proteins' + input[2] = 'bacteria_odb10' + input[3] = [] + input[4] = [] + """ + } + } + + then { + assert process.success + + with(path(process.out.short_summaries_txt[0][1]).text) { + assert contains('BUSCO version') + assert contains('The lineage dataset is') + assert contains('BUSCO was run in mode') + assert contains('Complete BUSCOs') + assert contains('Missing BUSCOs') + assert contains('Dependencies and versions') + } + + with(path(process.out.short_summaries_json[0][1]).text) { + assert contains('one_line_summary') + assert contains('mode') + assert contains('dataset') + } + + assert snapshot( + process.out.batch_summary[0][1], + process.out.full_table[0][1], + process.out.missing_busco_list[0][1], + process.out.versions[0] + ).match() + + with(file(process.out.seq_dir[0][1]).listFiles().collect { it.name }) { + assert contains('single_copy_busco_sequences.tar.gz') + assert contains('multi_copy_busco_sequences.tar.gz') + assert contains('fragmented_busco_sequences.tar.gz') + } + + with(path("${process.out.busco_dir[0][1]}/logs/busco.log").text) { + assert contains('DEBUG:busco.run_BUSCO') + assert contains('Results from dataset') + assert contains('how to cite BUSCO') + } + + assert process.out.single_copy_proteins == [] + assert process.out.translated_dir == [] + } + + } + + test("test_busco_transcriptome") { + + config './nextflow.config' + + when { + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file(params.modules_testdata_base_path + 'genomics/prokaryotes/bacteroides_fragilis/illumina/fasta/test1.contigs.fa.gz', checkIfExists: true) + ] + input[1] = 'transcriptome' + input[2] = 'bacteria_odb10' + input[3] = [] + input[4] = [] + """ + } + } + + then { + assert process.success + + with(path(process.out.short_summaries_txt[0][1]).text) { + assert contains('BUSCO version') + assert contains('The lineage dataset is') + assert contains('BUSCO was run in mode') + assert contains('Complete BUSCOs') + assert contains('Missing BUSCOs') + assert contains('Dependencies and versions') + } + + with(path(process.out.short_summaries_json[0][1]).text) { + assert contains('one_line_summary') + assert contains('mode') + assert contains('dataset') + } + + assert snapshot( + process.out.batch_summary[0][1], + process.out.full_table[0][1], + process.out.missing_busco_list[0][1], + process.out.translated_dir[0][1], + process.out.single_copy_proteins[0][1], + process.out.versions[0] + ).match() + + with(file(process.out.seq_dir[0][1]).listFiles().collect { it.name }) { + assert contains('single_copy_busco_sequences.tar.gz') + assert contains('multi_copy_busco_sequences.tar.gz') + assert contains('fragmented_busco_sequences.tar.gz') + } + + with(path("${process.out.busco_dir[0][1]}/logs/busco.log").text) { + assert contains('DEBUG:busco.run_BUSCO') + assert contains('Results from dataset') + assert contains('how to cite BUSCO') + } + } + + } + + test("minimal-stub") { + + options '-stub' + + when { + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file(params.modules_testdata_base_path + 'genomics/prokaryotes/bacteroides_fragilis/genome/genome.fna.gz', checkIfExists: true) + ] + input[1] = 'genome' + input[2] = 'bacteria_odb10' + input[3] = [] + input[4] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + +} diff --git a/modules/nf-core/busco/busco/tests/main.nf.test.snap b/modules/nf-core/busco/busco/tests/main.nf.test.snap new file mode 100644 index 00000000..1b6411bc --- /dev/null +++ b/modules/nf-core/busco/busco/tests/main.nf.test.snap @@ -0,0 +1,230 @@ +{ + "minimal-stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test-bacteria_odb10-busco.batch_summary.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + + ], + "2": [ + + ], + "3": [ + + ], + "4": [ + + ], + "5": [ + + ], + "6": [ + [ + { + "id": "test" + }, + [ + + ] + ] + ], + "7": [ + + ], + "8": [ + [ + { + "id": "test" + }, + [ + [ + [ + [ + + ] + ] + ] + ] + ] + ], + "9": [ + "versions.yml:md5,3fc94714b95c2dc15399a4229d9dd1d9" + ], + "batch_summary": [ + [ + { + "id": "test" + }, + "test-bacteria_odb10-busco.batch_summary.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "busco_dir": [ + [ + { + "id": "test" + }, + [ + [ + [ + [ + + ] + ] + ] + ] + ] + ], + "full_table": [ + + ], + "missing_busco_list": [ + + ], + "seq_dir": [ + [ + { + "id": "test" + }, + [ + + ] + ] + ], + "short_summaries_json": [ + + ], + "short_summaries_txt": [ + + ], + "single_copy_proteins": [ + + ], + "translated_dir": [ + + ], + "versions": [ + "versions.yml:md5,3fc94714b95c2dc15399a4229d9dd1d9" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-05-03T13:28:04.451297" + }, + "test_busco_eukaryote_augustus": { + "content": [ + "test-eukaryota_odb10-busco.batch_summary.txt:md5,3ea3bdc423a461dae514d816bdc61c89", + "versions.yml:md5,3fc94714b95c2dc15399a4229d9dd1d9" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-05-03T13:26:36.974986" + }, + "test_busco_genome_single_fasta": { + "content": [ + "test-bacteria_odb10-busco.batch_summary.txt:md5,21b3fb771cf36be917cc451540d999be", + "full_table.tsv:md5,638fe7590f442c57361554dae330eca1", + "missing_busco_list.tsv:md5,1530af4fe7673a6d001349537bcd410a", + "versions.yml:md5,3fc94714b95c2dc15399a4229d9dd1d9" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-05-03T13:22:45.07816" + }, + "test_busco_genome_multi_fasta": { + "content": [ + "test-bacteria_odb10-busco.batch_summary.txt:md5,fcd3c208913e8abda3d6742c43fec5fa", + [ + "full_table.tsv:md5,c657edcc7d0de0175869717551df6e83", + "full_table.tsv:md5,638fe7590f442c57361554dae330eca1" + ], + [ + "missing_busco_list.tsv:md5,aceb66e347a353cb7fca8e2a725f9112", + "missing_busco_list.tsv:md5,1530af4fe7673a6d001349537bcd410a" + ], + "versions.yml:md5,3fc94714b95c2dc15399a4229d9dd1d9" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-05-03T13:23:50.255602" + }, + "test_busco_eukaryote_metaeuk": { + "content": [ + "test-eukaryota_odb10-busco.batch_summary.txt:md5,ff6d8277e452a83ce9456bbee666feb6", + "full_table.tsv:md5,92b1b1d5cb5ea0e2093d16f00187e8c7", + "missing_busco_list.tsv:md5,0352e563de290bf804c708323c35a9e3", + "versions.yml:md5,3fc94714b95c2dc15399a4229d9dd1d9" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-05-03T13:25:38.159041" + }, + "test_busco_transcriptome": { + "content": [ + "test-bacteria_odb10-busco.batch_summary.txt:md5,8734b3f379c4c0928e5dd4ea1873dc64", + "full_table.tsv:md5,1b2ce808fdafa744c56b5f781551272d", + "missing_busco_list.tsv:md5,a6931b6470262b997b8b99ea0f1d14a4", + [ + "1024388at2.faa:md5,797d603d262a6595a112e25b73e878b0", + "1054741at2.faa:md5,cd4b928cba6b19b4437746ba507e7195", + "1093223at2.faa:md5,df9549708e5ffcfaee6a74dd70a0e5dc", + "1151822at2.faa:md5,12726afc1cdc40c13392e1596e93df3a", + "143460at2.faa:md5,d887431fd988a5556a523440f02d9594", + "1491686at2.faa:md5,d03362d19979b27306c192f1c74a84e5", + "1504821at2.faa:md5,4f5f6e5c57bac0092c1d85ded73d7e67", + "1574817at2.faa:md5,1153e55998c2929eacad2aed7d08d248", + "1592033at2.faa:md5,bb7a59e5f3a57ba12d10dabf4c77ab57", + "1623045at2.faa:md5,8fe38155feb1802beb97ef7714837bf5", + "1661836at2.faa:md5,6c6d592c2fbb0d7a4e5e1f47a15644f0", + "1674344at2.faa:md5,bb41b44e53565a54cadf0b780532fe08", + "1698718at2.faa:md5,f233860000028eb00329aa85236c71e5", + "1990650at2.faa:md5,34a2d29c5f8b6253159ddb7a43fa1829", + "223233at2.faa:md5,dec6705c7846c989296e73942f953cbc", + "402899at2.faa:md5,acc0f271f9a586d2ce1ee41669b22999", + "505485at2.faa:md5,aa0391f8fa5d9bd19b30d844d5a99845", + "665824at2.faa:md5,47f8ad43b6a6078206feb48c2e552793", + "776861at2.faa:md5,f8b90c13f7c6be828dea3bb920195e3d", + "874197at2.faa:md5,8d22a35a768debe6f376fc695d233a69", + "932854at2.faa:md5,2eff2de1ab83b22f3234a529a44e22bb", + "95696at2.faa:md5,247bfd1aef432f7b5456307768e9149c" + ], + "single_copy_proteins.faa:md5,73e2c5d6a9b0f01f2deea3cc5f21b764", + "versions.yml:md5,3fc94714b95c2dc15399a4229d9dd1d9" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-05-03T13:27:53.992893" + }, + "test_busco_protein": { + "content": [ + "test-bacteria_odb10-busco.batch_summary.txt:md5,f5a782378f9f94a748aa907381fdef91", + "full_table.tsv:md5,812ab6a0496fccab774643cf40c4f2a8", + "missing_busco_list.tsv:md5,aceb66e347a353cb7fca8e2a725f9112", + "versions.yml:md5,3fc94714b95c2dc15399a4229d9dd1d9" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-05-03T13:27:12.724862" + } +} \ No newline at end of file diff --git a/modules/nf-core/busco/busco/tests/nextflow.augustus.config b/modules/nf-core/busco/busco/tests/nextflow.augustus.config new file mode 100644 index 00000000..84daa69d --- /dev/null +++ b/modules/nf-core/busco/busco/tests/nextflow.augustus.config @@ -0,0 +1,5 @@ +process { + withName: 'BUSCO_BUSCO' { + ext.args = '--tar --augustus' + } +} diff --git a/modules/nf-core/busco/busco/tests/nextflow.config b/modules/nf-core/busco/busco/tests/nextflow.config new file mode 100644 index 00000000..1ec3fec0 --- /dev/null +++ b/modules/nf-core/busco/busco/tests/nextflow.config @@ -0,0 +1,5 @@ +process { + withName: 'BUSCO_BUSCO' { + ext.args = '--tar' + } +} diff --git a/modules/nf-core/busco/busco/tests/nextflow.metaeuk.config b/modules/nf-core/busco/busco/tests/nextflow.metaeuk.config new file mode 100644 index 00000000..c1418445 --- /dev/null +++ b/modules/nf-core/busco/busco/tests/nextflow.metaeuk.config @@ -0,0 +1,5 @@ +process { + withName: 'BUSCO_BUSCO' { + ext.args = '--tar --metaeuk' + } +} diff --git a/modules/nf-core/busco/busco/tests/old_test.yml b/modules/nf-core/busco/busco/tests/old_test.yml new file mode 100644 index 00000000..75177f5d --- /dev/null +++ b/modules/nf-core/busco/busco/tests/old_test.yml @@ -0,0 +1,624 @@ +- name: busco test_busco_genome_single_fasta + command: nextflow run ./tests/modules/nf-core/busco -entry test_busco_genome_single_fasta -c ./tests/config/nextflow.config + tags: + - busco + files: + - path: output/busco/short_summary.specific.bacteria_odb10.genome.fna.json + contains: + - "one_line_summary" + - "mode" + - "dataset" + - path: output/busco/short_summary.specific.bacteria_odb10.genome.fna.txt + contains: + - "BUSCO version" + - "The lineage dataset is" + - "BUSCO was run in mode" + - "Complete BUSCOs" + - "Missing BUSCOs" + - "Dependencies and versions" + - path: output/busco/test-bacteria_odb10-busco.batch_summary.txt + md5sum: bc2440f8a68d7fbf931ff911c1c3fdfa + - path: output/busco/test-bacteria_odb10-busco/genome.fna/logs/bbtools_err.log + - path: output/busco/test-bacteria_odb10-busco/genome.fna/logs/bbtools_out.log + md5sum: 9caf1a1434414c78562eb0bbb9c0e53f + - path: output/busco/test-bacteria_odb10-busco/genome.fna/logs/hmmsearch_err.log + - path: output/busco/test-bacteria_odb10-busco/genome.fna/logs/hmmsearch_out.log + contains: + - "# hmmsearch :: search profile(s) against a sequence database" + - "# target sequence database:" + - "Internal pipeline statistics summary:" + - "[ok]" + - path: output/busco/test-bacteria_odb10-busco/genome.fna/logs/prodigal_err.log + md5sum: 538510cfc7483498210f01e53fe035ad + - path: output/busco/test-bacteria_odb10-busco/genome.fna/logs/prodigal_out.log + md5sum: 61050b0706addc9498b2088a2d6efa9a + - path: output/busco/test-bacteria_odb10-busco/genome.fna/prodigal_output/.checkpoint + contains: + - "Tool: prodigal" + - "Completed" + - "jobs" + - path: output/busco/test-bacteria_odb10-busco/genome.fna/prodigal_output/predicted_genes/predicted.faa + md5sum: 836e9a80d33d8b89168f07ddc13ee991 + - path: output/busco/test-bacteria_odb10-busco/genome.fna/prodigal_output/predicted_genes/predicted.fna + md5sum: 20eeb75f86842e6e136f02bca8b73a9f + - path: output/busco/test-bacteria_odb10-busco/genome.fna/prodigal_output/predicted_genes/tmp/prodigal_mode_single_code_11.faa + md5sum: 836e9a80d33d8b89168f07ddc13ee991 + - path: output/busco/test-bacteria_odb10-busco/genome.fna/prodigal_output/predicted_genes/tmp/prodigal_mode_single_code_11.fna + md5sum: 20eeb75f86842e6e136f02bca8b73a9f + - path: output/busco/test-bacteria_odb10-busco/genome.fna/prodigal_output/predicted_genes/tmp/prodigal_mode_single_code_11_err.log + md5sum: 538510cfc7483498210f01e53fe035ad + - path: output/busco/test-bacteria_odb10-busco/genome.fna/prodigal_output/predicted_genes/tmp/prodigal_mode_single_code_11_out.log + md5sum: 61050b0706addc9498b2088a2d6efa9a + - path: output/busco/test-bacteria_odb10-busco/genome.fna/run_bacteria_odb10/.bbtools_output/.checkpoint + contains: + - "Tool: bbtools" + - "Completed" + - "jobs" + - path: output/busco/test-bacteria_odb10-busco/genome.fna/run_bacteria_odb10/busco_sequences/fragmented_busco_sequences.tar.gz + - path: output/busco/test-bacteria_odb10-busco/genome.fna/run_bacteria_odb10/busco_sequences/multi_copy_busco_sequences.tar.gz + - path: output/busco/test-bacteria_odb10-busco/genome.fna/run_bacteria_odb10/busco_sequences/single_copy_busco_sequences.tar.gz + - path: output/busco/test-bacteria_odb10-busco/genome.fna/run_bacteria_odb10/full_table.tsv + md5sum: c56edab1dc1522e993c25ae2b730799f + - path: output/busco/test-bacteria_odb10-busco/genome.fna/run_bacteria_odb10/hmmer_output.tar.gz + - path: output/busco/test-bacteria_odb10-busco/genome.fna/run_bacteria_odb10/missing_busco_list.tsv + md5sum: b533ef30270f27160acce85a22d01bf5 + - path: output/busco/test-bacteria_odb10-busco/genome.fna/run_bacteria_odb10/short_summary.json + contains: + - "one_line_summary" + - "mode" + - "lineage_dataset" + - path: output/busco/test-bacteria_odb10-busco/genome.fna/run_bacteria_odb10/short_summary.txt + contains: + - "# BUSCO version is:" + - "Results:" + - "busco:" + - path: output/busco/test-bacteria_odb10-busco/logs/busco.log + contains: + - "DEBUG:busco.run_BUSCO" + - "Results from dataset" + - "how to cite BUSCO" + - path: output/busco/versions.yml + +- name: busco test_busco_genome_multi_fasta + command: nextflow run ./tests/modules/nf-core/busco -entry test_busco_genome_multi_fasta -c ./tests/config/nextflow.config + tags: + - busco + files: + - path: output/busco/short_summary.specific.bacteria_odb10.genome.fasta.json + contains: + - "one_line_summary" + - "mode" + - "dataset" + - path: output/busco/short_summary.specific.bacteria_odb10.genome.fasta.txt + contains: + - "BUSCO version" + - "The lineage dataset is" + - "BUSCO was run in mode" + - "Complete BUSCOs" + - "Missing BUSCOs" + - "Dependencies and versions" + - path: output/busco/short_summary.specific.bacteria_odb10.genome.fna.json + contains: + - "one_line_summary" + - "mode" + - "dataset" + - path: output/busco/short_summary.specific.bacteria_odb10.genome.fna.txt + contains: + - "BUSCO version" + - "The lineage dataset is" + - "BUSCO was run in mode" + - "Complete BUSCOs" + - "Missing BUSCOs" + - "Dependencies and versions" + - path: output/busco/test-bacteria_odb10-busco.batch_summary.txt + md5sum: 8c64c1a28b086ef2ee444f99cbed5f7d + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/logs/bbtools_err.log + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/logs/bbtools_out.log + md5sum: 8f047bdb33264d22a83920bc2c63f29a + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/logs/hmmsearch_err.log + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/logs/hmmsearch_out.log + contains: + - "# hmmsearch :: search profile(s) against a sequence database" + - "# target sequence database:" + - "Internal pipeline statistics summary:" + - "[ok]" + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/logs/prodigal_err.log + md5sum: c1fdc6977332f53dfe7f632733bb4585 + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/logs/prodigal_out.log + md5sum: 50752acb1c5a20be886bfdfc06635bcb + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/prodigal_output/.checkpoint + contains: + - "Tool: prodigal" + - "Completed" + - "jobs" + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/prodigal_output/predicted_genes/predicted.faa + md5sum: 8166471fc5f08c82fd5643ab42327f9d + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/prodigal_output/predicted_genes/predicted.fna + md5sum: ddc508a18f60e7f3314534df50cdf8ca + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/prodigal_output/predicted_genes/tmp/prodigal_mode_single_code_11.faa + md5sum: 8166471fc5f08c82fd5643ab42327f9d + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/prodigal_output/predicted_genes/tmp/prodigal_mode_single_code_11.fna + md5sum: ddc508a18f60e7f3314534df50cdf8ca + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/prodigal_output/predicted_genes/tmp/prodigal_mode_single_code_11_err.log + md5sum: c1fdc6977332f53dfe7f632733bb4585 + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/prodigal_output/predicted_genes/tmp/prodigal_mode_single_code_11_out.log + md5sum: 50752acb1c5a20be886bfdfc06635bcb + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/prodigal_output/predicted_genes/tmp/prodigal_mode_single_code_4.faa + md5sum: e56fd59c38248dc21ac94355dca98121 + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/prodigal_output/predicted_genes/tmp/prodigal_mode_single_code_4.fna + md5sum: b365f84bf99c68357952e0b98ed7ce42 + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/prodigal_output/predicted_genes/tmp/prodigal_mode_single_code_4_err.log + md5sum: e5f14d7925ba14a0f9850542f3739894 + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/prodigal_output/predicted_genes/tmp/prodigal_mode_single_code_4_out.log + md5sum: d41971bfc1b621d4ffd2633bc47017ea + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/run_bacteria_odb10/.bbtools_output/.checkpoint + contains: + - "Tool: bbtools" + - "Completed" + - "jobs" + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/run_bacteria_odb10/busco_sequences/fragmented_busco_sequences.tar.gz + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/run_bacteria_odb10/busco_sequences/multi_copy_busco_sequences.tar.gz + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/run_bacteria_odb10/busco_sequences/single_copy_busco_sequences.tar.gz + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/run_bacteria_odb10/full_table.tsv + md5sum: c9651b88b10871abc260ee655898e828 + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/run_bacteria_odb10/hmmer_output.tar.gz + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/run_bacteria_odb10/missing_busco_list.tsv + md5sum: 9939309df2da5419de88c32d1435c779 + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/run_bacteria_odb10/short_summary.json + contains: + - "one_line_summary" + - "mode" + - "dataset" + - path: output/busco/test-bacteria_odb10-busco/genome.fasta/run_bacteria_odb10/short_summary.txt + contains: + - "# BUSCO version is:" + - "Results:" + - "busco:" + - path: output/busco/test-bacteria_odb10-busco/genome.fna/logs/bbtools_err.log + - path: output/busco/test-bacteria_odb10-busco/genome.fna/logs/bbtools_out.log + md5sum: 9caf1a1434414c78562eb0bbb9c0e53f + - path: output/busco/test-bacteria_odb10-busco/genome.fna/logs/hmmsearch_err.log + - path: output/busco/test-bacteria_odb10-busco/genome.fna/logs/hmmsearch_out.log + contains: + - "# hmmsearch :: search profile(s) against a sequence database" + - "# target sequence database:" + - "Internal pipeline statistics summary:" + - "[ok]" + - path: output/busco/test-bacteria_odb10-busco/genome.fna/logs/prodigal_err.log + md5sum: 538510cfc7483498210f01e53fe035ad + - path: output/busco/test-bacteria_odb10-busco/genome.fna/logs/prodigal_out.log + md5sum: 61050b0706addc9498b2088a2d6efa9a + - path: output/busco/test-bacteria_odb10-busco/genome.fna/prodigal_output/.checkpoint + contains: + - "Tool: prodigal" + - "Completed" + - "jobs" + - path: output/busco/test-bacteria_odb10-busco/genome.fna/prodigal_output/predicted_genes/predicted.faa + md5sum: 836e9a80d33d8b89168f07ddc13ee991 + - path: output/busco/test-bacteria_odb10-busco/genome.fna/prodigal_output/predicted_genes/predicted.fna + md5sum: 20eeb75f86842e6e136f02bca8b73a9f + - path: output/busco/test-bacteria_odb10-busco/genome.fna/prodigal_output/predicted_genes/tmp/prodigal_mode_single_code_11.faa + md5sum: 836e9a80d33d8b89168f07ddc13ee991 + - path: output/busco/test-bacteria_odb10-busco/genome.fna/prodigal_output/predicted_genes/tmp/prodigal_mode_single_code_11.fna + md5sum: 20eeb75f86842e6e136f02bca8b73a9f + - path: output/busco/test-bacteria_odb10-busco/genome.fna/prodigal_output/predicted_genes/tmp/prodigal_mode_single_code_11_err.log + md5sum: 538510cfc7483498210f01e53fe035ad + - path: output/busco/test-bacteria_odb10-busco/genome.fna/prodigal_output/predicted_genes/tmp/prodigal_mode_single_code_11_out.log + md5sum: 61050b0706addc9498b2088a2d6efa9a + - path: output/busco/test-bacteria_odb10-busco/genome.fna/run_bacteria_odb10/.bbtools_output/.checkpoint + contains: + - "Tool: bbtools" + - "Completed" + - "jobs" + - path: output/busco/test-bacteria_odb10-busco/genome.fna/run_bacteria_odb10/busco_sequences/fragmented_busco_sequences.tar.gz + - path: output/busco/test-bacteria_odb10-busco/genome.fna/run_bacteria_odb10/busco_sequences/multi_copy_busco_sequences.tar.gz + - path: output/busco/test-bacteria_odb10-busco/genome.fna/run_bacteria_odb10/busco_sequences/single_copy_busco_sequences.tar.gz + - path: output/busco/test-bacteria_odb10-busco/genome.fna/run_bacteria_odb10/full_table.tsv + md5sum: c56edab1dc1522e993c25ae2b730799f + - path: output/busco/test-bacteria_odb10-busco/genome.fna/run_bacteria_odb10/hmmer_output.tar.gz + - path: output/busco/test-bacteria_odb10-busco/genome.fna/run_bacteria_odb10/missing_busco_list.tsv + md5sum: b533ef30270f27160acce85a22d01bf5 + - path: output/busco/test-bacteria_odb10-busco/genome.fna/run_bacteria_odb10/short_summary.json + contains: + - "one_line_summary" + - "mode" + - "dataset" + - path: output/busco/test-bacteria_odb10-busco/genome.fna/run_bacteria_odb10/short_summary.txt + contains: + - "# BUSCO version is:" + - "Results:" + - "busco:" + - path: output/busco/test-bacteria_odb10-busco/logs/busco.log + contains: + - "DEBUG:busco.run_BUSCO" + - "Results from dataset" + - "how to cite BUSCO" + - path: output/busco/versions.yml + +- name: busco test_busco_eukaryote_metaeuk + command: nextflow run ./tests/modules/nf-core/busco -entry test_busco_eukaryote_metaeuk -c ./tests/config/nextflow.config + tags: + - busco + files: + - path: output/busco/short_summary.specific.eukaryota_odb10.genome.fasta.json + contains: + - "one_line_summary" + - "mode" + - "dataset" + - path: output/busco/short_summary.specific.eukaryota_odb10.genome.fasta.txt + contains: + - "BUSCO version" + - "The lineage dataset is" + - "BUSCO was run in mode" + - "Complete BUSCOs" + - "Missing BUSCOs" + - "Dependencies and versions" + - path: output/busco/test-eukaryota_odb10-busco.batch_summary.txt + md5sum: ff6d8277e452a83ce9456bbee666feb6 + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/logs/bbtools_err.log + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/logs/bbtools_out.log + md5sum: e63debaa653f18f7405d936050abc093 + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/logs/hmmsearch_err.log + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/logs/hmmsearch_out.log + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/logs/metaeuk_run1_err.log + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/logs/metaeuk_run1_out.log + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/logs/metaeuk_run2_err.log + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/logs/metaeuk_run2_out.log + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/.bbtools_output/.checkpoint + contains: + - "Tool: bbtools" + - "Completed" + - "jobs" + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/busco_sequences/fragmented_busco_sequences.tar.gz + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/busco_sequences/multi_copy_busco_sequences.tar.gz + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/busco_sequences/single_copy_busco_sequences.tar.gz + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/full_table.tsv + md5sum: bd880e90b9e5620a58943a3e0f9ff16b + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/hmmer_output.tar.gz + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/metaeuk_output/.checkpoint + contains: + - "Tool: metaeuk" + - "Completed" + - "jobs" + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/metaeuk_output/combined_pred_proteins.fas + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/metaeuk_output/initial_results/genome.fasta.codon.fas + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/metaeuk_output/initial_results/genome.fasta.fas + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/metaeuk_output/initial_results/genome.fasta.gff + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/metaeuk_output/initial_results/genome.fasta.headersMap.tsv + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/metaeuk_output/refseq_db_rerun.faa + md5sum: d80b8fa4cb5ed0d47d63d6aa93635bc2 + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/metaeuk_output/rerun_results/genome.fasta.codon.fas + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/metaeuk_output/rerun_results/genome.fasta.fas + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/metaeuk_output/rerun_results/genome.fasta.gff + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/metaeuk_output/rerun_results/genome.fasta.headersMap.tsv + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/missing_busco_list.tsv + md5sum: 1e8e79c540fd2e69ba0d2659d9eb2988 + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/short_summary.json + contains: + - "one_line_summary" + - "mode" + - "dataset" + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/short_summary.txt + contains: + - "# BUSCO version is:" + - "Results:" + - "busco:" + - path: output/busco/test-eukaryota_odb10-busco/logs/busco.log + contains: + - "DEBUG:busco.run_BUSCO" + - "Results from dataset" + - "how to cite BUSCO" + - path: output/busco/versions.yml + +- name: busco test_busco_eukaryote_augustus + command: nextflow run ./tests/modules/nf-core/busco -entry test_busco_eukaryote_augustus -c ./tests/config/nextflow.config + tags: + - busco + files: + - path: output/busco/short_summary.specific.eukaryota_odb10.genome.fasta.json + contains: + - "one_line_summary" + - "mode" + - "dataset" + - path: output/busco/short_summary.specific.eukaryota_odb10.genome.fasta.txt + contains: + - "BUSCO version" + - "The lineage dataset is" + - "BUSCO was run in mode" + - "Complete BUSCOs" + - "Missing BUSCOs" + - "Dependencies and versions" + - path: output/busco/test-eukaryota_odb10-busco.batch_summary.txt + md5sum: ff6d8277e452a83ce9456bbee666feb6 + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/logs/bbtools_err.log + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/logs/bbtools_out.log + md5sum: e63debaa653f18f7405d936050abc093 + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/logs/hmmsearch_err.log + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/logs/hmmsearch_out.log + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/logs/metaeuk_run1_err.log + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/logs/metaeuk_run1_out.log + contains: + - "metaeuk" + - "easy-predict" + - "Compute score and coverage" + - "Time for processing:" + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/logs/metaeuk_run2_err.log + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/logs/metaeuk_run2_out.log + contains: + - "metaeuk" + - "easy-predict" + - "Compute score and coverage" + - "Time for processing:" + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/.bbtools_output/.checkpoint + contains: + - "Tool: bbtools" + - "Completed" + - "jobs" + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/busco_sequences/fragmented_busco_sequences.tar.gz + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/busco_sequences/multi_copy_busco_sequences.tar.gz + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/busco_sequences/single_copy_busco_sequences.tar.gz + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/full_table.tsv + md5sum: bd880e90b9e5620a58943a3e0f9ff16b + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/hmmer_output.tar.gz + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/metaeuk_output/.checkpoint + contains: + - "Tool: metaeuk" + - "Completed" + - "jobs" + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/metaeuk_output/combined_pred_proteins.fas + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/metaeuk_output/initial_results/genome.fasta.codon.fas + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/metaeuk_output/initial_results/genome.fasta.fas + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/metaeuk_output/initial_results/genome.fasta.gff + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/metaeuk_output/initial_results/genome.fasta.headersMap.tsv + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/metaeuk_output/refseq_db_rerun.faa + md5sum: d80b8fa4cb5ed0d47d63d6aa93635bc2 + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/metaeuk_output/rerun_results/genome.fasta.codon.fas + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/metaeuk_output/rerun_results/genome.fasta.fas + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/metaeuk_output/rerun_results/genome.fasta.gff + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/metaeuk_output/rerun_results/genome.fasta.headersMap.tsv + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/missing_busco_list.tsv + md5sum: 1e8e79c540fd2e69ba0d2659d9eb2988 + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/short_summary.json + contains: + - "one_line_summary" + - "mode" + - "dataset" + - path: output/busco/test-eukaryota_odb10-busco/genome.fasta/run_eukaryota_odb10/short_summary.txt + contains: + - "# BUSCO version is:" + - "Results:" + - "busco:" + - path: output/busco/test-eukaryota_odb10-busco/logs/busco.log + contains: + - "DEBUG:busco.run_BUSCO" + - "Results from dataset" + - "how to cite BUSCO" + - path: output/busco/versions.yml + +- name: busco test_busco_protein + command: nextflow run ./tests/modules/nf-core/busco -entry test_busco_protein -c ./tests/config/nextflow.config + tags: + - busco + files: + - path: output/busco/short_summary.specific.bacteria_odb10.proteome.fasta.json + contains: + - "one_line_summary" + - "mode" + - "dataset" + - path: output/busco/short_summary.specific.bacteria_odb10.proteome.fasta.txt + contains: + - "BUSCO version" + - "The lineage dataset is" + - "BUSCO was run in mode" + - "Complete BUSCOs" + - "Missing BUSCOs" + - "Dependencies and versions" + - path: output/busco/test-bacteria_odb10-busco.batch_summary.txt + md5sum: 7a65e6cbb6c56a2ea4e739ae0aa3297d + - path: output/busco/test-bacteria_odb10-busco/logs/busco.log + contains: + - "DEBUG:busco.run_BUSCO" + - "Results from dataset" + - "how to cite BUSCO" + - path: output/busco/test-bacteria_odb10-busco/proteome.fasta/logs/hmmsearch_err.log + - path: output/busco/test-bacteria_odb10-busco/proteome.fasta/logs/hmmsearch_out.log + contains: + - "# hmmsearch :: search profile(s) against a sequence database" + - "# target sequence database:" + - "Internal pipeline statistics summary:" + - "[ok]" + - path: output/busco/test-bacteria_odb10-busco/proteome.fasta/run_bacteria_odb10/busco_sequences/fragmented_busco_sequences.tar.gz + - path: output/busco/test-bacteria_odb10-busco/proteome.fasta/run_bacteria_odb10/busco_sequences/multi_copy_busco_sequences.tar.gz + - path: output/busco/test-bacteria_odb10-busco/proteome.fasta/run_bacteria_odb10/busco_sequences/single_copy_busco_sequences.tar.gz + - path: output/busco/test-bacteria_odb10-busco/proteome.fasta/run_bacteria_odb10/full_table.tsv + md5sum: 0e34f1011cd83ea1d5d5103ec62b8922 + - path: output/busco/test-bacteria_odb10-busco/proteome.fasta/run_bacteria_odb10/hmmer_output.tar.gz + - path: output/busco/test-bacteria_odb10-busco/proteome.fasta/run_bacteria_odb10/missing_busco_list.tsv + md5sum: 9939309df2da5419de88c32d1435c779 + - path: output/busco/test-bacteria_odb10-busco/proteome.fasta/run_bacteria_odb10/short_summary.json + contains: + - "one_line_summary" + - "mode" + - "dataset" + - path: output/busco/test-bacteria_odb10-busco/proteome.fasta/run_bacteria_odb10/short_summary.txt + contains: + - "# BUSCO version is:" + - "Results:" + - "busco:" + - path: output/busco/versions.yml + +- name: busco test_busco_transcriptome + command: nextflow run ./tests/modules/nf-core/busco -entry test_busco_transcriptome -c ./tests/config/nextflow.config + tags: + - busco + files: + - path: output/busco/short_summary.specific.bacteria_odb10.test1.contigs.fa.json + contains: + - "one_line_summary" + - "mode" + - "dataset" + - path: output/busco/short_summary.specific.bacteria_odb10.test1.contigs.fa.txt + contains: + - "BUSCO version" + - "The lineage dataset is" + - "BUSCO was run in mode" + - "Complete BUSCOs" + - "Missing BUSCOs" + - "Dependencies and versions" + - path: output/busco/test-bacteria_odb10-busco.batch_summary.txt + md5sum: 46118ecf60d1b87d22b96d80f4f03632 + - path: output/busco/test-bacteria_odb10-busco/logs/busco.log + contains: + - "DEBUG:busco.run_BUSCO" + - "Results from dataset" + - "how to cite BUSCO" + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/blast_db/.checkpoint + contains: + - "Tool: makeblastdb" + - "Completed" + - "jobs" + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/blast_db/test1.contigs.fa.ndb + md5sum: 3788c017fe5e6f0f58224e9cdd21822b + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/blast_db/test1.contigs.fa.nhr + md5sum: 8ecd2ce392bb5e25ddbe1d85f879582e + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/blast_db/test1.contigs.fa.nin + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/blast_db/test1.contigs.fa.njs + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/blast_db/test1.contigs.fa.not + md5sum: 0c340e376c7e85d19f82ec1a833e6a6e + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/blast_db/test1.contigs.fa.nsq + md5sum: 532d5c0a7ea00fe95ca3c97cb3be6198 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/blast_db/test1.contigs.fa.ntf + md5sum: de1250813f0c7affc6d12dac9d0fb6bb + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/blast_db/test1.contigs.fa.nto + md5sum: ff74bd41f9cc9b011c63a32c4f7693bf + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/logs/hmmsearch_err.log + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/logs/hmmsearch_out.log + contains: + - "# hmmsearch :: search profile(s) against a sequence database" + - "# target sequence database:" + - "Internal pipeline statistics summary:" + - "[ok]" + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/logs/makeblastdb_err.log + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/logs/makeblastdb_out.log + contains: + - "Building a new DB" + - "Adding sequences from FASTA" + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/logs/tblastn_err.log + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/logs/tblastn_out.log + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/.checkpoint + contains: + - "Tool: tblastn" + - "Completed" + - "jobs" + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/coordinates.tsv + md5sum: cc30eed321944af293452bdbcfc24292 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/sequences/k141_101.temp + md5sum: 73e9c65fc83fedc58f57f09b08f08238 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/sequences/k141_119.temp + md5sum: 7fa4cc7955ec0cc36330a221c579b975 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/sequences/k141_129.temp + md5sum: 6f1601c875d019e3f6f1f98ed8e988d4 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/sequences/k141_138.temp + md5sum: 3f8e034686cd240c2330650d791bcae2 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/sequences/k141_143.temp + md5sum: df3dfa8e9ba30ed70cf75b5e7abf2179 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/sequences/k141_172.temp + md5sum: 7d463e0e6cf7169bc9077d8dc776dda1 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/sequences/k141_178.temp + md5sum: 2288edf7fa4f88f51b4cf4d94086f77e + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/sequences/k141_188.temp + md5sum: 029906abbad6d87fc57830dd548cac24 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/sequences/k141_195.temp + md5sum: 4937f3b348774a31b1160a00297c29cc + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/sequences/k141_210.temp + md5sum: afcb20ba4c466479d6b91c8c62251e1f + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/sequences/k141_232.temp + md5sum: 2e1e823ce017345bd998191a39fa9924 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/sequences/k141_268.temp + md5sum: 08c2d82c34ecffbe1c638b410349412e + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/sequences/k141_29.temp + md5sum: cd9b63cf93524284781535c888313764 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/sequences/k141_44.temp + md5sum: d1929b742b24ebe379bf4801ca882dca + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/sequences/k141_58.temp + md5sum: 69215765b010c05336538cb322c900b3 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/sequences/k141_72.temp + md5sum: 6feaa1cc3b0899a147ea9d466878f3e3 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/sequences/k141_80.temp + md5sum: 13625eae14e860a96ce17cd4e37e9d01 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/sequences/k141_81.temp + md5sum: e14b2484649b0dbc8926815c207b806d + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/sequences/k141_93.temp + md5sum: 6902c93691df00e690faea914c71839e + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/sequences/k141_97.temp + md5sum: 0a0d9d38a83acbd5ad43c29cdf429988 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/blast_output/tblastn.tsv + contains: + - "TBLASTN" + - "BLAST processed" + - "queries" + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/busco_sequences/fragmented_busco_sequences.tar.gz + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/busco_sequences/multi_copy_busco_sequences.tar.gz + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/busco_sequences/single_copy_busco_sequences.tar.gz + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/full_table.tsv + md5sum: 24df25199e13c88bd892fc3e7b541ca0 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/hmmer_output.tar.gz + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/missing_busco_list.tsv + md5sum: e7232e2b8cca4fdfdd9e363b39ebbc81 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/short_summary.json + contains: + - "one_line_summary" + - "mode" + - "dataset" + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/short_summary.txt + contains: + - "# BUSCO version is:" + - "Results:" + - "busco:" + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/run_bacteria_odb10/single_copy_proteins.faa + md5sum: e04b9465733577ae6e4bccb7aa01e720 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/translated_proteins/1024388at2.faa + md5sum: 7333c39a20258f20c7019ea0cd83157c + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/translated_proteins/1054741at2.faa + md5sum: ebb481e77a824685fbe04d8a2f3a0d7d + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/translated_proteins/1093223at2.faa + md5sum: 34621c7d499034e8f8e6b92fd4020a93 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/translated_proteins/1151822at2.faa + md5sum: aa89ca381c1c70c9c4e1380351ca7c2a + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/translated_proteins/143460at2.faa + md5sum: f2e91d78b8dd3722840378789f29e8c8 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/translated_proteins/1491686at2.faa + md5sum: 73c25aef5c9cba7f4151804941b146ea + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/translated_proteins/1504821at2.faa + md5sum: cda556018d1f84ebe517e89f6fc107d0 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/translated_proteins/1574817at2.faa + md5sum: a9096c9fb8b25c78a72871ab0463acdc + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/translated_proteins/1592033at2.faa + md5sum: e463d25ce186c0cebfd749474f3a4c64 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/translated_proteins/1623045at2.faa + md5sum: f2cfd241590c6d8377286d6135480937 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/translated_proteins/1661836at2.faa + md5sum: 586569546fb9861502468e3d9ba2775c + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/translated_proteins/1674344at2.faa + md5sum: 24c658bee14ad84b062d81ad96642eb8 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/translated_proteins/1698718at2.faa + md5sum: 0b8e26ddf5149bbd8805be7af125208d + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/translated_proteins/1990650at2.faa + md5sum: 159320712ee01fb2ccb31a25df44eead + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/translated_proteins/223233at2.faa + md5sum: 812629c0b06ac3d18661c2ca78de0c08 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/translated_proteins/402899at2.faa + md5sum: f7ff4e1591342d30b77392a2e84b57d9 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/translated_proteins/505485at2.faa + md5sum: 7b34a24fc49c540d46fcf96ff5129564 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/translated_proteins/665824at2.faa + md5sum: 4cff2df64f6bcaff8bc19c234c8bcccd + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/translated_proteins/776861at2.faa + md5sum: 613af7a3fea30ea2bece66f603b9284a + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/translated_proteins/874197at2.faa + md5sum: a7cd1b13c9ef91c7ef4e31614166f197 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/translated_proteins/932854at2.faa + md5sum: fe313ffd5efdb0fed887a04fba352552 + - path: output/busco/test-bacteria_odb10-busco/test1.contigs.fa/translated_proteins/95696at2.faa + md5sum: 4e1f30a2fea4dfbf9bb7fae2700622a0 + - path: output/busco/versions.yml diff --git a/modules/nf-core/busco/busco/tests/tags.yml b/modules/nf-core/busco/busco/tests/tags.yml new file mode 100644 index 00000000..7c4d2835 --- /dev/null +++ b/modules/nf-core/busco/busco/tests/tags.yml @@ -0,0 +1,2 @@ +busco/busco: + - "modules/nf-core/busco/busco/**" diff --git a/modules/nf-core/busco/meta.yml b/modules/nf-core/busco/meta.yml deleted file mode 100644 index 90b30d4d..00000000 --- a/modules/nf-core/busco/meta.yml +++ /dev/null @@ -1,96 +0,0 @@ -name: busco -description: Benchmarking Universal Single Copy Orthologs -keywords: - - quality control - - genome - - transcriptome - - proteome -tools: - - busco: - description: BUSCO provides measures for quantitative assessment of genome assembly, gene set, and transcriptome completeness based on evolutionarily informed expectations of gene content from near-universal single-copy orthologs selected from OrthoDB. - homepage: https://busco.ezlab.org/ - documentation: https://busco.ezlab.org/busco_userguide.html - tool_dev_url: https://gitlab.com/ezlab/busco - doi: "10.1007/978-1-4939-9173-0_14" - licence: ["MIT"] -input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - fasta: - type: file - description: Nucleic or amino acid sequence file in FASTA format. - pattern: "*.{fasta,fna,fa,fasta.gz,fna.gz,fa.gz}" - - mode: - type: string - description: The mode to run Busco in. One of genome, proteins, or transcriptome - pattern: "{genome,proteins,transcriptome}" - - lineage: - type: string - description: The BUSCO lineage to use, or "auto" to automatically select lineage - - busco_lineages_path: - type: directory - description: Path to local BUSCO lineages directory. - - config_file: - type: file - description: Path to BUSCO config file. -output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - batch_summary: - type: file - description: Summary of all sequence files analyzed - pattern: "*-busco.batch_summary.txt" - - short_summaries_txt: - type: file - description: Short Busco summary in plain text format - pattern: "short_summary.*.txt" - - short_summaries_json: - type: file - description: Short Busco summary in JSON format - pattern: "short_summary.*.json" - - busco_dir: - type: directory - description: BUSCO lineage specific output - pattern: "*-busco" - - full_table: - type: file - description: Full BUSCO results table - pattern: "full_table.tsv" - - missing_busco_list: - type: file - description: List of missing BUSCOs - pattern: "missing_busco_list.tsv" - - single_copy_proteins: - type: file - description: Fasta file of single copy proteins (transcriptome mode) - pattern: "single_copy_proteins.faa" - - seq_dir: - type: directory - description: BUSCO sequence directory - pattern: "busco_sequences" - - translated_proteins: - type: directory - description: Six frame translations of each transcript made by the transcriptome mode - pattern: "translated_proteins" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" -authors: - - "@priyanka-surana" - - "@charles-plessy" - - "@mahesh-panchal" - - "@muffato" - - "@jvhagey" -maintainers: - - "@priyanka-surana" - - "@charles-plessy" - - "@mahesh-panchal" - - "@muffato" - - "@jvhagey" diff --git a/subworkflows/local/annotation_statistics.nf b/subworkflows/local/annotation_statistics.nf index 41ab6c42..1cc5d64a 100644 --- a/subworkflows/local/annotation_statistics.nf +++ b/subworkflows/local/annotation_statistics.nf @@ -4,7 +4,7 @@ include { AGAT_SPSTATISTICS } from '../../modules/nf include { AGAT_SQSTATBASIC } from '../../modules/nf-core/agat/sqstatbasic/main' include { GUNZIP } from '../../modules/nf-core/gunzip/main' include { EXTRACT_ANNOTATION_STATISTICS_INFO } from '../../modules/local/extract_annotation_statistics_info.nf' -include { BUSCO as BUSCOPROTEINS } from '../../modules/nf-core/busco/main' +include { BUSCO_BUSCO as BUSCOPROTEINS } from '../../modules/nf-core/busco/busco/main' include { NCBIDATASETS_SUMMARYGENOME as SUMMARYGENOME } from '../../modules/local/ncbidatasets/summarygenome' include { GFFREAD } from '../../modules/nf-core/gffread/main' include { NCBI_GET_ODB } from '../../modules/local/ncbidatasets/get_odb' @@ -16,13 +16,13 @@ workflow ANNOTATION_STATISTICS { genome // channel: [ meta, fasta ] lineage_tax_ids // channel: /path/to/lineage_tax_ids lineage_db // channel: /path/to/buscoDB - + main: ch_versions = Channel.empty() // Map the GFF channel to create a tuple with metadata and the file gff - | map { file -> + | map { file -> [ [ 'id': params.assembly + '_annotation', 'ext': "gff", 'filename': file.baseName ], file ] } | set { ch_gff_tupple } @@ -58,7 +58,7 @@ workflow ANNOTATION_STATISTICS { // Get ODB lineage value NCBI_GET_ODB ( SUMMARYGENOME.out.summary, lineage_tax_ids ) ch_versions = ch_versions.mix ( NCBI_GET_ODB.out.versions.first() ) - + // BUSCO NCBI_GET_ODB.out.csv | map { meta, csv -> csv } @@ -70,13 +70,13 @@ workflow ANNOTATION_STATISTICS { BUSCOPROTEINS(GFFREAD.out.gffread_fasta, 'proteins', ch_lineage, lineage_db.ifEmpty([]), [] ) ch_versions = ch_versions.mix ( BUSCOPROTEINS.out.versions.first() ) - // Parsing the stats_txt files as input channels + // Parsing the stats_txt files as input channels EXTRACT_ANNOTATION_STATISTICS_INFO( - AGAT_SQSTATBASIC.out.stats_txt, + AGAT_SQSTATBASIC.out.stats_txt, AGAT_SPSTATISTICS.out.stats_txt, BUSCOPROTEINS.out.short_summaries_json ) - + ch_versions = ch_versions.mix( EXTRACT_ANNOTATION_STATISTICS_INFO.out.versions.first() ) emit: diff --git a/subworkflows/local/genome_statistics.nf b/subworkflows/local/genome_statistics.nf index 73a7e2ba..9ac06b94 100644 --- a/subworkflows/local/genome_statistics.nf +++ b/subworkflows/local/genome_statistics.nf @@ -5,7 +5,7 @@ include { NCBIDATASETS_SUMMARYGENOME as SUMMARYGENOME } from '../../modules/local/ncbidatasets/summarygenome' include { NCBIDATASETS_SUMMARYGENOME as SUMMARYSEQUENCE } from '../../modules/local/ncbidatasets/summarygenome' include { NCBI_GET_ODB } from '../../modules/local/ncbidatasets/get_odb' -include { BUSCO } from '../../modules/nf-core/busco/main' +include { BUSCO_BUSCO as BUSCO } from '../../modules/nf-core/busco/busco/main' include { RESTRUCTUREBUSCODIR } from '../../modules/local/restructurebuscodir' include { FASTK_FASTK } from '../../modules/nf-core/fastk/fastk/main' include { MERQURYFK_MERQURYFK } from '../../modules/nf-core/merquryfk/merquryfk/main' @@ -46,7 +46,7 @@ workflow GENOME_STATISTICS { | splitCsv() | map { row -> row[1] } | set { ch_lineage } - + BUSCO ( genome, "genome", ch_lineage, lineage_db.ifEmpty([]), [] ) ch_versions = ch_versions.mix ( BUSCO.out.versions.first() ) @@ -87,7 +87,7 @@ workflow GENOME_STATISTICS { FASTK_FASTK.out.hist | join ( FASTK_FASTK.out.ktab ) | set { ch_combo } - + ch_pacbio.dir | map { meta, dir -> [ meta, @@ -95,7 +95,7 @@ workflow GENOME_STATISTICS { dir.listFiles().findAll { it.toString().contains(".ktab") } .collect(), ] } | set { ch_grab } - + ch_combo | mix ( ch_grab ) | combine ( genome ) @@ -112,11 +112,11 @@ workflow GENOME_STATISTICS { SUMMARYGENOME.out.summary | join ( SUMMARYSEQUENCE.out.summary ) | set { ch_summary } - + BUSCO.out.short_summaries_json | ifEmpty ( [ [], [] ] ) | set { ch_busco } - + MERQURYFK_MERQURYFK.out.qv | join ( MERQURYFK_MERQURYFK.out.stats ) | map { meta, qv, comp -> [ meta + [ id: "merq" ], qv, comp ] } From 798369b5a24a5785b2ec8f4a98c929598b5061e9 Mon Sep 17 00:00:00 2001 From: Tyler Chafin Date: Fri, 22 Nov 2024 16:38:27 +0000 Subject: [PATCH 117/132] nf-core/cooler updated --- modules.json | 68 +++++----------- modules/nf-core/cooler/cload/environment.yml | 5 ++ modules/nf-core/cooler/cload/main.nf | 17 +++- modules/nf-core/cooler/cload/meta.yml | 77 ++++++++++--------- modules/nf-core/cooler/dump/environment.yml | 5 ++ modules/nf-core/cooler/dump/main.nf | 18 ++++- modules/nf-core/cooler/dump/meta.yml | 59 +++++++------- .../nf-core/cooler/dump/tests/main.nf.test | 60 +++++++++++++++ .../cooler/dump/tests/main.nf.test.snap | 68 ++++++++++++++++ .../nf-core/cooler/zoomify/environment.yml | 5 ++ modules/nf-core/cooler/zoomify/main.nf | 17 +++- modules/nf-core/cooler/zoomify/meta.yml | 52 +++++++------ 12 files changed, 307 insertions(+), 144 deletions(-) create mode 100644 modules/nf-core/cooler/cload/environment.yml create mode 100644 modules/nf-core/cooler/dump/environment.yml create mode 100644 modules/nf-core/cooler/dump/tests/main.nf.test create mode 100644 modules/nf-core/cooler/dump/tests/main.nf.test.snap create mode 100644 modules/nf-core/cooler/zoomify/environment.yml diff --git a/modules.json b/modules.json index 0a622365..2abe2959 100644 --- a/modules.json +++ b/modules.json @@ -8,113 +8,83 @@ "agat/spstatistics": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "agat/sqstatbasic": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "bedtools/bamtobed": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "busco/busco": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ], + "installed_by": ["modules"], "patch": "modules/nf-core/busco/busco/busco-busco.diff" }, "cooler/cload": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": [ - "modules" - ] + "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", + "installed_by": ["modules"] }, "cooler/dump": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": [ - "modules" - ] + "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", + "installed_by": ["modules"] }, "cooler/zoomify": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": [ - "modules" - ] + "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", + "installed_by": ["modules"] }, "custom/dumpsoftwareversions": { "branch": "master", "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "fastk/fastk": { "branch": "master", "git_sha": "0f8a77ff00e65eaeebc509b8156eaa983192474b", - "installed_by": [ - "modules" - ], + "installed_by": ["modules"], "patch": "modules/nf-core/fastk/fastk/fastk-fastk.diff" }, "gffread": { "branch": "master", "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "gnu/sort": { "branch": "master", "git_sha": "88f6e982fb8bd40488d837b3b08a65008e602840", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "gunzip": { "branch": "master", "git_sha": "5c460c5a4736974abde2843294f35307ee2b0e5e", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "merquryfk/merquryfk": { "branch": "master", "git_sha": "0f8a77ff00e65eaeebc509b8156eaa983192474b", - "installed_by": [ - "modules" - ], + "installed_by": ["modules"], "patch": "modules/nf-core/merquryfk/merquryfk/merquryfk-merquryfk.diff" }, "multiqc": { "branch": "master", "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "samtools/view": { "branch": "master", "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] } } } } } -} \ No newline at end of file +} diff --git a/modules/nf-core/cooler/cload/environment.yml b/modules/nf-core/cooler/cload/environment.yml new file mode 100644 index 00000000..f8165ca9 --- /dev/null +++ b/modules/nf-core/cooler/cload/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::cooler=0.9.2 diff --git a/modules/nf-core/cooler/cload/main.nf b/modules/nf-core/cooler/cload/main.nf index 80109d48..b170a5d0 100644 --- a/modules/nf-core/cooler/cload/main.nf +++ b/modules/nf-core/cooler/cload/main.nf @@ -2,10 +2,10 @@ process COOLER_CLOAD { tag "$meta.id" label 'process_high' - conda "bioconda::cooler=0.8.11" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/cooler:0.8.11--pyh3252c3a_0' : - 'biocontainers/cooler:0.8.11--pyh3252c3a_0' }" + 'https://depot.galaxyproject.org/singularity/cooler:0.9.2--pyh7cba7a3_0' : + 'biocontainers/cooler:0.9.2--pyh7cba7a3_0' }" input: tuple val(meta), path(pairs), path(index), val(cool_bin) @@ -36,4 +36,15 @@ process COOLER_CLOAD { cooler: \$(cooler --version 2>&1 | sed 's/cooler, version //') END_VERSIONS """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.cool + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + cooler: \$(cooler --version 2>&1 | sed 's/cooler, version //') + END_VERSIONS + """ } diff --git a/modules/nf-core/cooler/cload/meta.yml b/modules/nf-core/cooler/cload/meta.yml index 8513aaec..1bb9f748 100644 --- a/modules/nf-core/cooler/cload/meta.yml +++ b/modules/nf-core/cooler/cload/meta.yml @@ -2,6 +2,9 @@ name: cooler_cload description: Create a cooler from genomic pairs and bins keywords: - cool + - cooler + - cload + - hic tools: - cooler: description: Sparse binary format for genomic interaction matrices @@ -10,44 +13,48 @@ tools: tool_dev_url: https://github.com/open2c/cooler doi: "10.1093/bioinformatics/btz540" licence: ["BSD-3-clause"] - + identifier: "" input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - pairs: - type: file - description: Path to contacts (i.e. read pairs) file. - - index: - type: file - description: Path to index file of the contacts. - - cool_bin: - type: value - description: Bins size in bp - - chromsizes: - type: file - description: Path to a chromsizes file. - + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - pairs: + type: file + description: Path to contacts (i.e. read pairs) file. + - index: + type: file + description: Path to index file of the contacts. + - cool_bin: + type: integer + description: Bins size in bp + - - chromsizes: + type: file + description: Path to a chromsizes file. output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - version: - type: file - description: File containing software version - pattern: "versions.yml" - cool: - type: file - description: Output COOL file path - pattern: "*.cool" - - cool_bin: - type: value - description: Bins size in bp - + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.cool": + type: file + description: Output COOL file path + pattern: "*.cool" + - cool_bin: + type: file + description: Output COOL file path + pattern: "*.cool" + - versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@jianhong" - "@muffato" +maintainers: + - "@jianhong" + - "@muffato" diff --git a/modules/nf-core/cooler/dump/environment.yml b/modules/nf-core/cooler/dump/environment.yml new file mode 100644 index 00000000..45f3b64b --- /dev/null +++ b/modules/nf-core/cooler/dump/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::cooler=0.10.2 diff --git a/modules/nf-core/cooler/dump/main.nf b/modules/nf-core/cooler/dump/main.nf index fed7502f..0cf527f3 100644 --- a/modules/nf-core/cooler/dump/main.nf +++ b/modules/nf-core/cooler/dump/main.nf @@ -2,10 +2,10 @@ process COOLER_DUMP { tag "$meta.id" label 'process_high' - conda "bioconda::cooler=0.8.11" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/cooler:0.8.11--pyh3252c3a_0' : - 'biocontainers/cooler:0.8.11--pyh3252c3a_0' }" + 'https://depot.galaxyproject.org/singularity/cooler:0.10.2--pyhdfd78af_0' : + 'biocontainers/cooler:0.10.2--pyhdfd78af_0' }" input: tuple val(meta), path(cool), val(resolution) @@ -32,4 +32,16 @@ process COOLER_DUMP { cooler: \$(cooler --version 2>&1 | sed 's/cooler, version //') END_VERSIONS """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.bedpe + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + cooler: \$(cooler --version 2>&1 | sed 's/cooler, version //') + END_VERSIONS + """ } diff --git a/modules/nf-core/cooler/dump/meta.yml b/modules/nf-core/cooler/dump/meta.yml index fe60523e..e8150097 100644 --- a/modules/nf-core/cooler/dump/meta.yml +++ b/modules/nf-core/cooler/dump/meta.yml @@ -2,6 +2,8 @@ name: cooler_dump description: Dump a cooler’s data to a text stream. keywords: - dump + - text + - cooler tools: - cooler: description: Sparse binary format for genomic interaction matrices @@ -10,36 +12,39 @@ tools: tool_dev_url: https://github.com/open2c/cooler doi: "10.1093/bioinformatics/btz540" licence: ["BSD-3-Clause"] - + identifier: "" input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - cool: - type: file - description: Path to COOL file - pattern: "*.{cool,mcool}" - - resolution: - type: value - description: Resolution - + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - cool: + type: file + description: Path to COOL file + pattern: "*.{cool,mcool}" + - resolution: + type: integer + description: Resolution output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" - bedpe: - type: file - description: Output text file - pattern: "*.bedpe" - + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.bedpe": + type: file + description: Output text file + pattern: "*.bedpe" + - versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@jianhong" - "@muffato" +maintainers: + - "@jianhong" + - "@muffato" diff --git a/modules/nf-core/cooler/dump/tests/main.nf.test b/modules/nf-core/cooler/dump/tests/main.nf.test new file mode 100644 index 00000000..fc5a2249 --- /dev/null +++ b/modules/nf-core/cooler/dump/tests/main.nf.test @@ -0,0 +1,60 @@ + +nextflow_process { + + name "Test Process COOLER_DUMP" + script "../main.nf" + process "COOLER_DUMP" + + tag "modules" + tag "modules_nfcore" + tag "cooler" + tag "cooler/dump" + + test("test-cooler-dump") { + + when { + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file("https://raw.githubusercontent.com/open2c/cooler/master/tests/data/toy.asymm.16.cool", checkIfExists: true), + [:] // resolution if any + ] + + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("test-cooler-dump-stub") { + options '-stub' + + when { + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file("https://raw.githubusercontent.com/open2c/cooler/master/tests/data/toy.asymm.16.cool", checkIfExists: true), + [:] // resolution if any + ] + + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + +} diff --git a/modules/nf-core/cooler/dump/tests/main.nf.test.snap b/modules/nf-core/cooler/dump/tests/main.nf.test.snap new file mode 100644 index 00000000..e415486d --- /dev/null +++ b/modules/nf-core/cooler/dump/tests/main.nf.test.snap @@ -0,0 +1,68 @@ +{ + "test-cooler-dump-stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.bedpe:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,af2717b7d684ac9de4d3729d85bfc82f" + ], + "bedpe": [ + [ + { + "id": "test" + }, + "test.bedpe:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,af2717b7d684ac9de4d3729d85bfc82f" + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-09-02T15:27:00.895925" + }, + "test-cooler-dump": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.bedpe:md5,38e9b0b8cc74f55a15e8ab01023048bd" + ] + ], + "1": [ + "versions.yml:md5,af2717b7d684ac9de4d3729d85bfc82f" + ], + "bedpe": [ + [ + { + "id": "test" + }, + "test.bedpe:md5,38e9b0b8cc74f55a15e8ab01023048bd" + ] + ], + "versions": [ + "versions.yml:md5,af2717b7d684ac9de4d3729d85bfc82f" + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-09-02T15:26:53.676822" + } +} \ No newline at end of file diff --git a/modules/nf-core/cooler/zoomify/environment.yml b/modules/nf-core/cooler/zoomify/environment.yml new file mode 100644 index 00000000..f8165ca9 --- /dev/null +++ b/modules/nf-core/cooler/zoomify/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::cooler=0.9.2 diff --git a/modules/nf-core/cooler/zoomify/main.nf b/modules/nf-core/cooler/zoomify/main.nf index 95e7daff..f9933dff 100644 --- a/modules/nf-core/cooler/zoomify/main.nf +++ b/modules/nf-core/cooler/zoomify/main.nf @@ -2,10 +2,10 @@ process COOLER_ZOOMIFY { tag "$meta.id" label 'process_high' - conda "bioconda::cooler=0.8.11" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/cooler:0.8.11--pyh3252c3a_0' : - 'biocontainers/cooler:0.8.11--pyh3252c3a_0' }" + 'https://depot.galaxyproject.org/singularity/cooler:0.9.2--pyh7cba7a3_0' : + 'biocontainers/cooler:0.9.2--pyh7cba7a3_0' }" input: tuple val(meta), path(cool) @@ -32,4 +32,15 @@ process COOLER_ZOOMIFY { cooler: \$(cooler --version 2>&1 | sed 's/cooler, version //') END_VERSIONS """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.mcool + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + cooler: \$(cooler --version 2>&1 | sed 's/cooler, version //') + END_VERSIONS + """ } diff --git a/modules/nf-core/cooler/zoomify/meta.yml b/modules/nf-core/cooler/zoomify/meta.yml index 57f55486..3f928781 100644 --- a/modules/nf-core/cooler/zoomify/meta.yml +++ b/modules/nf-core/cooler/zoomify/meta.yml @@ -2,6 +2,8 @@ name: cooler_zoomify description: Generate a multi-resolution cooler file by coarsening keywords: - mcool + - cool + - cooler tools: - cooler: description: Sparse binary format for genomic interaction matrices @@ -10,32 +12,34 @@ tools: tool_dev_url: https://github.com/open2c/cooler doi: "10.1093/bioinformatics/btz540" licence: ["BSD-3-clause"] - + identifier: "" input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - cool: - type: file - description: Path to COOL file - pattern: "*.{cool,mcool}" - + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - cool: + type: file + description: Path to COOL file + pattern: "*.{cool,mcool}" output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" - mcool: - type: file - description: Output mcool file - pattern: "*.mcool" - + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.mcool": + type: file + description: Output mcool file + pattern: "*.mcool" + - versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@jianhong" +maintainers: + - "@jianhong" From c9e4211c8153d04490780b68c925b59cd409e394 Mon Sep 17 00:00:00 2001 From: Tyler Chafin Date: Fri, 22 Nov 2024 16:51:50 +0000 Subject: [PATCH 118/132] nf-core/dumpsoftwareversions updated --- modules.json | 2 +- .../dumpsoftwareversions/environment.yml | 5 +++ .../custom/dumpsoftwareversions/main.nf | 6 +-- .../custom/dumpsoftwareversions/meta.yml | 43 +++++++++++-------- .../templates/dumpsoftwareversions.py | 4 +- .../dumpsoftwareversions/tests/main.nf.test | 43 +++++++++++++++++++ .../tests/main.nf.test.snap | 33 ++++++++++++++ .../dumpsoftwareversions/tests/tags.yml | 2 + 8 files changed, 114 insertions(+), 24 deletions(-) create mode 100644 modules/nf-core/custom/dumpsoftwareversions/environment.yml create mode 100644 modules/nf-core/custom/dumpsoftwareversions/tests/main.nf.test create mode 100644 modules/nf-core/custom/dumpsoftwareversions/tests/main.nf.test.snap create mode 100644 modules/nf-core/custom/dumpsoftwareversions/tests/tags.yml diff --git a/modules.json b/modules.json index 2abe2959..19c75c25 100644 --- a/modules.json +++ b/modules.json @@ -43,7 +43,7 @@ }, "custom/dumpsoftwareversions": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", "installed_by": ["modules"] }, "fastk/fastk": { diff --git a/modules/nf-core/custom/dumpsoftwareversions/environment.yml b/modules/nf-core/custom/dumpsoftwareversions/environment.yml new file mode 100644 index 00000000..9d79af93 --- /dev/null +++ b/modules/nf-core/custom/dumpsoftwareversions/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::multiqc=1.20 diff --git a/modules/nf-core/custom/dumpsoftwareversions/main.nf b/modules/nf-core/custom/dumpsoftwareversions/main.nf index ebc87273..105f9265 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 "${moduleDir}/environment.yml" 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.20--pyhdfd78af_0' : + 'biocontainers/multiqc:1.20--pyhdfd78af_0' }" input: path versions diff --git a/modules/nf-core/custom/dumpsoftwareversions/meta.yml b/modules/nf-core/custom/dumpsoftwareversions/meta.yml index c32657de..dc1e412f 100644 --- a/modules/nf-core/custom/dumpsoftwareversions/meta.yml +++ b/modules/nf-core/custom/dumpsoftwareversions/meta.yml @@ -1,36 +1,43 @@ -# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/yaml-schema.json +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/meta-schema.json name: custom_dumpsoftwareversions -description: Custom module used to dump software versions within the nf-core pipeline template +description: Custom module used to dump software versions within the nf-core pipeline + template keywords: - custom - dump - version tools: - custom: - description: Custom module used to dump software versions within the nf-core pipeline template + description: Custom module used to dump software versions within the nf-core pipeline + template homepage: https://github.com/nf-core/tools documentation: https://github.com/nf-core/tools licence: ["MIT"] + identifier: "" input: - - versions: - type: file - description: YML file containing software versions - pattern: "*.yml" - + - - versions: + type: file + description: YML file containing software versions + pattern: "*.yml" output: - yml: - type: file - description: Standard YML file containing software versions - pattern: "software_versions.yml" + - software_versions.yml: + type: file + description: Standard YML file containing software versions + pattern: "software_versions.yml" - mqc_yml: - type: file - description: MultiQC custom content YML file containing software versions - pattern: "software_versions_mqc.yml" + - software_versions_mqc.yml: + type: file + description: MultiQC custom content YML file containing software versions + pattern: "software_versions_mqc.yml" - versions: - type: file - description: File containing software versions - pattern: "versions.yml" - + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@drpatelh" - "@grst" +maintainers: + - "@drpatelh" + - "@grst" diff --git a/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py index da033408..b83b32c4 100755 --- a/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py +++ b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py @@ -3,11 +3,11 @@ """Provide functions to merge multiple versions.yml files.""" - -import yaml import platform from textwrap import dedent +import yaml + def _make_versions_html(versions): """Generate a tabular HTML output of all versions for MultiQC.""" diff --git a/modules/nf-core/custom/dumpsoftwareversions/tests/main.nf.test b/modules/nf-core/custom/dumpsoftwareversions/tests/main.nf.test new file mode 100644 index 00000000..b1e1630b --- /dev/null +++ b/modules/nf-core/custom/dumpsoftwareversions/tests/main.nf.test @@ -0,0 +1,43 @@ +nextflow_process { + + name "Test Process CUSTOM_DUMPSOFTWAREVERSIONS" + script "../main.nf" + process "CUSTOM_DUMPSOFTWAREVERSIONS" + tag "modules" + tag "modules_nfcore" + tag "custom" + tag "dumpsoftwareversions" + tag "custom/dumpsoftwareversions" + + test("Should run without failures") { + when { + process { + """ + def tool1_version = ''' + TOOL1: + tool1: 0.11.9 + '''.stripIndent() + + def tool2_version = ''' + TOOL2: + tool2: 1.9 + '''.stripIndent() + + input[0] = Channel.of(tool1_version, tool2_version).collectFile() + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + process.out.versions, + file(process.out.mqc_yml[0]).readLines()[0..10], + file(process.out.yml[0]).readLines()[0..7] + ).match() + } + ) + } + } +} diff --git a/modules/nf-core/custom/dumpsoftwareversions/tests/main.nf.test.snap b/modules/nf-core/custom/dumpsoftwareversions/tests/main.nf.test.snap new file mode 100644 index 00000000..5f59a936 --- /dev/null +++ b/modules/nf-core/custom/dumpsoftwareversions/tests/main.nf.test.snap @@ -0,0 +1,33 @@ +{ + "Should run without failures": { + "content": [ + [ + "versions.yml:md5,76d454d92244589d32455833f7c1ba6d" + ], + [ + "data: \"\\n\\n \\n \\n \\n \\n \\n \\n \\n\\", + " \\n\\n\\n \\n \\n\\", + " \\ \\n\\n\\n\\n \\n \\", + " \\ \\n \\n\\n\\n\\n\\", + " \\n\\n \\n \\n\\", + " \\ \\n\\n\\n\\n\\n\\n \\n\\", + " \\ \\n \\n\\n\\n\\n\\", + " \\n\\n \\n \\n\\" + ], + [ + "CUSTOM_DUMPSOFTWAREVERSIONS:", + " python: 3.11.7", + " yaml: 5.4.1", + "TOOL1:", + " tool1: 0.11.9", + "TOOL2:", + " tool2: '1.9'", + "Workflow:" + ] + ], + "timestamp": "2024-01-09T23:01:18.710682" + } +} \ No newline at end of file diff --git a/modules/nf-core/custom/dumpsoftwareversions/tests/tags.yml b/modules/nf-core/custom/dumpsoftwareversions/tests/tags.yml new file mode 100644 index 00000000..405aa24a --- /dev/null +++ b/modules/nf-core/custom/dumpsoftwareversions/tests/tags.yml @@ -0,0 +1,2 @@ +custom/dumpsoftwareversions: + - modules/nf-core/custom/dumpsoftwareversions/** From 061ac2e555fb66f315dde542e30de3a05011323f Mon Sep 17 00:00:00 2001 From: Tyler Chafin Date: Fri, 22 Nov 2024 17:24:33 +0000 Subject: [PATCH 119/132] nf-core/gffread updated --- modules.json | 2 +- modules/nf-core/gffread/meta.yml | 84 ++++++++++++++++++++------------ 2 files changed, 53 insertions(+), 33 deletions(-) diff --git a/modules.json b/modules.json index 19c75c25..0ee6453e 100644 --- a/modules.json +++ b/modules.json @@ -54,7 +54,7 @@ }, "gffread": { "branch": "master", - "git_sha": "06c8865e36741e05ad32ef70ab3fac127486af48", + "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", "installed_by": ["modules"] }, "gnu/sort": { diff --git a/modules/nf-core/gffread/meta.yml b/modules/nf-core/gffread/meta.yml index c0602820..bebe7f57 100644 --- a/modules/nf-core/gffread/meta.yml +++ b/modules/nf-core/gffread/meta.yml @@ -1,53 +1,73 @@ name: gffread -description: Validate, filter, convert and perform various other operations on GFF files +description: Validate, filter, convert and perform various other operations on GFF + files keywords: - gff - conversion - validation tools: - gffread: - description: GFF/GTF utility providing format conversions, region filtering, FASTA sequence extraction and more. + description: GFF/GTF utility providing format conversions, region filtering, FASTA + sequence extraction and more. homepage: http://ccb.jhu.edu/software/stringtie/gff.shtml#gffread documentation: http://ccb.jhu.edu/software/stringtie/gff.shtml#gffread tool_dev_url: https://github.com/gpertea/gffread doi: 10.12688/f1000research.23297.1 licence: ["MIT"] + identifier: biotools:gffread input: - - meta: - type: map - description: | - Groovy Map containing meta data - e.g. [ id:'test' ] - - gff: - type: file - description: A reference file in either the GFF3, GFF2 or GTF format. - pattern: "*.{gff, gtf}" - - fasta: - type: file - description: A multi-fasta file with the genomic sequences - pattern: "*.{fasta,fa,faa,fas,fsa}" + - - meta: + type: map + description: | + Groovy Map containing meta data + e.g. [ id:'test' ] + - gff: + type: file + description: A reference file in either the GFF3, GFF2 or GTF format. + pattern: "*.{gff, gtf}" + - - fasta: + type: file + description: A multi-fasta file with the genomic sequences + pattern: "*.{fasta,fa,faa,fas,fsa}" output: - - meta: - type: map - description: | - Groovy Map containing meta data - e.g. [ id:'test' ] - gtf: - type: file - description: GTF file resulting from the conversion of the GFF input file if '-T' argument is present - pattern: "*.{gtf}" + - meta: + type: map + description: | + Groovy Map containing meta data + e.g. [ id:'test' ] + - "*.gtf": + type: file + description: GTF file resulting from the conversion of the GFF input file if + '-T' argument is present + pattern: "*.{gtf}" - gffread_gff: - type: file - description: GFF3 file resulting from the conversion of the GFF input file if '-T' argument is absent - pattern: "*.gff3" + - meta: + type: map + description: | + Groovy Map containing meta data + e.g. [ id:'test' ] + - "*.gff3": + type: file + description: GFF3 file resulting from the conversion of the GFF input file if + '-T' argument is absent + pattern: "*.gff3" - gffread_fasta: - type: file - description: Fasta file produced when either of '-w', '-x', '-y' parameters is present - pattern: "*.fasta" + - meta: + type: map + description: | + Groovy Map containing meta data + e.g. [ id:'test' ] + - "*.fasta": + type: file + description: Fasta file produced when either of '-w', '-x', '-y' parameters + is present + pattern: "*.fasta" - versions: - type: file - description: File containing software versions - pattern: "versions.yml" + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@edmundmiller" maintainers: From 1f18dad5dad2f38a1928a1b7748ec8b9b7e57a28 Mon Sep 17 00:00:00 2001 From: Tyler Chafin Date: Sat, 23 Nov 2024 09:35:54 +0000 Subject: [PATCH 120/132] nf-core module updates --- modules.json | 4 +- modules/nf-core/gnu/sort/environment.yml | 7 + modules/nf-core/gnu/sort/main.nf | 15 +- modules/nf-core/gnu/sort/meta.yml | 46 +++-- modules/nf-core/gnu/sort/tests/main.nf.test | 120 +++++++++++++ .../nf-core/gnu/sort/tests/main.nf.test.snap | 164 ++++++++++++++++++ .../gnu/sort/tests/sort_complex.config | 6 + .../gnu/sort/tests/sort_simple_bed.config | 6 + .../gnu/sort/tests/sort_simple_genome.config | 6 + modules/nf-core/gnu/sort/tests/tags.yml | 2 + modules/nf-core/gunzip/environment.yml | 7 + modules/nf-core/gunzip/main.nf | 29 +++- modules/nf-core/gunzip/meta.yml | 42 +++-- modules/nf-core/gunzip/tests/main.nf.test | 121 +++++++++++++ .../nf-core/gunzip/tests/main.nf.test.snap | 134 ++++++++++++++ modules/nf-core/gunzip/tests/nextflow.config | 5 + modules/nf-core/gunzip/tests/tags.yml | 2 + 17 files changed, 658 insertions(+), 58 deletions(-) create mode 100644 modules/nf-core/gnu/sort/environment.yml create mode 100644 modules/nf-core/gnu/sort/tests/main.nf.test create mode 100644 modules/nf-core/gnu/sort/tests/main.nf.test.snap create mode 100644 modules/nf-core/gnu/sort/tests/sort_complex.config create mode 100644 modules/nf-core/gnu/sort/tests/sort_simple_bed.config create mode 100644 modules/nf-core/gnu/sort/tests/sort_simple_genome.config create mode 100644 modules/nf-core/gnu/sort/tests/tags.yml create mode 100644 modules/nf-core/gunzip/environment.yml create mode 100644 modules/nf-core/gunzip/tests/main.nf.test create mode 100644 modules/nf-core/gunzip/tests/main.nf.test.snap create mode 100644 modules/nf-core/gunzip/tests/nextflow.config create mode 100644 modules/nf-core/gunzip/tests/tags.yml diff --git a/modules.json b/modules.json index 0ee6453e..232da38f 100644 --- a/modules.json +++ b/modules.json @@ -59,12 +59,12 @@ }, "gnu/sort": { "branch": "master", - "git_sha": "88f6e982fb8bd40488d837b3b08a65008e602840", + "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", "installed_by": ["modules"] }, "gunzip": { "branch": "master", - "git_sha": "5c460c5a4736974abde2843294f35307ee2b0e5e", + "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", "installed_by": ["modules"] }, "merquryfk/merquryfk": { diff --git a/modules/nf-core/gnu/sort/environment.yml b/modules/nf-core/gnu/sort/environment.yml new file mode 100644 index 00000000..babcfb55 --- /dev/null +++ b/modules/nf-core/gnu/sort/environment.yml @@ -0,0 +1,7 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + - conda-forge::coreutils=9.3 diff --git a/modules/nf-core/gnu/sort/main.nf b/modules/nf-core/gnu/sort/main.nf index b0a57fbb..e1167666 100644 --- a/modules/nf-core/gnu/sort/main.nf +++ b/modules/nf-core/gnu/sort/main.nf @@ -1,11 +1,11 @@ process GNU_SORT { - tag "${meta.id}" + tag "$meta.id" label "process_low" - conda "bioconda::coreutils=8.25" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/coreutils:8.25--1' : - 'biocontainers/coreutils:8.25--1' }" + 'https://depot.galaxyproject.org/singularity/coreutils:9.3': + 'biocontainers/coreutils:9.3' }" input: tuple val(meta), path(input) @@ -22,7 +22,7 @@ process GNU_SORT { def prefix = task.ext.prefix ?: "${meta.id}" suffix = task.ext.suffix ?: "${input.extension}" output_file = "${prefix}.${suffix}" - def VERSION = "9.1" // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. + def VERSION = "9.3" // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. if ("$input" == "$output_file") error "Input and output names are the same, use \"task.ext.prefix\" to disambiguate!" """ sort ${args} ${input} > ${output_file} @@ -34,15 +34,14 @@ process GNU_SORT { """ stub: - def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" suffix = task.ext.suffix ?: "${input.extension}" output_file = "${prefix}.${suffix}" - def VERSION = "9.1" + def VERSION = "9.3" if ("$input" == "$output_file") error "Input and output names are the same, use \"task.ext.prefix\" to disambiguate!" """ - sort ${args} ${input} > ${output_file} + touch ${output_file} cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/nf-core/gnu/sort/meta.yml b/modules/nf-core/gnu/sort/meta.yml index e7fb0284..c555dbb5 100644 --- a/modules/nf-core/gnu/sort/meta.yml +++ b/modules/nf-core/gnu/sort/meta.yml @@ -1,4 +1,4 @@ -name: "GNU_SORT" +name: "gnu_sort" description: | Writes a sorted concatenation of file/s keywords: @@ -11,32 +11,30 @@ tools: homepage: "https://github.com/vgl-hub/gfastats" documentation: "https://www.gnu.org/software/coreutils/manual/html_node/sort-invocation.html" licence: ["GPL"] - + identifier: "" input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - input: - type: file - description: Draft assembly file - pattern: "*.{txt,bed,interval,genome,bins}" - + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - input: + type: file + description: Draft assembly file + pattern: "*.{txt,bed,interval,genome,bins}" output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - sorted: - type: file - description: The sorted txt file generated by sort - pattern: "*.{txt,bed,interval,genome,bins}" + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] - versions: - type: file - description: File containing software versions - pattern: "versions.yml" - + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@DLBPointon" +maintainers: + - "@DLBPointon" diff --git a/modules/nf-core/gnu/sort/tests/main.nf.test b/modules/nf-core/gnu/sort/tests/main.nf.test new file mode 100644 index 00000000..e4030187 --- /dev/null +++ b/modules/nf-core/gnu/sort/tests/main.nf.test @@ -0,0 +1,120 @@ +nextflow_process { + + name "Test Process GNU_SORT" + script "modules/nf-core/gnu/sort/main.nf" + process "GNU_SORT" + + tag "modules" + tag "modules_nfcore" + tag "gnu" + tag "gnu/sort" + + test("unsorted_genome_sort") { + config "./sort_simple_bed.config" + + when { + process { + """ + input[0] = [ + [id:'genome_test'], + file(params.test_data['generic']['unsorted_data']['unsorted_text']['genome_file'], + checkIfExists: true) + ] + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() }, + { assert snapshot( + file(process.out.sorted[0][1]).name + ).match("genome_sort") + } + ) + } + + } + + test("unsorted_intervals_sort") { + config "./sort_simple_bed.config" + when { + process { + """ + input[0] = [ + [id:'test'], + file(params.test_data['generic']['unsorted_data']['unsorted_text']['intervals'], + checkIfExists: true) + ] + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() }, + { assert snapshot( + file(process.out.sorted[0][1]).name + ).match("interval_sort") + } + ) + } + + } + + test("unsorted_csv_sort") { + config "./sort_complex.config" + + when { + process { + """ + input[0] = [ + [id:'test'], + file(params.test_data['generic']['unsorted_data']['unsorted_text']['numbers_csv'], + checkIfExists: true) + ] + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() }, + { assert snapshot( + file(process.out.sorted[0][1]).name + ).match("csv_sort") + } + ) + } + + } + + test("unsorted_csv_sort_stub") { + config "./sort_complex.config" + options "-stub" + + when { + process { + """ + input[0] = [ + [id:'test'], + file(params.test_data['generic']['unsorted_data']['unsorted_text']['numbers_csv'], + checkIfExists: true) + ] + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() }, + ) + } + + } + +} diff --git a/modules/nf-core/gnu/sort/tests/main.nf.test.snap b/modules/nf-core/gnu/sort/tests/main.nf.test.snap new file mode 100644 index 00000000..63891bc4 --- /dev/null +++ b/modules/nf-core/gnu/sort/tests/main.nf.test.snap @@ -0,0 +1,164 @@ +{ + "unsorted_csv_sort": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.csv.sorted:md5,0b52d1b4c4a0c6e972c6f94aafd75a1d" + ] + ], + "1": [ + "versions.yml:md5,dd412503ec9dd665203e083ea44326cb" + ], + "sorted": [ + [ + { + "id": "test" + }, + "test.csv.sorted:md5,0b52d1b4c4a0c6e972c6f94aafd75a1d" + ] + ], + "versions": [ + "versions.yml:md5,dd412503ec9dd665203e083ea44326cb" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-14T11:13:44.714632791" + }, + "interval_sort": { + "content": [ + "test.bed.sorted" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-14T11:13:37.962807086" + }, + "unsorted_csv_sort_stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.csv.sorted:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,dd412503ec9dd665203e083ea44326cb" + ], + "sorted": [ + [ + { + "id": "test" + }, + "test.csv.sorted:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,dd412503ec9dd665203e083ea44326cb" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-14T11:13:51.456258705" + }, + "csv_sort": { + "content": [ + "test.csv.sorted" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-14T11:13:44.725431761" + }, + "unsorted_genome_sort": { + "content": [ + { + "0": [ + [ + { + "id": "genome_test" + }, + "genome_test.bed.sorted:md5,fd97f7efafdbbfa71d9b560f10b4b048" + ] + ], + "1": [ + "versions.yml:md5,dd412503ec9dd665203e083ea44326cb" + ], + "sorted": [ + [ + { + "id": "genome_test" + }, + "genome_test.bed.sorted:md5,fd97f7efafdbbfa71d9b560f10b4b048" + ] + ], + "versions": [ + "versions.yml:md5,dd412503ec9dd665203e083ea44326cb" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-14T11:13:31.041778719" + }, + "genome_sort": { + "content": [ + "genome_test.bed.sorted" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-14T11:13:31.060201722" + }, + "unsorted_intervals_sort": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.bed.sorted:md5,abbce903ef263d38b2f71856387799ab" + ] + ], + "1": [ + "versions.yml:md5,dd412503ec9dd665203e083ea44326cb" + ], + "sorted": [ + [ + { + "id": "test" + }, + "test.bed.sorted:md5,abbce903ef263d38b2f71856387799ab" + ] + ], + "versions": [ + "versions.yml:md5,dd412503ec9dd665203e083ea44326cb" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-14T11:13:37.951397547" + } +} \ No newline at end of file diff --git a/modules/nf-core/gnu/sort/tests/sort_complex.config b/modules/nf-core/gnu/sort/tests/sort_complex.config new file mode 100644 index 00000000..103eaaf6 --- /dev/null +++ b/modules/nf-core/gnu/sort/tests/sort_complex.config @@ -0,0 +1,6 @@ +process { + withName: GNU_SORT { + ext.args = { "-t ';' -g -k 1,1 -k 2,2" } + ext.suffix = { "csv.sorted" } + } +} \ No newline at end of file diff --git a/modules/nf-core/gnu/sort/tests/sort_simple_bed.config b/modules/nf-core/gnu/sort/tests/sort_simple_bed.config new file mode 100644 index 00000000..d7d52e0f --- /dev/null +++ b/modules/nf-core/gnu/sort/tests/sort_simple_bed.config @@ -0,0 +1,6 @@ +process { + withName: GNU_SORT { + ext.args = { "-k1,1 -k2,2n" } + ext.suffix = { "bed.sorted" } + } +} \ No newline at end of file diff --git a/modules/nf-core/gnu/sort/tests/sort_simple_genome.config b/modules/nf-core/gnu/sort/tests/sort_simple_genome.config new file mode 100644 index 00000000..4dcec385 --- /dev/null +++ b/modules/nf-core/gnu/sort/tests/sort_simple_genome.config @@ -0,0 +1,6 @@ +process { + withName: GNU_SORT { + ext.args = { "-k1,1 -k2,2n" } + ext.suffix = { "genome.sorted" } + } +} \ No newline at end of file diff --git a/modules/nf-core/gnu/sort/tests/tags.yml b/modules/nf-core/gnu/sort/tests/tags.yml new file mode 100644 index 00000000..ac40e376 --- /dev/null +++ b/modules/nf-core/gnu/sort/tests/tags.yml @@ -0,0 +1,2 @@ +gnu/sort: + - "modules/nf-core/gnu/sort/**" diff --git a/modules/nf-core/gunzip/environment.yml b/modules/nf-core/gunzip/environment.yml new file mode 100644 index 00000000..c7794856 --- /dev/null +++ b/modules/nf-core/gunzip/environment.yml @@ -0,0 +1,7 @@ +channels: + - conda-forge + - bioconda +dependencies: + - conda-forge::grep=3.11 + - conda-forge::sed=4.8 + - conda-forge::tar=1.34 diff --git a/modules/nf-core/gunzip/main.nf b/modules/nf-core/gunzip/main.nf index e7189d2f..5e67e3b9 100644 --- a/modules/nf-core/gunzip/main.nf +++ b/modules/nf-core/gunzip/main.nf @@ -2,10 +2,10 @@ process GUNZIP { tag "$archive" label 'process_single' - conda "conda-forge::sed=4.7" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/ubuntu:20.04' : - 'nf-core/ubuntu:20.04' }" + 'https://depot.galaxyproject.org/singularity/ubuntu:22.04' : + 'nf-core/ubuntu:22.04' }" input: tuple val(meta), path(archive) @@ -18,13 +18,20 @@ process GUNZIP { task.ext.when == null || task.ext.when script: - def args = task.ext.args ?: '' - gunzip = archive.toString() - '.gz' + def args = task.ext.args ?: '' + def extension = ( archive.toString() - '.gz' ).tokenize('.')[-1] + def name = archive.toString() - '.gz' - ".$extension" + def prefix = task.ext.prefix ?: name + gunzip = prefix + ".$extension" """ - gunzip \\ - -f \\ + # Not calling gunzip itself because it creates files + # with the original group ownership rather than the + # default one for that user / the work directory + gzip \\ + -cd \\ $args \\ - $archive + $archive \\ + > $gunzip cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -33,7 +40,11 @@ process GUNZIP { """ stub: - gunzip = archive.toString() - '.gz' + def args = task.ext.args ?: '' + def extension = ( archive.toString() - '.gz' ).tokenize('.')[-1] + def name = archive.toString() - '.gz' - ".$extension" + def prefix = task.ext.prefix ?: name + gunzip = prefix + ".$extension" """ touch $gunzip cat <<-END_VERSIONS > versions.yml diff --git a/modules/nf-core/gunzip/meta.yml b/modules/nf-core/gunzip/meta.yml index 4cdcdf4c..9066c035 100644 --- a/modules/nf-core/gunzip/meta.yml +++ b/modules/nf-core/gunzip/meta.yml @@ -10,26 +10,38 @@ tools: gzip is a file format and a software application used for file compression and decompression. documentation: https://www.gnu.org/software/gzip/manual/gzip.html licence: ["GPL-3.0-or-later"] + identifier: "" input: - - meta: - type: map - description: | - Optional groovy Map containing meta information - e.g. [ id:'test', single_end:false ] - - archive: - type: file - description: File to be compressed/uncompressed - pattern: "*.*" + - - meta: + type: map + description: | + Optional groovy Map containing meta information + e.g. [ id:'test', single_end:false ] + - archive: + type: file + description: File to be compressed/uncompressed + pattern: "*.*" output: - gunzip: - type: file - description: Compressed/uncompressed file - pattern: "*.*" + - meta: + type: file + description: Compressed/uncompressed file + pattern: "*.*" + - $gunzip: + type: file + description: Compressed/uncompressed file + pattern: "*.*" - versions: - type: file - description: File containing software versions - pattern: "versions.yml" + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@joseespinosa" - "@drpatelh" - "@jfy133" +maintainers: + - "@joseespinosa" + - "@drpatelh" + - "@jfy133" + - "@gallvp" diff --git a/modules/nf-core/gunzip/tests/main.nf.test b/modules/nf-core/gunzip/tests/main.nf.test new file mode 100644 index 00000000..776211ad --- /dev/null +++ b/modules/nf-core/gunzip/tests/main.nf.test @@ -0,0 +1,121 @@ +nextflow_process { + + name "Test Process GUNZIP" + script "../main.nf" + process "GUNZIP" + tag "gunzip" + tag "modules_nfcore" + tag "modules" + + test("Should run without failures") { + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = Channel.of([ + [], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + ) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("Should run without failures - prefix") { + + config './nextflow.config' + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = Channel.of([ + [ id: 'test' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + ) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("Should run without failures - stub") { + + options '-stub' + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = Channel.of([ + [], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + ) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("Should run without failures - prefix - stub") { + + options '-stub' + config './nextflow.config' + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = Channel.of([ + [ id: 'test' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + ) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + +} diff --git a/modules/nf-core/gunzip/tests/main.nf.test.snap b/modules/nf-core/gunzip/tests/main.nf.test.snap new file mode 100644 index 00000000..069967e7 --- /dev/null +++ b/modules/nf-core/gunzip/tests/main.nf.test.snap @@ -0,0 +1,134 @@ +{ + "Should run without failures - prefix - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.xyz.fastq:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,54376d32aca20e937a4ec26dac228e84" + ], + "gunzip": [ + [ + { + "id": "test" + }, + "test.xyz.fastq:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,54376d32aca20e937a4ec26dac228e84" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-25T11:35:10.861293" + }, + "Should run without failures - stub": { + "content": [ + { + "0": [ + [ + [ + + ], + "test_1.fastq:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,54376d32aca20e937a4ec26dac228e84" + ], + "gunzip": [ + [ + [ + + ], + "test_1.fastq:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,54376d32aca20e937a4ec26dac228e84" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-25T11:35:05.857145" + }, + "Should run without failures": { + "content": [ + { + "0": [ + [ + [ + + ], + "test_1.fastq:md5,4161df271f9bfcd25d5845a1e220dbec" + ] + ], + "1": [ + "versions.yml:md5,54376d32aca20e937a4ec26dac228e84" + ], + "gunzip": [ + [ + [ + + ], + "test_1.fastq:md5,4161df271f9bfcd25d5845a1e220dbec" + ] + ], + "versions": [ + "versions.yml:md5,54376d32aca20e937a4ec26dac228e84" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2023-10-17T15:35:37.690477896" + }, + "Should run without failures - prefix": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.xyz.fastq:md5,4161df271f9bfcd25d5845a1e220dbec" + ] + ], + "1": [ + "versions.yml:md5,54376d32aca20e937a4ec26dac228e84" + ], + "gunzip": [ + [ + { + "id": "test" + }, + "test.xyz.fastq:md5,4161df271f9bfcd25d5845a1e220dbec" + ] + ], + "versions": [ + "versions.yml:md5,54376d32aca20e937a4ec26dac228e84" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-06-25T11:33:32.921739" + } +} \ No newline at end of file diff --git a/modules/nf-core/gunzip/tests/nextflow.config b/modules/nf-core/gunzip/tests/nextflow.config new file mode 100644 index 00000000..dec77642 --- /dev/null +++ b/modules/nf-core/gunzip/tests/nextflow.config @@ -0,0 +1,5 @@ +process { + withName: GUNZIP { + ext.prefix = { "${meta.id}.xyz" } + } +} diff --git a/modules/nf-core/gunzip/tests/tags.yml b/modules/nf-core/gunzip/tests/tags.yml new file mode 100644 index 00000000..fd3f6915 --- /dev/null +++ b/modules/nf-core/gunzip/tests/tags.yml @@ -0,0 +1,2 @@ +gunzip: + - modules/nf-core/gunzip/** From bd8bfaa2511cd1f58d12908f2facdbac2cc76b01 Mon Sep 17 00:00:00 2001 From: Tyler Chafin Date: Mon, 25 Nov 2024 12:18:47 +0000 Subject: [PATCH 121/132] nf-core module updates --- modules.json | 68 ++- modules/nf-core/fastk/fastk/environment.yml | 5 + modules/nf-core/fastk/fastk/fastk-fastk.diff | 15 +- modules/nf-core/fastk/fastk/main.nf | 47 +- modules/nf-core/fastk/fastk/meta.yml | 81 ++-- .../nf-core/fastk/fastk/tests/main.nf.test | 110 +++++ .../fastk/fastk/tests/main.nf.test.snap | 346 +++++++++++++ .../nf-core/fastk/fastk/tests/nextflow.config | 3 + modules/nf-core/fastk/fastk/tests/tags.yml | 2 + modules/nf-core/merquryfk/merquryfk/main.nf | 73 ++- .../merquryfk/merquryfk-merquryfk.diff | 19 +- modules/nf-core/merquryfk/merquryfk/meta.yml | 298 ++++++++---- .../merquryfk/merquryfk/tests/main.nf.test | 170 +++++++ .../merquryfk/tests/main.nf.test.snap | 454 ++++++++++++++++++ .../merquryfk/merquryfk/tests/nextflow.config | 8 + .../merquryfk/tests/nextflow.pdf.config | 9 + .../merquryfk/tests/nextflow.png.config | 9 + .../merquryfk/tests/nextflow.trio.config | 9 + .../merquryfk/merquryfk/tests/tags.yml | 2 + modules/nf-core/multiqc/environment.yml | 5 + modules/nf-core/multiqc/main.nf | 20 +- modules/nf-core/multiqc/meta.yml | 88 ++-- modules/nf-core/multiqc/tests/main.nf.test | 92 ++++ .../nf-core/multiqc/tests/main.nf.test.snap | 41 ++ modules/nf-core/multiqc/tests/nextflow.config | 5 + modules/nf-core/multiqc/tests/tags.yml | 2 + subworkflows/local/genome_statistics.nf | 2 +- workflows/genomenote.nf | 10 +- 28 files changed, 1741 insertions(+), 252 deletions(-) create mode 100644 modules/nf-core/fastk/fastk/environment.yml create mode 100644 modules/nf-core/fastk/fastk/tests/main.nf.test create mode 100644 modules/nf-core/fastk/fastk/tests/main.nf.test.snap create mode 100644 modules/nf-core/fastk/fastk/tests/nextflow.config create mode 100644 modules/nf-core/fastk/fastk/tests/tags.yml create mode 100644 modules/nf-core/merquryfk/merquryfk/tests/main.nf.test create mode 100644 modules/nf-core/merquryfk/merquryfk/tests/main.nf.test.snap create mode 100644 modules/nf-core/merquryfk/merquryfk/tests/nextflow.config create mode 100644 modules/nf-core/merquryfk/merquryfk/tests/nextflow.pdf.config create mode 100644 modules/nf-core/merquryfk/merquryfk/tests/nextflow.png.config create mode 100644 modules/nf-core/merquryfk/merquryfk/tests/nextflow.trio.config create mode 100644 modules/nf-core/merquryfk/merquryfk/tests/tags.yml create mode 100644 modules/nf-core/multiqc/environment.yml create mode 100644 modules/nf-core/multiqc/tests/main.nf.test create mode 100644 modules/nf-core/multiqc/tests/main.nf.test.snap create mode 100644 modules/nf-core/multiqc/tests/nextflow.config create mode 100644 modules/nf-core/multiqc/tests/tags.yml diff --git a/modules.json b/modules.json index 232da38f..709b8f1a 100644 --- a/modules.json +++ b/modules.json @@ -8,83 +8,113 @@ "agat/spstatistics": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "agat/sqstatbasic": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "bedtools/bamtobed": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "busco/busco": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"], + "installed_by": [ + "modules" + ], "patch": "modules/nf-core/busco/busco/busco-busco.diff" }, "cooler/cload": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "cooler/dump": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "cooler/zoomify": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "custom/dumpsoftwareversions": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "fastk/fastk": { "branch": "master", - "git_sha": "0f8a77ff00e65eaeebc509b8156eaa983192474b", - "installed_by": ["modules"], + "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", + "installed_by": [ + "modules" + ], "patch": "modules/nf-core/fastk/fastk/fastk-fastk.diff" }, "gffread": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "gnu/sort": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "gunzip": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "merquryfk/merquryfk": { "branch": "master", - "git_sha": "0f8a77ff00e65eaeebc509b8156eaa983192474b", - "installed_by": ["modules"], + "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", + "installed_by": [ + "modules" + ], "patch": "modules/nf-core/merquryfk/merquryfk/merquryfk-merquryfk.diff" }, "multiqc": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": ["modules"] + "git_sha": "cf17ca47590cc578dfb47db1c2a44ef86f89976d", + "installed_by": [ + "modules" + ] }, "samtools/view": { "branch": "master", "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] } } } } } -} +} \ No newline at end of file diff --git a/modules/nf-core/fastk/fastk/environment.yml b/modules/nf-core/fastk/fastk/environment.yml new file mode 100644 index 00000000..14207ff6 --- /dev/null +++ b/modules/nf-core/fastk/fastk/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::false_flag # False flag to pass nf-core/lint diff --git a/modules/nf-core/fastk/fastk/fastk-fastk.diff b/modules/nf-core/fastk/fastk/fastk-fastk.diff index e019c85c..b39f0bb6 100644 --- a/modules/nf-core/fastk/fastk/fastk-fastk.diff +++ b/modules/nf-core/fastk/fastk/fastk-fastk.diff @@ -1,21 +1,12 @@ Changes in module 'nf-core/fastk/fastk' --- modules/nf-core/fastk/fastk/main.nf +++ modules/nf-core/fastk/fastk/main.nf -@@ -3,7 +3,7 @@ - label 'process_medium' - - // WARN: Version information not provided by tool on CLI. Please update version string below when bumping container versions. -- container 'ghcr.io/nbisweden/fastk_genescopefk_merquryfk:1.2' -+ container 'quay.io/sanger-tol/fastk:1.0.1-c1' - - // Exit if running this module with -profile conda / -profile mamba - if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { -@@ -25,7 +25,7 @@ - script: +@@ -24,7 +24,7 @@ + } def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" - def FASTK_VERSION = 'f18a4e6d2207539f7b84461daebc54530a9559b0' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. -+ def FASTK_VERSION = '427104ea91c78c3b8b8b49f1a7d6bbeaa869ba1c' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. ++ def FASTK_VERSION = '666652151335353eef2fcd58880bcef5bc2928e1' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. """ FastK \\ $args \\ diff --git a/modules/nf-core/fastk/fastk/main.nf b/modules/nf-core/fastk/fastk/main.nf index e953cd89..f51c9d90 100644 --- a/modules/nf-core/fastk/fastk/main.nf +++ b/modules/nf-core/fastk/fastk/main.nf @@ -3,12 +3,7 @@ process FASTK_FASTK { label 'process_medium' // WARN: Version information not provided by tool on CLI. Please update version string below when bumping container versions. - container 'quay.io/sanger-tol/fastk:1.0.1-c1' - - // Exit if running this module with -profile conda / -profile mamba - if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - exit 1, "FASTK_FASTK module does not support Conda. Please use Docker / Singularity / Podman instead." - } + container 'ghcr.io/nbisweden/fastk_genescopefk_merquryfk:1.2' input: tuple val(meta), path(reads) @@ -23,16 +18,54 @@ process FASTK_FASTK { task.ext.when == null || task.ext.when script: + // Exit if running this module with -profile conda / -profile mamba + if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { + error "FASTK_FASTK module does not support Conda. Please use Docker / Singularity / Podman instead." + } def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" - def FASTK_VERSION = '427104ea91c78c3b8b8b49f1a7d6bbeaa869ba1c' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. + def FASTK_VERSION = '666652151335353eef2fcd58880bcef5bc2928e1' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. """ FastK \\ $args \\ -T$task.cpus \\ + -M${task.memory.toGiga()} \\ -N${prefix}_fk \\ $reads + find . -name '*.ktab*' \\ + | xargs chmod a+r + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + fastk: $FASTK_VERSION + END_VERSIONS + """ + + stub: + // Exit if running this module with -profile conda / -profile mamba + if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { + error "FASTK_FASTK module does not support Conda. Please use Docker / Singularity / Podman instead." + } + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def FASTK_VERSION = 'f18a4e6d2207539f7b84461daebc54530a9559b0' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. + + def touch_ktab = args.contains('-t') ? "touch ${prefix}_fk.ktab .${prefix}_fk.ktab.1" : '' + def touch_prof = args.contains('-p') ? "touch ${prefix}_fk.prof .${prefix}_fk.pidx.1" : '' + """ + touch ${prefix}_fk.hist + $touch_ktab + $touch_prof + + echo \\ + "FastK \\ + $args \\ + -T$task.cpus \\ + -M${task.memory.toGiga()} \\ + -N${prefix}_fk \\ + $reads" + cat <<-END_VERSIONS > versions.yml "${task.process}": fastk: $FASTK_VERSION diff --git a/modules/nf-core/fastk/fastk/meta.yml b/modules/nf-core/fastk/fastk/meta.yml index 55fd1be7..4abc1033 100644 --- a/modules/nf-core/fastk/fastk/meta.yml +++ b/modules/nf-core/fastk/fastk/meta.yml @@ -8,45 +8,58 @@ tools: - "fastk": description: "A fast K-mer counter for high-fidelity shotgun datasets" homepage: "https://github.com/thegenemyers/FASTK" - tool_dev_url: "https://github.com/thegenemyers/FASTK" - - licence: "https://github.com/thegenemyers/FASTK/blob/master/LICENSE" - + licence: ["https://github.com/thegenemyers/FASTK/blob/master/LICENSE"] + identifier: "" 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. - + - - 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 ] - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" - hist: - type: file - description: Histogram of k-mers - pattern: "*.hist" + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.hist": + type: file + description: Histogram of k-mers + pattern: "*.hist" - ktab: - type: file - description: A sorted table of all canonical k‑mers along with their counts. - pattern: "*.ktab" + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - '*.ktab*", hidden: true': + type: file + description: A sorted table of all canonical k‑mers along with their counts. + pattern: "*.ktab" - prof: - type: file - description: A k‑mer count profile of each sequence in the input data set. - pattern: "*.prof" - + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - '*.{prof,pidx}*", hidden: true': + type: file + description: A k‑mer count profile of each sequence in the input data set. + pattern: "*.prof" + - versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@mahesh-panchal" +maintainers: + - "@mahesh-panchal" + - "@gallvp" diff --git a/modules/nf-core/fastk/fastk/tests/main.nf.test b/modules/nf-core/fastk/fastk/tests/main.nf.test new file mode 100644 index 00000000..856c36a8 --- /dev/null +++ b/modules/nf-core/fastk/fastk/tests/main.nf.test @@ -0,0 +1,110 @@ +nextflow_process { + + name "Test Process FASTK_FASTK" + script "../main.nf" + config './nextflow.config' + process "FASTK_FASTK" + + tag "modules" + tag "modules_nfcore" + tag "fastk" + tag "fastk/fastk" + + test("test_fastk_fastk_single_end") { + when { + process { + """ + input[0] = [ + [ id:'test' , single_end: true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("test_fastk_fastk_paired_end") { + + when { + process { + """ + input[0] = [ + [ id:'test' , single_end: false ], // meta map + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) + ] + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("test_fastk_fastk_single_end_stub") { + + options '-stub' + + when { + process { + """ + input[0] = [ + [ id:'test' , single_end: true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("test_fastk_fastk_paired_end_stub") { + + options '-stub' + + when { + process { + """ + input[0] = [ + [ id:'test' , single_end: false ], // meta map + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) + ] + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + +} diff --git a/modules/nf-core/fastk/fastk/tests/main.nf.test.snap b/modules/nf-core/fastk/fastk/tests/main.nf.test.snap new file mode 100644 index 00000000..1e3fc4da --- /dev/null +++ b/modules/nf-core/fastk/fastk/tests/main.nf.test.snap @@ -0,0 +1,346 @@ +{ + "test_fastk_fastk_single_end_stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test_fk.hist:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + [ + ".test_fk.ktab.1:md5,d41d8cd98f00b204e9800998ecf8427e", + "test_fk.ktab:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "2": [ + [ + { + "id": "test", + "single_end": true + }, + [ + ".test_fk.pidx.1:md5,d41d8cd98f00b204e9800998ecf8427e", + "test_fk.prof:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "3": [ + "versions.yml:md5,c216a1608924d1662d2086e1de1d5abd" + ], + "hist": [ + [ + { + "id": "test", + "single_end": true + }, + "test_fk.hist:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "ktab": [ + [ + { + "id": "test", + "single_end": true + }, + [ + ".test_fk.ktab.1:md5,d41d8cd98f00b204e9800998ecf8427e", + "test_fk.ktab:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "prof": [ + [ + { + "id": "test", + "single_end": true + }, + [ + ".test_fk.pidx.1:md5,d41d8cd98f00b204e9800998ecf8427e", + "test_fk.prof:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "versions": [ + "versions.yml:md5,c216a1608924d1662d2086e1de1d5abd" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-05-18T19:39:28.510263" + }, + "test_fastk_fastk_single_end": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test_fk.hist:md5,c80e12f7321e62dba4b437d7bff36ec0" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + [ + ".test_fk.ktab.1:md5,ceeacd0cb3aa69bf9b2a402830b40e26", + ".test_fk.ktab.2:md5,f2629fd15b285aed3dc2d5fe546edf3f", + "test_fk.ktab:md5,a605a58931a4b5029469e1c2575c8cee" + ] + ] + ], + "2": [ + [ + { + "id": "test", + "single_end": true + }, + [ + ".test_fk.pidx.1:md5,90bc384f61d2ecdb4586ab52ab04fddf", + ".test_fk.prof.1:md5,ebd48923a724cf79934f0b2ed42ba73d", + "test_fk.prof:md5,43d426c95d277b8148406624d513bd40" + ] + ] + ], + "3": [ + "versions.yml:md5,c216a1608924d1662d2086e1de1d5abd" + ], + "hist": [ + [ + { + "id": "test", + "single_end": true + }, + "test_fk.hist:md5,c80e12f7321e62dba4b437d7bff36ec0" + ] + ], + "ktab": [ + [ + { + "id": "test", + "single_end": true + }, + [ + ".test_fk.ktab.1:md5,ceeacd0cb3aa69bf9b2a402830b40e26", + ".test_fk.ktab.2:md5,f2629fd15b285aed3dc2d5fe546edf3f", + "test_fk.ktab:md5,a605a58931a4b5029469e1c2575c8cee" + ] + ] + ], + "prof": [ + [ + { + "id": "test", + "single_end": true + }, + [ + ".test_fk.pidx.1:md5,90bc384f61d2ecdb4586ab52ab04fddf", + ".test_fk.prof.1:md5,ebd48923a724cf79934f0b2ed42ba73d", + "test_fk.prof:md5,43d426c95d277b8148406624d513bd40" + ] + ] + ], + "versions": [ + "versions.yml:md5,c216a1608924d1662d2086e1de1d5abd" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-05-18T19:31:31.128388" + }, + "test_fastk_fastk_paired_end": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test_fk.hist:md5,4f75b550d87ed4f26a2b10a05ac7e98c" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + [ + ".test_fk.ktab.1:md5,7f28fb44940fda799797e3069f5d7263", + ".test_fk.ktab.2:md5,c14a85c128926ace78372f09029977b1", + "test_fk.ktab:md5,fddd5be0c36ad1d2131b8d8774f7657a" + ] + ] + ], + "2": [ + [ + { + "id": "test", + "single_end": false + }, + [ + ".test_fk.pidx.1:md5,e7e760f714070a4afefb38ffff559684", + ".test_fk.pidx.2:md5,a549612bbdba2506eb3311237638c4b0", + ".test_fk.prof.1:md5,46a5fd9e297262b058f8c1fd062fcf56", + ".test_fk.prof.2:md5,80326a7406f41ccf2e51e341fc804132", + "test_fk.prof:md5,d3c7d8decd4ea6e298291b8be0e2de85" + ] + ] + ], + "3": [ + "versions.yml:md5,c216a1608924d1662d2086e1de1d5abd" + ], + "hist": [ + [ + { + "id": "test", + "single_end": false + }, + "test_fk.hist:md5,4f75b550d87ed4f26a2b10a05ac7e98c" + ] + ], + "ktab": [ + [ + { + "id": "test", + "single_end": false + }, + [ + ".test_fk.ktab.1:md5,7f28fb44940fda799797e3069f5d7263", + ".test_fk.ktab.2:md5,c14a85c128926ace78372f09029977b1", + "test_fk.ktab:md5,fddd5be0c36ad1d2131b8d8774f7657a" + ] + ] + ], + "prof": [ + [ + { + "id": "test", + "single_end": false + }, + [ + ".test_fk.pidx.1:md5,e7e760f714070a4afefb38ffff559684", + ".test_fk.pidx.2:md5,a549612bbdba2506eb3311237638c4b0", + ".test_fk.prof.1:md5,46a5fd9e297262b058f8c1fd062fcf56", + ".test_fk.prof.2:md5,80326a7406f41ccf2e51e341fc804132", + "test_fk.prof:md5,d3c7d8decd4ea6e298291b8be0e2de85" + ] + ] + ], + "versions": [ + "versions.yml:md5,c216a1608924d1662d2086e1de1d5abd" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-05-18T19:31:35.565502" + }, + "test_fastk_fastk_paired_end_stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test_fk.hist:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + [ + ".test_fk.ktab.1:md5,d41d8cd98f00b204e9800998ecf8427e", + "test_fk.ktab:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "2": [ + [ + { + "id": "test", + "single_end": false + }, + [ + ".test_fk.pidx.1:md5,d41d8cd98f00b204e9800998ecf8427e", + "test_fk.prof:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "3": [ + "versions.yml:md5,c216a1608924d1662d2086e1de1d5abd" + ], + "hist": [ + [ + { + "id": "test", + "single_end": false + }, + "test_fk.hist:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "ktab": [ + [ + { + "id": "test", + "single_end": false + }, + [ + ".test_fk.ktab.1:md5,d41d8cd98f00b204e9800998ecf8427e", + "test_fk.ktab:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "prof": [ + [ + { + "id": "test", + "single_end": false + }, + [ + ".test_fk.pidx.1:md5,d41d8cd98f00b204e9800998ecf8427e", + "test_fk.prof:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "versions": [ + "versions.yml:md5,c216a1608924d1662d2086e1de1d5abd" + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-05-18T19:39:32.570957" + } +} \ No newline at end of file diff --git a/modules/nf-core/fastk/fastk/tests/nextflow.config b/modules/nf-core/fastk/fastk/tests/nextflow.config new file mode 100644 index 00000000..c89ce9d5 --- /dev/null +++ b/modules/nf-core/fastk/fastk/tests/nextflow.config @@ -0,0 +1,3 @@ +process { + ext.args = '-t -p' +} diff --git a/modules/nf-core/fastk/fastk/tests/tags.yml b/modules/nf-core/fastk/fastk/tests/tags.yml new file mode 100644 index 00000000..82f9df82 --- /dev/null +++ b/modules/nf-core/fastk/fastk/tests/tags.yml @@ -0,0 +1,2 @@ +fastk/fastk: + - "modules/nf-core/fastk/fastk/**" diff --git a/modules/nf-core/merquryfk/merquryfk/main.nf b/modules/nf-core/merquryfk/merquryfk/main.nf index 43bfe468..2a5ab221 100644 --- a/modules/nf-core/merquryfk/merquryfk/main.nf +++ b/modules/nf-core/merquryfk/merquryfk/main.nf @@ -3,48 +3,53 @@ process MERQURYFK_MERQURYFK { label 'process_medium' // WARN: Version information not provided by tool on CLI. Please update version string below when bumping container versions. - container 'quay.io/sanger-tol/fastk:1.0.1-c1' - - // Exit if running this module with -profile conda / -profile mamba - if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - exit 1, "MERQURYFK_MERQURYFK module does not support Conda. Please use Docker / Singularity / Podman instead." - } + container 'ghcr.io/nbisweden/fastk_genescopefk_merquryfk:1.2' input: - tuple val(meta), path(fastk_hist), path(fastk_ktab), path(assembly), path(haplotigs) + tuple val(meta), path(fastk_hist),path(fastk_ktab),path(assembly),path(haplotigs) + path matktab //optional + path patktab //optional output: - tuple val(meta), path("${prefix}.completeness.stats") , emit: stats - tuple val(meta), path("${prefix}.*_only.bed") , emit: bed - tuple val(meta), path("${prefix}.*.qv") , emit: assembly_qv - tuple val(meta), path("${prefix}.*.spectra-cn.fl.png"), emit: spectra_cn_fl_png, optional: true - tuple val(meta), path("${prefix}.*.spectra-cn.fl.pdf"), emit: spectra_cn_fl_pdf, optional: true - tuple val(meta), path("${prefix}.*.spectra-cn.ln.png"), emit: spectra_cn_ln_png, optional: true - tuple val(meta), path("${prefix}.*.spectra-cn.ln.pdf"), emit: spectra_cn_ln_pdf, optional: true - tuple val(meta), path("${prefix}.*.spectra-cn.st.png"), emit: spectra_cn_st_png, optional: true - tuple val(meta), path("${prefix}.*.spectra-cn.st.pdf"), emit: spectra_cn_st_pdf, optional: true - tuple val(meta), path("${prefix}.qv") , emit: qv - tuple val(meta), path("${prefix}.spectra-asm.fl.png") , emit: spectra_asm_fl_png, optional: true - tuple val(meta), path("${prefix}.spectra-asm.fl.pdf") , emit: spectra_asm_fl_pdf, optional: true - tuple val(meta), path("${prefix}.spectra-asm.ln.png") , emit: spectra_asm_ln_png, optional: true - tuple val(meta), path("${prefix}.spectra-asm.ln.pdf") , emit: spectra_asm_ln_pdf, optional: true - tuple val(meta), path("${prefix}.spectra-asm.st.png") , emit: spectra_asm_st_png, optional: true - tuple val(meta), path("${prefix}.spectra-asm.st.pdf") , emit: spectra_asm_st_pdf, optional: true - path "versions.yml" , emit: versions + tuple val(meta), path("${prefix}.completeness.stats") , emit: stats + tuple val(meta), path("${prefix}.*_only.bed") , emit: bed + tuple val(meta), path("${prefix}.*.qv") , emit: assembly_qv + tuple val(meta), path("${prefix}.*.spectra-cn.fl.{png,pdf}") , emit: spectra_cn_fl, optional: true + tuple val(meta), path("${prefix}.*.spectra-cn.ln.{png,pdf}") , emit: spectra_cn_ln, optional: true + tuple val(meta), path("${prefix}.*.spectra-cn.st.{png,pdf}") , emit: spectra_cn_st, optional: true + tuple val(meta), path("${prefix}.qv") , emit: qv + tuple val(meta), path("${prefix}.spectra-asm.fl.{png,pdf}") , emit: spectra_asm_fl, optional: true + tuple val(meta), path("${prefix}.spectra-asm.ln.{png,pdf}") , emit: spectra_asm_ln, optional: true + tuple val(meta), path("${prefix}.spectra-asm.st.{png,pdf}") , emit: spectra_asm_st, optional: true + tuple val(meta), path("${prefix}.phased_block.bed") , emit: phased_block_bed, optional: true + tuple val(meta), path("${prefix}.phased_block.stats") , emit: phased_block_stats, optional: true + tuple val(meta), path("${prefix}.continuity.N.{pdf,png}") , emit: continuity_N, optional: true + tuple val(meta), path("${prefix}.block.N.{pdf,png}") , emit: block_N, optional: true + tuple val(meta), path("${prefix}.block.blob.{pdf,png}") , emit: block_blob, optional: true + tuple val(meta), path("${prefix}.hapmers.blob.{pdf,png}") , emit: hapmers_blob, optional: true + path "versions.yml" , emit: versions when: task.ext.when == null || task.ext.when script: + // Exit if running this module with -profile conda / -profile mamba + if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { + error "MERQURYFK_MERQURYFK module does not support Conda. Please use Docker / Singularity / Podman instead." + } def args = task.ext.args ?: '' prefix = task.ext.prefix ?: "${meta.id}" - def FASTK_VERSION = '427104ea91c78c3b8b8b49f1a7d6bbeaa869ba1c' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. - def MERQURY_VERSION = 'd00d98157618f4e8d1a9190026b19b471055b22e' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. + def mat_ktab = matktab ? "${matktab.find{ it.toString().endsWith(".ktab") }}" : '' + def pat_ktab = patktab ? "${patktab.find{ it.toString().endsWith(".ktab") }}" : '' + def FASTK_VERSION = '666652151335353eef2fcd58880bcef5bc2928e1' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. + def MERQURY_VERSION = '666652151335353eef2fcd58880bcef5bc2928e1' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. """ MerquryFK \\ $args \\ -T$task.cpus \\ ${fastk_ktab.find{ it.toString().endsWith(".ktab") }} \\ + ${mat_ktab} \\ + ${pat_ktab} \\ $assembly \\ $haplotigs \\ $prefix @@ -56,4 +61,20 @@ process MERQURYFK_MERQURYFK { r: \$( R --version | sed '1!d; s/.*version //; s/ .*//' ) END_VERSIONS """ + stub: + prefix = task.ext.prefix ?: "${meta.id}" + def FASTK_VERSION = 'f18a4e6d2207539f7b84461daebc54530a9559b0' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. + def MERQURY_VERSION = '8ae344092df5dcaf83cfb7f90f662597a9b1fc61' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. + """ + touch ${prefix}.completeness.stats + touch ${prefix}.qv + touch ${prefix}._.qv + touch ${prefix}._only.bed + cat <<-END_VERSIONS > versions.yml + "${task.process}": + fastk: $FASTK_VERSION + merquryfk: $MERQURY_VERSION + r: \$( R --version | sed '1!d; s/.*version //; s/ .*//' ) + END_VERSIONS + """ } diff --git a/modules/nf-core/merquryfk/merquryfk/merquryfk-merquryfk.diff b/modules/nf-core/merquryfk/merquryfk/merquryfk-merquryfk.diff index c98c6057..b0ecbe5d 100644 --- a/modules/nf-core/merquryfk/merquryfk/merquryfk-merquryfk.diff +++ b/modules/nf-core/merquryfk/merquryfk/merquryfk-merquryfk.diff @@ -1,23 +1,14 @@ Changes in module 'nf-core/merquryfk/merquryfk' --- modules/nf-core/merquryfk/merquryfk/main.nf +++ modules/nf-core/merquryfk/merquryfk/main.nf -@@ -3,7 +3,7 @@ - label 'process_medium' - - // WARN: Version information not provided by tool on CLI. Please update version string below when bumping container versions. -- container 'ghcr.io/nbisweden/fastk_genescopefk_merquryfk:1.2' -+ container 'quay.io/sanger-tol/fastk:1.0.1-c1' - - // Exit if running this module with -profile conda / -profile mamba - if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { -@@ -38,8 +38,8 @@ - script: - def args = task.ext.args ?: '' +@@ -41,8 +41,8 @@ prefix = task.ext.prefix ?: "${meta.id}" + def mat_ktab = matktab ? "${matktab.find{ it.toString().endsWith(".ktab") }}" : '' + def pat_ktab = patktab ? "${patktab.find{ it.toString().endsWith(".ktab") }}" : '' - def FASTK_VERSION = 'f18a4e6d2207539f7b84461daebc54530a9559b0' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. - def MERQURY_VERSION = '8ae344092df5dcaf83cfb7f90f662597a9b1fc61' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. -+ def FASTK_VERSION = '427104ea91c78c3b8b8b49f1a7d6bbeaa869ba1c' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. -+ def MERQURY_VERSION = 'd00d98157618f4e8d1a9190026b19b471055b22e' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. ++ def FASTK_VERSION = '666652151335353eef2fcd58880bcef5bc2928e1' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. ++ def MERQURY_VERSION = '666652151335353eef2fcd58880bcef5bc2928e1' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. """ MerquryFK \\ $args \\ diff --git a/modules/nf-core/merquryfk/merquryfk/meta.yml b/modules/nf-core/merquryfk/merquryfk/meta.yml index ad89f8ba..82bfbec4 100644 --- a/modules/nf-core/merquryfk/merquryfk/meta.yml +++ b/modules/nf-core/merquryfk/merquryfk/meta.yml @@ -1,113 +1,217 @@ name: "merquryfk_merquryfk" description: FastK based version of Merqury keywords: - - sort + - Merqury + - reference-free + - assembly evaluation tools: - "merquryfk": description: "FastK based version of Merqury" homepage: "https://github.com/thegenemyers/MERQURY.FK" - tool_dev_url: "https://github.com/thegenemyers/MERQURY.FK" - - licence: "https://github.com/thegenemyers/MERQURY.FK/blob/main/LICENSE" - + licence: ["https://github.com/thegenemyers/MERQURY.FK/blob/main/LICENSE"] + identifier: "" input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - fastk_hist: - type: file - description: A histogram files from the program FastK - pattern: "*.hist" - - fastk_ktab: - type: file - description: Histogram ktab files from the program FastK (option -t) - pattern: "*.ktab*" - - assembly: - type: file - description: Genome (primary) assembly files (fasta format) - pattern: ".fasta" - - haplotigs: - type: file - description: Assembly haplotigs (fasta format) - pattern: ".fasta" - + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - fastk_hist: + type: file + description: A histogram files from the program FastK + pattern: "*.hist" + - fastk_ktab: + type: file + description: Histogram ktab files from the program FastK (option -t) + pattern: "*.ktab*" + - assembly: + type: file + description: Genome (primary) assembly files (fasta format) + pattern: ".fasta" + - haplotigs: + type: file + description: Assembly haplotigs (fasta format) + pattern: ".fasta" + - - matktab: + type: file + description: trio maternal histogram ktab files from the program FastK (option + -t) + pattern: "*.ktab*" + - - patktab: + type: file + description: trio paternal histogram ktab files from the program FastK (option + -t) + pattern: "*.ktab*" output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" - stats: - type: file - description: Assembly statistics file - pattern: "*.completeness.stats" + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.completeness.stats: + type: file + description: Assembly statistics file + pattern: "*.completeness.stats" - bed: - type: file - description: Assembly only kmer positions not supported by reads in bed format - pattern: "*_only.bed" - - spectra_cn_fl_png: - type: file - description: "Unstacked copy number spectra filled plot in PNG format" - pattern: "*.spectra-cn.fl.png" - - spectra_cn_ln_png: - type: file - description: "Unstacked copy number spectra line plot in PNG format" - pattern: "*.spectra-cn.ln.png" - - spectra_cn_st_png: - type: file - description: "Stacked copy number spectra line plot in PNG format" - pattern: "*.spectra-cn.st.png" - - spectra_asm_fl_png: - type: file - description: "Unstacked assembly spectra filled plot in PNG format" - pattern: "*.spectra-asm.fl.png" - - spectra_asm_ln_png: - type: file - description: "Unstacked assembly spectra line plot in PNG format" - pattern: "*.spectra-asm.ln.png" - - spectra_asm_st_png: - type: file - description: "Stacked assembly spectra line plot in PNG format" - pattern: "*.spectra-asm.st.png" - - spectra_cn_fl_pdf: - type: file - description: "Unstacked copy number spectra filled plot in PDF format" - pattern: "*.spectra-cn.fl.pdf" - - spectra_cn_ln_pdf: - type: file - description: "Unstacked copy number spectra line plot in PDF format" - pattern: "*.spectra-cn.ln.pdf" - - spectra_cn_st_pdf: - type: file - description: "Stacked copy number spectra line plot in PDF format" - pattern: "*.spectra-cn.st.pdf" - - spectra_asm_fl_pdf: - type: file - description: "Unstacked assembly spectra filled plot in PDF format" - pattern: "*.spectra-asm.fl.pdf" - - spectra_asm_ln_pdf: - type: file - description: "Unstacked assembly spectra line plot in PDF format" - pattern: "*.spectra-asm.ln.pdf" - - spectra_asm_st_pdf: - type: file - description: "Stacked assembly spectra line plot in PDF format" - pattern: "*.spectra-asm.st.pdf" + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.*_only.bed: + type: file + description: Assembly only kmer positions not supported by reads in bed format + pattern: "*_only.bed" - assembly_qv: - type: file - description: "error and qv table for each scaffold of the assembly" - pattern: "*.qv" + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.*.qv: + type: file + description: "error and qv table for each scaffold of the assembly" + pattern: "*.qv" + - spectra_cn_fl: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.*.spectra-cn.fl.{png,pdf}: + type: file + description: "Unstacked copy number spectra filled plot in PNG or PDF format" + pattern: "*.spectra-cn.fl.{png,pdf}" + - spectra_cn_ln: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.*.spectra-cn.ln.{png,pdf}: + type: file + description: "Unstacked copy number spectra line plot in PNG or PDF format" + pattern: "*.spectra-cn.ln.{png,pdf}" + - spectra_cn_st: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.*.spectra-cn.st.{png,pdf}: + type: file + description: "Stacked copy number spectra line plot in PNG or PDF format" + pattern: "*.spectra-cn.st.{png,pdf}" - qv: - type: file - description: "error and qv of each assembly as a whole" - pattern: "*.qv" - + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.qv: + type: file + description: "error and qv of each assembly as a whole" + pattern: "*.qv" + - spectra_asm_fl: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.spectra-asm.fl.{png,pdf}: + type: file + description: "Unstacked assembly spectra filled plot in PNG or PDF format" + pattern: "*.spectra-asm.fl.{png,pdf}" + - spectra_asm_ln: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.spectra-asm.ln.{png,pdf}: + type: file + description: "Unstacked assembly spectra line plot in PNG or PDF format" + pattern: "*.spectra-asm.ln.{png,pdf}" + - spectra_asm_st: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.spectra-asm.st.{png,pdf}: + type: file + description: "Stacked assembly spectra line plot in PNG or PDF format" + pattern: "*.spectra-asm.st.{png,pdf}" + - phased_block_bed: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.phased_block.bed: + type: file + description: Assembly kmer positions seperated by block in bed format + pattern: "*.phased.block.bed" + - phased_block_stats: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.phased_block.stats: + type: file + description: phased assembly statistics file + pattern: "*.phased.block.stats" + - continuity_N: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.continuity.N.{pdf,png}: + type: file + description: "Stacked assembly N continuity plot in PNG or PDF format" + pattern: "*.continuity.N.{png,pdf}" + - block_N: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.block.N.{pdf,png}: + type: file + description: "Stacked assembly N continuity by block plot in PNG or PDF format" + pattern: "*.block.N.{png,pdf}" + - block_blob: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.block.blob.{pdf,png}: + type: file + description: "Stacked assembly block plot in PNG or PDF format" + pattern: "*.block.blob.{png,pdf}" + - hapmers_blob: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.hapmers.blob.{pdf,png}: + type: file + description: "Stacked assembly hapmers block plot in PNG or PDF format" + pattern: "*.hapmers.blob.{png,pdf}" + - versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@mahesh-panchal" + - "@yumisims" +maintainers: + - "@mahesh-panchal" + - "@yumisims" diff --git a/modules/nf-core/merquryfk/merquryfk/tests/main.nf.test b/modules/nf-core/merquryfk/merquryfk/tests/main.nf.test new file mode 100644 index 00000000..c46843c6 --- /dev/null +++ b/modules/nf-core/merquryfk/merquryfk/tests/main.nf.test @@ -0,0 +1,170 @@ +nextflow_process { + + name "Test Process MERQURYFK" + script "../main.nf" + process "MERQURYFK_MERQURYFK" + + tag "modules" + tag "modules_nfcore" + tag "merquryfk" + tag "merquryfk/merquryfk" + tag "fastk" + tag "fastk/fastk" + + setup { + run("FASTK_FASTK") { + script "../../../fastk/fastk" + process { + """ + input[0] = [ + [ id:'test', single_end:false ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + """ + } + } + run("FASTK_FASTK", alias: "FASTK_MAT") { + script "../../../fastk/fastk" + process { + """ + input[0] = [ + [ id:'test', single_end:false ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + ] + """ + } + } + + run("FASTK_FASTK", alias: "FASTK_PAT") { + script "../../../fastk/fastk" + process { + """ + input[0] = [ + [ id:'test', single_end:false ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/fastq/test_2.fastq.gz', checkIfExists: true), + ] + """ + } + } + } + + test("homo_sapiens - Illumina - png") { + config "./nextflow.png.config" + when { + process { + """ + assembly = [ + [ id:'test', single_end:true ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + ] + + haplotigs = [ + [ id:'test', single_end:true ], [] + ] + input[0] = FASTK_FASTK.out.hist.join(FASTK_FASTK.out.ktab).join(Channel.from(assembly)).join(Channel.from(haplotigs)) + input[1] = [] + input[2] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("homo_sapiens - Illumina - pdf") { + config "./nextflow.pdf.config" + when { + process { + """ + assembly = [ + [ id:'test', single_end:true ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + ] + + haplotigs = [ + [ id:'test', single_end:true ], [] + ] + input[0] = FASTK_FASTK.out.hist.join(FASTK_FASTK.out.ktab).join(Channel.from(assembly)).join(Channel.from(haplotigs)) + input[1] = [] + input[2] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("homo_sapiens - Illumina - trio") { + config "./nextflow.trio.config" + when { + process { + """ + assembly = [ + [ id:'test', single_end:true ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + ] + + haplotigs = [ + [ id:'test', single_end:true ], [] + ] + input[0] = FASTK_FASTK.out.hist.join(FASTK_FASTK.out.ktab).join(Channel.from(assembly)).join(Channel.from(haplotigs)) + input[1] = FASTK_MAT.out.ktab + input[2] = FASTK_PAT.out.ktab + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("homo_sapiens - Illumina - stub") { + options "-stub" + config "./nextflow.pdf.config" + when { + process { + """ + assembly = [ + [ id:'test', single_end:true ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + ] + + haplotigs = [ + [ id:'test', single_end:true ], [] + ] + input[0] = FASTK_FASTK.out.hist.join(FASTK_FASTK.out.ktab).join(Channel.from(assembly)).join(Channel.from(haplotigs)) + input[1] = [] + input[2] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + + +} \ No newline at end of file diff --git a/modules/nf-core/merquryfk/merquryfk/tests/main.nf.test.snap b/modules/nf-core/merquryfk/merquryfk/tests/main.nf.test.snap new file mode 100644 index 00000000..f7ce47f0 --- /dev/null +++ b/modules/nf-core/merquryfk/merquryfk/tests/main.nf.test.snap @@ -0,0 +1,454 @@ +{ + "homo_sapiens - Illumina - stub": { + "content": [ + { + "0": [ + + ], + "1": [ + + ], + "10": [ + + ], + "11": [ + + ], + "12": [ + + ], + "13": [ + + ], + "14": [ + + ], + "15": [ + + ], + "16": [ + + ], + "2": [ + + ], + "3": [ + + ], + "4": [ + + ], + "5": [ + + ], + "6": [ + + ], + "7": [ + + ], + "8": [ + + ], + "9": [ + + ], + "assembly_qv": [ + + ], + "bed": [ + + ], + "block_N": [ + + ], + "block_blob": [ + + ], + "continuity_N": [ + + ], + "hapmers_blob": [ + + ], + "phased_block_bed": [ + + ], + "phased_block_stats": [ + + ], + "qv": [ + + ], + "spectra_asm_fl": [ + + ], + "spectra_asm_ln": [ + + ], + "spectra_asm_st": [ + + ], + "spectra_cn_fl": [ + + ], + "spectra_cn_ln": [ + + ], + "spectra_cn_st": [ + + ], + "stats": [ + + ], + "versions": [ + + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-08-15T15:22:52.240373868" + }, + "homo_sapiens - Illumina - pdf": { + "content": [ + { + "0": [ + + ], + "1": [ + + ], + "10": [ + + ], + "11": [ + + ], + "12": [ + + ], + "13": [ + + ], + "14": [ + + ], + "15": [ + + ], + "16": [ + + ], + "2": [ + + ], + "3": [ + + ], + "4": [ + + ], + "5": [ + + ], + "6": [ + + ], + "7": [ + + ], + "8": [ + + ], + "9": [ + + ], + "assembly_qv": [ + + ], + "bed": [ + + ], + "block_N": [ + + ], + "block_blob": [ + + ], + "continuity_N": [ + + ], + "hapmers_blob": [ + + ], + "phased_block_bed": [ + + ], + "phased_block_stats": [ + + ], + "qv": [ + + ], + "spectra_asm_fl": [ + + ], + "spectra_asm_ln": [ + + ], + "spectra_asm_st": [ + + ], + "spectra_cn_fl": [ + + ], + "spectra_cn_ln": [ + + ], + "spectra_cn_st": [ + + ], + "stats": [ + + ], + "versions": [ + + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-08-15T15:22:19.530675341" + }, + "homo_sapiens - Illumina - png": { + "content": [ + { + "0": [ + + ], + "1": [ + + ], + "10": [ + + ], + "11": [ + + ], + "12": [ + + ], + "13": [ + + ], + "14": [ + + ], + "15": [ + + ], + "16": [ + + ], + "2": [ + + ], + "3": [ + + ], + "4": [ + + ], + "5": [ + + ], + "6": [ + + ], + "7": [ + + ], + "8": [ + + ], + "9": [ + + ], + "assembly_qv": [ + + ], + "bed": [ + + ], + "block_N": [ + + ], + "block_blob": [ + + ], + "continuity_N": [ + + ], + "hapmers_blob": [ + + ], + "phased_block_bed": [ + + ], + "phased_block_stats": [ + + ], + "qv": [ + + ], + "spectra_asm_fl": [ + + ], + "spectra_asm_ln": [ + + ], + "spectra_asm_st": [ + + ], + "spectra_cn_fl": [ + + ], + "spectra_cn_ln": [ + + ], + "spectra_cn_st": [ + + ], + "stats": [ + + ], + "versions": [ + + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-08-15T15:21:57.682723412" + }, + "homo_sapiens - Illumina - trio": { + "content": [ + { + "0": [ + + ], + "1": [ + + ], + "10": [ + + ], + "11": [ + + ], + "12": [ + + ], + "13": [ + + ], + "14": [ + + ], + "15": [ + + ], + "16": [ + + ], + "2": [ + + ], + "3": [ + + ], + "4": [ + + ], + "5": [ + + ], + "6": [ + + ], + "7": [ + + ], + "8": [ + + ], + "9": [ + + ], + "assembly_qv": [ + + ], + "bed": [ + + ], + "block_N": [ + + ], + "block_blob": [ + + ], + "continuity_N": [ + + ], + "hapmers_blob": [ + + ], + "phased_block_bed": [ + + ], + "phased_block_stats": [ + + ], + "qv": [ + + ], + "spectra_asm_fl": [ + + ], + "spectra_asm_ln": [ + + ], + "spectra_asm_st": [ + + ], + "spectra_cn_fl": [ + + ], + "spectra_cn_ln": [ + + ], + "spectra_cn_st": [ + + ], + "stats": [ + + ], + "versions": [ + + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "24.04.2" + }, + "timestamp": "2024-08-15T15:22:40.060937299" + } +} \ No newline at end of file diff --git a/modules/nf-core/merquryfk/merquryfk/tests/nextflow.config b/modules/nf-core/merquryfk/merquryfk/tests/nextflow.config new file mode 100644 index 00000000..ba1eebc9 --- /dev/null +++ b/modules/nf-core/merquryfk/merquryfk/tests/nextflow.config @@ -0,0 +1,8 @@ +process { + publishDir = { "${params.outdir}/${task.process.tokenize(':')[-1].tokenize('_')[0].toLowerCase()}" } + + withName: 'FASTK_.*' { + ext.args = '-t' + publishDir = [ enabled: false ] + } +} diff --git a/modules/nf-core/merquryfk/merquryfk/tests/nextflow.pdf.config b/modules/nf-core/merquryfk/merquryfk/tests/nextflow.pdf.config new file mode 100644 index 00000000..52beeaa3 --- /dev/null +++ b/modules/nf-core/merquryfk/merquryfk/tests/nextflow.pdf.config @@ -0,0 +1,9 @@ +process { + withName: 'FASTK_.*' { + ext.args = '-t' + publishDir = [ enabled: false ] + } + withName: 'MERQURYFK_MERQURYFK' { + ext.args = '-lfs -pdf' + } +} diff --git a/modules/nf-core/merquryfk/merquryfk/tests/nextflow.png.config b/modules/nf-core/merquryfk/merquryfk/tests/nextflow.png.config new file mode 100644 index 00000000..47c3d63e --- /dev/null +++ b/modules/nf-core/merquryfk/merquryfk/tests/nextflow.png.config @@ -0,0 +1,9 @@ +process { + withName: 'FASTK_.*' { + ext.args = '-t' + publishDir = [ enabled: false ] + } + withName: 'MERQURYFK_MERQURYFK' { + ext.args = '-lfs' + } +} diff --git a/modules/nf-core/merquryfk/merquryfk/tests/nextflow.trio.config b/modules/nf-core/merquryfk/merquryfk/tests/nextflow.trio.config new file mode 100644 index 00000000..47c3d63e --- /dev/null +++ b/modules/nf-core/merquryfk/merquryfk/tests/nextflow.trio.config @@ -0,0 +1,9 @@ +process { + withName: 'FASTK_.*' { + ext.args = '-t' + publishDir = [ enabled: false ] + } + withName: 'MERQURYFK_MERQURYFK' { + ext.args = '-lfs' + } +} diff --git a/modules/nf-core/merquryfk/merquryfk/tests/tags.yml b/modules/nf-core/merquryfk/merquryfk/tests/tags.yml new file mode 100644 index 00000000..7dcac99b --- /dev/null +++ b/modules/nf-core/merquryfk/merquryfk/tests/tags.yml @@ -0,0 +1,2 @@ +merquryfk/merquryfk: + - "modules/nf-core/merquryfk/merquryfk/**" diff --git a/modules/nf-core/multiqc/environment.yml b/modules/nf-core/multiqc/environment.yml new file mode 100644 index 00000000..6f5b867b --- /dev/null +++ b/modules/nf-core/multiqc/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::multiqc=1.25.1 diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index 1fc387be..cc0643e1 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -1,16 +1,18 @@ process MULTIQC { label 'process_single' - conda "bioconda::multiqc=1.14" + conda "${moduleDir}/environment.yml" 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.25.1--pyhdfd78af_0' : + 'biocontainers/multiqc:1.25.1--pyhdfd78af_0' }" input: path multiqc_files, stageAs: "?/*" path(multiqc_config) path(extra_multiqc_config) path(multiqc_logo) + path(replace_names) + path(sample_names) output: path "*multiqc_report.html", emit: report @@ -23,14 +25,22 @@ process MULTIQC { script: def args = task.ext.args ?: '' + def prefix = task.ext.prefix ? "--filename ${task.ext.prefix}.html" : '' def config = multiqc_config ? "--config $multiqc_config" : '' def extra_config = extra_multiqc_config ? "--config $extra_multiqc_config" : '' + def logo = multiqc_logo ? "--cl-config 'custom_logo: \"${multiqc_logo}\"'" : '' + def replace = replace_names ? "--replace-names ${replace_names}" : '' + def samples = sample_names ? "--sample-names ${sample_names}" : '' """ multiqc \\ --force \\ $args \\ $config \\ + $prefix \\ $extra_config \\ + $logo \\ + $replace \\ + $samples \\ . cat <<-END_VERSIONS > versions.yml @@ -41,8 +51,8 @@ process MULTIQC { stub: """ - touch multiqc_data - touch multiqc_plots + mkdir multiqc_data + mkdir multiqc_plots touch multiqc_report.html cat <<-END_VERSIONS > versions.yml diff --git a/modules/nf-core/multiqc/meta.yml b/modules/nf-core/multiqc/meta.yml index f93b5ee5..b16c1879 100644 --- a/modules/nf-core/multiqc/meta.yml +++ b/modules/nf-core/multiqc/meta.yml @@ -1,6 +1,6 @@ -# 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 +name: multiqc +description: Aggregate results from bioinformatics analyses across many samples into + a single report keywords: - QC - bioinformatics tools @@ -13,44 +13,66 @@ tools: homepage: https://multiqc.info/ documentation: https://multiqc.info/docs/ licence: ["GPL-3.0-or-later"] - + identifier: biotools:multiqc 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}" - + - - 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}" + - - replace_names: + type: file + description: | + Optional two-column sample renaming file. First column a set of + patterns, second column a set of corresponding replacements. Passed via + MultiQC's `--replace-names` option. + pattern: "*.{tsv}" + - - sample_names: + type: file + description: | + Optional TSV file with headers, passed to the MultiQC --sample_names + argument. + pattern: "*.{tsv}" output: - report: - type: file - description: MultiQC report file - pattern: "multiqc_report.html" + - "*multiqc_report.html": + type: file + description: MultiQC report file + pattern: "multiqc_report.html" - data: - type: directory - description: MultiQC data dir - pattern: "multiqc_data" + - "*_data": + type: directory + description: MultiQC data dir + pattern: "multiqc_data" - plots: - type: file - description: Plots created by MultiQC - pattern: "*_data" + - "*_plots": + type: file + description: Plots created by MultiQC + pattern: "*_data" - versions: - type: file - description: File containing software versions - pattern: "versions.yml" + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@abhi18av" - "@bunop" - "@drpatelh" - "@jfy133" +maintainers: + - "@abhi18av" + - "@bunop" + - "@drpatelh" + - "@jfy133" diff --git a/modules/nf-core/multiqc/tests/main.nf.test b/modules/nf-core/multiqc/tests/main.nf.test new file mode 100644 index 00000000..33316a7d --- /dev/null +++ b/modules/nf-core/multiqc/tests/main.nf.test @@ -0,0 +1,92 @@ +nextflow_process { + + name "Test Process MULTIQC" + script "../main.nf" + process "MULTIQC" + + tag "modules" + tag "modules_nfcore" + tag "multiqc" + + config "./nextflow.config" + + test("sarscov2 single-end [fastqc]") { + + when { + process { + """ + input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) + input[1] = [] + input[2] = [] + input[3] = [] + input[4] = [] + input[5] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert process.out.report[0] ==~ ".*/multiqc_report.html" }, + { assert process.out.data[0] ==~ ".*/multiqc_data" }, + { assert snapshot(process.out.versions).match("multiqc_versions_single") } + ) + } + + } + + test("sarscov2 single-end [fastqc] [config]") { + + when { + process { + """ + input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) + input[1] = Channel.of(file("https://github.com/nf-core/tools/raw/dev/nf_core/pipeline-template/assets/multiqc_config.yml", checkIfExists: true)) + input[2] = [] + input[3] = [] + input[4] = [] + input[5] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert process.out.report[0] ==~ ".*/multiqc_report.html" }, + { assert process.out.data[0] ==~ ".*/multiqc_data" }, + { assert snapshot(process.out.versions).match("multiqc_versions_config") } + ) + } + } + + test("sarscov2 single-end [fastqc] - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) + input[1] = [] + input[2] = [] + input[3] = [] + input[4] = [] + input[5] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out.report.collect { file(it).getName() } + + process.out.data.collect { file(it).getName() } + + process.out.plots.collect { file(it).getName() } + + process.out.versions ).match("multiqc_stub") } + ) + } + + } +} diff --git a/modules/nf-core/multiqc/tests/main.nf.test.snap b/modules/nf-core/multiqc/tests/main.nf.test.snap new file mode 100644 index 00000000..2fcbb5ff --- /dev/null +++ b/modules/nf-core/multiqc/tests/main.nf.test.snap @@ -0,0 +1,41 @@ +{ + "multiqc_versions_single": { + "content": [ + [ + "versions.yml:md5,41f391dcedce7f93ca188f3a3ffa0916" + ] + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-10-02T17:51:46.317523" + }, + "multiqc_stub": { + "content": [ + [ + "multiqc_report.html", + "multiqc_data", + "multiqc_plots", + "versions.yml:md5,41f391dcedce7f93ca188f3a3ffa0916" + ] + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-10-02T17:52:20.680978" + }, + "multiqc_versions_config": { + "content": [ + [ + "versions.yml:md5,41f391dcedce7f93ca188f3a3ffa0916" + ] + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-10-02T17:52:09.185842" + } +} \ No newline at end of file diff --git a/modules/nf-core/multiqc/tests/nextflow.config b/modules/nf-core/multiqc/tests/nextflow.config new file mode 100644 index 00000000..c537a6a3 --- /dev/null +++ b/modules/nf-core/multiqc/tests/nextflow.config @@ -0,0 +1,5 @@ +process { + withName: 'MULTIQC' { + ext.prefix = null + } +} diff --git a/modules/nf-core/multiqc/tests/tags.yml b/modules/nf-core/multiqc/tests/tags.yml new file mode 100644 index 00000000..bea6c0d3 --- /dev/null +++ b/modules/nf-core/multiqc/tests/tags.yml @@ -0,0 +1,2 @@ +multiqc: + - modules/nf-core/multiqc/** diff --git a/subworkflows/local/genome_statistics.nf b/subworkflows/local/genome_statistics.nf index 9ac06b94..e8807f96 100644 --- a/subworkflows/local/genome_statistics.nf +++ b/subworkflows/local/genome_statistics.nf @@ -104,7 +104,7 @@ workflow GENOME_STATISTICS { // MerquryFK - MERQURYFK_MERQURYFK ( ch_merq ) + MERQURYFK_MERQURYFK ( ch_merq, [], [] ) ch_versions = ch_versions.mix ( MERQURYFK_MERQURYFK.out.versions.first() ) diff --git a/workflows/genomenote.nf b/workflows/genomenote.nf index 7af41c21..6ed474aa 100644 --- a/workflows/genomenote.nf +++ b/workflows/genomenote.nf @@ -25,7 +25,7 @@ if (params.lineage_tax_ids) { ch_lineage_tax_ids = Channel.fromPath(params.linea // Check optional parameters if (params.lineage_db) { ch_lineage_db = Channel.fromPath(params.lineage_db) } else { ch_lineage_db = Channel.empty() } -if (params.note_template) { ch_note_template = Channel.fromPath(params.note_template) } else { ch_note_template = Channel.empty() } +if (params.note_template) { ch_note_template = Channel.fromPath(params.note_template) } else { ch_note_template = Channel.empty() } if (params.cool_order) { ch_cool_order = Channel.fromPath(params.cool_order) } else { ch_cool_order = Channel.empty() } if (params.biosample_hic) metadata_inputs.add(params.biosample_hic) else metadata_inputs.add(null) if (params.biosample_rna) metadata_inputs.add(params.biosample_rna) else metadata_inputs.add(null) @@ -59,7 +59,7 @@ include { GENOME_METADATA } from '../subworkflows/local/genome_metadata' include { CONTACT_MAPS } from '../subworkflows/local/contact_maps' include { GENOME_STATISTICS } from '../subworkflows/local/genome_statistics' include { COMBINE_NOTE_DATA } from '../subworkflows/local/combine_note_data' -include { ANNOTATION_STATISTICS } from '../subworkflows/local/annotation_statistics' +include { ANNOTATION_STATISTICS } from '../subworkflows/local/annotation_statistics' /* @@ -166,7 +166,7 @@ workflow GENOMENOTE { // COMBINE_NOTE_DATA (GENOME_METADATA.out.consistent, GENOME_METADATA.out.inconsistent, GENOME_STATISTICS.out.summary, ch_annotation_stats.ifEmpty([[],[]]), CONTACT_MAPS.out.link, ch_note_template) ch_versions = ch_versions.mix ( COMBINE_NOTE_DATA.out.versions ) - + // // MODULE: Combine different versions.yml // @@ -192,7 +192,9 @@ workflow GENOMENOTE { ch_multiqc_files.collect(), ch_multiqc_config.toList(), ch_multiqc_custom_config.toList(), - ch_multiqc_logo.toList() + ch_multiqc_logo.toList(), + [], + [] ) multiqc_report = MULTIQC.out.report.toList() From dd58ec1fa4d5668ddc796ba29d83cd4d5008fd67 Mon Sep 17 00:00:00 2001 From: Tyler Chafin Date: Mon, 25 Nov 2024 12:22:16 +0000 Subject: [PATCH 122/132] remove anaconda references --- CITATIONS.md | 4 ++-- README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CITATIONS.md b/CITATIONS.md index 8bff25a0..dd2af30d 100644 --- a/CITATIONS.md +++ b/CITATIONS.md @@ -48,9 +48,9 @@ ## Software packaging/containerisation tools -- [Anaconda](https://anaconda.com) +- [Conda](https://conda.org/) - > Anaconda Software Distribution. Computer software. Vers. 2-2.4.0. Anaconda, Nov. 2016. Web. + > conda contributors. conda: A system-level, binary package and environment manager running on all major operating systems and platforms. Computer software. https://github.com/conda/conda - [Bioconda](https://bioconda.github.io) diff --git a/README.md b/README.md index 01a1a915..4f6b10dd 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.7949384-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.7949384) [![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 conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=conda)](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/sanger-tol/genomenote) From f6220c026fb3d655cb353439000617b4743f3c9c Mon Sep 17 00:00:00 2001 From: Tyler Chafin Date: Mon, 25 Nov 2024 12:48:59 +0000 Subject: [PATCH 123/132] nf-core samtools/view updated --- modules.json | 64 +-- modules/nf-core/samtools/view/environment.yml | 10 + modules/nf-core/samtools/view/main.nf | 51 +- modules/nf-core/samtools/view/meta.yml | 158 ++++-- .../nf-core/samtools/view/tests/bam.config | 3 + .../samtools/view/tests/bam_index.config | 3 + .../nf-core/samtools/view/tests/main.nf.test | 214 +++++++ .../samtools/view/tests/main.nf.test.snap | 528 ++++++++++++++++++ modules/nf-core/samtools/view/tests/tags.yml | 2 + subworkflows/local/contact_maps.nf | 13 +- 10 files changed, 922 insertions(+), 124 deletions(-) create mode 100644 modules/nf-core/samtools/view/environment.yml create mode 100644 modules/nf-core/samtools/view/tests/bam.config create mode 100644 modules/nf-core/samtools/view/tests/bam_index.config create mode 100644 modules/nf-core/samtools/view/tests/main.nf.test create mode 100644 modules/nf-core/samtools/view/tests/main.nf.test.snap create mode 100644 modules/nf-core/samtools/view/tests/tags.yml diff --git a/modules.json b/modules.json index 709b8f1a..bc77dc22 100644 --- a/modules.json +++ b/modules.json @@ -8,113 +8,83 @@ "agat/spstatistics": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "agat/sqstatbasic": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "bedtools/bamtobed": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "busco/busco": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ], + "installed_by": ["modules"], "patch": "modules/nf-core/busco/busco/busco-busco.diff" }, "cooler/cload": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "cooler/dump": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "cooler/zoomify": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "custom/dumpsoftwareversions": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "fastk/fastk": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ], + "installed_by": ["modules"], "patch": "modules/nf-core/fastk/fastk/fastk-fastk.diff" }, "gffread": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "gnu/sort": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "gunzip": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "merquryfk/merquryfk": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ], + "installed_by": ["modules"], "patch": "modules/nf-core/merquryfk/merquryfk/merquryfk-merquryfk.diff" }, "multiqc": { "branch": "master", "git_sha": "cf17ca47590cc578dfb47db1c2a44ef86f89976d", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "samtools/view": { "branch": "master", - "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", - "installed_by": [ - "modules" - ] + "git_sha": "2d20463181b1c38981a02e90d3084b5f9fa8d540", + "installed_by": ["modules"] } } } } } -} \ No newline at end of file +} diff --git a/modules/nf-core/samtools/view/environment.yml b/modules/nf-core/samtools/view/environment.yml new file mode 100644 index 00000000..02cda6e6 --- /dev/null +++ b/modules/nf-core/samtools/view/environment.yml @@ -0,0 +1,10 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + # renovate: datasource=conda depName=bioconda/htslib + - bioconda::htslib=1.21 + # renovate: datasource=conda depName=bioconda/samtools + - bioconda::samtools=1.21 diff --git a/modules/nf-core/samtools/view/main.nf b/modules/nf-core/samtools/view/main.nf index b87369e5..a6941e63 100644 --- a/modules/nf-core/samtools/view/main.nf +++ b/modules/nf-core/samtools/view/main.nf @@ -2,24 +2,26 @@ process SAMTOOLS_VIEW { tag "$meta.id" label 'process_low' - conda "bioconda::samtools=1.17" + conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/samtools:1.17--h00cdaf9_0' : - 'biocontainers/samtools:1.17--h00cdaf9_0' }" + 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/9e/9edc2564215d5cd137a8b25ca8a311600987186d406b092022444adf3c4447f7/data' : + 'community.wave.seqera.io/library/htslib_samtools:1.21--6cb89bfd40cbaabf' }" input: tuple val(meta), path(input), path(index) - path fasta + tuple val(meta2), path(fasta) path qname output: - tuple val(meta), path("*.bam"), emit: bam, optional: true - tuple val(meta), path("*.cram"), emit: cram, optional: true - tuple val(meta), path("*.sam"), emit: sam, optional: true - tuple val(meta), path("*.bai"), emit: bai, optional: true - tuple val(meta), path("*.csi"), emit: csi, optional: true - tuple val(meta), path("*.crai"), emit: crai, optional: true - path "versions.yml", emit: versions + tuple val(meta), path("${prefix}.bam"), emit: bam, optional: true + tuple val(meta), path("${prefix}.cram"), emit: cram, optional: true + tuple val(meta), path("${prefix}.sam"), emit: sam, optional: true + tuple val(meta), path("${prefix}.${file_type}.bai"), emit: bai, optional: true + tuple val(meta), path("${prefix}.${file_type}.csi"), emit: csi, optional: true + tuple val(meta), path("${prefix}.${file_type}.crai"), emit: crai, optional: true + tuple val(meta), path("${prefix}.unselected.${file_type}"), emit: unselected, optional: true + tuple val(meta), path("${prefix}.unselected.${file_type}.{bai,csi,crsi}"), emit: unselected_index, optional: true + path "versions.yml", emit: versions when: task.ext.when == null || task.ext.when @@ -27,13 +29,13 @@ process SAMTOOLS_VIEW { script: def args = task.ext.args ?: '' def args2 = task.ext.args2 ?: '' - def prefix = task.ext.prefix ?: "${meta.id}" + prefix = task.ext.prefix ?: "${meta.id}" def reference = fasta ? "--reference ${fasta}" : "" - def readnames = qname ? "--qname-file ${qname}": "" - def file_type = args.contains("--output-fmt sam") ? "sam" : - args.contains("--output-fmt bam") ? "bam" : - args.contains("--output-fmt cram") ? "cram" : - input.getExtension() + file_type = args.contains("--output-fmt sam") ? "sam" : + args.contains("--output-fmt bam") ? "bam" : + args.contains("--output-fmt cram") ? "cram" : + input.getExtension() + readnames = qname ? "--qname-file ${qname} --output-unselected ${prefix}.unselected.${file_type}": "" if ("$input" == "${prefix}.${file_type}") error "Input and output names are the same, use \"task.ext.prefix\" to disambiguate!" """ samtools \\ @@ -53,10 +55,19 @@ process SAMTOOLS_VIEW { """ stub: - def prefix = task.ext.prefix ?: "${meta.id}" + def args = task.ext.args ?: '' + prefix = task.ext.prefix ?: "${meta.id}" + file_type = args.contains("--output-fmt sam") ? "sam" : + args.contains("--output-fmt bam") ? "bam" : + args.contains("--output-fmt cram") ? "cram" : + input.getExtension() + if ("$input" == "${prefix}.${file_type}") error "Input and output names are the same, use \"task.ext.prefix\" to disambiguate!" + + index = args.contains("--write-index") ? "touch ${prefix}.${file_type}.csi" : "" + """ - touch ${prefix}.bam - touch ${prefix}.cram + touch ${prefix}.${file_type} + ${index} cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/nf-core/samtools/view/meta.yml b/modules/nf-core/samtools/view/meta.yml index 76916033..caa7b015 100644 --- a/modules/nf-core/samtools/view/meta.yml +++ b/modules/nf-core/samtools/view/meta.yml @@ -15,65 +15,127 @@ tools: documentation: http://www.htslib.org/doc/samtools.html doi: 10.1093/bioinformatics/btp352 licence: ["MIT"] + identifier: biotools:samtools input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - input: - type: file - description: BAM/CRAM/SAM file - pattern: "*.{bam,cram,sam}" - - index: - type: optional file - description: BAM.BAI/BAM.CSI/CRAM.CRAI file - pattern: "*.{.bai,.csi,.crai}" - - fasta: - type: optional file - description: Reference file the CRAM was created with - pattern: "*.{fasta,fa}" - - qname: - type: file - description: Optional file with read names to output only select alignments - pattern: "*.{txt,list}" + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - input: + type: file + description: BAM/CRAM/SAM file + pattern: "*.{bam,cram,sam}" + - index: + type: file + description: BAM.BAI/BAM.CSI/CRAM.CRAI file (optional) + pattern: "*.{.bai,.csi,.crai}" + - - meta2: + type: map + description: | + Groovy Map containing reference information + e.g. [ id:'test' ] + - fasta: + type: file + description: Reference file the CRAM was created with (optional) + pattern: "*.{fasta,fa}" + - - qname: + type: file + description: Optional file with read names to output only select alignments + pattern: "*.{txt,list}" output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - bam: - type: file - description: optional filtered/converted BAM file - pattern: "*.{bam}" + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.bam: + type: file + description: optional filtered/converted BAM file + pattern: "*.{bam}" - cram: - type: file - description: optional filtered/converted CRAM file - pattern: "*.{cram}" + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.cram: + type: file + description: optional filtered/converted CRAM file + pattern: "*.{cram}" - sam: - type: file - description: optional filtered/converted SAM file - pattern: "*.{sam}" - # bai, csi, and crai are created with `--write-index` + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.sam: + type: file + description: optional filtered/converted SAM file + pattern: "*.{sam}" - bai: - type: file - description: optional BAM file index - pattern: "*.{bai}" + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.${file_type}.bai: + type: file + description: optional BAM file index + pattern: "*.{bai}" - csi: - type: file - description: optional tabix BAM file index - pattern: "*.{csi}" + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.${file_type}.csi: + type: file + description: optional tabix BAM file index + pattern: "*.{csi}" - crai: - type: file - description: optional CRAM file index - pattern: "*.{crai}" + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.${file_type}.crai: + type: file + description: optional CRAM file index + pattern: "*.{crai}" + - unselected: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.unselected.${file_type}: + type: file + description: optional file with unselected alignments + pattern: "*.unselected.{bam,cram,sam}" + - unselected_index: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - ${prefix}.unselected.${file_type}.{bai,csi,crsi}: + type: file + description: index for the "unselected" file + pattern: "*.unselected.{bai,csi,crai}" - versions: - type: file - description: File containing software versions - pattern: "versions.yml" + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@drpatelh" - "@joseespinosa" - "@FriederikeHanssen" - "@priyanka-surana" +maintainers: + - "@drpatelh" + - "@joseespinosa" + - "@FriederikeHanssen" + - "@priyanka-surana" diff --git a/modules/nf-core/samtools/view/tests/bam.config b/modules/nf-core/samtools/view/tests/bam.config new file mode 100644 index 00000000..c10d1081 --- /dev/null +++ b/modules/nf-core/samtools/view/tests/bam.config @@ -0,0 +1,3 @@ +process { + ext.args = "--output-fmt bam" +} \ No newline at end of file diff --git a/modules/nf-core/samtools/view/tests/bam_index.config b/modules/nf-core/samtools/view/tests/bam_index.config new file mode 100644 index 00000000..771ae033 --- /dev/null +++ b/modules/nf-core/samtools/view/tests/bam_index.config @@ -0,0 +1,3 @@ +process { + ext.args = "--output-fmt bam --write-index" +} \ No newline at end of file diff --git a/modules/nf-core/samtools/view/tests/main.nf.test b/modules/nf-core/samtools/view/tests/main.nf.test new file mode 100644 index 00000000..37b81a91 --- /dev/null +++ b/modules/nf-core/samtools/view/tests/main.nf.test @@ -0,0 +1,214 @@ +nextflow_process { + + name "Test Process SAMTOOLS_VIEW" + script "../main.nf" + process "SAMTOOLS_VIEW" + + tag "modules" + tag "modules_nfcore" + tag "samtools" + tag "samtools/view" + + test("bam") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.bam', checkIfExists: true), + [] + ]) + input[1] = [[],[]] + input[2] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(file(process.out.bam[0][1]).name).match("bam_bam") }, + { assert snapshot(process.out.bai).match("bam_bai") }, + { assert snapshot(process.out.crai).match("bam_crai") }, + { assert snapshot(process.out.cram).match("bam_cram") }, + { assert snapshot(process.out.csi).match("bam_csi") }, + { assert snapshot(process.out.sam).match("bam_sam") }, + { assert snapshot(process.out.versions).match("bam_versions") } + ) + } + } + + test("cram") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.sorted.cram', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.sorted.cram.crai', checkIfExists: true) + ]) + input[1] = Channel.of([ + [ id:'genome' ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + ]) + input[2] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(file(process.out.cram[0][1]).name).match("cram_cram") }, + { assert snapshot(process.out.bai).match("cram_bai") }, + { assert snapshot(process.out.bam).match("cram_bam") }, + { assert snapshot(process.out.crai).match("cram_crai") }, + { assert snapshot(process.out.csi).match("cram_csi") }, + { assert snapshot(process.out.sam).match("cram_sam") }, + { assert snapshot(process.out.versions).match("cram_versions") } + ) + } + } + + test("cram_to_bam") { + + config "./bam.config" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.sorted.cram', checkIfExists: true), + [] + ]) + input[1] = Channel.of([ + [ id:'genome' ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + ]) + input[2] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(file(process.out.bam[0][1]).name).match("cram_to_bam_bam") }, + { assert snapshot(process.out.bai).match("cram_to_bam_bai") }, + { assert snapshot(process.out.crai).match("cram_to_bam_crai") }, + { assert snapshot(process.out.cram).match("cram_to_bam_cram") }, + { assert snapshot(process.out.csi).match("cram_to_bam_csi") }, + { assert snapshot(process.out.sam).match("cram_to_bam_sam") }, + { assert snapshot(process.out.versions).match("cram_to_bam_versions") } + ) + } + } + + test("cram_to_bam_index") { + + config "./bam_index.config" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.sorted.cram', checkIfExists: true), + [] + ]) + input[1] = Channel.of([ + [ id:'genome' ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + ]) + input[2] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(file(process.out.bam[0][1]).name).match("cram_to_bam_index_bam") }, + { assert snapshot(file(process.out.csi[0][1]).name).match("cram_to_bam_index_csi") }, + { assert snapshot(process.out.bai).match("cram_to_bam_index_bai") }, + { assert snapshot(process.out.crai).match("cram_to_bam_index_crai") }, + { assert snapshot(process.out.cram).match("cram_to_bam_index_cram") }, + { assert snapshot(process.out.sam).match("cram_to_bam_index_sam") }, + { assert snapshot(process.out.versions).match("cram_to_bam_index_versions") } + ) + } + } + + test("cram_to_bam_index_qname") { + + config "./bam_index.config" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.sorted.cram', checkIfExists: true), + [] + ]) + input[1] = Channel.of([ + [ id:'genome' ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + ]) + input[2] = Channel.of("testN:2817", "testN:2814").collectFile(name: "readnames.list", newLine: true) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(file(process.out.bam[0][1]).name).match("cram_to_bam_index_qname_bam") }, + { assert snapshot(file(process.out.csi[0][1]).name).match("cram_to_bam_index_qname_csi") }, + { assert snapshot(process.out.bai).match("cram_to_bam_index_qname_bai") }, + { assert snapshot(process.out.crai).match("cram_to_bam_index_qname_crai") }, + { assert snapshot(process.out.cram).match("cram_to_bam_index_qname_cram") }, + { assert snapshot(process.out.sam).match("cram_to_bam_index_qname_sam") }, + { assert snapshot(file(process.out.unselected[0][1]).name).match("cram_to_bam_index_qname_unselected") }, + { assert snapshot(file(process.out.unselected_index[0][1]).name).match("cram_to_bam_index_qname_unselected_csi") }, + { assert snapshot(process.out.versions).match("cram_to_bam_index_qname_versions") } + ) + } + } + + test("bam_stub") { + + options "-stub" + config "./bam_index.config" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.bam', checkIfExists: true), + [] + ]) + input[1] = [[],[]] + input[2] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(file(process.out.bam[0][1]).name).match("bam_stub_bam") }, + { assert snapshot(file(process.out.csi[0][1]).name).match("bam_stub_csi") }, + { assert snapshot(process.out.bai).match("bam_stub_bai") }, + { assert snapshot(process.out.crai).match("bam_stub_crai") }, + { assert snapshot(process.out.cram).match("bam_stub_cram") }, + { assert snapshot(process.out.sam).match("bam_stub_sam") }, + { assert snapshot(process.out.versions).match("bam_stub_versions") } + ) + } + } +} diff --git a/modules/nf-core/samtools/view/tests/main.nf.test.snap b/modules/nf-core/samtools/view/tests/main.nf.test.snap new file mode 100644 index 00000000..63849b03 --- /dev/null +++ b/modules/nf-core/samtools/view/tests/main.nf.test.snap @@ -0,0 +1,528 @@ +{ + "bam_bam": { + "content": [ + "test.bam" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:51.256068" + }, + "cram_to_bam_index_csi": { + "content": [ + "test.bam.csi" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:12.958617" + }, + "bam_stub_bam": { + "content": [ + "test.bam" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:32.065301" + }, + "bam_bai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:51.258578" + }, + "bam_stub_bai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:32.071284" + }, + "bam_stub_versions": { + "content": [ + [ + "versions.yml:md5,176db5ec46b965219604bcdbb3ef9e07" + ] + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-09-16T09:26:24.461775464" + }, + "cram_to_bam_index_cram": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:12.972288" + }, + "cram_to_bam_sam": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:04.999247" + }, + "cram_to_bam_index_sam": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:12.976457" + }, + "cram_crai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:56.497581" + }, + "cram_csi": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:56.50038" + }, + "cram_to_bam_cram": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:04.992239" + }, + "cram_to_bam_index_qname_csi": { + "content": [ + "test.bam.csi" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:23.325496" + }, + "bam_stub_sam": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:32.079529" + }, + "cram_cram": { + "content": [ + "test.cram" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:56.490286" + }, + "cram_to_bam_index_qname_unselected_csi": { + "content": [ + "test.unselected.bam.csi" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:23.328458" + }, + "bam_csi": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:51.262882" + }, + "cram_to_bam_crai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:04.989247" + }, + "cram_to_bam_index_crai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:12.967681" + }, + "cram_to_bam_index_qname_versions": { + "content": [ + [ + "versions.yml:md5,176db5ec46b965219604bcdbb3ef9e07" + ] + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-09-16T09:25:51.953436682" + }, + "cram_to_bam_bam": { + "content": [ + "test.bam" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:04.982361" + }, + "cram_to_bam_index_bam": { + "content": [ + "test.bam" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:12.95456" + }, + "cram_to_bam_index_versions": { + "content": [ + [ + "versions.yml:md5,176db5ec46b965219604bcdbb3ef9e07" + ] + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-09-16T09:25:14.475388399" + }, + "cram_to_bam_bai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:04.98601" + }, + "cram_to_bam_versions": { + "content": [ + [ + "versions.yml:md5,176db5ec46b965219604bcdbb3ef9e07" + ] + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-09-16T09:24:49.673441798" + }, + "cram_bam": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:56.495512" + }, + "bam_stub_cram": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:32.076908" + }, + "cram_to_bam_index_qname_bai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:23.328458" + }, + "cram_to_bam_index_qname_crai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:23.330789" + }, + "cram_bai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:56.493129" + }, + "bam_stub_crai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:32.074313" + }, + "cram_to_bam_index_qname_bam": { + "content": [ + "test.bam" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:23.322874" + }, + "cram_to_bam_index_qname_unselected": { + "content": [ + "test.unselected.bam" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:23.322874" + }, + "cram_to_bam_index_qname_unselected_csi": { + "content": [ + "test.unselected.bam.csi" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:23.328458" + }, + "bam_versions": { + "content": [ + [ + "versions.yml:md5,176db5ec46b965219604bcdbb3ef9e07" + ] + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-09-16T09:23:27.151650338" + }, + "cram_to_bam_index_qname_cram": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:23.333248" + }, + "bam_crai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:51.259774" + }, + "bam_cram": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:51.261287" + }, + "cram_to_bam_csi": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:04.995454" + }, + "cram_sam": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:56.502625" + }, + "cram_versions": { + "content": [ + [ + "versions.yml:md5,176db5ec46b965219604bcdbb3ef9e07" + ] + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.4" + }, + "timestamp": "2024-09-16T09:24:12.95416913" + }, + "cram_to_bam_index_qname_unselected": { + "content": [ + "test.unselected.bam" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:23.322874" + }, + "bam_sam": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:37:51.264651" + }, + "cram_to_bam_index_bai": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:12.962863" + }, + "cram_to_bam_index_qname_sam": { + "content": [ + [ + + ] + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:23.337634" + }, + "bam_stub_csi": { + "content": [ + "test.bam.csi" + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.04.3" + }, + "timestamp": "2024-02-12T19:38:32.068596" + } +} \ No newline at end of file diff --git a/modules/nf-core/samtools/view/tests/tags.yml b/modules/nf-core/samtools/view/tests/tags.yml new file mode 100644 index 00000000..4fdf1dd1 --- /dev/null +++ b/modules/nf-core/samtools/view/tests/tags.yml @@ -0,0 +1,2 @@ +samtools/view: + - "modules/nf-core/samtools/view/**" diff --git a/subworkflows/local/contact_maps.nf b/subworkflows/local/contact_maps.nf index 5d06d680..6c720f59 100644 --- a/subworkflows/local/contact_maps.nf +++ b/subworkflows/local/contact_maps.nf @@ -33,12 +33,7 @@ workflow CONTACT_MAPS { // CRAM to BAM - genome - | map { meta, fasta -> fasta } - | first - | set { ch_fasta } - - SAMTOOLS_VIEW ( reads, ch_fasta, [] ) + SAMTOOLS_VIEW ( reads, genome.first(), [] ) ch_versions = ch_versions.mix ( SAMTOOLS_VIEW.out.versions.first() ) @@ -72,7 +67,7 @@ workflow CONTACT_MAPS { GET_CHROMLIST.out.list | map { meta, list -> list } | first - | set { ch_chromsizes } + | set { ch_chromsizes } COOLER_CLOAD ( ch_cooler, ch_chromsizes ) ch_versions = ch_versions.mix ( COOLER_CLOAD.out.versions.first() ) @@ -90,7 +85,7 @@ workflow CONTACT_MAPS { // Create the `.genome` file COOLER_CLOAD.out.cool | map { meta, cool, bin -> [ meta, cool, [] ] } - | set { ch_dump } + | set { ch_dump } COOLER_DUMP ( ch_dump ) ch_versions = ch_versions.mix ( COOLER_DUMP.out.versions.first() ) @@ -101,7 +96,7 @@ workflow CONTACT_MAPS { if ( params.upload_higlass_data ) { UPLOAD_HIGLASS_DATA (COOLER_ZOOMIFY.out.mcool, COOLER_DUMP.out.bedpe, params.higlass_data_project_dir, params.higlass_upload_directory ) ch_versions = ch_versions.mix ( UPLOAD_HIGLASS_DATA.out.versions.first() ) - + GENERATE_HIGLASS_LINK (UPLOAD_HIGLASS_DATA.out.file_name, UPLOAD_HIGLASS_DATA.out.map_uuid, UPLOAD_HIGLASS_DATA.out.grid_uuid, params.higlass_url, UPLOAD_HIGLASS_DATA.out.genome_file) ch_versions = ch_versions.mix ( GENERATE_HIGLASS_LINK.out.versions.first() ) ch_higlass_link = ch_higlass_link.mix ( GENERATE_HIGLASS_LINK.out.higlass_link.first() ) From a01d5925f5c81874b24ad04f1827d1bcadc6933a Mon Sep 17 00:00:00 2001 From: Tyler Chafin Date: Thu, 5 Dec 2024 10:21:55 +0000 Subject: [PATCH 124/132] remote deprecated cleanup=true --- conf/test_full.config | 2 -- 1 file changed, 2 deletions(-) diff --git a/conf/test_full.config b/conf/test_full.config index c0b078d6..c746a6ae 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' From 2f5b69b34551e31fed20aae4ace8cdfd5395681a Mon Sep 17 00:00:00 2001 From: Tyler Chafin Date: Thu, 5 Dec 2024 10:37:14 +0000 Subject: [PATCH 125/132] Update CHANGELOG.md --- CHANGELOG.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ed60a41..c9dcac02 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). -## [[2.0.0](https://github.com/sanger-tol/genomenote/releases/tag/2.0.0)] - English Cocker Spaniel [2024-10-10] +## [[2.0.0](https://github.com/sanger-tol/genomenote/releases/tag/2.0.0)] - English Cocker Spaniel [2024-12-05] ### Enhancements & fixes @@ -33,6 +33,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | | --higlass_upload_directory | | | --higlass_data_project_dir | +### Software dependencies + +Note, since the pipeline is using Nextflow DSL2, each process will be run with its own [Biocontainer](https://biocontainers.pro/#/registry). This means that on occasion it is entirely possible for the pipeline to be using different versions of the same tool. However, the overall software dependency changes compared to the last release have been listed below for reference. Only `Docker` or `Singularity` containers are supported, `conda` is not supported. + +| Dependency | Old version | New version | +|-------------|--------------------------|--------------------------| +| `agat` | | 1.4.0 | +| `bedtools` | 2.30.0 | 2.31.1 | +| `busco` | 5.5.0 | 5.7.1 | +| `cooler` | 0.8.11 | 0.9.2 | +| `fastk` | 427104ea91c78c3b8b8b49f1a7d6bbeaa869ba1c | 666652151335353eef2fcd58880bcef5bc2928e1 | +| `merquryfk` | d00d98157618f4e8d1a9190026b19b471055b22e | 666652151335353eef2fcd58880bcef5bc2928e1 | +| `multiqc` | 1.14 | 1.25.1 | +| `samtools` | 1.17 | 1.21 | + ## [[1.2.2](https://github.com/sanger-tol/genomenote/releases/tag/1.2.2)] - Pyrenean Mountain Dog (patch 2) - [2024-09-10] ### Enhancements & fixes From c4e97c3cde59936bd2481409d6bd391986df7794 Mon Sep 17 00:00:00 2001 From: Tyler Chafin Date: Thu, 5 Dec 2024 10:41:47 +0000 Subject: [PATCH 126/132] Update CHANGELOG.md --- CHANGELOG.md | 49 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9dcac02..54cc1b0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,40 @@ 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). -## [[2.0.0](https://github.com/sanger-tol/genomenote/releases/tag/2.0.0)] - English Cocker Spaniel [2024-12-05] +## [[2.1.0](https://github.com/sanger-tol/genomenote/releases/tag/2.1.0)] - Pembroke Welsh Corgi [2024-12-05] + +### Enhancements & fixes + +- New annotation_statistics subworkfow which runs BUSCO in protein mode and generates some basic statistics on the the annotated gene set if provided with a GFF3 file of gene annotations using the `--annotation_set` option. +- The genome_metadata subworkflow now queries Ensembl's GraphQL API to determine if Ensembl has released gene annotation for the assembly being processed. + +### Parameters + +| Old parameter | New parameter | +| ------------- | ---------------- | +| | --annotation_set | + +> **NB:** Parameter has been **updated** if both old and new parameter information is present.
**NB:** Parameter has been **added** if just the new parameter information is present.
**NB:** Parameter has been **removed** if new parameter information isn't present. + +### Software dependencies + +Note, since the pipeline is using Nextflow DSL2, each process will be run with its own [Biocontainer](https://biocontainers.pro/#/registry). This means that on occasion it is entirely possible for the pipeline to be using different versions of the same tool. However, the overall software dependency changes compared to the last release have been listed below for reference. Only `Docker` or `Singularity` containers are supported, `conda` is not supported. + +| Dependency | Old version | New version | +|-------------|--------------------------|--------------------------| +| `agat` | | 1.4.0 | +| `bedtools` | 2.30.0 | 2.31.1 | +| `busco` | 5.5.0 | 5.7.1 | +| `cooler` | 0.8.11 | 0.9.2 | +| `fastk` | 427104ea91c78c3b8b8b49f1a7d6bbeaa869ba1c | 666652151335353eef2fcd58880bcef5bc2928e1 | +| `gffread` | | 0.12.7 | +| `merquryfk` | d00d98157618f4e8d1a9190026b19b471055b22e | 666652151335353eef2fcd58880bcef5bc2928e1 | +| `multiqc` | 1.14 | 1.25.1 | +| `samtools` | 1.17 | 1.21 | + +> **NB:** Dependency has been **updated** if both old and new version information is present.
**NB:** Dependency has been **added** if just the new version information is present.
**NB:** Dependency has been **removed** if version information isn't present. + +## [[2.0.0](https://github.com/sanger-tol/genomenote/releases/tag/2.0.0)] - English Cocker Spaniel [2024-10-10] ### Enhancements & fixes @@ -33,20 +66,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | | --higlass_upload_directory | | | --higlass_data_project_dir | -### Software dependencies - -Note, since the pipeline is using Nextflow DSL2, each process will be run with its own [Biocontainer](https://biocontainers.pro/#/registry). This means that on occasion it is entirely possible for the pipeline to be using different versions of the same tool. However, the overall software dependency changes compared to the last release have been listed below for reference. Only `Docker` or `Singularity` containers are supported, `conda` is not supported. - -| Dependency | Old version | New version | -|-------------|--------------------------|--------------------------| -| `agat` | | 1.4.0 | -| `bedtools` | 2.30.0 | 2.31.1 | -| `busco` | 5.5.0 | 5.7.1 | -| `cooler` | 0.8.11 | 0.9.2 | -| `fastk` | 427104ea91c78c3b8b8b49f1a7d6bbeaa869ba1c | 666652151335353eef2fcd58880bcef5bc2928e1 | -| `merquryfk` | d00d98157618f4e8d1a9190026b19b471055b22e | 666652151335353eef2fcd58880bcef5bc2928e1 | -| `multiqc` | 1.14 | 1.25.1 | -| `samtools` | 1.17 | 1.21 | ## [[1.2.2](https://github.com/sanger-tol/genomenote/releases/tag/1.2.2)] - Pyrenean Mountain Dog (patch 2) - [2024-09-10] From bbfada72181c24dc34c84392bb14ae062814126f Mon Sep 17 00:00:00 2001 From: Bethan Yates Date: Thu, 5 Dec 2024 18:17:08 +0000 Subject: [PATCH 127/132] prettier fix --- CHANGELOG.md | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dbacd52..6aa48c9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +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). - ## [[2.1.0](https://github.com/sanger-tol/genomenote/releases/tag/2.1.0)] - Pembroke Welsh Corgi [2024-12-05] ### Enhancements & fixes @@ -23,18 +22,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 Note, since the pipeline is using Nextflow DSL2, each process will be run with its own [Biocontainer](https://biocontainers.pro/#/registry). This means that on occasion it is entirely possible for the pipeline to be using different versions of the same tool. However, the overall software dependency changes compared to the last release have been listed below for reference. Only `Docker` or `Singularity` containers are supported, `conda` is not supported. -| Dependency | Old version | New version | -|-------------|--------------------------|--------------------------| -| `agat` | | 1.4.0 | -| `bedtools` | 2.30.0 | 2.31.1 | -| `busco` | 5.5.0 | 5.7.1 | -| `cooler` | 0.8.11 | 0.9.2 | +| Dependency | Old version | New version | +| ----------- | ---------------------------------------- | ---------------------------------------- | +| `agat` | | 1.4.0 | +| `bedtools` | 2.30.0 | 2.31.1 | +| `busco` | 5.5.0 | 5.7.1 | +| `cooler` | 0.8.11 | 0.9.2 | | `fastk` | 427104ea91c78c3b8b8b49f1a7d6bbeaa869ba1c | 666652151335353eef2fcd58880bcef5bc2928e1 | -| `gffread` | | 0.12.7 | +| `gffread` | | 0.12.7 | | `merquryfk` | d00d98157618f4e8d1a9190026b19b471055b22e | 666652151335353eef2fcd58880bcef5bc2928e1 | -| `multiqc` | 1.14 | 1.25.1 | -| `samtools` | 1.17 | 1.21 | - +| `multiqc` | 1.14 | 1.25.1 | +| `samtools` | 1.17 | 1.21 | > **NB:** Dependency has been **updated** if both old and new version information is present.
**NB:** Dependency has been **added** if just the new version information is present.
**NB:** Dependency has been **removed** if version information isn't present. @@ -68,7 +66,6 @@ Note, since the pipeline is using Nextflow DSL2, each process will be run with i | | --higlass_upload_directory | | | --higlass_data_project_dir | - ## [[1.2.2](https://github.com/sanger-tol/genomenote/releases/tag/1.2.2)] - Pyrenean Mountain Dog (patch 2) - [2024-09-10] ### Enhancements & fixes From e448f756e106b41230134114485b1c4b6f25085e Mon Sep 17 00:00:00 2001 From: Tyler Chafin Date: Mon, 9 Dec 2024 09:53:09 +0000 Subject: [PATCH 128/132] Update Utils.groovy --- lib/Utils.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Utils.groovy b/lib/Utils.groovy index 8d030f4e..13cb02df 100755 --- a/lib/Utils.groovy +++ b/lib/Utils.groovy @@ -22,7 +22,7 @@ class Utils { // Check that all channels are present // This channel list is ordered by required channel priority. - def required_channels_in_order = ['conda-forge', 'bioconda', 'defaults'] + def required_channels_in_order = ['conda-forge', 'bioconda'] def channels_missing = ((required_channels_in_order as Set) - (channels as Set)) as Boolean // Check that they are in the right order From bf9e345aaf3a22d5206c6f6a04ecb365239c68f0 Mon Sep 17 00:00:00 2001 From: Tyler Chafin Date: Mon, 9 Dec 2024 12:03:42 +0000 Subject: [PATCH 129/132] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6aa48c9f..9a313b1b 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 - New annotation_statistics subworkfow which runs BUSCO in protein mode and generates some basic statistics on the the annotated gene set if provided with a GFF3 file of gene annotations using the `--annotation_set` option. - The genome_metadata subworkflow now queries Ensembl's GraphQL API to determine if Ensembl has released gene annotation for the assembly being processed. +- Module updates and remove Anaconda channels ### Parameters From 44f238e45d7181daaf73f65829efa8606801f322 Mon Sep 17 00:00:00 2001 From: Tyler Chafin Date: Tue, 10 Dec 2024 16:35:32 +0000 Subject: [PATCH 130/132] removed merquryfk --- CHANGELOG.md | 5 +- modules.json | 64 ++- modules/nf-core/merquryfk/merquryfk/main.nf | 80 --- .../merquryfk/merquryfk-merquryfk.diff | 16 - modules/nf-core/merquryfk/merquryfk/meta.yml | 217 --------- .../merquryfk/merquryfk/tests/main.nf.test | 170 ------- .../merquryfk/tests/main.nf.test.snap | 454 ------------------ .../merquryfk/merquryfk/tests/nextflow.config | 8 - .../merquryfk/tests/nextflow.pdf.config | 9 - .../merquryfk/tests/nextflow.png.config | 9 - .../merquryfk/tests/nextflow.trio.config | 9 - .../merquryfk/merquryfk/tests/tags.yml | 2 - subworkflows/local/genome_statistics.nf | 26 +- 13 files changed, 61 insertions(+), 1008 deletions(-) delete mode 100644 modules/nf-core/merquryfk/merquryfk/main.nf delete mode 100644 modules/nf-core/merquryfk/merquryfk/merquryfk-merquryfk.diff delete mode 100644 modules/nf-core/merquryfk/merquryfk/meta.yml delete mode 100644 modules/nf-core/merquryfk/merquryfk/tests/main.nf.test delete mode 100644 modules/nf-core/merquryfk/merquryfk/tests/main.nf.test.snap delete mode 100644 modules/nf-core/merquryfk/merquryfk/tests/nextflow.config delete mode 100644 modules/nf-core/merquryfk/merquryfk/tests/nextflow.pdf.config delete mode 100644 modules/nf-core/merquryfk/merquryfk/tests/nextflow.png.config delete mode 100644 modules/nf-core/merquryfk/merquryfk/tests/nextflow.trio.config delete mode 100644 modules/nf-core/merquryfk/merquryfk/tests/tags.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a313b1b..345c3250 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,13 +3,14 @@ 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). -## [[2.1.0](https://github.com/sanger-tol/genomenote/releases/tag/2.1.0)] - Pembroke Welsh Corgi [2024-12-05] +## [[2.1.0](https://github.com/sanger-tol/genomenote/releases/tag/2.1.0)] - Pembroke Welsh Corgi [2024-12-11] ### Enhancements & fixes - New annotation_statistics subworkfow which runs BUSCO in protein mode and generates some basic statistics on the the annotated gene set if provided with a GFF3 file of gene annotations using the `--annotation_set` option. - The genome_metadata subworkflow now queries Ensembl's GraphQL API to determine if Ensembl has released gene annotation for the assembly being processed. - Module updates and remove Anaconda channels +- Removed merquryfk completeness metric ### Parameters @@ -31,7 +32,7 @@ Note, since the pipeline is using Nextflow DSL2, each process will be run with i | `cooler` | 0.8.11 | 0.9.2 | | `fastk` | 427104ea91c78c3b8b8b49f1a7d6bbeaa869ba1c | 666652151335353eef2fcd58880bcef5bc2928e1 | | `gffread` | | 0.12.7 | -| `merquryfk` | d00d98157618f4e8d1a9190026b19b471055b22e | 666652151335353eef2fcd58880bcef5bc2928e1 | +| `merquryfk` | d00d98157618f4e8d1a9190026b19b471055b22e | | | `multiqc` | 1.14 | 1.25.1 | | `samtools` | 1.17 | 1.21 | diff --git a/modules.json b/modules.json index bc77dc22..ff107640 100644 --- a/modules.json +++ b/modules.json @@ -8,83 +8,105 @@ "agat/spstatistics": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "agat/sqstatbasic": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "bedtools/bamtobed": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "busco/busco": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"], + "installed_by": [ + "modules" + ], "patch": "modules/nf-core/busco/busco/busco-busco.diff" }, "cooler/cload": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "cooler/dump": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "cooler/zoomify": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "custom/dumpsoftwareversions": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "fastk/fastk": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"], + "installed_by": [ + "modules" + ], "patch": "modules/nf-core/fastk/fastk/fastk-fastk.diff" }, "gffread": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "gnu/sort": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "gunzip": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"] - }, - "merquryfk/merquryfk": { - "branch": "master", - "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": ["modules"], - "patch": "modules/nf-core/merquryfk/merquryfk/merquryfk-merquryfk.diff" + "installed_by": [ + "modules" + ] }, "multiqc": { "branch": "master", "git_sha": "cf17ca47590cc578dfb47db1c2a44ef86f89976d", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] }, "samtools/view": { "branch": "master", "git_sha": "2d20463181b1c38981a02e90d3084b5f9fa8d540", - "installed_by": ["modules"] + "installed_by": [ + "modules" + ] } } } } } -} +} \ No newline at end of file diff --git a/modules/nf-core/merquryfk/merquryfk/main.nf b/modules/nf-core/merquryfk/merquryfk/main.nf deleted file mode 100644 index 2a5ab221..00000000 --- a/modules/nf-core/merquryfk/merquryfk/main.nf +++ /dev/null @@ -1,80 +0,0 @@ -process MERQURYFK_MERQURYFK { - tag "$meta.id" - label 'process_medium' - - // WARN: Version information not provided by tool on CLI. Please update version string below when bumping container versions. - container 'ghcr.io/nbisweden/fastk_genescopefk_merquryfk:1.2' - - input: - tuple val(meta), path(fastk_hist),path(fastk_ktab),path(assembly),path(haplotigs) - path matktab //optional - path patktab //optional - - output: - tuple val(meta), path("${prefix}.completeness.stats") , emit: stats - tuple val(meta), path("${prefix}.*_only.bed") , emit: bed - tuple val(meta), path("${prefix}.*.qv") , emit: assembly_qv - tuple val(meta), path("${prefix}.*.spectra-cn.fl.{png,pdf}") , emit: spectra_cn_fl, optional: true - tuple val(meta), path("${prefix}.*.spectra-cn.ln.{png,pdf}") , emit: spectra_cn_ln, optional: true - tuple val(meta), path("${prefix}.*.spectra-cn.st.{png,pdf}") , emit: spectra_cn_st, optional: true - tuple val(meta), path("${prefix}.qv") , emit: qv - tuple val(meta), path("${prefix}.spectra-asm.fl.{png,pdf}") , emit: spectra_asm_fl, optional: true - tuple val(meta), path("${prefix}.spectra-asm.ln.{png,pdf}") , emit: spectra_asm_ln, optional: true - tuple val(meta), path("${prefix}.spectra-asm.st.{png,pdf}") , emit: spectra_asm_st, optional: true - tuple val(meta), path("${prefix}.phased_block.bed") , emit: phased_block_bed, optional: true - tuple val(meta), path("${prefix}.phased_block.stats") , emit: phased_block_stats, optional: true - tuple val(meta), path("${prefix}.continuity.N.{pdf,png}") , emit: continuity_N, optional: true - tuple val(meta), path("${prefix}.block.N.{pdf,png}") , emit: block_N, optional: true - tuple val(meta), path("${prefix}.block.blob.{pdf,png}") , emit: block_blob, optional: true - tuple val(meta), path("${prefix}.hapmers.blob.{pdf,png}") , emit: hapmers_blob, optional: true - path "versions.yml" , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - // Exit if running this module with -profile conda / -profile mamba - if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { - error "MERQURYFK_MERQURYFK module does not support Conda. Please use Docker / Singularity / Podman instead." - } - def args = task.ext.args ?: '' - prefix = task.ext.prefix ?: "${meta.id}" - def mat_ktab = matktab ? "${matktab.find{ it.toString().endsWith(".ktab") }}" : '' - def pat_ktab = patktab ? "${patktab.find{ it.toString().endsWith(".ktab") }}" : '' - def FASTK_VERSION = '666652151335353eef2fcd58880bcef5bc2928e1' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. - def MERQURY_VERSION = '666652151335353eef2fcd58880bcef5bc2928e1' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. - """ - MerquryFK \\ - $args \\ - -T$task.cpus \\ - ${fastk_ktab.find{ it.toString().endsWith(".ktab") }} \\ - ${mat_ktab} \\ - ${pat_ktab} \\ - $assembly \\ - $haplotigs \\ - $prefix - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - fastk: $FASTK_VERSION - merquryfk: $MERQURY_VERSION - r: \$( R --version | sed '1!d; s/.*version //; s/ .*//' ) - END_VERSIONS - """ - stub: - prefix = task.ext.prefix ?: "${meta.id}" - def FASTK_VERSION = 'f18a4e6d2207539f7b84461daebc54530a9559b0' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. - def MERQURY_VERSION = '8ae344092df5dcaf83cfb7f90f662597a9b1fc61' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. - """ - touch ${prefix}.completeness.stats - touch ${prefix}.qv - touch ${prefix}._.qv - touch ${prefix}._only.bed - cat <<-END_VERSIONS > versions.yml - "${task.process}": - fastk: $FASTK_VERSION - merquryfk: $MERQURY_VERSION - r: \$( R --version | sed '1!d; s/.*version //; s/ .*//' ) - END_VERSIONS - """ -} diff --git a/modules/nf-core/merquryfk/merquryfk/merquryfk-merquryfk.diff b/modules/nf-core/merquryfk/merquryfk/merquryfk-merquryfk.diff deleted file mode 100644 index b0ecbe5d..00000000 --- a/modules/nf-core/merquryfk/merquryfk/merquryfk-merquryfk.diff +++ /dev/null @@ -1,16 +0,0 @@ -Changes in module 'nf-core/merquryfk/merquryfk' ---- modules/nf-core/merquryfk/merquryfk/main.nf -+++ modules/nf-core/merquryfk/merquryfk/main.nf -@@ -41,8 +41,8 @@ - prefix = task.ext.prefix ?: "${meta.id}" - def mat_ktab = matktab ? "${matktab.find{ it.toString().endsWith(".ktab") }}" : '' - def pat_ktab = patktab ? "${patktab.find{ it.toString().endsWith(".ktab") }}" : '' -- def FASTK_VERSION = 'f18a4e6d2207539f7b84461daebc54530a9559b0' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. -- def MERQURY_VERSION = '8ae344092df5dcaf83cfb7f90f662597a9b1fc61' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. -+ def FASTK_VERSION = '666652151335353eef2fcd58880bcef5bc2928e1' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. -+ def MERQURY_VERSION = '666652151335353eef2fcd58880bcef5bc2928e1' // WARN: Version information not provided by tool on CLI. Please update this string when bumping container versions. - """ - MerquryFK \\ - $args \\ - -************************************************************ diff --git a/modules/nf-core/merquryfk/merquryfk/meta.yml b/modules/nf-core/merquryfk/merquryfk/meta.yml deleted file mode 100644 index 82bfbec4..00000000 --- a/modules/nf-core/merquryfk/merquryfk/meta.yml +++ /dev/null @@ -1,217 +0,0 @@ -name: "merquryfk_merquryfk" -description: FastK based version of Merqury -keywords: - - Merqury - - reference-free - - assembly evaluation -tools: - - "merquryfk": - description: "FastK based version of Merqury" - homepage: "https://github.com/thegenemyers/MERQURY.FK" - tool_dev_url: "https://github.com/thegenemyers/MERQURY.FK" - licence: ["https://github.com/thegenemyers/MERQURY.FK/blob/main/LICENSE"] - identifier: "" -input: - - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - fastk_hist: - type: file - description: A histogram files from the program FastK - pattern: "*.hist" - - fastk_ktab: - type: file - description: Histogram ktab files from the program FastK (option -t) - pattern: "*.ktab*" - - assembly: - type: file - description: Genome (primary) assembly files (fasta format) - pattern: ".fasta" - - haplotigs: - type: file - description: Assembly haplotigs (fasta format) - pattern: ".fasta" - - - matktab: - type: file - description: trio maternal histogram ktab files from the program FastK (option - -t) - pattern: "*.ktab*" - - - patktab: - type: file - description: trio paternal histogram ktab files from the program FastK (option - -t) - pattern: "*.ktab*" -output: - - stats: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - ${prefix}.completeness.stats: - type: file - description: Assembly statistics file - pattern: "*.completeness.stats" - - bed: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - ${prefix}.*_only.bed: - type: file - description: Assembly only kmer positions not supported by reads in bed format - pattern: "*_only.bed" - - assembly_qv: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - ${prefix}.*.qv: - type: file - description: "error and qv table for each scaffold of the assembly" - pattern: "*.qv" - - spectra_cn_fl: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - ${prefix}.*.spectra-cn.fl.{png,pdf}: - type: file - description: "Unstacked copy number spectra filled plot in PNG or PDF format" - pattern: "*.spectra-cn.fl.{png,pdf}" - - spectra_cn_ln: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - ${prefix}.*.spectra-cn.ln.{png,pdf}: - type: file - description: "Unstacked copy number spectra line plot in PNG or PDF format" - pattern: "*.spectra-cn.ln.{png,pdf}" - - spectra_cn_st: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - ${prefix}.*.spectra-cn.st.{png,pdf}: - type: file - description: "Stacked copy number spectra line plot in PNG or PDF format" - pattern: "*.spectra-cn.st.{png,pdf}" - - qv: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - ${prefix}.qv: - type: file - description: "error and qv of each assembly as a whole" - pattern: "*.qv" - - spectra_asm_fl: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - ${prefix}.spectra-asm.fl.{png,pdf}: - type: file - description: "Unstacked assembly spectra filled plot in PNG or PDF format" - pattern: "*.spectra-asm.fl.{png,pdf}" - - spectra_asm_ln: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - ${prefix}.spectra-asm.ln.{png,pdf}: - type: file - description: "Unstacked assembly spectra line plot in PNG or PDF format" - pattern: "*.spectra-asm.ln.{png,pdf}" - - spectra_asm_st: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - ${prefix}.spectra-asm.st.{png,pdf}: - type: file - description: "Stacked assembly spectra line plot in PNG or PDF format" - pattern: "*.spectra-asm.st.{png,pdf}" - - phased_block_bed: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - ${prefix}.phased_block.bed: - type: file - description: Assembly kmer positions seperated by block in bed format - pattern: "*.phased.block.bed" - - phased_block_stats: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - ${prefix}.phased_block.stats: - type: file - description: phased assembly statistics file - pattern: "*.phased.block.stats" - - continuity_N: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - ${prefix}.continuity.N.{pdf,png}: - type: file - description: "Stacked assembly N continuity plot in PNG or PDF format" - pattern: "*.continuity.N.{png,pdf}" - - block_N: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - ${prefix}.block.N.{pdf,png}: - type: file - description: "Stacked assembly N continuity by block plot in PNG or PDF format" - pattern: "*.block.N.{png,pdf}" - - block_blob: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - ${prefix}.block.blob.{pdf,png}: - type: file - description: "Stacked assembly block plot in PNG or PDF format" - pattern: "*.block.blob.{png,pdf}" - - hapmers_blob: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - ${prefix}.hapmers.blob.{pdf,png}: - type: file - description: "Stacked assembly hapmers block plot in PNG or PDF format" - pattern: "*.hapmers.blob.{png,pdf}" - - versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" -authors: - - "@mahesh-panchal" - - "@yumisims" -maintainers: - - "@mahesh-panchal" - - "@yumisims" diff --git a/modules/nf-core/merquryfk/merquryfk/tests/main.nf.test b/modules/nf-core/merquryfk/merquryfk/tests/main.nf.test deleted file mode 100644 index c46843c6..00000000 --- a/modules/nf-core/merquryfk/merquryfk/tests/main.nf.test +++ /dev/null @@ -1,170 +0,0 @@ -nextflow_process { - - name "Test Process MERQURYFK" - script "../main.nf" - process "MERQURYFK_MERQURYFK" - - tag "modules" - tag "modules_nfcore" - tag "merquryfk" - tag "merquryfk/merquryfk" - tag "fastk" - tag "fastk/fastk" - - setup { - run("FASTK_FASTK") { - script "../../../fastk/fastk" - process { - """ - input[0] = [ - [ id:'test', single_end:false ], - file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/fastq/test_1.fastq.gz', checkIfExists: true) - ] - """ - } - } - run("FASTK_FASTK", alias: "FASTK_MAT") { - script "../../../fastk/fastk" - process { - """ - input[0] = [ - [ id:'test', single_end:false ], - file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/fastq/test_1.fastq.gz', checkIfExists: true), - ] - """ - } - } - - run("FASTK_FASTK", alias: "FASTK_PAT") { - script "../../../fastk/fastk" - process { - """ - input[0] = [ - [ id:'test', single_end:false ], - file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/fastq/test_2.fastq.gz', checkIfExists: true), - ] - """ - } - } - } - - test("homo_sapiens - Illumina - png") { - config "./nextflow.png.config" - when { - process { - """ - assembly = [ - [ id:'test', single_end:true ], - file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) - ] - - haplotigs = [ - [ id:'test', single_end:true ], [] - ] - input[0] = FASTK_FASTK.out.hist.join(FASTK_FASTK.out.ktab).join(Channel.from(assembly)).join(Channel.from(haplotigs)) - input[1] = [] - input[2] = [] - """ - } - } - - then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) - } - - } - - test("homo_sapiens - Illumina - pdf") { - config "./nextflow.pdf.config" - when { - process { - """ - assembly = [ - [ id:'test', single_end:true ], - file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) - ] - - haplotigs = [ - [ id:'test', single_end:true ], [] - ] - input[0] = FASTK_FASTK.out.hist.join(FASTK_FASTK.out.ktab).join(Channel.from(assembly)).join(Channel.from(haplotigs)) - input[1] = [] - input[2] = [] - """ - } - } - - then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) - } - - } - - test("homo_sapiens - Illumina - trio") { - config "./nextflow.trio.config" - when { - process { - """ - assembly = [ - [ id:'test', single_end:true ], - file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) - ] - - haplotigs = [ - [ id:'test', single_end:true ], [] - ] - input[0] = FASTK_FASTK.out.hist.join(FASTK_FASTK.out.ktab).join(Channel.from(assembly)).join(Channel.from(haplotigs)) - input[1] = FASTK_MAT.out.ktab - input[2] = FASTK_PAT.out.ktab - """ - } - } - - then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) - } - - } - - test("homo_sapiens - Illumina - stub") { - options "-stub" - config "./nextflow.pdf.config" - when { - process { - """ - assembly = [ - [ id:'test', single_end:true ], - file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) - ] - - haplotigs = [ - [ id:'test', single_end:true ], [] - ] - input[0] = FASTK_FASTK.out.hist.join(FASTK_FASTK.out.ktab).join(Channel.from(assembly)).join(Channel.from(haplotigs)) - input[1] = [] - input[2] = [] - """ - } - } - - then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) - } - - } - - - -} \ No newline at end of file diff --git a/modules/nf-core/merquryfk/merquryfk/tests/main.nf.test.snap b/modules/nf-core/merquryfk/merquryfk/tests/main.nf.test.snap deleted file mode 100644 index f7ce47f0..00000000 --- a/modules/nf-core/merquryfk/merquryfk/tests/main.nf.test.snap +++ /dev/null @@ -1,454 +0,0 @@ -{ - "homo_sapiens - Illumina - stub": { - "content": [ - { - "0": [ - - ], - "1": [ - - ], - "10": [ - - ], - "11": [ - - ], - "12": [ - - ], - "13": [ - - ], - "14": [ - - ], - "15": [ - - ], - "16": [ - - ], - "2": [ - - ], - "3": [ - - ], - "4": [ - - ], - "5": [ - - ], - "6": [ - - ], - "7": [ - - ], - "8": [ - - ], - "9": [ - - ], - "assembly_qv": [ - - ], - "bed": [ - - ], - "block_N": [ - - ], - "block_blob": [ - - ], - "continuity_N": [ - - ], - "hapmers_blob": [ - - ], - "phased_block_bed": [ - - ], - "phased_block_stats": [ - - ], - "qv": [ - - ], - "spectra_asm_fl": [ - - ], - "spectra_asm_ln": [ - - ], - "spectra_asm_st": [ - - ], - "spectra_cn_fl": [ - - ], - "spectra_cn_ln": [ - - ], - "spectra_cn_st": [ - - ], - "stats": [ - - ], - "versions": [ - - ] - } - ], - "meta": { - "nf-test": "0.8.4", - "nextflow": "24.04.2" - }, - "timestamp": "2024-08-15T15:22:52.240373868" - }, - "homo_sapiens - Illumina - pdf": { - "content": [ - { - "0": [ - - ], - "1": [ - - ], - "10": [ - - ], - "11": [ - - ], - "12": [ - - ], - "13": [ - - ], - "14": [ - - ], - "15": [ - - ], - "16": [ - - ], - "2": [ - - ], - "3": [ - - ], - "4": [ - - ], - "5": [ - - ], - "6": [ - - ], - "7": [ - - ], - "8": [ - - ], - "9": [ - - ], - "assembly_qv": [ - - ], - "bed": [ - - ], - "block_N": [ - - ], - "block_blob": [ - - ], - "continuity_N": [ - - ], - "hapmers_blob": [ - - ], - "phased_block_bed": [ - - ], - "phased_block_stats": [ - - ], - "qv": [ - - ], - "spectra_asm_fl": [ - - ], - "spectra_asm_ln": [ - - ], - "spectra_asm_st": [ - - ], - "spectra_cn_fl": [ - - ], - "spectra_cn_ln": [ - - ], - "spectra_cn_st": [ - - ], - "stats": [ - - ], - "versions": [ - - ] - } - ], - "meta": { - "nf-test": "0.8.4", - "nextflow": "24.04.2" - }, - "timestamp": "2024-08-15T15:22:19.530675341" - }, - "homo_sapiens - Illumina - png": { - "content": [ - { - "0": [ - - ], - "1": [ - - ], - "10": [ - - ], - "11": [ - - ], - "12": [ - - ], - "13": [ - - ], - "14": [ - - ], - "15": [ - - ], - "16": [ - - ], - "2": [ - - ], - "3": [ - - ], - "4": [ - - ], - "5": [ - - ], - "6": [ - - ], - "7": [ - - ], - "8": [ - - ], - "9": [ - - ], - "assembly_qv": [ - - ], - "bed": [ - - ], - "block_N": [ - - ], - "block_blob": [ - - ], - "continuity_N": [ - - ], - "hapmers_blob": [ - - ], - "phased_block_bed": [ - - ], - "phased_block_stats": [ - - ], - "qv": [ - - ], - "spectra_asm_fl": [ - - ], - "spectra_asm_ln": [ - - ], - "spectra_asm_st": [ - - ], - "spectra_cn_fl": [ - - ], - "spectra_cn_ln": [ - - ], - "spectra_cn_st": [ - - ], - "stats": [ - - ], - "versions": [ - - ] - } - ], - "meta": { - "nf-test": "0.8.4", - "nextflow": "24.04.2" - }, - "timestamp": "2024-08-15T15:21:57.682723412" - }, - "homo_sapiens - Illumina - trio": { - "content": [ - { - "0": [ - - ], - "1": [ - - ], - "10": [ - - ], - "11": [ - - ], - "12": [ - - ], - "13": [ - - ], - "14": [ - - ], - "15": [ - - ], - "16": [ - - ], - "2": [ - - ], - "3": [ - - ], - "4": [ - - ], - "5": [ - - ], - "6": [ - - ], - "7": [ - - ], - "8": [ - - ], - "9": [ - - ], - "assembly_qv": [ - - ], - "bed": [ - - ], - "block_N": [ - - ], - "block_blob": [ - - ], - "continuity_N": [ - - ], - "hapmers_blob": [ - - ], - "phased_block_bed": [ - - ], - "phased_block_stats": [ - - ], - "qv": [ - - ], - "spectra_asm_fl": [ - - ], - "spectra_asm_ln": [ - - ], - "spectra_asm_st": [ - - ], - "spectra_cn_fl": [ - - ], - "spectra_cn_ln": [ - - ], - "spectra_cn_st": [ - - ], - "stats": [ - - ], - "versions": [ - - ] - } - ], - "meta": { - "nf-test": "0.8.4", - "nextflow": "24.04.2" - }, - "timestamp": "2024-08-15T15:22:40.060937299" - } -} \ No newline at end of file diff --git a/modules/nf-core/merquryfk/merquryfk/tests/nextflow.config b/modules/nf-core/merquryfk/merquryfk/tests/nextflow.config deleted file mode 100644 index ba1eebc9..00000000 --- a/modules/nf-core/merquryfk/merquryfk/tests/nextflow.config +++ /dev/null @@ -1,8 +0,0 @@ -process { - publishDir = { "${params.outdir}/${task.process.tokenize(':')[-1].tokenize('_')[0].toLowerCase()}" } - - withName: 'FASTK_.*' { - ext.args = '-t' - publishDir = [ enabled: false ] - } -} diff --git a/modules/nf-core/merquryfk/merquryfk/tests/nextflow.pdf.config b/modules/nf-core/merquryfk/merquryfk/tests/nextflow.pdf.config deleted file mode 100644 index 52beeaa3..00000000 --- a/modules/nf-core/merquryfk/merquryfk/tests/nextflow.pdf.config +++ /dev/null @@ -1,9 +0,0 @@ -process { - withName: 'FASTK_.*' { - ext.args = '-t' - publishDir = [ enabled: false ] - } - withName: 'MERQURYFK_MERQURYFK' { - ext.args = '-lfs -pdf' - } -} diff --git a/modules/nf-core/merquryfk/merquryfk/tests/nextflow.png.config b/modules/nf-core/merquryfk/merquryfk/tests/nextflow.png.config deleted file mode 100644 index 47c3d63e..00000000 --- a/modules/nf-core/merquryfk/merquryfk/tests/nextflow.png.config +++ /dev/null @@ -1,9 +0,0 @@ -process { - withName: 'FASTK_.*' { - ext.args = '-t' - publishDir = [ enabled: false ] - } - withName: 'MERQURYFK_MERQURYFK' { - ext.args = '-lfs' - } -} diff --git a/modules/nf-core/merquryfk/merquryfk/tests/nextflow.trio.config b/modules/nf-core/merquryfk/merquryfk/tests/nextflow.trio.config deleted file mode 100644 index 47c3d63e..00000000 --- a/modules/nf-core/merquryfk/merquryfk/tests/nextflow.trio.config +++ /dev/null @@ -1,9 +0,0 @@ -process { - withName: 'FASTK_.*' { - ext.args = '-t' - publishDir = [ enabled: false ] - } - withName: 'MERQURYFK_MERQURYFK' { - ext.args = '-lfs' - } -} diff --git a/modules/nf-core/merquryfk/merquryfk/tests/tags.yml b/modules/nf-core/merquryfk/merquryfk/tests/tags.yml deleted file mode 100644 index 7dcac99b..00000000 --- a/modules/nf-core/merquryfk/merquryfk/tests/tags.yml +++ /dev/null @@ -1,2 +0,0 @@ -merquryfk/merquryfk: - - "modules/nf-core/merquryfk/merquryfk/**" diff --git a/subworkflows/local/genome_statistics.nf b/subworkflows/local/genome_statistics.nf index e8807f96..758e5920 100644 --- a/subworkflows/local/genome_statistics.nf +++ b/subworkflows/local/genome_statistics.nf @@ -8,9 +8,10 @@ include { NCBI_GET_ODB } from '../../modules/lo include { BUSCO_BUSCO as BUSCO } from '../../modules/nf-core/busco/busco/main' include { RESTRUCTUREBUSCODIR } from '../../modules/local/restructurebuscodir' include { FASTK_FASTK } from '../../modules/nf-core/fastk/fastk/main' -include { MERQURYFK_MERQURYFK } from '../../modules/nf-core/merquryfk/merquryfk/main' include { CREATETABLE } from '../../modules/local/createtable' +// This is only temporarily removed so I'm leaving it here for now +//include { MERQURYFK_MERQURYFK } from '../../modules/nf-core/merquryfk/merquryfk/main' workflow GENOME_STATISTICS { take: @@ -103,9 +104,10 @@ workflow GENOME_STATISTICS { | set { ch_merq } - // MerquryFK - MERQURYFK_MERQURYFK ( ch_merq, [], [] ) - ch_versions = ch_versions.mix ( MERQURYFK_MERQURYFK.out.versions.first() ) + // This is only temporarily removed so I'm leaving it here for now + // // MerquryFK + // MERQURYFK_MERQURYFK ( ch_merq, [], [] ) + // ch_versions = ch_versions.mix ( MERQURYFK_MERQURYFK.out.versions.first() ) // Combined table @@ -117,12 +119,13 @@ workflow GENOME_STATISTICS { | ifEmpty ( [ [], [] ] ) | set { ch_busco } - MERQURYFK_MERQURYFK.out.qv - | join ( MERQURYFK_MERQURYFK.out.stats ) - | map { meta, qv, comp -> [ meta + [ id: "merq" ], qv, comp ] } - | groupTuple () - | ifEmpty ( [ [], [], [] ] ) - | set { ch_merqury } + // This is only temporarily removed so I'm leaving it here for now + // MERQURYFK_MERQURYFK.out.qv + // | join ( MERQURYFK_MERQURYFK.out.stats ) + // | map { meta, qv, comp -> [ meta + [ id: "merq" ], qv, comp ] } + // | groupTuple () + // | ifEmpty ( [ [], [], [] ] ) + // | set { ch_merqury } flagstat // Queue channel of tuple(meta, file) @@ -135,7 +138,8 @@ workflow GENOME_STATISTICS { // Now channel of tuple(list(meta), list(file)) | set { ch_flagstat } - CREATETABLE ( ch_summary, ch_busco, ch_merqury, ch_flagstat ) + //CREATETABLE ( ch_summary, ch_busco, ch_merqury, ch_flagstat ) + CREATETABLE ( ch_summary, ch_busco, [[], [], []], ch_flagstat ) ch_versions = ch_versions.mix ( CREATETABLE.out.versions.first() ) From 8add69e7f8794012e36cbb6a63978c7df784e409 Mon Sep 17 00:00:00 2001 From: Tyler Chafin Date: Tue, 10 Dec 2024 18:55:13 +0000 Subject: [PATCH 131/132] prettier linting --- modules.json | 58 ++++++++++++++-------------------------------------- 1 file changed, 15 insertions(+), 43 deletions(-) diff --git a/modules.json b/modules.json index ff107640..05680e71 100644 --- a/modules.json +++ b/modules.json @@ -8,105 +8,77 @@ "agat/spstatistics": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "agat/sqstatbasic": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "bedtools/bamtobed": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "busco/busco": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ], + "installed_by": ["modules"], "patch": "modules/nf-core/busco/busco/busco-busco.diff" }, "cooler/cload": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "cooler/dump": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "cooler/zoomify": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "custom/dumpsoftwareversions": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "fastk/fastk": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ], + "installed_by": ["modules"], "patch": "modules/nf-core/fastk/fastk/fastk-fastk.diff" }, "gffread": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "gnu/sort": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "gunzip": { "branch": "master", "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "multiqc": { "branch": "master", "git_sha": "cf17ca47590cc578dfb47db1c2a44ef86f89976d", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] }, "samtools/view": { "branch": "master", "git_sha": "2d20463181b1c38981a02e90d3084b5f9fa8d540", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] } } } } } -} \ No newline at end of file +} From 974f5cc0849d5fef8d9f2c7cc87f50dc5fd29920 Mon Sep 17 00:00:00 2001 From: Matthieu Muffato Date: Fri, 13 Dec 2024 22:33:19 +0000 Subject: [PATCH 132/132] Fixed the CI by switching to the v2 of the action --- .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 8092f270..1ac9ba25 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: uses: actions/checkout@v3 - name: Install Nextflow - uses: nf-core/setup-nextflow@v1 + uses: nf-core/setup-nextflow@v2 with: version: "${{ matrix.NXF_VER }}"
Process Name \\", + " \\ Software Version
CUSTOM_DUMPSOFTWAREVERSIONSpython3.11.7
yaml5.4.1
TOOL1tool10.11.9
TOOL2tool21.9
WorkflowNextflow